From 6481bde2da5995c2d7c110cde41acd871812a284 Mon Sep 17 00:00:00 2001 From: Cerion Armour-Brown Date: Mon, 20 Jun 2005 12:42:04 +0000 Subject: [PATCH] guest-ppc32 ~~~~~~~~~~ - store-with-update instrs: Valgrind pagefault handler expects faulting address >= current stack ptr, so we need to update the stack ptr register _before_ storing the old stack ptr - branch_ctr_ok (bad calc for 'branch if %ctr zero' case) - mcrf: scanning bitfields in the wrong direction - on spotting the magic sequence, delta += 24 - updated DIPs for +ve-only args host-ppc32 ~~~~~~~~~ - fixed CMov reg usage - fixed Pin_Call in emit_PPC32Instr(): we already know how far we're jumping - fixed Pin_Goto in emit_PPC32Instr(): vassert right range of jump deltas other-ppc32 ~~~~~~~~~~ - exported OFFSET_ppc32_(various) for valgrind git-svn-id: svn://svn.valgrind.org/vex/trunk@1211 --- VEX/auxprogs/genoffsets.c | 74 ++++++++--- VEX/priv/guest-ppc32/gdefs.h | 15 +-- VEX/priv/guest-ppc32/ghelpers.c | 12 +- VEX/priv/guest-ppc32/toIR.c | 86 +++++++------ VEX/priv/host-ppc32/hdefs.c | 194 +++++------------------------ VEX/priv/host-ppc32/hdefs.h | 88 +++++-------- VEX/priv/host-ppc32/isel.c | 212 ++++++++++++++++++-------------- VEX/pub/libvex_guest_ppc32.h | 5 +- VEX/switchback/switchback.c | 3 +- 9 files changed, 305 insertions(+), 384 deletions(-) diff --git a/VEX/auxprogs/genoffsets.c b/VEX/auxprogs/genoffsets.c index bcb7ffebc1..66c549d303 100644 --- a/VEX/auxprogs/genoffsets.c +++ b/VEX/auxprogs/genoffsets.c @@ -6,60 +6,98 @@ #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; } diff --git a/VEX/priv/guest-ppc32/gdefs.h b/VEX/priv/guest-ppc32/gdefs.h index f8de81d544..d95a17ebe6 100644 --- a/VEX/priv/guest-ppc32/gdefs.h +++ b/VEX/priv/guest-ppc32/gdefs.h @@ -41,7 +41,7 @@ /*---------------------------------------------------------*/ -/*--- ppc32 to IR conversion ---*/ +/*--- ppc32 to IR conversion ---*/ /*---------------------------------------------------------*/ extern @@ -75,7 +75,7 @@ VexGuestLayout ppc32Guest_layout; /* --- 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 ); @@ -89,8 +89,9 @@ extern UInt ppc32g_calculate_xer_ca ( 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. @@ -103,11 +104,11 @@ extern UInt ppc32g_calculate_xer_ca ( UInt op, UInt res, UInt argL, UInt argR, 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 */ diff --git a/VEX/priv/guest-ppc32/ghelpers.c b/VEX/priv/guest-ppc32/ghelpers.c index 2414969ed1..588a8ce859 100644 --- a/VEX/priv/guest-ppc32/ghelpers.c +++ b/VEX/priv/guest-ppc32/ghelpers.c @@ -64,7 +64,7 @@ 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); @@ -98,7 +98,7 @@ UInt ppc32g_calculate_xer_ov ( UInt op, UInt res, UInt argL, UInt argR ) /* 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; } @@ -190,7 +190,7 @@ IRExpr* guest_ppc32_spechelper ( HChar* function_name, /* 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 @@ -198,9 +198,9 @@ void LibVEX_GuestPPC32_put_flags ( UInt flags_native, #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 @@ -304,6 +304,8 @@ VexGuestLayout .alwaysDefd = { /* 0 */ ALWAYSDEFD(guest_CC_OP) + + // FIXME } }; diff --git a/VEX/priv/guest-ppc32/toIR.c b/VEX/priv/guest-ppc32/toIR.c index 5701f01a69..48908e32c4 100644 --- a/VEX/priv/guest-ppc32/toIR.c +++ b/VEX/priv/guest-ppc32/toIR.c @@ -69,6 +69,10 @@ 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; @@ -302,13 +306,14 @@ IRBB* bbToIR_PPC32 ( UChar* ppc32code, 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; @@ -380,7 +385,7 @@ IRBB* bbToIR_PPC32 ( UChar* ppc32code, 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) @@ -555,10 +560,12 @@ static IRExpr* mkU8 ( UChar i ) 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 ) { @@ -602,7 +609,7 @@ static IRExpr* ROTL32 ( IRExpr* src, IRExpr* rot_amt ) /* -------------- 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), @@ -612,7 +619,7 @@ static IRExpr* mk_ppc32g_calculate_cr7_all ( void ) = mkIRExprCCall( Ity_I32, 0/*regparm*/, - "ppc32g_calculate_cr7_all", &ppc32g_calculate_cr7_all, + "ppc32g_calculate_cr7", &ppc32g_calculate_cr7, args ); @@ -682,7 +689,7 @@ static IRExpr* mk_ppc32g_calculate_xer_ca ( UInt op, IRExpr* res, 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; @@ -769,7 +776,8 @@ static IRExpr* getReg_masked ( PPC32SPR reg, UInt mask ) 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) ); @@ -810,7 +818,7 @@ static IRExpr* getReg_field ( PPC32SPR reg, UInt field_idx ) 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; } @@ -826,7 +834,7 @@ static IRExpr* getReg_bit ( PPC32SPR reg, UInt bit_idx ) val = getReg_masked( reg, 1<> 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); @@ -2452,7 +2456,7 @@ static Bool dis_cond_logic ( UInt theInstr ) 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) ) ); @@ -2987,7 +2991,7 @@ static Bool dis_proc_ctl ( UInt theInstr ) DIP("mtcrf 0x%x,r%d\n", CRM, Rs_addr); for (i=0; i<8; i++) { if (CRM & (1< 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) @@ -3863,7 +3868,7 @@ static DisResult disInstr ( /*IN*/ Bool resteerOK, 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 && @@ -3874,7 +3879,8 @@ static DisResult disInstr ( /*IN*/ Bool resteerOK, DIP("? = client_request ( ? )\n"); *size = 24; - + delta += 24; + irbb->next = mkU32(guest_pc_bbstart+delta); irbb->jumpkind = Ijk_ClientReq; @@ -3895,14 +3901,6 @@ static DisResult disInstr ( /*IN*/ Bool resteerOK, #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) { diff --git a/VEX/priv/host-ppc32/hdefs.c b/VEX/priv/host-ppc32/hdefs.c index 926fee6493..9d0b02cf46 100644 --- a/VEX/priv/host-ppc32/hdefs.c +++ b/VEX/priv/host-ppc32/hdefs.c @@ -227,7 +227,7 @@ HChar* showPPC32CondCode ( PPC32CondCode cond ) } } -/* constructor */ +/* construct condition code */ PPC32CondCode mk_PPCCondCode ( PPC32CondTest test, PPC32CondFlag flag ) { PPC32CondCode cc; @@ -531,22 +531,6 @@ PPC32Instr* PPC32Instr_Div ( Bool syned, HReg dst, HReg srcL, HReg srcR ) { 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; @@ -600,14 +584,6 @@ PPC32Instr* PPC32Instr_Set32 ( PPC32CondCode cond, HReg dst ) { 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)); @@ -822,20 +798,6 @@ void ppPPC32Instr ( PPC32Instr* i ) 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) { @@ -927,12 +889,6 @@ void ppPPC32Instr ( PPC32Instr* i ) } 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; @@ -1125,16 +1081,6 @@ void getRegUsage_PPC32Instr ( HRegUsage* u, PPC32Instr* i ) 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 @@ -1183,7 +1129,7 @@ void getRegUsage_PPC32Instr ( HRegUsage* u, PPC32Instr* i ) 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); @@ -1196,10 +1142,6 @@ void getRegUsage_PPC32Instr ( HRegUsage* u, PPC32Instr* i ) 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: @@ -1364,13 +1306,6 @@ void mapRegs_PPC32Instr (HRegRemap* m, PPC32Instr* i) 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: @@ -1391,10 +1326,6 @@ void mapRegs_PPC32Instr (HRegRemap* m, PPC32Instr* i) 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: @@ -1808,6 +1739,10 @@ static UChar* emit32 ( UChar* p, UInt w32 ) //.. 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; @@ -1932,13 +1867,12 @@ static UChar* mkFormM ( UChar* p, UInt opc1, UInt r1, UInt r2, 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; @@ -1948,13 +1882,11 @@ static UChar* doAMode_IR ( UChar* p, UInt opc1, HReg hrSD, PPC32AMode* am ) 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); @@ -2001,16 +1933,10 @@ static UChar* mkMoveReg ( UChar* p, UInt r_dst, UInt r_src ) 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"); @@ -2039,7 +1965,7 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i ) } 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; @@ -2215,50 +2141,18 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i ) 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 */ @@ -2269,15 +2163,6 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i ) /* 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; } @@ -2319,26 +2204,26 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i ) 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); } @@ -2385,6 +2270,8 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i ) } 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) { @@ -2395,17 +2282,16 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i ) 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; @@ -2442,37 +2328,25 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i ) 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; @@ -2916,8 +2790,6 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i ) done: vassert(p - &buf[0] <= 32); return p - &buf[0]; - -# undef fake } /*---------------------------------------------------------------*/ diff --git a/VEX/priv/host-ppc32/hdefs.h b/VEX/priv/host-ppc32/hdefs.h index 41e4944fd2..c8de36e8e0 100644 --- a/VEX/priv/host-ppc32/hdefs.h +++ b/VEX/priv/host-ppc32/hdefs.h @@ -48,7 +48,7 @@ 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 ); @@ -297,23 +297,20 @@ extern HChar* showPPC32CmpOp ( PPC32CmpOp ); /* --------- */ 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 */ @@ -325,7 +322,7 @@ typedef //.. 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; @@ -378,16 +375,6 @@ typedef 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 { @@ -430,12 +417,6 @@ typedef 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". */ @@ -511,25 +492,22 @@ typedef 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* ); @@ -540,7 +518,7 @@ extern PPC32Instr* PPC32Instr_MFence ( void ); //.. 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* ); diff --git a/VEX/priv/host-ppc32/isel.c b/VEX/priv/host-ppc32/isel.c index 9ad2d8fea7..149c2d43b7 100644 --- a/VEX/priv/host-ppc32/isel.c +++ b/VEX/priv/host-ppc32/isel.c @@ -342,7 +342,7 @@ static PPC32Instr* mk_iMOVds_RRI ( ISelEnv* env, HReg r_dst, PPC32RI* ri_src ) 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)); @@ -351,7 +351,7 @@ static PPC32Instr* mk_iMOVds_RRI ( ISelEnv* env, HReg r_dst, PPC32RI* ri_src ) 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); } } @@ -659,7 +659,7 @@ void doHelperCall ( ISelEnv* env, /* 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) )); } @@ -835,9 +835,9 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) /* --------- 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; @@ -1114,7 +1114,7 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) //.. addInstr(env, X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(0x4700), dst)); //.. return dst; //.. } -//.. + break; } @@ -1259,6 +1259,14 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) 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); @@ -1287,8 +1295,8 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) 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; @@ -1337,16 +1345,14 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) 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; } @@ -1357,10 +1363,11 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) 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"); } @@ -1520,6 +1527,8 @@ static PPC32CondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e ) 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)))); @@ -1544,6 +1553,18 @@ static PPC32CondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e ) 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 @@ -1884,14 +1905,14 @@ static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) //.. *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 @@ -2180,10 +2201,10 @@ static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) } /* 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); @@ -2196,19 +2217,17 @@ static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) //.. *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: { @@ -2315,13 +2334,13 @@ static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) //.. *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); @@ -3192,14 +3211,15 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt ) /* --------- 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) { @@ -3235,8 +3255,8 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt ) 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) { @@ -3339,49 +3359,59 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt ) 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; @@ -3398,7 +3428,7 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt ) default: break; } ppIRStmt(stmt); - vpanic("iselStmt"); + vpanic("iselStmt(ppc32)"); } diff --git a/VEX/pub/libvex_guest_ppc32.h b/VEX/pub/libvex_guest_ppc32.h index 395c39faa9..7b6bc06c42 100644 --- a/VEX/pub/libvex_guest_ppc32.h +++ b/VEX/pub/libvex_guest_ppc32.h @@ -154,10 +154,11 @@ typedef 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 */ diff --git a/VEX/switchback/switchback.c b/VEX/switchback/switchback.c index 51dd57db53..58cc34712b 100644 --- a/VEX/switchback/switchback.c +++ b/VEX/switchback/switchback.c @@ -302,7 +302,7 @@ void switchback ( void ) } 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 */ @@ -629,6 +629,7 @@ static void log_bytes ( HChar* bytes, Int nbytes ) { fwrite ( bytes, 1, nbytes, stdout ); + fflush ( stdout ); } -- 2.47.3