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 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/Makefile b/Makefile
index dd7d827..10e9787 100644
--- a/Makefile
+++ b/Makefile
@@ -137,6 +137,18 @@
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 @@
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/auxprogs/genoffsets.c b/auxprogs/genoffsets.c
index 13ea551..4d0b767 100644
--- a/auxprogs/genoffsets.c
+++ b/auxprogs/genoffsets.c
@@ -143,6 +143,9 @@
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 @@
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 @@
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 @@
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/newline.txt b/newline.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/newline.txt
@@ -0,0 +1 @@
+
diff --git a/priv/guest-amd64/gdefs.h b/priv/guest-amd64/gdefs.h
index 36100be..01a8642 100644
--- a/priv/guest-amd64/gdefs.h
+++ b/priv/guest-amd64/gdefs.h
@@ -66,6 +66,7 @@
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/priv/guest-amd64/toIR.c b/priv/guest-amd64/toIR.c
index 74fc124..a6588f9 100644
--- a/priv/guest-amd64/toIR.c
+++ b/priv/guest-amd64/toIR.c
@@ -1931,14 +1931,24 @@
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 @@
/* 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 @@
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 @@
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 @@
//.. }
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 @@
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 @@
Bool (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
void* callback_opaque,
Long delta64,
- VexArchInfo* archinfo
+ VexArchInfo* archinfo,
+ VexMiscInfo* vmi
)
{
IRType ty;
@@ -12170,7 +12182,7 @@
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 @@
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 @@
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 @@
Addr64 guest_IP,
VexArch guest_arch,
VexArchInfo* archinfo,
+ VexMiscInfo* miscinfo,
Bool host_bigendian_IN )
{
DisResult dres;
@@ -14357,7 +14370,7 @@
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/priv/guest-generic/bb_to_IR.c b/priv/guest-generic/bb_to_IR.c
index c79f4b4..e262a55 100644
--- a/priv/guest-generic/bb_to_IR.c
+++ b/priv/guest-generic/bb_to_IR.c
@@ -101,6 +101,7 @@
/*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 @@
guest_IP_curr_instr,
arch_guest,
archinfo_guest,
+ miscinfo_both,
host_bigendian );
/* stay sane ... */
@@ -342,6 +344,7 @@
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->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 @@
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/priv/guest-generic/bb_to_IR.h b/priv/guest-generic/bb_to_IR.h
index 935b920..e1fab3b 100644
--- a/priv/guest-generic/bb_to_IR.h
+++ b/priv/guest-generic/bb_to_IR.h
@@ -143,6 +143,9 @@
/*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 @@
/*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/priv/guest-ppc/gdefs.h b/priv/guest-ppc/gdefs.h
index 3f9295d..1c9aaa9 100644
--- a/priv/guest-ppc/gdefs.h
+++ b/priv/guest-ppc/gdefs.h
@@ -67,6 +67,7 @@
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/priv/guest-ppc/ghelpers.c b/priv/guest-ppc/ghelpers.c
index 300f13c..8eb35b2 100644
--- a/priv/guest-ppc/ghelpers.c
+++ b/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 @@
/* 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 @@
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 @@
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 @@
/* 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 @@
/* 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 @@
/* 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 @@
/* 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/priv/guest-ppc/toIR.c b/priv/guest-ppc/toIR.c
index 9b9e5a7..0d23e73 100644
--- a/priv/guest-ppc/toIR.c
+++ b/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 @@
// 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 )
+// ppc64-linux it isn't (sigh) and ditto for ppc32-aix5 and
+// ppc64-aix5.
+static void* fnptr_to_fnentry( VexMiscInfo* vmi, 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
+ 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 @@
(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 @@
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 @@
}
-/* 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 @@
{
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 @@
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 @@
/*
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 @@
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 @@
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 @@
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 @@
/*
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 @@
// 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 @@
/*
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 @@
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 @@
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 @@
/*
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 @@
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 @@
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 @@
Bool (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
void* callback_opaque,
Long delta64,
- VexArchInfo* archinfo
+ VexArchInfo* archinfo,
+ VexMiscInfo* miscinfo
)
{
UChar opc1;
@@ -8797,14 +8842,12 @@
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 @@
/* 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 @@
/* 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 @@
/* 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 @@
/* 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 @@
/* 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 @@
/* 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 @@
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 @@
Addr64 guest_IP,
VexArch guest_arch,
VexArchInfo* archinfo,
+ VexMiscInfo* miscinfo,
Bool host_bigendian_IN )
{
IRType ty;
@@ -9504,7 +9550,7 @@
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/priv/guest-x86/gdefs.h b/priv/guest-x86/gdefs.h
index 4ceaaa8..1a53a48 100644
--- a/priv/guest-x86/gdefs.h
+++ b/priv/guest-x86/gdefs.h
@@ -66,6 +66,7 @@
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/priv/guest-x86/toIR.c b/priv/guest-x86/toIR.c
index 8edb730..08ae111 100644
--- a/priv/guest-x86/toIR.c
+++ b/priv/guest-x86/toIR.c
@@ -12902,6 +12902,7 @@
Addr64 guest_IP,
VexArch guest_arch,
VexArchInfo* archinfo,
+ VexMiscInfo* miscinfo,
Bool host_bigendian_IN )
{
DisResult dres;
diff --git a/priv/host-amd64/hdefs.h b/priv/host-amd64/hdefs.h
index a8475e9..9fd5ee6 100644
--- a/priv/host-amd64/hdefs.h
+++ b/priv/host-amd64/hdefs.h
@@ -725,7 +725,9 @@
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/priv/host-amd64/isel.c b/priv/host-amd64/isel.c
index 5911779..07b159d 100644
--- a/priv/host-amd64/isel.c
+++ b/priv/host-amd64/isel.c
@@ -3801,8 +3801,9 @@
/* 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/priv/host-ppc/hdefs.c b/priv/host-ppc/hdefs.c
index 9c866dd..2085157 100644
--- a/priv/host-ppc/hdefs.c
+++ b/priv/host-ppc/hdefs.c
@@ -1123,67 +1123,13 @@
/* 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 @@
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/priv/host-ppc/hdefs.h b/priv/host-ppc/hdefs.h
index 54d3f74..ca71731 100644
--- a/priv/host-ppc/hdefs.h
+++ b/priv/host-ppc/hdefs.h
@@ -838,7 +838,9 @@
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/priv/host-ppc/isel.c b/priv/host-ppc/isel.c
index 89f88d3..4dda13d 100644
--- a/priv/host-ppc/isel.c
+++ b/priv/host-ppc/isel.c
@@ -253,6 +253,9 @@
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 @@
Bool mode64;
IRExpr* previous_rm;
+
+ VexMiscInfo* vmi;
}
ISelEnv;
@@ -532,7 +537,7 @@
/* 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
/* --------- 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 @@
/* 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 @@
/* 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/priv/host-x86/hdefs.h b/priv/host-x86/hdefs.h
index c4ea61d..2958190 100644
--- a/priv/host-x86/hdefs.h
+++ b/priv/host-x86/hdefs.h
@@ -665,7 +665,9 @@
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/priv/host-x86/isel.c b/priv/host-x86/isel.c
index 22e3ef6..d22b656 100644
--- a/priv/host-x86/isel.c
+++ b/priv/host-x86/isel.c
@@ -3604,8 +3604,9 @@
/* 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/priv/main/vex_main.c b/priv/main/vex_main.c
index 0475f68..a590774 100644
--- a/priv/main/vex_main.c
+++ b/priv/main/vex_main.c
@@ -193,7 +193,8 @@
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 @@
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 @@
" 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 @@
}
-
/* Write default settings info *vai. */
void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai )
{
@@ -703,6 +705,17 @@
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/pub/libvex.h b/pub/libvex.h
index 26fe0b0..f1cbd97 100644
--- a/pub/libvex.h
+++ b/pub/libvex.h
@@ -110,8 +110,8 @@
/* 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 @@
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 @@
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/pub/libvex_basictypes.h b/pub/libvex_basictypes.h
index 370f5f9..d22bc63 100644
--- a/pub/libvex_basictypes.h
+++ b/pub/libvex_basictypes.h
@@ -135,6 +135,7 @@
#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 @@
# 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/pub/libvex_guest_ppc32.h b/pub/libvex_guest_ppc32.h
index 4203e3b..7c8bb9b 100644
--- a/pub/libvex_guest_ppc32.h
+++ b/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 @@
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/pub/libvex_guest_ppc64.h b/pub/libvex_guest_ppc64.h
index fec4e56..12b7134 100644
--- a/pub/libvex_guest_ppc64.h
+++ b/pub/libvex_guest_ppc64.h
@@ -266,6 +266,14 @@
/* 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/quote.txt b/quote.txt
new file mode 100644
index 0000000..9d68933
--- /dev/null
+++ b/quote.txt
@@ -0,0 +1 @@
+"
\ No newline at end of file
diff --git a/test_main.c b/test_main.c
index 0680ae4..3ca12ce 100644
--- a/test_main.c
+++ b/test_main.c
@@ -67,6 +67,7 @@
VexControl vcon;
VexGuestExtents vge;
VexArchInfo vai_x86, vai_amd64, vai_ppc32;
+ VexMiscInfo vmi;
VexTranslateArgs vta;
if (argc != 2) {
@@ -135,6 +136,8 @@
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 @@
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;