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>