[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)] [MethodImpl(MethodImplOptions.AggressiveInlining)]
private static ArenaAllocator GetAllocator(ref ArenaAllocator alloc, uint pageSize, uint pageCount) 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; return alloc;
} }

View file

@ -221,7 +221,7 @@ namespace ARMeilleure.CodeGen.Arm64
2 => Multiplier.x4, 2 => Multiplier.x4,
3 => Multiplier.x8, 3 => Multiplier.x8,
4 => Multiplier.x16, 4 => Multiplier.x16,
_ => Multiplier.x1 _ => Multiplier.x1,
}; };
baseOp = indexOnSrc2 ? src1 : src2; baseOp = indexOnSrc2 ? src1 : src2;

View file

@ -20,7 +20,7 @@ namespace ARMeilleure.CodeGen.Arm64
Gt = 12, Gt = 12,
Le = 13, Le = 13,
Al = 14, Al = 14,
Nv = 15 Nv = 15,
} }
static class ComparisonArm64Extensions static class ComparisonArm64Extensions
@ -29,6 +29,7 @@ namespace ARMeilleure.CodeGen.Arm64
{ {
return comp switch return comp switch
{ {
#pragma warning disable IDE0055 // Disable formatting
Comparison.Equal => ArmCondition.Eq, Comparison.Equal => ArmCondition.Eq,
Comparison.NotEqual => ArmCondition.Ne, Comparison.NotEqual => ArmCondition.Ne,
Comparison.Greater => ArmCondition.Gt, Comparison.Greater => ArmCondition.Gt,
@ -39,8 +40,9 @@ namespace ARMeilleure.CodeGen.Arm64
Comparison.Less => ArmCondition.Lt, Comparison.Less => ArmCondition.Lt,
Comparison.GreaterOrEqualUI => ArmCondition.GeUn, Comparison.GreaterOrEqualUI => ArmCondition.GeUn,
Comparison.LessUI => ArmCondition.LtUn, 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, Sxtb = 4,
Sxth = 5, Sxth = 5,
Sxtw = 6, Sxtw = 6,
Sxtx = 7 Sxtx = 7,
} }
} }

View file

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

View file

@ -992,7 +992,7 @@ namespace ARMeilleure.CodeGen.Arm64
{ {
OperandType.FP32 => 0, OperandType.FP32 => 0,
OperandType.FP64 => 1, OperandType.FP64 => 1,
_ => 2 _ => 2,
}; };
instruction = vecInst | ((uint)opc << 30); instruction = vecInst | ((uint)opc << 30);
@ -1124,10 +1124,11 @@ namespace ARMeilleure.CodeGen.Arm64
OperandType.FP32 => 2, OperandType.FP32 => 2,
OperandType.FP64 => 3, OperandType.FP64 => 3,
OperandType.V128 => 4, 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) private void WriteInt16(short value)
{ {
WriteUInt16((ushort)value); WriteUInt16((ushort)value);
@ -1142,6 +1143,7 @@ namespace ARMeilleure.CodeGen.Arm64
{ {
_stream.WriteByte(value); _stream.WriteByte(value);
} }
#pragma warning restore IDE0051
private void WriteUInt16(ushort value) private void WriteUInt16(ushort value)
{ {

View file

@ -14,7 +14,7 @@ namespace ARMeilleure.CodeGen.Arm64
private const int CbnzInstLength = 4; private const int CbnzInstLength = 4;
private const int LdrLitInstLength = 4; private const int LdrLitInstLength = 4;
private Stream _stream; private readonly Stream _stream;
public int StreamOffset => (int)_stream.Length; public int StreamOffset => (int)_stream.Length;
@ -32,7 +32,7 @@ namespace ARMeilleure.CodeGen.Arm64
private readonly Dictionary<BasicBlock, long> _visitedBlocks; private readonly Dictionary<BasicBlock, long> _visitedBlocks;
private readonly Dictionary<BasicBlock, List<(ArmCondition Condition, long BranchPos)>> _pendingBranches; private readonly Dictionary<BasicBlock, List<(ArmCondition Condition, long BranchPos)>> _pendingBranches;
private struct ConstantPoolEntry private readonly struct ConstantPoolEntry
{ {
public readonly int Offset; public readonly int Offset;
public readonly Symbol Symbol; public readonly Symbol Symbol;
@ -58,7 +58,7 @@ namespace ARMeilleure.CodeGen.Arm64
private readonly bool _relocatable; 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(); _stream = MemoryStreamManager.Shared.GetStream();
@ -93,10 +93,10 @@ namespace ARMeilleure.CodeGen.Arm64
if (_pendingBranches.TryGetValue(block, out var list)) 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); _stream.Seek(branchPos, SeekOrigin.Begin);
WriteBranch(tuple.Condition, target); WriteBranch(condition, target);
} }
_stream.Seek(target, SeekOrigin.Begin); _stream.Seek(target, SeekOrigin.Begin);

View file

@ -10,7 +10,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Numerics; using System.Numerics;
using static ARMeilleure.IntermediateRepresentation.Operand; using static ARMeilleure.IntermediateRepresentation.Operand;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory; using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
@ -31,15 +30,16 @@ namespace ARMeilleure.CodeGen.Arm64
{ {
Byte, Byte,
Hword, Hword,
Auto Auto,
} }
private static Action<CodeGenContext, Operation>[] _instTable; private static readonly Action<CodeGenContext, Operation>[] _instTable;
static CodeGenerator() static CodeGenerator()
{ {
_instTable = new Action<CodeGenContext, Operation>[EnumUtils.GetCount(typeof(Instruction))]; _instTable = new Action<CodeGenContext, Operation>[EnumUtils.GetCount(typeof(Instruction))];
#pragma warning disable IDE0055 // Disable formatting
Add(Instruction.Add, GenerateAdd); Add(Instruction.Add, GenerateAdd);
Add(Instruction.BitwiseAnd, GenerateBitwiseAnd); Add(Instruction.BitwiseAnd, GenerateBitwiseAnd);
Add(Instruction.BitwiseExclusiveOr, GenerateBitwiseExclusiveOr); Add(Instruction.BitwiseExclusiveOr, GenerateBitwiseExclusiveOr);
@ -100,6 +100,7 @@ namespace ARMeilleure.CodeGen.Arm64
Add(Instruction.ZeroExtend16, GenerateZeroExtend16); Add(Instruction.ZeroExtend16, GenerateZeroExtend16);
Add(Instruction.ZeroExtend32, GenerateZeroExtend32); Add(Instruction.ZeroExtend32, GenerateZeroExtend32);
Add(Instruction.ZeroExtend8, GenerateZeroExtend8); Add(Instruction.ZeroExtend8, GenerateZeroExtend8);
#pragma warning restore IDE0055
static void Add(Instruction inst, Action<CodeGenContext, Operation> func) static void Add(Instruction inst, Action<CodeGenContext, Operation> func)
{ {
@ -131,7 +132,7 @@ namespace ARMeilleure.CodeGen.Arm64
StackAllocator stackAlloc = new(); StackAllocator stackAlloc = new();
PreAllocator.RunPass(cctx, stackAlloc, out int maxCallArgs); PreAllocator.RunPass(cctx, out int maxCallArgs);
Logger.EndPass(PassName.PreAllocation, cfg); Logger.EndPass(PassName.PreAllocation, cfg);
@ -170,7 +171,7 @@ namespace ARMeilleure.CodeGen.Arm64
bool relocatable = (cctx.Options & CompilerOptions.Relocatable) != 0; 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); UnwindInfo unwindInfo = WritePrologue(context);
@ -1078,7 +1079,7 @@ namespace ARMeilleure.CodeGen.Arm64
private static UnwindInfo WritePrologue(CodeGenContext context) private static UnwindInfo WritePrologue(CodeGenContext context)
{ {
List<UnwindPushEntry> pushEntries = new List<UnwindPushEntry>(); List<UnwindPushEntry> pushEntries = new();
Operand rsp = Register(SpRegister); Operand rsp = Register(SpRegister);
@ -1568,11 +1569,13 @@ namespace ARMeilleure.CodeGen.Arm64
Debug.Assert(op1.Type == op3.Type); 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) private static void EnsureSameType(Operand op1, Operand op2, Operand op3, Operand op4)
{ {
Debug.Assert(op1.Type == op2.Type); Debug.Assert(op1.Type == op2.Type);
Debug.Assert(op1.Type == op3.Type); Debug.Assert(op1.Type == op3.Type);
Debug.Assert(op1.Type == op4.Type); Debug.Assert(op1.Type == op4.Type);
} }
#pragma warning restore IDE0051
} }
} }

View file

@ -1,7 +1,4 @@
using System; using System;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Runtime.Intrinsics.Arm; using System.Runtime.Intrinsics.Arm;
using System.Runtime.Versioning; using System.Runtime.Versioning;
@ -77,7 +74,7 @@ namespace ARMeilleure.CodeGen.Arm64
Ssbs = 1 << 28, Ssbs = 1 << 28,
Sb = 1 << 29, Sb = 1 << 29,
Paca = 1 << 30, Paca = 1 << 30,
Pacg = 1UL << 31 Pacg = 1UL << 31,
} }
[Flags] [Flags]
@ -119,7 +116,7 @@ namespace ARMeilleure.CodeGen.Arm64
Sve_Ebf16 = 1UL << 33, Sve_Ebf16 = 1UL << 33,
Cssc = 1UL << 34, Cssc = 1UL << 34,
Rprfm = 1UL << 35, Rprfm = 1UL << 35,
Sve2p1 = 1UL << 36 Sve2p1 = 1UL << 36,
} }
public static LinuxFeatureFlagsHwCap LinuxFeatureInfoHwCap { get; } = 0; public static LinuxFeatureFlagsHwCap LinuxFeatureInfoHwCap { get; } = 0;
@ -143,7 +140,7 @@ namespace ARMeilleure.CodeGen.Arm64
return false; return false;
} }
private static string[] _sysctlNames = new string[] private static readonly string[] _sysctlNames = new string[]
{ {
"hw.optional.floatingpoint", "hw.optional.floatingpoint",
"hw.optional.AdvSIMD", "hw.optional.AdvSIMD",
@ -153,7 +150,7 @@ namespace ARMeilleure.CodeGen.Arm64
"hw.optional.arm.FEAT_LSE", "hw.optional.arm.FEAT_LSE",
"hw.optional.armv8_crc32", "hw.optional.armv8_crc32",
"hw.optional.arm.FEAT_SHA1", "hw.optional.arm.FEAT_SHA1",
"hw.optional.arm.FEAT_SHA256" "hw.optional.arm.FEAT_SHA256",
}; };
[Flags] [Flags]
@ -167,7 +164,7 @@ namespace ARMeilleure.CodeGen.Arm64
Lse = 1 << 5, Lse = 1 << 5,
Crc32 = 1 << 6, Crc32 = 1 << 6,
Sha1 = 1 << 7, Sha1 = 1 << 7,
Sha256 = 1 << 8 Sha256 = 1 << 8,
} }
public static MacOsFeatureFlags MacOsFeatureInfo { get; } = 0; public static MacOsFeatureFlags MacOsFeatureInfo { get; } = 0;

View file

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

View file

@ -5,12 +5,13 @@ namespace ARMeilleure.CodeGen.Arm64
{ {
static class IntrinsicTable static class IntrinsicTable
{ {
private static IntrinsicInfo[] _intrinTable; private static readonly IntrinsicInfo[] _intrinTable;
static IntrinsicTable() static IntrinsicTable()
{ {
_intrinTable = new IntrinsicInfo[EnumUtils.GetCount(typeof(Intrinsic))]; _intrinTable = new IntrinsicInfo[EnumUtils.GetCount(typeof(Intrinsic))];
#pragma warning disable IDE0055 // Disable formatting
Add(Intrinsic.Arm64AbsS, new IntrinsicInfo(0x5e20b800u, IntrinsicType.ScalarUnary)); Add(Intrinsic.Arm64AbsS, new IntrinsicInfo(0x5e20b800u, IntrinsicType.ScalarUnary));
Add(Intrinsic.Arm64AbsV, new IntrinsicInfo(0x0e20b800u, IntrinsicType.VectorUnary)); Add(Intrinsic.Arm64AbsV, new IntrinsicInfo(0x0e20b800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64AddhnV, new IntrinsicInfo(0x0e204000u, IntrinsicType.VectorTernaryRd)); 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.Arm64XtnV, new IntrinsicInfo(0x0e212800u, IntrinsicType.VectorUnary));
Add(Intrinsic.Arm64Zip1V, new IntrinsicInfo(0x0e003800u, IntrinsicType.VectorBinary)); Add(Intrinsic.Arm64Zip1V, new IntrinsicInfo(0x0e003800u, IntrinsicType.VectorBinary));
Add(Intrinsic.Arm64Zip2V, new IntrinsicInfo(0x0e007800u, IntrinsicType.VectorBinary)); Add(Intrinsic.Arm64Zip2V, new IntrinsicInfo(0x0e007800u, IntrinsicType.VectorBinary));
#pragma warning restore IDE0055
} }
private static void Add(Intrinsic intrin, IntrinsicInfo info) private static void Add(Intrinsic intrin, IntrinsicInfo info)

View file

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

View file

@ -1,4 +1,3 @@
using ARMeilleure.CodeGen.RegisterAllocators;
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System; 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; maxCallArgs = -1;
@ -41,7 +40,7 @@ namespace ARMeilleure.CodeGen.Arm64
for (BasicBlock block = cctx.Cfg.Blocks.First; block != null; block = block.ListNext) for (BasicBlock block = cctx.Cfg.Blocks.First; block != null; block = block.ListNext)
{ {
ConstantDict constants = new ConstantDict(); ConstantDict constants = new();
Operation nextNode; Operation nextNode;
@ -92,7 +91,7 @@ namespace ARMeilleure.CodeGen.Arm64
InsertReturnCopy(block.Operations, node); InsertReturnCopy(block.Operations, node);
break; break;
case Instruction.Tailcall: case Instruction.Tailcall:
InsertTailcallCopies(constants, block.Operations, stackAlloc, node, node); InsertTailcallCopies(constants, block.Operations, node, node);
break; break;
} }
} }
@ -138,10 +137,7 @@ namespace ARMeilleure.CodeGen.Arm64
{ {
src2 = node.GetSource(1); src2 = node.GetSource(1);
Operand temp = src1; (src2, src1) = (src1, src2);
src1 = src2;
src2 = temp;
node.SetSource(0, src1); node.SetSource(0, src1);
node.SetSource(1, src2); node.SetSource(1, src2);
@ -265,9 +261,9 @@ namespace ARMeilleure.CodeGen.Arm64
Operand dest = operation.Destination; 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; int argsCount = operation.SourcesCount - 1;
@ -364,16 +360,14 @@ namespace ARMeilleure.CodeGen.Arm64
operation.SetSources(sources.ToArray()); operation.SetSources(sources.ToArray());
} }
private static void InsertTailcallCopies( private static void InsertTailcallCopies(ConstantDict constants,
ConstantDict constants,
IntrusiveList<Operation> nodes, IntrusiveList<Operation> nodes,
StackAllocator stackAlloc,
Operation node, Operation node,
Operation operation) Operation operation)
{ {
List<Operand> sources = new List<Operand> List<Operand> sources = new()
{ {
operation.GetSource(0) operation.GetSource(0),
}; };
int argsCount = operation.SourcesCount - 1; int argsCount = operation.SourcesCount - 1;

View file

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

View file

@ -171,13 +171,12 @@ namespace ARMeilleure.CodeGen.Optimizations
private static ulong AllOnes(OperandType type) private static ulong AllOnes(OperandType type)
{ {
switch (type) return type switch
{ {
case OperandType.I32: return ~0U; OperandType.I32 => ~0U,
case OperandType.I64: return ~0UL; OperandType.I64 => ~0UL,
} _ => throw new ArgumentException("Invalid operand type \"" + type + "\"."),
};
throw new ArgumentException("Invalid operand type \"" + type + "\".");
} }
} }
} }

