#include "../pub/libvex_basictypes.h"
#include "../pub/libvex_guest_x86.h"
#include "../pub/libvex_guest_amd64.h"
+#include "../pub/libvex_guest_ppc32.h"
Int main ( void )
{
- printf("#define OFFSET_x86_EAX %d\n",
+ // x86
+ printf("#define OFFSET_x86_EAX %3d\n",
offsetof(VexGuestX86State,guest_EAX));
- printf("#define OFFSET_x86_EBX %d\n",
+ printf("#define OFFSET_x86_EBX %3d\n",
offsetof(VexGuestX86State,guest_EBX));
- printf("#define OFFSET_x86_ECX %d\n",
+ printf("#define OFFSET_x86_ECX %3d\n",
offsetof(VexGuestX86State,guest_ECX));
- printf("#define OFFSET_x86_EDX %d\n",
+ printf("#define OFFSET_x86_EDX %3d\n",
offsetof(VexGuestX86State,guest_EDX));
- printf("#define OFFSET_x86_ESI %d\n",
+ printf("#define OFFSET_x86_ESI %3d\n",
offsetof(VexGuestX86State,guest_ESI));
- printf("#define OFFSET_x86_EDI %d\n",
+ printf("#define OFFSET_x86_EDI %3d\n",
offsetof(VexGuestX86State,guest_EDI));
- printf("#define OFFSET_x86_EBP %d\n",
+ printf("#define OFFSET_x86_EBP %3d\n",
offsetof(VexGuestX86State,guest_EBP));
- printf("#define OFFSET_x86_ESP %d\n",
+ printf("#define OFFSET_x86_ESP %3d\n",
offsetof(VexGuestX86State,guest_ESP));
- printf("#define OFFSET_x86_EIP %d\n",
+ printf("#define OFFSET_x86_EIP %3d\n",
offsetof(VexGuestX86State,guest_EIP));
+ printf("\n");
-
- printf("#define OFFSET_amd64_RAX %d\n",
+ // amd64
+ printf("#define OFFSET_amd64_RAX %3d\n",
offsetof(VexGuestAMD64State,guest_RAX));
- printf("#define OFFSET_amd64_RDI %d\n",
+ printf("#define OFFSET_amd64_RDI %3d\n",
offsetof(VexGuestAMD64State,guest_RDI));
- printf("#define OFFSET_amd64_RSI %d\n",
+ printf("#define OFFSET_amd64_RSI %3d\n",
offsetof(VexGuestAMD64State,guest_RSI));
- printf("#define OFFSET_amd64_RDX %d\n",
+ printf("#define OFFSET_amd64_RDX %3d\n",
offsetof(VexGuestAMD64State,guest_RDX));
- printf("#define OFFSET_amd64_R8 %d\n",
+ printf("#define OFFSET_amd64_R8 %3d\n",
offsetof(VexGuestAMD64State,guest_R8));
- printf("#define OFFSET_amd64_R9 %d\n",
+ printf("#define OFFSET_amd64_R9 %3d\n",
offsetof(VexGuestAMD64State,guest_R9));
- printf("#define OFFSET_amd64_R10 %d\n",
+ printf("#define OFFSET_amd64_R10 %3d\n",
offsetof(VexGuestAMD64State,guest_R10));
- printf("#define OFFSET_amd64_RIP %d\n",
+ printf("#define OFFSET_amd64_RIP %3d\n",
offsetof(VexGuestAMD64State,guest_RIP));
+ printf("\n");
+
+ // ppc32
+ printf("#define OFFSET_ppc32_GPR0 %3d\n",
+ offsetof(VexGuestPPC32State,guest_GPR0));
+
+ printf("#define OFFSET_ppc32_GPR3 %3d\n",
+ offsetof(VexGuestPPC32State,guest_GPR3));
+
+ printf("#define OFFSET_ppc32_GPR4 %3d\n",
+ offsetof(VexGuestPPC32State,guest_GPR4));
+
+ printf("#define OFFSET_ppc32_GPR5 %3d\n",
+ offsetof(VexGuestPPC32State,guest_GPR5));
+
+ printf("#define OFFSET_ppc32_GPR6 %3d\n",
+ offsetof(VexGuestPPC32State,guest_GPR6));
+
+ printf("#define OFFSET_ppc32_GPR7 %3d\n",
+ offsetof(VexGuestPPC32State,guest_GPR7));
+
+ printf("#define OFFSET_ppc32_GPR8 %3d\n",
+ offsetof(VexGuestPPC32State,guest_GPR8));
+
+ printf("#define OFFSET_ppc32_CIA %3d\n",
+ offsetof(VexGuestPPC32State,guest_CIA));
+
+ printf("#define OFFSET_ppc32_CC_OP %3d\n",
+ offsetof(VexGuestPPC32State,guest_CC_OP));
+
+ printf("#define OFFSET_ppc32_CC_DEP1 %3d\n",
+ offsetof(VexGuestPPC32State,guest_CC_DEP1));
+
+ printf("\n");
+
return 0;
}
/*---------------------------------------------------------*/
-/*--- ppc32 to IR conversion ---*/
+/*--- ppc32 to IR conversion ---*/
/*---------------------------------------------------------*/
extern
/* --- CLEAN HELPERS --- */
// Calculate CR7 flags
-extern UInt ppc32g_calculate_cr7_all ( UInt op, UInt val, UInt xer_so );
+extern UInt ppc32g_calculate_cr7 ( UInt op, UInt val, UInt xer_so );
// Calculate XER flags
extern UInt ppc32g_calculate_xer_ov ( UInt op, UInt res, UInt argL, UInt argR );
The three words are:
- CC_OP, which describes whether to return the DEP1 value as the flags,
- or to calculate the flags based on that value.
+ CC_OP, which describes whether to:
+ 0: Calculate the flags based on DEP1, DEP2.
+ 1: Return DEP1 as the flags.
CC_DEP1: This holds either an immediate value to be returned as the flags,
or a value with which to calculate the flags.
A summary of the field usages is:
- Operation DEP1 DEP2
+ Operation DEP1 DEP2
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- 0 flags value unused
+ 0 calculation result xer_so
- 1 result xer_so
+ 1 flags value unused
*/
thunk parameters.
Returns values in high field (correct wrt actual CR)
*/
-UInt ppc32g_calculate_cr7_all ( UInt op, UInt val, UInt xer_so )
+UInt ppc32g_calculate_cr7 ( UInt op, UInt val, UInt xer_so )
{
if (op) { // val contains cr7 flags to be returned
return (val & 0xF0000000);
/* OV true if result can't be represented in 32 bits
i.e sHi != sign extension of sLo */
Long l_res = (Long)((Int)argL) * (Long)((Int)argR);
- Int sHi = (Int)toUInt(l_res >> 32);
+ Int sHi = (Int)(l_res >> 32);
Int sLo = (Int)l_res;
return (sHi != (sLo >> /*s*/ 31)) ? 1:0;
}
/* VISIBLE TO LIBVEX CLIENT */
#if 0
-void LibVEX_GuestPPC32_put_flags ( UInt flags_native,
+void LibVEX_GuestPPC32_put_cr7 ( UInt flags_native,
/*OUT*/VexGuestPPC32State* vex_state )
{
vassert(0); // FIXME
#endif
/* VISIBLE TO LIBVEX CLIENT */
-UInt LibVEX_GuestPPC32_get_flags ( /*IN*/VexGuestPPC32State* vex_state )
+UInt LibVEX_GuestPPC32_get_cr7 ( /*IN*/VexGuestPPC32State* vex_state )
{
- UInt flags = ppc32g_calculate_cr7_all(
+ UInt flags = ppc32g_calculate_cr7(
vex_state->guest_CC_OP,
vex_state->guest_CC_DEP1,
vex_state->guest_CC_DEP2
.alwaysDefd
= { /* 0 */ ALWAYSDEFD(guest_CC_OP)
+
+ // FIXME
}
};
change during translation of a bb.
*/
+/* We need to know this to do sub-register accesses correctly. */
+/* CONST */
+static Bool host_is_bigendian;
+
/* Pointer to the guest code area. */
/* CONST */
static UChar* guest_code;
vge->len[0] = 0;
/* Set up globals. */
+ host_is_bigendian = host_bigendian;
guest_code = ppc32code;
guest_pc_bbstart = (Addr32)guest_pc_start;
irbb = emptyIRBB();
vassert((guest_pc_start >> 32) == 0);
- /* Delta keeps track of how far along the x86code array we
+ /* Delta keeps track of how far along the ppc32code array we
have so far gone. */
delta = 0;
n_instrs = 0;
vassert(irbb->next == NULL);
/* figure out a new delta to continue at. */
vassert(chase_into_ok(guest_next));
- delta = toUInt(guest_next - guest_pc_start);
+ delta = (UInt)(guest_next - guest_pc_start);
n_resteers++;
d_resteers++;
if (0 && (n_resteers & 0xFF) == 0)
return IRExpr_Const(IRConst_U8(i));
}
+#if 0
static IRExpr* mkU16 ( UShort i )
{
return IRExpr_Const(IRConst_U16(i));
}
+#endif
static IRExpr* mkU32 ( UInt i )
{
/* -------------- Evaluating the flags-thunk. -------------- */
/* Calculate CR7 (IBM CR0) conditional flags */
-static IRExpr* mk_ppc32g_calculate_cr7_all ( void )
+static IRExpr* mk_ppc32g_calculate_cr7 ( void )
{
IRExpr** args =
mkIRExprVec_3( IRExpr_Get(OFFB_CC_OP, Ity_I32),
= mkIRExprCCall(
Ity_I32,
0/*regparm*/,
- "ppc32g_calculate_cr7_all", &ppc32g_calculate_cr7_all,
+ "ppc32g_calculate_cr7", &ppc32g_calculate_cr7,
args
);
flag-setting operation. Hence the various setFlags_* functions.
*/
-/* Set the flags thunk OP=0, DEP1, DEP2 fields. */
+/* Set the flags thunk OP=0, DEP1, DEP2 fields. PPC32 p60 */
static void setFlags_CR7 ( IRExpr* result )
{
IRExpr* xer_so;
case PPC32_SPR_CR:
if (mask & 0xF0000000) {
// Call helper function to calculate latest CR7 from thunk:
- assign( val, binop(Iop_Or32, mk_ppc32g_calculate_cr7_all(),
+ // ... and OR it with CR0to6
+ assign( val, binop(Iop_Or32, mk_ppc32g_calculate_cr7(),
IRExpr_Get(OFFB_CR0to6, Ity_I32)) );
} else {
assign( val, IRExpr_Get(OFFB_CR0to6, Ity_I32) );
fld = getReg_masked( reg, (0xF << (field_idx*4)) );
if (field_idx != 0) {
- fld = binop(Iop_Shr32, fld, mkU8(toUChar(field_idx * 4)));
+ fld = binop(Iop_Shr32, fld, mkU8(field_idx * 4));
}
return fld;
}
val = getReg_masked( reg, 1<<bit_idx );
if (bit_idx != 0) {
- val = binop(Iop_Shr32, val, mkU8(toUChar(bit_idx)));
+ val = binop(Iop_Shr32, val, mkU8(bit_idx));
}
return val;
}
vassert( reg < PPC32_SPR_MAX );
if (field_idx != 0) {
- src = binop(Iop_Shl32, src, mkU8(toUChar(field_idx * 4)));
+ src = binop(Iop_Shl32, src, mkU8(field_idx * 4));
}
putReg_masked( reg, src, (0xF << (field_idx*4)) );
}
vassert( reg < PPC32_SPR_MAX );
if (bit_idx != 0) {
- src = binop(Iop_Shl32, src, mkU8(toUChar(bit_idx)));
+ src = binop(Iop_Shl32, src, mkU8(bit_idx));
}
putReg_masked( reg, src, (1<<bit_idx) );
}
switch (opc1) {
case 0x0B: // cmpi (Compare Immediate, PPC32 p368)
EXTS_SIMM = extend_s_16to32(SIMM_16);
- DIP("cmpi crf%d,%d,r%d,0x%x\n", crfD, flag_L, Ra_addr, EXTS_SIMM);
+ DIP("cmpi crf%d,%u,r%d,0x%x\n", crfD, flag_L, Ra_addr, EXTS_SIMM);
irx_cmp_lt = binop(Iop_CmpLT32S, mkexpr(Ra), mkU32(EXTS_SIMM));
irx_cmp_eq = binop(Iop_CmpEQ32, mkexpr(Ra), mkU32(EXTS_SIMM));
break;
case 0x0A: // cmpli (Compare Logical Immediate, PPC32 p370)
- DIP("cmpli crf%d,%d,r%d,0x%x\n", crfD, flag_L, Ra_addr, UIMM_16);
+ DIP("cmpli crf%d,%u,r%d,0x%x\n", crfD, flag_L, Ra_addr, UIMM_16);
irx_cmp_lt = binop(Iop_CmpLT32U, mkexpr(Ra), mkU32(UIMM_16));
irx_cmp_eq = binop(Iop_CmpEQ32, mkexpr(Ra), mkU32(UIMM_16));
break;
switch (opc2) {
case 0x000: // cmp (Compare, PPC32 p367)
- DIP("cmp crf%d,%d,r%d,r%d\n", crfD, flag_L,
+ DIP("cmp crf%d,%u,r%d,r%d\n", crfD, flag_L,
Ra_addr, Rb_addr);
irx_cmp_lt = binop(Iop_CmpLT32S, mkexpr(Ra), mkexpr(Rb));
break;
case 0x020: // cmpl (Compare Logical, PPC32 p369)
- DIP("cmpl crf%d,%d,r%d,r%d\n", crfD, flag_L,
+ DIP("cmpl crf%d,%u,r%d,r%d\n", crfD, flag_L,
Ra_addr, Rb_addr);
irx_cmp_lt = binop(Iop_CmpLT32U, mkexpr(Ra), mkexpr(Rb));
break;
switch (opc1) {
case 0x14: // rlwimi (Rotate Left Word Immediate then Mask Insert, PPC32 p500)
- DIP("rlwimi%s r%d,r%d,%d,%d,%d\n", flag_Rc ? "." : "",
+ DIP("rlwimi%s r%d,r%d,%d,%u,%u\n", flag_Rc ? "." : "",
Ra_addr, Rs_addr, sh_imm, MaskBegin, MaskEnd);
// Ra = (ROTL(Rs, Imm) & mask) | (Ra & ~mask);
assign( Ra, binop(Iop_Or32,
break;
case 0x15: // rlwinm (Rotate Left Word Immediate then AND with Mask, PPC32 p501)
- DIP("rlwinm%s r%d,r%d,%d,%d,%d\n", flag_Rc ? "." : "",
+ DIP("rlwinm%s r%d,r%d,%d,%u,%u\n", flag_Rc ? "." : "",
Ra_addr, Rs_addr, sh_imm, MaskBegin, MaskEnd);
// Ra = ROTL(Rs, Imm) & mask
assign( Ra, binop(Iop_And32, ROTL32(mkexpr(Rs),
break;
case 0x17: // rlwnm (Rotate Left Word then AND with Mask, PPC32 p503
- DIP("rlwnm%s r%d,r%d,r%d,%d,%d\n", flag_Rc ? "." : "",
+ DIP("rlwnm%s r%d,r%d,r%d,%u,%u\n", flag_Rc ? "." : "",
Ra_addr, Rs_addr, Rb_addr, MaskBegin, MaskEnd);
// Ra = ROTL(Rs, Rb[0-4]) & mask
assign( rot_amt,
return False;
}
DIP("stbu r%d,%d(r%d)\n", Rs_addr, (Int)d_imm, Ra_addr);
- storeBE( mkexpr(EA_imm), mkexpr(Rs_8) );
putIReg( Ra_addr, mkexpr(EA_imm) );
+ storeBE( mkexpr(EA_imm), mkexpr(Rs_8) );
break;
case 0x2C: // sth (Store HW, PPC32 p522)
return False;
}
DIP("sthu r%d,%d(r%d)\n", Rs_addr, (Int)d_imm, Ra_addr);
- assign( Rs_16, binop(Iop_And16, mkexpr(Rs), mkU16(0xFFFF)) );
- storeBE( mkexpr(EA_imm), mkexpr(Rs_16) );
putIReg( Ra_addr, mkexpr(EA_imm) );
+ storeBE( mkexpr(EA_imm), mkexpr(Rs_16) );
break;
case 0x24: // stw (Store W, PPC32 p530)
return False;
}
DIP("stwu r%d,%d(r%d)\n", Rs_addr, (Int)d_imm, Ra_addr);
- storeBE( mkexpr(EA_imm), mkexpr(Rs) );
putIReg( Ra_addr, mkexpr(EA_imm) );
+ storeBE( mkexpr(EA_imm), mkexpr(Rs) );
break;
/* X Form */
return False;
}
DIP("stbux r%d,r%d,r%d\n", Rs_addr, Ra_addr, Rb_addr);
- storeBE( mkexpr(EA_reg), mkexpr(Rs_8) );
putIReg( Ra_addr, mkexpr(EA_reg) );
+ storeBE( mkexpr(EA_reg), mkexpr(Rs_8) );
break;
case 0x0D7: // stbx (Store B Indexed, PPC32 p512)
return False;
}
DIP("sthux r%d,r%d,r%d\n", Rs_addr, Ra_addr, Rb_addr);
- storeBE( mkexpr(EA_reg), mkexpr(Rs_16) );
putIReg( Ra_addr, mkexpr(EA_reg) );
+ storeBE( mkexpr(EA_reg), mkexpr(Rs_16) );
break;
case 0x197: // sthx (Store HW Indexed, PPC32 p526)
return False;
}
DIP("stwux r%d,r%d,r%d\n", Rs_addr, Ra_addr, Rb_addr);
- storeBE( mkexpr(EA_reg), mkexpr(Rs) );
putIReg( Ra_addr, mkexpr(EA_reg) );
+ storeBE( mkexpr(EA_reg), mkexpr(Rs) );
break;
case 0x097: // stwx (Store W Indexed, PPC32 p536)
return False;
}
}
- DIP("lswi r%d,r%d,%d\n", Rd_addr, Ra_addr, NumBytes);
+ DIP("lswi r%d,r%d,%u\n", Rd_addr, Ra_addr, NumBytes);
assign( EA, mkexpr(b_EA) );
return False;
case 0x2D5: // stswi (Store String Word Immediate, PPC32 p528)
- DIP("stswi r%d,r%d,%d\n", Rs_addr, Ra_addr, NumBytes);
+ DIP("stswi r%d,r%d,%u\n", Rs_addr, Ra_addr, NumBytes);
if (Ra_addr == 0) {
assign( EA, mkU32(0) );
} else {
static IRExpr* branch_ctr_ok( UInt BO )
{
IRTemp ok = newTemp(Ity_I1);
- IRTemp ctr_0 = newTemp(Ity_I1);
-
+
if ((BO >> 2) & 1) {
assign( ok, mkU1(1) );
} else {
- assign( ctr_0, unop(Iop_32to1, getReg_bit( PPC32_SPR_CTR, 0 )) );
-
if ((BO >> 1) & 1) {
- assign( ok, unop(Iop_Not1, mkexpr(ctr_0)) );
+ assign( ok, binop(Iop_CmpEQ32, getReg( PPC32_SPR_CTR ), mkU32(0)) );
} else {
- assign( ok, mkexpr(ctr_0) );
+ assign( ok, binop(Iop_CmpNE32, getReg( PPC32_SPR_CTR ), mkU32(0)) );
}
}
return mkexpr(ok);
if (opc2 == 0) { // mcrf (Move Cond Reg Field, PPC32 p464)
if (((crbD_addr & 0x3) != 0) ||
- ((crbA_addr & 0x3) != 0) || (crbB != 0))
+ ((crbA_addr & 0x3) != 0) || (crbB_addr != 0))
return False;
DIP("mcrf crf%d,crf%d\n", crfD_addr, crfS_addr);
assign( tmp, getReg_field( PPC32_SPR_CR, (7-crfS_addr) ) );
DIP("mtcrf 0x%x,r%d\n", CRM, Rs_addr);
for (i=0; i<8; i++) {
if (CRM & (1<<i)) {
- mask = mask | (0xF << (7-i)*4);
+ mask |= (0xF << (i)*4);
}
}
putReg_masked( PPC32_SPR_CR, mkexpr(Rs), mask );
UInt* code = (UInt*)(guest_code + delta);
/* Spot this:
+ 0x7C03D808 tw 0,3,27 => trap word if(0) => nothing
0x60000000 ori 0,0,0 => r0 = r0 | 0
0x5400E800 rlwinm 0,0,29,0,0 => r0 = rotl(r0,29)
0x54001800 rlwinm 0,0,3,0,0 => r0 = rotl(r0,3)
0x54009800 rlwinm 0,0,19,0,0 => r0 = rotl(r0,19)
0x60000000 ori 0,0,0 => r0 = r0 | 0
*/
- if (code[0] == 0x60000000 &&
+ if (code[0] == 0x7C03D808 &&
code[1] == 0x5400E800 &&
code[2] == 0x54001800 &&
code[3] == 0x54006800 &&
DIP("? = client_request ( ? )\n");
*size = 24;
-
+ delta += 24;
+
irbb->next = mkU32(guest_pc_bbstart+delta);
irbb->jumpkind = Ijk_ClientReq;
#endif
- if (theInstr == 0x7C0042A6) {
- // CAB: what's this?
- DIP("Invalid instruction! Would be 'mfspr 0,256', which doesn't exist!.\n");
- goto decode_failure;
-// DIP("Passing through for now...\n");
-// goto decode_success;
- }
-
// Note: all 'reserved' bits must be cleared, else invalid
switch (opc1) {
}
}
-/* constructor */
+/* construct condition code */
PPC32CondCode mk_PPCCondCode ( PPC32CondTest test, PPC32CondFlag flag )
{
PPC32CondCode cc;
i->Pin.Div.srcR = srcR;
return i;
}
-//.. X86Instr* X86Instr_Sh3232 ( X86ShiftOp op, UInt amt, HReg src, HReg dst ) {
-//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
-//.. i->tag = Xin_Sh3232;
-//.. i->Xin.Sh3232.op = op;
-//.. i->Xin.Sh3232.amt = amt;
-//.. i->Xin.Sh3232.src = src;
-//.. i->Xin.Sh3232.dst = dst;
-//.. vassert(op == Xsh_SHL || op == Xsh_SHR);
-//.. return i;
-//.. }
-//.. X86Instr* X86Instr_Push( X86RMI* src ) {
-//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
-//.. i->tag = Xin_Push;
-//.. i->Xin.Push.src = src;
-//.. return i;
-//.. }
PPC32Instr* PPC32Instr_Call ( PPC32CondCode cond, Addr32 target, Int regparms ) {
PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
i->tag = Pin_Call;
i->Pin.Set32.dst = dst;
return i;
}
-//.. X86Instr* X86Instr_Bsfr32 ( Bool isFwds, HReg src, HReg dst ) {
-//.. X86Instr* i = LibVEX_Alloc(sizeof(X86Instr));
-//.. i->tag = Xin_Bsfr32;
-//.. i->Xin.Bsfr32.isFwds = isFwds;
-//.. i->Xin.Bsfr32.src = src;
-//.. i->Xin.Bsfr32.dst = dst;
-//.. return i;
-//.. }
PPC32Instr* PPC32Instr_MFence ( void )
{
PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr));
vex_printf(",");
ppHRegPPC32(i->Pin.Div.srcR);
return;
-//.. case Xin_Sh3232:
-//.. vex_printf("%sdl ", showX86ShiftOp(i->Xin.Sh3232.op));
-//.. if (i->Xin.Sh3232.amt == 0)
-//.. vex_printf(" %%cl,");
-//.. else
-//.. vex_printf(" $%d,", i->Xin.Sh3232.amt);
-//.. ppHRegX86(i->Xin.Sh3232.src);
-//.. vex_printf(",");
-//.. ppHRegX86(i->Xin.Sh3232.dst);
-//.. return;
-//.. case Xin_Push:
-//.. vex_printf("pushl ");
-//.. ppX86RMI(i->Xin.Push.src);
-//.. return;
case Pin_Call:
vex_printf("call: ");
if (i->Pin.Call.cond.test != Pct_ALWAYS) {
}
return;
}
-//.. case Xin_Bsfr32:
-//.. vex_printf("bs%cl ", i->Xin.Bsfr32.isFwds ? 'f' : 'r');
-//.. ppHRegX86(i->Xin.Bsfr32.src);
-//.. vex_printf(",");
-//.. ppHRegX86(i->Xin.Bsfr32.dst);
-//.. return;
case Pin_MFence:
vex_printf("mfence (=sync)");
return;
addHRegUse(u, HRmRead, i->Pin.Div.srcL);
addHRegUse(u, HRmRead, i->Pin.Div.srcR);
return;
-//.. case Xin_Sh3232:
-//.. addHRegUse(u, HRmRead, i->Xin.Sh3232.src);
-//.. addHRegUse(u, HRmModify, i->Xin.Sh3232.dst);
-//.. if (i->Xin.Sh3232.amt == 0)
-//.. addHRegUse(u, HRmRead, hregX86_ECX());
-//.. return;
-//.. case Xin_Push:
-//.. addRegUsage_X86RMI(u, i->Xin.Push.src);
-//.. addHRegUse(u, HRmModify, hregX86_ESP());
-//.. return;
case Pin_Call:
/* This is a bit subtle. */
/* First off, claim it trashes all the caller-saved regs
return;
case Pin_CMov32:
addRegUsage_PPC32RI(u, i->Pin.CMov32.src);
- addHRegUse(u, HRmModify, i->Pin.CMov32.dst);
+ addHRegUse(u, HRmWrite, i->Pin.CMov32.dst);
return;
case Pin_Load:
addRegUsage_PPC32AMode(u, i->Pin.Load.src);
case Pin_Set32:
addHRegUse(u, HRmWrite, i->Pin.Set32.dst);
return;
-//.. case Xin_Bsfr32:
-//.. addHRegUse(u, HRmRead, i->Xin.Bsfr32.src);
-//.. addHRegUse(u, HRmWrite, i->Xin.Bsfr32.dst);
-//.. return;
case Pin_MFence:
return;
//.. case Xin_FpUnary:
mapReg(m, &i->Pin.Div.srcL);
mapReg(m, &i->Pin.Div.srcR);
return;
-//.. case Xin_Sh3232:
-//.. mapReg(m, &i->Xin.Sh3232.src);
-//.. mapReg(m, &i->Xin.Sh3232.dst);
-//.. return;
-//.. case Xin_Push:
-//.. mapRegs_X86RMI(m, i->Xin.Push.src);
-//.. return;
case Pin_Call:
return;
case Pin_Goto:
case Pin_Set32:
mapReg(m, &i->Pin.Set32.dst);
return;
-//.. case Xin_Bsfr32:
-//.. mapReg(m, &i->Xin.Bsfr32.src);
-//.. mapReg(m, &i->Xin.Bsfr32.dst);
-//.. return;
case Pin_MFence:
return;
//.. case Xin_FpUnary:
//.. return p;
//.. }
+/*
+ mkForm[...] refer to PPC32 instruction forms as per PPC32 p576
+*/
+
static UChar* mkFormD ( UChar* p, UInt opc1, UInt r1, UInt r2, UInt imm )
{
UInt theInstr;
return emit32(p, theInstr);
}
-static UChar* doAMode_IR ( UChar* p, UInt opc1, HReg hrSD, PPC32AMode* am )
+static UChar* doAMode_IR ( UChar* p, UInt opc1, UInt rSD, PPC32AMode* am )
{
- UInt rSD, rA, idx;
+ UInt rA, idx;
vassert(am->tag == Pam_IR);
vassert(am->Pam.IR.index < 0x10000);
- rSD = iregNo(hrSD);
rA = iregNo(am->Pam.IR.base);
idx = am->Pam.IR.index;
static UChar* doAMode_RR ( UChar* p, UInt opc1, UInt opc2,
- HReg hrSD, PPC32AMode* am )
+ UInt rSD, PPC32AMode* am )
{
- UInt rSD, rA, rB;
-// vassert(hregClass(hrSD) == HRcInt32); // CAB: etc. worth doing this?
+ UInt rA, rB;
vassert(am->tag == Pam_RR);
- rSD = iregNo(hrSD);
rA = iregNo(am->Pam.RR.base);
rB = iregNo(am->Pam.RR.index);
Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i )
{
//.. UInt irno, opc, opc_rr, subopc_imm, opc_imma, opc_cl, opc_imm, subopc;
-//..
-//.. UInt xtra;
+
UChar* p = &buf[0];
UChar* ptmp = p;
vassert(nbuf >= 32);
-//..
-//.. /* Wrap an integer as a int register, for use assembling
-//.. GrpN insns, in which the greg field is used as a sub-opcode
-//.. and does not really contain a register. */
-//.. # define fake(_n) mkHReg((_n), HRcInt32, False)
// vex_printf("asm ");ppPPC32Instr(i); vex_printf("\n");
} else {
p = mkFormX(p, opc1, r_srcL, r_dst, r_srcR, opc2, 0);
}
- } else { // Pri_Imm:
+ } else { // tag == Pri_Imm:
imm_srcR = i->Pin.Alu32.srcR->Pri.Imm.imm32;
switch (i->Pin.Alu32.op) {
case Palu_ADD: opc1 = 14; break;
goto done;
}
-//.. case Xin_Sh3232:
-//.. vassert(i->Xin.Sh3232.op == Xsh_SHL || i->Xin.Sh3232.op == Xsh_SHR);
-//.. if (i->Xin.Sh3232.amt == 0) {
-//.. /* shldl/shrdl by %cl */
-//.. *p++ = 0x0F;
-//.. if (i->Xin.Sh3232.op == Xsh_SHL) {
-//.. *p++ = 0xA5;
-//.. } else {
-//.. *p++ = 0xAD;
-//.. }
-//.. p = doAMode_R(p, i->Xin.Sh3232.src, i->Xin.Sh3232.dst);
-//.. goto done;
-//.. }
-//.. break;
-
-//.. case Xin_Push:
-//.. switch (i->Xin.Push.src->tag) {
-//.. case Xrmi_Mem:
-//.. *p++ = 0xFF;
-//.. p = doAMode_M(p, fake(6), i->Xin.Push.src->Xrmi.Mem.am);
-//.. goto done;
-//.. case Xrmi_Imm:
-//.. *p++ = 0x68;
-//.. p = emit32(p, i->Xin.Push.src->Xrmi.Imm.imm32);
-//.. goto done;
-//.. case Xrmi_Reg:
-//.. *p++ = 0x50 + iregNo(i->Xin.Push.src->Xrmi.Reg.reg);
-//.. goto done;
-//.. default:
-//.. goto bad;
-//.. }
-
case Pin_Call: {
PPC32CondCode cond = i->Pin.Call.cond;
UInt r_dst = 12;
/* As per detailed comment for Pin_Call in
getRegUsage_PPC32Instr above, %r12 is used as an address temp */
- /* jump over the following two insns if condition does not hold */
+ /* jump over the following insns if condition does not hold */
if (cond.test != Pct_ALWAYS) {
- /* don't know how many bytes to jump over yet...
- make space for a jump instruction and fill in later. */
- ptmp = p; /* fill in this bit later */
- p += 4;
+ UInt delta = 4*4; /* jump 4 instrs */
+
+ /* bca !ct,cf,dst */
+ p = mkFormB(ptmp, invertCondTest(cond.test), cond.flag, (delta>>2), 1, 0);
}
/* load target to r_dst */
/* bctrl => branch to count register (and save to lr) */
p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 528, 1);
-
- /* Fix up the conditional jump, if there was one. */
- if (cond.test != Pct_ALWAYS) {
- Int delta = p - ptmp;
- vassert(delta >= 8 && delta <= 16);
-
- /* bca !ct,cf,jump */
- mkFormB(ptmp, invertCondTest(cond.test), cond.flag, (delta>>2), 1, 0);
- }
goto done;
}
if (magic_num !=0) {
vassert(magic_num < 0x10000);
/* addi r31,0,magic_num */
- p = mkFormD(p, 14, 31, 0, magic_num);
+ p = mkFormD(p, 14, 31, 0, magic_num); // p += 4
}
/* Get the destination address into %r_return */
if (i->Pin.Goto.dst->tag == Pri_Imm) {
imm_dst = i->Pin.Goto.dst->Pri.Imm.imm32;
- p = mkLoadImm(p, r_return, imm_dst);
+ p = mkLoadImm(p, r_return, imm_dst); // p += 4|8
} else {
vassert(i->Pin.Goto.dst->tag == Pri_Reg);
r_dst = iregNo(i->Pin.Goto.dst->Pri.Reg.reg);
- p = mkMoveReg(p, r_return, r_dst);
+ p = mkMoveReg(p, r_return, r_dst); // p += 4
}
/* blr */
- p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 16, 0);
+ p = mkFormXL(p, 19, Pct_ALWAYS, 0, 0, 16, 0); // p += 4
/* Fix up the conditional jump, if there was one. */
if (cond.test != Pct_ALWAYS) {
Int delta = p - ptmp;
- vassert(delta >= 8 && delta <= 16);
+ vassert(delta >= 12 && delta <= 20);
/* bc !ct,cf,delta */
mkFormB(ptmp, invertCondTest(cond.test), cond.flag, (delta>>2), 0, 0);
}
}
case Pin_Load: {
+ PPC32AMode* am_addr = i->Pin.Load.src;
+ UInt r_dst = iregNo(i->Pin.Load.dst);
Bool syned = i->Pin.Load.syned;
UInt opc1, opc2, sz = i->Pin.Load.sz;
switch (i->Pin.Load.src->tag) {
vassert(syned == False);
opc1 = (sz == 1) ? 34 : 32; // 1:4
}
- p = doAMode_IR(p, opc1, i->Pin.Load.dst, i->Pin.Load.src);
+ p = doAMode_IR(p, opc1, r_dst, am_addr);
goto done;
case Pam_RR:
- opc1 = 31;
if (sz == 2) { // the only signed load
opc2 = (syned) ? 343: 279;
} else {
vassert(syned == False);
opc2 = (sz == 1) ? 87 : 23; // 1:4
}
- p = doAMode_RR(p, opc1, opc2, i->Pin.Load.dst, i->Pin.Load.src);
+ p = doAMode_RR(p, 31, opc2, r_dst, am_addr);
goto done;
default:
goto bad;
goto done;
}
-//.. case Xin_Bsfr32:
-//.. *p++ = 0x0F;
-//.. if (i->Xin.Bsfr32.isFwds) {
-//.. *p++ = 0xBC;
-//.. } else {
-//.. *p++ = 0xBD;
-//.. }
-//.. p = doAMode_R(p, i->Xin.Bsfr32.dst, i->Xin.Bsfr32.src);
-//.. goto done;
-
case Pin_MFence: {
-// CAB: choose...
-#if 1 // sync (Synchronise, p616)
- p = mkFormX(p, 31, 0, 0, 0, 598, 0);
-#else // isync (instruction synchronise, p467)
- p = mkFormXL(p, 19, 0, 0, 0, 150, 0);
-#endif
+ p = mkFormX(p, 31, 0, 0, 0, 598, 0); // sync, PPC32 p616
+// CAB: Should this be isync?
+// p = mkFormXL(p, 19, 0, 0, 0, 150, 0); // isync, PPC32 p467
goto done;
}
case Pin_Store: {
+ PPC32AMode* am_addr = i->Pin.Store.dst;
+ UInt r_src = iregNo(i->Pin.Store.src);
UInt opc1, opc2, sz = i->Pin.Store.sz;
switch (i->Pin.Store.dst->tag) {
case Pam_IR:
opc1 = (sz == 1) ? 38 : ((sz == 2) ? 44 : 36); // 1:2:4
- p = doAMode_IR(p, opc1, i->Pin.Store.src, i->Pin.Store.dst);
+ p = doAMode_IR(p, opc1, r_src, am_addr);
goto done;
case Pam_RR:
- opc1 = 31;
opc2 = (sz == 1) ? 215 : ((sz == 2) ? 407 : 151); // 1:2:4
- p = doAMode_RR(p, opc1, opc2, i->Pin.Store.src, i->Pin.Store.dst);
+ p = doAMode_RR(p, 31, opc2, r_src, am_addr);
goto done;
default:
goto bad;
done:
vassert(p - &buf[0] <= 32);
return p - &buf[0];
-
-# undef fake
}
/*---------------------------------------------------------------*/
extern void ppHRegPPC32 ( HReg );
-extern HReg hregPPC32_GPR0 ( void ); // reserved
+extern HReg hregPPC32_GPR0 ( void ); // scratch reg / zero reg
extern HReg hregPPC32_GPR1 ( void ); // Stack Frame Pointer
extern HReg hregPPC32_GPR2 ( void ); // TOC pointer - not used
extern HReg hregPPC32_GPR3 ( void );
/* --------- */
typedef
enum {
- Pin_Alu32, /* 32-bit mov/arith/logical */
- Pin_Sub32, /* 32-bit mov/arith/logical */
- Pin_Sh32, /* 32-bit shift/rotate */
- Pin_Cmp32, /* 32-bit compare */
- Pin_Unary32, /* 32-bit not, neg, clz */
- Pin_MulL, /* widening multiply */
- Pin_Div, /* div */
-//.. Xin_Sh3232, /* shldl or shrdl */
-//.. Xin_Push, /* push (32-bit?) value on stack */
- Pin_Call, /* call to address in register */
- Pin_Goto, /* conditional/unconditional jmp to dst */
- Pin_CMov32, /* conditional move */
- Pin_Load, /* load a 8|16|32 bit value from mem */
- Pin_Store, /* store a 8|16|32 bit value to mem */
- Pin_Set32, /* convert condition code to 32-bit value */
-//.. Xin_Bsfr32, /* 32-bit bsf/bsr */
- Pin_MFence, /* mem fence (not just sse2, but sse0 and 1 too) */
+ Pin_Alu32, /* 32-bit mov/arith/logical */
+ Pin_Sub32, /* 32-bit mov/arith/logical */
+ Pin_Sh32, /* 32-bit shift/rotate */
+ Pin_Cmp32, /* 32-bit compare */
+ Pin_Unary32, /* 32-bit not, neg, clz */
+ Pin_MulL, /* widening multiply */
+ Pin_Div, /* div */
+ Pin_Call, /* call to address in register */
+ Pin_Goto, /* conditional/unconditional jmp to dst */
+ Pin_CMov32, /* conditional move */
+ Pin_Load, /* load a 8|16|32 bit value from mem */
+ Pin_Store, /* store a 8|16|32 bit value to mem */
+ Pin_Set32, /* convert condition code to 32-bit value */
+ Pin_MFence, /* mem fence (not just sse2, but sse0 and 1 too) */
//.. Xin_FpUnary, /* FP fake unary op */
//.. Xin_FpBinary, /* FP fake binary op */
//.. Xin_FpStSW_AX, /* fstsw %ax */
//.. Xin_FpCmp, /* FP compare, generating a C320 value into int reg */
- Pin_RdWrLR /* Read/Write Link Register */
+ Pin_RdWrLR /* Read/Write Link Register */
}
PPC32InstrTag;
HReg srcL;
HReg srcR;
} Div;
-//.. /* shld/shrd. op may only be Xsh_SHL or Xsh_SHR */
-//.. struct {
-//.. X86ShiftOp op;
-//.. UInt amt; /* shift amount, or 0 means %cl */
-//.. HReg src;
-//.. HReg dst;
-//.. } Sh3232;
-//.. struct {
-//.. X86RMI* src;
-//.. } Push;
/* Pseudo-insn. Call target (an absolute address), on given
condition (which could be Pct_ALWAYS). */
struct {
PPC32CondCode cond;
HReg dst;
} Set32;
-//.. /* 32-bit bsf or bsr. */
-//.. struct {
-//.. Bool isFwds;
-//.. HReg src;
-//.. HReg dst;
-//.. } Bsfr32;
/* Mem fence. In short, an insn which flushes all preceding
loads and stores as much as possible before continuing.
On PPC32 we emit a "sync". */
PPC32Instr;
-extern PPC32Instr* PPC32Instr_Alu32 ( PPC32AluOp, HReg, HReg, PPC32RI* );
-extern PPC32Instr* PPC32Instr_Sub32 ( HReg, PPC32RI*, HReg );
-extern PPC32Instr* PPC32Instr_Sh32 ( PPC32ShiftOp, HReg, HReg, PPC32RI* );
-extern PPC32Instr* PPC32Instr_Cmp32 ( PPC32CmpOp, UInt, HReg, PPC32RI* );
-extern PPC32Instr* PPC32Instr_Unary32 ( PPC32UnaryOp op, HReg dst, HReg src );
-extern PPC32Instr* PPC32Instr_MulL ( Bool syned, Bool word, HReg, HReg, PPC32RI* );
-extern PPC32Instr* PPC32Instr_Div ( Bool syned, HReg dst, HReg srcL, HReg srcR );
-//.. extern X86Instr* X86Instr_Sh3232 ( X86ShiftOp, UInt amt, HReg src, HReg dst );
-//.. extern X86Instr* X86Instr_Push ( X86RMI* );
-extern PPC32Instr* PPC32Instr_Call ( PPC32CondCode, Addr32, Int );
-extern PPC32Instr* PPC32Instr_Goto ( IRJumpKind, PPC32CondCode cond, PPC32RI* dst );
-extern PPC32Instr* PPC32Instr_CMov32 ( PPC32CondCode, HReg dst, PPC32RI* src );
-extern PPC32Instr* PPC32Instr_Load ( UChar sz, Bool syned,
- HReg dst, PPC32AMode* src );
-extern PPC32Instr* PPC32Instr_Store ( UChar sz, PPC32AMode* dst, HReg src );
-extern PPC32Instr* PPC32Instr_Set32 ( PPC32CondCode cond, HReg dst );
-//.. extern X86Instr* X86Instr_Bsfr32 ( Bool isFwds, HReg src, HReg dst );
-extern PPC32Instr* PPC32Instr_MFence ( void );
-//..
+extern PPC32Instr* PPC32Instr_Alu32 ( PPC32AluOp, HReg, HReg, PPC32RI* );
+extern PPC32Instr* PPC32Instr_Sub32 ( HReg, PPC32RI*, HReg );
+extern PPC32Instr* PPC32Instr_Sh32 ( PPC32ShiftOp, HReg, HReg, PPC32RI* );
+extern PPC32Instr* PPC32Instr_Cmp32 ( PPC32CmpOp, UInt, HReg, PPC32RI* );
+extern PPC32Instr* PPC32Instr_Unary32 ( PPC32UnaryOp op, HReg dst, HReg src );
+extern PPC32Instr* PPC32Instr_MulL ( Bool syned, Bool word, HReg, HReg, PPC32RI* );
+extern PPC32Instr* PPC32Instr_Div ( Bool syned, HReg dst, HReg srcL, HReg srcR );
+extern PPC32Instr* PPC32Instr_Call ( PPC32CondCode, Addr32, Int );
+extern PPC32Instr* PPC32Instr_Goto ( IRJumpKind, PPC32CondCode cond, PPC32RI* dst );
+extern PPC32Instr* PPC32Instr_CMov32 ( PPC32CondCode, HReg dst, PPC32RI* src );
+extern PPC32Instr* PPC32Instr_Load ( UChar sz, Bool syned,
+ HReg dst, PPC32AMode* src );
+extern PPC32Instr* PPC32Instr_Store ( UChar sz, PPC32AMode* dst, HReg src );
+extern PPC32Instr* PPC32Instr_Set32 ( PPC32CondCode cond, HReg dst );
+extern PPC32Instr* PPC32Instr_MFence ( void );
+
//.. extern X86Instr* X86Instr_FpUnary ( X86FpOp op, HReg src, HReg dst );
//.. extern X86Instr* X86Instr_FpBinary ( X86FpOp op, HReg srcL, HReg srcR, HReg dst );
//.. extern X86Instr* X86Instr_FpLdSt ( Bool isLoad, UChar sz, HReg reg, X86AMode* );
//.. extern X86Instr* X86Instr_FpStSW_AX ( void );
//.. extern X86Instr* X86Instr_FpCmp ( HReg srcL, HReg srcR, HReg dst );
-extern PPC32Instr* PPC32Instr_RdWrLR ( Bool wrLR, HReg gpr );
+extern PPC32Instr* PPC32Instr_RdWrLR ( Bool wrLR, HReg gpr );
extern void ppPPC32Instr ( PPC32Instr* );
return PPC32Instr_Alu32(Palu_ADD, r_dst, zero, PPC32RI_Imm(imm & 0xFFFF));
}
if (imm > 0xFFFF) {
- // CAB: addis (aka lis) would be good...
+ // CAB: perhaps add Palu_ADDIS ?
addInstr(env, PPC32Instr_Alu32(Palu_ADD, r_dst, zero, PPC32RI_Imm(imm>>16)));
addInstr(env, mk_sh32(env, Psh_SHL, r_dst, r_dst, PPC32RI_Imm(16)));
return PPC32Instr_Alu32(Palu_OR, r_dst, r_dst, PPC32RI_Imm(imm & 0xFFFF));
addInstr(env, PPC32Instr_Alu32(Palu_ADD, r_dst, zero, PPC32RI_Imm(0)));
return PPC32Instr_Alu32(Palu_OR, r_dst, r_dst, ri_src);
} else {
- // mr rD,rS
+ // Just mr rD,rS
return PPC32Instr_Alu32(Palu_OR, r_dst, ri_src->Pri.Reg.reg, ri_src);
}
}
/* Finally, the call itself. */
addInstr(env, PPC32Instr_Call( cc,
- toUInt(Ptr_to_ULong(cee->addr)),
+ Ptr_to_ULong(cee->addr),
n_args + (passBBP ? 1 : 0) ));
}
/* --------- LOAD --------- */
case Iex_LDle: {
HReg r_dst = newVRegI(env);
- PPC32AMode* am_src = iselIntExpr_AMode(env, e->Iex.LDle.addr);
+ PPC32AMode* am_addr = iselIntExpr_AMode(env, e->Iex.LDle.addr);
if (ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32) {
- addInstr(env, PPC32Instr_Load( sizeofIRType(ty), False, r_dst, am_src ));
+ addInstr(env, PPC32Instr_Load( sizeofIRType(ty), False, r_dst, am_addr ));
return r_dst;
}
break;
//.. addInstr(env, X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(0x4700), dst));
//.. return dst;
//.. }
-//..
+
break;
}
addInstr(env, PPC32Instr_Unary32(Pun_CLZ,r_dst,r_src));
return r_dst;
}
+ case Iop_Neg8:
+ case Iop_Neg16:
+ case Iop_Neg32: {
+ HReg r_dst = newVRegI(env);
+ HReg r_src = iselIntExpr_R(env, e->Iex.Unop.arg);
+ addInstr(env, PPC32Instr_Unary32(Pun_NEG,r_dst,r_src));
+ return r_dst;
+ }
//.. case Iop_128to32: {
//.. HReg dst = newVRegI(env);
case Iex_Get: {
if (ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32) {
HReg r_dst = newVRegI(env);
- PPC32AMode* am_src = PPC32AMode_IR(e->Iex.Get.offset, GuestStatePtr );
- addInstr(env, PPC32Instr_Load( sizeofIRType(ty), False, r_dst, am_src ));
+ PPC32AMode* am_addr = PPC32AMode_IR(e->Iex.Get.offset, GuestStatePtr );
+ addInstr(env, PPC32Instr_Load( sizeofIRType(ty), False, r_dst, am_addr ));
return r_dst;
}
break;
case Iex_Mux0X: {
if ((ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8)
&& typeOfIRExpr(env->type_env,e->Iex.Mux0X.cond) == Ity_I8) {
- PPC32CondCode cc;
- HReg r_cond;
- HReg rX = iselIntExpr_R(env, e->Iex.Mux0X.exprX);
- PPC32RI* r0 = iselIntExpr_RI(env, e->Iex.Mux0X.expr0);
- HReg r_dst = newVRegI(env);
+ PPC32CondCode cc = mk_PPCCondCode( Pct_TRUE, Pcf_EQ );
+ HReg r_cond = iselIntExpr_R(env, e->Iex.Mux0X.cond);
+ HReg rX = iselIntExpr_R(env, e->Iex.Mux0X.exprX);
+ PPC32RI* r0 = iselIntExpr_RI(env, e->Iex.Mux0X.expr0);
+ HReg r_dst = newVRegI(env);
addInstr(env, mk_iMOVds_RR(r_dst,rX));
- r_cond = iselIntExpr_R(env, e->Iex.Mux0X.cond);
addInstr(env, PPC32Instr_Cmp32(Pcmp_U, 7, r_cond, PPC32RI_Imm(0)));
- cc = mk_PPCCondCode( Pct_TRUE, Pcf_EQ );
addInstr(env, PPC32Instr_CMov32(cc,r_dst,r0));
return r_dst;
}
break;
} /* switch (e->tag) */
+
/* We get here if no pattern matched. */
irreducible:
ppIRExpr(e);
- vpanic("iselIntExpr_R: cannot reduce tree");
+ vpanic("iselIntExpr_R(ppc32): cannot reduce tree");
}
return cond;
}
+ /* --- patterns rooted at: 32to1 --- */
+
//.. /* 32to1(1Uto32(expr1)) -- the casts are pointless, ignore them */
//.. DEFINE_PATTERN(p_1Uto32_then_32to1,
//.. unop(Iop_32to1,unop(Iop_1Uto32,bind(0))));
return mk_PPCCondCode( Pct_TRUE, Pcf_EQ );
}
+ /* --- patterns rooted at: CmpNEZ32 --- */
+
+ /* CmpNEZ32(x) */
+ if (e->tag == Iex_Unop
+ && e->Iex.Unop.op == Iop_CmpNEZ32) {
+ HReg r1 = iselIntExpr_R(env, e->Iex.Unop.arg);
+ addInstr(env, PPC32Instr_Cmp32(Pcmp_S, 7, r1, PPC32RI_Imm(0)));
+ return mk_PPCCondCode( Pct_FALSE, Pcf_EQ );
+ }
+
+ /* --- patterns rooted at: Cmp{EQ,NE}{8,16} --- */
+
//.. /* CmpEQ8 / CmpNE8 */
//.. if (e->tag == Iex_Binop
//.. && (e->Iex.Binop.op == Iop_CmpEQ8
//.. *rLo = tLo;
//.. return;
//.. }
-//..
-//..
-//.. /* 32HLto64(e1,e2) */
-//.. case Iop_32HLto64:
-//.. *rHi = iselIntExpr_R(env, e->Iex.Binop.arg1);
-//.. *rLo = iselIntExpr_R(env, e->Iex.Binop.arg2);
-//.. return;
-//..
+
+
+ /* 32HLto64(e1,e2) */
+ case Iop_32HLto64:
+ *rHi = iselIntExpr_R(env, e->Iex.Binop.arg1);
+ *rLo = iselIntExpr_R(env, e->Iex.Binop.arg2);
+ return;
+
//.. /* 64-bit shifts */
//.. case Iop_Shl64: {
//.. /* We use the same ingenious scheme as gcc. Put the value
} /* if (e->tag == Iex_Binop) */
-//.. /* --------- UNARY ops --------- */
-//.. if (e->tag == Iex_Unop) {
-//.. switch (e->Iex.Unop.op) {
-//..
+ /* --------- UNARY ops --------- */
+ if (e->tag == Iex_Unop) {
+ switch (e->Iex.Unop.op) {
+
//.. /* 32Sto64(e) */
//.. case Iop_32Sto64: {
//.. HReg tLo = newVRegI(env);
//.. *rLo = tLo;
//.. return;
//.. }
-//..
-//.. /* 32Uto64(e) */
-//.. case Iop_32Uto64: {
-//.. HReg tLo = newVRegI(env);
-//.. HReg tHi = newVRegI(env);
-//.. HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
-//.. addInstr(env, mk_iMOVsd_RR(src,tLo));
-//.. addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(0), tHi));
-//.. *rHi = tHi;
-//.. *rLo = tLo;
-//.. return;
-//.. }
-//..
+
+ /* 32Uto64(e) */
+ case Iop_32Uto64: {
+ HReg tHi = newVRegI(env);
+ HReg tLo = iselIntExpr_R(env, e->Iex.Unop.arg);
+ addInstr(env, mk_iMOVds_RRI(env, tHi, PPC32RI_Imm(0)));
+ *rHi = tHi;
+ *rLo = tLo;
+ return;
+ }
+
//.. /* 128{HI}to64 */
//.. case Iop_128HIto64:
//.. case Iop_128to64: {
//.. *rLo = tLo;
//.. return;
//.. }
-//..
-//.. default:
-//.. break;
-//.. }
-//.. } /* if (e->tag == Iex_Unop) */
-//..
-//..
+
+ default:
+ break;
+ }
+ } /* if (e->tag == Iex_Unop) */
+
+
//.. /* --------- CCALL --------- */
//.. if (e->tag == Iex_CCall) {
//.. HReg tLo = newVRegI(env);
/* --------- STORE --------- */
case Ist_STle: {
- PPC32AMode* am_dst;
+ PPC32AMode* am_addr;
IRType tya = typeOfIRExpr(env->type_env, stmt->Ist.STle.addr);
IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.STle.data);
vassert(tya == Ity_I32);
- am_dst = iselIntExpr_AMode(env, stmt->Ist.STle.addr);
+
+ am_addr = iselIntExpr_AMode(env, stmt->Ist.STle.addr);
if (tyd == Ity_I8 || tyd == Ity_I16 || tyd == Ity_I32) {
HReg r_src = iselIntExpr_R(env, stmt->Ist.STle.data);
- addInstr(env, PPC32Instr_Store(sizeofIRType(tyd),am_dst,r_src));
+ addInstr(env, PPC32Instr_Store(sizeofIRType(tyd), am_addr, r_src));
return;
}
//.. if (tyd == Ity_F64) {
IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.Put.data);
if (ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32) {
HReg r_src = iselIntExpr_R(env, stmt->Ist.Put.data);
- PPC32AMode* am_dst = PPC32AMode_IR(stmt->Ist.Put.offset, GuestStatePtr);
- addInstr(env, PPC32Instr_Store( sizeofIRType(ty), am_dst, r_src ));
+ PPC32AMode* am_addr = PPC32AMode_IR(stmt->Ist.Put.offset, GuestStatePtr);
+ addInstr(env, PPC32Instr_Store( sizeofIRType(ty), am_addr, r_src ));
return;
}
//.. if (ty == Ity_I64) {
break;
}
-//.. /* --------- Call to DIRTY helper --------- */
-//.. case Ist_Dirty: {
-//.. IRType retty;
-//.. IRDirty* d = stmt->Ist.Dirty.details;
-//.. Bool passBBP = False;
-//..
-//.. if (d->nFxState == 0)
-//.. vassert(!d->needsBBP);
-//.. passBBP = d->nFxState > 0 && d->needsBBP;
-//..
-//.. /* Marshal args, do the call, clear stack. */
-//.. doHelperCall( env, passBBP, d->guard, d->cee, d->args );
-//..
-//.. /* Now figure out what to do with the returned value, if any. */
-//.. if (d->tmp == IRTemp_INVALID)
-//.. /* No return value. Nothing to do. */
-//.. return;
-//..
-//.. retty = typeOfIRTemp(env->type_env, d->tmp);
-//.. if (retty == Ity_I64) {
-//.. HReg dstHi, dstLo;
-//.. /* The returned value is in %edx:%eax. Park it in the
-//.. register-pair associated with tmp. */
-//.. lookupIRTemp64( &dstHi, &dstLo, env, d->tmp);
-//.. addInstr(env, mk_iMOVsd_RR(hregX86_EDX(),dstHi) );
-//.. addInstr(env, mk_iMOVsd_RR(hregX86_EAX(),dstLo) );
-//.. return;
-//.. }
-//.. if (retty == Ity_I32 || retty == Ity_I16 || retty == Ity_I8) {
-//.. /* The returned value is in %eax. Park it in the register
-//.. associated with tmp. */
-//.. HReg dst = lookupIRTemp(env, d->tmp);
-//.. addInstr(env, mk_iMOVsd_RR(hregX86_EAX(),dst) );
-//.. return;
-//.. }
-//.. break;
-//.. }
+ /* --------- Call to DIRTY helper --------- */
+ case Ist_Dirty: {
+ IRType retty;
+ IRDirty* d = stmt->Ist.Dirty.details;
+ Bool passBBP = False;
+
+ if (d->nFxState == 0)
+ vassert(!d->needsBBP);
+ passBBP = d->nFxState > 0 && d->needsBBP;
+
+ /* Marshal args, do the call, clear stack. */
+ doHelperCall( env, passBBP, d->guard, d->cee, d->args );
+
+ /* Now figure out what to do with the returned value, if any. */
+ if (d->tmp == IRTemp_INVALID)
+ /* No return value. Nothing to do. */
+ return;
+
+ retty = typeOfIRTemp(env->type_env, d->tmp);
+ if (retty == Ity_I64) {
+ HReg r_dstHi, r_dstLo;
+ /* The returned value is in %r3:%r4. Park it in the
+ register-pair associated with tmp. */
+ lookupIRTemp64( &r_dstHi, &r_dstLo, env, d->tmp);
+ addInstr(env, mk_iMOVds_RR(r_dstHi, hregPPC32_GPR3()));
+ addInstr(env, mk_iMOVds_RR(r_dstLo, hregPPC32_GPR4()));
+ return;
+ }
+ if (retty == Ity_I32 || retty == Ity_I16 || retty == Ity_I8) {
+ /* The returned value is in %r3. Park it in the register
+ associated with tmp. */
+ HReg r_dst = lookupIRTemp(env, d->tmp);
+ addInstr(env, mk_iMOVds_RR(r_dst, hregPPC32_GPR3()));
+ return;
+ }
+ break;
+ }
/* --------- MEM FENCE --------- */
case Ist_MFence:
addInstr(env, PPC32Instr_MFence());
return;
+ /* --------- INSTR MARK --------- */
+ /* Doesn't generate any executable code ... */
+ case Ist_IMark:
+ return;
+
+ /* --------- NO-OP --------- */
+ /* Fairly self-explanatory, wouldn't you say? */
+ case Ist_NoOp:
+ return;
+
/* --------- EXIT --------- */
case Ist_Exit: {
PPC32RI* ri_dst;
default: break;
}
ppIRStmt(stmt);
- vpanic("iselStmt");
+ vpanic("iselStmt(ppc32)");
}
extern
void LibVEX_GuestPPC32_initialise ( /*OUT*/VexGuestPPC32State* vex_state );
-/* Calculate the PPC32 flag state from the saved data. */
+/* Extract from the supplied VexGuestPPC32State structure the
+ corresponding native %cr7 value. */
extern
-UInt LibVEX_GuestPPC32_get_flags ( /*IN*/VexGuestPPC32State* vex_state );
+UInt LibVEX_GuestPPC32_get_cr7 ( /*IN*/VexGuestPPC32State* vex_state );
#endif /* ndef __LIBVEX_PUB_GUEST_PPC32_H */
}
sb_helper1 = (HWord)&gst;
- sb_helper2 = LibVEX_GuestPPC32_get_flags(&gst);
+ sb_helper2 = LibVEX_GuestPPC32_get_cr7(&gst);
/* stay sane ... */
assert(p[0] == 24<<26); /* nop */
void log_bytes ( HChar* bytes, Int nbytes )
{
fwrite ( bytes, 1, nbytes, stdout );
+ fflush ( stdout );
}