UInt dM = INSN(3,0) | (INSN(5,5) << 4);
UInt rD = INSN(15,12); /* lo32 */
UInt rN = INSN(19,16); /* hi32 */
- if (rD == 15 || rN == 15) {
+ if (rD == 15 || rN == 15 || (isT && (rD == 13 || rN == 13))) {
/* fall through */
} else {
putDReg(dM,
UInt dM = INSN(3,0) | (INSN(5,5) << 4);
UInt rD = INSN(15,12); /* lo32 */
UInt rN = INSN(19,16); /* hi32 */
- if (rD == 15 || rN == 15 || rD == rN) {
+ if (rD == 15 || rN == 15 || (isT && (rD == 13 || rN == 13))
+ || rD == rN) {
/* fall through */
} else {
IRTemp i64 = newTemp(Ity_I64);
/* fall through */
}
- // VMOV rD[x], rT
+ // VMOV sD, sD+1, rN, rM
+ if (0x0C400A10 == (insn28 & 0x0FF00FD0)) {
+ UInt sD = (INSN(3,0) << 1) | INSN(5,5);
+ UInt rN = INSN(15,12);
+ UInt rM = INSN(19,16);
+ if (rM == 15 || rN == 15 || (isT && (rM == 13 || rN == 13))
+ || sD == 31) {
+ /* fall through */
+ } else {
+ putFReg(sD,
+ unop(Iop_ReinterpI32asF32, isT ? getIRegT(rN) : getIRegA(rN)),
+ condT);
+ putFReg(sD+1,
+ unop(Iop_ReinterpI32asF32, isT ? getIRegT(rM) : getIRegA(rM)),
+ condT);
+ DIP("vmov%s, s%u, s%u, r%u, r%u\n",
+ nCC(conq), sD, sD + 1, rN, rM);
+ goto decode_success_vfp;
+ }
+ }
+
+ // VMOV rN, rM, sD, sD+1
+ if (0x0C500A10 == (insn28 & 0x0FF00FD0)) {
+ UInt sD = (INSN(3,0) << 1) | INSN(5,5);
+ UInt rN = INSN(15,12);
+ UInt rM = INSN(19,16);
+ if (rM == 15 || rN == 15 || (isT && (rM == 13 || rN == 13))
+ || sD == 31 || rN == rM) {
+ /* fall through */
+ } else {
+ IRExpr* res0 = unop(Iop_ReinterpF32asI32, getFReg(sD));
+ IRExpr* res1 = unop(Iop_ReinterpF32asI32, getFReg(sD+1));
+ if (isT) {
+ putIRegT(rN, res0, condT);
+ putIRegT(rM, res1, condT);
+ } else {
+ putIRegA(rN, res0, condT, Ijk_Boring);
+ putIRegA(rM, res1, condT, Ijk_Boring);
+ }
+ DIP("vmov%s, r%u, r%u, s%u, s%u\n",
+ nCC(conq), rN, rM, sD, sD + 1);
+ goto decode_success_vfp;
+ }
+ }
+
+ // VMOV rD[x], rT (ARM core register to scalar)
if (0x0E000B10 == (insn28 & 0x0F900F1F)) {
UInt rD = (INSN(7,7) << 4) | INSN(19,16);
UInt rT = INSN(15,12);
UInt opc = (INSN(22,21) << 2) | INSN(6,5);
UInt index;
- if (rT == 15) {
+ if (rT == 15 || (isT && rT == 13)) {
/* fall through */
} else {
if ((opc & BITS4(1,0,0,0)) == BITS4(1,0,0,0)) {
}
}
+ // VMOV (scalar to ARM core register)
// VMOV rT, rD[x]
if (0x0E100B10 == (insn28 & 0x0F100F1F)) {
UInt rN = (INSN(7,7) << 4) | INSN(19,16);
UInt U = INSN(23,23);
UInt opc = (INSN(22,21) << 2) | INSN(6,5);
UInt index;
- if (rT == 15) {
+ if (rT == 15 || (isT && rT == 13)) {
/* fall through */
} else {
if ((opc & BITS4(1,0,0,0)) == BITS4(1,0,0,0)) {
UInt rT = INSN(15,12);
UInt Q = INSN(21,21);
UInt size = (INSN(22,22) << 1) | INSN(5,5);
- if (rT == 15 || size == 3i || (Q && (rD & 1))) {
+ if (rT == 15 || (isT && rT == 13) || size == 3i || (Q && (rD & 1))) {
/* fall through */
} else {
IRExpr* e = isT ? getIRegT(rT) : getIRegA(rT);
/* --------------------- f{ld,st}d --------------------- */
// FLDD, FSTD
- if (BITS8(1,1,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,1,1,0))
+ if (BITS8(1,1,0,1,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,1,0))
&& BITS4(1,0,1,1) == INSN(11,8)) {
- UInt dD = INSN(15,12);
+ UInt dD = INSN(15,12) | (INSN(22,22) << 4);
UInt rN = INSN(19,16);
UInt offset = (insn28 & 0xFF) << 2;
UInt bU = (insn28 >> 23) & 1; /* 1: +offset 0: -offset */
}
/* --------------------- dp insns (D) --------------------- */
- if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,1,0,0))
+ if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0))
&& BITS4(1,0,1,1) == INSN(11,8)
- && BITS4(0,0,0,0) == (INSN(7,4) & BITS4(1,0,1,1))) {
- UInt dM = INSN(3,0); /* argR */
- UInt dD = INSN(15,12); /* dst/acc */
- UInt dN = INSN(19,16); /* argL */
+ && BITS4(0,0,0,0) == (INSN(7,4) & BITS4(0,0,0,1))) {
+ UInt dM = INSN(3,0) | (INSN(5,5) << 4); /* argR */
+ UInt dD = INSN(15,12) | (INSN(22,22) << 4); /* dst/acc */
+ UInt dN = INSN(19,16) | (INSN(7,7) << 4); /* argL */
UInt bP = (insn28 >> 23) & 1;
UInt bQ = (insn28 >> 21) & 1;
UInt bR = (insn28 >> 20) & 1;
condT);
DIP("fmacd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
goto decode_success_vfp;
- case BITS4(0,0,0,1): /* NMAC: d - n * m */
- putDReg(dD, triop(Iop_SubF64, rm,
+ case BITS4(0,0,0,1): /* NMAC: d + -(n * m) */
+ putDReg(dD, triop(Iop_AddF64, rm,
getDReg(dD),
- triop(Iop_MulF64, rm, getDReg(dN),
- getDReg(dM))),
+ unop(Iop_NegF64,
+ triop(Iop_MulF64, rm, getDReg(dN),
+ getDReg(dM)))),
condT);
DIP("fnmacd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
goto decode_success_vfp;
condT);
DIP("fmscd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
goto decode_success_vfp;
- case BITS4(0,0,1,1): /* NMSC: - d - n * m */
- putDReg(dD, triop(Iop_SubF64, rm,
+ case BITS4(0,0,1,1): /* NMSC: - d + -(n * m) */
+ putDReg(dD, triop(Iop_AddF64, rm,
unop(Iop_NegF64, getDReg(dD)),
- triop(Iop_MulF64, rm, getDReg(dN),
- getDReg(dM))),
+ unop(Iop_NegF64,
+ triop(Iop_MulF64, rm, getDReg(dN),
+ getDReg(dM)))),
condT);
DIP("fnmscd%s d%u, d%u, d%u\n", nCC(conq), dD, dN, dM);
goto decode_success_vfp;
/* --------------------- compares (D) --------------------- */
/* 31 27 23 19 15 11 7 3
28 24 20 16 12 8 4 0
- FCMPD cond 1110 1011 0100 Dd 1011 0100 Dm
- FCMPED cond 1110 1011 0100 Dd 1011 1100 Dm
- FCMPZD cond 1110 1011 0101 Dd 1011 0100 0000
- FCMPZED cond 1110 1011 0101 Dd 1011 1100 0000
+ FCMPD cond 1110 1D11 0100 Dd 1011 0100 Dm
+ FCMPED cond 1110 1D11 0100 Dd 1011 1100 Dm
+ FCMPZD cond 1110 1D11 0101 Dd 1011 0100 0000
+ FCMPZED cond 1110 1D11 0101 Dd 1011 1100 0000
Z N
Z=0 Compare Dd vs Dm and set FPSCR 31:28 accordingly
N=0 generates Invalid Operation exn if either arg is a signalling NaN
(Not that we pay any attention to N here)
*/
- if (BITS8(1,1,1,0,1,0,1,1) == INSN(27,20)
+ if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
&& BITS4(0,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
&& BITS4(1,0,1,1) == INSN(11,8)
- && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,1,1))) {
+ && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
UInt bZ = (insn28 >> 16) & 1;
UInt bN = (insn28 >> 7) & 1;
- UInt dD = INSN(15,12);
- UInt dM = INSN(3,0);
+ UInt dD = INSN(15,12) | (INSN(22,22) << 4);
+ UInt dM = INSN(3,0) | (INSN(5,5) << 4);
if (bZ && INSN(3,0) != 0) {
/* does not decode; fall through */
} else {
}
/* --------------------- unary (D) --------------------- */
- if (BITS8(1,1,1,0,1,0,1,1) == INSN(27,20)
+ if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
&& BITS4(0,0,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
&& BITS4(1,0,1,1) == INSN(11,8)
- && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,1,1))) {
- UInt dD = INSN(15,12);
- UInt dM = INSN(3,0);
+ && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
+ UInt dD = INSN(15,12) | (INSN(22,22) << 4);
+ UInt dM = INSN(3,0) | (INSN(5,5) << 4);
UInt b16 = (insn28 >> 16) & 1;
UInt b7 = (insn28 >> 7) & 1;
/**/ if (b16 == 0 && b7 == 0) {
/* ----------------- I <-> D conversions ----------------- */
// F{S,U}ITOD dD, fM
- if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,1,1,1))
+ if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
&& BITS4(1,0,0,0) == (INSN(19,16) & BITS4(1,1,1,1))
&& BITS4(1,0,1,1) == INSN(11,8)
&& BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
UInt bM = (insn28 >> 5) & 1;
UInt fM = (INSN(3,0) << 1) | bM;
- UInt dD = INSN(15,12);
+ UInt dD = INSN(15,12) | (INSN(22,22) << 4);
UInt syned = (insn28 >> 7) & 1;
if (syned) {
// FSITOD
if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
&& BITS4(1,1,0,0) == (INSN(19,16) & BITS4(1,1,1,0))
&& BITS4(1,0,1,1) == INSN(11,8)
- && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,1,1))) {
+ && BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
UInt bD = (insn28 >> 22) & 1;
UInt fD = (INSN(15,12) << 1) | bD;
- UInt dM = INSN(3,0);
+ UInt dM = INSN(3,0) | (INSN(5,5) << 4);
UInt bZ = (insn28 >> 7) & 1;
UInt syned = (insn28 >> 16) & 1;
IRTemp rmode = newTemp(Ity_I32);
/* --------------------- dp insns (F) --------------------- */
if (BITS8(1,1,1,0,0,0,0,0) == (INSN(27,20) & BITS8(1,1,1,1,0,0,0,0))
- && BITS4(1,0,1,0) == INSN(11,8)
+ && BITS4(1,0,1,0) == (INSN(11,8) & BITS4(1,1,1,0))
&& BITS4(0,0,0,0) == (INSN(7,4) & BITS4(0,0,0,1))) {
UInt bM = (insn28 >> 5) & 1;
UInt bD = (insn28 >> 22) & 1;
condT);
DIP("fmacs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
goto decode_success_vfp;
- case BITS4(0,0,0,1): /* NMAC: d - n * m */
- putFReg(fD, triop(Iop_SubF32, rm,
+ case BITS4(0,0,0,1): /* NMAC: d + -(n * m) */
+ putFReg(fD, triop(Iop_AddF32, rm,
getFReg(fD),
- triop(Iop_MulF32, rm, getFReg(fN), getFReg(fM))),
+ unop(Iop_NegF32,
+ triop(Iop_MulF32, rm, getFReg(fN),
+ getFReg(fM)))),
condT);
DIP("fnmacs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
goto decode_success_vfp;
condT);
DIP("fmscs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
goto decode_success_vfp;
- case BITS4(0,0,1,1): /* NMSC: - d - n * m */
- break; //ATC
+ case BITS4(0,0,1,1): /* NMSC: - d + -(n * m) */
+ putFReg(fD, triop(Iop_AddF32, rm,
+ unop(Iop_NegF32, getFReg(fD)),
+ unop(Iop_NegF32,
+ triop(Iop_MulF32, rm,
+ getFReg(fN),
+ getFReg(fM)))),
+ condT);
+ DIP("fnmscs%s s%u, s%u, s%u\n", nCC(conq), fD, fN, fM);
+ goto decode_success_vfp;
case BITS4(0,1,0,0): /* MUL: n * m */
putFReg(fD, triop(Iop_MulF32, rm, getFReg(fN), getFReg(fM)),
condT);
the case here. Hence this case possibly requires rounding, and
so it drags in the current rounding mode. */
if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
- && BITS4(1,0,0,0) == (INSN(19,16) & BITS4(1,1,1,1))
- && BITS4(1,0,1,0) == INSN(11,8)
+ && BITS4(1,0,0,0) == INSN(19,16)
+ && BITS4(1,0,1,0) == (INSN(11,8) & BITS4(1,1,1,0))
&& BITS4(0,1,0,0) == (INSN(7,4) & BITS4(0,1,0,1))) {
UInt bM = (insn28 >> 5) & 1;
UInt bD = (insn28 >> 22) & 1;
/* ----------------- S <-> D conversions ----------------- */
// FCVTDS
- if (BITS8(1,1,1,0,1,0,1,1) == INSN(27,20)
+ if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
&& BITS4(0,1,1,1) == INSN(19,16)
&& BITS4(1,0,1,0) == INSN(11,8)
&& BITS4(1,1,0,0) == (INSN(7,4) & BITS4(1,1,0,1))) {
- UInt dD = INSN(15,12);
+ UInt dD = INSN(15,12) | (INSN(22,22) << 4);
UInt bM = (insn28 >> 5) & 1;
UInt fM = (INSN(3,0) << 1) | bM;
putDReg(dD, unop(Iop_F32toF64, getFReg(fM)), condT);
if (BITS8(1,1,1,0,1,0,1,1) == (INSN(27,20) & BITS8(1,1,1,1,1,0,1,1))
&& BITS4(0,1,1,1) == INSN(19,16)
&& BITS4(1,0,1,1) == INSN(11,8)
- && BITS4(1,1,0,0) == INSN(7,4)) {
+ && BITS4(1,1,0,0) == (INSN(7,4) & BITS4(1,1,0,1))) {
UInt bD = (insn28 >> 22) & 1;
UInt fD = (INSN(15,12) << 1) | bD;
- UInt dM = INSN(3,0);
+ UInt dM = INSN(3,0) | (INSN(5,5) << 4);
IRTemp rmode = newTemp(Ity_I32);
assign(rmode, mkexpr(mk_get_IR_rounding_mode()));
putFReg(fD, binop(Iop_F64toF32, mkexpr(rmode), getDReg(dM)),