|
From: <sv...@va...> - 2012-12-12 00:16:56
|
sewardj 2012-12-12 00:16:41 +0000 (Wed, 12 Dec 2012)
New Revision: 2588
Log:
Support the UMAAL instruction. (n-i-bz). Based on a patch from
Torbjorn Granlund, tg...@gm....
Modified files:
trunk/priv/guest_arm_toIR.c
trunk/priv/host_arm_isel.c
Modified: trunk/priv/guest_arm_toIR.c (+72 -0)
===================================================================
--- trunk/priv/guest_arm_toIR.c 2012-12-11 04:09:43 +00:00 (rev 2587)
+++ trunk/priv/guest_arm_toIR.c 2012-12-12 00:16:41 +00:00 (rev 2588)
@@ -13841,6 +13841,44 @@
/* fall through */
}
+ // UMAAL
+ if (BITS8(0,0,0,0,0,1,0,0) == INSN(27,20) && INSN(7,4) == BITS4(1,0,0,1)) {
+ UInt rDhi = INSN(19,16);
+ UInt rDlo = INSN(15,12);
+ UInt rM = INSN(11,8);
+ UInt rN = INSN(3,0);
+ if (rDlo == 15 || rDhi == 15 || rN == 15 || rM == 15 || rDhi == rDlo) {
+ /* Unpredictable; don't decode; fall through */
+ } else {
+ IRTemp argN = newTemp(Ity_I32);
+ IRTemp argM = newTemp(Ity_I32);
+ IRTemp argDhi = newTemp(Ity_I32);
+ IRTemp argDlo = newTemp(Ity_I32);
+ IRTemp res = newTemp(Ity_I64);
+ IRTemp resHi = newTemp(Ity_I32);
+ IRTemp resLo = newTemp(Ity_I32);
+ assign( argN, getIRegA(rN) );
+ assign( argM, getIRegA(rM) );
+ assign( argDhi, getIRegA(rDhi) );
+ assign( argDlo, getIRegA(rDlo) );
+ assign( res,
+ binop(Iop_Add64,
+ binop(Iop_Add64,
+ binop(Iop_MullU32, mkexpr(argN), mkexpr(argM)),
+ unop(Iop_32Uto64, mkexpr(argDhi))),
+ unop(Iop_32Uto64, mkexpr(argDlo))) );
+ assign( resHi, unop(Iop_64HIto32, mkexpr(res)) );
+ assign( resLo, unop(Iop_64to32, mkexpr(res)) );
+ // now update guest state
+ putIRegA( rDhi, mkexpr(resHi), condT, Ijk_Boring );
+ putIRegA( rDlo, mkexpr(resLo), condT, Ijk_Boring );
+ DIP("umaal %s r%u, r%u, r%u, r%u\n",
+ nCC(INSN_COND), rDlo, rDhi, rN, rM);
+ goto decode_success;
+ }
+ /* fall through */
+ }
+
/* --------------------- Msr etc --------------------- */
// MSR apsr, #imm
@@ -18251,6 +18289,40 @@
}
}
+ /* ------------------ (T1) UMAAL ------------------ */
+ if (INSN0(15,4) == 0xFBE && INSN1(7,4) == BITS4(0,1,1,0)) {
+ UInt rN = INSN0(3,0);
+ UInt rDlo = INSN1(15,12);
+ UInt rDhi = INSN1(11,8);
+ UInt rM = INSN1(3,0);
+ if (!isBadRegT(rDlo) && !isBadRegT(rDhi) && !isBadRegT(rN)
+ && !isBadRegT(rM) && rDhi != rDlo) {
+ IRTemp argN = newTemp(Ity_I32);
+ IRTemp argM = newTemp(Ity_I32);
+ IRTemp argDhi = newTemp(Ity_I32);
+ IRTemp argDlo = newTemp(Ity_I32);
+ IRTemp res = newTemp(Ity_I64);
+ IRTemp resHi = newTemp(Ity_I32);
+ IRTemp resLo = newTemp(Ity_I32);
+ assign( argN, getIRegT(rN) );
+ assign( argM, getIRegT(rM) );
+ assign( argDhi, getIRegT(rDhi) );
+ assign( argDlo, getIRegT(rDlo) );
+ assign( res,
+ binop(Iop_Add64,
+ binop(Iop_Add64,
+ binop(Iop_MullU32, mkexpr(argN), mkexpr(argM)),
+ unop(Iop_32Uto64, mkexpr(argDhi))),
+ unop(Iop_32Uto64, mkexpr(argDlo))) );
+ assign( resHi, unop(Iop_64HIto32, mkexpr(res)) );
+ assign( resLo, unop(Iop_64to32, mkexpr(res)) );
+ putIRegT( rDhi, mkexpr(resHi), condT );
+ putIRegT( rDlo, mkexpr(resLo), condT );
+ DIP("umaal r%u, r%u, r%u, r%u\n", rDlo, rDhi, rN, rM);
+ goto decode_success;
+ }
+ }
+
/* ------------------ (T2) ADR ------------------ */
if ((INSN0(15,0) == 0xF2AF || INSN0(15,0) == 0xF6AF)
&& INSN1(15,15) == 0) {
Modified: trunk/priv/host_arm_isel.c (+10 -0)
===================================================================
--- trunk/priv/host_arm_isel.c 2012-12-11 04:09:43 +00:00 (rev 2587)
+++ trunk/priv/host_arm_isel.c 2012-12-12 00:16:41 +00:00 (rev 2588)
@@ -3085,6 +3085,16 @@
if (e->tag == Iex_Unop) {
switch (e->Iex.Unop.op) {
+ /* 32Uto64 */
+ case Iop_32Uto64: {
+ HReg rLo = iselIntExpr_R(env, e->Iex.Unop.arg);
+ HReg rHi = newVRegI(env);
+ HReg res = newVRegD(env);
+ addInstr(env, ARMInstr_Imm32(rHi, 0));
+ addInstr(env, ARMInstr_VXferD(True/*toD*/, res, rHi, rLo));
+ return res;
+ }
+
/* ReinterpF64asI64 */
case Iop_ReinterpF64asI64:
/* Left64(e) */
|