diff --git a/src/alloy/frontend/ppc/ppc_context.h b/src/alloy/frontend/ppc/ppc_context.h index 5bc5f159e..5e40b19f2 100644 --- a/src/alloy/frontend/ppc/ppc_context.h +++ b/src/alloy/frontend/ppc/ppc_context.h @@ -144,40 +144,40 @@ typedef struct XECACHEALIGN64 PPCContext_s { union { uint32_t value; struct { - uint8_t fx :1; // FP exception summary -- sticky - uint8_t fex :1; // FP enabled exception summary - uint8_t vx :1; // FP invalid operation exception summary - uint8_t ox :1; // FP overflow exception -- sticky - uint8_t ux :1; // FP underflow exception -- sticky - uint8_t zx :1; // FP zero divide exception -- sticky - uint8_t xx :1; // FP inexact exception -- sticky - uint8_t vxsnan :1; // FP invalid op exception: SNaN -- sticky - uint8_t vxisi :1; // FP invalid op exception: infinity - infinity -- sticky - uint8_t vxidi :1; // FP invalid op exception: infinity / infinity -- sticky - uint8_t vxzdz :1; // FP invalid op exception: 0 / 0 -- sticky - uint8_t vximz :1; // FP invalid op exception: infinity * 0 -- sticky - uint8_t vxvc :1; // FP invalid op exception: invalid compare -- sticky - uint8_t fr :1; // FP fraction rounded - uint8_t fi :1; // FP fraction inexact - uint8_t fprf_c :1; // FP result class - uint8_t fprf_lt :1; // FP result less than or negative (FL or <) - uint8_t fprf_gt :1; // FP result greater than or positive (FG or >) - uint8_t fprf_eq :1; // FP result equal or zero (FE or =) - uint8_t fprf_un :1; // FP result unordered or NaN (FU or ?) - uint8_t reserved :1; - uint8_t vxsoft :1; // FP invalid op exception: software request -- sticky - uint8_t vxsqrt :1; // FP invalid op exception: invalid sqrt -- sticky - uint8_t vxcvi :1; // FP invalid op exception: invalid integer convert -- sticky - uint8_t ve :1; // FP invalid op exception enable - uint8_t oe :1; // IEEE floating-point overflow exception enable - uint8_t ue :1; // IEEE floating-point underflow exception enable - uint8_t ze :1; // IEEE floating-point zero divide exception enable - uint8_t xe :1; // IEEE floating-point inexact exception enable - uint8_t ni :1; // Floating-point non-IEEE mode - uint8_t rn :2; // FP rounding control: 00 = nearest + uint32_t rn :2; // FP rounding control: 00 = nearest // 01 = toward zero // 10 = toward +infinity // 11 = toward -infinity + uint32_t ni :1; // Floating-point non-IEEE mode + uint32_t xe :1; // IEEE floating-point inexact exception enable + uint32_t ze :1; // IEEE floating-point zero divide exception enable + uint32_t ue :1; // IEEE floating-point underflow exception enable + uint32_t oe :1; // IEEE floating-point overflow exception enable + uint32_t ve :1; // FP invalid op exception enable + uint32_t vxcvi :1; // FP invalid op exception: invalid integer convert -- sticky + uint32_t vxsqrt :1; // FP invalid op exception: invalid sqrt -- sticky + uint32_t vxsoft :1; // FP invalid op exception: software request -- sticky + uint32_t reserved :1; + uint32_t fprf_un :1; // FP result unordered or NaN (FU or ?) + uint32_t fprf_eq :1; // FP result equal or zero (FE or =) + uint32_t fprf_gt :1; // FP result greater than or positive (FG or >) + uint32_t fprf_lt :1; // FP result less than or negative (FL or <) + uint32_t fprf_c :1; // FP result class + uint32_t fi :1; // FP fraction inexact + uint32_t fr :1; // FP fraction rounded + uint32_t vxvc :1; // FP invalid op exception: invalid compare -- sticky + uint32_t vximz :1; // FP invalid op exception: infinity * 0 -- sticky + uint32_t vxzdz :1; // FP invalid op exception: 0 / 0 -- sticky + uint32_t vxidi :1; // FP invalid op exception: infinity / infinity -- sticky + uint32_t vxisi :1; // FP invalid op exception: infinity - infinity -- sticky + uint32_t vxsnan :1; // FP invalid op exception: SNaN -- sticky + uint32_t xx :1; // FP inexact exception -- sticky + uint32_t zx :1; // FP zero divide exception -- sticky + uint32_t ux :1; // FP underflow exception -- sticky + uint32_t ox :1; // FP overflow exception -- sticky + uint32_t vx :1; // FP invalid operation exception summary + uint32_t fex :1; // FP enabled exception summary + uint32_t fx :1; // FP exception summary -- sticky } bits; } fpscr; // Floating-point status and control register diff --git a/src/alloy/frontend/ppc/ppc_emit_fpu.cc b/src/alloy/frontend/ppc/ppc_emit_fpu.cc index 683a2d3de..c09fea20f 100644 --- a/src/alloy/frontend/ppc/ppc_emit_fpu.cc +++ b/src/alloy/frontend/ppc/ppc_emit_fpu.cc @@ -426,8 +426,12 @@ XEEMITTER(mcrfs, 0xFC000080, X )(PPCHIRBuilder& f, InstrData& i) { } XEEMITTER(mffsx, 0xFC00048E, X )(PPCHIRBuilder& f, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + if (i.X.Rc) { + XEINSTRNOTIMPLEMENTED(); + return 1; + } + f.StoreFPR(i.X.RT, f.Cast(f.LoadFPSCR(), FLOAT64_TYPE)); + return 0; } XEEMITTER(mtfsb0x, 0xFC00008C, X )(PPCHIRBuilder& f, InstrData& i) { @@ -441,8 +445,19 @@ XEEMITTER(mtfsb1x, 0xFC00004C, X )(PPCHIRBuilder& f, InstrData& i) { } XEEMITTER(mtfsfx, 0xFC00058E, XFL)(PPCHIRBuilder& f, InstrData& i) { - XEINSTRNOTIMPLEMENTED(); - return 1; + if (i.XFL.Rc) { + XEINSTRNOTIMPLEMENTED(); + return 1; + } + if (i.XFL.L) { + // Move/shift. + XEINSTRNOTIMPLEMENTED(); + return 1; + } else { + // Directly store. + f.StoreFPSCR(f.Cast(f.LoadFPR(i.XFL.RB), INT64_TYPE)); + } + return 0; } XEEMITTER(mtfsfix, 0xFC00010C, X )(PPCHIRBuilder& f, InstrData& i) { diff --git a/src/alloy/frontend/ppc/ppc_hir_builder.cc b/src/alloy/frontend/ppc/ppc_hir_builder.cc index a8bec8435..db2f304b4 100644 --- a/src/alloy/frontend/ppc/ppc_hir_builder.cc +++ b/src/alloy/frontend/ppc/ppc_hir_builder.cc @@ -268,6 +268,15 @@ void PPCHIRBuilder::UpdateCR6(Value* src_value) { StoreContext(offsetof(PPCContext, cr6.cr6_none_equal), IsFalse(src_value)); } +Value* PPCHIRBuilder::LoadFPSCR() { + return LoadContext(offsetof(PPCContext, fpscr), INT64_TYPE); +} + +void PPCHIRBuilder::StoreFPSCR(Value* value) { + XEASSERT(value->type == INT64_TYPE); + StoreContext(offsetof(PPCContext, fpscr), value); +} + Value* PPCHIRBuilder::LoadXER() { XEASSERTALWAYS(); return NULL; diff --git a/src/alloy/frontend/ppc/ppc_hir_builder.h b/src/alloy/frontend/ppc/ppc_hir_builder.h index b386d95a1..58560bf02 100644 --- a/src/alloy/frontend/ppc/ppc_hir_builder.h +++ b/src/alloy/frontend/ppc/ppc_hir_builder.h @@ -49,6 +49,8 @@ public: void UpdateCR(uint32_t n, Value* lhs, bool is_signed = true); void UpdateCR(uint32_t n, Value* lhs, Value* rhs, bool is_signed = true); void UpdateCR6(Value* src_value); + Value* LoadFPSCR(); + void StoreFPSCR(Value* value); Value* LoadXER(); void StoreXER(Value* value); //void UpdateXERWithOverflow(); diff --git a/src/alloy/frontend/ppc/ppc_instr.h b/src/alloy/frontend/ppc/ppc_instr.h index b9c0c30f3..01026e7f6 100644 --- a/src/alloy/frontend/ppc/ppc_instr.h +++ b/src/alloy/frontend/ppc/ppc_instr.h @@ -177,9 +177,9 @@ typedef struct { uint32_t Rc : 1; uint32_t : 10; uint32_t RB : 5; - uint32_t : 1; + uint32_t W : 1; uint32_t FM : 8; - uint32_t : 1; + uint32_t L : 1; uint32_t : 6; } XFL; // kXEPPCInstrFormatXS