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;
}
}
}
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*/
}
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
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
// 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*/
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");
}
}
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
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),
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
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");
}
}
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");
}
}
/* 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");
+ }
}
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) { // <addressing_mode>
- 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) { // <addressing_mode>
+ 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;
}
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;
}
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;
}
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;
}
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;
}
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);
+ }
+ }
}
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;
}
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);
}
/*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;
// 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. */
// 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;
}
/*
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;
}
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;
}
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(" ");
+ }
+ }
}
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;
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?
}
}
}
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
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*/
// 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))));
}
// 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);
// 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);
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
}
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) ));
}
/* 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)) );
}
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));
/* 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)");
+ }
}
*/
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;
}
*/
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);
}
/*
*/
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<<i)) {
- mask = mask | (0xF << (7-i)*4);
- }
- }
- putReg_masked( REG_CR, mkexpr(Rs), mask );
- break;
-
- case 0x1D3: // mtspr (Move to Special-Purpose Register, p530)
- DIP("mtspr 0x%x,r%d\n", SPR_flipped, Rs_addr);
-
- switch (SPR_flipped) { // Choose a register...
- case 0x1: // XER
- putReg( REG_XER, mkexpr(Rs) );
- break;
- case 0x8: // LR
- putReg( REG_LR, mkexpr(Rs) );
- break;
- case 0x9: // CTR
- putReg( REG_CTR, mkexpr(Rs) );
- 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 0x11C: case 0x11D:
- 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)(mtspr) - supervisor level op\n");
- return False;
-
- default:
- vex_printf("dis_proc_ctl(PPC32)(mtspr,SPR)\n");
- return False;
- }
- break;
-
- default:
- vex_printf("dis_proc_ctl(PPC32)(opc2)\n");
- return False;
- }
- return True;
+ 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<<i)) {
+ mask = mask | (0xF << (7-i)*4);
+ }
+ }
+ putReg_masked( REG_CR, mkexpr(Rs), mask );
+ break;
+
+ case 0x1D3: // mtspr (Move to Special-Purpose Register, p530)
+ DIP("mtspr 0x%x,r%d\n", SPR_flipped, Rs_addr);
+
+ switch (SPR_flipped) { // Choose a register...
+ case 0x1: // XER
+ putReg( REG_XER, mkexpr(Rs) );
+ break;
+ case 0x8: // LR
+ putReg( REG_LR, mkexpr(Rs) );
+ break;
+ case 0x9: // CTR
+ putReg( REG_CTR, mkexpr(Rs) );
+ 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 0x11C: case 0x11D:
+ 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)(mtspr) - supervisor level op\n");
+ return False;
+
+ default:
+ vex_printf("dis_proc_ctl(PPC32)(mtspr,SPR)\n");
+ return False;
+ }
+ break;
+
+ default:
+ vex_printf("dis_proc_ctl(PPC32)(opc2)\n");
+ return False;
+ }
+ return True;
}
static Bool dis_cache_manage ( UInt theInstr )
{
- /* 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;
+ /* 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;
}
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 &&
// 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;
}
#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
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
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
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
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
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
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 );
{
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);
}
/* 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");
}
}
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");
}
}
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");
}
}
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");
}
}
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");
}
}
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;
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;
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;
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)
//.. 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);
//.. 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)");
}
}
// 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);
//.. 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);
//.. 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");
}
}
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);
//.. 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);
//.. 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");
}
}
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;
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");
}
}
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");
}
}
//.. }
//.. 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;
}
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);
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);
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);
}
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);
}
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:
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;
}
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:
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:
//.. 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);
//.. *p++ = 0xBD;
//.. p = emit32(p, VEX_TRC_JMP_NODECODE); break;
//.. case Ijk_Ret:
-//.. case Ijk_Call:
+//.. case Ijk_Call:
//.. case Ijk_Boring:
//.. break;
//.. default:
//.. /* 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;
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;
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;
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:
//.. */
//.. 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;
//.. } 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;