diff --git a/ChangeLog b/ChangeLog index 1c0afba75..24e97d7d7 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2013-07-01 Paulo Andrade + + * check/lightning.c, lib/jit_disasm.c, lib/jit_ppc-cpu.c, + lib/jit_ppc-fpu.c, lib/jit_ppc.c, include/lightning.h, + include/lightning/jit_ppc.h, include/lightning/jit_private.h: + Adapt code to work on 32 bit AIX ppc using gcc. Most changes + are basically to adapt the elf64 logic to 32 bit, as it does + not use the same convention of 32 bit Darwin ppc. + + * check/stack.tst: Add a fake memcpy function to the test + case if running under AIX, as it is not available to dlsym. + + * configure.ac: Check for getopt.h header, not available in + AIX. + 2013-06-01 Paulo Andrade * include/lightning/jit_hppa.h, lib/jit_hppa-cpu.c, diff --git a/check/lightning.c b/check/lightning.c index bf1e126ae..6ffbdc5c0 100644 --- a/check/lightning.c +++ b/check/lightning.c @@ -15,7 +15,15 @@ * Paulo Cesar Pereira de Andrade */ -#include +#if HAVE_CONFIG_H +# include "config.h" +#endif + +#if HAVE_GETOPT_H +# include +#else +# include +#endif #include #include #include @@ -25,6 +33,11 @@ # include #endif +/* The label_t identifier clashes with a definition in sys/types.h */ +#if defined(_AIX) +# define label_t l_label_t +#endif + #if defined(__GNUC__) # define noreturn __attribute__ ((noreturn)) # define printf_format(f, v) __attribute__ ((format (printf, f, v))) @@ -3769,25 +3782,34 @@ rehash(hash_t *hash) static void usage(void) { +#if HAVE_GETOPT_H fprintf(stderr, "\ Usage: %s [jit assembler options] file [jit program options]\n\ Jit assembler options:\n\ -help Display this information\n\ -v[0-3] Verbose output level\n\ -D[=] Preprocessor options\n" -#if defined(__i386__) && __WORDSIZE == 32 +# if defined(__i386__) && __WORDSIZE == 32 " -mx87=1 Force using x87 when sse2 available\n" -#endif -#if defined(__i386__) || defined(__x86_64__) +# endif +# if defined(__i386__) || defined(__x86_64__) " -msse4_1=0 Do not use sse4_1 instructions when available\n" -#endif -#if defined(__arm__) +# endif +# if defined(__arm__) " -mcpu= Force cpu version (4, 5, 6 or 7)\n\ -mthumb[=0|1] Enable or disable thumb\n\ -mvfp= Set vpf version (0 to disable)\n\ -mneon[=0|1] Enable or disable neon\n" -#endif +# endif , progname); +#else + fprintf(stderr, "\ +Usage: %s [jit assembler options] file [jit program options]\n\ +Jit assembler options:\n\ + -h Display this information\n\ + -v Verbose output level\n\ + -D[=] Preprocessor options\n", progname); +#endif finish_jit(); exit(1); } @@ -3795,23 +3817,26 @@ Jit assembler options:\n\ int main(int argc, char *argv[]) { +#if HAVE_GETOPT_H static const char *short_options = "v::"; static struct option long_options[] = { { "help", 0, 0, 'h' }, -#if defined(__i386__) && __WORDSIZE == 32 +# if defined(__i386__) && __WORDSIZE == 32 { "mx87", 2, 0, '7' }, -#endif -#if defined(__i386__) || defined(__x86_64__) +# endif +# if defined(__i386__) || defined(__x86_64__) { "msse4_1", 2, 0, '4' }, -#endif -#if defined(__arm__) +# endif +# if defined(__arm__) { "mcpu", 2, 0, 'c' }, { "mthumb", 2, 0, 't' }, { "mvfp", 2, 0, 'f' }, { "mneon", 2, 0, 'n' }, -#endif +# endif { 0, 0, 0, 0 } }; +#else +#endif /* HAVE_GETOPT_H */ int offset; char *endptr; int opt_index; @@ -3822,6 +3847,7 @@ main(int argc, char *argv[]) init_jit(progname); +#if HAVE_GETOPT_H for (;;) { if ((opt_short = getopt_long_only(argc, argv, short_options, long_options, &opt_index)) < 0) @@ -3903,6 +3929,14 @@ main(int argc, char *argv[]) #endif } } +#else + while ((opt_short = getopt(argc, argv, "hv")) >= 0) { + if (opt_short == 'v') + ++flag_verbose; + else + usage(); + } +#endif opt_index = optind; if (opt_index < 0 || opt_index >= argc) @@ -3979,6 +4013,11 @@ main(int argc, char *argv[]) opt_short += snprintf(cmdline + opt_short, sizeof(cmdline) - opt_short, " -D__hppa__=1"); +#endif +#if defined(_AIX) + opt_short += snprintf(cmdline + opt_short, + sizeof(cmdline) - opt_short, + " -D_AIX=1"); #endif if ((parser.fp = popen(cmdline, "r")) == NULL) error("cannot execute %s", cmdline); diff --git a/check/stack.tst b/check/stack.tst index be63dc3c6..e69971938 100644 --- a/check/stack.tst +++ b/check/stack.tst @@ -181,7 +181,7 @@ test##T##_##N: \ pushargr %v1 \ pushargr %v0 \ pushargi $(N * szof##T) \ - finishi @memcpy \ + finishi MEMCPY \ /* stack buffer for next function in %v2 */ \ allocai $(M * szof##T) $index \ addi %v2 %fp $index \ @@ -235,7 +235,7 @@ test##T##_17: \ pushargr %v1 \ pushargr %v2 \ pushargi $(16 * szof##T) \ - finishi @memcpy \ + finishi MEMCPY \ /* call next function */ \ prepare \ pushargr %v2 \ @@ -286,6 +286,32 @@ ok: .code jmpi main +#if _AIX +# define MEMCPY memcpy +/* error: Function not implemented (memcpy) */ + name memcpy +memcpy: + prolog + arg $dst + arg $src + arg $len + getarg %r0 $dst + getarg %r1 $src + getarg %r2 $len + movr %v1 %r0 + blti memcpy_done %r2 1 +memcpy_loop: + subi %r2 %r2 1 + ldxr_c %v0 %r1 %r2 + stxr_c %r2 %r0 %v0 + bgti memcpy_loop %r2 0 +memcpy_done: + retr %v1 + epilog +#else +# define MEMCPY @memcpy +#endif + FILL(_c) FILL(_s) FILL(_i) diff --git a/configure.ac b/configure.ac index 4c78588c3..edbb072e8 100644 --- a/configure.ac +++ b/configure.ac @@ -27,6 +27,8 @@ AC_PROG_LIBTOOL AC_CHECK_FUNCS(mremap,,) +AC_CHECK_HEADERS([getopt.h],,,) + AC_ARG_ENABLE(disassembler, AS_HELP_STRING([--enable-disassembler], [Enable jit disassembler using binutils]), diff --git a/include/lightning.h b/include/lightning.h index 3ff474827..ef21a1521 100644 --- a/include/lightning.h +++ b/include/lightning.h @@ -28,16 +28,32 @@ #include #ifndef __WORDSIZE -# define __WORDSIZE WORDSIZE +# if defined(_AIX) +# define __WORDSIZE (__SIZEOF_POINTER__ << 3) +# else +# define __WORDSIZE WORDSIZE +# endif #endif #ifndef __BYTE_ORDER -# define __BYTE_ORDER BYTE_ORDER +# if defined(_AIX) +# define __BYTE_ORDER __BYTE_ORDER__ +# else +# define __BYTE_ORDER BYTE_ORDER +# endif #endif #ifndef __LITTLE_ENDIAN -# define __LITTLE_ENDIAN LITTLE_ENDIAN +# if defined(_AIX) +# define __LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__ +# else +# define __LITTLE_ENDIAN LITTLE_ENDIAN +# endif #endif #ifndef __BIG_ENDIAN -# define __BIG_ENDIAN BIG_ENDIAN +# if defined(_AIX) +# define __BIG_ENDIAN __ORDER_BIG_ENDIAN__ +# else +# define __BIG_ENDIAN BIG_ENDIAN +# endif #endif typedef signed char jit_int8_t; diff --git a/include/lightning/jit_ppc.h b/include/lightning/jit_ppc.h index c4380e23c..daca61c1c 100644 --- a/include/lightning/jit_ppc.h +++ b/include/lightning/jit_ppc.h @@ -28,7 +28,7 @@ typedef enum { #define jit_arg_reg_p(i) ((i) >= 0 && (i) < 8) #define jit_r(i) (_R11 + (i)) #define jit_r_num() 3 -#if __WORDSIZE == 32 +#if __ppc__ # define jit_v(i) (_R30 - (i)) # define jit_v_num() 17 #else @@ -39,7 +39,7 @@ typedef enum { #define jit_f(i) (_F14 + (i)) #define jit_f_num() 6 _R0, -#if __WORDSIZE == 32 +#if __ppc__ # define JIT_R0 _R11 # define JIT_R1 _R12 # define JIT_R2 _R13 @@ -63,7 +63,7 @@ typedef enum { #define JIT_V11 jit_v(11) #define JIT_V12 jit_v(12) #define JIT_V13 jit_v(13) -#if __WORDSIZE == 32 +#if __ppc__ # define JIT_V14 jit_v(14) # define JIT_V15 jit_v(15) # define JIT_V16 jit_v(16) diff --git a/include/lightning/jit_private.h b/include/lightning/jit_private.h index 75dc1b77d..f8d6cc2db 100644 --- a/include/lightning/jit_private.h +++ b/include/lightning/jit_private.h @@ -405,7 +405,7 @@ struct jit_compiler { jit_int32_t values[1024]; /* pending constants */ jit_word_t patches[2048]; } consts; -#elif __powerpc64__ || __ia64__ +#elif __powerpc__ || __ia64__ /* Keep track of prolog addresses, just for the sake of making * jit that starts with a jump to a "main" label work like other * backends. */ diff --git a/lib/jit_disasm.c b/lib/jit_disasm.c index 3708886b7..eb85f6ea5 100644 --- a/lib/jit_disasm.c +++ b/lib/jit_disasm.c @@ -81,12 +81,16 @@ jit_init_debug(void) if (jit_cpu.thumb) disasm_info.disassembler_options = "force-thumb"; # endif -# if defined(__powerpc64__) +# if defined(__powerpc__) disasm_info.arch = bfd_arch_powerpc; disasm_info.mach = bfd_mach_ppc64; + disassemble_init_powerpc(&disasm_info); +# if defined(__powerpc64__) disasm_info.disassembler_options = "64"; +# endif disassemble_init_powerpc(&disasm_info); # endif + # if defined(__sparc__) disasm_info.endian = disasm_info.display_endian = BFD_ENDIAN_BIG; # endif diff --git a/lib/jit_ppc-cpu.c b/lib/jit_ppc-cpu.c index 5abbf5836..eca8581f6 100644 --- a/lib/jit_ppc-cpu.c +++ b/lib/jit_ppc-cpu.c @@ -35,7 +35,11 @@ # define fpr_save_area 64 # define alloca_offset -(gpr_save_area + fpr_save_area) # define ii(i) *_jit->pc.ui++ = i -# define il(i) *_jit->pc.ul++ = i +# if __WORDSIZE == 32 +# define iw(i) *_jit->pc.ui++ = i +# else +# define iw(i) *_jit->pc.ul++ = i +# endif # define can_sign_extend_short_p(im) ((im) >= -32768 && (im) <= 32767) # define can_zero_extend_short_p(im) ((im) >= 0 && (im) <= 65535) # define can_sign_extend_jump_p(im) ((im) >= -33554432 && (im) <= 33554431) @@ -45,9 +49,11 @@ # define _R11_REGNO 11 # define _FP_REGNO 31 # if __WORDSIZE == 32 +# define ldr(r0,r1) ldr_i(r0,r1) # define ldxi(r0,r1,i0) ldxi_i(r0,r1,i0) # define stxi(i0,r0,r1) stxi_i(i0,r0,r1) # else +# define ldr(r0,r1) ldr_l(r0,r1) # define ldxi(r0,r1,i0) ldxi_l(r0,r1,i0) # define stxi(i0,r0,r1) stxi_l(i0,r0,r1) # endif @@ -2992,26 +2998,26 @@ _jmpi_p(jit_state_t *_jit, jit_word_t i0) static void _callr(jit_state_t *_jit, jit_int32_t r0) { -# if __WORDSIZE == 64 - stxi(40, _SP_REGNO, _R2_REGNO); +# if __powerpc__ + stxi(sizeof(void*) * 5, _SP_REGNO, _R2_REGNO); /* FIXME Pretend to not know about r11? */ if (r0 == _R0_REGNO) { movr(_R11_REGNO, _R0_REGNO); - ldxi(_R2_REGNO, _R11_REGNO, 8); - ldxi(_R11_REGNO, _R11_REGNO, 16); + ldxi(_R2_REGNO, _R11_REGNO, sizeof(void*)); + ldxi(_R11_REGNO, _R11_REGNO, sizeof(void*) * 2); } else { - ldxi(_R2_REGNO, r0, 8); - ldxi(_R11_REGNO, r0, 16); + ldxi(_R2_REGNO, r0, sizeof(void*)); + ldxi(_R11_REGNO, r0, sizeof(void*) * 2); } - LDX(r0, _R0_REGNO, r0); + ldr(r0, r0); # endif MTCTR(r0); BCTRL(); -# if __WORDSIZE == 64 - ldxi(_R2_REGNO, _SP_REGNO, 40); +# if __powerpc__ + ldxi(_R2_REGNO, _SP_REGNO, sizeof(void*) * 5); # endif } @@ -3019,11 +3025,11 @@ _callr(jit_state_t *_jit, jit_int32_t r0) static void _calli(jit_state_t *_jit, jit_word_t i0) { -# if __WORDSIZE == 32 +# if __ppc__ jit_word_t d; # endif jit_int32_t reg; -# if __WORDSIZE == 32 +# if __ppc__ d = (i0 - _jit->pc.w) & ~3; if (can_sign_extend_jump_p(d)) BL(d); @@ -3050,7 +3056,7 @@ _calli_p(jit_state_t *_jit, jit_word_t i0) return (w); } -# if __WORDSIZE == 64 +# if __powerpc__ /* order is not guaranteed to be sequential */ static jit_int32_t save[] = { _R14, _R15, _R16, _R17, _R18, _R19, _R20, _R21, _R22, @@ -3074,7 +3080,7 @@ _prolog(jit_state_t *_jit, jit_node_t *node) /* params >= %r31+params_offset+(8*sizeof(jit_word_t)) * alloca < %r31-80 */ -# if __WORDSIZE == 32 +#if __ppc__ /* save any clobbered callee save gpr register */ regno = jit_regset_scan1(&_jitc->function->regset, _R14); if (regno == ULONG_MAX || regno > _R31) @@ -3086,23 +3092,26 @@ _prolog(jit_state_t *_jit, jit_node_t *node) } stxi(8, _SP_REGNO, _R0_REGNO); - movr(_FP_REGNO, _SP_REGNO); - - STWU(_SP_REGNO, _SP_REGNO, -_jitc->function->stack); -# else - stxi(16, _SP_REGNO, _R0_REGNO); - offset = -144; - for (regno = 0; regno < jit_size(save); regno++, offset += 8) { +#else /* __powerpc__ */ + stxi(sizeof(void*) * 2, _SP_REGNO, _R0_REGNO); + offset = -gpr_save_area; + for (regno = 0; regno < jit_size(save); regno++, offset += sizeof(void*)) { if (jit_regset_tstbit(&_jitc->function->regset, save[regno])) stxi(offset, _SP_REGNO, rn(save[regno])); } for (offset = 0; offset < 8; offset++) { if (jit_regset_tstbit(&_jitc->function->regset, _F14 + offset)) - stxi_d(-(152 + offset * 8), _SP_REGNO, rn(_F14 + offset)); + stxi_d(-(gpr_save_area + 8 + offset * 8), + _SP_REGNO, rn(_F14 + offset)); } - stxi(-8, _SP_REGNO, _FP_REGNO); + stxi(-(sizeof(void*)), _SP_REGNO, _FP_REGNO); +#endif + movr(_FP_REGNO, _SP_REGNO); +#if __WORDSIZE == 32 + STWU(_SP_REGNO, _SP_REGNO, -_jitc->function->stack); +#else STDU(_SP_REGNO, _SP_REGNO, -_jitc->function->stack); #endif } @@ -3113,7 +3122,7 @@ _epilog(jit_state_t *_jit, jit_node_t *node) unsigned long regno; jit_word_t offset; -#if __WORDSIZE == 32 +#if __ppc__ LWZ(_SP_REGNO, _SP_REGNO, 0); ldxi(_R0_REGNO, _SP_REGNO, 8); @@ -3128,21 +3137,22 @@ _epilog(jit_state_t *_jit, jit_node_t *node) ldxi_d(rn(_F14 + offset), _SP_REGNO, -fpr_save_area + offset * 8); } -#else +#else /* __powerpc__ */ addi(_SP_REGNO, _SP_REGNO, _jitc->function->stack); - ldxi(_R0_REGNO, _SP_REGNO, 16); - offset = -144; - for (regno = 0; regno < jit_size(save); regno++, offset += 8) { + ldxi(_R0_REGNO, _SP_REGNO, sizeof(void*) * 2); + offset = -gpr_save_area; + for (regno = 0; regno < jit_size(save); regno++, offset += sizeof(void*)) { if (jit_regset_tstbit(&_jitc->function->regset, save[regno])) ldxi(rn(save[regno]), _SP_REGNO, offset); } for (offset = 0; offset < 8; offset++) { if (jit_regset_tstbit(&_jitc->function->regset, _F14 + offset)) - ldxi_d(rn(_F14 + offset), _SP_REGNO, -(152 + offset * 8)); + ldxi_d(rn(_F14 + offset), _SP_REGNO, + -(gpr_save_area + 8 + offset * 8)); } MTLR(_R0_REGNO); - ldxi(_FP_REGNO, _SP_REGNO, -8); + ldxi(_FP_REGNO, _SP_REGNO, -(sizeof(void*))); #endif BLR(); @@ -3169,24 +3179,24 @@ _patch_at(jit_state_t *_jit, jit_word_t instr, jit_word_t label) u.i[0] = (u.i[0] & ~0xfffd) | (d & 0xfffe); break; case 18: /* Bx */ -# if __powerpc64__ +#if __powerpc__ if (_jitc->jump && (!(u.i[0] & 1))) { /* jmpi label */ /* zero is used for toc and env, so, quick check * if this is a "jmpi main" like initial jit * instruction */ if (((long *)label)[1] == 0 && ((long *)label)[2] == 0) { for (d = 0; d < _jitc->prolog.offset; d++) { - /* not so pretty, but hides powerpc64 + /* not so pretty, but hides powerpc * specific abi intrinsics and/or * implementation from user */ if (_jitc->prolog.ptr[d] == label) { - label += 24; + label += sizeof(void*) * 3; break; } } } } -# endif +#endif d = label - instr; assert(!(d & 3)); if (!can_sign_extend_jump_p(d)) { @@ -3197,13 +3207,13 @@ _patch_at(jit_state_t *_jit, jit_word_t instr, jit_word_t label) u.i[0] = (u.i[0] & ~0x3fffffd) | (d & 0x3fffffe); break; case 15: /* LI */ -# if __WORDSIZE == 32 +#if __WORDSIZE == 32 assert(!(u.i[0] & 0x1f0000)); u.i[0] = (u.i[0] & ~0xffff) | ((label >> 16) & 0xffff); assert((u.i[1] & 0xfc000000) >> 26 == 24); /* ORI */ assert(((u.i[1] >> 16) & 0x1f) == ((u.i[1] >> 21) & 0x1f)); u.i[1] = (u.i[1] & ~0xffff) | (label & 0xffff); -# else +#else assert(!(u.i[0] & 0x1f0000)); u.i[0] = (u.i[0] & ~0xffff) | ((label >> 48) & 0xffff); assert((u.i[1] & 0xfc000000) >> 26 == 24); /* ORI */ @@ -3221,7 +3231,7 @@ _patch_at(jit_state_t *_jit, jit_word_t instr, jit_word_t label) assert((u.i[5] & 0xfc000000) >> 26 == 24); /* ORI */ assert(((u.i[5] >> 16) & 0x1f) == ((u.i[5] >> 21) & 0x1f)); u.i[5] = (u.i[5] & ~0xffff) | (label & 0xffff); -# endif +#endif break; default: assert(!"unhandled branch opcode"); diff --git a/lib/jit_ppc-fpu.c b/lib/jit_ppc-fpu.c index 5dd93f52f..75d552a9e 100644 --- a/lib/jit_ppc-fpu.c +++ b/lib/jit_ppc-fpu.c @@ -21,7 +21,7 @@ static void _FA(jit_state_t*,int,int,int,int,int,int,int); #define FXFL(o,m,b,x) _FXFL(_jit,o,m,b,x,0) #define FXFL_(o,m,b,x) _FXFL(_jit,o,m,b,x,1) -static void _FXFL(jit_state_t*,int,int,int,int,int); +static void _FXFL(jit_state_t*,int,int,int,int,int) maybe_unused; # define FABS(d,b) FX(63,d,0,b,264) # define FABS_(d,b) FX_(63,d,0,b,264) diff --git a/lib/jit_ppc.c b/lib/jit_ppc.c index 89782f9e6..a2e640153 100644 --- a/lib/jit_ppc.c +++ b/lib/jit_ppc.c @@ -37,7 +37,7 @@ extern void __clear_cache(void *, void *); */ jit_register_t _rvs[] = { { rc(gpr) | 0, "r0" }, -#if __WORDSIZE == 32 +#if __ppc__ { rc(gpr) | 11, "r11" }, { rc(gpr) | 12, "r12" }, { rc(gpr) | 13, "r13" }, @@ -761,7 +761,7 @@ _emit_code(jit_state_t *_jit) jit_node_t *node; jit_word_t word; jit_word_t patch_offset; -#if __powerpc64__ +#if __powerpc__ jit_word_t prolog_offset; #endif } undo; @@ -773,13 +773,13 @@ _emit_code(jit_state_t *_jit) undo.word = 0; undo.node = NULL; undo.patch_offset = 0; -#if __powerpc64__ - undo.prolog_offset = 0; +#if __powerpc__ + undo.prolog_offset = 0; /* code may start with a jump so add an initial function descriptor */ - il(_jit->pc.w + 24); /* addr */ - il(0); /* toc */ - il(0); /* env */ + iw(_jit->pc.w + sizeof(void*) * 3); /* addr */ + iw(0); /* toc */ + iw(0); /* env */ #endif #define case_rr(name, type) \ @@ -1233,8 +1233,8 @@ _emit_code(jit_state_t *_jit) jmpr(rn(node->u.w)); break; case jit_code_jmpi: -#if __powerpc64__ - if (_jit->pc.uc == _jit->code.ptr + 24) +#if __powerpc__ + if (_jit->pc.uc == _jit->code.ptr + sizeof(void*) * 3) _jitc->jump = 1; #endif temp = node->u.n; @@ -1268,12 +1268,12 @@ _emit_code(jit_state_t *_jit) undo.node = node; undo.word = _jit->pc.w; undo.patch_offset = _jitc->patches.offset; -#if __powerpc64__ +#if __powerpc__ undo.prolog_offset = _jitc->prolog.offset; #endif restart_function: _jitc->again = 0; -#if __powerpc64__ +#if __powerpc__ if (_jitc->jump) { /* remember prolog to hide offset adjustment for a jump * to the start of a function, what is expected to be @@ -1287,9 +1287,9 @@ _emit_code(jit_state_t *_jit) } _jitc->prolog.ptr[_jitc->prolog.offset++] = _jit->pc.w; /* function descriptor */ - il(_jit->pc.w + 24); /* addr */ - il(0); /* toc */ - il(0); /* env */ + iw(_jit->pc.w + sizeof(void*) * 3); /* addr */ + iw(0); /* toc */ + iw(0); /* env */ } #endif prolog(node); @@ -1307,7 +1307,7 @@ _emit_code(jit_state_t *_jit) node = undo.node; _jit->pc.w = undo.word; _jitc->patches.offset = undo.patch_offset; -#if __powerpc64__ +#if __powerpc__ _jitc->prolog.offset = undo.prolog_offset; #endif goto restart_function; @@ -1393,7 +1393,6 @@ static void _patch(jit_state_t *_jit, jit_word_t instr, jit_node_t *node) { jit_int32_t flag; - jit_word_t *patches; assert(node->flag & jit_flag_node); if (node->code == jit_code_movi)