/* fall through */
}
- /////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////
-
/* ------------------- qsax<c> <Rd>,<Rn>,<Rm> ------------------- */
/* note: the hardware seems to construct the result differently
from wot the manual says. */
}
}
- if (gate) {
- IRTemp rNt = newTemp(Ity_I32);
- IRTemp rMt = newTemp(Ity_I32);
- IRTemp res_q = newTemp(Ity_I32);
+ if (gate) {
+ IRTemp rNt = newTemp(Ity_I32);
+ IRTemp rMt = newTemp(Ity_I32);
+ IRTemp res_q = newTemp(Ity_I32);
+
+ assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
+ assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
+
+ assign(res_q, binop(Iop_QAdd32S, mkexpr(rMt), mkexpr(rNt)));
+ if (isT)
+ putIRegT( regD, mkexpr(res_q), condT );
+ else
+ putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
+
+ or_into_QFLAG32(
+ signed_overflow_after_Add32(
+ binop(Iop_Add32, mkexpr(rMt), mkexpr(rNt)), rMt, rNt),
+ condT
+ );
+
+ DIP("qadd%s r%u, r%u, r%u\n", nCC(conq),regD,regM,regN);
+ return True;
+ }
+ /* fall through */
+ }
+
+ /* ------------------ qdadd<c> <Rd>,<Rm>,<Rn> ------------------- */
+ {
+ UInt regD = 99, regN = 99, regM = 99;
+ Bool gate = False;
+
+ if (isT) {
+ if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF090) {
+ regN = INSNT0(3,0);
+ regD = INSNT1(11,8);
+ regM = INSNT1(3,0);
+ if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
+ gate = True;
+ }
+ } else {
+ if (INSNA(27,20) == BITS8(0,0,0,1,0,1,0,0) &&
+ INSNA(11,8) == BITS4(0,0,0,0) &&
+ INSNA(7,4) == BITS4(0,1,0,1)) {
+ regD = INSNA(15,12);
+ regN = INSNA(19,16);
+ regM = INSNA(3,0);
+ if (regD != 15 && regN != 15 && regM != 15)
+ gate = True;
+ }
+ }
+
+ if (gate) {
+ IRTemp rNt = newTemp(Ity_I32);
+ IRTemp rMt = newTemp(Ity_I32);
+ IRTemp rN_d = newTemp(Ity_I32);
+ IRTemp res_q = newTemp(Ity_I32);
+
+ assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
+ assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
+
+ or_into_QFLAG32(
+ signed_overflow_after_Add32(
+ binop(Iop_Add32, mkexpr(rNt), mkexpr(rNt)), rNt, rNt),
+ condT
+ );
+
+ assign(rN_d, binop(Iop_QAdd32S, mkexpr(rNt), mkexpr(rNt)));
+ assign(res_q, binop(Iop_QAdd32S, mkexpr(rMt), mkexpr(rN_d)));
+ if (isT)
+ putIRegT( regD, mkexpr(res_q), condT );
+ else
+ putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
+
+ or_into_QFLAG32(
+ signed_overflow_after_Add32(
+ binop(Iop_Add32, mkexpr(rMt), mkexpr(rN_d)), rMt, rN_d),
+ condT
+ );
+
+ DIP("qdadd%s r%u, r%u, r%u\n", nCC(conq),regD,regM,regN);
+ return True;
+ }
+ /* fall through */
+ }
+
+ /* ------------------ qsub<c> <Rd>,<Rn>,<Rm> ------------------- */
+ {
+ UInt regD = 99, regN = 99, regM = 99;
+ Bool gate = False;
+
+ if (isT) {
+ if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF0A0) {
+ regN = INSNT0(3,0);
+ regD = INSNT1(11,8);
+ regM = INSNT1(3,0);
+ if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
+ gate = True;
+ }
+ } else {
+ if (INSNA(27,20) == BITS8(0,0,0,1,0,0,1,0) &&
+ INSNA(11,8) == BITS4(0,0,0,0) &&
+ INSNA(7,4) == BITS4(0,1,0,1)) {
+ regD = INSNA(15,12);
+ regN = INSNA(19,16);
+ regM = INSNA(3,0);
+ if (regD != 15 && regN != 15 && regM != 15)
+ gate = True;
+ }
+ }
+
+ if (gate) {
+ IRTemp rNt = newTemp(Ity_I32);
+ IRTemp rMt = newTemp(Ity_I32);
+ IRTemp res_q = newTemp(Ity_I32);
+
+ assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
+ assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
+
+ assign(res_q, binop(Iop_QSub32S, mkexpr(rMt), mkexpr(rNt)));
+ if (isT)
+ putIRegT( regD, mkexpr(res_q), condT );
+ else
+ putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
+
+ or_into_QFLAG32(
+ signed_overflow_after_Sub32(
+ binop(Iop_Sub32, mkexpr(rMt), mkexpr(rNt)), rMt, rNt),
+ condT
+ );
+
+ DIP("qsub%s r%u, r%u, r%u\n", nCC(conq),regD,regM,regN);
+ return True;
+ }
+ /* fall through */
+ }
+
+ /* ------------------ qdsub<c> <Rd>,<Rm>,<Rn> ------------------- */
+ {
+ UInt regD = 99, regN = 99, regM = 99;
+ Bool gate = False;
+
+ if (isT) {
+ if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF0B0) {
+ regN = INSNT0(3,0);
+ regD = INSNT1(11,8);
+ regM = INSNT1(3,0);
+ if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
+ gate = True;
+ }
+ } else {
+ if (INSNA(27,20) == BITS8(0,0,0,1,0,1,1,0) &&
+ INSNA(11,8) == BITS4(0,0,0,0) &&
+ INSNA(7,4) == BITS4(0,1,0,1)) {
+ regD = INSNA(15,12);
+ regN = INSNA(19,16);
+ regM = INSNA(3,0);
+ if (regD != 15 && regN != 15 && regM != 15)
+ gate = True;
+ }
+ }
+
+ if (gate) {
+ IRTemp rNt = newTemp(Ity_I32);
+ IRTemp rMt = newTemp(Ity_I32);
+ IRTemp rN_d = newTemp(Ity_I32);
+ IRTemp res_q = newTemp(Ity_I32);
+
+ assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
+ assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
+
+ or_into_QFLAG32(
+ signed_overflow_after_Add32(
+ binop(Iop_Add32, mkexpr(rNt), mkexpr(rNt)), rNt, rNt),
+ condT
+ );
+
+ assign(rN_d, binop(Iop_QAdd32S, mkexpr(rNt), mkexpr(rNt)));
+ assign(res_q, binop(Iop_QSub32S, mkexpr(rMt), mkexpr(rN_d)));
+ if (isT)
+ putIRegT( regD, mkexpr(res_q), condT );
+ else
+ putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
+
+ or_into_QFLAG32(
+ signed_overflow_after_Sub32(
+ binop(Iop_Sub32, mkexpr(rMt), mkexpr(rN_d)), rMt, rN_d),
+ condT
+ );
+
+ DIP("qdsub%s r%u, r%u, r%u\n", nCC(conq),regD,regM,regN);
+ return True;
+ }
+ /* fall through */
+ }
+
+ /* ------------------ uqsub16<c> <Rd>,<Rn>,<Rm> ------------------ */
+ {
+ UInt regD = 99, regN = 99, regM = 99;
+ Bool gate = False;
+
+ if (isT) {
+ if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
+ regN = INSNT0(3,0);
+ regD = INSNT1(11,8);
+ regM = INSNT1(3,0);
+ if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
+ gate = True;
+ }
+ } else {
+ if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
+ INSNA(11,8) == BITS4(1,1,1,1) &&
+ INSNA(7,4) == BITS4(0,1,1,1)) {
+ regD = INSNA(15,12);
+ regN = INSNA(19,16);
+ regM = INSNA(3,0);
+ if (regD != 15 && regN != 15 && regM != 15)
+ gate = True;
+ }
+ }
+
+ if (gate) {
+ IRTemp rNt = newTemp(Ity_I32);
+ IRTemp rMt = newTemp(Ity_I32);
+ IRTemp res_q = newTemp(Ity_I32);
+
+ assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
+ assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
+
+ assign(res_q, binop(Iop_QSub16Ux2, mkexpr(rNt), mkexpr(rMt)));
+ if (isT)
+ putIRegT( regD, mkexpr(res_q), condT );
+ else
+ putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
+
+ DIP("uqsub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
+ return True;
+ }
+ /* fall through */
+ }
+
+ /* ----------------- shadd16<c> <Rd>,<Rn>,<Rm> ------------------- */
+ {
+ UInt regD = 99, regN = 99, regM = 99;
+ Bool gate = False;
+
+ if (isT) {
+ if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF020) {
+ regN = INSNT0(3,0);
+ regD = INSNT1(11,8);
+ regM = INSNT1(3,0);
+ if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
+ gate = True;
+ }
+ } else {
+ if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,1) &&
+ INSNA(11,8) == BITS4(1,1,1,1) &&
+ INSNA(7,4) == BITS4(0,0,0,1)) {
+ regD = INSNA(15,12);
+ regN = INSNA(19,16);
+ regM = INSNA(3,0);
+ if (regD != 15 && regN != 15 && regM != 15)
+ gate = True;
+ }
+ }
+
+ if (gate) {
+ IRTemp rNt = newTemp(Ity_I32);
+ IRTemp rMt = newTemp(Ity_I32);
+ IRTemp res_q = newTemp(Ity_I32);
+
+ assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
+ assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
+
+ assign(res_q, binop(Iop_HAdd16Sx2, mkexpr(rNt), mkexpr(rMt)));
+ if (isT)
+ putIRegT( regD, mkexpr(res_q), condT );
+ else
+ putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
+
+ DIP("shadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
+ return True;
+ }
+ /* fall through */
+ }
+
+ /* ----------------- uhsub8<c> <Rd>,<Rn>,<Rm> ------------------- */
+ {
+ UInt regD = 99, regN = 99, regM = 99;
+ Bool gate = False;
+
+ if (isT) {
+ if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
+ regN = INSNT0(3,0);
+ regD = INSNT1(11,8);
+ regM = INSNT1(3,0);
+ if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
+ gate = True;
+ }
+ } else {
+ if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
+ INSNA(11,8) == BITS4(1,1,1,1) &&
+ INSNA(7,4) == BITS4(1,1,1,1)) {
+ regD = INSNA(15,12);
+ regN = INSNA(19,16);
+ regM = INSNA(3,0);
+ if (regD != 15 && regN != 15 && regM != 15)
+ gate = True;
+ }
+ }
+
+ if (gate) {
+ IRTemp rNt = newTemp(Ity_I32);
+ IRTemp rMt = newTemp(Ity_I32);
+ IRTemp res_q = newTemp(Ity_I32);
+
+ assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
+ assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
+
+ assign(res_q, binop(Iop_HSub8Ux4, mkexpr(rNt), mkexpr(rMt)));
+ if (isT)
+ putIRegT( regD, mkexpr(res_q), condT );
+ else
+ putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
+
+ DIP("uhsub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
+ return True;
+ }
+ /* fall through */
+ }
+
+ /* ----------------- uhsub16<c> <Rd>,<Rn>,<Rm> ------------------- */
+ {
+ UInt regD = 99, regN = 99, regM = 99;
+ Bool gate = False;
+
+ if (isT) {
+ if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
+ regN = INSNT0(3,0);
+ regD = INSNT1(11,8);
+ regM = INSNT1(3,0);
+ if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
+ gate = True;
+ }
+ } else {
+ if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
+ INSNA(11,8) == BITS4(1,1,1,1) &&
+ INSNA(7,4) == BITS4(0,1,1,1)) {
+ regD = INSNA(15,12);
+ regN = INSNA(19,16);
+ regM = INSNA(3,0);
+ if (regD != 15 && regN != 15 && regM != 15)
+ gate = True;
+ }
+ }
+
+ if (gate) {
+ IRTemp rNt = newTemp(Ity_I32);
+ IRTemp rMt = newTemp(Ity_I32);
+ IRTemp res_q = newTemp(Ity_I32);
+
+ assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
+ assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
+
+ assign(res_q, binop(Iop_HSub16Ux2, mkexpr(rNt), mkexpr(rMt)));
+ if (isT)
+ putIRegT( regD, mkexpr(res_q), condT );
+ else
+ putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
+
+ DIP("uhsub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
+ return True;
+ }
+ /* fall through */
+ }
+
+ /* ------------------ uqadd16<c> <Rd>,<Rn>,<Rm> ------------------ */
+ {
+ UInt regD = 99, regN = 99, regM = 99;
+ Bool gate = False;
+
+ if (isT) {
+ if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
+ regN = INSNT0(3,0);
+ regD = INSNT1(11,8);
+ regM = INSNT1(3,0);
+ if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
+ gate = True;
+ }
+ } else {
+ if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
+ INSNA(11,8) == BITS4(1,1,1,1) &&
+ INSNA(7,4) == BITS4(0,0,0,1)) {
+ regD = INSNA(15,12);
+ regN = INSNA(19,16);
+ regM = INSNA(3,0);
+ if (regD != 15 && regN != 15 && regM != 15)
+ gate = True;
+ }
+ }
+
+ if (gate) {
+ IRTemp rNt = newTemp(Ity_I32);
+ IRTemp rMt = newTemp(Ity_I32);
+ IRTemp res_q = newTemp(Ity_I32);
+
+ assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
+ assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
+
+ assign(res_q, binop(Iop_QAdd16Ux2, mkexpr(rNt), mkexpr(rMt)));
+ if (isT)
+ putIRegT( regD, mkexpr(res_q), condT );
+ else
+ putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
+
+ DIP("uqadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
+ return True;
+ }
+ /* fall through */
+ }
+
+ /* ------------------- uqsax<c> <Rd>,<Rn>,<Rm> ------------------- */
+ {
+ UInt regD = 99, regN = 99, regM = 99;
+ Bool gate = False;
+
+ if (isT) {
+ if (INSNT0(15,4) == 0xFAE && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
+ regN = INSNT0(3,0);
+ regD = INSNT1(11,8);
+ regM = INSNT1(3,0);
+ if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
+ gate = True;
+ }
+ } else {
+ if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
+ INSNA(11,8) == BITS4(1,1,1,1) &&
+ INSNA(7,4) == BITS4(0,1,0,1)) {
+ regD = INSNA(15,12);
+ regN = INSNA(19,16);
+ regM = INSNA(3,0);
+ if (regD != 15 && regN != 15 && regM != 15)
+ gate = True;
+ }
+ }
+
+ if (gate) {
+ IRTemp irt_regN = newTemp(Ity_I32);
+ IRTemp irt_regM = newTemp(Ity_I32);
+ IRTemp irt_sum = newTemp(Ity_I32);
+ IRTemp irt_diff = newTemp(Ity_I32);
+ IRTemp irt_sum_res = newTemp(Ity_I32);
+ IRTemp irt_diff_res = newTemp(Ity_I32);
+
+ assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
+ assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
+
+ assign( irt_diff,
+ binop( Iop_Sub32,
+ binop( Iop_Shr32, mkexpr(irt_regN), mkU8(16) ),
+ binop( Iop_Shr32,
+ binop(Iop_Shl32, mkexpr(irt_regM), mkU8(16)),
+ mkU8(16) ) ) );
+ armUnsignedSatQ( &irt_diff_res, NULL, irt_diff, 0x10);
+
+ assign( irt_sum,
+ binop( Iop_Add32,
+ binop( Iop_Shr32,
+ binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ),
+ mkU8(16) ),
+ binop( Iop_Shr32, mkexpr(irt_regM), mkU8(16) )) );
+ armUnsignedSatQ( &irt_sum_res, NULL, irt_sum, 0x10 );
+
+ IRExpr* ire_result = binop( Iop_Or32,
+ binop( Iop_Shl32, mkexpr(irt_diff_res),
+ mkU8(16) ),
+ binop( Iop_And32, mkexpr(irt_sum_res),
+ mkU32(0xFFFF)) );
+
+ if (isT)
+ putIRegT( regD, ire_result, condT );
+ else
+ putIRegA( regD, ire_result, condT, Ijk_Boring );
+
+ DIP( "uqsax%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
+ return True;
+ }
+ /* fall through */
+ }
+
+ /* ------------------- uqasx<c> <Rd>,<Rn>,<Rm> ------------------- */
+ {
+ UInt regD = 99, regN = 99, regM = 99;
+ Bool gate = False;
+
+ if (isT) {
+ if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
+ regN = INSNT0(3,0);
+ regD = INSNT1(11,8);
+ regM = INSNT1(3,0);
+ if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
+ gate = True;
+ }
+ } else {
+ if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
+ INSNA(11,8) == BITS4(1,1,1,1) &&
+ INSNA(7,4) == BITS4(0,0,1,1)) {
+ regD = INSNA(15,12);
+ regN = INSNA(19,16);
+ regM = INSNA(3,0);
+ if (regD != 15 && regN != 15 && regM != 15)
+ gate = True;
+ }
+ }
+
+ if (gate) {
+ IRTemp irt_regN = newTemp(Ity_I32);
+ IRTemp irt_regM = newTemp(Ity_I32);
+ IRTemp irt_sum = newTemp(Ity_I32);
+ IRTemp irt_diff = newTemp(Ity_I32);
+ IRTemp irt_res_sum = newTemp(Ity_I32);
+ IRTemp irt_res_diff = newTemp(Ity_I32);
+
+ assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
+ assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
+
+ assign( irt_diff,
+ binop( Iop_Sub32,
+ binop( Iop_Shr32,
+ binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ),
+ mkU8(16) ),
+ binop( Iop_Shr32, mkexpr(irt_regM), mkU8(16) ) ) );
+ armUnsignedSatQ( &irt_res_diff, NULL, irt_diff, 0x10 );
+
+ assign( irt_sum,
+ binop( Iop_Add32,
+ binop( Iop_Shr32, mkexpr(irt_regN), mkU8(16) ),
+ binop( Iop_Shr32,
+ binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ),
+ mkU8(16) ) ) );
+ armUnsignedSatQ( &irt_res_sum, NULL, irt_sum, 0x10 );
+
+ IRExpr* ire_result
+ = binop( Iop_Or32,
+ binop( Iop_Shl32, mkexpr(irt_res_sum), mkU8(16) ),
+ binop( Iop_And32, mkexpr(irt_res_diff), mkU32(0xFFFF) ) );
+
+ if (isT)
+ putIRegT( regD, ire_result, condT );
+ else
+ putIRegA( regD, ire_result, condT, Ijk_Boring );
+
+ DIP( "uqasx%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
+ return True;
+ }
+ /* fall through */
+ }
+
+ /* ------------------- usax<c> <Rd>,<Rn>,<Rm> ------------------- */
+ {
+ UInt regD = 99, regN = 99, regM = 99;
+ Bool gate = False;
+
+ if (isT) {
+ if (INSNT0(15,4) == 0xFAE && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
+ regN = INSNT0(3,0);
+ regD = INSNT1(11,8);
+ regM = INSNT1(3,0);
+ if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
+ gate = True;
+ }
+ } else {
+ if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
+ INSNA(11,8) == BITS4(1,1,1,1) &&
+ INSNA(7,4) == BITS4(0,1,0,1)) {
+ regD = INSNA(15,12);
+ regN = INSNA(19,16);
+ regM = INSNA(3,0);
+ if (regD != 15 && regN != 15 && regM != 15)
+ gate = True;
+ }
+ }
+
+ if (gate) {
+ IRTemp irt_regN = newTemp(Ity_I32);
+ IRTemp irt_regM = newTemp(Ity_I32);
+ IRTemp irt_sum = newTemp(Ity_I32);
+ IRTemp irt_diff = newTemp(Ity_I32);
+
+ assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
+ assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
+
+ assign( irt_sum,
+ binop( Iop_Add32,
+ unop( Iop_16Uto32,
+ unop( Iop_32to16, mkexpr(irt_regN) )
+ ),
+ binop( Iop_Shr32, mkexpr(irt_regM), mkU8(16) ) ) );
+
+ assign( irt_diff,
+ binop( Iop_Sub32,
+ binop( Iop_Shr32, mkexpr(irt_regN), mkU8(16) ),
+ unop( Iop_16Uto32,
+ unop( Iop_32to16, mkexpr(irt_regM) )
+ )
+ )
+ );
+
+ IRExpr* ire_result
+ = binop( Iop_Or32,
+ binop( Iop_Shl32, mkexpr(irt_diff), mkU8(16) ),
+ binop( Iop_And32, mkexpr(irt_sum), mkU32(0xFFFF) ) );
+
+ IRTemp ge10 = newTemp(Ity_I32);
+ assign( ge10, IRExpr_ITE( binop( Iop_CmpLE32U,
+ mkU32(0x10000), mkexpr(irt_sum) ),
+ mkU32(1), mkU32(0) ) );
+ put_GEFLAG32( 0, 0, mkexpr(ge10), condT );
+ put_GEFLAG32( 1, 0, mkexpr(ge10), condT );
+
+ IRTemp ge32 = newTemp(Ity_I32);
+ assign(ge32, unop(Iop_Not32, mkexpr(irt_diff)));
+ put_GEFLAG32( 2, 31, mkexpr(ge32), condT );
+ put_GEFLAG32( 3, 31, mkexpr(ge32), condT );
+
+ if (isT)
+ putIRegT( regD, ire_result, condT );
+ else
+ putIRegA( regD, ire_result, condT, Ijk_Boring );
+
+ DIP( "usax%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
+ return True;
+ }
+ /* fall through */
+ }
+
+ /* ------------------- uasx<c> <Rd>,<Rn>,<Rm> ------------------- */
+ {
+ UInt regD = 99, regN = 99, regM = 99;
+ Bool gate = False;
+
+ if (isT) {
+ if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF040) {
+ regN = INSNT0(3,0);
+ regD = INSNT1(11,8);
+ regM = INSNT1(3,0);
+ if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
+ gate = True;
+ }
+ } else {
+ if (INSNA(27,20) == BITS8(0,1,1,0,0,1,0,1) &&
+ INSNA(11,8) == BITS4(1,1,1,1) &&
+ INSNA(7,4) == BITS4(0,0,1,1)) {
+ regD = INSNA(15,12);
+ regN = INSNA(19,16);
+ regM = INSNA(3,0);
+ if (regD != 15 && regN != 15 && regM != 15)
+ gate = True;
+ }
+ }
+
+ if (gate) {
+ IRTemp irt_regN = newTemp(Ity_I32);
+ IRTemp irt_regM = newTemp(Ity_I32);
+ IRTemp irt_sum = newTemp(Ity_I32);
+ IRTemp irt_diff = newTemp(Ity_I32);
+
+ assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
+ assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
+
+ assign( irt_diff,
+ binop( Iop_Sub32,
+ unop( Iop_16Uto32,
+ unop( Iop_32to16, mkexpr(irt_regN) )
+ ),
+ binop( Iop_Shr32, mkexpr(irt_regM), mkU8(16) ) ) );
+
+ assign( irt_sum,
+ binop( Iop_Add32,
+ binop( Iop_Shr32, mkexpr(irt_regN), mkU8(16) ),
+ unop( Iop_16Uto32,
+ unop( Iop_32to16, mkexpr(irt_regM) )
+ ) ) );
+
+ IRExpr* ire_result
+ = binop( Iop_Or32,
+ binop( Iop_Shl32, mkexpr(irt_sum), mkU8(16) ),
+ binop( Iop_And32, mkexpr(irt_diff), mkU32(0xFFFF) ) );
+
+ IRTemp ge10 = newTemp(Ity_I32);
+ assign(ge10, unop(Iop_Not32, mkexpr(irt_diff)));
+ put_GEFLAG32( 0, 31, mkexpr(ge10), condT );
+ put_GEFLAG32( 1, 31, mkexpr(ge10), condT );
+
+ IRTemp ge32 = newTemp(Ity_I32);
+ assign( ge32, IRExpr_ITE( binop( Iop_CmpLE32U,
+ mkU32(0x10000), mkexpr(irt_sum) ),
+ mkU32(1), mkU32(0) ) );
+ put_GEFLAG32( 2, 0, mkexpr(ge32), condT );
+ put_GEFLAG32( 3, 0, mkexpr(ge32), condT );
+
+ if (isT)
+ putIRegT( regD, ire_result, condT );
+ else
+ putIRegA( regD, ire_result, condT, Ijk_Boring );
+
+ DIP( "uasx%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
+ return True;
+ }
+ /* fall through */
+ }
+
+ /* ------------------- ssax<c> <Rd>,<Rn>,<Rm> ------------------- */
+ {
+ UInt regD = 99, regN = 99, regM = 99;
+ Bool gate = False;
+
+ if (isT) {
+ if (INSNT0(15,4) == 0xFAE && (INSNT1(15,0) & 0xF0F0) == 0xF000) {
+ regN = INSNT0(3,0);
+ regD = INSNT1(11,8);
+ regM = INSNT1(3,0);
+ if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
+ gate = True;
+ }
+ } else {
+ if (INSNA(27,20) == BITS8(0,1,1,0,0,0,0,1) &&
+ INSNA(11,8) == BITS4(1,1,1,1) &&
+ INSNA(7,4) == BITS4(0,1,0,1)) {
+ regD = INSNA(15,12);
+ regN = INSNA(19,16);
+ regM = INSNA(3,0);
+ if (regD != 15 && regN != 15 && regM != 15)
+ gate = True;
+ }
+ }
+
+ if (gate) {
+ IRTemp irt_regN = newTemp(Ity_I32);
+ IRTemp irt_regM = newTemp(Ity_I32);
+ IRTemp irt_sum = newTemp(Ity_I32);
+ IRTemp irt_diff = newTemp(Ity_I32);
+
+ assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
+ assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
+
+ assign( irt_sum,
+ binop( Iop_Add32,
+ binop( Iop_Sar32,
+ binop( Iop_Shl32, mkexpr(irt_regN), mkU8(16) ),
+ mkU8(16) ),
+ binop( Iop_Sar32, mkexpr(irt_regM), mkU8(16) ) ) );
+
+ assign( irt_diff,
+ binop( Iop_Sub32,
+ binop( Iop_Sar32, mkexpr(irt_regN), mkU8(16) ),
+ binop( Iop_Sar32,
+ binop( Iop_Shl32, mkexpr(irt_regM), mkU8(16) ),
+ mkU8(16) ) ) );
+
+ IRExpr* ire_result
+ = binop( Iop_Or32,
+ binop( Iop_Shl32, mkexpr(irt_diff), mkU8(16) ),
+ binop( Iop_And32, mkexpr(irt_sum), mkU32(0xFFFF) ) );
+
+ IRTemp ge10 = newTemp(Ity_I32);
+ assign(ge10, unop(Iop_Not32, mkexpr(irt_sum)));
+ put_GEFLAG32( 0, 31, mkexpr(ge10), condT );
+ put_GEFLAG32( 1, 31, mkexpr(ge10), condT );
- assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
- assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
+ IRTemp ge32 = newTemp(Ity_I32);
+ assign(ge32, unop(Iop_Not32, mkexpr(irt_diff)));
+ put_GEFLAG32( 2, 31, mkexpr(ge32), condT );
+ put_GEFLAG32( 3, 31, mkexpr(ge32), condT );
- assign(res_q, binop(Iop_QAdd32S, mkexpr(rMt), mkexpr(rNt)));
if (isT)
- putIRegT( regD, mkexpr(res_q), condT );
+ putIRegT( regD, ire_result, condT );
else
- putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
-
- or_into_QFLAG32(
- signed_overflow_after_Add32(
- binop(Iop_Add32, mkexpr(rMt), mkexpr(rNt)), rMt, rNt),
- condT
- );
+ putIRegA( regD, ire_result, condT, Ijk_Boring );
- DIP("qadd%s r%u, r%u, r%u\n", nCC(conq),regD,regM,regN);
+ DIP( "ssax%s r%u, r%u, r%u\n", nCC(conq), regD, regN, regM );
return True;
}
/* fall through */
}
- /* ------------------ qdadd<c> <Rd>,<Rm>,<Rn> ------------------- */
+ /* ----------------- shsub8<c> <Rd>,<Rn>,<Rm> ------------------- */
{
UInt regD = 99, regN = 99, regM = 99;
Bool gate = False;
if (isT) {
- if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF090) {
+ if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF020) {
regN = INSNT0(3,0);
regD = INSNT1(11,8);
regM = INSNT1(3,0);
gate = True;
}
} else {
- if (INSNA(27,20) == BITS8(0,0,0,1,0,1,0,0) &&
- INSNA(11,8) == BITS4(0,0,0,0) &&
- INSNA(7,4) == BITS4(0,1,0,1)) {
+ if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,1) &&
+ INSNA(11,8) == BITS4(1,1,1,1) &&
+ INSNA(7,4) == BITS4(1,1,1,1)) {
regD = INSNA(15,12);
regN = INSNA(19,16);
regM = INSNA(3,0);
if (gate) {
IRTemp rNt = newTemp(Ity_I32);
IRTemp rMt = newTemp(Ity_I32);
- IRTemp rN_d = newTemp(Ity_I32);
IRTemp res_q = newTemp(Ity_I32);
assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
- or_into_QFLAG32(
- signed_overflow_after_Add32(
- binop(Iop_Add32, mkexpr(rNt), mkexpr(rNt)), rNt, rNt),
- condT
- );
-
- assign(rN_d, binop(Iop_QAdd32S, mkexpr(rNt), mkexpr(rNt)));
- assign(res_q, binop(Iop_QAdd32S, mkexpr(rMt), mkexpr(rN_d)));
+ assign(res_q, binop(Iop_HSub8Sx4, mkexpr(rNt), mkexpr(rMt)));
if (isT)
putIRegT( regD, mkexpr(res_q), condT );
else
putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
- or_into_QFLAG32(
- signed_overflow_after_Add32(
- binop(Iop_Add32, mkexpr(rMt), mkexpr(rN_d)), rMt, rN_d),
- condT
- );
-
- DIP("qdadd%s r%u, r%u, r%u\n", nCC(conq),regD,regM,regN);
+ DIP("shsub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
return True;
}
/* fall through */
}
- /* ------------------ qsub<c> <Rd>,<Rn>,<Rm> ------------------- */
+ /* ----------------- sxtab16<c> Rd,Rn,Rm{,rot} ------------------ */
{
- UInt regD = 99, regN = 99, regM = 99;
+ UInt regD = 99, regN = 99, regM = 99, rotate = 99;
Bool gate = False;
if (isT) {
- if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF0A0) {
- regN = INSNT0(3,0);
- regD = INSNT1(11,8);
- regM = INSNT1(3,0);
+ if (INSNT0(15,4) == 0xFA2 && (INSNT1(15,0) & 0xF0C0) == 0xF080) {
+ regN = INSNT0(3,0);
+ regD = INSNT1(11,8);
+ regM = INSNT1(3,0);
+ rotate = INSNT1(5,4);
if (!isBadRegT(regD) && !isBadRegT(regN) && !isBadRegT(regM))
gate = True;
}
} else {
- if (INSNA(27,20) == BITS8(0,0,0,1,0,0,1,0) &&
- INSNA(11,8) == BITS4(0,0,0,0) &&
- INSNA(7,4) == BITS4(0,1,0,1)) {
- regD = INSNA(15,12);
- regN = INSNA(19,16);
- regM = INSNA(3,0);
+ if (INSNA(27,20) == BITS8(0,1,1,0,1,0,0,0) &&
+ INSNA(9,4) == BITS6(0,0,0,1,1,1) ) {
+ regD = INSNA(15,12);
+ regN = INSNA(19,16);
+ regM = INSNA(3,0);
+ rotate = INSNA(11,10);
if (regD != 15 && regN != 15 && regM != 15)
- gate = True;
+ gate = True;
}
}
if (gate) {
- IRTemp rNt = newTemp(Ity_I32);
- IRTemp rMt = newTemp(Ity_I32);
- IRTemp res_q = newTemp(Ity_I32);
+ IRTemp irt_regN = newTemp(Ity_I32);
+ assign( irt_regN, isT ? getIRegT(regN) : getIRegA(regN) );
- assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
- assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
+ IRTemp irt_regM = newTemp(Ity_I32);
+ assign( irt_regM, isT ? getIRegT(regM) : getIRegA(regM) );
+
+ IRTemp irt_rot = newTemp(Ity_I32);
+ assign( irt_rot, genROR32(irt_regM, 8 * rotate) );
+
+ /* FIXME Maybe we can write this arithmetic in shorter form. */
+ IRExpr* resLo
+ = binop(Iop_And32,
+ binop(Iop_Add32,
+ mkexpr(irt_regN),
+ unop(Iop_16Uto32,
+ unop(Iop_8Sto16,
+ unop(Iop_32to8, mkexpr(irt_rot))))),
+ mkU32(0x0000FFFF));
+
+ IRExpr* resHi
+ = binop(Iop_And32,
+ binop(Iop_Add32,
+ mkexpr(irt_regN),
+ binop(Iop_Shl32,
+ unop(Iop_16Uto32,
+ unop(Iop_8Sto16,
+ unop(Iop_32to8,
+ binop(Iop_Shr32,
+ mkexpr(irt_rot),
+ mkU8(16))))),
+ mkU8(16))),
+ mkU32(0xFFFF0000));
+
+ IRExpr* ire_result
+ = binop( Iop_Or32, resHi, resLo );
- assign(res_q, binop(Iop_QSub32S, mkexpr(rMt), mkexpr(rNt)));
if (isT)
- putIRegT( regD, mkexpr(res_q), condT );
+ putIRegT( regD, ire_result, condT );
else
- putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
-
- or_into_QFLAG32(
- signed_overflow_after_Sub32(
- binop(Iop_Sub32, mkexpr(rMt), mkexpr(rNt)), rMt, rNt),
- condT
- );
+ putIRegA( regD, ire_result, condT, Ijk_Boring );
- DIP("qsub%s r%u, r%u, r%u\n", nCC(conq),regD,regM,regN);
+ DIP( "sxtab16%s r%u, r%u, r%u, ROR #%u\n",
+ nCC(conq), regD, regN, regM, 8 * rotate );
return True;
}
/* fall through */
}
- /* ------------------ qdsub<c> <Rd>,<Rm>,<Rn> ------------------- */
+ /* ----------------- shasx<c> <Rd>,<Rn>,<Rm> ------------------- */
{
UInt regD = 99, regN = 99, regM = 99;
Bool gate = False;
if (isT) {
- if (INSNT0(15,4) == 0xFA8 && (INSNT1(15,0) & 0xF0F0) == 0xF0B0) {
+ if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF020) {
regN = INSNT0(3,0);
regD = INSNT1(11,8);
regM = INSNT1(3,0);
gate = True;
}
} else {
- if (INSNA(27,20) == BITS8(0,0,0,1,0,1,1,0) &&
- INSNA(11,8) == BITS4(0,0,0,0) &&
- INSNA(7,4) == BITS4(0,1,0,1)) {
+ if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,1) &&
+ INSNA(11,8) == BITS4(1,1,1,1) &&
+ INSNA(7,4) == BITS4(0,0,1,1)) {
regD = INSNA(15,12);
regN = INSNA(19,16);
regM = INSNA(3,0);
if (gate) {
IRTemp rNt = newTemp(Ity_I32);
IRTemp rMt = newTemp(Ity_I32);
- IRTemp rN_d = newTemp(Ity_I32);
+ IRTemp irt_diff = newTemp(Ity_I32);
+ IRTemp irt_sum = newTemp(Ity_I32);
IRTemp res_q = newTemp(Ity_I32);
assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
- or_into_QFLAG32(
- signed_overflow_after_Add32(
- binop(Iop_Add32, mkexpr(rNt), mkexpr(rNt)), rNt, rNt),
- condT
+ assign( irt_diff,
+ binop(Iop_Sub32,
+ unop(Iop_16Sto32,
+ unop(Iop_32to16,
+ mkexpr(rNt)
+ )
+ ),
+ unop(Iop_16Sto32,
+ unop(Iop_32to16,
+ binop(Iop_Shr32,
+ mkexpr(rMt), mkU8(16)
+ )
+ )
+ )
+ )
+ );
+
+ assign( irt_sum,
+ binop(Iop_Add32,
+ unop(Iop_16Sto32,
+ unop(Iop_32to16,
+ binop(Iop_Shr32,
+ mkexpr(rNt), mkU8(16)
+ )
+ )
+ ),
+ unop(Iop_16Sto32,
+ unop(Iop_32to16, mkexpr(rMt)
+ )
+ )
+ )
+ );
+
+ assign( res_q,
+ binop(Iop_Or32,
+ unop(Iop_16Uto32,
+ unop(Iop_32to16,
+ binop(Iop_Shr32,
+ mkexpr(irt_diff), mkU8(1)
+ )
+ )
+ ),
+ binop(Iop_Shl32,
+ binop(Iop_Shr32,
+ mkexpr(irt_sum), mkU8(1)
+ ),
+ mkU8(16)
+ )
+ )
);
- assign(rN_d, binop(Iop_QAdd32S, mkexpr(rNt), mkexpr(rNt)));
- assign(res_q, binop(Iop_QSub32S, mkexpr(rMt), mkexpr(rN_d)));
if (isT)
putIRegT( regD, mkexpr(res_q), condT );
else
putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
- or_into_QFLAG32(
- signed_overflow_after_Sub32(
- binop(Iop_Sub32, mkexpr(rMt), mkexpr(rN_d)), rMt, rN_d),
- condT
- );
-
- DIP("qdsub%s r%u, r%u, r%u\n", nCC(conq),regD,regM,regN);
+ DIP("shasx%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
return True;
}
/* fall through */
}
- /* ------------------ uqsub16<c> <Rd>,<Rn>,<Rm> ------------------ */
+ /* ----------------- uhasx<c> <Rd>,<Rn>,<Rm> ------------------- */
{
UInt regD = 99, regN = 99, regM = 99;
Bool gate = False;
if (isT) {
- if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF050) {
+ if (INSNT0(15,4) == 0xFAA && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
regN = INSNT0(3,0);
regD = INSNT1(11,8);
regM = INSNT1(3,0);
gate = True;
}
} else {
- if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,0) &&
+ if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
INSNA(11,8) == BITS4(1,1,1,1) &&
- INSNA(7,4) == BITS4(0,1,1,1)) {
+ INSNA(7,4) == BITS4(0,0,1,1)) {
regD = INSNA(15,12);
regN = INSNA(19,16);
regM = INSNA(3,0);
if (regD != 15 && regN != 15 && regM != 15)
- gate = True;
+ gate = True;
}
}
if (gate) {
IRTemp rNt = newTemp(Ity_I32);
IRTemp rMt = newTemp(Ity_I32);
+ IRTemp irt_diff = newTemp(Ity_I32);
+ IRTemp irt_sum = newTemp(Ity_I32);
IRTemp res_q = newTemp(Ity_I32);
assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
- assign(res_q, binop(Iop_QSub16Ux2, mkexpr(rNt), mkexpr(rMt)));
+ assign( irt_diff,
+ binop(Iop_Sub32,
+ unop(Iop_16Uto32,
+ unop(Iop_32to16,
+ mkexpr(rNt)
+ )
+ ),
+ unop(Iop_16Uto32,
+ unop(Iop_32to16,
+ binop(Iop_Shr32,
+ mkexpr(rMt), mkU8(16)
+ )
+ )
+ )
+ )
+ );
+
+ assign( irt_sum,
+ binop(Iop_Add32,
+ unop(Iop_16Uto32,
+ unop(Iop_32to16,
+ binop(Iop_Shr32,
+ mkexpr(rNt), mkU8(16)
+ )
+ )
+ ),
+ unop(Iop_16Uto32,
+ unop(Iop_32to16, mkexpr(rMt)
+ )
+ )
+ )
+ );
+
+ assign( res_q,
+ binop(Iop_Or32,
+ unop(Iop_16Uto32,
+ unop(Iop_32to16,
+ binop(Iop_Shr32,
+ mkexpr(irt_diff), mkU8(1)
+ )
+ )
+ ),
+ binop(Iop_Shl32,
+ binop(Iop_Shr32,
+ mkexpr(irt_sum), mkU8(1)
+ ),
+ mkU8(16)
+ )
+ )
+ );
+
if (isT)
putIRegT( regD, mkexpr(res_q), condT );
else
putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
- DIP("uqsub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
+ DIP("uhasx%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
return True;
}
/* fall through */
}
- /* ----------------- shadd16<c> <Rd>,<Rn>,<Rm> ------------------- */
+ /* ----------------- shsax<c> <Rd>,<Rn>,<Rm> ------------------- */
{
UInt regD = 99, regN = 99, regM = 99;
Bool gate = False;
if (isT) {
- if (INSNT0(15,4) == 0xFA9 && (INSNT1(15,0) & 0xF0F0) == 0xF020) {
+ if (INSNT0(15,4) == 0xFAE && (INSNT1(15,0) & 0xF0F0) == 0xF020) {
regN = INSNT0(3,0);
regD = INSNT1(11,8);
regM = INSNT1(3,0);
} else {
if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,1) &&
INSNA(11,8) == BITS4(1,1,1,1) &&
- INSNA(7,4) == BITS4(0,0,0,1)) {
+ INSNA(7,4) == BITS4(0,1,0,1)) {
regD = INSNA(15,12);
regN = INSNA(19,16);
regM = INSNA(3,0);
if (gate) {
IRTemp rNt = newTemp(Ity_I32);
IRTemp rMt = newTemp(Ity_I32);
+ IRTemp irt_diff = newTemp(Ity_I32);
+ IRTemp irt_sum = newTemp(Ity_I32);
IRTemp res_q = newTemp(Ity_I32);
assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
- assign(res_q, binop(Iop_HAdd16Sx2, mkexpr(rNt), mkexpr(rMt)));
+ assign( irt_sum,
+ binop(Iop_Add32,
+ unop(Iop_16Sto32,
+ unop(Iop_32to16,
+ mkexpr(rNt)
+ )
+ ),
+ unop(Iop_16Sto32,
+ unop(Iop_32to16,
+ binop(Iop_Shr32,
+ mkexpr(rMt), mkU8(16)
+ )
+ )
+ )
+ )
+ );
+
+ assign( irt_diff,
+ binop(Iop_Sub32,
+ unop(Iop_16Sto32,
+ unop(Iop_32to16,
+ binop(Iop_Shr32,
+ mkexpr(rNt), mkU8(16)
+ )
+ )
+ ),
+ unop(Iop_16Sto32,
+ unop(Iop_32to16, mkexpr(rMt)
+ )
+ )
+ )
+ );
+
+ assign( res_q,
+ binop(Iop_Or32,
+ unop(Iop_16Uto32,
+ unop(Iop_32to16,
+ binop(Iop_Shr32,
+ mkexpr(irt_sum), mkU8(1)
+ )
+ )
+ ),
+ binop(Iop_Shl32,
+ binop(Iop_Shr32,
+ mkexpr(irt_diff), mkU8(1)
+ ),
+ mkU8(16)
+ )
+ )
+ );
+
if (isT)
putIRegT( regD, mkexpr(res_q), condT );
else
putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
- DIP("shadd16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
+ DIP("shsax%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
return True;
}
/* fall through */
}
- /* ----------------- uhsub8<c> <Rd>,<Rn>,<Rm> ------------------- */
+ /* ----------------- uhsax<c> <Rd>,<Rn>,<Rm> ------------------- */
{
UInt regD = 99, regN = 99, regM = 99;
Bool gate = False;
if (isT) {
- if (INSNT0(15,4) == 0xFAC && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
+ if (INSNT0(15,4) == 0xFAE && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
regN = INSNT0(3,0);
regD = INSNT1(11,8);
regM = INSNT1(3,0);
} else {
if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
INSNA(11,8) == BITS4(1,1,1,1) &&
- INSNA(7,4) == BITS4(1,1,1,1)) {
+ INSNA(7,4) == BITS4(0,1,0,1)) {
regD = INSNA(15,12);
regN = INSNA(19,16);
regM = INSNA(3,0);
if (gate) {
IRTemp rNt = newTemp(Ity_I32);
IRTemp rMt = newTemp(Ity_I32);
+ IRTemp irt_diff = newTemp(Ity_I32);
+ IRTemp irt_sum = newTemp(Ity_I32);
IRTemp res_q = newTemp(Ity_I32);
assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
- assign(res_q, binop(Iop_HSub8Ux4, mkexpr(rNt), mkexpr(rMt)));
+ assign( irt_sum,
+ binop(Iop_Add32,
+ unop(Iop_16Uto32,
+ unop(Iop_32to16,
+ mkexpr(rNt)
+ )
+ ),
+ unop(Iop_16Uto32,
+ unop(Iop_32to16,
+ binop(Iop_Shr32,
+ mkexpr(rMt), mkU8(16)
+ )
+ )
+ )
+ )
+ );
+
+ assign( irt_diff,
+ binop(Iop_Sub32,
+ unop(Iop_16Uto32,
+ unop(Iop_32to16,
+ binop(Iop_Shr32,
+ mkexpr(rNt), mkU8(16)
+ )
+ )
+ ),
+ unop(Iop_16Uto32,
+ unop(Iop_32to16, mkexpr(rMt)
+ )
+ )
+ )
+ );
+
+ assign( res_q,
+ binop(Iop_Or32,
+ unop(Iop_16Uto32,
+ unop(Iop_32to16,
+ binop(Iop_Shr32,
+ mkexpr(irt_sum), mkU8(1)
+ )
+ )
+ ),
+ binop(Iop_Shl32,
+ binop(Iop_Shr32,
+ mkexpr(irt_diff), mkU8(1)
+ ),
+ mkU8(16)
+ )
+ )
+ );
+
if (isT)
putIRegT( regD, mkexpr(res_q), condT );
else
putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
- DIP("uhsub8%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
+ DIP("uhsax%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
return True;
}
/* fall through */
}
- /* ----------------- uhsub16<c> <Rd>,<Rn>,<Rm> ------------------- */
+ /* ----------------- shsub16<c> <Rd>,<Rn>,<Rm> ------------------- */
{
UInt regD = 99, regN = 99, regM = 99;
Bool gate = False;
if (isT) {
- if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF060) {
+ if (INSNT0(15,4) == 0xFAD && (INSNT1(15,0) & 0xF0F0) == 0xF020) {
regN = INSNT0(3,0);
regD = INSNT1(11,8);
regM = INSNT1(3,0);
gate = True;
}
} else {
- if (INSNA(27,20) == BITS8(0,1,1,0,0,1,1,1) &&
+ if (INSNA(27,20) == BITS8(0,1,1,0,0,0,1,1) &&
INSNA(11,8) == BITS4(1,1,1,1) &&
INSNA(7,4) == BITS4(0,1,1,1)) {
regD = INSNA(15,12);
assign( rNt, isT ? getIRegT(regN) : getIRegA(regN) );
assign( rMt, isT ? getIRegT(regM) : getIRegA(regM) );
- assign(res_q, binop(Iop_HSub16Ux2, mkexpr(rNt), mkexpr(rMt)));
+ assign(res_q, binop(Iop_HSub16Sx2, mkexpr(rNt), mkexpr(rMt)));
if (isT)
putIRegT( regD, mkexpr(res_q), condT );
else
putIRegA( regD, mkexpr(res_q), condT, Ijk_Boring );
- DIP("uhsub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
+ DIP("shsub16%s r%u, r%u, r%u\n", nCC(conq),regD,regN,regM);
return True;
}
/* fall through */
}
}
+ /* ------------------- revsh ----------------------- */
+ if (INSN(27,16) == 0x6FF && INSN(11,4) == 0xFB) {
+ UInt rM = INSN(3,0);
+ UInt rD = INSN(15,12);
+ if (rM != 15 && rD != 15) {
+ IRTemp irt_rM = newTemp(Ity_I32);
+ IRTemp irt_hi = newTemp(Ity_I32);
+ IRTemp irt_low = newTemp(Ity_I32);
+ IRTemp irt_res = newTemp(Ity_I32);
+ assign(irt_rM, getIRegA(rM));
+ assign(irt_hi,
+ binop(Iop_Sar32,
+ binop(Iop_Shl32, mkexpr(irt_rM), mkU8(24)),
+ mkU8(16)
+ )
+ );
+ assign(irt_low,
+ binop(Iop_And32,
+ binop(Iop_Shr32, mkexpr(irt_rM), mkU8(8)),
+ mkU32(0xFF)
+ )
+ );
+ assign(irt_res,
+ binop(Iop_Or32, mkexpr(irt_hi), mkexpr(irt_low))
+ );
+ putIRegA(rD, mkexpr(irt_res), condT, Ijk_Boring);
+ DIP("revsh%s r%u, r%u\n", nCC(INSN_COND), rD, rM);
+ goto decode_success;
+ }
+ }
+
/* ------------------- rbit ------------------ */
if (INSN(27,16) == 0x6FF && INSN(11,4) == 0xF3) {
UInt rD = INSN(15,12);
goto decode_success;
}
+ case 0x2EB: { // REVSH
+ /* ---------------- REVSH Rd, Rn ---------------- */
+ UInt rM = INSN0(5,3);
+ UInt rD = INSN0(2,0);
+ IRTemp irt_rM = newTemp(Ity_I32);
+ IRTemp irt_hi = newTemp(Ity_I32);
+ IRTemp irt_low = newTemp(Ity_I32);
+ IRTemp irt_res = newTemp(Ity_I32);
+ assign(irt_rM, getIRegT(rM));
+ assign(irt_hi,
+ binop(Iop_Sar32,
+ binop(Iop_Shl32, mkexpr(irt_rM), mkU8(24)),
+ mkU8(16)
+ )
+ );
+ assign(irt_low,
+ binop(Iop_And32,
+ binop(Iop_Shr32, mkexpr(irt_rM), mkU8(8)),
+ mkU32(0xFF)
+ )
+ );
+ assign(irt_res,
+ binop(Iop_Or32, mkexpr(irt_hi), mkexpr(irt_low))
+ );
+ putIRegT(rD, mkexpr(irt_res), condT);
+ DIP("revsh r%u, r%u\n", rD, rM);
+ goto decode_success;
+ }
+
default:
break; /* examine the next shortest prefix */
}
}
+ /* ------------------- (T2) REVSH ------------------ */
+ if (INSN0(15,4) == 0xFA9
+ && INSN1(15,12) == BITS4(1,1,1,1)
+ && INSN1(7,4) == BITS4(1,0,1,1)) {
+ UInt rM1 = INSN0(3,0);
+ UInt rM2 = INSN1(3,0);
+ UInt rD = INSN1(11,8);
+ if (!isBadRegT(rD) && !isBadRegT(rM1) && rM1 == rM2) {
+ IRTemp irt_rM = newTemp(Ity_I32);
+ IRTemp irt_hi = newTemp(Ity_I32);
+ IRTemp irt_low = newTemp(Ity_I32);
+ IRTemp irt_res = newTemp(Ity_I32);
+ assign(irt_rM, getIRegT(rM1));
+ assign(irt_hi,
+ binop(Iop_Sar32,
+ binop(Iop_Shl32, mkexpr(irt_rM), mkU8(24)),
+ mkU8(16)
+ )
+ );
+ assign(irt_low,
+ binop(Iop_And32,
+ binop(Iop_Shr32, mkexpr(irt_rM), mkU8(8)),
+ mkU32(0xFF)
+ )
+ );
+ assign(irt_res,
+ binop(Iop_Or32, mkexpr(irt_hi), mkexpr(irt_low))
+ );
+ putIRegT(rD, mkexpr(irt_res), condT);
+ DIP("revsh r%u, r%u\n", rD, rM1);
+ goto decode_success;
+ }
+ }
+
/* -------------- (T1) MSR apsr, reg -------------- */
if (INSN0(15,4) == 0xF38
&& INSN1(15,12) == BITS4(1,0,0,0) && INSN1(9,0) == 0x000) {