|
From: <sv...@va...> - 2013-04-19 12:31:44
|
petarj 2013-04-19 13:35:00 +0100 (Fri, 19 Apr 2013)
New Revision: 2709
Log:
mips: fix endian issues for LWL, LWR, LDR and LDL for mips64
This change:
- fixes endian issues for unaligned loads for MIPS64,
- (re)moves endian dependencies in guest-to-IR for Iop_ReinterpI32asF32
and Iop_ReinterpI64asF64 to host-mips-isel,
- adds minor style changes in the area touched by the code.
Modified files:
trunk/priv/guest_mips_toIR.c
trunk/priv/host_mips_defs.c
trunk/priv/host_mips_isel.c
Modified: trunk/priv/host_mips_defs.c (+54 -9)
===================================================================
--- trunk/priv/host_mips_defs.c 2013-04-18 12:50:58 +01:00 (rev 2708)
+++ trunk/priv/host_mips_defs.c 2013-04-19 13:35:00 +01:00 (rev 2709)
@@ -2734,11 +2734,13 @@
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) {
@@ -2778,6 +2780,49 @@
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)
{
@@ -3382,7 +3427,7 @@
}
/* 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);
@@ -4066,16 +4111,16 @@
*/
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 */
Modified: trunk/priv/guest_mips_toIR.c (+62 -43)
===================================================================
--- trunk/priv/guest_mips_toIR.c 2013-04-18 12:50:58 +01:00 (rev 2708)
+++ trunk/priv/guest_mips_toIR.c 2013-04-19 13:35:00 +01:00 (rev 2709)
@@ -72,6 +72,10 @@
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 ---*/
/*------------------------------------------------------------*/
@@ -1163,13 +1167,8 @@
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)));
@@ -1206,13 +1205,8 @@
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
}
}
@@ -1895,7 +1889,7 @@
}
/*------------------------------------------------------------*/
-/*--- Disassemble a single instruction ---*/
+/*--- Disassemble a single instruction ---*/
/*------------------------------------------------------------*/
/* Disassemble a single instruction into IR. The instruction is
@@ -2360,23 +2354,17 @@
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:
@@ -3239,7 +3227,7 @@
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;
@@ -3249,7 +3237,7 @@
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;
}
@@ -3615,38 +3603,54 @@
break;
case 0x22: /* LWL */
-
DIP("lwl r%d, %d(r%d)", rt, imm, rs);
if (mode64) {
/* t1 = addr */
+ t1 = newTemp(Ity_I64);
#if defined (_MIPSEL)
- t1 = newTemp(Ity_I64);
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);
@@ -3658,7 +3662,7 @@
#endif
/* t2 = word addr */
- /* t4 = addr mod 4 */
+ /* t4 = addr mod 8 */
LWX_SWX_PATTERN;
/* t3 = word content - shifted */
@@ -3678,36 +3682,51 @@
break;
case 0x26: /* LWR */
-
DIP("lwr r%d, %d(r%d)", rt, imm, rs);
if (mode64) {
/* t1 = addr */
+ t1 = newTemp(Ity_I64);
#if defined (_MIPSEL)
- t1 = newTemp(Ity_I64);
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);
@@ -3798,7 +3817,7 @@
#endif
/* t2 = word addr */
- /* t4 = addr mod 4 */
+ /* t4 = addr mod 8 */
LWX_SWX_PATTERN64_1;
/* t3 = rt content - shifted */
@@ -4549,7 +4568,7 @@
}
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))
@@ -6102,7 +6121,7 @@
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 */
@@ -6138,11 +6157,11 @@
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 */
Modified: trunk/priv/host_mips_isel.c (+13 -2)
===================================================================
--- trunk/priv/host_mips_isel.c 2013-04-18 12:50:58 +01:00 (rev 2708)
+++ trunk/priv/host_mips_isel.c 2013-04-19 13:35:00 +01:00 (rev 2709)
@@ -1,6 +1,6 @@
/*---------------------------------------------------------------*/
-/*--- begin host_mips_isel.c ---*/
+/*--- begin host_mips_isel.c ---*/
/*---------------------------------------------------------------*/
/*
@@ -359,8 +359,13 @@
am_addr1 = MIPSAMode_IR(4, StackPointer(mode64));
/* store hi,lo as Ity_I32's */
+#if defined (_MIPSEL)
addInstr(env, MIPSInstr_Store(4, am_addr0, r_srcLo, mode64));
addInstr(env, MIPSInstr_Store(4, am_addr1, r_srcHi, mode64));
+#elif defined (_MIPSEB)
+ addInstr(env, MIPSInstr_Store(4, am_addr0, r_srcHi, mode64));
+ addInstr(env, MIPSInstr_Store(4, am_addr1, r_srcLo, mode64));
+#endif
/* load as float */
addInstr(env, MIPSInstr_FpLdSt(True /*load */ , 8, fr_dst, am_addr0));
@@ -2317,9 +2322,15 @@
addInstr(env, MIPSInstr_FpLdSt(False /*store */ , 8, fr_src,
am_addr));
/* load as 2xI32 */
+#if defined (_MIPSEL)
addInstr(env, MIPSInstr_Load(4, tLo, am_addr, mode64));
addInstr(env, MIPSInstr_Load(4, tHi, nextMIPSAModeFloat(am_addr),
mode64));
+#elif defined (_MIPSEB)
+ addInstr(env, MIPSInstr_Load(4, tHi, am_addr, mode64));
+ addInstr(env, MIPSInstr_Load(4, tLo, nextMIPSAModeFloat(am_addr),
+ mode64));
+#endif
/* Reset SP */
add_to_sp(env, 16);
@@ -2436,7 +2447,7 @@
HReg r_dst = newVRegF(env);
/* Move Doubleword to Floating Point
- dmtc1 r_dst, valS */
+ dmtc1 r_dst, fr_src */
addInstr(env, MIPSInstr_FpGpMove(MFpGpMove_dmtc1, r_dst, fr_src));
return r_dst;
|