IR: Add fbits argument to FixedToFP-related opcodes

This commit is contained in:
MerryMage 2018-09-18 20:36:37 +01:00
parent 616a153c16
commit 90193b0e3d
8 changed files with 154 additions and 134 deletions

View file

@ -1201,82 +1201,115 @@ void EmitX64::EmitFPSingleToFixedU64(EmitContext& ctx, IR::Inst* inst) {
EmitFPToFixed(code, ctx, inst, 32, true, 64); EmitFPToFixed(code, ctx, inst, 32, true, 64);
} }
void EmitX64::EmitFPS32ToSingle(EmitContext& ctx, IR::Inst* inst) { void EmitX64::EmitFPFixedS32ToSingle(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg32 from = ctx.reg_alloc.UseGpr(args[0]).cvt32();
Xbyak::Xmm to = ctx.reg_alloc.ScratchXmm();
bool round_to_nearest = args[1].GetImmediateU1();
ASSERT_MSG(!round_to_nearest, "round_to_nearest unimplemented");
code.cvtsi2ss(to, from); const Xbyak::Reg32 from = ctx.reg_alloc.UseGpr(args[0]).cvt32();
const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm();
const size_t fbits = args[1].GetImmediateU8();
const FP::RoundingMode rounding_mode = static_cast<FP::RoundingMode>(args[2].GetImmediateU8());
ASSERT(rounding_mode == ctx.FPSCR_RMode());
ctx.reg_alloc.DefineValue(inst, to); code.cvtsi2ss(result, from);
if (fbits != 0) {
const u32 scale_factor = static_cast<u32>((127 - fbits) << 23);
code.mulss(result, code.MConst(xword, scale_factor));
}
ctx.reg_alloc.DefineValue(inst, result);
} }
void EmitX64::EmitFPU32ToSingle(EmitContext& ctx, IR::Inst* inst) { void EmitX64::EmitFPFixedU32ToSingle(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const Xbyak::Xmm to = ctx.reg_alloc.ScratchXmm(); const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm();
const bool round_to_nearest = args[1].GetImmediateU1(); const size_t fbits = args[1].GetImmediateU8();
ASSERT_MSG(!round_to_nearest, "round_to_nearest unimplemented"); const FP::RoundingMode rounding_mode = static_cast<FP::RoundingMode>(args[2].GetImmediateU8());
ASSERT(rounding_mode == ctx.FPSCR_RMode());
if (code.DoesCpuSupport(Xbyak::util::Cpu::tAVX512F)) { if (code.DoesCpuSupport(Xbyak::util::Cpu::tAVX512F)) {
const Xbyak::Reg64 from = ctx.reg_alloc.UseGpr(args[0]); const Xbyak::Reg64 from = ctx.reg_alloc.UseGpr(args[0]);
code.vcvtusi2ss(to, to, from.cvt32()); code.vcvtusi2ss(result, result, from.cvt32());
} else { } else {
// We are using a 64-bit GPR register to ensure we don't end up treating the input as signed // We are using a 64-bit GPR register to ensure we don't end up treating the input as signed
const Xbyak::Reg64 from = ctx.reg_alloc.UseScratchGpr(args[0]); const Xbyak::Reg64 from = ctx.reg_alloc.UseScratchGpr(args[0]);
code.mov(from.cvt32(), from.cvt32()); // TODO: Verify if this is necessary code.mov(from.cvt32(), from.cvt32()); // TODO: Verify if this is necessary
code.cvtsi2ss(to, from); code.cvtsi2ss(result, from);
} }
ctx.reg_alloc.DefineValue(inst, to); if (fbits != 0) {
const u32 scale_factor = static_cast<u32>((127 - fbits) << 23);
code.mulss(result, code.MConst(xword, scale_factor));
}
ctx.reg_alloc.DefineValue(inst, result);
} }
void EmitX64::EmitFPS32ToDouble(EmitContext& ctx, IR::Inst* inst) { void EmitX64::EmitFPFixedS32ToDouble(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
Xbyak::Reg32 from = ctx.reg_alloc.UseGpr(args[0]).cvt32();
Xbyak::Xmm to = ctx.reg_alloc.ScratchXmm();
bool round_to_nearest = args[1].GetImmediateU1();
ASSERT_MSG(!round_to_nearest, "round_to_nearest unimplemented");
code.cvtsi2sd(to, from);
ctx.reg_alloc.DefineValue(inst, to);
}
void EmitX64::EmitFPS64ToDouble(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const Xbyak::Reg64 from = ctx.reg_alloc.UseGpr(args[0]); const Xbyak::Reg32 from = ctx.reg_alloc.UseGpr(args[0]).cvt32();
const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm(); const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm();
const bool round_to_nearest = args[1].GetImmediateU1(); const size_t fbits = args[1].GetImmediateU8();
ASSERT_MSG(!round_to_nearest, "round_to_nearest unimplemented"); const FP::RoundingMode rounding_mode = static_cast<FP::RoundingMode>(args[2].GetImmediateU8());
ASSERT(rounding_mode == ctx.FPSCR_RMode());
code.cvtsi2sd(result, from); code.cvtsi2sd(result, from);
if (fbits != 0) {
const u64 scale_factor = static_cast<u64>((1023 - fbits) << 52);
code.mulsd(result, code.MConst(xword, scale_factor));
}
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
void EmitX64::EmitFPS64ToSingle(EmitContext& ctx, IR::Inst* inst) { void EmitX64::EmitFPFixedS64ToDouble(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const Xbyak::Reg64 from = ctx.reg_alloc.UseGpr(args[0]); const Xbyak::Reg64 from = ctx.reg_alloc.UseGpr(args[0]);
const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm(); const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm();
const bool round_to_nearest = args[1].GetImmediateU1(); const size_t fbits = args[1].GetImmediateU8();
ASSERT_MSG(!round_to_nearest, "round_to_nearest unimplemented"); const FP::RoundingMode rounding_mode = static_cast<FP::RoundingMode>(args[2].GetImmediateU8());
ASSERT(rounding_mode == ctx.FPSCR_RMode());
code.cvtsi2ss(result, from); code.cvtsi2sd(result, from);
if (fbits != 0) {
const u64 scale_factor = static_cast<u64>((1023 - fbits) << 52);
code.mulsd(result, code.MConst(xword, scale_factor));
}
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
void EmitX64::EmitFPU32ToDouble(EmitContext& ctx, IR::Inst* inst) { void EmitX64::EmitFPFixedS64ToSingle(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const Xbyak::Reg64 from = ctx.reg_alloc.UseGpr(args[0]);
const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm();
const size_t fbits = args[1].GetImmediateU8();
const FP::RoundingMode rounding_mode = static_cast<FP::RoundingMode>(args[2].GetImmediateU8());
ASSERT(rounding_mode == ctx.FPSCR_RMode());
code.cvtsi2ss(result, from);
if (fbits != 0) {
const u32 scale_factor = static_cast<u32>((127 - fbits) << 23);
code.mulss(result, code.MConst(xword, scale_factor));
}
ctx.reg_alloc.DefineValue(inst, result);
}
void EmitX64::EmitFPFixedU32ToDouble(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const Xbyak::Xmm to = ctx.reg_alloc.ScratchXmm(); const Xbyak::Xmm to = ctx.reg_alloc.ScratchXmm();
const bool round_to_nearest = args[1].GetImmediateU1(); const size_t fbits = args[1].GetImmediateU8();
ASSERT_MSG(!round_to_nearest, "round_to_nearest unimplemented"); const FP::RoundingMode rounding_mode = static_cast<FP::RoundingMode>(args[2].GetImmediateU8());
ASSERT(rounding_mode == ctx.FPSCR_RMode());
if (code.DoesCpuSupport(Xbyak::util::Cpu::tAVX512F)) { if (code.DoesCpuSupport(Xbyak::util::Cpu::tAVX512F)) {
const Xbyak::Reg64 from = ctx.reg_alloc.UseGpr(args[0]); const Xbyak::Reg64 from = ctx.reg_alloc.UseGpr(args[0]);
@ -1288,16 +1321,22 @@ void EmitX64::EmitFPU32ToDouble(EmitContext& ctx, IR::Inst* inst) {
code.cvtsi2sd(to, from); code.cvtsi2sd(to, from);
} }
if (fbits != 0) {
const u64 scale_factor = static_cast<u64>((1023 - fbits) << 52);
code.mulsd(to, code.MConst(xword, scale_factor));
}
ctx.reg_alloc.DefineValue(inst, to); ctx.reg_alloc.DefineValue(inst, to);
} }
void EmitX64::EmitFPU64ToDouble(EmitContext& ctx, IR::Inst* inst) { void EmitX64::EmitFPFixedU64ToDouble(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const Xbyak::Reg64 from = ctx.reg_alloc.UseGpr(args[0]); const Xbyak::Reg64 from = ctx.reg_alloc.UseGpr(args[0]);
const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm(); const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm();
const bool round_to_nearest = args[1].GetImmediateU1(); const size_t fbits = args[1].GetImmediateU8();
ASSERT_MSG(!round_to_nearest, "round_to_nearest unimplemented"); const FP::RoundingMode rounding_mode = static_cast<FP::RoundingMode>(args[2].GetImmediateU8());
ASSERT(rounding_mode == ctx.FPSCR_RMode());
if (code.DoesCpuSupport(Xbyak::util::Cpu::tAVX512F)) { if (code.DoesCpuSupport(Xbyak::util::Cpu::tAVX512F)) {
code.vcvtusi2sd(result, result, from); code.vcvtusi2sd(result, result, from);
@ -1314,15 +1353,21 @@ void EmitX64::EmitFPU64ToDouble(EmitContext& ctx, IR::Inst* inst) {
} }
} }
if (fbits != 0) {
const u64 scale_factor = static_cast<u64>((1023 - fbits) << 52);
code.mulsd(result, code.MConst(xword, scale_factor));
}
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
void EmitX64::EmitFPU64ToSingle(EmitContext& ctx, IR::Inst* inst) { void EmitX64::EmitFPFixedU64ToSingle(EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst); auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm(); const Xbyak::Xmm result = ctx.reg_alloc.ScratchXmm();
const bool round_to_nearest = args[1].GetImmediateU1(); const size_t fbits = args[1].GetImmediateU8();
ASSERT_MSG(!round_to_nearest, "round_to_nearest unimplemented"); const FP::RoundingMode rounding_mode = static_cast<FP::RoundingMode>(args[2].GetImmediateU8());
ASSERT(rounding_mode == ctx.FPSCR_RMode());
if (code.DoesCpuSupport(Xbyak::util::Cpu::tAVX512F)) { if (code.DoesCpuSupport(Xbyak::util::Cpu::tAVX512F)) {
const Xbyak::Reg64 from = ctx.reg_alloc.UseGpr(args[0]); const Xbyak::Reg64 from = ctx.reg_alloc.UseGpr(args[0]);
@ -1352,6 +1397,11 @@ void EmitX64::EmitFPU64ToSingle(EmitContext& ctx, IR::Inst* inst) {
code.L(end); code.L(end);
} }
if (fbits != 0) {
const u32 scale_factor = static_cast<u32>((127 - fbits) << 23);
code.mulss(result, code.MConst(xword, scale_factor));
}
ctx.reg_alloc.DefineValue(inst, result); ctx.reg_alloc.DefineValue(inst, result);
} }
} // namespace Dynarmic::BackendX64 } // namespace Dynarmic::BackendX64

View file

@ -414,20 +414,20 @@ bool ArmTranslatorVisitor::vfp2_VCVT_f_to_f(Cond cond, bool D, size_t Vd, bool s
bool ArmTranslatorVisitor::vfp2_VCVT_to_float(Cond cond, bool D, size_t Vd, bool sz, bool is_signed, bool M, size_t Vm) { bool ArmTranslatorVisitor::vfp2_VCVT_to_float(Cond cond, bool D, size_t Vd, bool sz, bool is_signed, bool M, size_t Vm) {
ExtReg d = ToExtReg(sz, Vd, D); ExtReg d = ToExtReg(sz, Vd, D);
ExtReg m = ToExtReg(false, Vm, M); ExtReg m = ToExtReg(false, Vm, M);
bool round_to_nearest = false; FP::RoundingMode rounding_mode = ir.current_location.FPSCR().RMode();
// VCVT.F32.{S32,U32} <Sd>, <Sm> // VCVT.F32.{S32,U32} <Sd>, <Sm>
// VCVT.F64.{S32,U32} <Sd>, <Dm> // VCVT.F64.{S32,U32} <Sd>, <Dm>
if (ConditionPassed(cond)) { if (ConditionPassed(cond)) {
auto reg_m = ir.GetExtendedRegister(m); auto reg_m = ir.GetExtendedRegister(m);
if (sz) { if (sz) {
auto result = is_signed auto result = is_signed
? ir.FPS32ToDouble(reg_m, round_to_nearest, true) ? ir.FPSignedFixedToDouble(reg_m, 0, rounding_mode)
: ir.FPU32ToDouble(reg_m, round_to_nearest, true); : ir.FPUnsignedFixedToDouble(reg_m, 0, rounding_mode);
ir.SetExtendedRegister(d, result); ir.SetExtendedRegister(d, result);
} else { } else {
auto result = is_signed auto result = is_signed
? ir.FPS32ToSingle(reg_m, round_to_nearest, true) ? ir.FPSignedFixedToSingle(reg_m, 0, rounding_mode)
: ir.FPU32ToSingle(reg_m, round_to_nearest, true); : ir.FPUnsignedFixedToSingle(reg_m, 0, rounding_mode);
ir.SetExtendedRegister(d, result); ir.SetExtendedRegister(d, result);
} }
} }

View file

@ -21,14 +21,10 @@ bool TranslatorVisitor::SCVTF_float_int(bool sf, Imm<2> type, Reg Rn, Vec Vd) {
const IR::U32U64 intval = X(intsize, Rn); const IR::U32U64 intval = X(intsize, Rn);
IR::U32U64 fltval; IR::U32U64 fltval;
if (intsize == 32 && *fltsize == 32) { if (*fltsize == 32) {
fltval = ir.FPS32ToSingle(intval, false, true); fltval = ir.FPSignedFixedToSingle(intval, 0, ir.current_location->FPCR().RMode());
} else if (intsize == 32 && *fltsize == 64) { } else if (*fltsize == 64) {
fltval = ir.FPS32ToDouble(intval, false, true); fltval = ir.FPSignedFixedToDouble(intval, 0, ir.current_location->FPCR().RMode());
} else if (intsize == 64 && *fltsize == 32) {
fltval = ir.FPS64ToSingle(intval, false, true);
} else if (intsize == 64 && *fltsize == 64) {
fltval = ir.FPS64ToDouble(intval, false, true);
} else { } else {
UNREACHABLE(); UNREACHABLE();
} }
@ -48,14 +44,10 @@ bool TranslatorVisitor::UCVTF_float_int(bool sf, Imm<2> type, Reg Rn, Vec Vd) {
const IR::U32U64 intval = X(intsize, Rn); const IR::U32U64 intval = X(intsize, Rn);
IR::U32U64 fltval; IR::U32U64 fltval;
if (intsize == 32 && *fltsize == 32) { if (*fltsize == 32) {
fltval = ir.FPU32ToSingle(intval, false, true); fltval = ir.FPUnsignedFixedToSingle(intval, 0, ir.current_location->FPCR().RMode());
} else if (intsize == 32 && *fltsize == 64) { } else if (*fltsize == 64) {
fltval = ir.FPU32ToDouble(intval, false, true); fltval = ir.FPUnsignedFixedToDouble(intval, 0, ir.current_location->FPCR().RMode());
} else if (intsize == 64 && *fltsize == 32) {
fltval = ir.FPU64ToSingle(intval, false, true);
} else if (intsize == 64 && *fltsize == 64) {
fltval = ir.FPU64ToDouble(intval, false, true);
} else { } else {
UNREACHABLE(); UNREACHABLE();
} }

View file

@ -195,13 +195,12 @@ bool TranslatorVisitor::NEG_1(Imm<2> size, Vec Vn, Vec Vd) {
bool TranslatorVisitor::SCVTF_int_2(bool sz, Vec Vn, Vec Vd) { bool TranslatorVisitor::SCVTF_int_2(bool sz, Vec Vn, Vec Vd) {
const auto esize = sz ? 64 : 32; const auto esize = sz ? 64 : 32;
IR::U32U64 element = V_scalar(esize, Vn); const IR::U32U64 element = V_scalar(esize, Vn);
if (esize == 32) { const IR::U32U64 result = esize == 32
element = ir.FPS32ToSingle(element, false, true); ? IR::U32U64(ir.FPSignedFixedToSingle(element, 0, ir.current_location->FPCR().RMode()))
} else { : IR::U32U64(ir.FPSignedFixedToDouble(element, 0, ir.current_location->FPCR().RMode()));
element = ir.FPS64ToDouble(element, false, true);
} V_scalar(esize, Vd, result);
V_scalar(esize, Vd, element);
return true; return true;
} }
@ -248,13 +247,12 @@ bool TranslatorVisitor::SUQADD_1(Imm<2> size, Vec Vn, Vec Vd) {
bool TranslatorVisitor::UCVTF_int_2(bool sz, Vec Vn, Vec Vd) { bool TranslatorVisitor::UCVTF_int_2(bool sz, Vec Vn, Vec Vd) {
const auto esize = sz ? 64 : 32; const auto esize = sz ? 64 : 32;
IR::U32U64 element = V_scalar(esize, Vn); const IR::U32U64 element = V_scalar(esize, Vn);
if (esize == 32) { const IR::U32U64 result = esize == 32
element = ir.FPU32ToSingle(element, false, true); ? IR::U32U64(ir.FPUnsignedFixedToSingle(element, 0, ir.current_location->FPCR().RMode()))
} else { : IR::U32U64(ir.FPUnsignedFixedToDouble(element, 0, ir.current_location->FPCR().RMode()));
element = ir.FPU64ToDouble(element, false, true);
} V_scalar(esize, Vd, result);
V_scalar(esize, Vd, element);
return true; return true;
} }

View file

@ -1960,44 +1960,28 @@ U64 IREmitter::FPToFixedU64(const U32U64& a, size_t fbits, FP::RoundingMode roun
return Inst<U64>(opcode, a, Imm8(static_cast<u8>(fbits)), Imm8(static_cast<u8>(rounding))); return Inst<U64>(opcode, a, Imm8(static_cast<u8>(fbits)), Imm8(static_cast<u8>(rounding)));
} }
U32 IREmitter::FPS32ToSingle(const U32& a, bool round_to_nearest, bool fpcr_controlled) { U32 IREmitter::FPSignedFixedToSingle(const U32U64& a, size_t fbits, FP::RoundingMode rounding) {
ASSERT(fpcr_controlled); ASSERT(fbits <= (a.GetType() == Type::U32 ? 32 : 64));
return Inst<U32>(Opcode::FPS32ToSingle, a, Imm1(round_to_nearest)); const Opcode opcode = a.GetType() == Type::U32 ? Opcode::FPFixedS32ToSingle : Opcode::FPFixedS64ToSingle;
return Inst<U32>(opcode, a, Imm8(static_cast<u8>(fbits)), Imm8(static_cast<u8>(rounding)));
} }
U64 IREmitter::FPS64ToDouble(const U64& a, bool round_to_nearest, bool fpcr_controlled) { U32 IREmitter::FPUnsignedFixedToSingle(const U32U64& a, size_t fbits, FP::RoundingMode rounding) {
ASSERT(fpcr_controlled); ASSERT(fbits <= (a.GetType() == Type::U32 ? 32 : 64));
return Inst<U64>(Opcode::FPS64ToDouble, a, Imm1(round_to_nearest)); const Opcode opcode = a.GetType() == Type::U32 ? Opcode::FPFixedU32ToSingle : Opcode::FPFixedU64ToSingle;
return Inst<U32>(opcode, a, Imm8(static_cast<u8>(fbits)), Imm8(static_cast<u8>(rounding)));
} }
U32 IREmitter::FPS64ToSingle(const U64& a, bool round_to_nearest, bool fpcr_controlled) { U64 IREmitter::FPSignedFixedToDouble(const U32U64& a, size_t fbits, FP::RoundingMode rounding) {
ASSERT(fpcr_controlled); ASSERT(fbits <= (a.GetType() == Type::U32 ? 32 : 64));
return Inst<U32>(Opcode::FPS64ToSingle, a, Imm1(round_to_nearest)); const Opcode opcode = a.GetType() == Type::U32 ? Opcode::FPFixedS32ToDouble : Opcode::FPFixedS64ToDouble;
return Inst<U64>(opcode, a, Imm8(static_cast<u8>(fbits)), Imm8(static_cast<u8>(rounding)));
} }
U32 IREmitter::FPU32ToSingle(const U32& a, bool round_to_nearest, bool fpcr_controlled) { U64 IREmitter::FPUnsignedFixedToDouble(const U32U64& a, size_t fbits, FP::RoundingMode rounding) {
ASSERT(fpcr_controlled); ASSERT(fbits <= (a.GetType() == Type::U32 ? 32 : 64));
return Inst<U32>(Opcode::FPU32ToSingle, a, Imm1(round_to_nearest)); const Opcode opcode = a.GetType() == Type::U32 ? Opcode::FPFixedU32ToDouble : Opcode::FPFixedU64ToDouble;
} return Inst<U64>(opcode, a, Imm8(static_cast<u8>(fbits)), Imm8(static_cast<u8>(rounding)));
U64 IREmitter::FPS32ToDouble(const U32& a, bool round_to_nearest, bool fpcr_controlled) {
ASSERT(fpcr_controlled);
return Inst<U64>(Opcode::FPS32ToDouble, a, Imm1(round_to_nearest));
}
U64 IREmitter::FPU32ToDouble(const U32& a, bool round_to_nearest, bool fpcr_controlled) {
ASSERT(fpcr_controlled);
return Inst<U64>(Opcode::FPU32ToDouble, a, Imm1(round_to_nearest));
}
U64 IREmitter::FPU64ToDouble(const U64& a, bool round_to_nearest, bool fpcr_controlled) {
ASSERT(fpcr_controlled);
return Inst<U64>(Opcode::FPU64ToDouble, a, Imm1(round_to_nearest));
}
U32 IREmitter::FPU64ToSingle(const U64& a, bool round_to_nearest, bool fpcr_controlled) {
ASSERT(fpcr_controlled);
return Inst<U32>(Opcode::FPU64ToSingle, a, Imm1(round_to_nearest));
} }
U128 IREmitter::FPVectorAbs(size_t esize, const U128& a) { U128 IREmitter::FPVectorAbs(size_t esize, const U128& a) {

View file

@ -316,14 +316,10 @@ public:
U64 FPToFixedS64(const U32U64& a, size_t fbits, FP::RoundingMode rounding); U64 FPToFixedS64(const U32U64& a, size_t fbits, FP::RoundingMode rounding);
U32 FPToFixedU32(const U32U64& a, size_t fbits, FP::RoundingMode rounding); U32 FPToFixedU32(const U32U64& a, size_t fbits, FP::RoundingMode rounding);
U64 FPToFixedU64(const U32U64& a, size_t fbits, FP::RoundingMode rounding); U64 FPToFixedU64(const U32U64& a, size_t fbits, FP::RoundingMode rounding);
U32 FPS32ToSingle(const U32& a, bool round_to_nearest, bool fpcr_controlled); U32 FPSignedFixedToSingle(const U32U64& a, size_t fbits, FP::RoundingMode rounding);
U32 FPU32ToSingle(const U32& a, bool round_to_nearest, bool fpcr_controlled); U32 FPUnsignedFixedToSingle(const U32U64& a, size_t fbits, FP::RoundingMode rounding);
U64 FPS32ToDouble(const U32& a, bool round_to_nearest, bool fpcr_controlled); U64 FPSignedFixedToDouble(const U32U64& a, size_t fbits, FP::RoundingMode rounding);
U64 FPS64ToDouble(const U64& a, bool round_to_nearest, bool fpcr_controlled); U64 FPUnsignedFixedToDouble(const U32U64& a, size_t fbits, FP::RoundingMode rounding);
U32 FPS64ToSingle(const U64& a, bool round_to_nearest, bool fpcr_controlled);
U64 FPU32ToDouble(const U32& a, bool round_to_nearest, bool fpcr_controlled);
U64 FPU64ToDouble(const U64& a, bool round_to_nearest, bool fpcr_controlled);
U32 FPU64ToSingle(const U64& a, bool round_to_nearest, bool fpcr_controlled);
U128 FPVectorAbs(size_t esize, const U128& a); U128 FPVectorAbs(size_t esize, const U128& a);
U128 FPVectorAdd(size_t esize, const U128& a, const U128& b); U128 FPVectorAdd(size_t esize, const U128& a, const U128& b);

View file

@ -293,14 +293,14 @@ bool Inst::ReadsFromAndWritesToFPSRCumulativeExceptionBits() const {
case Opcode::FPSingleToFixedS64: case Opcode::FPSingleToFixedS64:
case Opcode::FPSingleToFixedU32: case Opcode::FPSingleToFixedU32:
case Opcode::FPSingleToFixedU64: case Opcode::FPSingleToFixedU64:
case Opcode::FPU32ToSingle: case Opcode::FPFixedU32ToSingle:
case Opcode::FPS32ToSingle: case Opcode::FPFixedS32ToSingle:
case Opcode::FPU32ToDouble: case Opcode::FPFixedU32ToDouble:
case Opcode::FPU64ToDouble: case Opcode::FPFixedU64ToDouble:
case Opcode::FPU64ToSingle: case Opcode::FPFixedU64ToSingle:
case Opcode::FPS32ToDouble: case Opcode::FPFixedS32ToDouble:
case Opcode::FPS64ToDouble: case Opcode::FPFixedS64ToDouble:
case Opcode::FPS64ToSingle: case Opcode::FPFixedS64ToSingle:
case Opcode::FPVectorAdd32: case Opcode::FPVectorAdd32:
case Opcode::FPVectorAdd64: case Opcode::FPVectorAdd64:
case Opcode::FPVectorDiv32: case Opcode::FPVectorDiv32:

View file

@ -504,14 +504,14 @@ OPCODE(FPSingleToFixedS32, U32, U32,
OPCODE(FPSingleToFixedS64, U64, U32, U8, U8 ) OPCODE(FPSingleToFixedS64, U64, U32, U8, U8 )
OPCODE(FPSingleToFixedU32, U32, U32, U8, U8 ) OPCODE(FPSingleToFixedU32, U32, U32, U8, U8 )
OPCODE(FPSingleToFixedU64, U64, U32, U8, U8 ) OPCODE(FPSingleToFixedU64, U64, U32, U8, U8 )
OPCODE(FPU32ToSingle, U32, U32, U1 ) OPCODE(FPFixedU32ToSingle, U32, U32, U8, U8 )
OPCODE(FPS32ToSingle, U32, U32, U1 ) OPCODE(FPFixedS32ToSingle, U32, U32, U8, U8 )
OPCODE(FPU32ToDouble, U64, U32, U1 ) OPCODE(FPFixedU32ToDouble, U64, U32, U8, U8 )
OPCODE(FPU64ToDouble, U64, U64, U1 ) OPCODE(FPFixedU64ToDouble, U64, U64, U8, U8 )
OPCODE(FPU64ToSingle, U32, U64, U1 ) OPCODE(FPFixedU64ToSingle, U32, U64, U8, U8 )
OPCODE(FPS32ToDouble, U64, U32, U1 ) OPCODE(FPFixedS32ToDouble, U64, U32, U8, U8 )
OPCODE(FPS64ToDouble, U64, U64, U1 ) OPCODE(FPFixedS64ToDouble, U64, U64, U8, U8 )
OPCODE(FPS64ToSingle, U32, U64, U1 ) OPCODE(FPFixedS64ToSingle, U32, U64, U8, U8 )
// Floating-point vector instructions // Floating-point vector instructions
OPCODE(FPVectorAbs16, U128, U128 ) OPCODE(FPVectorAbs16, U128, U128 )