Add Profiled Persistent Translation Cache. (#769)
* Delete DelegateTypes.cs * Delete DelegateCache.cs * Add files via upload * Update Horizon.cs * Update Program.cs * Update MainWindow.cs * Update Aot.cs * Update RelocEntry.cs * Update Translator.cs * Update MemoryManager.cs * Update InstEmitMemoryHelper.cs * Update Delegates.cs * Nit. * Nit. * Nit. * 10 fewer MSIL bytes for us * Add comment. Nits. * Update Translator.cs * Update Aot.cs * Nits. * Opt.. * Opt.. * Opt.. * Opt.. * Allow to change compression level. * Update MemoryManager.cs * Update Translator.cs * Manage corner cases during the save phase. Nits. * Update Aot.cs * Translator response tweak for Aot disabled. Nit. * Nit. * Nits. * Create DelegateHelpers.cs * Update Delegates.cs * Nit. * Nit. * Nits. * Fix due to #784. * Fixes due to #757 & #841. * Fix due to #846. * Fix due to #847. * Use MethodInfo for managed method calls. Use IR methods instead of managed methods about Max/Min (S/U). Follow-ups & Nits. * Add missing exception messages. Reintroduce slow path for Fmov_Vi. Implement slow path for Fmov_Si. * Switch to the new folder structure. Nits. * Impl. index-based relocation information. Impl. cache file version field. * Nit. * Address gdkchan comments. Mainly: - fixed cache file corruption issue on exit; - exposed a way to disable AOT on the GUI. * Address AcK77 comment. * Address Thealexbarney, jduncanator & emmauss comments. Header magic, CpuId (FI) & Aot -> Ptc. * Adaptation to the new application reloading system. Improvements to the call system of managed methods. Follow-ups. Nits. * Get the same boot times as on master when PTC is disabled. * Profiled Aot. * A32 support (#897). * #975 support (1 of 2). * #975 support (2 of 2). * Rebase fix & nits. * Some fixes and nits (still one bug left). * One fix & nits. * Tests fix (by gdk) & nits. * Support translations not only in high quality and rejit. Nits. * Added possibility to skip translations and continue execution, using `ESC` key. * Update SettingsWindow.cs * Update GLRenderer.cs * Update Ptc.cs * Disabled Profiled PTC by default as requested in the past by gdk. * Fix rejit bug. Increased number of parallel translations. Add stack unwinding stuffs support (1 of 2). Nits. * Add stack unwinding stuffs support (2 of 2). Tuned number of parallel translations. * Restored the ability to assemble jumps with 8-bit offset when Profiled PTC is disabled or during profiling. Modifications due to rebase. Nits. * Limited profiling of the functions to be translated to the addresses belonging to the range of static objects only. * Nits. * Nits. * Update Delegates.cs * Nit. * Update InstEmitSimdArithmetic.cs * Address riperiperi comments. * Fixed the issue of unjustifiably longer boot times at the second boot than at the first boot, measured at the same time or reference point and with the same number of translated functions. * Implemented a simple redundant load/save mechanism. Halved the value of Decoder.MaxInstsPerFunction more appropriate for the current performance of the Translator. Replaced by Logger.PrintError to Logger.PrintDebug in TexturePool.cs about the supposed invalid texture format to avoid the spawn of the log. Nits. * Nit. Improved Logger.PrintError in TexturePool.cs to avoid log spawn. Added missing code for FZ handling (in output) for fp max/min instructions (slow paths). * Add configuration migration for PTC Co-authored-by: Thog <me@thog.eu>
This commit is contained in:
parent
fa286d3535
commit
5e724cf24e
78 changed files with 3066 additions and 1207 deletions
|
@ -1,94 +0,0 @@
|
|||
using ARMeilleure.State;
|
||||
using System;
|
||||
|
||||
namespace ARMeilleure.Instructions
|
||||
{
|
||||
delegate bool _Bool();
|
||||
|
||||
delegate double _F64_F64(double a1);
|
||||
delegate double _F64_F64_Bool(double a1, bool a2);
|
||||
delegate double _F64_F64_F64(double a1, double a2);
|
||||
delegate double _F64_F64_F64_Bool(double a1, double a2, bool a3);
|
||||
delegate double _F64_F64_F64_F64(double a1, double a2, double a3);
|
||||
delegate double _F64_F64_F64_F64_Bool(double a1, double a2, double a3, bool a4);
|
||||
delegate double _F64_F64_MidpointRounding(double a1, MidpointRounding a2);
|
||||
|
||||
delegate float _F32_F32(float a1);
|
||||
delegate float _F32_F32_Bool(float a1, bool a2);
|
||||
delegate float _F32_F32_F32(float a1, float a2);
|
||||
delegate float _F32_F32_F32_Bool(float a1, float a2, bool a3);
|
||||
delegate float _F32_F32_F32_F32(float a1, float a2, float a3);
|
||||
delegate float _F32_F32_F32_F32_Bool(float a1, float a2, float a3, bool a4);
|
||||
delegate float _F32_F32_MidpointRounding(float a1, MidpointRounding a2);
|
||||
delegate float _F32_U16(ushort a1);
|
||||
|
||||
delegate int _S32_F32(float a1);
|
||||
delegate int _S32_F32_F32_Bool(float a1, float a2, bool a3);
|
||||
delegate int _S32_F64(double a1);
|
||||
delegate int _S32_F64_F64_Bool(double a1, double a2, bool a3);
|
||||
delegate int _S32_U64_U16(ulong a1, ushort a2);
|
||||
delegate int _S32_U64_U32(ulong a1, uint a2);
|
||||
delegate int _S32_U64_U64(ulong a1, ulong a2);
|
||||
delegate int _S32_U64_U8(ulong a1, byte a2);
|
||||
delegate int _S32_U64_V128(ulong a1, V128 a2);
|
||||
|
||||
delegate long _S64_F32(float a1);
|
||||
delegate long _S64_F64(double a1);
|
||||
delegate long _S64_S64(long a1);
|
||||
delegate long _S64_S64_S32(long a1, int a2);
|
||||
delegate long _S64_S64_S64(long a1, long a2);
|
||||
delegate long _S64_S64_S64_Bool_S32(long a1, long a2, bool a3, int a4);
|
||||
delegate long _S64_S64_S64_S32(long a1, long a2, int a3);
|
||||
delegate long _S64_U64_S32(ulong a1, int a2);
|
||||
delegate long _S64_U64_S64(ulong a1, long a2);
|
||||
|
||||
delegate ushort _U16_F32(float a1);
|
||||
delegate ushort _U16_U64(ulong a1);
|
||||
|
||||
delegate uint _U32();
|
||||
delegate uint _U32_F32(float a1);
|
||||
delegate uint _U32_F64(double a1);
|
||||
delegate uint _U32_U32(uint a1);
|
||||
delegate uint _U32_U32_U16(uint a1, ushort a2);
|
||||
delegate uint _U32_U32_U32(uint a1, uint a2);
|
||||
delegate uint _U32_U32_U64(uint a1, ulong a2);
|
||||
delegate uint _U32_U32_U8(uint a1, byte a2);
|
||||
delegate uint _U32_U64(ulong a1);
|
||||
|
||||
delegate ulong _U64();
|
||||
delegate ulong _U64_F32(float a1);
|
||||
delegate ulong _U64_F64(double a1);
|
||||
delegate ulong _U64_S64_S32(long a1, int a2);
|
||||
delegate ulong _U64_S64_U64(long a1, ulong a2);
|
||||
delegate ulong _U64_U64(ulong a1);
|
||||
delegate ulong _U64_U64_S32(ulong a1, int a2);
|
||||
delegate ulong _U64_U64_S64_S32(ulong a1, long a2, int a3);
|
||||
delegate ulong _U64_U64_U64(ulong a1, ulong a2);
|
||||
delegate ulong _U64_U64_U64_Bool_S32(ulong a1, ulong a2, bool a3, int a4);
|
||||
|
||||
delegate byte _U8_U64(ulong a1);
|
||||
|
||||
delegate V128 _V128_U64(ulong a1);
|
||||
delegate V128 _V128_V128(V128 a1);
|
||||
delegate V128 _V128_V128_S32_V128(V128 a1, int a2, V128 a3);
|
||||
delegate V128 _V128_V128_S32_V128_V128(V128 a1, int a2, V128 a3, V128 a4);
|
||||
delegate V128 _V128_V128_S32_V128_V128_V128(V128 a1, int a2, V128 a3, V128 a4, V128 a5);
|
||||
delegate V128 _V128_V128_S32_V128_V128_V128_V128(V128 a1, int a2, V128 a3, V128 a4, V128 a5, V128 a6);
|
||||
delegate V128 _V128_V128_U32_V128(V128 a1, uint a2, V128 a3);
|
||||
delegate V128 _V128_V128_V128(V128 a1, V128 a2);
|
||||
delegate V128 _V128_V128_V128_S32_V128(V128 a1, V128 a2, int a3, V128 a4);
|
||||
delegate V128 _V128_V128_V128_S32_V128_V128(V128 a1, V128 a2, int a3, V128 a4, V128 a5);
|
||||
delegate V128 _V128_V128_V128_S32_V128_V128_V128(V128 a1, V128 a2, int a3, V128 a4, V128 a5, V128 a6);
|
||||
delegate V128 _V128_V128_V128_S32_V128_V128_V128_V128(V128 a1, V128 a2, int a3, V128 a4, V128 a5, V128 a6, V128 a7);
|
||||
delegate V128 _V128_V128_V128_V128(V128 a1, V128 a2, V128 a3);
|
||||
|
||||
delegate void _Void();
|
||||
delegate void _Void_U32(uint a1);
|
||||
delegate void _Void_U64(ulong a1);
|
||||
delegate void _Void_U64_S32(ulong a1, int a2);
|
||||
delegate void _Void_U64_U16(ulong a1, ushort a2);
|
||||
delegate void _Void_U64_U32(ulong a1, uint a2);
|
||||
delegate void _Void_U64_U64(ulong a1, ulong a2);
|
||||
delegate void _Void_U64_U8(ulong a1, byte a2);
|
||||
delegate void _Void_U64_V128(ulong a1, V128 a2);
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
using ARMeilleure.Decoders;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitFlowHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
|
||||
|
@ -11,21 +10,21 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
public static void Brk(ArmEmitterContext context)
|
||||
{
|
||||
EmitExceptionCall(context, NativeInterface.Break);
|
||||
EmitExceptionCall(context, nameof(NativeInterface.Break));
|
||||
}
|
||||
|
||||
public static void Svc(ArmEmitterContext context)
|
||||
{
|
||||
EmitExceptionCall(context, NativeInterface.SupervisorCall);
|
||||
EmitExceptionCall(context, nameof(NativeInterface.SupervisorCall));
|
||||
}
|
||||
|
||||
private static void EmitExceptionCall(ArmEmitterContext context, _Void_U64_S32 func)
|
||||
private static void EmitExceptionCall(ArmEmitterContext context, string name)
|
||||
{
|
||||
OpCodeException op = (OpCodeException)context.CurrOp;
|
||||
|
||||
context.StoreToContext();
|
||||
|
||||
context.Call(func, Const(op.Address), Const(op.Id));
|
||||
context.Call(typeof(NativeInterface).GetMethod(name), Const(op.Address), Const(op.Id));
|
||||
|
||||
context.LoadFromContext();
|
||||
|
||||
|
@ -39,11 +38,11 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCode op = context.CurrOp;
|
||||
|
||||
Delegate dlg = new _Void_U64_S32(NativeInterface.Undefined);
|
||||
string name = nameof(NativeInterface.Undefined);
|
||||
|
||||
context.StoreToContext();
|
||||
|
||||
context.Call(dlg, Const(op.Address), Const(op.RawOpCode));
|
||||
context.Call(typeof(NativeInterface).GetMethod(name), Const(op.Address), Const(op.RawOpCode));
|
||||
|
||||
context.LoadFromContext();
|
||||
|
||||
|
|
|
@ -10,21 +10,21 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
public static void Svc(ArmEmitterContext context)
|
||||
{
|
||||
EmitExceptionCall(context, NativeInterface.SupervisorCall);
|
||||
EmitExceptionCall(context, nameof(NativeInterface.SupervisorCall));
|
||||
}
|
||||
|
||||
public static void Trap(ArmEmitterContext context)
|
||||
{
|
||||
EmitExceptionCall(context, NativeInterface.Break);
|
||||
EmitExceptionCall(context, nameof(NativeInterface.Break));
|
||||
}
|
||||
|
||||
private static void EmitExceptionCall(ArmEmitterContext context, _Void_U64_S32 func)
|
||||
private static void EmitExceptionCall(ArmEmitterContext context, string name)
|
||||
{
|
||||
OpCode32Exception op = (OpCode32Exception)context.CurrOp;
|
||||
|
||||
context.StoreToContext();
|
||||
|
||||
context.Call(func, Const(op.Address), Const(op.Id));
|
||||
context.Call(typeof(NativeInterface).GetMethod(name), Const(op.Address), Const(op.Id));
|
||||
|
||||
context.LoadFromContext();
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ using ARMeilleure.Decoders;
|
|||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
using ARMeilleure.Translation.PTC;
|
||||
using System;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
|
@ -223,6 +224,7 @@ namespace ARMeilleure.Instructions
|
|||
public static void EmitTailContinue(ArmEmitterContext context, Operand address, bool allowRejit = false)
|
||||
{
|
||||
bool useTailContinue = true; // Left option here as it may be useful if we need to return to managed rather than tail call in future. (eg. for debug)
|
||||
|
||||
if (useTailContinue)
|
||||
{
|
||||
if (context.HighCq)
|
||||
|
@ -230,7 +232,7 @@ namespace ARMeilleure.Instructions
|
|||
// If we're doing a tail continue in HighCq, reserve a space in the jump table to avoid calling back to the translator.
|
||||
// This will always try to get a HighCq version of our continue target as well.
|
||||
EmitJumpTableBranch(context, address, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (allowRejit)
|
||||
|
@ -238,11 +240,11 @@ namespace ARMeilleure.Instructions
|
|||
address = context.BitwiseOr(address, Const(CallFlag));
|
||||
}
|
||||
|
||||
Operand fallbackAddr = context.Call(new _U64_U64(NativeInterface.GetFunctionAddress), address);
|
||||
Operand fallbackAddr = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress)), address);
|
||||
|
||||
EmitNativeCall(context, fallbackAddr, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Return(address);
|
||||
|
@ -260,7 +262,7 @@ namespace ARMeilleure.Instructions
|
|||
private static void EmitBranchFallback(ArmEmitterContext context, Operand address, bool isJump)
|
||||
{
|
||||
address = context.BitwiseOr(address, Const(address.Type, (long)CallFlag)); // Set call flag.
|
||||
Operand fallbackAddr = context.Call(new _U64_U64(NativeInterface.GetFunctionAddress), address);
|
||||
Operand fallbackAddr = context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFunctionAddress)), address);
|
||||
EmitNativeCall(context, fallbackAddr, isJump);
|
||||
}
|
||||
|
||||
|
@ -290,12 +292,12 @@ namespace ARMeilleure.Instructions
|
|||
};
|
||||
|
||||
// Currently this uses a size of 1, as higher values inflate code size for no real benefit.
|
||||
for (int i = 0; i < JumpTable.DynamicTableElems; i++)
|
||||
for (int i = 0; i < JumpTable.DynamicTableElems; i++)
|
||||
{
|
||||
if (i == JumpTable.DynamicTableElems - 1)
|
||||
{
|
||||
emitTableEntry(fallbackLabel); // If this is the last entry, avoid emitting the additional label and add.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Operand nextLabel = Label();
|
||||
|
@ -339,7 +341,18 @@ namespace ARMeilleure.Instructions
|
|||
int entry = context.JumpTable.ReserveDynamicEntry(isJump);
|
||||
|
||||
int jumpOffset = entry * JumpTable.JumpTableStride * JumpTable.DynamicTableElems;
|
||||
Operand dynTablePtr = Const(context.JumpTable.DynamicPointer.ToInt64() + jumpOffset);
|
||||
|
||||
Operand dynTablePtr;
|
||||
|
||||
if (Ptc.State == PtcState.Disabled)
|
||||
{
|
||||
dynTablePtr = Const(context.JumpTable.DynamicPointer.ToInt64() + jumpOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
dynTablePtr = Const(context.JumpTable.DynamicPointer.ToInt64(), true, Ptc.DynamicPointerIndex);
|
||||
dynTablePtr = context.Add(dynTablePtr, Const((long)jumpOffset));
|
||||
}
|
||||
|
||||
EmitDynamicTableCall(context, dynTablePtr, address, isJump);
|
||||
}
|
||||
|
@ -349,8 +362,17 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
int jumpOffset = entry * JumpTable.JumpTableStride + 8; // Offset directly to the host address.
|
||||
|
||||
// TODO: Relocatable jump table ptr for AOT. Would prefer a solution to patch this constant into functions as they are loaded rather than calculate at runtime.
|
||||
Operand tableEntryPtr = Const(context.JumpTable.JumpPointer.ToInt64() + jumpOffset);
|
||||
Operand tableEntryPtr;
|
||||
|
||||
if (Ptc.State == PtcState.Disabled)
|
||||
{
|
||||
tableEntryPtr = Const(context.JumpTable.JumpPointer.ToInt64() + jumpOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
tableEntryPtr = Const(context.JumpTable.JumpPointer.ToInt64(), true, Ptc.JumpPointerIndex);
|
||||
tableEntryPtr = context.Add(tableEntryPtr, Const((long)jumpOffset));
|
||||
}
|
||||
|
||||
Operand funcAddr = context.Load(OperandType.I64, tableEntryPtr);
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
using ARMeilleure.Decoders;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
|
@ -21,7 +20,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitCrc32Call(context, new _U32_U32_U8(SoftFallback.Crc32b));
|
||||
EmitCrc32Call(context, nameof(SoftFallback.Crc32b));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -33,7 +32,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitCrc32Call(context, new _U32_U32_U16(SoftFallback.Crc32h));
|
||||
EmitCrc32Call(context, nameof(SoftFallback.Crc32h));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,7 +44,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitCrc32Call(context, new _U32_U32_U32(SoftFallback.Crc32w));
|
||||
EmitCrc32Call(context, nameof(SoftFallback.Crc32w));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,7 +56,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitCrc32Call(context, new _U32_U32_U64(SoftFallback.Crc32x));
|
||||
EmitCrc32Call(context, nameof(SoftFallback.Crc32x));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,7 +68,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitCrc32Call(context, new _U32_U32_U8(SoftFallback.Crc32cb));
|
||||
EmitCrc32Call(context, nameof(SoftFallback.Crc32cb));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,7 +80,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitCrc32Call(context, new _U32_U32_U16(SoftFallback.Crc32ch));
|
||||
EmitCrc32Call(context, nameof(SoftFallback.Crc32ch));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -93,7 +92,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitCrc32Call(context, new _U32_U32_U32(SoftFallback.Crc32cw));
|
||||
EmitCrc32Call(context, nameof(SoftFallback.Crc32cw));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,7 +104,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitCrc32Call(context, new _U32_U32_U64(SoftFallback.Crc32cx));
|
||||
EmitCrc32Call(context, nameof(SoftFallback.Crc32cx));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -170,14 +169,14 @@ namespace ARMeilleure.Instructions
|
|||
SetIntOrZR(context, op.Rd, context.VectorExtract(OperandType.I32, tmp, 2));
|
||||
}
|
||||
|
||||
private static void EmitCrc32Call(ArmEmitterContext context, Delegate dlg)
|
||||
private static void EmitCrc32Call(ArmEmitterContext context, string name)
|
||||
{
|
||||
OpCodeAluBinary op = (OpCodeAluBinary)context.CurrOp;
|
||||
|
||||
Operand n = GetIntOrZR(context, op.Rn);
|
||||
Operand m = GetIntOrZR(context, op.Rm);
|
||||
|
||||
Operand d = context.Call(dlg, n, m);
|
||||
Operand d = context.Call(typeof(SoftFallback).GetMethod(name), n, m);
|
||||
|
||||
SetIntOrZR(context, op.Rd, d);
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static void Clrex(ArmEmitterContext context)
|
||||
{
|
||||
context.Call(new _Void(NativeInterface.ClearExclusive));
|
||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ClearExclusive)));
|
||||
}
|
||||
|
||||
public static void Dmb(ArmEmitterContext context) => EmitBarrier(context);
|
||||
|
@ -101,6 +101,7 @@ namespace ARMeilleure.Instructions
|
|||
SetIntOrZR(context, op.Rt, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Pfrm(ArmEmitterContext context)
|
||||
{
|
||||
// Memory Prefetch, execute as no-op.
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
public static void Clrex(ArmEmitterContext context)
|
||||
{
|
||||
context.Call(new _Void(NativeInterface.ClearExclusive));
|
||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.ClearExclusive)));
|
||||
}
|
||||
|
||||
public static void Dmb(ArmEmitterContext context) => EmitBarrier(context);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace ARMeilleure.Instructions
|
||||
{
|
||||
|
@ -12,32 +12,32 @@ namespace ARMeilleure.Instructions
|
|||
bool exclusive,
|
||||
int size)
|
||||
{
|
||||
Delegate fallbackMethodDlg = null;
|
||||
MethodInfo info = null;
|
||||
|
||||
if (exclusive)
|
||||
{
|
||||
switch (size)
|
||||
{
|
||||
case 0: fallbackMethodDlg = new _U8_U64(NativeInterface.ReadByteExclusive); break;
|
||||
case 1: fallbackMethodDlg = new _U16_U64(NativeInterface.ReadUInt16Exclusive); break;
|
||||
case 2: fallbackMethodDlg = new _U32_U64(NativeInterface.ReadUInt32Exclusive); break;
|
||||
case 3: fallbackMethodDlg = new _U64_U64(NativeInterface.ReadUInt64Exclusive); break;
|
||||
case 4: fallbackMethodDlg = new _V128_U64(NativeInterface.ReadVector128Exclusive); break;
|
||||
case 0: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadByteExclusive)); break;
|
||||
case 1: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt16Exclusive)); break;
|
||||
case 2: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt32Exclusive)); break;
|
||||
case 3: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64Exclusive)); break;
|
||||
case 4: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadVector128Exclusive)); break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (size)
|
||||
{
|
||||
case 0: fallbackMethodDlg = new _U8_U64(NativeInterface.ReadByte); break;
|
||||
case 1: fallbackMethodDlg = new _U16_U64(NativeInterface.ReadUInt16); break;
|
||||
case 2: fallbackMethodDlg = new _U32_U64(NativeInterface.ReadUInt32); break;
|
||||
case 3: fallbackMethodDlg = new _U64_U64(NativeInterface.ReadUInt64); break;
|
||||
case 4: fallbackMethodDlg = new _V128_U64(NativeInterface.ReadVector128); break;
|
||||
case 0: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadByte)); break;
|
||||
case 1: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt16)); break;
|
||||
case 2: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt32)); break;
|
||||
case 3: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64)); break;
|
||||
case 4: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadVector128)); break;
|
||||
}
|
||||
}
|
||||
|
||||
return context.Call(fallbackMethodDlg, address);
|
||||
return context.Call(info, address);
|
||||
}
|
||||
|
||||
public static Operand EmitStoreExclusive(
|
||||
|
@ -52,33 +52,33 @@ namespace ARMeilleure.Instructions
|
|||
value = context.ConvertI64ToI32(value);
|
||||
}
|
||||
|
||||
Delegate fallbackMethodDlg = null;
|
||||
MethodInfo info = null;
|
||||
|
||||
if (exclusive)
|
||||
{
|
||||
switch (size)
|
||||
{
|
||||
case 0: fallbackMethodDlg = new _S32_U64_U8(NativeInterface.WriteByteExclusive); break;
|
||||
case 1: fallbackMethodDlg = new _S32_U64_U16(NativeInterface.WriteUInt16Exclusive); break;
|
||||
case 2: fallbackMethodDlg = new _S32_U64_U32(NativeInterface.WriteUInt32Exclusive); break;
|
||||
case 3: fallbackMethodDlg = new _S32_U64_U64(NativeInterface.WriteUInt64Exclusive); break;
|
||||
case 4: fallbackMethodDlg = new _S32_U64_V128(NativeInterface.WriteVector128Exclusive); break;
|
||||
case 0: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteByteExclusive)); break;
|
||||
case 1: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt16Exclusive)); break;
|
||||
case 2: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt32Exclusive)); break;
|
||||
case 3: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt64Exclusive)); break;
|
||||
case 4: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteVector128Exclusive)); break;
|
||||
}
|
||||
|
||||
return context.Call(fallbackMethodDlg, address, value);
|
||||
return context.Call(info, address, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (size)
|
||||
{
|
||||
case 0: fallbackMethodDlg = new _Void_U64_U8(NativeInterface.WriteByte); break;
|
||||
case 1: fallbackMethodDlg = new _Void_U64_U16(NativeInterface.WriteUInt16); break;
|
||||
case 2: fallbackMethodDlg = new _Void_U64_U32(NativeInterface.WriteUInt32); break;
|
||||
case 3: fallbackMethodDlg = new _Void_U64_U64(NativeInterface.WriteUInt64); break;
|
||||
case 4: fallbackMethodDlg = new _Void_U64_V128(NativeInterface.WriteVector128); break;
|
||||
case 0: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteByte)); break;
|
||||
case 1: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt16)); break;
|
||||
case 2: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt32)); break;
|
||||
case 3: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt64)); break;
|
||||
case 4: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteVector128)); break;
|
||||
}
|
||||
|
||||
context.Call(fallbackMethodDlg, address, value);
|
||||
context.Call(info, address, value);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
using ARMeilleure.Decoders;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
using ARMeilleure.Translation.PTC;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
|
||||
|
@ -144,21 +146,10 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0:
|
||||
value = context.Load8(physAddr);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
value = context.Load16(physAddr);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
value = context.Load(OperandType.I32, physAddr);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
value = context.Load(OperandType.I64, physAddr);
|
||||
break;
|
||||
case 0: value = context.Load8 (physAddr); break;
|
||||
case 1: value = context.Load16(physAddr); break;
|
||||
case 2: value = context.Load (OperandType.I32, physAddr); break;
|
||||
case 3: value = context.Load (OperandType.I64, physAddr); break;
|
||||
}
|
||||
|
||||
SetInt(context, rt, value);
|
||||
|
@ -196,25 +187,11 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0:
|
||||
value = context.VectorInsert8(vector, context.Load8(physAddr), elem);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
value = context.VectorInsert16(vector, context.Load16(physAddr), elem);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
value = context.VectorInsert(vector, context.Load(OperandType.I32, physAddr), elem);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
value = context.VectorInsert(vector, context.Load(OperandType.I64, physAddr), elem);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
value = context.Load(OperandType.V128, physAddr);
|
||||
break;
|
||||
case 0: value = context.VectorInsert8 (vector, context.Load8(physAddr), elem); break;
|
||||
case 1: value = context.VectorInsert16(vector, context.Load16(physAddr), elem); break;
|
||||
case 2: value = context.VectorInsert (vector, context.Load(OperandType.I32, physAddr), elem); break;
|
||||
case 3: value = context.VectorInsert (vector, context.Load(OperandType.I64, physAddr), elem); break;
|
||||
case 4: value = context.Load (OperandType.V128, physAddr); break;
|
||||
}
|
||||
|
||||
context.Copy(GetVec(rt), value);
|
||||
|
@ -294,25 +271,11 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0:
|
||||
context.Store8(physAddr, context.VectorExtract8(value, elem));
|
||||
break;
|
||||
|
||||
case 1:
|
||||
context.Store16(physAddr, context.VectorExtract16(value, elem));
|
||||
break;
|
||||
|
||||
case 2:
|
||||
context.Store(physAddr, context.VectorExtract(OperandType.FP32, value, elem));
|
||||
break;
|
||||
|
||||
case 3:
|
||||
context.Store(physAddr, context.VectorExtract(OperandType.FP64, value, elem));
|
||||
break;
|
||||
|
||||
case 4:
|
||||
context.Store(physAddr, value);
|
||||
break;
|
||||
case 0: context.Store8 (physAddr, context.VectorExtract8(value, elem)); break;
|
||||
case 1: context.Store16(physAddr, context.VectorExtract16(value, elem)); break;
|
||||
case 2: context.Store (physAddr, context.VectorExtract(OperandType.FP32, value, elem)); break;
|
||||
case 3: context.Store (physAddr, context.VectorExtract(OperandType.FP64, value, elem)); break;
|
||||
case 4: context.Store (physAddr, value); break;
|
||||
}
|
||||
|
||||
context.MarkLabel(lblEnd);
|
||||
|
@ -333,7 +296,9 @@ namespace ARMeilleure.Instructions
|
|||
int ptLevelSize = 1 << ptLevelBits;
|
||||
int ptLevelMask = ptLevelSize - 1;
|
||||
|
||||
Operand pte = Const(context.Memory.PageTablePointer.ToInt64());
|
||||
Operand pte = Ptc.State == PtcState.Disabled
|
||||
? Const(context.Memory.PageTablePointer.ToInt64())
|
||||
: Const(context.Memory.PageTablePointer.ToInt64(), true, Ptc.PageTablePointerIndex);
|
||||
|
||||
int bit = PageBits;
|
||||
|
||||
|
@ -375,17 +340,17 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
private static void EmitReadIntFallback(ArmEmitterContext context, Operand address, int rt, int size)
|
||||
{
|
||||
Delegate fallbackMethodDlg = null;
|
||||
MethodInfo info = null;
|
||||
|
||||
switch (size)
|
||||
{
|
||||
case 0: fallbackMethodDlg = new _U8_U64 (NativeInterface.ReadByte); break;
|
||||
case 1: fallbackMethodDlg = new _U16_U64(NativeInterface.ReadUInt16); break;
|
||||
case 2: fallbackMethodDlg = new _U32_U64(NativeInterface.ReadUInt32); break;
|
||||
case 3: fallbackMethodDlg = new _U64_U64(NativeInterface.ReadUInt64); break;
|
||||
case 0: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadByte)); break;
|
||||
case 1: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt16)); break;
|
||||
case 2: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt32)); break;
|
||||
case 3: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64)); break;
|
||||
}
|
||||
|
||||
SetInt(context, rt, context.Call(fallbackMethodDlg, address));
|
||||
SetInt(context, rt, context.Call(info, address));
|
||||
}
|
||||
|
||||
private static void EmitReadVectorFallback(
|
||||
|
@ -396,18 +361,18 @@ namespace ARMeilleure.Instructions
|
|||
int elem,
|
||||
int size)
|
||||
{
|
||||
Delegate fallbackMethodDlg = null;
|
||||
MethodInfo info = null;
|
||||
|
||||
switch (size)
|
||||
{
|
||||
case 0: fallbackMethodDlg = new _U8_U64 (NativeInterface.ReadByte); break;
|
||||
case 1: fallbackMethodDlg = new _U16_U64 (NativeInterface.ReadUInt16); break;
|
||||
case 2: fallbackMethodDlg = new _U32_U64 (NativeInterface.ReadUInt32); break;
|
||||
case 3: fallbackMethodDlg = new _U64_U64 (NativeInterface.ReadUInt64); break;
|
||||
case 4: fallbackMethodDlg = new _V128_U64(NativeInterface.ReadVector128); break;
|
||||
case 0: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadByte)); break;
|
||||
case 1: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt16)); break;
|
||||
case 2: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt32)); break;
|
||||
case 3: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64)); break;
|
||||
case 4: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadVector128)); break;
|
||||
}
|
||||
|
||||
Operand value = context.Call(fallbackMethodDlg, address);
|
||||
Operand value = context.Call(info, address);
|
||||
|
||||
switch (size)
|
||||
{
|
||||
|
@ -422,14 +387,14 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
private static void EmitWriteIntFallback(ArmEmitterContext context, Operand address, int rt, int size)
|
||||
{
|
||||
Delegate fallbackMethodDlg = null;
|
||||
MethodInfo info = null;
|
||||
|
||||
switch (size)
|
||||
{
|
||||
case 0: fallbackMethodDlg = new _Void_U64_U8 (NativeInterface.WriteByte); break;
|
||||
case 1: fallbackMethodDlg = new _Void_U64_U16(NativeInterface.WriteUInt16); break;
|
||||
case 2: fallbackMethodDlg = new _Void_U64_U32(NativeInterface.WriteUInt32); break;
|
||||
case 3: fallbackMethodDlg = new _Void_U64_U64(NativeInterface.WriteUInt64); break;
|
||||
case 0: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteByte)); break;
|
||||
case 1: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt16)); break;
|
||||
case 2: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt32)); break;
|
||||
case 3: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt64)); break;
|
||||
}
|
||||
|
||||
Operand value = GetInt(context, rt);
|
||||
|
@ -439,7 +404,7 @@ namespace ARMeilleure.Instructions
|
|||
value = context.ConvertI64ToI32(value);
|
||||
}
|
||||
|
||||
context.Call(fallbackMethodDlg, address, value);
|
||||
context.Call(info, address, value);
|
||||
}
|
||||
|
||||
private static void EmitWriteVectorFallback(
|
||||
|
@ -449,15 +414,15 @@ namespace ARMeilleure.Instructions
|
|||
int elem,
|
||||
int size)
|
||||
{
|
||||
Delegate fallbackMethodDlg = null;
|
||||
MethodInfo info = null;
|
||||
|
||||
switch (size)
|
||||
{
|
||||
case 0: fallbackMethodDlg = new _Void_U64_U8 (NativeInterface.WriteByte); break;
|
||||
case 1: fallbackMethodDlg = new _Void_U64_U16 (NativeInterface.WriteUInt16); break;
|
||||
case 2: fallbackMethodDlg = new _Void_U64_U32 (NativeInterface.WriteUInt32); break;
|
||||
case 3: fallbackMethodDlg = new _Void_U64_U64 (NativeInterface.WriteUInt64); break;
|
||||
case 4: fallbackMethodDlg = new _Void_U64_V128(NativeInterface.WriteVector128); break;
|
||||
case 0: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteByte)); break;
|
||||
case 1: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt16)); break;
|
||||
case 2: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt32)); break;
|
||||
case 3: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt64)); break;
|
||||
case 4: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteVector128)); break;
|
||||
}
|
||||
|
||||
Operand value = null;
|
||||
|
@ -466,21 +431,10 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
switch (size)
|
||||
{
|
||||
case 0:
|
||||
value = context.VectorExtract8(GetVec(rt), elem);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
value = context.VectorExtract16(GetVec(rt), elem);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
value = context.VectorExtract(OperandType.I32, GetVec(rt), elem);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
value = context.VectorExtract(OperandType.I64, GetVec(rt), elem);
|
||||
break;
|
||||
case 0: value = context.VectorExtract8 (GetVec(rt), elem); break;
|
||||
case 1: value = context.VectorExtract16(GetVec(rt), elem); break;
|
||||
case 2: value = context.VectorExtract (OperandType.I32, GetVec(rt), elem); break;
|
||||
case 3: value = context.VectorExtract (OperandType.I64, GetVec(rt), elem); break;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -488,7 +442,7 @@ namespace ARMeilleure.Instructions
|
|||
value = GetVec(rt);
|
||||
}
|
||||
|
||||
context.Call(fallbackMethodDlg, address, value);
|
||||
context.Call(info, address, value);
|
||||
}
|
||||
|
||||
private static Operand GetInt(ArmEmitterContext context, int rt)
|
||||
|
@ -571,4 +525,4 @@ namespace ARMeilleure.Instructions
|
|||
return m;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ using ARMeilleure.IntermediateRepresentation;
|
|||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
|
@ -106,7 +107,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
Operand ne = EmitVectorExtractZx(context, op.Rn, index, op.Size);
|
||||
|
||||
Operand de = context.Call(new _U64_U64_S32(SoftFallback.CountLeadingSigns), ne, Const(eSize));
|
||||
Operand de = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.CountLeadingSigns)), ne, Const(eSize));
|
||||
|
||||
res = EmitVectorInsert(context, res, de, index, op.Size);
|
||||
}
|
||||
|
@ -128,16 +129,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
Operand ne = EmitVectorExtractZx(context, op.Rn, index, op.Size);
|
||||
|
||||
Operand de;
|
||||
|
||||
if (eSize == 64)
|
||||
{
|
||||
de = context.CountLeadingZeros(ne);
|
||||
}
|
||||
else
|
||||
{
|
||||
de = context.Call(new _U64_U64_S32(SoftFallback.CountLeadingZeros), ne, Const(eSize));
|
||||
}
|
||||
Operand de = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.CountLeadingZeros)), ne, Const(eSize));
|
||||
|
||||
res = EmitVectorInsert(context, res, de, index, op.Size);
|
||||
}
|
||||
|
@ -165,7 +157,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
de = context.Call(new _U64_U64(SoftFallback.CountSetBits8), ne);
|
||||
de = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.CountSetBits8)), ne);
|
||||
}
|
||||
|
||||
res = EmitVectorInsert(context, res, de, index, 0);
|
||||
|
@ -203,9 +195,9 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarBinaryOpF(context, (op1, op2) =>
|
||||
{
|
||||
Operand res = EmitSoftFloatCall(context, SoftFloat32.FPSub, SoftFloat64.FPSub, op1, op2);
|
||||
Operand res = EmitSoftFloatCall(context, nameof(SoftFloat32.FPSub), op1, op2);
|
||||
|
||||
return EmitUnaryMathCall(context, MathF.Abs, Math.Abs, res);
|
||||
return EmitUnaryMathCall(context, nameof(Math.Abs), res);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -244,9 +236,9 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorBinaryOpF(context, (op1, op2) =>
|
||||
{
|
||||
Operand res = EmitSoftFloatCall(context, SoftFloat32.FPSub, SoftFloat64.FPSub, op1, op2);
|
||||
Operand res = EmitSoftFloatCall(context, nameof(SoftFloat32.FPSub), op1, op2);
|
||||
|
||||
return EmitUnaryMathCall(context, MathF.Abs, Math.Abs, res);
|
||||
return EmitUnaryMathCall(context, nameof(Math.Abs), res);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -274,7 +266,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitUnaryMathCall(context, MathF.Abs, Math.Abs, op1);
|
||||
return EmitUnaryMathCall(context, nameof(Math.Abs), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -309,7 +301,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitUnaryMathCall(context, MathF.Abs, Math.Abs, op1);
|
||||
return EmitUnaryMathCall(context, nameof(Math.Abs), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -328,7 +320,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarBinaryOpF(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPAdd, SoftFloat64.FPAdd, op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPAdd), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -347,7 +339,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorBinaryOpF(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPAdd, SoftFloat64.FPAdd, op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPAdd), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -380,7 +372,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand ne0 = context.VectorExtract(type, GetVec(op.Rn), 0);
|
||||
Operand ne1 = context.VectorExtract(type, GetVec(op.Rn), 1);
|
||||
|
||||
Operand res = EmitSoftFloatCall(context, SoftFloat32.FPAdd, SoftFloat64.FPAdd, ne0, ne1);
|
||||
Operand res = EmitSoftFloatCall(context, nameof(SoftFloat32.FPAdd), ne0, ne1);
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
|
||||
}
|
||||
|
@ -396,7 +388,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorPairwiseOpF(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPAdd, SoftFloat64.FPAdd, op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPAdd), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -415,7 +407,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarBinaryOpF(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPDiv, SoftFloat64.FPDiv, op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPDiv), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -434,7 +426,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorBinaryOpF(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPDiv, SoftFloat64.FPDiv, op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPDiv), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -469,7 +461,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarTernaryRaOpF(context, (op1, op2, op3) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMulAdd, SoftFloat64.FPMulAdd, op1, op2, op3);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMulAdd), op1, op2, op3);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -484,7 +476,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarBinaryOpF(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMax, SoftFloat64.FPMax, op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMax), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -499,7 +491,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorBinaryOpF(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMax, SoftFloat64.FPMax, op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMax), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -514,7 +506,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarBinaryOpF(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMaxNum, SoftFloat64.FPMaxNum, op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMaxNum), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -529,7 +521,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorBinaryOpF(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMaxNum, SoftFloat64.FPMaxNum, op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMaxNum), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -538,7 +530,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorAcrossVectorOpF(context, (op1, op2) =>
|
||||
{
|
||||
return context.Call(new _F32_F32_F32(SoftFloat32.FPMaxNum), op1, op2);
|
||||
return context.Call(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMaxNum)), op1, op2);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -552,7 +544,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorPairwiseOpF(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMax, SoftFloat64.FPMax, op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMax), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -567,7 +559,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarBinaryOpF(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMin, SoftFloat64.FPMin, op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMin), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -582,7 +574,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorBinaryOpF(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMin, SoftFloat64.FPMin, op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMin), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -597,7 +589,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarBinaryOpF(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMinNum, SoftFloat64.FPMinNum, op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMinNum), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -612,7 +604,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorBinaryOpF(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMinNum, SoftFloat64.FPMinNum, op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMinNum), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -621,7 +613,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorAcrossVectorOpF(context, (op1, op2) =>
|
||||
{
|
||||
return context.Call(new _F32_F32_F32(SoftFloat32.FPMinNum), op1, op2);
|
||||
return context.Call(typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPMinNum)), op1, op2);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -635,7 +627,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorPairwiseOpF(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMin, SoftFloat64.FPMin, op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMin), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -686,7 +678,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorTernaryOpF(context, (op1, op2, op3) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMulAdd, SoftFloat64.FPMulAdd, op1, op2, op3);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMulAdd), op1, op2, op3);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -735,7 +727,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorTernaryOpByElemF(context, (op1, op2, op3) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMulAdd, SoftFloat64.FPMulAdd, op1, op2, op3);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMulAdd), op1, op2, op3);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -786,7 +778,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorTernaryOpF(context, (op1, op2, op3) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMulSub, SoftFloat64.FPMulSub, op1, op2, op3);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMulSub), op1, op2, op3);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -835,7 +827,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorTernaryOpByElemF(context, (op1, op2, op3) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMulSub, SoftFloat64.FPMulSub, op1, op2, op3);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMulSub), op1, op2, op3);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -870,7 +862,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarTernaryRaOpF(context, (op1, op2, op3) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMulSub, SoftFloat64.FPMulSub, op1, op2, op3);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMulSub), op1, op2, op3);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -889,7 +881,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarBinaryOpF(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMul, SoftFloat64.FPMul, op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMul), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -913,7 +905,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorBinaryOpF(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMul, SoftFloat64.FPMul, op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMul), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -963,7 +955,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorBinaryOpByElemF(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMul, SoftFloat64.FPMul, op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMul), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -972,7 +964,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarBinaryOpF(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMulX, SoftFloat64.FPMulX, op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMulX), op1, op2);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -980,7 +972,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarBinaryOpByElemF(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMulX, SoftFloat64.FPMulX, op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMulX), op1, op2);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -988,7 +980,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorBinaryOpF(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMulX, SoftFloat64.FPMulX, op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMulX), op1, op2);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -996,7 +988,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorBinaryOpByElemF(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMulX, SoftFloat64.FPMulX, op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMulX), op1, op2);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1103,7 +1095,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarTernaryRaOpF(context, (op1, op2, op3) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPNegMulAdd, SoftFloat64.FPNegMulAdd, op1, op2, op3);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPNegMulAdd), op1, op2, op3);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1146,7 +1138,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarTernaryRaOpF(context, (op1, op2, op3) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPNegMulSub, SoftFloat64.FPNegMulSub, op1, op2, op3);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPNegMulSub), op1, op2, op3);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1170,7 +1162,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPRecipEstimate, SoftFloat64.FPRecipEstimate, op1);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPRecipEstimate), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1189,7 +1181,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPRecipEstimate, SoftFloat64.FPRecipEstimate, op1);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPRecipEstimate), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1227,7 +1219,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarBinaryOpF(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPRecipStepFused, SoftFloat64.FPRecipStepFused, op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPRecipStepFused), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1270,7 +1262,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorBinaryOpF(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPRecipStepFused, SoftFloat64.FPRecipStepFused, op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPRecipStepFused), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1279,7 +1271,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPRecpX, SoftFloat64.FPRecpX, op1);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPRecpX), op1);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1307,11 +1299,11 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (op.Size == 0)
|
||||
{
|
||||
return context.Call(new _F32_F32(SoftFallback.RoundF), op1);
|
||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.RoundF)), op1);
|
||||
}
|
||||
else /* if (op.Size == 1) */
|
||||
{
|
||||
return context.Call(new _F64_F64(SoftFallback.Round), op1);
|
||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Round)), op1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1326,11 +1318,11 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (sizeF == 0)
|
||||
{
|
||||
return context.Call(new _F32_F32(SoftFallback.RoundF), op1);
|
||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.RoundF)), op1);
|
||||
}
|
||||
else /* if (sizeF == 1) */
|
||||
{
|
||||
return context.Call(new _F64_F64(SoftFallback.Round), op1);
|
||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Round)), op1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1345,7 +1337,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitUnaryMathCall(context, MathF.Floor, Math.Floor, op1);
|
||||
return EmitUnaryMathCall(context, nameof(Math.Floor), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1360,7 +1352,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitUnaryMathCall(context, MathF.Floor, Math.Floor, op1);
|
||||
return EmitUnaryMathCall(context, nameof(Math.Floor), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1405,7 +1397,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitUnaryMathCall(context, MathF.Ceiling, Math.Ceiling, op1);
|
||||
return EmitUnaryMathCall(context, nameof(Math.Ceiling), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1420,7 +1412,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitUnaryMathCall(context, MathF.Ceiling, Math.Ceiling, op1);
|
||||
return EmitUnaryMathCall(context, nameof(Math.Ceiling), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1433,11 +1425,11 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (op.Size == 0)
|
||||
{
|
||||
return context.Call(new _F32_F32(SoftFallback.RoundF), op1);
|
||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.RoundF)), op1);
|
||||
}
|
||||
else /* if (op.Size == 1) */
|
||||
{
|
||||
return context.Call(new _F64_F64(SoftFallback.Round), op1);
|
||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Round)), op1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1452,11 +1444,11 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (sizeF == 0)
|
||||
{
|
||||
return context.Call(new _F32_F32(SoftFallback.RoundF), op1);
|
||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.RoundF)), op1);
|
||||
}
|
||||
else /* if (sizeF == 1) */
|
||||
{
|
||||
return context.Call(new _F64_F64(SoftFallback.Round), op1);
|
||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Round)), op1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1471,7 +1463,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitUnaryMathCall(context, MathF.Truncate, Math.Truncate, op1);
|
||||
return EmitUnaryMathCall(context, nameof(Math.Truncate), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1486,7 +1478,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitUnaryMathCall(context, MathF.Truncate, Math.Truncate, op1);
|
||||
return EmitUnaryMathCall(context, nameof(Math.Truncate), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1505,7 +1497,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPRSqrtEstimate, SoftFloat64.FPRSqrtEstimate, op1);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPRSqrtEstimate), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1524,7 +1516,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPRSqrtEstimate, SoftFloat64.FPRSqrtEstimate, op1);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPRSqrtEstimate), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1566,7 +1558,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarBinaryOpF(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPRSqrtStepFused, SoftFloat64.FPRSqrtStepFused, op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPRSqrtStepFused), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1613,7 +1605,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorBinaryOpF(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPRSqrtStepFused, SoftFloat64.FPRSqrtStepFused, op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPRSqrtStepFused), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1628,7 +1620,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPSqrt, SoftFloat64.FPSqrt, op1);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPSqrt), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1643,7 +1635,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPSqrt, SoftFloat64.FPSqrt, op1);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPSqrt), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1662,7 +1654,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarBinaryOpF(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPSub, SoftFloat64.FPSub, op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPSub), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1681,7 +1673,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorBinaryOpF(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPSub, SoftFloat64.FPSub, op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPSub), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1690,7 +1682,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41Mul_AddSub(context, AddSub.Add);
|
||||
EmitSse41VectorMul_AddSub(context, AddSub.Add);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1713,7 +1705,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41Mul_AddSub(context, AddSub.Subtract);
|
||||
EmitSse41VectorMul_AddSub(context, AddSub.Subtract);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1736,7 +1728,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41Mul_AddSub(context, AddSub.None);
|
||||
EmitSse41VectorMul_AddSub(context, AddSub.None);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1805,14 +1797,14 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static void Sabd_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.UseSse2)
|
||||
if (Optimizations.UseSse41)
|
||||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
||||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
EmitSse41Sabd(context, op, n, m, isLong: false);
|
||||
EmitSse41VectorSabdOp(context, op, n, m, isLong: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1845,7 +1837,7 @@ namespace ARMeilleure.Instructions
|
|||
n = context.AddIntrinsic(movInst, n);
|
||||
m = context.AddIntrinsic(movInst, m);
|
||||
|
||||
EmitSse41Sabd(context, op, n, m, isLong: true);
|
||||
EmitSse41VectorSabdOp(context, op, n, m, isLong: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2027,9 +2019,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
Delegate dlg = new _S64_S64_S64(Math.Max);
|
||||
|
||||
EmitVectorBinaryOpSx(context, (op1, op2) => context.Call(dlg, op1, op2));
|
||||
EmitVectorBinaryOpSx(context, (op1, op2) => EmitMax64Op(context, op1, op2, signed: true));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2041,17 +2031,13 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
Delegate dlg = new _S64_S64_S64(Math.Max);
|
||||
|
||||
EmitVectorPairwiseOpSx(context, (op1, op2) => context.Call(dlg, op1, op2));
|
||||
EmitVectorPairwiseOpSx(context, (op1, op2) => EmitMax64Op(context, op1, op2, signed: true));
|
||||
}
|
||||
}
|
||||
|
||||
public static void Smaxv_V(ArmEmitterContext context)
|
||||
{
|
||||
Delegate dlg = new _S64_S64_S64(Math.Max);
|
||||
|
||||
EmitVectorAcrossVectorOpSx(context, (op1, op2) => context.Call(dlg, op1, op2));
|
||||
EmitVectorAcrossVectorOpSx(context, (op1, op2) => EmitMax64Op(context, op1, op2, signed: true));
|
||||
}
|
||||
|
||||
public static void Smin_V(ArmEmitterContext context)
|
||||
|
@ -2076,9 +2062,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
Delegate dlg = new _S64_S64_S64(Math.Min);
|
||||
|
||||
EmitVectorBinaryOpSx(context, (op1, op2) => context.Call(dlg, op1, op2));
|
||||
EmitVectorBinaryOpSx(context, (op1, op2) => EmitMin64Op(context, op1, op2, signed: true));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2090,17 +2074,13 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
Delegate dlg = new _S64_S64_S64(Math.Min);
|
||||
|
||||
EmitVectorPairwiseOpSx(context, (op1, op2) => context.Call(dlg, op1, op2));
|
||||
EmitVectorPairwiseOpSx(context, (op1, op2) => EmitMin64Op(context, op1, op2, signed: true));
|
||||
}
|
||||
}
|
||||
|
||||
public static void Sminv_V(ArmEmitterContext context)
|
||||
{
|
||||
Delegate dlg = new _S64_S64_S64(Math.Min);
|
||||
|
||||
EmitVectorAcrossVectorOpSx(context, (op1, op2) => context.Call(dlg, op1, op2));
|
||||
EmitVectorAcrossVectorOpSx(context, (op1, op2) => EmitMin64Op(context, op1, op2, signed: true));
|
||||
}
|
||||
|
||||
public static void Smlal_V(ArmEmitterContext context)
|
||||
|
@ -2458,7 +2438,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
EmitSse41Uabd(context, op, n, m, isLong: false);
|
||||
EmitSse41VectorUabdOp(context, op, n, m, isLong: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2491,7 +2471,7 @@ namespace ARMeilleure.Instructions
|
|||
n = context.AddIntrinsic(movInst, n);
|
||||
m = context.AddIntrinsic(movInst, m);
|
||||
|
||||
EmitSse41Uabd(context, op, n, m, isLong: true);
|
||||
EmitSse41VectorUabdOp(context, op, n, m, isLong: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2666,9 +2646,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
Delegate dlg = new _U64_U64_U64(Math.Max);
|
||||
|
||||
EmitVectorBinaryOpZx(context, (op1, op2) => context.Call(dlg, op1, op2));
|
||||
EmitVectorBinaryOpZx(context, (op1, op2) => EmitMax64Op(context, op1, op2, signed: false));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2680,17 +2658,13 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
Delegate dlg = new _U64_U64_U64(Math.Max);
|
||||
|
||||
EmitVectorPairwiseOpZx(context, (op1, op2) => context.Call(dlg, op1, op2));
|
||||
EmitVectorPairwiseOpZx(context, (op1, op2) => EmitMax64Op(context, op1, op2, signed: false));
|
||||
}
|
||||
}
|
||||
|
||||
public static void Umaxv_V(ArmEmitterContext context)
|
||||
{
|
||||
Delegate dlg = new _U64_U64_U64(Math.Max);
|
||||
|
||||
EmitVectorAcrossVectorOpZx(context, (op1, op2) => context.Call(dlg, op1, op2));
|
||||
EmitVectorAcrossVectorOpZx(context, (op1, op2) => EmitMax64Op(context, op1, op2, signed: false));
|
||||
}
|
||||
|
||||
public static void Umin_V(ArmEmitterContext context)
|
||||
|
@ -2715,9 +2689,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
Delegate dlg = new _U64_U64_U64(Math.Min);
|
||||
|
||||
EmitVectorBinaryOpZx(context, (op1, op2) => context.Call(dlg, op1, op2));
|
||||
EmitVectorBinaryOpZx(context, (op1, op2) => EmitMin64Op(context, op1, op2, signed: false));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2729,17 +2701,13 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
Delegate dlg = new _U64_U64_U64(Math.Min);
|
||||
|
||||
EmitVectorPairwiseOpZx(context, (op1, op2) => context.Call(dlg, op1, op2));
|
||||
EmitVectorPairwiseOpZx(context, (op1, op2) => EmitMin64Op(context, op1, op2, signed: false));
|
||||
}
|
||||
}
|
||||
|
||||
public static void Uminv_V(ArmEmitterContext context)
|
||||
{
|
||||
Delegate dlg = new _U64_U64_U64(Math.Min);
|
||||
|
||||
EmitVectorAcrossVectorOpZx(context, (op1, op2) => context.Call(dlg, op1, op2));
|
||||
EmitVectorAcrossVectorOpZx(context, (op1, op2) => EmitMin64Op(context, op1, op2, signed: false));
|
||||
}
|
||||
|
||||
public static void Umlal_V(ArmEmitterContext context)
|
||||
|
@ -3081,7 +3049,29 @@ namespace ARMeilleure.Instructions
|
|||
context.Copy(d, res);
|
||||
}
|
||||
|
||||
public static void EmitScalarRoundOpF(ArmEmitterContext context, FPRoundingMode roundMode)
|
||||
private static Operand EmitMax64Op(ArmEmitterContext context, Operand op1, Operand op2, bool signed)
|
||||
{
|
||||
Debug.Assert(op1.Type == OperandType.I64 && op2.Type == OperandType.I64);
|
||||
|
||||
Operand cmp = signed
|
||||
? context.ICompareGreaterOrEqual (op1, op2)
|
||||
: context.ICompareGreaterOrEqualUI(op1, op2);
|
||||
|
||||
return context.ConditionalSelect(cmp, op1, op2);
|
||||
}
|
||||
|
||||
private static Operand EmitMin64Op(ArmEmitterContext context, Operand op1, Operand op2, bool signed)
|
||||
{
|
||||
Debug.Assert(op1.Type == OperandType.I64 && op2.Type == OperandType.I64);
|
||||
|
||||
Operand cmp = signed
|
||||
? context.ICompareLessOrEqual (op1, op2)
|
||||
: context.ICompareLessOrEqualUI(op1, op2);
|
||||
|
||||
return context.ConditionalSelect(cmp, op1, op2);
|
||||
}
|
||||
|
||||
private static void EmitScalarRoundOpF(ArmEmitterContext context, FPRoundingMode roundMode)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
|
@ -3103,7 +3093,7 @@ namespace ARMeilleure.Instructions
|
|||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
|
||||
public static void EmitVectorRoundOpF(ArmEmitterContext context, FPRoundingMode roundMode)
|
||||
private static void EmitVectorRoundOpF(ArmEmitterContext context, FPRoundingMode roundMode)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
|
@ -3220,14 +3210,14 @@ namespace ARMeilleure.Instructions
|
|||
Subtract
|
||||
}
|
||||
|
||||
private static void EmitSse41Mul_AddSub(ArmEmitterContext context, AddSub addSub)
|
||||
private static void EmitSse41VectorMul_AddSub(ArmEmitterContext context, AddSub addSub)
|
||||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
||||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
Operand res = null;
|
||||
Operand res;
|
||||
|
||||
if (op.Size == 0)
|
||||
{
|
||||
|
@ -3257,23 +3247,15 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (addSub == AddSub.Add)
|
||||
{
|
||||
switch (op.Size)
|
||||
{
|
||||
case 0: res = context.AddIntrinsic(Intrinsic.X86Paddb, d, res); break;
|
||||
case 1: res = context.AddIntrinsic(Intrinsic.X86Paddw, d, res); break;
|
||||
case 2: res = context.AddIntrinsic(Intrinsic.X86Paddd, d, res); break;
|
||||
case 3: res = context.AddIntrinsic(Intrinsic.X86Paddq, d, res); break;
|
||||
}
|
||||
Intrinsic addInst = X86PaddInstruction[op.Size];
|
||||
|
||||
res = context.AddIntrinsic(addInst, d, res);
|
||||
}
|
||||
else if (addSub == AddSub.Subtract)
|
||||
{
|
||||
switch (op.Size)
|
||||
{
|
||||
case 0: res = context.AddIntrinsic(Intrinsic.X86Psubb, d, res); break;
|
||||
case 1: res = context.AddIntrinsic(Intrinsic.X86Psubw, d, res); break;
|
||||
case 2: res = context.AddIntrinsic(Intrinsic.X86Psubd, d, res); break;
|
||||
case 3: res = context.AddIntrinsic(Intrinsic.X86Psubq, d, res); break;
|
||||
}
|
||||
Intrinsic subInst = X86PsubInstruction[op.Size];
|
||||
|
||||
res = context.AddIntrinsic(subInst, d, res);
|
||||
}
|
||||
|
||||
if (op.RegisterSize == RegisterSize.Simd64)
|
||||
|
@ -3284,7 +3266,7 @@ namespace ARMeilleure.Instructions
|
|||
context.Copy(d, res);
|
||||
}
|
||||
|
||||
private static void EmitSse41Sabd(
|
||||
private static void EmitSse41VectorSabdOp(
|
||||
ArmEmitterContext context,
|
||||
OpCodeSimdReg op,
|
||||
Operand n,
|
||||
|
@ -3317,7 +3299,7 @@ namespace ARMeilleure.Instructions
|
|||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
|
||||
private static void EmitSse41Uabd(
|
||||
private static void EmitSse41VectorUabdOp(
|
||||
ArmEmitterContext context,
|
||||
OpCodeSimdReg op,
|
||||
Operand n,
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitScalarUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, MathF.Abs, Math.Abs, op1));
|
||||
EmitScalarUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Abs), op1));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -46,7 +46,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitVectorUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, MathF.Abs, Math.Abs, op1));
|
||||
EmitVectorUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Abs), op1));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -74,7 +74,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitScalarBinaryOpF32(context, (op1, op2) => EmitSoftFloatCall(context, SoftFloat32.FPAdd, SoftFloat64.FPAdd, op1, op2));
|
||||
EmitScalarBinaryOpF32(context, (op1, op2) => EmitSoftFloatCall(context, nameof(SoftFloat32.FPAdd), op1, op2));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,7 +90,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitVectorBinaryOpF32(context, (op1, op2) => EmitSoftFloatCallDefaultFpscr(context, SoftFloat32.FPAddFpscr, SoftFloat64.FPAddFpscr, op1, op2));
|
||||
EmitVectorBinaryOpF32(context, (op1, op2) => EmitSoftFloatCallDefaultFpscr(context, nameof(SoftFloat32.FPAddFpscr), op1, op2));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -330,7 +330,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarTernaryOpF32(context, (op1, op2, op3) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPNegMulAdd, SoftFloat64.FPNegMulAdd, op1, op2, op3);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPNegMulAdd), op1, op2, op3);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -371,7 +371,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarTernaryOpF32(context, (op1, op2, op3) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPNegMulSub, SoftFloat64.FPNegMulSub, op1, op2, op3);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPNegMulSub), op1, op2, op3);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -423,7 +423,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarBinaryOpF32(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPDiv, SoftFloat64.FPDiv, op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPDiv), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -436,7 +436,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitScalarBinaryOpF32(context, (op1, op2) => EmitSoftFloatCall(context, SoftFloat32.FPMaxNum, SoftFloat64.FPMaxNum, op1, op2));
|
||||
EmitScalarBinaryOpF32(context, (op1, op2) => EmitSoftFloatCall(context, nameof(SoftFloat32.FPMaxNum), op1, op2));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -448,7 +448,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitVectorBinaryOpSx32(context, (op1, op2) => EmitSoftFloatCallDefaultFpscr(context, SoftFloat32.FPMaxNumFpscr, SoftFloat64.FPMaxNumFpscr, op1, op2));
|
||||
EmitVectorBinaryOpSx32(context, (op1, op2) => EmitSoftFloatCallDefaultFpscr(context, nameof(SoftFloat32.FPMaxNumFpscr), op1, op2));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -460,7 +460,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitScalarBinaryOpF32(context, (op1, op2) => EmitSoftFloatCall(context, SoftFloat32.FPMinNum, SoftFloat64.FPMinNum, op1, op2));
|
||||
EmitScalarBinaryOpF32(context, (op1, op2) => EmitSoftFloatCall(context, nameof(SoftFloat32.FPMinNum), op1, op2));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -472,7 +472,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitVectorBinaryOpSx32(context, (op1, op2) => EmitSoftFloatCallDefaultFpscr(context, SoftFloat32.FPMinNumFpscr, SoftFloat64.FPMinNumFpscr, op1, op2));
|
||||
EmitVectorBinaryOpSx32(context, (op1, op2) => EmitSoftFloatCallDefaultFpscr(context, nameof(SoftFloat32.FPMinNumFpscr), op1, op2));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -486,7 +486,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorBinaryOpF32(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCallDefaultFpscr(context, SoftFloat32.FPMaxFpscr, SoftFloat64.FPMaxFpscr, op1, op2);
|
||||
return EmitSoftFloatCallDefaultFpscr(context, nameof(SoftFloat32.FPMaxFpscr), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -529,7 +529,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorBinaryOpF32(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCallDefaultFpscr(context, SoftFloat32.FPMinFpscr, SoftFloat64.FPMinFpscr, op1, op2);
|
||||
return EmitSoftFloatCallDefaultFpscr(context, nameof(SoftFloat32.FPMinFpscr), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -579,7 +579,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarTernaryOpF32(context, (op1, op2, op3) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMulAdd, SoftFloat64.FPMulAdd, op1, op2, op3);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMulAdd), op1, op2, op3);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -598,7 +598,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorTernaryOpF32(context, (op1, op2, op3) =>
|
||||
{
|
||||
return EmitSoftFloatCallDefaultFpscr(context, SoftFloat32.FPMulAddFpscr, SoftFloat64.FPMulAddFpscr, op1, op2, op3);
|
||||
return EmitSoftFloatCallDefaultFpscr(context, nameof(SoftFloat32.FPMulAddFpscr), op1, op2, op3);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -624,7 +624,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitVectorsByScalarOpF32(context, (op1, op2, op3) => EmitSoftFloatCallDefaultFpscr(context, SoftFloat32.FPMulAddFpscr, SoftFloat64.FPMulAddFpscr, op1, op2, op3));
|
||||
EmitVectorsByScalarOpF32(context, (op1, op2, op3) => EmitSoftFloatCallDefaultFpscr(context, nameof(SoftFloat32.FPMulAddFpscr), op1, op2, op3));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -650,7 +650,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarTernaryOpF32(context, (op1, op2, op3) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMulSub, SoftFloat64.FPMulSub, op1, op2, op3);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMulSub), op1, op2, op3);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -669,7 +669,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorTernaryOpF32(context, (op1, op2, op3) =>
|
||||
{
|
||||
return EmitSoftFloatCallDefaultFpscr(context, SoftFloat32.FPMulSubFpscr, SoftFloat64.FPMulSubFpscr, op1, op2, op3);
|
||||
return EmitSoftFloatCallDefaultFpscr(context, nameof(SoftFloat32.FPMulSubFpscr), op1, op2, op3);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -695,7 +695,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitVectorsByScalarOpF32(context, (op1, op2, op3) => EmitSoftFloatCallDefaultFpscr(context, SoftFloat32.FPMulSubFpscr, SoftFloat64.FPMulSubFpscr, op1, op2, op3));
|
||||
EmitVectorsByScalarOpF32(context, (op1, op2, op3) => EmitSoftFloatCallDefaultFpscr(context, nameof(SoftFloat32.FPMulSubFpscr), op1, op2, op3));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -725,7 +725,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarBinaryOpF32(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPMul, SoftFloat64.FPMul, op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPMul), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -744,7 +744,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorBinaryOpF32(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCallDefaultFpscr(context, SoftFloat32.FPMulFpscr, SoftFloat64.FPMulFpscr, op1, op2);
|
||||
return EmitSoftFloatCallDefaultFpscr(context, nameof(SoftFloat32.FPMulFpscr), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -779,7 +779,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitVectorByScalarOpF32(context, (op1, op2) => EmitSoftFloatCallDefaultFpscr(context, SoftFloat32.FPMulFpscr, SoftFloat64.FPMulFpscr, op1, op2));
|
||||
EmitVectorByScalarOpF32(context, (op1, op2) => EmitSoftFloatCallDefaultFpscr(context, nameof(SoftFloat32.FPMulFpscr), op1, op2));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -938,7 +938,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorUnaryOpF32(context, (op1) =>
|
||||
{
|
||||
return EmitSoftFloatCallDefaultFpscr(context, SoftFloat32.FPRecipEstimateFpscr, SoftFloat64.FPRecipEstimateFpscr, op1);
|
||||
return EmitSoftFloatCallDefaultFpscr(context, nameof(SoftFloat32.FPRecipEstimateFpscr), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -980,7 +980,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorBinaryOpF32(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPRecipStep, SoftFloat64.FPRecipStep, op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPRecipStep), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1001,7 +1001,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorUnaryOpF32(context, (op1) =>
|
||||
{
|
||||
return EmitSoftFloatCallDefaultFpscr(context, SoftFloat32.FPRSqrtEstimateFpscr, SoftFloat64.FPRSqrtEstimateFpscr, op1);
|
||||
return EmitSoftFloatCallDefaultFpscr(context, nameof(SoftFloat32.FPRSqrtEstimateFpscr), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1047,7 +1047,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorBinaryOpF32(context, (op1, op2) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPRSqrtStep, SoftFloat64.FPRSqrtStep, op1, op2);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPRSqrtStep), op1, op2);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1089,7 +1089,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarUnaryOpF32(context, (op1) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPSqrt, SoftFloat64.FPSqrt, op1);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPSqrt), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -288,49 +288,49 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static void Facge_S(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAvx)
|
||||
{
|
||||
EmitSse2CmpOpF(context, CmpCondition.GreaterThanOrEqual, scalar: true, absolute: true);
|
||||
EmitSse2OrAvxCmpOpF(context, CmpCondition.GreaterThanOrEqual, scalar: true, absolute: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitCmpOpF(context, SoftFloat32.FPCompareGE, SoftFloat64.FPCompareGE, scalar: true, absolute: true);
|
||||
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareGE), scalar: true, absolute: true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Facge_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAvx)
|
||||
{
|
||||
EmitSse2CmpOpF(context, CmpCondition.GreaterThanOrEqual, scalar: false, absolute: true);
|
||||
EmitSse2OrAvxCmpOpF(context, CmpCondition.GreaterThanOrEqual, scalar: false, absolute: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitCmpOpF(context, SoftFloat32.FPCompareGE, SoftFloat64.FPCompareGE, scalar: false, absolute: true);
|
||||
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareGE), scalar: false, absolute: true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Facgt_S(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAvx)
|
||||
{
|
||||
EmitSse2CmpOpF(context, CmpCondition.GreaterThan, scalar: true, absolute: true);
|
||||
EmitSse2OrAvxCmpOpF(context, CmpCondition.GreaterThan, scalar: true, absolute: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitCmpOpF(context, SoftFloat32.FPCompareGT, SoftFloat64.FPCompareGT, scalar: true, absolute: true);
|
||||
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareGT), scalar: true, absolute: true);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Facgt_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAvx)
|
||||
{
|
||||
EmitSse2CmpOpF(context, CmpCondition.GreaterThan, scalar: false, absolute: true);
|
||||
EmitSse2OrAvxCmpOpF(context, CmpCondition.GreaterThan, scalar: false, absolute: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitCmpOpF(context, SoftFloat32.FPCompareGT, SoftFloat64.FPCompareGT, scalar: false, absolute: true);
|
||||
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareGT), scalar: false, absolute: true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -348,11 +348,11 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitSse2CmpOpF(context, CmpCondition.Equal, scalar: true);
|
||||
EmitSse2OrAvxCmpOpF(context, CmpCondition.Equal, scalar: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitCmpOpF(context, SoftFloat32.FPCompareEQ, SoftFloat64.FPCompareEQ, scalar: true);
|
||||
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareEQ), scalar: true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -360,11 +360,11 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitSse2CmpOpF(context, CmpCondition.Equal, scalar: false);
|
||||
EmitSse2OrAvxCmpOpF(context, CmpCondition.Equal, scalar: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitCmpOpF(context, SoftFloat32.FPCompareEQ, SoftFloat64.FPCompareEQ, scalar: false);
|
||||
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareEQ), scalar: false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -372,11 +372,11 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseAvx)
|
||||
{
|
||||
EmitSse2CmpOpF(context, CmpCondition.GreaterThanOrEqual, scalar: true);
|
||||
EmitSse2OrAvxCmpOpF(context, CmpCondition.GreaterThanOrEqual, scalar: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitCmpOpF(context, SoftFloat32.FPCompareGE, SoftFloat64.FPCompareGE, scalar: true);
|
||||
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareGE), scalar: true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -384,11 +384,11 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseAvx)
|
||||
{
|
||||
EmitSse2CmpOpF(context, CmpCondition.GreaterThanOrEqual, scalar: false);
|
||||
EmitSse2OrAvxCmpOpF(context, CmpCondition.GreaterThanOrEqual, scalar: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitCmpOpF(context, SoftFloat32.FPCompareGE, SoftFloat64.FPCompareGE, scalar: false);
|
||||
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareGE), scalar: false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -396,11 +396,11 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseAvx)
|
||||
{
|
||||
EmitSse2CmpOpF(context, CmpCondition.GreaterThan, scalar: true);
|
||||
EmitSse2OrAvxCmpOpF(context, CmpCondition.GreaterThan, scalar: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitCmpOpF(context, SoftFloat32.FPCompareGT, SoftFloat64.FPCompareGT, scalar: true);
|
||||
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareGT), scalar: true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -408,11 +408,11 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseAvx)
|
||||
{
|
||||
EmitSse2CmpOpF(context, CmpCondition.GreaterThan, scalar: false);
|
||||
EmitSse2OrAvxCmpOpF(context, CmpCondition.GreaterThan, scalar: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitCmpOpF(context, SoftFloat32.FPCompareGT, SoftFloat64.FPCompareGT, scalar: false);
|
||||
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareGT), scalar: false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -420,11 +420,11 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitSse2CmpOpF(context, CmpCondition.LessThanOrEqual, scalar: true);
|
||||
EmitSse2OrAvxCmpOpF(context, CmpCondition.LessThanOrEqual, scalar: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitCmpOpF(context, SoftFloat32.FPCompareLE, SoftFloat64.FPCompareLE, scalar: true);
|
||||
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareLE), scalar: true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -432,11 +432,11 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitSse2CmpOpF(context, CmpCondition.LessThanOrEqual, scalar: false);
|
||||
EmitSse2OrAvxCmpOpF(context, CmpCondition.LessThanOrEqual, scalar: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitCmpOpF(context, SoftFloat32.FPCompareLE, SoftFloat64.FPCompareLE, scalar: false);
|
||||
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareLE), scalar: false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -444,11 +444,11 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitSse2CmpOpF(context, CmpCondition.LessThan, scalar: true);
|
||||
EmitSse2OrAvxCmpOpF(context, CmpCondition.LessThan, scalar: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitCmpOpF(context, SoftFloat32.FPCompareLT, SoftFloat64.FPCompareLT, scalar: true);
|
||||
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareLT), scalar: true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -456,11 +456,11 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitSse2CmpOpF(context, CmpCondition.LessThan, scalar: false);
|
||||
EmitSse2OrAvxCmpOpF(context, CmpCondition.LessThan, scalar: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitCmpOpF(context, SoftFloat32.FPCompareLT, SoftFloat64.FPCompareLT, scalar: false);
|
||||
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareLT), scalar: false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -592,11 +592,7 @@ namespace ARMeilleure.Instructions
|
|||
me = context.VectorExtract(type, GetVec(op.Rm), 0);
|
||||
}
|
||||
|
||||
Delegate dlg = op.Size != 0
|
||||
? (Delegate)new _S32_F64_F64_Bool(SoftFloat64.FPCompare)
|
||||
: (Delegate)new _S32_F32_F32_Bool(SoftFloat32.FPCompare);
|
||||
|
||||
Operand nzcv = context.Call(dlg, ne, me, Const(signalNaNs));
|
||||
Operand nzcv = EmitSoftFloatCall(context, nameof(SoftFloat32.FPCompare), ne, me, Const(signalNaNs));
|
||||
|
||||
EmitSetNzcv(context, nzcv);
|
||||
}
|
||||
|
@ -683,12 +679,7 @@ namespace ARMeilleure.Instructions
|
|||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
|
||||
private static void EmitCmpOpF(
|
||||
ArmEmitterContext context,
|
||||
_F32_F32_F32 f32,
|
||||
_F64_F64_F64 f64,
|
||||
bool scalar,
|
||||
bool absolute = false)
|
||||
private static void EmitCmpOpF(ArmEmitterContext context, string name, bool scalar, bool absolute = false)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
|
@ -716,11 +707,11 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (absolute)
|
||||
{
|
||||
ne = EmitUnaryMathCall(context, MathF.Abs, Math.Abs, ne);
|
||||
me = EmitUnaryMathCall(context, MathF.Abs, Math.Abs, me);
|
||||
ne = EmitUnaryMathCall(context, nameof(Math.Abs), ne);
|
||||
me = EmitUnaryMathCall(context, nameof(Math.Abs), me);
|
||||
}
|
||||
|
||||
Operand e = EmitSoftFloatCall(context, f32, f64, ne, me);
|
||||
Operand e = EmitSoftFloatCall(context, name, ne, me);
|
||||
|
||||
res = context.VectorInsert(res, e, index);
|
||||
}
|
||||
|
@ -728,7 +719,7 @@ namespace ARMeilleure.Instructions
|
|||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
|
||||
private static void EmitSse2CmpOpF(ArmEmitterContext context, CmpCondition cond, bool scalar, bool absolute = false)
|
||||
private static void EmitSse2OrAvxCmpOpF(ArmEmitterContext context, CmpCondition cond, bool scalar, bool absolute = false)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ using ARMeilleure.IntermediateRepresentation;
|
|||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
|
@ -19,11 +20,11 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitSse2CmpOpF32(context, CmpCondition.Equal, false);
|
||||
EmitSse2OrAvxCmpOpF32(context, CmpCondition.Equal, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitCmpOpF32(context, SoftFloat32.FPCompareEQFpscr, SoftFloat64.FPCompareEQFpscr, false);
|
||||
EmitCmpOpF32(context, nameof(SoftFloat32.FPCompareEQFpscr), false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,11 +41,11 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitSse2CmpOpF32(context, CmpCondition.Equal, true);
|
||||
EmitSse2OrAvxCmpOpF32(context, CmpCondition.Equal, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitCmpOpF32(context, SoftFloat32.FPCompareEQFpscr, SoftFloat64.FPCompareEQFpscr, true);
|
||||
EmitCmpOpF32(context, nameof(SoftFloat32.FPCompareEQFpscr), true);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -55,13 +56,13 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static void Vcge_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAvx)
|
||||
{
|
||||
EmitSse2CmpOpF32(context, CmpCondition.GreaterThanOrEqual, false);
|
||||
EmitSse2OrAvxCmpOpF32(context, CmpCondition.GreaterThanOrEqual, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitCmpOpF32(context, SoftFloat32.FPCompareGEFpscr, SoftFloat64.FPCompareGEFpscr, false);
|
||||
EmitCmpOpF32(context, nameof(SoftFloat32.FPCompareGEFpscr), false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,15 +79,15 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (op.F)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAvx)
|
||||
{
|
||||
EmitSse2CmpOpF32(context, CmpCondition.GreaterThanOrEqual, true);
|
||||
EmitSse2OrAvxCmpOpF32(context, CmpCondition.GreaterThanOrEqual, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitCmpOpF32(context, SoftFloat32.FPCompareGEFpscr, SoftFloat64.FPCompareGEFpscr, true);
|
||||
EmitCmpOpF32(context, nameof(SoftFloat32.FPCompareGEFpscr), true);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitCmpOpI32(context, context.ICompareGreaterOrEqual, context.ICompareGreaterOrEqualUI, true, true);
|
||||
|
@ -95,13 +96,13 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static void Vcgt_V(ArmEmitterContext context)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAvx)
|
||||
{
|
||||
EmitSse2CmpOpF32(context, CmpCondition.GreaterThan, false);
|
||||
EmitSse2OrAvxCmpOpF32(context, CmpCondition.GreaterThan, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitCmpOpF32(context, SoftFloat32.FPCompareGTFpscr, SoftFloat64.FPCompareGTFpscr, false);
|
||||
EmitCmpOpF32(context, nameof(SoftFloat32.FPCompareGTFpscr), false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -118,13 +119,13 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (op.F)
|
||||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
if (Optimizations.FastFP && Optimizations.UseAvx)
|
||||
{
|
||||
EmitSse2CmpOpF32(context, CmpCondition.GreaterThan, true);
|
||||
EmitSse2OrAvxCmpOpF32(context, CmpCondition.GreaterThan, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitCmpOpF32(context, SoftFloat32.FPCompareGTFpscr, SoftFloat64.FPCompareGTFpscr, true);
|
||||
EmitCmpOpF32(context, nameof(SoftFloat32.FPCompareGTFpscr), true);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -141,11 +142,11 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitSse2CmpOpF32(context, CmpCondition.LessThanOrEqual, true);
|
||||
EmitSse2OrAvxCmpOpF32(context, CmpCondition.LessThanOrEqual, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitCmpOpF32(context, SoftFloat32.FPCompareLEFpscr, SoftFloat64.FPCompareLEFpscr, true);
|
||||
EmitCmpOpF32(context, nameof(SoftFloat32.FPCompareLEFpscr), true);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -162,11 +163,11 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.FastFP && Optimizations.UseSse2)
|
||||
{
|
||||
EmitSse2CmpOpF32(context, CmpCondition.LessThan, true);
|
||||
EmitSse2OrAvxCmpOpF32(context, CmpCondition.LessThan, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitCmpOpF32(context, SoftFloat32.FPCompareLTFpscr, SoftFloat64.FPCompareLTFpscr, true);
|
||||
EmitCmpOpF32(context, nameof(SoftFloat32.FPCompareLTFpscr), true);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -175,11 +176,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
}
|
||||
|
||||
private static void EmitCmpOpF32(
|
||||
ArmEmitterContext context,
|
||||
_F32_F32_F32_Bool f32,
|
||||
_F64_F64_F64_Bool f64,
|
||||
bool zero)
|
||||
private static void EmitCmpOpF32(ArmEmitterContext context, string name, bool zero)
|
||||
{
|
||||
Operand one = Const(1);
|
||||
if (zero)
|
||||
|
@ -190,11 +187,11 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (type == OperandType.FP64)
|
||||
{
|
||||
return context.Call(f64, m, ConstF(0.0), one);
|
||||
return context.Call(typeof(SoftFloat64).GetMethod(name), m, ConstF(0.0d), one);
|
||||
}
|
||||
else
|
||||
{
|
||||
return context.Call(f32, m, ConstF(0.0f), one);
|
||||
return context.Call(typeof(SoftFloat32).GetMethod(name), m, ConstF(0.0f), one);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -206,11 +203,11 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (type == OperandType.FP64)
|
||||
{
|
||||
return context.Call(f64, n, m, one);
|
||||
return context.Call(typeof(SoftFloat64).GetMethod(name), n, m, one);
|
||||
}
|
||||
else
|
||||
{
|
||||
return context.Call(f32, n, m, one);
|
||||
return context.Call(typeof(SoftFloat32).GetMethod(name), n, m, one);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -241,7 +238,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
return ZerosOrOnes(context, signedOp(m, zeroV), type);
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitVectorUnaryOpZx32(context, (m) =>
|
||||
|
@ -258,7 +255,7 @@ namespace ARMeilleure.Instructions
|
|||
if (signed)
|
||||
{
|
||||
EmitVectorBinaryOpSx32(context, (n, m) => ZerosOrOnes(context, signedOp(n, m), n.Type));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitVectorBinaryOpZx32(context, (n, m) => ZerosOrOnes(context, unsignedOp(n, m), n.Type));
|
||||
|
@ -351,11 +348,11 @@ namespace ARMeilleure.Instructions
|
|||
me = ExtractScalar(context, type, op.Vm);
|
||||
}
|
||||
|
||||
Delegate dlg = sizeF != 0
|
||||
? (Delegate)new _S32_F64_F64_Bool(SoftFloat64.FPCompare)
|
||||
: (Delegate)new _S32_F32_F32_Bool(SoftFloat32.FPCompare);
|
||||
MethodInfo info = sizeF != 0
|
||||
? typeof(SoftFloat64).GetMethod(nameof(SoftFloat64.FPCompare))
|
||||
: typeof(SoftFloat32).GetMethod(nameof(SoftFloat32.FPCompare));
|
||||
|
||||
Operand nzcv = context.Call(dlg, ne, me, Const(signalNaNs));
|
||||
Operand nzcv = context.Call(info, ne, me, Const(signalNaNs));
|
||||
|
||||
EmitSetFPSCRFlags(context, nzcv);
|
||||
}
|
||||
|
@ -389,7 +386,7 @@ namespace ARMeilleure.Instructions
|
|||
SetFpFlag(context, FPState.NFlag, n);
|
||||
}
|
||||
|
||||
private static void EmitSse2CmpOpF32(ArmEmitterContext context, CmpCondition cond, bool zero)
|
||||
private static void EmitSse2OrAvxCmpOpF32(ArmEmitterContext context, CmpCondition cond, bool zero)
|
||||
{
|
||||
OpCode32Simd op = (OpCode32Simd)context.CurrOp;
|
||||
|
||||
|
|
|
@ -16,13 +16,14 @@ namespace ARMeilleure.Instructions
|
|||
Operand n = GetVec(op.Rn);
|
||||
|
||||
Operand res;
|
||||
|
||||
if (Optimizations.UseAesni)
|
||||
{
|
||||
res = context.AddIntrinsic(Intrinsic.X86Aesdeclast, context.AddIntrinsic(Intrinsic.X86Xorpd, d, n), context.VectorZero());
|
||||
}
|
||||
else
|
||||
{
|
||||
res = context.Call(new _V128_V128_V128(SoftFallback.Decrypt), d, n);
|
||||
res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Decrypt)), d, n);
|
||||
}
|
||||
|
||||
context.Copy(d, res);
|
||||
|
@ -36,13 +37,14 @@ namespace ARMeilleure.Instructions
|
|||
Operand n = GetVec(op.Rn);
|
||||
|
||||
Operand res;
|
||||
|
||||
if (Optimizations.UseAesni)
|
||||
{
|
||||
res = context.AddIntrinsic(Intrinsic.X86Aesenclast, context.AddIntrinsic(Intrinsic.X86Xorpd, d, n), context.VectorZero());
|
||||
}
|
||||
else
|
||||
{
|
||||
res = context.Call(new _V128_V128_V128(SoftFallback.Encrypt), d, n);
|
||||
res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Encrypt)), d, n);
|
||||
}
|
||||
|
||||
context.Copy(d, res);
|
||||
|
@ -55,13 +57,14 @@ namespace ARMeilleure.Instructions
|
|||
Operand n = GetVec(op.Rn);
|
||||
|
||||
Operand res;
|
||||
|
||||
if (Optimizations.UseAesni)
|
||||
{
|
||||
res = context.AddIntrinsic(Intrinsic.X86Aesimc, n);
|
||||
}
|
||||
else
|
||||
{
|
||||
res = context.Call(new _V128_V128(SoftFallback.InverseMixColumns), n);
|
||||
res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.InverseMixColumns)), n);
|
||||
}
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
|
@ -74,6 +77,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand n = GetVec(op.Rn);
|
||||
|
||||
Operand res;
|
||||
|
||||
if (Optimizations.UseAesni)
|
||||
{
|
||||
Operand roundKey = context.VectorZero();
|
||||
|
@ -86,7 +90,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
res = context.Call(new _V128_V128(SoftFallback.MixColumns), n);
|
||||
res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.MixColumns)), n);
|
||||
}
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
|
|
|
@ -16,13 +16,14 @@ namespace ARMeilleure.Instructions
|
|||
Operand n = GetVecA32(op.Qm);
|
||||
|
||||
Operand res;
|
||||
|
||||
if (Optimizations.UseAesni)
|
||||
{
|
||||
res = context.AddIntrinsic(Intrinsic.X86Aesdeclast, context.AddIntrinsic(Intrinsic.X86Xorpd, d, n), context.VectorZero());
|
||||
}
|
||||
else
|
||||
{
|
||||
res = context.Call(new _V128_V128_V128(SoftFallback.Decrypt), d, n);
|
||||
res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Decrypt)), d, n);
|
||||
}
|
||||
|
||||
context.Copy(d, res);
|
||||
|
@ -36,13 +37,14 @@ namespace ARMeilleure.Instructions
|
|||
Operand n = GetVecA32(op.Qm);
|
||||
|
||||
Operand res;
|
||||
|
||||
if (Optimizations.UseAesni)
|
||||
{
|
||||
res = context.AddIntrinsic(Intrinsic.X86Aesenclast, context.AddIntrinsic(Intrinsic.X86Xorpd, d, n), context.VectorZero());
|
||||
}
|
||||
else
|
||||
{
|
||||
res = context.Call(new _V128_V128_V128(SoftFallback.Encrypt), d, n);
|
||||
res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Encrypt)), d, n);
|
||||
}
|
||||
|
||||
context.Copy(d, res);
|
||||
|
@ -55,13 +57,14 @@ namespace ARMeilleure.Instructions
|
|||
Operand n = GetVecA32(op.Qm);
|
||||
|
||||
Operand res;
|
||||
|
||||
if (Optimizations.UseAesni)
|
||||
{
|
||||
res = context.AddIntrinsic(Intrinsic.X86Aesimc, n);
|
||||
}
|
||||
else
|
||||
{
|
||||
res = context.Call(new _V128_V128(SoftFallback.InverseMixColumns), n);
|
||||
res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.InverseMixColumns)), n);
|
||||
}
|
||||
|
||||
context.Copy(GetVecA32(op.Qd), res);
|
||||
|
@ -74,6 +77,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand n = GetVecA32(op.Qm);
|
||||
|
||||
Operand res;
|
||||
|
||||
if (Optimizations.UseAesni)
|
||||
{
|
||||
Operand roundKey = context.VectorZero();
|
||||
|
@ -86,7 +90,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
res = context.Call(new _V128_V128(SoftFallback.MixColumns), n);
|
||||
res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.MixColumns)), n);
|
||||
}
|
||||
|
||||
context.Copy(GetVecA32(op.Qd), res);
|
||||
|
|
|
@ -4,6 +4,7 @@ using ARMeilleure.State;
|
|||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
|
@ -61,9 +62,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
Operand ne = context.VectorExtract(OperandType.FP32, GetVec(op.Rn), 0);
|
||||
|
||||
Delegate dlg = new _U16_F32(SoftFloat32_16.FPConvert);
|
||||
|
||||
Operand res = context.Call(dlg, ne);
|
||||
Operand res = context.Call(typeof(SoftFloat32_16).GetMethod(nameof(SoftFloat32_16.FPConvert)), ne);
|
||||
|
||||
res = context.ZeroExtend16(OperandType.I64, res);
|
||||
|
||||
|
@ -73,9 +72,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
Operand ne = EmitVectorExtractZx(context, op.Rn, 0, 1);
|
||||
|
||||
Delegate dlg = new _F32_U16(SoftFloat16_32.FPConvert);
|
||||
|
||||
Operand res = context.Call(dlg, ne);
|
||||
Operand res = context.Call(typeof(SoftFloat16_32).GetMethod(nameof(SoftFloat16_32.FPConvert)), ne);
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
|
||||
}
|
||||
|
@ -161,9 +158,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
Operand ne = EmitVectorExtractZx(context, op.Rn, part + index, 1);
|
||||
|
||||
Delegate dlg = new _F32_U16(SoftFloat16_32.FPConvert);
|
||||
|
||||
Operand e = context.Call(dlg, ne);
|
||||
Operand e = context.Call(typeof(SoftFloat16_32).GetMethod(nameof(SoftFloat16_32.FPConvert)), ne);
|
||||
|
||||
res = context.VectorInsert(res, e, index);
|
||||
}
|
||||
|
@ -189,7 +184,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitFcvt_s_Gp(context, (op1) => EmitUnaryMathCall(context, MathF.Floor, Math.Floor, op1));
|
||||
EmitFcvt_s_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Floor), op1));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -201,7 +196,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitFcvt_u_Gp(context, (op1) => EmitUnaryMathCall(context, MathF.Floor, Math.Floor, op1));
|
||||
EmitFcvt_u_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Floor), op1));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -247,9 +242,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (sizeF == 0)
|
||||
{
|
||||
Delegate dlg = new _U16_F32(SoftFloat32_16.FPConvert);
|
||||
|
||||
Operand e = context.Call(dlg, ne);
|
||||
Operand e = context.Call(typeof(SoftFloat32_16).GetMethod(nameof(SoftFloat32_16.FPConvert)), ne);
|
||||
|
||||
e = context.ZeroExtend16(OperandType.I64, e);
|
||||
|
||||
|
@ -271,7 +264,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41Fcvts(context, FPRoundingMode.ToNearest, scalar: true);
|
||||
EmitSse41FcvtsOpF(context, FPRoundingMode.ToNearest, scalar: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -283,7 +276,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41Fcvts(context, FPRoundingMode.ToNearest, scalar: false);
|
||||
EmitSse41FcvtsOpF(context, FPRoundingMode.ToNearest, scalar: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -295,7 +288,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41Fcvtu(context, FPRoundingMode.ToNearest, scalar: true);
|
||||
EmitSse41FcvtuOpF(context, FPRoundingMode.ToNearest, scalar: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -307,7 +300,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41Fcvtu(context, FPRoundingMode.ToNearest, scalar: false);
|
||||
EmitSse41FcvtuOpF(context, FPRoundingMode.ToNearest, scalar: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -323,7 +316,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitFcvt_s_Gp(context, (op1) => EmitUnaryMathCall(context, MathF.Ceiling, Math.Ceiling, op1));
|
||||
EmitFcvt_s_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Ceiling), op1));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -335,7 +328,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitFcvt_u_Gp(context, (op1) => EmitUnaryMathCall(context, MathF.Ceiling, Math.Ceiling, op1));
|
||||
EmitFcvt_u_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Ceiling), op1));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -367,7 +360,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41Fcvts(context, FPRoundingMode.TowardsZero, scalar: true);
|
||||
EmitSse41FcvtsOpF(context, FPRoundingMode.TowardsZero, scalar: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -379,7 +372,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41Fcvts(context, FPRoundingMode.TowardsZero, scalar: false);
|
||||
EmitSse41FcvtsOpF(context, FPRoundingMode.TowardsZero, scalar: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -391,7 +384,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41Fcvts(context, FPRoundingMode.TowardsZero, scalar: false);
|
||||
EmitSse41FcvtsOpF(context, FPRoundingMode.TowardsZero, scalar: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -427,7 +420,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41Fcvtu(context, FPRoundingMode.TowardsZero, scalar: true);
|
||||
EmitSse41FcvtuOpF(context, FPRoundingMode.TowardsZero, scalar: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -439,7 +432,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41Fcvtu(context, FPRoundingMode.TowardsZero, scalar: false);
|
||||
EmitSse41FcvtuOpF(context, FPRoundingMode.TowardsZero, scalar: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -451,7 +444,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.UseSse41)
|
||||
{
|
||||
EmitSse41Fcvtu(context, FPRoundingMode.TowardsZero, scalar: false);
|
||||
EmitSse41FcvtuOpF(context, FPRoundingMode.TowardsZero, scalar: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -497,7 +490,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.UseSse2)
|
||||
{
|
||||
EmitSse2Scvtf(context, scalar: true);
|
||||
EmitSse2ScvtfOp(context, scalar: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -517,7 +510,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.UseSse2)
|
||||
{
|
||||
EmitSse2Scvtf(context, scalar: false);
|
||||
EmitSse2ScvtfOp(context, scalar: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -529,7 +522,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.UseSse2)
|
||||
{
|
||||
EmitSse2Scvtf(context, scalar: false);
|
||||
EmitSse2ScvtfOp(context, scalar: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -565,7 +558,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.UseSse2)
|
||||
{
|
||||
EmitSse2Ucvtf(context, scalar: true);
|
||||
EmitSse2UcvtfOp(context, scalar: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -585,7 +578,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.UseSse2)
|
||||
{
|
||||
EmitSse2Ucvtf(context, scalar: false);
|
||||
EmitSse2UcvtfOp(context, scalar: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -597,7 +590,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.UseSse2)
|
||||
{
|
||||
EmitSse2Ucvtf(context, scalar: false);
|
||||
EmitSse2UcvtfOp(context, scalar: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -628,21 +621,21 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (sizeF == 0)
|
||||
{
|
||||
Delegate dlg = signed
|
||||
? (Delegate)new _S32_F32(SoftFallback.SatF32ToS32)
|
||||
: (Delegate)new _U32_F32(SoftFallback.SatF32ToU32);
|
||||
MethodInfo info = signed
|
||||
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS32))
|
||||
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToU32));
|
||||
|
||||
e = context.Call(dlg, e);
|
||||
e = context.Call(info, e);
|
||||
|
||||
e = context.ZeroExtend32(OperandType.I64, e);
|
||||
}
|
||||
else /* if (sizeF == 1) */
|
||||
{
|
||||
Delegate dlg = signed
|
||||
? (Delegate)new _S64_F64(SoftFallback.SatF64ToS64)
|
||||
: (Delegate)new _U64_F64(SoftFallback.SatF64ToU64);
|
||||
MethodInfo info = signed
|
||||
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF64ToS64))
|
||||
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF64ToU64));
|
||||
|
||||
e = context.Call(dlg, e);
|
||||
e = context.Call(info, e);
|
||||
}
|
||||
|
||||
res = EmitVectorInsert(context, res, e, index, sizeI);
|
||||
|
@ -676,21 +669,21 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (sizeF == 0)
|
||||
{
|
||||
Delegate dlg = signed
|
||||
? (Delegate)new _S32_F32(SoftFallback.SatF32ToS32)
|
||||
: (Delegate)new _U32_F32(SoftFallback.SatF32ToU32);
|
||||
MethodInfo info = signed
|
||||
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS32))
|
||||
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToU32));
|
||||
|
||||
e = context.Call(dlg, e);
|
||||
e = context.Call(info, e);
|
||||
|
||||
e = context.ZeroExtend32(OperandType.I64, e);
|
||||
}
|
||||
else /* if (sizeF == 1) */
|
||||
{
|
||||
Delegate dlg = signed
|
||||
? (Delegate)new _S64_F64(SoftFallback.SatF64ToS64)
|
||||
: (Delegate)new _U64_F64(SoftFallback.SatF64ToU64);
|
||||
MethodInfo info = signed
|
||||
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF64ToS64))
|
||||
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF64ToU64));
|
||||
|
||||
e = context.Call(dlg, e);
|
||||
e = context.Call(info, e);
|
||||
}
|
||||
|
||||
res = EmitVectorInsert(context, res, e, index, sizeI);
|
||||
|
@ -809,22 +802,22 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
value = EmitF2iFBitsMul(context, value, fBits);
|
||||
|
||||
MethodInfo info;
|
||||
|
||||
if (context.CurrOp.RegisterSize == RegisterSize.Int32)
|
||||
{
|
||||
Delegate dlg = value.Type == OperandType.FP32
|
||||
? (Delegate)new _S32_F32(SoftFallback.SatF32ToS32)
|
||||
: (Delegate)new _S32_F64(SoftFallback.SatF64ToS32);
|
||||
|
||||
return context.Call(dlg, value);
|
||||
info = value.Type == OperandType.FP32
|
||||
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS32))
|
||||
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF64ToS32));
|
||||
}
|
||||
else
|
||||
{
|
||||
Delegate dlg = value.Type == OperandType.FP32
|
||||
? (Delegate)new _S64_F32(SoftFallback.SatF32ToS64)
|
||||
: (Delegate)new _S64_F64(SoftFallback.SatF64ToS64);
|
||||
|
||||
return context.Call(dlg, value);
|
||||
info = value.Type == OperandType.FP32
|
||||
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS64))
|
||||
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF64ToS64));
|
||||
}
|
||||
|
||||
return context.Call(info, value);
|
||||
}
|
||||
|
||||
private static Operand EmitScalarFcvtu(ArmEmitterContext context, Operand value, int fBits)
|
||||
|
@ -833,22 +826,22 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
value = EmitF2iFBitsMul(context, value, fBits);
|
||||
|
||||
MethodInfo info;
|
||||
|
||||
if (context.CurrOp.RegisterSize == RegisterSize.Int32)
|
||||
{
|
||||
Delegate dlg = value.Type == OperandType.FP32
|
||||
? (Delegate)new _U32_F32(SoftFallback.SatF32ToU32)
|
||||
: (Delegate)new _U32_F64(SoftFallback.SatF64ToU32);
|
||||
|
||||
return context.Call(dlg, value);
|
||||
info = value.Type == OperandType.FP32
|
||||
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToU32))
|
||||
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF64ToU32));
|
||||
}
|
||||
else
|
||||
{
|
||||
Delegate dlg = value.Type == OperandType.FP32
|
||||
? (Delegate)new _U64_F32(SoftFallback.SatF32ToU64)
|
||||
: (Delegate)new _U64_F64(SoftFallback.SatF64ToU64);
|
||||
|
||||
return context.Call(dlg, value);
|
||||
info = value.Type == OperandType.FP32
|
||||
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToU64))
|
||||
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF64ToU64));
|
||||
}
|
||||
|
||||
return context.Call(info, value);
|
||||
}
|
||||
|
||||
private static Operand EmitF2iFBitsMul(ArmEmitterContext context, Operand value, int fBits)
|
||||
|
@ -925,7 +918,7 @@ namespace ARMeilleure.Instructions
|
|||
return res;
|
||||
}
|
||||
|
||||
private static void EmitSse2Scvtf(ArmEmitterContext context, bool scalar)
|
||||
private static void EmitSse2ScvtfOp(ArmEmitterContext context, bool scalar)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
|
@ -990,7 +983,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
}
|
||||
|
||||
private static void EmitSse2Ucvtf(ArmEmitterContext context, bool scalar)
|
||||
private static void EmitSse2UcvtfOp(ArmEmitterContext context, bool scalar)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
|
@ -1079,7 +1072,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
}
|
||||
|
||||
private static void EmitSse41Fcvts(ArmEmitterContext context, FPRoundingMode roundMode, bool scalar)
|
||||
private static void EmitSse41FcvtsOpF(ArmEmitterContext context, FPRoundingMode roundMode, bool scalar)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
|
@ -1170,7 +1163,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
}
|
||||
|
||||
private static void EmitSse41Fcvtu(ArmEmitterContext context, FPRoundingMode roundMode, bool scalar)
|
||||
private static void EmitSse41FcvtuOpF(ArmEmitterContext context, FPRoundingMode roundMode, bool scalar)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ using ARMeilleure.State;
|
|||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
|
@ -20,7 +21,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
// Move the low bit to the top.
|
||||
return ((vd & 0x1) << 4) | (vd >> 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Move the high bit to the bottom.
|
||||
|
@ -30,29 +31,22 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
private static Operand EmitSaturateFloatToInt(ArmEmitterContext context, Operand op1, bool unsigned)
|
||||
{
|
||||
MethodInfo info;
|
||||
|
||||
if (op1.Type == OperandType.FP64)
|
||||
{
|
||||
if (unsigned)
|
||||
{
|
||||
return context.Call(new _U32_F64(SoftFallback.SatF64ToU32), op1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return context.Call(new _S32_F64(SoftFallback.SatF64ToS32), op1);
|
||||
}
|
||||
|
||||
info = unsigned
|
||||
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF64ToU32))
|
||||
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF64ToS32));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (unsigned)
|
||||
{
|
||||
return context.Call(new _U32_F32(SoftFallback.SatF32ToU32), op1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return context.Call(new _S32_F32(SoftFallback.SatF32ToS32), op1);
|
||||
}
|
||||
info = unsigned
|
||||
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToU32))
|
||||
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS32));
|
||||
}
|
||||
|
||||
return context.Call(info, op1);
|
||||
}
|
||||
|
||||
public static void Vcvt_V(ArmEmitterContext context)
|
||||
|
@ -96,7 +90,7 @@ namespace ARMeilleure.Instructions
|
|||
res2 = context.AddIntrinsic(Intrinsic.X86Cvtdq2ps, res2);
|
||||
|
||||
return context.AddIntrinsic(Intrinsic.X86Addps, res, res2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return context.AddIntrinsic(Intrinsic.X86Cvtdq2ps, n);
|
||||
|
@ -114,9 +108,7 @@ namespace ARMeilleure.Instructions
|
|||
EmitVectorUnaryOpSx32(context, (op1) => EmitFPConvert(context, op1, floatSize, true));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void Vcvt_FD(ArmEmitterContext context)
|
||||
|
@ -173,29 +165,22 @@ namespace ARMeilleure.Instructions
|
|||
// TODO: Fast Path.
|
||||
if (roundWithFpscr)
|
||||
{
|
||||
MethodInfo info;
|
||||
|
||||
if (floatSize == OperandType.FP64)
|
||||
{
|
||||
if (unsigned)
|
||||
{
|
||||
asInteger = context.Call(new _U32_F64(SoftFallback.DoubleToUInt32), toConvert);
|
||||
}
|
||||
else
|
||||
{
|
||||
asInteger = context.Call(new _S32_F64(SoftFallback.DoubleToInt32), toConvert);
|
||||
}
|
||||
|
||||
info = unsigned
|
||||
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.DoubleToUInt32))
|
||||
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.DoubleToInt32));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (unsigned)
|
||||
{
|
||||
asInteger = context.Call(new _U32_F32(SoftFallback.FloatToUInt32), toConvert);
|
||||
}
|
||||
else
|
||||
{
|
||||
asInteger = context.Call(new _S32_F32(SoftFallback.FloatToInt32), toConvert);
|
||||
}
|
||||
info = unsigned
|
||||
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.FloatToUInt32))
|
||||
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.FloatToInt32));
|
||||
}
|
||||
|
||||
asInteger = context.Call(info, toConvert);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -205,7 +190,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
InsertScalar(context, op.Vd, asInteger);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool unsigned = op.Opc == 0;
|
||||
|
@ -218,22 +203,17 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
}
|
||||
|
||||
public static Operand EmitRoundMathCall(ArmEmitterContext context, MidpointRounding roundMode, Operand n)
|
||||
private static Operand EmitRoundMathCall(ArmEmitterContext context, MidpointRounding roundMode, Operand n)
|
||||
{
|
||||
IOpCode32Simd op = (IOpCode32Simd)context.CurrOp;
|
||||
|
||||
Delegate dlg;
|
||||
string name = nameof(Math.Round);
|
||||
|
||||
if ((op.Size & 1) == 0)
|
||||
{
|
||||
dlg = new _F32_F32_MidpointRounding(MathF.Round);
|
||||
}
|
||||
else /* if ((op.Size & 1) == 1) */
|
||||
{
|
||||
dlg = new _F64_F64_MidpointRounding(Math.Round);
|
||||
}
|
||||
MethodInfo info = (op.Size & 1) == 0
|
||||
? typeof(MathF).GetMethod(name, new Type[] { typeof(float), typeof(MidpointRounding) })
|
||||
: typeof(Math). GetMethod(name, new Type[] { typeof(double), typeof(MidpointRounding) });
|
||||
|
||||
return context.Call(dlg, n, Const((int)roundMode));
|
||||
return context.Call(info, n, Const((int)roundMode));
|
||||
}
|
||||
|
||||
private static FPRoundingMode RMToRoundMode(int rm)
|
||||
|
@ -282,10 +262,10 @@ namespace ARMeilleure.Instructions
|
|||
toConvert = EmitRoundMathCall(context, MidpointRounding.ToEven, toConvert);
|
||||
break;
|
||||
case 0b10: // Towards positive infinity
|
||||
toConvert = EmitUnaryMathCall(context, MathF.Ceiling, Math.Ceiling, toConvert);
|
||||
toConvert = EmitUnaryMathCall(context, nameof(Math.Ceiling), toConvert);
|
||||
break;
|
||||
case 0b11: // Towards negative infinity
|
||||
toConvert = EmitUnaryMathCall(context, MathF.Floor, Math.Floor, toConvert);
|
||||
toConvert = EmitUnaryMathCall(context, nameof(Math.Floor), toConvert);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -316,7 +296,7 @@ namespace ARMeilleure.Instructions
|
|||
return context.AddIntrinsic(inst, m, Const(X86GetRoundControl(roundMode)));
|
||||
});
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
Operand toConvert = ExtractScalar(context, floatSize, op.Vm);
|
||||
|
||||
|
@ -329,10 +309,10 @@ namespace ARMeilleure.Instructions
|
|||
toConvert = EmitRoundMathCall(context, MidpointRounding.ToEven, toConvert);
|
||||
break;
|
||||
case 0b10: // Towards positive infinity
|
||||
toConvert = EmitUnaryMathCall(context, MathF.Ceiling, Math.Ceiling, toConvert);
|
||||
toConvert = EmitUnaryMathCall(context, nameof(Math.Ceiling), toConvert);
|
||||
break;
|
||||
case 0b11: // Towards negative infinity
|
||||
toConvert = EmitUnaryMathCall(context, MathF.Floor, Math.Floor, toConvert);
|
||||
toConvert = EmitUnaryMathCall(context, nameof(Math.Floor), toConvert);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -351,10 +331,10 @@ namespace ARMeilleure.Instructions
|
|||
Intrinsic inst = (op.Size & 1) == 0 ? Intrinsic.X86Roundss : Intrinsic.X86Roundsd;
|
||||
return context.AddIntrinsic(inst, m, Const(X86GetRoundControl(FPRoundingMode.TowardsZero)));
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitScalarUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, MathF.Truncate, Math.Truncate, op1));
|
||||
EmitScalarUnaryOpF32(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Truncate), op1));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -423,7 +403,7 @@ namespace ARMeilleure.Instructions
|
|||
if (signed)
|
||||
{
|
||||
dRes = context.BitwiseExclusiveOr(nIntOrLong, nInt);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dRes = context.BitwiseExclusiveOr(nIntOrLong2, nInt);
|
||||
|
@ -527,7 +507,7 @@ namespace ARMeilleure.Instructions
|
|||
if (signed)
|
||||
{
|
||||
return context.AddIntrinsic(Intrinsic.X86Pxor, nInt, nRes);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Operand dRes = context.AddIntrinsic(Intrinsic.X86Pxor, nInt2, nRes);
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
Operand res = context.Call(new _V128_V128_U32_V128(SoftFallback.HashChoose), d, ne, m);
|
||||
Operand res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashChoose)), d, ne, m);
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand ne = context.VectorExtract(OperandType.I32, GetVec(op.Rn), 0);
|
||||
|
||||
Operand res = context.Call(new _U32_U32(SoftFallback.FixedRotate), ne);
|
||||
Operand res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.FixedRotate)), ne);
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.VectorCreateScalar(res));
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
Operand res = context.Call(new _V128_V128_U32_V128(SoftFallback.HashMajority), d, ne, m);
|
||||
Operand res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashMajority)), d, ne, m);
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
Operand res = context.Call(new _V128_V128_U32_V128(SoftFallback.HashParity), d, ne, m);
|
||||
Operand res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashParity)), d, ne, m);
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
Operand res = context.Call(new _V128_V128_V128_V128(SoftFallback.Sha1SchedulePart1), d, n, m);
|
||||
Operand res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha1SchedulePart1)), d, n, m);
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand d = GetVec(op.Rd);
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
Operand res = context.Call(new _V128_V128_V128(SoftFallback.Sha1SchedulePart2), d, n);
|
||||
Operand res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha1SchedulePart2)), d, n);
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
Operand res = context.Call(new _V128_V128_V128_V128(SoftFallback.HashLower), d, n, m);
|
||||
Operand res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashLower)), d, n, m);
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
|
@ -113,7 +113,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
Operand res = context.Call(new _V128_V128_V128_V128(SoftFallback.HashUpper), d, n, m);
|
||||
Operand res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.HashUpper)), d, n, m);
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand d = GetVec(op.Rd);
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
Operand res = context.Call(new _V128_V128_V128(SoftFallback.Sha256SchedulePart1), d, n);
|
||||
Operand res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart1)), d, n);
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
|
@ -138,7 +138,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand n = GetVec(op.Rn);
|
||||
Operand m = GetVec(op.Rm);
|
||||
|
||||
Operand res = context.Call(new _V128_V128_V128_V128(SoftFallback.Sha256SchedulePart2), d, n, m);
|
||||
Operand res = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.Sha256SchedulePart2)), d, n, m);
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ using ARMeilleure.State;
|
|||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
|
||||
|
@ -310,68 +311,39 @@ namespace ARMeilleure.Instructions
|
|||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
|
||||
public static Operand EmitUnaryMathCall(ArmEmitterContext context, _F32_F32 f32, _F64_F64 f64, Operand n)
|
||||
public static Operand EmitUnaryMathCall(ArmEmitterContext context, string name, Operand n)
|
||||
{
|
||||
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
|
||||
|
||||
return (op.Size & 1) == 0 ? context.Call(f32, n) : context.Call(f64, n);
|
||||
MethodInfo info = (op.Size & 1) == 0
|
||||
? typeof(MathF).GetMethod(name, new Type[] { typeof(float) })
|
||||
: typeof(Math). GetMethod(name, new Type[] { typeof(double) });
|
||||
|
||||
return context.Call(info, n);
|
||||
}
|
||||
|
||||
public static Operand EmitRoundMathCall(ArmEmitterContext context, MidpointRounding roundMode, Operand n)
|
||||
{
|
||||
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
|
||||
|
||||
Delegate dlg;
|
||||
string name = nameof(Math.Round);
|
||||
|
||||
if ((op.Size & 1) == 0)
|
||||
{
|
||||
dlg = new _F32_F32_MidpointRounding(MathF.Round);
|
||||
}
|
||||
else /* if ((op.Size & 1) == 1) */
|
||||
{
|
||||
dlg = new _F64_F64_MidpointRounding(Math.Round);
|
||||
}
|
||||
MethodInfo info = (op.Size & 1) == 0
|
||||
? typeof(MathF).GetMethod(name, new Type[] { typeof(float), typeof(MidpointRounding) })
|
||||
: typeof(Math). GetMethod(name, new Type[] { typeof(double), typeof(MidpointRounding) });
|
||||
|
||||
return context.Call(dlg, n, Const((int)roundMode));
|
||||
return context.Call(info, n, Const((int)roundMode));
|
||||
}
|
||||
|
||||
public static Operand EmitSoftFloatCall(
|
||||
ArmEmitterContext context,
|
||||
_F32_F32 f32,
|
||||
_F64_F64 f64,
|
||||
params Operand[] callArgs)
|
||||
public static Operand EmitSoftFloatCall(ArmEmitterContext context, string name, params Operand[] callArgs)
|
||||
{
|
||||
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
|
||||
|
||||
Delegate dlg = (op.Size & 1) == 0 ? (Delegate)f32 : (Delegate)f64;
|
||||
MethodInfo info = (op.Size & 1) == 0
|
||||
? typeof(SoftFloat32).GetMethod(name)
|
||||
: typeof(SoftFloat64).GetMethod(name);
|
||||
|
||||
return context.Call(dlg, callArgs);
|
||||
}
|
||||
|
||||
public static Operand EmitSoftFloatCall(
|
||||
ArmEmitterContext context,
|
||||
_F32_F32_F32 f32,
|
||||
_F64_F64_F64 f64,
|
||||
params Operand[] callArgs)
|
||||
{
|
||||
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
|
||||
|
||||
Delegate dlg = (op.Size & 1) == 0 ? (Delegate)f32 : (Delegate)f64;
|
||||
|
||||
return context.Call(dlg, callArgs);
|
||||
}
|
||||
|
||||
public static Operand EmitSoftFloatCall(
|
||||
ArmEmitterContext context,
|
||||
_F32_F32_F32_F32 f32,
|
||||
_F64_F64_F64_F64 f64,
|
||||
params Operand[] callArgs)
|
||||
{
|
||||
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
|
||||
|
||||
Delegate dlg = (op.Size & 1) == 0 ? (Delegate)f32 : (Delegate)f64;
|
||||
|
||||
return context.Call(dlg, callArgs);
|
||||
return context.Call(info, callArgs);
|
||||
}
|
||||
|
||||
public static void EmitScalarBinaryOpByElemF(ArmEmitterContext context, Func2I emit)
|
||||
|
@ -1425,22 +1397,22 @@ namespace ARMeilleure.Instructions
|
|||
throw new ArgumentOutOfRangeException(nameof(sizeDst));
|
||||
}
|
||||
|
||||
Delegate dlg;
|
||||
MethodInfo info;
|
||||
|
||||
if (signedSrc)
|
||||
{
|
||||
dlg = signedDst
|
||||
? (Delegate)new _S64_S64_S32(SoftFallback.SignedSrcSignedDstSatQ)
|
||||
: (Delegate)new _U64_S64_S32(SoftFallback.SignedSrcUnsignedDstSatQ);
|
||||
info = signedDst
|
||||
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedSrcSignedDstSatQ))
|
||||
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedSrcUnsignedDstSatQ));
|
||||
}
|
||||
else
|
||||
{
|
||||
dlg = signedDst
|
||||
? (Delegate)new _S64_U64_S32(SoftFallback.UnsignedSrcSignedDstSatQ)
|
||||
: (Delegate)new _U64_U64_S32(SoftFallback.UnsignedSrcUnsignedDstSatQ);
|
||||
info = signedDst
|
||||
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedSrcSignedDstSatQ))
|
||||
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedSrcUnsignedDstSatQ));
|
||||
}
|
||||
|
||||
return context.Call(dlg, op, Const(sizeDst));
|
||||
return context.Call(info, op, Const(sizeDst));
|
||||
}
|
||||
|
||||
// TSrc (64bit) == TDst (64bit); signed.
|
||||
|
@ -1448,7 +1420,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
Debug.Assert(((OpCodeSimd)context.CurrOp).Size == 3, "Invalid element size.");
|
||||
|
||||
return context.Call(new _S64_S64(SoftFallback.UnarySignedSatQAbsOrNeg), op);
|
||||
return context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnarySignedSatQAbsOrNeg)), op);
|
||||
}
|
||||
|
||||
// TSrcs (64bit) == TDst (64bit); signed, unsigned.
|
||||
|
@ -1456,11 +1428,11 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
Debug.Assert(((OpCodeSimd)context.CurrOp).Size == 3, "Invalid element size.");
|
||||
|
||||
Delegate dlg = signed
|
||||
? (Delegate)new _S64_S64_S64(SoftFallback.BinarySignedSatQAdd)
|
||||
: (Delegate)new _U64_U64_U64(SoftFallback.BinaryUnsignedSatQAdd);
|
||||
MethodInfo info = signed
|
||||
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinarySignedSatQAdd))
|
||||
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinaryUnsignedSatQAdd));
|
||||
|
||||
return context.Call(dlg, op1, op2);
|
||||
return context.Call(info, op1, op2);
|
||||
}
|
||||
|
||||
// TSrcs (64bit) == TDst (64bit); signed, unsigned.
|
||||
|
@ -1468,11 +1440,11 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
Debug.Assert(((OpCodeSimd)context.CurrOp).Size == 3, "Invalid element size.");
|
||||
|
||||
Delegate dlg = signed
|
||||
? (Delegate)new _S64_S64_S64(SoftFallback.BinarySignedSatQSub)
|
||||
: (Delegate)new _U64_U64_U64(SoftFallback.BinaryUnsignedSatQSub);
|
||||
MethodInfo info = signed
|
||||
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinarySignedSatQSub))
|
||||
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinaryUnsignedSatQSub));
|
||||
|
||||
return context.Call(dlg, op1, op2);
|
||||
return context.Call(info, op1, op2);
|
||||
}
|
||||
|
||||
// TSrcs (64bit) == TDst (64bit); signed, unsigned.
|
||||
|
@ -1480,11 +1452,11 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
Debug.Assert(((OpCodeSimd)context.CurrOp).Size == 3, "Invalid element size.");
|
||||
|
||||
Delegate dlg = signed
|
||||
? (Delegate)new _S64_U64_S64(SoftFallback.BinarySignedSatQAcc)
|
||||
: (Delegate)new _U64_S64_U64(SoftFallback.BinaryUnsignedSatQAcc);
|
||||
MethodInfo info = signed
|
||||
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinarySignedSatQAcc))
|
||||
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.BinaryUnsignedSatQAcc));
|
||||
|
||||
return context.Call(dlg, op1, op2);
|
||||
return context.Call(info, op1, op2);
|
||||
}
|
||||
|
||||
public static Operand EmitFloatAbs(ArmEmitterContext context, Operand value, bool single, bool vector)
|
||||
|
@ -1493,7 +1465,7 @@ namespace ARMeilleure.Instructions
|
|||
if (single)
|
||||
{
|
||||
mask = vector ? X86GetAllElements(context, -0f) : X86GetScalar(context, -0f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mask = vector ? X86GetAllElements(context, -0d) : X86GetScalar(context, -0d);
|
||||
|
|
|
@ -3,6 +3,8 @@ using ARMeilleure.IntermediateRepresentation;
|
|||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
|
||||
|
@ -39,7 +41,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
// From dreg.
|
||||
return context.VectorExtract(type, GetVecA32(reg >> 1), reg & 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// From sreg.
|
||||
|
@ -575,7 +577,7 @@ namespace ARMeilleure.Instructions
|
|||
if (targetSide == 1)
|
||||
{
|
||||
return context.AddIntrinsic(Intrinsic.X86Movlhps, input, input); // Low to high.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return context.AddIntrinsic(Intrinsic.X86Movhlps, input, input); // High to low.
|
||||
|
@ -592,7 +594,7 @@ namespace ARMeilleure.Instructions
|
|||
if (targetSide == 1)
|
||||
{
|
||||
return context.AddIntrinsic(Intrinsic.X86Shufpd, target, value, Const(shuffleMask));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return context.AddIntrinsic(Intrinsic.X86Shufpd, value, target, Const(shuffleMask));
|
||||
|
@ -622,7 +624,7 @@ namespace ARMeilleure.Instructions
|
|||
if (Optimizations.UseSse41)
|
||||
{
|
||||
return context.AddIntrinsic(Intrinsic.X86Insertps, target, value, Const(index << 4));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
target = EmitSwapScalar(context, target, index, doubleWidth); // Swap value to replace into element 0.
|
||||
|
@ -642,7 +644,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
int shuffleMask = 1; // Swap top and bottom. (b0 = 1, b1 = 0)
|
||||
return context.AddIntrinsic(Intrinsic.X86Shufpd, target, target, Const(shuffleMask));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int shuffleMask = (3 << 6) | (2 << 4) | (1 << 2) | index; // Swap index and 0. (others remain)
|
||||
|
@ -1000,52 +1002,18 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
// Generic Functions
|
||||
|
||||
public static Operand EmitSoftFloatCallDefaultFpscr(
|
||||
ArmEmitterContext context,
|
||||
_F32_F32_Bool f32,
|
||||
_F64_F64_Bool f64,
|
||||
params Operand[] callArgs)
|
||||
public static Operand EmitSoftFloatCallDefaultFpscr(ArmEmitterContext context, string name, params Operand[] callArgs)
|
||||
{
|
||||
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
|
||||
|
||||
Delegate dlg = (op.Size & 1) == 0 ? (Delegate)f32 : (Delegate)f64;
|
||||
MethodInfo info = (op.Size & 1) == 0
|
||||
? typeof(SoftFloat32).GetMethod(name)
|
||||
: typeof(SoftFloat64).GetMethod(name);
|
||||
|
||||
Array.Resize(ref callArgs, callArgs.Length + 1);
|
||||
callArgs[callArgs.Length - 1] = Const(1);
|
||||
|
||||
return context.Call(dlg, callArgs);
|
||||
}
|
||||
|
||||
public static Operand EmitSoftFloatCallDefaultFpscr(
|
||||
ArmEmitterContext context,
|
||||
_F32_F32_F32_Bool f32,
|
||||
_F64_F64_F64_Bool f64,
|
||||
params Operand[] callArgs)
|
||||
{
|
||||
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
|
||||
|
||||
Delegate dlg = (op.Size & 1) == 0 ? (Delegate)f32 : (Delegate)f64;
|
||||
|
||||
Array.Resize(ref callArgs, callArgs.Length + 1);
|
||||
callArgs[callArgs.Length - 1] = Const(1);
|
||||
|
||||
return context.Call(dlg, callArgs);
|
||||
}
|
||||
|
||||
public static Operand EmitSoftFloatCallDefaultFpscr(
|
||||
ArmEmitterContext context,
|
||||
_F32_F32_F32_F32_Bool f32,
|
||||
_F64_F64_F64_F64_Bool f64,
|
||||
params Operand[] callArgs)
|
||||
{
|
||||
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
|
||||
|
||||
Delegate dlg = (op.Size & 1) == 0 ? (Delegate)f32 : (Delegate)f64;
|
||||
|
||||
Array.Resize(ref callArgs, callArgs.Length + 1);
|
||||
callArgs[callArgs.Length - 1] = Const(1);
|
||||
|
||||
return context.Call(dlg, callArgs);
|
||||
return context.Call(info, callArgs);
|
||||
}
|
||||
|
||||
public static Operand EmitVectorExtractSx32(ArmEmitterContext context, int reg, int index, int size)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
using ARMeilleure.Decoders;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
|
@ -284,13 +284,26 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeSimdFmov op = (OpCodeSimdFmov)context.CurrOp;
|
||||
|
||||
if (op.Size == 0)
|
||||
if (Optimizations.UseSse2)
|
||||
{
|
||||
context.Copy(GetVec(op.Rd), X86GetScalar(context, (int)op.Immediate));
|
||||
if (op.Size == 0)
|
||||
{
|
||||
context.Copy(GetVec(op.Rd), X86GetScalar(context, (int)op.Immediate));
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Copy(GetVec(op.Rd), X86GetScalar(context, op.Immediate));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Copy(GetVec(op.Rd), X86GetScalar(context, op.Immediate));
|
||||
Operand e = Const(op.Immediate);
|
||||
|
||||
Operand res = context.VectorZero();
|
||||
|
||||
res = EmitVectorInsert(context, res, e, 0, op.Size + 2);
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -350,7 +363,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.UseSse2)
|
||||
{
|
||||
EmitSse2MoviMvni(context, not: false);
|
||||
EmitSse2VectorMoviMvniOp(context, not: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -362,7 +375,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (Optimizations.UseSse2)
|
||||
{
|
||||
EmitSse2MoviMvni(context, not: true);
|
||||
EmitSse2VectorMoviMvniOp(context, not: true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -476,7 +489,7 @@ namespace ARMeilleure.Instructions
|
|||
EmitVectorZip(context, part: 1);
|
||||
}
|
||||
|
||||
private static void EmitSse2MoviMvni(ArmEmitterContext context, bool not)
|
||||
private static void EmitSse2VectorMoviMvniOp(ArmEmitterContext context, bool not)
|
||||
{
|
||||
OpCodeSimdImm op = (OpCodeSimdImm)context.CurrOp;
|
||||
|
||||
|
@ -593,32 +606,30 @@ namespace ARMeilleure.Instructions
|
|||
args.Add(GetVec((op.Rn + index) & 0x1F));
|
||||
}
|
||||
|
||||
Delegate dlg = null;
|
||||
MethodInfo info = null;
|
||||
|
||||
switch (op.Size)
|
||||
if (isTbl)
|
||||
{
|
||||
case 1: dlg = isTbl
|
||||
? (Delegate)new _V128_V128_S32_V128 (SoftFallback.Tbl1)
|
||||
: (Delegate)new _V128_V128_V128_S32_V128(SoftFallback.Tbx1);
|
||||
break;
|
||||
|
||||
case 2: dlg = isTbl
|
||||
? (Delegate)new _V128_V128_S32_V128_V128 (SoftFallback.Tbl2)
|
||||
: (Delegate)new _V128_V128_V128_S32_V128_V128(SoftFallback.Tbx2);
|
||||
break;
|
||||
|
||||
case 3: dlg = isTbl
|
||||
? (Delegate)new _V128_V128_S32_V128_V128_V128 (SoftFallback.Tbl3)
|
||||
: (Delegate)new _V128_V128_V128_S32_V128_V128_V128(SoftFallback.Tbx3);
|
||||
break;
|
||||
|
||||
case 4: dlg = isTbl
|
||||
? (Delegate)new _V128_V128_S32_V128_V128_V128_V128 (SoftFallback.Tbl4)
|
||||
: (Delegate)new _V128_V128_V128_S32_V128_V128_V128_V128(SoftFallback.Tbx4);
|
||||
break;
|
||||
switch (op.Size)
|
||||
{
|
||||
case 1: info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl1)); break;
|
||||
case 2: info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl2)); break;
|
||||
case 3: info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl3)); break;
|
||||
case 4: info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl4)); break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (op.Size)
|
||||
{
|
||||
case 1: info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx1)); break;
|
||||
case 2: info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx2)); break;
|
||||
case 3: info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx3)); break;
|
||||
case 4: info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx4)); break;
|
||||
}
|
||||
}
|
||||
|
||||
context.Copy(d, context.Call(dlg, args.ToArray()));
|
||||
context.Copy(d, context.Call(info, args.ToArray()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ using ARMeilleure.IntermediateRepresentation;
|
|||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
|
@ -198,7 +199,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand ne = EmitVectorExtractSx(context, op.Rn, index, op.Size);
|
||||
Operand me = EmitVectorExtractSx(context, op.Rm, index, op.Size);
|
||||
|
||||
Operand e = context.Call(new _S64_S64_S64_Bool_S32(SoftFallback.SignedShlRegSatQ), ne, me, Const(1), Const(op.Size));
|
||||
Operand e = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShlRegSatQ)), ne, me, Const(1), Const(op.Size));
|
||||
|
||||
res = EmitVectorInsert(context, res, e, index, op.Size);
|
||||
}
|
||||
|
@ -239,7 +240,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand ne = EmitVectorExtractSx(context, op.Rn, index, op.Size);
|
||||
Operand me = EmitVectorExtractSx(context, op.Rm, index, op.Size);
|
||||
|
||||
Operand e = context.Call(new _S64_S64_S64_Bool_S32(SoftFallback.SignedShlRegSatQ), ne, me, Const(0), Const(op.Size));
|
||||
Operand e = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShlRegSatQ)), ne, me, Const(0), Const(op.Size));
|
||||
|
||||
res = EmitVectorInsert(context, res, e, index, op.Size);
|
||||
}
|
||||
|
@ -290,7 +291,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand ne = EmitVectorExtractSx(context, op.Rn, index, op.Size);
|
||||
Operand me = EmitVectorExtractSx(context, op.Rm, index, op.Size);
|
||||
|
||||
Operand e = context.Call(new _S64_S64_S64_Bool_S32(SoftFallback.SignedShlReg), ne, me, Const(1), Const(op.Size));
|
||||
Operand e = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShlReg)), ne, me, Const(1), Const(op.Size));
|
||||
|
||||
res = EmitVectorInsert(context, res, e, index, op.Size);
|
||||
}
|
||||
|
@ -403,7 +404,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand ne = EmitVectorExtractSx(context, op.Rn, index, op.Size);
|
||||
Operand me = EmitVectorExtractSx(context, op.Rm, index, op.Size);
|
||||
|
||||
Operand e = context.Call(new _S64_S64_S64_Bool_S32(SoftFallback.SignedShlReg), ne, me, Const(0), Const(op.Size));
|
||||
Operand e = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShlReg)), ne, me, Const(0), Const(op.Size));
|
||||
|
||||
res = EmitVectorInsert(context, res, e, index, op.Size);
|
||||
}
|
||||
|
@ -527,7 +528,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand ne = EmitVectorExtractZx(context, op.Rn, index, op.Size);
|
||||
Operand me = EmitVectorExtractZx(context, op.Rm, index, op.Size);
|
||||
|
||||
Operand e = context.Call(new _U64_U64_U64_Bool_S32(SoftFallback.UnsignedShlRegSatQ), ne, me, Const(1), Const(op.Size));
|
||||
Operand e = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShlRegSatQ)), ne, me, Const(1), Const(op.Size));
|
||||
|
||||
res = EmitVectorInsert(context, res, e, index, op.Size);
|
||||
}
|
||||
|
@ -558,7 +559,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand ne = EmitVectorExtractZx(context, op.Rn, index, op.Size);
|
||||
Operand me = EmitVectorExtractZx(context, op.Rm, index, op.Size);
|
||||
|
||||
Operand e = context.Call(new _U64_U64_U64_Bool_S32(SoftFallback.UnsignedShlRegSatQ), ne, me, Const(0), Const(op.Size));
|
||||
Operand e = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShlRegSatQ)), ne, me, Const(0), Const(op.Size));
|
||||
|
||||
res = EmitVectorInsert(context, res, e, index, op.Size);
|
||||
}
|
||||
|
@ -589,7 +590,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand ne = EmitVectorExtractZx(context, op.Rn, index, op.Size);
|
||||
Operand me = EmitVectorExtractZx(context, op.Rm, index, op.Size);
|
||||
|
||||
Operand e = context.Call(new _U64_U64_U64_Bool_S32(SoftFallback.UnsignedShlReg), ne, me, Const(1), Const(op.Size));
|
||||
Operand e = context.Call(typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShlReg)), ne, me, Const(1), Const(op.Size));
|
||||
|
||||
res = EmitVectorInsert(context, res, e, index, op.Size);
|
||||
}
|
||||
|
@ -1026,11 +1027,11 @@ namespace ARMeilleure.Instructions
|
|||
long roundConst,
|
||||
int shift)
|
||||
{
|
||||
Delegate dlg = signed
|
||||
? (Delegate)new _S64_S64_S64_S32(SoftFallback.SignedShrImm64)
|
||||
: (Delegate)new _U64_U64_S64_S32(SoftFallback.UnsignedShrImm64);
|
||||
MethodInfo info = signed
|
||||
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShrImm64))
|
||||
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShrImm64));
|
||||
|
||||
return context.Call(dlg, value, Const(roundConst), Const(shift));
|
||||
return context.Call(info, value, Const(roundConst), Const(shift));
|
||||
}
|
||||
|
||||
private static void EmitVectorShImmWidenBinarySx(ArmEmitterContext context, Func2I emit, int imm)
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
using ARMeilleure.Decoders;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper32;
|
||||
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
|
||||
|
@ -244,11 +244,11 @@ namespace ARMeilleure.Instructions
|
|||
long roundConst,
|
||||
int shift)
|
||||
{
|
||||
Delegate dlg = signed
|
||||
? (Delegate)new _S64_S64_S64_S32(SoftFallback.SignedShrImm64)
|
||||
: (Delegate)new _U64_U64_S64_S32(SoftFallback.UnsignedShrImm64);
|
||||
MethodInfo info = signed
|
||||
? typeof(SoftFallback).GetMethod(nameof(SoftFallback.SignedShrImm64))
|
||||
: typeof(SoftFallback).GetMethod(nameof(SoftFallback.UnsignedShrImm64));
|
||||
|
||||
return context.Call(dlg, value, Const(roundConst), Const(shift));
|
||||
return context.Call(info, value, Const(roundConst), Const(shift));
|
||||
}
|
||||
|
||||
private static Operand EmitSatQ(ArmEmitterContext context, Operand value, int eSize, bool signed)
|
||||
|
|
|
@ -3,6 +3,7 @@ using ARMeilleure.IntermediateRepresentation;
|
|||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
|
||||
|
@ -27,44 +28,44 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
||||
|
||||
Delegate dlg;
|
||||
MethodInfo info;
|
||||
|
||||
switch (GetPackedId(op))
|
||||
{
|
||||
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: 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;
|
||||
case 0b11_011_1101_0000_011: dlg = new _U64(NativeInterface.GetTpidr); break;
|
||||
case 0b11_011_1110_0000_000: dlg = new _U64(NativeInterface.GetCntfrqEl0); break;
|
||||
case 0b11_011_1110_0000_001: dlg = new _U64(NativeInterface.GetCntpctEl0); break;
|
||||
case 0b11_011_1110_0000_010: dlg = new _U64(NativeInterface.GetCntvctEl0); break;
|
||||
case 0b11_011_0000_0000_001: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCtrEl0)); break;
|
||||
case 0b11_011_0000_0000_111: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetDczidEl0)); break;
|
||||
case 0b11_011_0100_0010_000: EmitGetNzcv(context); return;
|
||||
case 0b11_011_0100_0100_000: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpcr)); break;
|
||||
case 0b11_011_0100_0100_001: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpsr)); break;
|
||||
case 0b11_011_1101_0000_010: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrEl0)); break;
|
||||
case 0b11_011_1101_0000_011: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidr)); break;
|
||||
case 0b11_011_1110_0000_000: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntfrqEl0)); break;
|
||||
case 0b11_011_1110_0000_001: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntpctEl0)); break;
|
||||
case 0b11_011_1110_0000_010: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntvctEl0)); break;
|
||||
|
||||
default: throw new NotImplementedException($"Unknown MRS 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
|
||||
}
|
||||
|
||||
SetIntOrZR(context, op.Rt, context.Call(dlg));
|
||||
SetIntOrZR(context, op.Rt, context.Call(info));
|
||||
}
|
||||
|
||||
public static void Msr(ArmEmitterContext context)
|
||||
{
|
||||
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
||||
|
||||
Delegate dlg;
|
||||
MethodInfo info;
|
||||
|
||||
switch (GetPackedId(op))
|
||||
{
|
||||
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;
|
||||
case 0b11_011_0100_0010_000: EmitSetNzcv(context); return;
|
||||
case 0b11_011_0100_0100_000: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpcr)); break;
|
||||
case 0b11_011_0100_0100_001: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpsr)); break;
|
||||
case 0b11_011_1101_0000_010: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl0)); break;
|
||||
|
||||
default: throw new NotImplementedException($"Unknown MSR 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
|
||||
}
|
||||
|
||||
context.Call(dlg, GetIntOrZR(context, op.Rt));
|
||||
context.Call(info, GetIntOrZR(context, op.Rt));
|
||||
}
|
||||
|
||||
public static void Nop(ArmEmitterContext context)
|
||||
|
@ -90,7 +91,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
Operand address = context.Add(t, Const(offset));
|
||||
|
||||
context.Call(new _Void_U64_U64(NativeInterface.WriteUInt64), address, Const(0L));
|
||||
context.Call(typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt64)), address, Const(0L));
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
@ -3,6 +3,7 @@ using ARMeilleure.IntermediateRepresentation;
|
|||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
|
||||
|
@ -18,6 +19,7 @@ namespace ARMeilleure.Instructions
|
|||
if (op.Coproc != 15)
|
||||
{
|
||||
InstEmit.Und(context);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -26,7 +28,8 @@ namespace ARMeilleure.Instructions
|
|||
throw new NotImplementedException($"Unknown MRC Opc1 0x{op.Opc1:X16} at 0x{op.Address:X16}.");
|
||||
}
|
||||
|
||||
Delegate dlg;
|
||||
MethodInfo info;
|
||||
|
||||
switch (op.CRn)
|
||||
{
|
||||
case 13: // Process and Thread Info.
|
||||
|
@ -34,13 +37,16 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
throw new NotImplementedException($"Unknown MRC CRm 0x{op.CRm:X16} at 0x{op.Address:X16}.");
|
||||
}
|
||||
|
||||
switch (op.Opc2)
|
||||
{
|
||||
case 2:
|
||||
dlg = new _Void_U32(NativeInterface.SetTpidrEl032); break;
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetTpidrEl032)); break;
|
||||
|
||||
default:
|
||||
throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X16} at 0x{op.Address:X16}.");
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 7:
|
||||
|
@ -51,18 +57,20 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
case 5: // Data Memory Barrier Register.
|
||||
return; // No-op.
|
||||
|
||||
default:
|
||||
throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X16} at 0x{op.Address:X16}.");
|
||||
}
|
||||
|
||||
default:
|
||||
throw new NotImplementedException($"Unknown MRC CRm 0x{op.CRm:X16} at 0x{op.Address:X16}.");
|
||||
}
|
||||
|
||||
default:
|
||||
default:
|
||||
throw new NotImplementedException($"Unknown MRC 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
|
||||
}
|
||||
|
||||
context.Call(dlg, GetIntA32(context, op.Rt));
|
||||
context.Call(info, GetIntA32(context, op.Rt));
|
||||
}
|
||||
|
||||
public static void Mrc(ArmEmitterContext context)
|
||||
|
@ -72,6 +80,7 @@ namespace ARMeilleure.Instructions
|
|||
if (op.Coproc != 15)
|
||||
{
|
||||
InstEmit.Und(context);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -80,7 +89,8 @@ namespace ARMeilleure.Instructions
|
|||
throw new NotImplementedException($"Unknown MRC Opc1 0x{op.Opc1:X16} at 0x{op.Address:X16}.");
|
||||
}
|
||||
|
||||
Delegate dlg;
|
||||
MethodInfo info;
|
||||
|
||||
switch (op.CRn)
|
||||
{
|
||||
case 13: // Process and Thread Info.
|
||||
|
@ -88,30 +98,35 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
throw new NotImplementedException($"Unknown MRC CRm 0x{op.CRm:X16} at 0x{op.Address:X16}.");
|
||||
}
|
||||
|
||||
switch (op.Opc2)
|
||||
{
|
||||
case 2:
|
||||
dlg = new _U32(NativeInterface.GetTpidrEl032); break;
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidrEl032)); break;
|
||||
|
||||
case 3:
|
||||
dlg = new _U32(NativeInterface.GetTpidr32); break;
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetTpidr32)); break;
|
||||
|
||||
default:
|
||||
throw new NotImplementedException($"Unknown MRC Opc2 0x{op.Opc2:X16} at 0x{op.Address:X16}.");
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
|
||||
default:
|
||||
throw new NotImplementedException($"Unknown MRC 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
|
||||
}
|
||||
|
||||
if (op.Rt == RegisterAlias.Aarch32Pc)
|
||||
{
|
||||
// Special behavior: copy NZCV flags into APSR.
|
||||
EmitSetNzcv(context, context.Call(dlg));
|
||||
|
||||
EmitSetNzcv(context, context.Call(info));
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
SetIntA32(context, op.Rt, context.Call(dlg));
|
||||
SetIntA32(context, op.Rt, context.Call(info));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -122,28 +137,33 @@ namespace ARMeilleure.Instructions
|
|||
if (op.Coproc != 15)
|
||||
{
|
||||
InstEmit.Und(context);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
var opc = op.MrrcOp;
|
||||
int opc = op.MrrcOp;
|
||||
|
||||
MethodInfo info;
|
||||
|
||||
Delegate dlg;
|
||||
switch (op.CRm)
|
||||
{
|
||||
case 14: // Timer.
|
||||
switch (opc)
|
||||
{
|
||||
case 0:
|
||||
dlg = new _U64(NativeInterface.GetCntpctEl0); break;
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetCntpctEl0)); break;
|
||||
|
||||
default:
|
||||
throw new NotImplementedException($"Unknown MRRC Opc1 0x{opc:X16} at 0x{op.Address:X16}.");
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
|
||||
default:
|
||||
throw new NotImplementedException($"Unknown MRRC 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
|
||||
}
|
||||
|
||||
Operand result = context.Call(dlg);
|
||||
Operand result = context.Call(info);
|
||||
|
||||
SetIntA32(context, op.Rt, context.ConvertI64ToI32(result));
|
||||
SetIntA32(context, op.CRn, context.ConvertI64ToI32(context.ShiftRightUI(result, Const(32))));
|
||||
|
@ -162,16 +182,18 @@ namespace ARMeilleure.Instructions
|
|||
SetFlag(context, PState.CFlag, GetFpFlag(FPState.CFlag));
|
||||
SetFlag(context, PState.ZFlag, GetFpFlag(FPState.ZFlag));
|
||||
SetFlag(context, PState.NFlag, GetFpFlag(FPState.NFlag));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
Delegate dlg;
|
||||
MethodInfo info;
|
||||
|
||||
switch (op.Sreg)
|
||||
{
|
||||
case 0b0000: // FPSID
|
||||
throw new NotImplementedException("Supervisor Only");
|
||||
case 0b0001: // FPSCR
|
||||
dlg = new _U32(NativeInterface.GetFpscr); break;
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.GetFpscr)); break;
|
||||
case 0b0101: // MVFR2
|
||||
throw new NotImplementedException("MVFR2");
|
||||
case 0b0110: // MVFR1
|
||||
|
@ -180,24 +202,25 @@ namespace ARMeilleure.Instructions
|
|||
throw new NotImplementedException("MVFR0");
|
||||
case 0b1000: // FPEXC
|
||||
throw new NotImplementedException("Supervisor Only");
|
||||
default:
|
||||
default:
|
||||
throw new NotImplementedException($"Unknown VMRS 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
|
||||
}
|
||||
|
||||
SetIntA32(context, op.Rt, context.Call(dlg));
|
||||
SetIntA32(context, op.Rt, context.Call(info));
|
||||
}
|
||||
|
||||
public static void Vmsr(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32SimdSpecial op = (OpCode32SimdSpecial)context.CurrOp;
|
||||
|
||||
Delegate dlg;
|
||||
MethodInfo info;
|
||||
|
||||
switch (op.Sreg)
|
||||
{
|
||||
case 0b0000: // FPSID
|
||||
throw new NotImplementedException("Supervisor Only");
|
||||
case 0b0001: // FPSCR
|
||||
dlg = new _Void_U32(NativeInterface.SetFpscr); break;
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.SetFpscr)); break;
|
||||
case 0b0101: // MVFR2
|
||||
throw new NotImplementedException("MVFR2");
|
||||
case 0b0110: // MVFR1
|
||||
|
@ -206,11 +229,11 @@ namespace ARMeilleure.Instructions
|
|||
throw new NotImplementedException("MVFR0");
|
||||
case 0b1000: // FPEXC
|
||||
throw new NotImplementedException("Supervisor Only");
|
||||
default:
|
||||
default:
|
||||
throw new NotImplementedException($"Unknown VMSR 0x{op.RawOpCode:X8} at 0x{op.Address:X16}.");
|
||||
}
|
||||
|
||||
context.Call(dlg, GetIntA32(context, op.Rt));
|
||||
context.Call(info, GetIntA32(context, op.Rt));
|
||||
}
|
||||
|
||||
private static void EmitSetNzcv(ArmEmitterContext context, Operand t)
|
||||
|
|
|
@ -407,18 +407,22 @@ namespace ARMeilleure.Instructions
|
|||
public static ulong GetFunctionAddress(ulong address)
|
||||
{
|
||||
TranslatedFunction function = _context.Translator.GetOrTranslate(address, GetContext().ExecutionMode);
|
||||
return (ulong)function.GetPointer().ToInt64();
|
||||
|
||||
return (ulong)function.FuncPtr.ToInt64();
|
||||
}
|
||||
|
||||
public static ulong GetIndirectFunctionAddress(ulong address, ulong entryAddress)
|
||||
{
|
||||
TranslatedFunction function = _context.Translator.GetOrTranslate(address, GetContext().ExecutionMode);
|
||||
ulong ptr = (ulong)function.GetPointer().ToInt64();
|
||||
|
||||
ulong ptr = (ulong)function.FuncPtr.ToInt64();
|
||||
|
||||
if (function.HighCq)
|
||||
{
|
||||
// Rewrite the host function address in the table to point to the highCq function.
|
||||
Marshal.WriteInt64((IntPtr)entryAddress, 8, (long)ptr);
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -903,6 +903,13 @@ namespace ARMeilleure.Instructions
|
|||
else
|
||||
{
|
||||
result = value1;
|
||||
|
||||
if ((fpcr & FPCR.Fz) != 0 && float.IsSubnormal(result))
|
||||
{
|
||||
context.Fpsr |= FPSR.Ufc;
|
||||
|
||||
result = FPZero(result < 0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -987,6 +994,13 @@ namespace ARMeilleure.Instructions
|
|||
else
|
||||
{
|
||||
result = value1;
|
||||
|
||||
if ((fpcr & FPCR.Fz) != 0 && float.IsSubnormal(result))
|
||||
{
|
||||
context.Fpsr |= FPSR.Ufc;
|
||||
|
||||
result = FPZero(result < 0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -2196,6 +2210,13 @@ namespace ARMeilleure.Instructions
|
|||
else
|
||||
{
|
||||
result = value1;
|
||||
|
||||
if ((fpcr & FPCR.Fz) != 0 && double.IsSubnormal(result))
|
||||
{
|
||||
context.Fpsr |= FPSR.Ufc;
|
||||
|
||||
result = FPZero(result < 0d);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -2280,6 +2301,13 @@ namespace ARMeilleure.Instructions
|
|||
else
|
||||
{
|
||||
result = value1;
|
||||
|
||||
if ((fpcr & FPCR.Fz) != 0 && double.IsSubnormal(result))
|
||||
{
|
||||
context.Fpsr |= FPSR.Ufc;
|
||||
|
||||
result = FPZero(result < 0d);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue