aboutsummaryrefslogtreecommitdiff
path: root/ARMeilleure/Instructions
diff options
context:
space:
mode:
Diffstat (limited to 'ARMeilleure/Instructions')
-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
6 files changed, 82 insertions, 47 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)