Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 09 Dec 2012 16:07:21 +1300
From:      Andrew Turner <andrew@fubar.geek.nz>
To:        freebsd-arm@freebsd.org
Subject:   ARM EABI patch
Message-ID:  <20121209160721.571186d8@fubar.geek.nz>

next in thread | raw e-mail | index | archive | help
--MP_/7MVrwQO4FwHdxm_6EcPilkm
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

Hello,

I have attached a patch for testing and review to add support for the
ARM EABI. After applying this patch you will need to update both the
kernel and userland as the interface between them is slightly different.

Most things should still work however there are known issues with GDB,
syslog and devd. Also there may be parts of the base userland that fail
to build if they have been updated recently as the wchar_t type has
changed from a signed int to an unsigned int.

Before merging this into HEAD I would like to move the __aeabi_{d,f}
functions from libc to compiler-rt.

There is a WITH/WITHOUT_ARM_EABI flag to switch the ABI. The default in
the patch is to enable the EABI but it is intended to be disabled when 

Andrew
--MP_/7MVrwQO4FwHdxm_6EcPilkm
Content-Type: text/x-patch
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename=eabi.diff

Index: libexec/rtld-elf/Makefile
===================================================================
--- libexec/rtld-elf/Makefile	(.../head)	(revision 243940)
+++ libexec/rtld-elf/Makefile	(.../projects/arm_eabi)	(revision 243946)
@@ -42,6 +42,16 @@ LDFLAGS+=	-shared -Wl,-Bsymbolic
 DPADD=		${LIBC_PIC}
 LDADD=		-lc_pic
 
+.if ${MACHINE_CPUARCH} == "arm"
+# Some of the required math functions (div & mod) are implemented in libgcc
+# on ARM. The library also needs to be placed first to be correctly linked.
+# As some of the functions are used before we have shared libraries.
+DPADD+=		${LIBGCC}
+LDADD+=		-lgcc
+.endif
+
+
+
 .if ${MK_SYMVER} == "yes"
 LIBCDIR=	${TOPSRCDIR}/lib/libc
 VERSION_DEF=	${LIBCDIR}/Versions.def
Index: sys/arm/arm/db_trace.c
===================================================================
--- sys/arm/arm/db_trace.c	(.../head)	(revision 243940)
+++ sys/arm/arm/db_trace.c	(.../projects/arm_eabi)	(revision 243946)
@@ -50,6 +50,396 @@ __FBSDID("$FreeBSD$");
 #include <ddb/db_sym.h>
 #include <ddb/db_output.h>
 
