disInstr_MIPS below. */
static Bool mode64 = False;
+/* Define 1.0 in single and double precision. */
+#define ONE_SINGLE 0x3F800000
+#define ONE_DOUBLE 0x3FF0000000000000ULL
+
/*------------------------------------------------------------*/
/*--- Debugging output ---*/
/*------------------------------------------------------------*/
IRTemp t4 = newTemp(Ity_I32);
IRTemp t5 = newTemp(Ity_I64);
-#if defined (_MIPSEL)
assign(t0, getFReg(dregNo));
assign(t1, getFReg(dregNo + 1));
-#elif defined (_MIPSEB)
- assign(t0, getFReg(dregNo + 1));
- assign(t1, getFReg(dregNo));
-#endif
assign(t3, unop(Iop_ReinterpF32asI32, mkexpr(t0)));
assign(t4, unop(Iop_ReinterpF32asI32, mkexpr(t1)));
assign(t6, unop(Iop_ReinterpF64asI64, mkexpr(t1)));
assign(t4, unop(Iop_64HIto32, mkexpr(t6))); /* hi */
assign(t5, unop(Iop_64to32, mkexpr(t6))); /* lo */
-#if defined (_MIPSEL)
putFReg(dregNo, unop(Iop_ReinterpI32asF32, mkexpr(t5)));
putFReg(dregNo + 1, unop(Iop_ReinterpI32asF32, mkexpr(t4)));
-#elif defined (_MIPSEB)
- putFReg(dregNo + 1, unop(Iop_ReinterpI32asF32, mkexpr(t5)));
- putFReg(dregNo, unop(Iop_ReinterpI32asF32, mkexpr(t4)));
-#endif
}
}
}
/*------------------------------------------------------------*/
-/*--- Disassemble a single instruction ---*/
+/*--- Disassemble a single instruction ---*/
/*------------------------------------------------------------*/
/* Disassemble a single instruction into IR. The instruction is
IRExpr *rm = get_IR_roundingmode();
putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32,
rm, unop(Iop_ReinterpI32asF32,
- mkU32(0x3F800000)), getLoFromF64(tyF,
+ mkU32(ONE_SINGLE)), getLoFromF64(tyF,
getFReg(fs)))));
break;
}
case 0x11: { /* D */
DIP("recip.d f%d, f%d\n", fd, fs);
-#if defined (_MIPSEL)
- IRExpr *rm = get_IR_roundingmode();
- putDReg(fd, triop(Iop_DivF64, rm,
- unop(Iop_ReinterpI64asF64,
- mkU64(0x3FF0000000000000ULL)), getDReg(fs)));
-#elif defined (_MIPSEB)
IRExpr *rm = get_IR_roundingmode();
+ /* putDReg(fd, 1.0/getDreg(fs)); */
putDReg(fd, triop(Iop_DivF64, rm,
unop(Iop_ReinterpI64asF64,
- mkU64(0x000000003FF00000ULL)), getDReg(fs)));
-#endif
+ mkU64(ONE_DOUBLE)), getDReg(fs)));
break;
}
default:
DIP("rsqrt.s %d, %d\n", fd, fs);
IRExpr *rm = get_IR_roundingmode();
putFReg(fd, mkWidenFromF32(tyF, triop(Iop_DivF32, rm,
- unop(Iop_ReinterpI32asF32, mkU32(0x3F800000)),
+ unop(Iop_ReinterpI32asF32, mkU32(ONE_SINGLE)),
binop(Iop_SqrtF32, rm, getLoFromF64(tyF,
getFReg(fs))))));
break;
IRExpr *rm = get_IR_roundingmode();
putDReg(fd, triop(Iop_DivF64, rm,
unop(Iop_ReinterpI64asF64,
- mkU64(0x3FF0000000000000ULL)),
+ mkU64(ONE_DOUBLE)),
binop(Iop_SqrtF64, rm, getDReg(fs))));
break;
}
break;
case 0x22: /* LWL */
-
DIP("lwl r%d, %d(r%d)", rt, imm, rs);
if (mode64) {
/* t1 = addr */
-#if defined (_MIPSEL)
t1 = newTemp(Ity_I64);
+#if defined (_MIPSEL)
assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
+ /* t2 = word addr */
+ /* t4 = addr mod 4 */
+ LWX_SWX_PATTERN64;
+
+ /* t3 = word content - shifted */
+ t3 = newTemp(Ity_I32);
+ assign(t3, binop(Iop_Shl32, mkNarrowTo32(ty, load(Ity_I64,
+ mkexpr(t2))), narrowTo(Ity_I8, binop(Iop_Shl32,
+ binop(Iop_Sub32, mkU32(0x03), mkexpr(t4)), mkU8(3)))));
+
+ /* rt content - adjusted */
+ t5 = newTemp(Ity_I32);
+ assign(t5, binop(Iop_And32, mkNarrowTo32(ty, getIReg(rt)),
+ binop(Iop_Shr32, mkU32(0xFFFFFFFF), narrowTo(Ity_I8,
+ binop(Iop_Shl32, binop(Iop_Add32, mkexpr(t4), mkU32(0x1)),
+ mkU8(0x3))))));
+
+ putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t5),
+ mkexpr(t3)), True));
#elif defined (_MIPSEB)
- t1 = newTemp(Ity_I64);
assign(t1, binop(Iop_Xor64, mkU64(0x3),
binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm)))));
-#endif
-
/* t2 = word addr */
/* t4 = addr mod 4 */
LWX_SWX_PATTERN64;
/* t3 = word content - shifted */
t3 = newTemp(Ity_I32);
- assign(t3, binop(Iop_Shl32, mkNarrowTo32(ty, load(Ity_I64,
+ assign(t3, binop(Iop_Shl32, unop(Iop_64HIto32, load(Ity_I64,
mkexpr(t2))), narrowTo(Ity_I8, binop(Iop_Shl32,
binop(Iop_Sub32, mkU32(0x03), mkexpr(t4)), mkU8(3)))));
- /* rt content - adjusted */
+ /* rt content - adjusted */
t5 = newTemp(Ity_I32);
- assign(t5, binop(Iop_And32, mkNarrowTo32(ty, getIReg(rt)),
+ assign(t5, binop(Iop_And32, unop(Iop_64HIto32, getIReg(rt)),
binop(Iop_Shr32, mkU32(0xFFFFFFFF), narrowTo(Ity_I8,
binop(Iop_Shl32, binop(Iop_Add32, mkexpr(t4), mkU32(0x1)),
mkU8(0x3))))));
putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t5),
mkexpr(t3)), True));
+#endif
} else {
/* t1 = addr */
t1 = newTemp(Ity_I32);
#endif
/* t2 = word addr */
- /* t4 = addr mod 4 */
+ /* t4 = addr mod 8 */
LWX_SWX_PATTERN;
/* t3 = word content - shifted */
break;
case 0x26: /* LWR */
-
DIP("lwr r%d, %d(r%d)", rt, imm, rs);
if (mode64) {
/* t1 = addr */
-#if defined (_MIPSEL)
t1 = newTemp(Ity_I64);
+#if defined (_MIPSEL)
assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
+ /* t2 = word addr */
+ /* t4 = addr mod 8 */
+ LWX_SWX_PATTERN64;
+
+ /* t3 = word content - shifted */
+ t3 = newTemp(Ity_I32);
+ assign(t3, binop(Iop_Shr32, mkNarrowTo32(ty, load(Ity_I64,mkexpr(t2))),
+ narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4), mkU8(3)))));
+
+ /* rt content - adjusted */
+ t5 = newTemp(Ity_I32);
+ assign(t5, binop(Iop_And32, mkNarrowTo32(ty, getIReg(rt)),
+ unop(Iop_Not32, binop(Iop_Shr32, mkU32(0xFFFFFFFF),
+ narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4), mkU8(0x3)))))));
+
+ putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t5),
+ mkexpr(t3)), True));
#elif defined (_MIPSEB)
- t1 = newTemp(Ity_I64);
assign(t1, binop(Iop_Xor64, mkU64(0x3), binop(Iop_Add64, getIReg(rs),
mkU64(extend_s_16to64(imm)))));
-#endif
-
/* t2 = word addr */
/* t4 = addr mod 4 */
LWX_SWX_PATTERN64;
/* t3 = word content - shifted */
t3 = newTemp(Ity_I32);
- assign(t3, binop(Iop_Shr32, mkNarrowTo32(ty, load(Ity_I64,mkexpr(t2))),
+ assign(t3, binop(Iop_Shr32, unop(Iop_64HIto32, load(Ity_I64,mkexpr(t2))),
narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4), mkU8(3)))));
/* rt content - adjusted */
t5 = newTemp(Ity_I32);
- assign(t5, binop(Iop_And32, mkNarrowTo32(ty, getIReg(rt)),
+ assign(t5, binop(Iop_And32, unop(Iop_64HIto32, getIReg(rt)),
unop(Iop_Not32, binop(Iop_Shr32, mkU32(0xFFFFFFFF),
narrowTo(Ity_I8, binop(Iop_Shl32, mkexpr(t4), mkU8(0x3)))))));
putIReg(rt, mkWidenFrom32(ty, binop(Iop_Or32, mkexpr(t5),
mkexpr(t3)), True));
+#endif
+
} else {
/* t1 = addr */
t1 = newTemp(Ity_I32);
#endif
/* t2 = word addr */
- /* t4 = addr mod 4 */
+ /* t4 = addr mod 8 */
LWX_SWX_PATTERN64_1;
/* t3 = rt content - shifted */
}
break;
case 0x3B: { /* RDHWR */
- DIP("rdhwr r%d, r%d\n", rt, rd);
+ DIP("rdhwr r%d, r%d", rt, rd);
if (rd == 29) {
putIReg(rt, getULR());
#if defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev >= 2))
mkU64(extend_s_16to64(imm)))));
#endif
/* t2 = word addr */
- /* t4 = addr mod 4 */
+ /* t4 = addr mod 8 */
LWX_SWX_PATTERN64_1;
/* t3 = word content - shifted */
assign(t1, binop(Iop_Add64, getIReg(rs), mkU64(extend_s_16to64(imm))));
#elif defined (_MIPSEB)
t1 = newTemp(Ity_I64);
- assign(t1, binop(Iop_Xor64, mkU64(0x3), binop(Iop_Add64, getIReg(rs),
+ assign(t1, binop(Iop_Xor64, mkU64(0x7), binop(Iop_Add64, getIReg(rs),
mkU64(extend_s_16to64(imm)))));
#endif
/* t2 = word addr */
- /* t4 = addr mod 4 */
+ /* t4 = addr mod 8 */
LWX_SWX_PATTERN64_1;
/* t3 = word content - shifted */
return ret;
}
-/* Generate a machine-word sized load or store. Simplified version of
- the Min_Load and Min_Store cases below. */
-static UChar* do_load_or_store_machine_word (
- UChar* p, Bool isLoad,
- UInt reg, MIPSAMode* am, Bool mode64 )
+/* Generate a machine-word sized load or store. Simplified version of
+ the Min_Load and Min_Store cases below.
+ This will generate 32-bit load/store on MIPS32, and 64-bit load/store on
+ MIPS64 platforms.
+*/
+static UChar* do_load_or_store_machine_word ( UChar* p, Bool isLoad, UInt reg,
+ MIPSAMode* am, Bool mode64 )
{
if (isLoad) { /* load */
switch (am->tag) {
return p;
}
+/* Generate a 32-bit sized load or store. Simplified version of
+ do_load_or_store_machine_word above. */
+static UChar* do_load_or_store_word32 ( UChar* p, Bool isLoad, UInt reg,
+ MIPSAMode* am, Bool mode64 )
+{
+ if (isLoad) { /* load */
+ switch (am->tag) {
+ case Mam_IR:
+ if (mode64) {
+ vassert(0 == (am->Mam.IR.index & 3));
+ }
+ p = doAMode_IR(p, 35, reg, am, mode64);
+ break;
+ case Mam_RR:
+ /* we could handle this case, but we don't expect to ever
+ need to. */
+ vassert(0);
+ break;
+ default:
+ vassert(0);
+ break;
+ }
+ } else /* store */ {
+ switch (am->tag) {
+ case Mam_IR:
+ if (mode64) {
+ vassert(0 == (am->Mam.IR.index & 3));
+ }
+ p = doAMode_IR(p, 43, reg, am, mode64);
+ break;
+ case Mam_RR:
+ /* we could handle this case, but we don't expect to ever
+ need to. */
+ vassert(0);
+ break;
+ default:
+ vassert(0);
+ break;
+ }
+ }
+ return p;
+}
+
/* Move r_dst to r_src */
static UChar *mkMoveReg(UChar * p, UInt r_dst, UInt r_src)
{
}
/* Update the guest PC. */
- /* sw r-dstGA, amPC */
+ /* sw/sd r-dstGA, amPC */
p = do_load_or_store_machine_word(p, False /*!isLoad*/ ,
iregNo(i->Min.XIndir.dstGA, mode64),
i->Min.XIndir.amPC, mode64);
*/
UChar* p0 = p;
/* lw r9, amCounter */
- p = do_load_or_store_machine_word(p, True /*isLoad*/ , /*r*/ 9,
+ p = do_load_or_store_word32(p, True /*isLoad*/ , /*r*/ 9,
i->Min.EvCheck.amCounter, mode64);
/* addiu r9,r9,-1 */
p = mkFormI(p, 9, 9, 9, 0xFFFF);
/* sw r30, amCounter */
- p = do_load_or_store_machine_word(p, False /*!isLoad*/ , /*r*/ 9,
+ p = do_load_or_store_word32(p, False /*!isLoad*/ , /*r*/ 9,
i->Min.EvCheck.amCounter, mode64);
/* bgez t9, nofail */
p = mkFormI(p, 1, 9, 1, 3);
- /* lw r9, amFailAddr */
+ /* lw/ld r9, amFailAddr */
p = do_load_or_store_machine_word(p, True /*isLoad*/ , /*r*/ 9,
i->Min.EvCheck.amFailAddr, mode64);
/* jalr $9 */