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
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
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));
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));
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));
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));
Addr64 guest_IP,
VexArch guest_arch,
VexArchInfo* archinfo,
+ VexMiscInfo* miscinfo,
Bool host_bigendian );
/* Used by the optimiser to specialise calls to helpers. */
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
+ ));
}
/* 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;
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;
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;
//.. }
static
-void dis_ret ( ULong d64 )
+void dis_ret ( VexMiscInfo* vmi, ULong d64 )
{
IRTemp t1 = newTemp(Ity_I64);
IRTemp t2 = newTemp(Ity_I64);
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);
}
Bool (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
void* callback_opaque,
Long delta64,
- VexArchInfo* archinfo
+ VexArchInfo* archinfo,
+ VexMiscInfo* vmi
)
{
IRType ty;
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;
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;
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 -- */
Addr64 guest_IP,
VexArch guest_arch,
VexArchInfo* archinfo,
+ VexMiscInfo* miscinfo,
Bool host_bigendian_IN )
{
DisResult dres;
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
/*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*),
guest_IP_curr_instr,
arch_guest,
archinfo_guest,
+ miscinfo_both,
host_bigendian );
/* stay sane ... */
UInt len2check, adler32;
IRTemp tistart_tmp, tilen_tmp;
+ HWord p_adler_helper;
vassert(vge->n_used == 1);
len2check = vge->len[0];
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(
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 )
/*IN*/ VexArch guest_arch,
/*IN*/ VexArchInfo* archinfo,
+ /* Misc info about guest and host */
+ /*IN*/ VexMiscInfo* miscinfo,
+
/* Is the host bigendian? */
/*IN*/ Bool host_bigendian
/*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*),
Addr64 guest_IP,
VexArch guest_arch,
VexArchInfo* archinfo,
+ VexMiscInfo* miscinfo,
Bool host_bigendian );
/* Used by the optimiser to specialise calls to helpers. */
/* 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) {
/* 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;
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;
}
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;
}
/* Describe any sections to be regarded by Memcheck as
'always-defined'. */
- .n_alwaysDefd = 8,
+ .n_alwaysDefd = 12,
.alwaysDefd
= { /* 0 */ ALWAYSDEFD32(guest_CIA),
/* 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)
}
};
/* Describe any sections to be regarded by Memcheck as
'always-defined'. */
- .n_alwaysDefd = 11,
+ .n_alwaysDefd = 12,
.alwaysDefd
= { /* 0 */ ALWAYSDEFD64(guest_CIA),
/* 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)
}
};
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.
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
// 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;
+ }
}
(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)
/*------------------------------------------------------------*/
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;
}
-/* 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
+ ));
+ }
}
{
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 );
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 ) );
/*
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);
Integer Branch Instructions
*/
static Bool dis_branch ( UInt theInstr,
+ VexMiscInfo* vmi,
/*OUT*/DisResult* dres,
Bool (*resteerOkFn)(void*,Addr64),
void* callback_opaque )
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 )) {
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
/*
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;
// 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;
/*
Processor Control Instructions
*/
-static Bool dis_proc_ctl ( UInt theInstr )
+static Bool dis_proc_ctl ( VexMiscInfo* vmi, UInt theInstr )
{
UChar opc1 = ifieldOPC(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;
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) );
/*
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);
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);
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);
Bool (*resteerOkFn) ( /*opaque*/void*, Addr64 ),
void* callback_opaque,
Long delta64,
- VexArchInfo* archinfo
+ VexArchInfo* archinfo,
+ VexMiscInfo* miscinfo
)
{
UChar opc1;
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
/* 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 */
/* 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 */
/* 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:
/* 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;
/* 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 */
/* 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 */
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 */
Addr64 guest_IP,
VexArch guest_arch,
VexArchInfo* archinfo,
+ VexMiscInfo* miscinfo,
Bool host_bigendian_IN )
{
IRType ty;
guest_CIA_bbstart = mkSzAddr(ty, guest_IP - delta);
dres = disInstr_PPC_WRK ( put_IP, resteerOkFn, callback_opaque,
- delta, archinfo );
+ delta, archinfo, miscinfo );
return dres;
}
Addr64 guest_IP,
VexArch guest_arch,
VexArchInfo* archinfo,
+ VexMiscInfo* miscinfo,
Bool host_bigendian );
/* Used by the optimiser to specialise calls to helpers. */
Addr64 guest_IP,
VexArch guest_arch,
VexArchInfo* archinfo,
+ VexMiscInfo* miscinfo,
Bool host_bigendian_IN )
{
DisResult dres;
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 */
/* 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;
/* 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 ) {
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;
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 */
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
Bool mode64;
IRExpr* previous_rm;
+
+ VexMiscInfo* vmi;
}
ISelEnv;
/* 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 )
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:
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(
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
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));
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;
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: {
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;
}
/* --------- 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: {
/* 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;
/* and finally ... */
env->hwcaps = hwcaps_host;
env->previous_rm = NULL;
+ env->vmi = vmi;
/* For each IR temporary, allocate a suitably-kinded virtual
register. */
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 */
/* 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;
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 );
host_is_bigendian,
vta->arch_guest,
&vta->archinfo_guest,
+ &vta->miscinfo_both,
guest_word_type,
vta->do_self_check,
vta->preamble_function,
" 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();
}
-
/* Write default settings info *vai. */
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
/* 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 {
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). ---*/
/*-------------------------------------------------------*/
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
#undef VEX_HOST_WORDSIZE
+/* The following 4 work OK for Linux. */
#if defined(__x86_64__)
# define VEX_HOST_WORDSIZE 8
#elif defined(__i386__)
# 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
/*--- 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 */
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;
/* 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; */
}
--- /dev/null
+"
\ No newline at end of file
VexControl vcon;
VexGuestExtents vge;
VexArchInfo vai_x86, vai_amd64, vai_ppc32;
+ VexMiscInfo vmi;
VexTranslateArgs vta;
if (argc != 2) {
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;
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;