IR: Merge U32 and U64 variants of FP instructions

This commit is contained in:
MerryMage 2018-02-02 21:55:23 +00:00
parent ed2bedec43
commit 429dc24587
3 changed files with 92 additions and 164 deletions

View file

@ -98,13 +98,8 @@ bool ArmTranslatorVisitor::vfp2_VADD(Cond cond, bool D, size_t Vn, size_t Vd, bo
return EmitVfpVectorOperation(sz, d, n, m, [sz, this](ExtReg d, ExtReg n, ExtReg m) { return EmitVfpVectorOperation(sz, d, n, m, [sz, this](ExtReg d, ExtReg n, ExtReg m) {
auto reg_n = ir.GetExtendedRegister(n); auto reg_n = ir.GetExtendedRegister(n);
auto reg_m = ir.GetExtendedRegister(m); auto reg_m = ir.GetExtendedRegister(m);
if (sz) { auto result = ir.FPAdd(reg_n, reg_m, true);
auto result = ir.FPAdd64(reg_n, reg_m, true);
ir.SetExtendedRegister(d, result); ir.SetExtendedRegister(d, result);
} else {
auto result = ir.FPAdd32(reg_n, reg_m, true);
ir.SetExtendedRegister(d, result);
}
}); });
} }
return true; return true;
@ -119,13 +114,8 @@ bool ArmTranslatorVisitor::vfp2_VSUB(Cond cond, bool D, size_t Vn, size_t Vd, bo
return EmitVfpVectorOperation(sz, d, n, m, [sz, this](ExtReg d, ExtReg n, ExtReg m) { return EmitVfpVectorOperation(sz, d, n, m, [sz, this](ExtReg d, ExtReg n, ExtReg m) {
auto reg_n = ir.GetExtendedRegister(n); auto reg_n = ir.GetExtendedRegister(n);
auto reg_m = ir.GetExtendedRegister(m); auto reg_m = ir.GetExtendedRegister(m);
if (sz) { auto result = ir.FPSub(reg_n, reg_m, true);
auto result = ir.FPSub64(reg_n, reg_m, true);
ir.SetExtendedRegister(d, result); ir.SetExtendedRegister(d, result);
} else {
auto result = ir.FPSub32(reg_n, reg_m, true);
ir.SetExtendedRegister(d, result);
}
}); });
} }
return true; return true;
@ -140,13 +130,8 @@ bool ArmTranslatorVisitor::vfp2_VMUL(Cond cond, bool D, size_t Vn, size_t Vd, bo
return EmitVfpVectorOperation(sz, d, n, m, [sz, this](ExtReg d, ExtReg n, ExtReg m) { return EmitVfpVectorOperation(sz, d, n, m, [sz, this](ExtReg d, ExtReg n, ExtReg m) {
auto reg_n = ir.GetExtendedRegister(n); auto reg_n = ir.GetExtendedRegister(n);
auto reg_m = ir.GetExtendedRegister(m); auto reg_m = ir.GetExtendedRegister(m);
if (sz) { auto result = ir.FPMul(reg_n, reg_m, true);
auto result = ir.FPMul64(reg_n, reg_m, true);
ir.SetExtendedRegister(d, result); ir.SetExtendedRegister(d, result);
} else {
auto result = ir.FPMul32(reg_n, reg_m, true);
ir.SetExtendedRegister(d, result);
}
}); });
} }
return true; return true;
@ -162,13 +147,8 @@ bool ArmTranslatorVisitor::vfp2_VMLA(Cond cond, bool D, size_t Vn, size_t Vd, bo
auto reg_n = ir.GetExtendedRegister(n); auto reg_n = ir.GetExtendedRegister(n);
auto reg_m = ir.GetExtendedRegister(m); auto reg_m = ir.GetExtendedRegister(m);
auto reg_d = ir.GetExtendedRegister(d); auto reg_d = ir.GetExtendedRegister(d);
if (sz) { auto result = ir.FPAdd(reg_d, ir.FPMul(reg_n, reg_m, true), true);
auto result = ir.FPAdd64(reg_d, ir.FPMul64(reg_n, reg_m, true), true);
ir.SetExtendedRegister(d, result); ir.SetExtendedRegister(d, result);
} else {
auto result = ir.FPAdd32(reg_d, ir.FPMul32(reg_n, reg_m, true), true);
ir.SetExtendedRegister(d, result);
}
}); });
} }
return true; return true;
@ -184,13 +164,8 @@ bool ArmTranslatorVisitor::vfp2_VMLS(Cond cond, bool D, size_t Vn, size_t Vd, bo
auto reg_n = ir.GetExtendedRegister(n); auto reg_n = ir.GetExtendedRegister(n);
auto reg_m = ir.GetExtendedRegister(m); auto reg_m = ir.GetExtendedRegister(m);
auto reg_d = ir.GetExtendedRegister(d); auto reg_d = ir.GetExtendedRegister(d);
if (sz) { auto result = ir.FPAdd(reg_d, ir.FPNeg(ir.FPMul(reg_n, reg_m, true)), true);
auto result = ir.FPAdd64(reg_d, ir.FPNeg64(ir.FPMul64(reg_n, reg_m, true)), true);
ir.SetExtendedRegister(d, result); ir.SetExtendedRegister(d, result);
} else {
auto result = ir.FPAdd32(reg_d, ir.FPNeg32(ir.FPMul32(reg_n, reg_m, true)), true);
ir.SetExtendedRegister(d, result);
}
}); });
} }
return true; return true;
@ -205,13 +180,8 @@ bool ArmTranslatorVisitor::vfp2_VNMUL(Cond cond, bool D, size_t Vn, size_t Vd, b
return EmitVfpVectorOperation(sz, d, n, m, [sz, this](ExtReg d, ExtReg n, ExtReg m) { return EmitVfpVectorOperation(sz, d, n, m, [sz, this](ExtReg d, ExtReg n, ExtReg m) {
auto reg_n = ir.GetExtendedRegister(n); auto reg_n = ir.GetExtendedRegister(n);
auto reg_m = ir.GetExtendedRegister(m); auto reg_m = ir.GetExtendedRegister(m);
if (sz) { auto result = ir.FPNeg(ir.FPMul(reg_n, reg_m, true));
auto result = ir.FPNeg64(ir.FPMul64(reg_n, reg_m, true));
ir.SetExtendedRegister(d, result); ir.SetExtendedRegister(d, result);
} else {
auto result = ir.FPNeg32(ir.FPMul32(reg_n, reg_m, true));
ir.SetExtendedRegister(d, result);
}
}); });
} }
return true; return true;
@ -227,13 +197,8 @@ bool ArmTranslatorVisitor::vfp2_VNMLA(Cond cond, bool D, size_t Vn, size_t Vd, b
auto reg_n = ir.GetExtendedRegister(n); auto reg_n = ir.GetExtendedRegister(n);
auto reg_m = ir.GetExtendedRegister(m); auto reg_m = ir.GetExtendedRegister(m);
auto reg_d = ir.GetExtendedRegister(d); auto reg_d = ir.GetExtendedRegister(d);
if (sz) { auto result = ir.FPAdd(ir.FPNeg(reg_d), ir.FPNeg(ir.FPMul(reg_n, reg_m, true)), true);
auto result = ir.FPAdd64(ir.FPNeg64(reg_d), ir.FPNeg64(ir.FPMul64(reg_n, reg_m, true)), true);
ir.SetExtendedRegister(d, result); ir.SetExtendedRegister(d, result);
} else {
auto result = ir.FPAdd32(ir.FPNeg32(reg_d), ir.FPNeg32(ir.FPMul32(reg_n, reg_m, true)), true);
ir.SetExtendedRegister(d, result);
}
}); });
} }
return true; return true;
@ -249,13 +214,8 @@ bool ArmTranslatorVisitor::vfp2_VNMLS(Cond cond, bool D, size_t Vn, size_t Vd, b
auto reg_n = ir.GetExtendedRegister(n); auto reg_n = ir.GetExtendedRegister(n);
auto reg_m = ir.GetExtendedRegister(m); auto reg_m = ir.GetExtendedRegister(m);
auto reg_d = ir.GetExtendedRegister(d); auto reg_d = ir.GetExtendedRegister(d);
if (sz) { auto result = ir.FPAdd(ir.FPNeg(reg_d), ir.FPMul(reg_n, reg_m, true), true);
auto result = ir.FPAdd64(ir.FPNeg64(reg_d), ir.FPMul64(reg_n, reg_m, true), true);
ir.SetExtendedRegister(d, result); ir.SetExtendedRegister(d, result);
} else {
auto result = ir.FPAdd32(ir.FPNeg32(reg_d), ir.FPMul32(reg_n, reg_m, true), true);
ir.SetExtendedRegister(d, result);
}
}); });
} }
return true; return true;
@ -270,13 +230,8 @@ bool ArmTranslatorVisitor::vfp2_VDIV(Cond cond, bool D, size_t Vn, size_t Vd, bo
return EmitVfpVectorOperation(sz, d, n, m, [sz, this](ExtReg d, ExtReg n, ExtReg m) { return EmitVfpVectorOperation(sz, d, n, m, [sz, this](ExtReg d, ExtReg n, ExtReg m) {
auto reg_n = ir.GetExtendedRegister(n); auto reg_n = ir.GetExtendedRegister(n);
auto reg_m = ir.GetExtendedRegister(m); auto reg_m = ir.GetExtendedRegister(m);
if (sz) { auto result = ir.FPDiv(reg_n, reg_m, true);
auto result = ir.FPDiv64(reg_n, reg_m, true);
ir.SetExtendedRegister(d, result); ir.SetExtendedRegister(d, result);
} else {
auto result = ir.FPDiv32(reg_n, reg_m, true);
ir.SetExtendedRegister(d, result);
}
}); });
} }
return true; return true;
@ -403,13 +358,8 @@ bool ArmTranslatorVisitor::vfp2_VABS(Cond cond, bool D, size_t Vd, bool sz, bool
if (ConditionPassed(cond)) { if (ConditionPassed(cond)) {
return EmitVfpVectorOperation(sz, d, m, [sz, this](ExtReg d, ExtReg m) { return EmitVfpVectorOperation(sz, d, m, [sz, this](ExtReg d, ExtReg m) {
auto reg_m = ir.GetExtendedRegister(m); auto reg_m = ir.GetExtendedRegister(m);
if (sz) { auto result = ir.FPAbs(reg_m);
auto result = ir.FPAbs64(reg_m);
ir.SetExtendedRegister(d, result); ir.SetExtendedRegister(d, result);
} else {
auto result = ir.FPAbs32(reg_m);
ir.SetExtendedRegister(d, result);
}
}); });
} }
return true; return true;
@ -422,13 +372,8 @@ bool ArmTranslatorVisitor::vfp2_VNEG(Cond cond, bool D, size_t Vd, bool sz, bool
if (ConditionPassed(cond)) { if (ConditionPassed(cond)) {
return EmitVfpVectorOperation(sz, d, m, [sz, this](ExtReg d, ExtReg m) { return EmitVfpVectorOperation(sz, d, m, [sz, this](ExtReg d, ExtReg m) {
auto reg_m = ir.GetExtendedRegister(m); auto reg_m = ir.GetExtendedRegister(m);
if (sz) { auto result = ir.FPNeg(reg_m);
auto result = ir.FPNeg64(reg_m);
ir.SetExtendedRegister(d, result); ir.SetExtendedRegister(d, result);
} else {
auto result = ir.FPNeg32(reg_m);
ir.SetExtendedRegister(d, result);
}
}); });
} }
return true; return true;
@ -441,13 +386,8 @@ bool ArmTranslatorVisitor::vfp2_VSQRT(Cond cond, bool D, size_t Vd, bool sz, boo
if (ConditionPassed(cond)) { if (ConditionPassed(cond)) {
return EmitVfpVectorOperation(sz, d, m, [sz, this](ExtReg d, ExtReg m) { return EmitVfpVectorOperation(sz, d, m, [sz, this](ExtReg d, ExtReg m) {
auto reg_m = ir.GetExtendedRegister(m); auto reg_m = ir.GetExtendedRegister(m);
if (sz) { auto result = ir.FPSqrt(reg_m);
auto result = ir.FPSqrt64(reg_m);
ir.SetExtendedRegister(d, result); ir.SetExtendedRegister(d, result);
} else {
auto result = ir.FPSqrt32(reg_m);
ir.SetExtendedRegister(d, result);
}
}); });
} }
return true; return true;
@ -533,11 +473,7 @@ bool ArmTranslatorVisitor::vfp2_VCMP(Cond cond, bool D, size_t Vd, bool sz, bool
if (ConditionPassed(cond)) { if (ConditionPassed(cond)) {
auto reg_d = ir.GetExtendedRegister(d); auto reg_d = ir.GetExtendedRegister(d);
auto reg_m = ir.GetExtendedRegister(m); auto reg_m = ir.GetExtendedRegister(m);
if (sz) { ir.FPCompare(reg_d, reg_m, exc_on_qnan, true);
ir.FPCompare64(reg_d, reg_m, exc_on_qnan, true);
} else {
ir.FPCompare32(reg_d, reg_m, exc_on_qnan, true);
}
} }
return true; return true;
} }
@ -550,9 +486,9 @@ bool ArmTranslatorVisitor::vfp2_VCMP_zero(Cond cond, bool D, size_t Vd, bool sz,
if (ConditionPassed(cond)) { if (ConditionPassed(cond)) {
auto reg_d = ir.GetExtendedRegister(d); auto reg_d = ir.GetExtendedRegister(d);
if (sz) { if (sz) {
ir.FPCompare64(reg_d, ir.Imm64(0), exc_on_qnan, true); ir.FPCompare(reg_d, ir.Imm64(0), exc_on_qnan, true);
} else { } else {
ir.FPCompare32(reg_d, ir.Imm32(0), exc_on_qnan, true); ir.FPCompare(reg_d, ir.Imm32(0), exc_on_qnan, true);
} }
} }
return true; return true;

View file

@ -869,78 +869,78 @@ U128 IREmitter::VectorZeroUpper(const U128& a) {
return Inst<U128>(Opcode::VectorZeroUpper, a); return Inst<U128>(Opcode::VectorZeroUpper, a);
} }
U32 IREmitter::FPAbs32(const U32& a) { U32U64 IREmitter::FPAbs(const U32U64& a) {
if (a.GetType() == Type::U32) {
return Inst<U32>(Opcode::FPAbs32, a); return Inst<U32>(Opcode::FPAbs32, a);
} } else {
U64 IREmitter::FPAbs64(const U64& a) {
return Inst<U64>(Opcode::FPAbs64, a); return Inst<U64>(Opcode::FPAbs64, a);
}
} }
U32 IREmitter::FPAdd32(const U32& a, const U32& b, bool fpscr_controlled) { U32U64 IREmitter::FPAdd(const U32U64& a, const U32U64& b, bool fpscr_controlled) {
ASSERT(fpscr_controlled); ASSERT(fpscr_controlled);
ASSERT(a.GetType() == b.GetType());
if (a.GetType() == Type::U32) {
return Inst<U32>(Opcode::FPAdd32, a, b); return Inst<U32>(Opcode::FPAdd32, a, b);
} } else {
U64 IREmitter::FPAdd64(const U64& a, const U64& b, bool fpscr_controlled) {
ASSERT(fpscr_controlled);
return Inst<U64>(Opcode::FPAdd64, a, b); return Inst<U64>(Opcode::FPAdd64, a, b);
}
} }
void IREmitter::FPCompare32(const U32& a, const U32& b, bool exc_on_qnan, bool fpscr_controlled) { void IREmitter::FPCompare(const U32U64& a, const U32U64& b, bool exc_on_qnan, bool fpscr_controlled) {
ASSERT(fpscr_controlled); ASSERT(fpscr_controlled);
ASSERT(a.GetType() == b.GetType());
if (a.GetType() == Type::U32) {
Inst(Opcode::FPCompare32, a, b, Imm1(exc_on_qnan)); Inst(Opcode::FPCompare32, a, b, Imm1(exc_on_qnan));
} } else {
void IREmitter::FPCompare64(const U64& a, const U64& b, bool exc_on_qnan, bool fpscr_controlled) {
ASSERT(fpscr_controlled);
Inst(Opcode::FPCompare64, a, b, Imm1(exc_on_qnan)); Inst(Opcode::FPCompare64, a, b, Imm1(exc_on_qnan));
}
} }
U32 IREmitter::FPDiv32(const U32& a, const U32& b, bool fpscr_controlled) { U32U64 IREmitter::FPDiv(const U32U64& a, const U32U64& b, bool fpscr_controlled) {
ASSERT(fpscr_controlled); ASSERT(fpscr_controlled);
ASSERT(a.GetType() == b.GetType());
if (a.GetType() == Type::U32) {
return Inst<U32>(Opcode::FPDiv32, a, b); return Inst<U32>(Opcode::FPDiv32, a, b);
} } else {
U64 IREmitter::FPDiv64(const U64& a, const U64& b, bool fpscr_controlled) {
ASSERT(fpscr_controlled);
return Inst<U64>(Opcode::FPDiv64, a, b); return Inst<U64>(Opcode::FPDiv64, a, b);
}
} }
U32 IREmitter::FPMul32(const U32& a, const U32& b, bool fpscr_controlled) { U32U64 IREmitter::FPMul(const U32U64& a, const U32U64& b, bool fpscr_controlled) {
ASSERT(fpscr_controlled); ASSERT(fpscr_controlled);
ASSERT(a.GetType() == b.GetType());
if (a.GetType() == Type::U32) {
return Inst<U32>(Opcode::FPMul32, a, b); return Inst<U32>(Opcode::FPMul32, a, b);
} } else {
U64 IREmitter::FPMul64(const U64& a, const U64& b, bool fpscr_controlled) {
ASSERT(fpscr_controlled);
return Inst<U64>(Opcode::FPMul64, a, b); return Inst<U64>(Opcode::FPMul64, a, b);
}
} }
U32 IREmitter::FPNeg32(const U32& a) { U32U64 IREmitter::FPNeg(const U32U64& a) {
if (a.GetType() == Type::U32) {
return Inst<U32>(Opcode::FPNeg32, a); return Inst<U32>(Opcode::FPNeg32, a);
} } else {
U64 IREmitter::FPNeg64(const U64& a) {
return Inst<U64>(Opcode::FPNeg64, a); return Inst<U64>(Opcode::FPNeg64, a);
}
} }
U32 IREmitter::FPSqrt32(const U32& a) { U32U64 IREmitter::FPSqrt(const U32U64& a) {
if (a.GetType() == Type::U32) {
return Inst<U32>(Opcode::FPSqrt32, a); return Inst<U32>(Opcode::FPSqrt32, a);
} } else {
U64 IREmitter::FPSqrt64(const U64& a) {
return Inst<U64>(Opcode::FPSqrt64, a); return Inst<U64>(Opcode::FPSqrt64, a);
}
} }
U32 IREmitter::FPSub32(const U32& a, const U32& b, bool fpscr_controlled) { U32U64 IREmitter::FPSub(const U32U64& a, const U32U64& b, bool fpscr_controlled) {
ASSERT(fpscr_controlled); ASSERT(fpscr_controlled);
ASSERT(a.GetType() == b.GetType());
if (a.GetType() == Type::U32) {
return Inst<U32>(Opcode::FPSub32, a, b); return Inst<U32>(Opcode::FPSub32, a, b);
} } else {
U64 IREmitter::FPSub64(const U64& a, const U64& b, bool fpscr_controlled) {
ASSERT(fpscr_controlled);
return Inst<U64>(Opcode::FPSub64, a, b); return Inst<U64>(Opcode::FPSub64, a, b);
}
} }
U32 IREmitter::FPDoubleToSingle(const U64& a, bool fpscr_controlled) { U32 IREmitter::FPDoubleToSingle(const U64& a, bool fpscr_controlled) {

View file

@ -229,22 +229,14 @@ public:
U128 VectorPairedAdd64(const U128& a, const U128& b); U128 VectorPairedAdd64(const U128& a, const U128& b);
U128 VectorZeroUpper(const U128& a); U128 VectorZeroUpper(const U128& a);
U32 FPAbs32(const U32& a); U32U64 FPAbs(const U32U64& a);
U64 FPAbs64(const U64& a); U32U64 FPAdd(const U32U64& a, const U32U64& b, bool fpscr_controlled);
U32 FPAdd32(const U32& a, const U32& b, bool fpscr_controlled); void FPCompare(const U32U64& a, const U32U64& b, bool exc_on_qnan, bool fpscr_controlled);
U64 FPAdd64(const U64& a, const U64& b, bool fpscr_controlled); U32U64 FPDiv(const U32U64& a, const U32U64& b, bool fpscr_controlled);
void FPCompare32(const U32& a, const U32& b, bool exc_on_qnan, bool fpscr_controlled); U32U64 FPMul(const U32U64& a, const U32U64& b, bool fpscr_controlled);
void FPCompare64(const U64& a, const U64& b, bool exc_on_qnan, bool fpscr_controlled); U32U64 FPNeg(const U32U64& a);
U32 FPDiv32(const U32& a, const U32& b, bool fpscr_controlled); U32U64 FPSqrt(const U32U64& a);
U64 FPDiv64(const U64& a, const U64& b, bool fpscr_controlled); U32U64 FPSub(const U32U64& a, const U32U64& b, bool fpscr_controlled);
U32 FPMul32(const U32& a, const U32& b, bool fpscr_controlled);
U64 FPMul64(const U64& a, const U64& b, bool fpscr_controlled);
U32 FPNeg32(const U32& a);
U64 FPNeg64(const U64& a);
U32 FPSqrt32(const U32& a);
U64 FPSqrt64(const U64& a);
U32 FPSub32(const U32& a, const U32& b, bool fpscr_controlled);
U64 FPSub64(const U64& a, const U64& b, bool fpscr_controlled);
U32 FPDoubleToSingle(const U64& a, bool fpscr_controlled); U32 FPDoubleToSingle(const U64& a, bool fpscr_controlled);
U64 FPSingleToDouble(const U32& a, bool fpscr_controlled); U64 FPSingleToDouble(const U32& a, bool fpscr_controlled);
U32 FPSingleToS32(const U32& a, bool round_towards_zero, bool fpscr_controlled); U32 FPSingleToS32(const U32& a, bool round_towards_zero, bool fpscr_controlled);