From: Cerion Armour-Brown Date: Wed, 16 Feb 2005 08:54:33 +0000 (+0000) Subject: spacing/comment cleanup only X-Git-Tag: svn/VALGRIND_3_0_1^2~425 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2b2549ae534a3792eee3c389a3d03e8473c18bae;p=thirdparty%2Fvalgrind.git spacing/comment cleanup only git-svn-id: svn://svn.valgrind.org/vex/trunk@909 --- diff --git a/VEX/priv/guest-arm/gdefs.h b/VEX/priv/guest-arm/gdefs.h index 101e69eb06..aa50506d30 100644 --- a/VEX/priv/guest-arm/gdefs.h +++ b/VEX/priv/guest-arm/gdefs.h @@ -146,16 +146,15 @@ extern UInt armg_calculate_condition ( */ enum { - ARMG_CC_OP_COPY, /* DEP1 = current flags, DEP2 = 0 */ - /* just copy DEP1 to output */ - - ARMG_CC_OP_LOGIC, /* DEP1 = result, DEP2 = shifter_carry_out */ - - ARMG_CC_OP_SUB, /* DEP1 = arg1(Rn), DEP2 = arg2 (shifter_op) */ - ARMG_CC_OP_ADD, /* DEP1 = arg1(Rn), DEP2 = arg2 (shifter_op) */ - - - ARMG_CC_OP_NUMBER + ARMG_CC_OP_COPY, /* DEP1 = current flags, DEP2 = 0 */ + /* just copy DEP1 to output */ + + ARMG_CC_OP_LOGIC, /* DEP1 = result, DEP2 = shifter_carry_out */ + + ARMG_CC_OP_SUB, /* DEP1 = arg1(Rn), DEP2 = arg2 (shifter_op) */ + ARMG_CC_OP_ADD, /* DEP1 = arg1(Rn), DEP2 = arg2 (shifter_op) */ + + ARMG_CC_OP_NUMBER }; /* requires further study */ diff --git a/VEX/priv/guest-arm/ghelpers.c b/VEX/priv/guest-arm/ghelpers.c index de19f2d905..429b18a10f 100644 --- a/VEX/priv/guest-arm/ghelpers.c +++ b/VEX/priv/guest-arm/ghelpers.c @@ -77,16 +77,16 @@ c: shifter_carry_out v: unaffected */ -#define ACTIONS_LOGIC() \ -{ \ - { Int nf, zf, cf, vf; \ - Int oldV=0; /* CAB: vf unaffected: what todo? */ \ - nf = cc_dep1_formal & ARMG_CC_MASK_N; \ - zf = cc_dep1_formal == 0 ? 1 : 0; \ - cf = (cc_dep2_formal << ARMG_CC_SHIFT_C) & ARMG_CC_MASK_C; \ - vf = oldV & ARMG_CC_MASK_V; \ - return nf | zf | cf | vf; \ - } \ +#define ACTIONS_LOGIC() \ +{ \ + { Int nf, zf, cf, vf; \ + Int oldV=0; /* CAB: vf unaffected: what todo? */ \ + nf = cc_dep1_formal & ARMG_CC_MASK_N; \ + zf = cc_dep1_formal == 0 ? 1 : 0; \ + cf = (cc_dep2_formal << ARMG_CC_SHIFT_C) & ARMG_CC_MASK_C; \ + vf = oldV & ARMG_CC_MASK_V; \ + return nf | zf | cf | vf; \ + } \ } /*-------------------------------------------------------------*/ @@ -98,20 +98,20 @@ c: CarryFrom(Rn + shifter_op) v: OverflowFrom(Rn + shifter_op) */ -#define ACTIONS_ADD() \ -{ \ - { Int nf, zf, cf, vf; \ - Int argL, argR, res; \ - argL = cc_dep1_formal; \ - argR = cc_dep2_formal; \ - res = argL + argR; \ - nf = res & ARMG_CC_MASK_N; \ - zf = (res == 0) << ARMG_CC_SHIFT_Z; \ - cf = ((UInt)argL < (UInt)argR) << ARMG_CC_SHIFT_C; \ - vf = (((argL ^ argR ^ -1) & (argL ^ res)) >> \ - (32 - ARMG_CC_SHIFT_V)) & ARMG_CC_MASK_V; \ - return nf | zf | cf | vf; \ - } \ +#define ACTIONS_ADD() \ +{ \ + { Int nf, zf, cf, vf; \ + Int argL, argR, res; \ + argL = cc_dep1_formal; \ + argR = cc_dep2_formal; \ + res = argL + argR; \ + nf = res & ARMG_CC_MASK_N; \ + zf = (res == 0) << ARMG_CC_SHIFT_Z; \ + cf = ((UInt)argL < (UInt)argR) << ARMG_CC_SHIFT_C; \ + vf = (((argL ^ argR ^ -1) & (argL ^ res)) >> \ + (32 - ARMG_CC_SHIFT_V)) & ARMG_CC_MASK_V; \ + return nf | zf | cf | vf; \ + } \ } /*-------------------------------------------------------------*/ @@ -124,21 +124,21 @@ v: OverflowFrom(Rn - shifter_op) */ // CAB: cf right? ARM ARM A4-99 -#define ACTIONS_SUB() \ -{ \ - { Int nf, zf, cf, vf; \ - Int argL, argR, res; \ - argL = cc_dep1_formal; \ - argR = cc_dep2_formal; \ - res = argL - argR; \ - nf = res & ARMG_CC_MASK_N; \ - zf = (res == 0) << ARMG_CC_SHIFT_Z; \ - cf = (~((UInt)argL < (UInt)argR) << \ - ARMG_CC_SHIFT_C) & ARMG_CC_MASK_C; \ - vf = (((argL ^ argR ^ -1) & (argL ^ res)) >> \ - (32 - ARMG_CC_SHIFT_V)) & ARMG_CC_MASK_V; \ - return nf | zf | cf | vf; \ - } \ +#define ACTIONS_SUB() \ +{ \ + { Int nf, zf, cf, vf; \ + Int argL, argR, res; \ + argL = cc_dep1_formal; \ + argR = cc_dep2_formal; \ + res = argL - argR; \ + nf = res & ARMG_CC_MASK_N; \ + zf = (res == 0) << ARMG_CC_SHIFT_Z; \ + cf = (~((UInt)argL < (UInt)argR) << \ + ARMG_CC_SHIFT_C) & ARMG_CC_MASK_C; \ + vf = (((argL ^ argR ^ -1) & (argL ^ res)) >> \ + (32 - ARMG_CC_SHIFT_V)) & ARMG_CC_MASK_V; \ + return nf | zf | cf | vf; \ + } \ } @@ -183,38 +183,33 @@ /* CALLED FROM GENERATED CODE: CLEAN HELPER */ /* Calculate all the 4 flags from the supplied thunk parameters. */ UInt armg_calculate_flags_all ( UInt cc_op, - UInt cc_dep1_formal, - UInt cc_dep2_formal ) + UInt cc_dep1_formal, + UInt cc_dep2_formal ) { switch (cc_op) { + case ARMG_CC_OP_LOGIC: ACTIONS_LOGIC(); + case ARMG_CC_OP_ADD: ACTIONS_ADD(); + case ARMG_CC_OP_SUB: ACTIONS_SUB(); - case ARMG_CC_OP_LOGIC: ACTIONS_LOGIC(); - - case ARMG_CC_OP_ADD: ACTIONS_ADD(); - - case ARMG_CC_OP_SUB: ACTIONS_SUB(); - - - default: - /* shouldn't really make these calls from generated code */ - vex_printf("armg_calculate_flags_all(ARM)( %d, 0x%x, 0x%x )\n", - cc_op, cc_dep1_formal, cc_dep2_formal ); - vpanic("armg_calculate_flags_all(ARM)"); + default: + /* shouldn't really make these calls from generated code */ + vex_printf("armg_calculate_flags_all(ARM)( %d, 0x%x, 0x%x )\n", + cc_op, cc_dep1_formal, cc_dep2_formal ); + vpanic("armg_calculate_flags_all(ARM)"); } } /* CALLED FROM GENERATED CODE: CLEAN HELPER */ /* Calculate just the carry flag from the supplied thunk parameters. */ UInt armg_calculate_flags_c ( UInt cc_op, - UInt cc_dep1, - UInt cc_dep2 ) + UInt cc_dep1, + UInt cc_dep2 ) { /* Fast-case some common ones. */ switch (cc_op) { - default: - break; + default: + break; } - return armg_calculate_flags_all(cc_op,cc_dep1,cc_dep2) & ARMG_CC_MASK_C; } @@ -224,9 +219,9 @@ UInt armg_calculate_flags_c ( UInt cc_op, /* returns 1 or 0 */ /*static*/ UInt armg_calculate_condition ( UInt/*ARMCondcode*/ cond, - UInt cc_op, - UInt cc_dep1, - UInt cc_dep2 ) + UInt cc_op, + UInt cc_dep1, + UInt cc_dep2 ) { UInt nf,zf,vf,cf; UInt inv = cond & 1; @@ -236,50 +231,50 @@ UInt armg_calculate_condition ( UInt/*ARMCondcode*/ cond, switch (cond) { case ARMCondEQ: // Z=1 => z case ARMCondNE: // Z=0 - zf = nzvc >> ARMG_CC_SHIFT_Z; - return 1 & (inv ^ zf); + zf = nzvc >> ARMG_CC_SHIFT_Z; + return 1 & (inv ^ zf); case ARMCondHS: // C=1 => c case ARMCondLO: // C=0 - cf = nzvc >> ARMG_CC_SHIFT_C; - return 1 & (inv ^ cf); + cf = nzvc >> ARMG_CC_SHIFT_C; + return 1 & (inv ^ cf); case ARMCondMI: // N=1 => n case ARMCondPL: // N=0 - nf = nzvc >> ARMG_CC_SHIFT_N; - return 1 & (inv ^ nf); + nf = nzvc >> ARMG_CC_SHIFT_N; + return 1 & (inv ^ nf); case ARMCondVS: // V=1 => v case ARMCondVC: // V=0 - vf = nzvc >> ARMG_CC_SHIFT_V; - return 1 & (inv ^ vf); + vf = nzvc >> ARMG_CC_SHIFT_V; + return 1 & (inv ^ vf); case ARMCondHI: // C=1 && Z=0 => c & ~z case ARMCondLS: // C=0 || Z=1 - cf = nzvc >> ARMG_CC_SHIFT_C; - zf = nzvc >> ARMG_CC_SHIFT_Z; - return 1 & (inv ^ (cf & ~zf)); + cf = nzvc >> ARMG_CC_SHIFT_C; + zf = nzvc >> ARMG_CC_SHIFT_Z; + return 1 & (inv ^ (cf & ~zf)); case ARMCondGE: // N=V => ~(n^v) case ARMCondLT: // N!=V - nf = nzvc >> ARMG_CC_SHIFT_N; - vf = nzvc >> ARMG_CC_SHIFT_V; - return 1 & (inv ^ ~(nf ^ vf)); + nf = nzvc >> ARMG_CC_SHIFT_N; + vf = nzvc >> ARMG_CC_SHIFT_V; + return 1 & (inv ^ ~(nf ^ vf)); case ARMCondGT: // Z=0 && N=V => (~z & ~(n^v) => ~(z | (n^v) case ARMCondLE: // Z=1 || N!=V - nf = nzvc >> ARMG_CC_SHIFT_N; - vf = nzvc >> ARMG_CC_SHIFT_V; - zf = nzvc >> ARMG_CC_SHIFT_Z; + nf = nzvc >> ARMG_CC_SHIFT_N; + vf = nzvc >> ARMG_CC_SHIFT_V; + zf = nzvc >> ARMG_CC_SHIFT_Z; return 1 & (inv ^ ~(zf | (nf ^ vf))); case ARMCondAL: // should never get here: Always => no flags to calc case ARMCondNV: // should never get here: Illegal instr default: - /* shouldn't really make these calls from generated code */ - vex_printf("armg_calculate_condition(ARM)( %d, %d, 0x%x, 0x%x )\n", - cond, cc_op, cc_dep1, cc_dep2 ); - vpanic("armg_calculate_condition(ARM)"); + /* shouldn't really make these calls from generated code */ + vex_printf("armg_calculate_condition(ARM)( %d, %d, 0x%x, 0x%x )\n", + cond, cc_op, cc_dep1, cc_dep2 ); + vpanic("armg_calculate_condition(ARM)"); } } @@ -291,9 +286,9 @@ UInt armg_calculate_condition ( UInt/*ARMCondcode*/ cond, /* temporarily unused */ static Bool isU32 ( IRExpr* e, UInt n ) { - return e->tag == Iex_Const - && e->Iex.Const.con->tag == Ico_U32 - && e->Iex.Const.con->Ico.U32 == n; + return (e->tag == Iex_Const + && e->Iex.Const.con->tag == Ico_U32 + && e->Iex.Const.con->Ico.U32 == n); } #endif IRExpr* guest_arm_spechelper ( HChar* function_name, @@ -317,7 +312,7 @@ void LibVEX_GuestARM_put_flags ( UInt flags_native, /* Mask out everything except N Z V C. */ flags_native &= (ARMG_CC_MASK_N | ARMG_CC_MASK_Z | ARMG_CC_MASK_V | ARMG_CC_MASK_C); - + vex_state->guest_CC_OP = ARMG_CC_OP_COPY; vex_state->guest_CC_DEP1 = flags_native; vex_state->guest_CC_DEP2 = 0; diff --git a/VEX/priv/guest-arm/toIR.c b/VEX/priv/guest-arm/toIR.c index 61e229eb62..741c71dedc 100644 --- a/VEX/priv/guest-arm/toIR.c +++ b/VEX/priv/guest-arm/toIR.c @@ -252,32 +252,32 @@ IRBB* bbToIR_ARM ( UChar* armCode, vassert(guest_next == 0); switch (dres) { - case Dis_Continue: - vassert(irbb->next == NULL); - if (n_instrs < vex_control.guest_max_insns) { - /* keep going */ - } else { - irbb->next = mkU32(((Addr32)guest_pc_start)+delta); - return irbb; - } - break; - case Dis_StopHere: - vassert(irbb->next != NULL); + case Dis_Continue: + vassert(irbb->next == NULL); + if (n_instrs < vex_control.guest_max_insns) { + /* keep going */ + } else { + irbb->next = mkU32(((Addr32)guest_pc_start)+delta); return irbb; - case Dis_Resteer: - vpanic("bbToIR_ARM: Dis_Resteer: fixme"); - /* need to add code here to start a new extent ... */ - vassert(irbb->next == NULL); - /* figure out a new delta to continue at. */ - vassert(chase_into_ok(guest_next)); - delta = (UInt)(guest_next - guest_pc_start); - n_resteers++; - d_resteers++; - if (0 && (n_resteers & 0xFF) == 0) + } + break; + case Dis_StopHere: + vassert(irbb->next != NULL); + return irbb; + case Dis_Resteer: + vpanic("bbToIR_ARM: Dis_Resteer: fixme"); + /* need to add code here to start a new extent ... */ + vassert(irbb->next == NULL); + /* figure out a new delta to continue at. */ + vassert(chase_into_ok(guest_next)); + delta = (UInt)(guest_next - guest_pc_start); + n_resteers++; + d_resteers++; + if (0 && (n_resteers & 0xFF) == 0) vex_printf("resteer[%d,%d] to %p (delta = %d)\n", n_resteers, d_resteers, ULong_to_Ptr(guest_next), delta); - break; + break; } } } @@ -372,10 +372,10 @@ static UInt getUDisp32 ( UInt delta ) static UInt getUDisp ( Int size, UInt delta ) { switch (size) { - case 4: return getUDisp32(delta); - case 2: return getUDisp16(delta); - case 1: return getUChar(delta); - default: vpanic("getUDisp(ARM)"); + case 4: return getUDisp32(delta); + case 2: return getUDisp16(delta); + case 1: return getUChar(delta); + default: vpanic("getUDisp(ARM)"); } return 0; /*notreached*/ } @@ -404,12 +404,12 @@ static UInt getSDisp16 ( UInt delta0 ) static UInt getSDisp ( Int size, UInt delta ) { switch (size) { - case 4: return getUDisp32(delta); - case 2: return getSDisp16(delta); - case 1: return getSDisp8(delta); - default: vpanic("getSDisp(ARM)"); - } - return 0; /*notreached*/ + case 4: return getUDisp32(delta); + case 2: return getSDisp16(delta); + case 1: return getSDisp8(delta); + default: vpanic("getSDisp(ARM)"); + } + return 0; /*notreached*/ } #endif @@ -427,10 +427,10 @@ static UInt getSDisp ( Int size, UInt delta ) static IRType szToITy ( Int n ) { switch (n) { - case 1: return Ity_I8; - case 2: return Ity_I16; - case 4: return Ity_I32; - default: vpanic("szToITy(ARM)"); + case 1: return Ity_I8; + case 2: return Ity_I16; + case 4: return Ity_I32; + default: vpanic("szToITy(ARM)"); } } #endif @@ -443,22 +443,22 @@ static Int integerGuestRegOffset ( UInt archreg ) // jrs: probably not; only matters if we reference sub-parts // of the arm registers, but that isn't the case switch (archreg) { - case 0: return offsetof(VexGuestARMState, guest_R0); - case 1: return offsetof(VexGuestARMState, guest_R1); - case 2: return offsetof(VexGuestARMState, guest_R2); - case 3: return offsetof(VexGuestARMState, guest_R3); - case 4: return offsetof(VexGuestARMState, guest_R4); - case 5: return offsetof(VexGuestARMState, guest_R5); - case 6: return offsetof(VexGuestARMState, guest_R6); - case 7: return offsetof(VexGuestARMState, guest_R7); - case 8: return offsetof(VexGuestARMState, guest_R8); - case 9: return offsetof(VexGuestARMState, guest_R9); - case 10: return offsetof(VexGuestARMState,guest_R10); - case 11: return offsetof(VexGuestARMState,guest_R11); - case 12: return offsetof(VexGuestARMState,guest_R12); - case 13: return offsetof(VexGuestARMState,guest_R13); - case 14: return offsetof(VexGuestARMState,guest_R14); - case 15: return offsetof(VexGuestARMState,guest_R15); + case 0: return offsetof(VexGuestARMState,guest_R0); + case 1: return offsetof(VexGuestARMState,guest_R1); + case 2: return offsetof(VexGuestARMState,guest_R2); + case 3: return offsetof(VexGuestARMState,guest_R3); + case 4: return offsetof(VexGuestARMState,guest_R4); + case 5: return offsetof(VexGuestARMState,guest_R5); + case 6: return offsetof(VexGuestARMState,guest_R6); + case 7: return offsetof(VexGuestARMState,guest_R7); + case 8: return offsetof(VexGuestARMState,guest_R8); + case 9: return offsetof(VexGuestARMState,guest_R9); + case 10: return offsetof(VexGuestARMState,guest_R10); + case 11: return offsetof(VexGuestARMState,guest_R11); + case 12: return offsetof(VexGuestARMState,guest_R12); + case 13: return offsetof(VexGuestARMState,guest_R13); + case 14: return offsetof(VexGuestARMState,guest_R14); + case 15: return offsetof(VexGuestARMState,guest_R15); } vpanic("integerGuestRegOffset(arm,le)"); /*notreached*/ @@ -691,10 +691,10 @@ static Bool isLogic ( IROp op8 ) static IRExpr* widenUto32 ( IRExpr* e ) { switch (typeOfIRExpr(irbb->tyenv,e)) { - case Ity_I32: return e; - case Ity_I16: return unop(Iop_16Uto32,e); - case Ity_I8: return unop(Iop_8Uto32,e); - default: vpanic("widenUto32"); + case Ity_I32: return e; + case Ity_I16: return unop(Iop_16Uto32,e); + case Ity_I8: return unop(Iop_8Uto32,e); + default: vpanic("widenUto32"); } } @@ -703,10 +703,10 @@ static IRExpr* widenUto32 ( IRExpr* e ) static IRExpr* widenSto32 ( IRExpr* e ) { switch (typeOfIRExpr(irbb->tyenv,e)) { - case Ity_I32: return e; - case Ity_I16: return unop(Iop_16Sto32,e); - case Ity_I8: return unop(Iop_8Sto32,e); - default: vpanic("widenSto32"); + case Ity_I32: return e; + case Ity_I16: return unop(Iop_16Sto32,e); + case Ity_I8: return unop(Iop_8Sto32,e); + default: vpanic("widenSto32"); } } #endif @@ -766,8 +766,8 @@ static void setFlags_DEP1_DEP2_shift ( IROp op, IRTemp resUS, IRTemp guard ) { - vassert(guard); - + vassert(guard); + /* DEP1 contains the result, DEP2 contains the undershifted value. */ stmt( IRStmt_Put( OFFB_CC_OP, IRExpr_Mux0X( mkexpr(guard), @@ -795,9 +795,9 @@ static void setFlags_DEP1_DEP2_shift ( IROp op, static void setFlags_MUL ( IRTemp arg1, IRTemp arg2, UInt op ) { - stmt( IRStmt_Put( OFFB_CC_OP, mkU32(op) ) ); - stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto32(mkexpr(arg1)) )); - stmt( IRStmt_Put( OFFB_CC_DEP2, widenUto32(mkexpr(arg2)) )); + stmt( IRStmt_Put( OFFB_CC_OP, mkU32(op) ) ); + stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto32(mkexpr(arg1)) )); + stmt( IRStmt_Put( OFFB_CC_DEP2, widenUto32(mkexpr(arg2)) )); } #endif @@ -816,23 +816,23 @@ void setFlags_MUL ( IRTemp arg1, IRTemp arg2, UInt op ) static HChar* name_ARMCondcode ( ARMCondcode cond ) { switch (cond) { - case ARMCondEQ: return "{eq}"; - case ARMCondNE: return "{ne}"; - case ARMCondHS: return "{hs}"; // or 'cs' - case ARMCondLO: return "{lo}"; // or 'cc' - case ARMCondMI: return "{mi}"; - case ARMCondPL: return "{pl}"; - case ARMCondVS: return "{vs}"; - case ARMCondVC: return "{vc}"; - case ARMCondHI: return "{hi}"; - case ARMCondLS: return "{ls}"; - case ARMCondGE: return "{ge}"; - case ARMCondLT: return "{lt}"; - case ARMCondGT: return "{gt}"; - case ARMCondLE: return "{le}"; - case ARMCondAL: return ""; // {al}: default, doesn't need specifying - case ARMCondNV: return "{nv}"; - default: vpanic("name_ARMCondcode"); + case ARMCondEQ: return "{eq}"; + case ARMCondNE: return "{ne}"; + case ARMCondHS: return "{hs}"; // or 'cs' + case ARMCondLO: return "{lo}"; // or 'cc' + case ARMCondMI: return "{mi}"; + case ARMCondPL: return "{pl}"; + case ARMCondVS: return "{vs}"; + case ARMCondVC: return "{vc}"; + case ARMCondHI: return "{hi}"; + case ARMCondLS: return "{ls}"; + case ARMCondGE: return "{ge}"; + case ARMCondLT: return "{lt}"; + case ARMCondGT: return "{gt}"; + case ARMCondLE: return "{le}"; + case ARMCondAL: return ""; // {al}: default, doesn't need specifying + case ARMCondNV: return "{nv}"; + default: vpanic("name_ARMCondcode"); } } @@ -859,12 +859,12 @@ ARMCondcode positiveIse_ARMCondcode ( ARMCondcode cond, static HChar* name_ARMShiftOp ( UChar shift_op, UChar imm_val ) { switch (shift_op) { - case 0x0: case 0x1: case 0x8: return "lsl"; - case 0x2: case 0x3: case 0xA: return "lsr"; - case 0x4: case 0x5: case 0xC: return "asr"; - case 0x6: return (imm_val==0) ? "rrx" : "ror"; - case 0x7: case 0xE: return "ror"; - default: vpanic("name_ARMShiftcode"); + case 0x0: case 0x1: case 0x8: return "lsl"; + case 0x2: case 0x3: case 0xA: return "lsr"; + case 0x4: case 0x5: case 0xC: return "asr"; + case 0x6: return (imm_val==0) ? "rrx" : "ror"; + case 0x7: case 0xE: return "ror"; + default: vpanic("name_ARMShiftcode"); } } @@ -872,39 +872,39 @@ static HChar* name_ARMShiftOp ( UChar shift_op, UChar imm_val ) /* Addressing Mode 4 - Load/Store Multiple */ static HChar* name_ARMAddrMode4 ( UChar mode ) { - /* See ARM ARM A5-55 for alternative names for stack operations - ldmfa (full ascending), etc. */ + /* See ARM ARM A5-55 for alternative names for stack operations + ldmfa (full ascending), etc. */ switch (mode) { - case 0x0: return "da"; // Decrement after - case 0x1: return "ia"; // Increment after - case 0x2: return "db"; // Decrement before - case 0x3: return "ib"; // Increment before - default: vpanic("name_ARMAddrMode4"); + case 0x0: return "da"; // Decrement after + case 0x1: return "ia"; // Increment after + case 0x2: return "db"; // Decrement before + case 0x3: return "ib"; // Increment before + default: vpanic("name_ARMAddrMode4"); } } /* Data Processing ops */ static HChar* name_ARMDataProcOp ( UChar opc ) { - switch (opc) { - case 0x0: return "and"; - case 0x1: return "eor"; - case 0x2: return "sub"; - case 0x3: return "rsb"; - case 0x4: return "add"; - case 0x5: return "adc"; - case 0x6: return "sbc"; - case 0x7: return "rsc"; - case 0x8: return "tst"; - case 0x9: return "teq"; - case 0xA: return "cmp"; - case 0xB: return "cmn"; - case 0xC: return "orr"; - case 0xD: return "mov"; - case 0xE: return "bic"; - case 0xF: return "mvn"; - default: vpanic("name_ARMDataProcOp"); - } + switch (opc) { + case 0x0: return "and"; + case 0x1: return "eor"; + case 0x2: return "sub"; + case 0x3: return "rsb"; + case 0x4: return "add"; + case 0x5: return "adc"; + case 0x6: return "sbc"; + case 0x7: return "rsc"; + case 0x8: return "tst"; + case 0x9: return "teq"; + case 0xA: return "cmp"; + case 0xB: return "cmn"; + case 0xC: return "orr"; + case 0xD: return "mov"; + case 0xE: return "bic"; + case 0xF: return "mvn"; + default: vpanic("name_ARMDataProcOp"); + } } @@ -916,145 +916,145 @@ static HChar* name_ARMDataProcOp ( UChar opc ) static Bool dis_loadstore_mult ( UInt theInstr ) { - UChar flags = (theInstr >> 20) & 0x1F; // theInstr[24:20] - UChar Rn_addr = (theInstr >> 16) & 0xF; - IRTemp Rn = newTemp(Ity_I32); - IRTemp Rn_orig = newTemp(Ity_I32); - UInt reg_list = theInstr & 0xFFFF; // each bit addresses a register: R15 to R0 - - UChar L = (flags >> 0) & 1; // Load(1) | Store(0) - UChar W = (flags >> 1) & 1; // (W)riteback Rn (incr(U=1) | decr(U=0) by n_bytes) - UChar S = (flags >> 2) & 1; // Priviledged mode flag - *** CAB TODO *** - UChar U = (flags >> 3) & 1; // Txfr ctl: Direction = upwards(1) | downwards(0) - UChar PU = (flags >> 3) & 3; // Txfr ctl: Rn within(P=1) | outside(P=0) accessed mem - - IRTemp start_addr = newTemp(Ity_I32); - IRTemp end_addr = newTemp(Ity_I32); - IRTemp data=0; - UInt n_bytes=0; - UInt tmp_reg = reg_list; - UInt reg_idx, offset; - Bool decode_ok = True; - - HChar* cond_name = name_ARMCondcode( (theInstr >> 28) & 0xF ); - HChar reg_names[70]; - UInt buf_offset; - - while (tmp_reg > 0) { // Count num bits in reg_list => num_bytes - if (tmp_reg & 1) { n_bytes += 4; } - tmp_reg = tmp_reg >> 1; - } - - assign( Rn, getIReg(Rn_addr) ); - assign( Rn_orig, mkexpr(Rn) ); - - switch (PU) { // - case 0x0: // Decrement after (DA) - assign( start_addr, binop( Iop_Add32, mkexpr(Rn), mkU32(n_bytes + 4) ) ); - assign( end_addr, mkexpr(Rn) ); - break; - - case 0x1: // Increment after (IA) - assign( start_addr, mkexpr(Rn) ); - assign( end_addr, binop( Iop_Add32, mkexpr(Rn), mkU32(n_bytes - 4) ) ); - break; - - case 0x2: // Decrement before (DB) - assign( start_addr, binop( Iop_Sub32, mkexpr(Rn), mkU32(n_bytes) ) ); - assign( end_addr, binop( Iop_Sub32, mkexpr(Rn), mkU32(4) ) ); - break; - - case 0x3: // Increment before (IB) - assign( start_addr, binop( Iop_Add32, mkexpr(Rn), mkU32(4) ) ); - assign( end_addr, binop( Iop_Add32, mkexpr(Rn), mkU32(n_bytes) ) ); - break; - - default: - vex_printf("dis_loadstore_mult(ARM): No such case: 0x%x", PU); - return False; - } - - if (W==1) { - if (U==1) { // upwards - putIReg( Rn_addr, binop( Iop_Add32, mkexpr(Rn), mkU32(n_bytes) ) ); - } else { // downwards - putIReg( Rn_addr, binop( Iop_Sub32, mkexpr(Rn), mkU32(n_bytes) ) ); - } - } - - - /* - Loop through register list, LOAD/STORE indicated registers - Lowest numbered reg -> lowest address, so start with lowest register - reg_idx: guest register address - offset : current mem offset from start_addr - */ - reg_names[0] = '\0'; - buf_offset=0; - offset=0; - for (reg_idx=0; reg_idx < 16; reg_idx++) { - if (( reg_list >> reg_idx ) & 1) { // reg_list[i] == 1? - - if (L==1) { // LOAD Ri, (start_addr + offset) - - if (Rn_addr == reg_idx && W==1) { // Undefined - ARM ARM A4-31 - decode_ok=False; - break; - } - - assign( data, loadLE(Ity_I32, binop(Iop_Add32, - mkexpr(start_addr), - mkU32(offset))) ); - if (reg_idx == 15) { - // assuming architecture < 5: See ARM ARM A4-31 - putIReg( reg_idx, binop(Iop_And32, mkexpr(data), mkU32(0xFFFFFFFC)) ); - } else { - putIReg( reg_idx, mkexpr(data) ); - } - } else { // STORE Ri, (start_addr + offset) - - // ARM ARM A4-85 (Operand restrictions) - if (reg_idx == Rn_addr && W==1) { // Rn in reg_list && writeback - if (offset != 0) { // Undefined - See ARM ARM A4-85 - decode_ok=False; - break; - } - // is lowest reg in reg_list: store Rn_orig - storeLE( mkexpr(start_addr), mkexpr(Rn_orig) ); - } else { - storeLE( binop(Iop_Add32, mkexpr(start_addr), mkU32(offset) ), - getIReg(reg_idx) ); - } - } - offset += 4; - - reg_names[buf_offset++] = 'R'; - if (reg_idx > 9) { - reg_names[buf_offset++] = '1'; - reg_names[buf_offset++] = 38 + reg_idx; - } else { - reg_names[buf_offset++] = 48 + reg_idx; - } - reg_names[buf_offset++] = ','; - // CAB: Eugh! Where's strcpy?! - } - } - if (buf_offset > 0) { - reg_names[buf_offset-1] = '\0'; - } - DIP("%s%s%s R%d%s, {%s}%s\n", (L==1) ? "ldm":"stm", cond_name, - name_ARMAddrMode4( PU ), Rn_addr, (W==1) ? "!" : "", - reg_names, (S==1) ? "^" : ""); - - // CAB TODO: - // IR assert( end_addr == (start_addr + offset) - 8 ) - - if (offset == 0) { // Unpredictable - ARM ARM A5-21 - vex_printf("dis_loadstore_mult(arm): Unpredictable - offset==0\n"); - decode_ok = False; - } - - return decode_ok; + UChar flags = (theInstr >> 20) & 0x1F; // theInstr[24:20] + UChar Rn_addr = (theInstr >> 16) & 0xF; + IRTemp Rn = newTemp(Ity_I32); + IRTemp Rn_orig = newTemp(Ity_I32); + UInt reg_list = theInstr & 0xFFFF; // each bit addresses a register: R15 to R0 + + UChar L = (flags >> 0) & 1; // Load(1) | Store(0) + UChar W = (flags >> 1) & 1; // (W)riteback Rn (incr(U=1) | decr(U=0) by n_bytes) + UChar S = (flags >> 2) & 1; // Priviledged mode flag - *** CAB TODO *** + UChar U = (flags >> 3) & 1; // Txfr ctl: Direction = upwards(1) | downwards(0) + UChar PU = (flags >> 3) & 3; // Txfr ctl: Rn within(P=1) | outside(P=0) accessed mem + + IRTemp start_addr = newTemp(Ity_I32); + IRTemp end_addr = newTemp(Ity_I32); + IRTemp data=0; + UInt n_bytes=0; + UInt tmp_reg = reg_list; + UInt reg_idx, offset; + Bool decode_ok = True; + + HChar* cond_name = name_ARMCondcode( (theInstr >> 28) & 0xF ); + HChar reg_names[70]; + UInt buf_offset; + + while (tmp_reg > 0) { // Count num bits in reg_list => num_bytes + if (tmp_reg & 1) { n_bytes += 4; } + tmp_reg = tmp_reg >> 1; + } + + assign( Rn, getIReg(Rn_addr) ); + assign( Rn_orig, mkexpr(Rn) ); + + switch (PU) { // + case 0x0: // Decrement after (DA) + assign( start_addr, binop( Iop_Add32, mkexpr(Rn), mkU32(n_bytes + 4) ) ); + assign( end_addr, mkexpr(Rn) ); + break; + + case 0x1: // Increment after (IA) + assign( start_addr, mkexpr(Rn) ); + assign( end_addr, binop( Iop_Add32, mkexpr(Rn), mkU32(n_bytes - 4) ) ); + break; + + case 0x2: // Decrement before (DB) + assign( start_addr, binop( Iop_Sub32, mkexpr(Rn), mkU32(n_bytes) ) ); + assign( end_addr, binop( Iop_Sub32, mkexpr(Rn), mkU32(4) ) ); + break; + + case 0x3: // Increment before (IB) + assign( start_addr, binop( Iop_Add32, mkexpr(Rn), mkU32(4) ) ); + assign( end_addr, binop( Iop_Add32, mkexpr(Rn), mkU32(n_bytes) ) ); + break; + + default: + vex_printf("dis_loadstore_mult(ARM): No such case: 0x%x", PU); + return False; + } + + if (W==1) { + if (U==1) { // upwards + putIReg( Rn_addr, binop( Iop_Add32, mkexpr(Rn), mkU32(n_bytes) ) ); + } else { // downwards + putIReg( Rn_addr, binop( Iop_Sub32, mkexpr(Rn), mkU32(n_bytes) ) ); + } + } + + + /* + Loop through register list, LOAD/STORE indicated registers + Lowest numbered reg -> lowest address, so start with lowest register + reg_idx: guest register address + offset : current mem offset from start_addr + */ + reg_names[0] = '\0'; + buf_offset=0; + offset=0; + for (reg_idx=0; reg_idx < 16; reg_idx++) { + if (( reg_list >> reg_idx ) & 1) { // reg_list[i] == 1? + + if (L==1) { // LOAD Ri, (start_addr + offset) + + if (Rn_addr == reg_idx && W==1) { // Undefined - ARM ARM A4-31 + decode_ok=False; + break; + } + + assign( data, loadLE(Ity_I32, binop(Iop_Add32, + mkexpr(start_addr), + mkU32(offset))) ); + if (reg_idx == 15) { + // assuming architecture < 5: See ARM ARM A4-31 + putIReg( reg_idx, binop(Iop_And32, mkexpr(data), mkU32(0xFFFFFFFC)) ); + } else { + putIReg( reg_idx, mkexpr(data) ); + } + } else { // STORE Ri, (start_addr + offset) + + // ARM ARM A4-85 (Operand restrictions) + if (reg_idx == Rn_addr && W==1) { // Rn in reg_list && writeback + if (offset != 0) { // Undefined - See ARM ARM A4-85 + decode_ok=False; + break; + } + // is lowest reg in reg_list: store Rn_orig + storeLE( mkexpr(start_addr), mkexpr(Rn_orig) ); + } else { + storeLE( binop(Iop_Add32, mkexpr(start_addr), mkU32(offset) ), + getIReg(reg_idx) ); + } + } + offset += 4; + + reg_names[buf_offset++] = 'R'; + if (reg_idx > 9) { + reg_names[buf_offset++] = '1'; + reg_names[buf_offset++] = 38 + reg_idx; + } else { + reg_names[buf_offset++] = 48 + reg_idx; + } + reg_names[buf_offset++] = ','; + // CAB: Eugh! Where's strcpy?! + } + } + if (buf_offset > 0) { + reg_names[buf_offset-1] = '\0'; + } + DIP("%s%s%s R%d%s, {%s}%s\n", (L==1) ? "ldm":"stm", cond_name, + name_ARMAddrMode4( PU ), Rn_addr, (W==1) ? "!" : "", + reg_names, (S==1) ? "^" : ""); + + // CAB TODO: + // IR assert( end_addr == (start_addr + offset) - 8 ) + + if (offset == 0) { // Unpredictable - ARM ARM A5-21 + vex_printf("dis_loadstore_mult(arm): Unpredictable - offset==0\n"); + decode_ok = False; + } + + return decode_ok; } @@ -1064,160 +1064,160 @@ Bool dis_loadstore_mult ( UInt theInstr ) static Bool dis_loadstore_w_ub_address ( UInt theInstr, IRTemp* address, HChar* buf ) { - UChar is_reg = (theInstr >> 25) & 0x1; // immediate | register offset/index - UInt flags = (theInstr >> 20) & 0x3F; // theInstr[25:20] - UChar Rn_addr = (theInstr >> 16) & 0xF; - UChar Rm_addr = (theInstr >> 00) & 0xF; - UChar shift_op = (theInstr >> 04) & 0xFF; - UInt offset_12 = (theInstr >> 00) & 0xFFF; - IRTemp Rn = newTemp(Ity_I32); - IRTemp Rm = newTemp(Ity_I32); - UChar shift_imm, shift; - - UChar W = (flags >> 1) & 1; // base register writeback flag - See *Note - UChar U = (flags >> 3) & 1; // offset is added(1)|subtracted(0) from the base - UChar P = (flags >> 4) & 1; // addressing mode flag - See *Note - /* *Note - P==0: post-indexed addressing: addr -> Rn - W==0: normal mem access - W==1: unprivileged mem access - P==1: W==0: offset addressing: Rn not updated - ARM ARM A5-20 - W==1: pre-indexed addressing: addr -> Rn - */ - - IRTemp scaled_index = newTemp(Ity_I32); - IRTemp reg_offset = newTemp(Ity_I32); - - IRTemp oldFlagC = newTemp(Ity_I32); - - HChar buf2[30]; - HChar buf3[20]; - buf3[0] = '\0'; - - if (Rn_addr == 15) { - if (P==1 && W==0) { // offset addressing - // CAB: This right? - assign( Rn, binop(Iop_And32, getIReg(15), mkU32(8)) ); - } else { // Unpredictable - ARM ARM A5-25,29... - vex_printf("dis_loadstore_w_ub_address(arm): Unpredictable - Rn_addr==15\n"); - return False; - } - } else { - assign( Rn, getIReg(Rn_addr) ); - } - - /* - Retrieve / Calculate reg_offset - */ - if (is_reg) { - if (Rm_addr == 15) { // Unpredictable - ARM ARM A5-21 - vex_printf("dis_loadstore_w_ub_address(arm): Unpredictable - Rm_addr==15\n"); - return False; - } - if (P==0 || W==1) { // pre|post-indexed addressing - if (Rm_addr == Rn_addr) { // Unpredictable - ARM ARM A5-25 - vex_printf("dis_loadstore_w_ub_address(arm): Unpredictable - Rm_addr==Rn_addr\n"); - return False; - } - } - assign( Rm, getIReg(Rm_addr) ); - - if (shift_op == 0) { // Register addressing - assign( reg_offset, mkexpr(Rm) ); - } else { // Scaled Register addressing - shift_imm = (shift_op >> 3) & 0x1F; - shift = (shift_op >> 1) & 0x3; - - switch (shift) { - case 0x0: // LSL - assign( scaled_index, binop(Iop_Shl32, mkexpr(Rm), mkU8(shift_imm)) ); - break; - - case 0x1: // LSR - if (shift_imm) { - assign( scaled_index, binop(Iop_Shr32, mkexpr(Rm), mkU8(shift_imm)) ); - } else { - assign( scaled_index, mkU32(0) ); - } - break; - - case 0x2: // ASR - if (shift_imm) { - assign( scaled_index, binop(Iop_Sar32, mkexpr(Rm), mkU32(shift_imm)) ); - } else { - assign( scaled_index, // Rm[31] ? 0xFFFFFFFF : 0x0 - IRExpr_Mux0X(binop(Iop_And32, mkexpr(Rm), mkU32(0x8FFFFFFF)), - mkexpr(0x0), mkexpr(0xFFFFFFFF)) ); - } - break; - - case 0x3: // ROR|RRX - assign( oldFlagC, binop(Iop_Shr32, - mk_armg_calculate_flags_c(), - mkU8(ARMG_CC_SHIFT_C)) ); - - if (shift_imm == 0) { // RRX (ARM ARM A5-17) - // 33 bit ROR using carry flag as the 33rd bit - // op = Rm >> 1, carry flag replacing vacated bit position. - // scaled_index = (c_flag << 31) | (Rm >> 1) - assign( scaled_index, binop(Iop_Or32, - binop(Iop_Shl32, mkexpr(oldFlagC), mkU32(31)), - binop(Iop_Shr32, mkexpr(Rm), mkU8(1))) ); - - } else { // ROR - // scaled_index = Rm ROR shift_imm - // = (Rm >> shift_imm) | (Rm << (32-shift_imm)) - assign( scaled_index, - binop(Iop_Or32, - binop(Iop_Shr32, mkexpr(Rm), mkU8(shift_imm)), - binop(Iop_Shl32, mkexpr(Rm), - binop(Iop_Sub8, mkU8(32), mkU32(shift_imm)))) ); - } - break; - - default: - vex_printf("dis_loadstore_w_ub(ARM): No such case: 0x%x", shift); - return False; - } - assign( reg_offset, mkexpr(scaled_index) ); - - if (shift == 0x3 && shift_imm == 0) { - DIS(buf3, ", %s", name_ARMShiftOp(shift_op * 2, shift_imm)); - } else { - DIS(buf3, ", %s #%d", name_ARMShiftOp(shift_op * 2, shift_imm), shift_imm); - } - } - DIS(buf2, "%cR%d%s", (U==1) ? '+' : '-', Rm_addr, buf3); - } else { // immediate - assign( reg_offset, mkU32(offset_12) ); - - DIS(buf2, "#%c%d", (U==1) ? '+' : '-', offset_12); - } - DIS(buf, "[R%d%s, %s%s", Rn_addr, - (P==0) ? "]" : "", buf2, - (P==1) ? ((W==1) ? "]!" : "]") : ""); - - /* - Depending on P,U,W, write to Rn and set address to load/store - */ - if (P==1) { // offset | pre-indexed addressing - if (U == 1) { // - increment - assign( *address, binop(Iop_Add32, mkexpr(Rn), mkexpr(reg_offset)) ); - } else { // - decrement - assign( *address, binop(Iop_Sub32, mkexpr(Rn), mkexpr(reg_offset)) ); - } - if (W == 1) { // pre-indexed addressing, base register writeback - putIReg( Rn_addr, mkexpr(*address) ); - } - } else { // post-indexed addressing - assign( *address, mkexpr(Rn) ); - if (U == 1) { // - increment - putIReg( Rn_addr, binop( Iop_Add32, mkexpr(Rn), mkexpr(reg_offset) ) ); - } else { // - decrement - putIReg( Rn_addr, binop( Iop_Sub32, mkexpr(Rn), mkexpr(reg_offset) ) ); - } - } - return True; + UChar is_reg = (theInstr >> 25) & 0x1; // immediate | register offset/index + UInt flags = (theInstr >> 20) & 0x3F; // theInstr[25:20] + UChar Rn_addr = (theInstr >> 16) & 0xF; + UChar Rm_addr = (theInstr >> 00) & 0xF; + UChar shift_op = (theInstr >> 04) & 0xFF; + UInt offset_12 = (theInstr >> 00) & 0xFFF; + IRTemp Rn = newTemp(Ity_I32); + IRTemp Rm = newTemp(Ity_I32); + UChar shift_imm, shift; + + UChar W = (flags >> 1) & 1; // base register writeback flag - See *Note + UChar U = (flags >> 3) & 1; // offset is added(1)|subtracted(0) from the base + UChar P = (flags >> 4) & 1; // addressing mode flag - See *Note + /* *Note + P==0: post-indexed addressing: addr -> Rn + W==0: normal mem access + W==1: unprivileged mem access + P==1: W==0: offset addressing: Rn not updated - ARM ARM A5-20 + W==1: pre-indexed addressing: addr -> Rn + */ + + IRTemp scaled_index = newTemp(Ity_I32); + IRTemp reg_offset = newTemp(Ity_I32); + + IRTemp oldFlagC = newTemp(Ity_I32); + + HChar buf2[30]; + HChar buf3[20]; + buf3[0] = '\0'; + + if (Rn_addr == 15) { + if (P==1 && W==0) { // offset addressing + // CAB: This right? + assign( Rn, binop(Iop_And32, getIReg(15), mkU32(8)) ); + } else { // Unpredictable - ARM ARM A5-25,29... + vex_printf("dis_loadstore_w_ub_address(arm): Unpredictable - Rn_addr==15\n"); + return False; + } + } else { + assign( Rn, getIReg(Rn_addr) ); + } + + /* + Retrieve / Calculate reg_offset + */ + if (is_reg) { + if (Rm_addr == 15) { // Unpredictable - ARM ARM A5-21 + vex_printf("dis_loadstore_w_ub_address(arm): Unpredictable - Rm_addr==15\n"); + return False; + } + if (P==0 || W==1) { // pre|post-indexed addressing + if (Rm_addr == Rn_addr) { // Unpredictable - ARM ARM A5-25 + vex_printf("dis_loadstore_w_ub_address(arm): Unpredictable - Rm_addr==Rn_addr\n"); + return False; + } + } + assign( Rm, getIReg(Rm_addr) ); + + if (shift_op == 0) { // Register addressing + assign( reg_offset, mkexpr(Rm) ); + } else { // Scaled Register addressing + shift_imm = (shift_op >> 3) & 0x1F; + shift = (shift_op >> 1) & 0x3; + + switch (shift) { + case 0x0: // LSL + assign( scaled_index, binop(Iop_Shl32, mkexpr(Rm), mkU8(shift_imm)) ); + break; + + case 0x1: // LSR + if (shift_imm) { + assign( scaled_index, binop(Iop_Shr32, mkexpr(Rm), mkU8(shift_imm)) ); + } else { + assign( scaled_index, mkU32(0) ); + } + break; + + case 0x2: // ASR + if (shift_imm) { + assign( scaled_index, binop(Iop_Sar32, mkexpr(Rm), mkU32(shift_imm)) ); + } else { + assign( scaled_index, // Rm[31] ? 0xFFFFFFFF : 0x0 + IRExpr_Mux0X(binop(Iop_And32, mkexpr(Rm), mkU32(0x8FFFFFFF)), + mkexpr(0x0), mkexpr(0xFFFFFFFF)) ); + } + break; + + case 0x3: // ROR|RRX + assign( oldFlagC, binop(Iop_Shr32, + mk_armg_calculate_flags_c(), + mkU8(ARMG_CC_SHIFT_C)) ); + + if (shift_imm == 0) { // RRX (ARM ARM A5-17) + // 33 bit ROR using carry flag as the 33rd bit + // op = Rm >> 1, carry flag replacing vacated bit position. + // scaled_index = (c_flag << 31) | (Rm >> 1) + assign( scaled_index, binop(Iop_Or32, + binop(Iop_Shl32, mkexpr(oldFlagC), mkU32(31)), + binop(Iop_Shr32, mkexpr(Rm), mkU8(1))) ); + + } else { // ROR + // scaled_index = Rm ROR shift_imm + // = (Rm >> shift_imm) | (Rm << (32-shift_imm)) + assign( scaled_index, + binop(Iop_Or32, + binop(Iop_Shr32, mkexpr(Rm), mkU8(shift_imm)), + binop(Iop_Shl32, mkexpr(Rm), + binop(Iop_Sub8, mkU8(32), mkU32(shift_imm)))) ); + } + break; + + default: + vex_printf("dis_loadstore_w_ub(ARM): No such case: 0x%x", shift); + return False; + } + assign( reg_offset, mkexpr(scaled_index) ); + + if (shift == 0x3 && shift_imm == 0) { + DIS(buf3, ", %s", name_ARMShiftOp(shift_op * 2, shift_imm)); + } else { + DIS(buf3, ", %s #%d", name_ARMShiftOp(shift_op * 2, shift_imm), shift_imm); + } + } + DIS(buf2, "%cR%d%s", (U==1) ? '+' : '-', Rm_addr, buf3); + } else { // immediate + assign( reg_offset, mkU32(offset_12) ); + + DIS(buf2, "#%c%d", (U==1) ? '+' : '-', offset_12); + } + DIS(buf, "[R%d%s, %s%s", Rn_addr, + (P==0) ? "]" : "", buf2, + (P==1) ? ((W==1) ? "]!" : "]") : ""); + + /* + Depending on P,U,W, write to Rn and set address to load/store + */ + if (P==1) { // offset | pre-indexed addressing + if (U == 1) { // - increment + assign( *address, binop(Iop_Add32, mkexpr(Rn), mkexpr(reg_offset)) ); + } else { // - decrement + assign( *address, binop(Iop_Sub32, mkexpr(Rn), mkexpr(reg_offset)) ); + } + if (W == 1) { // pre-indexed addressing, base register writeback + putIReg( Rn_addr, mkexpr(*address) ); + } + } else { // post-indexed addressing + assign( *address, mkexpr(Rn) ); + if (U == 1) { // - increment + putIReg( Rn_addr, binop( Iop_Add32, mkexpr(Rn), mkexpr(reg_offset) ) ); + } else { // - decrement + putIReg( Rn_addr, binop( Iop_Sub32, mkexpr(Rn), mkexpr(reg_offset) ) ); + } + } + return True; } @@ -1230,124 +1230,127 @@ Bool dis_loadstore_w_ub_address ( UInt theInstr, IRTemp* address, HChar* buf ) static Bool dis_loadstore_w_ub ( UInt theInstr ) { - UInt flags = (theInstr >> 20) & 0x3F; // theInstr[25:20] - UChar Rn_addr = (theInstr >> 16) & 0xF; - UChar Rd_addr = (theInstr >> 12) & 0xF; - IRTemp address = newTemp(Ity_I32); - - UChar L = (flags >> 0) & 1; // Load(1) | Store(0) - UChar W = (flags >> 1) & 1; // base register writeback - UChar B = (flags >> 2) & 1; // access = unsigned byte(1) | word(0) - - IRTemp value = newTemp(Ity_I32); - IRTemp data = newTemp(Ity_I32); - IRTemp data_ror8 = newTemp(Ity_I32); - IRTemp data_ror16 = newTemp(Ity_I32); - IRTemp data_ror24 = newTemp(Ity_I32); - IRExpr* expr_addr_10; - HChar* cond_name = name_ARMCondcode( (theInstr >> 28) & 0xF ); - HChar dis_buf[50]; - - - vassert(((theInstr >> 26) & 0x3) == 0x1); - - // Get the address to load/store - if (!dis_loadstore_w_ub_address(theInstr, &address, dis_buf)) { return False; } - - DIP("%s%s%s R%d, %s\n", (L==1) ? "ldr" : "str", cond_name, - (B==1) ? "b" : "", Rd_addr, dis_buf); - - if (Rd_addr == Rn_addr && W==1) { // Unpredictable - ARM ARM A4-39,41,89,91 - vex_printf("dis_loadstore_w_ub(arm): Unpredictable - Rd_addr==Rn_addr\n"); - return False; - } - - /* - LOAD/STORE Rd, address - */ - if (L==1) { // LOAD - if (B==1) { // unsigned byte (LDRB): ARM ARM A4-40 - if (Rd_addr == 15) { // Unpredictable - ARM ARM A4-40 - vex_printf("dis_loadstore_w_ub(arm): Unpredictable - Rd_addr==15\n"); - return False; - } - putIReg( Rd_addr, loadLE( Ity_I8, mkexpr( address ) ) ); - } - else { // word (LDR): ARM ARM A4-38 - expr_addr_10 = binop(Iop_And32, mkexpr(address), mkU32(0x3)); - - /* - CAB TODO - if (Rd_addr == 15 && address[1:0] == 0) => Unpredictable - How to bomb out using IR? - */ - - /* LOAD memory data (4 bytes) */ - assign( data, loadLE( Ity_I32, mkexpr( address ) ) ); - - // data ROR 8 - assign( data_ror8, binop(Iop_Sub8, mkU8(32), mkU32(8)) ); - assign( data_ror8, binop( Iop_Or32, - binop( Iop_Shr32, mkexpr(data), mkU8(8) ), - binop( Iop_Shl32, mkexpr(data), mkexpr(data_ror8) ) ) ); - // data ROR 16 - assign( data_ror16, binop(Iop_Sub8, mkU8(32), mkU32(16)) ); - assign( data_ror16, binop( Iop_Or32, - binop( Iop_Shr32, mkexpr(data), mkU8(16) ), - binop( Iop_Shl32, mkexpr(data), mkexpr(data_ror16) ) ) ); - - // data ROR 24 - assign( data_ror24, binop(Iop_Sub8, mkU8(32), mkU32(24)) ); - assign( data_ror24, binop( Iop_Or32, - binop( Iop_Shr32, mkexpr(data), mkU8(24) ), - binop( Iop_Shl32, mkexpr(data), mkexpr(data_ror24) ) ) ); - - /* switch (address[1:0]) { - 0x0: value = data; - 0x1: value = data ROR 8; - 0x2: value = data ROR 16; - 0x3: value = data ROR 24; } */ - assign( value, IRExpr_Mux0X( - binop(Iop_CmpEQ32, expr_addr_10, mkU32(0x0)), - IRExpr_Mux0X( - binop(Iop_CmpEQ32, expr_addr_10, mkU32(0x1)), - IRExpr_Mux0X( - binop(Iop_CmpEQ32, expr_addr_10, mkU32(0x2)), - mkexpr(data_ror24), - mkexpr(data_ror16) ), - mkexpr(data_ror8) ), - mkexpr(data) ) ); - - if (Rd_addr == 15) { - // assuming architecture < 5: See ARM ARM A4-28 - putIReg( Rd_addr, binop(Iop_And32, mkexpr(value), mkU32(0xFFFFFFFC)) ); - - // CAB: Need to tell vex we're doing a jump here? - // irbb->jumpkind = Ijk_Boring; - // irbb->next = mkexpr(value); - } else { - putIReg( Rd_addr, mkexpr(value) ); - } - - } - } else { // STORE: ARM ARM A4-88 - if (B==1) { // unsigned byte - if (Rd_addr == 15) { // Unpredictable - ARM ARM A4-90 - vex_printf("dis_loadstore_w_ub(arm): Unpredictable - Rd_addr==15\n"); - return False; - } - storeLE( mkexpr(address), unop(Iop_32to8, getIReg(Rd_addr)) ); // Rd[7:0] - } else { // word - - if (Rd_addr == 15) { // Implementation Defined - ARM ARM A4-88 - vex_printf("dis_loadstore_w_ub(arm): Implementation Defined - Rd_addr==15\n"); - return False; - // CAB TODO: What to do here? - } - storeLE( mkexpr(address), getIReg(Rd_addr) ); - } - } - return True; + UInt flags = (theInstr >> 20) & 0x3F; // theInstr[25:20] + UChar Rn_addr = (theInstr >> 16) & 0xF; + UChar Rd_addr = (theInstr >> 12) & 0xF; + IRTemp address = newTemp(Ity_I32); + + UChar L = (flags >> 0) & 1; // Load(1) | Store(0) + UChar W = (flags >> 1) & 1; // base register writeback + UChar B = (flags >> 2) & 1; // access = unsigned byte(1) | word(0) + + IRTemp value = newTemp(Ity_I32); + IRTemp data = newTemp(Ity_I32); + IRTemp data_ror8 = newTemp(Ity_I32); + IRTemp data_ror16 = newTemp(Ity_I32); + IRTemp data_ror24 = newTemp(Ity_I32); + IRExpr* expr_addr_10; + HChar* cond_name = name_ARMCondcode( (theInstr >> 28) & 0xF ); + HChar dis_buf[50]; + + + vassert(((theInstr >> 26) & 0x3) == 0x1); + + // Get the address to load/store + if (!dis_loadstore_w_ub_address(theInstr, &address, dis_buf)) { return False; } + + DIP("%s%s%s R%d, %s\n", (L==1) ? "ldr" : "str", cond_name, + (B==1) ? "b" : "", Rd_addr, dis_buf); + + if (Rd_addr == Rn_addr && W==1) { // Unpredictable - ARM ARM A4-39,41,89,91 + vex_printf("dis_loadstore_w_ub(arm): Unpredictable - Rd_addr==Rn_addr\n"); + return False; + } + + /* + LOAD/STORE Rd, address + */ + if (L==1) { // LOAD + if (B==1) { // unsigned byte (LDRB): ARM ARM A4-40 + if (Rd_addr == 15) { // Unpredictable - ARM ARM A4-40 + vex_printf("dis_loadstore_w_ub(arm): Unpredictable - Rd_addr==15\n"); + return False; + } + putIReg( Rd_addr, loadLE( Ity_I8, mkexpr( address ) ) ); + } + else { // word (LDR): ARM ARM A4-38 + expr_addr_10 = binop(Iop_And32, mkexpr(address), mkU32(0x3)); + + /* + CAB TODO + if (Rd_addr == 15 && address[1:0] == 0) => Unpredictable + How to bomb out using IR? + */ + + /* LOAD memory data (4 bytes) */ + assign( data, loadLE( Ity_I32, mkexpr( address ) ) ); + + // data ROR 8 + assign( data_ror8, binop(Iop_Sub8, mkU8(32), mkU32(8)) ); + assign( data_ror8, + binop( Iop_Or32, + binop( Iop_Shr32, mkexpr(data), mkU8(8) ), + binop( Iop_Shl32, mkexpr(data), mkexpr(data_ror8) ))); + // data ROR 16 + assign( data_ror16, binop(Iop_Sub8, mkU8(32), mkU32(16)) ); + assign( data_ror16, + binop( Iop_Or32, + binop( Iop_Shr32, mkexpr(data), mkU8(16) ), + binop( Iop_Shl32, mkexpr(data), mkexpr(data_ror16) ))); + + // data ROR 24 + assign( data_ror24, binop(Iop_Sub8, mkU8(32), mkU32(24)) ); + assign( data_ror24, + binop( Iop_Or32, + binop( Iop_Shr32, mkexpr(data), mkU8(24) ), + binop( Iop_Shl32, mkexpr(data), mkexpr(data_ror24) ))); + + /* switch (address[1:0]) { + 0x0: value = data; + 0x1: value = data ROR 8; + 0x2: value = data ROR 16; + 0x3: value = data ROR 24; } */ + assign( value, IRExpr_Mux0X( + binop(Iop_CmpEQ32, expr_addr_10, mkU32(0x0)), + IRExpr_Mux0X( + binop(Iop_CmpEQ32, expr_addr_10, mkU32(0x1)), + IRExpr_Mux0X( + binop(Iop_CmpEQ32, expr_addr_10, mkU32(0x2)), + mkexpr(data_ror24), + mkexpr(data_ror16) ), + mkexpr(data_ror8) ), + mkexpr(data) ) ); + + if (Rd_addr == 15) { + // assuming architecture < 5: See ARM ARM A4-28 + putIReg( Rd_addr, binop(Iop_And32, mkexpr(value), mkU32(0xFFFFFFFC)) ); + + // CAB: Need to tell vex we're doing a jump here? + // irbb->jumpkind = Ijk_Boring; + // irbb->next = mkexpr(value); + } else { + putIReg( Rd_addr, mkexpr(value) ); + } + + } + } else { // STORE: ARM ARM A4-88 + if (B==1) { // unsigned byte + if (Rd_addr == 15) { // Unpredictable - ARM ARM A4-90 + vex_printf("dis_loadstore_w_ub(arm): Unpredictable - Rd_addr==15\n"); + return False; + } + storeLE( mkexpr(address), unop(Iop_32to8, getIReg(Rd_addr)) ); // Rd[7:0] + } else { // word + + if (Rd_addr == 15) { // Implementation Defined - ARM ARM A4-88 + vex_printf("dis_loadstore_w_ub(arm): Implementation Defined - Rd_addr==15\n"); + return False; + // CAB TODO: What to do here? + } + storeLE( mkexpr(address), getIReg(Rd_addr) ); + } + } + return True; } @@ -1364,143 +1367,143 @@ Bool dis_loadstore_w_ub ( UInt theInstr ) static IRExpr* dis_shift( Bool* decode_ok, UInt theInstr, IRTemp* carry_out, HChar* buf ) { - UChar Rn_addr = (theInstr >> 16) & 0xF; - UChar Rd_addr = (theInstr >> 12) & 0xF; - UChar Rs_addr = (theInstr >> 8) & 0xF; - UChar Rm_addr = (theInstr >> 0) & 0xF; - UChar by_reg = (theInstr >> 4) & 0x1; // instr[4] - UChar shift_imm = (theInstr >> 7) & 0x1F; // instr[11:7] - UChar shift_op = (theInstr >> 4) & 0xF; // instr[7:4] - IRTemp Rm = newTemp(Ity_I32); - IRTemp Rs = newTemp(Ity_I32); - IRTemp shift_amt = newTemp(Ity_I8); - IRTemp carry_shift = newTemp(Ity_I8); - IRTemp oldFlagC = newTemp(Ity_I32); - IRTemp mux_false = newTemp(Ity_I32); - IRExpr* expr; - IROp op; - - assign( oldFlagC, binop(Iop_Shr32, - mk_armg_calculate_flags_c(), - mkU8(ARMG_CC_SHIFT_C)) ); - - switch (shift_op) { - case 0x0: case 0x8: case 0x1: op = Iop_Shl32; break; - case 0x2: case 0xA: case 0x3: op = Iop_Shr32; break; - case 0x4: case 0xC: case 0x5: op = Iop_Sar32; break; - default: - vex_printf("dis_shift(arm): No such case: 0x%x\n", shift_op); - *decode_ok = False; - return mkU32(0); - } - - - if (by_reg) { // Register Shift - assign( Rm, getIReg(Rm_addr) ); - - if (Rd_addr == 15 || Rm_addr == 15 || - Rn_addr == 15 || Rs_addr == 15) { // Unpredictable (ARM ARM A5-10) - vex_printf("dis_shift(arm): Unpredictable - Rd|Rm|Rn|Rs == R15\n"); - *decode_ok = False; - return mkU32(0); - } - - assign( Rs, getIReg((theInstr >> 8) & 0xF) ); // instr[11:8] - - // shift_amt = shift_expr & 31 => Rs[5:0] - assign( shift_amt, - narrowTo(Ity_I8, binop( Iop_And32, mkexpr(Rs), mkU32(0x1F)) ) ); - - // CAB TODO: support for >31 shift ? (Rs[7:0]) - - switch (shift_op) { - case 0x1: // LSL(reg) - assign( mux_false, mkU32(0) ); - assign( carry_shift, binop(Iop_Add8, mkU8(32), mkexpr(shift_amt)) ); - break; - - case 0x3: // LSR(reg) - assign( mux_false, mkU32(0) ); - assign( carry_shift, binop(Iop_Sub8, mkexpr(shift_amt), mkU8(1)) ); - break; - - case 0x5: // ASR(reg) - // Rs[31] == 0 ? 0x0 : 0xFFFFFFFF - assign( mux_false, - IRExpr_Mux0X( - binop(Iop_CmpLT32U, mkexpr(Rs), mkU32(0x80000000)), - mkU32(0xFFFFFFFF), mkU32(0) ) ); - assign( carry_shift, - binop(Iop_Sub8, mkexpr(shift_amt), mkU8(1)) ); - break; - - default: - vex_printf("dis_shift(arm): Reg shift: No such case: 0x%x\n", shift_op); - *decode_ok = False; - return mkU32(0); - } - - expr = IRExpr_Mux0X( - binop(Iop_CmpLT32U, widenUto32(mkexpr(shift_amt)), mkU32(32)), - mkexpr(mux_false), - binop(op, mkexpr(Rm), mkexpr(shift_amt)) ); - - // shift_amt == 0 ? old_flag_c : Rm >> x - assign( *carry_out, - IRExpr_Mux0X( - binop(Iop_CmpEQ8, mkexpr(shift_amt), mkU8(0)), - binop(Iop_Shr32, mkexpr(Rm), mkexpr(carry_shift)), - mkexpr(oldFlagC) ) ); - - DIS(buf, "R%d, %s R%d", Rm_addr, name_ARMShiftOp(shift_op, 0), Rs_addr); - } - else { // Immediate shift - - // CAB: This right? - // "the value used is the address of the current intruction plus 8" - if (Rm_addr == 15 || Rn_addr == 15) { // ARM ARM A5-9 - assign( Rm, binop(Iop_Add32, getIReg(15), mkU32(8)) ); - } else { - assign( Rm, getIReg(Rm_addr) ); - } - - if (shift_imm == 0) { - switch (shift_op) { - case 0x0: case 0x8: // LSL(imm) - expr = mkexpr(Rm); - assign( *carry_out, mkexpr(oldFlagC) ); - break; - - case 0x2: case 0xA: // LSR(imm) - expr = mkexpr(0); - // Rm >> 31: carry = R[0] - assign( *carry_out, binop(Iop_Shr32, mkexpr(Rm), mkU8(31)) ); - break; - - case 0x4: case 0xC: // ASR(imm) - // Rs[31] == 0 ? 0x0 : 0xFFFFFFFF - expr = IRExpr_Mux0X( - binop(Iop_CmpLT32U, mkexpr(Rs), mkU32(0x80000000)), - mkU32(0xFFFFFFFF), mkU32(0) ); - // Rm >> 31: carry = R[0] - assign( *carry_out, binop(Iop_Shr32, mkexpr(Rm), mkU8(31)) ); - break; - - default: - vex_printf("dis_shift(arm): Imm shift: No such case: 0x%x\n", shift_op); - *decode_ok = False; - return mkU32(0); - } - DIS(buf, "R%d", Rm_addr); - } else { - expr = binop(op, mkexpr(Rm), mkU8(shift_imm)); - assign( *carry_out, binop(op, mkexpr(Rm), - binop(Iop_Sub32, mkU32(shift_imm), mkU32(1)) ) ); - - DIS(buf, "R%d, %s #%d", Rm_addr, name_ARMShiftOp(shift_op, 0), shift_imm); - } - } - return expr; + UChar Rn_addr = (theInstr >> 16) & 0xF; + UChar Rd_addr = (theInstr >> 12) & 0xF; + UChar Rs_addr = (theInstr >> 8) & 0xF; + UChar Rm_addr = (theInstr >> 0) & 0xF; + UChar by_reg = (theInstr >> 4) & 0x1; // instr[4] + UChar shift_imm = (theInstr >> 7) & 0x1F; // instr[11:7] + UChar shift_op = (theInstr >> 4) & 0xF; // instr[7:4] + IRTemp Rm = newTemp(Ity_I32); + IRTemp Rs = newTemp(Ity_I32); + IRTemp shift_amt = newTemp(Ity_I8); + IRTemp carry_shift = newTemp(Ity_I8); + IRTemp oldFlagC = newTemp(Ity_I32); + IRTemp mux_false = newTemp(Ity_I32); + IRExpr* expr; + IROp op; + + assign( oldFlagC, binop(Iop_Shr32, + mk_armg_calculate_flags_c(), + mkU8(ARMG_CC_SHIFT_C)) ); + + switch (shift_op) { + case 0x0: case 0x8: case 0x1: op = Iop_Shl32; break; + case 0x2: case 0xA: case 0x3: op = Iop_Shr32; break; + case 0x4: case 0xC: case 0x5: op = Iop_Sar32; break; + default: + vex_printf("dis_shift(arm): No such case: 0x%x\n", shift_op); + *decode_ok = False; + return mkU32(0); + } + + + if (by_reg) { // Register Shift + assign( Rm, getIReg(Rm_addr) ); + + if (Rd_addr == 15 || Rm_addr == 15 || + Rn_addr == 15 || Rs_addr == 15) { // Unpredictable (ARM ARM A5-10) + vex_printf("dis_shift(arm): Unpredictable - Rd|Rm|Rn|Rs == R15\n"); + *decode_ok = False; + return mkU32(0); + } + + assign( Rs, getIReg((theInstr >> 8) & 0xF) ); // instr[11:8] + + // shift_amt = shift_expr & 31 => Rs[5:0] + assign( shift_amt, + narrowTo(Ity_I8, binop( Iop_And32, mkexpr(Rs), mkU32(0x1F)) ) ); + + // CAB TODO: support for >31 shift ? (Rs[7:0]) + + switch (shift_op) { + case 0x1: // LSL(reg) + assign( mux_false, mkU32(0) ); + assign( carry_shift, binop(Iop_Add8, mkU8(32), mkexpr(shift_amt)) ); + break; + + case 0x3: // LSR(reg) + assign( mux_false, mkU32(0) ); + assign( carry_shift, binop(Iop_Sub8, mkexpr(shift_amt), mkU8(1)) ); + break; + + case 0x5: // ASR(reg) + // Rs[31] == 0 ? 0x0 : 0xFFFFFFFF + assign( mux_false, + IRExpr_Mux0X( + binop(Iop_CmpLT32U, mkexpr(Rs), mkU32(0x80000000)), + mkU32(0xFFFFFFFF), mkU32(0) ) ); + assign( carry_shift, + binop(Iop_Sub8, mkexpr(shift_amt), mkU8(1)) ); + break; + + default: + vex_printf("dis_shift(arm): Reg shift: No such case: 0x%x\n", shift_op); + *decode_ok = False; + return mkU32(0); + } + + expr = IRExpr_Mux0X( + binop(Iop_CmpLT32U, widenUto32(mkexpr(shift_amt)), mkU32(32)), + mkexpr(mux_false), + binop(op, mkexpr(Rm), mkexpr(shift_amt)) ); + + // shift_amt == 0 ? old_flag_c : Rm >> x + assign( *carry_out, + IRExpr_Mux0X( + binop(Iop_CmpEQ8, mkexpr(shift_amt), mkU8(0)), + binop(Iop_Shr32, mkexpr(Rm), mkexpr(carry_shift)), + mkexpr(oldFlagC) ) ); + + DIS(buf, "R%d, %s R%d", Rm_addr, name_ARMShiftOp(shift_op, 0), Rs_addr); + } + else { // Immediate shift + + // CAB: This right? + // "the value used is the address of the current intruction plus 8" + if (Rm_addr == 15 || Rn_addr == 15) { // ARM ARM A5-9 + assign( Rm, binop(Iop_Add32, getIReg(15), mkU32(8)) ); + } else { + assign( Rm, getIReg(Rm_addr) ); + } + + if (shift_imm == 0) { + switch (shift_op) { + case 0x0: case 0x8: // LSL(imm) + expr = mkexpr(Rm); + assign( *carry_out, mkexpr(oldFlagC) ); + break; + + case 0x2: case 0xA: // LSR(imm) + expr = mkexpr(0); + // Rm >> 31: carry = R[0] + assign( *carry_out, binop(Iop_Shr32, mkexpr(Rm), mkU8(31)) ); + break; + + case 0x4: case 0xC: // ASR(imm) + // Rs[31] == 0 ? 0x0 : 0xFFFFFFFF + expr = IRExpr_Mux0X( + binop(Iop_CmpLT32U, mkexpr(Rs), mkU32(0x80000000)), + mkU32(0xFFFFFFFF), mkU32(0) ); + // Rm >> 31: carry = R[0] + assign( *carry_out, binop(Iop_Shr32, mkexpr(Rm), mkU8(31)) ); + break; + + default: + vex_printf("dis_shift(arm): Imm shift: No such case: 0x%x\n", shift_op); + *decode_ok = False; + return mkU32(0); + } + DIS(buf, "R%d", Rm_addr); + } else { + expr = binop(op, mkexpr(Rm), mkU8(shift_imm)); + assign( *carry_out, binop(op, mkexpr(Rm), + binop(Iop_Sub32, mkU32(shift_imm), mkU32(1)) ) ); + + DIS(buf, "R%d, %s #%d", Rm_addr, name_ARMShiftOp(shift_op, 0), shift_imm); + } + } + return expr; } @@ -1513,93 +1516,93 @@ IRExpr* dis_shift( Bool* decode_ok, UInt theInstr, IRTemp* carry_out, HChar* buf static IRExpr* dis_rotate ( Bool* decode_ok, UInt theInstr, IRTemp* carry_out, HChar* buf ) { - UChar Rn_addr = (theInstr >> 16) & 0xF; - UChar Rd_addr = (theInstr >> 12) & 0xF; - UChar Rs_addr = (theInstr >> 8) & 0xF; - UChar Rm_addr = (theInstr >> 0) & 0xF; - UChar by_reg = (theInstr >> 4) & 0x1; // instr[4] - UInt rot_imm = (theInstr >> 7) & 0x1F; // instr[11:7] - IRTemp Rm = newTemp(Ity_I32); - IRTemp Rs = newTemp(Ity_I32); - IRTemp rot_amt = newTemp(Ity_I8); // Rs[7:0] - IRTemp oldFlagC = newTemp(Ity_I32); - IRExpr* expr=0; - - assign( oldFlagC, binop(Iop_Shr32, - mk_armg_calculate_flags_c(), - mkU8(ARMG_CC_SHIFT_C)) ); - - if (by_reg) { // Register rotate - assign( Rm, getIReg(Rm_addr) ); - - if (Rd_addr == 15 || Rm_addr == 15 || - Rn_addr == 15 || Rs_addr == 15) { // Unpredictable (ARM ARM A5-10) - vex_printf("dis_rotate(arm): Unpredictable - Rd|Rm|Rn|Rs == R15\n"); - *decode_ok = False; - return mkU32(0); - } - - assign( Rs, getIReg((theInstr >> 8) & 0xF) ); // instr[11:8] - // Rs[4:0] - assign( rot_amt, narrowTo(Ity_I8, - binop(Iop_And32, mkexpr(Rs), mkU32(0x1F))) ); - - // CAB: This right? - // Rs[7:0] == 0 ? oldFlagC : (Rs[4:0] == 0 ? Rm >> 31 : Rm >> rot-1 ) - assign( *carry_out, - IRExpr_Mux0X( - binop(Iop_CmpNE32, mkU32(0), - binop(Iop_And32, mkexpr(Rs), mkU32(0xFF))), - mkexpr(oldFlagC), - IRExpr_Mux0X( - binop(Iop_CmpEQ8, mkexpr(rot_amt), mkU8(0)), - binop(Iop_Shr32, mkexpr(Rm), - binop(Iop_Sub8, mkexpr(rot_amt), mkU8(1))), - binop(Iop_Shr32, mkexpr(Rm), - binop(Iop_Shr32, mkexpr(Rm), mkU8(31))) ) ) ); - - - /* expr = (dst0 >> rot_amt) | (dst0 << (wordsize-rot_amt)) */ - expr = binop(Iop_Or32, - binop(Iop_Shr32, mkexpr(Rm), mkexpr(rot_amt)), - binop(Iop_Shl32, mkexpr(Rm), - binop(Iop_Sub8, mkU8(32), mkexpr(rot_amt)))); - - DIS(buf, "R%d, ror R%d", Rm_addr, Rs_addr); - } - else { // Immediate rotate - - // CAB: This right? - // "the value used is the address of the current intruction plus 8" - if (Rm_addr == 15 || Rn_addr == 15) { // ARM ARM A5-9 - assign( Rm, binop(Iop_Add32, getIReg(15), mkU32(8)) ); - } else { - assign( Rm, getIReg(Rm_addr) ); - } - - // Rm >> rot-1: carry = R[0] - assign( *carry_out, binop(Iop_Shr32, mkexpr(Rm), - binop(Iop_Sub8, mkU8(rot_imm), mkU8(1)) ) ); - - if (rot_imm == 0) { // RRX (ARM ARM A5-17) - // 33 bit ROR using carry flag as the 33rd bit - // op = Rm >> 1, carry flag replacing vacated bit position. - - // CAB: This right? - expr = binop(Iop_Or32, - binop(Iop_Shl32, mkexpr(oldFlagC), mkU8(31)), - binop(Iop_Shr32, mkexpr(Rm), mkU8(1))); - DIS(buf, "R%d, rrx", Rm_addr); - } else { - expr = binop(Iop_Or32, - binop(Iop_Shr32, mkexpr(Rm), mkU8(rot_imm)), - binop(Iop_Shl32, mkexpr(Rm), - binop(Iop_Sub8, mkU8(32), mkU8(rot_imm)))); - - DIS(buf, "R%d, ror #%d", Rm_addr, rot_imm); - } - } - return expr; + UChar Rn_addr = (theInstr >> 16) & 0xF; + UChar Rd_addr = (theInstr >> 12) & 0xF; + UChar Rs_addr = (theInstr >> 8) & 0xF; + UChar Rm_addr = (theInstr >> 0) & 0xF; + UChar by_reg = (theInstr >> 4) & 0x1; // instr[4] + UInt rot_imm = (theInstr >> 7) & 0x1F; // instr[11:7] + IRTemp Rm = newTemp(Ity_I32); + IRTemp Rs = newTemp(Ity_I32); + IRTemp rot_amt = newTemp(Ity_I8); // Rs[7:0] + IRTemp oldFlagC = newTemp(Ity_I32); + IRExpr* expr=0; + + assign( oldFlagC, binop(Iop_Shr32, + mk_armg_calculate_flags_c(), + mkU8(ARMG_CC_SHIFT_C)) ); + + if (by_reg) { // Register rotate + assign( Rm, getIReg(Rm_addr) ); + + if (Rd_addr == 15 || Rm_addr == 15 || + Rn_addr == 15 || Rs_addr == 15) { // Unpredictable (ARM ARM A5-10) + vex_printf("dis_rotate(arm): Unpredictable - Rd|Rm|Rn|Rs == R15\n"); + *decode_ok = False; + return mkU32(0); + } + + assign( Rs, getIReg((theInstr >> 8) & 0xF) ); // instr[11:8] + // Rs[4:0] + assign( rot_amt, narrowTo(Ity_I8, + binop(Iop_And32, mkexpr(Rs), mkU32(0x1F))) ); + + // CAB: This right? + // Rs[7:0] == 0 ? oldFlagC : (Rs[4:0] == 0 ? Rm >> 31 : Rm >> rot-1 ) + assign( *carry_out, + IRExpr_Mux0X( + binop(Iop_CmpNE32, mkU32(0), + binop(Iop_And32, mkexpr(Rs), mkU32(0xFF))), + mkexpr(oldFlagC), + IRExpr_Mux0X( + binop(Iop_CmpEQ8, mkexpr(rot_amt), mkU8(0)), + binop(Iop_Shr32, mkexpr(Rm), + binop(Iop_Sub8, mkexpr(rot_amt), mkU8(1))), + binop(Iop_Shr32, mkexpr(Rm), + binop(Iop_Shr32, mkexpr(Rm), mkU8(31))) ) ) ); + + + /* expr = (dst0 >> rot_amt) | (dst0 << (wordsize-rot_amt)) */ + expr = binop(Iop_Or32, + binop(Iop_Shr32, mkexpr(Rm), mkexpr(rot_amt)), + binop(Iop_Shl32, mkexpr(Rm), + binop(Iop_Sub8, mkU8(32), mkexpr(rot_amt)))); + + DIS(buf, "R%d, ror R%d", Rm_addr, Rs_addr); + } + else { // Immediate rotate + + // CAB: This right? + // "the value used is the address of the current intruction plus 8" + if (Rm_addr == 15 || Rn_addr == 15) { // ARM ARM A5-9 + assign( Rm, binop(Iop_Add32, getIReg(15), mkU32(8)) ); + } else { + assign( Rm, getIReg(Rm_addr) ); + } + + // Rm >> rot-1: carry = R[0] + assign( *carry_out, binop(Iop_Shr32, mkexpr(Rm), + binop(Iop_Sub8, mkU8(rot_imm), mkU8(1)) ) ); + + if (rot_imm == 0) { // RRX (ARM ARM A5-17) + // 33 bit ROR using carry flag as the 33rd bit + // op = Rm >> 1, carry flag replacing vacated bit position. + + // CAB: This right? + expr = binop(Iop_Or32, + binop(Iop_Shl32, mkexpr(oldFlagC), mkU8(31)), + binop(Iop_Shr32, mkexpr(Rm), mkU8(1))); + DIS(buf, "R%d, rrx", Rm_addr); + } else { + expr = binop(Iop_Or32, + binop(Iop_Shr32, mkexpr(Rm), mkU8(rot_imm)), + binop(Iop_Shl32, mkexpr(Rm), + binop(Iop_Sub8, mkU8(32), mkU8(rot_imm)))); + + DIS(buf, "R%d, ror #%d", Rm_addr, rot_imm); + } + } + return expr; } @@ -1622,47 +1625,47 @@ IRExpr* dis_rotate ( Bool* decode_ok, UInt theInstr, IRTemp* carry_out, HChar* b static IRExpr* dis_shifter_op ( Bool *decode_ok, UInt theInstr, IRTemp* carry_out, HChar* buf ) { - UChar is_immed = (theInstr >> 25) & 1; // immediate / register shift - UChar shift_op = (theInstr >> 4) & 0xF; // second byte - UInt immed_8, rot_imm; - UInt imm; - IRTemp oldFlagC = newTemp(Ity_I32); - - if (is_immed) { // ARM ARM A5-2 - // dst = src ROR rot << 1 - // = (src >> rot) | (src << (32-rot)); - immed_8 = theInstr & 0xFF; - rot_imm = ((theInstr >> 8) & 0xF) << 1; - imm = (immed_8 >> rot_imm) | (immed_8 << (32-rot_imm)); - - if (rot_imm == 0) { - assign( oldFlagC, binop(Iop_Shr32, - mk_armg_calculate_flags_c(), - mkU8(ARMG_CC_SHIFT_C)) ); - assign( *carry_out, mkexpr(oldFlagC) ); - } else { - assign( *carry_out, binop(Iop_Shr32, mkU32(imm), mkU8(31)) ); - } - DIS(buf, "#%d", imm); - return mkU32(imm); - } else { - - // We shouldn't have any 'op' with bits 4=1 and 7=1 : 1xx1 - switch (shift_op) { - case 0x0: case 0x8: case 0x1: - case 0x2: case 0xA: case 0x3: - case 0x4: case 0xC: case 0x5: - return dis_shift( decode_ok, theInstr, carry_out, buf ); - - case 0x6: case 0xE: case 0x7: - return dis_rotate( decode_ok, theInstr, carry_out, buf ); - - default: // Error: Any other value shouldn't be here. - *decode_ok = False; - vex_printf("dis_shifter_op(arm): shift: No such case: 0x%x\n", shift_op); - return mkU32(0); - } - } + UChar is_immed = (theInstr >> 25) & 1; // immediate / register shift + UChar shift_op = (theInstr >> 4) & 0xF; // second byte + UInt immed_8, rot_imm; + UInt imm; + IRTemp oldFlagC = newTemp(Ity_I32); + + if (is_immed) { // ARM ARM A5-2 + // dst = src ROR rot << 1 + // = (src >> rot) | (src << (32-rot)); + immed_8 = theInstr & 0xFF; + rot_imm = ((theInstr >> 8) & 0xF) << 1; + imm = (immed_8 >> rot_imm) | (immed_8 << (32-rot_imm)); + + if (rot_imm == 0) { + assign( oldFlagC, binop(Iop_Shr32, + mk_armg_calculate_flags_c(), + mkU8(ARMG_CC_SHIFT_C)) ); + assign( *carry_out, mkexpr(oldFlagC) ); + } else { + assign( *carry_out, binop(Iop_Shr32, mkU32(imm), mkU8(31)) ); + } + DIS(buf, "#%d", imm); + return mkU32(imm); + } else { + + // We shouldn't have any 'op' with bits 4=1 and 7=1 : 1xx1 + switch (shift_op) { + case 0x0: case 0x8: case 0x1: + case 0x2: case 0xA: case 0x3: + case 0x4: case 0xC: case 0x5: + return dis_shift( decode_ok, theInstr, carry_out, buf ); + + case 0x6: case 0xE: case 0x7: + return dis_rotate( decode_ok, theInstr, carry_out, buf ); + + default: // Error: Any other value shouldn't be here. + *decode_ok = False; + vex_printf("dis_shifter_op(arm): shift: No such case: 0x%x\n", shift_op); + return mkU32(0); + } + } } @@ -1674,149 +1677,149 @@ IRExpr* dis_shifter_op ( Bool *decode_ok, UInt theInstr, IRTemp* carry_out, HCha static Bool dis_dataproc ( UInt theInstr ) { - UChar opc = (theInstr >> 21) & 0xF; - UChar set_flags = (theInstr >> 20) & 1; - UChar Rn_addr = (theInstr >> 16) & 0xF; - UChar Rd_addr = (theInstr >> 12) & 0xF; - IRTemp Rn = newTemp(Ity_I32); - IRTemp Rd = newTemp(Ity_I32); - IRTemp alu_out = newTemp(Ity_I32); - IRTemp shifter_op = newTemp(Ity_I32); - IRTemp carry_out = newTemp(Ity_I32); - IROp op_set_flags = ARMG_CC_OP_LOGIC; - Bool testing_instr = False; - Bool decode_ok = True; - HChar* cond_name = name_ARMCondcode( (theInstr >> 28) & 0xF ); - HChar* ch_set_flags = (set_flags == 1) ? "S" : ""; - HChar dis_buf[50]; - - assign( shifter_op, dis_shifter_op( &decode_ok, theInstr, &carry_out, dis_buf ) ); - if (!decode_ok) return False; - - assign( Rd, getIReg(Rd_addr) ); - assign( Rn, getIReg(Rn_addr) ); - - - switch (opc) { - case 0x0: case 0x1: case 0x2: case 0x3: case 0x4: - case 0xC: case 0xE: - DIP("%s%s%s R%d, R%d, %s\n", name_ARMDataProcOp(opc), - cond_name, ch_set_flags, Rd_addr, Rn_addr, dis_buf); - break; - case 0x5: case 0x6: case 0x7: - // CAB: Unimplemented - break; - case 0x8: case 0x9: case 0xA: case 0xB: - DIP("%s%s R%d, %s\n", name_ARMDataProcOp(opc), - cond_name, Rn_addr, dis_buf); - break; - case 0xD: case 0xF: - DIP("%s%s%s R%d, %s\n", name_ARMDataProcOp(opc), - cond_name, ch_set_flags, Rd_addr, dis_buf); - break; - default:break; - } - - - switch (opc) { - case 0x0: // AND - assign( alu_out, binop(Iop_And32, getIReg(Rn_addr), mkexpr(shifter_op)) ); - break; - - case 0x1: // EOR - assign( alu_out, binop(Iop_Xor32, getIReg(Rn_addr), mkexpr(shifter_op)) ); - break; - - case 0x2: // SUB - assign( alu_out, binop( Iop_Sub32, getIReg(Rn_addr), mkexpr(shifter_op) ) ); - op_set_flags = ARMG_CC_OP_SUB; - break; - - case 0x3: // RSB - assign( alu_out, binop( Iop_Sub32, mkexpr(shifter_op), getIReg(Rn_addr) ) ); - op_set_flags = ARMG_CC_OP_SUB; - /* set_flags(), below, switches the args for this case */ - break; - - case 0x4: // ADD - assign( alu_out, binop( Iop_Add32, getIReg(Rn_addr), mkexpr(shifter_op) ) ); - op_set_flags = ARMG_CC_OP_ADD; - break; - - case 0x5: // ADC // CAB: Unimplemented - case 0x6: // SBC // CAB: Unimplemented - case 0x7: // RSC // CAB: Unimplemented - goto decode_failure; - - case 0x8: // TST - vassert(set_flags==1); - assign( alu_out, binop(Iop_And32, getIReg(Rn_addr), mkexpr(shifter_op)) ); - testing_instr = True; - break; - - case 0x9: // TEQ - vassert(set_flags==1); - assign( alu_out, binop(Iop_Xor32, getIReg(Rn_addr), mkexpr(shifter_op)) ); - testing_instr = True; - break; - - case 0xA: // CMP - vassert(set_flags==1); - op_set_flags = ARMG_CC_OP_SUB; - testing_instr = True; - break; - - case 0xB: // CMN - vassert(set_flags==1); - op_set_flags = ARMG_CC_OP_ADD; - testing_instr = True; - break; - - case 0xC: // ORR - assign( alu_out, binop(Iop_Or32, getIReg(Rn_addr), mkexpr(shifter_op)) ); - break; - - case 0xD: // MOV - assign( alu_out, mkexpr(shifter_op) ); - break; - - case 0xE: // BIC - assign( alu_out, binop(Iop_And32, getIReg(Rn_addr), - unop( Iop_Not32, mkexpr(shifter_op))) ); - break; - - case 0xF: // MVN - assign( alu_out, unop(Iop_Not32, mkexpr(shifter_op)) ); - break; - - default: - decode_failure: - vex_printf("dis_dataproc(arm): unhandled opcode: 0x%x\n", opc); - return False; - } - - if (!testing_instr) { - if ( Rd_addr == 15) { // dest reg == PC - // CPSR = SPSR: Unpredictable in User | System mode (no SPSR!) - // Unpredictable - We're only supporting user mode... - vex_printf("dis_dataproc(arm): Unpredictable - Rd_addr==15\n"); - return False; - } - putIReg( Rd_addr, mkexpr(alu_out) ); - } - - if (set_flags) { - if (op_set_flags == ARMG_CC_OP_LOGIC) { - setFlags_DEP1_DEP2( op_set_flags, alu_out, carry_out ); - } else { - if (opc == 0x3) { - setFlags_DEP1_DEP2( op_set_flags, shifter_op, Rn ); - } else { - setFlags_DEP1_DEP2( op_set_flags, Rn, shifter_op ); - } - } - } - return decode_ok; + UChar opc = (theInstr >> 21) & 0xF; + UChar set_flags = (theInstr >> 20) & 1; + UChar Rn_addr = (theInstr >> 16) & 0xF; + UChar Rd_addr = (theInstr >> 12) & 0xF; + IRTemp Rn = newTemp(Ity_I32); + IRTemp Rd = newTemp(Ity_I32); + IRTemp alu_out = newTemp(Ity_I32); + IRTemp shifter_op = newTemp(Ity_I32); + IRTemp carry_out = newTemp(Ity_I32); + IROp op_set_flags = ARMG_CC_OP_LOGIC; + Bool testing_instr = False; + Bool decode_ok = True; + HChar* cond_name = name_ARMCondcode( (theInstr >> 28) & 0xF ); + HChar* ch_set_flags = (set_flags == 1) ? "S" : ""; + HChar dis_buf[50]; + + assign( shifter_op, dis_shifter_op( &decode_ok, theInstr, &carry_out, dis_buf ) ); + if (!decode_ok) return False; + + assign( Rd, getIReg(Rd_addr) ); + assign( Rn, getIReg(Rn_addr) ); + + + switch (opc) { + case 0x0: case 0x1: case 0x2: case 0x3: case 0x4: + case 0xC: case 0xE: + DIP("%s%s%s R%d, R%d, %s\n", name_ARMDataProcOp(opc), + cond_name, ch_set_flags, Rd_addr, Rn_addr, dis_buf); + break; + case 0x5: case 0x6: case 0x7: + // CAB: Unimplemented + break; + case 0x8: case 0x9: case 0xA: case 0xB: + DIP("%s%s R%d, %s\n", name_ARMDataProcOp(opc), + cond_name, Rn_addr, dis_buf); + break; + case 0xD: case 0xF: + DIP("%s%s%s R%d, %s\n", name_ARMDataProcOp(opc), + cond_name, ch_set_flags, Rd_addr, dis_buf); + break; + default:break; + } + + + switch (opc) { + case 0x0: // AND + assign( alu_out, binop(Iop_And32, getIReg(Rn_addr), mkexpr(shifter_op)) ); + break; + + case 0x1: // EOR + assign( alu_out, binop(Iop_Xor32, getIReg(Rn_addr), mkexpr(shifter_op)) ); + break; + + case 0x2: // SUB + assign( alu_out, binop( Iop_Sub32, getIReg(Rn_addr), mkexpr(shifter_op) ) ); + op_set_flags = ARMG_CC_OP_SUB; + break; + + case 0x3: // RSB + assign( alu_out, binop( Iop_Sub32, mkexpr(shifter_op), getIReg(Rn_addr) ) ); + op_set_flags = ARMG_CC_OP_SUB; + /* set_flags(), below, switches the args for this case */ + break; + + case 0x4: // ADD + assign( alu_out, binop( Iop_Add32, getIReg(Rn_addr), mkexpr(shifter_op) ) ); + op_set_flags = ARMG_CC_OP_ADD; + break; + + case 0x5: // ADC // CAB: Unimplemented + case 0x6: // SBC // CAB: Unimplemented + case 0x7: // RSC // CAB: Unimplemented + goto decode_failure; + + case 0x8: // TST + vassert(set_flags==1); + assign( alu_out, binop(Iop_And32, getIReg(Rn_addr), mkexpr(shifter_op)) ); + testing_instr = True; + break; + + case 0x9: // TEQ + vassert(set_flags==1); + assign( alu_out, binop(Iop_Xor32, getIReg(Rn_addr), mkexpr(shifter_op)) ); + testing_instr = True; + break; + + case 0xA: // CMP + vassert(set_flags==1); + op_set_flags = ARMG_CC_OP_SUB; + testing_instr = True; + break; + + case 0xB: // CMN + vassert(set_flags==1); + op_set_flags = ARMG_CC_OP_ADD; + testing_instr = True; + break; + + case 0xC: // ORR + assign( alu_out, binop(Iop_Or32, getIReg(Rn_addr), mkexpr(shifter_op)) ); + break; + + case 0xD: // MOV + assign( alu_out, mkexpr(shifter_op) ); + break; + + case 0xE: // BIC + assign( alu_out, binop(Iop_And32, getIReg(Rn_addr), + unop( Iop_Not32, mkexpr(shifter_op))) ); + break; + + case 0xF: // MVN + assign( alu_out, unop(Iop_Not32, mkexpr(shifter_op)) ); + break; + + default: + decode_failure: + vex_printf("dis_dataproc(arm): unhandled opcode: 0x%x\n", opc); + return False; + } + + if (!testing_instr) { + if ( Rd_addr == 15) { // dest reg == PC + // CPSR = SPSR: Unpredictable in User | System mode (no SPSR!) + // Unpredictable - We're only supporting user mode... + vex_printf("dis_dataproc(arm): Unpredictable - Rd_addr==15\n"); + return False; + } + putIReg( Rd_addr, mkexpr(alu_out) ); + } + + if (set_flags) { + if (op_set_flags == ARMG_CC_OP_LOGIC) { + setFlags_DEP1_DEP2( op_set_flags, alu_out, carry_out ); + } else { + if (opc == 0x3) { + setFlags_DEP1_DEP2( op_set_flags, shifter_op, Rn ); + } else { + setFlags_DEP1_DEP2( op_set_flags, Rn, shifter_op ); + } + } + } + return decode_ok; } @@ -1827,30 +1830,30 @@ Bool dis_dataproc ( UInt theInstr ) static void dis_branch ( UInt theInstr ) { - UChar link = (theInstr >> 24) & 1; - UInt signed_immed_24 = theInstr & 0xFFFFFF; - UInt branch_offset; - IRTemp addr = newTemp(Ity_I32); - IRTemp dest = newTemp(Ity_I32); - - if (link) { // LR (R14) = addr of instr after branch instr - assign( addr, binop(Iop_Add32, getIReg(15), mkU32(4)) ); - putIReg( 14, mkexpr(addr) ); - } - - // PC = PC + (SignExtend(signed_immed_24) << 2) - branch_offset = extend_s_24to32( signed_immed_24 ) << 2; - assign( dest, binop(Iop_Add32, getIReg(15), mkU32(branch_offset)) ); - - irbb->jumpkind = link ? Ijk_Call : Ijk_Boring; - irbb->next = mkexpr(dest); - - // Note: Not actually writing to R15 - let the IR stuff do that. - - DIP("b%s%s 0x%x\n", - link ? "l" : "", - name_ARMCondcode( (theInstr >> 28) & 0xF ), - branch_offset); + UChar link = (theInstr >> 24) & 1; + UInt signed_immed_24 = theInstr & 0xFFFFFF; + UInt branch_offset; + IRTemp addr = newTemp(Ity_I32); + IRTemp dest = newTemp(Ity_I32); + + if (link) { // LR (R14) = addr of instr after branch instr + assign( addr, binop(Iop_Add32, getIReg(15), mkU32(4)) ); + putIReg( 14, mkexpr(addr) ); + } + + // PC = PC + (SignExtend(signed_immed_24) << 2) + branch_offset = extend_s_24to32( signed_immed_24 ) << 2; + assign( dest, binop(Iop_Add32, getIReg(15), mkU32(branch_offset)) ); + + irbb->jumpkind = link ? Ijk_Call : Ijk_Boring; + irbb->next = mkexpr(dest); + + // Note: Not actually writing to R15 - let the IR stuff do that. + + DIP("b%s%s 0x%x\n", + link ? "l" : "", + name_ARMCondcode( (theInstr >> 28) & 0xF ), + branch_offset); } @@ -1885,9 +1888,9 @@ static DisResult disInstr ( /*IN*/ Bool resteerOK, /*OUT*/ UInt* size, /*OUT*/ Addr64* whereNext ) { - // IRType ty; - // IRTemp addr, t1, t2; - // Int alen; + // IRType ty; + // IRTemp addr, t1, t2; + // Int alen; UChar opc1, opc2, opc_tmp; //, modrm, abyte; ARMCondcode cond; // UInt d32; @@ -1895,12 +1898,12 @@ static DisResult disInstr ( /*IN*/ Bool resteerOK, // Int am_sz, d_sz; DisResult whatNext = Dis_Continue; UInt theInstr; - + /* At least this is simple on ARM: insns are all 4 bytes long, and 4-aligned. So just fish the whole thing out of memory right now and have done. */ - + /* We will set *size to 4 if the insn is successfully decoded. Setting it to 0 by default makes bbToIR_ARM abort if we fail the decode. */ @@ -1920,32 +1923,32 @@ static DisResult disInstr ( /*IN*/ Bool resteerOK, // Essentially a v. unlikely sequence of noops that we can catch { UInt* code = (UInt*)(guest_code + delta); - + /* Spot this: E1A00EE0 mov r0, r0, ror #29 - E1A001E0 mov r0, r0, ror #3 - E1A00DE0 mov r0, r0, ror #27 - E1A002E0 mov r0, r0, ror #5 - E1A006E0 mov r0, r0, ror #13 - E1A009E0 mov r0, r0, ror #19 + E1A001E0 mov r0, r0, ror #3 + E1A00DE0 mov r0, r0, ror #27 + E1A002E0 mov r0, r0, ror #5 + E1A006E0 mov r0, r0, ror #13 + E1A009E0 mov r0, r0, ror #19 */ /* I suspect these will have to be turned the other way round to - work on little-endian arm. */ + work on little-endian arm. */ if (code[0] == 0xE1A00EE0 && code[1] == 0xE1A001E0 && code[2] == 0xE1A00DE0 && code[3] == 0xE1A002E0 && code[4] == 0xE1A006E0 && - code[5] == 0xE1A009E0) { + code[5] == 0xE1A009E0) { // uh ... I'll figure this out later. possibly r0 = client_request(r0) */ DIP("?CAB? = client_request ( ?CAB? )\n"); - - *size = 24; - - irbb->next = mkU32(guest_pc_bbstart+delta); - irbb->jumpkind = Ijk_ClientReq; - + + *size = 24; + + irbb->next = mkU32(guest_pc_bbstart+delta); + irbb->jumpkind = Ijk_ClientReq; + whatNext = Dis_StopHere; goto decode_success; } @@ -1957,25 +1960,25 @@ static DisResult disInstr ( /*IN*/ Bool resteerOK, /* Deal with condition first - */ + */ cond = (theInstr >> 28) & 0xF; /* opcode: bits 31:28 */ // vex_printf("\ndisInstr(arm): cond: 0x%x, %b\n", cond, cond ); - + switch (cond) { case 0xF: // => Illegal instruction prior to v5 (see ARM ARM A3-5) - vex_printf("disInstr(arm): illegal condition\n"); - goto decode_failure; - + vex_printf("disInstr(arm): illegal condition\n"); + goto decode_failure; + case 0xE: // => Unconditional: go translate the instruction - break; + break; default: - // => Valid condition: translate the condition test first - stmt( IRStmt_Exit( mk_armg_calculate_condition(cond), - Ijk_Boring, - IRConst_U32(guest_pc_bbstart+delta+4) ) ); - //irbb->next = mkU32(guest_pc_bbstart+delta+4); - //irbb->jumpkind = Ijk_Boring; + // => Valid condition: translate the condition test first + stmt( IRStmt_Exit( mk_armg_calculate_condition(cond), + Ijk_Boring, + IRConst_U32(guest_pc_bbstart+delta+4) ) ); + //irbb->next = mkU32(guest_pc_bbstart+delta+4); + //irbb->jumpkind = Ijk_Boring; } @@ -1986,179 +1989,179 @@ static DisResult disInstr ( /*IN*/ Bool resteerOK, opc2 = (theInstr >> 4 ) & 0xF; /* opcode2: bits 7:4 */ // vex_printf("disInstr(arm): opcode1: 0x%2x, %,09b\n", opc1, opc1 ); // vex_printf("disInstr(arm): opcode2: 0x%02x, %,04b\n", opc2, opc2 ); - + switch (opc1 >> 4) { // instr[27:24] case 0x0: case 0x1: - /* - Multiplies, extra load/store instructions: ARM ARM A3-3 - */ - if ( (opc1 & 0xE0) == 0x0 && (opc2 & 0x9) == 0x9 ) { // 000xxxxx && 1xx1 - if (opc2 == 0x9) { - if ((opc1 & 0x1C) == 0x00) { // multiply (accumulate) - goto decode_failure; - } - if ((opc1 & 0x18) == 0x08) { // multiply (accumulate) long - goto decode_failure; - } - if ((opc1 & 0x1B) == 0x10) { // swap/swap byte - goto decode_failure; - } - } - if ( opc2 == 0xB ) { - if ((opc1 & 0x04) == 0x00) { // load/store 1/2word reg offset - goto decode_failure; - } else { // load/store 1/2word imm offset - goto decode_failure; - } - } - if ((opc2 & 0xD) == 0xD) { - if ((opc1 & 0x05) == 0x00) { // load/store 2 words reg offset - goto decode_failure; - } - if ((opc1 & 0x05) == 0x04) { // load/store 2 words imm offset - goto decode_failure; - } - if ((opc1 & 0x05) == 0x01) { // load/store signed 1/2word/byte reg offset - goto decode_failure; - } - if ((opc1 & 0x05) == 0x05) { // load/store signed 1/2word/byte imm offset - goto decode_failure; - } - } - } /* endif: Multiplies, extra load/store... */ - - /* - 'Misc' Instructions: ARM ARM A3-4 - */ - if ((opc1 & 0xF9) == 0x10) { // 0001 0xx0 - opc_tmp = (opc1 >> 1) & 0x3; - switch (opc2) { - case 0x0: - if ((opc_tmp & 0x1) == 0x0) { // move stat reg -> reg - goto decode_failure; - } else { // move reg -> stat reg - goto decode_failure; - } - - case 0x1: - if (opc_tmp == 0x1) { // branch/exchange instr set - goto decode_failure; - } - if (opc_tmp == 0x3) { // count leading zeros - goto decode_failure; - } - break; - - case 0x3: - if (opc_tmp == 0x1) { // branch & link/exchange instr set - goto decode_failure; - } - break; - - case 0x5: // enhanced dsp add/subtracts - goto decode_failure; - - case 0x7: - if (opc_tmp == 0x1) { // software breakpoint - if (cond != 0xE) { // Unpredictable - ARM ARM A3-4 - vex_printf("disInstr(arm): Unpredictable instruction\n"); - goto decode_failure; - } - goto decode_failure; - } - break; - - case 0x8: case 0x9: case 0xA: // enhanced dsp multiplies - case 0xB: case 0xC: case 0xD: case 0xE: - goto decode_failure; - - default: break; - } - } /* endif: 'Misc' Instructions... */ + /* + Multiplies, extra load/store instructions: ARM ARM A3-3 + */ + if ( (opc1 & 0xE0) == 0x0 && (opc2 & 0x9) == 0x9 ) { // 000xxxxx && 1xx1 + if (opc2 == 0x9) { + if ((opc1 & 0x1C) == 0x00) { // multiply (accumulate) + goto decode_failure; + } + if ((opc1 & 0x18) == 0x08) { // multiply (accumulate) long + goto decode_failure; + } + if ((opc1 & 0x1B) == 0x10) { // swap/swap byte + goto decode_failure; + } + } + if ( opc2 == 0xB ) { + if ((opc1 & 0x04) == 0x00) { // load/store 1/2word reg offset + goto decode_failure; + } else { // load/store 1/2word imm offset + goto decode_failure; + } + } + if ((opc2 & 0xD) == 0xD) { + if ((opc1 & 0x05) == 0x00) { // load/store 2 words reg offset + goto decode_failure; + } + if ((opc1 & 0x05) == 0x04) { // load/store 2 words imm offset + goto decode_failure; + } + if ((opc1 & 0x05) == 0x01) { // load/store signed 1/2word/byte reg offset + goto decode_failure; + } + if ((opc1 & 0x05) == 0x05) { // load/store signed 1/2word/byte imm offset + goto decode_failure; + } + } + } /* endif: Multiplies, extra load/store... */ + + /* + 'Misc' Instructions: ARM ARM A3-4 + */ + if ((opc1 & 0xF9) == 0x10) { // 0001 0xx0 + opc_tmp = (opc1 >> 1) & 0x3; + switch (opc2) { + case 0x0: + if ((opc_tmp & 0x1) == 0x0) { // move stat reg -> reg + goto decode_failure; + } else { // move reg -> stat reg + goto decode_failure; + } + + case 0x1: + if (opc_tmp == 0x1) { // branch/exchange instr set + goto decode_failure; + } + if (opc_tmp == 0x3) { // count leading zeros + goto decode_failure; + } + break; + + case 0x3: + if (opc_tmp == 0x1) { // branch & link/exchange instr set + goto decode_failure; + } + break; + + case 0x5: // enhanced dsp add/subtracts + goto decode_failure; + + case 0x7: + if (opc_tmp == 0x1) { // software breakpoint + if (cond != 0xE) { // Unpredictable - ARM ARM A3-4 + vex_printf("disInstr(arm): Unpredictable instruction\n"); + goto decode_failure; + } + goto decode_failure; + } + break; + + case 0x8: case 0x9: case 0xA: // enhanced dsp multiplies + case 0xB: case 0xC: case 0xD: case 0xE: + goto decode_failure; + + default: break; + } + } /* endif: 'Misc' Instructions... */ // fall through... - + case 0x2: case 0x3: - if ((opc1 & 0xFB) == 0x30) goto decode_failure; // Undefined - ARM ARM A3-2 - - /* - A lonely 'MOV imm to status reg': - */ - if ((opc1 & 0xFB) == 0x32) { // 0011 0x10 - goto decode_failure; - } - - /* - Data Processing Instructions - (if we get here, it's a dpi) - */ - if (!dis_dataproc( theInstr )) { goto decode_failure; } - break; - - - /* - Load/Store word | unsigned byte - */ - case 0x6: case 0x7: // LOAD/STORE reg offset - if ((opc2 & 0x1) == 0x1) goto decode_failure; // Undefined - ARM ARM A3-2 - - case 0x4: case 0x5: // LOAD/STORE imm offset - if (!dis_loadstore_w_ub(theInstr)) { goto decode_failure; } - break; + if ((opc1 & 0xFB) == 0x30) goto decode_failure; // Undefined - ARM ARM A3-2 + + /* + A lonely 'MOV imm to status reg': + */ + if ((opc1 & 0xFB) == 0x32) { // 0011 0x10 + goto decode_failure; + } + + /* + Data Processing Instructions + (if we get here, it's a dpi) + */ + if (!dis_dataproc( theInstr )) { goto decode_failure; } + break; + - /* - Load/Store multiple - */ + /* + Load/Store word | unsigned byte + */ + case 0x6: case 0x7: // LOAD/STORE reg offset + if ((opc2 & 0x1) == 0x1) goto decode_failure; // Undefined - ARM ARM A3-2 + + case 0x4: case 0x5: // LOAD/STORE imm offset + if (!dis_loadstore_w_ub(theInstr)) { goto decode_failure; } + break; + + /* + Load/Store multiple + */ case 0x8: case 0x9: - if (!dis_loadstore_mult(theInstr)) { goto decode_failure; } - break; - - - /* - Branch, Branch and Link - */ + if (!dis_loadstore_mult(theInstr)) { goto decode_failure; } + break; + + + /* + Branch, Branch and Link + */ case 0xA: case 0xB: // B, BL - // B(L): L=1 => return address stored in link register (R14) - dis_branch(theInstr); - whatNext = Dis_StopHere; - break; - - - /* - Co-processor instructions - */ + // B(L): L=1 => return address stored in link register (R14) + dis_branch(theInstr); + whatNext = Dis_StopHere; + break; + + + /* + Co-processor instructions + */ case 0xC: case 0xD: // co-pro load/store & double reg trxfrs - goto decode_failure; - + goto decode_failure; + case 0xE: - if ((opc2 & 0x1) == 0x0) { // co-pro data processing - goto decode_failure; - } else { // co-pro register transfers - goto decode_failure; - } - - - /* - Software Interrupt - */ + if ((opc2 & 0x1) == 0x0) { // co-pro data processing + goto decode_failure; + } else { // co-pro register transfers + goto decode_failure; + } + + + /* + Software Interrupt + */ case 0xF: // swi - goto decode_failure; - + goto decode_failure; + default: decode_failure: /* All decode failures end up here. */ vex_printf("disInstr(arm): unhandled instruction: " "0x%x\n", theInstr); vpanic("armToIR: unimplemented insn"); - + } /* switch (opc) for the main (primary) opcode switch. */ - + decode_success: /* All decode successes end up here. */ // vex_printf("disInstr(arm): success"); DIP("\n"); - + *size = 4; return whatNext; } diff --git a/VEX/priv/guest-ppc32/gdefs.h b/VEX/priv/guest-ppc32/gdefs.h index 8db9dec410..734351ff5c 100644 --- a/VEX/priv/guest-ppc32/gdefs.h +++ b/VEX/priv/guest-ppc32/gdefs.h @@ -46,12 +46,12 @@ extern IRBB* bbToIR_PPC32 ( UChar* ppc32code, - Addr64 eip, - VexGuestExtents* vge, - Bool (*byte_accessible)(Addr64), - Bool (*resteerOkFn)(Addr64), - Bool host_bigendian, - VexSubArch subarch_guest ); + Addr64 eip, + VexGuestExtents* vge, + Bool (*byte_accessible)(Addr64), + Bool (*resteerOkFn)(Addr64), + Bool host_bigendian, + VexSubArch subarch_guest ); /* Used by the optimiser to specialise calls to helpers. */ extern @@ -88,24 +88,24 @@ extern UInt ppc32g_calculate_xer_ca ( UInt op, UInt res, UInt arg1, UInt arg2, Handy enumeration for flag calculation helper functions (xer_ca, ov) */ enum { - PPC32G_FLAG_OP_ADD=0, // addc, addo, addic - PPC32G_FLAG_OP_ADDE, // adde, addeo - PPC32G_FLAG_OP_ADDME, // addme, addmeo - PPC32G_FLAG_OP_ADDZE, // addze, addzeo - PPC32G_FLAG_OP_DIVW, // divwo - PPC32G_FLAG_OP_DIVWU, // divwuo - PPC32G_FLAG_OP_MULLW, // mullwo - PPC32G_FLAG_OP_NEG, // nego - PPC32G_FLAG_OP_SUBF, // subfo - PPC32G_FLAG_OP_SUBFC, // subfc, subfco - PPC32G_FLAG_OP_SUBFE, // subfe, subfeo - PPC32G_FLAG_OP_SUBFI, // subfic - PPC32G_FLAG_OP_SUBFME, // subfme, subfmeo - PPC32G_FLAG_OP_SUBFZE, // subfze, subfzeo - PPC32G_FLAG_OP_SRAW, // sraw - PPC32G_FLAG_OP_SRAWI, // srawi - - PPC32G_FLAG_OP_NUMBER + PPC32G_FLAG_OP_ADD=0, // addc, addo, addic + PPC32G_FLAG_OP_ADDE, // adde, addeo + PPC32G_FLAG_OP_ADDME, // addme, addmeo + PPC32G_FLAG_OP_ADDZE, // addze, addzeo + PPC32G_FLAG_OP_DIVW, // divwo + PPC32G_FLAG_OP_DIVWU, // divwuo + PPC32G_FLAG_OP_MULLW, // mullwo + PPC32G_FLAG_OP_NEG, // nego + PPC32G_FLAG_OP_SUBF, // subfo + PPC32G_FLAG_OP_SUBFC, // subfc, subfco + PPC32G_FLAG_OP_SUBFE, // subfe, subfeo + PPC32G_FLAG_OP_SUBFI, // subfic + PPC32G_FLAG_OP_SUBFME, // subfme, subfmeo + PPC32G_FLAG_OP_SUBFZE, // subfze, subfzeo + PPC32G_FLAG_OP_SRAW, // sraw + PPC32G_FLAG_OP_SRAWI, // srawi + + PPC32G_FLAG_OP_NUMBER }; diff --git a/VEX/priv/guest-ppc32/ghelpers.c b/VEX/priv/guest-ppc32/ghelpers.c index 2c083e90ad..dd87a38aa7 100644 --- a/VEX/priv/guest-ppc32/ghelpers.c +++ b/VEX/priv/guest-ppc32/ghelpers.c @@ -66,118 +66,118 @@ */ UInt ppc32g_calculate_cr7_all ( UInt op, UInt word1, UInt xer_so ) { - Int sword1 = (Int)word1; - if (op) { - return (word1 & 0xF0000000); - } else { - return - ((xer_so & 1) << 28) - | (((sword1 == 0) ? 1:0) << 29) - | (((sword1 > 0) ? 1:0) << 30) - | (((sword1 < 0) ? 1:0) << 31); - } + Int sword1 = (Int)word1; + if (op) { + return (word1 & 0xF0000000); + } else { + return + ((xer_so & 1) << 28) + | (((sword1 == 0) ? 1:0) << 29) + | (((sword1 > 0) ? 1:0) << 30) + | (((sword1 < 0) ? 1:0) << 31); + } } // Calculate XER_OV UInt ppc32g_calculate_xer_ov ( UInt op, UInt res, - UInt arg1, UInt arg2, UInt ov ) + UInt arg1, UInt arg2, UInt ov ) { - ULong ul_tmp=0; - - switch (op) { - case PPC32G_FLAG_OP_ADD: // addo, addc - case PPC32G_FLAG_OP_ADDE: // addeo - return ((arg1^arg2^-1) & (arg1^res) & (1<<31)) ? 1:0; - // i.e. ((both_same_sign) & (sign_changed) & (sign_mask)) - - case PPC32G_FLAG_OP_ADDME: // addmeo - return ((arg1) & (arg1 ^ res) & (1<<31)) ? 1:0; - // i.e. (neg & (sign_changed) & sign_mask) - - case PPC32G_FLAG_OP_ADDZE: // addzeo - return ((arg1^(-1)) & (arg1 ^ res) & (1<<31)) ? 1:0; - // i.e. (pos & (sign_changed) & sign_mask) - - case PPC32G_FLAG_OP_DIVW: // divwo - return ((arg1 == INT32_MIN && arg2 == -1) || arg2 == 0) ? 1:0; - - case PPC32G_FLAG_OP_DIVWU: // divwuo - return (arg2 == 0) ? 1:0; - - case PPC32G_FLAG_OP_MULLW: // mullwo - ul_tmp = (ULong)arg1 * (ULong)arg2; - return (res != res) ? 1:0; - - case PPC32G_FLAG_OP_NEG: // nego - return (arg1 == 0x80000000) ? 1:0; - - case PPC32G_FLAG_OP_SUBF: // subfo - case PPC32G_FLAG_OP_SUBFC: // subfco - case PPC32G_FLAG_OP_SUBFE: // subfeo - return (((~arg1)^arg2^(-1)) & ((~arg1)^res) & (1<<31)) ? 1:0; - - case PPC32G_FLAG_OP_SUBFME: // subfmeo - return ((~arg1) & ((~arg1)^res) & (1<<31)) ? 1:0; - - case PPC32G_FLAG_OP_SUBFZE: // subfzeo - return (((~arg1)^(-1)) & ((~arg1)^res) & (1<<31)) ? 1:0; - - default: - break; - } - - vpanic("ppc32g_calculate_xer_ov(ppc32)"); - return 0; // notreached + ULong ul_tmp=0; + + switch (op) { + case PPC32G_FLAG_OP_ADD: // addo, addc + case PPC32G_FLAG_OP_ADDE: // addeo + return ((arg1^arg2^-1) & (arg1^res) & (1<<31)) ? 1:0; + // i.e. ((both_same_sign) & (sign_changed) & (sign_mask)) + + case PPC32G_FLAG_OP_ADDME: // addmeo + return ((arg1) & (arg1 ^ res) & (1<<31)) ? 1:0; + // i.e. (neg & (sign_changed) & sign_mask) + + case PPC32G_FLAG_OP_ADDZE: // addzeo + return ((arg1^(-1)) & (arg1 ^ res) & (1<<31)) ? 1:0; + // i.e. (pos & (sign_changed) & sign_mask) + + case PPC32G_FLAG_OP_DIVW: // divwo + return ((arg1 == INT32_MIN && arg2 == -1) || arg2 == 0) ? 1:0; + + case PPC32G_FLAG_OP_DIVWU: // divwuo + return (arg2 == 0) ? 1:0; + + case PPC32G_FLAG_OP_MULLW: // mullwo + ul_tmp = (ULong)arg1 * (ULong)arg2; + return (res != res) ? 1:0; + + case PPC32G_FLAG_OP_NEG: // nego + return (arg1 == 0x80000000) ? 1:0; + + case PPC32G_FLAG_OP_SUBF: // subfo + case PPC32G_FLAG_OP_SUBFC: // subfco + case PPC32G_FLAG_OP_SUBFE: // subfeo + return (((~arg1)^arg2^(-1)) & ((~arg1)^res) & (1<<31)) ? 1:0; + + case PPC32G_FLAG_OP_SUBFME: // subfmeo + return ((~arg1) & ((~arg1)^res) & (1<<31)) ? 1:0; + + case PPC32G_FLAG_OP_SUBFZE: // subfzeo + return (((~arg1)^(-1)) & ((~arg1)^res) & (1<<31)) ? 1:0; + + default: + break; + } + + vpanic("ppc32g_calculate_xer_ov(ppc32)"); + return 0; // notreached } // Calculate XER_CA UInt ppc32g_calculate_xer_ca ( UInt op, UInt res, - UInt arg1, UInt arg2, UInt ca ) + UInt arg1, UInt arg2, UInt ca ) { - switch (op) { - case PPC32G_FLAG_OP_ADD: // addc, addco, addic - case PPC32G_FLAG_OP_ADDZE: // addze, addzeo - return (res < arg1) ? 1:0; - - case PPC32G_FLAG_OP_ADDE: // adde, addeo - return (res < arg1 || (ca==1 && res==arg1)) ? 1:0; - - case PPC32G_FLAG_OP_ADDME: // addme, addmeo - return (arg1 != 0) ? 1:0; - - case PPC32G_FLAG_OP_SUBFC: // subfc, subfco - case PPC32G_FLAG_OP_SUBFI: // subfic - case PPC32G_FLAG_OP_SUBFZE: // subfze, subfzeo - return (res <= arg2) ? 1:0; - - case PPC32G_FLAG_OP_SUBFE: // subfe, subfeo - return ((res < arg2) || (ca == 1 && res == arg2)) ? 1:0; - - case PPC32G_FLAG_OP_SUBFME: // subfme, subfmeo - return (res != -1) ? 1:0; - - case PPC32G_FLAG_OP_SRAW: // sraw - if ((arg2 & 0x20) == 0) { // shift <= 31 - // ca = sign && (bits_shifted_out != 0) - return (((arg1 & 0x80000000) && - ((arg1 & (0xFFFFFFFF >> (32-arg2))) != 0)) != 0) ? 1:0; - } - // shift > 31 - // ca = sign && src != 0 - return (((arg1 & 0x80000000) && (arg2 != 0)) != 0) ? 1:0; - - case PPC32G_FLAG_OP_SRAWI: // srawi - // ca = sign && (bits_shifted_out != 0) - return (((arg1 & 0x80000000) && - ((arg1 & (0xFFFFFFFF >> (32-arg2))) != 0)) != 0) ? 1:0; - - default: - break; - } - vpanic("ppc32g_calculate_xer_ov(ppc32)"); - return 0; // notreached + switch (op) { + case PPC32G_FLAG_OP_ADD: // addc, addco, addic + case PPC32G_FLAG_OP_ADDZE: // addze, addzeo + return (res < arg1) ? 1:0; + + case PPC32G_FLAG_OP_ADDE: // adde, addeo + return (res < arg1 || (ca==1 && res==arg1)) ? 1:0; + + case PPC32G_FLAG_OP_ADDME: // addme, addmeo + return (arg1 != 0) ? 1:0; + + case PPC32G_FLAG_OP_SUBFC: // subfc, subfco + case PPC32G_FLAG_OP_SUBFI: // subfic + case PPC32G_FLAG_OP_SUBFZE: // subfze, subfzeo + return (res <= arg2) ? 1:0; + + case PPC32G_FLAG_OP_SUBFE: // subfe, subfeo + return ((res < arg2) || (ca == 1 && res == arg2)) ? 1:0; + + case PPC32G_FLAG_OP_SUBFME: // subfme, subfmeo + return (res != -1) ? 1:0; + + case PPC32G_FLAG_OP_SRAW: // sraw + if ((arg2 & 0x20) == 0) { // shift <= 31 + // ca = sign && (bits_shifted_out != 0) + return (((arg1 & 0x80000000) && + ((arg1 & (0xFFFFFFFF >> (32-arg2))) != 0)) != 0) ? 1:0; + } + // shift > 31 + // ca = sign && src != 0 + return (((arg1 & 0x80000000) && (arg2 != 0)) != 0) ? 1:0; + + case PPC32G_FLAG_OP_SRAWI: // srawi + // ca = sign && (bits_shifted_out != 0) + return (((arg1 & 0x80000000) && + ((arg1 & (0xFFFFFFFF >> (32-arg2))) != 0)) != 0) ? 1:0; + + default: + break; + } + vpanic("ppc32g_calculate_xer_ov(ppc32)"); + return 0; // notreached } @@ -193,9 +193,9 @@ UInt ppc32g_calculate_xer_ca ( UInt op, UInt res, /* temporarily unused */ static Bool isU32 ( IRExpr* e, UInt n ) { - return e->tag == Iex_Const - && e->Iex.Const.con->tag == Ico_U32 - && e->Iex.Const.con->Ico.U32 == n; + return (e->tag == Iex_Const + && e->Iex.Const.con->tag == Ico_U32 + && e->Iex.Const.con->Ico.U32 == n); } #endif IRExpr* guest_ppc32_spechelper ( HChar* function_name, @@ -222,10 +222,10 @@ void LibVEX_GuestPPC32_put_flags ( UInt flags_native, UInt LibVEX_GuestPPC32_get_flags ( /*IN*/VexGuestPPC32State* vex_state ) { UInt flags = ppc32g_calculate_cr7_all( - vex_state->guest_CC_OP, - vex_state->guest_CC_DEP1, - vex_state->guest_CC_DEP2 - ); + vex_state->guest_CC_OP, + vex_state->guest_CC_DEP1, + vex_state->guest_CC_DEP2 + ); return flags; } diff --git a/VEX/priv/guest-ppc32/toIR.c b/VEX/priv/guest-ppc32/toIR.c index 893619ad94..61619417f8 100644 --- a/VEX/priv/guest-ppc32/toIR.c +++ b/VEX/priv/guest-ppc32/toIR.c @@ -185,26 +185,26 @@ typedef enum { static UInt MASK( UInt begin, UInt end ) { - UInt m1 = ((UInt)(-1)) << begin; - UInt m2 = ((UInt)(-1)) << (end + 1); - UInt mask = m1 ^ m2; - if (begin > end) mask = ~mask; // wrap mask - return mask; + UInt m1 = ((UInt)(-1)) << begin; + UInt m2 = ((UInt)(-1)) << (end + 1); + UInt mask = m1 ^ m2; + if (begin > end) mask = ~mask; // wrap mask + return mask; } static void vex_printf_binary( UInt x, UInt len, Bool spaces ) { - UInt i; - vassert(len > 0 && len <= 32); - - for (i=len; i>0; i--) { - vex_printf("%d", ((x & (1<<(len-1))) != 0) ); - x = x << 1; - if (((i-1)%4)==0 && (i > 1) && spaces) { - vex_printf(" "); - } - } + UInt i; + vassert(len > 0 && len <= 32); + + for (i=len; i>0; i--) { + vex_printf("%d", ((x & (1<<(len-1))) != 0) ); + x = x << 1; + if (((i-1)%4)==0 && (i > 1) && spaces) { + vex_printf(" "); + } + } } @@ -257,12 +257,12 @@ static DisResult disInstr ( /*IN*/ Bool resteerOK, the basic block. */ IRBB* bbToIR_PPC32 ( UChar* ppc32code, - Addr64 guest_pc_start, - VexGuestExtents* vge, - Bool (*byte_accessible)(Addr64), - Bool (*chase_into_ok)(Addr64), - Bool host_bigendian, - VexSubArch subarch_guest ) + Addr64 guest_pc_start, + VexGuestExtents* vge, + Bool (*byte_accessible)(Addr64), + Bool (*chase_into_ok)(Addr64), + Bool host_bigendian, + VexSubArch subarch_guest ) { UInt delta; Int i, n_instrs, size, first_stmt_idx; @@ -351,30 +351,31 @@ IRBB* bbToIR_PPC32 ( UChar* ppc32code, vassert(guest_next == 0); switch (dres) { - case Dis_Continue: - vassert(irbb->next == NULL); - if (n_instrs < vex_control.guest_max_insns) { - /* keep going */ - } else { - irbb->next = mkU32(((Addr32)guest_pc_start)+delta); - return irbb; - } - break; - case Dis_StopHere: - vassert(irbb->next != NULL); + case Dis_Continue: + vassert(irbb->next == NULL); + if (n_instrs < vex_control.guest_max_insns) { + /* keep going */ + } else { + irbb->next = mkU32(((Addr32)guest_pc_start)+delta); return irbb; - case Dis_Resteer: - vassert(irbb->next == NULL); - /* figure out a new delta to continue at. */ - vassert(chase_into_ok(guest_next)); - delta = (UInt)(guest_next - guest_pc_start); - n_resteers++; - d_resteers++; - if (0 && (n_resteers & 0xFF) == 0) + } + break; + case Dis_StopHere: + vassert(irbb->next != NULL); + return irbb; + case Dis_Resteer: + vassert(irbb->next == NULL); + /* figure out a new delta to continue at. */ + vassert(chase_into_ok(guest_next)); + delta = (UInt)(guest_next - guest_pc_start); + n_resteers++; + d_resteers++; + if (0 && (n_resteers & 0xFF) == 0) vex_printf("resteer[%d,%d] to %p (delta = %d)\n", n_resteers, d_resteers, ULong_to_Ptr(guest_next), (Int)delta); - break; + break; +// CAB: no default? } } } @@ -460,10 +461,10 @@ static UInt getUIntBigendianly ( UChar* p ) static IRType szToITy ( Int n ) { switch (n) { - case 1: return Ity_I8; - case 2: return Ity_I16; - case 4: return Ity_I32; - default: vpanic("szToITy(PPC32)"); + case 1: return Ity_I8; + case 2: return Ity_I16; + case 4: return Ity_I32; + default: vpanic("szToITy(PPC32)"); } } #endif @@ -472,43 +473,43 @@ static IRType szToITy ( Int n ) static Int integerGuestRegOffset ( UInt archreg ) { vassert(archreg < 32); - + // vassert(!host_is_bigendian); //TODO: is this necessary? // jrs: probably not; only matters if we reference sub-parts // of the ppc32 registers, but that isn't the case switch (archreg) { - case 0: return offsetof(VexGuestPPC32State, guest_GPR0); - case 1: return offsetof(VexGuestPPC32State, guest_GPR1); - case 2: return offsetof(VexGuestPPC32State, guest_GPR2); - case 3: return offsetof(VexGuestPPC32State, guest_GPR3); - case 4: return offsetof(VexGuestPPC32State, guest_GPR4); - case 5: return offsetof(VexGuestPPC32State, guest_GPR5); - case 6: return offsetof(VexGuestPPC32State, guest_GPR6); - case 7: return offsetof(VexGuestPPC32State, guest_GPR7); - case 8: return offsetof(VexGuestPPC32State, guest_GPR8); - case 9: return offsetof(VexGuestPPC32State, guest_GPR9); - case 10: return offsetof(VexGuestPPC32State, guest_GPR10); - case 11: return offsetof(VexGuestPPC32State, guest_GPR11); - case 12: return offsetof(VexGuestPPC32State, guest_GPR12); - case 13: return offsetof(VexGuestPPC32State, guest_GPR13); - case 14: return offsetof(VexGuestPPC32State, guest_GPR14); - case 15: return offsetof(VexGuestPPC32State, guest_GPR15); - case 16: return offsetof(VexGuestPPC32State, guest_GPR16); - case 17: return offsetof(VexGuestPPC32State, guest_GPR17); - case 18: return offsetof(VexGuestPPC32State, guest_GPR18); - case 19: return offsetof(VexGuestPPC32State, guest_GPR19); - case 20: return offsetof(VexGuestPPC32State, guest_GPR20); - case 21: return offsetof(VexGuestPPC32State, guest_GPR21); - case 22: return offsetof(VexGuestPPC32State, guest_GPR22); - case 23: return offsetof(VexGuestPPC32State, guest_GPR23); - case 24: return offsetof(VexGuestPPC32State, guest_GPR24); - case 25: return offsetof(VexGuestPPC32State, guest_GPR25); - case 26: return offsetof(VexGuestPPC32State, guest_GPR26); - case 27: return offsetof(VexGuestPPC32State, guest_GPR27); - case 28: return offsetof(VexGuestPPC32State, guest_GPR28); - case 29: return offsetof(VexGuestPPC32State, guest_GPR29); - case 30: return offsetof(VexGuestPPC32State, guest_GPR30); - case 31: return offsetof(VexGuestPPC32State, guest_GPR31); + case 0: return offsetof(VexGuestPPC32State, guest_GPR0); + case 1: return offsetof(VexGuestPPC32State, guest_GPR1); + case 2: return offsetof(VexGuestPPC32State, guest_GPR2); + case 3: return offsetof(VexGuestPPC32State, guest_GPR3); + case 4: return offsetof(VexGuestPPC32State, guest_GPR4); + case 5: return offsetof(VexGuestPPC32State, guest_GPR5); + case 6: return offsetof(VexGuestPPC32State, guest_GPR6); + case 7: return offsetof(VexGuestPPC32State, guest_GPR7); + case 8: return offsetof(VexGuestPPC32State, guest_GPR8); + case 9: return offsetof(VexGuestPPC32State, guest_GPR9); + case 10: return offsetof(VexGuestPPC32State, guest_GPR10); + case 11: return offsetof(VexGuestPPC32State, guest_GPR11); + case 12: return offsetof(VexGuestPPC32State, guest_GPR12); + case 13: return offsetof(VexGuestPPC32State, guest_GPR13); + case 14: return offsetof(VexGuestPPC32State, guest_GPR14); + case 15: return offsetof(VexGuestPPC32State, guest_GPR15); + case 16: return offsetof(VexGuestPPC32State, guest_GPR16); + case 17: return offsetof(VexGuestPPC32State, guest_GPR17); + case 18: return offsetof(VexGuestPPC32State, guest_GPR18); + case 19: return offsetof(VexGuestPPC32State, guest_GPR19); + case 20: return offsetof(VexGuestPPC32State, guest_GPR20); + case 21: return offsetof(VexGuestPPC32State, guest_GPR21); + case 22: return offsetof(VexGuestPPC32State, guest_GPR22); + case 23: return offsetof(VexGuestPPC32State, guest_GPR23); + case 24: return offsetof(VexGuestPPC32State, guest_GPR24); + case 25: return offsetof(VexGuestPPC32State, guest_GPR25); + case 26: return offsetof(VexGuestPPC32State, guest_GPR26); + case 27: return offsetof(VexGuestPPC32State, guest_GPR27); + case 28: return offsetof(VexGuestPPC32State, guest_GPR28); + case 29: return offsetof(VexGuestPPC32State, guest_GPR29); + case 30: return offsetof(VexGuestPPC32State, guest_GPR30); + case 31: return offsetof(VexGuestPPC32State, guest_GPR31); } vpanic("integerGuestRegOffset(ppc32,le)"); /*notreached*/ @@ -626,20 +627,20 @@ static IROp mkWidenOp ( Int szSmall, Int szBig, Bool signd ) // ROTL(src32, rot_amt5) static IRExpr* ROTL32 ( IRExpr* src, IRExpr* rot_amt ) { - vassert(typeOfIRExpr(irbb->tyenv,src) == Ity_I32); - vassert(typeOfIRExpr(irbb->tyenv,rot_amt) == Ity_I8); - - /* By masking the rotate amount thusly, the IR-level Shl/Shr - expressions never shift beyond the word size and thus remain - well defined. */ - IRTemp rot_amt5 = newTemp(Ity_I8); - assign(rot_amt5, binop(Iop_And8, rot_amt, mkU8(0x1F))); - - // (src << rot_amt) | (src >> (32-rot_amt)) - return binop(Iop_Or32, - binop(Iop_Shl32, src, mkexpr(rot_amt5)), - binop(Iop_Shr32, src, - binop(Iop_Sub8, mkU8(32), mkexpr(rot_amt5)))); + vassert(typeOfIRExpr(irbb->tyenv,src) == Ity_I32); + vassert(typeOfIRExpr(irbb->tyenv,rot_amt) == Ity_I8); + + /* By masking the rotate amount thusly, the IR-level Shl/Shr + expressions never shift beyond the word size and thus remain + well defined. */ + IRTemp rot_amt5 = newTemp(Ity_I8); + assign(rot_amt5, binop(Iop_And8, rot_amt, mkU8(0x1F))); + + // (src << rot_amt) | (src >> (32-rot_amt)) + return binop(Iop_Or32, + binop(Iop_Shl32, src, mkexpr(rot_amt5)), + binop(Iop_Shr32, src, + binop(Iop_Sub8, mkU8(32), mkexpr(rot_amt5)))); } @@ -688,7 +689,7 @@ static IRExpr* mk_ppc32g_calculate_cr7_all ( void ) // Calculate XER_OV flag static IRExpr* mk_ppc32g_calculate_xer_ov ( UInt op, IRExpr* res, - IRExpr* arg1, IRExpr* arg2 ) + IRExpr* arg1, IRExpr* arg2 ) { vassert(op < PPC32G_FLAG_OP_NUMBER); vassert(typeOfIRExpr(irbb->tyenv,res) == Ity_I32); @@ -711,7 +712,7 @@ static IRExpr* mk_ppc32g_calculate_xer_ov ( UInt op, IRExpr* res, // Calculate XER_CA flag static IRExpr* mk_ppc32g_calculate_xer_ca ( UInt op, IRExpr* res, - IRExpr* arg1, IRExpr* arg2 ) + IRExpr* arg1, IRExpr* arg2 ) { vassert(op < PPC32G_FLAG_OP_NUMBER); vassert(typeOfIRExpr(irbb->tyenv,res) == Ity_I32); @@ -747,10 +748,10 @@ static IRExpr* mk_ppc32g_calculate_xer_ca ( UInt op, IRExpr* res, static IRExpr* widenUto32 ( IRExpr* e ) { switch (typeOfIRExpr(irbb->tyenv,e)) { - case Ity_I32: return e; - case Ity_I16: return unop(Iop_16Uto32,e); - case Ity_I8: return unop(Iop_8Uto32,e); - default: vpanic("widenUto32(ppc32)"); + case Ity_I32: return e; + case Ity_I16: return unop(Iop_16Uto32,e); + case Ity_I8: return unop(Iop_8Uto32,e); + default: vpanic("widenUto32(ppc32)"); } } #endif @@ -803,30 +804,30 @@ static void setFlags_CR7_Imm ( IRExpr* flags ) } static void setFlags_XER_OV_SO( UInt op, IRExpr* res, - IRExpr* arg1, IRExpr* arg2 ) + IRExpr* arg1, IRExpr* arg2 ) { - vassert(op < PPC32G_FLAG_OP_NUMBER); - vassert(typeOfIRExpr(irbb->tyenv,res) == Ity_I32); - vassert(typeOfIRExpr(irbb->tyenv,arg1) == Ity_I32); - vassert(typeOfIRExpr(irbb->tyenv,arg2) == Ity_I32); + vassert(op < PPC32G_FLAG_OP_NUMBER); + vassert(typeOfIRExpr(irbb->tyenv,res) == Ity_I32); + vassert(typeOfIRExpr(irbb->tyenv,arg1) == Ity_I32); + vassert(typeOfIRExpr(irbb->tyenv,arg2) == Ity_I32); - // => Calculate result immediately - IRExpr* xer_ov = mk_ppc32g_calculate_xer_ov(op, res, arg1, arg2); - stmt( IRStmt_Put( OFFB_XER_SO, unop(Iop_1Uto8, xer_ov) )); - stmt( IRStmt_Put( OFFB_XER_OV, unop(Iop_1Uto8, xer_ov) )); + // => Calculate result immediately + IRExpr* xer_ov = mk_ppc32g_calculate_xer_ov(op, res, arg1, arg2); + stmt( IRStmt_Put( OFFB_XER_SO, unop(Iop_1Uto8, xer_ov) )); + stmt( IRStmt_Put( OFFB_XER_OV, unop(Iop_1Uto8, xer_ov) )); } static void setFlags_XER_CA( UInt op, IRExpr* res, - IRExpr* arg1, IRExpr* arg2 ) + IRExpr* arg1, IRExpr* arg2 ) { - vassert(op < PPC32G_FLAG_OP_NUMBER); - vassert(typeOfIRExpr(irbb->tyenv,res) == Ity_I32); - vassert(typeOfIRExpr(irbb->tyenv,arg1) == Ity_I32); - vassert(typeOfIRExpr(irbb->tyenv,arg2) == Ity_I32); - - // => Calculate result immediately - IRExpr* xer_ca = mk_ppc32g_calculate_xer_ca(op, res, arg1, arg2); - stmt( IRStmt_Put( OFFB_XER_CA, unop(Iop_1Uto8, xer_ca) )); + vassert(op < PPC32G_FLAG_OP_NUMBER); + vassert(typeOfIRExpr(irbb->tyenv,res) == Ity_I32); + vassert(typeOfIRExpr(irbb->tyenv,arg1) == Ity_I32); + vassert(typeOfIRExpr(irbb->tyenv,arg2) == Ity_I32); + + // => Calculate result immediately + IRExpr* xer_ca = mk_ppc32g_calculate_xer_ca(op, res, arg1, arg2); + stmt( IRStmt_Put( OFFB_XER_CA, unop(Iop_1Uto8, xer_ca) )); } @@ -844,33 +845,33 @@ static void setFlags_XER_CA( UInt op, IRExpr* res, /* Get single bits from given [register,idx] */ static IRExpr* getReg_bit ( PPC32Reg reg, UInt bit_idx ) { - vassert( bit_idx <= 32 ); - vassert( reg < REG_NUMBER ); - - IRExpr* val; - - switch (reg) { - case REG_XER: - switch (bit_idx) { - case OFFBIT_XER_SO: - val = IRExpr_Get(OFFB_XER_SO, Ity_I8); - break; - case OFFBIT_XER_OV: - val = IRExpr_Get(OFFB_XER_OV, Ity_I8); - break; - case OFFBIT_XER_CA: - val = IRExpr_Get(OFFB_XER_CA, Ity_I8); - break; - case OFFBIT_XER_BC: - val = IRExpr_Get(OFFB_XER_BC, Ity_I8); - break; - default: - vpanic("getReg_bit(ppc32, bit_idx)"); - } - break; + vassert( bit_idx <= 32 ); + vassert( reg < REG_NUMBER ); + + IRExpr* val; + + switch (reg) { + case REG_XER: + switch (bit_idx) { + case OFFBIT_XER_SO: + val = IRExpr_Get(OFFB_XER_SO, Ity_I8); + break; + case OFFBIT_XER_OV: + val = IRExpr_Get(OFFB_XER_OV, Ity_I8); + break; + case OFFBIT_XER_CA: + val = IRExpr_Get(OFFB_XER_CA, Ity_I8); + break; + case OFFBIT_XER_BC: + val = IRExpr_Get(OFFB_XER_BC, Ity_I8); + break; + default: + vpanic("getReg_bit(ppc32, bit_idx)"); + } + break; default: - vpanic("getReg_bit(ppc32, reg)"); + vpanic("getReg_bit(ppc32, reg)"); } return unop(Iop_8Uto32, binop(Iop_And8, val, mkU8(1)) ); } @@ -879,66 +880,66 @@ static IRExpr* getReg_bit ( PPC32Reg reg, UInt bit_idx ) shifted to position bit_idx */ static IRExpr* getReg_bit_shifted ( PPC32Reg reg, UInt bit_idx ) { - vassert( bit_idx <= 32 ); - vassert( reg < REG_NUMBER ); - return binop(Iop_Shl32, getReg_bit( reg, bit_idx ), mkU8(bit_idx)); + vassert( bit_idx <= 32 ); + vassert( reg < REG_NUMBER ); + return binop(Iop_Shl32, getReg_bit( reg, bit_idx ), mkU8(bit_idx)); } /* Get a word, controlled by a mask, from the given register */ static IRExpr* getReg_masked ( PPC32Reg reg, UInt mask ) { - IRTemp val = newTemp(Ity_I32); - IRExpr* irx_tmp1 = mkU32(0); - IRExpr* irx_tmp2 = mkU32(0); - IRExpr* irx_tmp3 = mkU32(0); - IRExpr* irx_tmp4 = mkU32(0); - - vassert( mask > 0 ); - vassert( reg < REG_NUMBER ); - - switch (reg) { - case REG_LR: - assign( val, IRExpr_Get(OFFB_LR, Ity_I32) ); - break; - - case REG_CTR: - assign( val, IRExpr_Get(OFFB_CTR, Ity_I32) ); - break; - - case REG_CR: - if (mask & 0xF0000000) { - // Call helper function to calculate latest CR7 from thunk: - irx_tmp1 = mk_ppc32g_calculate_cr7_all(); - } - irx_tmp2 = IRExpr_Get(OFFB_CR0to6, Ity_I32); - assign( val, binop(Iop_Or32, irx_tmp1, irx_tmp2) ); - break; - - case REG_XER: - if (mask & 0x80000000) { - irx_tmp1 = getReg_bit_shifted( REG_XER, OFFBIT_XER_SO ); - } - if (mask & 0x40000000) { - irx_tmp2 = getReg_bit_shifted( REG_XER, OFFBIT_XER_OV ); - } - if (mask & 0x20000000) { - irx_tmp3 = getReg_bit_shifted( REG_XER, OFFBIT_XER_CA ); - } - if (mask & 0x0000007F) { - irx_tmp4 = unop(Iop_8Uto32, - binop(Iop_And8, - IRExpr_Get(OFFB_XER_BC, Ity_I8), - mkU32(0x7F))); - } - assign( val, binop(Iop_Or32, - binop(Iop_Or32, irx_tmp1, irx_tmp2), - binop(Iop_Or32, irx_tmp3, irx_tmp4)) ); - break; + IRTemp val = newTemp(Ity_I32); + IRExpr* irx_tmp1 = mkU32(0); + IRExpr* irx_tmp2 = mkU32(0); + IRExpr* irx_tmp3 = mkU32(0); + IRExpr* irx_tmp4 = mkU32(0); + + vassert( mask > 0 ); + vassert( reg < REG_NUMBER ); + + switch (reg) { + case REG_LR: + assign( val, IRExpr_Get(OFFB_LR, Ity_I32) ); + break; + + case REG_CTR: + assign( val, IRExpr_Get(OFFB_CTR, Ity_I32) ); + break; + + case REG_CR: + if (mask & 0xF0000000) { + // Call helper function to calculate latest CR7 from thunk: + irx_tmp1 = mk_ppc32g_calculate_cr7_all(); + } + irx_tmp2 = IRExpr_Get(OFFB_CR0to6, Ity_I32); + assign( val, binop(Iop_Or32, irx_tmp1, irx_tmp2) ); + break; + + case REG_XER: + if (mask & 0x80000000) { + irx_tmp1 = getReg_bit_shifted( REG_XER, OFFBIT_XER_SO ); + } + if (mask & 0x40000000) { + irx_tmp2 = getReg_bit_shifted( REG_XER, OFFBIT_XER_OV ); + } + if (mask & 0x20000000) { + irx_tmp3 = getReg_bit_shifted( REG_XER, OFFBIT_XER_CA ); + } + if (mask & 0x0000007F) { + irx_tmp4 = unop(Iop_8Uto32, + binop(Iop_And8, + IRExpr_Get(OFFB_XER_BC, Ity_I8), + mkU32(0x7F))); + } + assign( val, binop(Iop_Or32, + binop(Iop_Or32, irx_tmp1, irx_tmp2), + binop(Iop_Or32, irx_tmp3, irx_tmp4)) ); + break; case REG_FPSCR: default: - vpanic("getReg(ppc32)"); + vpanic("getReg(ppc32)"); } return binop(Iop_And32, mkexpr(val), mkU32(mask)); @@ -947,142 +948,142 @@ static IRExpr* getReg_masked ( PPC32Reg reg, UInt mask ) /* Get a word, controlled by a mask, from the given register */ static IRExpr* getReg ( PPC32Reg reg ) { - vassert( reg < REG_NUMBER ); - return getReg_masked( reg, 0x0FFFFFFF ); + vassert( reg < REG_NUMBER ); + return getReg_masked( reg, 0x0FFFFFFF ); } /* Write single bit to given [register,idx] */ static void putReg_bit ( PPC32Reg reg, UInt bit_idx, IRExpr* src ) { - vassert( typeOfIRExpr(irbb->tyenv,src ) == Ity_I1 ); - vassert( bit_idx <= 32 ); - vassert( reg < REG_NUMBER ); - - switch (reg) { - case REG_XER: - switch (bit_idx) { - case OFFBIT_XER_SO: - stmt( IRStmt_Put( OFFB_XER_SO, unop(Iop_1Uto8, src) )); - break; - case OFFBIT_XER_OV: - stmt( IRStmt_Put( OFFB_XER_OV, unop(Iop_1Uto8, src) )); - break; - case OFFBIT_XER_CA: - stmt( IRStmt_Put( OFFB_XER_CA, unop(Iop_1Uto8, src) )); - break; - case OFFBIT_XER_BC: - stmt( IRStmt_Put( OFFB_XER_BC, unop(Iop_1Uto8, src) )); - break; - default: - vpanic("putReg_bit(ppc32, bit_idx)"); - } - break; + vassert( typeOfIRExpr(irbb->tyenv,src ) == Ity_I1 ); + vassert( bit_idx <= 32 ); + vassert( reg < REG_NUMBER ); + + switch (reg) { + case REG_XER: + switch (bit_idx) { + case OFFBIT_XER_SO: + stmt( IRStmt_Put( OFFB_XER_SO, unop(Iop_1Uto8, src) )); + break; + case OFFBIT_XER_OV: + stmt( IRStmt_Put( OFFB_XER_OV, unop(Iop_1Uto8, src) )); + break; + case OFFBIT_XER_CA: + stmt( IRStmt_Put( OFFB_XER_CA, unop(Iop_1Uto8, src) )); + break; + case OFFBIT_XER_BC: + stmt( IRStmt_Put( OFFB_XER_BC, unop(Iop_1Uto8, src) )); + break; + default: + vpanic("putReg_bit(ppc32, bit_idx)"); + } + break; default: - vpanic("putReg_bit(ppc32, reg)"); + vpanic("putReg_bit(ppc32, reg)"); } } /* Write a word, controlled by a mask, to the given register */ static void putReg_masked ( PPC32Reg reg, IRExpr* src, UInt mask ) { - vassert( reg < REG_NUMBER ); - vassert( typeOfIRExpr(irbb->tyenv,src ) == Ity_I32 ); - vassert( mask > 0 ); - - IRTemp src_mskd = newTemp(Ity_I32); - IRTemp old = newTemp(Ity_I32); - IRTemp tmp = newTemp(Ity_I32); - - assign( src_mskd, binop(Iop_And32, src, mkU32(mask)) ); - - switch (reg) { - case REG_LR: - stmt( IRStmt_Put( OFFB_LR, src) ); - break; - - case REG_CTR: - stmt( IRStmt_Put( OFFB_CTR, src) ); - break; - - case REG_CR: - if (mask & 0xF0000000) { // CR 7: - setFlags_CR7_Imm( mkexpr(src_mskd) ); - } - // CR 0 to 6: - assign( old, binop(Iop_And32, getReg( REG_CR ), mkU32(~mask)) ); - assign( tmp, binop(Iop_And32, mkexpr(src_mskd), mkU32(0x0FFFFFFF)) ); - stmt( IRStmt_Put( OFFB_CR0to6, binop(Iop_Or32, - mkexpr(tmp),mkexpr(old)) )); - break; - - case REG_XER: - if (mask & (1 << OFFBIT_XER_SO)) { - putReg_bit( REG_XER, OFFBIT_XER_SO, - unop(Iop_32to1, - binop(Iop_Shr32, src, mkU8(OFFBIT_XER_SO))) ); - } - if (mask & (1 << OFFBIT_XER_OV)) { - putReg_bit( REG_XER, OFFBIT_XER_OV, - unop(Iop_32to1, - binop(Iop_Shr32, src, mkU8(OFFBIT_XER_OV))) ); - } - if (mask & (1 << OFFBIT_XER_CA)) { - putReg_bit( REG_XER, OFFBIT_XER_CA, - unop(Iop_32to1, - binop(Iop_Shr32, src, mkU8(OFFBIT_XER_CA))) ); - } - if (mask & (0x7F << OFFBIT_XER_BC)) { - stmt( IRStmt_Put( OFFB_XER_BC, - binop(Iop_And8, mkU8(0x7F), - unop(Iop_32to8, src)) )); - } - break; + vassert( reg < REG_NUMBER ); + vassert( typeOfIRExpr(irbb->tyenv,src ) == Ity_I32 ); + vassert( mask > 0 ); + + IRTemp src_mskd = newTemp(Ity_I32); + IRTemp old = newTemp(Ity_I32); + IRTemp tmp = newTemp(Ity_I32); + + assign( src_mskd, binop(Iop_And32, src, mkU32(mask)) ); + + switch (reg) { + case REG_LR: + stmt( IRStmt_Put( OFFB_LR, src) ); + break; + + case REG_CTR: + stmt( IRStmt_Put( OFFB_CTR, src) ); + break; + + case REG_CR: + if (mask & 0xF0000000) { // CR 7: + setFlags_CR7_Imm( mkexpr(src_mskd) ); + } + // CR 0 to 6: + assign( old, binop(Iop_And32, getReg( REG_CR ), mkU32(~mask)) ); + assign( tmp, binop(Iop_And32, mkexpr(src_mskd), mkU32(0x0FFFFFFF)) ); + stmt( IRStmt_Put( OFFB_CR0to6, binop(Iop_Or32, + mkexpr(tmp),mkexpr(old)) )); + break; + + case REG_XER: + if (mask & (1 << OFFBIT_XER_SO)) { + putReg_bit( REG_XER, OFFBIT_XER_SO, + unop(Iop_32to1, + binop(Iop_Shr32, src, mkU8(OFFBIT_XER_SO))) ); + } + if (mask & (1 << OFFBIT_XER_OV)) { + putReg_bit( REG_XER, OFFBIT_XER_OV, + unop(Iop_32to1, + binop(Iop_Shr32, src, mkU8(OFFBIT_XER_OV))) ); + } + if (mask & (1 << OFFBIT_XER_CA)) { + putReg_bit( REG_XER, OFFBIT_XER_CA, + unop(Iop_32to1, + binop(Iop_Shr32, src, mkU8(OFFBIT_XER_CA))) ); + } + if (mask & (0x7F << OFFBIT_XER_BC)) { + stmt( IRStmt_Put( OFFB_XER_BC, + binop(Iop_And8, mkU8(0x7F), + unop(Iop_32to8, src)) )); + } + break; case REG_FPSCR: default: - vpanic("putReg(ppc32)"); + vpanic("putReg(ppc32)"); } } /* Write a word to the given register */ static void putReg ( PPC32Reg reg, IRExpr* src ) { - vassert( typeOfIRExpr(irbb->tyenv,src ) == Ity_I32 ); - vassert( reg < REG_NUMBER ); - putReg_masked( reg, src, 0xFFFFFFFF ); + vassert( typeOfIRExpr(irbb->tyenv,src ) == Ity_I32 ); + vassert( reg < REG_NUMBER ); + putReg_masked( reg, src, 0xFFFFFFFF ); } /* Write a nibble (least significant) to the given register,field */ static void putReg_field ( PPC32Reg reg, UInt field_idx, IRExpr* src ) { - vassert( typeOfIRExpr(irbb->tyenv,src ) == Ity_I32 ); - vassert( field_idx <= 8 ); - vassert( reg < REG_NUMBER ); - - UInt bit_idx = field_idx * 4; - UInt field_mask = 0x0000000F << field_idx; - - IRTemp val = newTemp(Ity_I32); - - assign( val, binop(Iop_Shl32, - binop(Iop_And32, src, mkU32(0xF)), - mkU8(bit_idx)) ); - - switch (reg) { - case REG_CR: - putReg_masked( REG_CR, mkexpr(val), field_mask ); - break; - - case REG_XER: - putReg_masked( REG_XER, mkexpr(val), field_mask ); - break; + vassert( typeOfIRExpr(irbb->tyenv,src ) == Ity_I32 ); + vassert( field_idx <= 8 ); + vassert( reg < REG_NUMBER ); + + UInt bit_idx = field_idx * 4; + UInt field_mask = 0x0000000F << field_idx; - default: - vpanic("putReg_field(ppc32)"); - } + IRTemp val = newTemp(Ity_I32); + + assign( val, binop(Iop_Shl32, + binop(Iop_And32, src, mkU32(0xF)), + mkU8(bit_idx)) ); + + switch (reg) { + case REG_CR: + putReg_masked( REG_CR, mkexpr(val), field_mask ); + break; + + case REG_XER: + putReg_masked( REG_XER, mkexpr(val), field_mask ); + break; + + default: + vpanic("putReg_field(ppc32)"); + } } @@ -1107,1231 +1108,1232 @@ static void putReg_field ( PPC32Reg reg, UInt field_idx, IRExpr* src ) */ static Bool dis_int_arith ( UInt theInstr ) { - UChar opc1 = toUChar((theInstr >> 26) & 0x3F); /* theInstr[26:31] */ - UChar Rd_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ - UChar Ra_addr = toUChar((theInstr >> 16) & 0x1F); /* theInstr[16:20] */ - - /* D-Form */ - UInt SIMM_16 = (theInstr >> 0) & 0xFFFF; /* theInstr[0:15] */ - - /* XO-Form */ - UChar Rb_addr = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */ - UChar flag_OE = toUChar((theInstr >> 10) & 1); /* theInstr[10] */ - UInt opc2 = (theInstr >> 1) & 0x1FF; /* theInstr[1:9] */ - UChar flag_Rc = toUChar((theInstr >> 0) & 1); /* theInstr[0] */ - - UInt EXTS_SIMM = 0; - - IRTemp Ra = newTemp(Ity_I32); - IRTemp Rb = newTemp(Ity_I32); - IRTemp Rd = newTemp(Ity_I32); - IRTemp res64 = newTemp(Ity_I64); // multiplies need this. - IRTemp xer_ca = newTemp(Ity_I32); - - UInt op = PPC32G_FLAG_OP_NUMBER; - Bool do_ca = False; - Bool do_ov = False; - Bool do_rc = False; - IRExpr* arg1; - IRExpr* arg2; - - assign( Ra, getIReg(Ra_addr) ); - assign( Rb, getIReg(Rb_addr) ); // XO-Form: Rd, Ra, Rb - EXTS_SIMM = extend_s_16to32(SIMM_16); // D-Form: Rd, Ra, EXTS(SIMM) - - arg1 = mkexpr(Ra); - arg2 = mkU32(EXTS_SIMM); - - assign( xer_ca, getReg_bit(REG_XER, OFFBIT_XER_CA) ); - - - switch (opc1) { - - /* D-Form */ - case 0x0C: // addi (Add Immediate, p380) - // li rD,val == addi rD,0,val - // la disp(rA) == addi rD,rA,disp - DIP("addi %d,%d,0x%x\n", Rd_addr, Ra_addr, SIMM_16); - if ( Ra_addr == 0 ) { - assign( Rd, mkU32(EXTS_SIMM) ); - } else { - assign( Rd, binop( Iop_Add32, mkexpr(Ra), mkU32(EXTS_SIMM) ) ); - } - break; - - case 0x0D: // addic (Add Immediate Carrying, p381) - DIP("addic r%d,r%d,0x%x\n", Rd_addr, Ra_addr, SIMM_16); - assign( Rd, binop( Iop_Add32, mkexpr(Ra), mkU32(EXTS_SIMM) ) ); - op = PPC32G_FLAG_OP_ADD; - do_ca = True; - break; - - case 0x0E: // addic. (Add Immediate Carrying and Record, p382) - DIP("addic. r%d,r%d,0x%x\n", Rd_addr, Ra_addr, SIMM_16); - assign( Rd, binop( Iop_Add32, mkexpr(Ra), mkU32(EXTS_SIMM) ) ); - op = PPC32G_FLAG_OP_ADD; - do_ca = True; - do_rc = True; - flag_Rc = 1; - break; - - case 0x0F: // addis (Add Immediate Shifted, p383) - // lis rD,val == addis rD,0,val - DIP("addis r%d,r%d,0x%x\n", Rd_addr, Ra_addr, SIMM_16); - if ( Ra_addr == 0 ) { - assign( Rd, mkU32(EXTS_SIMM << 16) ); - } else { - assign( Rd, binop(Iop_Add32, mkexpr(Ra), - mkU32(EXTS_SIMM << 16)) ); - } - break; - - case 0x07: // mulli (Multiply Low Immediate, p544) - DIP("mulli r%d,r%d,0x%x\n", Rd_addr, Ra_addr, SIMM_16); - assign( res64, binop(Iop_MullS32, mkexpr(Ra), mkU32(EXTS_SIMM)) ); - assign( Rd, unop(Iop_64to32, mkexpr(res64)) ); - break; - - case 0x08: // subfic (Subtract from Immediate Carrying, p613) - DIP("subfic r%d,r%d,0x%x\n", Rd_addr, Ra_addr, SIMM_16); - assign( Rd, binop(Iop_Add32, unop(Iop_Not32, mkexpr(Ra)), - mkU32(EXTS_SIMM)) ); - op = PPC32G_FLAG_OP_SUBFI; - do_ca = True; - break; - - - /* XO-Form */ - case 0x1F: - arg2 = mkexpr(Rb); - do_rc = True; // All below record to CR - - switch (opc2) { - case 0x10A: // add (Add, p377) - DIP("add%s%s r%d,r%d,r%d\n", - flag_OE ? "o" : "", flag_Rc ? "." : "", - Rd_addr, Ra_addr, Rb_addr); - assign( Rd, binop(Iop_Add32, mkexpr(Ra), mkexpr(Rb)) ); - op = PPC32G_FLAG_OP_ADD; - do_ov = True; - break; - - case 0x00A: // addc (Add Carrying, p378) - DIP("addc%s%s r%d,r%d,r%d\n", - flag_OE ? "o" : "", flag_Rc ? "." : "", - Rd_addr, Ra_addr, Rb_addr); - assign( Rd, binop(Iop_Add32, mkexpr(Ra), mkexpr(Rb)) ); - op = PPC32G_FLAG_OP_ADD; - do_ca = True; - do_ov = True; - break; - - case 0x08A: // adde (Add Extended, p379) - DIP("adde%s%s r%d,r%d,r%d\n", - flag_OE ? "o" : "", flag_Rc ? "." : "", - Rd_addr, Ra_addr, Rb_addr); - // rD = rA + rB + XER[CA] - assign( Rd, binop(Iop_Add32, mkexpr(Ra), - binop(Iop_Add32, mkexpr(Rb), mkexpr(xer_ca))) ); - op = PPC32G_FLAG_OP_ADDE; - do_ca = True; - do_ov = True; - break; - - case 0x0EA: // addme (Add to Minus One Extended, p384) - if (Rb_addr != 0) { - vex_printf("dis_int_arith(PPC32)(addme,Rb_addr)\n"); - return False; - } - DIP("addme%s%s r%d,r%d,r%d\n", - flag_OE ? "o" : "", flag_Rc ? "." : "", - Rd_addr, Ra_addr, Rb_addr); - // rD = rA + XER[CA] - 1 - assign( Rd, binop(Iop_Add32, mkexpr(Ra), - binop(Iop_Sub32, mkexpr(xer_ca), mkU32(1)) )); - op = PPC32G_FLAG_OP_ADDME; - do_ca = True; - do_ov = True; - break; - - case 0x0CA: // addze (Add to Zero Extended, p385) - if (Rb_addr != 0) { - vex_printf("dis_int_arith(PPC32)(addze,Rb_addr)\n"); - return False; - } - DIP("addze%s%s r%d,r%d,r%d\n", - flag_OE ? "o" : "", flag_Rc ? "." : "", - Rd_addr, Ra_addr, Rb_addr); - // rD = rA + XER[CA] - assign( Rd, binop(Iop_Add32, mkexpr(Ra), mkexpr(xer_ca)) ); - op = PPC32G_FLAG_OP_ADDZE; - do_ca = True; - do_ov = True; - break; - - case 0x1EB: // divw (Divide Word, p421) - DIP("divw%s%s r%d,r%d,r%d\n", - flag_OE ? "o" : "", flag_Rc ? "." : "", - Rd_addr, Ra_addr, Rb_addr); - assign( Rd, binop(Iop_DivS32, mkexpr(Ra), mkexpr(Rb)) ); - op = PPC32G_FLAG_OP_DIVW; - do_ov = True; - /* Note: - if (0x8000_0000 / -1) or (x / 0) - => Rd=undef, if(flag_Rc) CR7=undef, if(flag_OE) XER_OV=1 - => But _no_ exception raised. */ - break; - - case 0x1CB: // divwu (Divide Word Unsigned, p422) - DIP("divwu%s%s r%d,r%d,r%d\n", - flag_OE ? "o" : "", flag_Rc ? "." : "", - Rd_addr, Ra_addr, Rb_addr); - assign( Rd, binop(Iop_DivU32, mkexpr(Ra), mkexpr(Rb)) ); - op = PPC32G_FLAG_OP_DIVWU; - do_ov = True; - /* Note: ditto comment divw, for (x / 0) */ - break; - - case 0x04B: // mulhw (Multiply High Word, p541) - if (flag_OE != 0) { - vex_printf("dis_int_arith(PPC32)(mulhw,flag_OE)\n"); - return False; - } - DIP("mulhw%s r%d,r%d,r%d\n", flag_Rc ? "." : "", - Rd_addr, Ra_addr, Rb_addr); - assign( res64, binop(Iop_MullS32, mkexpr(Ra), mkexpr(Rb)) ); - assign( Rd, unop(Iop_64HIto32, mkexpr(res64)) ); - break; - - case 0x00B: // mulhwu (Multiply High Word Unsigned, p542) - if (flag_OE != 0) { - vex_printf("dis_int_arith(PPC32)(mulhwu,flag_OE)\n"); - return False; - } - DIP("mulhwu%s r%d,r%d,r%d\n", flag_Rc ? "." : "", - Rd_addr, Ra_addr, Rb_addr); - assign( res64, binop(Iop_MullU32, mkexpr(Ra), mkexpr(Rb)) ); - assign( Rd, unop(Iop_64HIto32, mkexpr(res64)) ); - break; - - case 0x0EB: // mullw (Multiply Low Word, p545) - DIP("mullw%s%s r%d,r%d,r%d\n", - flag_OE ? "o" : "", flag_Rc ? "." : "", - Rd_addr, Ra_addr, Rb_addr); - assign( res64, binop(Iop_MullU32, mkexpr(Ra), mkexpr(Rb)) ); - assign( Rd, unop(Iop_64to32, mkexpr(res64)) ); - op = PPC32G_FLAG_OP_MULLW; - do_ov = True; - break; - - case 0x068: // neg (Negate, p547) - if (Rb_addr != 0) { - vex_printf("dis_int_arith(PPC32)(neg,Rb_addr)\n"); - return False; - } - DIP("neg%s%s r%d,r%d\n", - flag_OE ? "o" : "", flag_Rc ? "." : "", - Rd_addr, Ra_addr); - // rD = (log not)rA + 1 - assign( Rd, binop(Iop_Add32, - unop(Iop_Not32, mkexpr(Ra)), mkU32(1)) ); - op = PPC32G_FLAG_OP_NEG; - do_ov = True; - break; - - case 0x028: // subf (Subtract From, p610) - DIP("subf%s%s r%d,r%d,r%d\n", - flag_OE ? "o" : "", flag_Rc ? "." : "", - Rd_addr, Ra_addr, Rb_addr); - // rD = (log not)rA + rB + 1 - assign( Rd, binop(Iop_Add32, unop(Iop_Not32, mkexpr(Ra)), - binop(Iop_Add32, mkexpr(Rb), mkU32(1))) ); - op = PPC32G_FLAG_OP_SUBF; - do_ov = True; - break; - - case 0x008: // subfc (Subtract from Carrying, p611) - DIP("subfc%s%s r%d,r%d,r%d\n", - flag_OE ? "o" : "", flag_Rc ? "." : "", - Rd_addr, Ra_addr, Rb_addr); - // rD = (log not)rA + rB + 1 - assign( Rd, binop(Iop_Add32, unop(Iop_Not32, mkexpr(Ra)), - binop(Iop_Add32, mkexpr(Rb), mkU32(1))) ); - op = PPC32G_FLAG_OP_SUBFC; - do_ca = True; - do_ov = True; - break; - - case 0x088: // subfe (Subtract from Extended, p612) - DIP("subfe%s%s r%d,r%d,r%d\n", - flag_OE ? "o" : "", flag_Rc ? "." : "", - Rd_addr, Ra_addr, Rb_addr); - // rD = (log not)rA + rB + XER[CA] - assign( Rd, binop(Iop_Add32, unop(Iop_Not32, mkexpr(Ra)), - binop(Iop_Add32, mkexpr(Rb), mkexpr(xer_ca))) ); - op = PPC32G_FLAG_OP_SUBFE; - do_ca = True; - do_ov = True; - break; - - case 0x0E8: // subfme (Subtract from Minus One Extended, p614) - if (Rb_addr != 0) { - vex_printf("dis_int_arith(PPC32)(subfme,Rb_addr)\n"); - return False; - } - DIP("subfme%s%s r%d,r%d\n", - flag_OE ? "o" : "", flag_Rc ? "." : "", - Rd_addr, Ra_addr); - // rD = (log not)rA + XER[CA] - 1 - assign( Rd, binop(Iop_Add32, unop(Iop_Not32, mkexpr(Ra)), - binop(Iop_Sub32, mkexpr(xer_ca), mkU32(1))) ); - op = PPC32G_FLAG_OP_SUBFME; - do_ca = True; - do_ov = True; - break; - - case 0x0C8: // subfze (Subtract from Zero Extended, p615) - if (Rb_addr != 0) { - vex_printf("dis_int_arith(PPC32)(subfze,Rb_addr)\n"); - return False; - } - DIP("subfze%s%s r%d,r%d\n", - flag_OE ? "o" : "", flag_Rc ? "." : "", - Rd_addr, Ra_addr); - // rD = (log not)rA + XER[CA] - assign( Rd, binop(Iop_Add32, unop(Iop_Not32, mkexpr(Ra)), - mkexpr(xer_ca)) ); - op = PPC32G_FLAG_OP_SUBFZE; - do_ca = True; - do_ov = True; - break; + UChar opc1 = toUChar((theInstr >> 26) & 0x3F); /* theInstr[26:31] */ + UChar Rd_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ + UChar Ra_addr = toUChar((theInstr >> 16) & 0x1F); /* theInstr[16:20] */ + + /* D-Form */ + UInt SIMM_16 = (theInstr >> 0) & 0xFFFF; /* theInstr[0:15] */ + + /* XO-Form */ + UChar Rb_addr = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */ + UChar flag_OE = toUChar((theInstr >> 10) & 1); /* theInstr[10] */ + UInt opc2 = (theInstr >> 1) & 0x1FF; /* theInstr[1:9] */ + UChar flag_Rc = toUChar((theInstr >> 0) & 1); /* theInstr[0] */ + + UInt EXTS_SIMM = 0; + + IRTemp Ra = newTemp(Ity_I32); + IRTemp Rb = newTemp(Ity_I32); + IRTemp Rd = newTemp(Ity_I32); + IRTemp res64 = newTemp(Ity_I64); // multiplies need this. + IRTemp xer_ca = newTemp(Ity_I32); + + UInt op = PPC32G_FLAG_OP_NUMBER; + Bool do_ca = False; + Bool do_ov = False; + Bool do_rc = False; + IRExpr* arg1; + IRExpr* arg2; + + assign( Ra, getIReg(Ra_addr) ); + assign( Rb, getIReg(Rb_addr) ); // XO-Form: Rd, Ra, Rb + EXTS_SIMM = extend_s_16to32(SIMM_16); // D-Form: Rd, Ra, EXTS(SIMM) + + arg1 = mkexpr(Ra); + arg2 = mkU32(EXTS_SIMM); - default: - vex_printf("dis_int_arith(PPC32)(opc2)\n"); - return False; - } - break; - default: - vex_printf("dis_int_arith(PPC32)(opc1)\n"); - return False; - } + assign( xer_ca, getReg_bit(REG_XER, OFFBIT_XER_CA) ); + - putIReg( Rd_addr, mkexpr(Rd) ); + switch (opc1) { - if (do_ov && flag_OE) { - vassert(op < PPC32G_FLAG_OP_NUMBER); - setFlags_XER_OV_SO( op, mkexpr(Rd), arg1, arg2 ); - } - if (do_ca) { - vassert(op < PPC32G_FLAG_OP_NUMBER); - setFlags_XER_CA( op, mkexpr(Rd), arg1, arg2 ); - } - if (do_rc && flag_Rc) { - setFlags_CR7( mkexpr(Rd) ); - } - return True; + /* D-Form */ + case 0x0C: // addi (Add Immediate, p380) + // li rD,val == addi rD,0,val + // la disp(rA) == addi rD,rA,disp + DIP("addi %d,%d,0x%x\n", Rd_addr, Ra_addr, SIMM_16); + if ( Ra_addr == 0 ) { + assign( Rd, mkU32(EXTS_SIMM) ); + } else { + assign( Rd, binop( Iop_Add32, mkexpr(Ra), mkU32(EXTS_SIMM) ) ); + } + break; + + case 0x0D: // addic (Add Immediate Carrying, p381) + DIP("addic r%d,r%d,0x%x\n", Rd_addr, Ra_addr, SIMM_16); + assign( Rd, binop( Iop_Add32, mkexpr(Ra), mkU32(EXTS_SIMM) ) ); + op = PPC32G_FLAG_OP_ADD; + do_ca = True; + break; + + case 0x0E: // addic. (Add Immediate Carrying and Record, p382) + DIP("addic. r%d,r%d,0x%x\n", Rd_addr, Ra_addr, SIMM_16); + assign( Rd, binop( Iop_Add32, mkexpr(Ra), mkU32(EXTS_SIMM) ) ); + op = PPC32G_FLAG_OP_ADD; + do_ca = True; + do_rc = True; + flag_Rc = 1; + break; + + case 0x0F: // addis (Add Immediate Shifted, p383) + // lis rD,val == addis rD,0,val + DIP("addis r%d,r%d,0x%x\n", Rd_addr, Ra_addr, SIMM_16); + if ( Ra_addr == 0 ) { + assign( Rd, mkU32(EXTS_SIMM << 16) ); + } else { + assign( Rd, binop(Iop_Add32, mkexpr(Ra), + mkU32(EXTS_SIMM << 16)) ); + } + break; + + case 0x07: // mulli (Multiply Low Immediate, p544) + DIP("mulli r%d,r%d,0x%x\n", Rd_addr, Ra_addr, SIMM_16); + assign( res64, binop(Iop_MullS32, mkexpr(Ra), mkU32(EXTS_SIMM)) ); + assign( Rd, unop(Iop_64to32, mkexpr(res64)) ); + break; + + case 0x08: // subfic (Subtract from Immediate Carrying, p613) + DIP("subfic r%d,r%d,0x%x\n", Rd_addr, Ra_addr, SIMM_16); + assign( Rd, binop(Iop_Add32, unop(Iop_Not32, mkexpr(Ra)), + mkU32(EXTS_SIMM)) ); + op = PPC32G_FLAG_OP_SUBFI; + do_ca = True; + break; + + + /* XO-Form */ + case 0x1F: + arg2 = mkexpr(Rb); + do_rc = True; // All below record to CR + + switch (opc2) { + case 0x10A: // add (Add, p377) + DIP("add%s%s r%d,r%d,r%d\n", + flag_OE ? "o" : "", flag_Rc ? "." : "", + Rd_addr, Ra_addr, Rb_addr); + assign( Rd, binop(Iop_Add32, mkexpr(Ra), mkexpr(Rb)) ); + op = PPC32G_FLAG_OP_ADD; + do_ov = True; + break; + + case 0x00A: // addc (Add Carrying, p378) + DIP("addc%s%s r%d,r%d,r%d\n", + flag_OE ? "o" : "", flag_Rc ? "." : "", + Rd_addr, Ra_addr, Rb_addr); + assign( Rd, binop(Iop_Add32, mkexpr(Ra), mkexpr(Rb)) ); + op = PPC32G_FLAG_OP_ADD; + do_ca = True; + do_ov = True; + break; + + case 0x08A: // adde (Add Extended, p379) + DIP("adde%s%s r%d,r%d,r%d\n", + flag_OE ? "o" : "", flag_Rc ? "." : "", + Rd_addr, Ra_addr, Rb_addr); + // rD = rA + rB + XER[CA] + assign( Rd, binop(Iop_Add32, mkexpr(Ra), + binop(Iop_Add32, mkexpr(Rb), mkexpr(xer_ca))) ); + op = PPC32G_FLAG_OP_ADDE; + do_ca = True; + do_ov = True; + break; + + case 0x0EA: // addme (Add to Minus One Extended, p384) + if (Rb_addr != 0) { + vex_printf("dis_int_arith(PPC32)(addme,Rb_addr)\n"); + return False; + } + DIP("addme%s%s r%d,r%d,r%d\n", + flag_OE ? "o" : "", flag_Rc ? "." : "", + Rd_addr, Ra_addr, Rb_addr); + // rD = rA + XER[CA] - 1 + assign( Rd, binop(Iop_Add32, mkexpr(Ra), + binop(Iop_Sub32, mkexpr(xer_ca), mkU32(1)) )); + op = PPC32G_FLAG_OP_ADDME; + do_ca = True; + do_ov = True; + break; + + case 0x0CA: // addze (Add to Zero Extended, p385) + if (Rb_addr != 0) { + vex_printf("dis_int_arith(PPC32)(addze,Rb_addr)\n"); + return False; + } + DIP("addze%s%s r%d,r%d,r%d\n", + flag_OE ? "o" : "", flag_Rc ? "." : "", + Rd_addr, Ra_addr, Rb_addr); + // rD = rA + XER[CA] + assign( Rd, binop(Iop_Add32, mkexpr(Ra), mkexpr(xer_ca)) ); + op = PPC32G_FLAG_OP_ADDZE; + do_ca = True; + do_ov = True; + break; + + case 0x1EB: // divw (Divide Word, p421) + DIP("divw%s%s r%d,r%d,r%d\n", + flag_OE ? "o" : "", flag_Rc ? "." : "", + Rd_addr, Ra_addr, Rb_addr); + assign( Rd, binop(Iop_DivS32, mkexpr(Ra), mkexpr(Rb)) ); + op = PPC32G_FLAG_OP_DIVW; + do_ov = True; + /* Note: + if (0x8000_0000 / -1) or (x / 0) + => Rd=undef, if(flag_Rc) CR7=undef, if(flag_OE) XER_OV=1 + => But _no_ exception raised. */ + break; + + case 0x1CB: // divwu (Divide Word Unsigned, p422) + DIP("divwu%s%s r%d,r%d,r%d\n", + flag_OE ? "o" : "", flag_Rc ? "." : "", + Rd_addr, Ra_addr, Rb_addr); + assign( Rd, binop(Iop_DivU32, mkexpr(Ra), mkexpr(Rb)) ); + op = PPC32G_FLAG_OP_DIVWU; + do_ov = True; + /* Note: ditto comment divw, for (x / 0) */ + break; + + case 0x04B: // mulhw (Multiply High Word, p541) + if (flag_OE != 0) { + vex_printf("dis_int_arith(PPC32)(mulhw,flag_OE)\n"); + return False; + } + DIP("mulhw%s r%d,r%d,r%d\n", flag_Rc ? "." : "", + Rd_addr, Ra_addr, Rb_addr); + assign( res64, binop(Iop_MullS32, mkexpr(Ra), mkexpr(Rb)) ); + assign( Rd, unop(Iop_64HIto32, mkexpr(res64)) ); + break; + + case 0x00B: // mulhwu (Multiply High Word Unsigned, p542) + if (flag_OE != 0) { + vex_printf("dis_int_arith(PPC32)(mulhwu,flag_OE)\n"); + return False; + } + DIP("mulhwu%s r%d,r%d,r%d\n", flag_Rc ? "." : "", + Rd_addr, Ra_addr, Rb_addr); + assign( res64, binop(Iop_MullU32, mkexpr(Ra), mkexpr(Rb)) ); + assign( Rd, unop(Iop_64HIto32, mkexpr(res64)) ); + break; + + case 0x0EB: // mullw (Multiply Low Word, p545) + DIP("mullw%s%s r%d,r%d,r%d\n", + flag_OE ? "o" : "", flag_Rc ? "." : "", + Rd_addr, Ra_addr, Rb_addr); + assign( res64, binop(Iop_MullU32, mkexpr(Ra), mkexpr(Rb)) ); + assign( Rd, unop(Iop_64to32, mkexpr(res64)) ); + op = PPC32G_FLAG_OP_MULLW; + do_ov = True; + break; + + case 0x068: // neg (Negate, p547) + if (Rb_addr != 0) { + vex_printf("dis_int_arith(PPC32)(neg,Rb_addr)\n"); + return False; + } + DIP("neg%s%s r%d,r%d\n", + flag_OE ? "o" : "", flag_Rc ? "." : "", + Rd_addr, Ra_addr); + // rD = (log not)rA + 1 + assign( Rd, binop(Iop_Add32, + unop(Iop_Not32, mkexpr(Ra)), mkU32(1)) ); + op = PPC32G_FLAG_OP_NEG; + do_ov = True; + break; + + case 0x028: // subf (Subtract From, p610) + DIP("subf%s%s r%d,r%d,r%d\n", + flag_OE ? "o" : "", flag_Rc ? "." : "", + Rd_addr, Ra_addr, Rb_addr); + // rD = (log not)rA + rB + 1 + assign( Rd, binop(Iop_Add32, unop(Iop_Not32, mkexpr(Ra)), + binop(Iop_Add32, mkexpr(Rb), mkU32(1))) ); + op = PPC32G_FLAG_OP_SUBF; + do_ov = True; + break; + + case 0x008: // subfc (Subtract from Carrying, p611) + DIP("subfc%s%s r%d,r%d,r%d\n", + flag_OE ? "o" : "", flag_Rc ? "." : "", + Rd_addr, Ra_addr, Rb_addr); + // rD = (log not)rA + rB + 1 + assign( Rd, binop(Iop_Add32, unop(Iop_Not32, mkexpr(Ra)), + binop(Iop_Add32, mkexpr(Rb), mkU32(1))) ); + op = PPC32G_FLAG_OP_SUBFC; + do_ca = True; + do_ov = True; + break; + + case 0x088: // subfe (Subtract from Extended, p612) + DIP("subfe%s%s r%d,r%d,r%d\n", + flag_OE ? "o" : "", flag_Rc ? "." : "", + Rd_addr, Ra_addr, Rb_addr); + // rD = (log not)rA + rB + XER[CA] + assign( Rd, binop(Iop_Add32, unop(Iop_Not32, mkexpr(Ra)), + binop(Iop_Add32, mkexpr(Rb), mkexpr(xer_ca))) ); + op = PPC32G_FLAG_OP_SUBFE; + do_ca = True; + do_ov = True; + break; + + case 0x0E8: // subfme (Subtract from Minus One Extended, p614) + if (Rb_addr != 0) { + vex_printf("dis_int_arith(PPC32)(subfme,Rb_addr)\n"); + return False; + } + DIP("subfme%s%s r%d,r%d\n", + flag_OE ? "o" : "", flag_Rc ? "." : "", + Rd_addr, Ra_addr); + // rD = (log not)rA + XER[CA] - 1 + assign( Rd, binop(Iop_Add32, unop(Iop_Not32, mkexpr(Ra)), + binop(Iop_Sub32, mkexpr(xer_ca), mkU32(1))) ); + op = PPC32G_FLAG_OP_SUBFME; + do_ca = True; + do_ov = True; + break; + + case 0x0C8: // subfze (Subtract from Zero Extended, p615) + if (Rb_addr != 0) { + vex_printf("dis_int_arith(PPC32)(subfze,Rb_addr)\n"); + return False; + } + DIP("subfze%s%s r%d,r%d\n", + flag_OE ? "o" : "", flag_Rc ? "." : "", + Rd_addr, Ra_addr); + // rD = (log not)rA + XER[CA] + assign( Rd, binop(Iop_Add32, unop(Iop_Not32, mkexpr(Ra)), + mkexpr(xer_ca)) ); + op = PPC32G_FLAG_OP_SUBFZE; + do_ca = True; + do_ov = True; + break; + + default: + vex_printf("dis_int_arith(PPC32)(opc2)\n"); + return False; + } + break; + default: + vex_printf("dis_int_arith(PPC32)(opc1)\n"); + return False; + } + + putIReg( Rd_addr, mkexpr(Rd) ); + + if (do_ov && flag_OE) { + vassert(op < PPC32G_FLAG_OP_NUMBER); + setFlags_XER_OV_SO( op, mkexpr(Rd), arg1, arg2 ); + } + if (do_ca) { + vassert(op < PPC32G_FLAG_OP_NUMBER); + setFlags_XER_CA( op, mkexpr(Rd), arg1, arg2 ); + } + if (do_rc && flag_Rc) { + setFlags_CR7( mkexpr(Rd) ); + } + return True; } static Bool dis_int_cmp ( UInt theInstr ) { - UChar opc1 = toUChar((theInstr >> 26) & 0x3F); /* theInstr[26:31] */ - UChar crfD = toUChar((theInstr >> 23) & 0x7); /* theInstr[23:25] */ - UChar b9 = toUChar((theInstr >> 22) & 0x1); /* theInstr[22] */ - UChar flag_L = toUChar((theInstr >> 21) & 0x1); /* theInstr[21] */ - UChar Ra_addr = toUChar((theInstr >> 16) & 0x1F); /* theInstr[16:20] */ - - /* D-Form */ - UInt SIMM_16 = (theInstr >> 0) & 0xFFFF; /* theInstr[0:15] */ - UInt UIMM_16 = (theInstr >> 0) & 0xFFFF; /* theInstr[0:15] */ - - /* X-Form */ - UChar Rb_addr = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */ - UInt opc2 = (theInstr >> 1) & 0x3FF; /* theInstr[1:10] */ - UChar b0 = toUChar((theInstr >> 0) & 1); /* theInstr[0] */ - - UInt EXTS_SIMM = 0; - IRTemp Ra = newTemp(Ity_I32); - IRTemp Rb = newTemp(Ity_I32); - IRTemp tmp = newTemp(Ity_I32); - IRTemp cr_f7 = newTemp(Ity_I32); - IRTemp tst1 = newTemp(Ity_I1); - IRTemp tst2 = newTemp(Ity_I1); - - assign( Ra, getIReg(Ra_addr) ); - - if (flag_L==1) { // L==1 invalid for 32 bit. - vex_printf("dis_int_cmp(PPC32)(flag_L)\n"); - return False; - } - - if (b9 != 0) { - vex_printf("dis_int_cmp(PPC32)(b9)\n"); - return False; - } - - switch (opc1) { - case 0x0B: // cmpi (Compare Immediate, p398) - DIP("cmpi crf%d,%u,r%d,0x%x\n", crfD, flag_L, Ra_addr, SIMM_16); - EXTS_SIMM = extend_s_16to32(SIMM_16); - assign( tst1, binop(Iop_CmpEQ32, mkU32(EXTS_SIMM), mkexpr(Ra)) ); - assign( tst2, binop(Iop_CmpLT32S, mkU32(EXTS_SIMM), mkexpr(Ra)) ); - break; - - case 0x0A: // cmpli (Compare Logical Immediate, p400) - DIP("cmpli crf%d,%u,r%d,0x%x\n", crfD, flag_L, Ra_addr, UIMM_16); - assign( tst1, binop(Iop_CmpEQ32, mkU32(UIMM_16), mkexpr(Ra)) ); - assign( tst2, binop(Iop_CmpLT32U, mkU32(UIMM_16), mkexpr(Ra)) ); - break; - - /* X Form */ - case 0x1F: - if (b0 != 0) { - vex_printf("dis_int_cmp(PPC32)(0x1F,b0)\n"); - return False; - } - - switch (opc2) { - case 0x000: // cmp (Compare, p397) - DIP("cmp crf%d,%u,r%d,r%d\n", crfD, flag_L, - Ra_addr, Rb_addr); - assign( Rb, getIReg(Rb_addr) ); - assign( tst1, binop(Iop_CmpEQ32, mkexpr(Rb), mkexpr(Ra)) ); - assign( tst2, binop(Iop_CmpLT32S, mkexpr(Rb), mkexpr(Ra)) ); - break; - - case 0x020: // cmpl (Compare Logical, p399) - DIP("cmpl crf%d,%u,r%d,r%d\n", crfD, flag_L, - Ra_addr, Rb_addr); - assign( Rb, getIReg(Rb_addr) ); - assign( tst1, binop(Iop_CmpEQ32, mkexpr(Rb), mkexpr(Ra)) ); - assign( tst2, binop(Iop_CmpLT32U, mkexpr(Rb), mkexpr(Ra)) ); - break; - - default: - vex_printf("dis_int_cmp(PPC32)(opc2)\n"); - return False; - } - break; + UChar opc1 = toUChar((theInstr >> 26) & 0x3F); /* theInstr[26:31] */ + UChar crfD = toUChar((theInstr >> 23) & 0x7); /* theInstr[23:25] */ + UChar b9 = toUChar((theInstr >> 22) & 0x1); /* theInstr[22] */ + UChar flag_L = toUChar((theInstr >> 21) & 0x1); /* theInstr[21] */ + UChar Ra_addr = toUChar((theInstr >> 16) & 0x1F); /* theInstr[16:20] */ + + /* D-Form */ + UInt SIMM_16 = (theInstr >> 0) & 0xFFFF; /* theInstr[0:15] */ + UInt UIMM_16 = (theInstr >> 0) & 0xFFFF; /* theInstr[0:15] */ + + /* X-Form */ + UChar Rb_addr = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */ + UInt opc2 = (theInstr >> 1) & 0x3FF; /* theInstr[1:10] */ + UChar b0 = toUChar((theInstr >> 0) & 1); /* theInstr[0] */ + + UInt EXTS_SIMM = 0; + IRTemp Ra = newTemp(Ity_I32); + IRTemp Rb = newTemp(Ity_I32); + IRTemp tmp = newTemp(Ity_I32); + IRTemp cr_f7 = newTemp(Ity_I32); + IRTemp tst1 = newTemp(Ity_I1); + IRTemp tst2 = newTemp(Ity_I1); + + assign( Ra, getIReg(Ra_addr) ); + + if (flag_L==1) { // L==1 invalid for 32 bit. + vex_printf("dis_int_cmp(PPC32)(flag_L)\n"); + return False; + } + + if (b9 != 0) { + vex_printf("dis_int_cmp(PPC32)(b9)\n"); + return False; + } + + switch (opc1) { + case 0x0B: // cmpi (Compare Immediate, p398) + DIP("cmpi crf%d,%u,r%d,0x%x\n", crfD, flag_L, Ra_addr, SIMM_16); + EXTS_SIMM = extend_s_16to32(SIMM_16); + assign( tst1, binop(Iop_CmpEQ32, mkU32(EXTS_SIMM), mkexpr(Ra)) ); + assign( tst2, binop(Iop_CmpLT32S, mkU32(EXTS_SIMM), mkexpr(Ra)) ); + break; + + case 0x0A: // cmpli (Compare Logical Immediate, p400) + DIP("cmpli crf%d,%u,r%d,0x%x\n", crfD, flag_L, Ra_addr, UIMM_16); + assign( tst1, binop(Iop_CmpEQ32, mkU32(UIMM_16), mkexpr(Ra)) ); + assign( tst2, binop(Iop_CmpLT32U, mkU32(UIMM_16), mkexpr(Ra)) ); + break; + + /* X Form */ + case 0x1F: + if (b0 != 0) { + vex_printf("dis_int_cmp(PPC32)(0x1F,b0)\n"); + return False; + } - default: - vex_printf("dis_int_cmp(PPC32)(opc1)\n"); - return False; - } + switch (opc2) { + case 0x000: // cmp (Compare, p397) + DIP("cmp crf%d,%u,r%d,r%d\n", crfD, flag_L, + Ra_addr, Rb_addr); + assign( Rb, getIReg(Rb_addr) ); + assign( tst1, binop(Iop_CmpEQ32, mkexpr(Rb), mkexpr(Ra)) ); + assign( tst2, binop(Iop_CmpLT32S, mkexpr(Rb), mkexpr(Ra)) ); + break; + + case 0x020: // cmpl (Compare Logical, p399) + DIP("cmpl crf%d,%u,r%d,r%d\n", crfD, flag_L, + Ra_addr, Rb_addr); + assign( Rb, getIReg(Rb_addr) ); + assign( tst1, binop(Iop_CmpEQ32, mkexpr(Rb), mkexpr(Ra)) ); + assign( tst2, binop(Iop_CmpLT32U, mkexpr(Rb), mkexpr(Ra)) ); + break; - assign( tmp, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(tst1)), - IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(tst2)), - mkU32(8), mkU32(4) ), - mkU32(2) )); + default: + vex_printf("dis_int_cmp(PPC32)(opc2)\n"); + return False; + } + break; - assign( cr_f7, binop(Iop_Or32, mkexpr(tmp), - getReg_bit(REG_XER, OFFBIT_XER_SO)) ); - putReg_field( REG_CR, 7-crfD, mkexpr(cr_f7) ); - return True; + default: + vex_printf("dis_int_cmp(PPC32)(opc1)\n"); + return False; + } + + assign( tmp, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(tst1)), + IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(tst2)), + mkU32(8), mkU32(4) ), + mkU32(2) )); + + assign( cr_f7, binop(Iop_Or32, mkexpr(tmp), + getReg_bit(REG_XER, OFFBIT_XER_SO)) ); + putReg_field( REG_CR, 7-crfD, mkexpr(cr_f7) ); + return True; } static Bool dis_int_logic ( UInt theInstr ) { - UChar opc1 = toUChar((theInstr >> 26) & 0x3F); /* theInstr[26:31] */ - UChar Rs_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ - UChar Ra_addr = toUChar((theInstr >> 16) & 0x1F); /* theInstr[16:20] */ - - /* D-Form */ - UInt UIMM_16 = (theInstr >> 0) & 0xFFFF; /* theInstr[0:15] */ - - /* X-Form */ - UChar Rb_addr = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */ - UInt opc2 = (theInstr >> 1) & 0x3FF; /* theInstr[1:10] */ - UChar flag_Rc = toUChar((theInstr >> 0) & 1); /* theInstr[0] */ - - Bool do_rc = False; - - IRTemp Rs = newTemp(Ity_I32); - IRTemp Ra = newTemp(Ity_I32); - IRTemp Rb = newTemp(Ity_I32); - IRTemp Sign = newTemp(Ity_I32); - - assign( Rs, getIReg(Ra_addr) ); - assign( Rb, getIReg(Ra_addr) ); - - switch (opc1) { - case 0x1C: // andi. (AND Immediate, p388) - DIP("andi r%d,r%d,0x%x\n", Ra_addr, Rs_addr, UIMM_16); - assign( Ra, binop(Iop_And32, mkexpr(Rs), mkU32(UIMM_16)) ); - putIReg( Ra_addr, mkexpr(Ra) ); - do_rc = True; - flag_Rc = 1; - break; - - case 0x1D: // andis. (AND Immediate Shifted, p389) - DIP("andis r%d,r%d,0x%x\n", Ra_addr, Rs_addr, UIMM_16); - assign( Ra, binop(Iop_And32, mkexpr(Rs), mkU32(UIMM_16 << 16)) ); - putIReg( Ra_addr, mkexpr(Ra) ); - do_rc = True; - flag_Rc = 1; - break; - - case 0x18: // ori (OR Immediate, p551) - DIP("ori r%d,r%d,0x%x\n", Ra_addr, Rs_addr, UIMM_16); - putIReg( Ra_addr, binop(Iop_Or32, mkexpr(Rs), mkU32(UIMM_16)) ); - break; - - case 0x19: // oris (OR Immediate Shifted, p552) - DIP("oris r%d,r%d,0x%x\n", Ra_addr, Rs_addr, UIMM_16); - putIReg( Ra_addr, binop(Iop_Or32, mkexpr(Rs), mkU32(UIMM_16 << 16)) ); - break; - - case 0x1A: // xori (XOR Immediate, p625) - DIP("xori r%d,r%d,0x%x\n", Ra_addr, Rs_addr, UIMM_16); - putIReg( Ra_addr, binop(Iop_Xor32, mkexpr(Rs), mkU32(UIMM_16)) ); - break; - - case 0x1B: // xoris (XOR Immediate Shifted, p626) - DIP("xoris r%d,r%d,0x%x\n", Ra_addr, Rs_addr, UIMM_16); - putIReg( Ra_addr, binop(Iop_Xor32, mkexpr(Rs), mkU32(UIMM_16 << 16)) ); - break; - - /* X Form */ - case 0x1F: - switch (opc2) { - case 0x01C: // and (AND, p386) - DIP("and%s r%d,r%d,r%d\n", - flag_Rc ? "." : "", Ra_addr, Rs_addr, Rb_addr); - assign(Ra, binop(Iop_And32, mkexpr(Rs), mkexpr(Rb))); - break; - - case 0x03C: // andc (AND with Complement, p387) - DIP("andc%s r%d,r%d,r%d\n", - flag_Rc ? "." : "", Ra_addr, Rs_addr, Rb_addr); - assign(Ra, binop(Iop_And32, mkexpr(Rs), - unop(Iop_Not32, mkexpr(Rb)))); - break; - - case 0x01A: // cntlzw (Count Leading Zeros Word, p402) - if (Rb_addr!=0) { - vex_printf("dis_int_logic(PPC32)(cntlzw,Rb_addr)\n"); - return False; - } - DIP("cntlzw%s r%d,r%d\n", - flag_Rc ? "." : "", Ra_addr, Rs_addr); - - // Iop_Clz32 undefined for arg==0, so deal with that case: - assign(Ra, IRExpr_Mux0X( - unop(Iop_1Uto8, binop(Iop_CmpNE32, - mkexpr(Rs), mkU32(0))), - mkU32(32), - unop(Iop_Clz32, mkexpr(Rs)) )); - break; - - case 0x11C: // eqv (Equivalent, p427) - DIP("eqv%s r%d,r%d,r%d\n", - flag_Rc ? "." : "", Ra_addr, Rs_addr, Rb_addr); - assign( Ra, unop(Iop_Not32, binop(Iop_Xor32, - mkexpr(Rs), mkexpr(Rb))) ); - break; - - case 0x3BA: // extsb (Extend Sign Byte, p428) - if (Rb_addr!=0) { - vex_printf("dis_int_logic(PPC32)(extsb,Rb_addr)\n"); - return False; - } - DIP("extsb%s r%d,r%d\n", - flag_Rc ? "." : "", Ra_addr, Rs_addr); - assign( Sign, binop(Iop_And32, mkU32(0x80), mkexpr(Rs)) ); - assign( Ra, IRExpr_Mux0X( - unop(Iop_1Uto8, binop(Iop_CmpEQ32, - mkexpr(Sign), mkU32(0))), - binop(Iop_Or32, mkU32(0xFFFFFF00), mkexpr(Rs)), - binop(Iop_And32, mkU32(0x000000FF), mkexpr(Rs)) )); - break; - - case 0x39A: // extsh (Extend Sign Half Word, p429) - if (Rb_addr!=0) { - vex_printf("dis_int_logic(PPC32)(extsh,Rb_addr)\n"); - return False; - } - DIP("extsh%s r%d,r%d\n", - flag_Rc ? "." : "", Ra_addr, Rs_addr); - assign( Sign, binop(Iop_And32, mkU32(0x8000), mkexpr(Rs)) ); - assign( Ra, IRExpr_Mux0X( - unop(Iop_1Uto8, binop(Iop_CmpEQ32, - mkexpr(Sign), mkU32(0))), - binop(Iop_Or32, mkU32(0xFFFF0000), mkexpr(Rs)), - binop(Iop_And32, mkU32(0x0000FFFF), mkexpr(Rs)) )); - break; - - case 0x1DC: // nand (NAND, p546) - DIP("nand%s r%d,r%d,r%d\n", - flag_Rc ? "." : "", Ra_addr, Rs_addr, Rb_addr); - assign( Ra, unop(Iop_Not32, - binop(Iop_And32, mkexpr(Rs), mkexpr(Rb))) ); - break; - - case 0x07C: // nor (NOR, p548) - DIP("nor%s r%d,r%d,r%d\n", - flag_Rc ? "." : "", Ra_addr, Rs_addr, Rb_addr); - assign( Ra, unop(Iop_Not32, - binop(Iop_Or32, mkexpr(Rs), mkexpr(Rb))) ); - break; - - case 0x1BC: // or (OR, p549) - DIP("or%s r%d,r%d,r%d\n", - flag_Rc ? "." : "", Ra_addr, Rs_addr, Rb_addr); - assign( Ra, binop(Iop_Or32, mkexpr(Rs), mkexpr(Rb)) ); - break; - - case 0x19C: // orc (OR with Complement, p550) - DIP("orc%s r%d,r%d,r%d\n", - flag_Rc ? "." : "", Ra_addr, Rs_addr, Rb_addr); - assign( Ra, binop(Iop_Or32, mkexpr(Rs), - unop(Iop_Not32, mkexpr(Rb))) ); - break; - - case 0x13C: // xor (XOR, p624) - DIP("xor%s r%d,r%d,r%d\n", - flag_Rc ? "." : "", Ra_addr, Rs_addr, Rb_addr); - assign( Ra, binop(Iop_Xor32, mkexpr(Rs), mkexpr(Rb)) ); - break; - - default: - vex_printf("dis_int_logic(PPC32)(opc2)\n"); - return False; - } - - putIReg( Ra_addr, mkexpr(Ra) ); - do_rc = True; - break; - - default: - vex_printf("dis_int_logic(PPC32)(opc1)\n"); - return False; - } + UChar opc1 = toUChar((theInstr >> 26) & 0x3F); /* theInstr[26:31] */ + UChar Rs_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ + UChar Ra_addr = toUChar((theInstr >> 16) & 0x1F); /* theInstr[16:20] */ + + /* D-Form */ + UInt UIMM_16 = (theInstr >> 0) & 0xFFFF; /* theInstr[0:15] */ + + /* X-Form */ + UChar Rb_addr = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */ + UInt opc2 = (theInstr >> 1) & 0x3FF; /* theInstr[1:10] */ + UChar flag_Rc = toUChar((theInstr >> 0) & 1); /* theInstr[0] */ + + Bool do_rc = False; + + IRTemp Rs = newTemp(Ity_I32); + IRTemp Ra = newTemp(Ity_I32); + IRTemp Rb = newTemp(Ity_I32); + IRTemp Sign = newTemp(Ity_I32); + + assign( Rs, getIReg(Ra_addr) ); + assign( Rb, getIReg(Ra_addr) ); + + switch (opc1) { + case 0x1C: // andi. (AND Immediate, p388) + DIP("andi r%d,r%d,0x%x\n", Ra_addr, Rs_addr, UIMM_16); + assign( Ra, binop(Iop_And32, mkexpr(Rs), mkU32(UIMM_16)) ); + putIReg( Ra_addr, mkexpr(Ra) ); + do_rc = True; + flag_Rc = 1; + break; + + case 0x1D: // andis. (AND Immediate Shifted, p389) + DIP("andis r%d,r%d,0x%x\n", Ra_addr, Rs_addr, UIMM_16); + assign( Ra, binop(Iop_And32, mkexpr(Rs), mkU32(UIMM_16 << 16)) ); + putIReg( Ra_addr, mkexpr(Ra) ); + do_rc = True; + flag_Rc = 1; + break; + + case 0x18: // ori (OR Immediate, p551) + DIP("ori r%d,r%d,0x%x\n", Ra_addr, Rs_addr, UIMM_16); + putIReg( Ra_addr, binop(Iop_Or32, mkexpr(Rs), mkU32(UIMM_16)) ); + break; + + case 0x19: // oris (OR Immediate Shifted, p552) + DIP("oris r%d,r%d,0x%x\n", Ra_addr, Rs_addr, UIMM_16); + putIReg( Ra_addr, binop(Iop_Or32, mkexpr(Rs), mkU32(UIMM_16 << 16)) ); + break; + + case 0x1A: // xori (XOR Immediate, p625) + DIP("xori r%d,r%d,0x%x\n", Ra_addr, Rs_addr, UIMM_16); + putIReg( Ra_addr, binop(Iop_Xor32, mkexpr(Rs), mkU32(UIMM_16)) ); + break; + + case 0x1B: // xoris (XOR Immediate Shifted, p626) + DIP("xoris r%d,r%d,0x%x\n", Ra_addr, Rs_addr, UIMM_16); + putIReg( Ra_addr, binop(Iop_Xor32, mkexpr(Rs), mkU32(UIMM_16 << 16)) ); + break; + + /* X Form */ + case 0x1F: + switch (opc2) { + case 0x01C: // and (AND, p386) + DIP("and%s r%d,r%d,r%d\n", + flag_Rc ? "." : "", Ra_addr, Rs_addr, Rb_addr); + assign(Ra, binop(Iop_And32, mkexpr(Rs), mkexpr(Rb))); + break; + + case 0x03C: // andc (AND with Complement, p387) + DIP("andc%s r%d,r%d,r%d\n", + flag_Rc ? "." : "", Ra_addr, Rs_addr, Rb_addr); + assign(Ra, binop(Iop_And32, mkexpr(Rs), + unop(Iop_Not32, mkexpr(Rb)))); + break; + + case 0x01A: // cntlzw (Count Leading Zeros Word, p402) + if (Rb_addr!=0) { + vex_printf("dis_int_logic(PPC32)(cntlzw,Rb_addr)\n"); + return False; + } + DIP("cntlzw%s r%d,r%d\n", + flag_Rc ? "." : "", Ra_addr, Rs_addr); + + // Iop_Clz32 undefined for arg==0, so deal with that case: + assign(Ra, IRExpr_Mux0X( + unop(Iop_1Uto8, binop(Iop_CmpNE32, + mkexpr(Rs), mkU32(0))), + mkU32(32), + unop(Iop_Clz32, mkexpr(Rs)) )); + break; + + case 0x11C: // eqv (Equivalent, p427) + DIP("eqv%s r%d,r%d,r%d\n", + flag_Rc ? "." : "", Ra_addr, Rs_addr, Rb_addr); + assign( Ra, unop(Iop_Not32, binop(Iop_Xor32, + mkexpr(Rs), mkexpr(Rb))) ); + break; + + case 0x3BA: // extsb (Extend Sign Byte, p428) + if (Rb_addr!=0) { + vex_printf("dis_int_logic(PPC32)(extsb,Rb_addr)\n"); + return False; + } + DIP("extsb%s r%d,r%d\n", + flag_Rc ? "." : "", Ra_addr, Rs_addr); + assign( Sign, binop(Iop_And32, mkU32(0x80), mkexpr(Rs)) ); + assign( Ra, IRExpr_Mux0X( + unop(Iop_1Uto8, binop(Iop_CmpEQ32, + mkexpr(Sign), mkU32(0))), + binop(Iop_Or32, mkU32(0xFFFFFF00), mkexpr(Rs)), + binop(Iop_And32, mkU32(0x000000FF), mkexpr(Rs)) )); + break; + + case 0x39A: // extsh (Extend Sign Half Word, p429) + if (Rb_addr!=0) { + vex_printf("dis_int_logic(PPC32)(extsh,Rb_addr)\n"); + return False; + } + DIP("extsh%s r%d,r%d\n", + flag_Rc ? "." : "", Ra_addr, Rs_addr); + assign( Sign, binop(Iop_And32, mkU32(0x8000), mkexpr(Rs)) ); + assign( Ra, IRExpr_Mux0X( + unop(Iop_1Uto8, binop(Iop_CmpEQ32, + mkexpr(Sign), mkU32(0))), + binop(Iop_Or32, mkU32(0xFFFF0000), mkexpr(Rs)), + binop(Iop_And32, mkU32(0x0000FFFF), mkexpr(Rs)) )); + break; + + case 0x1DC: // nand (NAND, p546) + DIP("nand%s r%d,r%d,r%d\n", + flag_Rc ? "." : "", Ra_addr, Rs_addr, Rb_addr); + assign( Ra, unop(Iop_Not32, + binop(Iop_And32, mkexpr(Rs), mkexpr(Rb))) ); + break; + + case 0x07C: // nor (NOR, p548) + DIP("nor%s r%d,r%d,r%d\n", + flag_Rc ? "." : "", Ra_addr, Rs_addr, Rb_addr); + assign( Ra, unop(Iop_Not32, + binop(Iop_Or32, mkexpr(Rs), mkexpr(Rb))) ); + break; + + case 0x1BC: // or (OR, p549) + DIP("or%s r%d,r%d,r%d\n", + flag_Rc ? "." : "", Ra_addr, Rs_addr, Rb_addr); + assign( Ra, binop(Iop_Or32, mkexpr(Rs), mkexpr(Rb)) ); + break; + + case 0x19C: // orc (OR with Complement, p550) + DIP("orc%s r%d,r%d,r%d\n", + flag_Rc ? "." : "", Ra_addr, Rs_addr, Rb_addr); + assign( Ra, binop(Iop_Or32, mkexpr(Rs), + unop(Iop_Not32, mkexpr(Rb))) ); + break; + + case 0x13C: // xor (XOR, p624) + DIP("xor%s r%d,r%d,r%d\n", + flag_Rc ? "." : "", Ra_addr, Rs_addr, Rb_addr); + assign( Ra, binop(Iop_Xor32, mkexpr(Rs), mkexpr(Rb)) ); + break; + + default: + vex_printf("dis_int_logic(PPC32)(opc2)\n"); + return False; + } - if (do_rc && flag_Rc) { - setFlags_CR7( mkexpr(Ra) ); - } - return True; + putIReg( Ra_addr, mkexpr(Ra) ); + do_rc = True; + break; + + default: + vex_printf("dis_int_logic(PPC32)(opc1)\n"); + return False; + } + + if (do_rc && flag_Rc) { + setFlags_CR7( mkexpr(Ra) ); + } + return True; } static Bool dis_int_rot ( UInt theInstr ) { - /* M-Form */ - UChar opc1 = toUChar((theInstr >> 26) & 0x3F); /* theInstr[26:31] */ - UChar Rs_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ - UChar Ra_addr = toUChar((theInstr >> 16) & 0x1F); /* theInstr[16:20] */ - UChar Rb_addr = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */ - UChar sh_imm = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */ - UChar MaskBegin = toUChar((theInstr >> 6) & 0x1F); /* theInstr[6:10] */ - UChar MaskEnd = toUChar((theInstr >> 1) & 0x1F); /* theInstr[1:5] */ - UChar flag_Rc = toUChar((theInstr >> 0) & 1); /* theInstr[0] */ - - UInt mask = MASK(MaskBegin, MaskEnd); - IRTemp rot_amt = newTemp(Ity_I8); - IRTemp Rs = newTemp(Ity_I32); - IRTemp Ra = newTemp(Ity_I32); - IRTemp Rb = newTemp(Ity_I32); - - assign( Rs, getIReg(Rs_addr) ); - assign( Rb, getIReg(Rb_addr) ); - - - switch (opc1) { - case 0x14: // rlwimi (Rotate Left Word Immediate then Mask Insert, p561) - 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, - binop(Iop_And32, mkU32(mask), - ROTL32(mkexpr(Rs), mkU8(sh_imm))), - binop(Iop_And32, getIReg(Ra_addr), mkU32(~mask))) ); - break; - - case 0x15: // rlwinm (Rotate Left Word Immediate then AND with Mask, p562) - 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), - mkU8(sh_imm)), mkU32(mask)) ); - break; - - case 0x17: // rlwnm (Rotate Left Word then AND with Mask, p564) - 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, narrowTo(Ity_I8, binop(Iop_And32, - mkexpr(Rb), mkU32(0x1F))) ); - assign( Ra, binop(Iop_And32, ROTL32(mkexpr(Rs), - mkexpr(rot_amt)), mkU32(mask)) ); - break; + /* M-Form */ + UChar opc1 = toUChar((theInstr >> 26) & 0x3F); /* theInstr[26:31] */ + UChar Rs_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ + UChar Ra_addr = toUChar((theInstr >> 16) & 0x1F); /* theInstr[16:20] */ + UChar Rb_addr = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */ + UChar sh_imm = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */ + UChar MaskBegin = toUChar((theInstr >> 6) & 0x1F); /* theInstr[6:10] */ + UChar MaskEnd = toUChar((theInstr >> 1) & 0x1F); /* theInstr[1:5] */ + UChar flag_Rc = toUChar((theInstr >> 0) & 1); /* theInstr[0] */ + + UInt mask = MASK(MaskBegin, MaskEnd); + IRTemp rot_amt = newTemp(Ity_I8); + IRTemp Rs = newTemp(Ity_I32); + IRTemp Ra = newTemp(Ity_I32); + IRTemp Rb = newTemp(Ity_I32); + + assign( Rs, getIReg(Rs_addr) ); + assign( Rb, getIReg(Rb_addr) ); + + + switch (opc1) { + case 0x14: // rlwimi (Rotate Left Word Immediate then Mask Insert, p561) + 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, + binop(Iop_And32, mkU32(mask), + ROTL32(mkexpr(Rs), mkU8(sh_imm))), + binop(Iop_And32, getIReg(Ra_addr), mkU32(~mask))) ); + break; + + case 0x15: // rlwinm (Rotate Left Word Immediate then AND with Mask, p562) + 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), + mkU8(sh_imm)), mkU32(mask)) ); + break; + + case 0x17: // rlwnm (Rotate Left Word then AND with Mask, p564) + 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, + narrowTo(Ity_I8, binop(Iop_And32, mkexpr(Rb), mkU32(0x1F))) ); + assign( Ra, binop(Iop_And32, + ROTL32(mkexpr(Rs), mkexpr(rot_amt)), mkU32(mask)) ); + break; - default: - vex_printf("dis_int_rot(PPC32)(opc1)\n"); - return False; - } - putIReg( Ra_addr, mkexpr(Ra) ); - if (flag_Rc) { - setFlags_CR7( mkexpr(Ra) ); - } - return True; + default: + vex_printf("dis_int_rot(PPC32)(opc1)\n"); + return False; + } + + putIReg( Ra_addr, mkexpr(Ra) ); + if (flag_Rc) { + setFlags_CR7( mkexpr(Ra) ); + } + return True; } static Bool dis_int_load ( UInt theInstr ) { - UChar opc1 = toUChar((theInstr >> 26) & 0x3F); /* theInstr[26:31] */ - UChar Rd_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ - UChar Ra_addr = toUChar((theInstr >> 16) & 0x1F); /* theInstr[16:20] */ - - /* D-Form */ - UInt d_imm = (theInstr >> 0) & 0xFFFF; /* theInstr[0:15] */ - - /* X-Form */ - UChar Rb_addr = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */ - UInt opc2 = (theInstr >> 1) & 0x3FF; /* theInstr[1:10] */ - UChar b0 = toUChar((theInstr >> 0) & 1); /* theInstr[0] */ - - UInt exts_d_imm = extend_s_16to32(d_imm); - - IRTemp Ra_or_0 = newTemp(Ity_I32); - IRTemp EA_imm = newTemp(Ity_I32); - IRTemp EA_reg = newTemp(Ity_I32); - IRTemp Ra = newTemp(Ity_I32); - IRTemp Rb = newTemp(Ity_I32); - - assign( Ra, getIReg(Ra_addr) ); - assign( Rb, getIReg(Rb_addr) ); - - if (Ra_addr == 0) { - assign( Ra_or_0, mkU32(0) ); - } else { - assign( Ra_or_0, mkexpr(Ra) ); - } - assign( EA_imm, binop(Iop_And32, mkexpr(Ra_or_0), mkU32(exts_d_imm)) ); - - switch (opc1) { - case 0x22: // lbz (Load B & Zero, p468) - DIP("lbz r%d,%u(r%d)\n", Rd_addr, d_imm, Ra_addr); - putIReg( Rd_addr, unop(Iop_8Uto32, - loadBE(Ity_I8, mkexpr(EA_imm))) ); - break; - - case 0x23: // lbzu (Load B & Zero with Update, p469) - if (Ra_addr == 0 || Ra_addr == Rd_addr) { - vex_printf("dis_int_load(PPC32)(lbzu,Ra_addr|Rd_addr)\n"); - return False; - } - DIP("lbzu r%d,%u(r%d)\n", Rd_addr, d_imm, Ra_addr); - putIReg( Rd_addr, unop(Iop_8Uto32, - loadBE(Ity_I8, mkexpr(EA_imm))) ); - putIReg( Ra_addr, mkexpr(EA_imm) ); - break; - - case 0x2A: // lha (Load HW Algebraic, p485) - DIP("lha r%d,%u(r%d)\n", Rd_addr, d_imm, Ra_addr); - putIReg( Rd_addr, unop(Iop_16Sto32, - loadBE(Ity_I16, mkexpr(EA_imm))) ); - break; - - case 0x2B: // lhau (Load HW Algebraic with Update, p486) - if (Ra_addr == 0 || Ra_addr == Rd_addr) { - vex_printf("dis_int_load(PPC32)(lhau,Ra_addr|Rd_addr)\n"); - return False; - } - DIP("lhau r%d,%u(r%d)\n", Rd_addr, d_imm, Ra_addr); - putIReg( Rd_addr, unop(Iop_16Sto32, - loadBE(Ity_I16, mkexpr(EA_imm))) ); - putIReg( Ra_addr, mkexpr(EA_imm) ); - break; - - case 0x28: // lhz (Load HW & Zero, p490) - DIP("lhz r%d,%u(r%d)\n", Rd_addr, d_imm, Ra_addr); - putIReg( Rd_addr, unop(Iop_16Sto32, - loadBE(Ity_I16, mkexpr(EA_imm))) ); - break; - - case 0x29: // lhzu (Load HW & and Zero with Update, p491) - if (Ra_addr == 0 || Ra_addr == Rd_addr) { - vex_printf("dis_int_load(PPC32)(lhzu,Ra_addr|Rd_addr)\n"); - return False; - } - DIP("lhzu r%d,%u(r%d)\n", Rd_addr, d_imm, Ra_addr); - putIReg( Rd_addr, loadBE(Ity_I16, mkexpr(EA_imm)) ); - putIReg( Ra_addr, mkexpr(EA_imm) ); - break; - - case 0x20: // lwz (Load W & Zero, p504) - DIP("lwz r%d,%u(r%d)\n", Rd_addr, d_imm, Ra_addr); - putIReg( Rd_addr, loadBE(Ity_I32, mkexpr(EA_imm)) ); - break; - - case 0x21: // lwzu (Load W & Zero with Update, p505)) - if (Ra_addr == 0 || Ra_addr == Rd_addr) { - vex_printf("dis_int_load(PPC32)(lwzu,Ra_addr|Rd_addr)\n"); - return False; - } - DIP("lwzu r%d,%u(r%d)\n", Rd_addr, d_imm, Ra_addr); - putIReg( Rd_addr, loadBE(Ity_I32, mkexpr(EA_imm)) ); - putIReg( Ra_addr, mkexpr(EA_imm) ); - break; - - /* X Form */ - case 0x1F: - if (b0 != 0) { - vex_printf("dis_int_load(PPC32)(Ox1F,b0)\n"); - return False; - } - assign( EA_reg, binop(Iop_And32, mkexpr(Ra_or_0), mkexpr(Rb)) ); - - switch (opc2) { - case 0x077: // lbzux (Load B & Zero with Update Indexed, p470) - DIP("lbzux r%d,r%d,r%d\n", Rd_addr, Ra_addr, Rb_addr); - if (Ra_addr == 0 || Ra_addr == Rd_addr) { - vex_printf("dis_int_load(PPC32)(lwzux,Ra_addr|Rd_addr)\n"); - return False; - } - putIReg( Rd_addr, unop(Iop_8Uto32, - loadBE(Ity_I8, mkexpr(EA_reg))) ); - putIReg( Ra_addr, mkexpr(EA_reg) ); - break; - - case 0x057: // lbzx (Load B & Zero Indexed, p471) - DIP("lbzx r%d,r%d,r%d\n", Rd_addr, Ra_addr, Rb_addr); - putIReg( Rd_addr, unop(Iop_8Uto32, - loadBE(Ity_I8, mkexpr(EA_reg))) ); - break; - - case 0x177: // lhaux (Load HW Algebraic with Update Indexed, p487) - if (Ra_addr == 0 || Ra_addr == Rd_addr) { - vex_printf("dis_int_load(PPC32)(lhaux,Ra_addr|Rd_addr)\n"); - return False; - } - DIP("lhaux r%d,r%d,r%d\n", Rd_addr, Ra_addr, Rb_addr); - putIReg( Rd_addr, unop(Iop_16Sto32, - loadBE(Ity_I16, mkexpr(EA_reg))) ); - putIReg( Ra_addr, mkexpr(EA_reg) ); - break; - - case 0x157: // lhax (Load HW Algebraic Indexed, p488) - DIP("lhax r%d,r%d,r%d\n", Rd_addr, Ra_addr, Rb_addr); - putIReg( Rd_addr, unop(Iop_16Sto32, - loadBE(Ity_I16, mkexpr(EA_reg))) ); - break; - - case 0x137: // lhzux (Load HW & Zero with Update Indexed, p492) - if (Ra_addr == 0 || Ra_addr == Rd_addr) { - vex_printf("dis_int_load(PPC32)(lhzux,Ra_addr|Rd_addr)\n"); - return False; - } - DIP("lhzux r%d,r%d,r%d\n", Rd_addr, Ra_addr, Rb_addr); - putIReg( Rd_addr, unop(Iop_16Sto32, - loadBE(Ity_I16, mkexpr(EA_reg))) ); - putIReg( Ra_addr, mkexpr(EA_reg) ); - break; - - case 0x117: // lhzx (Load HW & Zero Indexed, p493) - DIP("lhzx r%d,r%d,r%d\n", Rd_addr, Ra_addr, Rb_addr); - putIReg( Rd_addr, unop(Iop_16Sto32, - loadBE(Ity_I16, mkexpr(EA_reg))) ); - break; - - case 0x037: // lwzux (Load W & Zero with Update Indexed, p506) - if (Ra_addr == 0 || Ra_addr == Rd_addr) { - vex_printf("dis_int_load(PPC32)(lwzux,Ra_addr|Rd_addr)\n"); - return False; - } - DIP("lwzux r%d,r%d,r%d\n", Rd_addr, Ra_addr, Rb_addr); - putIReg( Rd_addr, loadBE(Ity_I32, mkexpr(EA_reg)) ); - putIReg( Ra_addr, mkexpr(EA_reg) ); - break; - - case 0x017: // lwzx (Load W & Zero Indexed, p507) - DIP("lwzx r%d,r%d,r%d\n", Rd_addr, Ra_addr, Rb_addr); - putIReg( Rd_addr, loadBE(Ity_I32, mkexpr(EA_reg)) ); - break; - - default: - vex_printf("dis_int_load(PPC32)(opc2)\n"); - return False; - } - break; - default: - vex_printf("dis_int_load(PPC32)(opc1)\n"); - return False; - } - return True; + UChar opc1 = toUChar((theInstr >> 26) & 0x3F); /* theInstr[26:31] */ + UChar Rd_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ + UChar Ra_addr = toUChar((theInstr >> 16) & 0x1F); /* theInstr[16:20] */ + + /* D-Form */ + UInt d_imm = (theInstr >> 0) & 0xFFFF; /* theInstr[0:15] */ + + /* X-Form */ + UChar Rb_addr = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */ + UInt opc2 = (theInstr >> 1) & 0x3FF; /* theInstr[1:10] */ + UChar b0 = toUChar((theInstr >> 0) & 1); /* theInstr[0] */ + + UInt exts_d_imm = extend_s_16to32(d_imm); + + IRTemp Ra_or_0 = newTemp(Ity_I32); + IRTemp EA_imm = newTemp(Ity_I32); + IRTemp EA_reg = newTemp(Ity_I32); + IRTemp Ra = newTemp(Ity_I32); + IRTemp Rb = newTemp(Ity_I32); + + assign( Ra, getIReg(Ra_addr) ); + assign( Rb, getIReg(Rb_addr) ); + + if (Ra_addr == 0) { + assign( Ra_or_0, mkU32(0) ); + } else { + assign( Ra_or_0, mkexpr(Ra) ); + } + assign( EA_imm, binop(Iop_And32, mkexpr(Ra_or_0), mkU32(exts_d_imm)) ); + + switch (opc1) { + case 0x22: // lbz (Load B & Zero, p468) + DIP("lbz r%d,%u(r%d)\n", Rd_addr, d_imm, Ra_addr); + putIReg( Rd_addr, unop(Iop_8Uto32, + loadBE(Ity_I8, mkexpr(EA_imm))) ); + break; + + case 0x23: // lbzu (Load B & Zero with Update, p469) + if (Ra_addr == 0 || Ra_addr == Rd_addr) { + vex_printf("dis_int_load(PPC32)(lbzu,Ra_addr|Rd_addr)\n"); + return False; + } + DIP("lbzu r%d,%u(r%d)\n", Rd_addr, d_imm, Ra_addr); + putIReg( Rd_addr, unop(Iop_8Uto32, + loadBE(Ity_I8, mkexpr(EA_imm))) ); + putIReg( Ra_addr, mkexpr(EA_imm) ); + break; + + case 0x2A: // lha (Load HW Algebraic, p485) + DIP("lha r%d,%u(r%d)\n", Rd_addr, d_imm, Ra_addr); + putIReg( Rd_addr, unop(Iop_16Sto32, + loadBE(Ity_I16, mkexpr(EA_imm))) ); + break; + + case 0x2B: // lhau (Load HW Algebraic with Update, p486) + if (Ra_addr == 0 || Ra_addr == Rd_addr) { + vex_printf("dis_int_load(PPC32)(lhau,Ra_addr|Rd_addr)\n"); + return False; + } + DIP("lhau r%d,%u(r%d)\n", Rd_addr, d_imm, Ra_addr); + putIReg( Rd_addr, unop(Iop_16Sto32, + loadBE(Ity_I16, mkexpr(EA_imm))) ); + putIReg( Ra_addr, mkexpr(EA_imm) ); + break; + + case 0x28: // lhz (Load HW & Zero, p490) + DIP("lhz r%d,%u(r%d)\n", Rd_addr, d_imm, Ra_addr); + putIReg( Rd_addr, unop(Iop_16Sto32, + loadBE(Ity_I16, mkexpr(EA_imm))) ); + break; + + case 0x29: // lhzu (Load HW & and Zero with Update, p491) + if (Ra_addr == 0 || Ra_addr == Rd_addr) { + vex_printf("dis_int_load(PPC32)(lhzu,Ra_addr|Rd_addr)\n"); + return False; + } + DIP("lhzu r%d,%u(r%d)\n", Rd_addr, d_imm, Ra_addr); + putIReg( Rd_addr, loadBE(Ity_I16, mkexpr(EA_imm)) ); + putIReg( Ra_addr, mkexpr(EA_imm) ); + break; + + case 0x20: // lwz (Load W & Zero, p504) + DIP("lwz r%d,%u(r%d)\n", Rd_addr, d_imm, Ra_addr); + putIReg( Rd_addr, loadBE(Ity_I32, mkexpr(EA_imm)) ); + break; + + case 0x21: // lwzu (Load W & Zero with Update, p505)) + if (Ra_addr == 0 || Ra_addr == Rd_addr) { + vex_printf("dis_int_load(PPC32)(lwzu,Ra_addr|Rd_addr)\n"); + return False; + } + DIP("lwzu r%d,%u(r%d)\n", Rd_addr, d_imm, Ra_addr); + putIReg( Rd_addr, loadBE(Ity_I32, mkexpr(EA_imm)) ); + putIReg( Ra_addr, mkexpr(EA_imm) ); + break; + + /* X Form */ + case 0x1F: + if (b0 != 0) { + vex_printf("dis_int_load(PPC32)(Ox1F,b0)\n"); + return False; + } + assign( EA_reg, binop(Iop_And32, mkexpr(Ra_or_0), mkexpr(Rb)) ); + + switch (opc2) { + case 0x077: // lbzux (Load B & Zero with Update Indexed, p470) + DIP("lbzux r%d,r%d,r%d\n", Rd_addr, Ra_addr, Rb_addr); + if (Ra_addr == 0 || Ra_addr == Rd_addr) { + vex_printf("dis_int_load(PPC32)(lwzux,Ra_addr|Rd_addr)\n"); + return False; + } + putIReg( Rd_addr, unop(Iop_8Uto32, + loadBE(Ity_I8, mkexpr(EA_reg))) ); + putIReg( Ra_addr, mkexpr(EA_reg) ); + break; + + case 0x057: // lbzx (Load B & Zero Indexed, p471) + DIP("lbzx r%d,r%d,r%d\n", Rd_addr, Ra_addr, Rb_addr); + putIReg( Rd_addr, unop(Iop_8Uto32, + loadBE(Ity_I8, mkexpr(EA_reg))) ); + break; + + case 0x177: // lhaux (Load HW Algebraic with Update Indexed, p487) + if (Ra_addr == 0 || Ra_addr == Rd_addr) { + vex_printf("dis_int_load(PPC32)(lhaux,Ra_addr|Rd_addr)\n"); + return False; + } + DIP("lhaux r%d,r%d,r%d\n", Rd_addr, Ra_addr, Rb_addr); + putIReg( Rd_addr, unop(Iop_16Sto32, + loadBE(Ity_I16, mkexpr(EA_reg))) ); + putIReg( Ra_addr, mkexpr(EA_reg) ); + break; + + case 0x157: // lhax (Load HW Algebraic Indexed, p488) + DIP("lhax r%d,r%d,r%d\n", Rd_addr, Ra_addr, Rb_addr); + putIReg( Rd_addr, unop(Iop_16Sto32, + loadBE(Ity_I16, mkexpr(EA_reg))) ); + break; + + case 0x137: // lhzux (Load HW & Zero with Update Indexed, p492) + if (Ra_addr == 0 || Ra_addr == Rd_addr) { + vex_printf("dis_int_load(PPC32)(lhzux,Ra_addr|Rd_addr)\n"); + return False; + } + DIP("lhzux r%d,r%d,r%d\n", Rd_addr, Ra_addr, Rb_addr); + putIReg( Rd_addr, unop(Iop_16Sto32, + loadBE(Ity_I16, mkexpr(EA_reg))) ); + putIReg( Ra_addr, mkexpr(EA_reg) ); + break; + + case 0x117: // lhzx (Load HW & Zero Indexed, p493) + DIP("lhzx r%d,r%d,r%d\n", Rd_addr, Ra_addr, Rb_addr); + putIReg( Rd_addr, unop(Iop_16Sto32, + loadBE(Ity_I16, mkexpr(EA_reg))) ); + break; + + case 0x037: // lwzux (Load W & Zero with Update Indexed, p506) + if (Ra_addr == 0 || Ra_addr == Rd_addr) { + vex_printf("dis_int_load(PPC32)(lwzux,Ra_addr|Rd_addr)\n"); + return False; + } + DIP("lwzux r%d,r%d,r%d\n", Rd_addr, Ra_addr, Rb_addr); + putIReg( Rd_addr, loadBE(Ity_I32, mkexpr(EA_reg)) ); + putIReg( Ra_addr, mkexpr(EA_reg) ); + break; + + case 0x017: // lwzx (Load W & Zero Indexed, p507) + DIP("lwzx r%d,r%d,r%d\n", Rd_addr, Ra_addr, Rb_addr); + putIReg( Rd_addr, loadBE(Ity_I32, mkexpr(EA_reg)) ); + break; + + default: + vex_printf("dis_int_load(PPC32)(opc2)\n"); + return False; + } + break; + default: + vex_printf("dis_int_load(PPC32)(opc1)\n"); + return False; + } + return True; } static Bool dis_int_store ( UInt theInstr ) { - UChar opc1 = toUChar((theInstr >> 26) & 0x3F); /* theInstr[26:31] */ - UChar Rs_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ - UChar Ra_addr = toUChar((theInstr >> 16) & 0x1F); /* theInstr[16:20] */ - - /* D-Form */ - UInt d_imm = (theInstr >> 0) & 0xFFFF; /* theInstr[0:15] */ - - /* X-Form */ - UChar Rb_addr = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */ - UInt opc2 = (theInstr >> 1) & 0x3FF; /* theInstr[1:10] */ - UChar b0 = toUChar((theInstr >> 0) & 1); /* theInstr[0] */ - - UInt exts_d_imm = extend_s_16to32(d_imm); - - IRTemp Ra = newTemp(Ity_I32); - IRTemp Ra_or_0 = newTemp(Ity_I32); - IRTemp Rb = newTemp(Ity_I32); - IRTemp Rs = newTemp(Ity_I32); - IRTemp Rs_8 = newTemp(Ity_I8); - IRTemp Rs_16 = newTemp(Ity_I16); - IRTemp EA_imm = newTemp(Ity_I32); - IRTemp EA_reg = newTemp(Ity_I32); - - assign( Ra, getIReg(Ra_addr) ); - assign( Rb, getIReg(Rb_addr) ); - assign( Rs, getIReg(Rs_addr) ); - assign( Rs_8, narrowTo(Ity_I8, mkexpr(Rs)) ); - assign( Rs_16, narrowTo(Ity_I16, mkexpr(Rs)) ); - - if (Ra_addr == 0) { - assign( Ra_or_0, mkU32(0) ); - } else { - assign( Ra_or_0, mkexpr(Ra) ); - } - assign( EA_imm, binop(Iop_And32, mkexpr(Ra_or_0), mkU32(exts_d_imm)) ); - - switch (opc1) { - case 0x26: // stb (Store B, p576) - DIP("stb r%d,%u(r%d)\n", Rs_addr, d_imm, Ra_addr); - storeBE( mkexpr(EA_imm), mkexpr(Rs_8) ); - break; - - case 0x27: // stbu (Store B with Update, p577) - if (Ra_addr == 0 ) { - vex_printf("dis_int_store(PPC32)(stbu,Ra_addr)\n"); - return False; - } - DIP("stbu r%d,%u(r%d)\n", Rs_addr, d_imm, Ra_addr); - storeBE( mkexpr(EA_imm), mkexpr(Rs_8) ); - putIReg( Ra_addr, mkexpr(EA_imm) ); - break; - - case 0x2C: // sth (Store HW, p595) - DIP("sth r%d,%u(r%d)\n", Rs_addr, d_imm, Ra_addr); - storeBE( mkexpr(EA_imm), mkexpr(Rs_16) ); - break; - - case 0x2D: // sthu (Store HW with Update, p597) - if (Ra_addr == 0) { - vex_printf("dis_int_store(PPC32)(sthu,Ra_addr)\n"); - return False; - } - DIP("sthu r%d,%u(r%d)\n", Rs_addr, 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) ); - break; - - case 0x24: // stw (Store W, p603) - DIP("stw r%d,%u(r%d)\n", Rs_addr, d_imm, Ra_addr); - storeBE( mkexpr(EA_imm), mkexpr(Rs) ); - break; - - case 0x25: // stwu (Store W with Update, p607) - if (Ra_addr == 0) { - vex_printf("dis_int_store(PPC32)(stwu,Ra_addr)\n"); - return False; - } - DIP("stwu r%d,%u(r%d)\n", Rs_addr, d_imm, Ra_addr); - storeBE( mkexpr(EA_imm), mkexpr(Rs) ); - putIReg( Ra_addr, mkexpr(EA_imm) ); - break; - - /* X Form */ - case 0x1F: - if (b0 != 0) { - vex_printf("dis_int_store(PPC32)(0x1F,b0)\n"); - return False; - } - assign( EA_reg, binop(Iop_And32, mkexpr(Ra_or_0), mkexpr(Rb)) ); - - switch (opc2) { - case 0x0F7: // stbux (Store B with Update Indexed, p578) - if (Ra_addr == 0) { - vex_printf("dis_int_store(PPC32)(stbux,Ra_addr)\n"); - 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) ); - break; - - case 0x0D7: // stbx (Store B Indexed, p579) - DIP("stbx r%d,r%d,r%d\n", Rs_addr, Ra_addr, Rb_addr); - storeBE( mkexpr(EA_reg), mkexpr(Rs_8) ); - break; - - case 0x1B7: // sthux (Store HW with Update Indexed, p598) - if (Ra_addr == 0) { - vex_printf("dis_int_store(PPC32)(sthux,Ra_addr)\n"); - 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) ); - break; - - case 0x197: // sthx (Store HW Indexed, p599) - DIP("sthx r%d,r%d,r%d\n", Rs_addr, Ra_addr, Rb_addr); - storeBE( mkexpr(EA_reg), mkexpr(Rs_16) ); - break; - - case 0x0B7: // stwux (Store W with Update Indexed, p608) - if (Ra_addr == 0) { - vex_printf("dis_int_store(PPC32)(stwux,Ra_addr)\n"); - 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) ); - break; - - case 0x097: // stwx (Store W Indexed, p609) - DIP("stwx r%d,r%d,r%d\n", Rs_addr, Ra_addr, Rb_addr); - storeBE( mkexpr(EA_reg), mkexpr(Rs) ); - break; - - default: - vex_printf("dis_int_store(PPC32)(opc2)\n"); - return False; - } - break; - default: - vex_printf("dis_int_store(PPC32)(opc1)\n"); - return False; - } - return True; + UChar opc1 = toUChar((theInstr >> 26) & 0x3F); /* theInstr[26:31] */ + UChar Rs_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ + UChar Ra_addr = toUChar((theInstr >> 16) & 0x1F); /* theInstr[16:20] */ + + /* D-Form */ + UInt d_imm = (theInstr >> 0) & 0xFFFF; /* theInstr[0:15] */ + + /* X-Form */ + UChar Rb_addr = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */ + UInt opc2 = (theInstr >> 1) & 0x3FF; /* theInstr[1:10] */ + UChar b0 = toUChar((theInstr >> 0) & 1); /* theInstr[0] */ + + UInt exts_d_imm = extend_s_16to32(d_imm); + + IRTemp Ra = newTemp(Ity_I32); + IRTemp Ra_or_0 = newTemp(Ity_I32); + IRTemp Rb = newTemp(Ity_I32); + IRTemp Rs = newTemp(Ity_I32); + IRTemp Rs_8 = newTemp(Ity_I8); + IRTemp Rs_16 = newTemp(Ity_I16); + IRTemp EA_imm = newTemp(Ity_I32); + IRTemp EA_reg = newTemp(Ity_I32); + + assign( Ra, getIReg(Ra_addr) ); + assign( Rb, getIReg(Rb_addr) ); + assign( Rs, getIReg(Rs_addr) ); + assign( Rs_8, narrowTo(Ity_I8, mkexpr(Rs)) ); + assign( Rs_16, narrowTo(Ity_I16, mkexpr(Rs)) ); + + if (Ra_addr == 0) { + assign( Ra_or_0, mkU32(0) ); + } else { + assign( Ra_or_0, mkexpr(Ra) ); + } + assign( EA_imm, binop(Iop_And32, mkexpr(Ra_or_0), mkU32(exts_d_imm)) ); + + switch (opc1) { + case 0x26: // stb (Store B, p576) + DIP("stb r%d,%u(r%d)\n", Rs_addr, d_imm, Ra_addr); + storeBE( mkexpr(EA_imm), mkexpr(Rs_8) ); + break; + + case 0x27: // stbu (Store B with Update, p577) + if (Ra_addr == 0 ) { + vex_printf("dis_int_store(PPC32)(stbu,Ra_addr)\n"); + return False; + } + DIP("stbu r%d,%u(r%d)\n", Rs_addr, d_imm, Ra_addr); + storeBE( mkexpr(EA_imm), mkexpr(Rs_8) ); + putIReg( Ra_addr, mkexpr(EA_imm) ); + break; + + case 0x2C: // sth (Store HW, p595) + DIP("sth r%d,%u(r%d)\n", Rs_addr, d_imm, Ra_addr); + storeBE( mkexpr(EA_imm), mkexpr(Rs_16) ); + break; + + case 0x2D: // sthu (Store HW with Update, p597) + if (Ra_addr == 0) { + vex_printf("dis_int_store(PPC32)(sthu,Ra_addr)\n"); + return False; + } + DIP("sthu r%d,%u(r%d)\n", Rs_addr, 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) ); + break; + + case 0x24: // stw (Store W, p603) + DIP("stw r%d,%u(r%d)\n", Rs_addr, d_imm, Ra_addr); + storeBE( mkexpr(EA_imm), mkexpr(Rs) ); + break; + + case 0x25: // stwu (Store W with Update, p607) + if (Ra_addr == 0) { + vex_printf("dis_int_store(PPC32)(stwu,Ra_addr)\n"); + return False; + } + DIP("stwu r%d,%u(r%d)\n", Rs_addr, d_imm, Ra_addr); + storeBE( mkexpr(EA_imm), mkexpr(Rs) ); + putIReg( Ra_addr, mkexpr(EA_imm) ); + break; + + /* X Form */ + case 0x1F: + if (b0 != 0) { + vex_printf("dis_int_store(PPC32)(0x1F,b0)\n"); + return False; + } + assign( EA_reg, binop(Iop_And32, mkexpr(Ra_or_0), mkexpr(Rb)) ); + + switch (opc2) { + case 0x0F7: // stbux (Store B with Update Indexed, p578) + if (Ra_addr == 0) { + vex_printf("dis_int_store(PPC32)(stbux,Ra_addr)\n"); + 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) ); + break; + + case 0x0D7: // stbx (Store B Indexed, p579) + DIP("stbx r%d,r%d,r%d\n", Rs_addr, Ra_addr, Rb_addr); + storeBE( mkexpr(EA_reg), mkexpr(Rs_8) ); + break; + + case 0x1B7: // sthux (Store HW with Update Indexed, p598) + if (Ra_addr == 0) { + vex_printf("dis_int_store(PPC32)(sthux,Ra_addr)\n"); + 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) ); + break; + + case 0x197: // sthx (Store HW Indexed, p599) + DIP("sthx r%d,r%d,r%d\n", Rs_addr, Ra_addr, Rb_addr); + storeBE( mkexpr(EA_reg), mkexpr(Rs_16) ); + break; + + case 0x0B7: // stwux (Store W with Update Indexed, p608) + if (Ra_addr == 0) { + vex_printf("dis_int_store(PPC32)(stwux,Ra_addr)\n"); + 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) ); + break; + + case 0x097: // stwx (Store W Indexed, p609) + DIP("stwx r%d,r%d,r%d\n", Rs_addr, Ra_addr, Rb_addr); + storeBE( mkexpr(EA_reg), mkexpr(Rs) ); + break; + + default: + vex_printf("dis_int_store(PPC32)(opc2)\n"); + return False; + } + break; + default: + vex_printf("dis_int_store(PPC32)(opc1)\n"); + return False; + } + return True; } static Bool dis_int_ldst_mult ( UInt theInstr ) { - /* D-Form */ - UChar opc1 = toUChar((theInstr >> 26) & 0x3F); /* theInstr[26:31] */ - UChar Rd_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ - UChar Rs_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ - UChar Ra_addr = toUChar((theInstr >> 16) & 0x1F); /* theInstr[16:20] */ - UInt d_imm = (theInstr >> 0) & 0xFFFF; /* theInstr[0:15] */ - - UInt exts_d_imm = extend_s_16to32(d_imm); - UInt reg_idx = 0; - UInt offset = 0; - - IRTemp Ra = newTemp(Ity_I32); - IRTemp EA = newTemp(Ity_I32); - - if (Ra_addr == 0) { - assign( EA, binop(Iop_And32, mkU32(0), mkU32(exts_d_imm)) ); - } else { - assign( Ra, getIReg(Ra_addr) ); - assign( EA, binop(Iop_And32, mkexpr(Ra), mkU32(exts_d_imm)) ); - } - - switch (opc1) { - case 0x2E: // lmw (Load Multiple Word, p494) - if (Ra_addr >= reg_idx) { - vex_printf("dis_int_ldst_mult(PPC32)(lmw,Ra_addr)\n"); - return False; - } - DIP("lmw r%d,%u(r%d)\n", Rd_addr, d_imm, Ra_addr); - for (reg_idx = Rd_addr; reg_idx<=31; reg_idx++) { - putIReg( reg_idx, - loadBE(Ity_I32, binop(Iop_Add32, mkexpr(EA), - mkU32(offset))) ); - offset +=4; - } - break; - - case 0x2F: // stmw (Store Multiple Word, p600) - DIP("stmw r%d,%u(r%d)\n", Rs_addr, d_imm, Ra_addr); - for (reg_idx = Rs_addr; reg_idx<=31; reg_idx++) { - storeBE( binop(Iop_Add32, mkexpr(EA), mkU32(offset)), - getIReg(reg_idx) ); - offset +=4; - } - break; - - default: - vex_printf("dis_int_ldst_mult(PPC32)(opc1)\n"); - return False; - } - return True; + /* D-Form */ + UChar opc1 = toUChar((theInstr >> 26) & 0x3F); /* theInstr[26:31] */ + UChar Rd_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ + UChar Rs_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ + UChar Ra_addr = toUChar((theInstr >> 16) & 0x1F); /* theInstr[16:20] */ + UInt d_imm = (theInstr >> 0) & 0xFFFF; /* theInstr[0:15] */ + + UInt exts_d_imm = extend_s_16to32(d_imm); + UInt reg_idx = 0; + UInt offset = 0; + + IRTemp Ra = newTemp(Ity_I32); + IRTemp EA = newTemp(Ity_I32); + + if (Ra_addr == 0) { + assign( EA, binop(Iop_And32, mkU32(0), mkU32(exts_d_imm)) ); + } else { + assign( Ra, getIReg(Ra_addr) ); + assign( EA, binop(Iop_And32, mkexpr(Ra), mkU32(exts_d_imm)) ); + } + + switch (opc1) { + case 0x2E: // lmw (Load Multiple Word, p494) + if (Ra_addr >= reg_idx) { + vex_printf("dis_int_ldst_mult(PPC32)(lmw,Ra_addr)\n"); + return False; + } + DIP("lmw r%d,%u(r%d)\n", Rd_addr, d_imm, Ra_addr); + for (reg_idx = Rd_addr; reg_idx<=31; reg_idx++) { + putIReg( reg_idx, + loadBE(Ity_I32, binop(Iop_Add32, mkexpr(EA), + mkU32(offset))) ); + offset +=4; + } + break; + + case 0x2F: // stmw (Store Multiple Word, p600) + DIP("stmw r%d,%u(r%d)\n", Rs_addr, d_imm, Ra_addr); + for (reg_idx = Rs_addr; reg_idx<=31; reg_idx++) { + storeBE( binop(Iop_Add32, mkexpr(EA), mkU32(offset)), + getIReg(reg_idx) ); + offset +=4; + } + break; + + default: + vex_printf("dis_int_ldst_mult(PPC32)(opc1)\n"); + return False; + } + return True; } static Bool dis_int_ldst_str ( UInt theInstr ) { - /* X-Form */ - UChar opc1 = toUChar((theInstr >> 26) & 0x3F); /* theInstr[26:31] */ - UChar Rd_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ - UChar Rs_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ - UChar Ra_addr = toUChar((theInstr >> 16) & 0x1F); /* theInstr[16:20] */ - UChar NumBytes = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */ - UChar Rb_addr = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */ - UInt opc2 = (theInstr >> 1) & 0x3FF; /* theInstr[1:10] */ - UChar b0 = toUChar((theInstr >> 0) & 1); /* theInstr[0] */ - - UInt reg_idx, bit_idx, n_byte; - UInt EA_offset = 0; - UInt n_regs, reg_first, reg_last; - - IRTemp Ra = newTemp(Ity_I32); + /* X-Form */ + UChar opc1 = toUChar((theInstr >> 26) & 0x3F); /* theInstr[26:31] */ + UChar Rd_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ + UChar Rs_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ + UChar Ra_addr = toUChar((theInstr >> 16) & 0x1F); /* theInstr[16:20] */ + UChar NumBytes = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */ + UChar Rb_addr = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */ + UInt opc2 = (theInstr >> 1) & 0x3FF; /* theInstr[1:10] */ + UChar b0 = toUChar((theInstr >> 0) & 1); /* theInstr[0] */ + + UInt reg_idx, bit_idx, n_byte; + UInt EA_offset = 0; + UInt n_regs, reg_first, reg_last; + + IRTemp Ra = newTemp(Ity_I32); // IRTemp Rb = newTemp(Ity_I32); - IRTemp EA = newTemp(Ity_I32); - IRTemp b_EA = newTemp(Ity_I32); - IRExpr* irx_byte; - IRExpr* irx_shl; - - if (Ra_addr == 0) { - assign( b_EA, mkU32(0) ); - } else { - assign( Ra, getIReg(Ra_addr) ); - assign( b_EA, mkexpr(Ra) ); - } - - if (opc1 != 0x1F || b0 != 0) { - vex_printf("dis_int_ldst_str(PPC32)(opc1)\n"); - return False; - } + IRTemp EA = newTemp(Ity_I32); + IRTemp b_EA = newTemp(Ity_I32); + IRExpr* irx_byte; + IRExpr* irx_shl; + + if (Ra_addr == 0) { + assign( b_EA, mkU32(0) ); + } else { + assign( Ra, getIReg(Ra_addr) ); + assign( b_EA, mkexpr(Ra) ); + } + + if (opc1 != 0x1F || b0 != 0) { + vex_printf("dis_int_ldst_str(PPC32)(opc1)\n"); + return False; + } - switch (opc2) { - case 0x255: // lswi (Load String Word Immediate, p495) - n_regs = (NumBytes / 4) + (NumBytes%4 == 0 ? 0:1); // ceil(nb/4) - reg_first = Rd_addr; - reg_last = Rd_addr + n_regs - 1; - - if (reg_last < reg_first) { - if (Ra_addr >= reg_first || Ra_addr <= reg_last) { - vex_printf("dis_int_ldst_str(PPC32)(lswi,Ra_addr,1)\n"); - return False; - } - } else { - if (Ra_addr >= reg_first && Ra_addr <= reg_last) { - vex_printf("dis_int_ldst_str(PPC32)(lswi,Ra_addr,2)\n"); - return False; - } - } - DIP("lswi r%d,r%d,%u\n", Rd_addr, Ra_addr, NumBytes); - - assign( EA, mkexpr(b_EA) ); - - bit_idx = 0; - reg_idx = Rd_addr - 1; - n_byte = NumBytes; - if (n_byte == 0) { n_byte = 32; } - - for (; n_byte>0; n_byte--) { - if (bit_idx == 0) { - reg_idx++; - if (reg_idx == 32) reg_idx = 0; - putIReg( reg_idx, mkU32(0) ); - } - irx_byte = loadBE(Ity_I8, binop(Iop_Add32, - mkexpr(EA), - mkU32(EA_offset))); - irx_shl = binop(Iop_Shl32, irx_byte, - mkU8(toUChar(24 - bit_idx))); - putIReg( reg_idx, binop(Iop_Or32, getIReg(reg_idx), irx_shl) ); - bit_idx += 8; - if (bit_idx == 32) { bit_idx = 0; } - EA_offset++; - } - - case 0x215: // lswx (Load String Word Indexed, p497) - DIP("lswx r%d,r%d,r%d\n", Rd_addr, Ra_addr, Rb_addr); - return False; - - case 0x2D5: // stswi (Store String Word Immediate, p601) - DIP("stswi r%d,r%d,%u\n", Rs_addr, Ra_addr, NumBytes); - if (Ra_addr == 0) { - assign( EA, mkU32(0) ); - } else { - assign( EA, mkexpr(b_EA) ); - } - - n_byte = NumBytes; - if (n_byte == 0) { n_byte = 32; } - reg_idx = Rs_addr - 1; - bit_idx = 0; - - for (; n_byte>0; n_byte--) { - if (bit_idx == 0) { - reg_idx++; - if (reg_idx==32) reg_idx = 0; - } - irx_byte = unop(Iop_32to8, - binop(Iop_Shr32, - getIReg(reg_idx), - mkU8(toUChar(24 - bit_idx)))); - storeBE( binop(Iop_Add32, mkexpr(EA), mkU32(EA_offset)), - irx_byte ); - - bit_idx += 8; - if (bit_idx == 32) { bit_idx = 0; } - EA_offset++; - } - break; - - case 0x295: // stswx (Store String Word Indexed, p602) - DIP("stswx r%d,r%d,r%d\n", Rs_addr, Ra_addr, Rb_addr); - return False; + switch (opc2) { + case 0x255: // lswi (Load String Word Immediate, p495) + n_regs = (NumBytes / 4) + (NumBytes%4 == 0 ? 0:1); // ceil(nb/4) + reg_first = Rd_addr; + reg_last = Rd_addr + n_regs - 1; + + if (reg_last < reg_first) { + if (Ra_addr >= reg_first || Ra_addr <= reg_last) { + vex_printf("dis_int_ldst_str(PPC32)(lswi,Ra_addr,1)\n"); + return False; + } + } else { + if (Ra_addr >= reg_first && Ra_addr <= reg_last) { + vex_printf("dis_int_ldst_str(PPC32)(lswi,Ra_addr,2)\n"); + return False; + } + } + DIP("lswi r%d,r%d,%u\n", Rd_addr, Ra_addr, NumBytes); + + assign( EA, mkexpr(b_EA) ); + + bit_idx = 0; + reg_idx = Rd_addr - 1; + n_byte = NumBytes; + if (n_byte == 0) { n_byte = 32; } + + for (; n_byte>0; n_byte--) { + if (bit_idx == 0) { + reg_idx++; + if (reg_idx == 32) reg_idx = 0; + putIReg( reg_idx, mkU32(0) ); + } + irx_byte = loadBE(Ity_I8, binop(Iop_Add32, + mkexpr(EA), + mkU32(EA_offset))); + irx_shl = binop(Iop_Shl32, irx_byte, + mkU8(toUChar(24 - bit_idx))); + putIReg( reg_idx, binop(Iop_Or32, getIReg(reg_idx), irx_shl) ); + bit_idx += 8; + if (bit_idx == 32) { bit_idx = 0; } + EA_offset++; + } + + case 0x215: // lswx (Load String Word Indexed, p497) + DIP("lswx r%d,r%d,r%d\n", Rd_addr, Ra_addr, Rb_addr); + return False; + + case 0x2D5: // stswi (Store String Word Immediate, p601) + DIP("stswi r%d,r%d,%u\n", Rs_addr, Ra_addr, NumBytes); + if (Ra_addr == 0) { + assign( EA, mkU32(0) ); + } else { + assign( EA, mkexpr(b_EA) ); + } + + n_byte = NumBytes; + if (n_byte == 0) { n_byte = 32; } + reg_idx = Rs_addr - 1; + bit_idx = 0; + + for (; n_byte>0; n_byte--) { + if (bit_idx == 0) { + reg_idx++; + if (reg_idx==32) reg_idx = 0; + } + irx_byte = unop(Iop_32to8, + binop(Iop_Shr32, + getIReg(reg_idx), + mkU8(toUChar(24 - bit_idx)))); + storeBE( binop(Iop_Add32, mkexpr(EA), mkU32(EA_offset)), + irx_byte ); + + bit_idx += 8; + if (bit_idx == 32) { bit_idx = 0; } + EA_offset++; + } + break; + + case 0x295: // stswx (Store String Word Indexed, p602) + DIP("stswx r%d,r%d,r%d\n", Rs_addr, Ra_addr, Rb_addr); + return False; #if 0 // CAB: Might something like this work ? // won't produce very nice code (ir_ctr will get _rather_ long...), but hey. // or perhaps arrays of IRTemp... - assign( NumBytes, AND(get(xer_bc), 0x1F) ); - IRExpr* irx_ea; - IRExpr* irx_orig_byte; - IRExpr* irx_tostore; - IRExpr* ir_ctr = mkU8(0); - Uint EA_offset = 0; - UInt start = Rs_addr; - UInt reg_idx; - UInt i; - for (i=0; i<128; i++) { - bit_idx = (i % 4) * 8; - reg_idx = (i / 4) + start; - reg_idx = reg_idx % 32; - word = getIReg(reg_idx); - byte = get_byte(word, bit_idx); - - irx_ea = (EA + EA_offset); - irx_orig_byte = loadBE(Ity_I8, irx_ea); - irx_tostore = IRExpr_Mux0X( (ir_ctr <= NumBytes), - irx_orig_byte, - mkexpr(byte0) ); - storeBE( irx_ea, irx_tostore ); - - ir_ctr = binop(Iop_And8, ir_ctr, mkU8(1)); - EA_offset++; - } - break; + assign( NumBytes, AND(get(xer_bc), 0x1F) ); + IRExpr* irx_ea; + IRExpr* irx_orig_byte; + IRExpr* irx_tostore; + IRExpr* ir_ctr = mkU8(0); + Uint EA_offset = 0; + UInt start = Rs_addr; + UInt reg_idx; + UInt i; + for (i=0; i<128; i++) { + bit_idx = (i % 4) * 8; + reg_idx = (i / 4) + start; + reg_idx = reg_idx % 32; + word = getIReg(reg_idx); + byte = get_byte(word, bit_idx); + + irx_ea = (EA + EA_offset); + irx_orig_byte = loadBE(Ity_I8, irx_ea); + irx_tostore = IRExpr_Mux0X( (ir_ctr <= NumBytes), + irx_orig_byte, + mkexpr(byte0) ); + storeBE( irx_ea, irx_tostore ); + + ir_ctr = binop(Iop_And8, ir_ctr, mkU8(1)); + EA_offset++; + } + break; #endif - default: - vex_printf("dis_int_ldst_str(PPC32)(opc2)\n"); - return False; - } - return True; + default: + vex_printf("dis_int_ldst_str(PPC32)(opc2)\n"); + return False; + } + return True; } @@ -2342,20 +2344,20 @@ static Bool dis_int_ldst_str ( UInt theInstr ) */ 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, IRExpr_Get(OFFB_CTR, Ity_I32)) ); - if ((BO >> 1) & 1) { - assign( ok, unop(Iop_Not1, mkexpr(ctr_0)) ); - } else { - assign( ok, mkexpr(ctr_0) ); - } - } - return mkexpr(ok); + 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, IRExpr_Get(OFFB_CTR, Ity_I32)) ); + if ((BO >> 1) & 1) { + assign( ok, unop(Iop_Not1, mkexpr(ctr_0)) ); + } else { + assign( ok, mkexpr(ctr_0) ); + } + } + return mkexpr(ok); } /* @@ -2364,774 +2366,774 @@ static IRExpr* branch_ctr_ok( UInt BO ) */ static IRExpr* branch_cond_ok( UInt BO, UInt BI ) { - IRTemp ok = newTemp(Ity_I1); - IRTemp tmp = newTemp(Ity_I1); - IRTemp cr_bi = newTemp(Ity_I32); - - if (BO >> 4) { - assign( ok, mkU1(1) ); - } else { - // ok = (CR[31-BI] == BO[3]) - assign( cr_bi, getReg_masked( REG_CR, (0x80000000 >> BI)) ); - assign( tmp, binop(Iop_CmpNE32, mkU32(0), mkexpr(cr_bi)) ); - - if ((BO >> 3) & 1) { - assign( ok, mkexpr(tmp) ); - } else { - assign( ok, unop(Iop_Not1, mkexpr(tmp)) ); - } - } - return mkexpr(ok); + IRTemp ok = newTemp(Ity_I1); + IRTemp tmp = newTemp(Ity_I1); + IRTemp cr_bi = newTemp(Ity_I32); + + if (BO >> 4) { + assign( ok, mkU1(1) ); + } else { + // ok = (CR[31-BI] == BO[3]) + assign( cr_bi, getReg_masked( REG_CR, (0x80000000 >> BI)) ); + assign( tmp, binop(Iop_CmpNE32, mkU32(0), mkexpr(cr_bi)) ); + + if ((BO >> 3) & 1) { + assign( ok, mkexpr(tmp) ); + } else { + assign( ok, unop(Iop_Not1, mkexpr(tmp)) ); + } + } + return mkexpr(ok); } static Bool dis_branch ( UInt theInstr, DisResult *whatNext ) { - UChar opc1 = toUChar((theInstr >> 26) & 0x3F); /* theInstr[26:31] */ - UChar BO = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ - UChar BI = toUChar((theInstr >> 16) & 0x1F); /* theInstr[16:20] */ - UInt BD = (theInstr >> 2) & 0x3FFF; /* theInstr[2:15] */ - UChar b11to15 = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */ - UInt opc2 = (theInstr >> 1) & 0x3FF; /* theInstr[1:10] */ - UInt LI_24 = (theInstr >> 2) & 0xFFFFFF; /* theInstr[2:25] */ - UChar flag_AA = toUChar((theInstr >> 1) & 1); /* theInstr[1] */ - UChar flag_LK = toUChar((theInstr >> 0) & 1); /* theInstr[0] */ - - UInt exts_BD = extend_s_24to32(BD << 2); - UInt exts_LI = extend_s_24to32(LI_24 << 2); - - Addr32 nia = 0; - - IRTemp ctr = newTemp(Ity_I32); - IRTemp lr = newTemp(Ity_I32); - IRTemp ir_nia = newTemp(Ity_I32); - IRTemp do_branch = newTemp(Ity_I32); - IRTemp ctr_ok = newTemp(Ity_I1); - IRTemp cond_ok = newTemp(Ity_I1); - - assign( ctr, IRExpr_Get(OFFB_CTR, Ity_I32) ); - + UChar opc1 = toUChar((theInstr >> 26) & 0x3F); /* theInstr[26:31] */ + UChar BO = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ + UChar BI = toUChar((theInstr >> 16) & 0x1F); /* theInstr[16:20] */ + UInt BD = (theInstr >> 2) & 0x3FFF; /* theInstr[2:15] */ + UChar b11to15 = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */ + UInt opc2 = (theInstr >> 1) & 0x3FF; /* theInstr[1:10] */ + UInt LI_24 = (theInstr >> 2) & 0xFFFFFF; /* theInstr[2:25] */ + UChar flag_AA = toUChar((theInstr >> 1) & 1); /* theInstr[1] */ + UChar flag_LK = toUChar((theInstr >> 0) & 1); /* theInstr[0] */ + + UInt exts_BD = extend_s_24to32(BD << 2); + UInt exts_LI = extend_s_24to32(LI_24 << 2); + + Addr32 nia = 0; + + IRTemp ctr = newTemp(Ity_I32); + IRTemp lr = newTemp(Ity_I32); + IRTemp ir_nia = newTemp(Ity_I32); + IRTemp do_branch = newTemp(Ity_I32); + IRTemp ctr_ok = newTemp(Ity_I1); + IRTemp cond_ok = newTemp(Ity_I1); + + assign( ctr, IRExpr_Get(OFFB_CTR, Ity_I32) ); + // vex_printf("disInstr(ppc32): In: 0x%8x, %,031b\n", theInstr, theInstr ); // vex_printf("disInstr(ppc32): LI: %,039b\n", LI_24); // vex_printf("disInstr(ppc32): LI: %,039b\n", LI_24 << 2); // vex_printf("disInstr(ppc32): LI: %,031b\n", extend_s_24to32(LI_24 << 2)); #if 1 - /* Hack to pass through code that just wants to read the PC */ - if (theInstr == 0x429F0005) { - DIP("bcl 0x%x, 0x%x,\n", BO, BI); - stmt( IRStmt_Put( OFFB_LR, mkU32(guest_cia_curr_instr + 4)) ); - return True; + /* Hack to pass through code that just wants to read the PC */ + if (theInstr == 0x429F0005) { + DIP("bcl 0x%x, 0x%x,\n", BO, BI); + stmt( IRStmt_Put( OFFB_LR, mkU32(guest_cia_curr_instr + 4)) ); + return True; } - // #endif - switch (opc1) { - case 0x12: // b (Branch, p390) -// DIP("b%s%s 0x%x\n", flag_LK ? "l" : "", flag_AA ? "a" : "", LI_24); - nia = exts_LI; - if (!flag_AA) { - nia += guest_cia_curr_instr; - } - if (flag_LK) { - stmt( IRStmt_Put( OFFB_LR, mkU32(guest_cia_curr_instr+4) )); - } - - irbb->jumpkind = flag_LK ? Ijk_Call : Ijk_Boring; - irbb->next = mkU32(nia); - DIP("b%s%s 0x%x\n", flag_LK ? "l" : "", flag_AA ? "a" : "", nia); - break; - - case 0x10: // bc (Branch Conditional, p391) - DIP("bc%s%s 0x%x, 0x%x, 0x%x\n", - flag_LK ? "l" : "", flag_AA ? "a" : "", BO, BI, BD); - - if (!(BO & 0x4)) { - stmt( IRStmt_Put(OFFB_CTR, binop(Iop_Sub32, - mkexpr(ctr), mkU32(1))) ); - } - assign( ctr_ok, branch_ctr_ok( BO ) ); - assign( cond_ok, branch_cond_ok( BO, BI ) ); - - assign( do_branch, binop(Iop_And32, - unop(Iop_1Uto32, mkexpr(ctr_ok)), - unop(Iop_1Uto32, mkexpr(cond_ok))) ); - nia = exts_BD; - if (!flag_AA) { - nia += guest_cia_curr_instr; - } - - if (flag_LK) { - assign( lr, IRExpr_Mux0X( unop(Iop_32to8, mkexpr(do_branch)), - IRExpr_Get(OFFB_LR, Ity_I32), - mkU32(guest_cia_curr_instr + 4))); - stmt( IRStmt_Put( OFFB_LR, mkexpr(lr) )); - } - - stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(do_branch)), - flag_LK ? Ijk_Call : Ijk_Boring, - IRConst_U32(nia) )); - - irbb->jumpkind = Ijk_Boring; - irbb->next = mkU32(guest_cia_curr_instr + 4); - break; - - case 0x13: - if (b11to15!=0) { - vex_printf("dis_int_branch(PPC32)(0x13,b11to15)\n"); - return False; - } - - switch (opc2) { - case 0x210: // bcctr (Branch Cond. to Count Register, p393) - if ((BO & 0x4) == 0) { // "decrement and test CTR" option invalid - vex_printf("dis_int_branch(PPC32)(bcctr,BO)\n"); - return False; - } - DIP("bcctr%s 0x%x, 0x%x,\n", flag_LK ? "l" : "", BO, BI); - - assign( cond_ok, branch_cond_ok( BO, BI ) ); - - assign( ir_nia, binop(Iop_And32, mkU32(0xFFFFFFFC), mkexpr(ctr)) ); - - if (flag_LK) { - assign( lr, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(cond_ok)), - IRExpr_Get(OFFB_LR, Ity_I32), - mkU32(guest_cia_curr_instr + 4))); - stmt( IRStmt_Put( OFFB_LR, mkexpr(lr) )); - } - - stmt( IRStmt_Exit( unop(Iop_Not1, mkexpr(cond_ok)), - Ijk_Boring, - IRConst_U32(guest_cia_curr_instr + 4) )); - - irbb->jumpkind = flag_LK ? Ijk_Call : Ijk_Boring; - irbb->next = mkexpr(ir_nia); - break; - - case 0x010: // bclr (Branch Cond. to Link Register, p395) - DIP("bclr%s 0x%x, 0x%x,\n", flag_LK ? "l" : "", BO, BI); - - if (!(BO & 0x4)) { - stmt( IRStmt_Put(OFFB_CTR, binop(Iop_Sub32, - mkexpr(ctr), mkU32(1))) ); - } - - assign( ctr_ok, branch_ctr_ok(BO) ); - assign( cond_ok, branch_cond_ok(BO, BI) ); - - assign( do_branch, binop(Iop_And32, - unop(Iop_1Uto32, mkexpr(ctr_ok)), - unop(Iop_1Uto32, mkexpr(cond_ok))) ); - - assign( ir_nia, binop(Iop_And32, - IRExpr_Get(OFFB_LR, Ity_I32), - mkU32(0xFFFFFFFC)) ); - if (flag_LK) { - assign( lr, IRExpr_Mux0X( unop(Iop_32to8, mkexpr(do_branch)), - IRExpr_Get(OFFB_LR, Ity_I32), - mkU32(guest_cia_curr_instr + 4)) ); - stmt( IRStmt_Put( OFFB_LR, mkexpr(lr) )); - } - - stmt( IRStmt_Exit( unop(Iop_Not1, unop(Iop_32to1, mkexpr(do_branch))), - Ijk_Boring, - IRConst_U32(guest_cia_curr_instr + 4) )); - - irbb->jumpkind = flag_LK ? Ijk_Call : Ijk_Boring; - irbb->next = mkexpr(ir_nia); - break; - - default: - vex_printf("dis_int_branch(PPC32)(opc2)\n"); - return False; - } - break; - default: - vex_printf("dis_int_branch(PPC32)(opc1)\n"); - return False; - } + switch (opc1) { + case 0x12: // b (Branch, p390) +// DIP("b%s%s 0x%x\n", flag_LK ? "l" : "", flag_AA ? "a" : "", LI_24); + nia = exts_LI; + if (!flag_AA) { + nia += guest_cia_curr_instr; + } + if (flag_LK) { + stmt( IRStmt_Put( OFFB_LR, mkU32(guest_cia_curr_instr+4) )); + } + + irbb->jumpkind = flag_LK ? Ijk_Call : Ijk_Boring; + irbb->next = mkU32(nia); + DIP("b%s%s 0x%x\n", flag_LK ? "l" : "", flag_AA ? "a" : "", nia); + break; + + case 0x10: // bc (Branch Conditional, p391) + DIP("bc%s%s 0x%x, 0x%x, 0x%x\n", + flag_LK ? "l" : "", flag_AA ? "a" : "", BO, BI, BD); + + if (!(BO & 0x4)) { + stmt( IRStmt_Put(OFFB_CTR, binop(Iop_Sub32, + mkexpr(ctr), mkU32(1))) ); + } + assign( ctr_ok, branch_ctr_ok( BO ) ); + assign( cond_ok, branch_cond_ok( BO, BI ) ); + + assign( do_branch, binop(Iop_And32, + unop(Iop_1Uto32, mkexpr(ctr_ok)), + unop(Iop_1Uto32, mkexpr(cond_ok))) ); + nia = exts_BD; + if (!flag_AA) { + nia += guest_cia_curr_instr; + } + + if (flag_LK) { + assign( lr, IRExpr_Mux0X( unop(Iop_32to8, mkexpr(do_branch)), + IRExpr_Get(OFFB_LR, Ity_I32), + mkU32(guest_cia_curr_instr + 4))); + stmt( IRStmt_Put( OFFB_LR, mkexpr(lr) )); + } + + stmt( IRStmt_Exit( unop(Iop_32to1, mkexpr(do_branch)), + flag_LK ? Ijk_Call : Ijk_Boring, + IRConst_U32(nia) )); + + irbb->jumpkind = Ijk_Boring; + irbb->next = mkU32(guest_cia_curr_instr + 4); + break; + + case 0x13: + if (b11to15!=0) { + vex_printf("dis_int_branch(PPC32)(0x13,b11to15)\n"); + return False; + } + + switch (opc2) { + case 0x210: // bcctr (Branch Cond. to Count Register, p393) + if ((BO & 0x4) == 0) { // "decrement and test CTR" option invalid + vex_printf("dis_int_branch(PPC32)(bcctr,BO)\n"); + return False; + } + DIP("bcctr%s 0x%x, 0x%x,\n", flag_LK ? "l" : "", BO, BI); + + assign( cond_ok, branch_cond_ok( BO, BI ) ); + + assign( ir_nia, binop(Iop_And32, mkU32(0xFFFFFFFC), mkexpr(ctr)) ); + + if (flag_LK) { + assign( lr, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(cond_ok)), + IRExpr_Get(OFFB_LR, Ity_I32), + mkU32(guest_cia_curr_instr + 4))); + stmt( IRStmt_Put( OFFB_LR, mkexpr(lr) )); + } + + stmt( IRStmt_Exit( unop(Iop_Not1, mkexpr(cond_ok)), + Ijk_Boring, + IRConst_U32(guest_cia_curr_instr + 4) )); + + irbb->jumpkind = flag_LK ? Ijk_Call : Ijk_Boring; + irbb->next = mkexpr(ir_nia); + break; + + case 0x010: // bclr (Branch Cond. to Link Register, p395) + DIP("bclr%s 0x%x, 0x%x,\n", flag_LK ? "l" : "", BO, BI); + + if (!(BO & 0x4)) { + stmt( IRStmt_Put(OFFB_CTR, binop(Iop_Sub32, + mkexpr(ctr), mkU32(1))) ); + } + + assign( ctr_ok, branch_ctr_ok(BO) ); + assign( cond_ok, branch_cond_ok(BO, BI) ); + + assign( do_branch, binop(Iop_And32, + unop(Iop_1Uto32, mkexpr(ctr_ok)), + unop(Iop_1Uto32, mkexpr(cond_ok))) ); + + assign( ir_nia, binop(Iop_And32, + IRExpr_Get(OFFB_LR, Ity_I32), + mkU32(0xFFFFFFFC)) ); + if (flag_LK) { + assign( lr, IRExpr_Mux0X( unop(Iop_32to8, mkexpr(do_branch)), + IRExpr_Get(OFFB_LR, Ity_I32), + mkU32(guest_cia_curr_instr + 4)) ); + stmt( IRStmt_Put( OFFB_LR, mkexpr(lr) )); + } + + stmt( IRStmt_Exit( unop(Iop_Not1, unop(Iop_32to1, mkexpr(do_branch))), + Ijk_Boring, + IRConst_U32(guest_cia_curr_instr + 4) )); + + irbb->jumpkind = flag_LK ? Ijk_Call : Ijk_Boring; + irbb->next = mkexpr(ir_nia); + break; + + default: + vex_printf("dis_int_branch(PPC32)(opc2)\n"); + return False; + } + break; + default: + vex_printf("dis_int_branch(PPC32)(opc1)\n"); + return False; + } - *whatNext = Dis_StopHere; - return True; + *whatNext = Dis_StopHere; + return True; } static Bool dis_syslink ( UInt theInstr, DisResult *whatNext ) { - if (theInstr != 0x44000002) { - vex_printf("dis_int_syslink(PPC32)(theInstr)\n"); - return False; - } - - // sc (System Call, p565) - DIP("sc\n"); - - /* 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 = mkU32( guest_cia_curr_instr + 4 ); - irbb->jumpkind = Ijk_Syscall; + if (theInstr != 0x44000002) { + vex_printf("dis_int_syslink(PPC32)(theInstr)\n"); + return False; + } - *whatNext = Dis_StopHere; - return True; + // sc (System Call, p565) + DIP("sc\n"); + + /* 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 = mkU32( guest_cia_curr_instr + 4 ); + irbb->jumpkind = Ijk_Syscall; + + *whatNext = Dis_StopHere; + return True; } static Bool dis_memsync ( UInt theInstr ) { - /* X-Form, XL-Form */ - UChar opc1 = toUChar((theInstr >> 26) & 0x3F); /* theInstr[26:31] */ - UInt b11to25 = (theInstr >> 11) & 0x7FFF; /* theInstr[11:25] */ - UChar Rd_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ - UChar Rs_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ - UChar Ra_addr = toUChar((theInstr >> 16) & 0x1F); /* theInstr[16:20] */ - UChar Rb_addr = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */ - UInt opc2 = (theInstr >> 1) & 0x3FF; /* theInstr[1:10] */ - UChar b0 = toUChar((theInstr >> 0) & 1); /* theInstr[0] */ - - IRTemp EA = newTemp(Ity_I32); - IRTemp Ra = newTemp(Ity_I32); - IRTemp Rb = newTemp(Ity_I32); - IRTemp Rs = newTemp(Ity_I32); - IRTemp cr_f7 = newTemp(Ity_I32); - - switch (opc1) { + /* X-Form, XL-Form */ + UChar opc1 = toUChar((theInstr >> 26) & 0x3F); /* theInstr[26:31] */ + UInt b11to25 = (theInstr >> 11) & 0x7FFF; /* theInstr[11:25] */ + UChar Rd_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ + UChar Rs_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ + UChar Ra_addr = toUChar((theInstr >> 16) & 0x1F); /* theInstr[16:20] */ + UChar Rb_addr = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */ + UInt opc2 = (theInstr >> 1) & 0x3FF; /* theInstr[1:10] */ + UChar b0 = toUChar((theInstr >> 0) & 1); /* theInstr[0] */ + + IRTemp EA = newTemp(Ity_I32); + IRTemp Ra = newTemp(Ity_I32); + IRTemp Rb = newTemp(Ity_I32); + IRTemp Rs = newTemp(Ity_I32); + IRTemp cr_f7 = newTemp(Ity_I32); + + switch (opc1) { /* XL-Form */ - case 0x13: // isync (Instruction Synchronize, p467) - if (opc2 != 0x096) { - vex_printf("dis_int_memsync(PPC32)(0x13,opc2)\n"); - return False; - } - if (b11to25 != 0 || b0 != 0) { - vex_printf("dis_int_memsync(PPC32)(0x13,b11to25|b0)\n"); - return False; - } - DIP("isync\n"); - - stmt( IRStmt_MFence() ); - break; - - /* X-Form */ - case 0x1F: - switch (opc2) { - case 0x356: // eieio (Enforce In-Order Execution of I/O, p425) - if (b11to25 != 0 || b0 != 0) { - vex_printf("dis_int_memsync(PPC32)(eiei0,b11to25|b0)\n"); - return False; - } - DIP("eieio\n"); - return False; - - case 0x014: // lwarx (Load Word and Reserve Indexed, p500) - /* Note: RESERVE, RESERVE_ADDR not implemented. - stwcx. is assumed to be always successful - */ - if (b0 != 0) { - vex_printf("dis_int_memsync(PPC32)(lwarx,b0)\n"); - return False; - } - DIP("lwarx r%d,r%d,r%d\n", Rd_addr, Ra_addr, Rb_addr); - assign( Rb, getIReg(Rb_addr) ); - if (Ra_addr == 0) { - assign( EA, mkexpr(Rb) ); - } else { - assign( Ra, getIReg(Ra_addr) ); - assign( EA, binop(Iop_And32, mkexpr(Ra), mkexpr(Rb)) ); - } - putIReg( Rd_addr, loadBE(Ity_I32, mkexpr(EA)) ); - break; - - case 0x096: // stwcx. (Store Word Conditional Indexed, p605) - /* Note: RESERVE, RESERVE_ADDR not implemented. - stwcx. is assumed to be always successful - */ - if (b0 != 1) { - vex_printf("dis_int_memsync(PPC32)(stwcx.,b0)\n"); - return False; - } - DIP("stwcx. r%d,r%d,r%d\n", Rs_addr, Ra_addr, Rb_addr); - - assign( Rb, getIReg(Rb_addr) ); - assign( Rs, getIReg(Rs_addr) ); - if (Ra_addr == 0) { - assign( EA, mkexpr(Rb) ); - } else { - assign( Ra, getIReg(Ra_addr) ); - assign( EA, binop(Iop_And32, mkexpr(Ra), mkexpr(Rb)) ); - } - storeBE( mkexpr(EA), mkexpr(Rs) ); - - // Set CR7[LT GT EQ S0] = 0b001 || XER[SO] - assign( cr_f7, binop(Iop_Or32, mkU32(2), - getReg_bit(REG_XER, OFFBIT_XER_SO)) ); - putReg_field( REG_CR, 7, mkexpr(cr_f7) ); - break; - - case 0x256: // sync (Synchronize, p616) - if (b11to25 != 0 || b0 != 0) { - vex_printf("dis_int_memsync(PPC32)(sync,b11to25|b0)\n"); - return False; - } - DIP("sync\n"); - /* Insert a memory fence. It's sometimes important that these - are carried through to the generated code. */ - stmt( IRStmt_MFence() ); - break; - - default: - vex_printf("dis_int_memsync(PPC32)(opc2)\n"); - return False; - } - break; + case 0x13: // isync (Instruction Synchronize, p467) + if (opc2 != 0x096) { + vex_printf("dis_int_memsync(PPC32)(0x13,opc2)\n"); + return False; + } + if (b11to25 != 0 || b0 != 0) { + vex_printf("dis_int_memsync(PPC32)(0x13,b11to25|b0)\n"); + return False; + } + DIP("isync\n"); + + stmt( IRStmt_MFence() ); + break; + + /* X-Form */ + case 0x1F: + switch (opc2) { + case 0x356: // eieio (Enforce In-Order Execution of I/O, p425) + if (b11to25 != 0 || b0 != 0) { + vex_printf("dis_int_memsync(PPC32)(eiei0,b11to25|b0)\n"); + return False; + } + DIP("eieio\n"); + return False; + + case 0x014: // lwarx (Load Word and Reserve Indexed, p500) + /* Note: RESERVE, RESERVE_ADDR not implemented. + stwcx. is assumed to be always successful + */ + if (b0 != 0) { + vex_printf("dis_int_memsync(PPC32)(lwarx,b0)\n"); + return False; + } + DIP("lwarx r%d,r%d,r%d\n", Rd_addr, Ra_addr, Rb_addr); + assign( Rb, getIReg(Rb_addr) ); + if (Ra_addr == 0) { + assign( EA, mkexpr(Rb) ); + } else { + assign( Ra, getIReg(Ra_addr) ); + assign( EA, binop(Iop_And32, mkexpr(Ra), mkexpr(Rb)) ); + } + putIReg( Rd_addr, loadBE(Ity_I32, mkexpr(EA)) ); + break; + + case 0x096: // stwcx. (Store Word Conditional Indexed, p605) + /* Note: RESERVE, RESERVE_ADDR not implemented. + stwcx. is assumed to be always successful + */ + if (b0 != 1) { + vex_printf("dis_int_memsync(PPC32)(stwcx.,b0)\n"); + return False; + } + DIP("stwcx. r%d,r%d,r%d\n", Rs_addr, Ra_addr, Rb_addr); + + assign( Rb, getIReg(Rb_addr) ); + assign( Rs, getIReg(Rs_addr) ); + if (Ra_addr == 0) { + assign( EA, mkexpr(Rb) ); + } else { + assign( Ra, getIReg(Ra_addr) ); + assign( EA, binop(Iop_And32, mkexpr(Ra), mkexpr(Rb)) ); + } + storeBE( mkexpr(EA), mkexpr(Rs) ); + + // Set CR7[LT GT EQ S0] = 0b001 || XER[SO] + assign( cr_f7, binop(Iop_Or32, mkU32(2), + getReg_bit(REG_XER, OFFBIT_XER_SO)) ); + putReg_field( REG_CR, 7, mkexpr(cr_f7) ); + break; + + case 0x256: // sync (Synchronize, p616) + if (b11to25 != 0 || b0 != 0) { + vex_printf("dis_int_memsync(PPC32)(sync,b11to25|b0)\n"); + return False; + } + DIP("sync\n"); + /* Insert a memory fence. It's sometimes important that these + are carried through to the generated code. */ + stmt( IRStmt_MFence() ); + break; + + default: + vex_printf("dis_int_memsync(PPC32)(opc2)\n"); + return False; + } + break; - default: - vex_printf("dis_int_memsync(PPC32)(opc1)\n"); - return False; - } - return True; + default: + vex_printf("dis_int_memsync(PPC32)(opc1)\n"); + return False; + } + return True; } static Bool dis_int_shift ( UInt theInstr ) { - /* X-Form */ - UChar opc1 = toUChar((theInstr >> 26) & 0x3F); /* theInstr[26:31] */ - UChar Rs_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ - UChar Ra_addr = toUChar((theInstr >> 16) & 0x1F); /* theInstr[16:20] */ - UChar Rb_addr = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */ - UChar sh_imm = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */ - UInt opc2 = (theInstr >> 1) & 0x3FF; /* theInstr[1:10] */ - UChar flag_Rc = toUChar((theInstr >> 0) & 1); /* theInstr[0] */ - - UInt op = PPC32G_FLAG_OP_NUMBER; - Bool do_ca = False; - - IRTemp sh_amt = newTemp(Ity_I8); - IRTemp sign = newTemp(Ity_I32); - IRTemp rb_b5 = newTemp(Ity_I32); - IRTemp sext = newTemp(Ity_I32); - IRTemp Rs = newTemp(Ity_I32); - IRTemp Rs_sh = newTemp(Ity_I32); - IRTemp Ra = newTemp(Ity_I32); - IRTemp Rb = newTemp(Ity_I32); - IRTemp mask = newTemp(Ity_I32); - - assign( Rs, getIReg(Rs_addr) ); - assign( Rb, getIReg(Rb_addr) ); - - if (opc1 == 0x1F) { - switch (opc2) { - case 0x018: // slw (Shift Left Word, p569) - DIP("slw%s r%d,r%d,r%d\n", flag_Rc ? "." : "", - Ra_addr, Rs_addr, Rb_addr); - assign( sh_amt, binop(Iop_And8, mkU8(0x1F), - unop(Iop_32to8, mkexpr(Rb))) ); - assign( Ra, binop(Iop_Shl32, mkexpr(Rs), mkexpr(sh_amt)) ); - break; - - case 0x318: // sraw (Shift Right Algebraic Word, p572) - DIP("sraw%s r%d,r%d,r%d\n", flag_Rc ? "." : "", - Ra_addr, Rs_addr, Rb_addr); - - assign( sh_amt, binop(Iop_And8, mkU8(0x1F), - unop(Iop_32to8, getIReg(Rb_addr))) ); - // Rs_shift = Rs >> sh_amt - assign( Rs_sh, binop(Iop_Shr32, mkexpr(Rs), mkexpr(sh_amt)) ); - // rb_b5 = Rb[5] - assign( rb_b5, binop(Iop_And32, mkexpr(Rb), mkU32(1<<5)) ); - // sign = Rs[31] - assign( sign, binop(Iop_Shr32, mkexpr(Rs), mkU8(31)) ); - // mask = rb_b5==0 ? (-1 >> sh_amt) : 0 - assign( mask, IRExpr_Mux0X( unop(Iop_32to8, mkexpr(rb_b5)), - binop(Iop_Shr32, mkU32(-1), mkexpr(sh_amt)), - mkU32(0) )); - // sign_ext = sign==0 ? 0 : ~mask - assign( sext, IRExpr_Mux0X( unop(Iop_32to8, mkexpr(sign)), - mkU32(0), - unop(Iop_Not32, mkexpr(mask)) )); - - // Ra = (rb_b5 == 0 ? Rs_sh : 0) | sext - assign( Ra, binop(Iop_Or32, mkexpr(sext), - IRExpr_Mux0X( unop(Iop_32to8, mkexpr(rb_b5)), - mkU32(0), mkexpr(Rs_sh))) ); - putIReg( Ra_addr, mkexpr(Ra) ); - op = PPC32G_FLAG_OP_SRAW; - do_ca = True; - break; - - case 0x338: // srawi (Shift Right Algebraic Word Immediate, p573) - DIP("srawi%s r%d,r%d,%d\n", flag_Rc ? "." : "", - Ra_addr, Rs_addr, sh_imm); - - assign( sh_amt, mkU8(sh_imm) ); - // Rs_shift = Rs >> sh_amt - assign( Rs_sh, binop(Iop_Shr32, mkexpr(Rs), mkexpr(sh_amt)) ); - // sign = Rs[31] - assign( sign, binop(Iop_And32, mkU32(1), - binop(Iop_Shr32, mkexpr(Rs), mkU8(31))) ); - // mask = (-1 >> sh_amt) - assign( mask, binop(Iop_Shr32, mkU32(-1), mkexpr(sh_amt)) ); - // sign_ext = sign==0 ? 0 : ~mask - assign( sext, IRExpr_Mux0X( unop(Iop_32to8, mkexpr(sign)), - mkU32(0), - unop(Iop_Not32, mkexpr(mask)) )); - // Ra = Rs_shift | sext - assign( Ra, binop(Iop_Or32, mkexpr(sext), mkexpr(Rs_sh)) ); - putIReg( Ra_addr, mkexpr(Ra) ); - op = PPC32G_FLAG_OP_SRAWI; - do_ca = True; - break; - - case 0x218: // srw (Shift Right Word, p575) - DIP("srw%s r%d,r%d,r%d\n", flag_Rc ? "." : "", - Ra_addr, Rs_addr, Rb_addr); - assign( sh_amt, binop(Iop_And8, mkU8(0x1F), - unop(Iop_32to8, getIReg(Rb_addr))) ); - assign( Rs_sh, binop(Iop_Shr32, mkexpr(Rs), mkexpr(sh_amt)) ); - assign( rb_b5, binop(Iop_And32, mkexpr(Rb), mkU32(1<<5)) ); - assign( Ra, IRExpr_Mux0X( unop(Iop_32to8, mkexpr(rb_b5)), - mkU32(0), mkexpr(Rs_sh) )); - putIReg( Ra_addr, mkexpr(Ra) ); - break; - - default: - vex_printf("dis_int_shift(PPC32)(opc2)\n"); - return False; - } - } else { - vex_printf("dis_int_shift(PPC32)(opc1)\n"); - return False; - } - - if (do_ca) { - vassert(op < PPC32G_FLAG_OP_NUMBER); - setFlags_XER_CA( op, mkexpr(Ra), mkexpr(Rs), mkexpr(Rb) ); - } - if (flag_Rc) { - setFlags_CR7( mkexpr(Ra) ); - } - return True; + /* X-Form */ + UChar opc1 = toUChar((theInstr >> 26) & 0x3F); /* theInstr[26:31] */ + UChar Rs_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ + UChar Ra_addr = toUChar((theInstr >> 16) & 0x1F); /* theInstr[16:20] */ + UChar Rb_addr = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */ + UChar sh_imm = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */ + UInt opc2 = (theInstr >> 1) & 0x3FF; /* theInstr[1:10] */ + UChar flag_Rc = toUChar((theInstr >> 0) & 1); /* theInstr[0] */ + + UInt op = PPC32G_FLAG_OP_NUMBER; + Bool do_ca = False; + + IRTemp sh_amt = newTemp(Ity_I8); + IRTemp sign = newTemp(Ity_I32); + IRTemp rb_b5 = newTemp(Ity_I32); + IRTemp sext = newTemp(Ity_I32); + IRTemp Rs = newTemp(Ity_I32); + IRTemp Rs_sh = newTemp(Ity_I32); + IRTemp Ra = newTemp(Ity_I32); + IRTemp Rb = newTemp(Ity_I32); + IRTemp mask = newTemp(Ity_I32); + + assign( Rs, getIReg(Rs_addr) ); + assign( Rb, getIReg(Rb_addr) ); + + if (opc1 == 0x1F) { + switch (opc2) { + case 0x018: // slw (Shift Left Word, p569) + DIP("slw%s r%d,r%d,r%d\n", flag_Rc ? "." : "", + Ra_addr, Rs_addr, Rb_addr); + assign( sh_amt, binop(Iop_And8, mkU8(0x1F), + unop(Iop_32to8, mkexpr(Rb))) ); + assign( Ra, binop(Iop_Shl32, mkexpr(Rs), mkexpr(sh_amt)) ); + break; + + case 0x318: // sraw (Shift Right Algebraic Word, p572) + DIP("sraw%s r%d,r%d,r%d\n", flag_Rc ? "." : "", + Ra_addr, Rs_addr, Rb_addr); + + assign( sh_amt, binop(Iop_And8, mkU8(0x1F), + unop(Iop_32to8, getIReg(Rb_addr))) ); + // Rs_shift = Rs >> sh_amt + assign( Rs_sh, binop(Iop_Shr32, mkexpr(Rs), mkexpr(sh_amt)) ); + // rb_b5 = Rb[5] + assign( rb_b5, binop(Iop_And32, mkexpr(Rb), mkU32(1<<5)) ); + // sign = Rs[31] + assign( sign, binop(Iop_Shr32, mkexpr(Rs), mkU8(31)) ); + // mask = rb_b5==0 ? (-1 >> sh_amt) : 0 + assign( mask, + IRExpr_Mux0X( unop(Iop_32to8, mkexpr(rb_b5)), + binop(Iop_Shr32, mkU32(-1), mkexpr(sh_amt)), + mkU32(0) )); + // sign_ext = sign==0 ? 0 : ~mask + assign( sext, IRExpr_Mux0X( unop(Iop_32to8, mkexpr(sign)), + mkU32(0), + unop(Iop_Not32, mkexpr(mask)) )); + + // Ra = (rb_b5 == 0 ? Rs_sh : 0) | sext + assign( Ra, binop(Iop_Or32, mkexpr(sext), + IRExpr_Mux0X( unop(Iop_32to8, mkexpr(rb_b5)), + mkU32(0), mkexpr(Rs_sh))) ); + putIReg( Ra_addr, mkexpr(Ra) ); + op = PPC32G_FLAG_OP_SRAW; + do_ca = True; + break; + + case 0x338: // srawi (Shift Right Algebraic Word Immediate, p573) + DIP("srawi%s r%d,r%d,%d\n", flag_Rc ? "." : "", + Ra_addr, Rs_addr, sh_imm); + + assign( sh_amt, mkU8(sh_imm) ); + // Rs_shift = Rs >> sh_amt + assign( Rs_sh, binop(Iop_Shr32, mkexpr(Rs), mkexpr(sh_amt)) ); + // sign = Rs[31] + assign( sign, binop(Iop_And32, mkU32(1), + binop(Iop_Shr32, mkexpr(Rs), mkU8(31))) ); + // mask = (-1 >> sh_amt) + assign( mask, binop(Iop_Shr32, mkU32(-1), mkexpr(sh_amt)) ); + // sign_ext = sign==0 ? 0 : ~mask + assign( sext, IRExpr_Mux0X( unop(Iop_32to8, mkexpr(sign)), + mkU32(0), + unop(Iop_Not32, mkexpr(mask)) )); + // Ra = Rs_shift | sext + assign( Ra, binop(Iop_Or32, mkexpr(sext), mkexpr(Rs_sh)) ); + putIReg( Ra_addr, mkexpr(Ra) ); + op = PPC32G_FLAG_OP_SRAWI; + do_ca = True; + break; + + case 0x218: // srw (Shift Right Word, p575) + DIP("srw%s r%d,r%d,r%d\n", flag_Rc ? "." : "", + Ra_addr, Rs_addr, Rb_addr); + assign( sh_amt, binop(Iop_And8, mkU8(0x1F), + unop(Iop_32to8, getIReg(Rb_addr))) ); + assign( Rs_sh, binop(Iop_Shr32, mkexpr(Rs), mkexpr(sh_amt)) ); + assign( rb_b5, binop(Iop_And32, mkexpr(Rb), mkU32(1<<5)) ); + assign( Ra, IRExpr_Mux0X( unop(Iop_32to8, mkexpr(rb_b5)), + mkU32(0), mkexpr(Rs_sh) )); + putIReg( Ra_addr, mkexpr(Ra) ); + break; + + default: + vex_printf("dis_int_shift(PPC32)(opc2)\n"); + return False; + } + } else { + vex_printf("dis_int_shift(PPC32)(opc1)\n"); + return False; + } + + if (do_ca) { + vassert(op < PPC32G_FLAG_OP_NUMBER); + setFlags_XER_CA( op, mkexpr(Ra), mkexpr(Rs), mkexpr(Rb) ); + } + if (flag_Rc) { + setFlags_CR7( mkexpr(Ra) ); + } + return True; } static Bool dis_int_ldst_rev ( UInt theInstr ) { - /* X-Form */ - UChar opc1 = toUChar((theInstr >> 26) & 0x3F); /* theInstr[26:31] */ - UChar Rd_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ - UChar Rs_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ - UChar Ra_addr = toUChar((theInstr >> 16) & 0x1F); /* theInstr[16:20] */ - UChar Rb_addr = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */ - UInt opc2 = (theInstr >> 1) & 0x3FF; /* theInstr[1:10] */ - UChar b0 = toUChar((theInstr >> 0) & 1); /* theInstr[0] */ - - IRTemp EA = newTemp(Ity_I32); - IRTemp Rd = newTemp(Ity_I32); - IRTemp Rs = newTemp(Ity_I32); - IRTemp byte0 = newTemp(Ity_I32); - IRTemp byte1 = newTemp(Ity_I32); - IRTemp byte2 = newTemp(Ity_I32); - IRTemp byte3 = newTemp(Ity_I32); - IRTemp tmp16 = newTemp(Ity_I16); - IRTemp tmp32 = newTemp(Ity_I32); - - if (opc1 != 0x1F || b0 != 0) { - vex_printf("dis_int_ldst_rev(PPC32)(opc1|b0)\n"); - return False; - } - - if (Ra_addr == 0) { - assign( EA, getIReg(Rb_addr)); - } else { - assign( EA, binop(Iop_Add32, getIReg(Ra_addr), getIReg(Rb_addr)) ); - } - - switch (opc2) { - case 0x316: // lhbrx (Load Half Word Byte-Reverse Indexed, p489) - DIP("lhbrx r%d,r%d,r%d\n", Rd_addr, Ra_addr, Rb_addr); - assign( byte0, loadBE(Ity_I8, mkexpr(EA)) ); - assign( byte1, loadBE(Ity_I8, binop(Iop_Add32, mkexpr(EA),mkU32(1))) ); - assign( Rd, binop(Iop_Or32, - binop(Iop_Shl32, mkexpr(byte1), mkU8(8)), - mkexpr(byte0)) ); - putIReg( Rd_addr, mkexpr(Rd)); - break; - - case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, p503) - DIP("lwbrx r%d,r%d,r%d\n", Rd_addr, Ra_addr, Rb_addr); - assign( byte0, loadBE(Ity_I8, mkexpr(EA)) ); - assign( byte1, loadBE(Ity_I8, binop(Iop_Add32, mkexpr(EA),mkU32(1))) ); - assign( byte2, loadBE(Ity_I8, binop(Iop_Add32, mkexpr(EA),mkU32(2))) ); - assign( byte3, loadBE(Ity_I8, binop(Iop_Add32, mkexpr(EA),mkU32(3))) ); - assign( Rd, binop(Iop_Or32, - binop(Iop_Or32, - binop(Iop_Shl32, mkexpr(byte3), mkU8(24)), - binop(Iop_Shl32, mkexpr(byte2), mkU8(16))), - binop(Iop_Or32, - binop(Iop_Shl32, mkexpr(byte1), mkU8(8)), - mkexpr(byte0))) ); - putIReg( Rd_addr, mkexpr(Rd)); - break; - - case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, p596) - DIP("sthbrx r%d,r%d,r%d\n", Rs_addr, Ra_addr, Rb_addr); - assign( Rs, getIReg(Rs_addr) ); - assign( byte0, binop(Iop_And32, mkexpr(Rs), mkU32(0x00FF)) ); - assign( byte1, binop(Iop_And32, mkexpr(Rs), mkU32(0xFF00)) ); - - assign( tmp16, - unop(Iop_32to16, - binop(Iop_Or32, - binop(Iop_Shl32, mkexpr(byte0), mkU8(8)), - binop(Iop_Shr32, mkexpr(byte1), mkU8(8)))) ); - storeBE( mkexpr(EA), getIReg(tmp16) ); - break; - - case 0x296: // stwbrx (Store Word Byte-Reverse Indexed, p604) - DIP("stwbrx r%d,r%d,r%d\n", Rs_addr, Ra_addr, Rb_addr); - assign( Rs, getIReg(Rs_addr) ); - assign( byte0, binop(Iop_And32, mkexpr(Rs), mkU32(0x000000FF)) ); - assign( byte1, binop(Iop_And32, mkexpr(Rs), mkU32(0x0000FF00)) ); - assign( byte2, binop(Iop_And32, mkexpr(Rs), mkU32(0x00FF0000)) ); - assign( byte3, binop(Iop_And32, mkexpr(Rs), mkU32(0xFF000000)) ); - - assign( tmp32, - binop(Iop_Or32, - binop(Iop_Or32, - binop(Iop_Shl32, mkexpr(byte0), mkU8(24)), - binop(Iop_Shl32, mkexpr(byte1), mkU8(8))), - binop(Iop_Or32, - binop(Iop_Shr32, mkexpr(byte2), mkU8(8)), - binop(Iop_Shr32, mkexpr(byte3), mkU8(24)))) ); - storeBE( mkexpr(EA), mkexpr(tmp32) ); - break; - - default: - vex_printf("dis_int_ldst_rev(PPC32)(opc2)\n"); - return False; - } - return True; + /* X-Form */ + UChar opc1 = toUChar((theInstr >> 26) & 0x3F); /* theInstr[26:31] */ + UChar Rd_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ + UChar Rs_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ + UChar Ra_addr = toUChar((theInstr >> 16) & 0x1F); /* theInstr[16:20] */ + UChar Rb_addr = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */ + UInt opc2 = (theInstr >> 1) & 0x3FF; /* theInstr[1:10] */ + UChar b0 = toUChar((theInstr >> 0) & 1); /* theInstr[0] */ + + IRTemp EA = newTemp(Ity_I32); + IRTemp Rd = newTemp(Ity_I32); + IRTemp Rs = newTemp(Ity_I32); + IRTemp byte0 = newTemp(Ity_I32); + IRTemp byte1 = newTemp(Ity_I32); + IRTemp byte2 = newTemp(Ity_I32); + IRTemp byte3 = newTemp(Ity_I32); + IRTemp tmp16 = newTemp(Ity_I16); + IRTemp tmp32 = newTemp(Ity_I32); + + if (opc1 != 0x1F || b0 != 0) { + vex_printf("dis_int_ldst_rev(PPC32)(opc1|b0)\n"); + return False; + } + + if (Ra_addr == 0) { + assign( EA, getIReg(Rb_addr)); + } else { + assign( EA, binop(Iop_Add32, getIReg(Ra_addr), getIReg(Rb_addr)) ); + } + + switch (opc2) { + case 0x316: // lhbrx (Load Half Word Byte-Reverse Indexed, p489) + DIP("lhbrx r%d,r%d,r%d\n", Rd_addr, Ra_addr, Rb_addr); + assign( byte0, loadBE(Ity_I8, mkexpr(EA)) ); + assign( byte1, loadBE(Ity_I8, binop(Iop_Add32, mkexpr(EA),mkU32(1))) ); + assign( Rd, binop(Iop_Or32, + binop(Iop_Shl32, mkexpr(byte1), mkU8(8)), + mkexpr(byte0)) ); + putIReg( Rd_addr, mkexpr(Rd)); + break; + + case 0x216: // lwbrx (Load Word Byte-Reverse Indexed, p503) + DIP("lwbrx r%d,r%d,r%d\n", Rd_addr, Ra_addr, Rb_addr); + assign( byte0, loadBE(Ity_I8, mkexpr(EA)) ); + assign( byte1, loadBE(Ity_I8, binop(Iop_Add32, mkexpr(EA),mkU32(1))) ); + assign( byte2, loadBE(Ity_I8, binop(Iop_Add32, mkexpr(EA),mkU32(2))) ); + assign( byte3, loadBE(Ity_I8, binop(Iop_Add32, mkexpr(EA),mkU32(3))) ); + assign( Rd, binop(Iop_Or32, + binop(Iop_Or32, + binop(Iop_Shl32, mkexpr(byte3), mkU8(24)), + binop(Iop_Shl32, mkexpr(byte2), mkU8(16))), + binop(Iop_Or32, + binop(Iop_Shl32, mkexpr(byte1), mkU8(8)), + mkexpr(byte0))) ); + putIReg( Rd_addr, mkexpr(Rd)); + break; + + case 0x396: // sthbrx (Store Half Word Byte-Reverse Indexed, p596) + DIP("sthbrx r%d,r%d,r%d\n", Rs_addr, Ra_addr, Rb_addr); + assign( Rs, getIReg(Rs_addr) ); + assign( byte0, binop(Iop_And32, mkexpr(Rs), mkU32(0x00FF)) ); + assign( byte1, binop(Iop_And32, mkexpr(Rs), mkU32(0xFF00)) ); + + assign( tmp16, + unop(Iop_32to16, + binop(Iop_Or32, + binop(Iop_Shl32, mkexpr(byte0), mkU8(8)), + binop(Iop_Shr32, mkexpr(byte1), mkU8(8)))) ); + storeBE( mkexpr(EA), getIReg(tmp16) ); + break; + + case 0x296: // stwbrx (Store Word Byte-Reverse Indexed, p604) + DIP("stwbrx r%d,r%d,r%d\n", Rs_addr, Ra_addr, Rb_addr); + assign( Rs, getIReg(Rs_addr) ); + assign( byte0, binop(Iop_And32, mkexpr(Rs), mkU32(0x000000FF)) ); + assign( byte1, binop(Iop_And32, mkexpr(Rs), mkU32(0x0000FF00)) ); + assign( byte2, binop(Iop_And32, mkexpr(Rs), mkU32(0x00FF0000)) ); + assign( byte3, binop(Iop_And32, mkexpr(Rs), mkU32(0xFF000000)) ); + + assign( tmp32, + binop(Iop_Or32, + binop(Iop_Or32, + binop(Iop_Shl32, mkexpr(byte0), mkU8(24)), + binop(Iop_Shl32, mkexpr(byte1), mkU8(8))), + binop(Iop_Or32, + binop(Iop_Shr32, mkexpr(byte2), mkU8(8)), + binop(Iop_Shr32, mkexpr(byte3), mkU8(24)))) ); + storeBE( mkexpr(EA), mkexpr(tmp32) ); + break; + + default: + vex_printf("dis_int_ldst_rev(PPC32)(opc2)\n"); + return False; + } + return True; } static Bool dis_proc_ctl ( UInt theInstr ) { - UChar opc1 = toUChar((theInstr >> 26) & 0x3F); /* theInstr[26:31] */ - - /* X-Form */ - UChar crfD = toUChar((theInstr >> 23) & 0x7); /* theInstr[23:25] */ - UChar b21to22 = toUChar((theInstr >> 21) & 0x3); /* theInstr[21:22] */ - UChar Rd_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ - UInt b11to20 = (theInstr >> 11) & 0x3FF; /* theInstr[11:20] */ - - /* XFX-Form */ - UChar Rs_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ - UInt SPR = (theInstr >> 11) & 0x3FF; /* theInstr[11:20] */ - UInt TBR = (theInstr >> 11) & 0x3FF; /* theInstr[11:20] */ - UChar b20 = toUChar((theInstr >> 11) & 0x1); /* theInstr[11] */ - UInt CRM = (theInstr >> 12) & 0xFF; /* theInstr[12:19] */ - UChar b11 = toUChar((theInstr >> 11) & 0x1); /* theInstr[20] */ - - UInt opc2 = (theInstr >> 1) & 0x3FF; /* theInstr[1:10] */ - UChar b0 = toUChar((theInstr >> 0) & 1); /* theInstr[0] */ - - UInt SPR_flipped = ((SPR & 0x1F) << 5) | ((SPR >> 5) & 0x1F); - UInt mask; - UChar i; - - IRTemp xer_f7 = newTemp(Ity_I32); - IRTemp Rs = newTemp(Ity_I32); - - assign( Rs, getIReg(Rs_addr) ); - - if (opc1 != 0x1F || b0 != 0) { - vex_printf("dis_proc_ctl(PPC32)(opc1|b0)\n"); - return False; - } - - switch (opc2) { - /* X-Form */ - case 0x200: // mcrxr (Move to Condition Register from XER, p510) - if (b21to22 != 0 || b11to20 != 0) { - vex_printf("dis_proc_ctl(PPC32)(mcrxr,b21to22|b11to20)\n"); - return False; - } - DIP("mcrxr crf%d\n", crfD); - - // CR[7-crfD] = XER[28-31] - assign( xer_f7, binop(Iop_Shr32, - getReg_masked( REG_XER, 0xF0000000 ), - mkU8(28)) ); - putReg_field( REG_CR, 7-crfD, mkexpr(xer_f7) ); - - // Clear XER[28 - 31] - putReg_field( REG_XER, 7, mkU32(0) ); - break; - - case 0x013: // mfcr (Move from Condition Register, p511) - if (b11to20 != 0) { - vex_printf("dis_proc_ctl(PPC32)(mfcr,b11to20)\n"); - return False; - } - DIP("mfcr crf%d\n", Rd_addr); - putIReg( Rd_addr, getReg( REG_CR ) ); - break; - - /* XFX-Form */ - case 0x153: // mfspr (Move from Special-Purpose Register, p514) - DIP("mfspr r%d,0x%x\n", Rd_addr, SPR_flipped); - - switch (SPR_flipped) { // Choose a register... - case 0x1: // XER - putIReg( Rd_addr, getReg( REG_XER ) ); - break; - case 0x8: // LR - putIReg( Rd_addr, getReg( REG_LR ) ); - break; - case 0x9: // CTR - putIReg( Rd_addr, getReg( REG_CTR ) ); - break; - - case 0x012: case 0x013: case 0x016: - case 0x019: case 0x01A: case 0x01B: - case 0x110: case 0x111: case 0x112: case 0x113: + UChar opc1 = toUChar((theInstr >> 26) & 0x3F); /* theInstr[26:31] */ + + /* X-Form */ + UChar crfD = toUChar((theInstr >> 23) & 0x7); /* theInstr[23:25] */ + UChar b21to22 = toUChar((theInstr >> 21) & 0x3); /* theInstr[21:22] */ + UChar Rd_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ + UInt b11to20 = (theInstr >> 11) & 0x3FF; /* theInstr[11:20] */ + + /* XFX-Form */ + UChar Rs_addr = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ + UInt SPR = (theInstr >> 11) & 0x3FF; /* theInstr[11:20] */ + UInt TBR = (theInstr >> 11) & 0x3FF; /* theInstr[11:20] */ + UChar b20 = toUChar((theInstr >> 11) & 0x1); /* theInstr[11] */ + UInt CRM = (theInstr >> 12) & 0xFF; /* theInstr[12:19] */ + UChar b11 = toUChar((theInstr >> 11) & 0x1); /* theInstr[20] */ + + UInt opc2 = (theInstr >> 1) & 0x3FF; /* theInstr[1:10] */ + UChar b0 = toUChar((theInstr >> 0) & 1); /* theInstr[0] */ + + UInt SPR_flipped = ((SPR & 0x1F) << 5) | ((SPR >> 5) & 0x1F); + UInt mask; + UChar i; + + IRTemp xer_f7 = newTemp(Ity_I32); + IRTemp Rs = newTemp(Ity_I32); + + assign( Rs, getIReg(Rs_addr) ); + + if (opc1 != 0x1F || b0 != 0) { + vex_printf("dis_proc_ctl(PPC32)(opc1|b0)\n"); + return False; + } + + switch (opc2) { + /* X-Form */ + case 0x200: // mcrxr (Move to Condition Register from XER, p510) + if (b21to22 != 0 || b11to20 != 0) { + vex_printf("dis_proc_ctl(PPC32)(mcrxr,b21to22|b11to20)\n"); + return False; + } + DIP("mcrxr crf%d\n", crfD); + + // CR[7-crfD] = XER[28-31] + assign( xer_f7, binop(Iop_Shr32, + getReg_masked( REG_XER, 0xF0000000 ), + mkU8(28)) ); + putReg_field( REG_CR, 7-crfD, mkexpr(xer_f7) ); + + // Clear XER[28 - 31] + putReg_field( REG_XER, 7, mkU32(0) ); + break; + + case 0x013: // mfcr (Move from Condition Register, p511) + if (b11to20 != 0) { + vex_printf("dis_proc_ctl(PPC32)(mfcr,b11to20)\n"); + return False; + } + DIP("mfcr crf%d\n", Rd_addr); + putIReg( Rd_addr, getReg( REG_CR ) ); + break; + + /* XFX-Form */ + case 0x153: // mfspr (Move from Special-Purpose Register, p514) + DIP("mfspr r%d,0x%x\n", Rd_addr, SPR_flipped); + + switch (SPR_flipped) { // Choose a register... + case 0x1: // XER + putIReg( Rd_addr, getReg( REG_XER ) ); + break; + case 0x8: // LR + putIReg( Rd_addr, getReg( REG_LR ) ); + break; + case 0x9: // CTR + putIReg( Rd_addr, getReg( REG_CTR ) ); + break; + + case 0x012: case 0x013: case 0x016: + case 0x019: case 0x01A: case 0x01B: + case 0x110: case 0x111: case 0x112: case 0x113: // case 0x118: // 64bit only - case 0x11A: case 0x11F: - case 0x210: case 0x211: case 0x212: case 0x213: - case 0x214: case 0x215: case 0x216: case 0x217: - case 0x218: case 0x219: case 0x21A: case 0x21B: - case 0x21C: case 0x21D: case 0x21E: case 0x21F: - case 0x3F5: - vex_printf("dis_proc_ctl(PPC32)(mfspr) - supervisor level op\n"); - return False; - - default: - vex_printf("dis_proc_ctl(PPC32)(mfspr,SPR)\n"); - return False; - } - break; - - case 0x173: // mftb (Move from Time Base, p521) - DIP("mftb r%d,0x%x\n", Rd_addr, TBR); - return False; - - case 0x090: // mtcrf (Move to Condition Register Fields, p523) - if (b11 != 0 || b20 != 0) { - vex_printf("dis_proc_ctl(PPC32)(mtcrf,b11|b20)\n"); - return False; - } - DIP("mtcrf 0x%x,r%d\n", CRM, Rs_addr); - mask=0; - for (i=0; i<8; i++) { - if (CRM & (1<> 26) & 0x3F); /* theInstr[26:31] */ - UChar b21to25 = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ - UChar Ra_addr = toUChar((theInstr >> 16) & 0x1F); /* theInstr[16:20] */ - UChar Rb_addr = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */ - UInt opc2 = (theInstr >> 1) & 0x3FF; /* theInstr[1:10] */ - UChar b0 = toUChar((theInstr >> 0) & 1); /* theInstr[0] */ - - if (opc1 != 0x1F || b21to25 != 0 || b0 != 0) { - vex_printf("dis_cache_manage(PPC32)(opc1|b21to25|b0)\n"); - return False; - } - - switch (opc2) { - case 0x2F6: // dcba (Data Cache Block Allocate, p411) - DIP("dcba r%d,r%d\n", Ra_addr, Rb_addr); - if (1) vex_printf("vex ppc32->IR: kludged dcba\n"); - break; - - case 0x056: // dcbf (Data Cache Block Flush, p413) - DIP("dcbf r%d,r%d\n", Ra_addr, Rb_addr); - if (1) vex_printf("vex ppc32->IR: kludged dcbf\n"); - break; - - case 0x036: // dcbst (Data Cache Block Store, p415) - DIP("dcbst r%d,r%d\n", Ra_addr, Rb_addr); - if (1) vex_printf("vex ppc32->IR: kludged dcbst\n"); - break; - - case 0x116: // dcbt (Data Cache Block Touch, p416) - DIP("dcbt r%d,r%d\n", Ra_addr, Rb_addr); - if (1) vex_printf("vex ppc32->IR: kludged dcbt\n"); - break; - - case 0x0F6: // dcbtst (Data Cache Block Touch for Store, p417) - DIP("dcbtst r%d,r%d\n", Ra_addr, Rb_addr); - if (1) vex_printf("vex ppc32->IR: kludged dcbtst\n"); - break; - - case 0x3F6: // dcbz (Data Cache Block Clear to Zero, p418) - DIP("dcbz r%d,r%d\n", Ra_addr, Rb_addr); - if (1) vex_printf("vex ppc32->IR: kludged dcbz\n"); - break; - - case 0x3D6: // icbi (Instruction Cache Block Invalidate, p466) - DIP("icbi r%d,r%d\n", Ra_addr, Rb_addr); - if (1) vex_printf("vex ppc32->IR: kludged icbi\n"); - break; + /* X-Form */ + UChar opc1 = toUChar((theInstr >> 26) & 0x3F); /* theInstr[26:31] */ + UChar b21to25 = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */ + UChar Ra_addr = toUChar((theInstr >> 16) & 0x1F); /* theInstr[16:20] */ + UChar Rb_addr = toUChar((theInstr >> 11) & 0x1F); /* theInstr[11:15] */ + UInt opc2 = (theInstr >> 1) & 0x3FF; /* theInstr[1:10] */ + UChar b0 = toUChar((theInstr >> 0) & 1); /* theInstr[0] */ + + if (opc1 != 0x1F || b21to25 != 0 || b0 != 0) { + vex_printf("dis_cache_manage(PPC32)(opc1|b21to25|b0)\n"); + return False; + } + + switch (opc2) { + case 0x2F6: // dcba (Data Cache Block Allocate, p411) + DIP("dcba r%d,r%d\n", Ra_addr, Rb_addr); + if (1) vex_printf("vex ppc32->IR: kludged dcba\n"); + break; + + case 0x056: // dcbf (Data Cache Block Flush, p413) + DIP("dcbf r%d,r%d\n", Ra_addr, Rb_addr); + if (1) vex_printf("vex ppc32->IR: kludged dcbf\n"); + break; + + case 0x036: // dcbst (Data Cache Block Store, p415) + DIP("dcbst r%d,r%d\n", Ra_addr, Rb_addr); + if (1) vex_printf("vex ppc32->IR: kludged dcbst\n"); + break; + + case 0x116: // dcbt (Data Cache Block Touch, p416) + DIP("dcbt r%d,r%d\n", Ra_addr, Rb_addr); + if (1) vex_printf("vex ppc32->IR: kludged dcbt\n"); + break; + + case 0x0F6: // dcbtst (Data Cache Block Touch for Store, p417) + DIP("dcbtst r%d,r%d\n", Ra_addr, Rb_addr); + if (1) vex_printf("vex ppc32->IR: kludged dcbtst\n"); + break; + + case 0x3F6: // dcbz (Data Cache Block Clear to Zero, p418) + DIP("dcbz r%d,r%d\n", Ra_addr, Rb_addr); + if (1) vex_printf("vex ppc32->IR: kludged dcbz\n"); + break; + + case 0x3D6: // icbi (Instruction Cache Block Invalidate, p466) + DIP("icbi r%d,r%d\n", Ra_addr, Rb_addr); + if (1) vex_printf("vex ppc32->IR: kludged icbi\n"); + break; - default: - vex_printf("dis_cache_manage(PPC32)(opc2)\n"); - return False; - } - return True; + default: + vex_printf("dis_cache_manage(PPC32)(opc2)\n"); + return False; + } + return True; } @@ -3192,12 +3194,12 @@ static DisResult disInstr ( /*IN*/ Bool resteerOK, UInt* code = (UInt*)(guest_code + delta); /* Spot this: - 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) - 0x54006800 rlwinm 0,0,13,0,0 => r0 = rotl(r0,13) - 0x54009800 rlwinm 0,0,19,0,0 => r0 = rotl(r0,19) - 0x60000000 ori 0,0,0 => r0 = r0 | 0 + 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) + 0x54006800 rlwinm 0,0,13,0,0 => r0 = rotl(r0,13) + 0x54009800 rlwinm 0,0,19,0,0 => r0 = rotl(r0,19) + 0x60000000 ori 0,0,0 => r0 = r0 | 0 */ if (code[0] == 0x60000000 && code[1] == 0x5400E800 && @@ -3209,11 +3211,11 @@ static DisResult disInstr ( /*IN*/ Bool resteerOK, // uh ... I'll figure this out later. possibly r0 = client_request(r0) DIP("?CAB? = client_request ( ?CAB? )\n"); - *size = 24; - - irbb->next = mkU32(guest_pc_bbstart+delta); - irbb->jumpkind = Ijk_ClientReq; - + *size = 24; + + irbb->next = mkU32(guest_pc_bbstart+delta); + irbb->jumpkind = Ijk_ClientReq; + whatNext = Dis_StopHere; goto decode_success; } @@ -3239,9 +3241,9 @@ static DisResult disInstr ( /*IN*/ Bool resteerOK, #endif if (theInstr == 0x7C0042A6) { - // CAB: what's this? - DIP("Invalid instruction! Would be 'mfspr 0,256'. Passing through for now...\n"); - goto decode_success; + // CAB: what's this? + DIP("Invalid instruction! Would be 'mfspr 0,256'. Passing through for now...\n"); + goto decode_success; } // Note: all 'reserved' bits must be cleared, else invalid @@ -3256,18 +3258,18 @@ static DisResult disInstr ( /*IN*/ Bool resteerOK, case 0x0F: // addis case 0x07: // mulli case 0x08: // subfic - if (dis_int_arith(theInstr)) - break; - goto decode_failure; + if (dis_int_arith(theInstr)) + break; + goto decode_failure; /* Integer Compare Instructions */ case 0x0B: // cmpi case 0x0A: // cmpli - if (dis_int_cmp(theInstr)) - break; - goto decode_failure; + if (dis_int_cmp(theInstr)) + break; + goto decode_failure; /* Integer Logical Instructions @@ -3278,9 +3280,9 @@ static DisResult disInstr ( /*IN*/ Bool resteerOK, case 0x19: // oris case 0x1A: // xori case 0x1B: // xoris - if (dis_int_logic(theInstr)) - break; - goto decode_failure; + if (dis_int_logic(theInstr)) + break; + goto decode_failure; /* Integer Rotate Instructions @@ -3288,9 +3290,9 @@ static DisResult disInstr ( /*IN*/ Bool resteerOK, case 0x14: // rlwimi case 0x15: // rlwinm case 0x17: // rlwnm - if (dis_int_rot(theInstr)) - break; - goto decode_failure; + if (dis_int_rot(theInstr)) + break; + goto decode_failure; /* Integer Load Instructions @@ -3303,9 +3305,9 @@ static DisResult disInstr ( /*IN*/ Bool resteerOK, case 0x29: // lhzu case 0x20: // lwz case 0x21: // lwzu - if (dis_int_load(theInstr)) - break; - goto decode_failure; + if (dis_int_load(theInstr)) + break; + goto decode_failure; /* Integer Store Instructions @@ -3316,42 +3318,42 @@ static DisResult disInstr ( /*IN*/ Bool resteerOK, case 0x2D: // sthu case 0x24: // stw case 0x25: // stwu - if (dis_int_store(theInstr)) - break; - goto decode_failure; + if (dis_int_store(theInstr)) + break; + goto decode_failure; /* Integer Load and Store Multiple Instructions */ case 0x2E: // lmw case 0x2F: // stmw - if (dis_int_ldst_mult(theInstr)) - break; - goto decode_failure; + if (dis_int_ldst_mult(theInstr)) + break; + goto decode_failure; /* Branch Instructions */ case 0x12: // b case 0x10: // bc - if (dis_branch(theInstr, &whatNext)) - break; - goto decode_failure; + if (dis_branch(theInstr, &whatNext)) + break; + goto decode_failure; /* System Linkage Instructions */ case 0x11: // sc - if (dis_syslink(theInstr, &whatNext)) - break; - goto decode_failure; + if (dis_syslink(theInstr, &whatNext)) + break; + goto decode_failure; /* Trap Instructions */ case 0x03: // twi - DIP("trap op (twi) => not implemented\n"); - goto decode_failure; + DIP("trap op (twi) => not implemented\n"); + goto decode_failure; /* Floating Point Ops @@ -3366,262 +3368,261 @@ static DisResult disInstr ( /*IN*/ Bool resteerOK, case 0x37: case 0x3B: case 0x3F: - DIP("Floating Point Op => not implemented\n"); - break; -// goto decode_failure; + DIP("Floating Point Op => not implemented\n"); + break; +// goto decode_failure; case 0x13: - switch (opc2) { - - /* - Condition Register Logical Instructions - */ - case 0x101: // crand - case 0x081: // crandc - case 0x121: // creqv - case 0x0E1: // crnand - case 0x021: // crnor - case 0x1C1: // cror - case 0x1A1: // crorc - case 0x0C1: // crxor - case 0x000: // mcrf - DIP("condition register logical op => not implemented\n"); - goto decode_failure; - - /* - Branch Instructions - */ - case 0x210: // bcctr - case 0x010: // bclr - if (dis_branch(theInstr, &whatNext)) - break; - goto decode_failure; - - /* - Memory Synchronization Instructions - */ - case 0x096: // isync - if (dis_memsync(theInstr)) - break; - goto decode_failure; + switch (opc2) { + + /* + Condition Register Logical Instructions + */ + case 0x101: // crand + case 0x081: // crandc + case 0x121: // creqv + case 0x0E1: // crnand + case 0x021: // crnor + case 0x1C1: // cror + case 0x1A1: // crorc + case 0x0C1: // crxor + case 0x000: // mcrf + DIP("condition register logical op => not implemented\n"); + goto decode_failure; + + /* + Branch Instructions + */ + case 0x210: // bcctr + case 0x010: // bclr + if (dis_branch(theInstr, &whatNext)) + break; + goto decode_failure; - default: - goto decode_failure; - } - break; - - - case 0x1F: - opc2 = (theInstr >> 1) & 0x1FF; /* theInstr[1:9] */ - switch (opc2) { - - /* - Integer Arithmetic Instructions - */ - case 0x10A: // add - case 0x00A: // addc - case 0x08A: // adde - case 0x0EA: // addme - case 0x0CA: // addze - case 0x1EB: // divw - case 0x1CB: // divwu - case 0x04B: // mulhw - case 0x00B: // mulhwu - case 0x0EB: // mullw - case 0x068: // neg - case 0x028: // subf - case 0x008: // subfc - case 0x088: // subfe - case 0x0E8: // subfme - case 0x0C8: // subfze - if (dis_int_arith(theInstr)) goto decode_success; - goto decode_failure; + /* + Memory Synchronization Instructions + */ + case 0x096: // isync + if (dis_memsync(theInstr)) + break; + goto decode_failure; + + default: + goto decode_failure; + } + break; - default: - break; - } - - - opc2 = (theInstr >> 1) & 0x3FF; /* theInstr[1:10] */ - switch (opc2) { - - /* - Integer Compare Instructions - */ - case 0x000: // cmp - case 0x020: // cmpl - if (dis_int_cmp(theInstr)) - break; - goto decode_failure; - - /* - Integer Logical Instructions - */ - case 0x01C: // and - case 0x03C: // andc - case 0x01A: // cntlzw - case 0x11C: // eqv - case 0x3BA: // extsb - case 0x39A: // extsh - case 0x1DC: // nand - case 0x07C: // nor - case 0x1BC: // or - case 0x19C: // orc - case 0x13C: // xor - if (dis_int_logic(theInstr)) - break; - goto decode_failure; - - /* - Integer Shift Instructions - */ - case 0x018: // slw - case 0x318: // sraw - case 0x338: // srawi - case 0x218: // srw - if (dis_int_shift(theInstr)) - break; - goto decode_failure; - - /* - Integer Load Instructions - */ - case 0x057: // lbzx - case 0x077: // lbzux - case 0x157: // lhax - case 0x177: // lhaux - case 0x117: // lhzx - case 0x137: // lhzux - case 0x017: // lwzx - case 0x037: // lwzux - if (dis_int_load(theInstr)) - break; - goto decode_failure; - - /* - Integer Store Instructions - */ - case 0x0F7: // stbux - case 0x0D7: // stbx - case 0x1B7: // sthux - case 0x197: // sthx - case 0x0B7: // stwux - case 0x097: // stwx - if (dis_int_store(theInstr)) - break; - goto decode_failure; - - /* - Integer Load and Store with Byte Reverse Instructions - */ - case 0x316: // lhbrx - case 0x216: // lwbrx - case 0x396: // sthbrx - case 0x296: // stwbrx - if (dis_int_ldst_rev(theInstr)) - break; - goto decode_failure; - - /* - Integer Load and Store String Instructions - */ - case 0x255: // lswi - case 0x215: // lswx - case 0x2D5: // stswi - case 0x295: // stswx - if (dis_int_ldst_str(theInstr)) - break; - goto decode_failure; - - /* - Memory Synchronization Instructions - */ - case 0x356: // eieio - case 0x014: // lwarx - case 0x096: // stwcx. - case 0x256: // sync - if (dis_memsync(theInstr)) - break; - goto decode_failure; - - /* - Processor Control Instructions - */ - case 0x200: // mcrxr - case 0x013: // mfcr - case 0x153: // mfspr - case 0x173: // mftb - case 0x090: // mtcrf - case 0x1D3: // mtspr - if (dis_proc_ctl(theInstr)) - break; - goto decode_failure; - - /* - Cache Management Instructions - */ - case 0x2F6: // dcba - case 0x056: // dcbf - case 0x036: // dcbst - case 0x116: // dcbt - case 0x0F6: // dcbtst - case 0x3F6: // dcbz - case 0x3D6: // icbi - if (dis_cache_manage(theInstr)) - break; - goto decode_failure; - - /* - External Control Instructions - Rc=0 - */ - case 0x136: // eciwx - case 0x1B6: // ecowx - DIP("external control op => not implemented\n"); - goto decode_failure; - - /* - Trap Instructions - */ - case 0x004: // tw - DIP("trap op (tw) => not implemented\n"); - goto decode_failure; - - /* - Floating Point Ops - */ - case 0x217: - case 0x237: - case 0x257: - case 0x277: - case 0x297: - case 0x2B7: - case 0x2D7: - case 0x2F7: - case 0x3D7: - DIP("Floating Point Op => not implemented\n"); - break; -// goto decode_failure; - - /* - AltiVec instructions - */ - case 0x0E7: // stvx - DIP("Altivec op (stvx) => not implemented\n"); - goto decode_success; - default: - goto decode_failure; - } - break; + case 0x1F: + opc2 = (theInstr >> 1) & 0x1FF; /* theInstr[1:9] */ + switch (opc2) { + + /* + Integer Arithmetic Instructions + */ + case 0x10A: // add + case 0x00A: // addc + case 0x08A: // adde + case 0x0EA: // addme + case 0x0CA: // addze + case 0x1EB: // divw + case 0x1CB: // divwu + case 0x04B: // mulhw + case 0x00B: // mulhwu + case 0x0EB: // mullw + case 0x068: // neg + case 0x028: // subf + case 0x008: // subfc + case 0x088: // subfe + case 0x0E8: // subfme + case 0x0C8: // subfze + if (dis_int_arith(theInstr)) goto decode_success; + goto decode_failure; + + default: + break; + } + + opc2 = (theInstr >> 1) & 0x3FF; /* theInstr[1:10] */ + switch (opc2) { + + /* + Integer Compare Instructions + */ + case 0x000: // cmp + case 0x020: // cmpl + if (dis_int_cmp(theInstr)) + break; + goto decode_failure; + + /* + Integer Logical Instructions + */ + case 0x01C: // and + case 0x03C: // andc + case 0x01A: // cntlzw + case 0x11C: // eqv + case 0x3BA: // extsb + case 0x39A: // extsh + case 0x1DC: // nand + case 0x07C: // nor + case 0x1BC: // or + case 0x19C: // orc + case 0x13C: // xor + if (dis_int_logic(theInstr)) + break; + goto decode_failure; + + /* + Integer Shift Instructions + */ + case 0x018: // slw + case 0x318: // sraw + case 0x338: // srawi + case 0x218: // srw + if (dis_int_shift(theInstr)) + break; + goto decode_failure; + + /* + Integer Load Instructions + */ + case 0x057: // lbzx + case 0x077: // lbzux + case 0x157: // lhax + case 0x177: // lhaux + case 0x117: // lhzx + case 0x137: // lhzux + case 0x017: // lwzx + case 0x037: // lwzux + if (dis_int_load(theInstr)) + break; + goto decode_failure; + + /* + Integer Store Instructions + */ + case 0x0F7: // stbux + case 0x0D7: // stbx + case 0x1B7: // sthux + case 0x197: // sthx + case 0x0B7: // stwux + case 0x097: // stwx + if (dis_int_store(theInstr)) + break; + goto decode_failure; + + /* + Integer Load and Store with Byte Reverse Instructions + */ + case 0x316: // lhbrx + case 0x216: // lwbrx + case 0x396: // sthbrx + case 0x296: // stwbrx + if (dis_int_ldst_rev(theInstr)) + break; + goto decode_failure; + + /* + Integer Load and Store String Instructions + */ + case 0x255: // lswi + case 0x215: // lswx + case 0x2D5: // stswi + case 0x295: // stswx + if (dis_int_ldst_str(theInstr)) + break; + goto decode_failure; + + /* + Memory Synchronization Instructions + */ + case 0x356: // eieio + case 0x014: // lwarx + case 0x096: // stwcx. + case 0x256: // sync + if (dis_memsync(theInstr)) + break; + goto decode_failure; + + /* + Processor Control Instructions + */ + case 0x200: // mcrxr + case 0x013: // mfcr + case 0x153: // mfspr + case 0x173: // mftb + case 0x090: // mtcrf + case 0x1D3: // mtspr + if (dis_proc_ctl(theInstr)) + break; + goto decode_failure; + + /* + Cache Management Instructions + */ + case 0x2F6: // dcba + case 0x056: // dcbf + case 0x036: // dcbst + case 0x116: // dcbt + case 0x0F6: // dcbtst + case 0x3F6: // dcbz + case 0x3D6: // icbi + if (dis_cache_manage(theInstr)) + break; + goto decode_failure; + + /* + External Control Instructions + Rc=0 + */ + case 0x136: // eciwx + case 0x1B6: // ecowx + DIP("external control op => not implemented\n"); + goto decode_failure; + + /* + Trap Instructions + */ + case 0x004: // tw + DIP("trap op (tw) => not implemented\n"); + goto decode_failure; + + /* + Floating Point Ops + */ + case 0x217: + case 0x237: + case 0x257: + case 0x277: + case 0x297: + case 0x2B7: + case 0x2D7: + case 0x2F7: + case 0x3D7: + DIP("Floating Point Op => not implemented\n"); + break; +// goto decode_failure; + + /* + AltiVec instructions + */ + case 0x0E7: // stvx + DIP("Altivec op (stvx) => not implemented\n"); + goto decode_success; + + default: + goto decode_failure; + } + break; default: decode_failure: /* All decode failures end up here. */ vex_printf("disInstr(ppc32): unhandled instruction: " "0x%x\n", theInstr); - + #if 1 vex_printf("disInstr(ppc32): instr: "); vex_printf_binary( theInstr, 32, True ); diff --git a/VEX/priv/host-ppc32/hdefs.c b/VEX/priv/host-ppc32/hdefs.c index 7ccb83392e..bb28e5b42e 100644 --- a/VEX/priv/host-ppc32/hdefs.c +++ b/VEX/priv/host-ppc32/hdefs.c @@ -48,10 +48,10 @@ void ppHRegPPC32 ( HReg reg ) { Int r; static HChar* ireg32_names[32] - = { "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7", - "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", - "%r16", "%r17", "%r18", "%r19", "%r20", "%r21", "%r22", "%r23", - "%r24", "%r25", "%r26", "%r27", "%r28", "%r29", "%r30", "%r31" }; + = { "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7", + "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", + "%r16", "%r17", "%r18", "%r19", "%r20", "%r21", "%r22", "%r23", + "%r24", "%r25", "%r26", "%r27", "%r28", "%r29", "%r30", "%r31" }; /* Be generic for all virtual regs. */ if (hregIsVirtual(reg)) { ppHReg(reg); @@ -59,18 +59,18 @@ void ppHRegPPC32 ( HReg reg ) } /* But specific for real regs. */ switch (hregClass(reg)) { - case HRcInt32: - r = hregNumber(reg); - vassert(r >= 0 && r < 32); - vex_printf("%s", ireg32_names[r]); - return; - case HRcFlt64: - r = hregNumber(reg); - vassert(r >= 0 && r < 6); - vex_printf("%%fpr%d", r); - return; - default: - vpanic("ppHRegPPC32"); + case HRcInt32: + r = hregNumber(reg); + vassert(r >= 0 && r < 32); + vex_printf("%s", ireg32_names[r]); + return; + case HRcFlt64: + r = hregNumber(reg); + vassert(r >= 0 && r < 6); + vex_printf("%%fpr%d", r); + return; + default: + vpanic("ppHRegPPC32"); } } @@ -247,60 +247,60 @@ PPC32AMode* PPC32AMode_RR ( HReg idx, HReg base ) { PPC32AMode* dopyPPC32AMode ( PPC32AMode* am ) { switch (am->tag) { - case Pam_IR: - return PPC32AMode_IR( am->Pam.IR.index, am->Pam.IR.base ); - case Pam_RR: - return PPC32AMode_RR( am->Pam.RR.index, am->Pam.RR.base ); - default: - vpanic("dopyPPC32AMode"); + case Pam_IR: + return PPC32AMode_IR( am->Pam.IR.index, am->Pam.IR.base ); + case Pam_RR: + return PPC32AMode_RR( am->Pam.RR.index, am->Pam.RR.base ); + default: + vpanic("dopyPPC32AMode"); } } void ppPPC32AMode ( PPC32AMode* am ) { switch (am->tag) { - case Pam_IR: - if (am->Pam.IR.index == 0) - vex_printf("("); - else - vex_printf("0x%x(", am->Pam.IR.index); - ppHRegPPC32(am->Pam.IR.base); - vex_printf(")"); - return; - case Pam_RR: - ppHRegPPC32(am->Pam.RR.base); - vex_printf(","); - ppHRegPPC32(am->Pam.RR.index); - return; - default: - vpanic("ppPPC32AMode"); + case Pam_IR: + if (am->Pam.IR.index == 0) + vex_printf("("); + else + vex_printf("0x%x(", am->Pam.IR.index); + ppHRegPPC32(am->Pam.IR.base); + vex_printf(")"); + return; + case Pam_RR: + ppHRegPPC32(am->Pam.RR.base); + vex_printf(","); + ppHRegPPC32(am->Pam.RR.index); + return; + default: + vpanic("ppPPC32AMode"); } } static void addRegUsage_PPC32AMode ( HRegUsage* u, PPC32AMode* am ) { switch (am->tag) { - case Pam_IR: - addHRegUse(u, HRmRead, am->Pam.IR.base); - return; - case Pam_RR: - addHRegUse(u, HRmRead, am->Pam.RR.base); - addHRegUse(u, HRmRead, am->Pam.RR.index); - return; - default: - vpanic("addRegUsage_PPC32AMode"); + case Pam_IR: + addHRegUse(u, HRmRead, am->Pam.IR.base); + return; + case Pam_RR: + addHRegUse(u, HRmRead, am->Pam.RR.base); + addHRegUse(u, HRmRead, am->Pam.RR.index); + return; + default: + vpanic("addRegUsage_PPC32AMode"); } } static void mapRegs_PPC32AMode ( HRegRemap* m, PPC32AMode* am ) { switch (am->tag) { - case Pam_IR: - am->Pam.IR.base = lookupHRegRemap(m, am->Pam.IR.base); - return; - case Pam_RR: - am->Pam.RR.base = lookupHRegRemap(m, am->Pam.RR.base); - am->Pam.RR.index = lookupHRegRemap(m, am->Pam.RR.index); - return; - default: - vpanic("mapRegs_PPC32AMode"); + case Pam_IR: + am->Pam.IR.base = lookupHRegRemap(m, am->Pam.IR.base); + return; + case Pam_RR: + am->Pam.RR.base = lookupHRegRemap(m, am->Pam.RR.base); + am->Pam.RR.index = lookupHRegRemap(m, am->Pam.RR.index); + return; + default: + vpanic("mapRegs_PPC32AMode"); } } @@ -321,14 +321,14 @@ PPC32RI* PPC32RI_Reg ( HReg reg ) { void ppPPC32RI ( PPC32RI* op ) { switch (op->tag) { - case Pri_Imm: - vex_printf("$0x%x", op->Pri.Imm.imm32); - return; - case Pri_Reg: - ppHRegPPC32(op->Pri.Reg.reg); - return; - default: - vpanic("ppPPC32RI"); + case Pri_Imm: + vex_printf("$0x%x", op->Pri.Imm.imm32); + return; + case Pri_Reg: + ppHRegPPC32(op->Pri.Reg.reg); + return; + default: + vpanic("ppPPC32RI"); } } @@ -337,25 +337,25 @@ void ppPPC32RI ( PPC32RI* op ) { accordingly. */ static void addRegUsage_PPC32RI ( HRegUsage* u, PPC32RI* op ) { switch (op->tag) { - case Pri_Imm: - return; - case Pri_Reg: - addHRegUse(u, HRmRead, op->Pri.Reg.reg); - return; - default: - vpanic("addRegUsage_PPC32RI"); + case Pri_Imm: + return; + case Pri_Reg: + addHRegUse(u, HRmRead, op->Pri.Reg.reg); + return; + default: + vpanic("addRegUsage_PPC32RI"); } } static void mapRegs_PPC32RI ( HRegRemap* m, PPC32RI* op ) { switch (op->tag) { - case Pri_Imm: - return; - case Pri_Reg: - op->Pri.Reg.reg = lookupHRegRemap(m, op->Pri.Reg.reg); - return; - default: - vpanic("mapRegs_PPC32RI"); + case Pri_Imm: + return; + case Pri_Reg: + op->Pri.Reg.reg = lookupHRegRemap(m, op->Pri.Reg.reg); + return; + default: + vpanic("mapRegs_PPC32RI"); } } @@ -371,43 +371,42 @@ static void mapRegs_PPC32RI ( HRegRemap* m, PPC32RI* op ) { HChar* showPPC32UnaryOp ( PPC32UnaryOp op ) { switch (op) { - case Pun_NOT: return "not"; - case Pun_NEG: return "neg"; - case Pun_CLZ: return "cntlzw"; - default: vpanic("showPPC32UnaryOp"); + case Pun_NOT: return "not"; + case Pun_NEG: return "neg"; + case Pun_CLZ: return "cntlzw"; + default: vpanic("showPPC32UnaryOp"); } } HChar* showPPC32AluOp ( PPC32AluOp op ) { switch (op) { -// case Palu_CMP: return "cmp"; - case Palu_ADD: return "add"; - case Palu_SUB: return "subf"; -// case Palu_ADC: return "adc"; -// case Palu_SBB: return "sbb"; - case Palu_AND: return "and"; - case Palu_OR: return "or"; - case Palu_XOR: return "xor"; - case Palu_MUL: return "mull"; - default: vpanic("showPPC32AluOp"); + case Palu_ADD: return "add"; + case Palu_SUB: return "subf"; +// case Palu_ADC: return "adc"; +// case Palu_SBB: return "sbb"; + case Palu_AND: return "and"; + case Palu_OR: return "or"; + case Palu_XOR: return "xor"; + case Palu_MUL: return "mull"; + default: vpanic("showPPC32AluOp"); } } HChar* showPPC32ShiftOp ( PPC32ShiftOp op ) { switch (op) { - case Psh_SHL: return "slw"; - case Psh_SHR: return "srw"; - case Psh_SAR: return "sraw"; - case Psh_ROL: return "rlw"; - default: vpanic("showPPC32ShiftOp"); + case Psh_SHL: return "slw"; + case Psh_SHR: return "srw"; + case Psh_SAR: return "sraw"; + case Psh_ROL: return "rlw"; + default: vpanic("showPPC32ShiftOp"); } } HChar* showPPC32CmpOp ( PPC32CmpOp op ) { switch (op) { - case Pcmp_U: return "cmpl"; - case Pcmp_S: return "cmp"; - default: vpanic("showPPC32CmpOp"); + case Pcmp_U: return "cmpl"; + case Pcmp_S: return "cmp"; + default: vpanic("showPPC32CmpOp"); } } @@ -483,7 +482,7 @@ PPC32Instr* PPC32Instr_Unary32 ( PPC32UnaryOp op, HReg dst, HReg src ) { return i; } PPC32Instr* PPC32Instr_MulL ( Bool syned, Bool word, HReg dst, - HReg src1, PPC32RI* src2 ) { + HReg src1, PPC32RI* src2 ) { PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr)); i->tag = Pin_MulL; i->Pin.MulL.syned = syned; @@ -494,7 +493,7 @@ PPC32Instr* PPC32Instr_MulL ( Bool syned, Bool word, HReg dst, return i; } PPC32Instr* PPC32Instr_Div ( Bool syned, HReg dst, - HReg src1, PPC32RI* src2 ) { + HReg src1, PPC32RI* src2 ) { PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr)); i->tag = Pin_Div; i->Pin.Div.syned = syned; @@ -546,7 +545,7 @@ PPC32Instr* PPC32Instr_CMov32 ( PPC32CondCode cond, HReg dst, PPC32RI* src ) { return i; } PPC32Instr* PPC32Instr_LoadEX ( UChar sz, Bool syned, - HReg dst, PPC32AMode* src ) { + HReg dst, PPC32AMode* src ) { PPC32Instr* i = LibVEX_Alloc(sizeof(PPC32Instr)); i->tag = Pin_LoadEX; i->Pin.LoadEX.sz = sz; @@ -668,85 +667,85 @@ PPC32Instr* PPC32Instr_MFence ( VexSubArch subarch ) void ppPPC32Instr ( PPC32Instr* i ) { switch (i->tag) { - case Pin_Alu32: - if (i->Pin.Alu32.op == Palu_OR && // or Rd,Rs,Rs == mr Rd,Rs - i->Pin.Alu32.src2->tag == Pri_Reg && - i->Pin.Alu32.src2->Pri.Reg.reg == i->Pin.Alu32.src1) { - vex_printf("mr "); - ppHRegPPC32(i->Pin.Alu32.dst); - vex_printf(","); - ppHRegPPC32(i->Pin.Alu32.src1); - return; - } - if (i->Pin.Alu32.op == Palu_ADD && // add Rd,R0,Rs == li Rd,Rs - i->Pin.Alu32.src1 == hregPPC32_GPR0() && - i->Pin.Alu32.src2->tag == Pri_Imm) { - vex_printf("li "); - ppHRegPPC32(i->Pin.Alu32.dst); - vex_printf(","); - ppPPC32RI(i->Pin.Alu32.src2); - return; - } - vex_printf("%s%s ", showPPC32AluOp(i->Pin.Alu32.op), - i->Pin.Alu32.src2->tag == Pri_Imm ? "i" : "" ); - ppHRegPPC32(i->Pin.Alu32.dst); - vex_printf(","); - ppHRegPPC32(i->Pin.Alu32.src1); - vex_printf(","); - ppPPC32RI(i->Pin.Alu32.src2); - return; - case Pin_Sh32: - vex_printf("%s%s ", showPPC32ShiftOp(i->Pin.Sh32.op), - i->Pin.Sh32.shft->tag == Pri_Imm ? "i" : "" ); - ppHRegPPC32(i->Pin.Sh32.dst); + case Pin_Alu32: + if (i->Pin.Alu32.op == Palu_OR && // or Rd,Rs,Rs == mr Rd,Rs + i->Pin.Alu32.src2->tag == Pri_Reg && + i->Pin.Alu32.src2->Pri.Reg.reg == i->Pin.Alu32.src1) { + vex_printf("mr "); + ppHRegPPC32(i->Pin.Alu32.dst); vex_printf(","); - ppHRegPPC32(i->Pin.Sh32.src); + ppHRegPPC32(i->Pin.Alu32.src1); + return; + } + if (i->Pin.Alu32.op == Palu_ADD && // add Rd,R0,Rs == li Rd,Rs + i->Pin.Alu32.src1 == hregPPC32_GPR0() && + i->Pin.Alu32.src2->tag == Pri_Imm) { + vex_printf("li "); + ppHRegPPC32(i->Pin.Alu32.dst); vex_printf(","); - ppPPC32RI(i->Pin.Sh32.shft); + ppPPC32RI(i->Pin.Alu32.src2); return; + } + vex_printf("%s%s ", showPPC32AluOp(i->Pin.Alu32.op), + i->Pin.Alu32.src2->tag == Pri_Imm ? "i" : "" ); + ppHRegPPC32(i->Pin.Alu32.dst); + vex_printf(","); + ppHRegPPC32(i->Pin.Alu32.src1); + vex_printf(","); + ppPPC32RI(i->Pin.Alu32.src2); + return; + case Pin_Sh32: + vex_printf("%s%s ", showPPC32ShiftOp(i->Pin.Sh32.op), + i->Pin.Sh32.shft->tag == Pri_Imm ? "i" : "" ); + ppHRegPPC32(i->Pin.Sh32.dst); + vex_printf(","); + ppHRegPPC32(i->Pin.Sh32.src); + vex_printf(","); + ppPPC32RI(i->Pin.Sh32.shft); + return; // case Pin_Test32: // vex_printf("test "); // ppHRegPPC32(i->Pin.Test32.dst); // vex_printf(","); // ppPPC32RI(i->Pin.Test32.src); // return; - case Pin_Cmp32: - vex_printf("cmp%s %%crf%d,", - i->Pin.Cmp32.src2->tag == Pri_Imm ? "i" : "", - i->Pin.Cmp32.crfD); - ppHRegPPC32(i->Pin.Alu32.src1); - vex_printf(","); - ppPPC32RI(i->Pin.Alu32.src2); - return; - case Pin_Unary32: - vex_printf("%s ", showPPC32UnaryOp(i->Pin.Unary32.op)); - ppHRegPPC32(i->Pin.Unary32.dst); - vex_printf(","); - ppHRegPPC32(i->Pin.Unary32.src); - return; - case Pin_MulL: - if (i->Pin.MulL.src2->tag == Pri_Imm) { - vex_printf("mulli "); - } else { - vex_printf("mul%s%c ", - i->Pin.MulL.word ? "hw" : "lw", - i->Pin.MulL.syned ? 's' : 'u'); - } - ppHRegPPC32(i->Pin.MulL.dst); - vex_printf(","); - ppHRegPPC32(i->Pin.MulL.src1); - vex_printf(","); - ppPPC32RI(i->Pin.MulL.src2); - return; - case Pin_Div: - vex_printf("divw%s ", - i->Pin.Div.syned ? "" : "u"); - ppHRegPPC32(i->Pin.MulL.dst); - vex_printf(","); - ppHRegPPC32(i->Pin.MulL.src1); - vex_printf(","); - ppPPC32RI(i->Pin.MulL.src2); - return; + case Pin_Cmp32: + vex_printf("cmp%s %%crf%d,", + i->Pin.Cmp32.src2->tag == Pri_Imm ? "i" : "", + i->Pin.Cmp32.crfD); + ppHRegPPC32(i->Pin.Alu32.src1); + vex_printf(","); + ppPPC32RI(i->Pin.Alu32.src2); + return; + case Pin_Unary32: + vex_printf("%s ", showPPC32UnaryOp(i->Pin.Unary32.op)); + ppHRegPPC32(i->Pin.Unary32.dst); + vex_printf(","); + ppHRegPPC32(i->Pin.Unary32.src); + return; + case Pin_MulL: + if (i->Pin.MulL.src2->tag == Pri_Imm) { + vex_printf("mulli "); + } else { + vex_printf("mul%s%c ", + i->Pin.MulL.word ? "hw" : "lw", + i->Pin.MulL.syned ? 's' : 'u'); + } + ppHRegPPC32(i->Pin.MulL.dst); + vex_printf(","); + ppHRegPPC32(i->Pin.MulL.src1); + vex_printf(","); + ppPPC32RI(i->Pin.MulL.src2); + return; + case Pin_Div: + vex_printf("divw%s ", + i->Pin.Div.syned ? "" : "u"); + ppHRegPPC32(i->Pin.MulL.dst); + vex_printf(","); + ppHRegPPC32(i->Pin.MulL.src1); + vex_printf(","); + ppPPC32RI(i->Pin.MulL.src2); + return; //.. case Xin_Sh3232: //.. vex_printf("%sdl ", showX86ShiftOp(i->Xin.Sh3232.op)); //.. if (i->Xin.Sh3232.amt == 0) @@ -761,89 +760,89 @@ void ppPPC32Instr ( PPC32Instr* i ) //.. vex_printf("pushl "); //.. ppX86RMI(i->Xin.Push.src); //.. return; - case Pin_Call: + case Pin_Call: // CAB: Add representation of BO to Pin_Call... // 001xx => branch if false // 011xx => branch if true // 1x100 => branch always - + // bcl false|true,cond,target - vex_printf("bcl (%s)[%d] ", - showPPC32CondCode(i->Pin.Call.cond), - i->Pin.Call.regparms); - vex_printf("0x%x", i->Pin.Call.target); - break; - case Pin_Goto: + vex_printf("bcl (%s)[%d] ", + showPPC32CondCode(i->Pin.Call.cond), + i->Pin.Call.regparms); + vex_printf("0x%x", i->Pin.Call.target); + break; + case Pin_Goto: // bc false|true,cond,target - if (i->Pin.Goto.cond.test != Pct_ALWAYS) { - vex_printf("if (%%CR.%s) { ", - showPPC32CondCode(i->Pin.Goto.cond)); - } - if (i->Pin.Goto.jk != Ijk_Boring) { - vex_printf("la %%r31, $"); - ppIRJumpKind(i->Pin.Goto.jk); - vex_printf(" ; "); - } - vex_printf("bc "); - vex_printf("%%r4, "); - ppPPC32RI(i->Pin.Goto.dst); - vex_printf(" ; ret"); - if (i->Pin.Goto.cond.test != Pct_ALWAYS) { - vex_printf(" }"); - } - return; - case Pin_CMov32: + if (i->Pin.Goto.cond.test != Pct_ALWAYS) { + vex_printf("if (%%CR.%s) { ", + showPPC32CondCode(i->Pin.Goto.cond)); + } + if (i->Pin.Goto.jk != Ijk_Boring) { + vex_printf("la %%r31, $"); + ppIRJumpKind(i->Pin.Goto.jk); + vex_printf(" ; "); + } + vex_printf("bc "); + vex_printf("%%r4, "); + ppPPC32RI(i->Pin.Goto.dst); + vex_printf(" ; ret"); + if (i->Pin.Goto.cond.test != Pct_ALWAYS) { + vex_printf(" }"); + } + return; + case Pin_CMov32: // bc false,cond,8 // li ... - vex_printf("cmov32 (%s) ", showPPC32CondCode(i->Pin.CMov32.cond)); - ppHRegPPC32(i->Pin.CMov32.dst); - vex_printf(","); - ppPPC32RI(i->Pin.CMov32.src); - return; - case Pin_LoadEX: { - UChar sz = i->Pin.LoadEX.sz; - Bool syned = i->Pin.LoadEX.syned; + vex_printf("cmov32 (%s) ", showPPC32CondCode(i->Pin.CMov32.cond)); + ppHRegPPC32(i->Pin.CMov32.dst); + vex_printf(","); + ppPPC32RI(i->Pin.CMov32.src); + return; + case Pin_LoadEX: { + UChar sz = i->Pin.LoadEX.sz; + Bool syned = i->Pin.LoadEX.syned; // CAB: How to get 'update'... ? - Bool update = False; - Bool idxd = (i->Pin.LoadEX.src->tag == Pam_IR) ? True : False; - vex_printf("l%c%c%s%s ", - (sz==1) ? 'b' : (sz==2 ? 'h' : 'w'), - syned ? 'a' : 'z', - update ? "u" : "", - idxd ? "x" : "" ); - ppHRegPPC32(i->Pin.LoadEX.dst); - vex_printf(","); - ppPPC32AMode(i->Pin.LoadEX.src); - return; - } - case Pin_Store: { - UChar sz = i->Pin.Store.sz; + Bool update = False; + Bool idxd = (i->Pin.LoadEX.src->tag == Pam_IR) ? True : False; + vex_printf("l%c%c%s%s ", + (sz==1) ? 'b' : (sz==2 ? 'h' : 'w'), + syned ? 'a' : 'z', + update ? "u" : "", + idxd ? "x" : "" ); + ppHRegPPC32(i->Pin.LoadEX.dst); + vex_printf(","); + ppPPC32AMode(i->Pin.LoadEX.src); + return; + } + case Pin_Store: { + UChar sz = i->Pin.Store.sz; // CAB: How to get 'update'... ? - Bool update = False; - Bool idxd = (i->Pin.Store.dst->tag == Pam_IR) ? True : False; - vex_printf("st%c%s%s ", - (sz==1) ? 'b' : (sz==2 ? 'h' : 'w'), - update ? "u" : "", - idxd ? "x" : "" ); - ppHRegPPC32(i->Pin.Store.src); - vex_printf(","); - ppPPC32AMode(i->Pin.Store.dst); - return; - } - case Pin_Set32: - vex_printf("set32 (%s) ", showPPC32CondCode(i->Pin.Set32.cond)); - ppHRegPPC32(i->Pin.Set32.dst); - return; + Bool update = False; + Bool idxd = (i->Pin.Store.dst->tag == Pam_IR) ? True : False; + vex_printf("st%c%s%s ", + (sz==1) ? 'b' : (sz==2 ? 'h' : 'w'), + update ? "u" : "", + idxd ? "x" : "" ); + ppHRegPPC32(i->Pin.Store.src); + vex_printf(","); + ppPPC32AMode(i->Pin.Store.dst); + return; + } + case Pin_Set32: + vex_printf("set32 (%s) ", showPPC32CondCode(i->Pin.Set32.cond)); + ppHRegPPC32(i->Pin.Set32.dst); + 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(%s)", - LibVEX_ppVexSubArch(i->Pin.MFence.subarch)); - return; + case Pin_MFence: + vex_printf("mfence(%s)", + LibVEX_ppVexSubArch(i->Pin.MFence.subarch)); + return; //.. case Xin_FpUnary: //.. vex_printf("g%sD ", showX86FpOp(i->Xin.FpUnary.op)); //.. ppHRegX86(i->Xin.FpUnary.src); @@ -978,9 +977,9 @@ void ppPPC32Instr ( PPC32Instr* i ) //.. ppHRegX86(i->Xin.SseShuf.dst); //.. return; - default: - vex_printf("\nppPPC32Instr(ppc32): No such tag(%d)\n", i->tag); - vpanic("ppPPC32Instr(ppc32)"); + default: + vex_printf("\nppPPC32Instr(ppc32): No such tag(%d)\n", i->tag); + vpanic("ppPPC32Instr(ppc32)"); } } @@ -991,48 +990,48 @@ void getRegUsage_PPC32Instr ( HRegUsage* u, PPC32Instr* i ) // Bool unary; initHRegUsage(u); switch (i->tag) { - case Pin_Alu32: - addHRegUse(u, HRmRead, i->Pin.Alu32.src1); - addRegUsage_PPC32RI(u, i->Pin.Alu32.src2); + case Pin_Alu32: + addHRegUse(u, HRmRead, i->Pin.Alu32.src1); + addRegUsage_PPC32RI(u, i->Pin.Alu32.src2); // if (i->Pin.Alu32.op == Palu_CMP) { // addHRegUse(u, HRmRead, i->Pin.Alu32.dst); // return; // } - addHRegUse(u, HRmWrite, i->Pin.Alu32.dst); + addHRegUse(u, HRmWrite, i->Pin.Alu32.dst); // CAB TODO: Any circumstance where dst is read & written? - return; + return; - case Pin_Sh32: - addHRegUse(u, HRmWrite, i->Pin.Sh32.dst); - addHRegUse(u, HRmRead, i->Pin.Sh32.src); - addRegUsage_PPC32RI(u, i->Pin.Sh32.shft); + case Pin_Sh32: + addHRegUse(u, HRmWrite, i->Pin.Sh32.dst); + addHRegUse(u, HRmRead, i->Pin.Sh32.src); + addRegUsage_PPC32RI(u, i->Pin.Sh32.shft); // CAB TODO: Any circumstance where dst is read & written? - return; - -// case Pin_Test32: -// addHRegUse(u, HRmRead, i->Pin.Test32.dst); -// addRegUsage_PPC32RI(u, i->Pin.Test32.src); -// return; - - case Pin_Cmp32: - addHRegUse(u, HRmRead, i->Pin.Cmp32.src1); - addRegUsage_PPC32RI(u, i->Pin.Cmp32.src2); - return; + return; + +// case Pin_Test32: +// addHRegUse(u, HRmRead, i->Pin.Test32.dst); +// addRegUsage_PPC32RI(u, i->Pin.Test32.src); +// return; + + case Pin_Cmp32: + addHRegUse(u, HRmRead, i->Pin.Cmp32.src1); + addRegUsage_PPC32RI(u, i->Pin.Cmp32.src2); + return; - case Pin_Unary32: - addHRegUse(u, HRmWrite, i->Pin.Unary32.dst); - addHRegUse(u, HRmRead, i->Pin.Unary32.src); - return; - case Pin_MulL: - addHRegUse(u, HRmWrite, i->Pin.MulL.dst); - addHRegUse(u, HRmRead, i->Pin.MulL.src1); - addRegUsage_PPC32RI(u, i->Pin.MulL.src2); - return; - case Pin_Div: - addHRegUse(u, HRmWrite, i->Pin.Div.dst); - addHRegUse(u, HRmRead, i->Pin.Div.src1); - addRegUsage_PPC32RI(u, i->Pin.Div.src2); - return; + case Pin_Unary32: + addHRegUse(u, HRmWrite, i->Pin.Unary32.dst); + addHRegUse(u, HRmRead, i->Pin.Unary32.src); + return; + case Pin_MulL: + addHRegUse(u, HRmWrite, i->Pin.MulL.dst); + addHRegUse(u, HRmRead, i->Pin.MulL.src1); + addRegUsage_PPC32RI(u, i->Pin.MulL.src2); + return; + case Pin_Div: + addHRegUse(u, HRmWrite, i->Pin.Div.dst); + addHRegUse(u, HRmRead, i->Pin.Div.src1); + addRegUsage_PPC32RI(u, i->Pin.Div.src2); + return; //.. case Xin_Sh3232: //.. addHRegUse(u, HRmRead, i->Xin.Sh3232.src); //.. addHRegUse(u, HRmModify, i->Xin.Sh3232.dst); @@ -1043,72 +1042,72 @@ void getRegUsage_PPC32Instr ( HRegUsage* u, PPC32Instr* i ) //.. 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 - which fall within the register allocator's jurisdiction. - These I believe to be: r0,r3:12 - */ - addHRegUse(u, HRmWrite, hregPPC32_GPR0()); - addHRegUse(u, HRmWrite, hregPPC32_GPR3()); - addHRegUse(u, HRmWrite, hregPPC32_GPR4()); - addHRegUse(u, HRmWrite, hregPPC32_GPR5()); - addHRegUse(u, HRmWrite, hregPPC32_GPR6()); - addHRegUse(u, HRmWrite, hregPPC32_GPR7()); - addHRegUse(u, HRmWrite, hregPPC32_GPR8()); - addHRegUse(u, HRmWrite, hregPPC32_GPR9()); - addHRegUse(u, HRmWrite, hregPPC32_GPR10()); - addHRegUse(u, HRmWrite, hregPPC32_GPR11()); - addHRegUse(u, HRmWrite, hregPPC32_GPR12()); - - /* Now we have to state any parameter-carrying registers - which might be read. This depends on the regparmness. */ - switch (i->Pin.Call.regparms) { - case 8: addHRegUse(u, HRmRead, hregPPC32_GPR10()); /*fallthru*/ - case 7: addHRegUse(u, HRmRead, hregPPC32_GPR9() ); /*fallthru*/ - case 6: addHRegUse(u, HRmRead, hregPPC32_GPR8() ); /*fallthru*/ - case 5: addHRegUse(u, HRmRead, hregPPC32_GPR7() ); /*fallthru*/ - case 4: addHRegUse(u, HRmRead, hregPPC32_GPR6() ); /*fallthru*/ - case 3: addHRegUse(u, HRmRead, hregPPC32_GPR5() ); /*fallthru*/ - case 2: addHRegUse(u, HRmRead, hregPPC32_GPR4() ); /*fallthru*/ - case 1: addHRegUse(u, HRmRead, hregPPC32_GPR3() ); /*fallthru*/ - case 0: break; - default: vpanic("getRegUsage_PPC32Instr:Call:regparms"); - } - /* Finally, there is the issue that the insn trashes a - register because the literal target address has to be - loaded into a register. %r12 seems a suitable victim. */ - addHRegUse(u, HRmWrite, hregPPC32_GPR12()); - /* Upshot of this is that the assembler really must use %r12, + case Pin_Call: + /* This is a bit subtle. */ + /* First off, claim it trashes all the caller-saved regs + which fall within the register allocator's jurisdiction. + These I believe to be: r0,r3:12 + */ + addHRegUse(u, HRmWrite, hregPPC32_GPR0()); + addHRegUse(u, HRmWrite, hregPPC32_GPR3()); + addHRegUse(u, HRmWrite, hregPPC32_GPR4()); + addHRegUse(u, HRmWrite, hregPPC32_GPR5()); + addHRegUse(u, HRmWrite, hregPPC32_GPR6()); + addHRegUse(u, HRmWrite, hregPPC32_GPR7()); + addHRegUse(u, HRmWrite, hregPPC32_GPR8()); + addHRegUse(u, HRmWrite, hregPPC32_GPR9()); + addHRegUse(u, HRmWrite, hregPPC32_GPR10()); + addHRegUse(u, HRmWrite, hregPPC32_GPR11()); + addHRegUse(u, HRmWrite, hregPPC32_GPR12()); + + /* Now we have to state any parameter-carrying registers + which might be read. This depends on the regparmness. */ + switch (i->Pin.Call.regparms) { + case 8: addHRegUse(u, HRmRead, hregPPC32_GPR10()); /*fallthru*/ + case 7: addHRegUse(u, HRmRead, hregPPC32_GPR9() ); /*fallthru*/ + case 6: addHRegUse(u, HRmRead, hregPPC32_GPR8() ); /*fallthru*/ + case 5: addHRegUse(u, HRmRead, hregPPC32_GPR7() ); /*fallthru*/ + case 4: addHRegUse(u, HRmRead, hregPPC32_GPR6() ); /*fallthru*/ + case 3: addHRegUse(u, HRmRead, hregPPC32_GPR5() ); /*fallthru*/ + case 2: addHRegUse(u, HRmRead, hregPPC32_GPR4() ); /*fallthru*/ + case 1: addHRegUse(u, HRmRead, hregPPC32_GPR3() ); /*fallthru*/ + case 0: break; + default: vpanic("getRegUsage_PPC32Instr:Call:regparms"); + } + /* Finally, there is the issue that the insn trashes a + register because the literal target address has to be + loaded into a register. %r12 seems a suitable victim. */ + addHRegUse(u, HRmWrite, hregPPC32_GPR12()); + /* Upshot of this is that the assembler really must use %r12, and no other, as a destination temporary. */ - return; - case Pin_Goto: - addRegUsage_PPC32RI(u, i->Pin.Goto.dst); - addHRegUse(u, HRmWrite, hregPPC32_GPR4()); - if (i->Pin.Goto.jk != Ijk_Boring) - addHRegUse(u, HRmWrite, GuestStatePtr); - return; - case Pin_CMov32: - addRegUsage_PPC32RI(u, i->Pin.CMov32.src); - addHRegUse(u, HRmModify, i->Pin.CMov32.dst); - return; - case Pin_LoadEX: - addRegUsage_PPC32AMode(u, i->Pin.LoadEX.src); - addHRegUse(u, HRmWrite, i->Pin.LoadEX.dst); - return; - case Pin_Store: - addHRegUse(u, HRmRead, i->Pin.Store.src); - addRegUsage_PPC32AMode(u, i->Pin.Store.dst); - return; - case Pin_Set32: - addHRegUse(u, HRmWrite, i->Pin.Set32.dst); - return; + return; + case Pin_Goto: + addRegUsage_PPC32RI(u, i->Pin.Goto.dst); + addHRegUse(u, HRmWrite, hregPPC32_GPR4()); + if (i->Pin.Goto.jk != Ijk_Boring) + addHRegUse(u, HRmWrite, GuestStatePtr); + return; + case Pin_CMov32: + addRegUsage_PPC32RI(u, i->Pin.CMov32.src); + addHRegUse(u, HRmModify, i->Pin.CMov32.dst); + return; + case Pin_LoadEX: + addRegUsage_PPC32AMode(u, i->Pin.LoadEX.src); + addHRegUse(u, HRmWrite, i->Pin.LoadEX.dst); + return; + case Pin_Store: + addHRegUse(u, HRmRead, i->Pin.Store.src); + addRegUsage_PPC32AMode(u, i->Pin.Store.dst); + return; + 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 Pin_MFence: + return; //.. case Xin_FpUnary: //.. addHRegUse(u, HRmRead, i->Xin.FpUnary.src); //.. addHRegUse(u, HRmWrite, i->Xin.FpUnary.dst); @@ -1217,9 +1216,9 @@ void getRegUsage_PPC32Instr ( HRegUsage* u, PPC32Instr* i ) //.. addHRegUse(u, HRmRead, i->Xin.SseShuf.src); //.. addHRegUse(u, HRmWrite, i->Xin.SseShuf.dst); //.. return; - default: - ppPPC32Instr(i); - vpanic("getRegUsage_PPC32Instr"); + default: + ppPPC32Instr(i); + vpanic("getRegUsage_PPC32Instr"); } } @@ -1232,38 +1231,38 @@ static void mapReg(HRegRemap* m, HReg* r) void mapRegs_PPC32Instr (HRegRemap* m, PPC32Instr* i) { switch (i->tag) { - case Pin_Alu32: - mapReg(m, &i->Pin.Alu32.dst); - mapReg(m, &i->Pin.Alu32.src1); - mapRegs_PPC32RI(m, i->Pin.Alu32.src2); - return; - case Pin_Sh32: - mapReg(m, &i->Pin.Sh32.dst); - mapReg(m, &i->Pin.Sh32.src); - mapRegs_PPC32RI(m, i->Pin.Sh32.shft); - return; + case Pin_Alu32: + mapReg(m, &i->Pin.Alu32.dst); + mapReg(m, &i->Pin.Alu32.src1); + mapRegs_PPC32RI(m, i->Pin.Alu32.src2); + return; + case Pin_Sh32: + mapReg(m, &i->Pin.Sh32.dst); + mapReg(m, &i->Pin.Sh32.src); + mapRegs_PPC32RI(m, i->Pin.Sh32.shft); + return; // case Pin_Test32: // mapReg(m, &i->Pin.Test32.dst); // mapRegs_PPC32RI(m, i->Pin.Test32.src); // return; - case Pin_Cmp32: - mapReg(m, &i->Pin.Cmp32.src1); - mapRegs_PPC32RI(m, i->Pin.Cmp32.src2); - return; - case Pin_Unary32: - mapReg(m, &i->Pin.Unary32.dst); - mapReg(m, &i->Pin.Unary32.src); - return; - case Pin_MulL: - mapReg(m, &i->Pin.MulL.dst); - mapReg(m, &i->Pin.MulL.src1); - mapRegs_PPC32RI(m, i->Pin.MulL.src2); - return; - case Pin_Div: - mapReg(m, &i->Pin.Div.dst); - mapReg(m, &i->Pin.Div.src1); - mapRegs_PPC32RI(m, i->Pin.Div.src2); - return; + case Pin_Cmp32: + mapReg(m, &i->Pin.Cmp32.src1); + mapRegs_PPC32RI(m, i->Pin.Cmp32.src2); + return; + case Pin_Unary32: + mapReg(m, &i->Pin.Unary32.dst); + mapReg(m, &i->Pin.Unary32.src); + return; + case Pin_MulL: + mapReg(m, &i->Pin.MulL.dst); + mapReg(m, &i->Pin.MulL.src1); + mapRegs_PPC32RI(m, i->Pin.MulL.src2); + return; + case Pin_Div: + mapReg(m, &i->Pin.Div.dst); + mapReg(m, &i->Pin.Div.src1); + mapRegs_PPC32RI(m, i->Pin.Div.src2); + return; //.. case Xin_Sh3232: //.. mapReg(m, &i->Xin.Sh3232.src); //.. mapReg(m, &i->Xin.Sh3232.dst); @@ -1271,32 +1270,32 @@ void mapRegs_PPC32Instr (HRegRemap* m, PPC32Instr* i) //.. case Xin_Push: //.. mapRegs_X86RMI(m, i->Xin.Push.src); //.. return; - case Pin_Call: - return; - case Pin_Goto: - mapRegs_PPC32RI(m, i->Pin.Goto.dst); - return; - case Pin_CMov32: - mapRegs_PPC32RI(m, i->Pin.CMov32.src); - mapReg(m, &i->Pin.CMov32.dst); - return; - case Pin_LoadEX: - mapRegs_PPC32AMode(m, i->Pin.LoadEX.src); - mapReg(m, &i->Pin.LoadEX.dst); - return; - case Pin_Store: - mapReg(m, &i->Pin.Store.src); - mapRegs_PPC32AMode(m, i->Pin.Store.dst); - return; - case Pin_Set32: - mapReg(m, &i->Pin.Set32.dst); - return; + case Pin_Call: + return; + case Pin_Goto: + mapRegs_PPC32RI(m, i->Pin.Goto.dst); + return; + case Pin_CMov32: + mapRegs_PPC32RI(m, i->Pin.CMov32.src); + mapReg(m, &i->Pin.CMov32.dst); + return; + case Pin_LoadEX: + mapRegs_PPC32AMode(m, i->Pin.LoadEX.src); + mapReg(m, &i->Pin.LoadEX.dst); + return; + case Pin_Store: + mapReg(m, &i->Pin.Store.src); + mapRegs_PPC32AMode(m, i->Pin.Store.dst); + return; + 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 Pin_MFence: + return; //.. case Xin_FpUnary: //.. mapReg(m, &i->Xin.FpUnary.src); //.. mapReg(m, &i->Xin.FpUnary.dst); @@ -1371,9 +1370,9 @@ void mapRegs_PPC32Instr (HRegRemap* m, PPC32Instr* i) //.. mapReg(m, &i->Xin.SseShuf.src); //.. mapReg(m, &i->Xin.SseShuf.dst); //.. return; - default: - ppPPC32Instr(i); - vpanic("mapRegs_PPC32Instr"); + default: + ppPPC32Instr(i); + vpanic("mapRegs_PPC32Instr"); } } @@ -1391,7 +1390,7 @@ Bool isMove_PPC32Instr ( PPC32Instr* i, HReg* src, HReg* dst ) if (i->Pin.Alu32.src2->tag != Pri_Reg) return False; if (i->Pin.Alu32.src2->Pri.Reg.reg != i->Pin.Alu32.src1) - return False; + return False; *src = i->Pin.Alu32.src1; *dst = i->Pin.Alu32.dst; return True; @@ -1425,17 +1424,17 @@ PPC32Instr* genSpill_PPC32 ( HReg rreg, Int offsetB ) vassert(offsetB >= 0); vassert(!hregIsVirtual(rreg)); am = PPC32AMode_IR(offsetB, GuestStatePtr); - + switch (hregClass(rreg)) { - case HRcInt32: - return PPC32Instr_Store( 4, am, rreg); - //case HRcFlt64: - // return PPC32Instr_FpLdSt ( False/*store*/, 8, rreg, am ); - //case HRcVec128: - // return PPC32Instr_SseLdSt ( False/*store*/, rreg, am ); - default: - ppHRegClass(hregClass(rreg)); - vpanic("genSpill_PPC32: unimplemented regclass"); + case HRcInt32: + return PPC32Instr_Store( 4, am, rreg); +// case HRcFlt64: +// return PPC32Instr_FpLdSt ( False/*store*/, 8, rreg, am ); +// case HRcVec128: +// return PPC32Instr_SseLdSt ( False/*store*/, rreg, am ); + default: + ppHRegClass(hregClass(rreg)); + vpanic("genSpill_PPC32: unimplemented regclass"); } } @@ -1447,15 +1446,15 @@ PPC32Instr* genReload_PPC32 ( HReg rreg, Int offsetB ) am = PPC32AMode_IR(offsetB, GuestStatePtr); switch (hregClass(rreg)) { - case HRcInt32: - return PPC32Instr_LoadEX( 4, False, rreg, am ); - //case HRcFlt64: - // return PPC32Instr_FpLdSt ( True/*load*/, 8, rreg, am ); - //case HRcVec128: - // return PPC32Instr_SseLdSt ( True/*load*/, rreg, am ); - default: - ppHRegClass(hregClass(rreg)); - vpanic("genReload_PPC32: unimplemented regclass"); + case HRcInt32: + return PPC32Instr_LoadEX( 4, False, rreg, am ); +// case HRcFlt64: +// return PPC32Instr_FpLdSt ( True/*load*/, 8, rreg, am ); +// case HRcVec128: +// return PPC32Instr_SseLdSt ( True/*load*/, rreg, am ); + default: + ppHRegClass(hregClass(rreg)); + vpanic("genReload_PPC32: unimplemented regclass"); } } @@ -1566,7 +1565,7 @@ static UChar* emit32 ( UChar* p, UInt w32 ) //.. } //.. if (am->Xam.IR.reg == hregX86_ESP() //.. && fits8bits(am->Xam.IR.imm)) { -//.. *p++ = mkModRegRM(1, iregNo(greg), 4); +//.. *p++ = mkModRegRM(1, iregNo(greg), 4); //.. *p++ = 0x24; //.. *p++ = am->Xam.IR.imm & 0xFF; //.. return p; @@ -1714,7 +1713,7 @@ static UChar* mkFormD ( UChar* p, UInt op1, UInt r1, UInt r2, UInt imm ) } static UChar* mkFormX ( UChar* p, UInt op1, UInt r1, UInt r2, - UInt r3, UInt op2, UInt b0 ) + UInt r3, UInt op2, UInt b0 ) { vassert(op1 < 0x40); vassert(r1 < 0x20); @@ -1723,12 +1722,12 @@ static UChar* mkFormX ( UChar* p, UInt op1, UInt r1, UInt r2, vassert(op2 < 0x400); vassert(b0 < 0x2); UInt theInstr = ((op1<<26) | (r1<<21) | (r2<<16) | - (r3<<11) | (op2<<1) | (b0)); + (r3<<11) | (op2<<1) | (b0)); return emit32(p, theInstr); } static UChar* mkFormXO ( UChar* p, UInt op1, UInt r1, UInt r2, - UInt r3, UInt b10, UInt op2, UInt b0 ) + UInt r3, UInt b10, UInt op2, UInt b0 ) { vassert(op1 < 0x40); vassert(r1 < 0x20); @@ -1738,7 +1737,7 @@ static UChar* mkFormXO ( UChar* p, UInt op1, UInt r1, UInt r2, vassert(op2 < 0x400); vassert(b0 < 0x2); UInt theInstr = ((op1<<26) | (r1<<21) | (r2<<16) | - (r3<<11) | (b10 << 10) | (op2<<1) | (b0)); + (r3<<11) | (b10 << 10) | (op2<<1) | (b0)); return emit32(p, theInstr); } @@ -1756,9 +1755,9 @@ static UChar* doAMode_IR ( UChar* p, UInt op1, HReg hrSD, PPC32AMode* am ) static UChar* doAMode_RR ( UChar* p, UInt op1, UInt op2, - HReg hrSD, PPC32AMode* am ) + HReg hrSD, PPC32AMode* am ) { -// vassert(hregClass(hrSD) == HRcInt32); // CAB: worth doing this? +// vassert(hregClass(hrSD) == HRcInt32); // CAB: etc. worth doing this? vassert(am->tag == Pam_RR); UInt rSD = iregNo(hrSD); UInt rA = iregNo(am->Pam.RR.base); @@ -1840,13 +1839,10 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i ) } switch (i->Pin.Alu32.op) { - case Palu_ADD: - case Palu_SUB: + case Palu_ADD: case Palu_SUB: p = mkFormXO(p, op1, r_dst, r_src1, rB, 0, op2, 0); // rD = rA... break; - case Palu_AND: - case Palu_XOR: - case Palu_OR: + case Palu_AND: case Palu_XOR: case Palu_OR: p = mkFormX(p, op1, r_src1, r_dst, rB, op2, 0); // rA = rS... break; // case Palu_ADC: @@ -1854,9 +1850,7 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i ) default: goto bad; } - goto done; - } - else { // Pri_Imm: + } else { // Pri_Imm: imm = i->Pin.Alu32.src2->Pri.Imm.imm32; switch (i->Pin.Alu32.op) { case Palu_ADD: op1 = 14; break; @@ -1871,13 +1865,10 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i ) } switch (i->Pin.Alu32.op) { - case Palu_ADD: - case Palu_SUB: + case Palu_ADD: case Palu_SUB: p = mkFormD(p, op1, r_dst, r_src1, imm); // rD = rA... break; - case Palu_AND: - case Palu_XOR: - case Palu_OR: + case Palu_AND: case Palu_XOR: case Palu_OR: p = mkFormD(p, op1, r_src1, r_dst, imm); // rA = rS... break; // case Palu_ADC: @@ -1885,53 +1876,40 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i ) default: goto bad; } - goto done; } - break; + goto done; } case Pin_Sh32: { UInt op1 = 31, op2, rB, imm; + UInt op = i->Pin.Sh32.op; UInt rD = iregNo(i->Pin.Alu32.dst); UInt rA = iregNo(i->Pin.Alu32.src1); + PPC32RITag ri_tag = i->Pin.Alu32.src2->tag; - switch (i->Pin.Sh32.op) { - case Psh_SHL: { - if (i->Pin.Alu32.src2->tag != Pri_Reg) goto bad; - op2 = 536; - break; - } - case Psh_SHR: { - if (i->Pin.Alu32.src2->tag != Pri_Reg) goto bad; - op2 = 536; - break; - } - case Psh_SAR: { - if (i->Pin.Alu32.src2->tag == Pri_Reg) { - op2 = 792; - } else { // Pri_Imm - op2 = 824; - } - break; - } + if ((op == Psh_SHL || op == Psh_SHR) && ri_tag == Pri_Imm) + goto bad; // No imm versions of these + + switch (op) { + case Psh_SHL: op2 = 24; break; + case Psh_SHR: op2 = 536; break; + case Psh_SAR: op2 = (ri_tag == Pri_Reg) ? 792 : 824; break; default: goto bad; } - // CAB: Optimise for shft_val == 0... - switch (i->Pin.Sh32.shft->tag) { case Pri_Reg: rB = iregNo(i->Pin.Alu32.src2->Pri.Reg.reg); p = mkFormX(p, op1, rD, rA, rB, op2, 0); - goto done; + break; case Pri_Imm: imm = i->Pin.Alu32.src2->Pri.Imm.imm32; p = mkFormX(p, op1, rD, rA, imm, op2, 0); - goto done; + break; default: goto bad; } - break; + goto done; } //.. case Xin_Test32: @@ -2070,7 +2048,7 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i ) //.. ptmp = NULL; //.. //.. /* First off, if this is conditional, create a conditional -//.. jump over the rest of it. */ +//.. jump over the rest of it. */ //.. if (i->Xin.Goto.cond != Xcc_ALWAYS) { //.. /* jmp fwds if !condition */ //.. *p++ = 0x70 + (i->Xin.Goto.cond ^ 1); @@ -2101,7 +2079,7 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i ) //.. *p++ = 0xBD; //.. p = emit32(p, VEX_TRC_JMP_NODECODE); break; //.. case Ijk_Ret: -//.. case Ijk_Call: +//.. case Ijk_Call: //.. case Ijk_Boring: //.. break; //.. default: @@ -2129,7 +2107,7 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i ) //.. /* Fix up the conditional jump, if there was one. */ //.. if (i->Xin.Goto.cond != Xcc_ALWAYS) { //.. Int delta = p - ptmp; -//.. vassert(delta > 0 && delta < 20); +//.. vassert(delta > 0 && delta < 20); //.. *ptmp = (UChar)(delta-1); //.. } //.. goto done; @@ -2189,7 +2167,7 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i ) op1 = (i->Pin.LoadEX.syned) ? 42: 40; } else { vassert(i->Pin.LoadEX.syned == False); - op1 = (sz == 1) ? 34 : 32; + op1 = (sz == 1) ? 34 : 32; // 1:4 } p = doAMode_IR(p, op1, i->Pin.LoadEX.dst, i->Pin.LoadEX.src); goto done; @@ -2199,7 +2177,7 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i ) op2 = (i->Pin.LoadEX.syned) ? 343: 279; } else { vassert(i->Pin.LoadEX.syned == False); - op2 = (sz == 1) ? 87 : 23; + op2 = (sz == 1) ? 87 : 23; // 1:4 } p = doAMode_RR(p, op1, op2, i->Pin.LoadEX.dst, i->Pin.LoadEX.src); goto done; @@ -2270,12 +2248,12 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i ) UInt op1, op2, sz = i->Pin.Store.sz; switch (i->Pin.Store.dst->tag) { case Pam_IR: - op1 = (sz == 1) ? 38 : ((sz == 2) ? 44 : 36); + op1 = (sz == 1) ? 38 : ((sz == 2) ? 44 : 36); // 1:2:4 p = doAMode_IR(p, op1, i->Pin.Store.src, i->Pin.Store.dst); goto done; case Pam_RR: op1 = 31; - op2 = (sz == 1) ? 215 : ((sz == 2) ? 407 : 151); + op2 = (sz == 1) ? 215 : ((sz == 2) ? 407 : 151); // 1:2:4 p = doAMode_RR(p, op1, op2, i->Pin.Store.src, i->Pin.Store.dst); goto done; default: @@ -2363,13 +2341,13 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i ) //.. */ //.. p = do_ffree_st7(p); //.. *p++ = i->Xin.FpLdSt.sz==4 ? 0xD9 : 0xDD; -//.. p = doAMode_M(p, fake(0)/*subopcode*/, i->Xin.FpLdSt.addr); +//.. p = doAMode_M(p, fake(0)/*subopcode*/, i->Xin.FpLdSt.addr); //.. p = do_fstp_st(p, 1+hregNumber(i->Xin.FpLdSt.reg)); //.. goto done; //.. } else { //.. /* Store from %fakeN into memory. //.. --> ffree %st(7) ; fld st(N) ; fstp{l|s} amode -//.. */ +//.. */ //.. p = do_ffree_st7(p); //.. p = do_fld_st(p, 0+hregNumber(i->Xin.FpLdSt.reg)); //.. *p++ = i->Xin.FpLdSt.sz==4 ? 0xD9 : 0xDD; @@ -2397,7 +2375,7 @@ Int emit_PPC32Instr ( UChar* buf, Int nbuf, PPC32Instr* i ) //.. } else { //.. /* Store from %fakeN into memory, converting to an int. //.. --> ffree %st(7) ; fld st(N) ; fistp{w/l/ll} amode -//.. */ +//.. */ //.. switch (i->Xin.FpLdStI.sz) { //.. case 8: opc = 0xDF; subopc_imm = 7; break; //.. case 4: opc = 0xDB; subopc_imm = 3; break; diff --git a/VEX/priv/host-ppc32/hdefs.h b/VEX/priv/host-ppc32/hdefs.h index 99dfd02d26..7507060170 100644 --- a/VEX/priv/host-ppc32/hdefs.h +++ b/VEX/priv/host-ppc32/hdefs.h @@ -289,7 +289,7 @@ typedef enum { Palu_INVALID, Palu_ADD, Palu_SUB, - // Palu_ADC, Palu_SBB, +// Palu_ADC, Palu_SBB, Palu_AND, Palu_OR, Palu_XOR, Palu_MUL } @@ -408,7 +408,7 @@ typedef /* DX:AX = AX *s/u r/m16, or EDX:EAX = EAX *s/u r/m32 */ struct { Bool syned; - Bool word; /* low=0, hi=1 */ + Bool word; /* low=0, hi=1 */ HReg dst; HReg src1; PPC32RI* src2; @@ -566,7 +566,7 @@ 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_LoadEX ( UChar sz, Bool syned, - HReg dst, PPC32AMode* src ); + 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 ); diff --git a/VEX/priv/host-ppc32/isel.c b/VEX/priv/host-ppc32/isel.c index 794bb2cd91..78c9113a7c 100644 --- a/VEX/priv/host-ppc32/isel.c +++ b/VEX/priv/host-ppc32/isel.c @@ -245,9 +245,9 @@ static PPC32AMode* iselIntExpr_AMode_wrk ( ISelEnv* env, IRExpr* e ); static PPC32AMode* iselIntExpr_AMode ( ISelEnv* env, IRExpr* e ); static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, - ISelEnv* env, IRExpr* e ); + ISelEnv* env, IRExpr* e ); static void iselInt64Expr ( HReg* rHi, HReg* rLo, - ISelEnv* env, IRExpr* e ); + ISelEnv* env, IRExpr* e ); static PPC32CondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e ); static PPC32CondCode iselCondCode ( ISelEnv* env, IRExpr* e ); @@ -414,10 +414,10 @@ static Bool mightRequireFixedRegs ( IRExpr* e ) { switch (e->tag) { - case Iex_Tmp: case Iex_Const: case Iex_Get: - return False; - default: - return True; + case Iex_Tmp: case Iex_Const: case Iex_Get: + return False; + default: + return True; } } @@ -493,9 +493,9 @@ void doHelperCall ( ISelEnv* env, if (PPC32_N_REGPARMS < n_args + (passBBP ? 1 : 0)) { vpanic("doHelperCall(PPC32): cannot currently handle > 8 args"); - // PPC32_N_REGPARMS + // PPC32_N_REGPARMS } - + argregs[0] = hregPPC32_GPR3(); argregs[1] = hregPPC32_GPR4(); argregs[2] = hregPPC32_GPR5(); @@ -551,7 +551,7 @@ void doHelperCall ( ISelEnv* env, vassert(argreg < PPC32_N_REGPARMS); vassert(typeOfIRExpr(env->type_env, args[i]) == Ity_I32); addInstr(env, mk_iMOVds_RR( argregs[argreg], - iselIntExpr_R(env, args[i]) )); + iselIntExpr_R(env, args[i]) )); argreg++; } @@ -776,9 +776,8 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) switch (e->tag) { /* --------- TEMP --------- */ - case Iex_Tmp: { + case Iex_Tmp: return lookupIRTemp(env, e->Iex.Tmp.tmp); - } /* --------- LOAD --------- */ case Iex_LDle: { @@ -984,17 +983,17 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) //.. /* Used several times ... */ //.. X86AMode* zero_esp = X86AMode_IR(0, hregX86_ESP()); -//.. /* rf now holds the value to be converted, and rrm holds the -//.. rounding mode value, encoded as per the IRRoundingMode -//.. enum. The first thing to do is set the FPU's rounding -//.. mode accordingly. */ +//.. /* rf now holds the value to be converted, and rrm holds the +//.. rounding mode value, encoded as per the IRRoundingMode +//.. enum. The first thing to do is set the FPU's rounding +//.. mode accordingly. */ //.. //.. /* Create a space for the format conversion. */ //.. /* subl $4, %esp */ //.. sub_from_esp(env, 4); -//.. /* Set host rounding mode */ -//.. set_FPU_rounding_mode( env, e->Iex.Binop.arg1 ); +//.. /* Set host rounding mode */ +//.. set_FPU_rounding_mode( env, e->Iex.Binop.arg1 ); //.. //.. /* gistw/l %rf, 0(%esp) */ //.. addInstr(env, X86Instr_FpLdStI(False/*store*/, sz, rf, zero_esp)); @@ -1009,11 +1008,11 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) //.. Xalu_MOV, X86RMI_Mem(zero_esp), dst)); //.. } -//.. /* Restore default FPU rounding. */ -//.. set_FPU_rounding_default( env ); +//.. /* Restore default FPU rounding. */ +//.. set_FPU_rounding_default( env ); //.. //.. /* addl $4, %esp */ -//.. add_to_esp(env, 4); +//.. add_to_esp(env, 4); //.. return dst; //.. } //.. @@ -1034,7 +1033,7 @@ static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e ) //.. flags set correctly. So bag them. */ //.. addInstr(env, X86Instr_FpStSW_AX()); //.. addInstr(env, mk_iMOVsd_RR(hregX86_EAX(), dst)); -//.. addInstr(env, X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(0x4700), dst)); +//.. addInstr(env, X86Instr_Alu32R(Xalu_AND, X86RMI_Imm(0x4700), dst)); //.. return dst; //.. } //.. @@ -1535,11 +1534,11 @@ static PPC32CondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e ) PPC32RI* ri2 = iselIntExpr_RI(env, e->Iex.Binop.arg2); PPC32CmpOp cmp_op = Pcmp_U; PPC32CondCode cond; + cond.test = Pct_TRUE; switch (e->Iex.Binop.op) { case Iop_CmpEQ32: cond.flag = Pcf_EQ; - cond.test = Pct_TRUE; break; case Iop_CmpNE32: cond.flag = Pcf_EQ; @@ -1548,11 +1547,9 @@ static PPC32CondCode iselCondCode_wrk ( ISelEnv* env, IRExpr* e ) case Iop_CmpLT32S: cmp_op = Pcmp_S; cond.flag = Pcf_LT; - cond.test = Pct_TRUE; break; case Iop_CmpLT32U: cond.flag = Pcf_LT; - cond.test = Pct_TRUE; break; case Iop_CmpLE32S: cmp_op = Pcmp_S; @@ -1936,8 +1933,8 @@ static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) //.. //.. /* Used several times ... */ //.. /* Careful ... this sharing is only safe because -//.. zero_esp/four_esp do not hold any registers which the -//.. register allocator could attempt to swizzle later. */ +//.. zero_esp/four_esp do not hold any registers which the +//.. register allocator could attempt to swizzle later. */ //.. X86AMode* zero_esp = X86AMode_IR(0, hregX86_ESP()); //.. X86AMode* four_esp = X86AMode_IR(4, hregX86_ESP()); //.. @@ -2488,8 +2485,8 @@ static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) //.. HReg srcL = iselDblExpr(env, e->Iex.Binop.arg1); //.. HReg srcR = iselDblExpr(env, e->Iex.Binop.arg2); //.. addInstr(env, X86Instr_FpBinary(fpop,srcL,srcR,res)); -//.. if (fpop != Xfp_ADD && fpop != Xfp_SUB -//.. && fpop != Xfp_MUL && fpop != Xfp_DIV) +//.. if (fpop != Xfp_ADD && fpop != Xfp_SUB +//.. && fpop != Xfp_MUL && fpop != Xfp_DIV) //.. roundToF64(env, res); //.. return res; //.. } @@ -2551,7 +2548,7 @@ static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) //.. HReg res = newVRegF(env); //.. HReg src = iselDblExpr(env, e->Iex.Unop.arg); //.. addInstr(env, X86Instr_FpUnary(fpop,src,res)); -//.. if (fpop != Xfp_SQRT +//.. if (fpop != Xfp_SQRT //.. && fpop != Xfp_NEG && fpop != Xfp_ABS) //.. roundToF64(env, res); //.. return res; @@ -2568,7 +2565,7 @@ static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) //.. addInstr(env, X86Instr_FpLdStI( //.. True/*load*/, 4, dst, //.. X86AMode_IR(0, hregX86_ESP()))); -//.. add_to_esp(env, 4); +//.. add_to_esp(env, 4); //.. return dst; //.. } //.. case Iop_ReinterpI64asF64: { @@ -2576,7 +2573,7 @@ static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) //.. bit pattern. */ //.. HReg dst = newVRegF(env); //.. HReg rHi, rLo; -//.. iselInt64Expr( &rHi, &rLo, env, e->Iex.Unop.arg); +//.. iselInt64Expr( &rHi, &rLo, env, e->Iex.Unop.arg); //.. /* paranoia */ //.. set_FPU_rounding_default(env); //.. addInstr(env, X86Instr_Push(X86RMI_Reg(rHi))); @@ -2584,14 +2581,14 @@ static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) //.. addInstr(env, X86Instr_FpLdSt( //.. True/*load*/, 8, dst, //.. X86AMode_IR(0, hregX86_ESP()))); -//.. add_to_esp(env, 8); +//.. add_to_esp(env, 8); //.. return dst; -//.. } +//.. } //.. case Iop_F32toF64: { //.. /* this is a no-op */ //.. HReg res = iselFltExpr(env, e->Iex.Unop.arg); //.. return res; -//.. } +//.. } //.. default: //.. break; //.. } @@ -2841,7 +2838,7 @@ static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) //.. X86AMode* esp0 = X86AMode_IR(0, hregX86_ESP()); //.. X86RMI* rmi = iselIntExpr_RMI(env, e->Iex.Unop.arg); //.. addInstr(env, X86Instr_Push(rmi)); -//.. addInstr(env, X86Instr_SseLdzLO(4, dst, esp0)); +//.. addInstr(env, X86Instr_SseLdzLO(4, dst, esp0)); //.. add_to_esp(env, 4); //.. return dst; //.. } @@ -2853,14 +2850,14 @@ static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) //.. iselInt64Expr(&rHi, &rLo, env, e->Iex.Unop.arg); //.. addInstr(env, X86Instr_Push(X86RMI_Reg(rHi))); //.. addInstr(env, X86Instr_Push(X86RMI_Reg(rLo))); -//.. addInstr(env, X86Instr_SseLdzLO(8, dst, esp0)); +//.. addInstr(env, X86Instr_SseLdzLO(8, dst, esp0)); //.. add_to_esp(env, 8); //.. return dst; //.. } //.. //.. default: //.. break; -//.. } /* switch (e->Iex.Unop.op) */ +//.. } /* switch (e->Iex.Unop.op) */ //.. } /* if (e->tag == Iex_Unop) */ //.. //.. if (e->tag == Iex_Binop) { @@ -2902,7 +2899,7 @@ static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) //.. X86AMode* esp8 = advance4(esp4); //.. X86AMode* esp12 = advance4(esp8); //.. HReg dst = newVRegV(env); -//.. /* do this via the stack (easy, convenient, etc) */ +//.. /* do this via the stack (easy, convenient, etc) */ //.. sub_from_esp(env, 16); //.. /* Do the less significant 64 bits */ //.. iselInt64Expr(&r1, &r0, env, e->Iex.Binop.arg2); @@ -2912,7 +2909,7 @@ static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) //.. iselInt64Expr(&r3, &r2, env, e->Iex.Binop.arg1); //.. addInstr(env, X86Instr_Alu32M(Xalu_MOV, X86RI_Reg(r2), esp8)); //.. addInstr(env, X86Instr_Alu32M(Xalu_MOV, X86RI_Reg(r3), esp12)); -//.. /* Fetch result back from stack. */ +//.. /* Fetch result back from stack. */ //.. addInstr(env, X86Instr_SseLdSt(True/*load*/, dst, esp0)); //.. add_to_esp(env, 16); //.. return dst; @@ -3089,7 +3086,7 @@ static void iselInt64Expr_wrk ( HReg* rHi, HReg* rLo, ISelEnv* env, IRExpr* e ) //.. addInstr(env, X86Instr_Push(X86RMI_Imm(0))); //.. addInstr(env, X86Instr_Push(rmi)); //.. addInstr(env, X86Instr_SseLdSt(True/*load*/, ereg, esp0)); -//.. addInstr(env, mk_vMOVsd_RR(greg, dst)); +//.. addInstr(env, mk_vMOVsd_RR(greg, dst)); //.. addInstr(env, X86Instr_SseReRg(op, ereg, dst)); //.. add_to_esp(env, 16); //.. return dst; diff --git a/VEX/priv/ir/irdefs.c b/VEX/priv/ir/irdefs.c index 1d06f2b24d..f08eaef270 100644 --- a/VEX/priv/ir/irdefs.c +++ b/VEX/priv/ir/irdefs.c @@ -1404,7 +1404,7 @@ void typeOfPrimop ( IROp op, IRType* t_dst, IRType* t_arg1, IRType* t_arg2 ) case Iop_ShlN16x8: case Iop_ShlN32x4: case Iop_ShlN64x2: case Iop_ShrN16x8: case Iop_ShrN32x4: case Iop_ShrN64x2: case Iop_SarN16x8: case Iop_SarN32x4: - BINARY(Ity_V128, Ity_V128, Ity_I8); + BINARY(Ity_V128, Ity_V128, Ity_I8); default: ppIROp(op); diff --git a/VEX/priv/ir/irmatch.c b/VEX/priv/ir/irmatch.c index 21ee601b36..fe1fbf40e1 100644 --- a/VEX/priv/ir/irmatch.c +++ b/VEX/priv/ir/irmatch.c @@ -81,9 +81,9 @@ Bool matchWrk ( MatchInfo* mi, IRExpr* p/*attern*/, IRExpr* e/*xpr*/ ) case Iex_Binop: if (e->tag != Iex_Binop) return False; if (p->Iex.Binop.op != e->Iex.Binop.op) return False; - if (!matchWrk(mi, p->Iex.Binop.arg1, e->Iex.Binop.arg1)) + if (!matchWrk(mi, p->Iex.Binop.arg1, e->Iex.Binop.arg1)) return False; - if (!matchWrk(mi, p->Iex.Binop.arg2, e->Iex.Binop.arg2)) + if (!matchWrk(mi, p->Iex.Binop.arg2, e->Iex.Binop.arg2)) return False; return True; case Iex_LDle: diff --git a/VEX/priv/main/vex_util.c b/VEX/priv/main/vex_util.c index 70f3386962..dd93df48b2 100644 --- a/VEX/priv/main/vex_util.c +++ b/VEX/priv/main/vex_util.c @@ -314,7 +314,7 @@ myvprintf_int64 ( void(*send)(HChar), Int flags, Int base, Int width, ULong p) } if (width > 0 && (flags & VG_MSG_LJUSTIFY)) { for(; ind < width; ind++) { - ret++; + ret++; send(' '); // Never pad with zeroes on RHS -- changes the value! } } @@ -340,7 +340,7 @@ UInt vprintf_wrk ( void(*send)(HChar), const HChar *format, va_list vargs ) for (i = 0; format[i] != 0; i++) { if (format[i] != '%') { send(format[i]); - ret++; + ret++; continue; } i++; @@ -350,15 +350,15 @@ UInt vprintf_wrk ( void(*send)(HChar), const HChar *format, va_list vargs ) if (format[i] == '%') { /* `%%' is replaced by `%'. */ send('%'); - ret++; + ret++; continue; } flags = 0; is_long = False; width = 0; /* length of the field. */ if (format[i] == '(') { - flags |= VG_MSG_PAREN; - i++; + flags |= VG_MSG_PAREN; + i++; } /* If ',' follows '%', commas will be inserted. */ if (format[i] == ',') { @@ -390,36 +390,36 @@ UInt vprintf_wrk ( void(*send)(HChar), const HChar *format, va_list vargs ) flags |= VG_MSG_SIGNED; if (is_long) ret += myvprintf_int64(send, flags, 10, width, - (ULong)(va_arg (vargs, Long))); + (ULong)(va_arg (vargs, Long))); else ret += myvprintf_int64(send, flags, 10, width, - (ULong)(va_arg (vargs, Int))); + (ULong)(va_arg (vargs, Int))); break; case 'u': /* %u */ if (is_long) ret += myvprintf_int64(send, flags, 10, width, - (ULong)(va_arg (vargs, ULong))); + (ULong)(va_arg (vargs, ULong))); else ret += myvprintf_int64(send, flags, 10, width, - (ULong)(va_arg (vargs, UInt))); + (ULong)(va_arg (vargs, UInt))); break; case 'p': /* %p */ - ret += 2; + ret += 2; send('0'); send('x'); ret += myvprintf_int64(send, flags, 16, width, - (ULong)((HWord)va_arg (vargs, void *))); + (ULong)((HWord)va_arg (vargs, void *))); break; case 'x': /* %x */ if (is_long) ret += myvprintf_int64(send, flags, 16, width, - (ULong)(va_arg (vargs, ULong))); + (ULong)(va_arg (vargs, ULong))); else ret += myvprintf_int64(send, flags, 16, width, - (ULong)(va_arg (vargs, UInt))); + (ULong)(va_arg (vargs, UInt))); break; case 'c': /* %c */ - ret++; + ret++; send(toHChar(va_arg (vargs, int))); break; case 's': case 'S': { /* %s */ @@ -428,25 +428,25 @@ UInt vprintf_wrk ( void(*send)(HChar), const HChar *format, va_list vargs ) ret += myvprintf_str(send, flags, width, str, toBool(format[i]=='S')); break; - } + } # if 0 - case 'y': { /* %y - print symbol */ - Char buf[100]; - Char *cp = buf; - Addr a = va_arg(vargs, Addr); - - if (flags & VG_MSG_PAREN) - *cp++ = '('; - if (VG_(get_fnname_w_offset)(a, cp, sizeof(buf)-4)) { - if (flags & VG_MSG_PAREN) { - cp += VG_(strlen)(cp); - *cp++ = ')'; - *cp = '\0'; - } - ret += myvprintf_str(send, flags, width, buf, 0); - } - break; - } + case 'y': { /* %y - print symbol */ + Char buf[100]; + Char *cp = buf; + Addr a = va_arg(vargs, Addr); + + if (flags & VG_MSG_PAREN) + *cp++ = '('; + if (VG_(get_fnname_w_offset)(a, cp, sizeof(buf)-4)) { + if (flags & VG_MSG_PAREN) { + cp += VG_(strlen)(cp); + *cp++ = ')'; + *cp = '\0'; + } + ret += myvprintf_str(send, flags, width, buf, 0); + } + break; + } # endif default: break; diff --git a/VEX/pub/libvex_ir.h b/VEX/pub/libvex_ir.h index 1d63002d97..53e34b5fdf 100644 --- a/VEX/pub/libvex_ir.h +++ b/VEX/pub/libvex_ir.h @@ -296,7 +296,7 @@ typedef /* --- Int to/from FP conversions. --- */ /* For the most part, these take a first argument :: Ity_I32 - (as IRRoundingMode) which is an indication of the rounding + (as IRRoundingMode) which is an indication of the rounding mode to use, as per the following encoding: 00b to nearest (the default) 01b to -infinity @@ -405,7 +405,7 @@ typedef /* --- 32x4 lowest-lane-only scalar FP --- */ /* In binary cases, upper 3/4 is copied from first operand. In - unary cases, upper 3/4 is copied from the operand. */ + unary cases, upper 3/4 is copied from the operand. */ /* binary */ Iop_Add32F0x4, Iop_Sub32F0x4, Iop_Mul32F0x4, Iop_Div32F0x4, @@ -428,7 +428,7 @@ typedef /* --- 64x2 lowest-lane-only scalar FP --- */ /* In binary cases, upper half is copied from first operand. In - unary cases, upper half is copied from the operand. */ + unary cases, upper half is copied from the operand. */ /* binary */ Iop_Add64F0x2, Iop_Sub64F0x2, Iop_Mul64F0x2, Iop_Div64F0x2, @@ -610,7 +610,7 @@ typedef struct _IRExpr { IRExprTag tag; union { - struct { + struct { Int binder; } Binder; struct {