return True;
}
+/* Generate specific vector FP binary ops, possibly with a fake
+ rounding mode as required by the primop. */
+static
+IRExpr* binop_w_fake_RM ( IROp op, IRExpr* argL, IRExpr* argR )
+{
+ switch (op) {
+ case Iop_Add32Fx4:
+ case Iop_Sub32Fx4:
+ case Iop_Mul32Fx4:
+ return triop(op, get_FAKE_roundingmode(), argL, argR );
+ case Iop_Add32x4: case Iop_Add16x8:
+ case Iop_Sub32x4: case Iop_Sub16x8:
+ case Iop_Mul32x4: case Iop_Mul16x8:
+ case Iop_Mul32x2: case Iop_Mul16x4:
+ case Iop_Add32Fx2:
+ case Iop_Sub32Fx2:
+ case Iop_Mul32Fx2:
+ case Iop_PwAdd32Fx2:
+ return binop(op, argL, argR);
+ default:
+ ppIROp(op);
+ vassert(0);
+ }
+}
+
/* VTBL, VTBX */
static
Bool dis_neon_vtb ( UInt theInstr, IRTemp condT )
/* VABD */
if (Q) {
assign(res, unop(Iop_Abs32Fx4,
- binop(Iop_Sub32Fx4,
+ triop(Iop_Sub32Fx4,
+ get_FAKE_roundingmode(),
mkexpr(arg_n),
mkexpr(arg_m))));
} else {
break;
}
}
- assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
+ assign(res, binop_w_fake_RM(op, mkexpr(arg_n), mkexpr(arg_m)));
} else {
if (U == 0) {
/* VMLA, VMLS */
default: vassert(0);
}
}
- assign(res, binop(op2,
- Q ? getQReg(dreg) : getDRegI64(dreg),
- binop(op, mkexpr(arg_n), mkexpr(arg_m))));
+ assign(res, binop_w_fake_RM(
+ op2,
+ Q ? getQReg(dreg) : getDRegI64(dreg),
+ binop_w_fake_RM(op, mkexpr(arg_n),
+ mkexpr(arg_m))));
DIP("vml%c.f32 %c%u, %c%u, %c%u\n",
P ? 's' : 'a', Q ? 'q' : 'd',
if ((C >> 1) != 0)
return False;
op = Q ? Iop_Mul32Fx4 : Iop_Mul32Fx2 ;
- assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
+ assign(res, binop_w_fake_RM(op, mkexpr(arg_n), mkexpr(arg_m)));
DIP("vmul.f32 %c%u, %c%u, %c%u\n",
Q ? 'q' : 'd', dreg,
Q ? 'q' : 'd', nreg, Q ? 'q' : 'd', mreg);
}
}
op2 = INSN(10,10) ? sub : add;
- assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
+ assign(res, binop_w_fake_RM(op, mkexpr(arg_n), mkexpr(arg_m)));
if (Q)
- putQReg(dreg, binop(op2, getQReg(dreg), mkexpr(res)),
- condT);
+ putQReg(dreg, binop_w_fake_RM(op2, getQReg(dreg), mkexpr(res)),
+ condT);
else
putDRegI64(dreg, binop(op2, getDRegI64(dreg), mkexpr(res)),
condT);
vassert(0);
}
}
- assign(res, binop(op, mkexpr(arg_n), mkexpr(arg_m)));
+ assign(res, binop_w_fake_RM(op, mkexpr(arg_n), mkexpr(arg_m)));
if (Q)
putQReg(dreg, mkexpr(res), condT);
else
return res;
}
case Iop_Abs32Fx4: {
- DECLARE_PATTERN(p_vabd_32fx4);
- DEFINE_PATTERN(p_vabd_32fx4,
- unop(Iop_Abs32Fx4,
- binop(Iop_Sub32Fx4,
- bind(0),
- bind(1))));
- if (matchIRExpr(&mi, p_vabd_32fx4, e)) {
- HReg res = newVRegV(env);
- HReg argL = iselNeonExpr(env, mi.bindee[0]);
- HReg argR = iselNeonExpr(env, mi.bindee[1]);
- addInstr(env, ARMInstr_NBinary(ARMneon_VABDFP,
- res, argL, argR, 0, True));
- return res;
- } else {
- HReg res = newVRegV(env);
- HReg argL = iselNeonExpr(env, e->Iex.Unop.arg);
- addInstr(env, ARMInstr_NUnary(ARMneon_VABSFP,
- res, argL, 0, True));
- return res;
- }
+ HReg res = newVRegV(env);
+ HReg argL = iselNeonExpr(env, e->Iex.Unop.arg);
+ addInstr(env, ARMInstr_NUnary(ARMneon_VABSFP,
+ res, argL, 0, True));
+ return res;
}
case Iop_Rsqrte32Fx4: {
HReg res = newVRegV(env);
res, argL, argR, size, True));
return res;
}
- case Iop_Add32Fx4: {
- HReg res = newVRegV(env);
- HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1);
- HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2);
- UInt size = 0;
- addInstr(env, ARMInstr_NBinary(ARMneon_VADDFP,
- res, argL, argR, size, True));
- return res;
- }
case Iop_Recps32Fx4: {
HReg res = newVRegV(env);
HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1);
res, argL, argR, size, True));
return res;
}
- case Iop_Sub32Fx4: {
- HReg res = newVRegV(env);
- HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1);
- HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2);
- UInt size = 0;
- addInstr(env, ARMInstr_NBinary(ARMneon_VSUBFP,
- res, argL, argR, size, True));
- return res;
- }
case Iop_QSub8Ux16:
case Iop_QSub16Ux8:
case Iop_QSub32Ux4:
res, argL, argR, size, True));
return res;
}
- case Iop_Mul32Fx4: {
- HReg res = newVRegV(env);
- HReg argL = iselNeonExpr(env, e->Iex.Binop.arg1);
- HReg argR = iselNeonExpr(env, e->Iex.Binop.arg2);
- UInt size = 0;
- addInstr(env, ARMInstr_NBinary(ARMneon_VMULFP,
- res, argL, argR, size, True));
- return res;
- }
case Iop_Mull8Ux8:
case Iop_Mull16Ux4:
case Iop_Mull32Ux2: {
res, argL, argR, imm4, True));
return res;
}
+ case Iop_Mul32Fx4:
+ case Iop_Sub32Fx4:
+ case Iop_Add32Fx4: {
+ HReg res = newVRegV(env);
+ HReg argL = iselNeonExpr(env, triop->arg2);
+ HReg argR = iselNeonExpr(env, triop->arg3);
+ UInt size = 0;
+ ARMNeonBinOp op = ARMneon_INVALID;
+ switch (triop->op) {
+ case Iop_Mul32Fx4: op = ARMneon_VMULFP; break;
+ case Iop_Sub32Fx4: op = ARMneon_VSUBFP; break;
+ case Iop_Add32Fx4: op = ARMneon_VADDFP; break;
+ default: vassert(0);
+ }
+ addInstr(env, ARMInstr_NBinary(op, res, argL, argR, size, True));
+ return res;
+ }
default:
break;
}