Fiddling with FPSCR and such. Still not implemented, but wiring done.

This commit is contained in:
Ben Vanik 2015-12-30 16:17:21 -08:00
parent 0482ffad5a
commit 214532a3e8
4 changed files with 89 additions and 181 deletions

View File

@ -37,12 +37,7 @@ int InstrEmit_faddx(PPCHIRBuilder& f, const InstrData& i) {
// frD <- (frA) + (frB)
Value* v = f.Add(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRB));
f.StoreFPR(i.A.FRT, v);
// f.UpdateFPRF(v);
if (i.A.Rc) {
// e.update_cr_with_cond(1, v);
XEINSTRNOTIMPLEMENTED();
return 1;
}
f.UpdateFPSCR(v, i.A.Rc);
return 0;
}
@ -51,12 +46,7 @@ int InstrEmit_faddsx(PPCHIRBuilder& f, const InstrData& i) {
Value* v = f.Add(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRB));
v = f.Convert(f.Convert(v, FLOAT32_TYPE), FLOAT64_TYPE);
f.StoreFPR(i.A.FRT, v);
// f.UpdateFPRF(v);
if (i.A.Rc) {
// e.update_cr_with_cond(1, v);
XEINSTRNOTIMPLEMENTED();
return 1;
}
f.UpdateFPSCR(v, i.A.Rc);
return 0;
}
@ -64,12 +54,7 @@ int InstrEmit_fdivx(PPCHIRBuilder& f, const InstrData& i) {
// frD <- frA / frB
Value* v = f.Div(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRB));
f.StoreFPR(i.A.FRT, v);
// f.UpdateFPRF(v);
if (i.A.Rc) {
// e.update_cr_with_cond(1, v);
XEINSTRNOTIMPLEMENTED();
return 1;
}
f.UpdateFPSCR(v, i.A.Rc);
return 0;
}
@ -78,12 +63,7 @@ int InstrEmit_fdivsx(PPCHIRBuilder& f, const InstrData& i) {
Value* v = f.Div(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRB));
v = f.Convert(f.Convert(v, FLOAT32_TYPE), FLOAT64_TYPE);
f.StoreFPR(i.A.FRT, v);
// f.UpdateFPRF(v);
if (i.A.Rc) {
// e.update_cr_with_cond(1, v);
XEINSTRNOTIMPLEMENTED();
return 1;
}
f.UpdateFPSCR(v, i.A.Rc);
return 0;
}
@ -91,12 +71,7 @@ int InstrEmit_fmulx(PPCHIRBuilder& f, const InstrData& i) {
// frD <- (frA) x (frC)
Value* v = f.Mul(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC));
f.StoreFPR(i.A.FRT, v);
// f.UpdateFPRF(v);
if (i.A.Rc) {
// e.update_cr_with_cond(1, v);
XEINSTRNOTIMPLEMENTED();
return 1;
}
f.UpdateFPSCR(v, i.A.Rc);
return 0;
}
@ -105,12 +80,7 @@ int InstrEmit_fmulsx(PPCHIRBuilder& f, const InstrData& i) {
Value* v = f.Mul(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC));
v = f.Convert(f.Convert(v, FLOAT32_TYPE), FLOAT64_TYPE);
f.StoreFPR(i.A.FRT, v);
// f.UpdateFPRF(v);
if (i.A.Rc) {
// e.update_cr_with_cond(1, v);
XEINSTRNOTIMPLEMENTED();
return 1;
}
f.UpdateFPSCR(v, i.A.Rc);
return 0;
}
@ -120,12 +90,7 @@ int InstrEmit_fresx(PPCHIRBuilder& f, const InstrData& i) {
f.Convert(f.LoadFPR(i.A.FRB), FLOAT32_TYPE)),
FLOAT64_TYPE);
f.StoreFPR(i.A.FRT, v);
// f.UpdateFPRF(v);
if (i.A.Rc) {
// e.update_cr_with_cond(1, v);
XEINSTRNOTIMPLEMENTED();
return 1;
}
f.UpdateFPSCR(v, i.A.Rc);
return 0;
}
@ -134,12 +99,7 @@ int InstrEmit_frsqrtex(PPCHIRBuilder& f, const InstrData& i) {
// frD <- 1/sqrt(frB)
Value* v = f.RSqrt(f.LoadFPR(i.A.FRB));
f.StoreFPR(i.A.FRT, v);
// f.UpdateFPRF(v);
if (i.A.Rc) {
// e.update_cr_with_cond(1, v);
XEINSTRNOTIMPLEMENTED();
return 1;
}
f.UpdateFPSCR(v, i.A.Rc);
return 0;
}
@ -147,12 +107,7 @@ int InstrEmit_fsubx(PPCHIRBuilder& f, const InstrData& i) {
// frD <- (frA) - (frB)
Value* v = f.Sub(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRB));
f.StoreFPR(i.A.FRT, v);
// f.UpdateFPRF(v);
if (i.A.Rc) {
// e.update_cr_with_cond(1, v);
XEINSTRNOTIMPLEMENTED();
return 1;
}
f.UpdateFPSCR(v, i.A.Rc);
return 0;
}
@ -161,12 +116,7 @@ int InstrEmit_fsubsx(PPCHIRBuilder& f, const InstrData& i) {
Value* v = f.Sub(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRB));
v = f.Convert(f.Convert(v, FLOAT32_TYPE), FLOAT64_TYPE);
f.StoreFPR(i.A.FRT, v);
// f.UpdateFPRF(v);
if (i.A.Rc) {
// e.update_cr_with_cond(1, v);
XEINSTRNOTIMPLEMENTED();
return 1;
}
f.UpdateFPSCR(v, i.A.Rc);
return 0;
}
@ -177,11 +127,7 @@ int InstrEmit_fselx(PPCHIRBuilder& f, const InstrData& i) {
Value* ge = f.CompareSGE(f.LoadFPR(i.A.FRA), f.LoadZeroFloat64());
Value* v = f.Select(ge, f.LoadFPR(i.A.FRC), f.LoadFPR(i.A.FRB));
f.StoreFPR(i.A.FRT, v);
if (i.A.Rc) {
// e.update_cr_with_cond(1, v);
XEINSTRNOTIMPLEMENTED();
return 1;
}
f.UpdateFPSCR(v, i.A.Rc);
return 0;
}
@ -190,12 +136,7 @@ int InstrEmit_fsqrtx(PPCHIRBuilder& f, const InstrData& i) {
// frD <- sqrt(frB)
Value* v = f.Sqrt(f.LoadFPR(i.A.FRB));
f.StoreFPR(i.A.FRT, v);
// f.UpdateFPRF(v);
if (i.A.Rc) {
// e.update_cr_with_cond(1, v);
XEINSTRNOTIMPLEMENTED();
return 1;
}
f.UpdateFPSCR(v, i.A.Rc);
return 0;
}
@ -205,12 +146,7 @@ int InstrEmit_fsqrtsx(PPCHIRBuilder& f, const InstrData& i) {
Value* v = f.Sqrt(f.LoadFPR(i.A.FRB));
v = f.Convert(f.Convert(v, FLOAT32_TYPE), FLOAT64_TYPE);
f.StoreFPR(i.A.FRT, v);
// f.UpdateFPRF(v);
if (i.A.Rc) {
// e.update_cr_with_cond(1, v);
XEINSTRNOTIMPLEMENTED();
return 1;
}
f.UpdateFPSCR(v, i.A.Rc);
return 0;
}
@ -221,12 +157,7 @@ int InstrEmit_fmaddx(PPCHIRBuilder& f, const InstrData& i) {
Value* v =
f.MulAdd(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC), f.LoadFPR(i.A.FRB));
f.StoreFPR(i.A.FRT, v);
// f.UpdateFPRF(v);
if (i.A.Rc) {
// e.update_cr_with_cond(1, v);
XEINSTRNOTIMPLEMENTED();
return 1;
}
f.UpdateFPSCR(v, i.A.Rc);
return 0;
}
@ -236,12 +167,7 @@ int InstrEmit_fmaddsx(PPCHIRBuilder& f, const InstrData& i) {
f.MulAdd(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC), f.LoadFPR(i.A.FRB));
v = f.Convert(f.Convert(v, FLOAT32_TYPE), FLOAT64_TYPE);
f.StoreFPR(i.A.FRT, v);
// f.UpdateFPRF(v);
if (i.A.Rc) {
// e.update_cr_with_cond(1, v);
XEINSTRNOTIMPLEMENTED();
return 1;
}
f.UpdateFPSCR(v, i.A.Rc);
return 0;
}
@ -250,12 +176,7 @@ int InstrEmit_fmsubx(PPCHIRBuilder& f, const InstrData& i) {
Value* v =
f.MulSub(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC), f.LoadFPR(i.A.FRB));
f.StoreFPR(i.A.FRT, v);
// f.UpdateFPRF(v);
if (i.A.Rc) {
// e.update_cr_with_cond(1, v);
XEINSTRNOTIMPLEMENTED();
return 1;
}
f.UpdateFPSCR(v, i.A.Rc);
return 0;
}
@ -265,12 +186,7 @@ int InstrEmit_fmsubsx(PPCHIRBuilder& f, const InstrData& i) {
f.MulSub(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC), f.LoadFPR(i.A.FRB));
v = f.Convert(f.Convert(v, FLOAT32_TYPE), FLOAT64_TYPE);
f.StoreFPR(i.A.FRT, v);
// f.UpdateFPRF(v);
if (i.A.Rc) {
// e.update_cr_with_cond(1, v);
XEINSTRNOTIMPLEMENTED();
return 1;
}
f.UpdateFPSCR(v, i.A.Rc);
return 0;
}
@ -279,12 +195,7 @@ int InstrEmit_fnmaddx(PPCHIRBuilder& f, const InstrData& i) {
Value* v = f.Neg(
f.MulAdd(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC), f.LoadFPR(i.A.FRB)));
f.StoreFPR(i.A.FRT, v);
// f.UpdateFPRF(v);
if (i.A.Rc) {
// e.update_cr_with_cond(1, v);
XEINSTRNOTIMPLEMENTED();
return 1;
}
f.UpdateFPSCR(v, i.A.Rc);
return 0;
}
@ -294,12 +205,7 @@ int InstrEmit_fnmaddsx(PPCHIRBuilder& f, const InstrData& i) {
f.MulAdd(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC), f.LoadFPR(i.A.FRB)));
v = f.Convert(f.Convert(v, FLOAT32_TYPE), FLOAT64_TYPE);
f.StoreFPR(i.A.FRT, v);
// f.UpdateFPRF(v);
if (i.A.Rc) {
// e.update_cr_with_cond(1, v);
XEINSTRNOTIMPLEMENTED();
return 1;
}
f.UpdateFPSCR(v, i.A.Rc);
return 0;
}
@ -308,12 +214,7 @@ int InstrEmit_fnmsubx(PPCHIRBuilder& f, const InstrData& i) {
Value* v = f.Neg(
f.MulSub(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC), f.LoadFPR(i.A.FRB)));
f.StoreFPR(i.A.FRT, v);
// f.UpdateFPRF(v);
if (i.A.Rc) {
// e.update_cr_with_cond(1, v);
XEINSTRNOTIMPLEMENTED();
return 1;
}
f.UpdateFPSCR(v, i.A.Rc);
return 0;
}
@ -323,12 +224,7 @@ int InstrEmit_fnmsubsx(PPCHIRBuilder& f, const InstrData& i) {
f.MulSub(f.LoadFPR(i.A.FRA), f.LoadFPR(i.A.FRC), f.LoadFPR(i.A.FRB)));
v = f.Convert(f.Convert(v, FLOAT32_TYPE), FLOAT64_TYPE);
f.StoreFPR(i.A.FRT, v);
// f.UpdateFPRF(v);
if (i.A.Rc) {
// e.update_cr_with_cond(1, v);
XEINSTRNOTIMPLEMENTED();
return 1;
}
f.UpdateFPSCR(v, i.A.Rc);
return 0;
}
@ -338,12 +234,7 @@ int InstrEmit_fcfidx(PPCHIRBuilder& f, const InstrData& i) {
// frD <- signed_int64_to_double( frB )
Value* v = f.Convert(f.Cast(f.LoadFPR(i.X.RB), INT64_TYPE), FLOAT64_TYPE);
f.StoreFPR(i.X.RT, v);
// f.UpdateFPRF(v);
if (i.A.Rc) {
// e.update_cr_with_cond(1, v);
XEINSTRNOTIMPLEMENTED();
return 1;
}
f.UpdateFPSCR(v, i.A.Rc);
return 0;
}
@ -354,12 +245,7 @@ int InstrEmit_fctidx(PPCHIRBuilder& f, const InstrData& i) {
Value* v = f.Convert(f.LoadFPR(i.X.RB), INT64_TYPE, round_mode);
v = f.Cast(v, FLOAT64_TYPE);
f.StoreFPR(i.X.RT, v);
// f.UpdateFPRF(v);
if (i.X.Rc) {
// e.update_cr_with_cond(1, v);
XEINSTRNOTIMPLEMENTED();
return 1;
}
f.UpdateFPSCR(v, i.X.Rc);
return 0;
}
@ -375,12 +261,7 @@ int InstrEmit_fctiwx(PPCHIRBuilder& f, const InstrData& i) {
Value* v = f.Convert(f.LoadFPR(i.X.RB), INT32_TYPE, round_mode);
v = f.Cast(f.ZeroExtend(v, INT64_TYPE), FLOAT64_TYPE);
f.StoreFPR(i.X.RT, v);
// f.UpdateFPRF(v);
if (i.X.Rc) {
// e.update_cr_with_cond(1, v);
XEINSTRNOTIMPLEMENTED();
return 1;
}
f.UpdateFPSCR(v, i.X.Rc);
return 0;
}
@ -396,12 +277,7 @@ int InstrEmit_frspx(PPCHIRBuilder& f, const InstrData& i) {
Value* v = f.Convert(f.LoadFPR(i.X.RB), FLOAT32_TYPE, round_mode);
v = f.Convert(v, FLOAT64_TYPE);
f.StoreFPR(i.X.RT, v);
// f.UpdateFPRF(v);
if (i.X.Rc) {
// e.update_cr_with_cond(1, v);
XEINSTRNOTIMPLEMENTED();
return 1;
}
f.UpdateFPSCR(v, i.X.Rc);
return 0;
}
@ -425,8 +301,7 @@ int InstrEmit_fcmpx_(PPCHIRBuilder& f, const InstrData& i, bool ordered) {
// TODO(benvanik): update FPCC for mffsx/etc
// TODO(benvanik): update VXSNAN
const uint32_t crf = i.X.RT >> 2;
// f.UpdateFPRF(v);
f.UpdateCR(crf, f.LoadFPR(i.X.RA), f.LoadFPR(i.X.RB), false);
f.UpdateCR(crf, f.LoadFPR(i.X.RA), f.LoadFPR(i.X.RB));
return 0;
}
int InstrEmit_fcmpo(PPCHIRBuilder& f, const InstrData& i) {
@ -448,7 +323,7 @@ int InstrEmit_mffsx(PPCHIRBuilder& f, const InstrData& i) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
Value* v = f.Cast(f.LoadFPSCR(), FLOAT64_TYPE);
Value* v = f.Cast(f.ZeroExtend(f.LoadFPSCR(), INT64_TYPE), FLOAT64_TYPE);
f.StoreFPR(i.X.RT, v);
return 0;
}
@ -464,10 +339,6 @@ int InstrEmit_mtfsb1x(PPCHIRBuilder& f, const InstrData& i) {
}
int InstrEmit_mtfsfx(PPCHIRBuilder& f, const InstrData& i) {
if (i.XFL.Rc) {
XEINSTRNOTIMPLEMENTED();
return 1;
}
if (i.XFL.L) {
// Move/shift.
XEINSTRNOTIMPLEMENTED();
@ -477,7 +348,11 @@ int InstrEmit_mtfsfx(PPCHIRBuilder& f, const InstrData& i) {
// TODO(benvanik): use w/field mask to select bits.
// i.XFL.W;
// i.XFL.FM;
f.StoreFPSCR(f.Cast(f.LoadFPR(i.XFL.RB), INT64_TYPE));
f.StoreFPSCR(
f.Truncate(f.Cast(f.LoadFPR(i.XFL.RB), INT64_TYPE), INT32_TYPE));
}
if (i.XFL.Rc) {
f.CopyFPSCRToCR1();
}
return 0;
}
@ -493,11 +368,7 @@ int InstrEmit_fabsx(PPCHIRBuilder& f, const InstrData& i) {
// frD <- abs(frB)
Value* v = f.Abs(f.LoadFPR(i.X.RB));
f.StoreFPR(i.X.RT, v);
if (i.X.Rc) {
// e.update_cr_with_cond(1, v);
XEINSTRNOTIMPLEMENTED();
return 1;
}
f.UpdateFPSCR(v, i.X.Rc);
return 0;
}
@ -505,11 +376,7 @@ int InstrEmit_fmrx(PPCHIRBuilder& f, const InstrData& i) {
// frD <- (frB)
Value* v = f.LoadFPR(i.X.RB);
f.StoreFPR(i.X.RT, v);
if (i.X.Rc) {
// e.update_cr_with_cond(1, v);
XEINSTRNOTIMPLEMENTED();
return 1;
}
f.UpdateFPSCR(v, i.X.Rc);
return 0;
}
@ -517,11 +384,7 @@ int InstrEmit_fnabsx(PPCHIRBuilder& f, const InstrData& i) {
// frD <- !abs(frB)
Value* v = f.Neg(f.Abs(f.LoadFPR(i.X.RB)));
f.StoreFPR(i.X.RT, v);
if (i.X.Rc) {
// e.update_cr_with_cond(1, v);
XEINSTRNOTIMPLEMENTED();
return 1;
}
f.UpdateFPSCR(v, i.X.Rc);
return 0;
}
@ -529,11 +392,7 @@ int InstrEmit_fnegx(PPCHIRBuilder& f, const InstrData& i) {
// frD <- ¬ frB[0] || frB[1-63]
Value* v = f.Neg(f.LoadFPR(i.X.RB));
f.StoreFPR(i.X.RT, v);
if (i.X.Rc) {
// e.update_cr_with_cond(1, v);
XEINSTRNOTIMPLEMENTED();
return 1;
}
f.UpdateFPSCR(v, i.X.Rc);
return 0;
}

View File

@ -380,11 +380,11 @@ void PPCHIRBuilder::UpdateCR6(Value* src_value) {
}
Value* PPCHIRBuilder::LoadFPSCR() {
return LoadContext(offsetof(PPCContext, fpscr), INT64_TYPE);
return LoadContext(offsetof(PPCContext, fpscr), INT32_TYPE);
}
void PPCHIRBuilder::StoreFPSCR(Value* value) {
assert_true(value->type == INT64_TYPE);
assert_true(value->type == INT32_TYPE);
StoreContext(offsetof(PPCContext, fpscr), value);
auto& trace_reg = trace_info_.dests[trace_info_.dest_count++];
@ -392,13 +392,59 @@ void PPCHIRBuilder::StoreFPSCR(Value* value) {
trace_reg.value = value;
}
void PPCHIRBuilder::UpdateFPSCR(Value* result, bool update_cr1) {
// TODO(benvanik): detect overflow and nan cases.
// fx and vx are the most important.
Value* fx = LoadConstantInt8(0);
Value* fex = LoadConstantInt8(0);
Value* vx = LoadConstantInt8(0);
Value* ox = LoadConstantInt8(0);
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_fex), fex);
StoreContext(offsetof(PPCContext, cr1.cr1_vx), vx);
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() {
// Pull out of FPSCR.
Value* fpscr = LoadFPSCR();
StoreContext(offsetof(PPCContext, cr1.cr1_fx),
And(Truncate(Shr(fpscr, 31), INT8_TYPE), LoadConstantInt8(1)));
StoreContext(offsetof(PPCContext, cr1.cr1_fex),
And(Truncate(Shr(fpscr, 30), INT8_TYPE), LoadConstantInt8(1)));
StoreContext(offsetof(PPCContext, cr1.cr1_vx),
And(Truncate(Shr(fpscr, 29), INT8_TYPE), LoadConstantInt8(1)));
StoreContext(offsetof(PPCContext, cr1.cr1_ox),
And(Truncate(Shr(fpscr, 28), INT8_TYPE), LoadConstantInt8(1)));
}
Value* PPCHIRBuilder::LoadXER() {
Value* v = Shl(ZeroExtend(LoadCA(), INT64_TYPE), 29);
// TODO(benvanik): construct with other flags; overflow, etc?
return v;
}
void PPCHIRBuilder::StoreXER(Value* value) { assert_always(); }
void PPCHIRBuilder::StoreXER(Value* value) {
// TODO(benvanik): use other fields? For now, just pull out CA.
StoreCA(Truncate(And(Shr(value, 29), LoadConstantInt64(1)), INT8_TYPE));
}
Value* PPCHIRBuilder::LoadCA() {
return LoadContext(offsetof(PPCContext, xer_ca), INT8_TYPE);

View File

@ -59,6 +59,8 @@ class PPCHIRBuilder : public hir::HIRBuilder {
void UpdateCR6(Value* src_value);
Value* LoadFPSCR();
void StoreFPSCR(Value* value);
void UpdateFPSCR(Value* result, bool update_cr1);
void CopyFPSCRToCR1();
Value* LoadXER();
void StoreXER(Value* value);
// void UpdateXERWithOverflow();

View File

@ -504,7 +504,8 @@ X_STATUS Emulator::CompleteLaunch(const std::wstring& path,
XELOGI("Launching module %s", next_module.c_str());
auto module = kernel_state_->LoadUserModule(next_module.c_str());
if (!module) {
XELOGE("Failed to load user module %s", path);
auto path_str = xe::to_string(path);
XELOGE("Failed to load user module %s", path.c_str());
return X_STATUS_NOT_FOUND;
}