+#ifdef __ARM_EABI__
+/*
+ * Definitions for the instruction interpreter.
+ *
+ * The ARM EABI specifies how to perform the frame unwinding in the
+ * Exception Handling ABI for the ARM Architecture document. To perform
+ * the unwind we need to know the initial frame pointer, stack pointer,
+ * link register and program counter. We then find the entry within the
+ * index table that points to the function the program counter is within.
+ * This gives us either a list of three instructions to process, a 31-bit
+ * relative offset to a table of instructions, or a value telling us
+ * we can't unwind any further.
+ *
+ * When we have the instructions to process we need to decode them
+ * following table 4 in section 9.3. This describes a collection of bit
+ * patterns to encode that steps to take to update the stack pointer and
+ * link register to the correct values at the start of the function.
+ */
+
+/* A special case when we are unable to unwind past this function */
+#define	EXIDX_CANTUNWIND	1
+
+/* The register names */
+#define	FP	11
+#define	SP	13
+#define	LR	14
+#define	PC	15
+
+/*
+ * These are set in the linker script. Their addresses will be
+ * either the start or end of the exception table or index.
+ */
+extern int extab_start, extab_end, exidx_start, exidx_end;
+
+/*
+ * Entry types.
+ * These are the only entry types that have been seen in the kernel.
+ */
+#define	ENTRY_MASK	0xff000000
+#define	ENTRY_ARM_SU16	0x80000000
+#define	ENTRY_ARM_LU16	0x81000000
+
+/* Instruction masks. */
+#define	INSN_VSP_MASK		0xc0
+#define	INSN_VSP_SIZE_MASK	0x3f
+#define	INSN_STD_MASK		0xf0
+#define	INSN_STD_DATA_MASK	0x0f
+#define	INSN_POP_TYPE_MASK	0x08
+#define	INSN_POP_COUNT_MASK	0x07
+#define	INSN_VSP_LARGE_INC_MASK	0xff
+
+/* Instruction definitions */
+#define	INSN_VSP_INC		0x00
+#define	INSN_VSP_DEC		0x40
+#define	INSN_POP_MASKED		0x80
+#define	INSN_VSP_REG		0x90
+#define	INSN_POP_COUNT		0xa0
+#define	INSN_FINISH		0xb0
+#define	INSN_VSP_LARGE_INC	0xb2
+
+/* An item in the exception index table */
+struct unwind_idx {
+	uint32_t offset;
+	uint32_t insn;
+};
+
+/* The state of the unwind process */
+struct unwind_state {
+	uint32_t registers[16];
+	uint32_t start_pc;
+	uint32_t *insn;
+	u_int entries;
+	u_int byte;
+	uint16_t update_mask;
+};
+
+/* We need to provide these but never use them */
+void __aeabi_unwind_cpp_pr0(void);
+void __aeabi_unwind_cpp_pr1(void);
+void __aeabi_unwind_cpp_pr2(void);
+
+void
+__aeabi_unwind_cpp_pr0(void)
+{
+	panic("__aeabi_unwind_cpp_pr0");
+}
+
+void
+__aeabi_unwind_cpp_pr1(void)
+{
+	panic("__aeabi_unwind_cpp_pr1");
+}
+
+void
+__aeabi_unwind_cpp_pr2(void)
+{
+	panic("__aeabi_unwind_cpp_pr2");
+}
+
+/* Expand a 31-bit signed value to a 32-bit signed value */
+static __inline int32_t
+db_expand_prel31(uint32_t prel31)
+{
+
+	return ((int32_t)(prel31 & 0x7fffffffu) << 1) / 2;
+}
+
+/*
+ * Perform a binary search of the index table to find the function
+ * with the largest address that doesn't exceed addr.
+ */
+static struct unwind_idx *
+db_find_index(uint32_t addr)
+{
+	unsigned int min, mid, max;
+	struct unwind_idx *start;
+	struct unwind_idx *item;
+	int32_t prel31_addr;
+	uint32_t func_addr;
+
+	start = (struct unwind_idx *)&exidx_start;
+
+	min = 0;
+	max = (&exidx_end - &exidx_start) / 2;
+
+	/* XXX: This is likely broken for small addresses */
+	while (min != max) {
+		mid = min + (max - min + 1) / 2;
+
+		item = &start[mid];
+
+	 	prel31_addr = db_expand_prel31(item->offset);
+		func_addr = (uint32_t)&item->offset + prel31_addr;
+
+		if (func_addr <= addr) {
+			min = mid;
+		} else {
+			max = mid - 1;
+		}
+	}
+
+	return &start[min];
+}
+
+/* Reads the next byte from the instruction list */
+static uint8_t
+db_unwind_exec_read_byte(struct unwind_state *state)
+{
+	uint8_t insn;
+
+	/* Read the unwind instruction */
+	insn = (*state->insn) >> (state->byte * 8);
+
+	/* Update the location of the next instruction */
+	if (state->byte == 0) {
+		state->byte = 3;
+		state->insn++;
+		state->entries--;
+	} else
+		state->byte--;
+
+	return insn;
+}
+
+/* Executes the next instruction on the list */
+static int
+db_unwind_exec_insn(struct unwind_state *state)
+{
+	unsigned int insn;
+	uint32_t *vsp = (uint32_t *)state->registers[SP];
+	int update_vsp = 0;
+
+	/* This should never happen */
+	if (state->entries == 0)
+		return 1;
+
+	/* Read the next instruction */
+	insn = db_unwind_exec_read_byte(state);
+
+	if ((insn & INSN_VSP_MASK) == INSN_VSP_INC) {
+		state->registers[SP] += ((insn & INSN_VSP_SIZE_MASK) << 2) + 4;
+
+	} else if ((insn & INSN_VSP_MASK) == INSN_VSP_DEC) {
+		state->registers[SP] -= ((insn & INSN_VSP_SIZE_MASK) << 2) + 4;
+
+	} else if ((insn & INSN_STD_MASK) == INSN_POP_MASKED) {
+		unsigned int mask, reg;
+
+		/* Load the mask */
+		mask = db_unwind_exec_read_byte(state);
+		mask |= (insn & INSN_STD_DATA_MASK) << 8;
+
+		/* We have a refuse to unwind instruction */
+		if (mask == 0)
+			return 1;
+
+		/* Update SP */
+		update_vsp = 1;
+
+		/* Load the registers */
+		for (reg = 4; mask && reg < 16; mask >>= 1, reg++) {
+			if (mask & 1) {
+				state->registers[reg] = *vsp++;
+				state->update_mask |= 1 << reg;
+
+				/* If we have updated SP kep its value */
+				if (reg == SP)
+					update_vsp = 0;
+			}
+		}
+
+	} else if ((insn & INSN_STD_MASK) == INSN_VSP_REG &&
+	    ((insn & INSN_STD_DATA_MASK) != 13) &&
+	    ((insn & INSN_STD_DATA_MASK) != 15)) {
+		/* sp = register */
+		state->registers[SP] =
+		    state->registers[insn & INSN_STD_DATA_MASK];
+
+	} else if ((insn & INSN_STD_MASK) == INSN_POP_COUNT) {
+		unsigned int count, reg;
+
+		/* Read how many registers to load */
+		count = insn & INSN_POP_COUNT_MASK;
+
+		/* Update sp */
+		update_vsp = 1;
+
+		/* Pop the registers */
+		for (reg = 4; reg <= 4 + count; reg++) {
+			state->registers[reg] = *vsp++;
+			state->update_mask |= 1 << reg;
+		}
+
+		/* Check if we are in the pop r14 version */
+		if ((insn & INSN_POP_TYPE_MASK) != 0) {
+			state->registers[14] = *vsp++;
+		}
+
+	} else if (insn == INSN_FINISH) {
+		/* Stop processing */
+		state->entries = 0;
+
+	} else if ((insn & INSN_VSP_LARGE_INC_MASK) == INSN_VSP_LARGE_INC) {
+		unsigned int uleb128;
+
+		/* Read the increment value */
+		uleb128 = db_unwind_exec_read_byte(state);
+
+		state->registers[SP] += 0x204 + (uleb128 << 2);
+
+	} else {
+		/* We hit a new instruction that needs to be implemented */
+		db_printf("Unhandled instruction %.2x\n", insn);
+		return 1;
+	}
+
+	if (update_vsp) {
+		state->registers[SP] = (uint32_t)vsp;
+	}
+
+#if 0
+	db_printf("fp = %08x, sp = %08x, lr = %08x, pc = %08x\n",
+	    state->registers[FP], state->registers[SP], state->registers[LR],
+	    state->registers[PC]);
+#endif
+
+	return 0;
+}
+
+/* Performs the unwind of a function */
+static int
+db_unwind_tab(struct unwind_state *state)
+{
+	uint32_t entry;
+
+	/* Set PC to a known value */
+	state->registers[PC] = 0;
+
+	/* Read the personality */
+	entry = *state->insn & ENTRY_MASK;
+
+	if (entry == ENTRY_ARM_SU16) {
+		state->byte = 2;
+		state->entries = 1;
+	} else if (entry == ENTRY_ARM_LU16) {
+		state->byte = 1;
+		state->entries = ((*state->insn >> 16) & 0xFF) + 1;
+	} else {
+		db_printf("Unknown entry: %x\n", entry);
+		return 1;
+	}
+
+	while (state->entries > 0) {
+		if (db_unwind_exec_insn(state) != 0)
+			return 1;
+	}
+
+	/*
+	 * The program counter was not updated, load it from the link register.
+	 */
+	if (state->registers[PC] == 0)
+		state->registers[PC] = state->registers[LR];
+
+	return 0;
+}
+
+static void
+db_stack_trace_cmd(struct unwind_state *state)
+{
+	struct unwind_idx *index;
+	const char *name;
+	db_expr_t value;
+	db_expr_t offset;
+	c_db_sym_t sym;
+	u_int reg, i;
+	char *sep;
+
+	while (1) {
+		/* Reset the mask of updated registers */
+		state->update_mask = 0;
+
+		/* The pc value is correct and will be overwritten, save it */
+		state->start_pc = state->registers[PC];
+
+		/* Find the item to run */
+		index = db_find_index(state->start_pc);
+
+		if (index->insn == EXIDX_CANTUNWIND) {
+			printf("Unable to unwind\n");
+			break;
+		} else if (index->insn & (1 << 31)) {
+			/* The data is within the instruction */
+			state->insn = &index->insn;
+		} else {
+			/* We have a prel31 offset to the unwind table */
+			uint32_t prel31_tbl = db_expand_prel31(index->insn);
+
+			state->insn = (uint32_t *)((uintptr_t)&index->insn +
+			    prel31_tbl);
+		}
+
+		/* Run the unwind function */
+		if (db_unwind_tab(state) != 0)
+			break;
+
+		/* This is not a kernel address, stop processing */
+		if (state->registers[PC] < VM_MIN_KERNEL_ADDRESS)
+			break;
+
+		/* Print the frame details */
+		sym = db_search_symbol(state->start_pc, DB_STGY_ANY, &offset);
+		if (sym == C_DB_SYM_NULL) {
+			value = 0;
+			name = "(null)";
+		} else
+			db_symbol_values(sym, &name, &value);
+		db_printf("%s() at ", name);
+		db_printsym(state->start_pc, DB_STGY_PROC);
+		db_printf("\n");
+		db_printf("\t pc = 0x%08x  lr = 0x%08x (", state->start_pc,
+		    state->registers[LR]);
+		db_printsym(state->registers[LR], DB_STGY_PROC);
+		db_printf(")\n");
+		db_printf("\t sp = 0x%08x  fp = 0x%08x",
+		    state->registers[SP], state->registers[FP]);
+
+		/* Don't print the registers we have already printed */
+		state->update_mask &= ~((1 << SP) | (1 << FP) | (1 << LR) |
+		    (1 << PC));
+		sep = "\n\t";
+		for (i = 0, reg = 0; state->update_mask != 0;
+		    state->update_mask >>= 1, reg++) {
+			if ((state->update_mask & 1) != 0) {
+				db_printf("%s%sr%d = 0x%08x", sep,
+				    (reg < 10) ? " " : "", reg,
+				    state->registers[reg]);
+				i++;
+				if (i == 2) {
+					sep = "\n\t";
+					i = 0;
+				} else
+					sep = " ";
+				
+			}
+		}
+		db_printf("\n");
+	}
+}
+#endif
+
 /*
  * APCS stack frames are awkward beasts, so I don't think even trying to use
  * a structure to represent them is a good idea.
@@ -78,6 +468,7 @@ __FBSDID("$FreeBSD$");
  * fields are actually present.
  */
 
+#ifndef __ARM_EABI__	/* The frame format is differend in AAPCS */
 static void
 db_stack_trace_cmd(db_expr_t addr, db_expr_t count, boolean_t kernel_only)
 {
@@ -171,6 +562,7 @@ db_stack_trace_cmd(db_expr_t addr, db_ex
 		}
 	}
 }
+#endif
 
 /* XXX stubs */
 void
