From: Julian Seward Date: Tue, 17 Oct 2006 00:28:22 +0000 (+0000) Subject: Merge r1663-r1666: X-Git-Tag: svn/VALGRIND_3_3_1^2~94 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9e674eb5ba61fdb01abe2ab8dcec59abcd27b4bf;p=thirdparty%2Fvalgrind.git Merge r1663-r1666: - AIX5 build changes - genoffsets.c: print the offsets of a few more ppc registers - Get rid of a bunch of ad-hoc hacks which hardwire in certain assumptions about guest and host ABIs. Instead pass that info in a VexMiscInfo structure. This cleans up various grotty bits. - Add to ppc32 guest state, redirection-stack stuff already present in ppc64 guest state. This is to enable function redirection/ wrapping in the presence of TOC pointers in 32-bit mode. - Add to both ppc32 and ppc64 guest states, a new pseudo-register LR_AT_SC. This holds the link register value at the most recent 'sc', so that AIX can back up to restart a syscall if needed. - Add to both ppc32 and ppc64 guest states, a SPRG3 register. - Use VexMiscInfo to handle 'sc' on AIX differently from Linux: on AIX, 'sc' continues at the location stated in the link register, not at the next insn. git-svn-id: svn://svn.valgrind.org/vex/trunk@1669 --- diff --git a/VEX/Makefile b/VEX/Makefile index dd7d82715b..10e97874ab 100644 --- a/VEX/Makefile +++ b/VEX/Makefile @@ -137,6 +137,18 @@ TAG_ppc64_linux: if [ ! -f TAG_ppc64_linux ] ; then rm -f $(LIB_OBJS) TAG_* libvex.a ; fi touch TAG_ppc64_linux +libvex_ppc32_aix5.a: TAG_ppc32_aix5 libvex.a + mv -f libvex.a libvex_ppc32_aix5.a +TAG_ppc32_aix5: + if [ ! -f TAG_ppc32_aix5 ] ; then rm -f $(LIB_OBJS) TAG_* libvex.a ; fi + touch TAG_ppc32_aix5 + +libvex_ppc64_aix5.a: TAG_ppc64_aix5 libvex.a + mv -f libvex.a libvex_ppc64_aix5.a +TAG_ppc64_aix5: + if [ ! -f TAG_ppc64_aix5 ] ; then rm -f $(LIB_OBJS) TAG_* libvex.a ; fi + touch TAG_ppc64_aix5 + # This doesn't get rid of priv/main/vex_svnversion.h, because # that can't be regenerated in the final Valgrind tarball, and @@ -148,9 +160,10 @@ clean: version: rm -f priv/main/vex_svnversion.h - echo -n "\"" > priv/main/vex_svnversion.h + cat quote.txt >> priv/main/vex_svnversion.h svnversion -n . >> priv/main/vex_svnversion.h - echo "\"" >> priv/main/vex_svnversion.h + cat quote.txt >> priv/main/vex_svnversion.h + cat newline.txt >> priv/main/vex_svnversion.h minidist: version rm -f vex--minidist-2005MMDD.tar diff --git a/VEX/auxprogs/genoffsets.c b/VEX/auxprogs/genoffsets.c index 13ea551b0b..4d0b767787 100644 --- a/VEX/auxprogs/genoffsets.c +++ b/VEX/auxprogs/genoffsets.c @@ -143,6 +143,9 @@ Int main ( void ) printf("#define OFFSET_ppc32_GPR0 %3d\n", offsetof(VexGuestPPC32State,guest_GPR0)); + printf("#define OFFSET_ppc32_GPR2 %3d\n", + offsetof(VexGuestPPC32State,guest_GPR2)); + printf("#define OFFSET_ppc32_GPR3 %3d\n", offsetof(VexGuestPPC32State,guest_GPR3)); @@ -161,6 +164,12 @@ Int main ( void ) printf("#define OFFSET_ppc32_GPR8 %3d\n", offsetof(VexGuestPPC32State,guest_GPR8)); + printf("#define OFFSET_ppc32_GPR9 %3d\n", + offsetof(VexGuestPPC32State,guest_GPR9)); + + printf("#define OFFSET_ppc32_GPR10 %3d\n", + offsetof(VexGuestPPC32State,guest_GPR10)); + printf("#define OFFSET_ppc32_CIA %3d\n", offsetof(VexGuestPPC32State,guest_CIA)); @@ -173,6 +182,9 @@ Int main ( void ) printf("#define OFFSET_ppc64_GPR0 %4d\n", offsetof(VexGuestPPC64State,guest_GPR0)); + printf("#define OFFSET_ppc64_GPR2 %4d\n", + offsetof(VexGuestPPC64State,guest_GPR2)); + printf("#define OFFSET_ppc64_GPR3 %4d\n", offsetof(VexGuestPPC64State,guest_GPR3)); @@ -191,6 +203,12 @@ Int main ( void ) printf("#define OFFSET_ppc64_GPR8 %4d\n", offsetof(VexGuestPPC64State,guest_GPR8)); + printf("#define OFFSET_ppc64_GPR9 %4d\n", + offsetof(VexGuestPPC64State,guest_GPR9)); + + printf("#define OFFSET_ppc64_GPR10 %4d\n", + offsetof(VexGuestPPC64State,guest_GPR10)); + printf("#define OFFSET_ppc64_CIA %4d\n", offsetof(VexGuestPPC64State,guest_CIA)); diff --git a/VEX/newline.txt b/VEX/newline.txt new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/VEX/newline.txt @@ -0,0 +1 @@ + diff --git a/VEX/priv/guest-amd64/gdefs.h b/VEX/priv/guest-amd64/gdefs.h index 36100be0bf..01a8642265 100644 --- a/VEX/priv/guest-amd64/gdefs.h +++ b/VEX/priv/guest-amd64/gdefs.h @@ -66,6 +66,7 @@ DisResult disInstr_AMD64 ( IRBB* irbb, Addr64 guest_IP, VexArch guest_arch, VexArchInfo* archinfo, + VexMiscInfo* miscinfo, Bool host_bigendian ); /* Used by the optimiser to specialise calls to helpers. */ diff --git a/VEX/priv/guest-amd64/toIR.c b/VEX/priv/guest-amd64/toIR.c index 74fc124f2d..a6588f9f2f 100644 --- a/VEX/priv/guest-amd64/toIR.c +++ b/VEX/priv/guest-amd64/toIR.c @@ -1931,14 +1931,24 @@ void jcc_01 ( AMD64Condcode cond, Addr64 d64_false, Addr64 d64_true ) generates an AbiHint to say that -128(%rsp) .. -1(%rsp) should now be regarded as uninitialised. */ -static void make_redzone_AbiHint ( IRTemp new_rsp, HChar* who ) +static +void make_redzone_AbiHint ( VexMiscInfo* vmi, IRTemp new_rsp, HChar* who ) { + Int szB = vmi->guest_stack_redzone_size; + vassert(szB >= 0); + + /* A bit of a kludge. Currently the only AbI we've guested AMD64 + for is ELF. So just check it's the expected 128 value + (paranoia). */ + vassert(szB == 128); + if (0) vex_printf("AbiHint: %s\n", who); vassert(typeOfIRTemp(irbb->tyenv, new_rsp) == Ity_I64); - stmt( IRStmt_AbiHint( - binop(Iop_Sub64, mkexpr(new_rsp), mkU64(128)), - 128 - )); + if (szB > 0) + stmt( IRStmt_AbiHint( + binop(Iop_Sub64, mkexpr(new_rsp), mkU64(szB)), + szB + )); } @@ -3626,7 +3636,8 @@ ULong dis_Grp4 ( Prefix pfx, Long delta ) /* Group 5 extended opcodes. */ static -ULong dis_Grp5 ( Prefix pfx, Int sz, Long delta, DisResult* dres ) +ULong dis_Grp5 ( VexMiscInfo* vmi, + Prefix pfx, Int sz, Long delta, DisResult* dres ) { Int len; UChar modrm; @@ -3666,7 +3677,7 @@ ULong dis_Grp5 ( Prefix pfx, Int sz, Long delta, DisResult* dres ) assign(t2, binop(Iop_Sub64, getIReg64(R_RSP), mkU64(8))); putIReg64(R_RSP, mkexpr(t2)); storeLE( mkexpr(t2), mkU64(guest_RIP_bbstart+delta+1)); - make_redzone_AbiHint(t2, "call-Ev(reg)"); + make_redzone_AbiHint(vmi, t2, "call-Ev(reg)"); jmp_treg(Ijk_Call,t3); dres->whatNext = Dis_StopHere; showSz = False; @@ -3721,7 +3732,7 @@ ULong dis_Grp5 ( Prefix pfx, Int sz, Long delta, DisResult* dres ) assign(t2, binop(Iop_Sub64, getIReg64(R_RSP), mkU64(8))); putIReg64(R_RSP, mkexpr(t2)); storeLE( mkexpr(t2), mkU64(guest_RIP_bbstart+delta+len)); - make_redzone_AbiHint(t2, "call-Ev(mem)"); + make_redzone_AbiHint(vmi, t2, "call-Ev(mem)"); jmp_treg(Ijk_Call,t3); dres->whatNext = Dis_StopHere; showSz = False; @@ -7565,7 +7576,7 @@ ULong dis_xadd_G_E ( /*OUT*/Bool* decode_ok, //.. } static -void dis_ret ( ULong d64 ) +void dis_ret ( VexMiscInfo* vmi, ULong d64 ) { IRTemp t1 = newTemp(Ity_I64); IRTemp t2 = newTemp(Ity_I64); @@ -7574,7 +7585,7 @@ void dis_ret ( ULong d64 ) assign(t2, loadLE(Ity_I64,mkexpr(t1))); assign(t3, binop(Iop_Add64, mkexpr(t1), mkU64(8+d64))); putIReg64(R_RSP, mkexpr(t3)); - make_redzone_AbiHint(t3, "ret"); + make_redzone_AbiHint(vmi, t3, "ret"); jmp_treg(Ijk_Ret,t2); } @@ -8218,7 +8229,8 @@ DisResult disInstr_AMD64_WRK ( Bool (*resteerOkFn) ( /*opaque*/void*, Addr64 ), void* callback_opaque, Long delta64, - VexArchInfo* archinfo + VexArchInfo* archinfo, + VexMiscInfo* vmi ) { IRType ty; @@ -12170,7 +12182,7 @@ DisResult disInstr_AMD64_WRK ( case 0xC3: /* RET */ if (haveF2(pfx)) goto decode_failure; /* F3 is acceptable on AMD. */ - dis_ret(0); + dis_ret(vmi, 0); dres.whatNext = Dis_StopHere; DIP(haveF3(pfx) ? "rep ; ret\n" : "ret\n"); break; @@ -12184,7 +12196,7 @@ DisResult disInstr_AMD64_WRK ( assign(t1, binop(Iop_Sub64, getIReg64(R_RSP), mkU64(8))); putIReg64(R_RSP, mkexpr(t1)); storeLE( mkexpr(t1), mkU64(guest_RIP_bbstart+delta)); - make_redzone_AbiHint(t1, "call-d32"); + make_redzone_AbiHint(vmi, t1, "call-d32"); if (resteerOkFn( callback_opaque, (Addr64)d64) ) { /* follow into the call target. */ dres.whatNext = Dis_Resteer; @@ -13711,7 +13723,7 @@ DisResult disInstr_AMD64_WRK ( case 0xFF: /* Grp5 Ev */ if (haveF2orF3(pfx)) goto decode_failure; - delta = dis_Grp5 ( pfx, sz, delta, &dres ); + delta = dis_Grp5 ( vmi, pfx, sz, delta, &dres ); break; /* ------------------------ Escapes to 2-byte opcodes -- */ @@ -14340,6 +14352,7 @@ DisResult disInstr_AMD64 ( IRBB* irbb_IN, Addr64 guest_IP, VexArch guest_arch, VexArchInfo* archinfo, + VexMiscInfo* miscinfo, Bool host_bigendian_IN ) { DisResult dres; @@ -14357,7 +14370,7 @@ DisResult disInstr_AMD64 ( IRBB* irbb_IN, guest_RIP_next_mustcheck = False; dres = disInstr_AMD64_WRK ( put_IP, resteerOkFn, callback_opaque, - delta, archinfo ); + delta, archinfo, miscinfo ); /* If disInstr_AMD64_WRK tried to figure out the next rip, check it got it right. Failure of this assertion is serious and denotes diff --git a/VEX/priv/guest-generic/bb_to_IR.c b/VEX/priv/guest-generic/bb_to_IR.c index c79f4b4fea..e262a551ad 100644 --- a/VEX/priv/guest-generic/bb_to_IR.c +++ b/VEX/priv/guest-generic/bb_to_IR.c @@ -101,6 +101,7 @@ IRBB* bb_to_IR ( /*OUT*/VexGuestExtents* vge, /*IN*/ Bool host_bigendian, /*IN*/ VexArch arch_guest, /*IN*/ VexArchInfo* archinfo_guest, + /*IN*/ VexMiscInfo* miscinfo_both, /*IN*/ IRType guest_word_type, /*IN*/ Bool do_self_check, /*IN*/ Bool (*preamble_function)(void*,IRBB*), @@ -234,6 +235,7 @@ IRBB* bb_to_IR ( /*OUT*/VexGuestExtents* vge, guest_IP_curr_instr, arch_guest, archinfo_guest, + miscinfo_both, host_bigendian ); /* stay sane ... */ @@ -342,6 +344,7 @@ IRBB* bb_to_IR ( /*OUT*/VexGuestExtents* vge, UInt len2check, adler32; IRTemp tistart_tmp, tilen_tmp; + HWord p_adler_helper; vassert(vge->n_used == 1); len2check = vge->len[0]; @@ -373,6 +376,10 @@ IRBB* bb_to_IR ( /*OUT*/VexGuestExtents* vge, irbb->stmts[selfcheck_idx+3] = IRStmt_Put( offB_TILEN, IRExpr_Tmp(tilen_tmp) ); + p_adler_helper = miscinfo_both->host_ppc_calls_use_fndescrs + ? ((HWord*)(&genericg_compute_adler32))[0] + : (HWord)&genericg_compute_adler32; + irbb->stmts[selfcheck_idx+4] = IRStmt_Exit( IRExpr_Binop( @@ -381,11 +388,7 @@ IRBB* bb_to_IR ( /*OUT*/VexGuestExtents* vge, Ity_I32, 2/*regparms*/, "genericg_compute_adler32", -#if defined(__powerpc__) && defined(__powerpc64__) - (void*)((ULong*)(&genericg_compute_adler32))[0], -#else - &genericg_compute_adler32, -#endif + (void*)p_adler_helper, mkIRExprVec_2( mkIRExpr_HWord( (HWord)guest_code ), mkIRExpr_HWord( (HWord)len2check ) diff --git a/VEX/priv/guest-generic/bb_to_IR.h b/VEX/priv/guest-generic/bb_to_IR.h index 935b920ebe..e1fab3b93c 100644 --- a/VEX/priv/guest-generic/bb_to_IR.h +++ b/VEX/priv/guest-generic/bb_to_IR.h @@ -143,6 +143,9 @@ typedef /*IN*/ VexArch guest_arch, /*IN*/ VexArchInfo* archinfo, + /* Misc info about guest and host */ + /*IN*/ VexMiscInfo* miscinfo, + /* Is the host bigendian? */ /*IN*/ Bool host_bigendian @@ -164,6 +167,7 @@ IRBB* bb_to_IR ( /*OUT*/VexGuestExtents* vge, /*IN*/ Bool host_bigendian, /*IN*/ VexArch arch_guest, /*IN*/ VexArchInfo* archinfo_guest, + /*IN*/ VexMiscInfo* miscinfo_both, /*IN*/ IRType guest_word_type, /*IN*/ Bool do_self_check, /*IN*/ Bool (*preamble_function)(void*,IRBB*), diff --git a/VEX/priv/guest-ppc/gdefs.h b/VEX/priv/guest-ppc/gdefs.h index 3f9295d231..1c9aaa9ab4 100644 --- a/VEX/priv/guest-ppc/gdefs.h +++ b/VEX/priv/guest-ppc/gdefs.h @@ -67,6 +67,7 @@ DisResult disInstr_PPC ( IRBB* irbb, Addr64 guest_IP, VexArch guest_arch, VexArchInfo* archinfo, + VexMiscInfo* miscinfo, Bool host_bigendian ); /* Used by the optimiser to specialise calls to helpers. */ diff --git a/VEX/priv/guest-ppc/ghelpers.c b/VEX/priv/guest-ppc/ghelpers.c index 300f13ce0c..8eb35b244b 100644 --- a/VEX/priv/guest-ppc/ghelpers.c +++ b/VEX/priv/guest-ppc/ghelpers.c @@ -78,7 +78,7 @@ /* Reads a complete, consistent 64-bit TB value. */ ULong ppcg_dirtyhelper_MFTB ( void ) { -# if defined(__powerpc__) +# if defined(__powerpc__) || defined(_AIX) ULong res; UInt lo, hi1, hi2; while (1) { @@ -320,6 +320,7 @@ void LibVEX_GuestPPC64_put_XER ( UInt xer_native, /* VISIBLE TO LIBVEX CLIENT */ void LibVEX_GuestPPC32_initialise ( /*OUT*/VexGuestPPC32State* vex_state ) { + Int i; vex_state->guest_GPR0 = 0; vex_state->guest_GPR1 = 0; vex_state->guest_GPR2 = 0; @@ -464,6 +465,14 @@ void LibVEX_GuestPPC32_initialise ( /*OUT*/VexGuestPPC32State* vex_state ) vex_state->guest_TILEN = 0; vex_state->guest_NRADDR = 0; + vex_state->guest_NRADDR_GPR2 = 0; + + vex_state->guest_REDIR_SP = -1; + for (i = 0; i < VEX_GUEST_PPC32_REDIR_STACK_SIZE; i++) + vex_state->guest_REDIR_STACK[i] = 0; + + vex_state->guest_CIA_AT_SC = 0; + vex_state->guest_SPRG3_RO = 0; } @@ -620,6 +629,9 @@ void LibVEX_GuestPPC64_initialise ( /*OUT*/VexGuestPPC64State* vex_state ) vex_state->guest_REDIR_SP = -1; for (i = 0; i < VEX_GUEST_PPC64_REDIR_STACK_SIZE; i++) vex_state->guest_REDIR_STACK[i] = 0; + + vex_state->guest_CIA_AT_SC = 0; + vex_state->guest_SPRG3_RO = 0; } @@ -733,7 +745,7 @@ VexGuestLayout /* Describe any sections to be regarded by Memcheck as 'always-defined'. */ - .n_alwaysDefd = 8, + .n_alwaysDefd = 12, .alwaysDefd = { /* 0 */ ALWAYSDEFD32(guest_CIA), @@ -743,7 +755,11 @@ VexGuestLayout /* 4 */ ALWAYSDEFD32(guest_VSCR), /* 5 */ ALWAYSDEFD32(guest_FPROUND), /* 6 */ ALWAYSDEFD32(guest_RESVN), - /* 7 */ ALWAYSDEFD32(guest_NRADDR) + /* 7 */ ALWAYSDEFD32(guest_NRADDR), + /* 8 */ ALWAYSDEFD32(guest_NRADDR_GPR2), + /* 9 */ ALWAYSDEFD32(guest_REDIR_SP), + /* 10 */ ALWAYSDEFD32(guest_REDIR_STACK), + /* 11 */ ALWAYSDEFD32(guest_CIA_AT_SC) } }; @@ -767,7 +783,7 @@ VexGuestLayout /* Describe any sections to be regarded by Memcheck as 'always-defined'. */ - .n_alwaysDefd = 11, + .n_alwaysDefd = 12, .alwaysDefd = { /* 0 */ ALWAYSDEFD64(guest_CIA), @@ -780,7 +796,8 @@ VexGuestLayout /* 7 */ ALWAYSDEFD64(guest_NRADDR), /* 8 */ ALWAYSDEFD64(guest_NRADDR_GPR2), /* 9 */ ALWAYSDEFD64(guest_REDIR_SP), - /* 10 */ ALWAYSDEFD64(guest_REDIR_STACK) + /* 10 */ ALWAYSDEFD64(guest_REDIR_STACK), + /* 11 */ ALWAYSDEFD64(guest_CIA_AT_SC) } }; diff --git a/VEX/priv/guest-ppc/toIR.c b/VEX/priv/guest-ppc/toIR.c index 9b9e5a7838..0d23e731fe 100644 --- a/VEX/priv/guest-ppc/toIR.c +++ b/VEX/priv/guest-ppc/toIR.c @@ -75,7 +75,7 @@ Non-Java mode would give us more inaccuracy, as our intermediate results would then be zeroed, too. - - 64-bit mode: AbiHints for the stack red zone are only emitted for + - AbiHints for the stack red zone are only emitted for unconditional calls and returns (bl, blr). They should also be emitted for conditional calls and returns, but we don't have a way to express that right now. Ah well. @@ -102,7 +102,7 @@ 7C210B78 (or 1,1,1) %R3 = client_request ( %R4 ) 7C421378 (or 2,2,2) %R3 = guest_NRADDR 7C631B78 (or 3,3,3) branch-and-link-to-noredir %R11 - 7C842378 (or 4,4,4) %R3 = guest_NRADDR_GPR2 (64-bit mode only) + 7C842378 (or 4,4,4) %R3 = guest_NRADDR_GPR2 Any other bytes following the 16-byte preamble are illegal and constitute a failure in instruction decoding. This all assumes @@ -178,17 +178,21 @@ static Bool mode64 = False; // Given a pointer to a function as obtained by "& functionname" in C, // produce a pointer to the actual entry point for the function. For // most platforms it's the identity function. Unfortunately, on -// ppc64-linux it isn't (sigh). -static void* fnptr_to_fnentry( void* f ) -{ -#if defined(__powerpc64__) - /* f is a pointer to a 3-word function descriptor, of which - the first word is the entry address. */ - ULong* fdescr = (ULong*)f; - return (void*)(fdescr[0]); -#else - return f; -#endif +// ppc64-linux it isn't (sigh) and ditto for ppc32-aix5 and +// ppc64-aix5. +static void* fnptr_to_fnentry( VexMiscInfo* vmi, void* f ) +{ + if (vmi->host_ppc_calls_use_fndescrs) { + /* f is a pointer to a 3-word function descriptor, of which the + first word is the entry address. */ + /* note, this is correct even with cross-jitting, since this is + purely a host issue, not a guest one. */ + HWord* fdescr = (HWord*)f; + return (void*)(fdescr[0]); + } else { + /* Simple; "& f" points directly at the code for f. */ + return f; + } } @@ -213,25 +217,24 @@ static void* fnptr_to_fnentry( void* f ) (mode64 ? offsetof(VexGuestPPC64State, _x) : \ offsetof(VexGuestPPC32State, _x)) -#define OFFB_CIA offsetofPPCGuestState(guest_CIA) -#define OFFB_LR offsetofPPCGuestState(guest_LR) -#define OFFB_CTR offsetofPPCGuestState(guest_CTR) -#define OFFB_XER_SO offsetofPPCGuestState(guest_XER_SO) -#define OFFB_XER_OV offsetofPPCGuestState(guest_XER_OV) -#define OFFB_XER_CA offsetofPPCGuestState(guest_XER_CA) -#define OFFB_XER_BC offsetofPPCGuestState(guest_XER_BC) -#define OFFB_FPROUND offsetofPPCGuestState(guest_FPROUND) -#define OFFB_VRSAVE offsetofPPCGuestState(guest_VRSAVE) -#define OFFB_VSCR offsetofPPCGuestState(guest_VSCR) -#define OFFB_EMWARN offsetofPPCGuestState(guest_EMWARN) -#define OFFB_TISTART offsetofPPCGuestState(guest_TISTART) -#define OFFB_TILEN offsetofPPCGuestState(guest_TILEN) -#define OFFB_RESVN offsetofPPCGuestState(guest_RESVN) -#define OFFB_NRADDR offsetofPPCGuestState(guest_NRADDR) - -/* This only exists in the 64-bit guest state */ -#define OFFB64_NRADDR_GPR2 \ - offsetof(VexGuestPPC64State,guest_NRADDR_GPR2) +#define OFFB_CIA offsetofPPCGuestState(guest_CIA) +#define OFFB_CIA_AT_SC offsetofPPCGuestState(guest_CIA_AT_SC) +#define OFFB_SPRG3_RO offsetofPPCGuestState(guest_SPRG3_RO) +#define OFFB_LR offsetofPPCGuestState(guest_LR) +#define OFFB_CTR offsetofPPCGuestState(guest_CTR) +#define OFFB_XER_SO offsetofPPCGuestState(guest_XER_SO) +#define OFFB_XER_OV offsetofPPCGuestState(guest_XER_OV) +#define OFFB_XER_CA offsetofPPCGuestState(guest_XER_CA) +#define OFFB_XER_BC offsetofPPCGuestState(guest_XER_BC) +#define OFFB_FPROUND offsetofPPCGuestState(guest_FPROUND) +#define OFFB_VRSAVE offsetofPPCGuestState(guest_VRSAVE) +#define OFFB_VSCR offsetofPPCGuestState(guest_VSCR) +#define OFFB_EMWARN offsetofPPCGuestState(guest_EMWARN) +#define OFFB_TISTART offsetofPPCGuestState(guest_TISTART) +#define OFFB_TILEN offsetofPPCGuestState(guest_TILEN) +#define OFFB_RESVN offsetofPPCGuestState(guest_RESVN) +#define OFFB_NRADDR offsetofPPCGuestState(guest_NRADDR) +#define OFFB_NRADDR_GPR2 offsetofPPCGuestState(guest_NRADDR_GPR2) /*------------------------------------------------------------*/ @@ -324,6 +327,8 @@ typedef enum { PPC_GST_TISTART,// For icbi: start of area to invalidate PPC_GST_TILEN, // For icbi: length of area to invalidate PPC_GST_RESVN, // For lwarx/stwcx. + PPC_GST_CIA_AT_SC, // the CIA of the most recently executed SC insn + PPC_GST_SPRG3_RO, // SPRG3 PPC_GST_MAX } PPC_GST; @@ -1203,19 +1208,28 @@ static IRExpr* addr_align( IRExpr* addr, UChar align ) } -/* Generate AbiHints which mark points at which the ELF ppc64 ABI says - that the stack red zone (viz, -288(r1) .. -1(r1)) becomes - undefined. That is at function calls and returns. Only in 64-bit - mode - ELF ppc32 doesn't have this "feature". +/* Generate AbiHints which mark points at which the ELF or PowerOpen + ABIs say that the stack red zone (viz, -N(r1) .. -1(r1), for some + N) becomes undefined. That is at function calls and returns. ELF + ppc32 doesn't have this "feature" (how fortunate for it). */ -static void make_redzone_AbiHint ( HChar* who ) +static void make_redzone_AbiHint ( VexMiscInfo* vmi, HChar* who ) { + Int szB = vmi->guest_stack_redzone_size; if (0) vex_printf("AbiHint: %s\n", who); - vassert(mode64); - stmt( IRStmt_AbiHint( - binop(Iop_Sub64, getIReg(1), mkU64(288)), - 288 - )); + vassert(szB >= 0); + if (szB > 0) { + if (mode64) + stmt( IRStmt_AbiHint( + binop(Iop_Sub64, getIReg(1), mkU64(szB)), + szB + )); + else + stmt( IRStmt_AbiHint( + binop(Iop_Sub32, getIReg(1), mkU32(szB)), + szB + )); + } } @@ -2051,6 +2065,12 @@ static IRExpr* /* :: Ity_I32/64 */ getGST ( PPC_GST reg ) { IRType ty = mode64 ? Ity_I64 : Ity_I32; switch (reg) { + case PPC_GST_SPRG3_RO: + return IRExpr_Get( OFFB_SPRG3_RO, ty ); + + case PPC_GST_CIA: + return IRExpr_Get( OFFB_CIA, ty ); + case PPC_GST_LR: return IRExpr_Get( OFFB_LR, ty ); @@ -2181,6 +2201,10 @@ static void putGST ( PPC_GST reg, IRExpr* src ) IRType ty_src = typeOfIRExpr(irbb->tyenv,src ); vassert( reg < PPC_GST_MAX ); switch (reg) { + case PPC_GST_CIA_AT_SC: + vassert( ty_src == ty ); + stmt( IRStmt_Put( OFFB_CIA_AT_SC, src ) ); + break; case PPC_GST_CIA: vassert( ty_src == ty ); stmt( IRStmt_Put( OFFB_CIA, src ) ); @@ -3714,7 +3738,7 @@ static Bool dis_int_load ( UInt theInstr ) /* Integer Store Instructions */ -static Bool dis_int_store ( UInt theInstr ) +static Bool dis_int_store ( UInt theInstr, VexMiscInfo* vmi ) { /* D-Form, X-Form, DS-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -4211,6 +4235,7 @@ static IRExpr* /* :: Ity_I32 */ branch_cond_ok( UInt BO, UInt BI ) Integer Branch Instructions */ static Bool dis_branch ( UInt theInstr, + VexMiscInfo* vmi, /*OUT*/DisResult* dres, Bool (*resteerOkFn)(void*,Addr64), void* callback_opaque ) @@ -4263,8 +4288,10 @@ static Bool dis_branch ( UInt theInstr, if (flag_LK) { putGST( PPC_GST_LR, e_nia ); - if (mode64) - make_redzone_AbiHint( "branch-and-link (unconditional call)" ); + if (vmi->guest_ppc_zap_RZ_at_bl + && vmi->guest_ppc_zap_RZ_at_bl( (ULong)tgt) ) + make_redzone_AbiHint( vmi, + "branch-and-link (unconditional call)" ); } if (resteerOkFn( callback_opaque, tgt )) { @@ -4378,8 +4405,8 @@ static Bool dis_branch ( UInt theInstr, Ijk_Boring, c_nia )); - if (vanilla_return && mode64) - make_redzone_AbiHint( "branch-to-lr (unconditional return)" ); + if (vanilla_return && vmi->guest_ppc_zap_RZ_at_blr) + make_redzone_AbiHint( vmi, "branch-to-lr (unconditional return)" ); /* blrl is pretty strange; it's like a return that sets the return address of its caller to the insn following this @@ -4627,7 +4654,8 @@ static Bool dis_trapi ( UInt theInstr, /* System Linkage Instructions */ -static Bool dis_syslink ( UInt theInstr, DisResult* dres ) +static Bool dis_syslink ( UInt theInstr, + VexMiscInfo* miscinfo, DisResult* dres ) { IRType ty = mode64 ? Ity_I64 : Ity_I32; @@ -4638,11 +4666,22 @@ static Bool dis_syslink ( UInt theInstr, DisResult* dres ) // sc (System Call, PPC32 p504) DIP("sc\n"); - + + /* Copy CIA into the CIA_AT_SC pseudo-register, so that on AIX + Valgrind can back the guest up to this instruction if it needs + to restart the syscall. */ + putGST( PPC_GST_CIA_AT_SC, getGST( PPC_GST_CIA ) ); + /* It's important that all ArchRegs carry their up-to-date value at this point. So we declare an end-of-block here, which forces any TempRegs caching ArchRegs to be flushed. */ - irbb->next = mkSzImm( ty, nextInsnAddr() ); + /* At this point, AIX's behaviour differs from Linux's: AIX resumes + after the syscall at %lr, whereas Linux does the obvious thing + and resumes at the next instruction. Hence we need to encode + that into the generated IR. */ + irbb->next = miscinfo->guest_ppc_sc_continues_at_LR + ? /*AIXishly*/getGST( PPC_GST_LR ) + : /*Linuxfully*/mkSzImm( ty, nextInsnAddr() ); irbb->jumpkind = Ijk_Sys_syscall; dres->whatNext = Dis_StopHere; @@ -5193,7 +5232,7 @@ static Bool dis_int_ldst_rev ( UInt theInstr ) /* Processor Control Instructions */ -static Bool dis_proc_ctl ( UInt theInstr ) +static Bool dis_proc_ctl ( VexMiscInfo* vmi, UInt theInstr ) { UChar opc1 = ifieldOPC(theInstr); @@ -5290,7 +5329,12 @@ static Bool dis_proc_ctl ( UInt theInstr ) putIReg( rD_addr, mkSzWiden32(ty, getGST( PPC_GST_VRSAVE ), /* Signed */False) ); break; - + + case 0x103: + DIP("mfspr r%u, SPRG3(readonly)\n", rD_addr); + putIReg( rD_addr, getGST( PPC_GST_SPRG3_RO ) ); + break; + default: vex_printf("dis_proc_ctl(ppc)(mfspr,SPR)(0x%x)\n", SPR); return False; @@ -5304,7 +5348,7 @@ static Bool dis_proc_ctl ( UInt theInstr ) val, 0/*regparms*/, "ppcg_dirtyhelper_MFTB", - fnptr_to_fnentry(&ppcg_dirtyhelper_MFTB), + fnptr_to_fnentry(vmi, &ppcg_dirtyhelper_MFTB), args ); /* execute the dirty call, dumping the result in val. */ stmt( IRStmt_Dirty(d) ); @@ -6708,7 +6752,7 @@ static Bool dis_av_procctl ( UInt theInstr ) /* AltiVec Load Instructions */ -static Bool dis_av_load ( UInt theInstr ) +static Bool dis_av_load ( VexMiscInfo* vmi, UInt theInstr ) { /* X-Form */ UChar opc1 = ifieldOPC(theInstr); @@ -6744,13 +6788,13 @@ static Bool dis_av_load ( UInt theInstr ) d = unsafeIRDirty_0_N ( 0/*regparms*/, "ppc32g_dirtyhelper_LVS", - fnptr_to_fnentry(&ppc32g_dirtyhelper_LVS), + fnptr_to_fnentry(vmi, &ppc32g_dirtyhelper_LVS), args ); } else { d = unsafeIRDirty_0_N ( 0/*regparms*/, "ppc64g_dirtyhelper_LVS", - fnptr_to_fnentry(&ppc64g_dirtyhelper_LVS), + fnptr_to_fnentry(vmi, &ppc64g_dirtyhelper_LVS), args ); } DIP("lvsl v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); @@ -6777,13 +6821,13 @@ static Bool dis_av_load ( UInt theInstr ) d = unsafeIRDirty_0_N ( 0/*regparms*/, "ppc32g_dirtyhelper_LVS", - fnptr_to_fnentry(&ppc32g_dirtyhelper_LVS), + fnptr_to_fnentry(vmi, &ppc32g_dirtyhelper_LVS), args ); } else { d = unsafeIRDirty_0_N ( 0/*regparms*/, "ppc64g_dirtyhelper_LVS", - fnptr_to_fnentry(&ppc64g_dirtyhelper_LVS), + fnptr_to_fnentry(vmi, &ppc64g_dirtyhelper_LVS), args ); } DIP("lvsr v%d,r%u,r%u\n", vD_addr, rA_addr, rB_addr); @@ -8694,7 +8738,8 @@ DisResult disInstr_PPC_WRK ( Bool (*resteerOkFn) ( /*opaque*/void*, Addr64 ), void* callback_opaque, Long delta64, - VexArchInfo* archinfo + VexArchInfo* archinfo, + VexMiscInfo* miscinfo ) { UChar opc1; @@ -8797,14 +8842,12 @@ DisResult disInstr_PPC_WRK ( goto decode_success; } else - if (mode64 - && getUIntBigendianly(code+16) == 0x7C842378 /* or 4,4,4 */) { + if (getUIntBigendianly(code+16) == 0x7C842378 /* or 4,4,4 */) { /* %R3 = guest_NRADDR_GPR2 */ DIP("r3 = guest_NRADDR_GPR2\n"); delta += 20; dres.len = 20; - vassert(ty == Ity_I64); - putIReg(3, IRExpr_Get( OFFB64_NRADDR_GPR2, ty )); + putIReg(3, IRExpr_Get( OFFB_NRADDR_GPR2, ty )); goto decode_success; } /* We don't know what it is. Set opc1/opc2 so decode_failure @@ -8860,7 +8903,7 @@ DisResult disInstr_PPC_WRK ( /* Integer Store Instructions */ case 0x26: case 0x27: case 0x2C: // stb, stbu, sth case 0x2D: case 0x24: case 0x25: // sthu, stw, stwu - if (dis_int_store( theInstr )) goto decode_success; + if (dis_int_store( theInstr, miscinfo )) goto decode_success; goto decode_failure; /* Integer Load and Store Multiple Instructions */ @@ -8870,13 +8913,14 @@ DisResult disInstr_PPC_WRK ( /* Branch Instructions */ case 0x12: case 0x10: // b, bc - if (dis_branch(theInstr, &dres, resteerOkFn, callback_opaque)) + if (dis_branch(theInstr, miscinfo, &dres, + resteerOkFn, callback_opaque)) goto decode_success; goto decode_failure; /* System Linkage Instructions */ case 0x11: // sc - if (dis_syslink(theInstr, &dres)) goto decode_success; + if (dis_syslink(theInstr, miscinfo, &dres)) goto decode_success; goto decode_failure; /* Trap Instructions */ @@ -8941,7 +8985,7 @@ DisResult disInstr_PPC_WRK ( /* 64bit Integer Stores */ case 0x3E: // std, stdu if (!mode64) goto decode_failure; - if (dis_int_store( theInstr )) goto decode_success; + if (dis_int_store( theInstr, miscinfo )) goto decode_success; goto decode_failure; case 0x3F: @@ -9033,7 +9077,8 @@ DisResult disInstr_PPC_WRK ( /* Branch Instructions */ case 0x210: case 0x010: // bcctr, bclr - if (dis_branch(theInstr, &dres, resteerOkFn, callback_opaque)) + if (dis_branch(theInstr, miscinfo, &dres, + resteerOkFn, callback_opaque)) goto decode_success; goto decode_failure; @@ -9129,13 +9174,13 @@ DisResult disInstr_PPC_WRK ( /* Integer Store Instructions */ case 0x0F7: case 0x0D7: case 0x1B7: // stbux, stbx, sthux case 0x197: case 0x0B7: case 0x097: // sthx, stwux, stwx - if (dis_int_store( theInstr )) goto decode_success; + if (dis_int_store( theInstr, miscinfo )) goto decode_success; goto decode_failure; /* 64bit Integer Store Instructions */ case 0x0B5: case 0x095: // stdux, stdx if (!mode64) goto decode_failure; - if (dis_int_store( theInstr )) goto decode_success; + if (dis_int_store( theInstr, miscinfo )) goto decode_success; goto decode_failure; /* Integer Load and Store with Byte Reverse Instructions */ @@ -9173,7 +9218,7 @@ DisResult disInstr_PPC_WRK ( /* Processor Control Instructions */ case 0x200: case 0x013: case 0x153: // mcrxr, mfcr, mfspr case 0x173: case 0x090: case 0x1D3: // mftb, mtcrf, mtspr - if (dis_proc_ctl( theInstr )) goto decode_success; + if (dis_proc_ctl( miscinfo, theInstr )) goto decode_success; goto decode_failure; /* Cache Management Instructions */ @@ -9229,7 +9274,7 @@ DisResult disInstr_PPC_WRK ( case 0x007: case 0x027: case 0x047: // lvebx, lvehx, lvewx case 0x067: case 0x167: // lvx, lvxl if (!allow_V) goto decode_noV; - if (dis_av_load( theInstr )) goto decode_success; + if (dis_av_load( miscinfo, theInstr )) goto decode_success; goto decode_failure; /* AV Store */ @@ -9469,6 +9514,7 @@ DisResult disInstr_PPC ( IRBB* irbb_IN, Addr64 guest_IP, VexArch guest_arch, VexArchInfo* archinfo, + VexMiscInfo* miscinfo, Bool host_bigendian_IN ) { IRType ty; @@ -9504,7 +9550,7 @@ DisResult disInstr_PPC ( IRBB* irbb_IN, guest_CIA_bbstart = mkSzAddr(ty, guest_IP - delta); dres = disInstr_PPC_WRK ( put_IP, resteerOkFn, callback_opaque, - delta, archinfo ); + delta, archinfo, miscinfo ); return dres; } diff --git a/VEX/priv/guest-x86/gdefs.h b/VEX/priv/guest-x86/gdefs.h index 4ceaaa86f4..1a53a480d4 100644 --- a/VEX/priv/guest-x86/gdefs.h +++ b/VEX/priv/guest-x86/gdefs.h @@ -66,6 +66,7 @@ DisResult disInstr_X86 ( IRBB* irbb, Addr64 guest_IP, VexArch guest_arch, VexArchInfo* archinfo, + VexMiscInfo* miscinfo, Bool host_bigendian ); /* Used by the optimiser to specialise calls to helpers. */ diff --git a/VEX/priv/guest-x86/toIR.c b/VEX/priv/guest-x86/toIR.c index 8edb730d15..08ae111550 100644 --- a/VEX/priv/guest-x86/toIR.c +++ b/VEX/priv/guest-x86/toIR.c @@ -12902,6 +12902,7 @@ DisResult disInstr_X86 ( IRBB* irbb_IN, Addr64 guest_IP, VexArch guest_arch, VexArchInfo* archinfo, + VexMiscInfo* miscinfo, Bool host_bigendian_IN ) { DisResult dres; diff --git a/VEX/priv/host-amd64/hdefs.h b/VEX/priv/host-amd64/hdefs.h index a8475e9d28..9fd5ee64f4 100644 --- a/VEX/priv/host-amd64/hdefs.h +++ b/VEX/priv/host-amd64/hdefs.h @@ -725,7 +725,9 @@ extern Int emit_AMD64Instr ( UChar* buf, Int nbuf, AMD64Instr*, extern AMD64Instr* genSpill_AMD64 ( HReg rreg, Int offset, Bool ); extern AMD64Instr* genReload_AMD64 ( HReg rreg, Int offset, Bool ); extern void getAllocableRegs_AMD64 ( Int*, HReg** ); -extern HInstrArray* iselBB_AMD64 ( IRBB*, VexArch, VexArchInfo* ); +extern HInstrArray* iselBB_AMD64 ( IRBB*, VexArch, + VexArchInfo*, + VexMiscInfo* ); #endif /* ndef __LIBVEX_HOST_AMD64_HDEFS_H */ diff --git a/VEX/priv/host-amd64/isel.c b/VEX/priv/host-amd64/isel.c index 59117792bf..07b159d1ad 100644 --- a/VEX/priv/host-amd64/isel.c +++ b/VEX/priv/host-amd64/isel.c @@ -3801,8 +3801,9 @@ static void iselNext ( ISelEnv* env, IRExpr* next, IRJumpKind jk ) /* Translate an entire BB to amd64 code. */ -HInstrArray* iselBB_AMD64 ( IRBB* bb, VexArch arch_host, - VexArchInfo* archinfo_host ) +HInstrArray* iselBB_AMD64 ( IRBB* bb, VexArch arch_host, + VexArchInfo* archinfo_host, + VexMiscInfo* vmi/*UNUSED*/ ) { Int i, j; HReg hreg, hregHI; diff --git a/VEX/priv/host-ppc/hdefs.c b/VEX/priv/host-ppc/hdefs.c index 9c866ddaaa..2085157952 100644 --- a/VEX/priv/host-ppc/hdefs.c +++ b/VEX/priv/host-ppc/hdefs.c @@ -1123,67 +1123,13 @@ PPCInstr* PPCInstr_AvLdVSCR ( HReg src ) { /* Pretty Print instructions */ static void ppLoadImm ( HReg dst, ULong imm, Bool mode64 ) { -#if 1 vex_printf("li_word "); ppHRegPPC(dst); if (!mode64) { - vassert(imm == (ULong)(Long)(Int)(UInt)imm); vex_printf(",0x%08x", (UInt)imm); } else { vex_printf(",0x%016llx", imm); } -#else - if (imm >= 0xFFFFFFFFFFFF8000ULL || imm < 0x8000) { - // sign-extendable from 16 bits - vex_printf("li "); - ppHRegPPC(dst); - vex_printf(",0x%x", (UInt)imm); - } else { - if (imm >= 0xFFFFFFFF80000000ULL || imm < 0x80000000ULL) { - // sign-extendable from 32 bits - vex_printf("lis "); - ppHRegPPC(dst); - vex_printf(",0x%x ; ", (UInt)(imm >> 16)); - vex_printf("ori "); - ppHRegPPC(dst); - vex_printf(","); - ppHRegPPC(dst); - vex_printf(",0x%x", (UInt)(imm & 0xFFFF)); - } else { - // full 64bit immediate load: 5 (five!) insns. - vassert(mode64); - - // load high word - vex_printf("lis "); - ppHRegPPC(dst); - vex_printf(",0x%x ; ", (UInt)(imm >> 48) & 0xFFFF); - vex_printf("ori "); - ppHRegPPC(dst); - vex_printf(","); - ppHRegPPC(dst); - vex_printf(",0x%x ; ", (UInt)(imm >> 32) & 0xFFFF); - - // shift r_dst low word to high word => rldicr - vex_printf("rldicr "); - ppHRegPPC(dst); - vex_printf(","); - ppHRegPPC(dst); - vex_printf(",32,31 ; "); - - // load low word - vex_printf("oris "); - ppHRegPPC(dst); - vex_printf(","); - ppHRegPPC(dst); - vex_printf(",0x%x ; ", (UInt)(imm >> 16) & 0xFFFF); - vex_printf("ori "); - ppHRegPPC(dst); - vex_printf(","); - ppHRegPPC(dst); - vex_printf(",0x%x", (UInt)(imm >> 0) & 0xFFFF); - } - } -#endif } static void ppMovReg ( HReg dst, HReg src ) { @@ -2496,19 +2442,26 @@ static UChar* mkLoadImm ( UChar* p, UInt r_dst, ULong imm, Bool mode64 ) vassert(mode64); // load high word + // lis r_dst, (imm>>48) & 0xFFFF p = mkFormD(p, 15, r_dst, 0, (imm>>48) & 0xFFFF); + // ori r_dst, r_dst, (imm>>32) & 0xFFFF - p = mkFormD(p, 24, r_dst, r_dst, (imm>>32) & 0xFFFF); + if ((imm>>32) & 0xFFFF) + p = mkFormD(p, 24, r_dst, r_dst, (imm>>32) & 0xFFFF); // shift r_dst low word to high word => rldicr p = mkFormMD(p, 30, r_dst, r_dst, 32, 31, 1); // load low word + // oris r_dst, r_dst, (imm>>16) & 0xFFFF - p = mkFormD(p, 25, r_dst, r_dst, (imm>>16) & 0xFFFF); + if ((imm>>16) & 0xFFFF) + p = mkFormD(p, 25, r_dst, r_dst, (imm>>16) & 0xFFFF); + // ori r_dst, r_dst, (imm) & 0xFFFF - p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF); + if (imm & 0xFFFF) + p = mkFormD(p, 24, r_dst, r_dst, imm & 0xFFFF); } } return p; diff --git a/VEX/priv/host-ppc/hdefs.h b/VEX/priv/host-ppc/hdefs.h index 54d3f74d6f..ca71731aa1 100644 --- a/VEX/priv/host-ppc/hdefs.h +++ b/VEX/priv/host-ppc/hdefs.h @@ -838,7 +838,9 @@ extern Int emit_PPCInstr ( UChar* buf, Int nbuf, PPCInstr*, extern PPCInstr* genSpill_PPC ( HReg rreg, UShort offsetB, Bool mode64 ); extern PPCInstr* genReload_PPC ( HReg rreg, UShort offsetB, Bool mode64 ); extern void getAllocableRegs_PPC ( Int*, HReg**, Bool mode64 ); -extern HInstrArray* iselBB_PPC ( IRBB*, VexArch, VexArchInfo* ); +extern HInstrArray* iselBB_PPC ( IRBB*, VexArch, + VexArchInfo*, + VexMiscInfo* ); #endif /* ndef __LIBVEX_HOST_PPC_HDEFS_H */ diff --git a/VEX/priv/host-ppc/isel.c b/VEX/priv/host-ppc/isel.c index 89f88d3d87..4dda13da66 100644 --- a/VEX/priv/host-ppc/isel.c +++ b/VEX/priv/host-ppc/isel.c @@ -253,6 +253,9 @@ static IRExpr* bind ( Int binder ) was most recently set. Setting to NULL is always safe. Used to avoid redundant settings of the FPU's rounding mode, as described in set_FPU_rounding_mode below. + + - A VexMiscInfo*, needed for knowing how to generate + function calls for this target */ typedef @@ -275,6 +278,8 @@ typedef Bool mode64; IRExpr* previous_rm; + + VexMiscInfo* vmi; } ISelEnv; @@ -532,7 +537,7 @@ static PPCAMode* advance4 ( ISelEnv* env, PPCAMode* am ) /* Given a guest-state array descriptor, an index expression and a bias, generate a PPCAMode pointing at the relevant piece of - guest state. Only needed in 64-bit mode. */ + guest state. */ static PPCAMode* genGuestArrayOffset ( ISelEnv* env, IRArray* descr, IRExpr* off, Int bias ) @@ -542,23 +547,22 @@ PPCAMode* genGuestArrayOffset ( ISelEnv* env, IRArray* descr, Int nElems = descr->nElems; Int shift = 0; - vassert(env->mode64); - /* Throw out any cases we don't need. In theory there might be a day where we need to handle others, but not today. */ if (nElems != 16 && nElems != 32) - vpanic("genGuestArrayOffset(ppc64 host)(1)"); + vpanic("genGuestArrayOffset(ppc host)(1)"); switch (elemSz) { + case 4: shift = 2; break; case 8: shift = 3; break; - default: vpanic("genGuestArrayOffset(ppc64 host)(2)"); + default: vpanic("genGuestArrayOffset(ppc host)(2)"); } if (bias < -100 || bias > 100) /* somewhat arbitrarily */ - vpanic("genGuestArrayOffset(ppc64 host)(3)"); + vpanic("genGuestArrayOffset(ppc host)(3)"); if (descr->base < 0 || descr->base > 2000) /* somewhat arbitrarily */ - vpanic("genGuestArrayOffset(ppc64 host)(4)"); + vpanic("genGuestArrayOffset(ppc host)(4)"); /* Compute off into a reg, %off. Then return: @@ -580,7 +584,7 @@ PPCAMode* genGuestArrayOffset ( ISelEnv* env, IRArray* descr, PPCRH_Imm(False/*signed*/, toUShort(nElems-1)))); addInstr(env, PPCInstr_Shft( Pshft_SHL, - False/*64-bit shift*/, + env->mode64 ? False : True/*F:64-bit, T:32-bit shift*/, rtmp, rtmp, PPCRH_Imm(False/*unsigned*/, toUShort(shift)))); addInstr(env, PPCInstr_Alu( @@ -631,6 +635,11 @@ void doHelperCall ( ISelEnv* env, ULong target; Bool mode64 = env->mode64; + /* Do we need to force use of an odd-even reg pair for 64-bit + args? */ + Bool regalign_int64s + = (!mode64) && env->vmi->host_ppc32_regalign_int64_args; + /* Marshal args for a call and do the call. If passBBP is True, %rbp (the baseblock pointer) is to be passed @@ -756,8 +765,9 @@ void doHelperCall ( ISelEnv* env, iselWordExpr_R(env, args[i]) )); } else { // Ity_I64 HReg rHi, rLo; - if (argreg%2 == 1) // ppc32 abi spec for passing LONG_LONG - argreg++; // XXX: odd argreg => even rN + if (regalign_int64s && (argreg%2) == 1) + // ppc32 ELF abi spec for passing LONG_LONG + argreg++; // XXX: odd argreg => even rN vassert(argreg < PPC_N_REGPARMS-1); iselInt64Expr(&rHi,&rLo, env, args[i]); argiregs |= (1 << (argreg+3)); @@ -799,8 +809,9 @@ void doHelperCall ( ISelEnv* env, tmpregs[argreg] = iselWordExpr_R(env, args[i]); } else { // Ity_I64 HReg rHi, rLo; - if (argreg%2 == 1) // ppc32 abi spec for passing LONG_LONG - argreg++; // XXX: odd argreg => even rN + if (regalign_int64s && (argreg%2) == 1) + // ppc32 ELF abi spec for passing LONG_LONG + argreg++; // XXX: odd argreg => even rN vassert(argreg < PPC_N_REGPARMS-1); iselInt64Expr(&rHi,&rLo, env, args[i]); tmpregs[argreg++] = rHi; @@ -1788,17 +1799,23 @@ static HReg iselWordExpr_R_wrk ( ISelEnv* env, IRExpr* e ) break; } - case Iex_GetI: + case Iex_GetI: { + PPCAMode* src_am + = genGuestArrayOffset( env, e->Iex.GetI.descr, + e->Iex.GetI.ix, e->Iex.GetI.bias ); + HReg r_dst = newVRegI(env); if (mode64 && ty == Ity_I64) { - PPCAMode* src_am - = genGuestArrayOffset( env, e->Iex.GetI.descr, - e->Iex.GetI.ix, e->Iex.GetI.bias ); - HReg r_dst = newVRegI(env); addInstr(env, PPCInstr_Load( toUChar(8), r_dst, src_am, mode64 )); return r_dst; } + if ((!mode64) && ty == Ity_I32) { + addInstr(env, PPCInstr_Load( toUChar(4), + r_dst, src_am, mode64 )); + return r_dst; + } break; + } /* --------- CCALL --------- */ case Iex_CCall: { @@ -2485,8 +2502,8 @@ static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, HReg tLo = newVRegI(env); HReg tHi = newVRegI(env); vassert(e->Iex.Const.con->tag == Ico_U64); - addInstr(env, PPCInstr_LI(tHi, wHi, False/*mode32*/)); - addInstr(env, PPCInstr_LI(tLo, wLo, False/*mode32*/)); + addInstr(env, PPCInstr_LI(tHi, (Long)(Int)wHi, False/*mode32*/)); + addInstr(env, PPCInstr_LI(tLo, (Long)(Int)wLo, False/*mode32*/)); *rHi = tHi; *rLo = tLo; return; @@ -3674,21 +3691,26 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt ) } /* --------- Indexed PUT --------- */ - case Ist_PutI: - if (mode64) { - PPCAMode* dst_am - = genGuestArrayOffset( - env, stmt->Ist.PutI.descr, - stmt->Ist.PutI.ix, stmt->Ist.PutI.bias ); - IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.PutI.data); - if (ty == Ity_I64) { - HReg r_src = iselWordExpr_R(env, stmt->Ist.PutI.data); - addInstr(env, PPCInstr_Store( toUChar(8), - dst_am, r_src, mode64 )); - return; - } + case Ist_PutI: { + PPCAMode* dst_am + = genGuestArrayOffset( + env, stmt->Ist.PutI.descr, + stmt->Ist.PutI.ix, stmt->Ist.PutI.bias ); + IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.PutI.data); + if (mode64 && ty == Ity_I64) { + HReg r_src = iselWordExpr_R(env, stmt->Ist.PutI.data); + addInstr(env, PPCInstr_Store( toUChar(8), + dst_am, r_src, mode64 )); + return; + } + if ((!mode64) && ty == Ity_I32) { + HReg r_src = iselWordExpr_R(env, stmt->Ist.PutI.data); + addInstr(env, PPCInstr_Store( toUChar(4), + dst_am, r_src, mode64 )); + return; } break; + } /* --------- TMP --------- */ case Ist_Tmp: { @@ -3856,8 +3878,9 @@ static void iselNext ( ISelEnv* env, IRExpr* next, IRJumpKind jk ) /* Translate an entire BB to ppc code. */ -HInstrArray* iselBB_PPC ( IRBB* bb, VexArch arch_host, - VexArchInfo* archinfo_host ) +HInstrArray* iselBB_PPC ( IRBB* bb, VexArch arch_host, + VexArchInfo* archinfo_host, + VexMiscInfo* vmi ) { Int i, j; HReg hreg, hregHI; @@ -3904,6 +3927,7 @@ HInstrArray* iselBB_PPC ( IRBB* bb, VexArch arch_host, /* and finally ... */ env->hwcaps = hwcaps_host; env->previous_rm = NULL; + env->vmi = vmi; /* For each IR temporary, allocate a suitably-kinded virtual register. */ diff --git a/VEX/priv/host-x86/hdefs.h b/VEX/priv/host-x86/hdefs.h index c4ea61d6b5..29581905b9 100644 --- a/VEX/priv/host-x86/hdefs.h +++ b/VEX/priv/host-x86/hdefs.h @@ -665,7 +665,9 @@ extern Int emit_X86Instr ( UChar* buf, Int nbuf, X86Instr*, extern X86Instr* genSpill_X86 ( HReg rreg, Int offset, Bool ); extern X86Instr* genReload_X86 ( HReg rreg, Int offset, Bool ); extern void getAllocableRegs_X86 ( Int*, HReg** ); -extern HInstrArray* iselBB_X86 ( IRBB*, VexArch, VexArchInfo* ); +extern HInstrArray* iselBB_X86 ( IRBB*, VexArch, + VexArchInfo*, + VexMiscInfo* ); #endif /* ndef __LIBVEX_HOST_X86_HDEFS_H */ diff --git a/VEX/priv/host-x86/isel.c b/VEX/priv/host-x86/isel.c index 22e3ef6524..d22b6565e5 100644 --- a/VEX/priv/host-x86/isel.c +++ b/VEX/priv/host-x86/isel.c @@ -3604,8 +3604,9 @@ static void iselNext ( ISelEnv* env, IRExpr* next, IRJumpKind jk ) /* Translate an entire BB to x86 code. */ -HInstrArray* iselBB_X86 ( IRBB* bb, VexArch arch_host, - VexArchInfo* archinfo_host ) +HInstrArray* iselBB_X86 ( IRBB* bb, VexArch arch_host, + VexArchInfo* archinfo_host, + VexMiscInfo* vmi/*UNUSED*/ ) { Int i, j; HReg hreg, hregHI; diff --git a/VEX/priv/main/vex_main.c b/VEX/priv/main/vex_main.c index 0475f68709..a590774abb 100644 --- a/VEX/priv/main/vex_main.c +++ b/VEX/priv/main/vex_main.c @@ -193,7 +193,8 @@ VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta ) HInstr* (*genReload) ( HReg, Int, Bool ); void (*ppInstr) ( HInstr*, Bool ); void (*ppReg) ( HReg ); - HInstrArray* (*iselBB) ( IRBB*, VexArch, VexArchInfo* ); + HInstrArray* (*iselBB) ( IRBB*, VexArch, VexArchInfo*, + VexMiscInfo* ); Int (*emit) ( UChar*, Int, HInstr*, Bool, void* ); IRExpr* (*specHelper) ( HChar*, IRExpr** ); Bool (*preciseMemExnsFn) ( Int, Int ); @@ -432,6 +433,7 @@ VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta ) host_is_bigendian, vta->arch_guest, &vta->archinfo_guest, + &vta->miscinfo_both, guest_word_type, vta->do_self_check, vta->preamble_function, @@ -558,7 +560,8 @@ VexTranslateResult LibVEX_Translate ( VexTranslateArgs* vta ) " Instruction selection " "------------------------\n"); - vcode = iselBB ( irbb, vta->arch_host, &vta->archinfo_host ); + vcode = iselBB ( irbb, vta->arch_host, &vta->archinfo_host, + &vta->miscinfo_both ); vexAllocSanityCheck(); @@ -695,7 +698,6 @@ const HChar* LibVEX_ppVexHwCaps ( VexArch arch, UInt hwcaps ) } - /* Write default settings info *vai. */ void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai ) { @@ -703,6 +705,17 @@ void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai ) vai->ppc_cache_line_szB = 0; } +/* Write default settings info *vmi. */ +void LibVEX_default_VexMiscInfo ( /*OUT*/VexMiscInfo* vmi ) +{ + vmi->guest_stack_redzone_size = 0; + vmi->guest_ppc_zap_RZ_at_blr = False; + vmi->guest_ppc_zap_RZ_at_bl = NULL; + vmi->guest_ppc_sc_continues_at_LR = False; + vmi->host_ppc_calls_use_fndescrs = False; + vmi->host_ppc32_regalign_int64_args = False; +} + /* Return a string showing the hwcaps in a nice way. The string will be NULL for invalid combinations of flags, so these functions also diff --git a/VEX/pub/libvex.h b/VEX/pub/libvex.h index 26fe0b0502..f1cbd971e7 100644 --- a/VEX/pub/libvex.h +++ b/VEX/pub/libvex.h @@ -110,8 +110,8 @@ extern const HChar* LibVEX_ppVexHwCaps ( VexArch, UInt ); /* This struct is a bit of a hack, but is needed to carry misc - important bits of info about an arch. Fields which are optional or - ignored on some arch should be set to zero. */ + important bits of info about an arch. Fields which are meaningless + or ignored for the platform in question should be set to zero. */ typedef struct { @@ -127,6 +127,90 @@ extern void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai ); +/* This struct carries guest and host ABI variant information that may + be needed. Fields which are meaningless or ignored for the + platform in question should be set to zero. + + Settings which are believed to be correct are: + + guest_stack_redzone_size + guest is ppc32-linux ==> 0 + guest is ppc64-linux ==> 288 + guest is ppc32-aix5 ==> 220 + guest is ppc64-aix5 ==> unknown + guest is amd64-linux ==> 128 + guest is other ==> inapplicable + + guest_ppc_zap_RZ_at_blr + guest is ppc64-linux ==> True + guest is ppc32-linux ==> False + guest is ppc64-aix5 ==> unknown + guest is ppc32-aix5 ==> False + guest is other ==> inapplicable + + guest_ppc_zap_RZ_at_bl + guest is ppc64-linux ==> const True + guest is ppc32-linux ==> const False + guest is ppc64-aix5 ==> unknown + guest is ppc32-aix5 ==> True except for calls to + millicode, $SAVEFn, $RESTFn + guest is other ==> inapplicable + + guest_ppc_sc_continues_at_LR: + guest is ppc32-aix5 or ppc64-aix5 ==> True + guest is ppc32-linux or ppc64-linux ==> False + guest is other ==> inapplicable + + host_ppc_calls_use_fndescrs: + host is ppc32-linux ==> False + host is ppc64-linux ==> True + host is ppc32-aix5 or ppc64-aix5 ==> True + host is other ==> inapplicable + + host_ppc32_regalign_int64_args: + host is ppc32-linux ==> True + host is ppc32-aix5 ==> False + host is other ==> inapplicable +*/ + +typedef + struct { + /* PPC and AMD64 GUESTS only: how many bytes below the + stack pointer are validly addressible? */ + Int guest_stack_redzone_size; + + /* PPC GUESTS only: should we zap the stack red zone at a 'blr' + (function return) ? */ + Bool guest_ppc_zap_RZ_at_blr; + + /* PPC GUESTS only: should we zap the stack red zone at a 'bl' + (function call) ? Is supplied with the guest address of the + target of the call since that may be significant. If NULL, + is assumed equivalent to a fn which always returns False. */ + Bool (*guest_ppc_zap_RZ_at_bl)(Addr64); + + /* PPC32/PPC64 GUESTS only: where does the kernel resume after + 'sc'? False => Linux style, at the next insn. True => AIX + style, at the address stated in the link register. */ + Bool guest_ppc_sc_continues_at_LR; + + /* PPC32/PPC64 HOSTS only: does '&f' give us a pointer to a + function descriptor on the host, or to the function code + itself? True => descriptor, False => code. */ + Bool host_ppc_calls_use_fndescrs; + + /* PPC32 HOSTS only: when generating code to pass a 64-bit value + (actual parameter) in a pair of regs, should we skip an arg + reg if it is even-numbered? True => yes, False => no. */ + Bool host_ppc32_regalign_int64_args; + } + VexMiscInfo; + +/* Write default settings info *vmi. */ +extern +void LibVEX_default_VexMiscInfo ( /*OUT*/VexMiscInfo* vmi ); + + /*-------------------------------------------------------*/ /*--- Control of Vex's optimiser (iropt). ---*/ /*-------------------------------------------------------*/ @@ -320,11 +404,13 @@ typedef many of them, it seems better to have a structure. */ typedef struct { - /* IN: The instruction sets we are translating from and to. */ + /* IN: The instruction sets we are translating from and to. And + guest/host misc info. */ VexArch arch_guest; VexArchInfo archinfo_guest; VexArch arch_host; VexArchInfo archinfo_host; + VexMiscInfo miscinfo_both; /* IN: an opaque value which is passed as the first arg to all callback functions supplied in this struct. Vex has no idea diff --git a/VEX/pub/libvex_basictypes.h b/VEX/pub/libvex_basictypes.h index 370f5f9ab8..d22bc63887 100644 --- a/VEX/pub/libvex_basictypes.h +++ b/VEX/pub/libvex_basictypes.h @@ -135,6 +135,7 @@ typedef unsigned long HWord; #undef VEX_HOST_WORDSIZE +/* The following 4 work OK for Linux. */ #if defined(__x86_64__) # define VEX_HOST_WORDSIZE 8 #elif defined(__i386__) @@ -143,6 +144,12 @@ typedef unsigned long HWord; # define VEX_HOST_WORDSIZE 8 #elif defined(__powerpc__) && !defined(__powerpc64__) # define VEX_HOST_WORDSIZE 4 + +#elif defined(_AIX) && !defined(__64BIT__) +# define VEX_HOST_WORDSIZE 4 +#elif defined(_AIX) && defined(__64BIT__) +# define VEX_HOST_WORDSIZE 8 + #else # error "Vex: Fatal: Can't establish the host architecture" #endif diff --git a/VEX/pub/libvex_guest_ppc32.h b/VEX/pub/libvex_guest_ppc32.h index 4203e3b146..7c8bb9b5ea 100644 --- a/VEX/pub/libvex_guest_ppc32.h +++ b/VEX/pub/libvex_guest_ppc32.h @@ -55,6 +55,8 @@ /*--- Vex's representation of the PPC32 CPU state ---*/ /*---------------------------------------------------------------*/ +#define VEX_GUEST_PPC32_REDIR_STACK_SIZE (16/*entries*/ * 2/*words per entry*/) + typedef struct { /* General Purpose Registers */ @@ -214,10 +216,25 @@ typedef Note, this is only set for wrap-style redirects, not for replace-style ones. */ /* 956 */ UInt guest_NRADDR; + /* 960 */ UInt guest_NRADDR_GPR2; /* needed by aix */ + + /* A grows-upwards stack for hidden saves/restores of LR and R2 + needed for function interception and wrapping on ppc32-aix5. + A horrible hack. REDIR_SP points to the highest live entry, + and so starts at -1. */ + /* 964 */ UInt guest_REDIR_SP; + /* 968 */ UInt guest_REDIR_STACK[VEX_GUEST_PPC32_REDIR_STACK_SIZE]; + + /* Needed for AIX: CIA at the last SC insn. Used when backing up + to restart a syscall that has been interrupted by a signal. */ + /* ??? */ UInt guest_CIA_AT_SC; + + /* SPRG3, which AIUI is readonly in user space. Needed for + threading on AIX. */ + /* ??? */ UInt guest_SPRG3_RO; /* Padding to make it have an 8-aligned size */ - /* 956 */ UInt padding; - /* 960 */ + /* UInt padding; */ } VexGuestPPC32State; diff --git a/VEX/pub/libvex_guest_ppc64.h b/VEX/pub/libvex_guest_ppc64.h index fec4e564f2..12b71348ff 100644 --- a/VEX/pub/libvex_guest_ppc64.h +++ b/VEX/pub/libvex_guest_ppc64.h @@ -266,6 +266,14 @@ typedef /* 1128 */ ULong guest_REDIR_SP; /* 1136 */ ULong guest_REDIR_STACK[VEX_GUEST_PPC64_REDIR_STACK_SIZE]; + /* Needed for AIX: CIA at the last SC insn. Used when backing up + to restart a syscall that has been interrupted by a signal. */ + /* ???? */ ULong guest_CIA_AT_SC; + + /* SPRG3, which AIUI is readonly in user space. Needed for + threading on AIX. */ + /* ???? */ ULong guest_SPRG3_RO; + /* Padding to make it have an 8-aligned size */ /* UInt padding; */ } diff --git a/VEX/quote.txt b/VEX/quote.txt new file mode 100644 index 0000000000..9d68933c44 --- /dev/null +++ b/VEX/quote.txt @@ -0,0 +1 @@ +" \ No newline at end of file diff --git a/VEX/test_main.c b/VEX/test_main.c index 0680ae43c8..3ca12ce600 100644 --- a/VEX/test_main.c +++ b/VEX/test_main.c @@ -67,6 +67,7 @@ int main ( int argc, char** argv ) VexControl vcon; VexGuestExtents vge; VexArchInfo vai_x86, vai_amd64, vai_ppc32; + VexMiscInfo vmi; VexTranslateArgs vta; if (argc != 2) { @@ -135,6 +136,8 @@ int main ( int argc, char** argv ) vai_ppc32.hwcaps = 0; vai_ppc32.ppc_cache_line_szB = 128; + LibVEX_default_VexMiscInfo(&vmi); + /* ----- Set up args for LibVEX_Translate ----- */ #if 1 /* ppc32 -> ppc32 */ vta.arch_guest = VexArchPPC32; @@ -154,6 +157,7 @@ int main ( int argc, char** argv ) vta.arch_host = VexArchX86; vta.archinfo_host = vai_x86; #endif + vta.miscinfo_both = vmi; vta.guest_bytes = origbuf; vta.guest_bytes_addr = (Addr64)orig_addr; vta.callback_opaque = NULL;