diff options
Diffstat (limited to 'ARMeilleure/Instructions/InstEmitSystem32.cs')
| -rw-r--r-- | ARMeilleure/Instructions/InstEmitSystem32.cs | 54 |
1 files changed, 44 insertions, 10 deletions
diff --git a/ARMeilleure/Instructions/InstEmitSystem32.cs b/ARMeilleure/Instructions/InstEmitSystem32.cs index 14f73c3a..fcd6fc8a 100644 --- a/ARMeilleure/Instructions/InstEmitSystem32.cs +++ b/ARMeilleure/Instructions/InstEmitSystem32.cs @@ -186,14 +186,12 @@ namespace ARMeilleure.Instructions return; } - MethodInfo info; - switch (op.Sreg) { case 0b0000: // FPSID throw new NotImplementedException("Supervisor Only"); case 0b0001: // FPSCR - info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpscr)); break; + EmitGetFpscr(context); return; case 0b0101: // MVFR2 throw new NotImplementedException("MVFR2"); case 0b0110: // MVFR1 @@ -205,22 +203,18 @@ namespace ARMeilleure.Instructions default: throw new NotImplementedException($"Unknown VMRS 0x{op.RawOpCode:X8} at 0x{op.Address:X16}."); } - - SetIntA32(context, op.Rt, context.Call(info)); } public static void Vmsr(ArmEmitterContext context) { OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp; - MethodInfo info; - switch (op.Sreg) { case 0b0000: // FPSID throw new NotImplementedException("Supervisor Only"); case 0b0001: // FPSCR - info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpscr)); break; + EmitSetFpscr(context); return; case 0b0101: // MVFR2 throw new NotImplementedException("MVFR2"); case 0b0110: // MVFR1 @@ -232,8 +226,6 @@ namespace ARMeilleure.Instructions default: throw new NotImplementedException($"Unknown VMSR 0x{op.RawOpCode:X8} at 0x{op.Address:X16}."); } - - context.Call(info, GetIntA32(context, op.Rt)); } private static void EmitSetNzcv(ArmEmitterContext context, Operand t) @@ -255,5 +247,47 @@ namespace ARMeilleure.Instructions SetFlag(context, PState.ZFlag, z); SetFlag(context, PState.NFlag, n); } + + private static void EmitGetFpscr(ArmEmitterContext context) + { + OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp; + + Operand vSh = context.ShiftLeft(GetFpFlag(FPState.VFlag), Const((int)FPState.VFlag)); + Operand cSh = context.ShiftLeft(GetFpFlag(FPState.CFlag), Const((int)FPState.CFlag)); + Operand zSh = context.ShiftLeft(GetFpFlag(FPState.ZFlag), Const((int)FPState.ZFlag)); + Operand nSh = context.ShiftLeft(GetFpFlag(FPState.NFlag), Const((int)FPState.NFlag)); + + Operand nzcvSh = context.BitwiseOr(context.BitwiseOr(nSh, zSh), context.BitwiseOr(cSh, vSh)); + + Operand fpscr = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpscr))); + + SetIntA32(context, op.Rt, context.BitwiseOr(nzcvSh, fpscr)); + } + + private static void EmitSetFpscr(ArmEmitterContext context) + { + OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp; + + Operand t = GetIntA32(context, op.Rt); + + Operand v = context.ShiftRightUI(t, Const((int)FPState.VFlag)); + v = context.BitwiseAnd(v, Const(1)); + + Operand c = context.ShiftRightUI(t, Const((int)FPState.CFlag)); + c = context.BitwiseAnd(c, Const(1)); + + Operand z = context.ShiftRightUI(t, Const((int)FPState.ZFlag)); + z = context.BitwiseAnd(z, Const(1)); + + Operand n = context.ShiftRightUI(t, Const((int)FPState.NFlag)); + n = context.BitwiseAnd(n, Const(1)); + + SetFpFlag(context, FPState.VFlag, v); + SetFpFlag(context, FPState.CFlag, c); + SetFpFlag(context, FPState.ZFlag, z); + SetFpFlag(context, FPState.NFlag, n); + + context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpscr)), t); + } } } |
