diff --git a/ARMeilleure/Instructions/InstEmitSystem.cs b/ARMeilleure/Instructions/InstEmitSystem.cs index 5bcfbff779..49973404fa 100644 --- a/ARMeilleure/Instructions/InstEmitSystem.cs +++ b/ARMeilleure/Instructions/InstEmitSystem.cs @@ -1,5 +1,6 @@ using ARMeilleure.Decoders; using ARMeilleure.IntermediateRepresentation; +using ARMeilleure.State; using ARMeilleure.Translation; using System; @@ -32,7 +33,7 @@ namespace ARMeilleure.Instructions { case 0b11_011_0000_0000_001: dlg = new _U64(NativeInterface.GetCtrEl0); break; case 0b11_011_0000_0000_111: dlg = new _U64(NativeInterface.GetDczidEl0); break; - case 0b11_011_0100_0010_000: dlg = new _U64(NativeInterface.GetNzcv); break; + case 0b11_011_0100_0010_000: EmitGetNzcv(context); return; case 0b11_011_0100_0100_000: dlg = new _U64(NativeInterface.GetFpcr); break; case 0b11_011_0100_0100_001: dlg = new _U64(NativeInterface.GetFpsr); break; case 0b11_011_1101_0000_010: dlg = new _U64(NativeInterface.GetTpidrEl0); break; @@ -54,7 +55,7 @@ namespace ARMeilleure.Instructions switch (GetPackedId(op)) { - case 0b11_011_0100_0010_000: dlg = new _Void_U64(NativeInterface.SetNzcv); break; + case 0b11_011_0100_0010_000: EmitSetNzcv(context); return; case 0b11_011_0100_0100_000: dlg = new _Void_U64(NativeInterface.SetFpcr); break; case 0b11_011_0100_0100_001: dlg = new _Void_U64(NativeInterface.SetFpsr); break; case 0b11_011_1101_0000_010: dlg = new _Void_U64(NativeInterface.SetTpidrEl0); break; @@ -112,5 +113,44 @@ namespace ARMeilleure.Instructions return id; } + + private static void EmitGetNzcv(ArmEmitterContext context) + { + OpCodeSystem op = (OpCodeSystem)context.CurrOp; + + Operand vSh = context.ShiftLeft(GetFlag(PState.VFlag), Const((int)PState.VFlag)); + Operand cSh = context.ShiftLeft(GetFlag(PState.CFlag), Const((int)PState.CFlag)); + Operand zSh = context.ShiftLeft(GetFlag(PState.ZFlag), Const((int)PState.ZFlag)); + Operand nSh = context.ShiftLeft(GetFlag(PState.NFlag), Const((int)PState.NFlag)); + + Operand nzcvSh = context.BitwiseOr(context.BitwiseOr(nSh, zSh), context.BitwiseOr(cSh, vSh)); + + SetIntOrZR(context, op.Rt, nzcvSh); + } + + private static void EmitSetNzcv(ArmEmitterContext context) + { + OpCodeSystem op = (OpCodeSystem)context.CurrOp; + + Operand t = GetIntOrZR(context, op.Rt); + t = context.ConvertI64ToI32(t); + + Operand v = context.ShiftRightUI(t, Const((int)PState.VFlag)); + v = context.BitwiseAnd (v, Const(1)); + + Operand c = context.ShiftRightUI(t, Const((int)PState.CFlag)); + c = context.BitwiseAnd (c, Const(1)); + + Operand z = context.ShiftRightUI(t, Const((int)PState.ZFlag)); + z = context.BitwiseAnd (z, Const(1)); + + Operand n = context.ShiftRightUI(t, Const((int)PState.NFlag)); + n = context.BitwiseAnd (n, Const(1)); + + SetFlag(context, PState.VFlag, v); + SetFlag(context, PState.CFlag, c); + SetFlag(context, PState.ZFlag, z); + SetFlag(context, PState.NFlag, n); + } } } diff --git a/ARMeilleure/Instructions/NativeInterface.cs b/ARMeilleure/Instructions/NativeInterface.cs index 2d76f4b246..3a1e91c8ed 100644 --- a/ARMeilleure/Instructions/NativeInterface.cs +++ b/ARMeilleure/Instructions/NativeInterface.cs @@ -77,25 +77,6 @@ namespace ARMeilleure.Instructions return (ulong)GetContext().DczidEl0; } - public static ulong GetNzcv() - { - void Insert(ref ulong value, PState bit, bool flag) - { - value |= (flag ? 1UL : 0UL) << (int)bit; - } - - ExecutionContext context = GetContext(); - - ulong value = 0UL; - - Insert(ref value, PState.VFlag, context.GetPstateFlag(PState.VFlag)); - Insert(ref value, PState.CFlag, context.GetPstateFlag(PState.CFlag)); - Insert(ref value, PState.ZFlag, context.GetPstateFlag(PState.ZFlag)); - Insert(ref value, PState.NFlag, context.GetPstateFlag(PState.NFlag)); - - return value; - } - public static ulong GetFpcr() { return (ulong)GetContext().Fpcr; @@ -126,25 +107,6 @@ namespace ARMeilleure.Instructions return GetContext().CntpctEl0; } - public static void SetNzcv(ulong value) - { - bool Extract(ulong value, PState bit) - { - value >>= (int)bit; - - value &= 1UL; - - return value != 0UL; - } - - ExecutionContext context = GetContext(); - - context.SetPstateFlag(PState.VFlag, Extract(value, PState.VFlag)); - context.SetPstateFlag(PState.CFlag, Extract(value, PState.CFlag)); - context.SetPstateFlag(PState.ZFlag, Extract(value, PState.ZFlag)); - context.SetPstateFlag(PState.NFlag, Extract(value, PState.NFlag)); - } - public static void SetFpcr(ulong value) { GetContext().Fpcr = (FPCR)value;