aboutsummaryrefslogtreecommitdiff
path: root/ARMeilleure
diff options
context:
space:
mode:
authorLDj3SNuD <35856442+LDj3SNuD@users.noreply.github.com>2020-12-07 10:37:07 +0100
committerGitHub <noreply@github.com>2020-12-07 10:37:07 +0100
commit567ea726e173040ae931a37bc85fd6cd92b69363 (patch)
tree5b6487d4821c978659732d5f34abf5aa69b0dafa /ARMeilleure
parent668720b0883106fc1f44da70dddb8a3502ac7dbb (diff)
Add support for guest Fz (Fpcr) mode through host Ftz and Daz (Mxcsr) modes (fast paths). (#1630)
* Add support for guest Fz (Fpcr) mode through host Ftz and Daz (Mxcsr) modes (fast paths). * Ptc.InternalVersion = 1630 * Nits. * Address comments. * Update Ptc.cs * Address comment.
Diffstat (limited to 'ARMeilleure')
-rw-r--r--ARMeilleure/CodeGen/X86/Assembler.cs14
-rw-r--r--ARMeilleure/CodeGen/X86/CodeGenerator.cs34
-rw-r--r--ARMeilleure/CodeGen/X86/IntrinsicTable.cs2
-rw-r--r--ARMeilleure/CodeGen/X86/IntrinsicType.cs1
-rw-r--r--ARMeilleure/CodeGen/X86/PreAllocator.cs10
-rw-r--r--ARMeilleure/CodeGen/X86/X86Instruction.cs3
-rw-r--r--ARMeilleure/Instructions/InstEmitSimdArithmetic.cs111
-rw-r--r--ARMeilleure/Instructions/InstEmitSimdHelper.cs33
-rw-r--r--ARMeilleure/Instructions/NativeInterface.cs11
-rw-r--r--ARMeilleure/IntermediateRepresentation/Intrinsic.cs2
-rw-r--r--ARMeilleure/Translation/Delegates.cs1
-rw-r--r--ARMeilleure/Translation/EmitterContext.cs5
-rw-r--r--ARMeilleure/Translation/PTC/Ptc.cs2
13 files changed, 210 insertions, 19 deletions
diff --git a/ARMeilleure/CodeGen/X86/Assembler.cs b/ARMeilleure/CodeGen/X86/Assembler.cs
index d65262ea..b9751059 100644
--- a/ARMeilleure/CodeGen/X86/Assembler.cs
+++ b/ARMeilleure/CodeGen/X86/Assembler.cs
@@ -72,7 +72,7 @@ namespace ARMeilleure.CodeGen.X86
{
_instTable = new InstructionInfo[(int)X86Instruction.Count];
- // Name RM/R RM/I8 RM/I32 R/I64 R/RM Flags
+ // Name RM/R RM/I8 RM/I32 R/I64 R/RM Flags
Add(X86Instruction.Add, new InstructionInfo(0x00000001, 0x00000083, 0x00000081, BadOp, 0x00000003, InstructionFlags.None));
Add(X86Instruction.Addpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Addps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstructionFlags.Vex));
@@ -131,6 +131,7 @@ namespace ARMeilleure.CodeGen.X86
Add(X86Instruction.Imul128, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x050000f7, InstructionFlags.None));
Add(X86Instruction.Insertps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a21, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Jmp, new InstructionInfo(0x040000ff, BadOp, BadOp, BadOp, BadOp, InstructionFlags.None));
+ Add(X86Instruction.Ldmxcsr, new InstructionInfo(0x02000fae, BadOp, BadOp, BadOp, BadOp, InstructionFlags.Vex));
Add(X86Instruction.Lea, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x0000008d, InstructionFlags.None));
Add(X86Instruction.Maxpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5f, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Maxps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5f, InstructionFlags.Vex));
@@ -257,6 +258,7 @@ namespace ARMeilleure.CodeGen.X86
Add(X86Instruction.Sqrtps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f51, InstructionFlags.Vex));
Add(X86Instruction.Sqrtsd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f51, InstructionFlags.Vex | InstructionFlags.PrefixF2));
Add(X86Instruction.Sqrtss, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f51, InstructionFlags.Vex | InstructionFlags.PrefixF3));
+ Add(X86Instruction.Stmxcsr, new InstructionInfo(0x03000fae, BadOp, BadOp, BadOp, BadOp, InstructionFlags.Vex));
Add(X86Instruction.Sub, new InstructionInfo(0x00000029, 0x05000083, 0x05000081, BadOp, 0x0000002b, InstructionFlags.None));
Add(X86Instruction.Subpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5c, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Subps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5c, InstructionFlags.Vex));
@@ -526,6 +528,11 @@ namespace ARMeilleure.CodeGen.X86
WriteInstruction(dest, null, OperandType.None, X86Instruction.Jmp);
}
+ public void Ldmxcsr(Operand dest)
+ {
+ WriteInstruction(dest, null, OperandType.I32, X86Instruction.Ldmxcsr);
+ }
+
public void Lea(Operand dest, Operand source, OperandType type)
{
WriteInstruction(dest, source, type, X86Instruction.Lea);
@@ -796,6 +803,11 @@ namespace ARMeilleure.CodeGen.X86
WriteOpCode(dest, null, null, OperandType.None, info.Flags, info.OpRRM | (int)condition);
}
+ public void Stmxcsr(Operand dest)
+ {
+ WriteInstruction(dest, null, OperandType.I32, X86Instruction.Stmxcsr);
+ }
+
public void Sub(Operand dest, Operand source, OperandType type)
{
WriteInstruction(dest, source, type, X86Instruction.Sub);
diff --git a/ARMeilleure/CodeGen/X86/CodeGenerator.cs b/ARMeilleure/CodeGen/X86/CodeGenerator.cs
index 83ff136a..29a4cd78 100644
--- a/ARMeilleure/CodeGen/X86/CodeGenerator.cs
+++ b/ARMeilleure/CodeGen/X86/CodeGenerator.cs
@@ -250,6 +250,40 @@ namespace ARMeilleure.CodeGen.X86
break;
}
+ case IntrinsicType.Mxcsr:
+ {
+ Operand offset = operation.GetSource(0);
+ Operand bits = operation.GetSource(1);
+
+ Debug.Assert(offset.Kind == OperandKind.Constant && bits.Kind == OperandKind.Constant);
+ Debug.Assert(offset.Type == OperandType.I32 && bits.Type == OperandType.I32);
+
+ int offs = offset.AsInt32() + context.CallArgsRegionSize;
+
+ Operand rsp = Register(X86Register.Rsp);
+
+ MemoryOperand memOp = MemoryOp(OperandType.I32, rsp, null, Multiplier.x1, offs);
+
+ Debug.Assert(HardwareCapabilities.SupportsSse || HardwareCapabilities.SupportsVexEncoding);
+
+ context.Assembler.Stmxcsr(memOp);
+
+ if (intrinOp.Intrinsic == Intrinsic.X86Mxcsrmb)
+ {
+ context.Assembler.Or(memOp, bits, OperandType.I32);
+ }
+ else /* if (intrinOp.Intrinsic == Intrinsic.X86Mxcsrub) */
+ {
+ Operand notBits = Const(~bits.AsInt32());
+
+ context.Assembler.And(memOp, notBits, OperandType.I32);
+ }
+
+ context.Assembler.Ldmxcsr(memOp);
+
+ break;
+ }
+
case IntrinsicType.PopCount:
{
Operand dest = operation.Destination;
diff --git a/ARMeilleure/CodeGen/X86/IntrinsicTable.cs b/ARMeilleure/CodeGen/X86/IntrinsicTable.cs
index 310fdc51..cc0c797b 100644
--- a/ARMeilleure/CodeGen/X86/IntrinsicTable.cs
+++ b/ARMeilleure/CodeGen/X86/IntrinsicTable.cs
@@ -76,6 +76,8 @@ namespace ARMeilleure.CodeGen.X86
Add(Intrinsic.X86Mulps, new IntrinsicInfo(X86Instruction.Mulps, IntrinsicType.Binary));
Add(Intrinsic.X86Mulsd, new IntrinsicInfo(X86Instruction.Mulsd, IntrinsicType.Binary));
Add(Intrinsic.X86Mulss, new IntrinsicInfo(X86Instruction.Mulss, IntrinsicType.Binary));
+ Add(Intrinsic.X86Mxcsrmb, new IntrinsicInfo(X86Instruction.None, IntrinsicType.Mxcsr)); // Mask bits.
+ Add(Intrinsic.X86Mxcsrub, new IntrinsicInfo(X86Instruction.None, IntrinsicType.Mxcsr)); // Unmask bits.
Add(Intrinsic.X86Paddb, new IntrinsicInfo(X86Instruction.Paddb, IntrinsicType.Binary));
Add(Intrinsic.X86Paddd, new IntrinsicInfo(X86Instruction.Paddd, IntrinsicType.Binary));
Add(Intrinsic.X86Paddq, new IntrinsicInfo(X86Instruction.Paddq, IntrinsicType.Binary));
diff --git a/ARMeilleure/CodeGen/X86/IntrinsicType.cs b/ARMeilleure/CodeGen/X86/IntrinsicType.cs
index 8248b048..5a9c14af 100644
--- a/ARMeilleure/CodeGen/X86/IntrinsicType.cs
+++ b/ARMeilleure/CodeGen/X86/IntrinsicType.cs
@@ -3,6 +3,7 @@ namespace ARMeilleure.CodeGen.X86
enum IntrinsicType
{
Comis_,
+ Mxcsr,
PopCount,
Unary,
UnaryToGpr,
diff --git a/ARMeilleure/CodeGen/X86/PreAllocator.cs b/ARMeilleure/CodeGen/X86/PreAllocator.cs
index 3aaf315a..4969fa43 100644
--- a/ARMeilleure/CodeGen/X86/PreAllocator.cs
+++ b/ARMeilleure/CodeGen/X86/PreAllocator.cs
@@ -114,6 +114,16 @@ namespace ARMeilleure.CodeGen.X86
node = HandleVectorInsert8(block.Operations, node, operation);
}
break;
+
+ case Instruction.Extended:
+ IntrinsicOperation intrinOp = (IntrinsicOperation)operation;
+
+ if (intrinOp.Intrinsic == Intrinsic.X86Mxcsrmb || intrinOp.Intrinsic == Intrinsic.X86Mxcsrub)
+ {
+ int stackOffset = stackAlloc.Allocate(OperandType.I32);
+ operation.SetSources(new Operand[] { Const(stackOffset), operation.GetSource(0) });
+ }
+ break;
}
}
}
diff --git a/ARMeilleure/CodeGen/X86/X86Instruction.cs b/ARMeilleure/CodeGen/X86/X86Instruction.cs
index 1c4bbed4..166567ae 100644
--- a/ARMeilleure/CodeGen/X86/X86Instruction.cs
+++ b/ARMeilleure/CodeGen/X86/X86Instruction.cs
@@ -2,6 +2,7 @@ namespace ARMeilleure.CodeGen.X86
{
enum X86Instruction
{
+ None,
Add,
Addpd,
Addps,
@@ -60,6 +61,7 @@ namespace ARMeilleure.CodeGen.X86
Imul128,
Insertps,
Jmp,
+ Ldmxcsr,
Lea,
Maxpd,
Maxps,
@@ -186,6 +188,7 @@ namespace ARMeilleure.CodeGen.X86
Sqrtps,
Sqrtsd,
Sqrtss,
+ Stmxcsr,
Sub,
Subpd,
Subps,
diff --git a/ARMeilleure/Instructions/InstEmitSimdArithmetic.cs b/ARMeilleure/Instructions/InstEmitSimdArithmetic.cs
index 0d417f70..3a97bc52 100644
--- a/ARMeilleure/Instructions/InstEmitSimdArithmetic.cs
+++ b/ARMeilleure/Instructions/InstEmitSimdArithmetic.cs
@@ -380,15 +380,21 @@ namespace ARMeilleure.Instructions
public static void Faddp_V(ArmEmitterContext context)
{
- if (Optimizations.FastFP && Optimizations.UseSse2)
+ if (Optimizations.FastFP && Optimizations.UseSse41)
{
EmitSse2VectorPairwiseOpF(context, (op1, op2) =>
{
- IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
+ return EmitSse41ProcessNaNsOpF(context, (op1, op2) =>
+ {
+ return EmitSseOrAvxHandleFzModeOpF(context, (op1, op2) =>
+ {
+ IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
- Intrinsic addInst = (op.Size & 1) == 0 ? Intrinsic.X86Addps : Intrinsic.X86Addpd;
+ Intrinsic addInst = (op.Size & 1) == 0 ? Intrinsic.X86Addps : Intrinsic.X86Addpd;
- return context.AddIntrinsic(addInst, op1, op2);
+ return context.AddIntrinsic(addInst, op1, op2);
+ }, scalar: false, op1, op2);
+ }, scalar: false, op1, op2);
});
}
else
@@ -479,7 +485,10 @@ namespace ARMeilleure.Instructions
{
EmitSse41ProcessNaNsOpF(context, (op1, op2) =>
{
- return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: true);
+ return EmitSseOrAvxHandleFzModeOpF(context, (op1, op2) =>
+ {
+ return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: true);
+ }, scalar: true, op1, op2);
}, scalar: true);
}
else
@@ -497,7 +506,10 @@ namespace ARMeilleure.Instructions
{
EmitSse41ProcessNaNsOpF(context, (op1, op2) =>
{
- return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: true);
+ return EmitSseOrAvxHandleFzModeOpF(context, (op1, op2) =>
+ {
+ return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: true);
+ }, scalar: false, op1, op2);
}, scalar: false);
}
else
@@ -583,7 +595,10 @@ namespace ARMeilleure.Instructions
{
return EmitSse41ProcessNaNsOpF(context, (op1, op2) =>
{
- return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: true);
+ return EmitSseOrAvxHandleFzModeOpF(context, (op1, op2) =>
+ {
+ return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: true);
+ }, scalar: false, op1, op2);
}, scalar: false, op1, op2);
});
}
@@ -604,7 +619,10 @@ namespace ARMeilleure.Instructions
{
return EmitSse41ProcessNaNsOpF(context, (op1, op2) =>
{
- return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: true);
+ return EmitSseOrAvxHandleFzModeOpF(context, (op1, op2) =>
+ {
+ return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: true);
+ }, scalar: false, op1, op2);
}, scalar: false, op1, op2);
});
}
@@ -623,7 +641,10 @@ namespace ARMeilleure.Instructions
{
EmitSse41ProcessNaNsOpF(context, (op1, op2) =>
{
- return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: false);
+ return EmitSseOrAvxHandleFzModeOpF(context, (op1, op2) =>
+ {
+ return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: false);
+ }, scalar: true, op1, op2);
}, scalar: true);
}
else
@@ -641,7 +662,10 @@ namespace ARMeilleure.Instructions
{
EmitSse41ProcessNaNsOpF(context, (op1, op2) =>
{
- return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: false);
+ return EmitSseOrAvxHandleFzModeOpF(context, (op1, op2) =>
+ {
+ return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: false);
+ }, scalar: false, op1, op2);
}, scalar: false);
}
else
@@ -727,7 +751,10 @@ namespace ARMeilleure.Instructions
{
return EmitSse41ProcessNaNsOpF(context, (op1, op2) =>
{
- return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: false);
+ return EmitSseOrAvxHandleFzModeOpF(context, (op1, op2) =>
+ {
+ return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: false);
+ }, scalar: false, op1, op2);
}, scalar: false, op1, op2);
});
}
@@ -748,7 +775,10 @@ namespace ARMeilleure.Instructions
{
return EmitSse41ProcessNaNsOpF(context, (op1, op2) =>
{
- return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: false);
+ return EmitSseOrAvxHandleFzModeOpF(context, (op1, op2) =>
+ {
+ return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: false);
+ }, scalar: false, op1, op2);
}, scalar: false, op1, op2);
});
}
@@ -3360,6 +3390,53 @@ namespace ARMeilleure.Instructions
}
}
+ public static Operand EmitSseOrAvxHandleFzModeOpF(
+ ArmEmitterContext context,
+ Func2I emit,
+ bool scalar,
+ Operand n = null,
+ Operand m = null)
+ {
+ Operand nCopy = n ?? context.Copy(GetVec(((OpCodeSimdReg)context.CurrOp).Rn));
+ Operand mCopy = m ?? context.Copy(GetVec(((OpCodeSimdReg)context.CurrOp).Rm));
+
+ EmitSseOrAvxEnterFtzAndDazModesOpF(context, out Operand isTrue);
+
+ Operand res = emit(nCopy, mCopy);
+
+ EmitSseOrAvxExitFtzAndDazModesOpF(context, isTrue);
+
+ if (n != null || m != null)
+ {
+ return res;
+ }
+
+ int sizeF = ((IOpCodeSimd)context.CurrOp).Size & 1;
+
+ if (sizeF == 0)
+ {
+ if (scalar)
+ {
+ res = context.VectorZeroUpper96(res);
+ }
+ else if (((OpCodeSimdReg)context.CurrOp).RegisterSize == RegisterSize.Simd64)
+ {
+ res = context.VectorZeroUpper64(res);
+ }
+ }
+ else /* if (sizeF == 1) */
+ {
+ if (scalar)
+ {
+ res = context.VectorZeroUpper64(res);
+ }
+ }
+
+ context.Copy(GetVec(((OpCodeSimdReg)context.CurrOp).Rd), res);
+
+ return null;
+ }
+
private static Operand EmitSse2VectorMaxMinOpF(ArmEmitterContext context, Operand n, Operand m, bool isMax)
{
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
@@ -3419,7 +3496,10 @@ namespace ARMeilleure.Instructions
Operand res = EmitSse41ProcessNaNsOpF(context, (op1, op2) =>
{
- return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: isMaxNum);
+ return EmitSseOrAvxHandleFzModeOpF(context, (op1, op2) =>
+ {
+ return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: isMaxNum);
+ }, scalar: scalar, op1, op2);
}, scalar: scalar, nCopy, mCopy);
if (n != null || m != null)
@@ -3454,7 +3534,10 @@ namespace ARMeilleure.Instructions
Operand res = EmitSse41ProcessNaNsOpF(context, (op1, op2) =>
{
- return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: isMaxNum);
+ return EmitSseOrAvxHandleFzModeOpF(context, (op1, op2) =>
+ {
+ return EmitSse2VectorMaxMinOpF(context, op1, op2, isMax: isMaxNum);
+ }, scalar: scalar, op1, op2);
}, scalar: scalar, nCopy, mCopy);
if (n != null || m != null)
diff --git a/ARMeilleure/Instructions/InstEmitSimdHelper.cs b/ARMeilleure/Instructions/InstEmitSimdHelper.cs
index 69e79a6d..eab891ec 100644
--- a/ARMeilleure/Instructions/InstEmitSimdHelper.cs
+++ b/ARMeilleure/Instructions/InstEmitSimdHelper.cs
@@ -1189,6 +1189,39 @@ namespace ARMeilleure.Instructions
}
}
+ [Flags]
+ public enum Mxcsr
+ {
+ Ftz = 1 << 15, // Flush To Zero.
+ Um = 1 << 11, // Underflow Mask.
+ Dm = 1 << 8, // Denormal Mask.
+ Daz = 1 << 6 // Denormals Are Zero.
+ }
+
+ public static void EmitSseOrAvxEnterFtzAndDazModesOpF(ArmEmitterContext context, out Operand isTrue)
+ {
+ isTrue = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpcrFz)));
+
+ Operand lblTrue = Label();
+ context.BranchIfFalse(lblTrue, isTrue);
+
+ context.AddIntrinsicNoRet(Intrinsic.X86Mxcsrmb, Const((int)(Mxcsr.Ftz | Mxcsr.Um | Mxcsr.Dm | Mxcsr.Daz)));
+
+ context.MarkLabel(lblTrue);
+ }
+
+ public static void EmitSseOrAvxExitFtzAndDazModesOpF(ArmEmitterContext context, Operand isTrue = null)
+ {
+ isTrue ??= context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpcrFz)));
+
+ Operand lblTrue = Label();
+ context.BranchIfFalse(lblTrue, isTrue);
+
+ context.AddIntrinsicNoRet(Intrinsic.X86Mxcsrub, Const((int)(Mxcsr.Ftz | Mxcsr.Daz)));
+
+ context.MarkLabel(lblTrue);
+ }
+
public enum CmpCondition
{
// Legacy Sse.
diff --git a/ARMeilleure/Instructions/NativeInterface.cs b/ARMeilleure/Instructions/NativeInterface.cs
index 8fb98df8..bc1be21d 100644
--- a/ARMeilleure/Instructions/NativeInterface.cs
+++ b/ARMeilleure/Instructions/NativeInterface.cs
@@ -78,6 +78,11 @@ namespace ARMeilleure.Instructions
return (ulong)GetContext().Fpcr;
}
+ public static bool GetFpcrFz()
+ {
+ return (GetContext().Fpcr & FPCR.Fz) != 0;
+ }
+
public static ulong GetFpsr()
{
return (ulong)GetContext().Fpsr;
@@ -85,7 +90,7 @@ namespace ARMeilleure.Instructions
public static uint GetFpscr()
{
- var context = GetContext();
+ ExecutionContext context = GetContext();
return (uint)(context.Fpsr & FPSR.A32Mask & ~FPSR.Nzcv) |
(uint)(context.Fpcr & FPCR.A32Mask);
@@ -143,7 +148,7 @@ namespace ARMeilleure.Instructions
public static void SetFpscr(uint fpscr)
{
- var context = GetContext();
+ ExecutionContext context = GetContext();
context.Fpsr = FPSR.A32Mask & (FPSR)fpscr;
context.Fpcr = FPCR.A32Mask & (FPCR)fpscr;
@@ -250,7 +255,7 @@ namespace ARMeilleure.Instructions
{
Statistics.PauseTimer();
- var context = GetContext();
+ ExecutionContext context = GetContext();
context.CheckInterrupt();
diff --git a/ARMeilleure/IntermediateRepresentation/Intrinsic.cs b/ARMeilleure/IntermediateRepresentation/Intrinsic.cs
index 7d8b8bf0..728bb018 100644
--- a/ARMeilleure/IntermediateRepresentation/Intrinsic.cs
+++ b/ARMeilleure/IntermediateRepresentation/Intrinsic.cs
@@ -65,6 +65,8 @@ namespace ARMeilleure.IntermediateRepresentation
X86Mulps,
X86Mulsd,
X86Mulss,
+ X86Mxcsrmb,
+ X86Mxcsrub,
X86Paddb,
X86Paddd,
X86Paddq,
diff --git a/ARMeilleure/Translation/Delegates.cs b/ARMeilleure/Translation/Delegates.cs
index c64dc8f0..20289d62 100644
--- a/ARMeilleure/Translation/Delegates.cs
+++ b/ARMeilleure/Translation/Delegates.cs
@@ -109,6 +109,7 @@ namespace ARMeilleure.Translation
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCtrEl0)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetDczidEl0)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpcr)));
+ SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpcrFz)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpscr))); // A32 only.
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpsr)));
SetDelegateInfo(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress)));
diff --git a/ARMeilleure/Translation/EmitterContext.cs b/ARMeilleure/Translation/EmitterContext.cs
index d85a502b..f41f3464 100644
--- a/ARMeilleure/Translation/EmitterContext.cs
+++ b/ARMeilleure/Translation/EmitterContext.cs
@@ -573,6 +573,11 @@ namespace ARMeilleure.Translation
return Add(intrin, Local(OperandType.I64), args);
}
+ public void AddIntrinsicNoRet(Intrinsic intrin, params Operand[] args)
+ {
+ Add(intrin, null, args);
+ }
+
private Operand Add(Intrinsic intrin, Operand dest, params Operand[] sources)
{
NewNextBlockIfNeeded();
diff --git a/ARMeilleure/Translation/PTC/Ptc.cs b/ARMeilleure/Translation/PTC/Ptc.cs
index 82104c03..8ba08393 100644
--- a/ARMeilleure/Translation/PTC/Ptc.cs
+++ b/ARMeilleure/Translation/PTC/Ptc.cs
@@ -21,7 +21,7 @@ namespace ARMeilleure.Translation.PTC
{
private const string HeaderMagic = "PTChd";
- private const int InternalVersion = 1758; //! To be incremented manually for each change to the ARMeilleure project.
+ private const int InternalVersion = 1631; //! To be incremented manually for each change to the ARMeilleure project.
private const string ActualDir = "0";
private const string BackupDir = "1";