@@ -193,11 +585,24 @@ db_md_set_watchpoint(db_expr_t addr, db_
 int
 db_trace_thread(struct thread *thr, int count)
 {
+#ifdef __ARM_EABI__
+	struct unwind_state state;
+#endif
 	struct pcb *ctx;
 
 	if (thr != curthread) {
 		ctx = kdb_thr_ctx(thr);
+
+#ifdef __ARM_EABI__
+		state.registers[FP] = ctx->un_32.pcb32_r11;
+		state.registers[SP] = ctx->un_32.pcb32_sp;
+		state.registers[LR] = ctx->un_32.pcb32_lr;
+		state.registers[PC] = ctx->un_32.pcb32_pc;
+
+		db_stack_trace_cmd(&state);
+#else
 		db_stack_trace_cmd(ctx->un_32.pcb32_r11, -1, TRUE);
+#endif
 	} else
 		db_trace_self();
 	return (0);
@@ -206,8 +611,20 @@ db_trace_thread(struct thread *thr, int 
 void
 db_trace_self(void)
 {
+#ifdef __ARM_EABI__
+	struct unwind_state state;
+	register uint32_t sp __asm__ ("sp");
+
+	state.registers[FP] = (uint32_t)__builtin_frame_address(0);
+	state.registers[SP] = (uint32_t)sp;
+	state.registers[LR] = (uint32_t)__builtin_return_address(0);
+	state.registers[PC] = (uint32_t)db_trace_self;
+
+	db_stack_trace_cmd(&state);
+#else
 	db_addr_t addr;
 
 	addr = (db_addr_t)__builtin_frame_address(0);
 	db_stack_trace_cmd(addr, -1, FALSE);
+#endif
 }
Index: sys/arm/arm/vm_machdep.c
===================================================================
--- sys/arm/arm/vm_machdep.c	(.../head)	(revision 243940)
+++ sys/arm/arm/vm_machdep.c	(.../projects/arm_eabi)	(revision 243946)
@@ -398,6 +398,8 @@ cpu_thread_alloc(struct thread *td)
 	    PAGE_SIZE) - 1;
 	td->td_frame = (struct trapframe *)
 	    ((u_int)td->td_kstack + USPACE_SVC_STACK_TOP - sizeof(struct pcb)) - 1;
+	/* Ensure the frame is aligned to an 8 byte boundary */
+	td->td_frame = (struct trapframe *)((u_int)td->td_frame & ~7);
 #ifdef __XSCALE__
 #ifndef CPU_XSCALE_CORE3
 	pmap_use_minicache(td->td_kstack, td->td_kstack_pages * PAGE_SIZE);
Index: sys/arm/arm/locore.S
===================================================================
--- sys/arm/arm/locore.S	(.../head)	(revision 243940)
+++ sys/arm/arm/locore.S	(.../projects/arm_eabi)	(revision 243946)
@@ -484,12 +484,29 @@ ENTRY_NP(abort)
 
 ENTRY_NP(sigcode)
 	mov	r0, sp
+
+	/*
+	 * Call the sigreturn system call.
+	 * 
+	 * We have to load r7 manually rather than using
+	 * "ldr r7, =SYS_sigreturn" to ensure the value of szsigcode is
+	 * correct. Using the alternative places esigcode at the address
+	 * of the datra rather than the address one past the data.
+	 */
+
+	ldr	r7, [pc, #12]	/* Load SYS_sigreturn */
 	swi	SYS_sigreturn
 
 	/* Well if that failed we better exit quick ! */
 
+	ldr	r7, [pc, #8]	/* Load SYS_exit */
 	swi	SYS_exit
-	b	. - 8
+
+	/* Branch back to retry SYS_sigreturn */
+	b	. - 16
+
+	.word	SYS_sigreturn
+	.word	SYS_exit
 
 	.align	0
 	.global _C_LABEL(esigcode)
Index: sys/arm/arm/trap.c
===================================================================
--- sys/arm/arm/trap.c	(.../head)	(revision 243940)
+++ sys/arm/arm/trap.c	(.../projects/arm_eabi)	(revision 243946)
@@ -866,7 +866,11 @@ cpu_fetch_syscall_args(struct thread *td
 	register_t *ap;
 	int error;
 
+#ifdef __ARM_EABI__
+	sa->code = td->td_frame->tf_r7;
+#else
 	sa->code = sa->insn & 0x000fffff;
+#endif
 	ap = &td->td_frame->tf_r0;
 	if (sa->code == SYS_syscall) {
 		sa->code = *ap++;
@@ -906,15 +910,18 @@ syscall(struct thread *td, trapframe_t *
 	int error;
 
 	sa.insn = *(uint32_t *)(frame->tf_pc - INSN_SIZE);
+#ifndef __ARM_EABI__
+	/* TODO: Also add the above line when we don't need it in the EABI case */
 	switch (sa.insn & SWI_OS_MASK) {
 	case 0: /* XXX: we need our own one. */
-		sa.nap = 4;
 		break;
 	default:
 		call_trapsignal(td, SIGILL, 0);
 		userret(td, frame);
 		return;
 	}
+#endif
+	sa.nap = 4;
 
 	error = syscallenter(td, &sa);
 	KASSERT(error != 0 || td->td_ar == NULL,
Index: sys/arm/include/proc.h
===================================================================
--- sys/arm/include/proc.h	(.../head)	(revision 243940)
+++ sys/arm/include/proc.h	(.../projects/arm_eabi)	(revision 243946)
@@ -60,7 +60,11 @@ struct mdproc {
 	void	*md_sigtramp;
 };
 
+#ifdef __ARM_EABI__
+#define	KINFO_PROC_SIZE 816
+#else
 #define	KINFO_PROC_SIZE 792
+#endif
 
 #define MAXARGS	8
 struct syscall_args {
Index: sys/conf/ldscript.arm
===================================================================
--- sys/conf/ldscript.arm	(.../head)	(revision 243940)
+++ sys/conf/ldscript.arm	(.../projects/arm_eabi)	(revision 243946)
@@ -56,6 +56,18 @@ SECTIONS
   .init          : { *(.init)	} =0x9090
   .plt      : { *(.plt)	}
 
+  _extab_start = .;
+  PROVIDE(extab_start = .);
+  .ARM.extab : { *(.ARM.extab) }
+  _extab.end = .;
+  PROVIDE(extab_end = .);
+
+  _exidx_start = .;
+  PROVIDE(exidx_start = .);
+  .ARM.exidx : { *(.ARM.exidx) }
+  _exidx_end = .;
+  PROVIDE(exidx_end = .);
+
   /* Adjust the address for the data segment.  We want to adjust up to
      the same address within the page on the next page up.  */
   . = ALIGN(0x1000) + (. & (0x1000 - 1)) ; 
Index: sys/conf/Makefile.arm
===================================================================
--- sys/conf/Makefile.arm	(.../head)	(revision 243940)
+++ sys/conf/Makefile.arm	(.../projects/arm_eabi)	(revision 243946)
@@ -41,6 +41,8 @@ STRIP_FLAGS = -S
 
 .if empty(DDB_ENABLED)
 CFLAGS += -mno-apcs-frame
+.else
+CFLAGS += -funwind-tables
 .endif
 
 SYSTEM_LD_ = ${LD} -Bdynamic -T ldscript.$M.noheader ${LDFLAGS} \
Index: sys/conf/files.arm
===================================================================
--- sys/conf/files.arm	(.../head)	(revision 243940)
+++ sys/conf/files.arm	(.../projects/arm_eabi)	(revision 243946)
@@ -72,6 +75,8 @@ font.h				optional	sc			\
 kern/subr_dummy_vdso_tc.c	standard
 libkern/arm/divsi3.S		standard
 libkern/arm/ffs.S		standard
+libkern/arm/ldivmod.S		standard
+libkern/arm/ldivmod_helper.c	standard
 libkern/arm/muldi3.c		standard
 libkern/ashldi3.c		standard
 libkern/ashrdi3.c		standard
Index: sys/boot/arm/uboot/Makefile
===================================================================
--- sys/boot/arm/uboot/Makefile	(.../head)	(revision 243940)
+++ sys/boot/arm/uboot/Makefile	(.../projects/arm_eabi)	(revision 243946)
@@ -109,8 +109,8 @@ CFLAGS+=	-I${.OBJDIR}/../../uboot/lib
 # where to get libstand from
 CFLAGS+=	-I${.CURDIR}/../../../../lib/libstand/
 
-DPADD=		${LIBFICL} ${LIBUBOOT} ${LIBFDT} ${LIBSTAND}
-LDADD=		${LIBFICL} ${LIBUBOOT} ${LIBFDT} -lstand
+DPADD=		${LIBFICL} ${LIBUBOOT} ${LIBFDT} ${LIBSTAND} ${LIBGCC}
+LDADD=		${LIBFICL} ${LIBUBOOT} ${LIBFDT} -lstand -lgcc
 
 vers.c:	${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version
 	sh ${.CURDIR}/../../common/newvers.sh ${.CURDIR}/version ${NEWVERSWHAT}
Index: sys/libkern/arm/ldivmod_helper.c
===================================================================
--- sys/libkern/arm/ldivmod_helper.c	(.../head)	(revision 0)
+++ sys/libkern/arm/ldivmod_helper.c	(.../projects/arm_eabi)	(revision 243946)
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2012 Andrew Turner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <libkern/quad.h>
+
+/*
+ * Helper for __aeabi_ldivmod.
+ * TODO: __divdi3 calls __qdivrem. We should do the same and use the
+ * remainder value rather than re-calculating it.
+ */
+long long __kern_ldivmod(long long, long long, long long *);
+
+long long
+__kern_ldivmod(long long n, long long m, long long *rem)
+{
+	long long q;
+
+	q = __divdi3(n, m);	/* q = n / m */
+	*rem = n - m * q;
+
+	return q;
+}
+
Index: sys/libkern/arm/ldivmod.S
===================================================================
--- sys/libkern/arm/ldivmod.S	(.../head)	(revision 0)
+++ sys/libkern/arm/ldivmod.S	(.../projects/arm_eabi)	(revision 243946)
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2012 Andrew Turner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * These calculate:
+ * q = n / m 
+ * With a remainer r.
+ *
+ * They take n in {r0, r1} and m in {r2, r3} then pass them into the
+ * helper function. The hepler functions return q in {r0, r1} as
+ * required by the API spec however r is returned on the stack. The
+ * ABI required us to return r in {r2, r3}.
+ *
+ * We need to allocate 8 bytes on the stack to store r, the link
+ * register, and a pointer to the space where the helper function
+ * will write r to. After returning from the helper fuinction we load
+ * the old link register and r from the stack and return.
+ */
+ENTRY_NP(__aeabi_ldivmod)
+	sub	sp, sp, #8	/* Space for the remainder */
+	stmfd	sp!, {sp, lr}	/* Save a pointer to the above space and lr */
+	bl	PIC_SYM(_C_LABEL(__kern_ldivmod), PLT)
+	ldr	lr, [sp, #4]	/* Restore lr */
+	add	sp, sp, #8	/* Move sp to the remainder value */
+	ldmfd	sp!, {r2, r3}	/* Load the remainder */
+	RET
+
+ENTRY_NP(__aeabi_uldivmod)
+	sub	sp, sp, #8	/* Space for the remainder */
+	stmfd	sp!, {sp, lr}	/* Save a pointer to the above space and lr */
+	bl	PIC_SYM(_C_LABEL(__qdivrem), PLT)
+	ldr	lr, [sp, #4]	/* Restore lr */
+	add	sp, sp, #8	/* Move sp to the remainder value */
+	ldmfd	sp!, {r2, r3}	/* Load the remainder */
+	RET
+
Index: sys/libkern/arm/divsi3.S
===================================================================
--- sys/libkern/arm/divsi3.S	(.../head)	(revision 243940)
+++ sys/libkern/arm/divsi3.S	(.../projects/arm_eabi)	(revision 243946)
@@ -49,6 +49,10 @@ ENTRY_NP(__modsi3)
 #endif
 	RET
 
+#ifdef __ARM_EABI__
+ENTRY_NP(__aeabi_uidiv)
+ENTRY_NP(__aeabi_uidivmod)
+#endif
 ENTRY_NP(__udivsi3)
 .L_udivide:				/* r0 = r0 / r1; r1 = r0 % r1 */
 	eor     r0, r1, r0 
@@ -71,6 +75,10 @@ ENTRY_NP(__udivsi3)
 	mov	r1, #0
 	RET
 
+#ifdef __ARM_EABI__
+ENTRY_NP(__aeabi_idiv)
+ENTRY_NP(__aeabi_idivmod)
+#endif
 ENTRY_NP(__divsi3)
 .L_divide:				/* r0 = r0 / r1; r1 = r0 % r1 */
 	eor     r0, r1, r0 
Index: usr.bin/tr/tr.c
===================================================================
--- usr.bin/tr/tr.c	(.../head)	(revision 243940)
+++ usr.bin/tr/tr.c	(.../projects/arm_eabi)	(revision 243946)
@@ -47,6 +47,7 @@ static const char sccsid[] = "@(#)tr.c	8
 #include <err.h>
 #include <limits.h>
 #include <locale.h>
+#include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -267,7 +268,7 @@ endloop:
 		 */
 		s2.str = argv[1];
 		s2.state = NORMAL;
-		for (cnt = 0; cnt < WCHAR_MAX; cnt++) {
+		for (cnt = 0; cnt < WINT_MAX; cnt++) {
 			if (Cflag && !iswrune(cnt))
 				continue;
 			if (cmap_lookup(map, cnt) == OOBCH) {
Index: usr.bin/ul/ul.c
===================================================================
--- usr.bin/ul/ul.c	(.../head)	(revision 243940)
+++ usr.bin/ul/ul.c	(.../projects/arm_eabi)	(revision 243946)
@@ -280,7 +280,7 @@ filter(FILE *f)
 			obuf[col].c_width = w;
 			for (i = 1; i < w; i++)
 				obuf[col + i].c_width = -1;
-		} else if (obuf[col].c_char == c) {
+		} else if ((wint_t)obuf[col].c_char == c) {
 			for (i = 0; i < w; i++)
 				obuf[col + i].c_mode |= BOLD|mode;
 		} else {
Index: gnu/lib/libgcc/Makefile
===================================================================
--- gnu/lib/libgcc/Makefile	(.../head)	(revision 243940)
+++ gnu/lib/libgcc/Makefile	(.../projects/arm_eabi)	(revision 243946)
@@ -15,6 +15,10 @@ MK_SSP=	no
 
 .include "${.CURDIR}/../../usr.bin/cc/Makefile.tgt"
 
+.if ${TARGET_CPUARCH} == "arm" && ${MK_ARM_EABI} != "no"
+CFLAGS+=	-DTARGET_ARM_EABI
+.endif
+
 .if ${TARGET_CPUARCH} == "mips"
 LIB=		gcc
 .endif
@@ -52,10 +56,13 @@ LIB2FUNCS+= _fixuns${mode}si
 .endfor
 
 # Likewise double-word routines.
+.if ${TARGET_CPUARCH} != "arm" && ${MK_ARM_EABI} != "no"
+# These are implemented in an ARM specific file but will not be filtered out
 .for mode in sf df xf tf
 LIB2FUNCS+= _fix${mode}di _fixuns${mode}di
 LIB2FUNCS+= _floatdi${mode} _floatundi${mode}
 .endfor
+.endif
 
 LIB2ADD = $(LIB2FUNCS_EXTRA)
 LIB2ADD_ST = $(LIB2FUNCS_STATIC_EXTRA)
@@ -108,15 +115,14 @@ LIB2_DIVMOD_FUNCS = _divdi3 _moddi3 _udi
 CFLAGS+=	-Dinhibit_libc -fno-inline
 LIB1ASMSRC =	lib1funcs.asm
 LIB1ASMFUNCS =  _dvmd_tls _bb_init_func
-LIB2FUNCS_EXTRA = floatunsidf.c floatunsisf.c
+.if ${MK_ARM_EABI} != "no"
+LIB1ASMFUNCS+=	_addsubdf3 _addsubsf3 _cmpdf2 _cmpsf2 _fixdfsi _fixsfsi \
+		_fixunsdfsi _fixunsdfsi _muldivdf3 _muldivsf3 _udivsi3
 
-# Not now
-#LIB1ASMFUNCS =  _udivsi3 _divsi3 _umodsi3 _modsi3 _dvmd_tls _bb_init_func
-#LIB1ASMFUNCS+=	_call_via_rX _interwork_call_via_rX \
-#	_lshrdi3 _ashrdi3 _ashldi3 \
-#	_negdf2 _addsubdf3 _muldivdf3 _cmpdf2 _unorddf2 _fixdfsi _fixunsdfsi \
-#	_truncdfsf2 _negsf2 _addsubsf3 _muldivsf3 _cmpsf2 _unordsf2 \
-#	_fixsfsi _fixunssfsi _floatdidf _floatdisf
+LIB2ADDEH =	unwind-arm.c libunwind.S pr-support.c unwind-c.c
+.else
+LIB2FUNCS_EXTRA = floatunsidf.c floatunsisf.c
+.endif
 .endif
 
 .if ${TARGET_CPUARCH} == mips
@@ -322,6 +328,9 @@ CLEANFILES += cs-*.h option*
 SHLIB_MKMAP      = ${GCCDIR}/mkmap-symver.awk
 SHLIB_MKMAP_OPTS =
 SHLIB_MAPFILES   = ${GCCDIR}/libgcc-std.ver
+.if ${TARGET_CPUARCH} == "arm" && ${MK_ARM_EABI} != "no"
+SHLIB_MAPFILES  += ${GCCDIR}/config/arm/libgcc-bpabi.ver
+.endif
 VERSION_MAP      = libgcc.map
 
 libgcc.map: ${SHLIB_MKMAP} ${SHLIB_MAPFILES} ${SOBJS} ${OBJS:R:S/$/.So/}
Index: gnu/lib/libgcov/Makefile
===================================================================
--- gnu/lib/libgcov/Makefile	(.../head)	(revision 243940)
+++ gnu/lib/libgcov/Makefile	(.../projects/arm_eabi)	(revision 243946)
@@ -15,6 +15,11 @@ CFLAGS+=	-DIN_GCC -DIN_LIBGCC2 -D__GCC_F
 CFLAGS+=	-D_PTHREADS -DGTHREAD_USE_WEAK
 CFLAGS+=	-I${.CURDIR}/../../usr.bin/cc/cc_tools \
 		-I${GCCLIB}/include -I${GCCDIR}/config -I${GCCDIR} -I.
+
+.if ${TARGET_CPUARCH} == "arm" && ${MK_ARM_EABI} != "no"
+CFLAGS+=	-DTARGET_ARM_EABI
+.endif
+
 #
 # Library members defined in libgcov.c.
 # Defined in libgcov.c, included only in gcov library
Index: gnu/lib/csu/Makefile
===================================================================
--- gnu/lib/csu/Makefile	(.../head)	(revision 243940)
+++ gnu/lib/csu/Makefile	(.../projects/arm_eabi)	(revision 243946)
@@ -24,6 +24,10 @@ CFLAGS+=	-I${GCCLIB}/include -I${GCCDIR}
 CRTS_CFLAGS=	-DCRTSTUFFS_O -DSHARED ${PICFLAG}
 MKDEP=		-DCRT_BEGIN
 
+.if ${TARGET_CPUARCH} == "arm" && ${MK_ARM_EABI} != "no"
+CFLAGS+=	-DTARGET_ARM_EABI
+.endif
+
 .if ${MACHINE_CPUARCH} == "ia64"
 BEGINSRC=	crtbegin.asm
 ENDSRC=		crtend.asm
Index: gnu/lib/libstdc++/Makefile
===================================================================
--- gnu/lib/libstdc++/Makefile	(.../head)	(revision 243940)
+++ gnu/lib/libstdc++/Makefile	(.../projects/arm_eabi)	(revision 243946)
@@ -1,5 +1,7 @@
 # $FreeBSD$
 
+.include <bsd.own.mk>
+
 GCCVER=	4.2
 GCCDIR=	${.CURDIR}/../../../contrib/gcc
 GCCLIB=	${.CURDIR}/../../../contrib/gcclibs
@@ -14,7 +16,7 @@ LIB=		stdc++
 SHLIB_MAJOR=	6
 
 CFLAGS+=	-DIN_GLIBCPP_V3 -DHAVE_CONFIG_H
-.if ${MACHINE_CPUARCH} == "arm"
+.if ${MACHINE_CPUARCH} == "arm" && ${MK_ARM_EABI} == "no"
 CFLAGS+=	-D_GLIBCXX_SJLJ_EXCEPTIONS=1
 .endif
 CFLAGS+=	-I${.CURDIR} -I${SUPDIR} -I${GCCDIR} -I${SRCDIR}/include
@@ -594,7 +596,13 @@ gthr-default.h: ${GCCDIR}/gthr-posix.h
 
 CLEANFILES+=	${THRHDRS}
 
+.if ${MACHINE_CPUARCH} == "arm" && ${MK_ARM_EABI} != "no"
+unwind.h: ${GCCDIR}/config/arm/unwind-arm.h
+.else
 unwind.h: ${GCCDIR}/unwind-generic.h
+.endif
+
+unwind.h:
 	ln -sf ${.ALLSRC} ${.TARGET}
 
 SRCS+=		unwind.h
Index: gnu/usr.bin/cc/c++filt/Makefile
===================================================================
--- gnu/usr.bin/cc/c++filt/Makefile	(.../head)	(revision 243940)
+++ gnu/usr.bin/cc/c++filt/Makefile	(.../projects/arm_eabi)	(revision 243946)
@@ -1,5 +1,8 @@
 # $FreeBSD$
 
+NO_MAN=
+.include <bsd.own.mk>
+
 .include "../Makefile.inc"
 .include "../Makefile.fe"
 
@@ -7,7 +10,6 @@
 
 PROG=	c++filt
 SRCS=	cp-demangle.c
-NO_MAN=
 
 CFLAGS+= -DSTANDALONE_DEMANGLER -DVERSION=\"$(GCC_VERSION)\"
 
Index: gnu/usr.bin/cc/libdecnumber/Makefile
===================================================================
--- gnu/usr.bin/cc/libdecnumber/Makefile	(.../head)	(revision 243940)
+++ gnu/usr.bin/cc/libdecnumber/Makefile	(.../projects/arm_eabi)	(revision 243946)
@@ -1,5 +1,7 @@
 # $FreeBSD$
 
+.include <bsd.own.mk>
+
 # Use our headers in preference to ones from ../cc_tools.
 CFLAGS+=	-I${.CURDIR} -I.
 
Index: gnu/usr.bin/cc/gcov/Makefile
===================================================================
--- gnu/usr.bin/cc/gcov/Makefile	(.../head)	(revision 243940)
+++ gnu/usr.bin/cc/gcov/Makefile	(.../projects/arm_eabi)	(revision 243946)
@@ -1,5 +1,7 @@
 # $FreeBSD$
 
+.include <bsd.own.mk>
+
 .include "../Makefile.inc"
 .include "../Makefile.ver"
 
Index: gnu/usr.bin/cc/cc_int/Makefile
===================================================================
--- gnu/usr.bin/cc/cc_int/Makefile	(.../head)	(revision 243940)
+++ gnu/usr.bin/cc/cc_int/Makefile	(.../projects/arm_eabi)	(revision 243946)
@@ -1,5 +1,7 @@
 # $FreeBSD$
 
+.include <bsd.own.mk>
+
 .include "../Makefile.inc"
 .include "../Makefile.ver"
 
Index: gnu/usr.bin/cc/cc_tools/Makefile
===================================================================
--- gnu/usr.bin/cc/cc_tools/Makefile	(.../head)	(revision 243940)
+++ gnu/usr.bin/cc/cc_tools/Makefile	(.../projects/arm_eabi)	(revision 243946)
@@ -51,6 +51,9 @@ TARGET_INC+=	${GCC_CPU}/elf.h
 .endif
 .if ${TARGET_CPUARCH} == "arm"
 TARGET_INC+=	${GCC_CPU}/aout.h
+.if ${MK_ARM_EABI} != "no"
+TARGET_INC+=	${GCC_CPU}/bpabi.h
+.endif
 .endif
 .if ${TARGET_ARCH} == "powerpc64"
 TARGET_INC+=	${GCC_CPU}/biarch64.h
@@ -349,7 +352,13 @@ gthr-default.h: ${GCCDIR}/gthr-posix.h
 
 GENSRCS+=	gthr-default.h
 
+.if ${TARGET_CPUARCH} == "arm" && ${MK_ARM_EABI} != "no"
+unwind.h: ${GCCDIR}/config/arm/unwind-arm.h
+.else
 unwind.h: ${GCCDIR}/unwind-generic.h
+.endif
+
+unwind.h:
 	ln -sf ${.ALLSRC} ${.TARGET}
 
 GENSRCS+=	unwind.h
Index: gnu/usr.bin/cc/doc/Makefile
===================================================================
--- gnu/usr.bin/cc/doc/Makefile	(.../head)	(revision 243940)
+++ gnu/usr.bin/cc/doc/Makefile	(.../projects/arm_eabi)	(revision 243946)
@@ -1,5 +1,7 @@
 # $FreeBSD$
 
+.include <bsd.own.mk>
+
 .include "../Makefile.inc"
 .include "../Makefile.ver"
 
Index: gnu/usr.bin/cc/cc1/Makefile
===================================================================
--- gnu/usr.bin/cc/cc1/Makefile	(.../head)	(revision 243940)
+++ gnu/usr.bin/cc/cc1/Makefile	(.../projects/arm_eabi)	(revision 243946)
@@ -1,9 +1,10 @@
 # $FreeBSD$
 
-.include "../Makefile.inc"
 NO_MAN=
 .include <bsd.own.mk>
 
+.include "../Makefile.inc"
+
 .PATH: ${GCCDIR}
 
 PROG=	cc1
Index: gnu/usr.bin/cc/libcpp/Makefile
===================================================================
--- gnu/usr.bin/cc/libcpp/Makefile	(.../head)	(revision 243940)
+++ gnu/usr.bin/cc/libcpp/Makefile	(.../projects/arm_eabi)	(revision 243946)
@@ -1,5 +1,7 @@
 # $FreeBSD$
 
+.include <bsd.own.mk>
+
 # Use our headers in preference to ones from ../cc_tools.
 CFLAGS+=	-I${.CURDIR} -I.
 
Index: gnu/usr.bin/cc/cc1plus/Makefile
===================================================================
--- gnu/usr.bin/cc/cc1plus/Makefile	(.../head)	(revision 243940)
+++ gnu/usr.bin/cc/cc1plus/Makefile	(.../projects/arm_eabi)	(revision 243946)
@@ -1,9 +1,10 @@
 # $FreeBSD$
 
-.include "../Makefile.inc"
 NO_MAN=
 .include <bsd.own.mk>
 
+.include "../Makefile.inc"
+
 .PATH: ${GCCDIR}/cp ${GCCDIR}
 
 PROG=	cc1plus
Index: gnu/usr.bin/cc/include/Makefile
===================================================================
--- gnu/usr.bin/cc/include/Makefile	(.../head)	(revision 243940)
+++ gnu/usr.bin/cc/include/Makefile	(.../projects/arm_eabi)	(revision 243946)
@@ -1,5 +1,7 @@
 # $FreeBSD$
 
+.include <bsd.own.mk>
+
 .include "../Makefile.inc"
 
 INCSDIR=${INCLUDEDIR}/gcc/${GCCVER}
Index: gnu/usr.bin/cc/libiberty/Makefile
===================================================================
--- gnu/usr.bin/cc/libiberty/Makefile	(.../head)	(revision 243940)
+++ gnu/usr.bin/cc/libiberty/Makefile	(.../projects/arm_eabi)	(revision 243946)
@@ -1,5 +1,7 @@
 # $FreeBSD$
 
+.include <bsd.own.mk>
+
 #
 # Make sure we will pick up our config.h file first, not the one from
 # cc_tools.
Index: gnu/usr.bin/cc/Makefile.inc
===================================================================
--- gnu/usr.bin/cc/Makefile.inc	(.../head)	(revision 243940)
+++ gnu/usr.bin/cc/Makefile.inc	(.../projects/arm_eabi)	(revision 243946)
@@ -26,6 +26,10 @@ CSTD?=	gnu89
 CFLAGS+=	-DCROSS_COMPILE
 .endif
 
+.if ${TARGET_CPUARCH} == "arm" && ${MK_ARM_EABI} != "no"
+CFLAGS+=	-DTARGET_ARM_EABI
+.endif
+
 .if ${TARGET_ARCH} == "armeb" || ${TARGET_ARCH} == "armv6eb"
 CFLAGS += -DTARGET_ENDIAN_DEFAULT=MASK_BIG_END
 .endif
Index: gnu/usr.bin/binutils/ld/armelfb_fbsd.sh
===================================================================
--- gnu/usr.bin/binutils/ld/armelfb_fbsd.sh	(.../head)	(revision 243940)
+++ gnu/usr.bin/binutils/ld/armelfb_fbsd.sh	(.../projects/arm_eabi)	(revision 243946)
@@ -5,6 +5,7 @@
 #OUTPUT_FORMAT="elf32-bigarm"
 . ${srcdir}/emulparams/armelf.sh
 . ${srcdir}/emulparams/elf_fbsd.sh
+TARGET2_TYPE=got-rel
 MAXPAGESIZE=0x8000
 GENERATE_PIE_SCRIPT=yes
 
Index: gnu/usr.bin/binutils/ld/armelf_fbsd.sh
===================================================================
--- gnu/usr.bin/binutils/ld/armelf_fbsd.sh	(.../head)	(revision 243940)
+++ gnu/usr.bin/binutils/ld/armelf_fbsd.sh	(.../projects/arm_eabi)	(revision 243946)
@@ -1,6 +1,7 @@
 # $FreeBSD$
 . ${srcdir}/emulparams/armelf.sh
 . ${srcdir}/emulparams/elf_fbsd.sh
+TARGET2_TYPE=got-rel
 MAXPAGESIZE=0x8000
 GENERATE_PIE_SCRIPT=yes
 
Index: tools/build/options/WITHOUT_ARM_EABI
===================================================================
--- tools/build/options/WITHOUT_ARM_EABI	(.../head)	(revision 0)
+++ tools/build/options/WITHOUT_ARM_EABI	(.../projects/arm_eabi)	(revision 243946)
@@ -0,0 +1,2 @@
+.\" $FreeBSD$
+Set the ARM ABI to EABI.
Index: contrib/gcc/config/arm/freebsd.h
===================================================================
--- contrib/gcc/config/arm/freebsd.h	(.../head)	(revision 243940)
+++ contrib/gcc/config/arm/freebsd.h	(.../projects/arm_eabi)	(revision 243946)
@@ -29,8 +29,13 @@
   { "fbsd_dynamic_linker", FBSD_DYNAMIC_LINKER }
 
 #undef SUBTARGET_EXTRA_ASM_SPEC
+#ifdef TARGET_ARM_EABI
+#define SUBTARGET_EXTRA_ASM_SPEC	\
+  "%{mabi=apcs-gnu|mabi=atpcs:-meabi=gnu;:-meabi=4} %{fpic|fpie:-k} %{fPIC|fPIE:-k}"
+#else
 #define SUBTARGET_EXTRA_ASM_SPEC	\
   "-matpcs %{fpic|fpie:-k} %{fPIC|fPIE:-k}"
+#endif
 
 /* Default to full FPA if -mhard-float is specified. */
 #undef SUBTARGET_ASM_FLOAT_SPEC
@@ -56,11 +61,28 @@
 
 /************************[  Target stuff  ]***********************************/
 
-
 #ifndef TARGET_ENDIAN_DEFAULT
 #define TARGET_ENDIAN_DEFAULT 0
 #endif
 
+#ifdef TARGET_ARM_EABI
+/* We default to a soft-float ABI so that binaries can run on all
+   target hardware.  */
+#undef TARGET_DEFAULT_FLOAT_ABI
+#define TARGET_DEFAULT_FLOAT_ABI ARM_FLOAT_ABI_SOFT
+
+#undef ARM_DEFAULT_ABI
+#define ARM_DEFAULT_ABI ARM_ABI_AAPCS_LINUX
+
+#undef  TARGET_OS_CPP_BUILTINS
+#define TARGET_OS_CPP_BUILTINS() 		\
+  do						\
+    {						\
+      FBSD_TARGET_OS_CPP_BUILTINS();		\
+      TARGET_BPABI_CPP_BUILTINS();		\
+    }						\
+  while (false)
+#else
 /* Default it to use ATPCS with soft-VFP.  */
 #undef TARGET_DEFAULT
 #define TARGET_DEFAULT			\
@@ -70,6 +92,10 @@
 #undef ARM_DEFAULT_ABI
 #define ARM_DEFAULT_ABI ARM_ABI_ATPCS
 
+#undef FPUTYPE_DEFAULT
+#define FPUTYPE_DEFAULT FPUTYPE_VFP
+#endif
+
 /* Define the actual types of some ANSI-mandated types.
    Needs to agree with <machine/ansi.h>.  GCC defaults come from c-decl.c,
    c-common.c, and config/<arch>/<arch>.h.  */
@@ -97,7 +123,7 @@
 #define TARGET_VERSION fprintf (stderr, " (FreeBSD/armv6 ELF)");
 #else
 #undef  SUBTARGET_CPU_DEFAULT
-#define SUBTARGET_CPU_DEFAULT	TARGET_CPU_strongarm
+#define SUBTARGET_CPU_DEFAULT	TARGET_CPU_arm9
 #undef  TARGET_VERSION
 #define TARGET_VERSION fprintf (stderr, " (FreeBSD/StrongARM ELF)");
 #endif
@@ -134,5 +160,3 @@ do									\
   }									\
 while (0)
 
-#undef FPUTYPE_DEFAULT
-#define FPUTYPE_DEFAULT FPUTYPE_VFP
Index: contrib/compiler-rt/lib/ucmpdi2.c
===================================================================
--- contrib/compiler-rt/lib/ucmpdi2.c	(.../head)	(revision 243940)
+++ contrib/compiler-rt/lib/ucmpdi2.c	(.../projects/arm_eabi)	(revision 243946)
@@ -36,3 +36,13 @@ __ucmpdi2(du_int a, du_int b)
         return 2;
     return 1;
 }
+
+#ifdef __ARM_EABI__
+/* Returns (-1, 0, 1) for (<, ==, >) */
+COMPILER_RT_ABI si_int
+__aeabi_ulcmp(di_int a, di_int b)
+{
+	return __ucmpdi2(a, b) - 1;
+}
+#endif
+
Index: contrib/compiler-rt/lib/int_lib.h
===================================================================
--- contrib/compiler-rt/lib/int_lib.h	(.../head)	(revision 243940)
+++ contrib/compiler-rt/lib/int_lib.h	(.../projects/arm_eabi)	(revision 243946)
@@ -25,7 +25,14 @@
 #if __ARM_EABI__
 # define ARM_EABI_FNALIAS(aeabi_name, name)         \
   void __aeabi_##aeabi_name() __attribute__((alias("__" #name)));
-# define COMPILER_RT_ABI __attribute__((pcs("aapcs")))
+
+# if defined(__GNUC__) && (__GNUC__ < 4 || __GNUC__ == 4 && __GNUC_MINOR__ < 5)
+/* The pcs attribute was introduced in GCC 4.5.0 */
+#  define COMPILER_RT_ABI
+# else
+#  define COMPILER_RT_ABI __attribute__((pcs("aapcs")))
+# endif
+
 #else
 # define ARM_EABI_FNALIAS(aeabi_name, name)
 # define COMPILER_RT_ABI
Index: contrib/compiler-rt/lib/fixsfdi.c
===================================================================
--- contrib/compiler-rt/lib/fixsfdi.c	(.../head)	(revision 243940)
+++ contrib/compiler-rt/lib/fixsfdi.c	(.../projects/arm_eabi)	(revision 243946)
@@ -23,7 +23,7 @@
 
 /* seee eeee emmm mmmm mmmm mmmm mmmm mmmm */
 
-ARM_EABI_FNALIAS(d2lz, fixsfdi)
+ARM_EABI_FNALIAS(f2lz, fixsfdi)
 
 COMPILER_RT_ABI di_int
 __fixsfdi(float a)
Index: contrib/compiler-rt/lib/cmpdi2.c
===================================================================
--- contrib/compiler-rt/lib/cmpdi2.c	(.../head)	(revision 243940)
+++ contrib/compiler-rt/lib/cmpdi2.c	(.../projects/arm_eabi)	(revision 243946)
@@ -36,3 +36,13 @@ __cmpdi2(di_int a, di_int b)
         return 2;
     return 1;
 }
+
+#ifdef __ARM_EABI__
+/* Returns (-1, 0, 1) for (<, ==, >) */
+COMPILER_RT_ABI si_int
+__aeabi_lcmp(di_int a, di_int b)
+{
+	return __cmpdi2(a, b) - 1;
+}
+#endif
+
Index: contrib/libstdc++/include/std/std_limits.h
===================================================================
--- contrib/libstdc++/include/std/std_limits.h	(.../head)	(revision 243940)
+++ contrib/libstdc++/include/std/std_limits.h	(.../projects/arm_eabi)	(revision 243946)
@@ -134,10 +134,11 @@
 #define __glibcxx_signed(T)	((T)(-1) < 0)
 
 #define __glibcxx_min(T) \
-  (__glibcxx_signed (T) ? (T)1 << __glibcxx_digits (T) : (T)0)
+  (__glibcxx_signed (T) ? (((T)1 << (__glibcxx_digits (T) - 1)) << 1) : (T)0)
 
 #define __glibcxx_max(T) \
-  (__glibcxx_signed (T) ? ((T)1 << __glibcxx_digits (T)) - 1 : ~(T)0)
+  (__glibcxx_signed (T) ? \
+   (((((T)1 << (__glibcxx_digits (T) - 1)) - 1) << 1) + 1) : ~(T)0)
 
 #define __glibcxx_digits(T) \
   (sizeof(T) * __CHAR_BIT__ - __glibcxx_signed (T))
Index: share/mk/bsd.own.mk
===================================================================
--- share/mk/bsd.own.mk	(.../head)	(revision 243940)
+++ share/mk/bsd.own.mk	(.../projects/arm_eabi)	(revision 243946)
@@ -304,6 +304,7 @@ __DEFAULT_YES_OPTIONS = \
     ACPI \
     AMD \
     APM \
+    ARM_EABI \
     ASSERT_DEBUG \
     AT \
     ATF \
Index: lib/libcompiler_rt/Makefile
===================================================================
--- lib/libcompiler_rt/Makefile	(.../head)	(revision 243940)
+++ lib/libcompiler_rt/Makefile	(.../projects/arm_eabi)	(revision 243946)
@@ -132,18 +132,23 @@ SRCF+=	adddf3 \
 	addsf3 \
 	divdf3 \
 	divsf3 \
-	divsi3 \
 	extendsfdf2 \
 	fixdfsi \
 	fixsfsi \
 	floatsidf \
 	floatsisf \
-	modsi3 \
 	muldf3 \
 	mulsf3 \
 	subdf3 \
 	subsf3 \
-	truncdfsf2 \
+	truncdfsf2
+.endif
+
+# TODO: Fix this logic for !mips, !arm oabi
+.if ${MACHINE_CPUARCH} != "mips" && \
+    (${MACHINE_CPUARCH} != "arm" || ${MK_ARM_EABI} != "no")
+SRCF+=	divsi3 \
+	modsi3 \
 	udivsi3 \
 	umodsi3
 .endif
@@ -176,6 +181,13 @@ SRCS+=	${file}.c
 . endif
 .endfor
 
+.if ${MACHINE_CPUARCH} == "arm" && ${MK_ARM_EABI} != "no"
+SRCS+=	aeabi_idivmod.S \
+	aeabi_ldivmod.S \
+	aeabi_uidivmod.S \
+	aeabi_uldivmod.S
+.endif
+
 .if ${MACHINE_CPUARCH} != "mips"
 . if ${MK_INSTALLLIB} != "no"
 SYMLINKS+=libcompiler_rt.a ${LIBDIR}/libgcc.a
Index: lib/libc/arm/Symbol.map
===================================================================
--- lib/libc/arm/Symbol.map	(.../head)	(revision 243940)
+++ lib/libc/arm/Symbol.map	(.../projects/arm_eabi)	(revision 243946)
@@ -46,10 +46,6 @@ FBSDprivate_1.0 {
 	_set_tp;
 	__aeabi_read_tp;
 	___longjmp;
-	__umodsi3;
-	__modsi3;
-	__udivsi3;
-	__divsi3;
 	__makecontext;
 	__longjmp;
 	signalcontext;
Index: lib/libc/arm/aeabi/aeabi_unwind_cpp.c
===================================================================
--- lib/libc/arm/aeabi/aeabi_unwind_cpp.c	(.../head)	(revision 0)
+++ lib/libc/arm/aeabi/aeabi_unwind_cpp.c	(.../projects/arm_eabi)	(revision 243946)
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2011 Andrew Turner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+/*
+ * Provide an implementation of __aeabi_unwind_cpp_pr{0,1,2}. These are
+ * required by libc but are implemented in libgcc_eh.a which we don't link
+ * against. The libgcc_eh.a version will be called so we call abort to
+ * check this.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+
+void __aeabi_unwind_cpp_pr0(void) __hidden;
+void __aeabi_unwind_cpp_pr1(void) __hidden;
+void __aeabi_unwind_cpp_pr2(void) __hidden;
+
+void
+__aeabi_unwind_cpp_pr0(void)
+{
+	abort();
+}
+
+void
+__aeabi_unwind_cpp_pr1(void)
+{
+	abort();
+}
+
+void
+__aeabi_unwind_cpp_pr2(void)
+{
+	abort();
+}
+
Index: lib/libc/arm/aeabi/aeabi_double.c
===================================================================
--- lib/libc/arm/aeabi/aeabi_double.c	(.../head)	(revision 0)
+++ lib/libc/arm/aeabi/aeabi_double.c	(.../projects/arm_eabi)	(revision 243946)
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2012 Andrew Turner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "softfloat-for-gcc.h"
+#include "milieu.h"
+#include "softfloat.h"
+
+flag __unorddf2(float64, float64);
+
+int __aeabi_dcmpeq(float64 a, float64 b)
+{
+	return float64_eq(a, b);
+}
+
+int __aeabi_dcmplt(float64 a, float64 b)
+{
+	return float64_lt(a, b);
+}
+
+int __aeabi_dcmple(float64 a, float64 b)
+{
+	return float64_le(a, b);
+}
+
+int __aeabi_dcmpge(float64 a, float64 b)
+{
+	return float64_le(b, a);
+}
+
+int __aeabi_dcmpgt(float64 a, float64 b)
+{
+	return float64_lt(b, a);
+}
+
+int __aeabi_dcmpun(float64 a, float64 b)
+{
+	return __unorddf2(a, b);
+}
+
+int __aeabi_d2iz(float64 a)
+{
+	return float64_to_int32_round_to_zero(a);
+}
+
+float32 __aeabi_d2f(float64 a)
+{
+	return float64_to_float32(a);
+}
+
+float64 __aeabi_i2d(int a)
+{
+	return int32_to_float64(a);
+}
+
+float64 __aeabi_dadd(float64 a, float64 b)
+{
+	return float64_add(a, b);
+}
+
+float64 __aeabi_ddiv(float64 a, float64 b)
+{
+	return float64_div(a, b);
+}
+
+float64 __aeabi_dmul(float64 a, float64 b)
+{
+	return float64_mul(a, b);
+}
+
+float64 __aeabi_dsub(float64 a, float64 b)
+{
+	return float64_sub(a, b);
+}
+
Index: lib/libc/arm/aeabi/aeabi_atexit.c
===================================================================
--- lib/libc/arm/aeabi/aeabi_atexit.c	(.../head)	(revision 0)
+++ lib/libc/arm/aeabi/aeabi_atexit.c	(.../projects/arm_eabi)	(revision 243946)
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2012 Andrew Turner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+int __cxa_atexit(void (*)(void *), void *, void *);
+
+int
+__aeabi_atexit(void *object, void (*func)(void*), void *dso)
+{
+	return __cxa_atexit(func, object, dso);
+}
+
Index: lib/libc/arm/aeabi/Symbol.map
===================================================================
--- lib/libc/arm/aeabi/Symbol.map	(.../head)	(revision 0)
+++ lib/libc/arm/aeabi/Symbol.map	(.../projects/arm_eabi)	(revision 243946)
@@ -0,0 +1,47 @@
+/*
+ * $FreeBSD: projects/arm_eabi/lib/libc/arm/Symbol.map 228591 2011-12-16 19:38:31Z andrew $
+ */
+
+/*
+ * This only needs to contain AEABI symbols that are not listed in
+ * symbol maps from other parts of libc (i.e., not found in
+ * stdlib/Symbol.map, string/Symbol.map, sys/Symbol.map, ...).
+ */
+FBSDprivate_1.0 {
+	__aeabi_atexit;
+
+	__aeabi_dcmpeq;
+	__aeabi_dcmplt;
+	__aeabi_dcmple;
+	__aeabi_dcmpge;
+	__aeabi_dcmpgt;
+	__aeabi_dcmpun;
+
+	__aeabi_d2iz;
+	__aeabi_d2f;
+
+	__aeabi_dadd;
+	__aeabi_ddiv;
+	__aeabi_dmul;
+	__aeabi_dsub;
+
+
+	__aeabi_fcmpeq;
+	__aeabi_fcmplt;
+	__aeabi_fcmple;
+	__aeabi_fcmpge;
+	__aeabi_fcmpgt;
+	__aeabi_fcmpun;
+
+	__aeabi_f2iz;
+	__aeabi_f2d;
+
+	__aeabi_fadd;
+	__aeabi_fdiv;
+	__aeabi_fmul;
+	__aeabi_fsub;
+
+
+	__aeabi_i2d;
+	__aeabi_i2f;
+};
Index: lib/libc/arm/aeabi/Makefile.inc
===================================================================
--- lib/libc/arm/aeabi/Makefile.inc	(.../head)	(revision 0)
+++ lib/libc/arm/aeabi/Makefile.inc	(.../projects/arm_eabi)	(revision 243946)
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/arm/aeabi
+
+SRCS+=	aeabi_atexit.c		\
+	aeabi_double.c		\
+	aeabi_float.c		\
+	aeabi_unwind_cpp.c
+
+SYM_MAPS+=${.CURDIR}/arm/aeabi/Symbol.map
+
Index: lib/libc/arm/aeabi/aeabi_float.c
===================================================================
--- lib/libc/arm/aeabi/aeabi_float.c	(.../head)	(revision 0)
+++ lib/libc/arm/aeabi/aeabi_float.c	(.../projects/arm_eabi)	(revision 243946)
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2012 Andrew Turner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "softfloat-for-gcc.h"
+#include "milieu.h"
+#include "softfloat.h"
+
+flag __unordsf2(float32, float32);
+
+int __aeabi_fcmpeq(float32 a, float32 b)
+{
+	return float32_eq(a, b);
+}
+
+int __aeabi_fcmplt(float32 a, float32 b)
+{
+	return float32_lt(a, b);
+}
+
+int __aeabi_fcmple(float32 a, float32 b)
+{
+	return float32_le(a, b);
+}
+
+int __aeabi_fcmpge(float32 a, float32 b)
+{
+	return float32_le(b, a);
+}
+
+int __aeabi_fcmpgt(float32 a, float32 b)
+{
+	return float32_lt(b, a);
+}
+
+int __aeabi_fcmpun(float32 a, float32 b)
+{
+	return __unordsf2(a, b);
+}
+
+int __aeabi_f2iz(float32 a)
+{
+	return float32_to_int32_round_to_zero(a);
+}
+
+float32 __aeabi_f2d(float32 a)
+{
+	return float32_to_float64(a);
+}
+
+float32 __aeabi_i2f(int a)
+{
+	return int32_to_float32(a);
+}
+
+float32 __aeabi_fadd(float32 a, float32 b)
+{
+	return float32_add(a, b);
+}
+
+float32 __aeabi_fdiv(float32 a, float32 b)
+{
+	return float32_div(a, b);
+}
+
+float32 __aeabi_fmul(float32 a, float32 b)
+{
+	return float32_mul(a, b);
+}
+
+float32 __aeabi_fsub(float32 a, float32 b)
+{
+	return float32_sub(a, b);
+}
+
Index: lib/libc/arm/SYS.h
===================================================================
--- lib/libc/arm/SYS.h	(.../head)	(revision 243940)
+++ lib/libc/arm/SYS.h	(.../projects/arm_eabi)	(revision 243946)
@@ -39,7 +39,15 @@
 #include <sys/syscall.h>
 #include <machine/swi.h>
 
+#ifdef __ARM_EABI__
+#define SYSTRAP(x)							\
+			mov ip, r7;					\
+			ldr r7, =SYS_ ## x;				\
+			swi 0 | SYS_ ## x;				\
+			mov r7, ip
+#else
 #define SYSTRAP(x)	swi 0 | SYS_ ## x
+#endif
 
 #define	CERROR		_C_LABEL(cerror)
 #define	CURBRK		_C_LABEL(curbrk)
Index: lib/libc/arm/Makefile.inc
===================================================================
--- lib/libc/arm/Makefile.inc	(.../head)	(revision 243940)
+++ lib/libc/arm/Makefile.inc	(.../projects/arm_eabi)	(revision 243946)
@@ -8,3 +8,11 @@ SOFTFLOAT_BITS=32
 # Long double is just double precision.
 MDSRCS+=machdep_ldisd.c
 SYM_MAPS+=${.CURDIR}/arm/Symbol.map
+
+.if ${MK_ARM_EABI} == "no"
+# This contains the symbols that were removed when moving to the ARM EABI
+SYM_MAPS+=${.CURDIR}/arm/Symbol_oabi.map
+.else
+.include "${.CURDIR}/arm/aeabi/Makefile.inc"
+.endif
+
Index: lib/libc/arm/gen/Makefile.inc
===================================================================
--- lib/libc/arm/gen/Makefile.inc	(.../head)	(revision 243940)
+++ lib/libc/arm/gen/Makefile.inc	(.../projects/arm_eabi)	(revision 243946)
@@ -3,4 +3,8 @@
 
 SRCS+=	_ctx_start.S _setjmp.S _set_tp.c alloca.S fabs.c \
 	getcontextx.c infinity.c ldexp.c makecontext.c \
-	__aeabi_read_tp.S setjmp.S signalcontext.c sigsetjmp.S divsi3.S flt_rounds.c
+	__aeabi_read_tp.S setjmp.S signalcontext.c sigsetjmp.S flt_rounds.c
+
+.if ${MK_ARM_EABI} == "no"
+SRCS+=	divsi3.S
+.endif
Index: lib/libc/arm/Symbol_oabi.map
===================================================================
--- lib/libc/arm/Symbol_oabi.map	(.../head)	(revision 0)
+++ lib/libc/arm/Symbol_oabi.map	(.../projects/arm_eabi)	(revision 243946)
@@ -0,0 +1,16 @@
+/*
+ * $FreeBSD: projects/arm_eabi/lib/libc/arm/Symbol.map 228591 2011-12-16 19:38:31Z andrew $
+ */
+
+/*
+ * This only needs to contain symbols that are not listed in
+ * symbol maps from other parts of libc (i.e., not found in
+ * stdlib/Symbol.map, string/Symbol.map, sys/Symbol.map, ...)
+ * and are not used in the ARM EABI.
+ */
+FBSDprivate_1.0 {
+	__umodsi3;
+	__modsi3;
+	__udivsi3;
+	__divsi3;
+};
Index: lib/libc/quad/Makefile.inc
===================================================================
--- lib/libc/quad/Makefile.inc	(.../head)	(revision 243940)
+++ lib/libc/quad/Makefile.inc	(.../projects/arm_eabi)	(revision 243946)
@@ -8,6 +8,10 @@
 
 SRCS+=	cmpdi2.c divdi3.c moddi3.c qdivrem.c ucmpdi2.c udivdi3.c umoddi3.c
 
+.elif ${LIBC_ARCH} == "arm" && ${MK_ARM_EABI} != "no"
+
+SRCS+=	adddi3.c anddi3.c floatunsdidf.c iordi3.c lshldi3.c notdi2.c \
+	qdivrem.c subdi3.c xordi3.c
 .else
 
 SRCS+=	adddi3.c anddi3.c ashldi3.c ashrdi3.c cmpdi2.c divdi3.c fixdfdi.c \
Index: bin/ls/util.c
===================================================================
--- bin/ls/util.c	(.../head)	(revision 243940)
+++ bin/ls/util.c	(.../projects/arm_eabi)	(revision 243946)
@@ -184,7 +184,10 @@ prn_octal(const char *s)
 			for (i = 0; i < (int)clen; i++)
 				putchar((unsigned char)s[i]);
 			len += wcwidth(wc);
-		} else if (goodchar && f_octal_escape && wc >= 0 &&
+		} else if (goodchar && f_octal_escape &&
+#if WCHAR_MIN < 0
+		    wc >= 0 &&
+#endif
 		    wc <= (wchar_t)UCHAR_MAX &&
 		    (p = strchr(esc, (char)wc)) != NULL) {
 			putchar('\\');

--MP_/7MVrwQO4FwHdxm_6EcPilkm--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20121209160721.571186d8>