mirror of
https://github.com/Ryujinx/Ryujinx.git
synced 2024-12-27 09:59:33 +01:00
[ARMeilleure] Address dotnet-format issues (#5357)
* dotnet format style --severity info Some changes were manually reverted. * dotnet format analyzers --serverity info Some changes have been minimally adapted. * Restore a few unused methods and variables * Silence dotnet format IDE0060 warnings * Silence dotnet format IDE0052 warnings * Address or silence dotnet format IDE1006 warnings * Address or silence dotnet format CA2208 warnings * Address dotnet format CA1822 warnings * Address or silence dotnet format CA1069 warnings * Silence CA1806 and CA1834 issues * Address dotnet format CA1401 warnings * Fix new dotnet-format issues after rebase * Address review comments * Address dotnet format CA2208 warnings properly * Fix formatting for switch expressions * Address most dotnet format whitespace warnings * Apply dotnet format whitespace formatting A few of them have been manually reverted and the corresponding warning was silenced * Add previously silenced warnings back I have no clue how these disappeared * Revert formatting changes for OpCodeTable.cs * Enable formatting for a few cases again * Format if-blocks correctly * Enable formatting for a few more cases again * Fix inline comment alignment * Run dotnet format after rebase and remove unused usings - analyzers - style - whitespace * Disable 'prefer switch expression' rule * Add comments to disabled warnings * Remove a few unused parameters * Adjust namespaces * Simplify properties and array initialization, Use const when possible, Remove trailing commas * Start working on disabled warnings * Fix and silence a few dotnet-format warnings again * Address IDE0251 warnings * Address a few disabled IDE0060 warnings * Silence IDE0060 in .editorconfig * Revert "Simplify properties and array initialization, Use const when possible, Remove trailing commas" This reverts commit 9462e4136c0a2100dc28b20cf9542e06790aa67e. * dotnet format whitespace after rebase * First dotnet format pass * Remove unnecessary formatting exclusion * Add unsafe dotnet format changes * Change visibility of JitSupportDarwin to internal
This commit is contained in:
parent
2de78a2d55
commit
ff53dcf560
300 changed files with 3515 additions and 3120 deletions
|
@ -23,10 +23,7 @@ namespace ARMeilleure
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static ArenaAllocator GetAllocator(ref ArenaAllocator alloc, uint pageSize, uint pageCount)
|
||||
{
|
||||
if (alloc == null)
|
||||
{
|
||||
alloc = new ArenaAllocator(pageSize, pageCount);
|
||||
}
|
||||
alloc ??= new ArenaAllocator(pageSize, pageCount);
|
||||
|
||||
return alloc;
|
||||
}
|
||||
|
|
|
@ -221,7 +221,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
2 => Multiplier.x4,
|
||||
3 => Multiplier.x8,
|
||||
4 => Multiplier.x16,
|
||||
_ => Multiplier.x1
|
||||
_ => Multiplier.x1,
|
||||
};
|
||||
|
||||
baseOp = indexOnSrc2 ? src1 : src2;
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
Gt = 12,
|
||||
Le = 13,
|
||||
Al = 14,
|
||||
Nv = 15
|
||||
Nv = 15,
|
||||
}
|
||||
|
||||
static class ComparisonArm64Extensions
|
||||
|
@ -29,6 +29,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
{
|
||||
return comp switch
|
||||
{
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
Comparison.Equal => ArmCondition.Eq,
|
||||
Comparison.NotEqual => ArmCondition.Ne,
|
||||
Comparison.Greater => ArmCondition.Gt,
|
||||
|
@ -39,8 +40,9 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
Comparison.Less => ArmCondition.Lt,
|
||||
Comparison.GreaterOrEqualUI => ArmCondition.GeUn,
|
||||
Comparison.LessUI => ArmCondition.LtUn,
|
||||
#pragma warning restore IDE0055
|
||||
|
||||
_ => throw new ArgumentException(null, nameof(comp))
|
||||
_ => throw new ArgumentException(null, nameof(comp)),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,6 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
Sxtb = 4,
|
||||
Sxth = 5,
|
||||
Sxtw = 6,
|
||||
Sxtx = 7
|
||||
Sxtx = 7,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,6 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
Lsl = 0,
|
||||
Lsr = 1,
|
||||
Asr = 2,
|
||||
Ror = 3
|
||||
Ror = 3,
|
||||
}
|
||||
}
|
|
@ -992,7 +992,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
{
|
||||
OperandType.FP32 => 0,
|
||||
OperandType.FP64 => 1,
|
||||
_ => 2
|
||||
_ => 2,
|
||||
};
|
||||
|
||||
instruction = vecInst | ((uint)opc << 30);
|
||||
|
@ -1124,10 +1124,11 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
OperandType.FP32 => 2,
|
||||
OperandType.FP64 => 3,
|
||||
OperandType.V128 => 4,
|
||||
_ => throw new ArgumentException($"Invalid type {type}.")
|
||||
_ => throw new ArgumentException($"Invalid type {type}."),
|
||||
};
|
||||
}
|
||||
|
||||
#pragma warning disable IDE0051 // Remove unused private member
|
||||
private void WriteInt16(short value)
|
||||
{
|
||||
WriteUInt16((ushort)value);
|
||||
|
@ -1142,6 +1143,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
{
|
||||
_stream.WriteByte(value);
|
||||
}
|
||||
#pragma warning restore IDE0051
|
||||
|
||||
private void WriteUInt16(ushort value)
|
||||
{
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
private const int CbnzInstLength = 4;
|
||||
private const int LdrLitInstLength = 4;
|
||||
|
||||
private Stream _stream;
|
||||
private readonly Stream _stream;
|
||||
|
||||
public int StreamOffset => (int)_stream.Length;
|
||||
|
||||
|
@ -32,7 +32,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
private readonly Dictionary<BasicBlock, long> _visitedBlocks;
|
||||
private readonly Dictionary<BasicBlock, List<(ArmCondition Condition, long BranchPos)>> _pendingBranches;
|
||||
|
||||
private struct ConstantPoolEntry
|
||||
private readonly struct ConstantPoolEntry
|
||||
{
|
||||
public readonly int Offset;
|
||||
public readonly Symbol Symbol;
|
||||
|
@ -58,7 +58,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
|
||||
private readonly bool _relocatable;
|
||||
|
||||
public CodeGenContext(AllocationResult allocResult, int maxCallArgs, int blocksCount, bool relocatable)
|
||||
public CodeGenContext(AllocationResult allocResult, int maxCallArgs, bool relocatable)
|
||||
{
|
||||
_stream = MemoryStreamManager.Shared.GetStream();
|
||||
|
||||
|
@ -93,10 +93,10 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
|
||||
if (_pendingBranches.TryGetValue(block, out var list))
|
||||
{
|
||||
foreach (var tuple in list)
|
||||
foreach ((ArmCondition condition, long branchPos) in list)
|
||||
{
|
||||
_stream.Seek(tuple.BranchPos, SeekOrigin.Begin);
|
||||
WriteBranch(tuple.Condition, target);
|
||||
_stream.Seek(branchPos, SeekOrigin.Begin);
|
||||
WriteBranch(condition, target);
|
||||
}
|
||||
|
||||
_stream.Seek(target, SeekOrigin.Begin);
|
||||
|
|
|
@ -10,7 +10,6 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Numerics;
|
||||
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
||||
|
@ -31,15 +30,16 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
{
|
||||
Byte,
|
||||
Hword,
|
||||
Auto
|
||||
Auto,
|
||||
}
|
||||
|
||||
private static Action<CodeGenContext, Operation>[] _instTable;
|
||||
private static readonly Action<CodeGenContext, Operation>[] _instTable;
|
||||
|
||||
static CodeGenerator()
|
||||
{
|
||||
_instTable = new Action<CodeGenContext, Operation>[EnumUtils.GetCount(typeof(Instruction))];
|
||||
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
Add(Instruction.Add, GenerateAdd);
|
||||
Add(Instruction.BitwiseAnd, GenerateBitwiseAnd);
|
||||
Add(Instruction.BitwiseExclusiveOr, GenerateBitwiseExclusiveOr);
|
||||
|
@ -48,7 +48,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
Add(Instruction.BranchIf, GenerateBranchIf);
|
||||
Add(Instruction.ByteSwap, GenerateByteSwap);
|
||||
Add(Instruction.Call, GenerateCall);
|
||||
//Add(Instruction.Clobber, GenerateClobber);
|
||||
// Add(Instruction.Clobber, GenerateClobber);
|
||||
Add(Instruction.Compare, GenerateCompare);
|
||||
Add(Instruction.CompareAndSwap, GenerateCompareAndSwap);
|
||||
Add(Instruction.CompareAndSwap16, GenerateCompareAndSwap16);
|
||||
|
@ -100,6 +100,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
Add(Instruction.ZeroExtend16, GenerateZeroExtend16);
|
||||
Add(Instruction.ZeroExtend32, GenerateZeroExtend32);
|
||||
Add(Instruction.ZeroExtend8, GenerateZeroExtend8);
|
||||
#pragma warning restore IDE0055
|
||||
|
||||
static void Add(Instruction inst, Action<CodeGenContext, Operation> func)
|
||||
{
|
||||
|
@ -131,7 +132,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
|
||||
StackAllocator stackAlloc = new();
|
||||
|
||||
PreAllocator.RunPass(cctx, stackAlloc, out int maxCallArgs);
|
||||
PreAllocator.RunPass(cctx, out int maxCallArgs);
|
||||
|
||||
Logger.EndPass(PassName.PreAllocation, cfg);
|
||||
|
||||
|
@ -170,7 +171,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
|
||||
bool relocatable = (cctx.Options & CompilerOptions.Relocatable) != 0;
|
||||
|
||||
CodeGenContext context = new(allocResult, maxCallArgs, cfg.Blocks.Count, relocatable);
|
||||
CodeGenContext context = new(allocResult, maxCallArgs, relocatable);
|
||||
|
||||
UnwindInfo unwindInfo = WritePrologue(context);
|
||||
|
||||
|
@ -444,7 +445,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
Debug.Assert(dest.Type.IsInteger());
|
||||
Debug.Assert(src1.Type == OperandType.I32);
|
||||
|
||||
context.Assembler.Cmp (src1, Const(src1.Type, 0));
|
||||
context.Assembler.Cmp(src1, Const(src1.Type, 0));
|
||||
context.Assembler.Csel(dest, src2, src3, ArmCondition.Ne);
|
||||
}
|
||||
|
||||
|
@ -1078,7 +1079,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
|
||||
private static UnwindInfo WritePrologue(CodeGenContext context)
|
||||
{
|
||||
List<UnwindPushEntry> pushEntries = new List<UnwindPushEntry>();
|
||||
List<UnwindPushEntry> pushEntries = new();
|
||||
|
||||
Operand rsp = Register(SpRegister);
|
||||
|
||||
|
@ -1568,11 +1569,13 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
Debug.Assert(op1.Type == op3.Type);
|
||||
}
|
||||
|
||||
#pragma warning disable IDE0051 // Remove unused private member
|
||||
private static void EnsureSameType(Operand op1, Operand op2, Operand op3, Operand op4)
|
||||
{
|
||||
Debug.Assert(op1.Type == op2.Type);
|
||||
Debug.Assert(op1.Type == op3.Type);
|
||||
Debug.Assert(op1.Type == op4.Type);
|
||||
}
|
||||
#pragma warning restore IDE0051
|
||||
}
|
||||
}
|
|
@ -1,7 +1,4 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Intrinsics.Arm;
|
||||
using System.Runtime.Versioning;
|
||||
|
@ -35,7 +32,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
}
|
||||
}
|
||||
|
||||
#region Linux
|
||||
#region Linux
|
||||
|
||||
private const ulong AT_HWCAP = 16;
|
||||
private const ulong AT_HWCAP2 = 26;
|
||||
|
@ -77,7 +74,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
Ssbs = 1 << 28,
|
||||
Sb = 1 << 29,
|
||||
Paca = 1 << 30,
|
||||
Pacg = 1UL << 31
|
||||
Pacg = 1UL << 31,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
|
@ -119,15 +116,15 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
Sve_Ebf16 = 1UL << 33,
|
||||
Cssc = 1UL << 34,
|
||||
Rprfm = 1UL << 35,
|
||||
Sve2p1 = 1UL << 36
|
||||
Sve2p1 = 1UL << 36,
|
||||
}
|
||||
|
||||
public static LinuxFeatureFlagsHwCap LinuxFeatureInfoHwCap { get; } = 0;
|
||||
public static LinuxFeatureFlagsHwCap2 LinuxFeatureInfoHwCap2 { get; } = 0;
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region macOS
|
||||
#region macOS
|
||||
|
||||
[LibraryImport("libSystem.dylib", SetLastError = true)]
|
||||
private static unsafe partial int sysctlbyname([MarshalAs(UnmanagedType.LPStr)] string name, out int oldValue, ref ulong oldSize, IntPtr newValue, ulong newValueSize);
|
||||
|
@ -143,7 +140,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
return false;
|
||||
}
|
||||
|
||||
private static string[] _sysctlNames = new string[]
|
||||
private static readonly string[] _sysctlNames = new string[]
|
||||
{
|
||||
"hw.optional.floatingpoint",
|
||||
"hw.optional.AdvSIMD",
|
||||
|
@ -153,7 +150,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
"hw.optional.arm.FEAT_LSE",
|
||||
"hw.optional.armv8_crc32",
|
||||
"hw.optional.arm.FEAT_SHA1",
|
||||
"hw.optional.arm.FEAT_SHA256"
|
||||
"hw.optional.arm.FEAT_SHA256",
|
||||
};
|
||||
|
||||
[Flags]
|
||||
|
@ -167,12 +164,12 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
Lse = 1 << 5,
|
||||
Crc32 = 1 << 6,
|
||||
Sha1 = 1 << 7,
|
||||
Sha256 = 1 << 8
|
||||
Sha256 = 1 << 8,
|
||||
}
|
||||
|
||||
public static MacOsFeatureFlags MacOsFeatureInfo { get; } = 0;
|
||||
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
public static bool SupportsAdvSimd => LinuxFeatureInfoHwCap.HasFlag(LinuxFeatureFlagsHwCap.Asimd) || MacOsFeatureInfo.HasFlag(MacOsFeatureFlags.AdvSimd);
|
||||
public static bool SupportsAes => LinuxFeatureInfoHwCap.HasFlag(LinuxFeatureFlagsHwCap.Aes) || MacOsFeatureInfo.HasFlag(MacOsFeatureFlags.Aes);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
namespace ARMeilleure.CodeGen.Arm64
|
||||
{
|
||||
struct IntrinsicInfo
|
||||
readonly struct IntrinsicInfo
|
||||
{
|
||||
public uint Inst { get; }
|
||||
public IntrinsicType Type { get; }
|
||||
|
|
|
@ -5,12 +5,13 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
{
|
||||
static class IntrinsicTable
|
||||
{
|
||||
private static IntrinsicInfo[] _intrinTable;
|
||||
private static readonly IntrinsicInfo[] _intrinTable;
|
||||
|
||||
static IntrinsicTable()
|
||||
{
|
||||
_intrinTable = new IntrinsicInfo[EnumUtils.GetCount(typeof(Intrinsic))];
|
||||
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
Add(Intrinsic.Arm64AbsS, new IntrinsicInfo(0x5e20b800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64AbsV, new IntrinsicInfo(0x0e20b800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64AddhnV, new IntrinsicInfo(0x0e204000u, IntrinsicType.VectorTernaryRd));
|
||||
|
@ -448,6 +449,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
Add(Intrinsic.Arm64XtnV, new IntrinsicInfo(0x0e212800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64Zip1V, new IntrinsicInfo(0x0e003800u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64Zip2V, new IntrinsicInfo(0x0e007800u, IntrinsicType.VectorBinary));
|
||||
#pragma warning restore IDE0055
|
||||
}
|
||||
|
||||
private static void Add(Intrinsic intrin, IntrinsicInfo info)
|
||||
|
|
|
@ -55,6 +55,6 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
VectorTernaryShrRd,
|
||||
|
||||
GetRegister,
|
||||
SetRegister
|
||||
SetRegister,
|
||||
}
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
using ARMeilleure.CodeGen.RegisterAllocators;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
|
@ -31,7 +30,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
}
|
||||
}
|
||||
|
||||
public static void RunPass(CompilerContext cctx, StackAllocator stackAlloc, out int maxCallArgs)
|
||||
public static void RunPass(CompilerContext cctx, out int maxCallArgs)
|
||||
{
|
||||
maxCallArgs = -1;
|
||||
|
||||
|
@ -41,7 +40,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
|
||||
for (BasicBlock block = cctx.Cfg.Blocks.First; block != null; block = block.ListNext)
|
||||
{
|
||||
ConstantDict constants = new ConstantDict();
|
||||
ConstantDict constants = new();
|
||||
|
||||
Operation nextNode;
|
||||
|
||||
|
@ -92,7 +91,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
InsertReturnCopy(block.Operations, node);
|
||||
break;
|
||||
case Instruction.Tailcall:
|
||||
InsertTailcallCopies(constants, block.Operations, stackAlloc, node, node);
|
||||
InsertTailcallCopies(constants, block.Operations, node, node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -138,10 +137,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
{
|
||||
src2 = node.GetSource(1);
|
||||
|
||||
Operand temp = src1;
|
||||
|
||||
src1 = src2;
|
||||
src2 = temp;
|
||||
(src2, src1) = (src1, src2);
|
||||
|
||||
node.SetSource(0, src1);
|
||||
node.SetSource(1, src2);
|
||||
|
@ -265,9 +261,9 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
|
||||
Operand dest = operation.Destination;
|
||||
|
||||
List<Operand> sources = new List<Operand>
|
||||
List<Operand> sources = new()
|
||||
{
|
||||
operation.GetSource(0)
|
||||
operation.GetSource(0),
|
||||
};
|
||||
|
||||
int argsCount = operation.SourcesCount - 1;
|
||||
|
@ -364,16 +360,14 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
operation.SetSources(sources.ToArray());
|
||||
}
|
||||
|
||||
private static void InsertTailcallCopies(
|
||||
ConstantDict constants,
|
||||
private static void InsertTailcallCopies(ConstantDict constants,
|
||||
IntrusiveList<Operation> nodes,
|
||||
StackAllocator stackAlloc,
|
||||
Operation node,
|
||||
Operation operation)
|
||||
{
|
||||
List<Operand> sources = new List<Operand>
|
||||
List<Operand> sources = new()
|
||||
{
|
||||
operation.GetSource(0)
|
||||
operation.GetSource(0),
|
||||
};
|
||||
|
||||
int argsCount = operation.SourcesCount - 1;
|
||||
|
|
|
@ -23,6 +23,6 @@
|
|||
/// <summary>
|
||||
/// Refers to a special symbol which is handled by <see cref="Translation.PTC.Ptc.PatchCode"/>.
|
||||
/// </summary>
|
||||
Special
|
||||
Special,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -171,13 +171,12 @@ namespace ARMeilleure.CodeGen.Optimizations
|
|||
|
||||
private static ulong AllOnes(OperandType type)
|
||||
{
|
||||
switch (type)
|
||||
return type switch
|
||||
{
|
||||
case OperandType.I32: return ~0U;
|
||||
case OperandType.I64: return ~0UL;
|
||||
}
|
||||
|
||||
throw new ArgumentException("Invalid operand type \"" + type + "\".");
|
||||
OperandType.I32 => ~0U,
|
||||
OperandType.I64 => ~0UL,
|
||||
_ => throw new ArgumentException("Invalid operand type \"" + type + "\"."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
using ARMeilleure.IntermediateRepresentation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operation.Factory;
|
||||
|
||||
|
@ -42,13 +41,13 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
public void Sequence(List<Operation> sequence)
|
||||
{
|
||||
Dictionary<Register, Register> locations = new Dictionary<Register, Register>();
|
||||
Dictionary<Register, Register> sources = new Dictionary<Register, Register>();
|
||||
Dictionary<Register, Register> locations = new();
|
||||
Dictionary<Register, Register> sources = new();
|
||||
|
||||
Dictionary<Register, OperandType> types = new Dictionary<Register, OperandType>();
|
||||
Dictionary<Register, OperandType> types = new();
|
||||
|
||||
Queue<Register> pendingQueue = new Queue<Register>();
|
||||
Queue<Register> readyQueue = new Queue<Register>();
|
||||
Queue<Register> pendingQueue = new();
|
||||
Queue<Register> readyQueue = new();
|
||||
|
||||
foreach (Copy copy in _copies)
|
||||
{
|
||||
|
@ -186,10 +185,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
private void AddSplitFill(LiveInterval left, LiveInterval right, OperandType type)
|
||||
{
|
||||
if (_fillQueue == null)
|
||||
{
|
||||
_fillQueue = new Queue<Operation>();
|
||||
}
|
||||
_fillQueue ??= new Queue<Operation>();
|
||||
|
||||
Operand register = GetRegister(right.Register, type);
|
||||
Operand offset = Const(left.SpillOffset);
|
||||
|
@ -201,10 +197,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
private void AddSplitSpill(LiveInterval left, LiveInterval right, OperandType type)
|
||||
{
|
||||
if (_spillQueue == null)
|
||||
{
|
||||
_spillQueue = new Queue<Operation>();
|
||||
}
|
||||
_spillQueue ??= new Queue<Operation>();
|
||||
|
||||
Operand offset = Const(right.SpillOffset);
|
||||
Operand register = GetRegister(left.Register, type);
|
||||
|
@ -216,10 +209,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
private void AddSplitCopy(LiveInterval left, LiveInterval right, OperandType type)
|
||||
{
|
||||
if (_parallelCopy == null)
|
||||
{
|
||||
_parallelCopy = new ParallelCopy();
|
||||
}
|
||||
_parallelCopy ??= new ParallelCopy();
|
||||
|
||||
_parallelCopy.AddCopy(right.Register, left.Register, type);
|
||||
|
||||
|
@ -228,7 +218,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
public Operation[] Sequence()
|
||||
{
|
||||
List<Operation> sequence = new List<Operation>();
|
||||
List<Operation> sequence = new();
|
||||
|
||||
if (_spillQueue != null)
|
||||
{
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
private int _first;
|
||||
private int _last;
|
||||
|
||||
public bool IsBlockLocal => _first == _last;
|
||||
public readonly bool IsBlockLocal => _first == _last;
|
||||
|
||||
public LocalInfo(OperandType type, int uses, int blkIndex)
|
||||
{
|
||||
|
|
|
@ -545,7 +545,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
_intervals.Insert(insertIndex, interval);
|
||||
}
|
||||
|
||||
private void Spill(AllocationContext context, LiveInterval interval)
|
||||
private static void Spill(AllocationContext context, LiveInterval interval)
|
||||
{
|
||||
Debug.Assert(!interval.IsFixed, "Trying to spill a fixed interval.");
|
||||
Debug.Assert(interval.UsesCount == 0, "Trying to spill a interval with uses.");
|
||||
|
@ -561,7 +561,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
private void InsertSplitCopies()
|
||||
{
|
||||
Dictionary<int, CopyResolver> copyResolvers = new Dictionary<int, CopyResolver>();
|
||||
Dictionary<int, CopyResolver> copyResolvers = new();
|
||||
|
||||
CopyResolver GetCopyResolver(int position)
|
||||
{
|
||||
|
@ -676,10 +676,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
if (left != default && right != default && left != right)
|
||||
{
|
||||
if (copyResolver == null)
|
||||
{
|
||||
copyResolver = new CopyResolver();
|
||||
}
|
||||
copyResolver ??= new CopyResolver();
|
||||
|
||||
copyResolver.AddSplit(left, right);
|
||||
}
|
||||
|
@ -862,8 +859,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
// Compute local live sets.
|
||||
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
|
||||
{
|
||||
BitMap liveGen = new BitMap(Allocators.Default, mapSize);
|
||||
BitMap liveKill = new BitMap(Allocators.Default, mapSize);
|
||||
BitMap liveGen = new(Allocators.Default, mapSize);
|
||||
BitMap liveKill = new(Allocators.Default, mapSize);
|
||||
|
||||
for (Operation node = block.Operations.First; node != default; node = node.ListNext)
|
||||
{
|
||||
|
@ -910,7 +907,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
}
|
||||
}
|
||||
|
||||
blkLiveGen [block.Index] = liveGen;
|
||||
blkLiveGen[block.Index] = liveGen;
|
||||
blkLiveKill[block.Index] = liveKill;
|
||||
}
|
||||
|
||||
|
@ -920,7 +917,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
for (int index = 0; index < cfg.Blocks.Count; index++)
|
||||
{
|
||||
blkLiveIn [index] = new BitMap(Allocators.Default, mapSize);
|
||||
blkLiveIn[index] = new BitMap(Allocators.Default, mapSize);
|
||||
blkLiveOut[index] = new BitMap(Allocators.Default, mapSize);
|
||||
}
|
||||
|
||||
|
@ -945,9 +942,9 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
BitMap liveIn = blkLiveIn[block.Index];
|
||||
|
||||
liveIn.Set (liveOut);
|
||||
liveIn.Set(liveOut);
|
||||
liveIn.Clear(blkLiveKill[block.Index]);
|
||||
liveIn.Set (blkLiveGen [block.Index]);
|
||||
liveIn.Set(blkLiveGen[block.Index]);
|
||||
}
|
||||
}
|
||||
while (modified);
|
||||
|
@ -1061,7 +1058,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
{
|
||||
int regIndex = BitOperations.TrailingZeroCount(mask);
|
||||
|
||||
Register callerSavedReg = new Register(regIndex, regType);
|
||||
Register callerSavedReg = new(regIndex, regType);
|
||||
|
||||
LiveInterval interval = _intervals[GetRegisterId(callerSavedReg)];
|
||||
|
||||
|
|
|
@ -240,8 +240,10 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
public LiveInterval Split(int position)
|
||||
{
|
||||
LiveInterval result = new(Local, Parent);
|
||||
result.End = End;
|
||||
LiveInterval result = new(Local, Parent)
|
||||
{
|
||||
End = End,
|
||||
};
|
||||
|
||||
LiveRange prev = PrevRange;
|
||||
LiveRange curr = CurrRange;
|
||||
|
|
|
@ -8,8 +8,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
private int _count;
|
||||
private int _capacity;
|
||||
|
||||
public int Count => _count;
|
||||
public Span<LiveInterval> Span => new(_items, _count);
|
||||
public readonly int Count => _count;
|
||||
public readonly Span<LiveInterval> Span => new(_items, _count);
|
||||
|
||||
public void Add(LiveInterval interval)
|
||||
{
|
||||
|
|
|
@ -6,15 +6,15 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
{
|
||||
private int* _items;
|
||||
private int _capacity;
|
||||
private int _count;
|
||||
|
||||
public int Count => _count;
|
||||
public int FirstUse => _count > 0 ? _items[_count - 1] : LiveInterval.NotFound;
|
||||
public Span<int> Span => new(_items, _count);
|
||||
public int Count { get; private set; }
|
||||
|
||||
public readonly int FirstUse => Count > 0 ? _items[Count - 1] : LiveInterval.NotFound;
|
||||
public readonly Span<int> Span => new(_items, Count);
|
||||
|
||||
public void Add(int position)
|
||||
{
|
||||
if (_count + 1 > _capacity)
|
||||
if (Count + 1 > _capacity)
|
||||
{
|
||||
var oldSpan = Span;
|
||||
|
||||
|
@ -28,7 +28,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
// Use positions are usually inserted in descending order, so inserting in descending order is faster,
|
||||
// since the number of half exchanges is reduced.
|
||||
int i = _count - 1;
|
||||
int i = Count - 1;
|
||||
|
||||
while (i >= 0 && _items[i] < position)
|
||||
{
|
||||
|
@ -36,19 +36,19 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
}
|
||||
|
||||
_items[i + 1] = position;
|
||||
_count++;
|
||||
Count++;
|
||||
}
|
||||
|
||||
public int NextUse(int position)
|
||||
public readonly int NextUse(int position)
|
||||
{
|
||||
int index = NextUseIndex(position);
|
||||
|
||||
return index != LiveInterval.NotFound ? _items[index] : LiveInterval.NotFound;
|
||||
}
|
||||
|
||||
public int NextUseIndex(int position)
|
||||
public readonly int NextUseIndex(int position)
|
||||
{
|
||||
int i = _count - 1;
|
||||
int i = Count - 1;
|
||||
|
||||
if (i == -1 || position > _items[0])
|
||||
{
|
||||
|
@ -69,14 +69,16 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
// Since the list is in descending order, the new split list takes the front of the list and the current
|
||||
// list takes the back of the list.
|
||||
UseList result = new();
|
||||
result._count = index + 1;
|
||||
result._capacity = result._count;
|
||||
UseList result = new()
|
||||
{
|
||||
Count = index + 1,
|
||||
};
|
||||
result._capacity = result.Count;
|
||||
result._items = _items;
|
||||
|
||||
_count = _count - result._count;
|
||||
_capacity = _count;
|
||||
_items = _items + result._count;
|
||||
Count -= result.Count;
|
||||
_capacity = Count;
|
||||
_items += result.Count;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,6 @@ namespace ARMeilleure.CodeGen.Unwinding
|
|||
SetFrame = 1,
|
||||
AllocStack = 2,
|
||||
SaveReg = 3,
|
||||
SaveXmm128 = 4
|
||||
SaveXmm128 = 4,
|
||||
}
|
||||
}
|
|
@ -799,7 +799,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
{
|
||||
JumpIndex = _jumps.Count - 1,
|
||||
Position = (int)_stream.Position,
|
||||
Symbol = source.Symbol
|
||||
Symbol = source.Symbol,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1049,7 +1049,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
InstructionFlags.Prefix66 => 1,
|
||||
InstructionFlags.PrefixF3 => 2,
|
||||
InstructionFlags.PrefixF2 => 3,
|
||||
_ => 0
|
||||
_ => 0,
|
||||
};
|
||||
|
||||
if (src1 != default)
|
||||
|
@ -1081,11 +1081,19 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
switch (opCodeHigh)
|
||||
{
|
||||
case 0xf: vexByte1 |= 1; break;
|
||||
case 0xf38: vexByte1 |= 2; break;
|
||||
case 0xf3a: vexByte1 |= 3; break;
|
||||
case 0xf:
|
||||
vexByte1 |= 1;
|
||||
break;
|
||||
case 0xf38:
|
||||
vexByte1 |= 2;
|
||||
break;
|
||||
case 0xf3a:
|
||||
vexByte1 |= 3;
|
||||
break;
|
||||
|
||||
default: Debug.Assert(false, $"Failed to VEX encode opcode 0x{opCode:X}."); break;
|
||||
default:
|
||||
Debug.Assert(false, $"Failed to VEX encode opcode 0x{opCode:X}.");
|
||||
break;
|
||||
}
|
||||
|
||||
vexByte2 |= (rexPrefix & 8) << 4;
|
||||
|
@ -1191,11 +1199,19 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
switch ((ushort)(opCode >> 8))
|
||||
{
|
||||
case 0xf00: mm = 0b01; break;
|
||||
case 0xf38: mm = 0b10; break;
|
||||
case 0xf3a: mm = 0b11; break;
|
||||
case 0xf00:
|
||||
mm = 0b01;
|
||||
break;
|
||||
case 0xf38:
|
||||
mm = 0b10;
|
||||
break;
|
||||
case 0xf3a:
|
||||
mm = 0b11;
|
||||
break;
|
||||
|
||||
default: Debug.Fail($"Failed to EVEX encode opcode 0x{opCode:X}."); break;
|
||||
default:
|
||||
Debug.Fail($"Failed to EVEX encode opcode 0x{opCode:X}.");
|
||||
break;
|
||||
}
|
||||
|
||||
WriteByte(
|
||||
|
@ -1217,7 +1233,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
InstructionFlags.Prefix66 => 0b01,
|
||||
InstructionFlags.PrefixF3 => 0b10,
|
||||
InstructionFlags.PrefixF2 => 0b11,
|
||||
_ => 0
|
||||
_ => 0,
|
||||
};
|
||||
WriteByte(
|
||||
(byte)(
|
||||
|
@ -1233,11 +1249,19 @@ namespace ARMeilleure.CodeGen.X86
|
|||
byte ll = 0b00;
|
||||
switch (registerWidth)
|
||||
{
|
||||
case 128: ll = 0b00; break;
|
||||
case 256: ll = 0b01; break;
|
||||
case 512: ll = 0b10; break;
|
||||
case 128:
|
||||
ll = 0b00;
|
||||
break;
|
||||
case 256:
|
||||
ll = 0b01;
|
||||
break;
|
||||
case 512:
|
||||
ll = 0b10;
|
||||
break;
|
||||
|
||||
default: Debug.Fail($"Invalid EVEX vector register width {registerWidth}."); break;
|
||||
default:
|
||||
Debug.Fail($"Invalid EVEX vector register width {registerWidth}.");
|
||||
break;
|
||||
}
|
||||
// Embedded broadcast in the case of a memory operand
|
||||
bool bcast = broadcast;
|
||||
|
@ -1315,10 +1339,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
ref Jump jump = ref jumps[i];
|
||||
|
||||
// If jump target not resolved yet, resolve it.
|
||||
if (jump.JumpTarget == null)
|
||||
{
|
||||
jump.JumpTarget = _labels[jump.JumpLabel];
|
||||
}
|
||||
jump.JumpTarget ??= _labels[jump.JumpLabel];
|
||||
|
||||
long jumpTarget = jump.JumpTarget.Value;
|
||||
long offset = jumpTarget - jump.JumpPosition;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace ARMeilleure.CodeGen.X86
|
||||
{
|
||||
|
@ -12,6 +13,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
private const int BadOp = 0;
|
||||
|
||||
[Flags]
|
||||
[SuppressMessage("Design", "CA1069: Enums values should not be duplicated")]
|
||||
private enum InstructionFlags
|
||||
{
|
||||
None = 0,
|
||||
|
@ -26,7 +28,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
PrefixMask = 7 << PrefixBit,
|
||||
Prefix66 = 1 << PrefixBit,
|
||||
PrefixF3 = 2 << PrefixBit,
|
||||
PrefixF2 = 4 << PrefixBit
|
||||
PrefixF2 = 4 << PrefixBit,
|
||||
}
|
||||
|
||||
private readonly struct InstructionInfo
|
||||
|
@ -62,6 +64,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
{
|
||||
_instTable = new InstructionInfo[(int)X86Instruction.Count];
|
||||
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
// Name RM/R RM/I8 RM/I32 R/I64 R/RM Flags
|
||||
Add(X86Instruction.Add, new InstructionInfo(0x00000001, 0x00000083, 0x00000081, BadOp, 0x00000003, InstructionFlags.None));
|
||||
Add(X86Instruction.Addpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
|
@ -285,6 +288,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
Add(X86Instruction.Xor, new InstructionInfo(0x00000031, 0x06000083, 0x06000081, BadOp, 0x00000033, InstructionFlags.None));
|
||||
Add(X86Instruction.Xorpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f57, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Xorps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f57, InstructionFlags.Vex));
|
||||
#pragma warning restore IDE0055
|
||||
|
||||
static void Add(X86Instruction inst, in InstructionInfo info)
|
||||
{
|
||||
|
|
|
@ -3,6 +3,6 @@ namespace ARMeilleure.CodeGen.X86
|
|||
enum CallConvName
|
||||
{
|
||||
SystemV,
|
||||
Windows
|
||||
Windows,
|
||||
}
|
||||
}
|
|
@ -20,6 +20,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
{
|
||||
if (GetCurrentCallConv() == CallConvName.Windows)
|
||||
{
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
return (1 << (int)X86Register.Rax) |
|
||||
(1 << (int)X86Register.Rcx) |
|
||||
(1 << (int)X86Register.Rdx) |
|
||||
|
@ -39,6 +40,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
(1 << (int)X86Register.R9) |
|
||||
(1 << (int)X86Register.R10) |
|
||||
(1 << (int)X86Register.R11);
|
||||
#pragma warning restore IDE0055
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,22 +92,32 @@ namespace ARMeilleure.CodeGen.X86
|
|||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0: return X86Register.Rcx;
|
||||
case 1: return X86Register.Rdx;
|
||||
case 2: return X86Register.R8;
|
||||
case 3: return X86Register.R9;
|
||||
case 0:
|
||||
return X86Register.Rcx;
|
||||
case 1:
|
||||
return X86Register.Rdx;
|
||||
case 2:
|
||||
return X86Register.R8;
|
||||
case 3:
|
||||
return X86Register.R9;
|
||||
}
|
||||
}
|
||||
else /* if (GetCurrentCallConv() == CallConvName.SystemV) */
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0: return X86Register.Rdi;
|
||||
case 1: return X86Register.Rsi;
|
||||
case 2: return X86Register.Rdx;
|
||||
case 3: return X86Register.Rcx;
|
||||
case 4: return X86Register.R8;
|
||||
case 5: return X86Register.R9;
|
||||
case 0:
|
||||
return X86Register.Rdi;
|
||||
case 1:
|
||||
return X86Register.Rsi;
|
||||
case 2:
|
||||
return X86Register.Rdx;
|
||||
case 3:
|
||||
return X86Register.Rcx;
|
||||
case 4:
|
||||
return X86Register.R8;
|
||||
case 5:
|
||||
return X86Register.R9;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
{
|
||||
_instTable = new Action<CodeGenContext, Operation>[EnumUtils.GetCount(typeof(Instruction))];
|
||||
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
Add(Instruction.Add, GenerateAdd);
|
||||
Add(Instruction.BitwiseAnd, GenerateBitwiseAnd);
|
||||
Add(Instruction.BitwiseExclusiveOr, GenerateBitwiseExclusiveOr);
|
||||
|
@ -85,6 +86,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
Add(Instruction.ZeroExtend16, GenerateZeroExtend16);
|
||||
Add(Instruction.ZeroExtend32, GenerateZeroExtend32);
|
||||
Add(Instruction.ZeroExtend8, GenerateZeroExtend8);
|
||||
#pragma warning restore IDE0055
|
||||
|
||||
static void Add(Instruction inst, Action<CodeGenContext, Operation> func)
|
||||
{
|
||||
|
@ -761,13 +763,13 @@ namespace ARMeilleure.CodeGen.X86
|
|||
Operand src2 = operation.GetSource(1);
|
||||
Operand src3 = operation.GetSource(2);
|
||||
|
||||
EnsureSameReg (dest, src3);
|
||||
EnsureSameReg(dest, src3);
|
||||
EnsureSameType(dest, src2, src3);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger());
|
||||
Debug.Assert(src1.Type == OperandType.I32);
|
||||
|
||||
context.Assembler.Test (src1, src1, src1.Type);
|
||||
context.Assembler.Test(src1, src1, src1.Type);
|
||||
context.Assembler.Cmovcc(dest, src2, dest.Type, X86Condition.NotEqual);
|
||||
}
|
||||
|
||||
|
@ -794,7 +796,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
if (source.Type.IsInteger())
|
||||
{
|
||||
context.Assembler.Xorps (dest, dest, dest);
|
||||
context.Assembler.Xorps(dest, dest, dest);
|
||||
context.Assembler.Cvtsi2ss(dest, dest, source, source.Type);
|
||||
}
|
||||
else /* if (source.Type == OperandType.FP64) */
|
||||
|
@ -810,7 +812,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
if (source.Type.IsInteger())
|
||||
{
|
||||
context.Assembler.Xorps (dest, dest, dest);
|
||||
context.Assembler.Xorps(dest, dest, dest);
|
||||
context.Assembler.Cvtsi2sd(dest, dest, source, source.Type);
|
||||
}
|
||||
else /* if (source.Type == OperandType.FP32) */
|
||||
|
@ -1278,7 +1280,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
mask1 = BitUtils.RotateRight(mask1, 8 - index * 2, 8);
|
||||
|
||||
context.Assembler.Pshufd(src1, src1, (byte)mask0);
|
||||
context.Assembler.Movd (dest, src1);
|
||||
context.Assembler.Movd(dest, src1);
|
||||
context.Assembler.Pshufd(src1, src1, (byte)mask1);
|
||||
}
|
||||
}
|
||||
|
@ -1297,7 +1299,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
const byte mask = 0b01_00_11_10;
|
||||
|
||||
context.Assembler.Pshufd(src1, src1, mask);
|
||||
context.Assembler.Movq (dest, src1);
|
||||
context.Assembler.Movq(dest, src1);
|
||||
context.Assembler.Pshufd(src1, src1, mask);
|
||||
}
|
||||
}
|
||||
|
@ -1308,7 +1310,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
(index == 1 && dest.Type == OperandType.FP64))
|
||||
{
|
||||
context.Assembler.Movhlps(dest, dest, src1);
|
||||
context.Assembler.Movq (dest, dest);
|
||||
context.Assembler.Movq(dest, dest);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -1459,7 +1461,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
mask1 = BitUtils.RotateRight(mask1, 8 - index * 2, 8);
|
||||
|
||||
context.Assembler.Pshufd(src1, src1, (byte)mask0); // Lane to be inserted in position 0.
|
||||
context.Assembler.Movss (dest, src1, src2); // dest[127:0] = src1[127:32] | src2[31:0]
|
||||
context.Assembler.Movss(dest, src1, src2); // dest[127:0] = src1[127:32] | src2[31:0]
|
||||
context.Assembler.Pshufd(dest, dest, (byte)mask1); // Inserted lane in original position.
|
||||
|
||||
if (dest.GetRegister() != src1.GetRegister())
|
||||
|
@ -1613,13 +1615,25 @@ namespace ARMeilleure.CodeGen.X86
|
|||
{
|
||||
switch (value.Type)
|
||||
{
|
||||
case OperandType.I32: context.Assembler.Mov (value, address, OperandType.I32); break;
|
||||
case OperandType.I64: context.Assembler.Mov (value, address, OperandType.I64); break;
|
||||
case OperandType.FP32: context.Assembler.Movd (value, address); break;
|
||||
case OperandType.FP64: context.Assembler.Movq (value, address); break;
|
||||
case OperandType.V128: context.Assembler.Movdqu(value, address); break;
|
||||
case OperandType.I32:
|
||||
context.Assembler.Mov(value, address, OperandType.I32);
|
||||
break;
|
||||
case OperandType.I64:
|
||||
context.Assembler.Mov(value, address, OperandType.I64);
|
||||
break;
|
||||
case OperandType.FP32:
|
||||
context.Assembler.Movd(value, address);
|
||||
break;
|
||||
case OperandType.FP64:
|
||||
context.Assembler.Movq(value, address);
|
||||
break;
|
||||
case OperandType.V128:
|
||||
context.Assembler.Movdqu(value, address);
|
||||
break;
|
||||
|
||||
default: Debug.Assert(false); break;
|
||||
default:
|
||||
Debug.Assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1627,13 +1641,25 @@ namespace ARMeilleure.CodeGen.X86
|
|||
{
|
||||
switch (value.Type)
|
||||
{
|
||||
case OperandType.I32: context.Assembler.Mov (address, value, OperandType.I32); break;
|
||||
case OperandType.I64: context.Assembler.Mov (address, value, OperandType.I64); break;
|
||||
case OperandType.FP32: context.Assembler.Movd (address, value); break;
|
||||
case OperandType.FP64: context.Assembler.Movq (address, value); break;
|
||||
case OperandType.V128: context.Assembler.Movdqu(address, value); break;
|
||||
case OperandType.I32:
|
||||
context.Assembler.Mov(address, value, OperandType.I32);
|
||||
break;
|
||||
case OperandType.I64:
|
||||
context.Assembler.Mov(address, value, OperandType.I64);
|
||||
break;
|
||||
case OperandType.FP32:
|
||||
context.Assembler.Movd(address, value);
|
||||
break;
|
||||
case OperandType.FP64:
|
||||
context.Assembler.Movq(address, value);
|
||||
break;
|
||||
case OperandType.V128:
|
||||
context.Assembler.Movdqu(address, value);
|
||||
break;
|
||||
|
||||
default: Debug.Assert(false); break;
|
||||
default:
|
||||
Debug.Assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1670,21 +1696,21 @@ namespace ARMeilleure.CodeGen.X86
|
|||
[Conditional("DEBUG")]
|
||||
private static void ValidateUnOp(Operand dest, Operand source)
|
||||
{
|
||||
EnsureSameReg (dest, source);
|
||||
EnsureSameReg(dest, source);
|
||||
EnsureSameType(dest, source);
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
private static void ValidateBinOp(Operand dest, Operand src1, Operand src2)
|
||||
{
|
||||
EnsureSameReg (dest, src1);
|
||||
EnsureSameReg(dest, src1);
|
||||
EnsureSameType(dest, src1, src2);
|
||||
}
|
||||
|
||||
[Conditional("DEBUG")]
|
||||
private static void ValidateShift(Operand dest, Operand src1, Operand src2)
|
||||
{
|
||||
EnsureSameReg (dest, src1);
|
||||
EnsureSameReg(dest, src1);
|
||||
EnsureSameType(dest, src1);
|
||||
|
||||
Debug.Assert(dest.Type.IsInteger() && src2.Type == OperandType.I32);
|
||||
|
@ -1722,7 +1748,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
private static UnwindInfo WritePrologue(CodeGenContext context)
|
||||
{
|
||||
List<UnwindPushEntry> pushEntries = new List<UnwindPushEntry>();
|
||||
List<UnwindPushEntry> pushEntries = new();
|
||||
|
||||
Operand rsp = Register(X86Register.Rsp);
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
0xc3, // ret
|
||||
};
|
||||
|
||||
using MemoryBlock memGetXcr0 = new MemoryBlock((ulong)asmGetXcr0.Length);
|
||||
using MemoryBlock memGetXcr0 = new((ulong)asmGetXcr0.Length);
|
||||
|
||||
memGetXcr0.Write(0, asmGetXcr0);
|
||||
|
||||
|
@ -62,7 +62,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
public enum FeatureFlags1Edx
|
||||
{
|
||||
Sse = 1 << 25,
|
||||
Sse2 = 1 << 26
|
||||
Sse2 = 1 << 26,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
|
@ -79,7 +79,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
Xsave = 1 << 26,
|
||||
Osxsave = 1 << 27,
|
||||
Avx = 1 << 28,
|
||||
F16c = 1 << 29
|
||||
F16c = 1 << 29,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
|
@ -90,7 +90,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
Avx512dq = 1 << 17,
|
||||
Sha = 1 << 29,
|
||||
Avx512bw = 1 << 30,
|
||||
Avx512vl = 1 << 31
|
||||
Avx512vl = 1 << 31,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
|
@ -106,7 +106,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
YmmHi128 = 1 << 2,
|
||||
Opmask = 1 << 5,
|
||||
ZmmHi256 = 1 << 6,
|
||||
Hi16Zmm = 1 << 7
|
||||
Hi16Zmm = 1 << 7,
|
||||
}
|
||||
|
||||
public static FeatureFlags1Edx FeatureInfo1Edx { get; }
|
||||
|
|
|
@ -5,12 +5,13 @@ namespace ARMeilleure.CodeGen.X86
|
|||
{
|
||||
static class IntrinsicTable
|
||||
{
|
||||
private static IntrinsicInfo[] _intrinTable;
|
||||
private static readonly IntrinsicInfo[] _intrinTable;
|
||||
|
||||
static IntrinsicTable()
|
||||
{
|
||||
_intrinTable = new IntrinsicInfo[EnumUtils.GetCount(typeof(Intrinsic))];
|
||||
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
Add(Intrinsic.X86Addpd, new IntrinsicInfo(X86Instruction.Addpd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Addps, new IntrinsicInfo(X86Instruction.Addps, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Addsd, new IntrinsicInfo(X86Instruction.Addsd, IntrinsicType.Binary));
|
||||
|
@ -185,6 +186,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
Add(Intrinsic.X86Vpternlogd, new IntrinsicInfo(X86Instruction.Vpternlogd, IntrinsicType.TernaryImm));
|
||||
Add(Intrinsic.X86Xorpd, new IntrinsicInfo(X86Instruction.Xorpd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Xorps, new IntrinsicInfo(X86Instruction.Xorps, IntrinsicType.Binary));
|
||||
#pragma warning restore IDE0055
|
||||
}
|
||||
|
||||
private static void Add(Intrinsic intrin, IntrinsicInfo info)
|
||||
|
|
|
@ -13,6 +13,6 @@ namespace ARMeilleure.CodeGen.X86
|
|||
Crc32,
|
||||
Ternary,
|
||||
TernaryImm,
|
||||
Fma
|
||||
Fma,
|
||||
}
|
||||
}
|
|
@ -10,6 +10,6 @@ namespace ARMeilleure.CodeGen.X86
|
|||
Rlo = 1 << 13, // Round Mode low bit.
|
||||
Um = 1 << 11, // Underflow Mask.
|
||||
Dm = 1 << 8, // Denormal Mask.
|
||||
Daz = 1 << 6 // Denormals Are Zero.
|
||||
Daz = 1 << 6, // Denormals Are Zero.
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,11 +104,11 @@ namespace ARMeilleure.CodeGen.X86
|
|||
case Instruction.Tailcall:
|
||||
if (callConv == CallConvName.Windows)
|
||||
{
|
||||
PreAllocatorWindows.InsertTailcallCopies(block.Operations, stackAlloc, node);
|
||||
PreAllocatorWindows.InsertTailcallCopies(block.Operations, node);
|
||||
}
|
||||
else
|
||||
{
|
||||
PreAllocatorSystemV.InsertTailcallCopies(block.Operations, stackAlloc, node);
|
||||
PreAllocatorSystemV.InsertTailcallCopies(block.Operations, node);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -177,10 +177,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
{
|
||||
src2 = node.GetSource(1);
|
||||
|
||||
Operand temp = src1;
|
||||
|
||||
src1 = src2;
|
||||
src2 = temp;
|
||||
(src2, src1) = (src1, src2);
|
||||
|
||||
node.SetSource(0, src1);
|
||||
node.SetSource(1, src2);
|
||||
|
@ -473,7 +470,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
Operand zex = Local(OperandType.I64);
|
||||
|
||||
node = nodes.AddAfter(node, Operation(Instruction.ZeroExtend32, zex, source));
|
||||
node = nodes.AddAfter(node, Operation(Instruction.ConvertToFP, dest, zex));
|
||||
nodes.AddAfter(node, Operation(Instruction.ConvertToFP, dest, zex));
|
||||
}
|
||||
else /* if (source.Type == OperandType.I64) */
|
||||
{
|
||||
|
@ -709,16 +706,11 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
private static bool HasConstSrc1(Instruction inst)
|
||||
{
|
||||
switch (inst)
|
||||
return inst switch
|
||||
{
|
||||
case Instruction.Copy:
|
||||
case Instruction.LoadArgument:
|
||||
case Instruction.Spill:
|
||||
case Instruction.SpillArg:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
Instruction.Copy or Instruction.LoadArgument or Instruction.Spill or Instruction.SpillArg => true,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
private static bool HasConstSrc2(Instruction inst)
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
using ARMeilleure.CodeGen.RegisterAllocators;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
|
@ -15,9 +14,9 @@ namespace ARMeilleure.CodeGen.X86
|
|||
{
|
||||
Operand dest = node.Destination;
|
||||
|
||||
List<Operand> sources = new List<Operand>
|
||||
List<Operand> sources = new()
|
||||
{
|
||||
node.GetSource(0)
|
||||
node.GetSource(0),
|
||||
};
|
||||
|
||||
int argsCount = node.SourcesCount - 1;
|
||||
|
@ -116,11 +115,11 @@ namespace ARMeilleure.CodeGen.X86
|
|||
}
|
||||
}
|
||||
|
||||
public static void InsertTailcallCopies(IntrusiveList<Operation> nodes, StackAllocator stackAlloc, Operation node)
|
||||
public static void InsertTailcallCopies(IntrusiveList<Operation> nodes, Operation node)
|
||||
{
|
||||
List<Operand> sources = new List<Operand>
|
||||
List<Operand> sources = new()
|
||||
{
|
||||
node.GetSource(0)
|
||||
node.GetSource(0),
|
||||
};
|
||||
|
||||
int argsCount = node.SourcesCount - 1;
|
||||
|
|
|
@ -155,7 +155,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
node.SetSources(sources);
|
||||
}
|
||||
|
||||
public static void InsertTailcallCopies(IntrusiveList<Operation> nodes, StackAllocator stackAlloc, Operation node)
|
||||
public static void InsertTailcallCopies(IntrusiveList<Operation> nodes, Operation node)
|
||||
{
|
||||
int argsCount = node.SourcesCount - 1;
|
||||
int maxArgs = CallingConvention.GetArgumentsOnRegsCount();
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
Less = 0xc,
|
||||
GreaterOrEqual = 0xd,
|
||||
LessOrEqual = 0xe,
|
||||
Greater = 0xf
|
||||
Greater = 0xf,
|
||||
}
|
||||
|
||||
static class ComparisonX86Extensions
|
||||
|
@ -29,6 +29,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
{
|
||||
return comp switch
|
||||
{
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
Comparison.Equal => X86Condition.Equal,
|
||||
Comparison.NotEqual => X86Condition.NotEqual,
|
||||
Comparison.Greater => X86Condition.Greater,
|
||||
|
@ -39,8 +40,9 @@ namespace ARMeilleure.CodeGen.X86
|
|||
Comparison.Less => X86Condition.Less,
|
||||
Comparison.GreaterOrEqualUI => X86Condition.AboveOrEqual,
|
||||
Comparison.LessUI => X86Condition.Below,
|
||||
#pragma warning restore IDE0055
|
||||
|
||||
_ => throw new ArgumentException(null, nameof(comp))
|
||||
_ => throw new ArgumentException(null, nameof(comp)),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -226,6 +226,6 @@ namespace ARMeilleure.CodeGen.X86
|
|||
Xorpd,
|
||||
Xorps,
|
||||
|
||||
Count
|
||||
Count,
|
||||
}
|
||||
}
|
|
@ -215,7 +215,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
1 => Multiplier.x2,
|
||||
2 => Multiplier.x4,
|
||||
3 => Multiplier.x8,
|
||||
_ => Multiplier.x1
|
||||
_ => Multiplier.x1,
|
||||
};
|
||||
|
||||
baseOp = indexOnSrc2 ? src1 : src2;
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace ARMeilleure.CodeGen.X86
|
||||
{
|
||||
[SuppressMessage("Design", "CA1069: Enums values should not be duplicated")]
|
||||
enum X86Register
|
||||
{
|
||||
Invalid = -1,
|
||||
|
@ -36,6 +39,6 @@ namespace ARMeilleure.CodeGen.X86
|
|||
Xmm12 = 12,
|
||||
Xmm13 = 13,
|
||||
Xmm14 = 14,
|
||||
Xmm15 = 15
|
||||
Xmm15 = 15,
|
||||
}
|
||||
}
|
|
@ -82,8 +82,10 @@ namespace ARMeilleure.Common
|
|||
}
|
||||
else
|
||||
{
|
||||
_page = new PageInfo();
|
||||
_page.Pointer = (byte*)NativeAllocator.Instance.Allocate(_pageSize);
|
||||
_page = new PageInfo
|
||||
{
|
||||
Pointer = (byte*)NativeAllocator.Instance.Allocate(_pageSize),
|
||||
};
|
||||
|
||||
_pages.Add(_page);
|
||||
}
|
||||
|
@ -106,7 +108,7 @@ namespace ARMeilleure.Common
|
|||
// Free excess pages that was allocated.
|
||||
while (_pages.Count > _pageCount)
|
||||
{
|
||||
NativeAllocator.Instance.Free(_pages[_pages.Count - 1].Pointer);
|
||||
NativeAllocator.Instance.Free(_pages[^1].Pointer);
|
||||
|
||||
_pages.RemoveAt(_pages.Count - 1);
|
||||
}
|
||||
|
@ -125,12 +127,13 @@ namespace ARMeilleure.Common
|
|||
|
||||
// If arena is used frequently, keep pages for longer. Otherwise keep pages for a shorter amount of time.
|
||||
int now = Environment.TickCount;
|
||||
int count = (now - _lastReset) switch {
|
||||
int count = (now - _lastReset) switch
|
||||
{
|
||||
>= 5000 => 0,
|
||||
>= 2500 => 50,
|
||||
>= 1000 => 100,
|
||||
>= 10 => 1500,
|
||||
_ => 5000
|
||||
_ => 5000,
|
||||
};
|
||||
|
||||
for (int i = _pages.Count - 1; i >= 0; i--)
|
||||
|
|
|
@ -138,7 +138,7 @@ namespace ARMeilleure.Common
|
|||
var newSpan = new Span<long>(_masks, _count);
|
||||
|
||||
oldSpan.CopyTo(newSpan);
|
||||
newSpan.Slice(oldSpan.Length).Clear();
|
||||
newSpan[oldSpan.Length..].Clear();
|
||||
|
||||
_allocator.Free(oldMask);
|
||||
}
|
||||
|
@ -176,8 +176,8 @@ namespace ARMeilleure.Common
|
|||
private int _bit;
|
||||
private readonly BitMap _map;
|
||||
|
||||
public int Current => (int)_index * IntSize + _bit;
|
||||
object IEnumerator.Current => Current;
|
||||
public readonly int Current => (int)_index * IntSize + _bit;
|
||||
readonly object IEnumerator.Current => Current;
|
||||
|
||||
public Enumerator(BitMap map)
|
||||
{
|
||||
|
@ -214,9 +214,9 @@ namespace ARMeilleure.Common
|
|||
return true;
|
||||
}
|
||||
|
||||
public void Reset() { }
|
||||
public readonly void Reset() { }
|
||||
|
||||
public void Dispose() { }
|
||||
public readonly void Dispose() { }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -92,7 +92,7 @@ namespace ARMeilleure.Decoders
|
|||
{
|
||||
if (OpCodes.Count > 0)
|
||||
{
|
||||
return OpCodes[OpCodes.Count - 1];
|
||||
return OpCodes[^1];
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace ARMeilleure.Decoders
|
|||
Gt = 12,
|
||||
Le = 13,
|
||||
Al = 14,
|
||||
Nv = 15
|
||||
Nv = 15,
|
||||
}
|
||||
|
||||
static class ConditionExtensions
|
||||
|
|
|
@ -5,6 +5,6 @@ namespace ARMeilleure.Decoders
|
|||
Adr = 0,
|
||||
Arithmetic = 1,
|
||||
Logical = 2,
|
||||
BitField = 3
|
||||
BitField = 3,
|
||||
}
|
||||
}
|
|
@ -20,11 +20,11 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
public static Block[] Decode(IMemoryManager memory, ulong address, ExecutionMode mode, bool highCq, DecoderMode dMode)
|
||||
{
|
||||
List<Block> blocks = new List<Block>();
|
||||
List<Block> blocks = new();
|
||||
|
||||
Queue<Block> workQueue = new Queue<Block>();
|
||||
Queue<Block> workQueue = new();
|
||||
|
||||
Dictionary<ulong, Block> visited = new Dictionary<ulong, Block>();
|
||||
Dictionary<ulong, Block> visited = new();
|
||||
|
||||
Debug.Assert(MaxInstsPerFunctionLowCq <= MaxInstsPerFunction);
|
||||
|
||||
|
@ -246,7 +246,7 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
private static bool IsAarch32UnconditionalBranch(OpCode opCode)
|
||||
{
|
||||
if (!(opCode is OpCode32 op))
|
||||
if (opCode is not OpCode32 op)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -40,36 +40,36 @@ namespace ARMeilleure.Decoders
|
|||
// abcdefgh -> aBbbbbbc defgh000 00000000 00000000 (B = ~b)
|
||||
private static uint ExpandImm8ToFP32(uint imm)
|
||||
{
|
||||
uint MoveBit(uint bits, int from, int to)
|
||||
static uint MoveBit(uint bits, int from, int to)
|
||||
{
|
||||
return ((bits >> from) & 1U) << to;
|
||||
}
|
||||
|
||||
return MoveBit(imm, 7, 31) | MoveBit(~imm, 6, 30) |
|
||||
MoveBit(imm, 6, 29) | MoveBit( imm, 6, 28) |
|
||||
MoveBit(imm, 6, 27) | MoveBit( imm, 6, 26) |
|
||||
MoveBit(imm, 6, 25) | MoveBit( imm, 5, 24) |
|
||||
MoveBit(imm, 4, 23) | MoveBit( imm, 3, 22) |
|
||||
MoveBit(imm, 2, 21) | MoveBit( imm, 1, 20) |
|
||||
MoveBit(imm, 6, 29) | MoveBit(imm, 6, 28) |
|
||||
MoveBit(imm, 6, 27) | MoveBit(imm, 6, 26) |
|
||||
MoveBit(imm, 6, 25) | MoveBit(imm, 5, 24) |
|
||||
MoveBit(imm, 4, 23) | MoveBit(imm, 3, 22) |
|
||||
MoveBit(imm, 2, 21) | MoveBit(imm, 1, 20) |
|
||||
MoveBit(imm, 0, 19);
|
||||
}
|
||||
|
||||
// abcdefgh -> aBbbbbbb bbcdefgh 00000000 00000000 00000000 00000000 00000000 00000000 (B = ~b)
|
||||
private static ulong ExpandImm8ToFP64(ulong imm)
|
||||
{
|
||||
ulong MoveBit(ulong bits, int from, int to)
|
||||
static ulong MoveBit(ulong bits, int from, int to)
|
||||
{
|
||||
return ((bits >> from) & 1UL) << to;
|
||||
}
|
||||
|
||||
return MoveBit(imm, 7, 63) | MoveBit(~imm, 6, 62) |
|
||||
MoveBit(imm, 6, 61) | MoveBit( imm, 6, 60) |
|
||||
MoveBit(imm, 6, 59) | MoveBit( imm, 6, 58) |
|
||||
MoveBit(imm, 6, 57) | MoveBit( imm, 6, 56) |
|
||||
MoveBit(imm, 6, 55) | MoveBit( imm, 6, 54) |
|
||||
MoveBit(imm, 5, 53) | MoveBit( imm, 4, 52) |
|
||||
MoveBit(imm, 3, 51) | MoveBit( imm, 2, 50) |
|
||||
MoveBit(imm, 1, 49) | MoveBit( imm, 0, 48);
|
||||
MoveBit(imm, 6, 61) | MoveBit(imm, 6, 60) |
|
||||
MoveBit(imm, 6, 59) | MoveBit(imm, 6, 58) |
|
||||
MoveBit(imm, 6, 57) | MoveBit(imm, 6, 56) |
|
||||
MoveBit(imm, 6, 55) | MoveBit(imm, 6, 54) |
|
||||
MoveBit(imm, 5, 53) | MoveBit(imm, 4, 52) |
|
||||
MoveBit(imm, 3, 51) | MoveBit(imm, 2, 50) |
|
||||
MoveBit(imm, 1, 49) | MoveBit(imm, 0, 48);
|
||||
}
|
||||
|
||||
public struct BitMask
|
||||
|
@ -80,7 +80,7 @@ namespace ARMeilleure.Decoders
|
|||
public int Shift;
|
||||
public bool IsUndefined;
|
||||
|
||||
public static BitMask Invalid => new BitMask { IsUndefined = true };
|
||||
public static BitMask Invalid => new() { IsUndefined = true };
|
||||
}
|
||||
|
||||
public static BitMask DecodeBitMask(int opCode, bool immediate)
|
||||
|
@ -125,7 +125,7 @@ namespace ARMeilleure.Decoders
|
|||
TMask = BitUtils.Replicate(tMask, size),
|
||||
|
||||
Pos = immS,
|
||||
Shift = immR
|
||||
Shift = immR,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ namespace ARMeilleure.Decoders
|
|||
{
|
||||
readonly struct InstDescriptor
|
||||
{
|
||||
public static InstDescriptor Undefined => new InstDescriptor(InstName.Und, InstEmit.Und);
|
||||
public static InstDescriptor Undefined => new(InstName.Und, InstEmit.Und);
|
||||
|
||||
public InstName Name { get; }
|
||||
public InstEmitter Emitter { get; }
|
||||
|
|
|
@ -9,6 +9,6 @@ namespace ARMeilleure.Decoders
|
|||
Int8 = 4,
|
||||
Int16 = 5,
|
||||
Int32 = 6,
|
||||
Int64 = 7
|
||||
Int64 = 7,
|
||||
}
|
||||
}
|
|
@ -14,7 +14,7 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
public RegisterSize RegisterSize { get; protected set; }
|
||||
|
||||
public static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode(inst, address, opCode);
|
||||
public static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new(inst, address, opCode);
|
||||
|
||||
public OpCode(InstDescriptor inst, ulong address, int opCode)
|
||||
{
|
||||
|
@ -30,15 +30,14 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
public int GetBitsCount()
|
||||
{
|
||||
switch (RegisterSize)
|
||||
return RegisterSize switch
|
||||
{
|
||||
case RegisterSize.Int32: return 32;
|
||||
case RegisterSize.Int64: return 64;
|
||||
case RegisterSize.Simd64: return 64;
|
||||
case RegisterSize.Simd128: return 128;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException();
|
||||
RegisterSize.Int32 => 32,
|
||||
RegisterSize.Int64 => 64,
|
||||
RegisterSize.Simd64 => 64,
|
||||
RegisterSize.Simd128 => 128,
|
||||
_ => throw new InvalidOperationException(),
|
||||
};
|
||||
}
|
||||
|
||||
public OperandType GetOperandType()
|
||||
|
|
|
@ -24,27 +24,21 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
protected int GetQuadwordIndex(int index)
|
||||
{
|
||||
switch (RegisterSize)
|
||||
return RegisterSize switch
|
||||
{
|
||||
case RegisterSize.Simd128:
|
||||
case RegisterSize.Simd64:
|
||||
return index >> 1;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException();
|
||||
RegisterSize.Simd128 or RegisterSize.Simd64 => index >> 1,
|
||||
_ => throw new InvalidOperationException(),
|
||||
};
|
||||
}
|
||||
|
||||
protected int GetQuadwordSubindex(int index)
|
||||
{
|
||||
switch (RegisterSize)
|
||||
return RegisterSize switch
|
||||
{
|
||||
case RegisterSize.Simd128:
|
||||
return 0;
|
||||
case RegisterSize.Simd64:
|
||||
return index & 1;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException();
|
||||
RegisterSize.Simd128 => 0,
|
||||
RegisterSize.Simd64 => index & 1,
|
||||
_ => throw new InvalidOperationException(),
|
||||
};
|
||||
}
|
||||
|
||||
protected OpCode32SimdBase(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
|
||||
|
|
|
@ -14,9 +14,15 @@
|
|||
// The value must be a power of 2, otherwise it is the encoding of another instruction.
|
||||
switch (imm3h)
|
||||
{
|
||||
case 1: Size = 0; break;
|
||||
case 2: Size = 1; break;
|
||||
case 4: Size = 2; break;
|
||||
case 1:
|
||||
Size = 0;
|
||||
break;
|
||||
case 2:
|
||||
Size = 1;
|
||||
break;
|
||||
case 4:
|
||||
Size = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
U = ((opCode >> (isThumb ? 28 : 24)) & 0x1) != 0;
|
||||
|
|
|
@ -4,12 +4,12 @@ namespace ARMeilleure.Decoders
|
|||
{
|
||||
class OpCode32SimdMemPair : OpCode32, IOpCode32Simd
|
||||
{
|
||||
private static int[] _regsMap =
|
||||
private static readonly int[] _regsMap =
|
||||
{
|
||||
1, 1, 4, 2,
|
||||
1, 1, 3, 1,
|
||||
1, 1, 2, 1,
|
||||
1, 1, 1, 1
|
||||
1, 1, 1, 1,
|
||||
};
|
||||
|
||||
public int Vd { get; }
|
||||
|
|
|
@ -18,6 +18,6 @@
|
|||
Eq = 0,
|
||||
Vs,
|
||||
Ge,
|
||||
Gt
|
||||
Gt,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace ARMeilleure.Decoders
|
|||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException(nameof(opCode));
|
||||
throw new ArgumentException($"Invalid data operation: {DataOp}", nameof(opCode));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace ARMeilleure.Decoders
|
|||
PostIndexed = 1,
|
||||
Unprivileged = 2,
|
||||
PreIndexed = 3,
|
||||
Unsigned
|
||||
Unsigned,
|
||||
}
|
||||
|
||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeMemImm(inst, address, opCode);
|
||||
|
|
|
@ -18,10 +18,26 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
switch ((opCode >> 30) & 3)
|
||||
{
|
||||
case 0: Size = 2; Signed = false; Prefetch = false; break;
|
||||
case 1: Size = 3; Signed = false; Prefetch = false; break;
|
||||
case 2: Size = 2; Signed = true; Prefetch = false; break;
|
||||
case 3: Size = 0; Signed = false; Prefetch = true; break;
|
||||
case 0:
|
||||
Size = 2;
|
||||
Signed = false;
|
||||
Prefetch = false;
|
||||
break;
|
||||
case 1:
|
||||
Size = 3;
|
||||
Signed = false;
|
||||
Prefetch = false;
|
||||
break;
|
||||
case 2:
|
||||
Size = 2;
|
||||
Signed = true;
|
||||
Prefetch = false;
|
||||
break;
|
||||
case 3:
|
||||
Size = 0;
|
||||
Signed = false;
|
||||
Prefetch = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,17 +52,20 @@
|
|||
else if ((modeHigh & 0b110) == 0b100)
|
||||
{
|
||||
// 16-bits shifted Immediate.
|
||||
size = 1; imm <<= (modeHigh & 1) << 3;
|
||||
size = 1;
|
||||
imm <<= (modeHigh & 1) << 3;
|
||||
}
|
||||
else if ((modeHigh & 0b100) == 0b000)
|
||||
{
|
||||
// 32-bits shifted Immediate.
|
||||
size = 2; imm <<= modeHigh << 3;
|
||||
size = 2;
|
||||
imm <<= modeHigh << 3;
|
||||
}
|
||||
else if ((modeHigh & 0b111) == 0b110)
|
||||
{
|
||||
// 32-bits shifted Immediate (fill with ones).
|
||||
size = 2; imm = ShlOnes(imm, 8 << modeLow);
|
||||
size = 2;
|
||||
imm = ShlOnes(imm, 8 << modeLow);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -67,17 +67,20 @@ namespace ARMeilleure.Decoders
|
|||
else if ((modeHigh & 0b110) == 0b100)
|
||||
{
|
||||
// 16-bits shifted Immediate.
|
||||
Size = 1; imm <<= (modeHigh & 1) << 3;
|
||||
Size = 1;
|
||||
imm <<= (modeHigh & 1) << 3;
|
||||
}
|
||||
else if ((modeHigh & 0b100) == 0b000)
|
||||
{
|
||||
// 32-bits shifted Immediate.
|
||||
Size = 2; imm <<= modeHigh << 3;
|
||||
Size = 2;
|
||||
imm <<= modeHigh << 3;
|
||||
}
|
||||
else if ((modeHigh & 0b111) == 0b110)
|
||||
{
|
||||
// 32-bits shifted Immediate (fill with ones).
|
||||
Size = 2; imm = ShlOnes(imm, 8 << modeLow);
|
||||
Size = 2;
|
||||
imm = ShlOnes(imm, 8 << modeLow);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -23,10 +23,18 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
switch (Size)
|
||||
{
|
||||
case 1: Size = 0; break;
|
||||
case 2: Size = 1; break;
|
||||
case 4: Size = 2; break;
|
||||
case 8: Size = 3; break;
|
||||
case 1:
|
||||
Size = 0;
|
||||
break;
|
||||
case 2:
|
||||
Size = 1;
|
||||
break;
|
||||
case 4:
|
||||
Size = 2;
|
||||
break;
|
||||
case 8:
|
||||
Size = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
SrcIndex = imm4 >> Size;
|
||||
|
|
|
@ -13,15 +13,38 @@ namespace ARMeilleure.Decoders
|
|||
{
|
||||
switch ((opCode >> 12) & 0xf)
|
||||
{
|
||||
case 0b0000: Reps = 1; SElems = 4; break;
|
||||
case 0b0010: Reps = 4; SElems = 1; break;
|
||||
case 0b0100: Reps = 1; SElems = 3; break;
|
||||
case 0b0110: Reps = 3; SElems = 1; break;
|
||||
case 0b0111: Reps = 1; SElems = 1; break;
|
||||
case 0b1000: Reps = 1; SElems = 2; break;
|
||||
case 0b1010: Reps = 2; SElems = 1; break;
|
||||
case 0b0000:
|
||||
Reps = 1;
|
||||
SElems = 4;
|
||||
break;
|
||||
case 0b0010:
|
||||
Reps = 4;
|
||||
SElems = 1;
|
||||
break;
|
||||
case 0b0100:
|
||||
Reps = 1;
|
||||
SElems = 3;
|
||||
break;
|
||||
case 0b0110:
|
||||
Reps = 3;
|
||||
SElems = 1;
|
||||
break;
|
||||
case 0b0111:
|
||||
Reps = 1;
|
||||
SElems = 1;
|
||||
break;
|
||||
case 0b1000:
|
||||
Reps = 1;
|
||||
SElems = 2;
|
||||
break;
|
||||
case 0b1010:
|
||||
Reps = 2;
|
||||
SElems = 1;
|
||||
break;
|
||||
|
||||
default: Instruction = InstDescriptor.Undefined; return;
|
||||
default:
|
||||
Instruction = InstDescriptor.Undefined;
|
||||
return;
|
||||
}
|
||||
|
||||
Size = (opCode >> 10) & 3;
|
||||
|
|
|
@ -24,7 +24,9 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
break;
|
||||
|
||||
default: Instruction = InstDescriptor.Undefined; break;
|
||||
default:
|
||||
Instruction = InstDescriptor.Undefined;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,9 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
break;
|
||||
|
||||
default: Instruction = InstDescriptor.Undefined; break;
|
||||
default:
|
||||
Instruction = InstDescriptor.Undefined;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCodeT16AddSubImm3: OpCodeT16, IOpCode32AluImm
|
||||
class OpCodeT16AddSubImm3 : OpCodeT16, IOpCode32AluImm
|
||||
{
|
||||
public int Rd { get; }
|
||||
public int Rn { get; }
|
||||
|
|
|
@ -36,23 +36,13 @@ namespace ARMeilleure.Decoders
|
|||
break;
|
||||
}
|
||||
|
||||
switch (inst.Name)
|
||||
Immediate = inst.Name switch
|
||||
{
|
||||
case InstName.Str:
|
||||
case InstName.Ldr:
|
||||
Immediate = ((opCode >> 6) & 0x1f) << 2;
|
||||
break;
|
||||
case InstName.Strb:
|
||||
case InstName.Ldrb:
|
||||
Immediate = ((opCode >> 6) & 0x1f);
|
||||
break;
|
||||
case InstName.Strh:
|
||||
case InstName.Ldrh:
|
||||
Immediate = ((opCode >> 6) & 0x1f) << 1;
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
InstName.Str or InstName.Ldr => ((opCode >> 6) & 0x1f) << 2,
|
||||
InstName.Strb or InstName.Ldrb => ((opCode >> 6) & 0x1f),
|
||||
InstName.Strh or InstName.Ldrh => ((opCode >> 6) & 0x1f) << 1,
|
||||
_ => throw new InvalidOperationException(),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace ARMeilleure.Decoders
|
|||
{
|
||||
InstName.Ldm => true,
|
||||
InstName.Stm => false,
|
||||
_ => throw new InvalidOperationException()
|
||||
_ => throw new InvalidOperationException(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,6 @@ namespace ARMeilleure.Decoders
|
|||
{
|
||||
public int Immediate { get; }
|
||||
|
||||
public bool IsRotated => false;
|
||||
|
||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32MovImm16(inst, address, opCode);
|
||||
|
||||
public OpCodeT32MovImm16(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
||||
|
|
|
@ -29,17 +29,18 @@ namespace ARMeilleure.Decoders
|
|||
}
|
||||
}
|
||||
|
||||
private static List<InstInfo> AllInstA32 = new();
|
||||
private static List<InstInfo> AllInstT32 = new();
|
||||
private static List<InstInfo> AllInstA64 = new();
|
||||
private static readonly List<InstInfo> _allInstA32 = new();
|
||||
private static readonly List<InstInfo> _allInstT32 = new();
|
||||
private static readonly List<InstInfo> _allInstA64 = new();
|
||||
|
||||
private static InstInfo[][] InstA32FastLookup = new InstInfo[FastLookupSize][];
|
||||
private static InstInfo[][] InstT32FastLookup = new InstInfo[FastLookupSize][];
|
||||
private static InstInfo[][] InstA64FastLookup = new InstInfo[FastLookupSize][];
|
||||
private static readonly InstInfo[][] _instA32FastLookup = new InstInfo[FastLookupSize][];
|
||||
private static readonly InstInfo[][] _instT32FastLookup = new InstInfo[FastLookupSize][];
|
||||
private static readonly InstInfo[][] _instA64FastLookup = new InstInfo[FastLookupSize][];
|
||||
|
||||
static OpCodeTable()
|
||||
{
|
||||
#region "OpCode Table (AArch64)"
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
#region "OpCode Table (AArch64)"
|
||||
// Base
|
||||
SetA64("x0011010000xxxxx000000xxxxxxxxxx", InstName.Adc, InstEmit.Adc, OpCodeAluRs.Create);
|
||||
SetA64("x0111010000xxxxx000000xxxxxxxxxx", InstName.Adcs, InstEmit.Adcs, OpCodeAluRs.Create);
|
||||
|
@ -638,9 +639,9 @@ namespace ARMeilleure.Decoders
|
|||
SetA64("0x001110<<100001001010xxxxxxxxxx", InstName.Xtn_V, InstEmit.Xtn_V, OpCodeSimd.Create);
|
||||
SetA64("0>001110<<0xxxxx001110xxxxxxxxxx", InstName.Zip1_V, InstEmit.Zip1_V, OpCodeSimdReg.Create);
|
||||
SetA64("0>001110<<0xxxxx011110xxxxxxxxxx", InstName.Zip2_V, InstEmit.Zip2_V, OpCodeSimdReg.Create);
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region "OpCode Table (AArch32, A32)"
|
||||
#region "OpCode Table (AArch32, A32)"
|
||||
// Base
|
||||
SetA32("<<<<0010101xxxxxxxxxxxxxxxxxxxxx", InstName.Adc, InstEmit32.Adc, OpCode32AluImm.Create);
|
||||
SetA32("<<<<0000101xxxxxxxxxxxxxxxx0xxxx", InstName.Adc, InstEmit32.Adc, OpCode32AluRsImm.Create);
|
||||
|
@ -1050,9 +1051,9 @@ namespace ARMeilleure.Decoders
|
|||
SetAsimd("111100100x<<xxxxxxxx1000xxx1xxxx", InstName.Vtst, InstEmit32.Vtst, OpCode32SimdReg.Create, OpCode32SimdReg.CreateT32);
|
||||
SetAsimd("111100111x11<<10xxxx00010xx0xxxx", InstName.Vuzp, InstEmit32.Vuzp, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
|
||||
SetAsimd("111100111x11<<10xxxx00011xx0xxxx", InstName.Vzip, InstEmit32.Vzip, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region "OpCode Table (AArch32, T16)"
|
||||
#region "OpCode Table (AArch32, T16)"
|
||||
SetT16("000<<xxxxxxxxxxx", InstName.Mov, InstEmit32.Mov, OpCodeT16ShiftImm.Create);
|
||||
SetT16("0001100xxxxxxxxx", InstName.Add, InstEmit32.Add, OpCodeT16AddSubReg.Create);
|
||||
SetT16("0001101xxxxxxxxx", InstName.Sub, InstEmit32.Sub, OpCodeT16AddSubReg.Create);
|
||||
|
@ -1131,7 +1132,7 @@ namespace ARMeilleure.Decoders
|
|||
SetT16("11100xxxxxxxxxxx", InstName.B, InstEmit32.B, OpCodeT16BImm11.Create);
|
||||
#endregion
|
||||
|
||||
#region "OpCode Table (AArch32, T32)"
|
||||
#region "OpCode Table (AArch32, T32)"
|
||||
// Base
|
||||
SetT32("11101011010xxxxx0xxxxxxxxxxxxxxx", InstName.Adc, InstEmit32.Adc, OpCodeT32AluRsImm.Create);
|
||||
SetT32("11110x01010xxxxx0xxxxxxxxxxxxxxx", InstName.Adc, InstEmit32.Adc, OpCodeT32AluImm.Create);
|
||||
|
@ -1299,12 +1300,13 @@ namespace ARMeilleure.Decoders
|
|||
SetT32("11110011101011111000000000000001", InstName.Yield, InstEmit32.Nop, OpCodeT32.Create);
|
||||
#endregion
|
||||
|
||||
FillFastLookupTable(InstA32FastLookup, AllInstA32, ToFastLookupIndexA);
|
||||
FillFastLookupTable(InstT32FastLookup, AllInstT32, ToFastLookupIndexT);
|
||||
FillFastLookupTable(InstA64FastLookup, AllInstA64, ToFastLookupIndexA);
|
||||
FillFastLookupTable(_instA32FastLookup, _allInstA32, ToFastLookupIndexA);
|
||||
FillFastLookupTable(_instT32FastLookup, _allInstT32, ToFastLookupIndexT);
|
||||
FillFastLookupTable(_instA64FastLookup, _allInstA64, ToFastLookupIndexA);
|
||||
#pragma warning restore IDE0055
|
||||
}
|
||||
|
||||
private static void FillFastLookupTable(InstInfo[][] table, List<InstInfo> allInsts, Func<int, int> ToFastLookupIndex)
|
||||
private static void FillFastLookupTable(InstInfo[][] table, List<InstInfo> allInsts, Func<int, int> toFastLookupIndex)
|
||||
{
|
||||
List<InstInfo>[] temp = new List<InstInfo>[FastLookupSize];
|
||||
|
||||
|
@ -1315,8 +1317,8 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
foreach (InstInfo inst in allInsts)
|
||||
{
|
||||
int mask = ToFastLookupIndex(inst.Mask);
|
||||
int value = ToFastLookupIndex(inst.Value);
|
||||
int mask = toFastLookupIndex(inst.Mask);
|
||||
int value = toFastLookupIndex(inst.Value);
|
||||
|
||||
for (int index = 0; index < temp.Length; index++)
|
||||
{
|
||||
|
@ -1335,22 +1337,21 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
private static void SetA32(string encoding, InstName name, InstEmitter emitter, MakeOp makeOp)
|
||||
{
|
||||
Set(encoding, AllInstA32, new InstDescriptor(name, emitter), makeOp);
|
||||
Set(encoding, _allInstA32, new InstDescriptor(name, emitter), makeOp);
|
||||
}
|
||||
|
||||
private static void SetT16(string encoding, InstName name, InstEmitter emitter, MakeOp makeOp)
|
||||
{
|
||||
encoding = "xxxxxxxxxxxxxxxx" + encoding;
|
||||
Set(encoding, AllInstT32, new InstDescriptor(name, emitter), makeOp);
|
||||
Set(encoding, _allInstT32, new InstDescriptor(name, emitter), makeOp);
|
||||
}
|
||||
|
||||
private static void SetT32(string encoding, InstName name, InstEmitter emitter, MakeOp makeOp)
|
||||
{
|
||||
string reversedEncoding = $"{encoding.AsSpan(16)}{encoding.AsSpan(0, 16)}";
|
||||
MakeOp reversedMakeOp =
|
||||
(inst, address, opCode)
|
||||
OpCode ReversedMakeOp(InstDescriptor inst, ulong address, int opCode)
|
||||
=> makeOp(inst, address, (int)BitOperations.RotateRight((uint)opCode, 16));
|
||||
Set(reversedEncoding, AllInstT32, new InstDescriptor(name, emitter), reversedMakeOp);
|
||||
Set(reversedEncoding, _allInstT32, new InstDescriptor(name, emitter), ReversedMakeOp);
|
||||
}
|
||||
|
||||
private static void SetVfp(string encoding, InstName name, InstEmitter emitter, MakeOp makeOpA32, MakeOp makeOpT32)
|
||||
|
@ -1395,7 +1396,7 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
private static void SetA64(string encoding, InstName name, InstEmitter emitter, MakeOp makeOp)
|
||||
{
|
||||
Set(encoding, AllInstA64, new InstDescriptor(name, emitter), makeOp);
|
||||
Set(encoding, _allInstA64, new InstDescriptor(name, emitter), makeOp);
|
||||
}
|
||||
|
||||
private static void Set(string encoding, List<InstInfo> list, InstDescriptor inst, MakeOp makeOp)
|
||||
|
@ -1439,7 +1440,7 @@ namespace ARMeilleure.Decoders
|
|||
}
|
||||
else if (chr != '0')
|
||||
{
|
||||
throw new ArgumentException(nameof(encoding));
|
||||
throw new ArgumentException($"Invalid encoding: {encoding}", nameof(encoding));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1470,17 +1471,17 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
public static (InstDescriptor inst, MakeOp makeOp) GetInstA32(int opCode)
|
||||
{
|
||||
return GetInstFromList(InstA32FastLookup[ToFastLookupIndexA(opCode)], opCode);
|
||||
return GetInstFromList(_instA32FastLookup[ToFastLookupIndexA(opCode)], opCode);
|
||||
}
|
||||
|
||||
public static (InstDescriptor inst, MakeOp makeOp) GetInstT32(int opCode)
|
||||
{
|
||||
return GetInstFromList(InstT32FastLookup[ToFastLookupIndexT(opCode)], opCode);
|
||||
return GetInstFromList(_instT32FastLookup[ToFastLookupIndexT(opCode)], opCode);
|
||||
}
|
||||
|
||||
public static (InstDescriptor inst, MakeOp makeOp) GetInstA64(int opCode)
|
||||
{
|
||||
return GetInstFromList(InstA64FastLookup[ToFastLookupIndexA(opCode)], opCode);
|
||||
return GetInstFromList(_instA64FastLookup[ToFastLookupIndexA(opCode)], opCode);
|
||||
}
|
||||
|
||||
private static (InstDescriptor inst, MakeOp makeOp) GetInstFromList(InstInfo[] insts, int opCode)
|
||||
|
|
|
@ -5,6 +5,6 @@ namespace ARMeilleure.Decoders
|
|||
Int32,
|
||||
Int64,
|
||||
Simd64,
|
||||
Simd128
|
||||
Simd128,
|
||||
}
|
||||
}
|
|
@ -5,6 +5,6 @@ namespace ARMeilleure.Decoders
|
|||
Lsl = 0,
|
||||
Lsr = 1,
|
||||
Asr = 2,
|
||||
Ror = 3
|
||||
Ror = 3,
|
||||
}
|
||||
}
|
|
@ -34,7 +34,9 @@ namespace ARMeilleure.Diagnostics
|
|||
|
||||
for (int index = 0; index < _indentLevel; index++)
|
||||
{
|
||||
#pragma warning disable CA1834 // Use StringBuilder.Append(char) for single character strings
|
||||
_builder.Append(Indentation);
|
||||
#pragma warning restore CA1834
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,10 +112,18 @@ namespace ARMeilleure.Diagnostics
|
|||
|
||||
switch (reg.Type)
|
||||
{
|
||||
case RegisterType.Flag: _builder.Append('b'); break;
|
||||
case RegisterType.FpFlag: _builder.Append('f'); break;
|
||||
case RegisterType.Integer: _builder.Append('r'); break;
|
||||
case RegisterType.Vector: _builder.Append('v'); break;
|
||||
case RegisterType.Flag:
|
||||
_builder.Append('b');
|
||||
break;
|
||||
case RegisterType.FpFlag:
|
||||
_builder.Append('f');
|
||||
break;
|
||||
case RegisterType.Integer:
|
||||
_builder.Append('r');
|
||||
break;
|
||||
case RegisterType.Vector:
|
||||
_builder.Append('v');
|
||||
break;
|
||||
}
|
||||
|
||||
_builder.Append(reg.Index);
|
||||
|
@ -145,9 +155,15 @@ namespace ARMeilleure.Diagnostics
|
|||
|
||||
switch (memOp.Scale)
|
||||
{
|
||||
case Multiplier.x2: _builder.Append("*2"); break;
|
||||
case Multiplier.x4: _builder.Append("*4"); break;
|
||||
case Multiplier.x8: _builder.Append("*8"); break;
|
||||
case Multiplier.x2:
|
||||
_builder.Append("*2");
|
||||
break;
|
||||
case Multiplier.x4:
|
||||
_builder.Append("*4");
|
||||
break;
|
||||
case Multiplier.x8:
|
||||
_builder.Append("*8");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace ARMeilleure.Diagnostics
|
|||
{
|
||||
private static long _startTime;
|
||||
|
||||
private static long[] _accumulatedTime;
|
||||
private static readonly long[] _accumulatedTime;
|
||||
|
||||
static Logger()
|
||||
{
|
||||
|
|
|
@ -14,6 +14,6 @@ namespace ARMeilleure.Diagnostics
|
|||
RegisterAllocation,
|
||||
CodeGeneration,
|
||||
|
||||
Count
|
||||
Count,
|
||||
}
|
||||
}
|
|
@ -33,9 +33,8 @@ namespace ARMeilleure.Diagnostics
|
|||
|
||||
public static string Get(ulong address)
|
||||
{
|
||||
string result;
|
||||
|
||||
if (_symbols.TryGetValue(address, out result))
|
||||
if (_symbols.TryGetValue(address, out string result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -19,19 +19,19 @@ namespace ARMeilleure.Diagnostics
|
|||
{
|
||||
_rejitQueueCounter = new PollingCounter("rejit-queue-length", this, () => _rejitQueue)
|
||||
{
|
||||
DisplayName = "Rejit Queue Length"
|
||||
DisplayName = "Rejit Queue Length",
|
||||
};
|
||||
|
||||
_funcTabSizeCounter = new PollingCounter("addr-tab-alloc", this, () => _funcTabSize / 1024d / 1024d)
|
||||
{
|
||||
DisplayName = "AddressTable Total Bytes Allocated",
|
||||
DisplayUnits = "MiB"
|
||||
DisplayUnits = "MiB",
|
||||
};
|
||||
|
||||
_funcTabLeafSizeCounter = new PollingCounter("addr-tab-leaf-alloc", this, () => _funcTabLeafSize / 1024d / 1024d)
|
||||
{
|
||||
DisplayName = "AddressTable Total Leaf Bytes Allocated",
|
||||
DisplayUnits = "MiB"
|
||||
DisplayUnits = "MiB",
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,8 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
static class CryptoHelper
|
||||
{
|
||||
#region "LookUp Tables"
|
||||
#region "LookUp Tables"
|
||||
#pragma warning disable IDE1006 // Naming rule violation
|
||||
private static ReadOnlySpan<byte> _sBox => new byte[]
|
||||
{
|
||||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
|
||||
|
@ -25,7 +26,7 @@ namespace ARMeilleure.Instructions
|
|||
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
|
||||
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
|
||||
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> _invSBox => new byte[]
|
||||
|
@ -45,7 +46,7 @@ namespace ARMeilleure.Instructions
|
|||
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
|
||||
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
|
||||
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
|
||||
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
|
||||
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> _gfMul02 => new byte[]
|
||||
|
@ -65,7 +66,7 @@ namespace ARMeilleure.Instructions
|
|||
0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85,
|
||||
0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5,
|
||||
0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5,
|
||||
0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5
|
||||
0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5,
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> _gfMul03 => new byte[]
|
||||
|
@ -85,7 +86,7 @@ namespace ARMeilleure.Instructions
|
|||
0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, 0x4f, 0x4c, 0x49, 0x4a,
|
||||
0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a,
|
||||
0x3b, 0x38, 0x3d, 0x3e, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a,
|
||||
0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a
|
||||
0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a,
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> _gfMul09 => new byte[]
|
||||
|
@ -105,7 +106,7 @@ namespace ARMeilleure.Instructions
|
|||
0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed,
|
||||
0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d,
|
||||
0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6,
|
||||
0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46
|
||||
0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46,
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> _gfMul0B => new byte[]
|
||||
|
@ -125,7 +126,7 @@ namespace ARMeilleure.Instructions
|
|||
0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68,
|
||||
0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8,
|
||||
0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13,
|
||||
0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3
|
||||
0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3,
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> _gfMul0D => new byte[]
|
||||
|
@ -145,7 +146,7 @@ namespace ARMeilleure.Instructions
|
|||
0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc,
|
||||
0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c,
|
||||
0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47,
|
||||
0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97
|
||||
0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97,
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> _gfMul0E => new byte[]
|
||||
|
@ -165,19 +166,20 @@ namespace ARMeilleure.Instructions
|
|||
0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6,
|
||||
0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56,
|
||||
0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d,
|
||||
0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d
|
||||
0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d,
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> _srPerm => new byte[]
|
||||
{
|
||||
0, 13, 10, 7, 4, 1, 14, 11, 8, 5, 2, 15, 12, 9, 6, 3
|
||||
0, 13, 10, 7, 4, 1, 14, 11, 8, 5, 2, 15, 12, 9, 6, 3,
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> _isrPerm => new byte[]
|
||||
{
|
||||
0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11
|
||||
0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11,
|
||||
};
|
||||
#endregion
|
||||
#pragma warning restore IDE1006
|
||||
#endregion
|
||||
|
||||
public static V128 AesInvMixColumns(V128 op)
|
||||
{
|
||||
|
|
|
@ -3,7 +3,6 @@ using ARMeilleure.IntermediateRepresentation;
|
|||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
using System.Diagnostics;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitAluHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
@ -281,16 +280,16 @@ namespace ARMeilleure.Instructions
|
|||
Debug.Assert(op.Type == OperandType.I64);
|
||||
|
||||
Operand val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(op, Const(0xaaaaaaaaaaaaaaaaul)), Const(1)),
|
||||
context.ShiftLeft (context.BitwiseAnd(op, Const(0x5555555555555555ul)), Const(1)));
|
||||
context.ShiftLeft(context.BitwiseAnd(op, Const(0x5555555555555555ul)), Const(1)));
|
||||
|
||||
val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(val, Const(0xccccccccccccccccul)), Const(2)),
|
||||
context.ShiftLeft (context.BitwiseAnd(val, Const(0x3333333333333333ul)), Const(2)));
|
||||
context.ShiftLeft(context.BitwiseAnd(val, Const(0x3333333333333333ul)), Const(2)));
|
||||
val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(val, Const(0xf0f0f0f0f0f0f0f0ul)), Const(4)),
|
||||
context.ShiftLeft (context.BitwiseAnd(val, Const(0x0f0f0f0f0f0f0f0ful)), Const(4)));
|
||||
context.ShiftLeft(context.BitwiseAnd(val, Const(0x0f0f0f0f0f0f0f0ful)), Const(4)));
|
||||
val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(val, Const(0xff00ff00ff00ff00ul)), Const(8)),
|
||||
context.ShiftLeft (context.BitwiseAnd(val, Const(0x00ff00ff00ff00fful)), Const(8)));
|
||||
context.ShiftLeft(context.BitwiseAnd(val, Const(0x00ff00ff00ff00fful)), Const(8)));
|
||||
val = context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(val, Const(0xffff0000ffff0000ul)), Const(16)),
|
||||
context.ShiftLeft (context.BitwiseAnd(val, Const(0x0000ffff0000fffful)), Const(16)));
|
||||
context.ShiftLeft(context.BitwiseAnd(val, Const(0x0000ffff0000fffful)), Const(16)));
|
||||
|
||||
return context.BitwiseOr(context.ShiftRightUI(val, Const(32)), context.ShiftLeft(val, Const(32)));
|
||||
}
|
||||
|
@ -340,7 +339,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand val = EmitReverseBytes16_64Op(context, op);
|
||||
|
||||
return context.BitwiseOr(context.ShiftRightUI(context.BitwiseAnd(val, Const(0xffff0000ffff0000ul)), Const(16)),
|
||||
context.ShiftLeft (context.BitwiseAnd(val, Const(0x0000ffff0000fffful)), Const(16)));
|
||||
context.ShiftLeft(context.BitwiseAnd(val, Const(0x0000ffff0000fffful)), Const(16)));
|
||||
}
|
||||
|
||||
public static void Rev64(ArmEmitterContext context)
|
||||
|
|
|
@ -2,13 +2,14 @@ using ARMeilleure.Decoders;
|
|||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using static ARMeilleure.Instructions.InstEmitAluHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
||||
namespace ARMeilleure.Instructions
|
||||
{
|
||||
[SuppressMessage("Style", "IDE0059: Remove unnecessary value assignment")]
|
||||
static partial class InstEmit32
|
||||
{
|
||||
public static void Add(ArmEmitterContext context)
|
||||
|
|
|
@ -26,7 +26,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static void EmitNZFlagsCheck(ArmEmitterContext context, Operand d)
|
||||
{
|
||||
SetFlag(context, PState.NFlag, context.ICompareLess (d, Const(d.Type, 0)));
|
||||
SetFlag(context, PState.NFlag, context.ICompareLess(d, Const(d.Type, 0)));
|
||||
SetFlag(context, PState.ZFlag, context.ICompareEqual(d, Const(d.Type, 0)));
|
||||
}
|
||||
|
||||
|
@ -205,12 +205,16 @@ namespace ARMeilleure.Instructions
|
|||
return Const(op.Immediate);
|
||||
}
|
||||
|
||||
case IOpCode32AluImm16 op: return Const(op.Immediate);
|
||||
case IOpCode32AluImm16 op:
|
||||
return Const(op.Immediate);
|
||||
|
||||
case IOpCode32AluRsImm op: return GetMShiftedByImmediate(context, op, setCarry);
|
||||
case IOpCode32AluRsReg op: return GetMShiftedByReg(context, op, setCarry);
|
||||
case IOpCode32AluRsImm op:
|
||||
return GetMShiftedByImmediate(context, op, setCarry);
|
||||
case IOpCode32AluRsReg op:
|
||||
return GetMShiftedByReg(context, op, setCarry);
|
||||
|
||||
case IOpCode32AluReg op: return GetIntA32(context, op.Rm);
|
||||
case IOpCode32AluReg op:
|
||||
return GetIntA32(context, op.Rm);
|
||||
|
||||
// ARM64.
|
||||
case IOpCodeAluImm op:
|
||||
|
@ -231,10 +235,18 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (op.ShiftType)
|
||||
{
|
||||
case ShiftType.Lsl: value = context.ShiftLeft (value, Const(op.Shift)); break;
|
||||
case ShiftType.Lsr: value = context.ShiftRightUI(value, Const(op.Shift)); break;
|
||||
case ShiftType.Asr: value = context.ShiftRightSI(value, Const(op.Shift)); break;
|
||||
case ShiftType.Ror: value = context.RotateRight (value, Const(op.Shift)); break;
|
||||
case ShiftType.Lsl:
|
||||
value = context.ShiftLeft(value, Const(op.Shift));
|
||||
break;
|
||||
case ShiftType.Lsr:
|
||||
value = context.ShiftRightUI(value, Const(op.Shift));
|
||||
break;
|
||||
case ShiftType.Asr:
|
||||
value = context.ShiftRightSI(value, Const(op.Shift));
|
||||
break;
|
||||
case ShiftType.Ror:
|
||||
value = context.RotateRight(value, Const(op.Shift));
|
||||
break;
|
||||
}
|
||||
|
||||
return value;
|
||||
|
@ -249,7 +261,8 @@ namespace ARMeilleure.Instructions
|
|||
return value;
|
||||
}
|
||||
|
||||
default: throw InvalidOpCodeType(context.CurrOp);
|
||||
default:
|
||||
throw InvalidOpCodeType(context.CurrOp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -269,9 +282,15 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
switch (op.ShiftType)
|
||||
{
|
||||
case ShiftType.Lsr: shift = 32; break;
|
||||
case ShiftType.Asr: shift = 32; break;
|
||||
case ShiftType.Ror: shift = 1; break;
|
||||
case ShiftType.Lsr:
|
||||
shift = 32;
|
||||
break;
|
||||
case ShiftType.Asr:
|
||||
shift = 32;
|
||||
break;
|
||||
case ShiftType.Ror:
|
||||
shift = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -281,9 +300,15 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (op.ShiftType)
|
||||
{
|
||||
case ShiftType.Lsl: m = GetLslC(context, m, setCarry, shift); break;
|
||||
case ShiftType.Lsr: m = GetLsrC(context, m, setCarry, shift); break;
|
||||
case ShiftType.Asr: m = GetAsrC(context, m, setCarry, shift); break;
|
||||
case ShiftType.Lsl:
|
||||
m = GetLslC(context, m, setCarry, shift);
|
||||
break;
|
||||
case ShiftType.Lsr:
|
||||
m = GetLsrC(context, m, setCarry, shift);
|
||||
break;
|
||||
case ShiftType.Asr:
|
||||
m = GetAsrC(context, m, setCarry, shift);
|
||||
break;
|
||||
case ShiftType.Ror:
|
||||
if (op.Immediate != 0)
|
||||
{
|
||||
|
@ -306,9 +331,15 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
switch (shiftType)
|
||||
{
|
||||
case ShiftType.Lsr: shift = 32; break;
|
||||
case ShiftType.Asr: shift = 32; break;
|
||||
case ShiftType.Ror: shift = 1; break;
|
||||
case ShiftType.Lsr:
|
||||
shift = 32;
|
||||
break;
|
||||
case ShiftType.Asr:
|
||||
shift = 32;
|
||||
break;
|
||||
case ShiftType.Ror:
|
||||
shift = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -328,10 +359,18 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (op.ShiftType)
|
||||
{
|
||||
case ShiftType.Lsl: shiftResult = EmitLslC(context, m, setCarry, s, shiftIsZero); break;
|
||||
case ShiftType.Lsr: shiftResult = EmitLsrC(context, m, setCarry, s, shiftIsZero); break;
|
||||
case ShiftType.Asr: shiftResult = EmitAsrC(context, m, setCarry, s, shiftIsZero); break;
|
||||
case ShiftType.Ror: shiftResult = EmitRorC(context, m, setCarry, s, shiftIsZero); break;
|
||||
case ShiftType.Lsl:
|
||||
shiftResult = EmitLslC(context, m, setCarry, s, shiftIsZero);
|
||||
break;
|
||||
case ShiftType.Lsr:
|
||||
shiftResult = EmitLsrC(context, m, setCarry, s, shiftIsZero);
|
||||
break;
|
||||
case ShiftType.Asr:
|
||||
shiftResult = EmitAsrC(context, m, setCarry, s, shiftIsZero);
|
||||
break;
|
||||
case ShiftType.Ror:
|
||||
shiftResult = EmitRorC(context, m, setCarry, s, shiftIsZero);
|
||||
break;
|
||||
}
|
||||
|
||||
return context.ConditionalSelect(shiftIsZero, zeroResult, shiftResult);
|
||||
|
|
|
@ -84,9 +84,9 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
Operand res = GetIntOrZR(context, op.Rn);
|
||||
|
||||
res = context.ShiftLeft (res, Const(bitsCount - 1 - op.Pos));
|
||||
res = context.ShiftLeft(res, Const(bitsCount - 1 - op.Pos));
|
||||
res = context.ShiftRightSI(res, Const(bitsCount - 1));
|
||||
res = context.BitwiseAnd (res, Const(res.Type, ~op.TMask));
|
||||
res = context.BitwiseAnd(res, Const(res.Type, ~op.TMask));
|
||||
|
||||
Operand n2 = GetBfmN(context);
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@ using ARMeilleure.Decoders;
|
|||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitAluHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitFlowHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using ARMeilleure.Decoders;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitFlowHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
@ -15,7 +14,7 @@ namespace ARMeilleure.Instructions
|
|||
None,
|
||||
Increment,
|
||||
Invert,
|
||||
Negate
|
||||
Negate,
|
||||
}
|
||||
|
||||
public static void Csel(ArmEmitterContext context) => EmitCsel(context, CselOperation.None);
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using ARMeilleure.Decoders;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
||||
|
@ -51,7 +50,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand d = unsigned
|
||||
? context.DivideUI(n, m)
|
||||
: context.Divide (n, m);
|
||||
: context.Divide(n, m);
|
||||
|
||||
SetAluDOrZR(context, d);
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ namespace ARMeilleure.Instructions
|
|||
(1, true) => nameof(SoftFallback.Crc32ch),
|
||||
(2, true) => nameof(SoftFallback.Crc32cw),
|
||||
(3, true) => nameof(SoftFallback.Crc32cx),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(size))
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(size)),
|
||||
};
|
||||
|
||||
return context.Call(typeof(SoftFallback).GetMethod(name), crc, value);
|
||||
|
@ -71,9 +71,15 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0: data = context.VectorInsert8(context.VectorZero(), data, 0); break;
|
||||
case 1: data = context.VectorInsert16(context.VectorZero(), data, 0); break;
|
||||
case 2: data = context.VectorInsert(context.VectorZero(), data, 0); break;
|
||||
case 0:
|
||||
data = context.VectorInsert8(context.VectorZero(), data, 0);
|
||||
break;
|
||||
case 1:
|
||||
data = context.VectorInsert16(context.VectorZero(), data, 0);
|
||||
break;
|
||||
case 2:
|
||||
data = context.VectorInsert(context.VectorZero(), data, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
int bitsize = 8 << size;
|
||||
|
|
|
@ -16,13 +16,25 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (type)
|
||||
{
|
||||
case IntType.UInt8: value = context.ZeroExtend8 (value.Type, value); break;
|
||||
case IntType.UInt16: value = context.ZeroExtend16(value.Type, value); break;
|
||||
case IntType.UInt32: value = context.ZeroExtend32(value.Type, value); break;
|
||||
case IntType.UInt8:
|
||||
value = context.ZeroExtend8(value.Type, value);
|
||||
break;
|
||||
case IntType.UInt16:
|
||||
value = context.ZeroExtend16(value.Type, value);
|
||||
break;
|
||||
case IntType.UInt32:
|
||||
value = context.ZeroExtend32(value.Type, value);
|
||||
break;
|
||||
|
||||
case IntType.Int8: value = context.SignExtend8 (value.Type, value); break;
|
||||
case IntType.Int16: value = context.SignExtend16(value.Type, value); break;
|
||||
case IntType.Int32: value = context.SignExtend32(value.Type, value); break;
|
||||
case IntType.Int8:
|
||||
value = context.SignExtend8(value.Type, value);
|
||||
break;
|
||||
case IntType.Int16:
|
||||
value = context.SignExtend16(value.Type, value);
|
||||
break;
|
||||
case IntType.Int32:
|
||||
value = context.SignExtend32(value.Type, value);
|
||||
break;
|
||||
}
|
||||
|
||||
return value;
|
||||
|
@ -100,78 +112,51 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static int GetBankedRegisterAlias(Aarch32Mode mode, int regIndex)
|
||||
{
|
||||
switch (regIndex)
|
||||
return regIndex switch
|
||||
{
|
||||
case 8: return mode == Aarch32Mode.Fiq
|
||||
? RegisterAlias.R8Fiq
|
||||
: RegisterAlias.R8Usr;
|
||||
|
||||
case 9: return mode == Aarch32Mode.Fiq
|
||||
? RegisterAlias.R9Fiq
|
||||
: RegisterAlias.R9Usr;
|
||||
|
||||
case 10: return mode == Aarch32Mode.Fiq
|
||||
? RegisterAlias.R10Fiq
|
||||
: RegisterAlias.R10Usr;
|
||||
|
||||
case 11: return mode == Aarch32Mode.Fiq
|
||||
? RegisterAlias.R11Fiq
|
||||
: RegisterAlias.R11Usr;
|
||||
|
||||
case 12: return mode == Aarch32Mode.Fiq
|
||||
? RegisterAlias.R12Fiq
|
||||
: RegisterAlias.R12Usr;
|
||||
|
||||
case 13:
|
||||
switch (mode)
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
8 => mode == Aarch32Mode.Fiq ? RegisterAlias.R8Fiq : RegisterAlias.R8Usr,
|
||||
9 => mode == Aarch32Mode.Fiq ? RegisterAlias.R9Fiq : RegisterAlias.R9Usr,
|
||||
10 => mode == Aarch32Mode.Fiq ? RegisterAlias.R10Fiq : RegisterAlias.R10Usr,
|
||||
11 => mode == Aarch32Mode.Fiq ? RegisterAlias.R11Fiq : RegisterAlias.R11Usr,
|
||||
12 => mode == Aarch32Mode.Fiq ? RegisterAlias.R12Fiq : RegisterAlias.R12Usr,
|
||||
13 => mode switch
|
||||
{
|
||||
case Aarch32Mode.User:
|
||||
case Aarch32Mode.System: return RegisterAlias.SpUsr;
|
||||
case Aarch32Mode.Fiq: return RegisterAlias.SpFiq;
|
||||
case Aarch32Mode.Irq: return RegisterAlias.SpIrq;
|
||||
case Aarch32Mode.Supervisor: return RegisterAlias.SpSvc;
|
||||
case Aarch32Mode.Abort: return RegisterAlias.SpAbt;
|
||||
case Aarch32Mode.Hypervisor: return RegisterAlias.SpHyp;
|
||||
case Aarch32Mode.Undefined: return RegisterAlias.SpUnd;
|
||||
|
||||
default: throw new ArgumentException(nameof(mode));
|
||||
}
|
||||
|
||||
case 14:
|
||||
switch (mode)
|
||||
Aarch32Mode.User or Aarch32Mode.System => RegisterAlias.SpUsr,
|
||||
Aarch32Mode.Fiq => RegisterAlias.SpFiq,
|
||||
Aarch32Mode.Irq => RegisterAlias.SpIrq,
|
||||
Aarch32Mode.Supervisor => RegisterAlias.SpSvc,
|
||||
Aarch32Mode.Abort => RegisterAlias.SpAbt,
|
||||
Aarch32Mode.Hypervisor => RegisterAlias.SpHyp,
|
||||
Aarch32Mode.Undefined => RegisterAlias.SpUnd,
|
||||
_ => throw new ArgumentException($"No such AArch32Mode: {mode}", nameof(mode)),
|
||||
},
|
||||
14 => mode switch
|
||||
{
|
||||
case Aarch32Mode.User:
|
||||
case Aarch32Mode.Hypervisor:
|
||||
case Aarch32Mode.System: return RegisterAlias.LrUsr;
|
||||
case Aarch32Mode.Fiq: return RegisterAlias.LrFiq;
|
||||
case Aarch32Mode.Irq: return RegisterAlias.LrIrq;
|
||||
case Aarch32Mode.Supervisor: return RegisterAlias.LrSvc;
|
||||
case Aarch32Mode.Abort: return RegisterAlias.LrAbt;
|
||||
case Aarch32Mode.Undefined: return RegisterAlias.LrUnd;
|
||||
|
||||
default: throw new ArgumentException(nameof(mode));
|
||||
}
|
||||
|
||||
default: throw new ArgumentOutOfRangeException(nameof(regIndex));
|
||||
}
|
||||
Aarch32Mode.User or Aarch32Mode.Hypervisor or Aarch32Mode.System => RegisterAlias.LrUsr,
|
||||
Aarch32Mode.Fiq => RegisterAlias.LrFiq,
|
||||
Aarch32Mode.Irq => RegisterAlias.LrIrq,
|
||||
Aarch32Mode.Supervisor => RegisterAlias.LrSvc,
|
||||
Aarch32Mode.Abort => RegisterAlias.LrAbt,
|
||||
Aarch32Mode.Undefined => RegisterAlias.LrUnd,
|
||||
_ => throw new ArgumentException($"No such AArch32Mode: {mode}", nameof(mode)),
|
||||
},
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(regIndex), regIndex, null),
|
||||
#pragma warning restore IDE0055
|
||||
};
|
||||
}
|
||||
|
||||
public static bool IsA32Return(ArmEmitterContext context)
|
||||
{
|
||||
switch (context.CurrOp)
|
||||
return context.CurrOp switch
|
||||
{
|
||||
case IOpCode32MemMult op:
|
||||
return true; // Setting PC using LDM is nearly always a return.
|
||||
case OpCode32AluRsImm op:
|
||||
return op.Rm == RegisterAlias.Aarch32Lr;
|
||||
case OpCode32AluRsReg op:
|
||||
return op.Rm == RegisterAlias.Aarch32Lr;
|
||||
case OpCode32AluReg op:
|
||||
return op.Rm == RegisterAlias.Aarch32Lr;
|
||||
case OpCode32Mem op:
|
||||
return op.Rn == RegisterAlias.Aarch32Sp && op.WBack && !op.Index; // Setting PC to an address stored on the stack is nearly always a return.
|
||||
}
|
||||
return false;
|
||||
IOpCode32MemMult => true, // Setting PC using LDM is nearly always a return.
|
||||
OpCode32AluRsImm op => op.Rm == RegisterAlias.Aarch32Lr,
|
||||
OpCode32AluRsReg op => op.Rm == RegisterAlias.Aarch32Lr,
|
||||
OpCode32AluReg op => op.Rm == RegisterAlias.Aarch32Lr,
|
||||
OpCode32Mem op => op.Rn == RegisterAlias.Aarch32Sp && op.WBack && !op.Index, // Setting PC to an address stored on the stack is nearly always a return.
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
public static void EmitBxWritePc(ArmEmitterContext context, Operand pc, int sourceRegister = 0)
|
||||
|
|
|
@ -3,7 +3,6 @@ using ARMeilleure.IntermediateRepresentation;
|
|||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitMemoryHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
@ -161,7 +160,7 @@ namespace ARMeilleure.Instructions
|
|||
if (op.Index || op.WBack)
|
||||
{
|
||||
temp = op.Add
|
||||
? context.Add (n, m)
|
||||
? context.Add(n, m)
|
||||
: context.Subtract(n, m);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ using ARMeilleure.IntermediateRepresentation;
|
|||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitMemoryExHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
@ -18,7 +17,7 @@ namespace ARMeilleure.Instructions
|
|||
None = 0,
|
||||
Ordered = 1,
|
||||
Exclusive = 2,
|
||||
OrderedEx = Ordered | Exclusive
|
||||
OrderedEx = Ordered | Exclusive,
|
||||
}
|
||||
|
||||
public static void Clrex(ArmEmitterContext context)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
||||
|
@ -118,14 +117,14 @@ namespace ARMeilleure.Instructions
|
|||
1 => context.Load16(exValuePtr),
|
||||
2 => context.Load(OperandType.I32, exValuePtr),
|
||||
3 => context.Load(OperandType.I64, exValuePtr),
|
||||
_ => context.Load(OperandType.V128, exValuePtr)
|
||||
_ => context.Load(OperandType.V128, exValuePtr),
|
||||
};
|
||||
|
||||
Operand currValue = size switch
|
||||
{
|
||||
0 => context.CompareAndSwap8(physAddr, exValue, value),
|
||||
1 => context.CompareAndSwap16(physAddr, exValue, value),
|
||||
_ => context.CompareAndSwap(physAddr, exValue, value)
|
||||
_ => context.CompareAndSwap(physAddr, exValue, value),
|
||||
};
|
||||
|
||||
// STEP 3: Check if we succeeded by comparing expected and in-memory values.
|
||||
|
|
|
@ -5,7 +5,6 @@ using ARMeilleure.Translation;
|
|||
using ARMeilleure.Translation.PTC;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
||||
|
@ -20,7 +19,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
Zx,
|
||||
Sx32,
|
||||
Sx64
|
||||
Sx64,
|
||||
}
|
||||
|
||||
public static void EmitLoadZx(ArmEmitterContext context, Operand address, int rt, int size)
|
||||
|
@ -66,9 +65,15 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0: value = context.SignExtend8 (destType, value); break;
|
||||
case 1: value = context.SignExtend16(destType, value); break;
|
||||
case 2: value = context.SignExtend32(destType, value); break;
|
||||
case 0:
|
||||
value = context.SignExtend8(destType, value);
|
||||
break;
|
||||
case 1:
|
||||
value = context.SignExtend16(destType, value);
|
||||
break;
|
||||
case 2:
|
||||
value = context.SignExtend32(destType, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -136,10 +141,18 @@ 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;
|
||||
}
|
||||
|
||||
context.Copy(temp, value);
|
||||
|
@ -169,10 +182,18 @@ 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);
|
||||
|
@ -204,7 +225,7 @@ namespace ARMeilleure.Instructions
|
|||
1 => context.Load16(physAddr),
|
||||
2 => context.Load(OperandType.I32, physAddr),
|
||||
3 => context.Load(OperandType.I64, physAddr),
|
||||
_ => context.Load(OperandType.V128, physAddr)
|
||||
_ => context.Load(OperandType.V128, physAddr),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -225,11 +246,21 @@ 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);
|
||||
|
@ -267,10 +298,18 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0: context.Store8 (physAddr, value); break;
|
||||
case 1: context.Store16(physAddr, value); break;
|
||||
case 2: context.Store (physAddr, value); break;
|
||||
case 3: context.Store (physAddr, value); break;
|
||||
case 0:
|
||||
context.Store8(physAddr, value);
|
||||
break;
|
||||
case 1:
|
||||
context.Store16(physAddr, value);
|
||||
break;
|
||||
case 2:
|
||||
context.Store(physAddr, value);
|
||||
break;
|
||||
case 3:
|
||||
context.Store(physAddr, value);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!context.Memory.Type.IsHostMapped())
|
||||
|
@ -329,11 +368,21 @@ 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.I32, value, elem)); break;
|
||||
case 3: context.Store (physAddr, context.VectorExtract(OperandType.I64, 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.I32, value, elem));
|
||||
break;
|
||||
case 3:
|
||||
context.Store(physAddr, context.VectorExtract(OperandType.I64, value, elem));
|
||||
break;
|
||||
case 4:
|
||||
context.Store(physAddr, value);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!context.Memory.Type.IsHostMapped())
|
||||
|
@ -464,10 +513,18 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadByte)); break;
|
||||
case 1: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt16)); break;
|
||||
case 2: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt32)); break;
|
||||
case 3: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64)); break;
|
||||
case 0:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadByte));
|
||||
break;
|
||||
case 1:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt16));
|
||||
break;
|
||||
case 2:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt32));
|
||||
break;
|
||||
case 3:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64));
|
||||
break;
|
||||
}
|
||||
|
||||
return context.Call(info, address);
|
||||
|
@ -485,21 +542,39 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadByte)); break;
|
||||
case 1: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt16)); break;
|
||||
case 2: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt32)); break;
|
||||
case 3: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64)); break;
|
||||
case 4: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadVector128)); break;
|
||||
case 0:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadByte));
|
||||
break;
|
||||
case 1:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt16));
|
||||
break;
|
||||
case 2:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt32));
|
||||
break;
|
||||
case 3:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64));
|
||||
break;
|
||||
case 4:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadVector128));
|
||||
break;
|
||||
}
|
||||
|
||||
Operand value = context.Call(info, address);
|
||||
|
||||
switch (size)
|
||||
{
|
||||
case 0: value = context.VectorInsert8 (vector, value, elem); break;
|
||||
case 1: value = context.VectorInsert16(vector, value, elem); break;
|
||||
case 2: value = context.VectorInsert (vector, value, elem); break;
|
||||
case 3: value = context.VectorInsert (vector, value, elem); break;
|
||||
case 0:
|
||||
value = context.VectorInsert8(vector, value, elem);
|
||||
break;
|
||||
case 1:
|
||||
value = context.VectorInsert16(vector, value, elem);
|
||||
break;
|
||||
case 2:
|
||||
value = context.VectorInsert(vector, value, elem);
|
||||
break;
|
||||
case 3:
|
||||
value = context.VectorInsert(vector, value, elem);
|
||||
break;
|
||||
}
|
||||
|
||||
context.Copy(GetVec(rt), value);
|
||||
|
@ -511,10 +586,18 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteByte)); break;
|
||||
case 1: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt16)); break;
|
||||
case 2: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt32)); break;
|
||||
case 3: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt64)); break;
|
||||
case 0:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteByte));
|
||||
break;
|
||||
case 1:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt16));
|
||||
break;
|
||||
case 2:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt32));
|
||||
break;
|
||||
case 3:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt64));
|
||||
break;
|
||||
}
|
||||
|
||||
Operand value = GetInt(context, rt);
|
||||
|
@ -538,11 +621,21 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteByte)); break;
|
||||
case 1: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt16)); break;
|
||||
case 2: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt32)); break;
|
||||
case 3: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt64)); break;
|
||||
case 4: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteVector128)); break;
|
||||
case 0:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteByte));
|
||||
break;
|
||||
case 1:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt16));
|
||||
break;
|
||||
case 2:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt32));
|
||||
break;
|
||||
case 3:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt64));
|
||||
break;
|
||||
case 4:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteVector128));
|
||||
break;
|
||||
}
|
||||
|
||||
Operand value = default;
|
||||
|
@ -551,10 +644,18 @@ 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
|
||||
|
@ -585,18 +686,14 @@ namespace ARMeilleure.Instructions
|
|||
// ARM32 helpers.
|
||||
public static Operand GetMemM(ArmEmitterContext context, bool setCarry = true)
|
||||
{
|
||||
switch (context.CurrOp)
|
||||
return context.CurrOp switch
|
||||
{
|
||||
case IOpCode32MemRsImm op: return GetMShiftedByImmediate(context, op, setCarry);
|
||||
|
||||
case IOpCode32MemReg op: return GetIntA32(context, op.Rm);
|
||||
|
||||
case IOpCode32Mem op: return Const(op.Immediate);
|
||||
|
||||
case OpCode32SimdMemImm op: return Const(op.Immediate);
|
||||
|
||||
default: throw InvalidOpCodeType(context.CurrOp);
|
||||
}
|
||||
IOpCode32MemRsImm op => GetMShiftedByImmediate(context, op, setCarry),
|
||||
IOpCode32MemReg op => GetIntA32(context, op.Rm),
|
||||
IOpCode32Mem op => Const(op.Immediate),
|
||||
OpCode32SimdMemImm op => Const(op.Immediate),
|
||||
_ => throw InvalidOpCodeType(context.CurrOp),
|
||||
};
|
||||
}
|
||||
|
||||
private static Exception InvalidOpCodeType(OpCode opCode)
|
||||
|
@ -614,9 +711,15 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
switch (op.ShiftType)
|
||||
{
|
||||
case ShiftType.Lsr: shift = 32; break;
|
||||
case ShiftType.Asr: shift = 32; break;
|
||||
case ShiftType.Ror: shift = 1; break;
|
||||
case ShiftType.Lsr:
|
||||
shift = 32;
|
||||
break;
|
||||
case ShiftType.Asr:
|
||||
shift = 32;
|
||||
break;
|
||||
case ShiftType.Ror:
|
||||
shift = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -626,9 +729,15 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (op.ShiftType)
|
||||
{
|
||||
case ShiftType.Lsl: m = InstEmitAluHelper.GetLslC(context, m, setCarry, shift); break;
|
||||
case ShiftType.Lsr: m = InstEmitAluHelper.GetLsrC(context, m, setCarry, shift); break;
|
||||
case ShiftType.Asr: m = InstEmitAluHelper.GetAsrC(context, m, setCarry, shift); break;
|
||||
case ShiftType.Lsl:
|
||||
m = InstEmitAluHelper.GetLslC(context, m, setCarry, shift);
|
||||
break;
|
||||
case ShiftType.Lsr:
|
||||
m = InstEmitAluHelper.GetLsrC(context, m, setCarry, shift);
|
||||
break;
|
||||
case ShiftType.Asr:
|
||||
m = InstEmitAluHelper.GetAsrC(context, m, setCarry, shift);
|
||||
break;
|
||||
case ShiftType.Ror:
|
||||
if (op.Immediate != 0)
|
||||
{
|
||||
|
|
|
@ -2,7 +2,7 @@ using ARMeilleure.Decoders;
|
|||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
|
||||
namespace ARMeilleure.Instructions
|
||||
|
@ -33,6 +33,7 @@ namespace ARMeilleure.Instructions
|
|||
public static void Umsubl(ArmEmitterContext context) => EmitMull(context, MullFlags.Subtract);
|
||||
|
||||
[Flags]
|
||||
[SuppressMessage("Design", "CA1069: Enums values should not be duplicated")]
|
||||
private enum MullFlags
|
||||
{
|
||||
Subtract = 0,
|
||||
|
@ -40,7 +41,7 @@ namespace ARMeilleure.Instructions
|
|||
Signed = 1 << 1,
|
||||
|
||||
SignedAdd = Signed | Add,
|
||||
SignedSubtract = Signed | Subtract
|
||||
SignedSubtract = Signed | Subtract,
|
||||
}
|
||||
|
||||
private static void EmitMull(ArmEmitterContext context, MullFlags flags)
|
||||
|
|
|
@ -3,7 +3,6 @@ using ARMeilleure.IntermediateRepresentation;
|
|||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitAluHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
@ -20,7 +19,7 @@ namespace ARMeilleure.Instructions
|
|||
Signed = 1 << 2,
|
||||
|
||||
SignedAdd = Signed | Add,
|
||||
SignedSubtract = Signed | Subtract
|
||||
SignedSubtract = Signed | Subtract,
|
||||
}
|
||||
|
||||
public static void Mla(ArmEmitterContext context)
|
||||
|
|
|
@ -7,7 +7,6 @@ using ARMeilleure.State;
|
|||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper32;
|
||||
|
@ -185,11 +184,12 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
int eSize = 8 << op.Size;
|
||||
|
||||
Operand res = eSize switch {
|
||||
8 => Clz_V_I8 (context, GetVec(op.Rn)),
|
||||
Operand res = eSize switch
|
||||
{
|
||||
8 => Clz_V_I8(context, GetVec(op.Rn)),
|
||||
16 => Clz_V_I16(context, GetVec(op.Rn)),
|
||||
32 => Clz_V_I32(context, GetVec(op.Rn)),
|
||||
_ => default
|
||||
_ => default,
|
||||
};
|
||||
|
||||
if (res != default)
|
||||
|
@ -282,12 +282,14 @@ namespace ARMeilleure.Instructions
|
|||
return default;
|
||||
}
|
||||
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
Operand AddVectorI32(Operand op0, Operand op1) => context.AddIntrinsic(Intrinsic.X86Paddd, op0, op1);
|
||||
Operand SubVectorI32(Operand op0, Operand op1) => context.AddIntrinsic(Intrinsic.X86Psubd, op0, op1);
|
||||
Operand ShiftRightVectorUI32(Operand op0, int imm8) => context.AddIntrinsic(Intrinsic.X86Psrld, op0, Const(imm8));
|
||||
Operand OrVector(Operand op0, Operand op1) => context.AddIntrinsic(Intrinsic.X86Por, op0, op1);
|
||||
Operand AndVector(Operand op0, Operand op1) => context.AddIntrinsic(Intrinsic.X86Pand, op0, op1);
|
||||
Operand NotVector(Operand op0) => context.AddIntrinsic(Intrinsic.X86Pandn, op0, context.VectorOne());
|
||||
#pragma warning restore IDE0055
|
||||
|
||||
Operand c55555555 = X86GetAllElements(context, 0x55555555);
|
||||
Operand c33333333 = X86GetAllElements(context, 0x33333333);
|
||||
|
@ -4686,7 +4688,7 @@ namespace ARMeilleure.Instructions
|
|||
Debug.Assert(op1.Type == OperandType.I64 && op2.Type == OperandType.I64);
|
||||
|
||||
Operand cmp = signed
|
||||
? context.ICompareGreaterOrEqual (op1, op2)
|
||||
? context.ICompareGreaterOrEqual(op1, op2)
|
||||
: context.ICompareGreaterOrEqualUI(op1, op2);
|
||||
|
||||
return context.ConditionalSelect(cmp, op1, op2);
|
||||
|
@ -4697,7 +4699,7 @@ namespace ARMeilleure.Instructions
|
|||
Debug.Assert(op1.Type == OperandType.I64 && op2.Type == OperandType.I64);
|
||||
|
||||
Operand cmp = signed
|
||||
? context.ICompareLessOrEqual (op1, op2)
|
||||
? context.ICompareLessOrEqual(op1, op2)
|
||||
: context.ICompareLessOrEqualUI(op1, op2);
|
||||
|
||||
return context.ConditionalSelect(cmp, op1, op2);
|
||||
|
@ -5003,7 +5005,7 @@ namespace ARMeilleure.Instructions
|
|||
if (sizeF == 0)
|
||||
{
|
||||
Operand negInfMask = scalar
|
||||
? X86GetScalar (context, isMaxNum ? float.NegativeInfinity : float.PositiveInfinity)
|
||||
? X86GetScalar(context, isMaxNum ? float.NegativeInfinity : float.PositiveInfinity)
|
||||
: X86GetAllElements(context, isMaxNum ? float.NegativeInfinity : float.PositiveInfinity);
|
||||
|
||||
Operand nMask = context.AddIntrinsic(Intrinsic.X86Andnps, mQNaNMask, nQNaNMask);
|
||||
|
@ -5038,7 +5040,7 @@ namespace ARMeilleure.Instructions
|
|||
else /* if (sizeF == 1) */
|
||||
{
|
||||
Operand negInfMask = scalar
|
||||
? X86GetScalar (context, isMaxNum ? double.NegativeInfinity : double.PositiveInfinity)
|
||||
? X86GetScalar(context, isMaxNum ? double.NegativeInfinity : double.PositiveInfinity)
|
||||
: X86GetAllElements(context, isMaxNum ? double.NegativeInfinity : double.PositiveInfinity);
|
||||
|
||||
Operand nMask = context.AddIntrinsic(Intrinsic.X86Andnpd, mQNaNMask, nQNaNMask);
|
||||
|
@ -5072,7 +5074,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
None,
|
||||
Add,
|
||||
Subtract
|
||||
Subtract,
|
||||
}
|
||||
|
||||
private static void EmitSse41VectorMul_AddSub(ArmEmitterContext context, AddSub addSub)
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitFlowHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
|
@ -190,7 +189,7 @@ namespace ARMeilleure.Instructions
|
|||
2 => context.Multiply(context.ZeroExtend32(OperandType.I64, insert), Const(0x0000000100000001u)),
|
||||
1 => context.Multiply(context.ZeroExtend16(OperandType.I64, insert), Const(0x0001000100010001u)),
|
||||
0 => context.Multiply(context.ZeroExtend8(OperandType.I64, insert), Const(0x0101010101010101u)),
|
||||
_ => throw new InvalidOperationException($"Invalid Vdup size \"{op.Size}\".")
|
||||
_ => throw new InvalidOperationException($"Invalid Vdup size \"{op.Size}\"."),
|
||||
};
|
||||
|
||||
InsertScalar(context, op.Vd, insert);
|
||||
|
@ -212,7 +211,7 @@ namespace ARMeilleure.Instructions
|
|||
2 => context.Multiply(context.ZeroExtend32(OperandType.I64, insert), Const(0x0000000100000001u)),
|
||||
1 => context.Multiply(context.ZeroExtend16(OperandType.I64, insert), Const(0x0001000100010001u)),
|
||||
0 => context.Multiply(context.ZeroExtend8(OperandType.I64, insert), Const(0x0101010101010101u)),
|
||||
_ => throw new InvalidOperationException($"Invalid Vdup size \"{op.Size}\".")
|
||||
_ => throw new InvalidOperationException($"Invalid Vdup size \"{op.Size}\"."),
|
||||
};
|
||||
|
||||
InsertScalar(context, op.Vd, insert);
|
||||
|
@ -1654,7 +1653,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
IOpCode32Simd op = (IOpCode32Simd)context.CurrOp;
|
||||
|
||||
Func<Operand, Operand, Operand> genericEmit = (n, m) =>
|
||||
Operand genericEmit(Operand n, Operand m)
|
||||
{
|
||||
Operand nNum = context.Copy(n);
|
||||
Operand mNum = context.Copy(m);
|
||||
|
@ -1688,7 +1687,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
return context.AddIntrinsic(isMaxNum ? Intrinsic.X86Maxpd : Intrinsic.X86Minpd, nNum, mNum);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (scalar)
|
||||
{
|
||||
|
|
|
@ -3,7 +3,6 @@ using ARMeilleure.IntermediateRepresentation;
|
|||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
@ -510,7 +509,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
private static void EmitSetNzcv(ArmEmitterContext context, int nzcv)
|
||||
{
|
||||
Operand Extract(int value, int bit)
|
||||
static Operand Extract(int value, int bit)
|
||||
{
|
||||
if (bit != 0)
|
||||
{
|
||||
|
@ -532,7 +531,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
||||
bool cmpWithZero = !(op is OpCodeSimdFcond) ? op.Bit3 : false;
|
||||
bool cmpWithZero = op is not OpCodeSimdFcond && op.Bit3;
|
||||
|
||||
if (Optimizations.FastFP && (signalNaNs ? Optimizations.UseAvx : Optimizations.UseSse2))
|
||||
{
|
||||
|
|
|
@ -5,7 +5,6 @@ using ARMeilleure.Translation;
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
@ -1225,15 +1224,15 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
Debug.Assert(opF.Type == OperandType.V128);
|
||||
|
||||
Operand longL = context.AddIntrinsicLong (Intrinsic.X86Cvtsd2si, opF); // opFL
|
||||
Operand longL = context.AddIntrinsicLong(Intrinsic.X86Cvtsd2si, opF); // opFL
|
||||
Operand res = context.VectorCreateScalar(longL);
|
||||
|
||||
if (!scalar)
|
||||
{
|
||||
Operand opFH = context.AddIntrinsic (Intrinsic.X86Movhlps, res, opF); // res doesn't matter.
|
||||
Operand longH = context.AddIntrinsicLong (Intrinsic.X86Cvtsd2si, opFH);
|
||||
Operand opFH = context.AddIntrinsic(Intrinsic.X86Movhlps, res, opF); // res doesn't matter.
|
||||
Operand longH = context.AddIntrinsicLong(Intrinsic.X86Cvtsd2si, opFH);
|
||||
Operand resH = context.VectorCreateScalar(longH);
|
||||
res = context.AddIntrinsic (Intrinsic.X86Movlhps, res, resH);
|
||||
res = context.AddIntrinsic(Intrinsic.X86Movlhps, res, resH);
|
||||
}
|
||||
|
||||
return res;
|
||||
|
@ -1244,14 +1243,14 @@ namespace ARMeilleure.Instructions
|
|||
Debug.Assert(op.Type == OperandType.V128);
|
||||
|
||||
Operand longL = context.AddIntrinsicLong(Intrinsic.X86Cvtsi2si, op); // opL
|
||||
Operand res = context.AddIntrinsic (Intrinsic.X86Cvtsi2sd, context.VectorZero(), longL);
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Cvtsi2sd, context.VectorZero(), longL);
|
||||
|
||||
if (!scalar)
|
||||
{
|
||||
Operand opH = context.AddIntrinsic (Intrinsic.X86Movhlps, res, op); // res doesn't matter.
|
||||
Operand opH = context.AddIntrinsic(Intrinsic.X86Movhlps, res, op); // res doesn't matter.
|
||||
Operand longH = context.AddIntrinsicLong(Intrinsic.X86Cvtsi2si, opH);
|
||||
Operand resH = context.AddIntrinsic (Intrinsic.X86Cvtsi2sd, res, longH); // res doesn't matter.
|
||||
res = context.AddIntrinsic (Intrinsic.X86Movlhps, res, resH);
|
||||
Operand resH = context.AddIntrinsic(Intrinsic.X86Cvtsi2sd, res, longH); // res doesn't matter.
|
||||
res = context.AddIntrinsic(Intrinsic.X86Movlhps, res, resH);
|
||||
}
|
||||
|
||||
return res;
|
||||
|
@ -1278,7 +1277,7 @@ namespace ARMeilleure.Instructions
|
|||
int fpScaled = 0x3F800000 - fBits * 0x800000;
|
||||
|
||||
Operand fpScaledMask = scalar
|
||||
? X86GetScalar (context, fpScaled)
|
||||
? X86GetScalar(context, fpScaled)
|
||||
: X86GetAllElements(context, fpScaled);
|
||||
|
||||
res = context.AddIntrinsic(Intrinsic.X86Mulps, res, fpScaledMask);
|
||||
|
@ -1307,7 +1306,7 @@ namespace ARMeilleure.Instructions
|
|||
long fpScaled = 0x3FF0000000000000L - fBits * 0x10000000000000L;
|
||||
|
||||
Operand fpScaledMask = scalar
|
||||
? X86GetScalar (context, fpScaled)
|
||||
? X86GetScalar(context, fpScaled)
|
||||
: X86GetAllElements(context, fpScaled);
|
||||
|
||||
res = context.AddIntrinsic(Intrinsic.X86Mulpd, res, fpScaledMask);
|
||||
|
@ -1334,7 +1333,7 @@ namespace ARMeilleure.Instructions
|
|||
if (sizeF == 0)
|
||||
{
|
||||
Operand mask = scalar // 65536.000f (1 << 16)
|
||||
? X86GetScalar (context, 0x47800000)
|
||||
? X86GetScalar(context, 0x47800000)
|
||||
: X86GetAllElements(context, 0x47800000);
|
||||
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Psrld, n, Const(16));
|
||||
|
@ -1355,7 +1354,7 @@ namespace ARMeilleure.Instructions
|
|||
int fpScaled = 0x3F800000 - fBits * 0x800000;
|
||||
|
||||
Operand fpScaledMask = scalar
|
||||
? X86GetScalar (context, fpScaled)
|
||||
? X86GetScalar(context, fpScaled)
|
||||
: X86GetAllElements(context, fpScaled);
|
||||
|
||||
res = context.AddIntrinsic(Intrinsic.X86Mulps, res, fpScaledMask);
|
||||
|
@ -1375,15 +1374,15 @@ namespace ARMeilleure.Instructions
|
|||
else /* if (sizeF == 1) */
|
||||
{
|
||||
Operand mask = scalar // 4294967296.0000000d (1L << 32)
|
||||
? X86GetScalar (context, 0x41F0000000000000L)
|
||||
? X86GetScalar(context, 0x41F0000000000000L)
|
||||
: X86GetAllElements(context, 0x41F0000000000000L);
|
||||
|
||||
Operand res = context.AddIntrinsic (Intrinsic.X86Psrlq, n, Const(32));
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Psrlq, n, Const(32));
|
||||
res = EmitSse2CvtInt64ToDoubleOp(context, res, scalar);
|
||||
res = context.AddIntrinsic (Intrinsic.X86Mulpd, res, mask);
|
||||
res = context.AddIntrinsic(Intrinsic.X86Mulpd, res, mask);
|
||||
|
||||
Operand res2 = context.AddIntrinsic (Intrinsic.X86Psllq, n, Const(32));
|
||||
res2 = context.AddIntrinsic (Intrinsic.X86Psrlq, res2, Const(32));
|
||||
Operand res2 = context.AddIntrinsic(Intrinsic.X86Psllq, n, Const(32));
|
||||
res2 = context.AddIntrinsic(Intrinsic.X86Psrlq, res2, Const(32));
|
||||
res2 = EmitSse2CvtInt64ToDoubleOp(context, res2, scalar);
|
||||
|
||||
res = context.AddIntrinsic(Intrinsic.X86Addpd, res, res2);
|
||||
|
@ -1396,7 +1395,7 @@ namespace ARMeilleure.Instructions
|
|||
long fpScaled = 0x3FF0000000000000L - fBits * 0x10000000000000L;
|
||||
|
||||
Operand fpScaledMask = scalar
|
||||
? X86GetScalar (context, fpScaled)
|
||||
? X86GetScalar(context, fpScaled)
|
||||
: X86GetAllElements(context, fpScaled);
|
||||
|
||||
res = context.AddIntrinsic(Intrinsic.X86Mulpd, res, fpScaledMask);
|
||||
|
@ -1433,7 +1432,7 @@ namespace ARMeilleure.Instructions
|
|||
int fpScaled = 0x3F800000 + fBits * 0x800000;
|
||||
|
||||
Operand fpScaledMask = scalar
|
||||
? X86GetScalar (context, fpScaled)
|
||||
? X86GetScalar(context, fpScaled)
|
||||
: X86GetAllElements(context, fpScaled);
|
||||
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Mulps, nRes, fpScaledMask);
|
||||
|
@ -1451,7 +1450,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand nInt = context.AddIntrinsic(Intrinsic.X86Cvtps2dq, nRes);
|
||||
|
||||
Operand fpMaxValMask = scalar // 2.14748365E9f (2147483648)
|
||||
? X86GetScalar (context, 0x4F000000)
|
||||
? X86GetScalar(context, 0x4F000000)
|
||||
: X86GetAllElements(context, 0x4F000000);
|
||||
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Cmpps, nRes, fpMaxValMask, Const((int)CmpCondition.NotLessThan));
|
||||
|
@ -1482,7 +1481,7 @@ namespace ARMeilleure.Instructions
|
|||
long fpScaled = 0x3FF0000000000000L + fBits * 0x10000000000000L;
|
||||
|
||||
Operand fpScaledMask = scalar
|
||||
? X86GetScalar (context, fpScaled)
|
||||
? X86GetScalar(context, fpScaled)
|
||||
: X86GetAllElements(context, fpScaled);
|
||||
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Mulpd, nRes, fpScaledMask);
|
||||
|
@ -1500,7 +1499,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand nLong = EmitSse2CvtDoubleToInt64OpF(context, nRes, scalar);
|
||||
|
||||
Operand fpMaxValMask = scalar // 9.2233720368547760E18d (9223372036854775808)
|
||||
? X86GetScalar (context, 0x43E0000000000000L)
|
||||
? X86GetScalar(context, 0x43E0000000000000L)
|
||||
: X86GetAllElements(context, 0x43E0000000000000L);
|
||||
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Cmppd, nRes, fpMaxValMask, Const((int)CmpCondition.NotLessThan));
|
||||
|
@ -1538,7 +1537,7 @@ namespace ARMeilleure.Instructions
|
|||
int fpScaled = 0x3F800000 + fBits * 0x800000;
|
||||
|
||||
Operand fpScaledMask = scalar
|
||||
? X86GetScalar (context, fpScaled)
|
||||
? X86GetScalar(context, fpScaled)
|
||||
: X86GetAllElements(context, fpScaled);
|
||||
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Mulps, nRes, fpScaledMask);
|
||||
|
@ -1559,7 +1558,7 @@ namespace ARMeilleure.Instructions
|
|||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, nCmp);
|
||||
|
||||
Operand fpMaxValMask = scalar // 2.14748365E9f (2147483648)
|
||||
? X86GetScalar (context, 0x4F000000)
|
||||
? X86GetScalar(context, 0x4F000000)
|
||||
: X86GetAllElements(context, 0x4F000000);
|
||||
|
||||
Operand nInt = context.AddIntrinsic(Intrinsic.X86Cvtps2dq, nRes);
|
||||
|
@ -1600,7 +1599,7 @@ namespace ARMeilleure.Instructions
|
|||
long fpScaled = 0x3FF0000000000000L + fBits * 0x10000000000000L;
|
||||
|
||||
Operand fpScaledMask = scalar
|
||||
? X86GetScalar (context, fpScaled)
|
||||
? X86GetScalar(context, fpScaled)
|
||||
: X86GetAllElements(context, fpScaled);
|
||||
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Mulpd, nRes, fpScaledMask);
|
||||
|
@ -1621,7 +1620,7 @@ namespace ARMeilleure.Instructions
|
|||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, nCmp);
|
||||
|
||||
Operand fpMaxValMask = scalar // 9.2233720368547760E18d (9223372036854775808)
|
||||
? X86GetScalar (context, 0x43E0000000000000L)
|
||||
? X86GetScalar(context, 0x43E0000000000000L)
|
||||
: X86GetAllElements(context, 0x43E0000000000000L);
|
||||
|
||||
Operand nLong = EmitSse2CvtDoubleToInt64OpF(context, nRes, scalar);
|
||||
|
@ -1678,7 +1677,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
|
||||
Operand nIntOrLong = op.RegisterSize == RegisterSize.Int32
|
||||
? context.AddIntrinsicInt (Intrinsic.X86Cvtss2si, nRes)
|
||||
? context.AddIntrinsicInt(Intrinsic.X86Cvtss2si, nRes)
|
||||
: context.AddIntrinsicLong(Intrinsic.X86Cvtss2si, nRes);
|
||||
|
||||
int fpMaxVal = op.RegisterSize == RegisterSize.Int32
|
||||
|
@ -1725,7 +1724,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
|
||||
Operand nIntOrLong = op.RegisterSize == RegisterSize.Int32
|
||||
? context.AddIntrinsicInt (Intrinsic.X86Cvtsd2si, nRes)
|
||||
? context.AddIntrinsicInt(Intrinsic.X86Cvtsd2si, nRes)
|
||||
: context.AddIntrinsicLong(Intrinsic.X86Cvtsd2si, nRes);
|
||||
|
||||
long fpMaxVal = op.RegisterSize == RegisterSize.Int32
|
||||
|
@ -1791,7 +1790,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand fpMaxValMask = X86GetScalar(context, fpMaxVal);
|
||||
|
||||
Operand nIntOrLong = op.RegisterSize == RegisterSize.Int32
|
||||
? context.AddIntrinsicInt (Intrinsic.X86Cvtss2si, nRes)
|
||||
? context.AddIntrinsicInt(Intrinsic.X86Cvtss2si, nRes)
|
||||
: context.AddIntrinsicLong(Intrinsic.X86Cvtss2si, nRes);
|
||||
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Subss, nRes, fpMaxValMask);
|
||||
|
@ -1800,7 +1799,7 @@ namespace ARMeilleure.Instructions
|
|||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, nCmp);
|
||||
|
||||
Operand nIntOrLong2 = op.RegisterSize == RegisterSize.Int32
|
||||
? context.AddIntrinsicInt (Intrinsic.X86Cvtss2si, nRes)
|
||||
? context.AddIntrinsicInt(Intrinsic.X86Cvtss2si, nRes)
|
||||
: context.AddIntrinsicLong(Intrinsic.X86Cvtss2si, nRes);
|
||||
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Cmpss, nRes, fpMaxValMask, Const((int)CmpCondition.NotLessThan));
|
||||
|
@ -1853,7 +1852,7 @@ namespace ARMeilleure.Instructions
|
|||
Operand fpMaxValMask = X86GetScalar(context, fpMaxVal);
|
||||
|
||||
Operand nIntOrLong = op.RegisterSize == RegisterSize.Int32
|
||||
? context.AddIntrinsicInt (Intrinsic.X86Cvtsd2si, nRes)
|
||||
? context.AddIntrinsicInt(Intrinsic.X86Cvtsd2si, nRes)
|
||||
: context.AddIntrinsicLong(Intrinsic.X86Cvtsd2si, nRes);
|
||||
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Subsd, nRes, fpMaxValMask);
|
||||
|
@ -1862,7 +1861,7 @@ namespace ARMeilleure.Instructions
|
|||
nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, nCmp);
|
||||
|
||||
Operand nIntOrLong2 = op.RegisterSize == RegisterSize.Int32
|
||||
? context.AddIntrinsicInt (Intrinsic.X86Cvtsd2si, nRes)
|
||||
? context.AddIntrinsicInt(Intrinsic.X86Cvtsd2si, nRes)
|
||||
: context.AddIntrinsicLong(Intrinsic.X86Cvtsd2si, nRes);
|
||||
|
||||
nRes = context.AddIntrinsic(Intrinsic.X86Cmpsd, nRes, fpMaxValMask, Const((int)CmpCondition.NotLessThan));
|
||||
|
|
|
@ -5,7 +5,6 @@ using ARMeilleure.Translation;
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper32;
|
||||
|
@ -218,32 +217,21 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
MethodInfo info = (op.Size & 1) == 0
|
||||
? typeof(MathF).GetMethod(name, new Type[] { typeof(float), typeof(MidpointRounding) })
|
||||
: typeof(Math). GetMethod(name, new Type[] { typeof(double), typeof(MidpointRounding) });
|
||||
: typeof(Math).GetMethod(name, new Type[] { typeof(double), typeof(MidpointRounding) });
|
||||
|
||||
return context.Call(info, n, Const((int)roundMode));
|
||||
}
|
||||
|
||||
private static FPRoundingMode RMToRoundMode(int rm)
|
||||
{
|
||||
FPRoundingMode roundMode;
|
||||
switch (rm)
|
||||
return rm switch
|
||||
{
|
||||
case 0b00:
|
||||
roundMode = FPRoundingMode.ToNearestAway;
|
||||
break;
|
||||
case 0b01:
|
||||
roundMode = FPRoundingMode.ToNearest;
|
||||
break;
|
||||
case 0b10:
|
||||
roundMode = FPRoundingMode.TowardsPlusInfinity;
|
||||
break;
|
||||
case 0b11:
|
||||
roundMode = FPRoundingMode.TowardsMinusInfinity;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(rm));
|
||||
}
|
||||
return roundMode;
|
||||
0b00 => FPRoundingMode.ToNearestAway,
|
||||
0b01 => FPRoundingMode.ToNearest,
|
||||
0b10 => FPRoundingMode.TowardsPlusInfinity,
|
||||
0b11 => FPRoundingMode.TowardsMinusInfinity,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(rm)),
|
||||
};
|
||||
}
|
||||
|
||||
// VCVTA/M/N/P (floating-point).
|
||||
|
@ -270,22 +258,24 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (unsigned)
|
||||
{
|
||||
inst = rm switch {
|
||||
inst = rm switch
|
||||
{
|
||||
0b00 => Intrinsic.Arm64FcvtauGp,
|
||||
0b01 => Intrinsic.Arm64FcvtnuGp,
|
||||
0b10 => Intrinsic.Arm64FcvtpuGp,
|
||||
0b11 => Intrinsic.Arm64FcvtmuGp,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(rm))
|
||||
_ => throw new InvalidOperationException($"{nameof(rm)} contains an invalid value: {rm}"),
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
inst = rm switch {
|
||||
inst = rm switch
|
||||
{
|
||||
0b00 => Intrinsic.Arm64FcvtasGp,
|
||||
0b01 => Intrinsic.Arm64FcvtnsGp,
|
||||
0b10 => Intrinsic.Arm64FcvtpsGp,
|
||||
0b11 => Intrinsic.Arm64FcvtmsGp,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(rm))
|
||||
_ => throw new InvalidOperationException($"{nameof(rm)} contains an invalid value: {rm}"),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -297,22 +287,24 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (unsigned)
|
||||
{
|
||||
inst = rm switch {
|
||||
inst = rm switch
|
||||
{
|
||||
0b00 => Intrinsic.Arm64FcvtauS,
|
||||
0b01 => Intrinsic.Arm64FcvtnuS,
|
||||
0b10 => Intrinsic.Arm64FcvtpuS,
|
||||
0b11 => Intrinsic.Arm64FcvtmuS,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(rm))
|
||||
_ => throw new InvalidOperationException($"{nameof(rm)} contains an invalid value: {rm}"),
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
inst = rm switch {
|
||||
inst = rm switch
|
||||
{
|
||||
0b00 => Intrinsic.Arm64FcvtasS,
|
||||
0b01 => Intrinsic.Arm64FcvtnsS,
|
||||
0b10 => Intrinsic.Arm64FcvtpsS,
|
||||
0b11 => Intrinsic.Arm64FcvtmsS,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(rm))
|
||||
_ => throw new InvalidOperationException($"{nameof(rm)} contains an invalid value: {rm}"),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -432,12 +424,13 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
Intrinsic inst = rm switch {
|
||||
Intrinsic inst = rm switch
|
||||
{
|
||||
0b00 => Intrinsic.Arm64FrintaS,
|
||||
0b01 => Intrinsic.Arm64FrintnS,
|
||||
0b10 => Intrinsic.Arm64FrintpS,
|
||||
0b11 => Intrinsic.Arm64FrintmS,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(rm))
|
||||
_ => throw new InvalidOperationException($"{nameof(rm)} contains an invalid value: {rm}"),
|
||||
};
|
||||
|
||||
InstEmitSimdHelper32Arm64.EmitScalarUnaryOpF32(context, inst);
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
static partial class InstEmit
|
||||
{
|
||||
#region "Sha1"
|
||||
#region "Sha1"
|
||||
public static void Sha1c_V(ArmEmitterContext context)
|
||||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
@ -89,9 +89,9 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region "Sha256"
|
||||
#region "Sha256"
|
||||
public static void Sha256h_V(ArmEmitterContext context)
|
||||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
@ -142,6 +142,6 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
static partial class InstEmit32
|
||||
{
|
||||
#region "Sha256"
|
||||
#region "Sha256"
|
||||
public static void Sha256h_V(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32SimdReg op = (OpCode32SimdReg)context.CurrOp;
|
||||
|
@ -59,6 +59,6 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
context.Copy(GetVecA32(op.Qd), res);
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ using ARMeilleure.Translation;
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
||||
|
@ -18,19 +17,19 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
static class InstEmitSimdHelper
|
||||
{
|
||||
#region "Masks"
|
||||
#region "Masks"
|
||||
public static readonly long[] EvenMasks = new long[]
|
||||
{
|
||||
14L << 56 | 12L << 48 | 10L << 40 | 08L << 32 | 06L << 24 | 04L << 16 | 02L << 8 | 00L << 0, // B
|
||||
13L << 56 | 12L << 48 | 09L << 40 | 08L << 32 | 05L << 24 | 04L << 16 | 01L << 8 | 00L << 0, // H
|
||||
11L << 56 | 10L << 48 | 09L << 40 | 08L << 32 | 03L << 24 | 02L << 16 | 01L << 8 | 00L << 0 // S
|
||||
11L << 56 | 10L << 48 | 09L << 40 | 08L << 32 | 03L << 24 | 02L << 16 | 01L << 8 | 00L << 0, // S
|
||||
};
|
||||
|
||||
public static readonly long[] OddMasks = new long[]
|
||||
{
|
||||
15L << 56 | 13L << 48 | 11L << 40 | 09L << 32 | 07L << 24 | 05L << 16 | 03L << 8 | 01L << 0, // B
|
||||
15L << 56 | 14L << 48 | 11L << 40 | 10L << 32 | 07L << 24 | 06L << 16 | 03L << 8 | 02L << 0, // H
|
||||
15L << 56 | 14L << 48 | 13L << 40 | 12L << 32 | 07L << 24 | 06L << 16 | 05L << 8 | 04L << 0 // S
|
||||
15L << 56 | 14L << 48 | 13L << 40 | 12L << 32 | 07L << 24 | 06L << 16 | 05L << 8 | 04L << 0, // S
|
||||
};
|
||||
|
||||
public static readonly long ZeroMask = 128L << 56 | 128L << 48 | 128L << 40 | 128L << 32 | 128L << 24 | 128L << 16 | 128L << 8 | 128L << 0;
|
||||
|
@ -42,15 +41,15 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
return shift >= 0 ? identity >> (shift * 8) : identity << (-shift * 8);
|
||||
}
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
#region "X86 SSE Intrinsics"
|
||||
#region "X86 SSE Intrinsics"
|
||||
public static readonly Intrinsic[] X86PaddInstruction = new Intrinsic[]
|
||||
{
|
||||
Intrinsic.X86Paddb,
|
||||
Intrinsic.X86Paddw,
|
||||
Intrinsic.X86Paddd,
|
||||
Intrinsic.X86Paddq
|
||||
Intrinsic.X86Paddq,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PcmpeqInstruction = new Intrinsic[]
|
||||
|
@ -58,7 +57,7 @@ namespace ARMeilleure.Instructions
|
|||
Intrinsic.X86Pcmpeqb,
|
||||
Intrinsic.X86Pcmpeqw,
|
||||
Intrinsic.X86Pcmpeqd,
|
||||
Intrinsic.X86Pcmpeqq
|
||||
Intrinsic.X86Pcmpeqq,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PcmpgtInstruction = new Intrinsic[]
|
||||
|
@ -66,49 +65,49 @@ namespace ARMeilleure.Instructions
|
|||
Intrinsic.X86Pcmpgtb,
|
||||
Intrinsic.X86Pcmpgtw,
|
||||
Intrinsic.X86Pcmpgtd,
|
||||
Intrinsic.X86Pcmpgtq
|
||||
Intrinsic.X86Pcmpgtq,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PmaxsInstruction = new Intrinsic[]
|
||||
{
|
||||
Intrinsic.X86Pmaxsb,
|
||||
Intrinsic.X86Pmaxsw,
|
||||
Intrinsic.X86Pmaxsd
|
||||
Intrinsic.X86Pmaxsd,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PmaxuInstruction = new Intrinsic[]
|
||||
{
|
||||
Intrinsic.X86Pmaxub,
|
||||
Intrinsic.X86Pmaxuw,
|
||||
Intrinsic.X86Pmaxud
|
||||
Intrinsic.X86Pmaxud,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PminsInstruction = new Intrinsic[]
|
||||
{
|
||||
Intrinsic.X86Pminsb,
|
||||
Intrinsic.X86Pminsw,
|
||||
Intrinsic.X86Pminsd
|
||||
Intrinsic.X86Pminsd,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PminuInstruction = new Intrinsic[]
|
||||
{
|
||||
Intrinsic.X86Pminub,
|
||||
Intrinsic.X86Pminuw,
|
||||
Intrinsic.X86Pminud
|
||||
Intrinsic.X86Pminud,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PmovsxInstruction = new Intrinsic[]
|
||||
{
|
||||
Intrinsic.X86Pmovsxbw,
|
||||
Intrinsic.X86Pmovsxwd,
|
||||
Intrinsic.X86Pmovsxdq
|
||||
Intrinsic.X86Pmovsxdq,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PmovzxInstruction = new Intrinsic[]
|
||||
{
|
||||
Intrinsic.X86Pmovzxbw,
|
||||
Intrinsic.X86Pmovzxwd,
|
||||
Intrinsic.X86Pmovzxdq
|
||||
Intrinsic.X86Pmovzxdq,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PsllInstruction = new Intrinsic[]
|
||||
|
@ -116,14 +115,14 @@ namespace ARMeilleure.Instructions
|
|||
0,
|
||||
Intrinsic.X86Psllw,
|
||||
Intrinsic.X86Pslld,
|
||||
Intrinsic.X86Psllq
|
||||
Intrinsic.X86Psllq,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PsraInstruction = new Intrinsic[]
|
||||
{
|
||||
0,
|
||||
Intrinsic.X86Psraw,
|
||||
Intrinsic.X86Psrad
|
||||
Intrinsic.X86Psrad,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PsrlInstruction = new Intrinsic[]
|
||||
|
@ -131,7 +130,7 @@ namespace ARMeilleure.Instructions
|
|||
0,
|
||||
Intrinsic.X86Psrlw,
|
||||
Intrinsic.X86Psrld,
|
||||
Intrinsic.X86Psrlq
|
||||
Intrinsic.X86Psrlq,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PsubInstruction = new Intrinsic[]
|
||||
|
@ -139,7 +138,7 @@ namespace ARMeilleure.Instructions
|
|||
Intrinsic.X86Psubb,
|
||||
Intrinsic.X86Psubw,
|
||||
Intrinsic.X86Psubd,
|
||||
Intrinsic.X86Psubq
|
||||
Intrinsic.X86Psubq,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PunpckhInstruction = new Intrinsic[]
|
||||
|
@ -147,7 +146,7 @@ namespace ARMeilleure.Instructions
|
|||
Intrinsic.X86Punpckhbw,
|
||||
Intrinsic.X86Punpckhwd,
|
||||
Intrinsic.X86Punpckhdq,
|
||||
Intrinsic.X86Punpckhqdq
|
||||
Intrinsic.X86Punpckhqdq,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PunpcklInstruction = new Intrinsic[]
|
||||
|
@ -155,9 +154,9 @@ namespace ARMeilleure.Instructions
|
|||
Intrinsic.X86Punpcklbw,
|
||||
Intrinsic.X86Punpcklwd,
|
||||
Intrinsic.X86Punpckldq,
|
||||
Intrinsic.X86Punpcklqdq
|
||||
Intrinsic.X86Punpcklqdq,
|
||||
};
|
||||
#endregion
|
||||
#endregion
|
||||
|
||||
public static void EnterArmFpMode(EmitterContext context, Func<FPState, Operand> getFpFlag)
|
||||
{
|
||||
|
@ -310,15 +309,16 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static int X86GetRoundControl(FPRoundingMode roundMode)
|
||||
{
|
||||
switch (roundMode)
|
||||
return roundMode switch
|
||||
{
|
||||
case FPRoundingMode.ToNearest: return 8 | 0; // even
|
||||
case FPRoundingMode.TowardsPlusInfinity: return 8 | 2;
|
||||
case FPRoundingMode.TowardsMinusInfinity: return 8 | 1;
|
||||
case FPRoundingMode.TowardsZero: return 8 | 3;
|
||||
}
|
||||
|
||||
throw new ArgumentException($"Invalid rounding mode \"{roundMode}\".");
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
FPRoundingMode.ToNearest => 8 | 0, // even
|
||||
FPRoundingMode.TowardsPlusInfinity => 8 | 2,
|
||||
FPRoundingMode.TowardsMinusInfinity => 8 | 1,
|
||||
FPRoundingMode.TowardsZero => 8 | 3,
|
||||
_ => throw new ArgumentException($"Invalid rounding mode \"{roundMode}\"."),
|
||||
#pragma warning restore IDE0055
|
||||
};
|
||||
}
|
||||
|
||||
public static Operand EmitSse41RoundToNearestWithTiesToAwayOpF(ArmEmitterContext context, Operand n, bool scalar)
|
||||
|
@ -461,7 +461,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
MethodInfo info = (op.Size & 1) == 0
|
||||
? typeof(MathF).GetMethod(name, new Type[] { typeof(float) })
|
||||
: typeof(Math). GetMethod(name, new Type[] { typeof(double) });
|
||||
: typeof(Math).GetMethod(name, new Type[] { typeof(double) });
|
||||
|
||||
return context.Call(info, n);
|
||||
}
|
||||
|
@ -474,7 +474,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
MethodInfo info = (op.Size & 1) == 0
|
||||
? typeof(MathF).GetMethod(name, new Type[] { typeof(float), typeof(MidpointRounding) })
|
||||
: typeof(Math). GetMethod(name, new Type[] { typeof(double), typeof(MidpointRounding) });
|
||||
: typeof(Math).GetMethod(name, new Type[] { typeof(double), typeof(MidpointRounding) });
|
||||
|
||||
return context.Call(info, n, Const((int)roundMode));
|
||||
}
|
||||
|
@ -1197,7 +1197,7 @@ namespace ARMeilleure.Instructions
|
|||
if (op.RegisterSize == RegisterSize.Simd64)
|
||||
{
|
||||
Operand zeroEvenMask = X86GetElements(context, ZeroMask, EvenMasks[op.Size]);
|
||||
Operand zeroOddMask = X86GetElements(context, ZeroMask, OddMasks [op.Size]);
|
||||
Operand zeroOddMask = X86GetElements(context, ZeroMask, OddMasks[op.Size]);
|
||||
|
||||
Operand mN = context.AddIntrinsic(Intrinsic.X86Punpcklqdq, n, m); // m:n
|
||||
|
||||
|
@ -1444,7 +1444,7 @@ namespace ARMeilleure.Instructions
|
|||
// Vex.
|
||||
GreaterThanOrEqual = 13, // Ordered, signaling.
|
||||
GreaterThan = 14, // Ordered, signaling.
|
||||
OrderedS = 23 // Signaling.
|
||||
OrderedS = 23, // Signaling.
|
||||
}
|
||||
|
||||
[Flags]
|
||||
|
@ -1459,7 +1459,7 @@ namespace ARMeilleure.Instructions
|
|||
Add = 1 << 3,
|
||||
Sub = 1 << 4,
|
||||
|
||||
Accumulate = 1 << 5
|
||||
Accumulate = 1 << 5,
|
||||
}
|
||||
|
||||
public static void EmitScalarSaturatingUnaryOpSx(ArmEmitterContext context, Func1I emit)
|
||||
|
@ -1637,7 +1637,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
VectorSxSx = SignedSrc | SignedDst,
|
||||
VectorSxZx = SignedSrc,
|
||||
VectorZxZx = 0
|
||||
VectorZxZx = 0,
|
||||
}
|
||||
|
||||
public static void EmitSaturatingNarrowOp(ArmEmitterContext context, SaturatingNarrowFlags flags)
|
||||
|
@ -2034,18 +2034,30 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
switch (size)
|
||||
{
|
||||
case 0: res = context.SignExtend8 (OperandType.I64, res); break;
|
||||
case 1: res = context.SignExtend16(OperandType.I64, res); break;
|
||||
case 2: res = context.SignExtend32(OperandType.I64, res); break;
|
||||
case 0:
|
||||
res = context.SignExtend8(OperandType.I64, res);
|
||||
break;
|
||||
case 1:
|
||||
res = context.SignExtend16(OperandType.I64, res);
|
||||
break;
|
||||
case 2:
|
||||
res = context.SignExtend32(OperandType.I64, res);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (size)
|
||||
{
|
||||
case 0: res = context.ZeroExtend8 (OperandType.I64, res); break;
|
||||
case 1: res = context.ZeroExtend16(OperandType.I64, res); break;
|
||||
case 2: res = context.ZeroExtend32(OperandType.I64, res); break;
|
||||
case 0:
|
||||
res = context.ZeroExtend8(OperandType.I64, res);
|
||||
break;
|
||||
case 1:
|
||||
res = context.ZeroExtend16(OperandType.I64, res);
|
||||
break;
|
||||
case 2:
|
||||
res = context.ZeroExtend32(OperandType.I64, res);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2063,10 +2075,18 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0: vector = context.VectorInsert8 (vector, value, index); break;
|
||||
case 1: vector = context.VectorInsert16(vector, value, index); break;
|
||||
case 2: vector = context.VectorInsert (vector, value, index); break;
|
||||
case 3: vector = context.VectorInsert (vector, value, index); break;
|
||||
case 0:
|
||||
vector = context.VectorInsert8(vector, value, index);
|
||||
break;
|
||||
case 1:
|
||||
vector = context.VectorInsert16(vector, value, index);
|
||||
break;
|
||||
case 2:
|
||||
vector = context.VectorInsert(vector, value, index);
|
||||
break;
|
||||
case 3:
|
||||
vector = context.VectorInsert(vector, value, index);
|
||||
break;
|
||||
}
|
||||
|
||||
return vector;
|
||||
|
|
|
@ -4,7 +4,6 @@ using ARMeilleure.Translation;
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
@ -19,18 +18,13 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
public static (int, int) GetQuadwordAndSubindex(int index, RegisterSize size)
|
||||
{
|
||||
switch (size)
|
||||
return size switch
|
||||
{
|
||||
case RegisterSize.Simd128:
|
||||
return (index >> 1, 0);
|
||||
case RegisterSize.Simd64:
|
||||
case RegisterSize.Int64:
|
||||
return (index >> 1, index & 1);
|
||||
case RegisterSize.Int32:
|
||||
return (index >> 2, index & 3);
|
||||
}
|
||||
|
||||
throw new ArgumentException("Unrecognized Vector Register Size.");
|
||||
RegisterSize.Simd128 => (index >> 1, 0),
|
||||
RegisterSize.Simd64 or RegisterSize.Int64 => (index >> 1, index & 1),
|
||||
RegisterSize.Int32 => (index >> 2, index & 3),
|
||||
_ => throw new ArgumentException("Unrecognized Vector Register Size."),
|
||||
};
|
||||
}
|
||||
|
||||
public static Operand ExtractScalar(ArmEmitterContext context, OperandType type, int reg)
|
||||
|
@ -778,7 +772,10 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
// Index into 0, 0 into index. This swap happens at the start of an A32 scalar op if required.
|
||||
int index = reg & (doubleWidth ? 1 : 3);
|
||||
if (index == 0) return target;
|
||||
if (index == 0)
|
||||
{
|
||||
return target;
|
||||
}
|
||||
|
||||
if (doubleWidth)
|
||||
{
|
||||
|
@ -1195,7 +1192,7 @@ namespace ARMeilleure.Instructions
|
|||
: typeof(SoftFloat64).GetMethod(name);
|
||||
|
||||
Array.Resize(ref callArgs, callArgs.Length + 1);
|
||||
callArgs[callArgs.Length - 1] = Const(1);
|
||||
callArgs[^1] = Const(1);
|
||||
|
||||
context.ExitArmFpMode();
|
||||
context.StoreToContext();
|
||||
|
@ -1245,16 +1242,24 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
switch (size)
|
||||
{
|
||||
case 0: res = context.SignExtend8(OperandType.I32, res); break;
|
||||
case 1: res = context.SignExtend16(OperandType.I32, res); break;
|
||||
case 0:
|
||||
res = context.SignExtend8(OperandType.I32, res);
|
||||
break;
|
||||
case 1:
|
||||
res = context.SignExtend16(OperandType.I32, res);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (size)
|
||||
{
|
||||
case 0: res = context.ZeroExtend8(OperandType.I32, res); break;
|
||||
case 1: res = context.ZeroExtend16(OperandType.I32, res); break;
|
||||
case 0:
|
||||
res = context.ZeroExtend8(OperandType.I32, res);
|
||||
break;
|
||||
case 1:
|
||||
res = context.ZeroExtend16(OperandType.I32, res);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
|
||||
using ARMeilleure.Decoders;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
@ -74,7 +72,10 @@ namespace ARMeilleure.Instructions
|
|||
public static Operand EmitExtractScalar(ArmEmitterContext context, Operand target, int reg, bool doubleWidth)
|
||||
{
|
||||
int index = reg & (doubleWidth ? 1 : 3);
|
||||
if (index == 0) return target; // Element is already at index 0, so just return the vector directly.
|
||||
if (index == 0)
|
||||
{
|
||||
return target; // Element is already at index 0, so just return the vector directly.
|
||||
}
|
||||
|
||||
if (doubleWidth)
|
||||
{
|
||||
|
@ -336,16 +337,17 @@ namespace ARMeilleure.Instructions
|
|||
CmpCondition.GreaterThanOrEqual => Intrinsic.Arm64FcmgeVz,
|
||||
CmpCondition.LessThan => Intrinsic.Arm64FcmltVz,
|
||||
CmpCondition.LessThanOrEqual => Intrinsic.Arm64FcmleVz,
|
||||
_ => throw new InvalidOperationException()
|
||||
_ => throw new InvalidOperationException(),
|
||||
};
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
inst = cond switch
|
||||
{
|
||||
CmpCondition.Equal => Intrinsic.Arm64FcmeqV,
|
||||
CmpCondition.GreaterThan => Intrinsic.Arm64FcmgtV,
|
||||
CmpCondition.GreaterThanOrEqual => Intrinsic.Arm64FcmgeV,
|
||||
_ => throw new InvalidOperationException()
|
||||
_ => throw new InvalidOperationException(),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
|
||||
SetIntOrZR(context, op.Rd, op.RegisterSize == RegisterSize.Int32
|
||||
? context.AddIntrinsicInt (inst, n)
|
||||
? context.AddIntrinsicInt(inst, n)
|
||||
: context.AddIntrinsicLong(inst, n));
|
||||
}
|
||||
|
||||
|
@ -288,7 +288,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
|
||||
SetIntOrZR(context, op.Rd, op.RegisterSize == RegisterSize.Int32
|
||||
? context.AddIntrinsicInt (inst, n, Const(fBits))
|
||||
? context.AddIntrinsicInt(inst, n, Const(fBits))
|
||||
: context.AddIntrinsicLong(inst, n, Const(fBits)));
|
||||
}
|
||||
|
||||
|
@ -695,7 +695,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
||||
bool cmpWithZero = !(op is OpCodeSimdFcond) ? op.Bit3 : false;
|
||||
bool cmpWithZero = op is not OpCodeSimdFcond && op.Bit3;
|
||||
|
||||
Intrinsic inst = signalNaNs ? Intrinsic.Arm64FcmpeS : Intrinsic.Arm64FcmpS;
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue