IR: Simplify types. F32 -> U32, F64 -> U64, F128 -> U128

ARM's Architecture Specification Language doesn't distinguish between floats and integers
as much as we do. This makes some things difficult to implement. Since our register
allocator is now capable of allocating values to XMMs and GPRs as necessary, the
Transfer IR instructions are no longer necessary as they used to be and they can be
removed.
This commit is contained in:
MerryMage 2018-01-19 01:09:46 +00:00
parent 9a812b0c61
commit 5eb0bdecdf
10 changed files with 150 additions and 226 deletions

View file

@ -2351,42 +2351,6 @@ static void FPTwoOp64(BlockOfCode* code, EmitContext& ctx, IR::Inst* inst, void
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
template <typename JST>
void EmitX64<JST>::EmitTransferFromFP32(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
ctx.reg_alloc.DefineValue(inst, args[0]);
}
template <typename JST>
void EmitX64<JST>::EmitTransferFromFP64(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
ctx.reg_alloc.DefineValue(inst, args[0]);
}
template <typename JST>
void EmitX64<JST>::EmitTransferToFP32(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
if (args[0].IsImmediate() && args[0].GetImmediateU32() == 0) {
Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm();
code->xorps(result, result);
ctx.reg_alloc.DefineValue(inst, result);
} else {
ctx.reg_alloc.DefineValue(inst, args[0]);
}
}
template <typename JST>
void EmitX64<JST>::EmitTransferToFP64(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
if (args[0].IsImmediate() && args[0].GetImmediateU64() == 0) {
Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm();
code->xorps(result, result);
ctx.reg_alloc.DefineValue(inst, result);
} else {
ctx.reg_alloc.DefineValue(inst, args[0]);
}
}
template <typename JST> template <typename JST>
void EmitX64<JST>::EmitFPAbs32(EmitContext& ctx, IR::Inst* inst) { void EmitX64<JST>::EmitFPAbs32(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);

View file

@ -64,11 +64,7 @@ static size_t GetBitWidth(IR::Type type) {
return 32; return 32;
case IR::Type::U64: case IR::Type::U64:
return 64; return 64;
case IR::Type::F32: case IR::Type::U128:
return 32;
case IR::Type::F64:
return 64;
case IR::Type::F128:
return 128; return 128;
case IR::Type::NZCVFlags: case IR::Type::NZCVFlags:
return 32; // TODO: Update to 16 when flags optimization is done return 32; // TODO: Update to 16 when flags optimization is done

View file

@ -30,13 +30,13 @@ IR::U32 IREmitter::GetRegister(Reg reg) {
return Inst<IR::U32>(Opcode::A32GetRegister, IR::Value(reg)); return Inst<IR::U32>(Opcode::A32GetRegister, IR::Value(reg));
} }
IR::F32F64 IREmitter::GetExtendedRegister(ExtReg reg) { IR::U32U64 IREmitter::GetExtendedRegister(ExtReg reg) {
if (A32::IsSingleExtReg(reg)) { if (A32::IsSingleExtReg(reg)) {
return Inst<IR::F32F64>(Opcode::A32GetExtendedRegister32, IR::Value(reg)); return Inst<IR::U32U64>(Opcode::A32GetExtendedRegister32, IR::Value(reg));
} }
if (A32::IsDoubleExtReg(reg)) { if (A32::IsDoubleExtReg(reg)) {
return Inst<IR::F32F64>(Opcode::A32GetExtendedRegister64, IR::Value(reg)); return Inst<IR::U32U64>(Opcode::A32GetExtendedRegister64, IR::Value(reg));
} }
ASSERT_MSG(false, "Invalid reg."); ASSERT_MSG(false, "Invalid reg.");
@ -47,7 +47,7 @@ void IREmitter::SetRegister(const Reg reg, const IR::U32& value) {
Inst(Opcode::A32SetRegister, IR::Value(reg), value); Inst(Opcode::A32SetRegister, IR::Value(reg), value);
} }
void IREmitter::SetExtendedRegister(const ExtReg reg, const IR::F32F64& value) { void IREmitter::SetExtendedRegister(const ExtReg reg, const IR::U32U64& value) {
if (A32::IsSingleExtReg(reg)) { if (A32::IsSingleExtReg(reg)) {
Inst(Opcode::A32SetExtendedRegister32, IR::Value(reg), value); Inst(Opcode::A32SetExtendedRegister32, IR::Value(reg), value);
} else if (A32::IsDoubleExtReg(reg)) { } else if (A32::IsDoubleExtReg(reg)) {

View file

@ -34,9 +34,9 @@ public:
u32 AlignPC(size_t alignment); u32 AlignPC(size_t alignment);
IR::U32 GetRegister(Reg source_reg); IR::U32 GetRegister(Reg source_reg);
IR::F32F64 GetExtendedRegister(ExtReg source_reg); IR::U32U64 GetExtendedRegister(ExtReg source_reg);
void SetRegister(const Reg dest_reg, const IR::U32& value); void SetRegister(const Reg dest_reg, const IR::U32& value);
void SetExtendedRegister(const ExtReg dest_reg, const IR::F32F64& value); void SetExtendedRegister(const ExtReg dest_reg, const IR::U32U64& value);
void ALUWritePC(const IR::U32& value); void ALUWritePC(const IR::U32& value);
void BranchWritePC(const IR::U32& value); void BranchWritePC(const IR::U32& value);

View file

@ -9,9 +9,6 @@
namespace Dynarmic { namespace Dynarmic {
namespace A32 { namespace A32 {
using F32 = IR::F32;
using F64 = IR::F64;
static ExtReg ToExtReg(bool sz, size_t base, bool bit) { static ExtReg ToExtReg(bool sz, size_t base, bool bit) {
if (sz) { if (sz) {
return static_cast<ExtReg>(static_cast<size_t>(ExtReg::D0) + base + (bit ? 16 : 0)); return static_cast<ExtReg>(static_cast<size_t>(ExtReg::D0) + base + (bit ? 16 : 0));
@ -292,13 +289,11 @@ bool ArmTranslatorVisitor::vfp2_VMOV_u32_f64(Cond cond, size_t Vd, Reg t, bool D
return UnpredictableInstruction(); return UnpredictableInstruction();
// VMOV.32 <Dd[0]>, <Rt> // VMOV.32 <Dd[0]>, <Rt>
if (ConditionPassed(cond)) { if (ConditionPassed(cond)) {
auto d_f64 = ir.GetExtendedRegister(d); auto reg_d = ir.GetExtendedRegister(d);
auto t_u32 = ir.GetRegister(t); auto reg_t = ir.GetRegister(t);
auto result = ir.Pack2x32To1x64(reg_t, ir.MostSignificantWord(reg_d).result);
auto d_u64 = ir.TransferFromFP64(d_f64); ir.SetExtendedRegister(d, result);
auto result = ir.Pack2x32To1x64(t_u32, ir.MostSignificantWord(d_u64).result);
ir.SetExtendedRegister(d, ir.TransferToFP64(result));
} }
return true; return true;
} }
@ -309,8 +304,8 @@ bool ArmTranslatorVisitor::vfp2_VMOV_f64_u32(Cond cond, size_t Vn, Reg t, bool N
return UnpredictableInstruction(); return UnpredictableInstruction();
// VMOV.32 <Rt>, <Dn[0]> // VMOV.32 <Rt>, <Dn[0]>
if (ConditionPassed(cond)) { if (ConditionPassed(cond)) {
auto n_f64 = ir.GetExtendedRegister(n); auto reg_n = ir.GetExtendedRegister(n);
ir.SetRegister(t, ir.LeastSignificantWord(ir.TransferFromFP64(n_f64))); ir.SetRegister(t, ir.LeastSignificantWord(reg_n));
} }
return true; return true;
} }
@ -321,7 +316,7 @@ bool ArmTranslatorVisitor::vfp2_VMOV_u32_f32(Cond cond, size_t Vn, Reg t, bool N
return UnpredictableInstruction(); return UnpredictableInstruction();
// VMOV <Sn>, <Rt> // VMOV <Sn>, <Rt>
if (ConditionPassed(cond)) { if (ConditionPassed(cond)) {
ir.SetExtendedRegister(n, ir.TransferToFP32(ir.GetRegister(t))); ir.SetExtendedRegister(n, ir.GetRegister(t));
} }
return true; return true;
} }
@ -332,7 +327,7 @@ bool ArmTranslatorVisitor::vfp2_VMOV_f32_u32(Cond cond, size_t Vn, Reg t, bool N
return UnpredictableInstruction(); return UnpredictableInstruction();
// VMOV <Rt>, <Sn> // VMOV <Rt>, <Sn>
if (ConditionPassed(cond)) { if (ConditionPassed(cond)) {
ir.SetRegister(t, ir.TransferFromFP32(ir.GetExtendedRegister(n))); ir.SetRegister(t, ir.GetExtendedRegister(n));
} }
return true; return true;
} }
@ -343,8 +338,8 @@ bool ArmTranslatorVisitor::vfp2_VMOV_2u32_2f32(Cond cond, Reg t2, Reg t, bool M,
return UnpredictableInstruction(); return UnpredictableInstruction();
// VMOV <Sm>, <Sm1>, <Rt>, <Rt2> // VMOV <Sm>, <Sm1>, <Rt>, <Rt2>
if (ConditionPassed(cond)) { if (ConditionPassed(cond)) {
ir.SetExtendedRegister(m, ir.TransferToFP32(ir.GetRegister(t))); ir.SetExtendedRegister(m, ir.GetRegister(t));
ir.SetExtendedRegister(m+1, ir.TransferToFP32(ir.GetRegister(t2))); ir.SetExtendedRegister(m+1, ir.GetRegister(t2));
} }
return true; return true;
} }
@ -357,8 +352,8 @@ bool ArmTranslatorVisitor::vfp2_VMOV_2f32_2u32(Cond cond, Reg t2, Reg t, bool M,
return UnpredictableInstruction(); return UnpredictableInstruction();
// VMOV <Rt>, <Rt2>, <Sm>, <Sm1> // VMOV <Rt>, <Rt2>, <Sm>, <Sm1>
if (ConditionPassed(cond)) { if (ConditionPassed(cond)) {
ir.SetRegister(t, ir.TransferFromFP32(ir.GetExtendedRegister(m))); ir.SetRegister(t, ir.GetExtendedRegister(m));
ir.SetRegister(t2, ir.TransferFromFP32(ir.GetExtendedRegister(m+1))); ir.SetRegister(t2, ir.GetExtendedRegister(m+1));
} }
return true; return true;
} }
@ -370,7 +365,7 @@ bool ArmTranslatorVisitor::vfp2_VMOV_2u32_f64(Cond cond, Reg t2, Reg t, bool M,
// VMOV<c> <Dm>, <Rt>, <Rt2> // VMOV<c> <Dm>, <Rt>, <Rt2>
if (ConditionPassed(cond)) { if (ConditionPassed(cond)) {
auto value = ir.Pack2x32To1x64(ir.GetRegister(t), ir.GetRegister(t2)); auto value = ir.Pack2x32To1x64(ir.GetRegister(t), ir.GetRegister(t2));
ir.SetExtendedRegister(m, ir.TransferToFP64(value)); ir.SetExtendedRegister(m, value);
} }
return true; return true;
} }
@ -383,7 +378,7 @@ bool ArmTranslatorVisitor::vfp2_VMOV_f64_2u32(Cond cond, Reg t2, Reg t, bool M,
return UnpredictableInstruction(); return UnpredictableInstruction();
// VMOV<c> <Rt>, <Rt2>, <Dm> // VMOV<c> <Rt>, <Rt2>, <Dm>
if (ConditionPassed(cond)) { if (ConditionPassed(cond)) {
auto value = ir.TransferFromFP64(ir.GetExtendedRegister(m)); auto value = ir.GetExtendedRegister(m);
ir.SetRegister(t, ir.LeastSignificantWord(value)); ir.SetRegister(t, ir.LeastSignificantWord(value));
ir.SetRegister(t2, ir.MostSignificantWord(value).result); ir.SetRegister(t2, ir.MostSignificantWord(value).result);
} }
@ -556,11 +551,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) {
auto zero = ir.TransferToFP64(ir.Imm64(0)); ir.FPCompare64(reg_d, ir.Imm64(0), exc_on_qnan, true);
ir.FPCompare64(reg_d, zero, exc_on_qnan, true);
} else { } else {
auto zero = ir.TransferToFP32(ir.Imm32(0)); ir.FPCompare32(reg_d, ir.Imm32(0), exc_on_qnan, true);
ir.FPCompare32(reg_d, zero, exc_on_qnan, true);
} }
} }
return true; return true;
@ -615,10 +608,10 @@ bool ArmTranslatorVisitor::vfp2_VPOP(Cond cond, bool D, size_t Vd, bool sz, Imm8
auto hi = ir.ReadMemory32(address); auto hi = ir.ReadMemory32(address);
address = ir.Add(address, ir.Imm32(4)); address = ir.Add(address, ir.Imm32(4));
if (ir.current_location.EFlag()) std::swap(lo, hi); if (ir.current_location.EFlag()) std::swap(lo, hi);
ir.SetExtendedRegister(d + i, ir.TransferToFP64(ir.Pack2x32To1x64(lo, hi))); ir.SetExtendedRegister(d + i, ir.Pack2x32To1x64(lo, hi));
} else { } else {
auto res = ir.ReadMemory32(address); auto res = ir.ReadMemory32(address);
ir.SetExtendedRegister(d + i, ir.TransferToFP32(res)); ir.SetExtendedRegister(d + i, res);
address = ir.Add(address, ir.Imm32(4)); address = ir.Add(address, ir.Imm32(4));
} }
} }
@ -645,16 +638,16 @@ bool ArmTranslatorVisitor::vfp2_VPUSH(Cond cond, bool D, size_t Vd, bool sz, Imm
for (size_t i = 0; i < regs; ++i) { for (size_t i = 0; i < regs; ++i) {
if (sz) { if (sz) {
const auto d_u64 = ir.TransferFromFP64(ir.GetExtendedRegister(d + i)); const auto reg_d = ir.GetExtendedRegister(d + i);
auto lo = ir.LeastSignificantWord(d_u64); auto lo = ir.LeastSignificantWord(reg_d);
auto hi = ir.MostSignificantWord(d_u64).result; auto hi = ir.MostSignificantWord(reg_d).result;
if (ir.current_location.EFlag()) std::swap(lo, hi); if (ir.current_location.EFlag()) std::swap(lo, hi);
ir.WriteMemory32(address, lo); ir.WriteMemory32(address, lo);
address = ir.Add(address, ir.Imm32(4)); address = ir.Add(address, ir.Imm32(4));
ir.WriteMemory32(address, hi); ir.WriteMemory32(address, hi);
address = ir.Add(address, ir.Imm32(4)); address = ir.Add(address, ir.Imm32(4));
} else { } else {
ir.WriteMemory32(address, ir.TransferFromFP32(ir.GetExtendedRegister(d + i))); ir.WriteMemory32(address, ir.GetExtendedRegister(d + i));
address = ir.Add(address, ir.Imm32(4)); address = ir.Add(address, ir.Imm32(4));
} }
} }
@ -673,9 +666,9 @@ bool ArmTranslatorVisitor::vfp2_VLDR(Cond cond, bool U, bool D, Reg n, size_t Vd
auto lo = ir.ReadMemory32(address); auto lo = ir.ReadMemory32(address);
auto hi = ir.ReadMemory32(ir.Add(address, ir.Imm32(4))); auto hi = ir.ReadMemory32(ir.Add(address, ir.Imm32(4)));
if (ir.current_location.EFlag()) std::swap(lo, hi); if (ir.current_location.EFlag()) std::swap(lo, hi);
ir.SetExtendedRegister(d, ir.TransferToFP64(ir.Pack2x32To1x64(lo, hi))); ir.SetExtendedRegister(d, ir.Pack2x32To1x64(lo, hi));
} else { } else {
ir.SetExtendedRegister(d, ir.TransferToFP32(ir.ReadMemory32(address))); ir.SetExtendedRegister(d, ir.ReadMemory32(address));
} }
} }
return true; return true;
@ -689,14 +682,14 @@ bool ArmTranslatorVisitor::vfp2_VSTR(Cond cond, bool U, bool D, Reg n, size_t Vd
auto base = n == Reg::PC ? ir.Imm32(ir.AlignPC(4)) : ir.GetRegister(n); auto base = n == Reg::PC ? ir.Imm32(ir.AlignPC(4)) : ir.GetRegister(n);
auto address = U ? ir.Add(base, ir.Imm32(imm32)) : ir.Sub(base, ir.Imm32(imm32)); auto address = U ? ir.Add(base, ir.Imm32(imm32)) : ir.Sub(base, ir.Imm32(imm32));
if (sz) { if (sz) {
auto d_u64 = ir.TransferFromFP64(ir.GetExtendedRegister(d)); auto reg_d = ir.GetExtendedRegister(d);
auto lo = ir.LeastSignificantWord(d_u64); auto lo = ir.LeastSignificantWord(reg_d);
auto hi = ir.MostSignificantWord(d_u64).result; auto hi = ir.MostSignificantWord(reg_d).result;
if (ir.current_location.EFlag()) std::swap(lo, hi); if (ir.current_location.EFlag()) std::swap(lo, hi);
ir.WriteMemory32(address, lo); ir.WriteMemory32(address, lo);
ir.WriteMemory32(ir.Add(address, ir.Imm32(4)), hi); ir.WriteMemory32(ir.Add(address, ir.Imm32(4)), hi);
} else { } else {
ir.WriteMemory32(address, ir.TransferFromFP32(ir.GetExtendedRegister(d))); ir.WriteMemory32(address, ir.GetExtendedRegister(d));
} }
} }
return true; return true;
@ -725,7 +718,7 @@ bool ArmTranslatorVisitor::vfp2_VSTM_a1(Cond cond, bool p, bool u, bool D, bool
if (w) if (w)
ir.SetRegister(n, u ? ir.Add(address, ir.Imm32(imm32)) : address); ir.SetRegister(n, u ? ir.Add(address, ir.Imm32(imm32)) : address);
for (size_t i = 0; i < regs; i++) { for (size_t i = 0; i < regs; i++) {
auto value = ir.TransferFromFP64(ir.GetExtendedRegister(d + i)); auto value = ir.GetExtendedRegister(d + i);
auto word1 = ir.LeastSignificantWord(value); auto word1 = ir.LeastSignificantWord(value);
auto word2 = ir.MostSignificantWord(value).result; auto word2 = ir.MostSignificantWord(value).result;
if (ir.current_location.EFlag()) std::swap(word1, word2); if (ir.current_location.EFlag()) std::swap(word1, word2);
@ -761,7 +754,7 @@ bool ArmTranslatorVisitor::vfp2_VSTM_a2(Cond cond, bool p, bool u, bool D, bool
if (w) if (w)
ir.SetRegister(n, u ? ir.Add(address, ir.Imm32(imm32)) : address); ir.SetRegister(n, u ? ir.Add(address, ir.Imm32(imm32)) : address);
for (size_t i = 0; i < regs; i++) { for (size_t i = 0; i < regs; i++) {
auto word = ir.TransferFromFP32(ir.GetExtendedRegister(d + i)); auto word = ir.GetExtendedRegister(d + i);
ir.WriteMemory32(address, word); ir.WriteMemory32(address, word);
address = ir.Add(address, ir.Imm32(4)); address = ir.Add(address, ir.Imm32(4));
} }
@ -797,7 +790,7 @@ bool ArmTranslatorVisitor::vfp2_VLDM_a1(Cond cond, bool p, bool u, bool D, bool
auto word2 = ir.ReadMemory32(address); auto word2 = ir.ReadMemory32(address);
address = ir.Add(address, ir.Imm32(4)); address = ir.Add(address, ir.Imm32(4));
if (ir.current_location.EFlag()) std::swap(word1, word2); if (ir.current_location.EFlag()) std::swap(word1, word2);
ir.SetExtendedRegister(d + i, ir.TransferToFP64(ir.Pack2x32To1x64(word1, word2))); ir.SetExtendedRegister(d + i, ir.Pack2x32To1x64(word1, word2));
} }
} }
return true; return true;
@ -828,7 +821,7 @@ bool ArmTranslatorVisitor::vfp2_VLDM_a2(Cond cond, bool p, bool u, bool D, bool
for (size_t i = 0; i < regs; i++) { for (size_t i = 0; i < regs; i++) {
auto word = ir.ReadMemory32(address); auto word = ir.ReadMemory32(address);
address = ir.Add(address, ir.Imm32(4)); address = ir.Add(address, ir.Imm32(4));
ir.SetExtendedRegister(d + i, ir.TransferToFP32(word)); ir.SetExtendedRegister(d + i, word);
} }
} }
return true; return true;

