diff --git a/arm-gen.c b/arm-gen.c index bf3c2cf9..c11d9474 100644 --- a/arm-gen.c +++ b/arm-gen.c @@ -1717,8 +1717,12 @@ void gen_opi(int op) uint32_t x; x=stuff_const(opc|0x2000000|(c<<16),vtop->c.i); if(x) { - r=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r))); - o(x|(r<<12)); + if ((x & 0xfff00000) == 0xe3500000) // cmp rx,#c + o(x); + else { + r=intr(vtop[-1].r=get_reg_ex(RC_INT,regmask(vtop[-1].r))); + o(x|(r<<12)); + } goto done; } } @@ -1728,8 +1732,12 @@ void gen_opi(int op) c=intr(gv(RC_INT)); vswap(); } - r=intr(vtop[-1].r=get_reg_ex(RC_INT,two2mask(vtop->r,vtop[-1].r))); - o(opc|(c<<16)|(r<<12)|fr); + if ((opc & 0xfff00000) == 0xe1500000) // cmp rx,ry + o(opc|(c<<16)|fr); + else { + r=intr(vtop[-1].r=get_reg_ex(RC_INT,two2mask(vtop->r,vtop[-1].r))); + o(opc|(c<<16)|(r<<12)|fr); + } done: vtop--; if (op >= TOK_ULT && op <= TOK_GT) diff --git a/arm-link.c b/arm-link.c index 8e19a904..420639a0 100644 --- a/arm-link.c +++ b/arm-link.c @@ -12,8 +12,8 @@ #define R_NUM R_ARM_NUM -#define ELF_START_ADDR 0x00008000 -#define ELF_PAGE_SIZE 0x1000 +#define ELF_START_ADDR 0x00010000 +#define ELF_PAGE_SIZE 0x10000 #define PCRELATIVE_DLLPLT 1 #define RELOCATE_DLLPLT 1 @@ -133,7 +133,7 @@ ST_FUNC unsigned create_plt_entry(TCCState *s1, unsigned got_offset, struct sym_ write32le(p, 0x4778); /* bx pc */ write32le(p+2, 0x46c0); /* nop */ } - p = section_ptr_add(plt, 12); + p = section_ptr_add(plt, 16); /* save GOT offset for relocate_plt */ write32le(p + 4, got_offset); return plt_offset; @@ -159,10 +159,11 @@ ST_FUNC void relocate_plt(TCCState *s1) unsigned off = x + read32le(p + 4) + (s1->plt->data - p) + 4; if (read32le(p) == 0x46c04778) /* PLT Thumb stub present */ p += 4; - write32le(p, 0xe28fc600 | ((off >> 20) & 0xff)); // add ip, pc, #0xNN00000 - write32le(p + 4, 0xe28cca00 | ((off >> 12) & 0xff)); // add ip, ip, #0xNN000 - write32le(p + 8, 0xe5bcf000 | (off & 0xfff)); // ldr pc, [ip, #0xNNN]! - p += 12; + write32le(p, 0xe28fc200 | ((off >> 28) & 0xf)); // add ip, pc, #0xN0000000 + write32le(p + 4, 0xe28cc600 | ((off >> 20) & 0xff)); // add ip, pc, #0xNN00000 + write32le(p + 8, 0xe28cca00 | ((off >> 12) & 0xff)); // add ip, ip, #0xNN000 + write32le(p + 12, 0xe5bcf000 | (off & 0xfff)); // ldr pc, [ip, #0xNNN]! + p += 16; } } @@ -378,6 +379,7 @@ void relocate(TCCState *s1, ElfW_Rel *rel, int type, unsigned char *ptr, addr_t tcc_error("can't relocate value at %x,%d",addr, type); (*(int *)ptr) |= x & 0x7fffffff; } + return; case R_ARM_ABS32: case R_ARM_TARGET1: if (s1->output_type == TCC_OUTPUT_DLL) { diff --git a/tcc.h b/tcc.h index 319845a1..afe696b7 100644 --- a/tcc.h +++ b/tcc.h @@ -94,6 +94,14 @@ extern long double strtold (const char *__nptr, char **__endptr); # undef CONFIG_TCC_STATIC #endif +#ifndef PAGESIZE +# ifdef _SC_PAGESIZE +# define PAGESIZE sysconf(_SC_PAGESIZE) +# else +# define PAGESIZE 4096 +# endif +#endif + #ifndef O_BINARY # define O_BINARY 0 #endif diff --git a/tccelf.c b/tccelf.c index 2119d9b6..0371ae59 100644 --- a/tccelf.c +++ b/tccelf.c @@ -47,10 +47,6 @@ struct sym_version { /* section is dynsymtab_section */ #define SHF_DYNSYM 0x40000000 -#ifndef PAGESIZE -# define PAGESIZE 4096 -#endif - /* ------------------------------------------------------------------------- */ ST_FUNC void tccelf_new(TCCState *s) @@ -1036,6 +1032,7 @@ static int prepare_dynamic_rel(TCCState *s1, Section *sr) case R_X86_64_64: #elif defined(TCC_TARGET_ARM) case R_ARM_ABS32: + case R_ARM_TARGET1: #elif defined(TCC_TARGET_ARM64) case R_AARCH64_ABS32: case R_AARCH64_ABS64: @@ -1452,6 +1449,9 @@ ST_FUNC void tcc_add_runtime(TCCState *s1) tcc_add_dll(s1, TCC_LIBGCC, 0); } #endif +#if TCC_TARGET_ARM && TARGETOS_FreeBSD + tcc_add_library_err(s1, "gcc_s"); // unwind code +#endif #ifdef CONFIG_TCC_BCHECK if (s1->do_bounds_check && s1->output_type != TCC_OUTPUT_DLL) { tcc_add_library_err(s1, "pthread"); diff --git a/tccrun.c b/tccrun.c index d59df8fa..318dd384 100644 --- a/tccrun.c +++ b/tccrun.c @@ -63,10 +63,6 @@ static void *win64_add_function_table(TCCState *s1); static void win64_del_function_table(void *); #endif -#ifndef PAGESIZE -# define PAGESIZE 4096 -#endif - /* ------------------------------------------------------------- */ /* Do all relocations (needed before using tcc_get_symbol()) Returns -1 on error. */ @@ -333,7 +329,10 @@ static void set_pages_executable(TCCState *s1, void *ptr, unsigned long length) if (mprotect((void *)start, end - start, PROT_READ | PROT_WRITE | PROT_EXEC)) tcc_error("mprotect failed: did you mean to configure --with-selinux?"); # endif -# if defined TCC_TARGET_ARM || defined TCC_TARGET_ARM64 +/* XXX: BSD sometimes dump core with bad system call */ +# if (defined(TCC_TARGET_ARM) && \ + !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__)) || \ + defined(TCC_TARGET_ARM64) __clear_cache(ptr, (char *)ptr + length); # endif #endif @@ -667,6 +666,9 @@ static void rt_getcontext(ucontext_t *uc, rt_context *rc) #elif defined(__arm__) && defined(__OpenBSD__) rc->ip = uc->sc_pc; rc->fp = uc->sc_fpreg[29]; +#elif defined(__arm__) && defined(__FreeBSD__) + rc->ip = uc->uc_mcontext.__gregs[_REG_PC]; + rc->fp = uc->uc_mcontext.__gregs[_REG_FP]; #elif defined(__arm__) rc->ip = uc->uc_mcontext.arm_pc; rc->fp = uc->uc_mcontext.arm_fp; @@ -830,8 +832,9 @@ static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level) #elif defined(__arm__) static int rt_get_caller_pc(addr_t *paddr, rt_context *rc, int level) { - /* XXX: only supports linux */ -#if !defined(__linux__) + /* XXX: only supports linux/bsd */ +#if !defined(__linux__) && \ + !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) return -1; #else if (level == 0) { diff --git a/tests/tcctest.c b/tests/tcctest.c index 04c1e594..de2546f9 100644 --- a/tests/tcctest.c +++ b/tests/tcctest.c @@ -21,7 +21,9 @@ typedef __SIZE_TYPE__ uintptr_t; #endif -#if defined(_WIN32) +#if defined(_WIN32) || \ + (defined(__arm__) && \ + (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__))) #define LONG_LONG_FORMAT "%lld" #define ULONG_LONG_FORMAT "%llu" #else