"PowerPC Microprocessor Family:
Programming Environments Manual for 64 and 32-Bit Microprocessors
Version 2.0"
+ 06/10/2003
http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/F6153E213FDD912E87256D49006C6541
+
+ Also see (but not for the page refs):
+ "PowerPC Microprocessor Family:
+ The Programming Environments for 32-Bit Microprocessors"
+ 02/21/2000
+ http://www-3.ibm.com/chips/techlib/techlib.nsf/techdocs/852569B20050FF778525699600719DF2
*/
#include "libvex_basictypes.h"
if (n_instrs > 0) {
/* for the first insn, the dispatch loop will have set
- GPR1, but for all the others we have to do it ourselves. */
+ CIA, but for all the others we have to do it ourselves. */
stmt( IRStmt_Put( OFFB_CIA, mkU32(guest_cia_curr_instr)) );
}
// call->Iex.CCall.cee->mcx_mask = 1;
// CAB: Haven't looked at the whole 'definedness' stuff...
+// 02/02/05 - leaving 'till get memcheck working well.
return call;
}
vassert(typeOfIRTemp(irbb->tyenv,arg2) == Ity_I32);
IRTemp ov = newTemp(Ity_I8);
- assign( ov, unop(Iop_32to8, mk_ppc32g_calculate_xer_ov(op, res, arg1, arg2)) );
+ assign( ov, unop(Iop_32to8,
+ mk_ppc32g_calculate_xer_ov(op, res, arg1, arg2)) );
stmt( IRStmt_Put( OFFB_XER_OV, mkexpr(ov) ));
stmt( IRStmt_Put( OFFB_XER_SO, mkexpr(ov) ));
}
}
// CAB: How to represent the following, if at all ?
// If (0x8000_0000 / -1) or (x / 0)
- // => Rd = undef, CR0 = undef, if (OE) => set XER_OV
+ // => Rd=undef, if(flag_Rc) => CR0=undef, if(OE) => XER_OV=1
break;
case 0x1CB: // divwu (Divide Word Unsigned, p422)
flag_OE ? "o" : "", flag_Rc ? "." : "",
Rd_addr, Ra_addr);
// rD = (log not)rA + 1
- assign( Rd, binop(Iop_Add32, mkU32(1), unop(Iop_Not32, mkexpr(Ra))) );
+ assign( Rd, binop(Iop_Add32, mkU32(1),
+ unop(Iop_Not32, mkexpr(Ra))) );
if (flag_OE) {
mk_ppc32g_set_xer_ov_so( PPC32G_FLAG_OP_NEG, Rd, Ra, Rb );
}
if (crfD == 0) {
setFlags_CR0_Flags( binop(Iop_Shl32, mkexpr(cr_flags), mkU8(28)) );
} else {
- stmt( IRStmt_Put( OFFB_CR1to7,
- binop(Iop_Shl32, mkexpr(cr_flags), mkU8(crfD * 4)) ));
+ stmt( IRStmt_Put( OFFB_CR1to7, binop(Iop_Shl32, mkexpr(cr_flags),
+ mkU8(crfD * 4)) ));
}
return True;
}
case 0x01A: // cntlzw (Count Leading Zeros Word, p402)
if (Rb_addr!=0) { return False; }
DIP("cntlzw%s %d,%d\n", flag_Rc ? "." : "", Ra_addr, Rs_addr);
- // Iop_Clz32 undefined for arg==0...
- assign(Ra, IRExpr_Mux0X( mkexpr(Rs), mkU32(32),
- unop(Iop_Clz32, mkexpr(Rs)) ));
- // CAB ?
- // "If Rc = 1, then LT is cleared in the CR0 field."
+ // 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 %d,%d,%d\n",
flag_Rc ? "." : "", Ra_addr, Rs_addr, Rb_addr);
- assign( Ra, unop(Iop_Not32, binop(Iop_Xor32, mkexpr(Rs), mkexpr(Rb))) );
+ assign( Ra, unop(Iop_Not32, binop(Iop_Xor32,
+ mkexpr(Rs), mkexpr(Rb))) );
break;
case 0x3BA: // extsb (Extend Sign Byte, p428)
if (Rb_addr!=0) { return False; }
DIP("extsb%s %d,%d\n", flag_Rc ? "." : "", Ra_addr, Rs_addr);
assign( Sign, binop(Iop_And32, mkU32(0x80), mkexpr(Rs)) );
- assign( Ra,
- IRExpr_Mux0X( binop(Iop_CmpEQ32, mkexpr(Sign), mkU32(0)),
- binop(Iop_Or32, mkU32(0xFFFFFF00), mkexpr(Rs)),
- binop(Iop_And32, mkU32(0x000000FF), 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) { return False; }
DIP("extsh%s %d,%d\n", flag_Rc ? "." : "", Ra_addr, Rs_addr);
assign( Sign, binop(Iop_And32, mkU32(0x8000), mkexpr(Rs)) );
- assign( Ra,
- IRExpr_Mux0X( binop(Iop_CmpEQ32, mkexpr(Sign), mkU32(0)),
- binop(Iop_Or32, mkU32(0xFFFF0000), mkexpr(Rs)),
- binop(Iop_And32, mkU32(0x0000FFFF), 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 0x1DA: // nand (NAND, p546)
switch (opc1) {
case 0x22: // lbz (Load B & Zero, p468)
DIP("lbz %d,%d(%d)\n", Rd_addr, d_imm, Ra_addr);
- putIReg( Rd_addr, loadBE(Ity_I8, mkexpr(EA_imm)) );
+ 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) { return False; }
DIP("lbzu %d,%d(%d)\n", Rd_addr, d_imm, Ra_addr);
- putIReg( Rd_addr, loadBE(Ity_I8, mkexpr(EA_imm)) );
+ 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 %d,%d(%d)\n", Rd_addr, d_imm, Ra_addr);
- putIReg( Rd_addr, unop(Iop_16Sto32, loadBE(Ity_I16, mkexpr(EA_imm))) );
+ 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) { return False; }
DIP("lhau %d,%d(%d)\n", Rd_addr, d_imm, Ra_addr);
- putIReg( Rd_addr, unop(Iop_16Sto32, loadBE(Ity_I16, mkexpr(EA_imm))) );
+ 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 %d,%d(%d)\n", Rd_addr, d_imm, Ra_addr);
- putIReg( Rd_addr, loadBE(Ity_I16, mkexpr(EA_imm)) );
+ putIReg( Rd_addr, unop(Iop_16Sto32,
+ loadBE(Ity_I16, mkexpr(EA_imm))) );
break;
case 0x29: // lhzu (Load HW & and Zero with Update, p491)
case 0x20: // lwz (Load W & Zero, p504)
DIP("lwz %d,%d(%d)\n", Rd_addr, d_imm, Ra_addr);
- putIReg( Rd_addr, loadBE(Ity_I32, mkexpr(EA_imm)) );
+ 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) { return False; }
DIP("lwzu %d,%d(%d)\n", Rd_addr, d_imm, Ra_addr);
- putIReg( Rd_addr, loadBE(Ity_I32, mkexpr(EA_imm)) );
+ putIReg( Rd_addr, loadBE(Ity_I32, mkexpr(EA_imm)) );
putIReg( Ra_addr, mkexpr(EA_imm) );
break;
case 0x077: // lbzux (Load B & Zero with Update Indexed, p470)
DIP("lbzux %d,%d,%d\n", Rd_addr, Ra_addr, Rb_addr);
if (Ra_addr == 0 || Ra_addr == Rd_addr) { return False; }
- putIReg( Rd_addr, loadBE(Ity_I8, mkexpr(EA_reg)) );
+ 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 %d,%d,%d\n", Rd_addr, Ra_addr, Rb_addr);
- putIReg( Rd_addr, loadBE(Ity_I8, mkexpr(EA_reg)) );
+ 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) { return False; }
DIP("lhaux %d,%d,%d\n", Rd_addr, Ra_addr, Rb_addr);
- putIReg( Rd_addr, unop(Iop_16Sto32, loadBE(Ity_I16, mkexpr(EA_reg))) );
+ 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 %d,%d,%d\n", Rd_addr, Ra_addr, Rb_addr);
- putIReg( Rd_addr, unop(Iop_16Sto32, loadBE(Ity_I16, mkexpr(EA_reg))) );
+ 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) { return False; }
DIP("lhzux %d,%d,%d\n", Rd_addr, Ra_addr, Rb_addr);
- putIReg( Rd_addr, loadBE(Ity_I16, mkexpr(EA_reg)) );
+ 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 %d,%d,%d\n", Rd_addr, Ra_addr, Rb_addr);
- putIReg( Rd_addr, loadBE(Ity_I16, mkexpr(EA_reg)) );
+ putIReg( Rd_addr, unop(Iop_16Sto32,
+ loadBE(Ity_I16, mkexpr(EA_reg))) );
break;
case 0x037: // lwzux (Load W & Zero with Update Indexed, p506)
UInt n_regs, reg_first, reg_last;
IRTemp Ra = newTemp(Ity_I32);
- IRTemp Rb = newTemp(Ity_I32);
+// IRTemp Rb = newTemp(Ity_I32);
IRTemp EA = newTemp(Ity_I32);
IRTemp b_EA = newTemp(Ity_I32);
IRExpr* irx_byte;
} else {
assign( Ra, getIReg(Ra_addr) );
assign( b_EA, mkexpr(Ra) );
- }
-
+ }
if (opc1 != 0x1F || b0 != 0) { return False; }
switch (opc2) {
}
case 0x215: // lswx (Load String Word Indexed, p497)
-/*
- if ((Rd_addr == Ra_addr || Rd_addr == Rb_addr) ||
- (Rd_addr == 0 && Ra_addr == 0 )) {
- return False;
- }
- if (reg_last < reg_first) {
- if ((Ra_addr >= reg_first || Ra_addr <= reg_last) ||
- (Rb_addr >= reg_first || Rb_addr <= reg_last)) {
- return False;
- }
- } else {
- if ((Ra_addr >= reg_first && Ra_addr <= reg_last) ||
- (Rb_addr >= reg_first && Rb_addr <= reg_last)) {
- return False;
- }
- }
-*/
DIP("lswx %d,%d,%d\n", Rd_addr, Ra_addr, Rb_addr);
+ return False;
- assign( Rb, getIReg(Rb_addr) );
- assign( EA, binop(Iop_And32, mkexpr(b_EA), mkexpr(Rb)) );
-
-/*
-// assign( n_byte, IRExpr_Get(OFFB_XER_BC, Ity_I8) );
-
-
- // CAB: What to do now? Can't loop in IR...
-
+ case 0x2D5: // stswi (Store String Word Immediate, p601)
+ DIP("stswi %d,%d,%d\n", Rs_addr, Ra_addr, NumBytes);
+ if (Ra_addr == 0) {
+ assign( EA, mkU32(0) );
+ } else {
+ assign( EA, mkexpr(b_EA) );
+ }
- reg_idx = Rd_addr - 1;
- bit_idx = 32;
-// rD = undef;
+ 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==32) {
+ if (bit_idx == 0) {
reg_idx++;
- if (reg_idx >=32) reg_idx=0;
- putIReg( reg_idx, mkU32(0) );
+ if (reg_idx==32) reg_idx = 0;
}
- irx_byte = loadBE(Ity_I8, binop(Iop_Add32,
- mkexpr(EA),
- mkU32(EA_offset)));
- irx_shl = binop(Iop_Shl32, irx_byte, mkU8(24 - bit_idx));
- putIReg( reg_idx, binop(Iop_Or32, getIReg(reg_idx), irx_shl) );
+ irx_byte = unop(Iop_32to8,
+ binop(Iop_Shr32,
+ getIReg(reg_idx), mkU8(24 - bit_idx)));
+ storeBE( binop(Iop_Add32, mkexpr(EA), mkU32(EA_offset)),
+ irx_byte );
- bit_idx +=8;
- if (bit_idx==32) bit_idx = 0;
+ bit_idx += 8;
+ if (bit_idx == 32) { bit_idx = 0; }
EA_offset++;
}
break;
-*/
- return False;
-
- case 0x2D5: // stswi (Store String Word Immediate, p601)
- DIP("stswi %d,%d,%d\n", Rs_addr, Ra_addr, NumBytes);
- return False;
case 0x295: // stswx (Store String Word Indexed, p602)
DIP("stswx %d,%d,%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;
+#endif
default:
return False;
UChar flag_LK = (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 cia = newTemp(Ity_I32);
IRTemp lr = newTemp(Ity_I32);
- IRTemp nia = newTemp(Ity_I32);
- IRTemp nia_tmp = newTemp(Ity_I32);
+ IRTemp ir_nia = newTemp(Ity_I32);
IRTemp ctr_ok = newTemp(Ity_I32);
IRTemp cond_ok = newTemp(Ity_I32);
- IRTemp do_branch = newTemp(Ity_I8);
+ IRTemp do_branch = newTemp(Ity_I32);
IRTemp cr = newTemp(Ity_I32);
- IRTemp tmp = newTemp(Ity_I32);
-// IRTemp tmp2 = newTemp(Ity_I32);
IROp tmp_op;
- assign( cia, IRExpr_Get(OFFB_CIA, Ity_I32) );
-
- assign( lr, binop(Iop_Add32, mkexpr(cia), mkU32(4)) );
-
// 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);
switch (opc1) {
case 0x12: // b (Branch, p390)
DIP("b%s%s 0x%x\n", flag_LK ? "l" : "", flag_AA ? "a" : "", LI_24);
- assign( tmp, mkU32(extend_s_24to32(LI_24 << 2)) );
- if (flag_AA) {
- assign( nia, mkexpr(tmp) );
- } else {
- assign( nia, binop( Iop_Add32, mkexpr(cia), mkexpr(tmp) ));
+ nia = exts_LI;
+ if (!flag_AA) {
+ nia += guest_cia_curr_instr;
}
if (flag_LK) {
- stmt( IRStmt_Put( OFFB_LR, mkexpr(lr) ));
+ stmt( IRStmt_Put( OFFB_LR, mkU32(guest_cia_curr_instr+4) ));
}
irbb->jumpkind = flag_LK ? Ijk_Call : Ijk_Boring;
- irbb->next = mkexpr(nia);
+ irbb->next = mkU32(nia);
break;
case 0x10: // bc (Branch Conditional, p391)
// BO[1] == 1: ctr_ok = BO[2] | (CTR[0] == 0)
// BO[1] == 0: ctr_ok = BO[2] | (CTR[0] != 0)
tmp_op = ((BO & 0x2) != 0) ? Iop_CmpEQ32 : Iop_CmpNE32;
- assign( ctr_ok, binop(Iop_Or32, mkU32(BO & 4),
+ assign( ctr_ok, binop(Iop_Or32, mkU32((BO >> 2)&1),
unop(Iop_1Uto32,
binop(tmp_op, mkU32(0),
binop(Iop_And32, mkU32(1),
mkexpr(ctr))))) );
-
+
// cond_ok = BO[4] | (CR[BI] == BO[3])
if (BI < 4) { // Get from guest_CC_OP etc.
assign( cr, mk_ppc32g_calculate_cr0_all() );
assign( cr, IRExpr_Get(OFFB_CR1to7, Ity_I32) );
}
tmp_op = ((BO & 0x8) != 0) ? Iop_CmpNE32 : Iop_CmpEQ32;
- assign( cond_ok, binop(Iop_Or32, mkU32(BO & 16),
- unop(Iop_1Uto32,
+ assign( cond_ok, binop(Iop_Or32, mkU32(BO >> 4),
+ unop(Iop_1Uto32,
binop(tmp_op, mkU32(0),
binop(Iop_And32, mkU32(1<<BI),
mkexpr(cr))))) );
+ assign( do_branch,
+ binop(Iop_And32, mkexpr(ctr_ok), mkexpr(cond_ok)) );
- assign( do_branch, narrowTo(Ity_I8,
- binop(Iop_And32, mkexpr(ctr_ok), mkexpr(cond_ok))) );
- if (flag_AA) {
- assign( nia_tmp, mkU32(exts_BD) );
- } else {
- assign( nia_tmp, binop(Iop_Add32, mkexpr(cia),
- mkU32(exts_BD)) );
+ nia = exts_BD;
+ if (!flag_AA) {
+ nia += guest_cia_curr_instr;
}
-#if 0
- // CAB: Ummm.. get nia how?
- assign( nia, IRExpr_Mux0X( mkexpr(do_branch),
- IRExpr_Get(OFFB_NIA, Ity_I32),
- mkexpr(nia_tmp)) );
if (flag_LK) {
- stmt( IRStmt_Put( OFFB_LR,
- IRExpr_Mux0X( mkexpr(do_branch),
- IRExpr_Get(OFFB_LR, Ity_I32),
- mkexpr(lr) )));
+ 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) ));
}
- irbb->jumpkind = flag_LK ? Ijk_Call : Ijk_Boring;
- irbb->next = mkexpr(nia);
+ 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;
-#endif
- return False;
+
case 0x13:
if (b11to15!=0) { return False; }
switch (opc2) {
case 0x210: // bcctr (Branch Cond. to Count Register, p393)
DIP("bcctr%s 0x%x, 0x%x,\n", flag_LK ? "l" : "", BO, BI);
-/*
- cond_ok = BO[0] | (CR[BI] == BO[1])
- if (cond_ok) {
- NIA = CTR[0-61] || 0b00
- if (flag_LK) {
- LR = CIA + 4
- }
+
+ // cond_ok = BO[4] | (CR[BI] == BO[3])
+ if (BI < 4) { // Get from guest_CC_OP etc.
+ assign( cr, mk_ppc32g_calculate_cr0_all() );
+ } else { // Get from guest_CR1to7
+ assign( cr, IRExpr_Get(OFFB_CR1to7, Ity_I32) );
}
-*/
- return False;
+ tmp_op = ((BO & 0x8) != 0) ? Iop_CmpNE32 : Iop_CmpEQ32;
+ assign( cond_ok, binop(Iop_Or32, mkU32(BO >> 4),
+ unop(Iop_1Uto32,
+ binop(tmp_op, mkU32(0),
+ binop(Iop_And32, mkU32(1<<BI),
+ mkexpr(cr))))) );
+ assign( ir_nia, binop(Iop_And32,
+ IRExpr_Get(OFFB_CTR, Ity_I32),
+ mkU32(-1 << 2)) );
+ if (flag_LK) {
+ assign( lr, IRExpr_Mux0X( unop(Iop_32to8, mkexpr(cond_ok)),
+ IRExpr_Get(OFFB_LR, Ity_I32),
+ mkU32(guest_cia_curr_instr + 4)));
+ stmt( IRStmt_Put( OFFB_LR, mkexpr(lr) ));
+ }
+
+ // CAB: Can't give ir_nia as IRConst, so reversing things...
+ // Not sure about this at all...
+ stmt( IRStmt_Exit( unop(Iop_32to1, unop(Iop_Not32, mkexpr(cond_ok))),
+ Ijk_Boring,
+ IRConst_U32(guest_cia_curr_instr + 4) ));
+
+ irbb->jumpkind = flag_LK ? Ijk_Call : Ijk_Boring;
+ irbb->next = mkU32(nia);
+ break;
case 0x010: // bclr (Branch Cond. to Link Register, p395)
DIP("bclr%s 0x%x, 0x%x,\n", flag_LK ? "l" : "", BO, BI);
// BO[1] == 1: ctr_ok = BO[2] | (CTR[0] == 0)
// BO[1] == 0: ctr_ok = BO[2] | (CTR[0] != 0)
tmp_op = ((BO & 0x2) != 0) ? Iop_CmpEQ32 : Iop_CmpNE32;
- assign( ctr_ok, binop(Iop_Or32, mkU32(BO & 4),
+ assign( ctr_ok, binop(Iop_Or32, mkU32((BO >> 2)&1),
unop(Iop_1Uto32,
binop(tmp_op, mkU32(0),
binop(Iop_And32, mkU32(1),
assign( cr, IRExpr_Get(OFFB_CR1to7, Ity_I32) );
}
tmp_op = ((BO & 0x8) != 0) ? Iop_CmpNE32 : Iop_CmpEQ32;
- assign( cond_ok, binop(Iop_Or32, mkU32(BO & 16),
+ assign( cond_ok, binop(Iop_Or32, mkU32(BO >> 4),
unop(Iop_1Uto32,
binop(tmp_op, mkU32(0),
binop(Iop_And32, mkU32(1<<BI),
mkexpr(cr))))) );
+ assign( do_branch,
+ binop(Iop_And32, mkexpr(ctr_ok), mkexpr(cond_ok)) );
- assign( do_branch, narrowTo(Ity_I8,
- binop(Iop_And32, mkexpr(ctr_ok), mkexpr(cond_ok))) );
-
-#if 0
- // CAB: Ummm... get nia how?
-
- assign( nia, IRExpr_Mux0X( mkexpr(do_branch),
- IRExpr_Get(OFFB_NIA, Ity_I32),
- binop(Iop_Shl32,
- IRExpr_Get(OFFB_NIA, Ity_I32),
- mkU8(2))) );
+ assign( ir_nia, binop(Iop_And32,
+ IRExpr_Get(OFFB_LR, Ity_I32),
+ mkU32(-1 << 2)) );
if (flag_LK) {
- stmt( IRStmt_Put( OFFB_LR,
- IRExpr_Mux0X(mkexpr(do_branch),
- IRExpr_Get(OFFB_LR, Ity_I32),
- mkexpr(lr)) ));
+ 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) ));
}
+ // CAB: Can't give ir_nia as IRConst, so reversing things...
+ // Not sure about this at all...
+ stmt( IRStmt_Exit( unop(Iop_32to1, unop(Iop_Not32, mkexpr(do_branch))),
+ Ijk_Boring,
+ IRConst_U32(guest_cia_curr_instr + 4) ));
+
irbb->jumpkind = flag_LK ? Ijk_Call : Ijk_Boring;
- irbb->next = mkexpr(nia);
+ irbb->next = mkexpr(ir_nia);
break;
-#endif
- return False;
default:
return False;
static Bool dis_syslink ( UInt theInstr )
{
- if (theInstr != 0x44000010) { return False; }
+// const UChar IP_bit = 6;
+ Addr32 base_ea = 0;
+ Addr32 nia;
+
// sc (System Call, p565)
+ if (theInstr != 0x44000002) { return False; }
DIP("sc\n");
- /*
- See 2.3.1 Machine State Register (MSR), p72
- See Section 6.4, Exception Definitions, p237
- */
- /*
- SRR0 ¬iea CIA + 4
- SRR1[1-4, 10-15] = 0
- SRR1[0,5-9, 16-23, 25-27, 30-31] = MSR[0,5-9, 16-23, 25-27, 30-31]
- MSR = new_value (see Section 6.4, Exception Definitions)
- base_ea determined from MSR[IP]
- NIA = base_ea + 0xC00
- */
- return False;
-}
+ // CAB: how to get MSR[IP] ?
+ //
+ // I'm confused - no other ops in date.orig have anything to do with MSR
+ // And this op (or any other exception) doesn't change bit IP... (p237)
+ // Moreover, on start, bit IP is not guaranteed to be defined (p75)
+ // Where does MSR[IP] get set?!
+ // base_ea = (MSR[IP_bit] == 1) ? 0xFFF00000 : 0; // See p234, Table 6-5
+ nia = base_ea + 0xC00;
+
+
+ /* 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( nia );
+ irbb->jumpkind = Ijk_Syscall;
+
+ return True;
+}
static Bool dis_memsync ( UInt theInstr )
{
if (opc2 != 0x096) { return False; }
if (b11to25 != 0 || b0 != 0) { return False; }
DIP("isync\n");
- return False;
+
+ // CAB: This right? What's the diff from 'sync' ?
+ stmt( IRStmt_MFence() );
+ break;
/* X-Form */
case 0x1F:
case 0x256: // sync (Synchronize, p616)
if (b11to25 != 0 || b0 != 0) { return False; }
DIP("sync\n");
- return False;
+ /* Insert a memory fence. It's sometimes important that these
+ are carried through to the generated code. */
+ stmt( IRStmt_MFence() );
+ break;
default:
return False;
// sign = Rs[31]
assign( sign, binop(Iop_And32, mkU32(1),
binop(Iop_Shr32, mkexpr(Rs), mkU8(31))) );
- // sign_ext = sign==0 ? 0 : (sign_rb==0 ? -1 : (-1 << (31-shft_amt)))
+ // sign_ext = sign==0 ? 0 : (sign_rb==0 ? -1 : (-1<<(31-shft_amt)))
assign( tmp, IRExpr_Mux0X( unop(Iop_32to8, mkexpr(sign_rb)),
mkU32(-1),
binop(Iop_Shl32, mkU32(-1),
assign( xer_ca, binop(Iop_And8,
unop(Iop_32to8, mkexpr(sign)),
unop(Iop_1Uto8, binop(Iop_CmpNE32, mkU32(0),
- mkexpr(Rs_out)))) );
+ mkexpr(Rs_out)))) );
stmt( IRStmt_Put( OFFB_XER_CA, mkexpr(xer_ca) ) );
if (flag_Rc) { setFlags_CR0_Result( mkexpr(Ra) ); }
break;
/* XFX-Form */
case 0x153: // mfspr (Move from Special-Purpose Register, p514)
+ if ((SPR & 0x1F) != 0) { return False; }
DIP("mfspr %d,%d\n", Rd_addr, SPR);
- switch (SPR) { // Choose a register...
- case 0x020: // 00001 00000 => XER
+
+ switch (SPR>>5) { // Choose a register...
+ case 1: // XER
assign( xer_so, binop(Iop_Shl32,
IRExpr_Get(OFFB_XER_SO, Ity_I8),
mkU8(31)) );
mkexpr(xer_ca), mkexpr(xer_bc))) );
putIReg( Rd_addr, mkexpr(xer) );
break;
- case 0x100: // 01000 00000 => LR
+ case 8: // LR
putIReg( Rd_addr, IRExpr_Get(OFFB_LR, Ity_I32) );
break;
- case 0x120: // 01001 00000 => CTR
+ case 9: // CTR
putIReg( Rd_addr, IRExpr_Get(OFFB_CTR, Ity_I32) );
break;
default:
}
}
assign( Rs_masked, binop(Iop_And32, mkexpr(Rs), mkU32(mask)) );
-
+
if (CRM & 0x80) { // guest_CC_OP etc.
- setFlags_CR0_Flags( binop(Iop_And32, mkexpr(Rs_masked), mkU32(0xF0000000)) );
+ setFlags_CR0_Flags( binop(Iop_And32,
+ mkexpr(Rs_masked), mkU32(0xF0000000)) );
}
// guest_CR1to7...
assign( cr1to7,
break;
case 0x1D3: // mtspr (Move to Special-Purpose Register, p530)
+ if ((SPR & 0x1F) != 0) { return False; }
DIP("mtspr %d,%d\n", SPR, Rs_addr);
- switch (SPR) { // Choose a register...
- case 0x020: // 00001 00000 => XER
+
+ switch (SPR>>5) { // Choose a register...
+ case 1: // XER
assign( xer, mkexpr(Rs) );
assign( xer_so, binop(Iop_Shr32,
binop(Iop_And32, mkexpr(xer), mkU32(0x80000000)),
stmt( IRStmt_Put( OFFB_XER_CA, mkexpr(xer_ca)) );
stmt( IRStmt_Put( OFFB_XER_BC, mkexpr(xer_bc)) );
break;
- case 0x100: // 01000 00000 => LR
+ case 8: // LR
stmt( IRStmt_Put( OFFB_LR, mkexpr(Rs)) );
break;
- case 0x120: // 01001 00000 => CTR
+ case 9: // CTR
stmt( IRStmt_Put( OFFB_CTR, mkexpr(Rs)) );
break;
default:
switch (opc2) {
case 0x2F6: // dcba (Data Cache Block Allocate, p411)
DIP("dcba %d,%d\n", Ra_addr, Rb_addr);
- return False;
+ if (1) vex_printf("vex ppc32->IR: kludged dcba\n");
+ break;
case 0x056: // dcbf (Data Cache Block Flush, p413)
DIP("dcbf %d,%d\n", Ra_addr, Rb_addr);
- return False;
+ if (1) vex_printf("vex ppc32->IR: kludged dcbf\n");
+ break;
case 0x036: // dcbst (Data Cache Block Store, p415)
DIP("dcbst %d,%d\n", Ra_addr, Rb_addr);
- return False;
+ if (1) vex_printf("vex ppc32->IR: kludged dcbst\n");
+ break;
case 0x116: // dcbt (Data Cache Block Touch, p416)
DIP("dcbt %d,%d\n", Ra_addr, Rb_addr);
- return False;
+ if (1) vex_printf("vex ppc32->IR: kludged dcbt\n");
+ break;
case 0x0F6: // dcbtst (Data Cache Block Touch for Store, p417)
DIP("dcbtst %d,%d\n", Ra_addr, Rb_addr);
- return False;
+ if (1) vex_printf("vex ppc32->IR: kludged dcbtst\n");
+ break;
case 0x3F6: // dcbz (Data Cache Block Clear to Zero, p418)
DIP("dcbz %d,%d\n", Ra_addr, Rb_addr);
- return False;
+ if (1) vex_printf("vex ppc32->IR: kludged dcbz\n");
+ break;
case 0x3D6: // icbi (Instruction Cache Block Invalidate, p466)
DIP("icbi %d,%d\n", Ra_addr, Rb_addr);
- return False;
+ if (1) vex_printf("vex ppc32->IR: kludged icbi\n");
+ break;
default:
return False;
System Linkage Instructions
*/
case 0x11: // sc
- if (dis_syslink(theInstr)) break;
+ if (dis_syslink(theInstr)) {
+ whatNext = Dis_StopHere;
+ break;
+ }
+ goto decode_failure;
+
+ /*
+ Trap Instructions
+ */
+ case 0x03: // twi
+ DIP("trap op (twi) => not implemented\n");
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)) {
+ if (dis_branch(theInstr)) {
whatNext = Dis_StopHere;
break;
}
- goto decode_failure;
/*
Memory Synchronization Instructions
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;
+
default:
goto decode_failure;
}