View file

@ -604,144 +604,128 @@ U32 IREmitter::PackedSelect(const U32& ge, const U32& a, const U32& b) {
return Inst<U32>(Opcode::PackedSelect, ge, a, b); return Inst<U32>(Opcode::PackedSelect, ge, a, b);
} }
F32 IREmitter::TransferToFP32(const U32& a) { U32 IREmitter::FPAbs32(const U32& a) {
return Inst<F32>(Opcode::TransferToFP32, a); return Inst<U32>(Opcode::FPAbs32, a);
} }
F64 IREmitter::TransferToFP64(const U64& a) { U64 IREmitter::FPAbs64(const U64& a) {
return Inst<F64>(Opcode::TransferToFP64, a); return Inst<U64>(Opcode::FPAbs64, a);
} }
U32 IREmitter::TransferFromFP32(const F32& a) { U32 IREmitter::FPAdd32(const U32& a, const U32& b, bool fpscr_controlled) {
return Inst<U32>(Opcode::TransferFromFP32, a);
}
U64 IREmitter::TransferFromFP64(const F64& a) {
return Inst<U64>(Opcode::TransferFromFP64, a);
}
F32 IREmitter::FPAbs32(const F32& a) {
return Inst<F32>(Opcode::FPAbs32, a);
}
F64 IREmitter::FPAbs64(const F64& a) {
return Inst<F64>(Opcode::FPAbs64, a);
}
F32 IREmitter::FPAdd32(const F32& a, const F32& b, bool fpscr_controlled) {
ASSERT(fpscr_controlled); ASSERT(fpscr_controlled);
return Inst<F32>(Opcode::FPAdd32, a, b); return Inst<U32>(Opcode::FPAdd32, a, b);
} }
F64 IREmitter::FPAdd64(const F64& a, const F64& b, bool fpscr_controlled) { U64 IREmitter::FPAdd64(const U64& a, const U64& b, bool fpscr_controlled) {
ASSERT(fpscr_controlled); ASSERT(fpscr_controlled);
return Inst<F64>(Opcode::FPAdd64, a, b); return Inst<U64>(Opcode::FPAdd64, a, b);
} }
void IREmitter::FPCompare32(const F32& a, const F32& b, bool exc_on_qnan, bool fpscr_controlled) { void IREmitter::FPCompare32(const U32& a, const U32& b, bool exc_on_qnan, bool fpscr_controlled) {
ASSERT(fpscr_controlled); ASSERT(fpscr_controlled);
Inst(Opcode::FPCompare32, a, b, Imm1(exc_on_qnan)); Inst(Opcode::FPCompare32, a, b, Imm1(exc_on_qnan));
} }
void IREmitter::FPCompare64(const F64& a, const F64& b, bool exc_on_qnan, bool fpscr_controlled) { void IREmitter::FPCompare64(const U64& a, const U64& b, bool exc_on_qnan, bool fpscr_controlled) {
ASSERT(fpscr_controlled); ASSERT(fpscr_controlled);
Inst(Opcode::FPCompare64, a, b, Imm1(exc_on_qnan)); Inst(Opcode::FPCompare64, a, b, Imm1(exc_on_qnan));
} }
F32 IREmitter::FPDiv32(const F32& a, const F32& b, bool fpscr_controlled) { U32 IREmitter::FPDiv32(const U32& a, const U32& b, bool fpscr_controlled) {
ASSERT(fpscr_controlled); ASSERT(fpscr_controlled);
return Inst<F32>(Opcode::FPDiv32, a, b); return Inst<U32>(Opcode::FPDiv32, a, b);
} }
F64 IREmitter::FPDiv64(const F64& a, const F64& b, bool fpscr_controlled) { U64 IREmitter::FPDiv64(const U64& a, const U64& b, bool fpscr_controlled) {
ASSERT(fpscr_controlled); ASSERT(fpscr_controlled);
return Inst<F64>(Opcode::FPDiv64, a, b); return Inst<U64>(Opcode::FPDiv64, a, b);
} }
F32 IREmitter::FPMul32(const F32& a, const F32& b, bool fpscr_controlled) { U32 IREmitter::FPMul32(const U32& a, const U32& b, bool fpscr_controlled) {
ASSERT(fpscr_controlled); ASSERT(fpscr_controlled);
return Inst<F32>(Opcode::FPMul32, a, b); return Inst<U32>(Opcode::FPMul32, a, b);
} }
F64 IREmitter::FPMul64(const F64& a, const F64& b, bool fpscr_controlled) { U64 IREmitter::FPMul64(const U64& a, const U64& b, bool fpscr_controlled) {
ASSERT(fpscr_controlled); ASSERT(fpscr_controlled);
return Inst<F64>(Opcode::FPMul64, a, b); return Inst<U64>(Opcode::FPMul64, a, b);
} }
F32 IREmitter::FPNeg32(const F32& a) { U32 IREmitter::FPNeg32(const U32& a) {
return Inst<F32>(Opcode::FPNeg32, a); return Inst<U32>(Opcode::FPNeg32, a);
} }
F64 IREmitter::FPNeg64(const F64& a) { U64 IREmitter::FPNeg64(const U64& a) {
return Inst<F64>(Opcode::FPNeg64, a); return Inst<U64>(Opcode::FPNeg64, a);
} }
F32 IREmitter::FPSqrt32(const F32& a) { U32 IREmitter::FPSqrt32(const U32& a) {
return Inst<F32>(Opcode::FPSqrt32, a); return Inst<U32>(Opcode::FPSqrt32, a);
} }
F64 IREmitter::FPSqrt64(const F64& a) { U64 IREmitter::FPSqrt64(const U64& a) {
return Inst<F64>(Opcode::FPSqrt64, a); return Inst<U64>(Opcode::FPSqrt64, a);
} }
F32 IREmitter::FPSub32(const F32& a, const F32& b, bool fpscr_controlled) { U32 IREmitter::FPSub32(const U32& a, const U32& b, bool fpscr_controlled) {
ASSERT(fpscr_controlled); ASSERT(fpscr_controlled);
return Inst<F32>(Opcode::FPSub32, a, b); return Inst<U32>(Opcode::FPSub32, a, b);
} }
F64 IREmitter::FPSub64(const F64& a, const F64& b, bool fpscr_controlled) { U64 IREmitter::FPSub64(const U64& a, const U64& b, bool fpscr_controlled) {
ASSERT(fpscr_controlled); ASSERT(fpscr_controlled);
return Inst<F64>(Opcode::FPSub64, a, b); return Inst<U64>(Opcode::FPSub64, a, b);
} }
F32 IREmitter::FPDoubleToSingle(const F64& a, bool fpscr_controlled) { U32 IREmitter::FPDoubleToSingle(const U64& a, bool fpscr_controlled) {
ASSERT(fpscr_controlled); ASSERT(fpscr_controlled);
return Inst<F32>(Opcode::FPDoubleToSingle, a); return Inst<U32>(Opcode::FPDoubleToSingle, a);
} }
F64 IREmitter::FPSingleToDouble(const F32& a, bool fpscr_controlled) { U64 IREmitter::FPSingleToDouble(const U32& a, bool fpscr_controlled) {
ASSERT(fpscr_controlled); ASSERT(fpscr_controlled);
return Inst<F64>(Opcode::FPSingleToDouble, a); return Inst<U64>(Opcode::FPSingleToDouble, a);
} }
F32 IREmitter::FPSingleToS32(const F32& a, bool round_towards_zero, bool fpscr_controlled) { U32 IREmitter::FPSingleToS32(const U32& a, bool round_towards_zero, bool fpscr_controlled) {
ASSERT(fpscr_controlled); ASSERT(fpscr_controlled);
return Inst<F32>(Opcode::FPSingleToS32, a, Imm1(round_towards_zero)); return Inst<U32>(Opcode::FPSingleToS32, a, Imm1(round_towards_zero));
} }
F32 IREmitter::FPSingleToU32(const F32& a, bool round_towards_zero, bool fpscr_controlled) { U32 IREmitter::FPSingleToU32(const U32& a, bool round_towards_zero, bool fpscr_controlled) {
ASSERT(fpscr_controlled); ASSERT(fpscr_controlled);
return Inst<F32>(Opcode::FPSingleToU32, a, Imm1(round_towards_zero)); return Inst<U32>(Opcode::FPSingleToU32, a, Imm1(round_towards_zero));
} }
F32 IREmitter::FPDoubleToS32(const F32& a, bool round_towards_zero, bool fpscr_controlled) { U32 IREmitter::FPDoubleToS32(const U32& a, bool round_towards_zero, bool fpscr_controlled) {
ASSERT(fpscr_controlled); ASSERT(fpscr_controlled);
return Inst<F32>(Opcode::FPDoubleToS32, a, Imm1(round_towards_zero)); return Inst<U32>(Opcode::FPDoubleToS32, a, Imm1(round_towards_zero));
} }
F32 IREmitter::FPDoubleToU32(const F32& a, bool round_towards_zero, bool fpscr_controlled) { U32 IREmitter::FPDoubleToU32(const U32& a, bool round_towards_zero, bool fpscr_controlled) {
ASSERT(fpscr_controlled); ASSERT(fpscr_controlled);
return Inst<F32>(Opcode::FPDoubleToU32, a, Imm1(round_towards_zero)); return Inst<U32>(Opcode::FPDoubleToU32, a, Imm1(round_towards_zero));
} }
F32 IREmitter::FPS32ToSingle(const F32& a, bool round_to_nearest, bool fpscr_controlled) { U32 IREmitter::FPS32ToSingle(const U32& a, bool round_to_nearest, bool fpscr_controlled) {
ASSERT(fpscr_controlled); ASSERT(fpscr_controlled);
return Inst<F32>(Opcode::FPS32ToSingle, a, Imm1(round_to_nearest)); return Inst<U32>(Opcode::FPS32ToSingle, a, Imm1(round_to_nearest));
} }
F32 IREmitter::FPU32ToSingle(const F32& a, bool round_to_nearest, bool fpscr_controlled) { U32 IREmitter::FPU32ToSingle(const U32& a, bool round_to_nearest, bool fpscr_controlled) {
ASSERT(fpscr_controlled); ASSERT(fpscr_controlled);
return Inst<F32>(Opcode::FPU32ToSingle, a, Imm1(round_to_nearest)); return Inst<U32>(Opcode::FPU32ToSingle, a, Imm1(round_to_nearest));
} }
F64 IREmitter::FPS32ToDouble(const F32& a, bool round_to_nearest, bool fpscr_controlled) { U64 IREmitter::FPS32ToDouble(const U32& a, bool round_to_nearest, bool fpscr_controlled) {
ASSERT(fpscr_controlled); ASSERT(fpscr_controlled);
return Inst<F64>(Opcode::FPS32ToDouble, a, Imm1(round_to_nearest)); return Inst<U64>(Opcode::FPS32ToDouble, a, Imm1(round_to_nearest));
} }
F64 IREmitter::FPU32ToDouble(const F32& a, bool round_to_nearest, bool fpscr_controlled) { U64 IREmitter::FPU32ToDouble(const U32& a, bool round_to_nearest, bool fpscr_controlled) {
ASSERT(fpscr_controlled); ASSERT(fpscr_controlled);
return Inst<F64>(Opcode::FPU32ToDouble, a, Imm1(round_to_nearest)); return Inst<U64>(Opcode::FPU32ToDouble, a, Imm1(round_to_nearest));
} }
void IREmitter::Breakpoint() { void IREmitter::Breakpoint() {

View file

@ -177,36 +177,32 @@ public:
U32 PackedAbsDiffSumS8(const U32& a, const U32& b); U32 PackedAbsDiffSumS8(const U32& a, const U32& b);
U32 PackedSelect(const U32& ge, const U32& a, const U32& b); U32 PackedSelect(const U32& ge, const U32& a, const U32& b);
F32 TransferToFP32(const U32& a); U32 FPAbs32(const U32& a);
F64 TransferToFP64(const U64& a); U64 FPAbs64(const U64& a);
U32 TransferFromFP32(const F32& a); U32 FPAdd32(const U32& a, const U32& b, bool fpscr_controlled);
U64 TransferFromFP64(const F64& a); U64 FPAdd64(const U64& a, const U64& b, bool fpscr_controlled);
F32 FPAbs32(const F32& a); void FPCompare32(const U32& a, const U32& b, bool exc_on_qnan, bool fpscr_controlled);
F64 FPAbs64(const F64& a); void FPCompare64(const U64& a, const U64& b, bool exc_on_qnan, bool fpscr_controlled);
F32 FPAdd32(const F32& a, const F32& b, bool fpscr_controlled); U32 FPDiv32(const U32& a, const U32& b, bool fpscr_controlled);
F64 FPAdd64(const F64& a, const F64& b, bool fpscr_controlled); U64 FPDiv64(const U64& a, const U64& b, bool fpscr_controlled);
void FPCompare32(const F32& a, const F32& b, bool exc_on_qnan, bool fpscr_controlled); U32 FPMul32(const U32& a, const U32& b, bool fpscr_controlled);
void FPCompare64(const F64& a, const F64& b, bool exc_on_qnan, bool fpscr_controlled); U64 FPMul64(const U64& a, const U64& b, bool fpscr_controlled);
F32 FPDiv32(const F32& a, const F32& b, bool fpscr_controlled); U32 FPNeg32(const U32& a);
F64 FPDiv64(const F64& a, const F64& b, bool fpscr_controlled); U64 FPNeg64(const U64& a);
F32 FPMul32(const F32& a, const F32& b, bool fpscr_controlled); U32 FPSqrt32(const U32& a);
F64 FPMul64(const F64& a, const F64& b, bool fpscr_controlled); U64 FPSqrt64(const U64& a);
F32 FPNeg32(const F32& a); U32 FPSub32(const U32& a, const U32& b, bool fpscr_controlled);
F64 FPNeg64(const F64& a); U64 FPSub64(const U64& a, const U64& b, bool fpscr_controlled);
F32 FPSqrt32(const F32& a); U32 FPDoubleToSingle(const U64& a, bool fpscr_controlled);
F64 FPSqrt64(const F64& a); U64 FPSingleToDouble(const U32& a, bool fpscr_controlled);
F32 FPSub32(const F32& a, const F32& b, bool fpscr_controlled); U32 FPSingleToS32(const U32& a, bool round_towards_zero, bool fpscr_controlled);
F64 FPSub64(const F64& a, const F64& b, bool fpscr_controlled); U32 FPSingleToU32(const U32& a, bool round_towards_zero, bool fpscr_controlled);
F32 FPDoubleToSingle(const F64& a, bool fpscr_controlled); U32 FPDoubleToS32(const U32& a, bool round_towards_zero, bool fpscr_controlled);
F64 FPSingleToDouble(const F32& a, bool fpscr_controlled); U32 FPDoubleToU32(const U32& a, bool round_towards_zero, bool fpscr_controlled);
F32 FPSingleToS32(const F32& a, bool round_towards_zero, bool fpscr_controlled); U32 FPS32ToSingle(const U32& a, bool round_to_nearest, bool fpscr_controlled);
F32 FPSingleToU32(const F32& a, bool round_towards_zero, bool fpscr_controlled); U32 FPU32ToSingle(const U32& a, bool round_to_nearest, bool fpscr_controlled);
F32 FPDoubleToS32(const F32& a, bool round_towards_zero, bool fpscr_controlled); U64 FPS32ToDouble(const U32& a, bool round_to_nearest, bool fpscr_controlled);
F32 FPDoubleToU32(const F32& a, bool round_towards_zero, bool fpscr_controlled); U64 FPU32ToDouble(const U32& a, bool round_to_nearest, bool fpscr_controlled);
F32 FPS32ToSingle(const F32& a, bool round_to_nearest, bool fpscr_controlled);
F32 FPU32ToSingle(const F32& a, bool round_to_nearest, bool fpscr_controlled);
F64 FPS32ToDouble(const F32& a, bool round_to_nearest, bool fpscr_controlled);
F64 FPU32ToDouble(const F32& a, bool round_to_nearest, bool fpscr_controlled);
void Breakpoint(); void Breakpoint();

View file

@ -43,12 +43,10 @@ enum class Type {
U16 = 1 << 7, U16 = 1 << 7,
U32 = 1 << 8, U32 = 1 << 8,
U64 = 1 << 9, U64 = 1 << 9,
F32 = 1 << 10, U128 = 1 << 10,
F64 = 1 << 11, CoprocInfo = 1 << 11,
F128 = 1 << 12, NZCVFlags = 1 << 12,
CoprocInfo = 1 << 13, Cond = 1 << 13,
NZCVFlags = 1 << 14,
Cond = 1 << 15,
}; };
constexpr Type operator|(Type a, Type b) { constexpr Type operator|(Type a, Type b) {

View file

@ -6,11 +6,11 @@ OPCODE(Breakpoint, T::Void,
// A32 Context getters/setters // A32 Context getters/setters
A32OPC(GetRegister, T::U32, T::A32Reg ) A32OPC(GetRegister, T::U32, T::A32Reg )
A32OPC(GetExtendedRegister32, T::F32, T::A32ExtReg ) A32OPC(GetExtendedRegister32, T::U32, T::A32ExtReg )
A32OPC(GetExtendedRegister64, T::F64, T::A32ExtReg ) A32OPC(GetExtendedRegister64, T::U64, T::A32ExtReg )
A32OPC(SetRegister, T::Void, T::A32Reg, T::U32 ) A32OPC(SetRegister, T::Void, T::A32Reg, T::U32 )
A32OPC(SetExtendedRegister32, T::Void, T::A32ExtReg, T::F32 ) A32OPC(SetExtendedRegister32, T::Void, T::A32ExtReg, T::U32 )
A32OPC(SetExtendedRegister64, T::Void, T::A32ExtReg, T::F64 ) A32OPC(SetExtendedRegister64, T::Void, T::A32ExtReg, T::U64 )
A32OPC(GetCpsr, T::U32, ) A32OPC(GetCpsr, T::U32, )
A32OPC(SetCpsr, T::Void, T::U32 ) A32OPC(SetCpsr, T::Void, T::U32 )
A32OPC(SetCpsrNZCV, T::Void, T::U32 ) A32OPC(SetCpsrNZCV, T::Void, T::U32 )
@ -150,38 +150,34 @@ OPCODE(PackedAbsDiffSumS8, T::U32, T::U32, T::U32
OPCODE(PackedSelect, T::U32, T::U32, T::U32, T::U32 ) OPCODE(PackedSelect, T::U32, T::U32, T::U32, T::U32 )
// Floating-point operations // Floating-point operations
OPCODE(TransferToFP32, T::F32, T::U32 ) OPCODE(FPAbs32, T::U32, T::U32 )
OPCODE(TransferToFP64, T::F64, T::U64 ) OPCODE(FPAbs64, T::U64, T::U64 )
OPCODE(TransferFromFP32, T::U32, T::F32 ) OPCODE(FPAdd32, T::U32, T::U32, T::U32 )
OPCODE(TransferFromFP64, T::U64, T::F64 ) OPCODE(FPAdd64, T::U64, T::U64, T::U64 )
OPCODE(FPAbs32, T::F32, T::F32 ) OPCODE(FPCompare32, T::Void, T::U32, T::U32, T::U1 )
OPCODE(FPAbs64, T::F64, T::F64 ) OPCODE(FPCompare64, T::Void, T::U64, T::U64, T::U1 )
OPCODE(FPAdd32, T::F32, T::F32, T::F32 ) OPCODE(FPDiv32, T::U32, T::U32, T::U32 )
OPCODE(FPAdd64, T::F64, T::F64, T::F64 ) OPCODE(FPDiv64, T::U64, T::U64, T::U64 )
OPCODE(FPCompare32, T::Void, T::F32, T::F32, T::U1 ) OPCODE(FPMul32, T::U32, T::U32, T::U32 )
OPCODE(FPCompare64, T::Void, T::F64, T::F64, T::U1 ) OPCODE(FPMul64, T::U64, T::U64, T::U64 )
OPCODE(FPDiv32, T::F32, T::F32, T::F32 ) OPCODE(FPNeg32, T::U32, T::U32 )
OPCODE(FPDiv64, T::F64, T::F64, T::F64 ) OPCODE(FPNeg64, T::U64, T::U64 )
OPCODE(FPMul32, T::F32, T::F32, T::F32 ) OPCODE(FPSqrt32, T::U32, T::U32 )
OPCODE(FPMul64, T::F64, T::F64, T::F64 ) OPCODE(FPSqrt64, T::U64, T::U64 )
OPCODE(FPNeg32, T::F32, T::F32 ) OPCODE(FPSub32, T::U32, T::U32, T::U32 )
OPCODE(FPNeg64, T::F64, T::F64 ) OPCODE(FPSub64, T::U64, T::U64, T::U64 )
OPCODE(FPSqrt32, T::F32, T::F32 )
OPCODE(FPSqrt64, T::F64, T::F64 )
OPCODE(FPSub32, T::F32, T::F32, T::F32 )
OPCODE(FPSub64, T::F64, T::F64, T::F64 )
// Floating-point conversions // Floating-point conversions
OPCODE(FPSingleToDouble, T::F64, T::F32 ) OPCODE(FPSingleToDouble, T::U64, T::U32 )
OPCODE(FPDoubleToSingle, T::F32, T::F64 ) OPCODE(FPDoubleToSingle, T::U32, T::U64 )
OPCODE(FPSingleToU32, T::F32, T::F32, T::U1 ) OPCODE(FPSingleToU32, T::U32, T::U32, T::U1 )
OPCODE(FPSingleToS32, T::F32, T::F32, T::U1 ) OPCODE(FPSingleToS32, T::U32, T::U32, T::U1 )
OPCODE(FPDoubleToU32, T::F32, T::F64, T::U1 ) OPCODE(FPDoubleToU32, T::U32, T::U64, T::U1 )
OPCODE(FPDoubleToS32, T::F32, T::F64, T::U1 ) OPCODE(FPDoubleToS32, T::U32, T::U64, T::U1 )
OPCODE(FPU32ToSingle, T::F32, T::F32, T::U1 ) OPCODE(FPU32ToSingle, T::U32, T::U32, T::U1 )
OPCODE(FPS32ToSingle, T::F32, T::F32, T::U1 ) OPCODE(FPS32ToSingle, T::U32, T::U32, T::U1 )
OPCODE(FPU32ToDouble, T::F64, T::F32, T::U1 ) OPCODE(FPU32ToDouble, T::U64, T::U32, T::U1 )
OPCODE(FPS32ToDouble, T::F64, T::F32, T::U1 ) OPCODE(FPS32ToDouble, T::U64, T::U32, T::U1 )
// A32 Memory access // A32 Memory access
A32OPC(ClearExclusive, T::Void, ) A32OPC(ClearExclusive, T::Void, )

View file

@ -97,12 +97,9 @@ using U8 = TypedValue<Type::U8>;
using U16 = TypedValue<Type::U16>; using U16 = TypedValue<Type::U16>;
using U32 = TypedValue<Type::U32>; using U32 = TypedValue<Type::U32>;
using U64 = TypedValue<Type::U64>; using U64 = TypedValue<Type::U64>;
using U128 = TypedValue<Type::U128>;
using U32U64 = TypedValue<Type::U32 | Type::U64>; using U32U64 = TypedValue<Type::U32 | Type::U64>;
using UAny = TypedValue<Type::U8 | Type::U16 | Type::U32 | Type::U64>; using UAny = TypedValue<Type::U8 | Type::U16 | Type::U32 | Type::U64>;
using F32 = TypedValue<Type::F32>;
using F64 = TypedValue<Type::F64>;
using F128 = TypedValue<Type::F128>;
using F32F64 = TypedValue<Type::F32 | Type::F64>;
using NZCV = TypedValue<Type::NZCVFlags>; using NZCV = TypedValue<Type::NZCVFlags>;
} // namespace IR } // namespace IR