View file

@ -1,7 +1,6 @@
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory; using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
using static ARMeilleure.IntermediateRepresentation.Operation.Factory; using static ARMeilleure.IntermediateRepresentation.Operation.Factory;
@ -42,13 +41,13 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
public void Sequence(List<Operation> sequence) public void Sequence(List<Operation> sequence)
{ {
Dictionary<Register, Register> locations = new Dictionary<Register, Register>(); Dictionary<Register, Register> locations = new();
Dictionary<Register, Register> sources = new Dictionary<Register, Register>(); 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> pendingQueue = new();
Queue<Register> readyQueue = new Queue<Register>(); Queue<Register> readyQueue = new();
foreach (Copy copy in _copies) foreach (Copy copy in _copies)
{ {
@ -186,10 +185,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private void AddSplitFill(LiveInterval left, LiveInterval right, OperandType type) 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 register = GetRegister(right.Register, type);
Operand offset = Const(left.SpillOffset); Operand offset = Const(left.SpillOffset);
@ -201,10 +197,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private void AddSplitSpill(LiveInterval left, LiveInterval right, OperandType type) 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 offset = Const(right.SpillOffset);
Operand register = GetRegister(left.Register, type); Operand register = GetRegister(left.Register, type);
@ -216,10 +209,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private void AddSplitCopy(LiveInterval left, LiveInterval right, OperandType type) 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); _parallelCopy.AddCopy(right.Register, left.Register, type);
@ -228,7 +218,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
public Operation[] Sequence() public Operation[] Sequence()
{ {
List<Operation> sequence = new List<Operation>(); List<Operation> sequence = new();
if (_spillQueue != null) if (_spillQueue != null)
{ {

View file

@ -39,7 +39,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private int _first; private int _first;
private int _last; private int _last;
public bool IsBlockLocal => _first == _last; public readonly bool IsBlockLocal => _first == _last;
public LocalInfo(OperandType type, int uses, int blkIndex) public LocalInfo(OperandType type, int uses, int blkIndex)
{ {

View file

@ -545,7 +545,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
_intervals.Insert(insertIndex, interval); _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.IsFixed, "Trying to spill a fixed interval.");
Debug.Assert(interval.UsesCount == 0, "Trying to spill a interval with uses."); Debug.Assert(interval.UsesCount == 0, "Trying to spill a interval with uses.");
@ -561,7 +561,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private void InsertSplitCopies() private void InsertSplitCopies()
{ {
Dictionary<int, CopyResolver> copyResolvers = new Dictionary<int, CopyResolver>(); Dictionary<int, CopyResolver> copyResolvers = new();
CopyResolver GetCopyResolver(int position) CopyResolver GetCopyResolver(int position)
{ {
@ -676,10 +676,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
if (left != default && right != default && left != right) if (left != default && right != default && left != right)
{ {
if (copyResolver == null) copyResolver ??= new CopyResolver();
{
copyResolver = new CopyResolver();
}
copyResolver.AddSplit(left, right); copyResolver.AddSplit(left, right);
} }
@ -862,8 +859,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
// Compute local live sets. // Compute local live sets.
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext) for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
{ {
BitMap liveGen = new BitMap(Allocators.Default, mapSize); BitMap liveGen = new(Allocators.Default, mapSize);
BitMap liveKill = new BitMap(Allocators.Default, mapSize); BitMap liveKill = new(Allocators.Default, mapSize);
for (Operation node = block.Operations.First; node != default; node = node.ListNext) for (Operation node = block.Operations.First; node != default; node = node.ListNext)
{ {
@ -1061,7 +1058,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{ {
int regIndex = BitOperations.TrailingZeroCount(mask); int regIndex = BitOperations.TrailingZeroCount(mask);
Register callerSavedReg = new Register(regIndex, regType); Register callerSavedReg = new(regIndex, regType);
LiveInterval interval = _intervals[GetRegisterId(callerSavedReg)]; LiveInterval interval = _intervals[GetRegisterId(callerSavedReg)];

View file

@ -240,8 +240,10 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
public LiveInterval Split(int position) public LiveInterval Split(int position)
{ {
LiveInterval result = new(Local, Parent); LiveInterval result = new(Local, Parent)
result.End = End; {
End = End,
};
LiveRange prev = PrevRange; LiveRange prev = PrevRange;
LiveRange curr = CurrRange; LiveRange curr = CurrRange;

View file

@ -8,8 +8,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private int _count; private int _count;
private int _capacity; private int _capacity;
public int Count => _count; public readonly int Count => _count;
public Span<LiveInterval> Span => new(_items, _count); public readonly Span<LiveInterval> Span => new(_items, _count);
public void Add(LiveInterval interval) public void Add(LiveInterval interval)
{ {

View file

@ -6,15 +6,15 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{ {
private int* _items; private int* _items;
private int _capacity; private int _capacity;
private int _count;
public int Count => _count; public int Count { get; private set; }
public int FirstUse => _count > 0 ? _items[_count - 1] : LiveInterval.NotFound;
public Span<int> Span => new(_items, _count); public readonly int FirstUse => Count > 0 ? _items[Count - 1] : LiveInterval.NotFound;
public readonly Span<int> Span => new(_items, Count);
public void Add(int position) public void Add(int position)
{ {
if (_count + 1 > _capacity) if (Count + 1 > _capacity)
{ {
var oldSpan = Span; 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, // Use positions are usually inserted in descending order, so inserting in descending order is faster,
// since the number of half exchanges is reduced. // since the number of half exchanges is reduced.
int i = _count - 1; int i = Count - 1;
while (i >= 0 && _items[i] < position) while (i >= 0 && _items[i] < position)
{ {
@ -36,19 +36,19 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
} }
_items[i + 1] = position; _items[i + 1] = position;
_count++; Count++;
} }
public int NextUse(int position) public readonly int NextUse(int position)
{ {
int index = NextUseIndex(position); int index = NextUseIndex(position);
return index != LiveInterval.NotFound ? _items[index] : LiveInterval.NotFound; 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]) 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 // 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. // list takes the back of the list.
UseList result = new(); UseList result = new()
result._count = index + 1; {
result._capacity = result._count; Count = index + 1,
};
result._capacity = result.Count;
result._items = _items; result._items = _items;
_count = _count - result._count; Count -= result.Count;
_capacity = _count; _capacity = Count;
_items = _items + result._count; _items += result.Count;
return result; return result;
} }

View file

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

View file

@ -799,7 +799,7 @@ namespace ARMeilleure.CodeGen.X86
{ {
JumpIndex = _jumps.Count - 1, JumpIndex = _jumps.Count - 1,
Position = (int)_stream.Position, Position = (int)_stream.Position,
Symbol = source.Symbol Symbol = source.Symbol,
}); });
} }
@ -1049,7 +1049,7 @@ namespace ARMeilleure.CodeGen.X86
InstructionFlags.Prefix66 => 1, InstructionFlags.Prefix66 => 1,
InstructionFlags.PrefixF3 => 2, InstructionFlags.PrefixF3 => 2,
InstructionFlags.PrefixF2 => 3, InstructionFlags.PrefixF2 => 3,
_ => 0 _ => 0,
}; };
if (src1 != default) if (src1 != default)
@ -1081,11 +1081,19 @@ namespace ARMeilleure.CodeGen.X86
switch (opCodeHigh) switch (opCodeHigh)
{ {
case 0xf: vexByte1 |= 1; break; case 0xf:
case 0xf38: vexByte1 |= 2; break; vexByte1 |= 1;
case 0xf3a: vexByte1 |= 3; break; 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; vexByte2 |= (rexPrefix & 8) << 4;
@ -1191,11 +1199,19 @@ namespace ARMeilleure.CodeGen.X86
switch ((ushort)(opCode >> 8)) switch ((ushort)(opCode >> 8))
{ {
case 0xf00: mm = 0b01; break; case 0xf00:
case 0xf38: mm = 0b10; break; mm = 0b01;
case 0xf3a: mm = 0b11; break; 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( WriteByte(
@ -1217,7 +1233,7 @@ namespace ARMeilleure.CodeGen.X86
InstructionFlags.Prefix66 => 0b01, InstructionFlags.Prefix66 => 0b01,
InstructionFlags.PrefixF3 => 0b10, InstructionFlags.PrefixF3 => 0b10,
InstructionFlags.PrefixF2 => 0b11, InstructionFlags.PrefixF2 => 0b11,
_ => 0 _ => 0,
}; };
WriteByte( WriteByte(
(byte)( (byte)(
@ -1233,11 +1249,19 @@ namespace ARMeilleure.CodeGen.X86
byte ll = 0b00; byte ll = 0b00;
switch (registerWidth) switch (registerWidth)
{ {
case 128: ll = 0b00; break; case 128:
case 256: ll = 0b01; break; ll = 0b00;
case 512: ll = 0b10; break; 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 // Embedded broadcast in the case of a memory operand
bool bcast = broadcast; bool bcast = broadcast;
@ -1315,10 +1339,7 @@ namespace ARMeilleure.CodeGen.X86
ref Jump jump = ref jumps[i]; ref Jump jump = ref jumps[i];
// If jump target not resolved yet, resolve it. // 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 jumpTarget = jump.JumpTarget.Value;
long offset = jumpTarget - jump.JumpPosition; long offset = jumpTarget - jump.JumpPosition;

View file

@ -1,4 +1,5 @@
using System; using System;
using System.Diagnostics.CodeAnalysis;
namespace ARMeilleure.CodeGen.X86 namespace ARMeilleure.CodeGen.X86
{ {
@ -12,6 +13,7 @@ namespace ARMeilleure.CodeGen.X86
private const int BadOp = 0; private const int BadOp = 0;
[Flags] [Flags]
[SuppressMessage("Design", "CA1069: Enums values should not be duplicated")]
private enum InstructionFlags private enum InstructionFlags
{ {
None = 0, None = 0,
@ -26,7 +28,7 @@ namespace ARMeilleure.CodeGen.X86
PrefixMask = 7 << PrefixBit, PrefixMask = 7 << PrefixBit,
Prefix66 = 1 << PrefixBit, Prefix66 = 1 << PrefixBit,
PrefixF3 = 2 << PrefixBit, PrefixF3 = 2 << PrefixBit,
PrefixF2 = 4 << PrefixBit PrefixF2 = 4 << PrefixBit,
} }
private readonly struct InstructionInfo private readonly struct InstructionInfo
@ -62,6 +64,7 @@ namespace ARMeilleure.CodeGen.X86
{ {
_instTable = new InstructionInfo[(int)X86Instruction.Count]; _instTable = new InstructionInfo[(int)X86Instruction.Count];
#pragma warning disable IDE0055 // Disable formatting
// Name RM/R RM/I8 RM/I32 R/I64 R/RM Flags // 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.Add, new InstructionInfo(0x00000001, 0x00000083, 0x00000081, BadOp, 0x00000003, InstructionFlags.None));
Add(X86Instruction.Addpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstructionFlags.Vex | InstructionFlags.Prefix66)); 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.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.Xorpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f57, InstructionFlags.Vex | InstructionFlags.Prefix66));
Add(X86Instruction.Xorps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f57, InstructionFlags.Vex)); Add(X86Instruction.Xorps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f57, InstructionFlags.Vex));
#pragma warning restore IDE0055
static void Add(X86Instruction inst, in InstructionInfo info) static void Add(X86Instruction inst, in InstructionInfo info)
{ {

View file

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

View file

@ -20,6 +20,7 @@ namespace ARMeilleure.CodeGen.X86
{ {
if (GetCurrentCallConv() == CallConvName.Windows) if (GetCurrentCallConv() == CallConvName.Windows)
{ {
#pragma warning disable IDE0055 // Disable formatting
return (1 << (int)X86Register.Rax) | return (1 << (int)X86Register.Rax) |
(1 << (int)X86Register.Rcx) | (1 << (int)X86Register.Rcx) |
(1 << (int)X86Register.Rdx) | (1 << (int)X86Register.Rdx) |
@ -39,6 +40,7 @@ namespace ARMeilleure.CodeGen.X86
(1 << (int)X86Register.R9) | (1 << (int)X86Register.R9) |
(1 << (int)X86Register.R10) | (1 << (int)X86Register.R10) |
(1 << (int)X86Register.R11); (1 << (int)X86Register.R11);
#pragma warning restore IDE0055
} }
} }
@ -90,22 +92,32 @@ namespace ARMeilleure.CodeGen.X86
{ {
switch (index) switch (index)
{ {
case 0: return X86Register.Rcx; case 0:
case 1: return X86Register.Rdx; return X86Register.Rcx;
case 2: return X86Register.R8; case 1:
case 3: return X86Register.R9; return X86Register.Rdx;
case 2:
return X86Register.R8;
case 3:
return X86Register.R9;
} }
} }
else /* if (GetCurrentCallConv() == CallConvName.SystemV) */ else /* if (GetCurrentCallConv() == CallConvName.SystemV) */
{ {
switch (index) switch (index)
{ {
case 0: return X86Register.Rdi; case 0:
case 1: return X86Register.Rsi; return X86Register.Rdi;
case 2: return X86Register.Rdx; case 1:
case 3: return X86Register.Rcx; return X86Register.Rsi;
case 4: return X86Register.R8; case 2:
case 5: return X86Register.R9; 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))]; _instTable = new Action<CodeGenContext, Operation>[EnumUtils.GetCount(typeof(Instruction))];
#pragma warning disable IDE0055 // Disable formatting
Add(Instruction.Add, GenerateAdd); Add(Instruction.Add, GenerateAdd);
Add(Instruction.BitwiseAnd, GenerateBitwiseAnd); Add(Instruction.BitwiseAnd, GenerateBitwiseAnd);
Add(Instruction.BitwiseExclusiveOr, GenerateBitwiseExclusiveOr); Add(Instruction.BitwiseExclusiveOr, GenerateBitwiseExclusiveOr);
@ -85,6 +86,7 @@ namespace ARMeilleure.CodeGen.X86
Add(Instruction.ZeroExtend16, GenerateZeroExtend16); Add(Instruction.ZeroExtend16, GenerateZeroExtend16);
Add(Instruction.ZeroExtend32, GenerateZeroExtend32); Add(Instruction.ZeroExtend32, GenerateZeroExtend32);
Add(Instruction.ZeroExtend8, GenerateZeroExtend8); Add(Instruction.ZeroExtend8, GenerateZeroExtend8);
#pragma warning restore IDE0055
static void Add(Instruction inst, Action<CodeGenContext, Operation> func) static void Add(Instruction inst, Action<CodeGenContext, Operation> func)
{ {
@ -1613,13 +1615,25 @@ namespace ARMeilleure.CodeGen.X86
{ {
switch (value.Type) switch (value.Type)
{ {
case OperandType.I32: context.Assembler.Mov (value, address, OperandType.I32); break; case OperandType.I32:
case OperandType.I64: context.Assembler.Mov (value, address, OperandType.I64); break; context.Assembler.Mov(value, address, OperandType.I32);
case OperandType.FP32: context.Assembler.Movd (value, address); break; break;
case OperandType.FP64: context.Assembler.Movq (value, address); break; case OperandType.I64:
case OperandType.V128: context.Assembler.Movdqu(value, address); break; 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) switch (value.Type)
{ {
case OperandType.I32: context.Assembler.Mov (address, value, OperandType.I32); break; case OperandType.I32:
case OperandType.I64: context.Assembler.Mov (address, value, OperandType.I64); break; context.Assembler.Mov(address, value, OperandType.I32);
case OperandType.FP32: context.Assembler.Movd (address, value); break; break;
case OperandType.FP64: context.Assembler.Movq (address, value); break; case OperandType.I64:
case OperandType.V128: context.Assembler.Movdqu(address, value); break; 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;
} }
} }
@ -1722,7 +1748,7 @@ namespace ARMeilleure.CodeGen.X86
private static UnwindInfo WritePrologue(CodeGenContext context) private static UnwindInfo WritePrologue(CodeGenContext context)
{ {
List<UnwindPushEntry> pushEntries = new List<UnwindPushEntry>(); List<UnwindPushEntry> pushEntries = new();
Operand rsp = Register(X86Register.Rsp); Operand rsp = Register(X86Register.Rsp);

View file

@ -47,7 +47,7 @@ namespace ARMeilleure.CodeGen.X86
0xc3, // ret 0xc3, // ret
}; };
using MemoryBlock memGetXcr0 = new MemoryBlock((ulong)asmGetXcr0.Length); using MemoryBlock memGetXcr0 = new((ulong)asmGetXcr0.Length);
memGetXcr0.Write(0, asmGetXcr0); memGetXcr0.Write(0, asmGetXcr0);
@ -62,7 +62,7 @@ namespace ARMeilleure.CodeGen.X86
public enum FeatureFlags1Edx public enum FeatureFlags1Edx
{ {
Sse = 1 << 25, Sse = 1 << 25,
Sse2 = 1 << 26 Sse2 = 1 << 26,
} }
[Flags] [Flags]
@ -79,7 +79,7 @@ namespace ARMeilleure.CodeGen.X86
Xsave = 1 << 26, Xsave = 1 << 26,
Osxsave = 1 << 27, Osxsave = 1 << 27,
Avx = 1 << 28, Avx = 1 << 28,
F16c = 1 << 29 F16c = 1 << 29,
} }
[Flags] [Flags]
@ -90,7 +90,7 @@ namespace ARMeilleure.CodeGen.X86
Avx512dq = 1 << 17, Avx512dq = 1 << 17,
Sha = 1 << 29, Sha = 1 << 29,
Avx512bw = 1 << 30, Avx512bw = 1 << 30,
Avx512vl = 1 << 31 Avx512vl = 1 << 31,
} }
[Flags] [Flags]
@ -106,7 +106,7 @@ namespace ARMeilleure.CodeGen.X86
YmmHi128 = 1 << 2, YmmHi128 = 1 << 2,
Opmask = 1 << 5, Opmask = 1 << 5,
ZmmHi256 = 1 << 6, ZmmHi256 = 1 << 6,
Hi16Zmm = 1 << 7 Hi16Zmm = 1 << 7,
} }
public static FeatureFlags1Edx FeatureInfo1Edx { get; } public static FeatureFlags1Edx FeatureInfo1Edx { get; }

View file

@ -5,12 +5,13 @@ namespace ARMeilleure.CodeGen.X86
{ {
static class IntrinsicTable static class IntrinsicTable
{ {
private static IntrinsicInfo[] _intrinTable; private static readonly IntrinsicInfo[] _intrinTable;
static IntrinsicTable() static IntrinsicTable()
{ {
_intrinTable = new IntrinsicInfo[EnumUtils.GetCount(typeof(Intrinsic))]; _intrinTable = new IntrinsicInfo[EnumUtils.GetCount(typeof(Intrinsic))];
#pragma warning disable IDE0055 // Disable formatting
Add(Intrinsic.X86Addpd, new IntrinsicInfo(X86Instruction.Addpd, IntrinsicType.Binary)); Add(Intrinsic.X86Addpd, new IntrinsicInfo(X86Instruction.Addpd, IntrinsicType.Binary));
Add(Intrinsic.X86Addps, new IntrinsicInfo(X86Instruction.Addps, IntrinsicType.Binary)); Add(Intrinsic.X86Addps, new IntrinsicInfo(X86Instruction.Addps, IntrinsicType.Binary));
Add(Intrinsic.X86Addsd, new IntrinsicInfo(X86Instruction.Addsd, 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.X86Vpternlogd, new IntrinsicInfo(X86Instruction.Vpternlogd, IntrinsicType.TernaryImm));
Add(Intrinsic.X86Xorpd, new IntrinsicInfo(X86Instruction.Xorpd, IntrinsicType.Binary)); Add(Intrinsic.X86Xorpd, new IntrinsicInfo(X86Instruction.Xorpd, IntrinsicType.Binary));
Add(Intrinsic.X86Xorps, new IntrinsicInfo(X86Instruction.Xorps, IntrinsicType.Binary)); Add(Intrinsic.X86Xorps, new IntrinsicInfo(X86Instruction.Xorps, IntrinsicType.Binary));
#pragma warning restore IDE0055
} }
private static void Add(Intrinsic intrin, IntrinsicInfo info) private static void Add(Intrinsic intrin, IntrinsicInfo info)

View file

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

View file

@ -10,6 +10,6 @@ namespace ARMeilleure.CodeGen.X86
Rlo = 1 << 13, // Round Mode low bit. Rlo = 1 << 13, // Round Mode low bit.
Um = 1 << 11, // Underflow Mask. Um = 1 << 11, // Underflow Mask.
Dm = 1 << 8, // Denormal 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: case Instruction.Tailcall:
if (callConv == CallConvName.Windows) if (callConv == CallConvName.Windows)
{ {
PreAllocatorWindows.InsertTailcallCopies(block.Operations, stackAlloc, node); PreAllocatorWindows.InsertTailcallCopies(block.Operations, node);
} }
else else
{ {
PreAllocatorSystemV.InsertTailcallCopies(block.Operations, stackAlloc, node); PreAllocatorSystemV.InsertTailcallCopies(block.Operations, node);
} }
break; break;
@ -177,10 +177,7 @@ namespace ARMeilleure.CodeGen.X86
{ {
src2 = node.GetSource(1); src2 = node.GetSource(1);
Operand temp = src1; (src2, src1) = (src1, src2);
src1 = src2;
src2 = temp;
node.SetSource(0, src1); node.SetSource(0, src1);
node.SetSource(1, src2); node.SetSource(1, src2);
@ -473,7 +470,7 @@ namespace ARMeilleure.CodeGen.X86
Operand zex = Local(OperandType.I64); Operand zex = Local(OperandType.I64);
node = nodes.AddAfter(node, Operation(Instruction.ZeroExtend32, zex, source)); 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) */ else /* if (source.Type == OperandType.I64) */
{ {
@ -709,16 +706,11 @@ namespace ARMeilleure.CodeGen.X86
private static bool HasConstSrc1(Instruction inst) private static bool HasConstSrc1(Instruction inst)
{ {
switch (inst) return inst switch
{ {
case Instruction.Copy: Instruction.Copy or Instruction.LoadArgument or Instruction.Spill or Instruction.SpillArg => true,
case Instruction.LoadArgument: _ => false,
case Instruction.Spill: };
case Instruction.SpillArg:
return true;
}
return false;
} }
private static bool HasConstSrc2(Instruction inst) private static bool HasConstSrc2(Instruction inst)

View file

@ -1,4 +1,3 @@
using ARMeilleure.CodeGen.RegisterAllocators;
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System; using System;
@ -15,9 +14,9 @@ namespace ARMeilleure.CodeGen.X86
{ {
Operand dest = node.Destination; 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; 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; int argsCount = node.SourcesCount - 1;

View file

@ -155,7 +155,7 @@ namespace ARMeilleure.CodeGen.X86
node.SetSources(sources); 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 argsCount = node.SourcesCount - 1;
int maxArgs = CallingConvention.GetArgumentsOnRegsCount(); int maxArgs = CallingConvention.GetArgumentsOnRegsCount();

View file

@ -20,7 +20,7 @@ namespace ARMeilleure.CodeGen.X86
Less = 0xc, Less = 0xc,
GreaterOrEqual = 0xd, GreaterOrEqual = 0xd,
LessOrEqual = 0xe, LessOrEqual = 0xe,
Greater = 0xf Greater = 0xf,
} }
static class ComparisonX86Extensions static class ComparisonX86Extensions
@ -29,6 +29,7 @@ namespace ARMeilleure.CodeGen.X86
{ {
return comp switch return comp switch
{ {
#pragma warning disable IDE0055 // Disable formatting
Comparison.Equal => X86Condition.Equal, Comparison.Equal => X86Condition.Equal,
Comparison.NotEqual => X86Condition.NotEqual, Comparison.NotEqual => X86Condition.NotEqual,
Comparison.Greater => X86Condition.Greater, Comparison.Greater => X86Condition.Greater,
@ -39,8 +40,9 @@ namespace ARMeilleure.CodeGen.X86
Comparison.Less => X86Condition.Less, Comparison.Less => X86Condition.Less,
Comparison.GreaterOrEqualUI => X86Condition.AboveOrEqual, Comparison.GreaterOrEqualUI => X86Condition.AboveOrEqual,
Comparison.LessUI => X86Condition.Below, 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, Xorpd,
Xorps, Xorps,
Count Count,
} }
} }

View file

@ -215,7 +215,7 @@ namespace ARMeilleure.CodeGen.X86
1 => Multiplier.x2, 1 => Multiplier.x2,
2 => Multiplier.x4, 2 => Multiplier.x4,
3 => Multiplier.x8, 3 => Multiplier.x8,
_ => Multiplier.x1 _ => Multiplier.x1,
}; };
baseOp = indexOnSrc2 ? src1 : src2; baseOp = indexOnSrc2 ? src1 : src2;

View file

@ -1,5 +1,8 @@
using System.Diagnostics.CodeAnalysis;
namespace ARMeilleure.CodeGen.X86 namespace ARMeilleure.CodeGen.X86
{ {
[SuppressMessage("Design", "CA1069: Enums values should not be duplicated")]
enum X86Register enum X86Register
{ {
Invalid = -1, Invalid = -1,
@ -36,6 +39,6 @@ namespace ARMeilleure.CodeGen.X86
Xmm12 = 12, Xmm12 = 12,
Xmm13 = 13, Xmm13 = 13,
Xmm14 = 14, Xmm14 = 14,
Xmm15 = 15 Xmm15 = 15,
} }
} }

View file

@ -82,8 +82,10 @@ namespace ARMeilleure.Common
} }
else else
{ {
_page = new PageInfo(); _page = new PageInfo
_page.Pointer = (byte*)NativeAllocator.Instance.Allocate(_pageSize); {
Pointer = (byte*)NativeAllocator.Instance.Allocate(_pageSize),
};
_pages.Add(_page); _pages.Add(_page);
} }
@ -106,7 +108,7 @@ namespace ARMeilleure.Common
// Free excess pages that was allocated. // Free excess pages that was allocated.
while (_pages.Count > _pageCount) while (_pages.Count > _pageCount)
{ {
NativeAllocator.Instance.Free(_pages[_pages.Count - 1].Pointer); NativeAllocator.Instance.Free(_pages[^1].Pointer);
_pages.RemoveAt(_pages.Count - 1); _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. // If arena is used frequently, keep pages for longer. Otherwise keep pages for a shorter amount of time.
int now = Environment.TickCount; int now = Environment.TickCount;
int count = (now - _lastReset) switch { int count = (now - _lastReset) switch
{
>= 5000 => 0, >= 5000 => 0,
>= 2500 => 50, >= 2500 => 50,
>= 1000 => 100, >= 1000 => 100,
>= 10 => 1500, >= 10 => 1500,
_ => 5000 _ => 5000,
}; };
for (int i = _pages.Count - 1; i >= 0; i--) 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); var newSpan = new Span<long>(_masks, _count);
oldSpan.CopyTo(newSpan); oldSpan.CopyTo(newSpan);
newSpan.Slice(oldSpan.Length).Clear(); newSpan[oldSpan.Length..].Clear();
_allocator.Free(oldMask); _allocator.Free(oldMask);
} }
@ -176,8 +176,8 @@ namespace ARMeilleure.Common
private int _bit; private int _bit;
private readonly BitMap _map; private readonly BitMap _map;
public int Current => (int)_index * IntSize + _bit; public readonly int Current => (int)_index * IntSize + _bit;
object IEnumerator.Current => Current; readonly object IEnumerator.Current => Current;
public Enumerator(BitMap map) public Enumerator(BitMap map)
{ {
@ -214,9 +214,9 @@ namespace ARMeilleure.Common
return true; 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) if (OpCodes.Count > 0)
{ {
return OpCodes[OpCodes.Count - 1]; return OpCodes[^1];
} }
return null; return null;

View file

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

View file

@ -5,6 +5,6 @@ namespace ARMeilleure.Decoders
Adr = 0, Adr = 0,
Arithmetic = 1, Arithmetic = 1,
Logical = 2, 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) 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); Debug.Assert(MaxInstsPerFunctionLowCq <= MaxInstsPerFunction);
@ -246,7 +246,7 @@ namespace ARMeilleure.Decoders
private static bool IsAarch32UnconditionalBranch(OpCode opCode) private static bool IsAarch32UnconditionalBranch(OpCode opCode)
{ {
if (!(opCode is OpCode32 op)) if (opCode is not OpCode32 op)
{ {
return false; return false;
} }

View file

@ -40,7 +40,7 @@ namespace ARMeilleure.Decoders
// abcdefgh -> aBbbbbbc defgh000 00000000 00000000 (B = ~b) // abcdefgh -> aBbbbbbc defgh000 00000000 00000000 (B = ~b)
private static uint ExpandImm8ToFP32(uint imm) 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 ((bits >> from) & 1U) << to;
} }
@ -57,7 +57,7 @@ namespace ARMeilleure.Decoders
// abcdefgh -> aBbbbbbb bbcdefgh 00000000 00000000 00000000 00000000 00000000 00000000 (B = ~b) // abcdefgh -> aBbbbbbb bbcdefgh 00000000 00000000 00000000 00000000 00000000 00000000 (B = ~b)
private static ulong ExpandImm8ToFP64(ulong imm) 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 ((bits >> from) & 1UL) << to;
} }
@ -80,7 +80,7 @@ namespace ARMeilleure.Decoders
public int Shift; public int Shift;
public bool IsUndefined; 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) public static BitMask DecodeBitMask(int opCode, bool immediate)
@ -125,7 +125,7 @@ namespace ARMeilleure.Decoders
TMask = BitUtils.Replicate(tMask, size), TMask = BitUtils.Replicate(tMask, size),
Pos = immS, Pos = immS,
Shift = immR Shift = immR,
}; };
} }

View file

@ -4,7 +4,7 @@ namespace ARMeilleure.Decoders
{ {
readonly struct InstDescriptor 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 InstName Name { get; }
public InstEmitter Emitter { get; } public InstEmitter Emitter { get; }

View file

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

View file

@ -14,7 +14,7 @@ namespace ARMeilleure.Decoders
public RegisterSize RegisterSize { get; protected set; } 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) public OpCode(InstDescriptor inst, ulong address, int opCode)
{ {
@ -30,15 +30,14 @@ namespace ARMeilleure.Decoders
public int GetBitsCount() public int GetBitsCount()
{ {
switch (RegisterSize) return RegisterSize switch
{ {
case RegisterSize.Int32: return 32; RegisterSize.Int32 => 32,
case RegisterSize.Int64: return 64; RegisterSize.Int64 => 64,
case RegisterSize.Simd64: return 64; RegisterSize.Simd64 => 64,
case RegisterSize.Simd128: return 128; RegisterSize.Simd128 => 128,
} _ => throw new InvalidOperationException(),
};
throw new InvalidOperationException();
} }
public OperandType GetOperandType() public OperandType GetOperandType()

View file

@ -24,27 +24,21 @@ namespace ARMeilleure.Decoders
protected int GetQuadwordIndex(int index) protected int GetQuadwordIndex(int index)
{ {
switch (RegisterSize) return RegisterSize switch
{ {
case RegisterSize.Simd128: RegisterSize.Simd128 or RegisterSize.Simd64 => index >> 1,
case RegisterSize.Simd64: _ => throw new InvalidOperationException(),
return index >> 1; };
}
throw new InvalidOperationException();
} }
protected int GetQuadwordSubindex(int index) protected int GetQuadwordSubindex(int index)
{ {
switch (RegisterSize) return RegisterSize switch
{ {
case RegisterSize.Simd128: RegisterSize.Simd128 => 0,
return 0; RegisterSize.Simd64 => index & 1,
case RegisterSize.Simd64: _ => throw new InvalidOperationException(),
return index & 1; };
}
throw new InvalidOperationException();
} }
protected OpCode32SimdBase(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode) 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. // The value must be a power of 2, otherwise it is the encoding of another instruction.
switch (imm3h) switch (imm3h)
{ {
case 1: Size = 0; break; case 1:
case 2: Size = 1; break; Size = 0;
case 4: Size = 2; break; break;
case 2:
Size = 1;
break;
case 4:
Size = 2;
break;
} }
U = ((opCode >> (isThumb ? 28 : 24)) & 0x1) != 0; U = ((opCode >> (isThumb ? 28 : 24)) & 0x1) != 0;

View file

@ -4,12 +4,12 @@ namespace ARMeilleure.Decoders
{ {
class OpCode32SimdMemPair : OpCode32, IOpCode32Simd class OpCode32SimdMemPair : OpCode32, IOpCode32Simd
{ {
private static int[] _regsMap = private static readonly int[] _regsMap =
{ {
1, 1, 4, 2, 1, 1, 4, 2,
1, 1, 3, 1, 1, 1, 3, 1,
1, 1, 2, 1, 1, 1, 2, 1,
1, 1, 1, 1 1, 1, 1, 1,
}; };
public int Vd { get; } public int Vd { get; }

View file

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

View file

@ -33,7 +33,7 @@ namespace ARMeilleure.Decoders
} }
else 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, PostIndexed = 1,
Unprivileged = 2, Unprivileged = 2,
PreIndexed = 3, PreIndexed = 3,
Unsigned Unsigned,
} }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeMemImm(inst, address, opCode); 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) switch ((opCode >> 30) & 3)
{ {
case 0: Size = 2; Signed = false; Prefetch = false; break; case 0:
case 1: Size = 3; Signed = false; Prefetch = false; break; Size = 2;
case 2: Size = 2; Signed = true; Prefetch = false; break; Signed = false;
case 3: Size = 0; Signed = false; Prefetch = true; break; 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) else if ((modeHigh & 0b110) == 0b100)
{ {
// 16-bits shifted Immediate. // 16-bits shifted Immediate.
size = 1; imm <<= (modeHigh & 1) << 3; size = 1;
imm <<= (modeHigh & 1) << 3;
} }
else if ((modeHigh & 0b100) == 0b000) else if ((modeHigh & 0b100) == 0b000)
{ {
// 32-bits shifted Immediate. // 32-bits shifted Immediate.
size = 2; imm <<= modeHigh << 3; size = 2;
imm <<= modeHigh << 3;
} }
else if ((modeHigh & 0b111) == 0b110) else if ((modeHigh & 0b111) == 0b110)
{ {
// 32-bits shifted Immediate (fill with ones). // 32-bits shifted Immediate (fill with ones).
size = 2; imm = ShlOnes(imm, 8 << modeLow); size = 2;
imm = ShlOnes(imm, 8 << modeLow);
} }
else else
{ {

View file

@ -67,17 +67,20 @@ namespace ARMeilleure.Decoders
else if ((modeHigh & 0b110) == 0b100) else if ((modeHigh & 0b110) == 0b100)
{ {
// 16-bits shifted Immediate. // 16-bits shifted Immediate.
Size = 1; imm <<= (modeHigh & 1) << 3; Size = 1;
imm <<= (modeHigh & 1) << 3;
} }
else if ((modeHigh & 0b100) == 0b000) else if ((modeHigh & 0b100) == 0b000)
{ {
// 32-bits shifted Immediate. // 32-bits shifted Immediate.
Size = 2; imm <<= modeHigh << 3; Size = 2;
imm <<= modeHigh << 3;
} }
else if ((modeHigh & 0b111) == 0b110) else if ((modeHigh & 0b111) == 0b110)
{ {
// 32-bits shifted Immediate (fill with ones). // 32-bits shifted Immediate (fill with ones).
Size = 2; imm = ShlOnes(imm, 8 << modeLow); Size = 2;
imm = ShlOnes(imm, 8 << modeLow);
} }
else else
{ {

View file

@ -23,10 +23,18 @@ namespace ARMeilleure.Decoders
switch (Size) switch (Size)
{ {
case 1: Size = 0; break; case 1:
case 2: Size = 1; break; Size = 0;
case 4: Size = 2; break; break;
case 8: Size = 3; break; case 2:
Size = 1;
break;
case 4:
Size = 2;
break;
case 8:
Size = 3;
break;
} }
SrcIndex = imm4 >> Size; SrcIndex = imm4 >> Size;

View file

@ -13,15 +13,38 @@ namespace ARMeilleure.Decoders
{ {
switch ((opCode >> 12) & 0xf) switch ((opCode >> 12) & 0xf)
{ {
case 0b0000: Reps = 1; SElems = 4; break; case 0b0000:
case 0b0010: Reps = 4; SElems = 1; break; Reps = 1;
case 0b0100: Reps = 1; SElems = 3; break; SElems = 4;
case 0b0110: Reps = 3; SElems = 1; break; break;
case 0b0111: Reps = 1; SElems = 1; break; case 0b0010:
case 0b1000: Reps = 1; SElems = 2; break; Reps = 4;
case 0b1010: Reps = 2; SElems = 1; break; 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; Size = (opCode >> 10) & 3;

View file

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

View file

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

View file

@ -36,23 +36,13 @@ namespace ARMeilleure.Decoders
break; break;
} }
switch (inst.Name) Immediate = inst.Name switch
{ {
case InstName.Str: InstName.Str or InstName.Ldr => ((opCode >> 6) & 0x1f) << 2,
case InstName.Ldr: InstName.Strb or InstName.Ldrb => ((opCode >> 6) & 0x1f),
Immediate = ((opCode >> 6) & 0x1f) << 2; InstName.Strh or InstName.Ldrh => ((opCode >> 6) & 0x1f) << 1,
break; _ => throw new InvalidOperationException(),
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();
}
} }
} }
} }

View file

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

View file

@ -4,8 +4,6 @@ namespace ARMeilleure.Decoders
{ {
public int Immediate { get; } 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 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) public OpCodeT32MovImm16(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)

View file

@ -29,16 +29,17 @@ namespace ARMeilleure.Decoders
} }
} }
private static List<InstInfo> AllInstA32 = new(); private static readonly List<InstInfo> _allInstA32 = new();
private static List<InstInfo> AllInstT32 = new(); private static readonly List<InstInfo> _allInstT32 = new();
private static List<InstInfo> AllInstA64 = new(); private static readonly List<InstInfo> _allInstA64 = new();
private static InstInfo[][] InstA32FastLookup = new InstInfo[FastLookupSize][]; private static readonly InstInfo[][] _instA32FastLookup = new InstInfo[FastLookupSize][];
private static InstInfo[][] InstT32FastLookup = new InstInfo[FastLookupSize][]; private static readonly InstInfo[][] _instT32FastLookup = new InstInfo[FastLookupSize][];
private static InstInfo[][] InstA64FastLookup = new InstInfo[FastLookupSize][]; private static readonly InstInfo[][] _instA64FastLookup = new InstInfo[FastLookupSize][];
static OpCodeTable() static OpCodeTable()
{ {
#pragma warning disable IDE0055 // Disable formatting
#region "OpCode Table (AArch64)" #region "OpCode Table (AArch64)"
// Base // Base
SetA64("x0011010000xxxxx000000xxxxxxxxxx", InstName.Adc, InstEmit.Adc, OpCodeAluRs.Create); SetA64("x0011010000xxxxx000000xxxxxxxxxx", InstName.Adc, InstEmit.Adc, OpCodeAluRs.Create);
@ -1299,12 +1300,13 @@ namespace ARMeilleure.Decoders
SetT32("11110011101011111000000000000001", InstName.Yield, InstEmit32.Nop, OpCodeT32.Create); SetT32("11110011101011111000000000000001", InstName.Yield, InstEmit32.Nop, OpCodeT32.Create);
#endregion #endregion
FillFastLookupTable(InstA32FastLookup, AllInstA32, ToFastLookupIndexA); FillFastLookupTable(_instA32FastLookup, _allInstA32, ToFastLookupIndexA);
FillFastLookupTable(InstT32FastLookup, AllInstT32, ToFastLookupIndexT); FillFastLookupTable(_instT32FastLookup, _allInstT32, ToFastLookupIndexT);
FillFastLookupTable(InstA64FastLookup, AllInstA64, ToFastLookupIndexA); 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]; List<InstInfo>[] temp = new List<InstInfo>[FastLookupSize];
@ -1315,8 +1317,8 @@ namespace ARMeilleure.Decoders
foreach (InstInfo inst in allInsts) foreach (InstInfo inst in allInsts)
{ {
int mask = ToFastLookupIndex(inst.Mask); int mask = toFastLookupIndex(inst.Mask);
int value = ToFastLookupIndex(inst.Value); int value = toFastLookupIndex(inst.Value);
for (int index = 0; index < temp.Length; index++) 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) 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) private static void SetT16(string encoding, InstName name, InstEmitter emitter, MakeOp makeOp)
{ {
encoding = "xxxxxxxxxxxxxxxx" + encoding; 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) private static void SetT32(string encoding, InstName name, InstEmitter emitter, MakeOp makeOp)
{ {
string reversedEncoding = $"{encoding.AsSpan(16)}{encoding.AsSpan(0, 16)}"; string reversedEncoding = $"{encoding.AsSpan(16)}{encoding.AsSpan(0, 16)}";
MakeOp reversedMakeOp = OpCode ReversedMakeOp(InstDescriptor inst, ulong address, int opCode)
(inst, address, opCode)
=> makeOp(inst, address, (int)BitOperations.RotateRight((uint)opCode, 16)); => 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) 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) 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) private static void Set(string encoding, List<InstInfo> list, InstDescriptor inst, MakeOp makeOp)
@ -1439,7 +1440,7 @@ namespace ARMeilleure.Decoders
} }
else if (chr != '0') 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) 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) 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) 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) private static (InstDescriptor inst, MakeOp makeOp) GetInstFromList(InstInfo[] insts, int opCode)

View file

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

View file

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

View file

@ -34,7 +34,9 @@ namespace ARMeilleure.Diagnostics
for (int index = 0; index < _indentLevel; index++) for (int index = 0; index < _indentLevel; index++)
{ {
#pragma warning disable CA1834 // Use StringBuilder.Append(char) for single character strings
_builder.Append(Indentation); _builder.Append(Indentation);
#pragma warning restore CA1834
} }
} }
@ -110,10 +112,18 @@ namespace ARMeilleure.Diagnostics
switch (reg.Type) switch (reg.Type)
{ {
case RegisterType.Flag: _builder.Append('b'); break; case RegisterType.Flag:
case RegisterType.FpFlag: _builder.Append('f'); break; _builder.Append('b');
case RegisterType.Integer: _builder.Append('r'); break; break;
case RegisterType.Vector: _builder.Append('v'); 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); _builder.Append(reg.Index);
@ -145,9 +155,15 @@ namespace ARMeilleure.Diagnostics
switch (memOp.Scale) switch (memOp.Scale)
{ {
case Multiplier.x2: _builder.Append("*2"); break; case Multiplier.x2:
case Multiplier.x4: _builder.Append("*4"); break; _builder.Append("*2");
case Multiplier.x8: _builder.Append("*8"); break; 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 _startTime;
private static long[] _accumulatedTime; private static readonly long[] _accumulatedTime;
static Logger() static Logger()
{ {

View file

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

View file

@ -33,9 +33,8 @@ namespace ARMeilleure.Diagnostics
public static string Get(ulong address) public static string Get(ulong address)
{ {
string result;
if (_symbols.TryGetValue(address, out result)) if (_symbols.TryGetValue(address, out string result))
{ {
return result; return result;
} }

View file

@ -19,19 +19,19 @@ namespace ARMeilleure.Diagnostics
{ {
_rejitQueueCounter = new PollingCounter("rejit-queue-length", this, () => _rejitQueue) _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) _funcTabSizeCounter = new PollingCounter("addr-tab-alloc", this, () => _funcTabSize / 1024d / 1024d)
{ {
DisplayName = "AddressTable Total Bytes Allocated", DisplayName = "AddressTable Total Bytes Allocated",
DisplayUnits = "MiB" DisplayUnits = "MiB",
}; };
_funcTabLeafSizeCounter = new PollingCounter("addr-tab-leaf-alloc", this, () => _funcTabLeafSize / 1024d / 1024d) _funcTabLeafSizeCounter = new PollingCounter("addr-tab-leaf-alloc", this, () => _funcTabLeafSize / 1024d / 1024d)
{ {
DisplayName = "AddressTable Total Leaf Bytes Allocated", DisplayName = "AddressTable Total Leaf Bytes Allocated",
DisplayUnits = "MiB" DisplayUnits = "MiB",
}; };
} }

View file

@ -8,6 +8,7 @@ namespace ARMeilleure.Instructions
static class CryptoHelper static class CryptoHelper
{ {
#region "LookUp Tables" #region "LookUp Tables"
#pragma warning disable IDE1006 // Naming rule violation
private static ReadOnlySpan<byte> _sBox => new byte[] private static ReadOnlySpan<byte> _sBox => new byte[]
{ {
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 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, 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, 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, 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[] 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, 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, 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, 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[] 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, 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, 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, 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[] 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, 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, 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, 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[] 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, 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, 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, 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[] 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, 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, 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, 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[] 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, 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, 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, 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[] private static ReadOnlySpan<byte> _gfMul0E => new byte[]
@ -165,18 +166,19 @@ namespace ARMeilleure.Instructions
0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6, 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, 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, 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[] 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[] 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,
}; };
#pragma warning restore IDE1006
#endregion #endregion
public static V128 AesInvMixColumns(V128 op) public static V128 AesInvMixColumns(V128 op)

View file

@ -3,7 +3,6 @@ using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State; using ARMeilleure.State;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System.Diagnostics; using System.Diagnostics;
using static ARMeilleure.Instructions.InstEmitAluHelper; using static ARMeilleure.Instructions.InstEmitAluHelper;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory; using static ARMeilleure.IntermediateRepresentation.Operand.Factory;

View file

@ -2,13 +2,14 @@ using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State; using ARMeilleure.State;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System.Diagnostics.CodeAnalysis;
using static ARMeilleure.Instructions.InstEmitAluHelper; using static ARMeilleure.Instructions.InstEmitAluHelper;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory; using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
namespace ARMeilleure.Instructions namespace ARMeilleure.Instructions
{ {
[SuppressMessage("Style", "IDE0059: Remove unnecessary value assignment")]
static partial class InstEmit32 static partial class InstEmit32
{ {
public static void Add(ArmEmitterContext context) public static void Add(ArmEmitterContext context)

View file

@ -205,12 +205,16 @@ namespace ARMeilleure.Instructions
return Const(op.Immediate); 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 IOpCode32AluRsImm op:
case IOpCode32AluRsReg op: return GetMShiftedByReg(context, op, setCarry); 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. // ARM64.
case IOpCodeAluImm op: case IOpCodeAluImm op:
@ -231,10 +235,18 @@ namespace ARMeilleure.Instructions
switch (op.ShiftType) switch (op.ShiftType)
{ {
case ShiftType.Lsl: value = context.ShiftLeft (value, Const(op.Shift)); break; case ShiftType.Lsl:
case ShiftType.Lsr: value = context.ShiftRightUI(value, Const(op.Shift)); break; value = context.ShiftLeft(value, Const(op.Shift));
case ShiftType.Asr: value = context.ShiftRightSI(value, Const(op.Shift)); break; break;
case ShiftType.Ror: value = context.RotateRight (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; return value;
@ -249,7 +261,8 @@ namespace ARMeilleure.Instructions
return value; return value;
} }
default: throw InvalidOpCodeType(context.CurrOp); default:
throw InvalidOpCodeType(context.CurrOp);
} }
} }
@ -269,9 +282,15 @@ namespace ARMeilleure.Instructions
{ {
switch (op.ShiftType) switch (op.ShiftType)
{ {
case ShiftType.Lsr: shift = 32; break; case ShiftType.Lsr:
case ShiftType.Asr: shift = 32; break; shift = 32;
case ShiftType.Ror: shift = 1; break; break;
case ShiftType.Asr:
shift = 32;
break;
case ShiftType.Ror:
shift = 1;
break;
} }
} }
@ -281,9 +300,15 @@ namespace ARMeilleure.Instructions
switch (op.ShiftType) switch (op.ShiftType)
{ {
case ShiftType.Lsl: m = GetLslC(context, m, setCarry, shift); break; case ShiftType.Lsl:
case ShiftType.Lsr: m = GetLsrC(context, m, setCarry, shift); break; m = GetLslC(context, m, setCarry, shift);
case ShiftType.Asr: m = GetAsrC(context, m, setCarry, shift); break; break;
case ShiftType.Lsr:
m = GetLsrC(context, m, setCarry, shift);
break;
case ShiftType.Asr:
m = GetAsrC(context, m, setCarry, shift);
break;
case ShiftType.Ror: case ShiftType.Ror:
if (op.Immediate != 0) if (op.Immediate != 0)
{ {
@ -306,9 +331,15 @@ namespace ARMeilleure.Instructions
{ {
switch (shiftType) switch (shiftType)
{ {
case ShiftType.Lsr: shift = 32; break; case ShiftType.Lsr:
case ShiftType.Asr: shift = 32; break; shift = 32;
case ShiftType.Ror: shift = 1; break; break;
case ShiftType.Asr:
shift = 32;
break;
case ShiftType.Ror:
shift = 1;
break;
} }
} }
@ -328,10 +359,18 @@ namespace ARMeilleure.Instructions
switch (op.ShiftType) switch (op.ShiftType)
{ {
case ShiftType.Lsl: shiftResult = EmitLslC(context, m, setCarry, s, shiftIsZero); break; case ShiftType.Lsl:
case ShiftType.Lsr: shiftResult = EmitLsrC(context, m, setCarry, s, shiftIsZero); break; shiftResult = EmitLslC(context, m, setCarry, s, shiftIsZero);
case ShiftType.Asr: shiftResult = EmitAsrC(context, m, setCarry, s, shiftIsZero); break; break;
case ShiftType.Ror: shiftResult = EmitRorC(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); return context.ConditionalSelect(shiftIsZero, zeroResult, shiftResult);

View file

@ -2,7 +2,6 @@ using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State; using ARMeilleure.State;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using static ARMeilleure.Instructions.InstEmitAluHelper; using static ARMeilleure.Instructions.InstEmitAluHelper;
using static ARMeilleure.Instructions.InstEmitFlowHelper; using static ARMeilleure.Instructions.InstEmitFlowHelper;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;

View file

@ -1,7 +1,6 @@
using ARMeilleure.Decoders; using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using static ARMeilleure.Instructions.InstEmitFlowHelper; using static ARMeilleure.Instructions.InstEmitFlowHelper;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory; using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
@ -15,7 +14,7 @@ namespace ARMeilleure.Instructions
None, None,
Increment, Increment,
Invert, Invert,
Negate Negate,
} }
public static void Csel(ArmEmitterContext context) => EmitCsel(context, CselOperation.None); public static void Csel(ArmEmitterContext context) => EmitCsel(context, CselOperation.None);

View file

@ -1,7 +1,6 @@
using ARMeilleure.Decoders; using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory; using static ARMeilleure.IntermediateRepresentation.Operand.Factory;

View file

@ -55,7 +55,7 @@ namespace ARMeilleure.Instructions
(1, true) => nameof(SoftFallback.Crc32ch), (1, true) => nameof(SoftFallback.Crc32ch),
(2, true) => nameof(SoftFallback.Crc32cw), (2, true) => nameof(SoftFallback.Crc32cw),
(3, true) => nameof(SoftFallback.Crc32cx), (3, true) => nameof(SoftFallback.Crc32cx),
_ => throw new ArgumentOutOfRangeException(nameof(size)) _ => throw new ArgumentOutOfRangeException(nameof(size)),
}; };
return context.Call(typeof(SoftFallback).GetMethod(name), crc, value); return context.Call(typeof(SoftFallback).GetMethod(name), crc, value);
@ -71,9 +71,15 @@ namespace ARMeilleure.Instructions
switch (size) switch (size)
{ {
case 0: data = context.VectorInsert8(context.VectorZero(), data, 0); break; case 0:
case 1: data = context.VectorInsert16(context.VectorZero(), data, 0); break; data = context.VectorInsert8(context.VectorZero(), data, 0);
case 2: data = context.VectorInsert(context.VectorZero(), data, 0); break; 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; int bitsize = 8 << size;

View file

@ -16,13 +16,25 @@ namespace ARMeilleure.Instructions
switch (type) switch (type)
{ {
case IntType.UInt8: value = context.ZeroExtend8 (value.Type, value); break; case IntType.UInt8:
case IntType.UInt16: value = context.ZeroExtend16(value.Type, value); break; value = context.ZeroExtend8(value.Type, value);
case IntType.UInt32: value = context.ZeroExtend32(value.Type, value); break; 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.Int8:
case IntType.Int16: value = context.SignExtend16(value.Type, value); break; value = context.SignExtend8(value.Type, value);
case IntType.Int32: value = context.SignExtend32(value.Type, value); break; break;
case IntType.Int16:
value = context.SignExtend16(value.Type, value);
break;
case IntType.Int32:
value = context.SignExtend32(value.Type, value);
break;
} }
return value; return value;
@ -100,78 +112,51 @@ namespace ARMeilleure.Instructions
public static int GetBankedRegisterAlias(Aarch32Mode mode, int regIndex) public static int GetBankedRegisterAlias(Aarch32Mode mode, int regIndex)
{ {
switch (regIndex) return regIndex switch
{ {
case 8: return mode == Aarch32Mode.Fiq #pragma warning disable IDE0055 // Disable formatting
? RegisterAlias.R8Fiq 8 => mode == Aarch32Mode.Fiq ? RegisterAlias.R8Fiq : RegisterAlias.R8Usr,
: RegisterAlias.R8Usr; 9 => mode == Aarch32Mode.Fiq ? RegisterAlias.R9Fiq : RegisterAlias.R9Usr,
10 => mode == Aarch32Mode.Fiq ? RegisterAlias.R10Fiq : RegisterAlias.R10Usr,
case 9: return mode == Aarch32Mode.Fiq 11 => mode == Aarch32Mode.Fiq ? RegisterAlias.R11Fiq : RegisterAlias.R11Usr,
? RegisterAlias.R9Fiq 12 => mode == Aarch32Mode.Fiq ? RegisterAlias.R12Fiq : RegisterAlias.R12Usr,
: RegisterAlias.R9Usr; 13 => mode switch
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)
{ {
case Aarch32Mode.User: Aarch32Mode.User or Aarch32Mode.System => RegisterAlias.SpUsr,
case Aarch32Mode.System: return RegisterAlias.SpUsr; Aarch32Mode.Fiq => RegisterAlias.SpFiq,
case Aarch32Mode.Fiq: return RegisterAlias.SpFiq; Aarch32Mode.Irq => RegisterAlias.SpIrq,
case Aarch32Mode.Irq: return RegisterAlias.SpIrq; Aarch32Mode.Supervisor => RegisterAlias.SpSvc,
case Aarch32Mode.Supervisor: return RegisterAlias.SpSvc; Aarch32Mode.Abort => RegisterAlias.SpAbt,
case Aarch32Mode.Abort: return RegisterAlias.SpAbt; Aarch32Mode.Hypervisor => RegisterAlias.SpHyp,
case Aarch32Mode.Hypervisor: return RegisterAlias.SpHyp; Aarch32Mode.Undefined => RegisterAlias.SpUnd,
case Aarch32Mode.Undefined: return RegisterAlias.SpUnd; _ => throw new ArgumentException($"No such AArch32Mode: {mode}", nameof(mode)),
},
default: throw new ArgumentException(nameof(mode)); 14 => mode switch
}
case 14:
switch (mode)
{ {
case Aarch32Mode.User: Aarch32Mode.User or Aarch32Mode.Hypervisor or Aarch32Mode.System => RegisterAlias.LrUsr,
case Aarch32Mode.Hypervisor: Aarch32Mode.Fiq => RegisterAlias.LrFiq,
case Aarch32Mode.System: return RegisterAlias.LrUsr; Aarch32Mode.Irq => RegisterAlias.LrIrq,
case Aarch32Mode.Fiq: return RegisterAlias.LrFiq; Aarch32Mode.Supervisor => RegisterAlias.LrSvc,
case Aarch32Mode.Irq: return RegisterAlias.LrIrq; Aarch32Mode.Abort => RegisterAlias.LrAbt,
case Aarch32Mode.Supervisor: return RegisterAlias.LrSvc; Aarch32Mode.Undefined => RegisterAlias.LrUnd,
case Aarch32Mode.Abort: return RegisterAlias.LrAbt; _ => throw new ArgumentException($"No such AArch32Mode: {mode}", nameof(mode)),
case Aarch32Mode.Undefined: return RegisterAlias.LrUnd; },
_ => throw new ArgumentOutOfRangeException(nameof(regIndex), regIndex, null),
default: throw new ArgumentException(nameof(mode)); #pragma warning restore IDE0055
} };
default: throw new ArgumentOutOfRangeException(nameof(regIndex));
}
} }
public static bool IsA32Return(ArmEmitterContext context) public static bool IsA32Return(ArmEmitterContext context)
{ {
switch (context.CurrOp) return context.CurrOp switch
{ {
case IOpCode32MemMult op: IOpCode32MemMult => true, // Setting PC using LDM is nearly always a return.
return true; // Setting PC using LDM is nearly always a return. OpCode32AluRsImm op => op.Rm == RegisterAlias.Aarch32Lr,
case OpCode32AluRsImm op: OpCode32AluRsReg op => op.Rm == RegisterAlias.Aarch32Lr,
return op.Rm == RegisterAlias.Aarch32Lr; OpCode32AluReg op => op.Rm == RegisterAlias.Aarch32Lr,
case OpCode32AluRsReg op: OpCode32Mem op => op.Rn == RegisterAlias.Aarch32Sp && op.WBack && !op.Index, // Setting PC to an address stored on the stack is nearly always a return.
return op.Rm == RegisterAlias.Aarch32Lr; _ => false,
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;
} }
public static void EmitBxWritePc(ArmEmitterContext context, Operand pc, int sourceRegister = 0) 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.State;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System; using System;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.Instructions.InstEmitMemoryHelper; using static ARMeilleure.Instructions.InstEmitMemoryHelper;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory; using static ARMeilleure.IntermediateRepresentation.Operand.Factory;

View file

@ -3,7 +3,6 @@ using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.Instructions.InstEmitMemoryExHelper; using static ARMeilleure.Instructions.InstEmitMemoryExHelper;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory; using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
@ -18,7 +17,7 @@ namespace ARMeilleure.Instructions
None = 0, None = 0,
Ordered = 1, Ordered = 1,
Exclusive = 2, Exclusive = 2,
OrderedEx = Ordered | Exclusive OrderedEx = Ordered | Exclusive,
} }
public static void Clrex(ArmEmitterContext context) public static void Clrex(ArmEmitterContext context)

View file

@ -1,7 +1,6 @@
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State; using ARMeilleure.State;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory; using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
@ -118,14 +117,14 @@ namespace ARMeilleure.Instructions
1 => context.Load16(exValuePtr), 1 => context.Load16(exValuePtr),
2 => context.Load(OperandType.I32, exValuePtr), 2 => context.Load(OperandType.I32, exValuePtr),
3 => context.Load(OperandType.I64, exValuePtr), 3 => context.Load(OperandType.I64, exValuePtr),
_ => context.Load(OperandType.V128, exValuePtr) _ => context.Load(OperandType.V128, exValuePtr),
}; };
Operand currValue = size switch Operand currValue = size switch
{ {
0 => context.CompareAndSwap8(physAddr, exValue, value), 0 => context.CompareAndSwap8(physAddr, exValue, value),
1 => context.CompareAndSwap16(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. // 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 ARMeilleure.Translation.PTC;
using System; using System;
using System.Reflection; using System.Reflection;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory; using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
@ -20,7 +19,7 @@ namespace ARMeilleure.Instructions
{ {
Zx, Zx,
Sx32, Sx32,
Sx64 Sx64,
} }
public static void EmitLoadZx(ArmEmitterContext context, Operand address, int rt, int size) public static void EmitLoadZx(ArmEmitterContext context, Operand address, int rt, int size)
@ -66,9 +65,15 @@ namespace ARMeilleure.Instructions
switch (size) switch (size)
{ {
case 0: value = context.SignExtend8 (destType, value); break; case 0:
case 1: value = context.SignExtend16(destType, value); break; value = context.SignExtend8(destType, value);
case 2: value = context.SignExtend32(destType, value); break; 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) switch (size)
{ {
case 0: value = context.Load8 (physAddr); break; case 0:
case 1: value = context.Load16(physAddr); break; value = context.Load8(physAddr);
case 2: value = context.Load (OperandType.I32, physAddr); break; break;
case 3: value = context.Load (OperandType.I64, 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); context.Copy(temp, value);
@ -169,10 +182,18 @@ namespace ARMeilleure.Instructions
switch (size) switch (size)
{ {
case 0: value = context.Load8 (physAddr); break; case 0:
case 1: value = context.Load16(physAddr); break; value = context.Load8(physAddr);
case 2: value = context.Load (OperandType.I32, physAddr); break; break;
case 3: value = context.Load (OperandType.I64, 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); SetInt(context, rt, value);
@ -204,7 +225,7 @@ namespace ARMeilleure.Instructions
1 => context.Load16(physAddr), 1 => context.Load16(physAddr),
2 => context.Load(OperandType.I32, physAddr), 2 => context.Load(OperandType.I32, physAddr),
3 => context.Load(OperandType.I64, 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) switch (size)
{ {
case 0: value = context.VectorInsert8 (vector, context.Load8(physAddr), elem); break; case 0:
case 1: value = context.VectorInsert16(vector, context.Load16(physAddr), elem); break; value = context.VectorInsert8(vector, context.Load8(physAddr), elem);
case 2: value = context.VectorInsert (vector, context.Load(OperandType.I32, physAddr), elem); break; break;
case 3: value = context.VectorInsert (vector, context.Load(OperandType.I64, physAddr), elem); break; case 1:
case 4: value = context.Load (OperandType.V128, physAddr); break; 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); context.Copy(GetVec(rt), value);
@ -267,10 +298,18 @@ namespace ARMeilleure.Instructions
switch (size) switch (size)
{ {
case 0: context.Store8 (physAddr, value); break; case 0:
case 1: context.Store16(physAddr, value); break; context.Store8(physAddr, value);
case 2: context.Store (physAddr, value); break; break;
case 3: context.Store (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()) if (!context.Memory.Type.IsHostMapped())
@ -329,11 +368,21 @@ namespace ARMeilleure.Instructions
switch (size) switch (size)
{ {
case 0: context.Store8 (physAddr, context.VectorExtract8(value, elem)); break; case 0:
case 1: context.Store16(physAddr, context.VectorExtract16(value, elem)); break; context.Store8(physAddr, context.VectorExtract8(value, elem));
case 2: context.Store (physAddr, context.VectorExtract(OperandType.I32, value, elem)); break; break;
case 3: context.Store (physAddr, context.VectorExtract(OperandType.I64, value, elem)); break; case 1:
case 4: context.Store (physAddr, value); break; 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()) if (!context.Memory.Type.IsHostMapped())
@ -464,10 +513,18 @@ namespace ARMeilleure.Instructions
switch (size) switch (size)
{ {
case 0: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadByte)); break; case 0:
case 1: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt16)); break; info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadByte));
case 2: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt32)); break; break;
case 3: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64)); 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); return context.Call(info, address);
@ -485,21 +542,39 @@ namespace ARMeilleure.Instructions
switch (size) switch (size)
{ {
case 0: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadByte)); break; case 0:
case 1: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt16)); break; info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadByte));
case 2: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt32)); break; break;
case 3: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64)); break; case 1:
case 4: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadVector128)); break; 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); Operand value = context.Call(info, address);
switch (size) switch (size)
{ {
case 0: value = context.VectorInsert8 (vector, value, elem); break; case 0:
case 1: value = context.VectorInsert16(vector, value, elem); break; value = context.VectorInsert8(vector, value, elem);
case 2: value = context.VectorInsert (vector, value, elem); break; break;
case 3: value = context.VectorInsert (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); context.Copy(GetVec(rt), value);
@ -511,10 +586,18 @@ namespace ARMeilleure.Instructions
switch (size) switch (size)
{ {
case 0: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteByte)); break; case 0:
case 1: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt16)); break; info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteByte));
case 2: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt32)); break; break;
case 3: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt64)); 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); Operand value = GetInt(context, rt);
@ -538,11 +621,21 @@ namespace ARMeilleure.Instructions
switch (size) switch (size)
{ {
case 0: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteByte)); break; case 0:
case 1: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt16)); break; info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteByte));
case 2: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt32)); break; break;
case 3: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt64)); break; case 1:
case 4: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteVector128)); break; 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; Operand value = default;
@ -551,10 +644,18 @@ namespace ARMeilleure.Instructions
{ {
switch (size) switch (size)
{ {
case 0: value = context.VectorExtract8 (GetVec(rt), elem); break; case 0:
case 1: value = context.VectorExtract16(GetVec(rt), elem); break; value = context.VectorExtract8(GetVec(rt), elem);
case 2: value = context.VectorExtract (OperandType.I32, GetVec(rt), elem); break; break;
case 3: value = context.VectorExtract (OperandType.I64, 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 else
@ -585,18 +686,14 @@ namespace ARMeilleure.Instructions
// ARM32 helpers. // ARM32 helpers.
public static Operand GetMemM(ArmEmitterContext context, bool setCarry = true) public static Operand GetMemM(ArmEmitterContext context, bool setCarry = true)
{ {
switch (context.CurrOp) return context.CurrOp switch
{ {
case IOpCode32MemRsImm op: return GetMShiftedByImmediate(context, op, setCarry); IOpCode32MemRsImm op => GetMShiftedByImmediate(context, op, setCarry),
IOpCode32MemReg op => GetIntA32(context, op.Rm),
case IOpCode32MemReg op: return GetIntA32(context, op.Rm); IOpCode32Mem op => Const(op.Immediate),
OpCode32SimdMemImm op => Const(op.Immediate),
case IOpCode32Mem op: return Const(op.Immediate); _ => throw InvalidOpCodeType(context.CurrOp),
};
case OpCode32SimdMemImm op: return Const(op.Immediate);
default: throw InvalidOpCodeType(context.CurrOp);
}
} }
private static Exception InvalidOpCodeType(OpCode opCode) private static Exception InvalidOpCodeType(OpCode opCode)
@ -614,9 +711,15 @@ namespace ARMeilleure.Instructions
{ {
switch (op.ShiftType) switch (op.ShiftType)
{ {
case ShiftType.Lsr: shift = 32; break; case ShiftType.Lsr:
case ShiftType.Asr: shift = 32; break; shift = 32;
case ShiftType.Ror: shift = 1; break; break;
case ShiftType.Asr:
shift = 32;
break;
case ShiftType.Ror:
shift = 1;
break;
} }
} }
@ -626,9 +729,15 @@ namespace ARMeilleure.Instructions
switch (op.ShiftType) switch (op.ShiftType)
{ {
case ShiftType.Lsl: m = InstEmitAluHelper.GetLslC(context, m, setCarry, shift); break; case ShiftType.Lsl:
case ShiftType.Lsr: m = InstEmitAluHelper.GetLsrC(context, m, setCarry, shift); break; m = InstEmitAluHelper.GetLslC(context, m, setCarry, shift);
case ShiftType.Asr: m = InstEmitAluHelper.GetAsrC(context, m, setCarry, shift); break; 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: case ShiftType.Ror:
if (op.Immediate != 0) if (op.Immediate != 0)
{ {

View file

@ -2,7 +2,7 @@ using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System; using System;
using System.Diagnostics.CodeAnalysis;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
namespace ARMeilleure.Instructions namespace ARMeilleure.Instructions
@ -33,6 +33,7 @@ namespace ARMeilleure.Instructions
public static void Umsubl(ArmEmitterContext context) => EmitMull(context, MullFlags.Subtract); public static void Umsubl(ArmEmitterContext context) => EmitMull(context, MullFlags.Subtract);
[Flags] [Flags]
[SuppressMessage("Design", "CA1069: Enums values should not be duplicated")]
private enum MullFlags private enum MullFlags
{ {
Subtract = 0, Subtract = 0,
@ -40,7 +41,7 @@ namespace ARMeilleure.Instructions
Signed = 1 << 1, Signed = 1 << 1,
SignedAdd = Signed | Add, SignedAdd = Signed | Add,
SignedSubtract = Signed | Subtract SignedSubtract = Signed | Subtract,
} }
private static void EmitMull(ArmEmitterContext context, MullFlags flags) private static void EmitMull(ArmEmitterContext context, MullFlags flags)

View file

@ -3,7 +3,6 @@ using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State; using ARMeilleure.State;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System; using System;
using static ARMeilleure.Instructions.InstEmitAluHelper; using static ARMeilleure.Instructions.InstEmitAluHelper;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory; using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
@ -20,7 +19,7 @@ namespace ARMeilleure.Instructions
Signed = 1 << 2, Signed = 1 << 2,
SignedAdd = Signed | Add, SignedAdd = Signed | Add,
SignedSubtract = Signed | Subtract SignedSubtract = Signed | Subtract,
} }
public static void Mla(ArmEmitterContext context) public static void Mla(ArmEmitterContext context)

View file

@ -7,7 +7,6 @@ using ARMeilleure.State;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.Instructions.InstEmitSimdHelper; using static ARMeilleure.Instructions.InstEmitSimdHelper;
using static ARMeilleure.Instructions.InstEmitSimdHelper32; using static ARMeilleure.Instructions.InstEmitSimdHelper32;
@ -185,11 +184,12 @@ namespace ARMeilleure.Instructions
int eSize = 8 << op.Size; int eSize = 8 << op.Size;
Operand res = eSize switch { Operand res = eSize switch
{
8 => Clz_V_I8(context, GetVec(op.Rn)), 8 => Clz_V_I8(context, GetVec(op.Rn)),
16 => Clz_V_I16(context, GetVec(op.Rn)), 16 => Clz_V_I16(context, GetVec(op.Rn)),
32 => Clz_V_I32(context, GetVec(op.Rn)), 32 => Clz_V_I32(context, GetVec(op.Rn)),
_ => default _ => default,
}; };
if (res != default) if (res != default)
@ -282,12 +282,14 @@ namespace ARMeilleure.Instructions
return default; return default;
} }
#pragma warning disable IDE0055 // Disable formatting
Operand AddVectorI32(Operand op0, Operand op1) => context.AddIntrinsic(Intrinsic.X86Paddd, op0, op1); 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 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 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 OrVector(Operand op0, Operand op1) => context.AddIntrinsic(Intrinsic.X86Por, op0, op1);
Operand AndVector(Operand op0, Operand op1) => context.AddIntrinsic(Intrinsic.X86Pand, 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()); Operand NotVector(Operand op0) => context.AddIntrinsic(Intrinsic.X86Pandn, op0, context.VectorOne());
#pragma warning restore IDE0055
Operand c55555555 = X86GetAllElements(context, 0x55555555); Operand c55555555 = X86GetAllElements(context, 0x55555555);
Operand c33333333 = X86GetAllElements(context, 0x33333333); Operand c33333333 = X86GetAllElements(context, 0x33333333);
@ -5072,7 +5074,7 @@ namespace ARMeilleure.Instructions
{ {
None, None,
Add, Add,
Subtract Subtract,
} }
private static void EmitSse41VectorMul_AddSub(ArmEmitterContext context, AddSub addSub) private static void EmitSse41VectorMul_AddSub(ArmEmitterContext context, AddSub addSub)

View file

@ -2,7 +2,6 @@
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System; using System;
using static ARMeilleure.Instructions.InstEmitFlowHelper; using static ARMeilleure.Instructions.InstEmitFlowHelper;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.Instructions.InstEmitSimdHelper; using static ARMeilleure.Instructions.InstEmitSimdHelper;
@ -190,7 +189,7 @@ namespace ARMeilleure.Instructions
2 => context.Multiply(context.ZeroExtend32(OperandType.I64, insert), Const(0x0000000100000001u)), 2 => context.Multiply(context.ZeroExtend32(OperandType.I64, insert), Const(0x0000000100000001u)),
1 => context.Multiply(context.ZeroExtend16(OperandType.I64, insert), Const(0x0001000100010001u)), 1 => context.Multiply(context.ZeroExtend16(OperandType.I64, insert), Const(0x0001000100010001u)),
0 => context.Multiply(context.ZeroExtend8(OperandType.I64, insert), Const(0x0101010101010101u)), 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); InsertScalar(context, op.Vd, insert);
@ -212,7 +211,7 @@ namespace ARMeilleure.Instructions
2 => context.Multiply(context.ZeroExtend32(OperandType.I64, insert), Const(0x0000000100000001u)), 2 => context.Multiply(context.ZeroExtend32(OperandType.I64, insert), Const(0x0000000100000001u)),
1 => context.Multiply(context.ZeroExtend16(OperandType.I64, insert), Const(0x0001000100010001u)), 1 => context.Multiply(context.ZeroExtend16(OperandType.I64, insert), Const(0x0001000100010001u)),
0 => context.Multiply(context.ZeroExtend8(OperandType.I64, insert), Const(0x0101010101010101u)), 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); InsertScalar(context, op.Vd, insert);
@ -1654,7 +1653,7 @@ namespace ARMeilleure.Instructions
{ {
IOpCode32Simd op = (IOpCode32Simd)context.CurrOp; IOpCode32Simd op = (IOpCode32Simd)context.CurrOp;
Func<Operand, Operand, Operand> genericEmit = (n, m) => Operand genericEmit(Operand n, Operand m)
{ {
Operand nNum = context.Copy(n); Operand nNum = context.Copy(n);
Operand mNum = context.Copy(m); Operand mNum = context.Copy(m);
@ -1688,7 +1687,7 @@ namespace ARMeilleure.Instructions
return context.AddIntrinsic(isMaxNum ? Intrinsic.X86Maxpd : Intrinsic.X86Minpd, nNum, mNum); return context.AddIntrinsic(isMaxNum ? Intrinsic.X86Maxpd : Intrinsic.X86Minpd, nNum, mNum);
} }
}; }
if (scalar) if (scalar)
{ {

View file

@ -3,7 +3,6 @@ using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State; using ARMeilleure.State;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System; using System;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.Instructions.InstEmitSimdHelper; using static ARMeilleure.Instructions.InstEmitSimdHelper;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory; using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
@ -510,7 +509,7 @@ namespace ARMeilleure.Instructions
private static void EmitSetNzcv(ArmEmitterContext context, int nzcv) private static void EmitSetNzcv(ArmEmitterContext context, int nzcv)
{ {
Operand Extract(int value, int bit) static Operand Extract(int value, int bit)
{ {
if (bit != 0) if (bit != 0)
{ {
@ -532,7 +531,7 @@ namespace ARMeilleure.Instructions
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; 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)) if (Optimizations.FastFP && (signalNaNs ? Optimizations.UseAvx : Optimizations.UseSse2))
{ {

View file

@ -5,7 +5,6 @@ using ARMeilleure.Translation;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Reflection; using System.Reflection;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.Instructions.InstEmitSimdHelper; using static ARMeilleure.Instructions.InstEmitSimdHelper;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory; using static ARMeilleure.IntermediateRepresentation.Operand.Factory;

View file

@ -5,7 +5,6 @@ using ARMeilleure.Translation;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Reflection; using System.Reflection;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.Instructions.InstEmitSimdHelper; using static ARMeilleure.Instructions.InstEmitSimdHelper;
using static ARMeilleure.Instructions.InstEmitSimdHelper32; using static ARMeilleure.Instructions.InstEmitSimdHelper32;
@ -225,25 +224,14 @@ namespace ARMeilleure.Instructions
private static FPRoundingMode RMToRoundMode(int rm) private static FPRoundingMode RMToRoundMode(int rm)
{ {
FPRoundingMode roundMode; return rm switch
switch (rm)
{ {
case 0b00: 0b00 => FPRoundingMode.ToNearestAway,
roundMode = FPRoundingMode.ToNearestAway; 0b01 => FPRoundingMode.ToNearest,
break; 0b10 => FPRoundingMode.TowardsPlusInfinity,
case 0b01: 0b11 => FPRoundingMode.TowardsMinusInfinity,
roundMode = FPRoundingMode.ToNearest; _ => throw new ArgumentOutOfRangeException(nameof(rm)),
break; };
case 0b10:
roundMode = FPRoundingMode.TowardsPlusInfinity;
break;
case 0b11:
roundMode = FPRoundingMode.TowardsMinusInfinity;
break;
default:
throw new ArgumentOutOfRangeException(nameof(rm));
}
return roundMode;
} }
// VCVTA/M/N/P (floating-point). // VCVTA/M/N/P (floating-point).
@ -270,22 +258,24 @@ namespace ARMeilleure.Instructions
if (unsigned) if (unsigned)
{ {
inst = rm switch { inst = rm switch
{
0b00 => Intrinsic.Arm64FcvtauGp, 0b00 => Intrinsic.Arm64FcvtauGp,
0b01 => Intrinsic.Arm64FcvtnuGp, 0b01 => Intrinsic.Arm64FcvtnuGp,
0b10 => Intrinsic.Arm64FcvtpuGp, 0b10 => Intrinsic.Arm64FcvtpuGp,
0b11 => Intrinsic.Arm64FcvtmuGp, 0b11 => Intrinsic.Arm64FcvtmuGp,
_ => throw new ArgumentOutOfRangeException(nameof(rm)) _ => throw new InvalidOperationException($"{nameof(rm)} contains an invalid value: {rm}"),
}; };
} }
else else
{ {
inst = rm switch { inst = rm switch
{
0b00 => Intrinsic.Arm64FcvtasGp, 0b00 => Intrinsic.Arm64FcvtasGp,
0b01 => Intrinsic.Arm64FcvtnsGp, 0b01 => Intrinsic.Arm64FcvtnsGp,
0b10 => Intrinsic.Arm64FcvtpsGp, 0b10 => Intrinsic.Arm64FcvtpsGp,
0b11 => Intrinsic.Arm64FcvtmsGp, 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) if (unsigned)
{ {
inst = rm switch { inst = rm switch
{
0b00 => Intrinsic.Arm64FcvtauS, 0b00 => Intrinsic.Arm64FcvtauS,
0b01 => Intrinsic.Arm64FcvtnuS, 0b01 => Intrinsic.Arm64FcvtnuS,
0b10 => Intrinsic.Arm64FcvtpuS, 0b10 => Intrinsic.Arm64FcvtpuS,
0b11 => Intrinsic.Arm64FcvtmuS, 0b11 => Intrinsic.Arm64FcvtmuS,
_ => throw new ArgumentOutOfRangeException(nameof(rm)) _ => throw new InvalidOperationException($"{nameof(rm)} contains an invalid value: {rm}"),
}; };
} }
else else
{ {
inst = rm switch { inst = rm switch
{
0b00 => Intrinsic.Arm64FcvtasS, 0b00 => Intrinsic.Arm64FcvtasS,
0b01 => Intrinsic.Arm64FcvtnsS, 0b01 => Intrinsic.Arm64FcvtnsS,
0b10 => Intrinsic.Arm64FcvtpsS, 0b10 => Intrinsic.Arm64FcvtpsS,
0b11 => Intrinsic.Arm64FcvtmsS, 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) if (Optimizations.UseAdvSimd)
{ {
Intrinsic inst = rm switch { Intrinsic inst = rm switch
{
0b00 => Intrinsic.Arm64FrintaS, 0b00 => Intrinsic.Arm64FrintaS,
0b01 => Intrinsic.Arm64FrintnS, 0b01 => Intrinsic.Arm64FrintnS,
0b10 => Intrinsic.Arm64FrintpS, 0b10 => Intrinsic.Arm64FrintpS,
0b11 => Intrinsic.Arm64FrintmS, 0b11 => Intrinsic.Arm64FrintmS,
_ => throw new ArgumentOutOfRangeException(nameof(rm)) _ => throw new InvalidOperationException($"{nameof(rm)} contains an invalid value: {rm}"),
}; };
InstEmitSimdHelper32Arm64.EmitScalarUnaryOpF32(context, inst); InstEmitSimdHelper32Arm64.EmitScalarUnaryOpF32(context, inst);

View file

@ -6,7 +6,6 @@ using ARMeilleure.Translation;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Reflection; using System.Reflection;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory; using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
@ -23,14 +22,14 @@ namespace ARMeilleure.Instructions
{ {
14L << 56 | 12L << 48 | 10L << 40 | 08L << 32 | 06L << 24 | 04L << 16 | 02L << 8 | 00L << 0, // B 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 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[] 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 | 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 | 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; public static readonly long ZeroMask = 128L << 56 | 128L << 48 | 128L << 40 | 128L << 32 | 128L << 24 | 128L << 16 | 128L << 8 | 128L << 0;
@ -50,7 +49,7 @@ namespace ARMeilleure.Instructions
Intrinsic.X86Paddb, Intrinsic.X86Paddb,
Intrinsic.X86Paddw, Intrinsic.X86Paddw,
Intrinsic.X86Paddd, Intrinsic.X86Paddd,
Intrinsic.X86Paddq Intrinsic.X86Paddq,
}; };
public static readonly Intrinsic[] X86PcmpeqInstruction = new Intrinsic[] public static readonly Intrinsic[] X86PcmpeqInstruction = new Intrinsic[]
@ -58,7 +57,7 @@ namespace ARMeilleure.Instructions
Intrinsic.X86Pcmpeqb, Intrinsic.X86Pcmpeqb,
Intrinsic.X86Pcmpeqw, Intrinsic.X86Pcmpeqw,
Intrinsic.X86Pcmpeqd, Intrinsic.X86Pcmpeqd,
Intrinsic.X86Pcmpeqq Intrinsic.X86Pcmpeqq,
}; };
public static readonly Intrinsic[] X86PcmpgtInstruction = new Intrinsic[] public static readonly Intrinsic[] X86PcmpgtInstruction = new Intrinsic[]
@ -66,49 +65,49 @@ namespace ARMeilleure.Instructions
Intrinsic.X86Pcmpgtb, Intrinsic.X86Pcmpgtb,
Intrinsic.X86Pcmpgtw, Intrinsic.X86Pcmpgtw,
Intrinsic.X86Pcmpgtd, Intrinsic.X86Pcmpgtd,
Intrinsic.X86Pcmpgtq Intrinsic.X86Pcmpgtq,
}; };
public static readonly Intrinsic[] X86PmaxsInstruction = new Intrinsic[] public static readonly Intrinsic[] X86PmaxsInstruction = new Intrinsic[]
{ {
Intrinsic.X86Pmaxsb, Intrinsic.X86Pmaxsb,
Intrinsic.X86Pmaxsw, Intrinsic.X86Pmaxsw,
Intrinsic.X86Pmaxsd Intrinsic.X86Pmaxsd,
}; };
public static readonly Intrinsic[] X86PmaxuInstruction = new Intrinsic[] public static readonly Intrinsic[] X86PmaxuInstruction = new Intrinsic[]
{ {
Intrinsic.X86Pmaxub, Intrinsic.X86Pmaxub,
Intrinsic.X86Pmaxuw, Intrinsic.X86Pmaxuw,
Intrinsic.X86Pmaxud Intrinsic.X86Pmaxud,
}; };
public static readonly Intrinsic[] X86PminsInstruction = new Intrinsic[] public static readonly Intrinsic[] X86PminsInstruction = new Intrinsic[]
{ {
Intrinsic.X86Pminsb, Intrinsic.X86Pminsb,
Intrinsic.X86Pminsw, Intrinsic.X86Pminsw,
Intrinsic.X86Pminsd Intrinsic.X86Pminsd,
}; };
public static readonly Intrinsic[] X86PminuInstruction = new Intrinsic[] public static readonly Intrinsic[] X86PminuInstruction = new Intrinsic[]
{ {
Intrinsic.X86Pminub, Intrinsic.X86Pminub,
Intrinsic.X86Pminuw, Intrinsic.X86Pminuw,
Intrinsic.X86Pminud Intrinsic.X86Pminud,
}; };
public static readonly Intrinsic[] X86PmovsxInstruction = new Intrinsic[] public static readonly Intrinsic[] X86PmovsxInstruction = new Intrinsic[]
{ {
Intrinsic.X86Pmovsxbw, Intrinsic.X86Pmovsxbw,
Intrinsic.X86Pmovsxwd, Intrinsic.X86Pmovsxwd,
Intrinsic.X86Pmovsxdq Intrinsic.X86Pmovsxdq,
}; };
public static readonly Intrinsic[] X86PmovzxInstruction = new Intrinsic[] public static readonly Intrinsic[] X86PmovzxInstruction = new Intrinsic[]
{ {
Intrinsic.X86Pmovzxbw, Intrinsic.X86Pmovzxbw,
Intrinsic.X86Pmovzxwd, Intrinsic.X86Pmovzxwd,
Intrinsic.X86Pmovzxdq Intrinsic.X86Pmovzxdq,
}; };
public static readonly Intrinsic[] X86PsllInstruction = new Intrinsic[] public static readonly Intrinsic[] X86PsllInstruction = new Intrinsic[]
@ -116,14 +115,14 @@ namespace ARMeilleure.Instructions
0, 0,
Intrinsic.X86Psllw, Intrinsic.X86Psllw,
Intrinsic.X86Pslld, Intrinsic.X86Pslld,
Intrinsic.X86Psllq Intrinsic.X86Psllq,
}; };
public static readonly Intrinsic[] X86PsraInstruction = new Intrinsic[] public static readonly Intrinsic[] X86PsraInstruction = new Intrinsic[]
{ {
0, 0,
Intrinsic.X86Psraw, Intrinsic.X86Psraw,
Intrinsic.X86Psrad Intrinsic.X86Psrad,
}; };
public static readonly Intrinsic[] X86PsrlInstruction = new Intrinsic[] public static readonly Intrinsic[] X86PsrlInstruction = new Intrinsic[]
@ -131,7 +130,7 @@ namespace ARMeilleure.Instructions
0, 0,
Intrinsic.X86Psrlw, Intrinsic.X86Psrlw,
Intrinsic.X86Psrld, Intrinsic.X86Psrld,
Intrinsic.X86Psrlq Intrinsic.X86Psrlq,
}; };
public static readonly Intrinsic[] X86PsubInstruction = new Intrinsic[] public static readonly Intrinsic[] X86PsubInstruction = new Intrinsic[]
@ -139,7 +138,7 @@ namespace ARMeilleure.Instructions
Intrinsic.X86Psubb, Intrinsic.X86Psubb,
Intrinsic.X86Psubw, Intrinsic.X86Psubw,
Intrinsic.X86Psubd, Intrinsic.X86Psubd,
Intrinsic.X86Psubq Intrinsic.X86Psubq,
}; };
public static readonly Intrinsic[] X86PunpckhInstruction = new Intrinsic[] public static readonly Intrinsic[] X86PunpckhInstruction = new Intrinsic[]
@ -147,7 +146,7 @@ namespace ARMeilleure.Instructions
Intrinsic.X86Punpckhbw, Intrinsic.X86Punpckhbw,
Intrinsic.X86Punpckhwd, Intrinsic.X86Punpckhwd,
Intrinsic.X86Punpckhdq, Intrinsic.X86Punpckhdq,
Intrinsic.X86Punpckhqdq Intrinsic.X86Punpckhqdq,
}; };
public static readonly Intrinsic[] X86PunpcklInstruction = new Intrinsic[] public static readonly Intrinsic[] X86PunpcklInstruction = new Intrinsic[]
@ -155,7 +154,7 @@ namespace ARMeilleure.Instructions
Intrinsic.X86Punpcklbw, Intrinsic.X86Punpcklbw,
Intrinsic.X86Punpcklwd, Intrinsic.X86Punpcklwd,
Intrinsic.X86Punpckldq, Intrinsic.X86Punpckldq,
Intrinsic.X86Punpcklqdq Intrinsic.X86Punpcklqdq,
}; };
#endregion #endregion
@ -310,15 +309,16 @@ namespace ARMeilleure.Instructions
public static int X86GetRoundControl(FPRoundingMode roundMode) public static int X86GetRoundControl(FPRoundingMode roundMode)
{ {
switch (roundMode) return roundMode switch
{ {
case FPRoundingMode.ToNearest: return 8 | 0; // even #pragma warning disable IDE0055 // Disable formatting
case FPRoundingMode.TowardsPlusInfinity: return 8 | 2; FPRoundingMode.ToNearest => 8 | 0, // even
case FPRoundingMode.TowardsMinusInfinity: return 8 | 1; FPRoundingMode.TowardsPlusInfinity => 8 | 2,
case FPRoundingMode.TowardsZero: return 8 | 3; FPRoundingMode.TowardsMinusInfinity => 8 | 1,
} FPRoundingMode.TowardsZero => 8 | 3,
_ => throw new ArgumentException($"Invalid rounding mode \"{roundMode}\"."),
throw new ArgumentException($"Invalid rounding mode \"{roundMode}\"."); #pragma warning restore IDE0055
};
} }
public static Operand EmitSse41RoundToNearestWithTiesToAwayOpF(ArmEmitterContext context, Operand n, bool scalar) public static Operand EmitSse41RoundToNearestWithTiesToAwayOpF(ArmEmitterContext context, Operand n, bool scalar)
@ -1444,7 +1444,7 @@ namespace ARMeilleure.Instructions
// Vex. // Vex.
GreaterThanOrEqual = 13, // Ordered, signaling. GreaterThanOrEqual = 13, // Ordered, signaling.
GreaterThan = 14, // Ordered, signaling. GreaterThan = 14, // Ordered, signaling.
OrderedS = 23 // Signaling. OrderedS = 23, // Signaling.
} }
[Flags] [Flags]
@ -1459,7 +1459,7 @@ namespace ARMeilleure.Instructions
Add = 1 << 3, Add = 1 << 3,
Sub = 1 << 4, Sub = 1 << 4,
Accumulate = 1 << 5 Accumulate = 1 << 5,
} }
public static void EmitScalarSaturatingUnaryOpSx(ArmEmitterContext context, Func1I emit) public static void EmitScalarSaturatingUnaryOpSx(ArmEmitterContext context, Func1I emit)
@ -1637,7 +1637,7 @@ namespace ARMeilleure.Instructions
VectorSxSx = SignedSrc | SignedDst, VectorSxSx = SignedSrc | SignedDst,
VectorSxZx = SignedSrc, VectorSxZx = SignedSrc,
VectorZxZx = 0 VectorZxZx = 0,
} }
public static void EmitSaturatingNarrowOp(ArmEmitterContext context, SaturatingNarrowFlags flags) public static void EmitSaturatingNarrowOp(ArmEmitterContext context, SaturatingNarrowFlags flags)
@ -2034,18 +2034,30 @@ namespace ARMeilleure.Instructions
{ {
switch (size) switch (size)
{ {
case 0: res = context.SignExtend8 (OperandType.I64, res); break; case 0:
case 1: res = context.SignExtend16(OperandType.I64, res); break; res = context.SignExtend8(OperandType.I64, res);
case 2: res = context.SignExtend32(OperandType.I64, res); break; break;
case 1:
res = context.SignExtend16(OperandType.I64, res);
break;
case 2:
res = context.SignExtend32(OperandType.I64, res);
break;
} }
} }
else else
{ {
switch (size) switch (size)
{ {
case 0: res = context.ZeroExtend8 (OperandType.I64, res); break; case 0:
case 1: res = context.ZeroExtend16(OperandType.I64, res); break; res = context.ZeroExtend8(OperandType.I64, res);
case 2: res = context.ZeroExtend32(OperandType.I64, res); break; 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) switch (size)
{ {
case 0: vector = context.VectorInsert8 (vector, value, index); break; case 0:
case 1: vector = context.VectorInsert16(vector, value, index); break; vector = context.VectorInsert8(vector, value, index);
case 2: vector = context.VectorInsert (vector, value, index); break; break;
case 3: vector = context.VectorInsert (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; return vector;

View file

@ -4,7 +4,6 @@ using ARMeilleure.Translation;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Reflection; using System.Reflection;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.Instructions.InstEmitSimdHelper; using static ARMeilleure.Instructions.InstEmitSimdHelper;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory; using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
@ -19,18 +18,13 @@ namespace ARMeilleure.Instructions
{ {
public static (int, int) GetQuadwordAndSubindex(int index, RegisterSize size) public static (int, int) GetQuadwordAndSubindex(int index, RegisterSize size)
{ {
switch (size) return size switch
{ {
case RegisterSize.Simd128: RegisterSize.Simd128 => (index >> 1, 0),
return (index >> 1, 0); RegisterSize.Simd64 or RegisterSize.Int64 => (index >> 1, index & 1),
case RegisterSize.Simd64: RegisterSize.Int32 => (index >> 2, index & 3),
case RegisterSize.Int64: _ => throw new ArgumentException("Unrecognized Vector Register Size."),
return (index >> 1, index & 1); };
case RegisterSize.Int32:
return (index >> 2, index & 3);
}
throw new ArgumentException("Unrecognized Vector Register Size.");
} }
public static Operand ExtractScalar(ArmEmitterContext context, OperandType type, int reg) 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. // 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); int index = reg & (doubleWidth ? 1 : 3);
if (index == 0) return target; if (index == 0)
{
return target;
}
if (doubleWidth) if (doubleWidth)
{ {
@ -1195,7 +1192,7 @@ namespace ARMeilleure.Instructions
: typeof(SoftFloat64).GetMethod(name); : typeof(SoftFloat64).GetMethod(name);
Array.Resize(ref callArgs, callArgs.Length + 1); Array.Resize(ref callArgs, callArgs.Length + 1);
callArgs[callArgs.Length - 1] = Const(1); callArgs[^1] = Const(1);
context.ExitArmFpMode(); context.ExitArmFpMode();
context.StoreToContext(); context.StoreToContext();
@ -1245,16 +1242,24 @@ namespace ARMeilleure.Instructions
{ {
switch (size) switch (size)
{ {
case 0: res = context.SignExtend8(OperandType.I32, res); break; case 0:
case 1: res = context.SignExtend16(OperandType.I32, res); break; res = context.SignExtend8(OperandType.I32, res);
break;
case 1:
res = context.SignExtend16(OperandType.I32, res);
break;
} }
} }
else else
{ {
switch (size) switch (size)
{ {
case 0: res = context.ZeroExtend8(OperandType.I32, res); break; case 0:
case 1: res = context.ZeroExtend16(OperandType.I32, res); break; 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.Decoders;
using ARMeilleure.IntermediateRepresentation; using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State; using ARMeilleure.State;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.Instructions.InstEmitSimdHelper; using static ARMeilleure.Instructions.InstEmitSimdHelper;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory; 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) public static Operand EmitExtractScalar(ArmEmitterContext context, Operand target, int reg, bool doubleWidth)
{ {
int index = reg & (doubleWidth ? 1 : 3); 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) if (doubleWidth)
{ {
@ -336,16 +337,17 @@ namespace ARMeilleure.Instructions
CmpCondition.GreaterThanOrEqual => Intrinsic.Arm64FcmgeVz, CmpCondition.GreaterThanOrEqual => Intrinsic.Arm64FcmgeVz,
CmpCondition.LessThan => Intrinsic.Arm64FcmltVz, CmpCondition.LessThan => Intrinsic.Arm64FcmltVz,
CmpCondition.LessThanOrEqual => Intrinsic.Arm64FcmleVz, CmpCondition.LessThanOrEqual => Intrinsic.Arm64FcmleVz,
_ => throw new InvalidOperationException() _ => throw new InvalidOperationException(),
}; };
} }
else { else
{
inst = cond switch inst = cond switch
{ {
CmpCondition.Equal => Intrinsic.Arm64FcmeqV, CmpCondition.Equal => Intrinsic.Arm64FcmeqV,
CmpCondition.GreaterThan => Intrinsic.Arm64FcmgtV, CmpCondition.GreaterThan => Intrinsic.Arm64FcmgtV,
CmpCondition.GreaterThanOrEqual => Intrinsic.Arm64FcmgeV, CmpCondition.GreaterThanOrEqual => Intrinsic.Arm64FcmgeV,
_ => throw new InvalidOperationException() _ => throw new InvalidOperationException(),
}; };
} }

View file

@ -695,7 +695,7 @@ namespace ARMeilleure.Instructions
{ {
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp; 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; Intrinsic inst = signalNaNs ? Intrinsic.Arm64FcmpeS : Intrinsic.Arm64FcmpS;

View file

@ -3,7 +3,6 @@ using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.Instructions.InstEmitSimdHelper; using static ARMeilleure.Instructions.InstEmitSimdHelper;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory; using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
@ -80,10 +79,11 @@ namespace ARMeilleure.Instructions
int eSize = 8 << op.Size; int eSize = 8 << op.Size;
Operand d = GetVec(op.Rd); Operand d = GetVec(op.Rd);
Operand imm = eSize switch { Operand imm = eSize switch
{
16 => X86GetAllElements(context, (short)~op.Immediate), 16 => X86GetAllElements(context, (short)~op.Immediate),
32 => X86GetAllElements(context, (int)~op.Immediate), 32 => X86GetAllElements(context, (int)~op.Immediate),
_ => throw new InvalidOperationException($"Invalid element size {eSize}.") _ => throw new InvalidOperationException($"Invalid element size {eSize}."),
}; };
Operand res = context.AddIntrinsic(Intrinsic.X86Pand, d, imm); Operand res = context.AddIntrinsic(Intrinsic.X86Pand, d, imm);
@ -380,10 +380,11 @@ namespace ARMeilleure.Instructions
int eSize = 8 << op.Size; int eSize = 8 << op.Size;
Operand d = GetVec(op.Rd); Operand d = GetVec(op.Rd);
Operand imm = eSize switch { Operand imm = eSize switch
{
16 => X86GetAllElements(context, (short)op.Immediate), 16 => X86GetAllElements(context, (short)op.Immediate),
32 => X86GetAllElements(context, (int)op.Immediate), 32 => X86GetAllElements(context, (int)op.Immediate),
_ => throw new InvalidOperationException($"Invalid element size {eSize}.") _ => throw new InvalidOperationException($"Invalid element size {eSize}."),
}; };
Operand res = context.AddIntrinsic(Intrinsic.X86Por, d, imm); Operand res = context.AddIntrinsic(Intrinsic.X86Por, d, imm);

View file

@ -52,9 +52,15 @@ namespace ARMeilleure.Instructions
// Replicate fields to fill the 64-bits, if size is < 64-bits. // Replicate fields to fill the 64-bits, if size is < 64-bits.
switch (op.Size) switch (op.Size)
{ {
case 0: immediate *= 0x0101010101010101L; break; case 0:
case 1: immediate *= 0x0001000100010001L; break; immediate *= 0x0101010101010101L;
case 2: immediate *= 0x0000000100000001L; break; break;
case 1:
immediate *= 0x0001000100010001L;
break;
case 2:
immediate *= 0x0000000100000001L;
break;
} }
Operand imm = Const(immediate); Operand imm = Const(immediate);
@ -199,9 +205,15 @@ namespace ARMeilleure.Instructions
// Replicate fields to fill the 64-bits, if size is < 64-bits. // Replicate fields to fill the 64-bits, if size is < 64-bits.
switch (op.Size) switch (op.Size)
{ {
case 0: immediate *= 0x0101010101010101L; break; case 0:
case 1: immediate *= 0x0001000100010001L; break; immediate *= 0x0101010101010101L;
case 2: immediate *= 0x0000000100000001L; break; break;
case 1:
immediate *= 0x0001000100010001L;
break;
case 2:
immediate *= 0x0000000100000001L;
break;
} }
Operand imm = Const(immediate); Operand imm = Const(immediate);

View file

@ -40,6 +40,7 @@ namespace ARMeilleure.Instructions
long offset = 0; long offset = 0;
#pragma warning disable IDE0055 // Disable formatting
for (int rep = 0; rep < op.Reps; rep++) for (int rep = 0; rep < op.Reps; rep++)
for (int elem = 0; elem < op.Elems; elem++) for (int elem = 0; elem < op.Elems; elem++)
for (int sElem = 0; sElem < op.SElems; sElem++) for (int sElem = 0; sElem < op.SElems; sElem++)
@ -66,6 +67,7 @@ namespace ARMeilleure.Instructions
offset += 1 << op.Size; offset += 1 << op.Size;
} }
#pragma warning restore IDE0055
if (op.WBack) if (op.WBack)
{ {

View file

@ -3,7 +3,6 @@ using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using static ARMeilleure.Instructions.InstEmitHelper; using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.Instructions.InstEmitSimdHelper; using static ARMeilleure.Instructions.InstEmitSimdHelper;
using static ARMeilleure.IntermediateRepresentation.Operand.Factory; using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
@ -16,13 +15,13 @@ namespace ARMeilleure.Instructions
private static readonly long[] _masksE0_Uzp = new long[] private static readonly long[] _masksE0_Uzp = new long[]
{ {
13L << 56 | 09L << 48 | 05L << 40 | 01L << 32 | 12L << 24 | 08L << 16 | 04L << 8 | 00L << 0, 13L << 56 | 09L << 48 | 05L << 40 | 01L << 32 | 12L << 24 | 08L << 16 | 04L << 8 | 00L << 0,
11L << 56 | 10L << 48 | 03L << 40 | 02L << 32 | 09L << 24 | 08L << 16 | 01L << 8 | 00L << 0 11L << 56 | 10L << 48 | 03L << 40 | 02L << 32 | 09L << 24 | 08L << 16 | 01L << 8 | 00L << 0,
}; };
private static readonly long[] _masksE1_Uzp = new long[] private static readonly long[] _masksE1_Uzp = new long[]
{ {
15L << 56 | 11L << 48 | 07L << 40 | 03L << 32 | 14L << 24 | 10L << 16 | 06L << 8 | 02L << 0, 15L << 56 | 11L << 48 | 07L << 40 | 03L << 32 | 14L << 24 | 10L << 16 | 06L << 8 | 02L << 0,
15L << 56 | 14L << 48 | 07L << 40 | 06L << 32 | 13L << 24 | 12L << 16 | 05L << 8 | 04L << 0 15L << 56 | 14L << 48 | 07L << 40 | 06L << 32 | 13L << 24 | 12L << 16 | 05L << 8 | 04L << 0,
}; };
#endregion #endregion
@ -36,9 +35,17 @@ namespace ARMeilleure.Instructions
{ {
switch (op.Size) switch (op.Size)
{ {
case 0: n = context.ZeroExtend8 (n.Type, n); n = context.Multiply(n, Const(n.Type, 0x01010101)); break; case 0:
case 1: n = context.ZeroExtend16(n.Type, n); n = context.Multiply(n, Const(n.Type, 0x00010001)); break; n = context.ZeroExtend8(n.Type, n);
case 2: n = context.ZeroExtend32(n.Type, n); break; n = context.Multiply(n, Const(n.Type, 0x01010101));
break;
case 1:
n = context.ZeroExtend16(n.Type, n);
n = context.Multiply(n, Const(n.Type, 0x00010001));
break;
case 2:
n = context.ZeroExtend32(n.Type, n);
break;
} }
Operand res = context.VectorInsert(context.VectorZero(), n, 0); Operand res = context.VectorInsert(context.VectorZero(), n, 0);
@ -497,8 +504,12 @@ namespace ARMeilleure.Instructions
switch (op.Size) switch (op.Size)
{ {
case 0: imm *= 0x01010101; break; case 0:
case 1: imm *= 0x00010001; break; imm *= 0x01010101;
break;
case 1:
imm *= 0x00010001;
break;
} }
if (not) if (not)
@ -590,7 +601,7 @@ namespace ARMeilleure.Instructions
{ {
Operand d = GetVec(op.Rd); Operand d = GetVec(op.Rd);
List<Operand> args = new List<Operand>(); List<Operand> args = new();
if (!isTbl) if (!isTbl)
{ {
@ -612,20 +623,36 @@ namespace ARMeilleure.Instructions
{ {
switch (op.Size) switch (op.Size)
{ {
case 1: info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl1)); break; case 1:
case 2: info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl2)); break; info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl1));
case 3: info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl3)); break; break;
case 4: info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl4)); break; case 2:
info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl2));
break;
case 3:
info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl3));
break;
case 4:
info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbl4));
break;
} }
} }
else else
{ {
switch (op.Size) switch (op.Size)
{ {
case 1: info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx1)); break; case 1:
case 2: info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx2)); break; info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx1));
case 3: info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx3)); break; break;
case 4: info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx4)); break; case 2:
info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx2));
break;
case 3:
info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx3));
break;
case 4:
info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Tbx4));
break;
} }
} }

Some files were not shown because too many files have changed in this diff Show more