diff --git a/ARMeilleure/CodeGen/CompiledFunction.cs b/ARMeilleure/CodeGen/CompiledFunction.cs index 61e89c2401..a0087d216f 100644 --- a/ARMeilleure/CodeGen/CompiledFunction.cs +++ b/ARMeilleure/CodeGen/CompiledFunction.cs @@ -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; } } } \ No newline at end of file diff --git a/ARMeilleure/CodeGen/Optimizations/ConstantFolding.cs b/ARMeilleure/CodeGen/Optimizations/ConstantFolding.cs index 84eedee0e5..eff53217ff 100644 --- a/ARMeilleure/CodeGen/Optimizations/ConstantFolding.cs +++ b/ARMeilleure/CodeGen/Optimizations/ConstantFolding.cs @@ -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; } diff --git a/ARMeilleure/CodeGen/Unwinding/UnwindInfo.cs b/ARMeilleure/CodeGen/Unwinding/UnwindInfo.cs index 4955f1b4a5..162cd1c99a 100644 --- a/ARMeilleure/CodeGen/Unwinding/UnwindInfo.cs +++ b/ARMeilleure/CodeGen/Unwinding/UnwindInfo.cs @@ -1,4 +1,4 @@ -namespace ARMeilleure.CodeGen.Unwinding +/*namespace ARMeilleure.CodeGen.Unwinding { struct UnwindInfo { @@ -15,4 +15,4 @@ namespace ARMeilleure.CodeGen.Unwinding FixedAllocSize = fixedAllocSize; } } -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/ARMeilleure/CodeGen/Unwinding/UnwindPushEntry.cs b/ARMeilleure/CodeGen/Unwinding/UnwindPushEntry.cs index 6597e2b4b9..d62d2ac140 100644 --- a/ARMeilleure/CodeGen/Unwinding/UnwindPushEntry.cs +++ b/ARMeilleure/CodeGen/Unwinding/UnwindPushEntry.cs @@ -1,4 +1,4 @@ -using ARMeilleure.IntermediateRepresentation; +/*using ARMeilleure.IntermediateRepresentation; namespace ARMeilleure.CodeGen.Unwinding { @@ -17,4 +17,4 @@ namespace ARMeilleure.CodeGen.Unwinding StreamEndOffset = streamEndOffset; } } -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/ARMeilleure/CodeGen/X86/Assembler.cs b/ARMeilleure/CodeGen/X86/Assembler.cs index c64838945f..a8965d36d3 100644 --- a/ARMeilleure/CodeGen/X86/Assembler.cs +++ b/ARMeilleure/CodeGen/X86/Assembler.cs @@ -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; diff --git a/ARMeilleure/CodeGen/X86/CodeGenContext.cs b/ARMeilleure/CodeGen/X86/CodeGenContext.cs index d719b51640..e76439df0a 100644 --- a/ARMeilleure/CodeGen/X86/CodeGenContext.cs +++ b/ARMeilleure/CodeGen/X86/CodeGenContext.cs @@ -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(); + + _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(); } } diff --git a/ARMeilleure/CodeGen/X86/CodeGenerator.cs b/ARMeilleure/CodeGen/X86/CodeGenerator.cs index ae24b5631a..f56f91b6e0 100644 --- a/ARMeilleure/CodeGen/X86/CodeGenerator.cs +++ b/ARMeilleure/CodeGen/X86/CodeGenerator.cs @@ -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 pushEntries = new List(); + //List pushEntries = new List(); 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) diff --git a/ARMeilleure/Instructions/InstEmitAlu.cs b/ARMeilleure/Instructions/InstEmitAlu.cs index 947c9f70bf..3d3e82a2fc 100644 --- a/ARMeilleure/Instructions/InstEmitAlu.cs +++ b/ARMeilleure/Instructions/InstEmitAlu.cs @@ -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); } diff --git a/ARMeilleure/Instructions/InstEmitException.cs b/ARMeilleure/Instructions/InstEmitException.cs index 6f7b6fd51f..f2bd1e6bc3 100644 --- a/ARMeilleure/Instructions/InstEmitException.cs +++ b/ARMeilleure/Instructions/InstEmitException.cs @@ -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(); diff --git a/ARMeilleure/Instructions/InstEmitHash.cs b/ARMeilleure/Instructions/InstEmitHash.cs index 0be8458e20..3edfff4109 100644 --- a/ARMeilleure/Instructions/InstEmitHash.cs +++ b/ARMeilleure/Instructions/InstEmitHash.cs @@ -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); } diff --git a/ARMeilleure/Instructions/InstEmitMemoryEx.cs b/ARMeilleure/Instructions/InstEmitMemoryEx.cs index bcca7619d2..1a6ca082b1 100644 --- a/ARMeilleure/Instructions/InstEmitMemoryEx.cs +++ b/ARMeilleure/Instructions/InstEmitMemoryEx.cs @@ -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; } diff --git a/ARMeilleure/Instructions/InstEmitMemoryHelper.cs b/ARMeilleure/Instructions/InstEmitMemoryHelper.cs index 0ae5e3f26a..2f9464fb87 100644 --- a/ARMeilleure/Instructions/InstEmitMemoryHelper.cs +++ b/ARMeilleure/Instructions/InstEmitMemoryHelper.cs @@ -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) diff --git a/ARMeilleure/Instructions/InstEmitSimdArithmetic.cs b/ARMeilleure/Instructions/InstEmitSimdArithmetic.cs index 44659e8057..aff0cf8c48 100644 --- a/ARMeilleure/Instructions/InstEmitSimdArithmetic.cs +++ b/ARMeilleure/Instructions/InstEmitSimdArithmetic.cs @@ -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) diff --git a/ARMeilleure/Instructions/InstEmitSimdCmp.cs b/ARMeilleure/Instructions/InstEmitSimdCmp.cs index f27121bb33..55b62001e0 100644 --- a/ARMeilleure/Instructions/InstEmitSimdCmp.cs +++ b/ARMeilleure/Instructions/InstEmitSimdCmp.cs @@ -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); } diff --git a/ARMeilleure/Instructions/InstEmitSimdCrypto.cs b/ARMeilleure/Instructions/InstEmitSimdCrypto.cs index 2b61fadac1..f7be3e76e6 100644 --- a/ARMeilleure/Instructions/InstEmitSimdCrypto.cs +++ b/ARMeilleure/Instructions/InstEmitSimdCrypto.cs @@ -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)); } } } diff --git a/ARMeilleure/Instructions/InstEmitSimdCvt.cs b/ARMeilleure/Instructions/InstEmitSimdCvt.cs index 012bfcce2a..d7925dea6e 100644 --- a/ARMeilleure/Instructions/InstEmitSimdCvt.cs +++ b/ARMeilleure/Instructions/InstEmitSimdCvt.cs @@ -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) diff --git a/ARMeilleure/Instructions/InstEmitSimdHash.cs b/ARMeilleure/Instructions/InstEmitSimdHash.cs index 4ed960612f..f24938a759 100644 --- a/ARMeilleure/Instructions/InstEmitSimdHash.cs +++ b/ARMeilleure/Instructions/InstEmitSimdHash.cs @@ -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); } diff --git a/ARMeilleure/Instructions/InstEmitSimdHelper.cs b/ARMeilleure/Instructions/InstEmitSimdHelper.cs index a3da80fb0d..3105c1a97f 100644 --- a/ARMeilleure/Instructions/InstEmitSimdHelper.cs +++ b/ARMeilleure/Instructions/InstEmitSimdHelper.cs @@ -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) diff --git a/ARMeilleure/Instructions/InstEmitSimdLogical.cs b/ARMeilleure/Instructions/InstEmitSimdLogical.cs index 551752d240..47529e7b68 100644 --- a/ARMeilleure/Instructions/InstEmitSimdLogical.cs +++ b/ARMeilleure/Instructions/InstEmitSimdLogical.cs @@ -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); diff --git a/ARMeilleure/Instructions/InstEmitSimdMove.cs b/ARMeilleure/Instructions/InstEmitSimdMove.cs index 47359161fb..c14721c6c7 100644 --- a/ARMeilleure/Instructions/InstEmitSimdMove.cs +++ b/ARMeilleure/Instructions/InstEmitSimdMove.cs @@ -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)); } } diff --git a/ARMeilleure/Instructions/InstEmitSimdShift.cs b/ARMeilleure/Instructions/InstEmitSimdShift.cs index 1aae491dfd..87db234aaf 100644 --- a/ARMeilleure/Instructions/InstEmitSimdShift.cs +++ b/ARMeilleure/Instructions/InstEmitSimdShift.cs @@ -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) diff --git a/ARMeilleure/Instructions/InstEmitSystem.cs b/ARMeilleure/Instructions/InstEmitSystem.cs index eeb53c1fe3..d8769c1861 100644 --- a/ARMeilleure/Instructions/InstEmitSystem.cs +++ b/ARMeilleure/Instructions/InstEmitSystem.cs @@ -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; diff --git a/ARMeilleure/Instructions/SoftFallback.cs b/ARMeilleure/Instructions/SoftFallback.cs index dc0309218b..549f076218 100644 --- a/ARMeilleure/Instructions/SoftFallback.cs +++ b/ARMeilleure/Instructions/SoftFallback.cs @@ -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 } } diff --git a/ARMeilleure/IntermediateRepresentation/Operand.cs b/ARMeilleure/IntermediateRepresentation/Operand.cs index 2df6256fc6..a98e2d53b2 100644 --- a/ARMeilleure/IntermediateRepresentation/Operand.cs +++ b/ARMeilleure/IntermediateRepresentation/Operand.cs @@ -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 Assignments { get; } public LinkedList 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) diff --git a/ARMeilleure/IntermediateRepresentation/OperandHelper.cs b/ARMeilleure/IntermediateRepresentation/OperandHelper.cs index 4a930e03f4..9d6f00c335 100644 --- a/ARMeilleure/IntermediateRepresentation/OperandHelper.cs +++ b/ARMeilleure/IntermediateRepresentation/OperandHelper.cs @@ -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) diff --git a/ARMeilleure/Memory/MemoryManager.cs b/ARMeilleure/Memory/MemoryManager.cs index 12c1184373..17638e463d 100644 --- a/ARMeilleure/Memory/MemoryManager.cs +++ b/ARMeilleure/Memory/MemoryManager.cs @@ -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) diff --git a/ARMeilleure/Translation/AOT/Aot.cs b/ARMeilleure/Translation/AOT/Aot.cs new file mode 100644 index 0000000000..c0bb458578 --- /dev/null +++ b/ARMeilleure/Translation/AOT/Aot.cs @@ -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 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(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; + } + } + } + } +} \ No newline at end of file diff --git a/ARMeilleure/Translation/AOT/AotInfo.cs b/ARMeilleure/Translation/AOT/AotInfo.cs new file mode 100644 index 0000000000..16f4150c83 --- /dev/null +++ b/ARMeilleure/Translation/AOT/AotInfo.cs @@ -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(); + } + } +} \ No newline at end of file diff --git a/ARMeilleure/Translation/AOT/EncodingCache.cs b/ARMeilleure/Translation/AOT/EncodingCache.cs new file mode 100644 index 0000000000..57229b088f --- /dev/null +++ b/ARMeilleure/Translation/AOT/EncodingCache.cs @@ -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); + } +} \ No newline at end of file diff --git a/ARMeilleure/Translation/AOT/RelocEntry.cs b/ARMeilleure/Translation/AOT/RelocEntry.cs new file mode 100644 index 0000000000..cd9c9d7918 --- /dev/null +++ b/ARMeilleure/Translation/AOT/RelocEntry.cs @@ -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; + } + } +} \ No newline at end of file diff --git a/ARMeilleure/Translation/Compiler.cs b/ARMeilleure/Translation/Compiler.cs index 4075a7f069..99990ee477 100644 --- a/ARMeilleure/Translation/Compiler.cs +++ b/ARMeilleure/Translation/Compiler.cs @@ -7,13 +7,16 @@ using System.Runtime.InteropServices; namespace ARMeilleure.Translation { + using AOT; + static class Compiler { public static T Compile( 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); diff --git a/ARMeilleure/Translation/DelegateInfo.cs b/ARMeilleure/Translation/DelegateInfo.cs new file mode 100644 index 0000000000..9ba3b183ee --- /dev/null +++ b/ARMeilleure/Translation/DelegateInfo.cs @@ -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(_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}\"."); + } + } + } +} \ No newline at end of file diff --git a/ARMeilleure/Translation/Delegates.cs b/ARMeilleure/Translation/Delegates.cs new file mode 100644 index 0000000000..8dbf10dddc --- /dev/null +++ b/ARMeilleure/Translation/Delegates.cs @@ -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 _mathDelegates; + private static readonly Dictionary _nativeInterfaceDelegates; + private static readonly Dictionary _softFallbackDelegates; + private static readonly Dictionary _softFloatDelegates; + + static Delegates() + { + _mathDelegates = new Dictionary(); + _nativeInterfaceDelegates = new Dictionary(); + _softFallbackDelegates = new Dictionary(); + _softFloatDelegates = new Dictionary(); + + 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); + } +} \ No newline at end of file diff --git a/ARMeilleure/Translation/EmitterContext.cs b/ARMeilleure/Translation/EmitterContext.cs index 13cf677c77..af1764ca82 100644 --- a/ARMeilleure/Translation/EmitterContext.cs +++ b/ARMeilleure/Translation/EmitterContext.cs @@ -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(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 _typeCodeToOperandTypeMap = - new Dictionary() + 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) diff --git a/ARMeilleure/Translation/JitCache.cs b/ARMeilleure/Translation/JitCache.cs index 73f04a966d..dc00b6d8a4 100644 --- a/ARMeilleure/Translation/JitCache.cs +++ b/ARMeilleure/Translation/JitCache.cs @@ -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 _cacheEntries; + //private static List _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(); + //_cacheEntries = new List(); - _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; - } + }*/ } } \ No newline at end of file diff --git a/ARMeilleure/Translation/JitCacheEntry.cs b/ARMeilleure/Translation/JitCacheEntry.cs index 87d020e683..298e3a9f35 100644 --- a/ARMeilleure/Translation/JitCacheEntry.cs +++ b/ARMeilleure/Translation/JitCacheEntry.cs @@ -1,4 +1,4 @@ -using ARMeilleure.CodeGen.Unwinding; +/*using ARMeilleure.CodeGen.Unwinding; namespace ARMeilleure.Translation { @@ -16,4 +16,4 @@ namespace ARMeilleure.Translation UnwindInfo = unwindInfo; } } -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/ARMeilleure/Translation/JitUnwindWindows.cs b/ARMeilleure/Translation/JitUnwindWindows.cs index 108dc2c560..6aa9bd5081 100644 --- a/ARMeilleure/Translation/JitUnwindWindows.cs +++ b/ARMeilleure/Translation/JitUnwindWindows.cs @@ -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)); } } -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/ARMeilleure/Translation/PriorityQueue.cs b/ARMeilleure/Translation/PriorityQueue.cs index ab593dc07f..aa45fe24bf 100644 --- a/ARMeilleure/Translation/PriorityQueue.cs +++ b/ARMeilleure/Translation/PriorityQueue.cs @@ -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; + } } -} \ No newline at end of file +}*/ \ No newline at end of file diff --git a/ARMeilleure/Translation/TranslatedFunction.cs b/ARMeilleure/Translation/TranslatedFunction.cs index 06069cf8fe..6b03c4f1b2 100644 --- a/ARMeilleure/Translation/TranslatedFunction.cs +++ b/ARMeilleure/Translation/TranslatedFunction.cs @@ -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; } } } \ No newline at end of file diff --git a/ARMeilleure/Translation/Translator.cs b/ARMeilleure/Translation/Translator.cs index 6a74512141..eb88385518 100644 --- a/ARMeilleure/Translation/Translator.cs +++ b/ARMeilleure/Translation/Translator.cs @@ -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 _funcs; + private readonly object _locker; - private PriorityQueue _backgroundQueue; + private Dictionary _funcs; + private ConcurrentDictionary _funcsHighCq; + + private ConcurrentQueue _backgroundQueue; private AutoResetEvent _backgroundTranslatorEvent; @@ -30,9 +37,14 @@ namespace ARMeilleure.Translation { _memory = memory; - _funcs = new ConcurrentDictionary(); + _locker = new object(); - _backgroundQueue = new PriorityQueue(2); + _funcs = new Dictionary(); + _funcsHighCq = new ConcurrentDictionary(); + + Aot.FullTranslate(_funcsHighCq); + + _backgroundQueue = new ConcurrentQueue(); _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(cfg, argTypes, OperandType.I64, options); + if (highCq) + { + if (Aot.Enabled) + { + AotInfo aotInfo = new AotInfo(); + + func = Compiler.Compile(cfg, argTypes, OperandType.I64, CompilerOptions.HighCq, aotInfo); + + if (aotInfo.CodeStream.Length >= Aot.MinCodeLengthToSave) + { + Aot.WriteInfoCodeReloc((long)address, aotInfo); + } + + aotInfo.Dispose(); + } + else + { + func = Compiler.Compile(cfg, argTypes, OperandType.I64, CompilerOptions.HighCq); + } + } + else + { + func = Compiler.Compile(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);