[PATCHv2,06/12] arm: Provide aeabi helpers in ARM format

Submitted by Dmitry Safonov on May 29, 2019, 4:15 p.m.

Details

Message ID 20190529161515.24867-7-dima@arista.com
State New
Series "vdso: arm32 support"
Headers show

Commit Message

Dmitry Safonov May 29, 2019, 4:15 p.m.
From: Dmitry Safonov <0x7f454c46@gmail.com>

We're building PIEs in arm format rather than in thumb.
Copy helpers from libgcc, provide a proper define and
link them into blobs.

Also substitute tabs by spaces, how it should have been
in pie/Makefile - tabs are for recipes.

Fixes:
  LINK     criu/pie/parasite.built-in.o
criu/pie/pie.lib.a(util-vdso.o): In function `elf_hash':
/criu/criu/pie/util-vdso.c:61: undefined reference to `__aeabi_uidivmod'
/criu/scripts/nmk/scripts/build.mk:209: recipe for target 'criu/pie/parasite.built-in.o' failed

Signed-off-by: Dmitry Safonov <0x7f454c46@gmail.com>
---
 criu/arch/arm/aeabi-helpers.S         |  96 +++++++++++++
 criu/arch/arm/uidiv.S                 | 186 --------------------------
 criu/pie/Makefile                     |   4 +-
 criu/pie/Makefile.library             |   4 +
 include/common/arch/arm/asm/linkage.h |   4 +
 5 files changed, 106 insertions(+), 188 deletions(-)
 create mode 100644 criu/arch/arm/aeabi-helpers.S
 delete mode 100644 criu/arch/arm/uidiv.S

Patch hide | download patch | download mbox

