Add files via upload

This commit is contained in:
LDj3SNuD 2019-09-10 23:09:37 +02:00 committed by GitHub
parent ca736aba5d
commit 385799d8d9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
40 changed files with 1432 additions and 660 deletions

View file

@ -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;
}
}
}

View file

@ -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;
}

View file

@ -1,4 +1,4 @@
namespace ARMeilleure.CodeGen.Unwinding
/*namespace ARMeilleure.CodeGen.Unwinding
{
struct UnwindInfo
{
@ -15,4 +15,4 @@ namespace ARMeilleure.CodeGen.Unwinding
FixedAllocSize = fixedAllocSize;
}
}
}
}*/

View file

@ -1,4 +1,4 @@
using ARMeilleure.IntermediateRepresentation;
/*using ARMeilleure.IntermediateRepresentation;
namespace ARMeilleure.CodeGen.Unwinding
{
@ -17,4 +17,4 @@ namespace ARMeilleure.CodeGen.Unwinding
StreamEndOffset = streamEndOffset;
}
}
}
}*/

View file

@ -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;

View file

@ -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();
}
}

View file

@ -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)

View file

@ -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);
}

View file

@ -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();

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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)

View file

@ -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)

View file

@ -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);
}

View file

@ -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));
}
}
}

View file

@ -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)

View file

@ -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);
}

View file

@ -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)

View file

@ -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);

View file

@ -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));
}
}

View file

@ -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)

View file

@ -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;

View file

@ -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
}
}

View file

@ -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)

View file

@ -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)

View file

@ -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)

View 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;
}
}
}
}
}

View 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();
}
}
}

View 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);
}
}

View 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;
}
}
}

View file

@ -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);

View 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}\".");
}
}
}
}

View 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);
}
}

View file

@ -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)

View file

@ -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;
}
}*/
}
}

View file

@ -1,4 +1,4 @@
using ARMeilleure.CodeGen.Unwinding;
/*using ARMeilleure.CodeGen.Unwinding;
namespace ARMeilleure.Translation
{
@ -16,4 +16,4 @@ namespace ARMeilleure.Translation
UnwindInfo = unwindInfo;
}
}
}
}*/

View file

@ -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));
}
}
}
}*/

View file

@ -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;
}
}
}
}*/

View file

@ -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;
}
}
}

View file

@ -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);