Revert "[CPU] Detect FPSCR exceptions in UpdateFPSCR for Rc=1 FPU instructions"

This reverts commit a769d70761.
Causes audio issues in The Godfather
This commit is contained in:
Herman S.
2026-02-22 20:28:27 +09:00
parent b2b1307822
commit 9190ce3e36
4 changed files with 2136 additions and 151 deletions

View File

@@ -37,64 +37,52 @@ using xe::cpu::hir::Value;
int InstrEmit_faddx(PPCHIRBuilder& f, const InstrData& i) { int InstrEmit_faddx(PPCHIRBuilder& f, const InstrData& i) {
// frD <- (frA) + (frB) // frD <- (frA) + (frB)
Value* fra = f.LoadFPR(i.A.FRA); Value* v = f.Add(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRB));
Value* frb = f.LoadFPR(i.A.FRB);
Value* v = f.Add(fra, frb);
f.StoreFPR(i.A.FRT, v); f.StoreFPR(i.A.FRT, v);
f.UpdateFPSCR(v, i.A.Rc, fra, frb); f.UpdateFPSCR(v, i.A.Rc);
return 0; return 0;
} }
int InstrEmit_faddsx(PPCHIRBuilder& f, const InstrData& i) { int InstrEmit_faddsx(PPCHIRBuilder& f, const InstrData& i) {
// frD <- (frA) + (frB) // frD <- (frA) + (frB)
Value* fra = f.LoadFPR(i.A.FRA); Value* v = f.Add(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRB));
Value* frb = f.LoadFPR(i.A.FRB);
Value* v = f.Add(fra, frb);
v = f.ToSingle(v); v = f.ToSingle(v);
f.StoreFPR(i.A.FRT, v); f.StoreFPR(i.A.FRT, v);
f.UpdateFPSCR(v, i.A.Rc, fra, frb); f.UpdateFPSCR(v, i.A.Rc);
return 0; return 0;
} }
int InstrEmit_fdivx(PPCHIRBuilder& f, const InstrData& i) { int InstrEmit_fdivx(PPCHIRBuilder& f, const InstrData& i) {
// frD <- frA / frB // frD <- frA / frB
Value* fra = f.LoadFPR(i.A.FRA); Value* v = f.Div(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRB));
Value* frb = f.LoadFPR(i.A.FRB);
Value* v = f.Div(fra, frb);
f.StoreFPR(i.A.FRT, v); f.StoreFPR(i.A.FRT, v);
f.UpdateFPSCR(v, i.A.Rc, fra, frb); f.UpdateFPSCR(v, i.A.Rc);
return 0; return 0;
} }
int InstrEmit_fdivsx(PPCHIRBuilder& f, const InstrData& i) { int InstrEmit_fdivsx(PPCHIRBuilder& f, const InstrData& i) {
// frD <- frA / frB // frD <- frA / frB
Value* fra = f.LoadFPR(i.A.FRA); Value* v = f.Div(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRB));
Value* frb = f.LoadFPR(i.A.FRB);
Value* v = f.Div(fra, frb);
v = f.ToSingle(v); v = f.ToSingle(v);
f.StoreFPR(i.A.FRT, v); f.StoreFPR(i.A.FRT, v);
f.UpdateFPSCR(v, i.A.Rc, fra, frb); f.UpdateFPSCR(v, i.A.Rc);
return 0; return 0;
} }
int InstrEmit_fmulx(PPCHIRBuilder& f, const InstrData& i) { int InstrEmit_fmulx(PPCHIRBuilder& f, const InstrData& i) {
// frD <- (frA) x (frC) // frD <- (frA) x (frC)
Value* fra = f.LoadFPR(i.A.FRA); Value* v = f.Mul(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC));
Value* frc = f.LoadFPR(i.A.FRC);
Value* v = f.Mul(fra, frc);
f.StoreFPR(i.A.FRT, v); f.StoreFPR(i.A.FRT, v);
f.UpdateFPSCR(v, i.A.Rc, fra, frc); f.UpdateFPSCR(v, i.A.Rc);
return 0; return 0;
} }
int InstrEmit_fmulsx(PPCHIRBuilder& f, const InstrData& i) { int InstrEmit_fmulsx(PPCHIRBuilder& f, const InstrData& i) {
// frD <- (frA) x (frC) // frD <- (frA) x (frC)
Value* fra = f.LoadFPR(i.A.FRA); Value* v = f.Mul(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC));
Value* frc = f.LoadFPR(i.A.FRC);
Value* v = f.Mul(fra, frc);
v = f.ToSingle(v); v = f.ToSingle(v);
f.StoreFPR(i.A.FRT, v); f.StoreFPR(i.A.FRT, v);
f.UpdateFPSCR(v, i.A.Rc, fra, frc); f.UpdateFPSCR(v, i.A.Rc);
return 0; return 0;
} }
@@ -103,42 +91,36 @@ int InstrEmit_fresx(PPCHIRBuilder& f, const InstrData& i) {
// this actually does seem to require single precision, oddly // this actually does seem to require single precision, oddly
// more research is needed // more research is needed
Value* frb = f.LoadFPR(i.A.FRB); Value* v = f.Recip(f.Convert(f.LoadFPR(i.A.FRB), FLOAT32_TYPE));
Value* v = f.Recip(f.Convert(frb, FLOAT32_TYPE));
v = f.Convert(v, FLOAT64_TYPE); // f.ToSingle(v); v = f.Convert(v, FLOAT64_TYPE); // f.ToSingle(v);
f.StoreFPR(i.A.FRT, v); f.StoreFPR(i.A.FRT, v);
f.UpdateFPSCR(v, i.A.Rc, frb); f.UpdateFPSCR(v, i.A.Rc);
return 0; return 0;
} }
int InstrEmit_frsqrtex(PPCHIRBuilder& f, const InstrData& i) { int InstrEmit_frsqrtex(PPCHIRBuilder& f, const InstrData& i) {
// Double precision: // Double precision:
// frD <- 1/sqrt(frB) // frD <- 1/sqrt(frB)
Value* frb = f.LoadFPR(i.A.FRB); Value* v = f.RSqrt(f.LoadFPR(i.A.FRB));
Value* v = f.RSqrt(frb);
f.StoreFPR(i.A.FRT, v); f.StoreFPR(i.A.FRT, v);
f.UpdateFPSCR(v, i.A.Rc, frb); f.UpdateFPSCR(v, i.A.Rc);
return 0; return 0;
} }
int InstrEmit_fsubx(PPCHIRBuilder& f, const InstrData& i) { int InstrEmit_fsubx(PPCHIRBuilder& f, const InstrData& i) {
// frD <- (frA) - (frB) // frD <- (frA) - (frB)
Value* fra = f.LoadFPR(i.A.FRA); Value* v = f.Sub(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRB));
Value* frb = f.LoadFPR(i.A.FRB);
Value* v = f.Sub(fra, frb);
f.StoreFPR(i.A.FRT, v); f.StoreFPR(i.A.FRT, v);
f.UpdateFPSCR(v, i.A.Rc, fra, frb); f.UpdateFPSCR(v, i.A.Rc);
return 0; return 0;
} }
int InstrEmit_fsubsx(PPCHIRBuilder& f, const InstrData& i) { int InstrEmit_fsubsx(PPCHIRBuilder& f, const InstrData& i) {
// frD <- (frA) - (frB) // frD <- (frA) - (frB)
Value* fra = f.LoadFPR(i.A.FRA); Value* v = f.Sub(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRB));
Value* frb = f.LoadFPR(i.A.FRB);
Value* v = f.Sub(fra, frb);
v = f.ToSingle(v); v = f.ToSingle(v);
f.StoreFPR(i.A.FRT, v); f.StoreFPR(i.A.FRT, v);
f.UpdateFPSCR(v, i.A.Rc, fra, frb); f.UpdateFPSCR(v, i.A.Rc);
return 0; return 0;
} }
@@ -154,13 +136,12 @@ int InstrEmit_fselx(PPCHIRBuilder& f, const InstrData& i) {
} }
static int InstrEmit_fsqrt(PPCHIRBuilder& f, const InstrData& i, bool single) { static int InstrEmit_fsqrt(PPCHIRBuilder& f, const InstrData& i, bool single) {
// frD <- sqrt(frB) // frD <- sqrt(frB)
Value* frb = f.LoadFPR(i.A.FRB); Value* v = f.Sqrt(f.LoadFPR(i.A.FRB));
Value* v = f.Sqrt(frb);
if (single) { if (single) {
v = f.ToSingle(v); v = f.ToSingle(v);
} }
f.StoreFPR(i.A.FRT, v); f.StoreFPR(i.A.FRT, v);
f.UpdateFPSCR(v, i.A.Rc, frb); f.UpdateFPSCR(v, i.A.Rc);
return 0; return 0;
} }
int InstrEmit_fsqrtx(PPCHIRBuilder& f, const InstrData& i) { int InstrEmit_fsqrtx(PPCHIRBuilder& f, const InstrData& i) {
@@ -175,15 +156,13 @@ int InstrEmit_fsqrtsx(PPCHIRBuilder& f, const InstrData& i) {
static int InstrEmit_fmadd(PPCHIRBuilder& f, const InstrData& i, bool single) { static int InstrEmit_fmadd(PPCHIRBuilder& f, const InstrData& i, bool single) {
// frD <- (frA x frC) + frB // frD <- (frA x frC) + frB
Value* fra = f.LoadFPR(i.A.FRA); Value* v =
Value* frc = f.LoadFPR(i.A.FRC); f.MulAdd(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC), f.LoadFPR(i.A.FRB));
Value* frb = f.LoadFPR(i.A.FRB);
Value* v = f.MulAdd(fra, frc, frb);
if (single) { if (single) {
v = f.ToSingle(v); v = f.ToSingle(v);
} }
f.StoreFPR(i.A.FRT, v); f.StoreFPR(i.A.FRT, v);
f.UpdateFPSCR(v, i.A.Rc, fra, frc, frb); f.UpdateFPSCR(v, i.A.Rc);
return 0; return 0;
} }
@@ -197,15 +176,13 @@ int InstrEmit_fmaddsx(PPCHIRBuilder& f, const InstrData& i) {
static int InstrEmit_fmsub(PPCHIRBuilder& f, const InstrData& i, bool single) { static int InstrEmit_fmsub(PPCHIRBuilder& f, const InstrData& i, bool single) {
// frD <- (frA x frC) - frB // frD <- (frA x frC) - frB
Value* fra = f.LoadFPR(i.A.FRA); Value* v =
Value* frc = f.LoadFPR(i.A.FRC); f.MulSub(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC), f.LoadFPR(i.A.FRB));
Value* frb = f.LoadFPR(i.A.FRB);
Value* v = f.MulSub(fra, frc, frb);
if (single) { if (single) {
v = f.ToSingle(v); v = f.ToSingle(v);
} }
f.StoreFPR(i.A.FRT, v); f.StoreFPR(i.A.FRT, v);
f.UpdateFPSCR(v, i.A.Rc, fra, frc, frb); f.UpdateFPSCR(v, i.A.Rc);
return 0; return 0;
} }
int InstrEmit_fmsubx(PPCHIRBuilder& f, const InstrData& i) { int InstrEmit_fmsubx(PPCHIRBuilder& f, const InstrData& i) {
@@ -218,47 +195,39 @@ int InstrEmit_fmsubsx(PPCHIRBuilder& f, const InstrData& i) {
int InstrEmit_fnmaddx(PPCHIRBuilder& f, const InstrData& i) { int InstrEmit_fnmaddx(PPCHIRBuilder& f, const InstrData& i) {
// frD <- -([frA x frC] + frB) // frD <- -([frA x frC] + frB)
Value* fra = f.LoadFPR(i.A.FRA); Value* v = f.Neg(
Value* frc = f.LoadFPR(i.A.FRC); f.MulAdd(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC), f.LoadFPR(i.A.FRB)));
Value* frb = f.LoadFPR(i.A.FRB);
Value* v = f.Neg(f.MulAdd(fra, frc, frb));
f.StoreFPR(i.A.FRT, v); f.StoreFPR(i.A.FRT, v);
f.UpdateFPSCR(v, i.A.Rc, fra, frc, frb); f.UpdateFPSCR(v, i.A.Rc);
return 0; return 0;
} }
int InstrEmit_fnmaddsx(PPCHIRBuilder& f, const InstrData& i) { int InstrEmit_fnmaddsx(PPCHIRBuilder& f, const InstrData& i) {
// frD <- -([frA x frC] + frB) // frD <- -([frA x frC] + frB)
Value* fra = f.LoadFPR(i.A.FRA); Value* v = f.Neg(
Value* frc = f.LoadFPR(i.A.FRC); f.MulAdd(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC), f.LoadFPR(i.A.FRB)));
Value* frb = f.LoadFPR(i.A.FRB);
Value* v = f.Neg(f.MulAdd(fra, frc, frb));
v = f.ToSingle(v); v = f.ToSingle(v);
f.StoreFPR(i.A.FRT, v); f.StoreFPR(i.A.FRT, v);
f.UpdateFPSCR(v, i.A.Rc, fra, frc, frb); f.UpdateFPSCR(v, i.A.Rc);
return 0; return 0;
} }
int InstrEmit_fnmsubx(PPCHIRBuilder& f, const InstrData& i) { int InstrEmit_fnmsubx(PPCHIRBuilder& f, const InstrData& i) {
// frD <- -([frA x frC] - frB) // frD <- -([frA x frC] - frB)
Value* fra = f.LoadFPR(i.A.FRA); Value* v = f.Neg(
Value* frc = f.LoadFPR(i.A.FRC); f.MulSub(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC), f.LoadFPR(i.A.FRB)));
Value* frb = f.LoadFPR(i.A.FRB);
Value* v = f.Neg(f.MulSub(fra, frc, frb));
f.StoreFPR(i.A.FRT, v); f.StoreFPR(i.A.FRT, v);
f.UpdateFPSCR(v, i.A.Rc, fra, frc, frb); f.UpdateFPSCR(v, i.A.Rc);
return 0; return 0;
} }
int InstrEmit_fnmsubsx(PPCHIRBuilder& f, const InstrData& i) { int InstrEmit_fnmsubsx(PPCHIRBuilder& f, const InstrData& i) {
// frD <- -([frA x frC] - frB) // frD <- -([frA x frC] - frB)
Value* fra = f.LoadFPR(i.A.FRA); Value* v = f.Neg(
Value* frc = f.LoadFPR(i.A.FRC); f.MulSub(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC), f.LoadFPR(i.A.FRB)));
Value* frb = f.LoadFPR(i.A.FRB);
Value* v = f.Neg(f.MulSub(fra, frc, frb));
v = f.ToSingle(v); v = f.ToSingle(v);
f.StoreFPR(i.A.FRT, v); f.StoreFPR(i.A.FRT, v);
f.UpdateFPSCR(v, i.A.Rc, fra, frc, frb); f.UpdateFPSCR(v, i.A.Rc);
return 0; return 0;
} }
@@ -266,7 +235,6 @@ int InstrEmit_fnmsubsx(PPCHIRBuilder& f, const InstrData& i) {
int InstrEmit_fcfidx(PPCHIRBuilder& f, const InstrData& i) { int InstrEmit_fcfidx(PPCHIRBuilder& f, const InstrData& i) {
// frD <- signed_int64_to_double( frB ) // frD <- signed_int64_to_double( frB )
// Input is an integer bit pattern in FPR, not a float - no NaN detection.
Value* v = f.Convert(f.Cast(f.LoadFPR(i.X.RB), INT64_TYPE), FLOAT64_TYPE); Value* v = f.Convert(f.Cast(f.LoadFPR(i.X.RB), INT64_TYPE), FLOAT64_TYPE);
f.StoreFPR(i.X.RT, v); f.StoreFPR(i.X.RT, v);
f.UpdateFPSCR(v, i.X.Rc); f.UpdateFPSCR(v, i.X.Rc);
@@ -275,14 +243,11 @@ int InstrEmit_fcfidx(PPCHIRBuilder& f, const InstrData& i) {
int InstrEmit_fctidxx_(PPCHIRBuilder& f, const InstrData& i, int InstrEmit_fctidxx_(PPCHIRBuilder& f, const InstrData& i,
RoundMode round_mode) { RoundMode round_mode) {
// Result is an integer bit pattern in FPR, not a float - no NaN detection.
// NaN input is already handled explicitly by the branch.
auto end = f.NewLabel(); auto end = f.NewLabel();
auto isnan = f.NewLabel(); auto isnan = f.NewLabel();
Value* v; Value* v;
Value* frb = f.LoadFPR(i.X.RB); f.BranchTrue(f.IsNan(f.LoadFPR(i.X.RB)), isnan);
f.BranchTrue(f.IsNan(frb), isnan); v = f.Convert(f.LoadFPR(i.X.RB), INT64_TYPE, round_mode);
v = f.Convert(frb, INT64_TYPE, round_mode);
v = f.Cast(v, FLOAT64_TYPE); v = f.Cast(v, FLOAT64_TYPE);
f.StoreFPR(i.X.RT, v); f.StoreFPR(i.X.RT, v);
f.UpdateFPSCR(v, i.X.Rc); f.UpdateFPSCR(v, i.X.Rc);
@@ -306,14 +271,11 @@ int InstrEmit_fctidzx(PPCHIRBuilder& f, const InstrData& i) {
int InstrEmit_fctiwxx_(PPCHIRBuilder& f, const InstrData& i, int InstrEmit_fctiwxx_(PPCHIRBuilder& f, const InstrData& i,
RoundMode round_mode) { RoundMode round_mode) {
// Result is an integer bit pattern in FPR, not a float - no NaN detection.
// NaN input is already handled explicitly by the branch.
auto end = f.NewLabel(); auto end = f.NewLabel();
auto isnan = f.NewLabel(); auto isnan = f.NewLabel();
Value* v; Value* v;
Value* frb = f.LoadFPR(i.X.RB); f.BranchTrue(f.IsNan(f.LoadFPR(i.X.RB)), isnan);
f.BranchTrue(f.IsNan(frb), isnan); v = f.Convert(f.LoadFPR(i.X.RB), INT32_TYPE, round_mode);
v = f.Convert(frb, INT32_TYPE, round_mode);
v = f.Cast(f.SignExtend(v, INT64_TYPE), FLOAT64_TYPE); v = f.Cast(f.SignExtend(v, INT64_TYPE), FLOAT64_TYPE);
f.StoreFPR(i.X.RT, v); f.StoreFPR(i.X.RT, v);
f.UpdateFPSCR(v, i.X.Rc); f.UpdateFPSCR(v, i.X.Rc);
@@ -338,11 +300,10 @@ int InstrEmit_fctiwzx(PPCHIRBuilder& f, const InstrData& i) {
int InstrEmit_frspx(PPCHIRBuilder& f, const InstrData& i) { int InstrEmit_frspx(PPCHIRBuilder& f, const InstrData& i) {
// frD <- Round_single(frB) // frD <- Round_single(frB)
Value* frb = f.LoadFPR(i.X.RB); Value* v = f.Convert(f.LoadFPR(i.X.RB), FLOAT32_TYPE, ROUND_DYNAMIC);
Value* v = f.Convert(frb, FLOAT32_TYPE, ROUND_DYNAMIC);
v = f.Convert(v, FLOAT64_TYPE); v = f.Convert(v, FLOAT64_TYPE);
f.StoreFPR(i.X.RT, v); f.StoreFPR(i.X.RT, v);
f.UpdateFPSCR(v, i.X.Rc, frb); f.UpdateFPSCR(v, i.X.Rc);
return 0; return 0;
} }

View File

@@ -450,79 +450,42 @@ void PPCHIRBuilder::StoreFPSCR(Value* value) {
trace_reg.value = value; trace_reg.value = value;
} }
void PPCHIRBuilder::UpdateFPSCR(Value* result, bool update_cr1, Value* src1, void PPCHIRBuilder::UpdateFPSCR(Value* result, bool update_cr1) {
Value* src2, Value* src3) { // TODO(benvanik): detect overflow and nan cases.
// Step 1: Detect new exception bits to OR into FPSCR. // fx and vx are the most important.
// Detect signaling NaN (SNaN) inputs → VXSNAN. /*
// For doubles, SNaN has all-1s exponent, quiet bit (bit 51) = 0. chrispy: i stubbed this out at one point because all it does is waste
// QNaN (quiet bit = 1) does NOT trigger VXSNAN per PPC spec. memory and CPU time, however, this introduced issues with raiden
Value* new_vxsnan = nullptr; (substitute w/ titleid later) which probably means they stash stuff in the
if (src1) { fpscr?
auto check_snan = [this](Value* v) -> Value* {
Value* is_nan = IsNan(v);
Value* quiet_bit = And(Truncate(Shr(Cast(v, INT64_TYPE), 51), INT8_TYPE),
LoadConstantInt8(1));
return And(is_nan, Xor(quiet_bit, LoadConstantInt8(1)));
};
new_vxsnan = check_snan(src1); */
Value* any_nan = IsNan(src1);
if (src2) {
new_vxsnan = Or(new_vxsnan, check_snan(src2));
any_nan = Or(any_nan, IsNan(src2));
}
if (src3) {
new_vxsnan = Or(new_vxsnan, check_snan(src3));
any_nan = Or(any_nan, IsNan(src3));
}
// Detect invalid op from non-NaN inputs producing NaN result
// (e.g., inf - inf, 0 * inf). Set VXSNAN as catch-all for now.
// TODO: Set specific sub-bits (VXISI, VXZDZ, VXIMZ, VXIDI).
Value* result_is_nan = IsNan(result);
Value* not_nan = Xor(any_nan, LoadConstantInt8(1));
new_vxsnan = Or(new_vxsnan, And(result_is_nan, not_nan));
}
// Step 2: Load FPSCR, OR in new sticky bits. Value* fx = LoadConstantInt8(0);
Value* fpscr = LoadFPSCR(); Value* fex = LoadConstantInt8(0);
if (new_vxsnan) { Value* vx = LoadConstantInt8(0);
// VXSNAN (bit 24) and FX (bit 31) are sticky. Value* ox = LoadConstantInt8(0);
fpscr = Or(fpscr, Shl(ZeroExtend(new_vxsnan, INT32_TYPE), 24));
fpscr = Or(fpscr, Shl(ZeroExtend(new_vxsnan, INT32_TYPE), 31));
}
// Step 3: Recompute VX from all sub-bits in updated FPSCR.
// VXSNAN(24)|VXISI(23)|VXIDI(22)|VXZDZ(21)|VXIMZ(20)|VXVC(19)|
// VXSOFT(10)|VXSQRT(9)|VXCVI(8) = mask 0x01F80700
Value* vx = CompareNE(And(fpscr, LoadConstantUint32(0x01F80700)),
LoadConstantUint32(0));
// Step 4: Compute FEX = (VX & VE) | (OX & OE) | (UX & UE) | (ZX & ZE) |
// (XX & XE).
// Exception bits OX(28),UX(27),ZX(26),XX(25) shifted right by 22 align with
// enable bits OE(6),UE(5),ZE(4),XE(3).
Value* exc_aligned =
And(And(Shr(fpscr, 22), fpscr), LoadConstantUint32(0x78));
Value* ve = And(Truncate(Shr(fpscr, 7), INT8_TYPE), LoadConstantInt8(1));
Value* fex = Or(And(vx, ve), CompareNE(exc_aligned, LoadConstantUint32(0)));
// Step 5: Read FX and OX from updated FPSCR (sticky, already OR'd in).
Value* fx = And(Truncate(Shr(fpscr, 31), INT8_TYPE), LoadConstantInt8(1));
Value* ox = And(Truncate(Shr(fpscr, 28), INT8_TYPE), LoadConstantInt8(1));
// Step 6: Store FPSCR with recomputed VX(29) and FEX(30).
fpscr = And(fpscr, LoadConstantUint32(0x9FFFFFFF));
fpscr = Or(fpscr, Shl(ZeroExtend(fex, INT32_TYPE), 30));
fpscr = Or(fpscr, Shl(ZeroExtend(vx, INT32_TYPE), 29));
StoreFPSCR(fpscr);
// Step 7: Mirror FPSCR[FX,FEX,VX,OX] to CR1 after FPSCR is finalized.
if (update_cr1) { if (update_cr1) {
// Store into the CR1 field.
// We do this instead of just calling CopyFPSCRToCR1 so that we don't
// have to read back the bits and do shifting work.
StoreContext(offsetof(PPCContext, cr1.cr1_fx), fx); StoreContext(offsetof(PPCContext, cr1.cr1_fx), fx);
StoreContext(offsetof(PPCContext, cr1.cr1_fex), fex); StoreContext(offsetof(PPCContext, cr1.cr1_fex), fex);
StoreContext(offsetof(PPCContext, cr1.cr1_vx), vx); StoreContext(offsetof(PPCContext, cr1.cr1_vx), vx);
StoreContext(offsetof(PPCContext, cr1.cr1_ox), ox); StoreContext(offsetof(PPCContext, cr1.cr1_ox), ox);
} }
// Generate our new bits.
Value* new_bits = Shl(ZeroExtend(fx, INT32_TYPE), 31);
new_bits = Or(new_bits, Shl(ZeroExtend(fex, INT32_TYPE), 30));
new_bits = Or(new_bits, Shl(ZeroExtend(vx, INT32_TYPE), 29));
new_bits = Or(new_bits, Shl(ZeroExtend(ox, INT32_TYPE), 28));
// Mix into fpscr while preserving sticky bits (FX and OX).
Value* bits = LoadFPSCR();
bits = Or(And(bits, LoadConstantUint32(0x9FFFFFFF)), new_bits);
StoreFPSCR(bits);
} }
void PPCHIRBuilder::CopyFPSCRToCR1() { void PPCHIRBuilder::CopyFPSCRToCR1() {

View File

@@ -59,8 +59,7 @@ class PPCHIRBuilder : public hir::HIRBuilder {
void UpdateCR6(Value* src_value); void UpdateCR6(Value* src_value);
Value* LoadFPSCR(); Value* LoadFPSCR();
void StoreFPSCR(Value* value); void StoreFPSCR(Value* value);
void UpdateFPSCR(Value* result, bool update_cr1, Value* src1 = nullptr, void UpdateFPSCR(Value* result, bool update_cr1);
Value* src2 = nullptr, Value* src3 = nullptr);
void CopyFPSCRToCR1(); void CopyFPSCRToCR1();
Value* LoadXER(); Value* LoadXER();
void StoreXER(Value* value); void StoreXER(Value* value);

File diff suppressed because it is too large Load Diff