diff --git a/criu/arch/arm/aeabi-helpers.S b/criu/arch/arm/aeabi-helpers.S
new file mode 100644
index 000000000000..ea8561d48fe4
--- /dev/null
+++ b/criu/arch/arm/aeabi-helpers.S
@@ -0,0 +1,96 @@ 
+/*
+ * Code borrowed from gcc, arm/lib1funcs.S
+ * and adapted to CRIU macros.
+ */
+
+#if defined(__thumb__)
+/*
+ * We don't support compiling PIEs in Thumb mode,
+ * see top Makefile for details (ARM CFLAGS_PIE section).
+*/
+#error Unsupported Thumb mode
+#endif
+
+#include "common/asm/linkage.h"
+
+#define RET	bx	lr
+#define RETc(x)	bx##x	lr
+#define LSYM(x) .x
+
+.macro do_it cond, suffix=""
+.endm
+
+.macro ARM_DIV2_ORDER divisor, order
+	clz	\order, \divisor
+	rsb	\order, \order, #31
+.endm
+
+.macro ARM_DIV_BODY dividend, divisor, result, curbit
+	clz	\curbit, \dividend
+	clz	\result, \divisor
+	sub	\curbit, \result, \curbit
+	rsbs	\curbit, \curbit, #31
+	addne	\curbit, \curbit, \curbit, lsl #1
+	mov	\result, #0
+	addne	pc, pc, \curbit, lsl #2
+	nop
+	.set	shift, 32
+	.rept	32
+	.set	shift, shift - 1
+	cmp	\dividend, \divisor, lsl #shift
+	adc	\result, \result, \result
+	subcs	\dividend, \dividend, \divisor, lsl #shift
+	.endr
+.endm
+
+/*
+ * XXX: as an optimization add udiv instruction based version.
+ * It's possible to check if CPU supports the instruction by
+ * reading Instruction Set Attribute Register (ID_ISAR0)
+ * and checking fields "Divide_instrs".
+ */
+ENTRY(__aeabi_uidiv)
+	/* Note: if called via udivsi3_skip_div0_test, this will unnecessarily
+	   check for division-by-zero a second time.  */
+LSYM(udivsi3_skip_div0_test):
+	subs	r2, r1, #1
+	do_it	eq
+	RETc(eq)
+	bcc	LSYM(Ldiv0)
+	cmp	r0, r1
+	bls	11f
+	tst	r1, r2
+	beq	12f
+
+	ARM_DIV_BODY r0, r1, r2, r3
+
+	mov	r0, r2
+	RET
+
+11:	do_it	eq, e
+	moveq	r0, #1
+	movne	r0, #0
+	RET
+
+12:	ARM_DIV2_ORDER r1, r2
+
+	mov	r0, r0, lsr r2
+	RET
+
+LSYM(Ldiv0):
+	.byte   0xf0, 0x01, 0xf0, 0xe7		@ the instruction UDF #32 generates the signal SIGTRAP in Linux
+
+END(__aeabi_uidiv)
+ALIAS(__udivsi3, __aeabi_uidiv)
+
+ENTRY(__aeabi_uidivmod)
+	cmp	r1, #0
+	beq	LSYM(Ldiv0)
+	stmfd	sp!, { r0, r1, lr }
+	bl	LSYM(udivsi3_skip_div0_test)
+	ldmfd	sp!, { r1, r2, lr }
+	mul	r3, r2, r0
+	sub	r1, r1, r3
+	RET
+END(__aeabi_uidivmod)
+ALIAS(__umodsi3, __aeabi_uidiv)
diff --git a/criu/arch/arm/uidiv.S b/criu/arch/arm/uidiv.S
deleted file mode 100644
index e77f6100c784..000000000000
--- a/criu/arch/arm/uidiv.S
+++ /dev/null
@@ -1,186 +0,0 @@ 
-.globl __aeabi_uidiv
-
-work		.req	r4	@ XXXX is this safe ?
-dividend	.req	r0
-divisor		.req	r1
-overdone	.req	r2
-result		.req	r2
-curbit		.req	r3
-
-#define	LSYM(x) x
-
-.macro THUMB_DIV_MOD_BODY modulo
-	@ Load the constant 0x10000000 into our work register.
-	mov	work, #1
-	lsl	work, #28
-LSYM(Loop1):
-	@ Unless the divisor is very big, shift it up in multiples of
-	@ four bits, since this is the amount of unwinding in the main
-	@ division loop.  Continue shifting until the divisor is
-	@ larger than the dividend.
-	cmp	divisor, work
-	bhs	LSYM(Lbignum)
-	cmp	divisor, dividend
-	bhs	LSYM(Lbignum)
-	lsl	divisor, #4
-	lsl	curbit,  #4
-	b	LSYM(Loop1)
-LSYM(Lbignum):
-	@ Set work to 0x80000000
-	lsl	work, #3
-LSYM(Loop2):
-	@ For very big divisors, we must shift it a bit at a time, or
-	@ we will be in danger of overflowing.
-	cmp	divisor, work
-	bhs	LSYM(Loop3)
-	cmp	divisor, dividend
-	bhs	LSYM(Loop3)
-	lsl	divisor, #1
-	lsl	curbit,  #1
-	b	LSYM(Loop2)
-LSYM(Loop3):
-	@ Test for possible subtractions ...
-  .if \modulo
-	@ ... On the final pass, this may subtract too much from the dividend,
-	@ so keep track of which subtractions are done, we can fix them up
-	@ afterwards.
-	mov	overdone, #0
-	cmp	dividend, divisor
-	blo	LSYM(Lover1)
-	sub	dividend, dividend, divisor
-LSYM(Lover1):
-	lsr	work, divisor, #1
-	cmp	dividend, work
-	blo	LSYM(Lover2)
-	sub	dividend, dividend, work
-	mov	ip, curbit
-	mov	work, #1
-	ror	curbit, work
-	orr	overdone, curbit
-	mov	curbit, ip
-LSYM(Lover2):
-	lsr	work, divisor, #2
-	cmp	dividend, work
-	blo	LSYM(Lover3)
-	sub	dividend, dividend, work
-	mov	ip, curbit
-	mov	work, #2
-	ror	curbit, work
-	orr	overdone, curbit
-	mov	curbit, ip
-LSYM(Lover3):
-	lsr	work, divisor, #3
-	cmp	dividend, work
-	blo	LSYM(Lover4)
-	sub	dividend, dividend, work
-	mov	ip, curbit
-	mov	work, #3
-	ror	curbit, work
-	orr	overdone, curbit
-	mov	curbit, ip
-LSYM(Lover4):
-	mov	ip, curbit
-  .else
-	@ ... and note which bits are done in the result.  On the final pass,
-	@ this may subtract too much from the dividend, but the result will be ok,
-	@ since the "bit" will have been shifted out at the bottom.
-	cmp	dividend, divisor
-	blo	LSYM(Lover1)
-	sub	dividend, dividend, divisor
-	orr	result, result, curbit
-LSYM(Lover1):
-	lsr	work, divisor, #1
-	cmp	dividend, work
-	blo	LSYM(Lover2)
-	sub	dividend, dividend, work
-	lsr	work, curbit, #1
-	orr	result, work
-LSYM(Lover2):
-	lsr	work, divisor, #2
-	cmp	dividend, work
-	blo	LSYM(Lover3)
-	sub	dividend, dividend, work
-	lsr	work, curbit, #2
-	orr	result, work
-LSYM(Lover3):
-	lsr	work, divisor, #3
-	cmp	dividend, work
-	blo	LSYM(Lover4)
-	sub	dividend, dividend, work
-	lsr	work, curbit, #3
-	orr	result, work
-LSYM(Lover4):
-  .endif
-
-	cmp	dividend, #0			@ Early termination?
-	beq	LSYM(Lover5)
-	lsr	curbit,  #4			@ No, any more bits to do?
-	beq	LSYM(Lover5)
-	lsr	divisor, #4
-	b	LSYM(Loop3)
-LSYM(Lover5):
-  .if \modulo
-	@ Any subtractions that we should not have done will be recorded in
-	@ the top three bits of "overdone".  Exactly which were not needed
-	@ are governed by the position of the bit, stored in ip.
-	mov	work, #0xe
-	lsl	work, #28
-	and	overdone, work
-	beq	LSYM(Lgot_result)
-
-	@ If we terminated early, because dividend became zero, then the
-	@ bit in ip will not be in the bottom nibble, and we should not
-	@ perform the additions below.  We must test for this though
-	@ (rather relying upon the TSTs to prevent the additions) since
-	@ the bit in ip could be in the top two bits which might then match
-	@ with one of the smaller RORs.
-	mov	curbit, ip
-	mov	work, #0x7
-	tst	curbit, work
-	beq	LSYM(Lgot_result)
-
-	mov	curbit, ip
-	mov	work, #3
-	ror	curbit, work
-	tst	overdone, curbit
-	beq	LSYM(Lover6)
-	lsr	work, divisor, #3
-	add	dividend, work
-LSYM(Lover6):
-	mov	curbit, ip
-	mov	work, #2
-	ror	curbit, work
-	tst	overdone, curbit
-	beq	LSYM(Lover7)
-	lsr	work, divisor, #2
-	add	dividend, work
-LSYM(Lover7):
-	mov	curbit, ip
-	mov	work, #1
-	ror	curbit, work
-	tst	overdone, curbit
-	beq	LSYM(Lgot_result)
-	lsr	work, divisor, #1
-	add	dividend, work
-  .endif
-LSYM(Lgot_result):
-.endm
-
-
-	.thumb
-	.text
-
-__aeabi_uidiv:
-	mov	curbit, #1
-	mov	result, #0
-
-	push	{ work }
-	cmp	dividend, divisor
-	blo	LSYM(Lgot_result)
-
-	THUMB_DIV_MOD_BODY 0
-
-	mov	r0, result
-	pop	{ work }
-
-	bx      lr
diff --git a/criu/pie/Makefile b/criu/pie/Makefile
index bdff44816c79..ade186346524 100644
--- a/criu/pie/Makefile
+++ b/criu/pie/Makefile
@@ -10,8 +10,8 @@  ccflags-y	+= -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0
 ccflags-y	+= -Wp,-U_FORTIFY_SOURCE -Wp,-D_FORTIFY_SOURCE=0
 
 ifneq ($(filter-out clean mrproper,$(MAKECMDGOALS)),)
-	LDFLAGS		+= $(shell $(COMPEL_BIN) ldflags)
-	compel_plugins	:= $(shell $(COMPEL_BIN) plugins)
+        LDFLAGS		+= $(shell $(COMPEL_BIN) ldflags)
+        compel_plugins	:= $(shell $(COMPEL_BIN) plugins)
 endif
 
 LDS		:= compel/arch/$(SRCARCH)/scripts/compel-pack.lds.S
diff --git a/criu/pie/Makefile.library b/criu/pie/Makefile.library
index 0a33a8861791..2d2d1faf1bd7 100644
--- a/criu/pie/Makefile.library
+++ b/criu/pie/Makefile.library
@@ -23,5 +23,9 @@  ifeq ($(SRCARCH),x86)
         CFLAGS_util-vdso-elf32.o	+= -DCONFIG_VDSO_32
 endif
 
+ifeq ($(SRCARCH),arm)
+        lib-y		+= ./$(ARCH_DIR)/aeabi-helpers.o
+endif
+
 CFLAGS		:= $(filter-out -pg $(CFLAGS-GCOV) $(CFLAGS-ASAN),$(CFLAGS))
 ccflags-y		+= $(CFLAGS_PIE)
diff --git a/include/common/arch/arm/asm/linkage.h b/include/common/arch/arm/asm/linkage.h
index 7380642337a0..a93898be5470 100644
--- a/include/common/arch/arm/asm/linkage.h
+++ b/include/common/arch/arm/asm/linkage.h
@@ -19,6 +19,10 @@ 
 #define END(sym)		\
 	.size sym, . - sym
 
+#define ALIAS(sym_new, sym_old)	\
+	.globl sym_new;		\
+	.set sym_new, sym_old
+
 #endif  /* __ASSEMBLY__ */
 
 #endif /* __CR_LINKAGE_H__ */