aboutsummaryrefslogtreecommitdiff
path: root/ARMeilleure
diff options
context:
space:
mode:
Diffstat (limited to 'ARMeilleure')
-rw-r--r--ARMeilleure/Instructions/InstEmitFlowHelper.cs2
-rw-r--r--ARMeilleure/Instructions/InstEmitSimdCmp.cs18
-rw-r--r--ARMeilleure/Instructions/InstEmitSimdCmp32.cs27
-rw-r--r--ARMeilleure/Instructions/InstEmitSimdShift32.cs2
-rw-r--r--ARMeilleure/Instructions/InstEmitSystem32.cs54
-rw-r--r--ARMeilleure/Instructions/NativeInterface.cs26
-rw-r--r--ARMeilleure/State/FPCR.cs10
-rw-r--r--ARMeilleure/State/FPSR.cs8
-rw-r--r--ARMeilleure/State/FPState.cs7
-rw-r--r--ARMeilleure/State/PState.cs3
-rw-r--r--ARMeilleure/Translation/Delegates.cs1
11 files changed, 94 insertions, 64 deletions
diff --git a/ARMeilleure/Instructions/InstEmitFlowHelper.cs b/ARMeilleure/Instructions/InstEmitFlowHelper.cs
index 1ce0cdaa..87549aa3 100644
--- a/ARMeilleure/Instructions/InstEmitFlowHelper.cs
+++ b/ARMeilleure/Instructions/InstEmitFlowHelper.cs
@@ -242,7 +242,7 @@ namespace ARMeilleure.Instructions
private static void EmitNativeCallWithGuestAddress(ArmEmitterContext context, Operand funcAddr, Operand guestAddress, bool isJump)
{
Operand nativeContextPtr = context.LoadArgument(OperandType.I64, 0);
- context.Store(context.Add(nativeContextPtr, Const(NativeContext.GetCallAddressOffset())), guestAddress);
+ context.Store(context.Add(nativeContextPtr, Const((long)NativeContext.GetCallAddressOffset())), guestAddress);
EmitNativeCall(context, nativeContextPtr, funcAddr, isJump);
}
diff --git a/ARMeilleure/Instructions/InstEmitSimdCmp.cs b/ARMeilleure/Instructions/InstEmitSimdCmp.cs
index ff97084b..22cf9f21 100644
--- a/ARMeilleure/Instructions/InstEmitSimdCmp.cs
+++ b/ARMeilleure/Instructions/InstEmitSimdCmp.cs
@@ -538,9 +538,12 @@ namespace ARMeilleure.Instructions
context.BranchIfFalse(lblNaN, isOrdered);
- Operand cf = context.AddIntrinsicInt(Intrinsic.X86Comissge, n, m);
- Operand zf = context.AddIntrinsicInt(Intrinsic.X86Comisseq, n, m);
- Operand nf = context.AddIntrinsicInt(Intrinsic.X86Comisslt, n, m);
+ Operand nCopy = context.Copy(n);
+ Operand mCopy = cmpWithZero ? context.VectorZero() : context.Copy(m);
+
+ Operand cf = context.AddIntrinsicInt(Intrinsic.X86Comissge, nCopy, mCopy);
+ Operand zf = context.AddIntrinsicInt(Intrinsic.X86Comisseq, nCopy, mCopy);
+ Operand nf = context.AddIntrinsicInt(Intrinsic.X86Comisslt, nCopy, mCopy);
SetFlag(context, PState.VFlag, Const(0));
SetFlag(context, PState.CFlag, cf);
@@ -555,9 +558,12 @@ namespace ARMeilleure.Instructions
context.BranchIfFalse(lblNaN, isOrdered);
- Operand cf = context.AddIntrinsicInt(Intrinsic.X86Comisdge, n, m);
- Operand zf = context.AddIntrinsicInt(Intrinsic.X86Comisdeq, n, m);
- Operand nf = context.AddIntrinsicInt(Intrinsic.X86Comisdlt, n, m);
+ Operand nCopy = context.Copy(n);
+ Operand mCopy = cmpWithZero ? context.VectorZero() : context.Copy(m);
+
+ Operand cf = context.AddIntrinsicInt(Intrinsic.X86Comisdge, nCopy, mCopy);
+ Operand zf = context.AddIntrinsicInt(Intrinsic.X86Comisdeq, nCopy, mCopy);
+ Operand nf = context.AddIntrinsicInt(Intrinsic.X86Comisdlt, nCopy, mCopy);
SetFlag(context, PState.VFlag, Const(0));
SetFlag(context, PState.CFlag, cf);
diff --git a/ARMeilleure/Instructions/InstEmitSimdCmp32.cs b/ARMeilleure/Instructions/InstEmitSimdCmp32.cs
index db925053..290cc17e 100644
--- a/ARMeilleure/Instructions/InstEmitSimdCmp32.cs
+++ b/ARMeilleure/Instructions/InstEmitSimdCmp32.cs
@@ -307,7 +307,10 @@ namespace ARMeilleure.Instructions
Operand zf = context.AddIntrinsicInt(Intrinsic.X86Comisseq, n, m);
Operand nf = context.AddIntrinsicInt(Intrinsic.X86Comisslt, n, m);
- EmitSetFPSCRFlags(context, nf, zf, cf, Const(0));
+ SetFpFlag(context, FPState.VFlag, Const(0));
+ SetFpFlag(context, FPState.CFlag, cf);
+ SetFpFlag(context, FPState.ZFlag, zf);
+ SetFpFlag(context, FPState.NFlag, nf);
}
else
{
@@ -321,14 +324,20 @@ namespace ARMeilleure.Instructions
Operand zf = context.AddIntrinsicInt(Intrinsic.X86Comisdeq, n, m);
Operand nf = context.AddIntrinsicInt(Intrinsic.X86Comisdlt, n, m);
- EmitSetFPSCRFlags(context, nf, zf, cf, Const(0));
+ SetFpFlag(context, FPState.VFlag, Const(0));
+ SetFpFlag(context, FPState.CFlag, cf);
+ SetFpFlag(context, FPState.ZFlag, zf);
+ SetFpFlag(context, FPState.NFlag, nf);
}
context.Branch(lblEnd);
context.MarkLabel(lblNaN);
- EmitSetFPSCRFlags(context, Const(3));
+ SetFpFlag(context, FPState.VFlag, Const(1));
+ SetFpFlag(context, FPState.CFlag, Const(1));
+ SetFpFlag(context, FPState.ZFlag, Const(0));
+ SetFpFlag(context, FPState.NFlag, Const(0));
context.MarkLabel(lblEnd);
}
@@ -354,11 +363,11 @@ namespace ARMeilleure.Instructions
Operand nzcv = context.Call(info, ne, me, Const(signalNaNs));
- EmitSetFPSCRFlags(context, nzcv);
+ EmitSetFpscrNzcv(context, nzcv);
}
}
- private static void EmitSetFPSCRFlags(ArmEmitterContext context, Operand nzcv)
+ private static void EmitSetFpscrNzcv(ArmEmitterContext context, Operand nzcv)
{
Operand Extract(Operand value, int bit)
{
@@ -378,14 +387,6 @@ namespace ARMeilleure.Instructions
SetFpFlag(context, FPState.NFlag, Extract(nzcv, 3));
}
- private static void EmitSetFPSCRFlags(ArmEmitterContext context, Operand n, Operand z, Operand c, Operand v)
- {
- SetFpFlag(context, FPState.VFlag, v);
- SetFpFlag(context, FPState.CFlag, c);
- SetFpFlag(context, FPState.ZFlag, z);
- SetFpFlag(context, FPState.NFlag, n);
- }
-
private static void EmitSse2OrAvxCmpOpF32(ArmEmitterContext context, CmpCondition cond, bool zero)
{
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
diff --git a/ARMeilleure/Instructions/InstEmitSimdShift32.cs b/ARMeilleure/Instructions/InstEmitSimdShift32.cs
index 215fe1e8..f3c002db 100644
--- a/ARMeilleure/Instructions/InstEmitSimdShift32.cs
+++ b/ARMeilleure/Instructions/InstEmitSimdShift32.cs
@@ -289,7 +289,7 @@ namespace ARMeilleure.Instructions
context.BranchIfFalse(lblNoSat, context.BitwiseOr(gt, lt));
- // TODO: Set QC (to 1) on FPSCR here.
+ context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc)));
context.MarkLabel(lblNoSat);
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);
+ }
}
}
diff --git a/ARMeilleure/Instructions/NativeInterface.cs b/ARMeilleure/Instructions/NativeInterface.cs
index e8f0db84..b4afcc02 100644
--- a/ARMeilleure/Instructions/NativeInterface.cs
+++ b/ARMeilleure/Instructions/NativeInterface.cs
@@ -87,14 +87,8 @@ namespace ARMeilleure.Instructions
{
var context = GetContext();
- uint result = (uint)(context.Fpsr & FPSR.A32Mask) | (uint)(context.Fpcr & FPCR.A32Mask);
-
- result |= context.GetFPstateFlag(FPState.NFlag) ? (1u << 31) : 0;
- result |= context.GetFPstateFlag(FPState.ZFlag) ? (1u << 30) : 0;
- result |= context.GetFPstateFlag(FPState.CFlag) ? (1u << 29) : 0;
- result |= context.GetFPstateFlag(FPState.VFlag) ? (1u << 28) : 0;
-
- return result;
+ return (uint)(context.Fpsr & FPSR.A32Mask & ~FPSR.Nzcv) |
+ (uint)(context.Fpcr & FPCR.A32Mask);
}
public static ulong GetTpidrEl0()
@@ -142,17 +136,17 @@ namespace ARMeilleure.Instructions
GetContext().Fpsr = (FPSR)value;
}
- public static void SetFpscr(uint value)
+ public static void SetFpsrQc()
{
- var context = GetContext();
+ GetContext().Fpsr |= FPSR.Qc;
+ }
- context.SetFPstateFlag(FPState.NFlag, (value & (1u << 31)) != 0);
- context.SetFPstateFlag(FPState.ZFlag, (value & (1u << 30)) != 0);
- context.SetFPstateFlag(FPState.CFlag, (value & (1u << 29)) != 0);
- context.SetFPstateFlag(FPState.VFlag, (value & (1u << 28)) != 0);
+ public static void SetFpscr(uint fpscr)
+ {
+ var context = GetContext();
- context.Fpsr = FPSR.A32Mask & (FPSR)value;
- context.Fpcr = FPCR.A32Mask & (FPCR)value;
+ context.Fpsr = FPSR.A32Mask & (FPSR)fpscr;
+ context.Fpcr = FPCR.A32Mask & (FPCR)fpscr;
}
public static void SetTpidrEl0(ulong value)
diff --git a/ARMeilleure/State/FPCR.cs b/ARMeilleure/State/FPCR.cs
index 913065ea..40d56045 100644
--- a/ARMeilleure/State/FPCR.cs
+++ b/ARMeilleure/State/FPCR.cs
@@ -5,12 +5,12 @@ namespace ARMeilleure.State
[Flags]
public enum FPCR : uint
{
- Ufe = 1 << 11,
- Fz = 1 << 24,
- Dn = 1 << 25,
- Ahp = 1 << 26,
+ Ufe = 1u << 11,
+ Fz = 1u << 24,
+ Dn = 1u << 25,
+ Ahp = 1u << 26,
- A32Mask = 0x07ffff00
+ A32Mask = 0x07FF9F00u
}
public static class FPCRExtensions
diff --git a/ARMeilleure/State/FPSR.cs b/ARMeilleure/State/FPSR.cs
index 47323b35..800dcd10 100644
--- a/ARMeilleure/State/FPSR.cs
+++ b/ARMeilleure/State/FPSR.cs
@@ -5,9 +5,11 @@ namespace ARMeilleure.State
[Flags]
public enum FPSR : uint
{
- Ufc = 1 << 3,
- Qc = 1 << 27,
+ Ufc = 1u << 3,
+ Qc = 1u << 27,
- A32Mask = 0xf800000f
+ Nzcv = (1u << 31) | (1u << 30) | (1u << 29) | (1u << 28),
+
+ A32Mask = 0xF800009Fu
}
}
diff --git a/ARMeilleure/State/FPState.cs b/ARMeilleure/State/FPState.cs
index 2fe2a567..60c7126c 100644
--- a/ARMeilleure/State/FPState.cs
+++ b/ARMeilleure/State/FPState.cs
@@ -1,10 +1,5 @@
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace ARMeilleure.State
+namespace ARMeilleure.State
{
- [Flags]
public enum FPState
{
VFlag = 28,
diff --git a/ARMeilleure/State/PState.cs b/ARMeilleure/State/PState.cs
index 8dbd84df..e087e702 100644
--- a/ARMeilleure/State/PState.cs
+++ b/ARMeilleure/State/PState.cs
@@ -1,8 +1,5 @@
-using System;
-
namespace ARMeilleure.State
{
- [Flags]
public enum PState
{
TFlag = 5,
diff --git a/ARMeilleure/Translation/Delegates.cs b/ARMeilleure/Translation/Delegates.cs
index 7c1951ed..88d01818 100644
--- a/ARMeilleure/Translation/Delegates.cs
+++ b/ARMeilleure/Translation/Delegates.cs
@@ -126,6 +126,7 @@ namespace ARMeilleure.Translation
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpcr)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpscr))); // A32 only.
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsr)));
+ SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsrQc))); // A32 only.
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl0)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl032))); // A32 only.
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.SupervisorCall)));