A64: Remove NaN accuracy setting
Always do accuracte NaN handling.
This commit is contained in:
parent
b5df8d1ef8
commit
46445d0866
6 changed files with 8 additions and 28 deletions
|
@ -209,18 +209,6 @@ struct UserConfig {
|
||||||
/// This enables the fast dispatcher.
|
/// This enables the fast dispatcher.
|
||||||
bool enable_fast_dispatch = true;
|
bool enable_fast_dispatch = true;
|
||||||
|
|
||||||
// The below options relate to accuracy of floating-point emulation.
|
|
||||||
|
|
||||||
/// Determines how accurate NaN handling is.
|
|
||||||
enum class NaNAccuracy {
|
|
||||||
/// Results of operations with NaNs will exactly match hardware.
|
|
||||||
Accurate,
|
|
||||||
/// Behave as if FPCR.DN is always set.
|
|
||||||
AlwaysForceDefaultNaN,
|
|
||||||
/// No special handling of NaN, other than setting default NaN when FPCR.DN is set.
|
|
||||||
NoChecks,
|
|
||||||
} floating_point_nan_accuracy = NaNAccuracy::Accurate;
|
|
||||||
|
|
||||||
// Determines whether AddTicks and GetTicksRemaining are called.
|
// Determines whether AddTicks and GetTicksRemaining are called.
|
||||||
// If false, execution will continue until soon after Jit::HaltExecution is called.
|
// If false, execution will continue until soon after Jit::HaltExecution is called.
|
||||||
// bool enable_ticks = true; // TODO
|
// bool enable_ticks = true; // TODO
|
||||||
|
|
|
@ -52,10 +52,6 @@ FP::FPCR A64EmitContext::FPCR(bool fpcr_controlled) const {
|
||||||
return fpcr_controlled ? Location().FPCR() : Location().FPCR().ASIMDStandardValue();
|
return fpcr_controlled ? Location().FPCR() : Location().FPCR().ASIMDStandardValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool A64EmitContext::AccurateNaN() const {
|
|
||||||
return conf.floating_point_nan_accuracy == A64::UserConfig::NaNAccuracy::Accurate;
|
|
||||||
}
|
|
||||||
|
|
||||||
A64EmitX64::A64EmitX64(BlockOfCode& code, A64::UserConfig conf, A64::Jit* jit_interface)
|
A64EmitX64::A64EmitX64(BlockOfCode& code, A64::UserConfig conf, A64::Jit* jit_interface)
|
||||||
: EmitX64(code), conf(conf), jit_interface{jit_interface} {
|
: EmitX64(code), conf(conf), jit_interface{jit_interface} {
|
||||||
GenMemory128Accessors();
|
GenMemory128Accessors();
|
||||||
|
|
|
@ -28,7 +28,6 @@ struct A64EmitContext final : public EmitContext {
|
||||||
A64::LocationDescriptor Location() const;
|
A64::LocationDescriptor Location() const;
|
||||||
bool IsSingleStep() const;
|
bool IsSingleStep() const;
|
||||||
FP::FPCR FPCR(bool fpcr_controlled = true) const override;
|
FP::FPCR FPCR(bool fpcr_controlled = true) const override;
|
||||||
bool AccurateNaN() const override;
|
|
||||||
|
|
||||||
const A64::UserConfig& conf;
|
const A64::UserConfig& conf;
|
||||||
};
|
};
|
||||||
|
|
|
@ -50,7 +50,6 @@ struct EmitContext {
|
||||||
void EraseInstruction(IR::Inst* inst);
|
void EraseInstruction(IR::Inst* inst);
|
||||||
|
|
||||||
virtual FP::FPCR FPCR(bool fpcr_controlled = true) const = 0;
|
virtual FP::FPCR FPCR(bool fpcr_controlled = true) const = 0;
|
||||||
virtual bool AccurateNaN() const { return true; }
|
|
||||||
|
|
||||||
RegAlloc& reg_alloc;
|
RegAlloc& reg_alloc;
|
||||||
IR::Block& block;
|
IR::Block& block;
|
||||||
|
|
|
@ -258,7 +258,7 @@ void FPTwoOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, Function fn) {
|
||||||
|
|
||||||
Xbyak::Xmm result = ctx.reg_alloc.UseScratchXmm(args[0]);
|
Xbyak::Xmm result = ctx.reg_alloc.UseScratchXmm(args[0]);
|
||||||
|
|
||||||
if (ctx.AccurateNaN() && !ctx.FPCR().DN()) {
|
if (!ctx.FPCR().DN()) {
|
||||||
end = ProcessNaN<fsize>(code, result);
|
end = ProcessNaN<fsize>(code, result);
|
||||||
}
|
}
|
||||||
if constexpr (std::is_member_function_pointer_v<Function>) {
|
if constexpr (std::is_member_function_pointer_v<Function>) {
|
||||||
|
@ -268,7 +268,7 @@ void FPTwoOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, Function fn) {
|
||||||
}
|
}
|
||||||
if (ctx.FPCR().DN()) {
|
if (ctx.FPCR().DN()) {
|
||||||
ForceToDefaultNaN<fsize>(code, result);
|
ForceToDefaultNaN<fsize>(code, result);
|
||||||
} else if (ctx.AccurateNaN()) {
|
} else {
|
||||||
PostProcessNaN<fsize>(code, result, ctx.reg_alloc.ScratchXmm());
|
PostProcessNaN<fsize>(code, result, ctx.reg_alloc.ScratchXmm());
|
||||||
}
|
}
|
||||||
code.L(end);
|
code.L(end);
|
||||||
|
@ -282,7 +282,7 @@ void FPThreeOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, Function fn)
|
||||||
|
|
||||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||||
|
|
||||||
if (ctx.FPCR().DN() || !ctx.AccurateNaN()) {
|
if (ctx.FPCR().DN()) {
|
||||||
const Xbyak::Xmm result = ctx.reg_alloc.UseScratchXmm(args[0]);
|
const Xbyak::Xmm result = ctx.reg_alloc.UseScratchXmm(args[0]);
|
||||||
const Xbyak::Xmm operand = ctx.reg_alloc.UseScratchXmm(args[1]);
|
const Xbyak::Xmm operand = ctx.reg_alloc.UseScratchXmm(args[1]);
|
||||||
|
|
||||||
|
@ -292,9 +292,7 @@ void FPThreeOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst, Function fn)
|
||||||
fn(result, operand);
|
fn(result, operand);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx.AccurateNaN()) {
|
ForceToDefaultNaN<fsize>(code, result);
|
||||||
ForceToDefaultNaN<fsize>(code, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.reg_alloc.DefineValue(inst, result);
|
ctx.reg_alloc.DefineValue(inst, result);
|
||||||
return;
|
return;
|
||||||
|
@ -437,7 +435,7 @@ static void EmitFPMinMax(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||||
code.jmp(end);
|
code.jmp(end);
|
||||||
|
|
||||||
code.L(nan);
|
code.L(nan);
|
||||||
if (ctx.FPCR().DN() || !ctx.AccurateNaN()) {
|
if (ctx.FPCR().DN()) {
|
||||||
code.movaps(result, code.MConst(xword, fsize == 32 ? f32_nan : f64_nan));
|
code.movaps(result, code.MConst(xword, fsize == 32 ? f32_nan : f64_nan));
|
||||||
code.jmp(end);
|
code.jmp(end);
|
||||||
} else {
|
} else {
|
||||||
|
@ -677,7 +675,7 @@ static void EmitFPMulX(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
|
||||||
|
|
||||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||||
|
|
||||||
const bool do_default_nan = ctx.FPCR().DN() || !ctx.AccurateNaN();
|
const bool do_default_nan = ctx.FPCR().DN();
|
||||||
|
|
||||||
const Xbyak::Xmm op1 = ctx.reg_alloc.UseXmm(args[0]);
|
const Xbyak::Xmm op1 = ctx.reg_alloc.UseXmm(args[0]);
|
||||||
const Xbyak::Xmm op2 = ctx.reg_alloc.UseXmm(args[1]);
|
const Xbyak::Xmm op2 = ctx.reg_alloc.UseXmm(args[1]);
|
||||||
|
|
|
@ -284,7 +284,7 @@ void EmitTwoOpVectorOperation(BlockOfCode& code, EmitContext& ctx, IR::Inst* ins
|
||||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||||
const bool fpcr_controlled = args[fpcr_controlled_arg_index].GetImmediateU1();
|
const bool fpcr_controlled = args[fpcr_controlled_arg_index].GetImmediateU1();
|
||||||
|
|
||||||
if (!ctx.AccurateNaN() || ctx.FPCR(fpcr_controlled).DN()) {
|
if (ctx.FPCR(fpcr_controlled).DN()) {
|
||||||
Xbyak::Xmm result;
|
Xbyak::Xmm result;
|
||||||
|
|
||||||
if constexpr (std::is_member_function_pointer_v<Function>) {
|
if constexpr (std::is_member_function_pointer_v<Function>) {
|
||||||
|
@ -336,7 +336,7 @@ void EmitThreeOpVectorOperation(BlockOfCode& code, EmitContext& ctx, IR::Inst* i
|
||||||
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
|
||||||
const bool fpcr_controlled = args[2].GetImmediateU1();
|
const bool fpcr_controlled = args[2].GetImmediateU1();
|
||||||
|
|
||||||
if (!ctx.AccurateNaN() || ctx.FPCR(fpcr_controlled).DN()) {
|
if (ctx.FPCR(fpcr_controlled).DN()) {
|
||||||
const Xbyak::Xmm xmm_a = ctx.reg_alloc.UseScratchXmm(args[0]);
|
const Xbyak::Xmm xmm_a = ctx.reg_alloc.UseScratchXmm(args[0]);
|
||||||
const Xbyak::Xmm xmm_b = ctx.reg_alloc.UseXmm(args[1]);
|
const Xbyak::Xmm xmm_b = ctx.reg_alloc.UseXmm(args[1]);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue