[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:
TSRBerry 2023-06-26 07:25:06 +02:00 committed by GitHub
parent 2de78a2d55
commit ff53dcf560
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
300 changed files with 3515 additions and 3120 deletions

View file

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

View file

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

View file

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

View file

@ -9,6 +9,6 @@ namespace ARMeilleure.CodeGen.Arm64
Sxtb = 4,
Sxth = 5,
Sxtw = 6,
Sxtx = 7
Sxtx = 7,
}
}

View file

@ -6,6 +6,6 @@ namespace ARMeilleure.CodeGen.Arm64
Lsl = 0,
Lsr = 1,
Asr = 2,
Ror = 3
Ror = 3,
}
}

View file

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

View file

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

View file

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

View file

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

View file

@ -1,6 +1,6 @@
namespace ARMeilleure.CodeGen.Arm64
{
struct IntrinsicInfo
readonly struct IntrinsicInfo
{
public uint Inst { get; }
public IntrinsicType Type { get; }

View file

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

View file

@ -55,6 +55,6 @@ namespace ARMeilleure.CodeGen.Arm64
VectorTernaryShrRd,
GetRegister,
SetRegister
SetRegister,
}
}

View file

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

View file

@ -23,6 +23,6 @@
/// <summary>
/// Refers to a special symbol which is handled by <see cref="Translation.PTC.Ptc.PatchCode"/>.
/// </summary>
Special
Special,
}
}

View file

@ -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 + "\"."),
};
}
}
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -6,6 +6,6 @@ namespace ARMeilleure.CodeGen.Unwinding
SetFrame = 1,
AllocStack = 2,
SaveReg = 3,
SaveXmm128 = 4
SaveXmm128 = 4,
}
}

View file

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

View file

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

View file

@ -3,6 +3,6 @@ namespace ARMeilleure.CodeGen.X86
enum CallConvName
{
SystemV,
Windows
Windows,
}
}

View file

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

View file

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

View file

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

View file

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

View file

@ -13,6 +13,6 @@ namespace ARMeilleure.CodeGen.X86
Crc32,
Ternary,
TernaryImm,
Fma
Fma,
}
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -226,6 +226,6 @@ namespace ARMeilleure.CodeGen.X86
Xorpd,
Xorps,
Count
Count,
}
}

View file

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

View file

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

View file

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

View file

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

View file

@ -92,7 +92,7 @@ namespace ARMeilleure.Decoders
{
if (OpCodes.Count > 0)
{
return OpCodes[OpCodes.Count - 1];
return OpCodes[^1];
}
return null;

View file

@ -17,7 +17,7 @@ namespace ARMeilleure.Decoders
Gt = 12,
Le = 13,
Al = 14,
Nv = 15
Nv = 15,
}
static class ConditionExtensions

View file

@ -5,6 +5,6 @@ namespace ARMeilleure.Decoders
Adr = 0,
Arithmetic = 1,
Logical = 2,
BitField = 3
BitField = 3,
}
}

View file

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

View file

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

View file

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

View file

@ -9,6 +9,6 @@ namespace ARMeilleure.Decoders
Int8 = 4,
Int16 = 5,
Int32 = 6,
Int64 = 7
Int64 = 7,
}
}

View file

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

View file

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

View file

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

View file

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

View file

@ -18,6 +18,6 @@
Eq = 0,
Vs,
Ge,
Gt
Gt,
}
}

View file

@ -33,7 +33,7 @@ namespace ARMeilleure.Decoders
}
else
{
throw new ArgumentException(nameof(opCode));
throw new ArgumentException($"Invalid data operation: {DataOp}", nameof(opCode));
}
}
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -24,7 +24,9 @@ namespace ARMeilleure.Decoders
break;
default: Instruction = InstDescriptor.Undefined; break;
default:
Instruction = InstDescriptor.Undefined;
break;
}
}
}

View file

@ -26,7 +26,9 @@ namespace ARMeilleure.Decoders
break;
default: Instruction = InstDescriptor.Undefined; break;
default:
Instruction = InstDescriptor.Undefined;
break;
}
}
}

View file

@ -1,6 +1,6 @@
namespace ARMeilleure.Decoders
{
class OpCodeT16AddSubImm3: OpCodeT16, IOpCode32AluImm
class OpCodeT16AddSubImm3 : OpCodeT16, IOpCode32AluImm
{
public int Rd { get; }
public int Rn { get; }

View file

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

View file

@ -27,7 +27,7 @@ namespace ARMeilleure.Decoders
{
InstName.Ldm => true,
InstName.Stm => false,
_ => throw new InvalidOperationException()
_ => throw new InvalidOperationException(),
};
}
}

View file

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

View file

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

View file

@ -5,6 +5,6 @@ namespace ARMeilleure.Decoders
Int32,
Int64,
Simd64,
Simd128
Simd128,
}
}

View file

@ -5,6 +5,6 @@ namespace ARMeilleure.Decoders
Lsl = 0,
Lsr = 1,
Asr = 2,
Ror = 3
Ror = 3,
}
}

View file

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

View file

@ -8,7 +8,7 @@ namespace ARMeilleure.Diagnostics
{
private static long _startTime;
private static long[] _accumulatedTime;
private static readonly long[] _accumulatedTime;
static Logger()
{

View file

@ -14,6 +14,6 @@ namespace ARMeilleure.Diagnostics
RegisterAllocation,
CodeGeneration,
Count
Count,
}
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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