Add files via upload
This commit is contained in:
parent
ca736aba5d
commit
385799d8d9
40 changed files with 1432 additions and 660 deletions
|
@ -1,4 +1,4 @@
|
|||
using ARMeilleure.CodeGen.Unwinding;
|
||||
//using ARMeilleure.CodeGen.Unwinding;
|
||||
|
||||
namespace ARMeilleure.CodeGen
|
||||
{
|
||||
|
@ -6,12 +6,12 @@ namespace ARMeilleure.CodeGen
|
|||
{
|
||||
public byte[] Code { get; }
|
||||
|
||||
public UnwindInfo UnwindInfo { get; }
|
||||
//public UnwindInfo UnwindInfo { get; }
|
||||
|
||||
public CompiledFunction(byte[] code, UnwindInfo unwindInfo)
|
||||
public CompiledFunction(byte[] code/*, UnwindInfo unwindInfo*/)
|
||||
{
|
||||
Code = code;
|
||||
UnwindInfo = unwindInfo;
|
||||
//UnwindInfo = unwindInfo;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,7 +14,7 @@ namespace ARMeilleure.CodeGen.Optimizations
|
|||
return;
|
||||
}
|
||||
|
||||
if (!AreAllSourcesConstant(operation))
|
||||
if (!AreAllSourcesConstantAndCFEnabled(operation))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -212,11 +212,13 @@ namespace ARMeilleure.CodeGen.Optimizations
|
|||
}
|
||||
}
|
||||
|
||||
private static bool AreAllSourcesConstant(Operation operation)
|
||||
private static bool AreAllSourcesConstantAndCFEnabled(Operation operation)
|
||||
{
|
||||
for (int index = 0; index < operation.SourcesCount; index++)
|
||||
{
|
||||
if (operation.GetSource(index).Kind != OperandKind.Constant)
|
||||
Operand srcOp = operation.GetSource(index);
|
||||
|
||||
if (srcOp.Kind != OperandKind.Constant || srcOp.DisableCF)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
namespace ARMeilleure.CodeGen.Unwinding
|
||||
/*namespace ARMeilleure.CodeGen.Unwinding
|
||||
{
|
||||
struct UnwindInfo
|
||||
{
|
||||
|
@ -15,4 +15,4 @@ namespace ARMeilleure.CodeGen.Unwinding
|
|||
FixedAllocSize = fixedAllocSize;
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
|
@ -1,4 +1,4 @@
|
|||
using ARMeilleure.IntermediateRepresentation;
|
||||
/*using ARMeilleure.IntermediateRepresentation;
|
||||
|
||||
namespace ARMeilleure.CodeGen.Unwinding
|
||||
{
|
||||
|
@ -17,4 +17,4 @@ namespace ARMeilleure.CodeGen.Unwinding
|
|||
StreamEndOffset = streamEndOffset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
|
@ -1,4 +1,5 @@
|
|||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation.AOT;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
@ -62,6 +63,8 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
private Stream _stream;
|
||||
|
||||
private AotInfo _aotInfo;
|
||||
|
||||
static Assembler()
|
||||
{
|
||||
_instTable = new InstructionInfo[(int)X86Instruction.Count];
|
||||
|
@ -256,9 +259,11 @@ namespace ARMeilleure.CodeGen.X86
|
|||
_instTable[(int)inst] = info;
|
||||
}
|
||||
|
||||
public Assembler(Stream stream)
|
||||
public Assembler(Stream stream, AotInfo aotInfo = null)
|
||||
{
|
||||
_stream = stream;
|
||||
|
||||
_aotInfo = aotInfo;
|
||||
}
|
||||
|
||||
public void Add(Operand dest, Operand source, OperandType type)
|
||||
|
@ -432,13 +437,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
public void Jcc(X86Condition condition, long offset)
|
||||
{
|
||||
if (ConstFitsOnS8(offset))
|
||||
{
|
||||
WriteByte((byte)(0x70 | (int)condition));
|
||||
|
||||
WriteByte((byte)offset);
|
||||
}
|
||||
else if (ConstFitsOnS32(offset))
|
||||
if (ConstFitsOnS32(offset))
|
||||
{
|
||||
WriteByte(0x0f);
|
||||
WriteByte((byte)(0x80 | (int)condition));
|
||||
|
@ -453,13 +452,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
public void Jmp(long offset)
|
||||
{
|
||||
if (ConstFitsOnS8(offset))
|
||||
{
|
||||
WriteByte(0xeb);
|
||||
|
||||
WriteByte((byte)offset);
|
||||
}
|
||||
else if (ConstFitsOnS32(offset))
|
||||
if (ConstFitsOnS32(offset))
|
||||
{
|
||||
WriteByte(0xe9);
|
||||
|
||||
|
@ -872,6 +865,8 @@ namespace ARMeilleure.CodeGen.X86
|
|||
}
|
||||
else if (dest != null && dest.Kind == OperandKind.Register && info.OpRImm64 != BadOp)
|
||||
{
|
||||
string name = source.Name;
|
||||
|
||||
int rexPrefix = GetRexPrefix(dest, source, type, rrm: false);
|
||||
|
||||
if (rexPrefix != 0)
|
||||
|
@ -881,6 +876,11 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
WriteByte((byte)(info.OpRImm64 + (dest.GetRegister().Index & 0b111)));
|
||||
|
||||
if (_aotInfo != null && name != null)
|
||||
{
|
||||
_aotInfo.WriteRelocEntry(new RelocEntry((int)_stream.Position, name));
|
||||
}
|
||||
|
||||
WriteUInt64(imm);
|
||||
}
|
||||
else
|
||||
|
@ -1274,11 +1274,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
public static int GetJccLength(long offset)
|
||||
{
|
||||
if (ConstFitsOnS8(offset < 0 ? offset - 2 : offset))
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
else if (ConstFitsOnS32(offset < 0 ? offset - 6 : offset))
|
||||
if (ConstFitsOnS32(offset))
|
||||
{
|
||||
return 6;
|
||||
}
|
||||
|
@ -1288,22 +1284,6 @@ namespace ARMeilleure.CodeGen.X86
|
|||
}
|
||||
}
|
||||
|
||||
public static int GetJmpLength(long offset)
|
||||
{
|
||||
if (ConstFitsOnS8(offset < 0 ? offset - 2 : offset))
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
else if (ConstFitsOnS32(offset < 0 ? offset - 5 : offset))
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(offset));
|
||||
}
|
||||
}
|
||||
|
||||
private static bool ConstFitsOnS8(long value)
|
||||
{
|
||||
return value == (sbyte)value;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using ARMeilleure.CodeGen.RegisterAllocators;
|
||||
using ARMeilleure.Common;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation.AOT;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
@ -9,11 +10,11 @@ namespace ARMeilleure.CodeGen.X86
|
|||
{
|
||||
class CodeGenContext
|
||||
{
|
||||
private const int ReservedBytesForJump = 1;
|
||||
|
||||
private Stream _stream;
|
||||
|
||||
public int StreamOffset => (int)_stream.Length;
|
||||
private AotInfo _aotInfo;
|
||||
|
||||
//public int StreamOffset => (int)_stream.Length;
|
||||
|
||||
public AllocationResult AllocResult { get; }
|
||||
|
||||
|
@ -38,7 +39,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
public long RelativeOffset { get; set; }
|
||||
|
||||
public int InstSize { get; set; }
|
||||
public int InstSize { get; }
|
||||
|
||||
public Jump(BasicBlock target, long jumpPosition)
|
||||
{
|
||||
|
@ -49,7 +50,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
RelativeOffset = 0;
|
||||
|
||||
InstSize = 0;
|
||||
InstSize = 5;
|
||||
}
|
||||
|
||||
public Jump(X86Condition condition, BasicBlock target, long jumpPosition)
|
||||
|
@ -61,7 +62,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
RelativeOffset = 0;
|
||||
|
||||
InstSize = 0;
|
||||
InstSize = 6;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,13 +73,13 @@ namespace ARMeilleure.CodeGen.X86
|
|||
private long _jNearPosition;
|
||||
private int _jNearLength;
|
||||
|
||||
public CodeGenContext(Stream stream, AllocationResult allocResult, int maxCallArgs, int blocksCount)
|
||||
public CodeGenContext(Stream stream, AllocationResult allocResult, int maxCallArgs, int blocksCount, AotInfo aotInfo = null)
|
||||
{
|
||||
_stream = stream;
|
||||
|
||||
AllocResult = allocResult;
|
||||
|
||||
Assembler = new Assembler(stream);
|
||||
Assembler = new Assembler(stream, aotInfo);
|
||||
|
||||
CallArgsRegionSize = GetCallArgsRegionSize(allocResult, maxCallArgs, out int xmmSaveRegionSize);
|
||||
XmmSaveRegionSize = xmmSaveRegionSize;
|
||||
|
@ -86,6 +87,8 @@ namespace ARMeilleure.CodeGen.X86
|
|||
_blockOffsets = new long[blocksCount];
|
||||
|
||||
_jumps = new List<Jump>();
|
||||
|
||||
_aotInfo = aotInfo;
|
||||
}
|
||||
|
||||
private int GetCallArgsRegionSize(AllocationResult allocResult, int maxCallArgs, out int xmmSaveRegionSize)
|
||||
|
@ -138,14 +141,14 @@ namespace ARMeilleure.CodeGen.X86
|
|||
{
|
||||
_jumps.Add(new Jump(target, _stream.Position));
|
||||
|
||||
WritePadding(ReservedBytesForJump);
|
||||
WritePadding(5);
|
||||
}
|
||||
|
||||
public void JumpTo(X86Condition condition, BasicBlock target)
|
||||
{
|
||||
_jumps.Add(new Jump(condition, target, _stream.Position));
|
||||
|
||||
WritePadding(ReservedBytesForJump);
|
||||
WritePadding(6);
|
||||
}
|
||||
|
||||
public void JumpToNear(X86Condition condition)
|
||||
|
@ -165,7 +168,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
long offset = currentPosition - (_jNearPosition + _jNearLength);
|
||||
|
||||
Debug.Assert(_jNearLength == Assembler.GetJccLength(offset), "Relative offset doesn't fit on near jump.");
|
||||
Debug.Assert(_jNearLength == Assembler.GetJccLength(offset < 0 ? offset - 6 : offset), "Relative offset doesn't fit on near jump.");
|
||||
|
||||
Assembler.Jcc(_jNearCondition, offset);
|
||||
|
||||
|
@ -197,58 +200,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
long offset = jumpTarget - jump.JumpPosition;
|
||||
|
||||
if (offset < 0)
|
||||
{
|
||||
for (int index2 = index - 1; index2 >= 0; index2--)
|
||||
{
|
||||
Jump jump2 = _jumps[index2];
|
||||
|
||||
if (jump2.JumpPosition < jumpTarget)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
offset -= jump2.InstSize - ReservedBytesForJump;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int index2 = index + 1; index2 < _jumps.Count; index2++)
|
||||
{
|
||||
Jump jump2 = _jumps[index2];
|
||||
|
||||
if (jump2.JumpPosition >= jumpTarget)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
offset += jump2.InstSize - ReservedBytesForJump;
|
||||
}
|
||||
|
||||
offset -= ReservedBytesForJump;
|
||||
}
|
||||
|
||||
if (jump.IsConditional)
|
||||
{
|
||||
jump.InstSize = Assembler.GetJccLength(offset);
|
||||
}
|
||||
else
|
||||
{
|
||||
jump.InstSize = Assembler.GetJmpLength(offset);
|
||||
}
|
||||
|
||||
// The jump is relative to the next instruction, not the current one.
|
||||
// Since we didn't know the next instruction address when calculating
|
||||
// the offset (as the size of the current jump instruction was not know),
|
||||
// we now need to compensate the offset with the jump instruction size.
|
||||
// It's also worth to note that:
|
||||
// - This is only needed for backward jumps.
|
||||
// - The GetJmpLength and GetJccLength also compensates the offset
|
||||
// internally when computing the jump instruction size.
|
||||
if (offset < 0)
|
||||
{
|
||||
offset -= jump.InstSize;
|
||||
}
|
||||
offset -= jump.InstSize;
|
||||
|
||||
if (jump.RelativeOffset != offset)
|
||||
{
|
||||
|
@ -262,7 +214,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
}
|
||||
while (modified);
|
||||
|
||||
// Write the code, ignoring the dummy bytes after jumps, into a new stream.
|
||||
// Write the code into a new stream.
|
||||
_stream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
using (MemoryStream codeStream = new MemoryStream())
|
||||
|
@ -278,7 +230,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
buffer = new byte[jump.JumpPosition - _stream.Position];
|
||||
|
||||
_stream.Read(buffer, 0, buffer.Length);
|
||||
_stream.Seek(ReservedBytesForJump, SeekOrigin.Current);
|
||||
_stream.Seek(jump.InstSize, SeekOrigin.Current);
|
||||
|
||||
codeStream.Write(buffer);
|
||||
|
||||
|
@ -298,6 +250,11 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
codeStream.Write(buffer);
|
||||
|
||||
if (_aotInfo != null)
|
||||
{
|
||||
_aotInfo.WriteCode(codeStream);
|
||||
}
|
||||
|
||||
return codeStream.ToArray();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
using ARMeilleure.CodeGen.Optimizations;
|
||||
using ARMeilleure.CodeGen.RegisterAllocators;
|
||||
using ARMeilleure.CodeGen.Unwinding;
|
||||
//using ARMeilleure.CodeGen.Unwinding;
|
||||
using ARMeilleure.Common;
|
||||
using ARMeilleure.Diagnostics;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
using ARMeilleure.Translation.AOT;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
|
||||
|
@ -97,7 +97,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
_instTable[(int)inst] = func;
|
||||
}
|
||||
|
||||
public static CompiledFunction Generate(CompilerContext cctx)
|
||||
public static CompiledFunction Generate(CompilerContext cctx, AotInfo aotInfo = null)
|
||||
{
|
||||
ControlFlowGraph cfg = cctx.Cfg;
|
||||
|
||||
|
@ -153,9 +153,9 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
using (MemoryStream stream = new MemoryStream())
|
||||
{
|
||||
CodeGenContext context = new CodeGenContext(stream, allocResult, maxCallArgs, cfg.Blocks.Count);
|
||||
CodeGenContext context = new CodeGenContext(stream, allocResult, maxCallArgs, cfg.Blocks.Count, aotInfo);
|
||||
|
||||
UnwindInfo unwindInfo = WritePrologue(context);
|
||||
/*UnwindInfo unwindInfo = */WritePrologue(context);
|
||||
|
||||
foreach (BasicBlock block in cfg.Blocks)
|
||||
{
|
||||
|
@ -172,7 +172,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
Logger.EndPass(PassName.CodeGeneration);
|
||||
|
||||
return new CompiledFunction(context.GetCode(), unwindInfo);
|
||||
return new CompiledFunction(context.GetCode()/*, unwindInfo*/);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1518,9 +1518,9 @@ namespace ARMeilleure.CodeGen.X86
|
|||
Debug.Assert(op1.Type == op4.Type);
|
||||
}
|
||||
|
||||
private static UnwindInfo WritePrologue(CodeGenContext context)
|
||||
private static /*UnwindInfo*/ void WritePrologue(CodeGenContext context)
|
||||
{
|
||||
List<UnwindPushEntry> pushEntries = new List<UnwindPushEntry>();
|
||||
//List<UnwindPushEntry> pushEntries = new List<UnwindPushEntry>();
|
||||
|
||||
Operand rsp = Register(X86Register.Rsp);
|
||||
|
||||
|
@ -1532,7 +1532,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
context.Assembler.Push(Register((X86Register)bit));
|
||||
|
||||
pushEntries.Add(new UnwindPushEntry(bit, RegisterType.Integer, context.StreamOffset));
|
||||
//pushEntries.Add(new UnwindPushEntry(bit, RegisterType.Integer, context.StreamOffset));
|
||||
|
||||
mask &= ~(1 << bit);
|
||||
}
|
||||
|
@ -1565,12 +1565,12 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
context.Assembler.Movdqu(memOp, Xmm((X86Register)bit));
|
||||
|
||||
pushEntries.Add(new UnwindPushEntry(bit, RegisterType.Vector, context.StreamOffset));
|
||||
//pushEntries.Add(new UnwindPushEntry(bit, RegisterType.Vector, context.StreamOffset));
|
||||
|
||||
mask &= ~(1 << bit);
|
||||
}
|
||||
|
||||
return new UnwindInfo(pushEntries.ToArray(), context.StreamOffset, reservedStackSize);
|
||||
//return new UnwindInfo(pushEntries.ToArray(), context.StreamOffset, reservedStackSize);
|
||||
}
|
||||
|
||||
private static void WriteEpilogue(CodeGenContext context)
|
||||
|
|
|
@ -265,11 +265,11 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (op.RegisterSize == RegisterSize.Int32)
|
||||
{
|
||||
d = context.Call(new _U32_U32(SoftFallback.ReverseBits32), n);
|
||||
d = context.SoftFallbackCall(nameof(SoftFallback.ReverseBits32), n);
|
||||
}
|
||||
else
|
||||
{
|
||||
d = context.Call(new _U64_U64(SoftFallback.ReverseBits64), n);
|
||||
d = context.SoftFallbackCall(nameof(SoftFallback.ReverseBits64), n);
|
||||
}
|
||||
|
||||
SetAluDOrZR(context, d);
|
||||
|
@ -284,11 +284,11 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (op.RegisterSize == RegisterSize.Int32)
|
||||
{
|
||||
d = context.Call(new _U32_U32(SoftFallback.ReverseBytes16_32), n);
|
||||
d = context.SoftFallbackCall(nameof(SoftFallback.ReverseBytes16_32), n);
|
||||
}
|
||||
else
|
||||
{
|
||||
d = context.Call(new _U64_U64(SoftFallback.ReverseBytes16_64), n);
|
||||
d = context.SoftFallbackCall(nameof(SoftFallback.ReverseBytes16_64), n);
|
||||
}
|
||||
|
||||
SetAluDOrZR(context, d);
|
||||
|
@ -306,7 +306,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
Operand d = context.Call(new _U64_U64(SoftFallback.ReverseBytes32_64), n);
|
||||
Operand d = context.SoftFallbackCall(nameof(SoftFallback.ReverseBytes32_64), n);
|
||||
|
||||
SetAluDOrZR(context, d);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using ARMeilleure.Decoders;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
|
||||
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
|
||||
|
||||
|
@ -10,21 +9,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.NativeInterfaceCall(name, Const(op.Address), Const(op.Id));
|
||||
|
||||
context.LoadFromContext();
|
||||
|
||||
|
@ -38,11 +37,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.NativeInterfaceCall(name, Const(op.Address), Const(op.RawOpCode));
|
||||
|
||||
context.LoadFromContext();
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using ARMeilleure.Decoders;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
|
||||
|
@ -11,52 +10,52 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
public static void Crc32b(ArmEmitterContext context)
|
||||
{
|
||||
EmitCrc32Call(context, new _U32_U32_U8(SoftFallback.Crc32b));
|
||||
EmitCrc32Call(context, nameof(SoftFallback.Crc32b));
|
||||
}
|
||||
|
||||
public static void Crc32h(ArmEmitterContext context)
|
||||
{
|
||||
EmitCrc32Call(context, new _U32_U32_U16(SoftFallback.Crc32h));
|
||||
EmitCrc32Call(context, nameof(SoftFallback.Crc32h));
|
||||
}
|
||||
|
||||
public static void Crc32w(ArmEmitterContext context)
|
||||
{
|
||||
EmitCrc32Call(context, new _U32_U32_U32(SoftFallback.Crc32w));
|
||||
EmitCrc32Call(context, nameof(SoftFallback.Crc32w));
|
||||
}
|
||||
|
||||
public static void Crc32x(ArmEmitterContext context)
|
||||
{
|
||||
EmitCrc32Call(context, new _U32_U32_U64(SoftFallback.Crc32x));
|
||||
EmitCrc32Call(context, nameof(SoftFallback.Crc32x));
|
||||
}
|
||||
|
||||
public static void Crc32cb(ArmEmitterContext context)
|
||||
{
|
||||
EmitCrc32Call(context, new _U32_U32_U8(SoftFallback.Crc32cb));
|
||||
EmitCrc32Call(context, nameof(SoftFallback.Crc32cb));
|
||||
}
|
||||
|
||||
public static void Crc32ch(ArmEmitterContext context)
|
||||
{
|
||||
EmitCrc32Call(context, new _U32_U32_U16(SoftFallback.Crc32ch));
|
||||
EmitCrc32Call(context, nameof(SoftFallback.Crc32ch));
|
||||
}
|
||||
|
||||
public static void Crc32cw(ArmEmitterContext context)
|
||||
{
|
||||
EmitCrc32Call(context, new _U32_U32_U32(SoftFallback.Crc32cw));
|
||||
EmitCrc32Call(context, nameof(SoftFallback.Crc32cw));
|
||||
}
|
||||
|
||||
public static void Crc32cx(ArmEmitterContext context)
|
||||
{
|
||||
EmitCrc32Call(context, new _U32_U32_U64(SoftFallback.Crc32cx));
|
||||
EmitCrc32Call(context, nameof(SoftFallback.Crc32cx));
|
||||
}
|
||||
|
||||
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.SoftFallbackCall(name, n, m);
|
||||
|
||||
SetIntOrZR(context, op.Rd, d);
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static void Clrex(ArmEmitterContext context)
|
||||
{
|
||||
context.Call(new _Void(NativeInterface.ClearExclusive));
|
||||
context.NativeInterfaceCall(nameof(NativeInterface.ClearExclusive));
|
||||
}
|
||||
|
||||
public static void Dmb(ArmEmitterContext context) => EmitBarrier(context);
|
||||
|
@ -107,32 +107,32 @@ namespace ARMeilleure.Instructions
|
|||
bool exclusive,
|
||||
int size)
|
||||
{
|
||||
Delegate fallbackMethodDlg = null;
|
||||
string fallbackMethodName = 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: fallbackMethodName = nameof(NativeInterface.ReadByteExclusive); break;
|
||||
case 1: fallbackMethodName = nameof(NativeInterface.ReadUInt16Exclusive); break;
|
||||
case 2: fallbackMethodName = nameof(NativeInterface.ReadUInt32Exclusive); break;
|
||||
case 3: fallbackMethodName = nameof(NativeInterface.ReadUInt64Exclusive); break;
|
||||
case 4: fallbackMethodName = 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: fallbackMethodName = nameof(NativeInterface.ReadByte); break;
|
||||
case 1: fallbackMethodName = nameof(NativeInterface.ReadUInt16); break;
|
||||
case 2: fallbackMethodName = nameof(NativeInterface.ReadUInt32); break;
|
||||
case 3: fallbackMethodName = nameof(NativeInterface.ReadUInt64); break;
|
||||
case 4: fallbackMethodName = nameof(NativeInterface.ReadVector128); break;
|
||||
}
|
||||
}
|
||||
|
||||
return context.Call(fallbackMethodDlg, address);
|
||||
return context.NativeInterfaceCall(fallbackMethodName, address);
|
||||
}
|
||||
|
||||
public static void Pfrm(ArmEmitterContext context)
|
||||
|
@ -219,33 +219,33 @@ namespace ARMeilleure.Instructions
|
|||
value = context.ConvertI64ToI32(value);
|
||||
}
|
||||
|
||||
Delegate fallbackMethodDlg = null;
|
||||
string fallbackMethodName = 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: fallbackMethodName = nameof(NativeInterface.WriteByteExclusive); break;
|
||||
case 1: fallbackMethodName = nameof(NativeInterface.WriteUInt16Exclusive); break;
|
||||
case 2: fallbackMethodName = nameof(NativeInterface.WriteUInt32Exclusive); break;
|
||||
case 3: fallbackMethodName = nameof(NativeInterface.WriteUInt64Exclusive); break;
|
||||
case 4: fallbackMethodName = nameof(NativeInterface.WriteVector128Exclusive); break;
|
||||
}
|
||||
|
||||
return context.Call(fallbackMethodDlg, address, value);
|
||||
return context.NativeInterfaceCall(fallbackMethodName, 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: fallbackMethodName = nameof(NativeInterface.WriteByte); break;
|
||||
case 1: fallbackMethodName = nameof(NativeInterface.WriteUInt16); break;
|
||||
case 2: fallbackMethodName = nameof(NativeInterface.WriteUInt32); break;
|
||||
case 3: fallbackMethodName = nameof(NativeInterface.WriteUInt64); break;
|
||||
case 4: fallbackMethodName = nameof(NativeInterface.WriteVector128); break;
|
||||
}
|
||||
|
||||
context.Call(fallbackMethodDlg, address, value);
|
||||
context.NativeInterfaceCall(fallbackMethodName, address, value);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -142,21 +142,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);
|
||||
|
@ -194,25 +183,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);
|
||||
|
@ -292,25 +267,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);
|
||||
|
@ -327,7 +288,9 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
private static Operand EmitPtPointerLoad(ArmEmitterContext context, Operand address, Operand lblFallbackPath)
|
||||
{
|
||||
Operand pte = Const(context.Memory.PageTable.ToInt64());
|
||||
string name = nameof(MemoryManager.PTbl);
|
||||
|
||||
Operand pte = Const(context.Memory.PageTable.ToInt64(), true, name);
|
||||
|
||||
int bit = MemoryManager.PageBits;
|
||||
|
||||
|
@ -376,17 +339,17 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
private static void EmitReadIntFallback(ArmEmitterContext context, Operand address, int rt, int size)
|
||||
{
|
||||
Delegate fallbackMethodDlg = null;
|
||||
string fallbackMethodName = 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: fallbackMethodName = nameof(NativeInterface.ReadByte); break;
|
||||
case 1: fallbackMethodName = nameof(NativeInterface.ReadUInt16); break;
|
||||
case 2: fallbackMethodName = nameof(NativeInterface.ReadUInt32); break;
|
||||
case 3: fallbackMethodName = nameof(NativeInterface.ReadUInt64); break;
|
||||
}
|
||||
|
||||
SetInt(context, rt, context.Call(fallbackMethodDlg, address));
|
||||
SetInt(context, rt, context.NativeInterfaceCall(fallbackMethodName, address));
|
||||
}
|
||||
|
||||
private static void EmitReadVectorFallback(
|
||||
|
@ -397,18 +360,18 @@ namespace ARMeilleure.Instructions
|
|||
int elem,
|
||||
int size)
|
||||
{
|
||||
Delegate fallbackMethodDlg = null;
|
||||
string fallbackMethodName = 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: fallbackMethodName = nameof(NativeInterface.ReadByte); break;
|
||||
case 1: fallbackMethodName = nameof(NativeInterface.ReadUInt16); break;
|
||||
case 2: fallbackMethodName = nameof(NativeInterface.ReadUInt32); break;
|
||||
case 3: fallbackMethodName = nameof(NativeInterface.ReadUInt64); break;
|
||||
case 4: fallbackMethodName = nameof(NativeInterface.ReadVector128); break;
|
||||
}
|
||||
|
||||
Operand value = context.Call(fallbackMethodDlg, address);
|
||||
Operand value = context.NativeInterfaceCall(fallbackMethodName, address);
|
||||
|
||||
switch (size)
|
||||
{
|
||||
|
@ -423,14 +386,14 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
private static void EmitWriteIntFallback(ArmEmitterContext context, Operand address, int rt, int size)
|
||||
{
|
||||
Delegate fallbackMethodDlg = null;
|
||||
string fallbackMethodName = 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: fallbackMethodName = nameof(NativeInterface.WriteByte); break;
|
||||
case 1: fallbackMethodName = nameof(NativeInterface.WriteUInt16); break;
|
||||
case 2: fallbackMethodName = nameof(NativeInterface.WriteUInt32); break;
|
||||
case 3: fallbackMethodName = nameof(NativeInterface.WriteUInt64); break;
|
||||
}
|
||||
|
||||
Operand value = GetInt(context, rt);
|
||||
|
@ -440,7 +403,7 @@ namespace ARMeilleure.Instructions
|
|||
value = context.ConvertI64ToI32(value);
|
||||
}
|
||||
|
||||
context.Call(fallbackMethodDlg, address, value);
|
||||
context.NativeInterfaceCall(fallbackMethodName, address, value);
|
||||
}
|
||||
|
||||
private static void EmitWriteVectorFallback(
|
||||
|
@ -450,15 +413,15 @@ namespace ARMeilleure.Instructions
|
|||
int elem,
|
||||
int size)
|
||||
{
|
||||
Delegate fallbackMethodDlg = null;
|
||||
string fallbackMethodName = 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: fallbackMethodName = nameof(NativeInterface.WriteByte); break;
|
||||
case 1: fallbackMethodName = nameof(NativeInterface.WriteUInt16); break;
|
||||
case 2: fallbackMethodName = nameof(NativeInterface.WriteUInt32); break;
|
||||
case 3: fallbackMethodName = nameof(NativeInterface.WriteUInt64); break;
|
||||
case 4: fallbackMethodName = nameof(NativeInterface.WriteVector128); break;
|
||||
}
|
||||
|
||||
Operand value = null;
|
||||
|
@ -467,21 +430,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
|
||||
|
@ -489,7 +441,7 @@ namespace ARMeilleure.Instructions
|
|||
value = GetVec(rt);
|
||||
}
|
||||
|
||||
context.Call(fallbackMethodDlg, address, value);
|
||||
context.NativeInterfaceCall(fallbackMethodName, address, value);
|
||||
}
|
||||
|
||||
private static Operand GetInt(ArmEmitterContext context, int rt)
|
||||
|
|
|
@ -99,7 +99,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.SoftFallbackCall(nameof(SoftFallback.CountLeadingSigns), ne, Const(eSize));
|
||||
|
||||
res = EmitVectorInsert(context, res, de, index, op.Size);
|
||||
}
|
||||
|
@ -121,16 +121,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.SoftFallbackCall(nameof(SoftFallback.CountLeadingZeros), ne, Const(eSize));
|
||||
|
||||
res = EmitVectorInsert(context, res, de, index, op.Size);
|
||||
}
|
||||
|
@ -158,7 +149,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
de = context.Call(new _U64_U64(SoftFallback.CountSetBits8), ne);
|
||||
de = context.SoftFallbackCall(nameof(SoftFallback.CountSetBits8), ne);
|
||||
}
|
||||
|
||||
res = EmitVectorInsert(context, res, de, index, 0);
|
||||
|
@ -200,9 +191,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -245,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -279,7 +270,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitUnaryMathCall(context, MathF.Abs, Math.Abs, op1);
|
||||
return EmitUnaryMathCall(context, nameof(Math.Abs), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -318,7 +309,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitUnaryMathCall(context, MathF.Abs, Math.Abs, op1);
|
||||
return EmitUnaryMathCall(context, nameof(Math.Abs), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -337,7 +328,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -356,7 +347,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -390,7 +381,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));
|
||||
}
|
||||
|
@ -406,7 +397,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -425,7 +416,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -444,7 +435,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -480,7 +471,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -495,7 +486,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -510,7 +501,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -519,7 +510,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);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -527,7 +518,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);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -541,7 +532,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -556,7 +547,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -571,7 +562,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -580,7 +571,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);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -588,7 +579,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);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -602,7 +593,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -653,7 +644,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -702,7 +693,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -753,7 +744,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -802,7 +793,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -838,7 +829,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -857,7 +848,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -881,7 +872,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -931,7 +922,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -940,7 +931,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);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -948,7 +939,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);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -956,7 +947,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);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -964,7 +955,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);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1088,7 +1079,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPRecipEstimate, SoftFloat64.FPRecipEstimate, op1);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPRecipEstimate), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1107,7 +1098,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPRecipEstimate, SoftFloat64.FPRecipEstimate, op1);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPRecipEstimate), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1145,7 +1136,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1188,7 +1179,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1197,7 +1188,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPRecpX, SoftFloat64.FPRecpX, op1);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPRecpX), op1);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1225,11 +1216,11 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (op.Size == 0)
|
||||
{
|
||||
return context.Call(new _F32_F32(SoftFallback.RoundF), op1);
|
||||
return context.SoftFallbackCall(nameof(SoftFallback.RoundF), op1);
|
||||
}
|
||||
else /* if (op.Size == 1) */
|
||||
{
|
||||
return context.Call(new _F64_F64(SoftFallback.Round), op1);
|
||||
return context.SoftFallbackCall(nameof(SoftFallback.Round), op1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1244,11 +1235,11 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (sizeF == 0)
|
||||
{
|
||||
return context.Call(new _F32_F32(SoftFallback.RoundF), op1);
|
||||
return context.SoftFallbackCall(nameof(SoftFallback.RoundF), op1);
|
||||
}
|
||||
else /* if (sizeF == 1) */
|
||||
{
|
||||
return context.Call(new _F64_F64(SoftFallback.Round), op1);
|
||||
return context.SoftFallbackCall(nameof(SoftFallback.Round), op1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1263,7 +1254,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitUnaryMathCall(context, MathF.Floor, Math.Floor, op1);
|
||||
return EmitUnaryMathCall(context, nameof(Math.Floor), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1278,7 +1269,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitUnaryMathCall(context, MathF.Floor, Math.Floor, op1);
|
||||
return EmitUnaryMathCall(context, nameof(Math.Floor), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1323,7 +1314,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitUnaryMathCall(context, MathF.Ceiling, Math.Ceiling, op1);
|
||||
return EmitUnaryMathCall(context, nameof(Math.Ceiling), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1338,7 +1329,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitUnaryMathCall(context, MathF.Ceiling, Math.Ceiling, op1);
|
||||
return EmitUnaryMathCall(context, nameof(Math.Ceiling), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1351,11 +1342,11 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (op.Size == 0)
|
||||
{
|
||||
return context.Call(new _F32_F32(SoftFallback.RoundF), op1);
|
||||
return context.SoftFallbackCall(nameof(SoftFallback.RoundF), op1);
|
||||
}
|
||||
else /* if (op.Size == 1) */
|
||||
{
|
||||
return context.Call(new _F64_F64(SoftFallback.Round), op1);
|
||||
return context.SoftFallbackCall(nameof(SoftFallback.Round), op1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1370,11 +1361,11 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (sizeF == 0)
|
||||
{
|
||||
return context.Call(new _F32_F32(SoftFallback.RoundF), op1);
|
||||
return context.SoftFallbackCall(nameof(SoftFallback.RoundF), op1);
|
||||
}
|
||||
else /* if (sizeF == 1) */
|
||||
{
|
||||
return context.Call(new _F64_F64(SoftFallback.Round), op1);
|
||||
return context.SoftFallbackCall(nameof(SoftFallback.Round), op1);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1389,7 +1380,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitUnaryMathCall(context, MathF.Truncate, Math.Truncate, op1);
|
||||
return EmitUnaryMathCall(context, nameof(Math.Truncate), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1404,7 +1395,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitUnaryMathCall(context, MathF.Truncate, Math.Truncate, op1);
|
||||
return EmitUnaryMathCall(context, nameof(Math.Truncate), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1423,7 +1414,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPRSqrtEstimate, SoftFloat64.FPRSqrtEstimate, op1);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPRSqrtEstimate), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1442,7 +1433,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPRSqrtEstimate, SoftFloat64.FPRSqrtEstimate, op1);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPRSqrtEstimate), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1484,7 +1475,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1531,7 +1522,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1546,7 +1537,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitScalarUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPSqrt, SoftFloat64.FPSqrt, op1);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPSqrt), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1561,7 +1552,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
EmitVectorUnaryOpF(context, (op1) =>
|
||||
{
|
||||
return EmitSoftFloatCall(context, SoftFloat32.FPSqrt, SoftFloat64.FPSqrt, op1);
|
||||
return EmitSoftFloatCall(context, nameof(SoftFloat32.FPSqrt), op1);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1580,7 +1571,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1599,7 +1590,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);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1945,24 +1936,24 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
Delegate dlg = new _S64_S64_S64(Math.Max);
|
||||
string name = nameof(SoftFallback.MaxS64);
|
||||
|
||||
EmitVectorBinaryOpSx(context, (op1, op2) => context.Call(dlg, op1, op2));
|
||||
EmitVectorBinaryOpSx(context, (op1, op2) => context.SoftFallbackCall(name, op1, op2));
|
||||
}
|
||||
}
|
||||
|
||||
public static void Smaxp_V(ArmEmitterContext context)
|
||||
{
|
||||
Delegate dlg = new _S64_S64_S64(Math.Max);
|
||||
string name = nameof(SoftFallback.MaxS64);
|
||||
|
||||
EmitVectorPairwiseOpSx(context, (op1, op2) => context.Call(dlg, op1, op2));
|
||||
EmitVectorPairwiseOpSx(context, (op1, op2) => context.SoftFallbackCall(name, op1, op2));
|
||||
}
|
||||
|
||||
public static void Smaxv_V(ArmEmitterContext context)
|
||||
{
|
||||
Delegate dlg = new _S64_S64_S64(Math.Max);
|
||||
string name = nameof(SoftFallback.MaxS64);
|
||||
|
||||
EmitVectorAcrossVectorOpSx(context, (op1, op2) => context.Call(dlg, op1, op2));
|
||||
EmitVectorAcrossVectorOpSx(context, (op1, op2) => context.SoftFallbackCall(name, op1, op2));
|
||||
}
|
||||
|
||||
public static void Smin_V(ArmEmitterContext context)
|
||||
|
@ -1987,24 +1978,24 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
Delegate dlg = new _S64_S64_S64(Math.Min);
|
||||
string name = nameof(SoftFallback.MinS64);
|
||||
|
||||
EmitVectorBinaryOpSx(context, (op1, op2) => context.Call(dlg, op1, op2));
|
||||
EmitVectorBinaryOpSx(context, (op1, op2) => context.SoftFallbackCall(name, op1, op2));
|
||||
}
|
||||
}
|
||||
|
||||
public static void Sminp_V(ArmEmitterContext context)
|
||||
{
|
||||
Delegate dlg = new _S64_S64_S64(Math.Min);
|
||||
string name = nameof(SoftFallback.MinS64);
|
||||
|
||||
EmitVectorPairwiseOpSx(context, (op1, op2) => context.Call(dlg, op1, op2));
|
||||
EmitVectorPairwiseOpSx(context, (op1, op2) => context.SoftFallbackCall(name, op1, op2));
|
||||
}
|
||||
|
||||
public static void Sminv_V(ArmEmitterContext context)
|
||||
{
|
||||
Delegate dlg = new _S64_S64_S64(Math.Min);
|
||||
string name = nameof(SoftFallback.MinS64);
|
||||
|
||||
EmitVectorAcrossVectorOpSx(context, (op1, op2) => context.Call(dlg, op1, op2));
|
||||
EmitVectorAcrossVectorOpSx(context, (op1, op2) => context.SoftFallbackCall(name, op1, op2));
|
||||
}
|
||||
|
||||
public static void Smlal_V(ArmEmitterContext context)
|
||||
|
@ -2572,24 +2563,24 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
Delegate dlg = new _U64_U64_U64(Math.Max);
|
||||
string name = nameof(SoftFallback.MaxU64);
|
||||
|
||||
EmitVectorBinaryOpZx(context, (op1, op2) => context.Call(dlg, op1, op2));
|
||||
EmitVectorBinaryOpZx(context, (op1, op2) => context.SoftFallbackCall(name, op1, op2));
|
||||
}
|
||||
}
|
||||
|
||||
public static void Umaxp_V(ArmEmitterContext context)
|
||||
{
|
||||
Delegate dlg = new _U64_U64_U64(Math.Max);
|
||||
string name = nameof(SoftFallback.MaxU64);
|
||||
|
||||
EmitVectorPairwiseOpZx(context, (op1, op2) => context.Call(dlg, op1, op2));
|
||||
EmitVectorPairwiseOpZx(context, (op1, op2) => context.SoftFallbackCall(name, op1, op2));
|
||||
}
|
||||
|
||||
public static void Umaxv_V(ArmEmitterContext context)
|
||||
{
|
||||
Delegate dlg = new _U64_U64_U64(Math.Max);
|
||||
string name = nameof(SoftFallback.MaxU64);
|
||||
|
||||
EmitVectorAcrossVectorOpZx(context, (op1, op2) => context.Call(dlg, op1, op2));
|
||||
EmitVectorAcrossVectorOpZx(context, (op1, op2) => context.SoftFallbackCall(name, op1, op2));
|
||||
}
|
||||
|
||||
public static void Umin_V(ArmEmitterContext context)
|
||||
|
@ -2614,24 +2605,24 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
Delegate dlg = new _U64_U64_U64(Math.Min);
|
||||
string name = nameof(SoftFallback.MinU64);
|
||||
|
||||
EmitVectorBinaryOpZx(context, (op1, op2) => context.Call(dlg, op1, op2));
|
||||
EmitVectorBinaryOpZx(context, (op1, op2) => context.SoftFallbackCall(name, op1, op2));
|
||||
}
|
||||
}
|
||||
|
||||
public static void Uminp_V(ArmEmitterContext context)
|
||||
{
|
||||
Delegate dlg = new _U64_U64_U64(Math.Min);
|
||||
string name = nameof(SoftFallback.MinU64);
|
||||
|
||||
EmitVectorPairwiseOpZx(context, (op1, op2) => context.Call(dlg, op1, op2));
|
||||
EmitVectorPairwiseOpZx(context, (op1, op2) => context.SoftFallbackCall(name, op1, op2));
|
||||
}
|
||||
|
||||
public static void Uminv_V(ArmEmitterContext context)
|
||||
{
|
||||
Delegate dlg = new _U64_U64_U64(Math.Min);
|
||||
string name = nameof(SoftFallback.MinU64);
|
||||
|
||||
EmitVectorAcrossVectorOpZx(context, (op1, op2) => context.Call(dlg, op1, op2));
|
||||
EmitVectorAcrossVectorOpZx(context, (op1, op2) => context.SoftFallbackCall(name, op1, op2));
|
||||
}
|
||||
|
||||
public static void Umlal_V(ArmEmitterContext context)
|
||||
|
|
|
@ -304,7 +304,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitCmpOpF(context, SoftFloat32.FPCompareEQ, SoftFloat64.FPCompareEQ, scalar: true);
|
||||
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareEQ), scalar: true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -316,7 +316,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitCmpOpF(context, SoftFloat32.FPCompareEQ, SoftFloat64.FPCompareEQ, scalar: false);
|
||||
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareEQ), scalar: false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -328,7 +328,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitCmpOpF(context, SoftFloat32.FPCompareGE, SoftFloat64.FPCompareGE, scalar: true);
|
||||
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareGE), scalar: true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -340,7 +340,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitCmpOpF(context, SoftFloat32.FPCompareGE, SoftFloat64.FPCompareGE, scalar: false);
|
||||
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareGE), scalar: false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -352,7 +352,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitCmpOpF(context, SoftFloat32.FPCompareGT, SoftFloat64.FPCompareGT, scalar: true);
|
||||
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareGT), scalar: true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -364,7 +364,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitCmpOpF(context, SoftFloat32.FPCompareGT, SoftFloat64.FPCompareGT, scalar: false);
|
||||
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareGT), scalar: false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -376,7 +376,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitCmpOpF(context, SoftFloat32.FPCompareLE, SoftFloat64.FPCompareLE, scalar: true);
|
||||
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareLE), scalar: true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -388,7 +388,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitCmpOpF(context, SoftFloat32.FPCompareLE, SoftFloat64.FPCompareLE, scalar: false);
|
||||
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareLE), scalar: false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -400,7 +400,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitCmpOpF(context, SoftFloat32.FPCompareLT, SoftFloat64.FPCompareLT, scalar: true);
|
||||
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareLT), scalar: true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -412,7 +412,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
EmitCmpOpF(context, SoftFloat32.FPCompareLT, SoftFloat64.FPCompareLT, scalar: false);
|
||||
EmitCmpOpF(context, nameof(SoftFloat32.FPCompareLT), scalar: false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -524,11 +524,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 = context.SoftFloatCall(op.Size == 0 ? nameof(SoftFloat32) : nameof(SoftFloat64), nameof(SoftFloat32.FPCompare), ne, me, Const(signalNaNs));
|
||||
|
||||
EmitSetNzcv(context, nzcv);
|
||||
}
|
||||
|
@ -615,11 +611,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)
|
||||
private static void EmitCmpOpF(ArmEmitterContext context, string name, bool scalar)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
|
@ -645,7 +637,7 @@ namespace ARMeilleure.Instructions
|
|||
me = sizeF == 0 ? ConstF(0f) : ConstF(0d);
|
||||
}
|
||||
|
||||
Operand e = EmitSoftFloatCall(context, f32, f64, ne, me);
|
||||
Operand e = EmitSoftFloatCall(context, name, ne, me);
|
||||
|
||||
res = context.VectorInsert(res, e, index);
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand d = GetVec(op.Rd);
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
context.Copy(d, context.Call(new _V128_V128_V128(SoftFallback.Decrypt), d, n));
|
||||
context.Copy(d, context.SoftFallbackCall(nameof(SoftFallback.Decrypt), d, n));
|
||||
}
|
||||
|
||||
public static void Aese_V(ArmEmitterContext context)
|
||||
|
@ -25,7 +25,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand d = GetVec(op.Rd);
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
context.Copy(d, context.Call(new _V128_V128_V128(SoftFallback.Encrypt), d, n));
|
||||
context.Copy(d, context.SoftFallbackCall(nameof(SoftFallback.Encrypt), d, n));
|
||||
}
|
||||
|
||||
public static void Aesimc_V(ArmEmitterContext context)
|
||||
|
@ -34,7 +34,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.Call(new _V128_V128(SoftFallback.InverseMixColumns), n));
|
||||
context.Copy(GetVec(op.Rd), context.SoftFallbackCall(nameof(SoftFallback.InverseMixColumns), n));
|
||||
}
|
||||
|
||||
public static void Aesmc_V(ArmEmitterContext context)
|
||||
|
@ -43,7 +43,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.Call(new _V128_V128(SoftFallback.MixColumns), n));
|
||||
context.Copy(GetVec(op.Rd), context.SoftFallbackCall(nameof(SoftFallback.MixColumns), n));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,9 +61,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.SoftFloatCall(nameof(SoftFloat32_16), nameof(SoftFloat32_16.FPConvert), ne);
|
||||
|
||||
res = context.ZeroExtend16(OperandType.I64, res);
|
||||
|
||||
|
@ -73,9 +71,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.SoftFloatCall(nameof(SoftFloat16_32), nameof(SoftFloat16_32.FPConvert), ne);
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.VectorInsert(context.VectorZero(), res, 0));
|
||||
}
|
||||
|
@ -141,9 +137,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.SoftFloatCall(nameof(SoftFloat16_32), nameof(SoftFloat16_32.FPConvert), ne);
|
||||
|
||||
res = context.VectorInsert(res, e, index);
|
||||
}
|
||||
|
@ -163,12 +157,12 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static void Fcvtms_Gp(ArmEmitterContext context)
|
||||
{
|
||||
EmitFcvt_s_Gp(context, (op1) => EmitUnaryMathCall(context, MathF.Floor, Math.Floor, op1));
|
||||
EmitFcvt_s_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Floor), op1));
|
||||
}
|
||||
|
||||
public static void Fcvtmu_Gp(ArmEmitterContext context)
|
||||
{
|
||||
EmitFcvt_u_Gp(context, (op1) => EmitUnaryMathCall(context, MathF.Floor, Math.Floor, op1));
|
||||
EmitFcvt_u_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Floor), op1));
|
||||
}
|
||||
|
||||
public static void Fcvtn_V(ArmEmitterContext context)
|
||||
|
@ -212,9 +206,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (sizeF == 0)
|
||||
{
|
||||
Delegate dlg = new _U16_F32(SoftFloat32_16.FPConvert);
|
||||
|
||||
Operand e = context.Call(dlg, ne);
|
||||
Operand e = context.SoftFloatCall(nameof(SoftFloat32_16), nameof(SoftFloat32_16.FPConvert), ne);
|
||||
|
||||
e = context.ZeroExtend16(OperandType.I64, e);
|
||||
|
||||
|
@ -282,12 +274,12 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static void Fcvtps_Gp(ArmEmitterContext context)
|
||||
{
|
||||
EmitFcvt_s_Gp(context, (op1) => EmitUnaryMathCall(context, MathF.Ceiling, Math.Ceiling, op1));
|
||||
EmitFcvt_s_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Ceiling), op1));
|
||||
}
|
||||
|
||||
public static void Fcvtpu_Gp(ArmEmitterContext context)
|
||||
{
|
||||
EmitFcvt_u_Gp(context, (op1) => EmitUnaryMathCall(context, MathF.Ceiling, Math.Ceiling, op1));
|
||||
EmitFcvt_u_Gp(context, (op1) => EmitUnaryMathCall(context, nameof(Math.Ceiling), op1));
|
||||
}
|
||||
|
||||
public static void Fcvtzs_Gp(ArmEmitterContext context)
|
||||
|
@ -569,21 +561,17 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (sizeF == 0)
|
||||
{
|
||||
Delegate dlg = signed
|
||||
? (Delegate)new _S32_F32(SoftFallback.SatF32ToS32)
|
||||
: (Delegate)new _U32_F32(SoftFallback.SatF32ToU32);
|
||||
string name = signed ? nameof(SoftFallback.SatF32ToS32) : nameof(SoftFallback.SatF32ToU32);
|
||||
|
||||
e = context.Call(dlg, e);
|
||||
e = context.SoftFallbackCall(name, 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);
|
||||
string name = signed ? nameof(SoftFallback.SatF64ToS64) : nameof(SoftFallback.SatF64ToU64);
|
||||
|
||||
e = context.Call(dlg, e);
|
||||
e = context.SoftFallbackCall(name, e);
|
||||
}
|
||||
|
||||
res = EmitVectorInsert(context, res, e, index, sizeI);
|
||||
|
@ -617,21 +605,17 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (sizeF == 0)
|
||||
{
|
||||
Delegate dlg = signed
|
||||
? (Delegate)new _S32_F32(SoftFallback.SatF32ToS32)
|
||||
: (Delegate)new _U32_F32(SoftFallback.SatF32ToU32);
|
||||
string name = signed ? nameof(SoftFallback.SatF32ToS32) : nameof(SoftFallback.SatF32ToU32);
|
||||
|
||||
e = context.Call(dlg, e);
|
||||
e = context.SoftFallbackCall(name, 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);
|
||||
string name = signed ? nameof(SoftFallback.SatF64ToS64) : nameof(SoftFallback.SatF64ToU64);
|
||||
|
||||
e = context.Call(dlg, e);
|
||||
e = context.SoftFallbackCall(name, e);
|
||||
}
|
||||
|
||||
res = EmitVectorInsert(context, res, e, index, sizeI);
|
||||
|
@ -751,22 +735,18 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
value = EmitF2iFBitsMul(context, value, fBits);
|
||||
|
||||
string name;
|
||||
|
||||
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);
|
||||
name = value.Type == OperandType.FP32 ? nameof(SoftFallback.SatF32ToS32) : 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);
|
||||
name = value.Type == OperandType.FP32 ? nameof(SoftFallback.SatF32ToS64) : nameof(SoftFallback.SatF64ToS64);
|
||||
}
|
||||
|
||||
return context.SoftFallbackCall(name, value);
|
||||
}
|
||||
|
||||
private static Operand EmitScalarFcvtu(ArmEmitterContext context, Operand value, int fBits)
|
||||
|
@ -775,22 +755,18 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
value = EmitF2iFBitsMul(context, value, fBits);
|
||||
|
||||
string name;
|
||||
|
||||
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);
|
||||
name = value.Type == OperandType.FP32 ? nameof(SoftFallback.SatF32ToU32) : 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);
|
||||
name = value.Type == OperandType.FP32 ? nameof(SoftFallback.SatF32ToU64) : nameof(SoftFallback.SatF64ToU64);
|
||||
}
|
||||
|
||||
return context.SoftFallbackCall(name, value);
|
||||
}
|
||||
|
||||
private static Operand EmitF2iFBitsMul(ArmEmitterContext context, Operand value, int fBits)
|
||||
|
|
|
@ -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.SoftFallbackCall(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.SoftFallbackCall(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.SoftFallbackCall(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.SoftFallbackCall(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.SoftFallbackCall(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.SoftFallbackCall(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.SoftFallbackCall(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.SoftFallbackCall(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.SoftFallbackCall(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.SoftFallbackCall(nameof(SoftFallback.Sha256SchedulePart2), d, n, m);
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
|
|
|
@ -284,68 +284,25 @@ 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);
|
||||
return context.MathCall((op.Size & 1) == 0 ? nameof(MathF) : nameof(Math), name, n);
|
||||
}
|
||||
|
||||
public static Operand EmitRoundMathCall(ArmEmitterContext context, MidpointRounding roundMode, Operand n)
|
||||
{
|
||||
IOpCodeSimd op = (IOpCodeSimd)context.CurrOp;
|
||||
|
||||
Delegate dlg;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return context.Call(dlg, n, Const((int)roundMode));
|
||||
return context.MathCall((op.Size & 1) == 0 ? nameof(MathF) : nameof(Math), nameof(Math.Round), 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;
|
||||
|
||||
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.SoftFloatCall((op.Size & 1) == 0 ? nameof(SoftFloat32) : nameof(SoftFloat64), name, callArgs);
|
||||
}
|
||||
|
||||
public static void EmitScalarBinaryOpByElemF(ArmEmitterContext context, Func2I emit)
|
||||
|
@ -1215,8 +1172,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (op.Size <= 2)
|
||||
{
|
||||
Operand temp = add ? context.Add (ne, me)
|
||||
: context.Subtract(ne, me);
|
||||
Operand temp = add ? context.Add(ne, me) : context.Subtract(ne, me);
|
||||
|
||||
de = EmitSatQ(context, temp, op.Size, signedSrc: true, signedDst: signed);
|
||||
}
|
||||
|
@ -1322,22 +1278,18 @@ namespace ARMeilleure.Instructions
|
|||
throw new ArgumentOutOfRangeException(nameof(sizeDst));
|
||||
}
|
||||
|
||||
Delegate dlg;
|
||||
string name;
|
||||
|
||||
if (signedSrc)
|
||||
{
|
||||
dlg = signedDst
|
||||
? (Delegate)new _S64_S64_S32(SoftFallback.SignedSrcSignedDstSatQ)
|
||||
: (Delegate)new _U64_S64_S32(SoftFallback.SignedSrcUnsignedDstSatQ);
|
||||
name = signedDst ? nameof(SoftFallback.SignedSrcSignedDstSatQ) : nameof(SoftFallback.SignedSrcUnsignedDstSatQ);
|
||||
}
|
||||
else
|
||||
{
|
||||
dlg = signedDst
|
||||
? (Delegate)new _S64_U64_S32(SoftFallback.UnsignedSrcSignedDstSatQ)
|
||||
: (Delegate)new _U64_U64_S32(SoftFallback.UnsignedSrcUnsignedDstSatQ);
|
||||
name = signedDst ? nameof(SoftFallback.UnsignedSrcSignedDstSatQ) : nameof(SoftFallback.UnsignedSrcUnsignedDstSatQ);
|
||||
}
|
||||
|
||||
return context.Call(dlg, op, Const(sizeDst));
|
||||
return context.SoftFallbackCall(name, op, Const(sizeDst));
|
||||
}
|
||||
|
||||
// TSrc (64bit) == TDst (64bit); signed.
|
||||
|
@ -1345,7 +1297,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.SoftFallbackCall(nameof(SoftFallback.UnarySignedSatQAbsOrNeg), op);
|
||||
}
|
||||
|
||||
// TSrcs (64bit) == TDst (64bit); signed, unsigned.
|
||||
|
@ -1353,11 +1305,9 @@ 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);
|
||||
string name = signed ? nameof(SoftFallback.BinarySignedSatQAdd) : nameof(SoftFallback.BinaryUnsignedSatQAdd);
|
||||
|
||||
return context.Call(dlg, op1, op2);
|
||||
return context.SoftFallbackCall(name, op1, op2);
|
||||
}
|
||||
|
||||
// TSrcs (64bit) == TDst (64bit); signed, unsigned.
|
||||
|
@ -1365,11 +1315,9 @@ 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);
|
||||
string name = signed ? nameof(SoftFallback.BinarySignedSatQSub) : nameof(SoftFallback.BinaryUnsignedSatQSub);
|
||||
|
||||
return context.Call(dlg, op1, op2);
|
||||
return context.SoftFallbackCall(name, op1, op2);
|
||||
}
|
||||
|
||||
// TSrcs (64bit) == TDst (64bit); signed, unsigned.
|
||||
|
@ -1377,11 +1325,9 @@ 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);
|
||||
string name = signed ? nameof(SoftFallback.BinarySignedSatQAcc) : nameof(SoftFallback.BinaryUnsignedSatQAcc);
|
||||
|
||||
return context.Call(dlg, op1, op2);
|
||||
return context.SoftFallbackCall(name, op1, op2);
|
||||
}
|
||||
|
||||
public static Operand EmitVectorExtractSx(ArmEmitterContext context, int reg, int index, int size)
|
||||
|
|
|
@ -294,7 +294,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
ne = context.ConvertI64ToI32(ne);
|
||||
|
||||
Operand de = context.Call(new _U32_U32(SoftFallback.ReverseBits8), ne);
|
||||
Operand de = context.SoftFallbackCall(nameof(SoftFallback.ReverseBits8), ne);
|
||||
|
||||
de = context.ZeroExtend32(OperandType.I64, de);
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using ARMeilleure.Decoders;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
|
@ -434,28 +433,28 @@ namespace ARMeilleure.Instructions
|
|||
args[1 + index] = GetVec((op.Rn + index) & 0x1f);
|
||||
}
|
||||
|
||||
Delegate dlg = null;
|
||||
string name = null;
|
||||
|
||||
switch (op.Size)
|
||||
{
|
||||
case 1: dlg = op.RegisterSize == RegisterSize.Simd64
|
||||
? (Delegate)new _V128_V128_V128(SoftFallback.Tbl1_V64)
|
||||
: (Delegate)new _V128_V128_V128(SoftFallback.Tbl1_V128); break;
|
||||
case 1: name = op.RegisterSize == RegisterSize.Simd64
|
||||
? nameof(SoftFallback.Tbl1_V64)
|
||||
: nameof(SoftFallback.Tbl1_V128); break;
|
||||
|
||||
case 2: dlg = op.RegisterSize == RegisterSize.Simd64
|
||||
? (Delegate)new _V128_V128_V128_V128(SoftFallback.Tbl2_V64)
|
||||
: (Delegate)new _V128_V128_V128_V128(SoftFallback.Tbl2_V128); break;
|
||||
case 2: name = op.RegisterSize == RegisterSize.Simd64
|
||||
? nameof(SoftFallback.Tbl2_V64)
|
||||
: nameof(SoftFallback.Tbl2_V128); break;
|
||||
|
||||
case 3: dlg = op.RegisterSize == RegisterSize.Simd64
|
||||
? (Delegate)new _V128_V128_V128_V128_V128(SoftFallback.Tbl3_V64)
|
||||
: (Delegate)new _V128_V128_V128_V128_V128(SoftFallback.Tbl3_V128); break;
|
||||
case 3: name = op.RegisterSize == RegisterSize.Simd64
|
||||
? nameof(SoftFallback.Tbl3_V64)
|
||||
: nameof(SoftFallback.Tbl3_V128); break;
|
||||
|
||||
case 4: dlg = op.RegisterSize == RegisterSize.Simd64
|
||||
? (Delegate)new _V128_V128_V128_V128_V128_V128(SoftFallback.Tbl4_V64)
|
||||
: (Delegate)new _V128_V128_V128_V128_V128_V128(SoftFallback.Tbl4_V128); break;
|
||||
case 4: name = op.RegisterSize == RegisterSize.Simd64
|
||||
? nameof(SoftFallback.Tbl4_V64)
|
||||
: nameof(SoftFallback.Tbl4_V128); break;
|
||||
}
|
||||
|
||||
context.Copy(GetVec(op.Rd), context.Call(dlg, args));
|
||||
context.Copy(GetVec(op.Rd), context.SoftFallbackCall(name, args));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -221,7 +221,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.SoftFallbackCall(nameof(SoftFallback.SignedShlRegSatQ), ne, me, Const(1), Const(op.Size));
|
||||
|
||||
res = EmitVectorInsert(context, res, e, index, op.Size);
|
||||
}
|
||||
|
@ -262,7 +262,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.SoftFallbackCall(nameof(SoftFallback.SignedShlRegSatQ), ne, me, Const(0), Const(op.Size));
|
||||
|
||||
res = EmitVectorInsert(context, res, e, index, op.Size);
|
||||
}
|
||||
|
@ -303,7 +303,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.SoftFallbackCall(nameof(SoftFallback.SignedShlReg), ne, me, Const(1), Const(op.Size));
|
||||
|
||||
res = EmitVectorInsert(context, res, e, index, op.Size);
|
||||
}
|
||||
|
@ -416,7 +416,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.SoftFallbackCall(nameof(SoftFallback.SignedShlReg), ne, me, Const(0), Const(op.Size));
|
||||
|
||||
res = EmitVectorInsert(context, res, e, index, op.Size);
|
||||
}
|
||||
|
@ -540,7 +540,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.SoftFallbackCall(nameof(SoftFallback.UnsignedShlRegSatQ), ne, me, Const(1), Const(op.Size));
|
||||
|
||||
res = EmitVectorInsert(context, res, e, index, op.Size);
|
||||
}
|
||||
|
@ -571,7 +571,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.SoftFallbackCall(nameof(SoftFallback.UnsignedShlRegSatQ), ne, me, Const(0), Const(op.Size));
|
||||
|
||||
res = EmitVectorInsert(context, res, e, index, op.Size);
|
||||
}
|
||||
|
@ -602,7 +602,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.SoftFallbackCall(nameof(SoftFallback.UnsignedShlReg), ne, me, Const(1), Const(op.Size));
|
||||
|
||||
res = EmitVectorInsert(context, res, e, index, op.Size);
|
||||
}
|
||||
|
@ -711,7 +711,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(0), Const(op.Size));
|
||||
Operand e = context.SoftFallbackCall(nameof(SoftFallback.UnsignedShlReg), ne, me, Const(0), Const(op.Size));
|
||||
|
||||
res = EmitVectorInsert(context, res, e, index, op.Size);
|
||||
}
|
||||
|
@ -1017,11 +1017,9 @@ 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);
|
||||
string name = signed ? nameof(SoftFallback.SignedShrImm64) : nameof(SoftFallback.UnsignedShrImm64);
|
||||
|
||||
return context.Call(dlg, value, Const(roundConst), Const(shift));
|
||||
return context.SoftFallbackCall(name, value, Const(roundConst), Const(shift));
|
||||
}
|
||||
|
||||
private static void EmitVectorShImmWidenBinarySx(ArmEmitterContext context, Func2I emit, int imm)
|
||||
|
|
|
@ -26,41 +26,41 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
||||
|
||||
Delegate dlg;
|
||||
string name;
|
||||
|
||||
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_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_0000_0000_001: name = nameof(NativeInterface.GetCtrEl0); break;
|
||||
case 0b11_011_0000_0000_111: name = nameof(NativeInterface.GetDczidEl0); break;
|
||||
case 0b11_011_0100_0100_000: name = nameof(NativeInterface.GetFpcr); break;
|
||||
case 0b11_011_0100_0100_001: name = nameof(NativeInterface.GetFpsr); break;
|
||||
case 0b11_011_1101_0000_010: name = nameof(NativeInterface.GetTpidrEl0); break;
|
||||
case 0b11_011_1101_0000_011: name = nameof(NativeInterface.GetTpidr); break;
|
||||
case 0b11_011_1110_0000_000: name = nameof(NativeInterface.GetCntfrqEl0); break;
|
||||
case 0b11_011_1110_0000_001: name = nameof(NativeInterface.GetCntpctEl0); 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.NativeInterfaceCall(name));
|
||||
}
|
||||
|
||||
public static void Msr(ArmEmitterContext context)
|
||||
{
|
||||
OpCodeSystem op = (OpCodeSystem)context.CurrOp;
|
||||
|
||||
Delegate dlg;
|
||||
string name;
|
||||
|
||||
switch (GetPackedId(op))
|
||||
{
|
||||
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_0100_000: name = nameof(NativeInterface.SetFpcr); break;
|
||||
case 0b11_011_0100_0100_001: name = nameof(NativeInterface.SetFpsr); break;
|
||||
case 0b11_011_1101_0000_010: name = 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.NativeInterfaceCall(name, GetIntOrZR(context, op.Rt));
|
||||
}
|
||||
|
||||
public static void Nop(ArmEmitterContext context)
|
||||
|
@ -86,7 +86,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
Operand address = context.Add(t, Const(offset));
|
||||
|
||||
context.Call(new _Void_U64_U64(NativeInterface.WriteUInt64), address, Const(0L));
|
||||
context.NativeInterfaceCall(nameof(NativeInterface.WriteUInt64), address, Const(0L));
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
@ -1302,6 +1302,13 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
throw new ArgumentException(nameof(size));
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region "MaxMin"
|
||||
public static long MaxS64(long val1, long val2) => (val1 >= val2) ? val1 : val2;
|
||||
public static ulong MaxU64(ulong val1, ulong val2) => (val1 >= val2) ? val1 : val2;
|
||||
public static long MinS64(long val1, long val2) => (val1 <= val2) ? val1 : val2;
|
||||
public static ulong MinU64(ulong val1, ulong val2) => (val1 <= val2) ? val1 : val2;
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,10 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||
|
||||
public ulong Value { get; private set; }
|
||||
|
||||
public bool DisableCF { get; private set; }
|
||||
|
||||
public string Name { get; private set; }
|
||||
|
||||
public LinkedList<Node> Assignments { get; }
|
||||
public LinkedList<Node> Uses { get; }
|
||||
|
||||
|
@ -36,9 +40,13 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||
Value = (uint)value;
|
||||
}
|
||||
|
||||
public Operand(long value) : this(OperandKind.Constant, OperandType.I64)
|
||||
public Operand(long value, bool disableCF = false, string name = null) : this(OperandKind.Constant, OperandType.I64)
|
||||
{
|
||||
Value = (ulong)value;
|
||||
|
||||
DisableCF = disableCF;
|
||||
|
||||
Name = name;
|
||||
}
|
||||
|
||||
public Operand(ulong value) : this(OperandKind.Constant, OperandType.I64)
|
||||
|
|
|
@ -1,6 +1,3 @@
|
|||
using ARMeilleure.State;
|
||||
using System;
|
||||
|
||||
namespace ARMeilleure.IntermediateRepresentation
|
||||
{
|
||||
static class OperandHelper
|
||||
|
@ -25,9 +22,9 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||
return new Operand(value);
|
||||
}
|
||||
|
||||
public static Operand Const(long value)
|
||||
public static Operand Const(long value, bool disableCF = false, string name = null)
|
||||
{
|
||||
return new Operand(value);
|
||||
return new Operand(value, disableCF, name);
|
||||
}
|
||||
|
||||
public static Operand Const(ulong value)
|
||||
|
|
|
@ -9,6 +9,8 @@ namespace ARMeilleure.Memory
|
|||
{
|
||||
public unsafe class MemoryManager : IMemoryManager
|
||||
{
|
||||
public static long PTbl { get; private set; }
|
||||
|
||||
public const int PageBits = 12;
|
||||
public const int PageSize = 1 << PageBits;
|
||||
public const int PageMask = PageSize - 1;
|
||||
|
@ -65,6 +67,8 @@ namespace ARMeilleure.Memory
|
|||
PtLevelMask = PtLevelSize - 1;
|
||||
|
||||
_pageTable = Allocate((ulong)(PtLevelSize * IntPtr.Size));
|
||||
|
||||
PTbl = _pageTable.ToInt64();
|
||||
}
|
||||
|
||||
public void Map(long va, long pa, long size)
|
||||
|
|
417
ARMeilleure/Translation/AOT/Aot.cs
Normal file
417
ARMeilleure/Translation/AOT/Aot.cs
Normal file
|
@ -0,0 +1,417 @@
|
|||
using ARMeilleure.CodeGen;
|
||||
using ARMeilleure.Memory;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.Cryptography;
|
||||
using System.Timers;
|
||||
|
||||
namespace ARMeilleure.Translation.AOT
|
||||
{
|
||||
public static class Aot
|
||||
{
|
||||
private const string WorkDir = "RyuAot";
|
||||
|
||||
private const long SaveInterval = 30L; // Seconds.
|
||||
|
||||
internal const long MinCodeLengthToSave = 0x180L; // Bytes.
|
||||
|
||||
private static readonly MemoryStream _infosStream;
|
||||
private static readonly MemoryStream _codesStream;
|
||||
private static readonly MemoryStream _relocsStream;
|
||||
|
||||
private static readonly BinaryWriter _infosWriter;
|
||||
|
||||
private static readonly Timer _timer;
|
||||
|
||||
private static readonly object _locker;
|
||||
|
||||
private static bool _disposed; // TODO: volatile?
|
||||
|
||||
public static string WorkPath { get; }
|
||||
public static string TitleId { get; private set; }
|
||||
|
||||
public static bool Enabled { get; private set; }
|
||||
|
||||
static Aot()
|
||||
{
|
||||
string basePath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
|
||||
|
||||
Debug.Assert(basePath != String.Empty);
|
||||
|
||||
WorkPath = Path.Combine(basePath, WorkDir);
|
||||
|
||||
if (!Directory.Exists(WorkPath))
|
||||
{
|
||||
Directory.CreateDirectory(WorkPath);
|
||||
}
|
||||
|
||||
TitleId = String.Empty;
|
||||
|
||||
Enabled = false;
|
||||
|
||||
_infosStream = new MemoryStream();
|
||||
_codesStream = new MemoryStream();
|
||||
_relocsStream = new MemoryStream();
|
||||
|
||||
_infosWriter = new BinaryWriter(_infosStream, EncodingCache.UTF8NoBOM, true);
|
||||
|
||||
_timer = new Timer((double)SaveInterval * 1000d);
|
||||
_timer.Elapsed += MergeAndSave;
|
||||
//_timer.AutoReset = true;
|
||||
//_timer.Enabled = false;
|
||||
|
||||
_locker = new object();
|
||||
|
||||
_disposed = false;
|
||||
}
|
||||
|
||||
public static void Init(string titleId, bool enabled, bool readOnly = false)
|
||||
{
|
||||
if (!String.IsNullOrEmpty(titleId))
|
||||
{
|
||||
TitleId = titleId.ToUpper();
|
||||
}
|
||||
|
||||
Enabled = enabled;
|
||||
|
||||
if (enabled)
|
||||
{
|
||||
LoadAndSplit();
|
||||
|
||||
if (!readOnly)
|
||||
{
|
||||
_timer.Enabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void LoadAndSplit()
|
||||
{
|
||||
string cachePath = Path.Combine(WorkPath, TitleId);
|
||||
|
||||
FileInfo cacheInfo = new FileInfo(cachePath);
|
||||
|
||||
if (cacheInfo.Exists && cacheInfo.Length != 0L)
|
||||
{
|
||||
using (FileStream cacheStream = new FileStream(cachePath, FileMode.Open))
|
||||
{
|
||||
MD5 md5 = MD5.Create();
|
||||
|
||||
int hashSize = md5.HashSize / 8;
|
||||
|
||||
try
|
||||
{
|
||||
byte[] currentHash = new byte[hashSize];
|
||||
cacheStream.Read(currentHash, 0, hashSize);
|
||||
|
||||
byte[] expectedHash = md5.ComputeHash(cacheStream);
|
||||
|
||||
if (CompareHash(currentHash, expectedHash))
|
||||
{
|
||||
cacheStream.Seek((long)hashSize, SeekOrigin.Begin);
|
||||
|
||||
ReadHeader(cacheStream, out int infosLen, out int codesLen, out int relocsLen);
|
||||
|
||||
byte[] infosBuf = new byte[infosLen];
|
||||
byte[] codesBuf = new byte[codesLen];
|
||||
byte[] relocsBuf = new byte[relocsLen];
|
||||
|
||||
cacheStream.Read(infosBuf, 0, infosLen);
|
||||
cacheStream.Read(codesBuf, 0, codesLen);
|
||||
cacheStream.Read(relocsBuf, 0, relocsLen);
|
||||
|
||||
_infosStream. Write(infosBuf, 0, infosLen);
|
||||
_codesStream. Write(codesBuf, 0, codesLen);
|
||||
_relocsStream.Write(relocsBuf, 0, relocsLen);
|
||||
}
|
||||
else
|
||||
{
|
||||
cacheStream.SetLength(0L);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
cacheStream.SetLength(0L);
|
||||
}
|
||||
|
||||
md5.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static bool CompareHash(byte[] currentHash, byte[] expectedHash)
|
||||
{
|
||||
for (int i = 0; i < currentHash.Length; i++)
|
||||
{
|
||||
if (currentHash[i] != expectedHash[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void ReadHeader(
|
||||
FileStream cacheStream,
|
||||
out int infosLen,
|
||||
out int codesLen,
|
||||
out int relocsLen)
|
||||
{
|
||||
BinaryReader headerReader = new BinaryReader(cacheStream, EncodingCache.UTF8NoBOM, true);
|
||||
|
||||
infosLen = headerReader.ReadInt32();
|
||||
codesLen = headerReader.ReadInt32();
|
||||
relocsLen = headerReader.ReadInt32();
|
||||
|
||||
headerReader.Dispose();
|
||||
}
|
||||
|
||||
private static void MergeAndSave(Object source, ElapsedEventArgs e)
|
||||
{
|
||||
string cachePath = Path.Combine(WorkPath, TitleId);
|
||||
|
||||
using (FileStream cacheStream = new FileStream(cachePath, FileMode.OpenOrCreate))
|
||||
{
|
||||
MD5 md5 = MD5.Create();
|
||||
|
||||
int hashSize = md5.HashSize / 8;
|
||||
|
||||
bool computeHash = false;
|
||||
|
||||
lock (_locker) // Read.
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
cacheStream.Write(GetPlaceholder(hashSize), 0, hashSize);
|
||||
|
||||
WriteHeader(cacheStream);
|
||||
|
||||
_infosStream. WriteTo(cacheStream);
|
||||
_codesStream. WriteTo(cacheStream);
|
||||
_relocsStream.WriteTo(cacheStream);
|
||||
|
||||
computeHash = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (computeHash)
|
||||
{
|
||||
cacheStream.Seek((long)hashSize, SeekOrigin.Begin);
|
||||
byte[] hash = md5.ComputeHash(cacheStream);
|
||||
|
||||
cacheStream.Seek(0L, SeekOrigin.Begin);
|
||||
cacheStream.Write(hash, 0, hashSize);
|
||||
|
||||
cacheStream.Seek(0L, SeekOrigin.End);
|
||||
}
|
||||
|
||||
md5.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private static byte[] GetPlaceholder(int size)
|
||||
{
|
||||
byte[] placeholder = new byte[size];
|
||||
|
||||
for (int i = 0; i < placeholder.Length; i++)
|
||||
{
|
||||
placeholder[i] = 0;
|
||||
}
|
||||
|
||||
return placeholder;
|
||||
}
|
||||
|
||||
private static void WriteHeader(FileStream cacheStream)
|
||||
{
|
||||
BinaryWriter headerWriter = new BinaryWriter(cacheStream, EncodingCache.UTF8NoBOM, true);
|
||||
|
||||
headerWriter.Write((int)_infosStream. Length); // infosLen
|
||||
headerWriter.Write((int)_codesStream. Length); // codesLen
|
||||
headerWriter.Write((int)_relocsStream.Length); // relocsLen
|
||||
|
||||
headerWriter.Dispose();
|
||||
}
|
||||
|
||||
internal static void FullTranslate(ConcurrentDictionary<ulong, TranslatedFunction> funcsHighCq)
|
||||
{
|
||||
if ((int)_infosStream.Length + (int)_codesStream.Length + (int)_relocsStream.Length != 0) // infosCodesRelocsLen
|
||||
{
|
||||
_infosStream. Seek(0L, SeekOrigin.Begin);
|
||||
_codesStream. Seek(0L, SeekOrigin.Begin);
|
||||
_relocsStream.Seek(0L, SeekOrigin.Begin);
|
||||
|
||||
BinaryReader infoReader = new BinaryReader(_infosStream, EncodingCache.UTF8NoBOM, true);
|
||||
BinaryReader relocReader = new BinaryReader(_relocsStream, EncodingCache.UTF8NoBOM, true);
|
||||
|
||||
Debug.Assert((int)_infosStream.Length % InfoEntry.Size == 0);
|
||||
|
||||
for (int i = 0; i < (int)_infosStream.Length / InfoEntry.Size; i++) // infosEntriesCount
|
||||
{
|
||||
InfoEntry infoEntry = ReadInfo(infoReader);
|
||||
|
||||
byte[] code = ReadCode(infoEntry.CodeLen);
|
||||
|
||||
if (infoEntry.RelocEntriesCount != 0)
|
||||
{
|
||||
PatchCode(code, GetRelocEntries(relocReader, infoEntry.RelocEntriesCount));
|
||||
}
|
||||
|
||||
bool isAddressUnique = funcsHighCq.TryAdd((ulong)infoEntry.Address, FakeTranslate(code));
|
||||
|
||||
Debug.Assert(isAddressUnique, $"The address 0x{(ulong)infoEntry.Address:X16} is not unique.");
|
||||
}
|
||||
|
||||
infoReader. Dispose();
|
||||
relocReader.Dispose();
|
||||
|
||||
Debug.Assert(_infosStream. Position == _infosStream. Length, "The Infos stream is unbalanced.");
|
||||
Debug.Assert(_codesStream. Position == _codesStream. Length, "The Codes stream is unbalanced.");
|
||||
Debug.Assert(_relocsStream.Position == _relocsStream.Length, "The Relocs stream is unbalanced.");
|
||||
}
|
||||
}
|
||||
|
||||
private static InfoEntry ReadInfo(BinaryReader infoReader)
|
||||
{
|
||||
long address = infoReader.ReadInt64();
|
||||
int codeLen = infoReader.ReadInt32();
|
||||
int relocEntriesCount = infoReader.ReadInt32();
|
||||
|
||||
return new InfoEntry(address, codeLen, relocEntriesCount);
|
||||
}
|
||||
|
||||
private static byte[] ReadCode(int codeLen)
|
||||
{
|
||||
byte[] codeBuf = new byte[codeLen];
|
||||
|
||||
_codesStream.Read(codeBuf, 0, codeLen);
|
||||
|
||||
return codeBuf;
|
||||
}
|
||||
|
||||
private static RelocEntry[] GetRelocEntries(BinaryReader relocReader, int relocEntriesCount)
|
||||
{
|
||||
RelocEntry[] relocEntries = new RelocEntry[relocEntriesCount];
|
||||
|
||||
for (int i = 0; i < relocEntriesCount; i++)
|
||||
{
|
||||
int position = relocReader.ReadInt32();
|
||||
string name = relocReader.ReadString();
|
||||
|
||||
relocEntries[i] = new RelocEntry(position, name);
|
||||
}
|
||||
|
||||
return relocEntries;
|
||||
}
|
||||
|
||||
private static void PatchCode(byte[] code, RelocEntry[] relocEntries)
|
||||
{
|
||||
foreach (RelocEntry relocEntry in relocEntries)
|
||||
{
|
||||
byte[] immBytes = new byte[8];
|
||||
|
||||
if (relocEntry.Name == nameof(MemoryManager.PTbl))
|
||||
{
|
||||
immBytes = BitConverter.GetBytes((ulong)MemoryManager.PTbl);
|
||||
}
|
||||
else
|
||||
{
|
||||
IntPtr funcPtr = Delegates.GetDelegateInfo(relocEntry.Name).FuncPtr;
|
||||
|
||||
immBytes = BitConverter.GetBytes((ulong)funcPtr.ToInt64());
|
||||
}
|
||||
|
||||
Buffer.BlockCopy(immBytes, 0, code, relocEntry.Position, 8);
|
||||
}
|
||||
}
|
||||
|
||||
private static TranslatedFunction FakeTranslate(byte[] code)
|
||||
{
|
||||
CompiledFunction cFunc = new CompiledFunction(code);
|
||||
|
||||
IntPtr codePtr = JitCache.Map(cFunc);
|
||||
|
||||
GuestFunction gFunc = Marshal.GetDelegateForFunctionPointer<GuestFunction>(codePtr);
|
||||
|
||||
TranslatedFunction tFunc = new TranslatedFunction(gFunc, rejit: false);
|
||||
|
||||
return tFunc;
|
||||
}
|
||||
|
||||
internal static void WriteInfoCodeReloc(long address, AotInfo aotInfo)
|
||||
{
|
||||
lock (_locker) // Write.
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
WriteInfo (new InfoEntry(address, aotInfo));
|
||||
WriteCode (aotInfo);
|
||||
WriteReloc(aotInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void WriteInfo(InfoEntry infoEntry)
|
||||
{
|
||||
_infosWriter.Write(infoEntry.Address);
|
||||
_infosWriter.Write(infoEntry.CodeLen);
|
||||
_infosWriter.Write(infoEntry.RelocEntriesCount);
|
||||
}
|
||||
|
||||
private static void WriteCode(AotInfo aotInfo)
|
||||
{
|
||||
aotInfo.CodeStream.WriteTo(_codesStream);
|
||||
}
|
||||
|
||||
private static void WriteReloc(AotInfo aotInfo)
|
||||
{
|
||||
aotInfo.RelocStream.WriteTo(_relocsStream);
|
||||
}
|
||||
|
||||
private struct InfoEntry
|
||||
{
|
||||
public const int Size = 16; // Bytes.
|
||||
|
||||
public long Address;
|
||||
public int CodeLen;
|
||||
public int RelocEntriesCount;
|
||||
|
||||
public InfoEntry(long address, int codeLen, int relocEntriesCount)
|
||||
{
|
||||
Address = address;
|
||||
CodeLen = codeLen;
|
||||
RelocEntriesCount = relocEntriesCount;
|
||||
}
|
||||
|
||||
public InfoEntry(long address, AotInfo aotInfo)
|
||||
{
|
||||
Address = address;
|
||||
CodeLen = (int)aotInfo.CodeStream.Length;
|
||||
RelocEntriesCount = aotInfo.RelocEntriesCount;
|
||||
}
|
||||
}
|
||||
|
||||
public static void Dispose()
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
_timer.Elapsed -= MergeAndSave;
|
||||
_timer.Dispose();
|
||||
|
||||
lock (_locker) // Dispose.
|
||||
{
|
||||
_infosWriter.Dispose();
|
||||
|
||||
_infosStream. Dispose();
|
||||
_codesStream. Dispose();
|
||||
_relocsStream.Dispose();
|
||||
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
45
ARMeilleure/Translation/AOT/AotInfo.cs
Normal file
45
ARMeilleure/Translation/AOT/AotInfo.cs
Normal file
|
@ -0,0 +1,45 @@
|
|||
using System.IO;
|
||||
|
||||
namespace ARMeilleure.Translation.AOT
|
||||
{
|
||||
class AotInfo
|
||||
{
|
||||
private readonly BinaryWriter _relocWriter;
|
||||
|
||||
public MemoryStream CodeStream { get; }
|
||||
public MemoryStream RelocStream { get; }
|
||||
|
||||
public int RelocEntriesCount { get; private set; }
|
||||
|
||||
public AotInfo()
|
||||
{
|
||||
CodeStream = new MemoryStream();
|
||||
RelocStream = new MemoryStream();
|
||||
|
||||
_relocWriter = new BinaryWriter(RelocStream, EncodingCache.UTF8NoBOM, true);
|
||||
|
||||
RelocEntriesCount = 0;
|
||||
}
|
||||
|
||||
public void WriteCode(MemoryStream codeStream)
|
||||
{
|
||||
codeStream.WriteTo(CodeStream);
|
||||
}
|
||||
|
||||
public void WriteRelocEntry(RelocEntry relocEntry)
|
||||
{
|
||||
_relocWriter.Write(relocEntry.Position);
|
||||
_relocWriter.Write(relocEntry.Name);
|
||||
|
||||
RelocEntriesCount++;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_relocWriter.Dispose();
|
||||
|
||||
CodeStream. Dispose();
|
||||
RelocStream.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
9
ARMeilleure/Translation/AOT/EncodingCache.cs
Normal file
9
ARMeilleure/Translation/AOT/EncodingCache.cs
Normal file
|
@ -0,0 +1,9 @@
|
|||
using System.Text;
|
||||
|
||||
namespace ARMeilleure.Translation.AOT
|
||||
{
|
||||
internal static class EncodingCache
|
||||
{
|
||||
internal static readonly Encoding UTF8NoBOM = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true);
|
||||
}
|
||||
}
|
14
ARMeilleure/Translation/AOT/RelocEntry.cs
Normal file
14
ARMeilleure/Translation/AOT/RelocEntry.cs
Normal file
|
@ -0,0 +1,14 @@
|
|||
namespace ARMeilleure.Translation.AOT
|
||||
{
|
||||
public struct RelocEntry
|
||||
{
|
||||
public int Position;
|
||||
public string Name;
|
||||
|
||||
public RelocEntry(int position, string name)
|
||||
{
|
||||
Position = position;
|
||||
Name = name;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,13 +7,16 @@ using System.Runtime.InteropServices;
|
|||
|
||||
namespace ARMeilleure.Translation
|
||||
{
|
||||
using AOT;
|
||||
|
||||
static class Compiler
|
||||
{
|
||||
public static T Compile<T>(
|
||||
ControlFlowGraph cfg,
|
||||
OperandType[] funcArgTypes,
|
||||
OperandType funcReturnType,
|
||||
CompilerOptions options)
|
||||
CompilerOptions options,
|
||||
AotInfo aotInfo = null)
|
||||
{
|
||||
Logger.StartPass(PassName.Dominance);
|
||||
|
||||
|
@ -37,7 +40,7 @@ namespace ARMeilleure.Translation
|
|||
|
||||
CompilerContext cctx = new CompilerContext(cfg, funcArgTypes, funcReturnType, options);
|
||||
|
||||
CompiledFunction func = CodeGenerator.Generate(cctx);
|
||||
CompiledFunction func = CodeGenerator.Generate(cctx, aotInfo);
|
||||
|
||||
IntPtr codePtr = JitCache.Map(func);
|
||||
|
||||
|
|
58
ARMeilleure/Translation/DelegateInfo.cs
Normal file
58
ARMeilleure/Translation/DelegateInfo.cs
Normal file
|
@ -0,0 +1,58 @@
|
|||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.State;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ARMeilleure.Translation
|
||||
{
|
||||
class DelegateInfo
|
||||
{
|
||||
private Delegate _dlg;
|
||||
|
||||
public IntPtr FuncPtr { get; private set; }
|
||||
public OperandType RetType { get; private set; }
|
||||
|
||||
public DelegateInfo(Delegate dlg)
|
||||
{
|
||||
_dlg = dlg;
|
||||
|
||||
FuncPtr = Marshal.GetFunctionPointerForDelegate<Delegate>(_dlg);
|
||||
RetType = GetOperandType(_dlg.Method.ReturnType);
|
||||
}
|
||||
|
||||
private static OperandType GetOperandType(Type type)
|
||||
{
|
||||
if (type == typeof(bool) || type == typeof(byte) ||
|
||||
type == typeof(char) || type == typeof(short) ||
|
||||
type == typeof(int) || type == typeof(sbyte) ||
|
||||
type == typeof(ushort) || type == typeof(uint))
|
||||
{
|
||||
return OperandType.I32;
|
||||
}
|
||||
else if (type == typeof(long) || type == typeof(ulong))
|
||||
{
|
||||
return OperandType.I64;
|
||||
}
|
||||
else if (type == typeof(double))
|
||||
{
|
||||
return OperandType.FP64;
|
||||
}
|
||||
else if (type == typeof(float))
|
||||
{
|
||||
return OperandType.FP32;
|
||||
}
|
||||
else if (type == typeof(V128))
|
||||
{
|
||||
return OperandType.V128;
|
||||
}
|
||||
else if (type == typeof(void))
|
||||
{
|
||||
return OperandType.None;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"Invalid type \"{type.Name}\".");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
370
ARMeilleure/Translation/Delegates.cs
Normal file
370
ARMeilleure/Translation/Delegates.cs
Normal file
|
@ -0,0 +1,370 @@
|
|||
using ARMeilleure.Instructions;
|
||||
using ARMeilleure.State;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace ARMeilleure.Translation
|
||||
{
|
||||
static class Delegates
|
||||
{
|
||||
public static DelegateInfo GetDelegateInfo(string key)
|
||||
{
|
||||
if (key == null)
|
||||
{
|
||||
throw new ArgumentNullException();
|
||||
}
|
||||
|
||||
if (_nativeInterfaceDelegates.TryGetValue(key, out DelegateInfo value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
else if (_softFallbackDelegates.TryGetValue(key, out value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
else if (_mathDelegates.TryGetValue(key, out value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
else if (_softFloatDelegates.TryGetValue(key, out value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
public static DelegateInfo GetMathDelegateInfo(string key)
|
||||
{
|
||||
if (key != null && _mathDelegates.TryGetValue(key, out DelegateInfo value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
public static DelegateInfo GetNativeInterfaceDelegateInfo(string key)
|
||||
{
|
||||
if (key != null && _nativeInterfaceDelegates.TryGetValue(key, out DelegateInfo value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
public static DelegateInfo GetSoftFallbackDelegateInfo(string key)
|
||||
{
|
||||
if (key != null && _softFallbackDelegates.TryGetValue(key, out DelegateInfo value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
public static DelegateInfo GetSoftFloatDelegateInfo(string key)
|
||||
{
|
||||
if (key != null && _softFloatDelegates.TryGetValue(key, out DelegateInfo value))
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
throw new Exception();
|
||||
}
|
||||
|
||||
private static void SetMathDelegateInfo(Delegate dlg)
|
||||
{
|
||||
if (dlg == null || !_mathDelegates.TryAdd(GetKey(dlg.Method), new DelegateInfo(dlg)))
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
|
||||
private static void SetNativeInterfaceDelegateInfo(Delegate dlg)
|
||||
{
|
||||
if (dlg == null || !_nativeInterfaceDelegates.TryAdd(GetKey(dlg.Method), new DelegateInfo(dlg)))
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
|
||||
private static void SetSoftFallbackDelegateInfo(Delegate dlg)
|
||||
{
|
||||
if (dlg == null || !_softFallbackDelegates.TryAdd(GetKey(dlg.Method), new DelegateInfo(dlg)))
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
|
||||
private static void SetSoftFloatDelegateInfo(Delegate dlg)
|
||||
{
|
||||
if (dlg == null || !_softFloatDelegates.TryAdd(GetKey(dlg.Method), new DelegateInfo(dlg)))
|
||||
{
|
||||
throw new Exception();
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetKey(MethodInfo info) => $"{info.DeclaringType.Name}.{info.Name}";
|
||||
|
||||
private static readonly Dictionary<string, DelegateInfo> _mathDelegates;
|
||||
private static readonly Dictionary<string, DelegateInfo> _nativeInterfaceDelegates;
|
||||
private static readonly Dictionary<string, DelegateInfo> _softFallbackDelegates;
|
||||
private static readonly Dictionary<string, DelegateInfo> _softFloatDelegates;
|
||||
|
||||
static Delegates()
|
||||
{
|
||||
_mathDelegates = new Dictionary<string, DelegateInfo>();
|
||||
_nativeInterfaceDelegates = new Dictionary<string, DelegateInfo>();
|
||||
_softFallbackDelegates = new Dictionary<string, DelegateInfo>();
|
||||
_softFloatDelegates = new Dictionary<string, DelegateInfo>();
|
||||
|
||||
SetMathDelegateInfo(new _F64_F64 (Math.Floor));
|
||||
SetMathDelegateInfo(new _F64_F64 (Math.Ceiling));
|
||||
SetMathDelegateInfo(new _F64_F64 (Math.Abs));
|
||||
SetMathDelegateInfo(new _F64_F64 (Math.Truncate));
|
||||
SetMathDelegateInfo(new _F64_F64_MidpointRounding(Math.Round));
|
||||
|
||||
SetMathDelegateInfo(new _F32_F32 (MathF.Floor));
|
||||
SetMathDelegateInfo(new _F32_F32 (MathF.Ceiling));
|
||||
SetMathDelegateInfo(new _F32_F32 (MathF.Abs));
|
||||
SetMathDelegateInfo(new _F32_F32 (MathF.Truncate));
|
||||
SetMathDelegateInfo(new _F32_F32_MidpointRounding(MathF.Round));
|
||||
|
||||
SetNativeInterfaceDelegateInfo(new _S32_U64_U8 (NativeInterface.WriteByteExclusive));
|
||||
SetNativeInterfaceDelegateInfo(new _S32_U64_U16 (NativeInterface.WriteUInt16Exclusive));
|
||||
SetNativeInterfaceDelegateInfo(new _S32_U64_U32 (NativeInterface.WriteUInt32Exclusive));
|
||||
SetNativeInterfaceDelegateInfo(new _S32_U64_U64 (NativeInterface.WriteUInt64Exclusive));
|
||||
SetNativeInterfaceDelegateInfo(new _S32_U64_V128 (NativeInterface.WriteVector128Exclusive));
|
||||
SetNativeInterfaceDelegateInfo(new _U16_U64 (NativeInterface.ReadUInt16Exclusive));
|
||||
SetNativeInterfaceDelegateInfo(new _U16_U64 (NativeInterface.ReadUInt16));
|
||||
SetNativeInterfaceDelegateInfo(new _U32_U64 (NativeInterface.ReadUInt32Exclusive));
|
||||
SetNativeInterfaceDelegateInfo(new _U32_U64 (NativeInterface.ReadUInt32));
|
||||
SetNativeInterfaceDelegateInfo(new _U64 (NativeInterface.GetCtrEl0));
|
||||
SetNativeInterfaceDelegateInfo(new _U64 (NativeInterface.GetDczidEl0));
|
||||
SetNativeInterfaceDelegateInfo(new _U64 (NativeInterface.GetFpcr));
|
||||
SetNativeInterfaceDelegateInfo(new _U64 (NativeInterface.GetFpsr));
|
||||
SetNativeInterfaceDelegateInfo(new _U64 (NativeInterface.GetTpidrEl0));
|
||||
SetNativeInterfaceDelegateInfo(new _U64 (NativeInterface.GetTpidr));
|
||||
SetNativeInterfaceDelegateInfo(new _U64 (NativeInterface.GetCntfrqEl0));
|
||||
SetNativeInterfaceDelegateInfo(new _U64 (NativeInterface.GetCntpctEl0));
|
||||
SetNativeInterfaceDelegateInfo(new _U64_U64 (NativeInterface.ReadUInt64Exclusive));
|
||||
SetNativeInterfaceDelegateInfo(new _U64_U64 (NativeInterface.ReadUInt64));
|
||||
SetNativeInterfaceDelegateInfo(new _U8_U64 (NativeInterface.ReadByteExclusive));
|
||||
SetNativeInterfaceDelegateInfo(new _U8_U64 (NativeInterface.ReadByte));
|
||||
SetNativeInterfaceDelegateInfo(new _V128_U64 (NativeInterface.ReadVector128Exclusive));
|
||||
SetNativeInterfaceDelegateInfo(new _V128_U64 (NativeInterface.ReadVector128));
|
||||
SetNativeInterfaceDelegateInfo(new _Void (NativeInterface.ClearExclusive));
|
||||
SetNativeInterfaceDelegateInfo(new _Void (NativeInterface.CheckSynchronization));
|
||||
SetNativeInterfaceDelegateInfo(new _Void_U64 (NativeInterface.SetFpcr));
|
||||
SetNativeInterfaceDelegateInfo(new _Void_U64 (NativeInterface.SetFpsr));
|
||||
SetNativeInterfaceDelegateInfo(new _Void_U64 (NativeInterface.SetTpidrEl0));
|
||||
SetNativeInterfaceDelegateInfo(new _Void_U64_S32 (NativeInterface.Break));
|
||||
SetNativeInterfaceDelegateInfo(new _Void_U64_S32 (NativeInterface.SupervisorCall));
|
||||
SetNativeInterfaceDelegateInfo(new _Void_U64_S32 (NativeInterface.Undefined));
|
||||
SetNativeInterfaceDelegateInfo(new _Void_U64_U16 (NativeInterface.WriteUInt16));
|
||||
SetNativeInterfaceDelegateInfo(new _Void_U64_U32 (NativeInterface.WriteUInt32));
|
||||
SetNativeInterfaceDelegateInfo(new _Void_U64_U64 (NativeInterface.WriteUInt64));
|
||||
SetNativeInterfaceDelegateInfo(new _Void_U64_U8 (NativeInterface.WriteByte));
|
||||
SetNativeInterfaceDelegateInfo(new _Void_U64_V128(NativeInterface.WriteVector128));
|
||||
|
||||
SetSoftFallbackDelegateInfo(new _F64_F64 (SoftFallback.Round));
|
||||
SetSoftFallbackDelegateInfo(new _F32_F32 (SoftFallback.RoundF));
|
||||
SetSoftFallbackDelegateInfo(new _S32_F32 (SoftFallback.SatF32ToS32));
|
||||
SetSoftFallbackDelegateInfo(new _S32_F64 (SoftFallback.SatF64ToS32));
|
||||
SetSoftFallbackDelegateInfo(new _S64_F32 (SoftFallback.SatF32ToS64));
|
||||
SetSoftFallbackDelegateInfo(new _S64_F64 (SoftFallback.SatF64ToS64));
|
||||
SetSoftFallbackDelegateInfo(new _S64_S64 (SoftFallback.UnarySignedSatQAbsOrNeg));
|
||||
SetSoftFallbackDelegateInfo(new _S64_S64_S32 (SoftFallback.SignedSrcSignedDstSatQ));
|
||||
SetSoftFallbackDelegateInfo(new _S64_S64_S64 (SoftFallback.MaxS64));
|
||||
SetSoftFallbackDelegateInfo(new _S64_S64_S64 (SoftFallback.MinS64));
|
||||
SetSoftFallbackDelegateInfo(new _S64_S64_S64 (SoftFallback.BinarySignedSatQAdd));
|
||||
SetSoftFallbackDelegateInfo(new _S64_S64_S64 (SoftFallback.BinarySignedSatQSub));
|
||||
SetSoftFallbackDelegateInfo(new _S64_S64_S64_Bool_S32 (SoftFallback.SignedShlRegSatQ));
|
||||
SetSoftFallbackDelegateInfo(new _S64_S64_S64_Bool_S32 (SoftFallback.SignedShlReg));
|
||||
SetSoftFallbackDelegateInfo(new _S64_S64_S64_S32 (SoftFallback.SignedShrImm64));
|
||||
SetSoftFallbackDelegateInfo(new _S64_U64_S32 (SoftFallback.UnsignedSrcSignedDstSatQ));
|
||||
SetSoftFallbackDelegateInfo(new _S64_U64_S64 (SoftFallback.BinarySignedSatQAcc));
|
||||
SetSoftFallbackDelegateInfo(new _U32_F32 (SoftFallback.SatF32ToU32));
|
||||
SetSoftFallbackDelegateInfo(new _U32_F64 (SoftFallback.SatF64ToU32));
|
||||
SetSoftFallbackDelegateInfo(new _U32_U32 (SoftFallback.ReverseBits32));
|
||||
SetSoftFallbackDelegateInfo(new _U32_U32 (SoftFallback.ReverseBytes16_32));
|
||||
SetSoftFallbackDelegateInfo(new _U32_U32 (SoftFallback.FixedRotate));
|
||||
SetSoftFallbackDelegateInfo(new _U32_U32 (SoftFallback.ReverseBits8));
|
||||
SetSoftFallbackDelegateInfo(new _U32_U32_U16 (SoftFallback.Crc32h));
|
||||
SetSoftFallbackDelegateInfo(new _U32_U32_U16 (SoftFallback.Crc32ch));
|
||||
SetSoftFallbackDelegateInfo(new _U32_U32_U32 (SoftFallback.Crc32w));
|
||||
SetSoftFallbackDelegateInfo(new _U32_U32_U32 (SoftFallback.Crc32cw));
|
||||
SetSoftFallbackDelegateInfo(new _U32_U32_U64 (SoftFallback.Crc32x));
|
||||
SetSoftFallbackDelegateInfo(new _U32_U32_U64 (SoftFallback.Crc32cx));
|
||||
SetSoftFallbackDelegateInfo(new _U32_U32_U8 (SoftFallback.Crc32b));
|
||||
SetSoftFallbackDelegateInfo(new _U32_U32_U8 (SoftFallback.Crc32cb));
|
||||
SetSoftFallbackDelegateInfo(new _U64_F32 (SoftFallback.SatF32ToU64));
|
||||
SetSoftFallbackDelegateInfo(new _U64_F64 (SoftFallback.SatF64ToU64));
|
||||
SetSoftFallbackDelegateInfo(new _U64_S64_S32 (SoftFallback.SignedSrcUnsignedDstSatQ));
|
||||
SetSoftFallbackDelegateInfo(new _U64_S64_U64 (SoftFallback.BinaryUnsignedSatQAcc));
|
||||
SetSoftFallbackDelegateInfo(new _U64_U64 (SoftFallback.ReverseBits64));
|
||||
SetSoftFallbackDelegateInfo(new _U64_U64 (SoftFallback.ReverseBytes16_64));
|
||||
SetSoftFallbackDelegateInfo(new _U64_U64 (SoftFallback.ReverseBytes32_64));
|
||||
SetSoftFallbackDelegateInfo(new _U64_U64 (SoftFallback.CountSetBits8));
|
||||
SetSoftFallbackDelegateInfo(new _U64_U64_S32 (SoftFallback.CountLeadingSigns));
|
||||
SetSoftFallbackDelegateInfo(new _U64_U64_S32 (SoftFallback.CountLeadingZeros));
|
||||
SetSoftFallbackDelegateInfo(new _U64_U64_S32 (SoftFallback.UnsignedSrcUnsignedDstSatQ));
|
||||
SetSoftFallbackDelegateInfo(new _U64_U64_S64_S32 (SoftFallback.UnsignedShrImm64));
|
||||
SetSoftFallbackDelegateInfo(new _U64_U64_U64 (SoftFallback.MaxU64));
|
||||
SetSoftFallbackDelegateInfo(new _U64_U64_U64 (SoftFallback.MinU64));
|
||||
SetSoftFallbackDelegateInfo(new _U64_U64_U64 (SoftFallback.BinaryUnsignedSatQAdd));
|
||||
SetSoftFallbackDelegateInfo(new _U64_U64_U64 (SoftFallback.BinaryUnsignedSatQSub));
|
||||
SetSoftFallbackDelegateInfo(new _U64_U64_U64_Bool_S32 (SoftFallback.UnsignedShlRegSatQ));
|
||||
SetSoftFallbackDelegateInfo(new _U64_U64_U64_Bool_S32 (SoftFallback.UnsignedShlReg));
|
||||
SetSoftFallbackDelegateInfo(new _V128_V128 (SoftFallback.InverseMixColumns));
|
||||
SetSoftFallbackDelegateInfo(new _V128_V128 (SoftFallback.MixColumns));
|
||||
SetSoftFallbackDelegateInfo(new _V128_V128_U32_V128 (SoftFallback.HashChoose));
|
||||
SetSoftFallbackDelegateInfo(new _V128_V128_U32_V128 (SoftFallback.HashMajority));
|
||||
SetSoftFallbackDelegateInfo(new _V128_V128_U32_V128 (SoftFallback.HashParity));
|
||||
SetSoftFallbackDelegateInfo(new _V128_V128_V128 (SoftFallback.Decrypt));
|
||||
SetSoftFallbackDelegateInfo(new _V128_V128_V128 (SoftFallback.Encrypt));
|
||||
SetSoftFallbackDelegateInfo(new _V128_V128_V128 (SoftFallback.Sha1SchedulePart2));
|
||||
SetSoftFallbackDelegateInfo(new _V128_V128_V128 (SoftFallback.Sha256SchedulePart1));
|
||||
SetSoftFallbackDelegateInfo(new _V128_V128_V128 (SoftFallback.Tbl1_V64));
|
||||
SetSoftFallbackDelegateInfo(new _V128_V128_V128 (SoftFallback.Tbl1_V128));
|
||||
SetSoftFallbackDelegateInfo(new _V128_V128_V128_V128 (SoftFallback.Sha1SchedulePart1));
|
||||
SetSoftFallbackDelegateInfo(new _V128_V128_V128_V128 (SoftFallback.HashLower));
|
||||
SetSoftFallbackDelegateInfo(new _V128_V128_V128_V128 (SoftFallback.HashUpper));
|
||||
SetSoftFallbackDelegateInfo(new _V128_V128_V128_V128 (SoftFallback.Sha256SchedulePart2));
|
||||
SetSoftFallbackDelegateInfo(new _V128_V128_V128_V128 (SoftFallback.Tbl2_V64));
|
||||
SetSoftFallbackDelegateInfo(new _V128_V128_V128_V128 (SoftFallback.Tbl2_V128));
|
||||
SetSoftFallbackDelegateInfo(new _V128_V128_V128_V128_V128 (SoftFallback.Tbl3_V64));
|
||||
SetSoftFallbackDelegateInfo(new _V128_V128_V128_V128_V128 (SoftFallback.Tbl3_V128));
|
||||
SetSoftFallbackDelegateInfo(new _V128_V128_V128_V128_V128_V128(SoftFallback.Tbl4_V64));
|
||||
SetSoftFallbackDelegateInfo(new _V128_V128_V128_V128_V128_V128(SoftFallback.Tbl4_V128));
|
||||
|
||||
SetSoftFloatDelegateInfo(new _F32_U16(SoftFloat16_32.FPConvert));
|
||||
|
||||
SetSoftFloatDelegateInfo(new _F32_F32 (SoftFloat32.FPRecipEstimate));
|
||||
SetSoftFloatDelegateInfo(new _F32_F32 (SoftFloat32.FPRecpX));
|
||||
SetSoftFloatDelegateInfo(new _F32_F32 (SoftFloat32.FPRSqrtEstimate));
|
||||
SetSoftFloatDelegateInfo(new _F32_F32 (SoftFloat32.FPSqrt));
|
||||
SetSoftFloatDelegateInfo(new _F32_F32_F32 (SoftFloat32.FPCompareEQ));
|
||||
SetSoftFloatDelegateInfo(new _F32_F32_F32 (SoftFloat32.FPCompareGE));
|
||||
SetSoftFloatDelegateInfo(new _F32_F32_F32 (SoftFloat32.FPCompareGT));
|
||||
SetSoftFloatDelegateInfo(new _F32_F32_F32 (SoftFloat32.FPCompareLE));
|
||||
SetSoftFloatDelegateInfo(new _F32_F32_F32 (SoftFloat32.FPCompareLT));
|
||||
SetSoftFloatDelegateInfo(new _F32_F32_F32 (SoftFloat32.FPSub));
|
||||
SetSoftFloatDelegateInfo(new _F32_F32_F32 (SoftFloat32.FPAdd));
|
||||
SetSoftFloatDelegateInfo(new _F32_F32_F32 (SoftFloat32.FPDiv));
|
||||
SetSoftFloatDelegateInfo(new _F32_F32_F32 (SoftFloat32.FPMax));
|
||||
SetSoftFloatDelegateInfo(new _F32_F32_F32 (SoftFloat32.FPMaxNum));
|
||||
SetSoftFloatDelegateInfo(new _F32_F32_F32 (SoftFloat32.FPMin));
|
||||
SetSoftFloatDelegateInfo(new _F32_F32_F32 (SoftFloat32.FPMinNum));
|
||||
SetSoftFloatDelegateInfo(new _F32_F32_F32 (SoftFloat32.FPMul));
|
||||
SetSoftFloatDelegateInfo(new _F32_F32_F32 (SoftFloat32.FPMulX));
|
||||
SetSoftFloatDelegateInfo(new _F32_F32_F32 (SoftFloat32.FPRecipStepFused));
|
||||
SetSoftFloatDelegateInfo(new _F32_F32_F32 (SoftFloat32.FPRSqrtStepFused));
|
||||
SetSoftFloatDelegateInfo(new _F32_F32_F32_F32 (SoftFloat32.FPMulAdd));
|
||||
SetSoftFloatDelegateInfo(new _F32_F32_F32_F32 (SoftFloat32.FPMulSub));
|
||||
SetSoftFloatDelegateInfo(new _S32_F32_F32_Bool(SoftFloat32.FPCompare));
|
||||
|
||||
SetSoftFloatDelegateInfo(new _U16_F32(SoftFloat32_16.FPConvert));
|
||||
|
||||
SetSoftFloatDelegateInfo(new _F64_F64 (SoftFloat64.FPRecipEstimate));
|
||||
SetSoftFloatDelegateInfo(new _F64_F64 (SoftFloat64.FPRecpX));
|
||||
SetSoftFloatDelegateInfo(new _F64_F64 (SoftFloat64.FPRSqrtEstimate));
|
||||
SetSoftFloatDelegateInfo(new _F64_F64 (SoftFloat64.FPSqrt));
|
||||
SetSoftFloatDelegateInfo(new _F64_F64_F64 (SoftFloat64.FPCompareEQ));
|
||||
SetSoftFloatDelegateInfo(new _F64_F64_F64 (SoftFloat64.FPCompareGE));
|
||||
SetSoftFloatDelegateInfo(new _F64_F64_F64 (SoftFloat64.FPCompareGT));
|
||||
SetSoftFloatDelegateInfo(new _F64_F64_F64 (SoftFloat64.FPCompareLE));
|
||||
SetSoftFloatDelegateInfo(new _F64_F64_F64 (SoftFloat64.FPCompareLT));
|
||||
SetSoftFloatDelegateInfo(new _F64_F64_F64 (SoftFloat64.FPSub));
|
||||
SetSoftFloatDelegateInfo(new _F64_F64_F64 (SoftFloat64.FPAdd));
|
||||
SetSoftFloatDelegateInfo(new _F64_F64_F64 (SoftFloat64.FPDiv));
|
||||
SetSoftFloatDelegateInfo(new _F64_F64_F64 (SoftFloat64.FPMax));
|
||||
SetSoftFloatDelegateInfo(new _F64_F64_F64 (SoftFloat64.FPMaxNum));
|
||||
SetSoftFloatDelegateInfo(new _F64_F64_F64 (SoftFloat64.FPMin));
|
||||
SetSoftFloatDelegateInfo(new _F64_F64_F64 (SoftFloat64.FPMinNum));
|
||||
SetSoftFloatDelegateInfo(new _F64_F64_F64 (SoftFloat64.FPMul));
|
||||
SetSoftFloatDelegateInfo(new _F64_F64_F64 (SoftFloat64.FPMulX));
|
||||
SetSoftFloatDelegateInfo(new _F64_F64_F64 (SoftFloat64.FPRecipStepFused));
|
||||
SetSoftFloatDelegateInfo(new _F64_F64_F64 (SoftFloat64.FPRSqrtStepFused));
|
||||
SetSoftFloatDelegateInfo(new _F64_F64_F64_F64 (SoftFloat64.FPMulAdd));
|
||||
SetSoftFloatDelegateInfo(new _F64_F64_F64_F64 (SoftFloat64.FPMulSub));
|
||||
SetSoftFloatDelegateInfo(new _S32_F64_F64_Bool(SoftFloat64.FPCompare));
|
||||
}
|
||||
|
||||
private delegate double _F64_F64(double a1);
|
||||
private delegate double _F64_F64_F64(double a1, double a2);
|
||||
private delegate double _F64_F64_F64_F64(double a1, double a2, double a3);
|
||||
private delegate double _F64_F64_MidpointRounding(double a1, MidpointRounding a2);
|
||||
|
||||
private delegate float _F32_F32(float a1);
|
||||
private delegate float _F32_F32_F32(float a1, float a2);
|
||||
private delegate float _F32_F32_F32_F32(float a1, float a2, float a3);
|
||||
private delegate float _F32_F32_MidpointRounding(float a1, MidpointRounding a2);
|
||||
private delegate float _F32_U16(ushort a1);
|
||||
|
||||
private delegate int _S32_F32(float a1);
|
||||
private delegate int _S32_F32_F32_Bool(float a1, float a2, bool a3);
|
||||
private delegate int _S32_F64(double a1);
|
||||
private delegate int _S32_F64_F64_Bool(double a1, double a2, bool a3);
|
||||
private delegate int _S32_U64_U16(ulong a1, ushort a2);
|
||||
private delegate int _S32_U64_U32(ulong a1, uint a2);
|
||||
private delegate int _S32_U64_U64(ulong a1, ulong a2);
|
||||
private delegate int _S32_U64_U8(ulong a1, byte a2);
|
||||
private delegate int _S32_U64_V128(ulong a1, V128 a2);
|
||||
|
||||
private delegate long _S64_F32(float a1);
|
||||
private delegate long _S64_F64(double a1);
|
||||
private delegate long _S64_S64(long a1);
|
||||
private delegate long _S64_S64_S32(long a1, int a2);
|
||||
private delegate long _S64_S64_S64(long a1, long a2);
|
||||
private delegate long _S64_S64_S64_Bool_S32(long a1, long a2, bool a3, int a4);
|
||||
private delegate long _S64_S64_S64_S32(long a1, long a2, int a3);
|
||||
private delegate long _S64_U64_S32(ulong a1, int a2);
|
||||
private delegate long _S64_U64_S64(ulong a1, long a2);
|
||||
|
||||
private delegate ushort _U16_F32(float a1);
|
||||
private delegate ushort _U16_U64(ulong a1);
|
||||
|
||||
private delegate uint _U32_F32(float a1);
|
||||
private delegate uint _U32_F64(double a1);
|
||||
private delegate uint _U32_U32(uint a1);
|
||||
private delegate uint _U32_U32_U16(uint a1, ushort a2);
|
||||
private delegate uint _U32_U32_U32(uint a1, uint a2);
|
||||
private delegate uint _U32_U32_U64(uint a1, ulong a2);
|
||||
private delegate uint _U32_U32_U8(uint a1, byte a2);
|
||||
private delegate uint _U32_U64(ulong a1);
|
||||
|
||||
private delegate ulong _U64();
|
||||
private delegate ulong _U64_F32(float a1);
|
||||
private delegate ulong _U64_F64(double a1);
|
||||
private delegate ulong _U64_S64_S32(long a1, int a2);
|
||||
private delegate ulong _U64_S64_U64(long a1, ulong a2);
|
||||
private delegate ulong _U64_U64(ulong a1);
|
||||
private delegate ulong _U64_U64_S32(ulong a1, int a2);
|
||||
private delegate ulong _U64_U64_S64_S32(ulong a1, long a2, int a3);
|
||||
private delegate ulong _U64_U64_U64(ulong a1, ulong a2);
|
||||
private delegate ulong _U64_U64_U64_Bool_S32(ulong a1, ulong a2, bool a3, int a4);
|
||||
|
||||
private delegate byte _U8_U64(ulong a1);
|
||||
|
||||
private delegate V128 _V128_U64(ulong a1);
|
||||
private delegate V128 _V128_V128(V128 a1);
|
||||
private delegate V128 _V128_V128_U32_V128(V128 a1, uint a2, V128 a3);
|
||||
private delegate V128 _V128_V128_V128(V128 a1, V128 a2);
|
||||
private delegate V128 _V128_V128_V128_V128(V128 a1, V128 a2, V128 a3);
|
||||
private delegate V128 _V128_V128_V128_V128_V128(V128 a1, V128 a2, V128 a3, V128 a4);
|
||||
private delegate V128 _V128_V128_V128_V128_V128_V128(V128 a1, V128 a2, V128 a3, V128 a4, V128 a5);
|
||||
|
||||
private delegate void _Void();
|
||||
private delegate void _Void_U64(ulong a1);
|
||||
private delegate void _Void_U64_S32(ulong a1, int a2);
|
||||
private delegate void _Void_U64_U16(ulong a1, ushort a2);
|
||||
private delegate void _Void_U64_U32(ulong a1, uint a2);
|
||||
private delegate void _Void_U64_U64(ulong a1, ulong a2);
|
||||
private delegate void _Void_U64_U8(ulong a1, byte a2);
|
||||
private delegate void _Void_U64_V128(ulong a1, V128 a2);
|
||||
}
|
||||
}
|
|
@ -1,8 +1,7 @@
|
|||
using ARMeilleure.Instructions;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.State;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
|
||||
|
||||
|
@ -78,51 +77,40 @@ namespace ARMeilleure.Translation
|
|||
return Add(Instruction.ByteSwap, Local(op1.Type), op1);
|
||||
}
|
||||
|
||||
public Operand Call(Delegate func, params Operand[] callArgs)
|
||||
public Operand MathCall(string className, string funcName, params Operand[] callArgs)
|
||||
{
|
||||
// Add the delegate to the cache to ensure it will not be garbage collected.
|
||||
func = DelegateCache.GetOrAdd(func);
|
||||
string name = $"{className}.{funcName}";
|
||||
|
||||
IntPtr ptr = Marshal.GetFunctionPointerForDelegate<Delegate>(func);
|
||||
DelegateInfo dlgInfo = Delegates.GetMathDelegateInfo(name);
|
||||
|
||||
OperandType returnType = GetOperandType(func.Method.ReturnType);
|
||||
|
||||
return Call(Const(ptr.ToInt64()), returnType, callArgs);
|
||||
return Call(Const(dlgInfo.FuncPtr.ToInt64(), true, name), dlgInfo.RetType, callArgs);
|
||||
}
|
||||
|
||||
private static Dictionary<TypeCode, OperandType> _typeCodeToOperandTypeMap =
|
||||
new Dictionary<TypeCode, OperandType>()
|
||||
public Operand NativeInterfaceCall(string funcName, params Operand[] callArgs)
|
||||
{
|
||||
{ TypeCode.Boolean, OperandType.I32 },
|
||||
{ TypeCode.Byte, OperandType.I32 },
|
||||
{ TypeCode.Char, OperandType.I32 },
|
||||
{ TypeCode.Double, OperandType.FP64 },
|
||||
{ TypeCode.Int16, OperandType.I32 },
|
||||
{ TypeCode.Int32, OperandType.I32 },
|
||||
{ TypeCode.Int64, OperandType.I64 },
|
||||
{ TypeCode.SByte, OperandType.I32 },
|
||||
{ TypeCode.Single, OperandType.FP32 },
|
||||
{ TypeCode.UInt16, OperandType.I32 },
|
||||
{ TypeCode.UInt32, OperandType.I32 },
|
||||
{ TypeCode.UInt64, OperandType.I64 }
|
||||
};
|
||||
funcName = $"{nameof(NativeInterface)}.{funcName}";
|
||||
|
||||
private static OperandType GetOperandType(Type type)
|
||||
DelegateInfo dlgInfo = Delegates.GetNativeInterfaceDelegateInfo(funcName);
|
||||
|
||||
return Call(Const(dlgInfo.FuncPtr.ToInt64(), true, funcName), dlgInfo.RetType, callArgs);
|
||||
}
|
||||
|
||||
public Operand SoftFallbackCall(string funcName, params Operand[] callArgs)
|
||||
{
|
||||
if (_typeCodeToOperandTypeMap.TryGetValue(Type.GetTypeCode(type), out OperandType ot))
|
||||
{
|
||||
return ot;
|
||||
}
|
||||
else if (type == typeof(V128))
|
||||
{
|
||||
return OperandType.V128;
|
||||
}
|
||||
else if (type == typeof(void))
|
||||
{
|
||||
return OperandType.None;
|
||||
}
|
||||
funcName = $"{nameof(SoftFallback)}.{funcName}";
|
||||
|
||||
throw new ArgumentException($"Invalid type \"{type.Name}\".");
|
||||
DelegateInfo dlgInfo = Delegates.GetSoftFallbackDelegateInfo(funcName);
|
||||
|
||||
return Call(Const(dlgInfo.FuncPtr.ToInt64(), true, funcName), dlgInfo.RetType, callArgs);
|
||||
}
|
||||
|
||||
public Operand SoftFloatCall(string className, string funcName, params Operand[] callArgs)
|
||||
{
|
||||
string name = $"{className}.{funcName}";
|
||||
|
||||
DelegateInfo dlgInfo = Delegates.GetSoftFloatDelegateInfo(name);
|
||||
|
||||
return Call(Const(dlgInfo.FuncPtr.ToInt64(), true, name), dlgInfo.RetType, callArgs);
|
||||
}
|
||||
|
||||
public Operand Call(Operand address, OperandType returnType, params Operand[] callArgs)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using ARMeilleure.CodeGen;
|
||||
using ARMeilleure.Memory;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace ARMeilleure.Translation
|
||||
|
@ -11,7 +10,7 @@ namespace ARMeilleure.Translation
|
|||
private const int PageSize = 4 * 1024;
|
||||
private const int PageMask = PageSize - 1;
|
||||
|
||||
private const int CodeAlignment = 4; // Bytes
|
||||
private const int CodeAlignment = 4; // Bytes.
|
||||
|
||||
private const int CacheSize = 512 * 1024 * 1024;
|
||||
|
||||
|
@ -19,32 +18,32 @@ namespace ARMeilleure.Translation
|
|||
|
||||
private static int _offset;
|
||||
|
||||
private static List<JitCacheEntry> _cacheEntries;
|
||||
//private static List<JitCacheEntry> _cacheEntries;
|
||||
|
||||
private static object _lock;
|
||||
private static readonly object _locker;
|
||||
|
||||
static JitCache()
|
||||
{
|
||||
_basePointer = MemoryManagement.Allocate(CacheSize);
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
/*if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
JitUnwindWindows.InstallFunctionTableHandler(_basePointer, CacheSize);
|
||||
|
||||
// The first page is used for the table based SEH structs.
|
||||
_offset = PageSize;
|
||||
}
|
||||
}*/
|
||||
|
||||
_cacheEntries = new List<JitCacheEntry>();
|
||||
//_cacheEntries = new List<JitCacheEntry>();
|
||||
|
||||
_lock = new object();
|
||||
_locker = new object();
|
||||
}
|
||||
|
||||
public static IntPtr Map(CompiledFunction func)
|
||||
{
|
||||
byte[] code = func.Code;
|
||||
|
||||
lock (_lock)
|
||||
lock (_locker)
|
||||
{
|
||||
int funcOffset = Allocate(code.Length);
|
||||
|
||||
|
@ -54,7 +53,7 @@ namespace ARMeilleure.Translation
|
|||
|
||||
ReprotectRange(funcOffset, code.Length);
|
||||
|
||||
Add(new JitCacheEntry(funcOffset, code.Length, func.UnwindInfo));
|
||||
//Add(new JitCacheEntry(funcOffset, code.Length, func.UnwindInfo));
|
||||
|
||||
return funcPtr;
|
||||
}
|
||||
|
@ -105,14 +104,14 @@ namespace ARMeilleure.Translation
|
|||
return allocOffset;
|
||||
}
|
||||
|
||||
private static void Add(JitCacheEntry entry)
|
||||
/*private static void Add(JitCacheEntry entry)
|
||||
{
|
||||
_cacheEntries.Add(entry);
|
||||
}
|
||||
}*/
|
||||
|
||||
public static bool TryFind(int offset, out JitCacheEntry entry)
|
||||
/*public static bool TryFind(int offset, out JitCacheEntry entry)
|
||||
{
|
||||
lock (_lock)
|
||||
lock (_locker)
|
||||
{
|
||||
foreach (JitCacheEntry cacheEntry in _cacheEntries)
|
||||
{
|
||||
|
@ -130,6 +129,6 @@ namespace ARMeilleure.Translation
|
|||
entry = default(JitCacheEntry);
|
||||
|
||||
return false;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
using ARMeilleure.CodeGen.Unwinding;
|
||||
/*using ARMeilleure.CodeGen.Unwinding;
|
||||
|
||||
namespace ARMeilleure.Translation
|
||||
{
|
||||
|
@ -16,4 +16,4 @@ namespace ARMeilleure.Translation
|
|||
UnwindInfo = unwindInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
|
@ -1,4 +1,4 @@
|
|||
using ARMeilleure.IntermediateRepresentation;
|
||||
/*using ARMeilleure.IntermediateRepresentation;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
|
@ -161,4 +161,4 @@ namespace ARMeilleure.Translation
|
|||
return (ushort)(prologOffset | ((int)uwop << 8) | (opInfo << 12));
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
|
@ -1,4 +1,4 @@
|
|||
using System.Collections.Concurrent;
|
||||
/*using System.Collections.Concurrent; // TODO: For future use.
|
||||
|
||||
namespace ARMeilleure.Translation
|
||||
{
|
||||
|
@ -35,5 +35,17 @@ namespace ARMeilleure.Translation
|
|||
|
||||
return false;
|
||||
}
|
||||
|
||||
public int GetQueuesCount()
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
for (int index = 0; index < _queues.Length; index++)
|
||||
{
|
||||
count += _queues[index].Count;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
|
@ -1,15 +1,10 @@
|
|||
using System.Threading;
|
||||
|
||||
namespace ARMeilleure.Translation
|
||||
{
|
||||
class TranslatedFunction
|
||||
{
|
||||
private const int MinCallsForRejit = 100;
|
||||
|
||||
private GuestFunction _func;
|
||||
|
||||
private bool _rejit;
|
||||
private int _callCount;
|
||||
|
||||
public TranslatedFunction(GuestFunction func, bool rejit)
|
||||
{
|
||||
|
@ -22,9 +17,14 @@ namespace ARMeilleure.Translation
|
|||
return _func(context.NativeContextPtr);
|
||||
}
|
||||
|
||||
public bool ShouldRejit()
|
||||
public bool GetRejit()
|
||||
{
|
||||
return _rejit && Interlocked.Increment(ref _callCount) == MinCallsForRejit;
|
||||
return _rejit;
|
||||
}
|
||||
|
||||
public void ResetRejit()
|
||||
{
|
||||
_rejit = false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -6,21 +6,28 @@ using ARMeilleure.Memory;
|
|||
using ARMeilleure.State;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
|
||||
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
|
||||
|
||||
namespace ARMeilleure.Translation
|
||||
{
|
||||
using AOT;
|
||||
|
||||
public class Translator : ITranslator
|
||||
{
|
||||
private const ulong CallFlag = InstEmitFlowHelper.CallFlag;
|
||||
|
||||
private MemoryManager _memory;
|
||||
|
||||
private ConcurrentDictionary<ulong, TranslatedFunction> _funcs;
|
||||
private readonly object _locker;
|
||||
|
||||
private PriorityQueue<ulong> _backgroundQueue;
|
||||
private Dictionary<ulong, TranslatedFunction> _funcs;
|
||||
private ConcurrentDictionary<ulong, TranslatedFunction> _funcsHighCq;
|
||||
|
||||
private ConcurrentQueue<ulong> _backgroundQueue;
|
||||
|
||||
private AutoResetEvent _backgroundTranslatorEvent;
|
||||
|
||||
|
@ -30,9 +37,14 @@ namespace ARMeilleure.Translation
|
|||
{
|
||||
_memory = memory;
|
||||
|
||||
_funcs = new ConcurrentDictionary<ulong, TranslatedFunction>();
|
||||
_locker = new object();
|
||||
|
||||
_backgroundQueue = new PriorityQueue<ulong>(2);
|
||||
_funcs = new Dictionary<ulong, TranslatedFunction>();
|
||||
_funcsHighCq = new ConcurrentDictionary<ulong, TranslatedFunction>();
|
||||
|
||||
Aot.FullTranslate(_funcsHighCq);
|
||||
|
||||
_backgroundQueue = new ConcurrentQueue<ulong>();
|
||||
|
||||
_backgroundTranslatorEvent = new AutoResetEvent(false);
|
||||
}
|
||||
|
@ -45,7 +57,9 @@ namespace ARMeilleure.Translation
|
|||
{
|
||||
TranslatedFunction func = Translate(address, ExecutionMode.Aarch64, highCq: true);
|
||||
|
||||
_funcs.AddOrUpdate(address, func, (key, oldFunc) => func);
|
||||
bool isAddressUnique = _funcsHighCq.TryAdd(address, func);
|
||||
|
||||
Debug.Assert(isAddressUnique, $"The address 0x{address:X16} is not unique.");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -99,23 +113,38 @@ namespace ARMeilleure.Translation
|
|||
|
||||
private TranslatedFunction GetOrTranslate(ulong address, ExecutionMode mode)
|
||||
{
|
||||
const int MaxQueueCount = 300;
|
||||
|
||||
// TODO: Investigate how we should handle code at unaligned addresses.
|
||||
// Currently, those low bits are used to store special flags.
|
||||
bool isCallTarget = (address & CallFlag) != 0;
|
||||
|
||||
address &= ~CallFlag;
|
||||
|
||||
if (!_funcs.TryGetValue(address, out TranslatedFunction func))
|
||||
{
|
||||
func = Translate(address, mode, highCq: false);
|
||||
TranslatedFunction func;
|
||||
|
||||
_funcs.TryAdd(address, func);
|
||||
}
|
||||
else if (isCallTarget && func.ShouldRejit())
|
||||
if (!isCallTarget || !_funcsHighCq.TryGetValue(address, out func))
|
||||
{
|
||||
_backgroundQueue.Enqueue(0, address);
|
||||
lock (_locker)
|
||||
{
|
||||
if (!_funcs.TryGetValue(address, out func))
|
||||
{
|
||||
func = Translate(address, mode, highCq: false);
|
||||
|
||||
_backgroundTranslatorEvent.Set();
|
||||
bool isAddressUnique = _funcs.TryAdd(address, func);
|
||||
|
||||
Debug.Assert(isAddressUnique, $"The address 0x{address:X16} is not unique.");
|
||||
}
|
||||
|
||||
if (isCallTarget && func.GetRejit() && _backgroundQueue.Count < MaxQueueCount)
|
||||
{
|
||||
func.ResetRejit();
|
||||
|
||||
_backgroundQueue.Enqueue(address);
|
||||
|
||||
_backgroundTranslatorEvent.Set();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return func;
|
||||
|
@ -154,11 +183,32 @@ namespace ARMeilleure.Translation
|
|||
|
||||
OperandType[] argTypes = new OperandType[] { OperandType.I64 };
|
||||
|
||||
CompilerOptions options = highCq
|
||||
? CompilerOptions.HighCq
|
||||
: CompilerOptions.None;
|
||||
GuestFunction func;
|
||||
|
||||
GuestFunction func = Compiler.Compile<GuestFunction>(cfg, argTypes, OperandType.I64, options);
|
||||
if (highCq)
|
||||
{
|
||||
if (Aot.Enabled)
|
||||
{
|
||||
AotInfo aotInfo = new AotInfo();
|
||||
|
||||
func = Compiler.Compile<GuestFunction>(cfg, argTypes, OperandType.I64, CompilerOptions.HighCq, aotInfo);
|
||||
|
||||
if (aotInfo.CodeStream.Length >= Aot.MinCodeLengthToSave)
|
||||
{
|
||||
Aot.WriteInfoCodeReloc((long)address, aotInfo);
|
||||
}
|
||||
|
||||
aotInfo.Dispose();
|
||||
}
|
||||
else
|
||||
{
|
||||
func = Compiler.Compile<GuestFunction>(cfg, argTypes, OperandType.I64, CompilerOptions.HighCq);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
func = Compiler.Compile<GuestFunction>(cfg, argTypes, OperandType.I64, CompilerOptions.None);
|
||||
}
|
||||
|
||||
return new TranslatedFunction(func, rejit: !highCq);
|
||||
}
|
||||
|
@ -237,7 +287,7 @@ namespace ARMeilleure.Translation
|
|||
|
||||
context.BranchIfTrue(lblNonZero, count);
|
||||
|
||||
context.Call(new _Void(NativeInterface.CheckSynchronization));
|
||||
context.NativeInterfaceCall(nameof(NativeInterface.CheckSynchronization));
|
||||
|
||||
context.Branch(lblExit);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue