[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

@ -5,22 +5,22 @@ namespace ARMeilleure.CodeGen.Arm64
{ {
enum ArmCondition enum ArmCondition
{ {
Eq = 0, Eq = 0,
Ne = 1, Ne = 1,
GeUn = 2, GeUn = 2,
LtUn = 3, LtUn = 3,
Mi = 4, Mi = 4,
Pl = 5, Pl = 5,
Vs = 6, Vs = 6,
Vc = 7, Vc = 7,
GtUn = 8, GtUn = 8,
LeUn = 9, LeUn = 9,
Ge = 10, Ge = 10,
Lt = 11, Lt = 11,
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

@ -188,7 +188,7 @@ namespace ARMeilleure.CodeGen.Arm64
uint rmode = topHalf ? 1u << 19 : 0u; uint rmode = topHalf ? 1u << 19 : 0u;
uint ftype = rd.Type == OperandType.FP64 || rn.Type == OperandType.FP64 ? 1u << 22 : 0u; uint ftype = rd.Type == OperandType.FP64 || rn.Type == OperandType.FP64 ? 1u << 22 : 0u;
uint sf = rd.Type == OperandType.I64 || rn.Type == OperandType.I64 ? SfFlag : 0u; uint sf = rd.Type == OperandType.I64 || rn.Type == OperandType.I64 ? SfFlag : 0u;
WriteUInt32(0x1e260000u | (opcode << 16) | rmode | ftype | sf | EncodeReg(rd) | (EncodeReg(rn) << 5)); WriteUInt32(0x1e260000u | (opcode << 16) | rmode | ftype | sf | EncodeReg(rd) | (EncodeReg(rn) << 5));
} }
@ -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);
@ -48,7 +48,7 @@ namespace ARMeilleure.CodeGen.Arm64
Add(Instruction.BranchIf, GenerateBranchIf); Add(Instruction.BranchIf, GenerateBranchIf);
Add(Instruction.ByteSwap, GenerateByteSwap); Add(Instruction.ByteSwap, GenerateByteSwap);
Add(Instruction.Call, GenerateCall); Add(Instruction.Call, GenerateCall);
//Add(Instruction.Clobber, GenerateClobber); // Add(Instruction.Clobber, GenerateClobber);
Add(Instruction.Compare, GenerateCompare); Add(Instruction.Compare, GenerateCompare);
Add(Instruction.CompareAndSwap, GenerateCompareAndSwap); Add(Instruction.CompareAndSwap, GenerateCompareAndSwap);
Add(Instruction.CompareAndSwap16, GenerateCompareAndSwap16); Add(Instruction.CompareAndSwap16, GenerateCompareAndSwap16);
@ -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);
@ -292,7 +293,7 @@ namespace ARMeilleure.CodeGen.Arm64
private static void GenerateBitwiseNot(CodeGenContext context, Operation operation) private static void GenerateBitwiseNot(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
ValidateUnOp(dest, source); ValidateUnOp(dest, source);
@ -330,7 +331,7 @@ namespace ARMeilleure.CodeGen.Arm64
private static void GenerateByteSwap(CodeGenContext context, Operation operation) private static void GenerateByteSwap(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
ValidateUnOp(dest, source); ValidateUnOp(dest, source);
@ -364,15 +365,15 @@ namespace ARMeilleure.CodeGen.Arm64
{ {
if (operation.SourcesCount == 5) // CompareAndSwap128 has 5 sources, compared to CompareAndSwap64/32's 3. if (operation.SourcesCount == 5) // CompareAndSwap128 has 5 sources, compared to CompareAndSwap64/32's 3.
{ {
Operand actualLow = operation.GetDestination(0); Operand actualLow = operation.GetDestination(0);
Operand actualHigh = operation.GetDestination(1); Operand actualHigh = operation.GetDestination(1);
Operand temp0 = operation.GetDestination(2); Operand temp0 = operation.GetDestination(2);
Operand temp1 = operation.GetDestination(3); Operand temp1 = operation.GetDestination(3);
Operand address = operation.GetSource(0); Operand address = operation.GetSource(0);
Operand expectedLow = operation.GetSource(1); Operand expectedLow = operation.GetSource(1);
Operand expectedHigh = operation.GetSource(2); Operand expectedHigh = operation.GetSource(2);
Operand desiredLow = operation.GetSource(3); Operand desiredLow = operation.GetSource(3);
Operand desiredHigh = operation.GetSource(4); Operand desiredHigh = operation.GetSource(4);
GenerateAtomicDcas( GenerateAtomicDcas(
context, context,
@ -388,11 +389,11 @@ namespace ARMeilleure.CodeGen.Arm64
} }
else else
{ {
Operand actual = operation.GetDestination(0); Operand actual = operation.GetDestination(0);
Operand result = operation.GetDestination(1); Operand result = operation.GetDestination(1);
Operand address = operation.GetSource(0); Operand address = operation.GetSource(0);
Operand expected = operation.GetSource(1); Operand expected = operation.GetSource(1);
Operand desired = operation.GetSource(2); Operand desired = operation.GetSource(2);
GenerateAtomicCas(context, address, expected, desired, actual, result, AccessSize.Auto); GenerateAtomicCas(context, address, expected, desired, actual, result, AccessSize.Auto);
} }
@ -400,22 +401,22 @@ namespace ARMeilleure.CodeGen.Arm64
private static void GenerateCompareAndSwap16(CodeGenContext context, Operation operation) private static void GenerateCompareAndSwap16(CodeGenContext context, Operation operation)
{ {
Operand actual = operation.GetDestination(0); Operand actual = operation.GetDestination(0);
Operand result = operation.GetDestination(1); Operand result = operation.GetDestination(1);
Operand address = operation.GetSource(0); Operand address = operation.GetSource(0);
Operand expected = operation.GetSource(1); Operand expected = operation.GetSource(1);
Operand desired = operation.GetSource(2); Operand desired = operation.GetSource(2);
GenerateAtomicCas(context, address, expected, desired, actual, result, AccessSize.Hword); GenerateAtomicCas(context, address, expected, desired, actual, result, AccessSize.Hword);
} }
private static void GenerateCompareAndSwap8(CodeGenContext context, Operation operation) private static void GenerateCompareAndSwap8(CodeGenContext context, Operation operation)
{ {
Operand actual = operation.GetDestination(0); Operand actual = operation.GetDestination(0);
Operand result = operation.GetDestination(1); Operand result = operation.GetDestination(1);
Operand address = operation.GetSource(0); Operand address = operation.GetSource(0);
Operand expected = operation.GetSource(1); Operand expected = operation.GetSource(1);
Operand desired = operation.GetSource(2); Operand desired = operation.GetSource(2);
GenerateAtomicCas(context, address, expected, desired, actual, result, AccessSize.Byte); GenerateAtomicCas(context, address, expected, desired, actual, result, AccessSize.Byte);
} }
@ -444,13 +445,13 @@ namespace ARMeilleure.CodeGen.Arm64
Debug.Assert(dest.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger());
Debug.Assert(src1.Type == OperandType.I32); Debug.Assert(src1.Type == OperandType.I32);
context.Assembler.Cmp (src1, Const(src1.Type, 0)); context.Assembler.Cmp(src1, Const(src1.Type, 0));
context.Assembler.Csel(dest, src2, src3, ArmCondition.Ne); context.Assembler.Csel(dest, src2, src3, ArmCondition.Ne);
} }
private static void GenerateConvertI64ToI32(CodeGenContext context, Operation operation) private static void GenerateConvertI64ToI32(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type == OperandType.I32 && source.Type == OperandType.I64); Debug.Assert(dest.Type == OperandType.I32 && source.Type == OperandType.I64);
@ -460,7 +461,7 @@ namespace ARMeilleure.CodeGen.Arm64
private static void GenerateConvertToFP(CodeGenContext context, Operation operation) private static void GenerateConvertToFP(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type == OperandType.FP32 || dest.Type == OperandType.FP64); Debug.Assert(dest.Type == OperandType.FP32 || dest.Type == OperandType.FP64);
@ -479,7 +480,7 @@ namespace ARMeilleure.CodeGen.Arm64
private static void GenerateConvertToFPUI(CodeGenContext context, Operation operation) private static void GenerateConvertToFPUI(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type == OperandType.FP32 || dest.Type == OperandType.FP64); Debug.Assert(dest.Type == OperandType.FP32 || dest.Type == OperandType.FP64);
@ -491,7 +492,7 @@ namespace ARMeilleure.CodeGen.Arm64
private static void GenerateCopy(CodeGenContext context, Operation operation) private static void GenerateCopy(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
EnsureSameType(dest, source); EnsureSameType(dest, source);
@ -523,7 +524,7 @@ namespace ARMeilleure.CodeGen.Arm64
private static void GenerateCountLeadingZeros(CodeGenContext context, Operation operation) private static void GenerateCountLeadingZeros(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
EnsureSameType(dest, source); EnsureSameType(dest, source);
@ -535,9 +536,9 @@ namespace ARMeilleure.CodeGen.Arm64
private static void GenerateDivide(CodeGenContext context, Operation operation) private static void GenerateDivide(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand dividend = operation.GetSource(0); Operand dividend = operation.GetSource(0);
Operand divisor = operation.GetSource(1); Operand divisor = operation.GetSource(1);
ValidateBinOp(dest, dividend, divisor); ValidateBinOp(dest, dividend, divisor);
@ -553,9 +554,9 @@ namespace ARMeilleure.CodeGen.Arm64
private static void GenerateDivideUI(CodeGenContext context, Operation operation) private static void GenerateDivideUI(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand dividend = operation.GetSource(0); Operand dividend = operation.GetSource(0);
Operand divisor = operation.GetSource(1); Operand divisor = operation.GetSource(1);
ValidateBinOp(dest, dividend, divisor); ValidateBinOp(dest, dividend, divisor);
@ -564,7 +565,7 @@ namespace ARMeilleure.CodeGen.Arm64
private static void GenerateLoad(CodeGenContext context, Operation operation) private static void GenerateLoad(CodeGenContext context, Operation operation)
{ {
Operand value = operation.Destination; Operand value = operation.Destination;
Operand address = operation.GetSource(0); Operand address = operation.GetSource(0);
context.Assembler.Ldr(value, address); context.Assembler.Ldr(value, address);
@ -572,7 +573,7 @@ namespace ARMeilleure.CodeGen.Arm64
private static void GenerateLoad16(CodeGenContext context, Operation operation) private static void GenerateLoad16(CodeGenContext context, Operation operation)
{ {
Operand value = operation.Destination; Operand value = operation.Destination;
Operand address = operation.GetSource(0); Operand address = operation.GetSource(0);
Debug.Assert(value.Type.IsInteger()); Debug.Assert(value.Type.IsInteger());
@ -582,7 +583,7 @@ namespace ARMeilleure.CodeGen.Arm64
private static void GenerateLoad8(CodeGenContext context, Operation operation) private static void GenerateLoad8(CodeGenContext context, Operation operation)
{ {
Operand value = operation.Destination; Operand value = operation.Destination;
Operand address = operation.GetSource(0); Operand address = operation.GetSource(0);
Debug.Assert(value.Type.IsInteger()); Debug.Assert(value.Type.IsInteger());
@ -641,7 +642,7 @@ namespace ARMeilleure.CodeGen.Arm64
private static void GenerateNegate(CodeGenContext context, Operation operation) private static void GenerateNegate(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
ValidateUnOp(dest, source); ValidateUnOp(dest, source);
@ -728,7 +729,7 @@ namespace ARMeilleure.CodeGen.Arm64
private static void GenerateSignExtend16(CodeGenContext context, Operation operation) private static void GenerateSignExtend16(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
@ -738,7 +739,7 @@ namespace ARMeilleure.CodeGen.Arm64
private static void GenerateSignExtend32(CodeGenContext context, Operation operation) private static void GenerateSignExtend32(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
@ -748,7 +749,7 @@ namespace ARMeilleure.CodeGen.Arm64
private static void GenerateSignExtend8(CodeGenContext context, Operation operation) private static void GenerateSignExtend8(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
@ -758,7 +759,7 @@ namespace ARMeilleure.CodeGen.Arm64
private static void GenerateFill(CodeGenContext context, Operation operation) private static void GenerateFill(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand offset = operation.GetSource(0); Operand offset = operation.GetSource(0);
Debug.Assert(offset.Kind == OperandKind.Constant); Debug.Assert(offset.Kind == OperandKind.Constant);
@ -799,7 +800,7 @@ namespace ARMeilleure.CodeGen.Arm64
private static void GenerateStackAlloc(CodeGenContext context, Operation operation) private static void GenerateStackAlloc(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand offset = operation.GetSource(0); Operand offset = operation.GetSource(0);
Debug.Assert(offset.Kind == OperandKind.Constant); Debug.Assert(offset.Kind == OperandKind.Constant);
@ -811,7 +812,7 @@ namespace ARMeilleure.CodeGen.Arm64
private static void GenerateStore(CodeGenContext context, Operation operation) private static void GenerateStore(CodeGenContext context, Operation operation)
{ {
Operand value = operation.GetSource(1); Operand value = operation.GetSource(1);
Operand address = operation.GetSource(0); Operand address = operation.GetSource(0);
context.Assembler.Str(value, address); context.Assembler.Str(value, address);
@ -819,7 +820,7 @@ namespace ARMeilleure.CodeGen.Arm64
private static void GenerateStore16(CodeGenContext context, Operation operation) private static void GenerateStore16(CodeGenContext context, Operation operation)
{ {
Operand value = operation.GetSource(1); Operand value = operation.GetSource(1);
Operand address = operation.GetSource(0); Operand address = operation.GetSource(0);
Debug.Assert(value.Type.IsInteger()); Debug.Assert(value.Type.IsInteger());
@ -829,7 +830,7 @@ namespace ARMeilleure.CodeGen.Arm64
private static void GenerateStore8(CodeGenContext context, Operation operation) private static void GenerateStore8(CodeGenContext context, Operation operation)
{ {
Operand value = operation.GetSource(1); Operand value = operation.GetSource(1);
Operand address = operation.GetSource(0); Operand address = operation.GetSource(0);
Debug.Assert(value.Type.IsInteger()); Debug.Assert(value.Type.IsInteger());
@ -876,7 +877,7 @@ namespace ARMeilleure.CodeGen.Arm64
private static void GenerateVectorCreateScalar(CodeGenContext context, Operation operation) private static void GenerateVectorCreateScalar(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
if (dest != default) if (dest != default)
@ -1022,7 +1023,7 @@ namespace ARMeilleure.CodeGen.Arm64
private static void GenerateVectorZeroUpper64(CodeGenContext context, Operation operation) private static void GenerateVectorZeroUpper64(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type == OperandType.V128 && source.Type == OperandType.V128); Debug.Assert(dest.Type == OperandType.V128 && source.Type == OperandType.V128);
@ -1032,7 +1033,7 @@ namespace ARMeilleure.CodeGen.Arm64
private static void GenerateVectorZeroUpper96(CodeGenContext context, Operation operation) private static void GenerateVectorZeroUpper96(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type == OperandType.V128 && source.Type == OperandType.V128); Debug.Assert(dest.Type == OperandType.V128 && source.Type == OperandType.V128);
@ -1042,7 +1043,7 @@ namespace ARMeilleure.CodeGen.Arm64
private static void GenerateZeroExtend16(CodeGenContext context, Operation operation) private static void GenerateZeroExtend16(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
@ -1052,7 +1053,7 @@ namespace ARMeilleure.CodeGen.Arm64
private static void GenerateZeroExtend32(CodeGenContext context, Operation operation) private static void GenerateZeroExtend32(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
@ -1068,7 +1069,7 @@ namespace ARMeilleure.CodeGen.Arm64
private static void GenerateZeroExtend8(CodeGenContext context, Operation operation) private static void GenerateZeroExtend8(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
@ -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;
@ -35,7 +32,7 @@ namespace ARMeilleure.CodeGen.Arm64
} }
} }
#region Linux #region Linux
private const ulong AT_HWCAP = 16; private const ulong AT_HWCAP = 16;
private const ulong AT_HWCAP2 = 26; private const ulong AT_HWCAP2 = 26;
@ -46,88 +43,88 @@ namespace ARMeilleure.CodeGen.Arm64
[Flags] [Flags]
public enum LinuxFeatureFlagsHwCap : ulong public enum LinuxFeatureFlagsHwCap : ulong
{ {
Fp = 1 << 0, Fp = 1 << 0,
Asimd = 1 << 1, Asimd = 1 << 1,
Evtstrm = 1 << 2, Evtstrm = 1 << 2,
Aes = 1 << 3, Aes = 1 << 3,
Pmull = 1 << 4, Pmull = 1 << 4,
Sha1 = 1 << 5, Sha1 = 1 << 5,
Sha2 = 1 << 6, Sha2 = 1 << 6,
Crc32 = 1 << 7, Crc32 = 1 << 7,
Atomics = 1 << 8, Atomics = 1 << 8,
FpHp = 1 << 9, FpHp = 1 << 9,
AsimdHp = 1 << 10, AsimdHp = 1 << 10,
CpuId = 1 << 11, CpuId = 1 << 11,
AsimdRdm = 1 << 12, AsimdRdm = 1 << 12,
Jscvt = 1 << 13, Jscvt = 1 << 13,
Fcma = 1 << 14, Fcma = 1 << 14,
Lrcpc = 1 << 15, Lrcpc = 1 << 15,
DcpOp = 1 << 16, DcpOp = 1 << 16,
Sha3 = 1 << 17, Sha3 = 1 << 17,
Sm3 = 1 << 18, Sm3 = 1 << 18,
Sm4 = 1 << 19, Sm4 = 1 << 19,
AsimdDp = 1 << 20, AsimdDp = 1 << 20,
Sha512 = 1 << 21, Sha512 = 1 << 21,
Sve = 1 << 22, Sve = 1 << 22,
AsimdFhm = 1 << 23, AsimdFhm = 1 << 23,
Dit = 1 << 24, Dit = 1 << 24,
Uscat = 1 << 25, Uscat = 1 << 25,
Ilrcpc = 1 << 26, Ilrcpc = 1 << 26,
FlagM = 1 << 27, FlagM = 1 << 27,
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]
public enum LinuxFeatureFlagsHwCap2 : ulong public enum LinuxFeatureFlagsHwCap2 : ulong
{ {
Dcpodp = 1 << 0, Dcpodp = 1 << 0,
Sve2 = 1 << 1, Sve2 = 1 << 1,
SveAes = 1 << 2, SveAes = 1 << 2,
SvePmull = 1 << 3, SvePmull = 1 << 3,
SveBitperm = 1 << 4, SveBitperm = 1 << 4,
SveSha3 = 1 << 5, SveSha3 = 1 << 5,
SveSm4 = 1 << 6, SveSm4 = 1 << 6,
FlagM2 = 1 << 7, FlagM2 = 1 << 7,
Frint = 1 << 8, Frint = 1 << 8,
SveI8mm = 1 << 9, SveI8mm = 1 << 9,
SveF32mm = 1 << 10, SveF32mm = 1 << 10,
SveF64mm = 1 << 11, SveF64mm = 1 << 11,
SveBf16 = 1 << 12, SveBf16 = 1 << 12,
I8mm = 1 << 13, I8mm = 1 << 13,
Bf16 = 1 << 14, Bf16 = 1 << 14,
Dgh = 1 << 15, Dgh = 1 << 15,
Rng = 1 << 16, Rng = 1 << 16,
Bti = 1 << 17, Bti = 1 << 17,
Mte = 1 << 18, Mte = 1 << 18,
Ecv = 1 << 19, Ecv = 1 << 19,
Afp = 1 << 20, Afp = 1 << 20,
Rpres = 1 << 21, Rpres = 1 << 21,
Mte3 = 1 << 22, Mte3 = 1 << 22,
Sme = 1 << 23, Sme = 1 << 23,
Sme_i16i64 = 1 << 24, Sme_i16i64 = 1 << 24,
Sme_f64f64 = 1 << 25, Sme_f64f64 = 1 << 25,
Sme_i8i32 = 1 << 26, Sme_i8i32 = 1 << 26,
Sme_f16f32 = 1 << 27, Sme_f16f32 = 1 << 27,
Sme_b16f32 = 1 << 28, Sme_b16f32 = 1 << 28,
Sme_f32f32 = 1 << 29, Sme_f32f32 = 1 << 29,
Sme_fa64 = 1 << 30, Sme_fa64 = 1 << 30,
Wfxt = 1UL << 31, Wfxt = 1UL << 31,
Ebf16 = 1UL << 32, Ebf16 = 1UL << 32,
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;
public static LinuxFeatureFlagsHwCap2 LinuxFeatureInfoHwCap2 { get; } = 0; public static LinuxFeatureFlagsHwCap2 LinuxFeatureInfoHwCap2 { get; } = 0;
#endregion #endregion
#region macOS #region macOS
[LibraryImport("libSystem.dylib", SetLastError = true)] [LibraryImport("libSystem.dylib", SetLastError = true)]
private static unsafe partial int sysctlbyname([MarshalAs(UnmanagedType.LPStr)] string name, out int oldValue, ref ulong oldSize, IntPtr newValue, ulong newValueSize); private static unsafe partial int sysctlbyname([MarshalAs(UnmanagedType.LPStr)] string name, out int oldValue, ref ulong oldSize, IntPtr newValue, ulong newValueSize);
@ -143,7 +140,7 @@ namespace ARMeilleure.CodeGen.Arm64
return false; 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,26 +150,26 @@ 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]
public enum MacOsFeatureFlags public enum MacOsFeatureFlags
{ {
Fp = 1 << 0, Fp = 1 << 0,
AdvSimd = 1 << 1, AdvSimd = 1 << 1,
Fp16 = 1 << 2, Fp16 = 1 << 2,
Aes = 1 << 3, Aes = 1 << 3,
Pmull = 1 << 4, Pmull = 1 << 4,
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;
#endregion #endregion
public static bool SupportsAdvSimd => LinuxFeatureInfoHwCap.HasFlag(LinuxFeatureFlagsHwCap.Asimd) || MacOsFeatureInfo.HasFlag(MacOsFeatureFlags.AdvSimd); public static bool SupportsAdvSimd => LinuxFeatureInfoHwCap.HasFlag(LinuxFeatureFlagsHwCap.Asimd) || MacOsFeatureInfo.HasFlag(MacOsFeatureFlags.AdvSimd);
public static bool SupportsAes => LinuxFeatureInfoHwCap.HasFlag(LinuxFeatureFlagsHwCap.Aes) || MacOsFeatureInfo.HasFlag(MacOsFeatureFlags.Aes); public static bool SupportsAes => LinuxFeatureInfoHwCap.HasFlag(LinuxFeatureFlagsHwCap.Aes) || MacOsFeatureInfo.HasFlag(MacOsFeatureFlags.Aes);

View file

@ -1,8 +1,8 @@
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; }
public IntrinsicInfo(uint inst, IntrinsicType type) public IntrinsicInfo(uint inst, IntrinsicType type)

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;
@ -302,10 +298,10 @@ namespace ARMeilleure.CodeGen.Arm64
if (source.Type == OperandType.V128 && passOnReg) if (source.Type == OperandType.V128 && passOnReg)
{ {
// V128 is a struct, we pass each half on a GPR if possible. // V128 is a struct, we pass each half on a GPR if possible.
Operand argReg = Gpr(CallingConvention.GetIntArgumentRegister(intCount++), OperandType.I64); Operand argReg = Gpr(CallingConvention.GetIntArgumentRegister(intCount++), OperandType.I64);
Operand argReg2 = Gpr(CallingConvention.GetIntArgumentRegister(intCount++), OperandType.I64); Operand argReg2 = Gpr(CallingConvention.GetIntArgumentRegister(intCount++), OperandType.I64);
nodes.AddBefore(node, Operation(Instruction.VectorExtract, argReg, source, Const(0))); nodes.AddBefore(node, Operation(Instruction.VectorExtract, argReg, source, Const(0)));
nodes.AddBefore(node, Operation(Instruction.VectorExtract, argReg2, source, Const(1))); nodes.AddBefore(node, Operation(Instruction.VectorExtract, argReg2, source, Const(1)));
continue; continue;
@ -339,7 +335,7 @@ namespace ARMeilleure.CodeGen.Arm64
{ {
if (dest.Type == OperandType.V128) if (dest.Type == OperandType.V128)
{ {
Operand retLReg = Gpr(CallingConvention.GetIntReturnRegister(), OperandType.I64); Operand retLReg = Gpr(CallingConvention.GetIntReturnRegister(), OperandType.I64);
Operand retHReg = Gpr(CallingConvention.GetIntReturnRegisterHigh(), OperandType.I64); Operand retHReg = Gpr(CallingConvention.GetIntReturnRegisterHigh(), OperandType.I64);
node = nodes.AddAfter(node, Operation(Instruction.VectorCreateScalar, dest, retLReg)); node = nodes.AddAfter(node, Operation(Instruction.VectorCreateScalar, dest, retLReg));
@ -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;
@ -403,7 +397,7 @@ namespace ARMeilleure.CodeGen.Arm64
if (source.Type == OperandType.V128 && passOnReg) if (source.Type == OperandType.V128 && passOnReg)
{ {
// V128 is a struct, we pass each half on a GPR if possible. // V128 is a struct, we pass each half on a GPR if possible.
Operand argReg = Gpr(CallingConvention.GetIntArgumentRegister(intCount++), OperandType.I64); Operand argReg = Gpr(CallingConvention.GetIntArgumentRegister(intCount++), OperandType.I64);
Operand argReg2 = Gpr(CallingConvention.GetIntArgumentRegister(intCount++), OperandType.I64); Operand argReg2 = Gpr(CallingConvention.GetIntArgumentRegister(intCount++), OperandType.I64);
nodes.AddBefore(node, Operation(Instruction.VectorExtract, argReg, source, Const(0))); nodes.AddBefore(node, Operation(Instruction.VectorExtract, argReg, source, Const(0)));
@ -519,7 +513,7 @@ namespace ARMeilleure.CodeGen.Arm64
if (source.Type == OperandType.V128) if (source.Type == OperandType.V128)
{ {
Operand retLReg = Gpr(CallingConvention.GetIntReturnRegister(), OperandType.I64); Operand retLReg = Gpr(CallingConvention.GetIntReturnRegister(), OperandType.I64);
Operand retHReg = Gpr(CallingConvention.GetIntReturnRegisterHigh(), OperandType.I64); Operand retHReg = Gpr(CallingConvention.GetIntReturnRegisterHigh(), OperandType.I64);
nodes.AddBefore(node, Operation(Instruction.VectorExtract, retLReg, source, Const(0))); nodes.AddBefore(node, Operation(Instruction.VectorExtract, retLReg, source, Const(0)));

View file

@ -35,9 +35,9 @@ namespace ARMeilleure.CodeGen
/// <param name="relocInfo">Relocation info</param> /// <param name="relocInfo">Relocation info</param>
internal CompiledFunction(byte[] code, UnwindInfo unwindInfo, RelocInfo relocInfo) internal CompiledFunction(byte[] code, UnwindInfo unwindInfo, RelocInfo relocInfo)
{ {
Code = code; Code = code;
UnwindInfo = unwindInfo; UnwindInfo = unwindInfo;
RelocInfo = relocInfo; RelocInfo = relocInfo;
} }
/// <summary> /// <summary>

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

@ -164,7 +164,7 @@ namespace ARMeilleure.CodeGen.Optimizations
} }
break; break;
case Instruction.Multiply: case Instruction.Multiply:
if (type == OperandType.I32) if (type == OperandType.I32)
{ {
EvaluateBinaryI32(operation, (x, y) => x * y); EvaluateBinaryI32(operation, (x, y) => x * y);

View file

@ -182,7 +182,7 @@ namespace ARMeilleure.CodeGen.Optimizations
private static void PropagateCopy(ref Span<Operation> buffer, Operation copyOp) private static void PropagateCopy(ref Span<Operation> buffer, Operation copyOp)
{ {
// Propagate copy source operand to all uses of the destination operand. // Propagate copy source operand to all uses of the destination operand.
Operand dest = copyOp.Destination; Operand dest = copyOp.Destination;
Operand source = copyOp.GetSource(0); Operand source = copyOp.GetSource(0);
Span<Operation> uses = dest.GetUses(ref buffer); Span<Operation> uses = dest.GetUses(ref buffer);

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

@ -4,7 +4,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{ {
public int IntUsedRegisters { get; } public int IntUsedRegisters { get; }
public int VecUsedRegisters { get; } public int VecUsedRegisters { get; }
public int SpillRegionSize { get; } public int SpillRegionSize { get; }
public AllocationResult( public AllocationResult(
int intUsedRegisters, int intUsedRegisters,
@ -13,7 +13,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{ {
IntUsedRegisters = intUsedRegisters; IntUsedRegisters = intUsedRegisters;
VecUsedRegisters = vecUsedRegisters; VecUsedRegisters = vecUsedRegisters;
SpillRegionSize = spillRegionSize; SpillRegionSize = spillRegionSize;
} }
} }
} }

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;
@ -13,16 +12,16 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{ {
private readonly struct Copy private readonly struct Copy
{ {
public Register Dest { get; } public Register Dest { get; }
public Register Source { get; } public Register Source { get; }
public OperandType Type { get; } public OperandType Type { get; }
public Copy(Register dest, Register source, OperandType type) public Copy(Register dest, Register source, OperandType type)
{ {
Dest = dest; Dest = dest;
Source = source; Source = source;
Type = type; Type = type;
} }
} }
@ -42,19 +41,19 @@ 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)
{ {
locations[copy.Source] = copy.Source; locations[copy.Source] = copy.Source;
sources[copy.Dest] = copy.Source; sources[copy.Dest] = copy.Source;
types[copy.Dest] = copy.Type; types[copy.Dest] = copy.Type;
pendingQueue.Enqueue(copy.Dest); pendingQueue.Enqueue(copy.Dest);
} }
@ -91,7 +90,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
} }
} }
copyDest = current; copyDest = current;
origSource = sources[copyDest]; origSource = sources[copyDest];
copySource = locations[origSource]; copySource = locations[origSource];
@ -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

@ -20,7 +20,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
public BlockInfo(bool hasCall, int intFixedRegisters, int vecFixedRegisters) public BlockInfo(bool hasCall, int intFixedRegisters, int vecFixedRegisters)
{ {
HasCall = hasCall; HasCall = hasCall;
IntFixedRegisters = intFixedRegisters; IntFixedRegisters = intFixedRegisters;
VecFixedRegisters = vecFixedRegisters; VecFixedRegisters = vecFixedRegisters;
} }
@ -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)
{ {
@ -53,7 +53,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
SpillOffset = default; SpillOffset = default;
_first = -1; _first = -1;
_last = -1; _last = -1;
SetBlockIndex(blkIndex); SetBlockIndex(blkIndex);
} }
@ -348,17 +348,17 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
if (dest.Type.IsInteger()) if (dest.Type.IsInteger())
{ {
intLocalFreeRegisters &= ~(1 << selectedReg); intLocalFreeRegisters &= ~(1 << selectedReg);
intUsedRegisters |= 1 << selectedReg; intUsedRegisters |= 1 << selectedReg;
} }
else else
{ {
vecLocalFreeRegisters &= ~(1 << selectedReg); vecLocalFreeRegisters &= ~(1 << selectedReg);
vecUsedRegisters |= 1 << selectedReg; vecUsedRegisters |= 1 << selectedReg;
} }
} }
else else
{ {
info.Register = default; info.Register = default;
info.SpillOffset = Const(stackAlloc.Allocate(dest.Type.GetSizeInBytes())); info.SpillOffset = Const(stackAlloc.Allocate(dest.Type.GetSizeInBytes()));
} }
} }
@ -382,7 +382,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
: GetSpillTemp(dest, vecSpillTempRegisters, ref vecLocalAsg); : GetSpillTemp(dest, vecSpillTempRegisters, ref vecLocalAsg);
info.Sequence = sequence; info.Sequence = sequence;
info.Temp = temp; info.Temp = temp;
} }
dest = temp; dest = temp;
@ -408,7 +408,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private static int SelectSpillTemps(int mask0, int mask1) private static int SelectSpillTemps(int mask0, int mask1)
{ {
int selection = 0; int selection = 0;
int count = 0; int count = 0;
while (count < MaxIROperands && mask0 != 0) while (count < MaxIROperands && mask0 != 0)
{ {

View file

@ -14,7 +14,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
// http://www.christianwimmer.at/Publications/Wimmer04a/Wimmer04a.pdf // http://www.christianwimmer.at/Publications/Wimmer04a/Wimmer04a.pdf
class LinearScanAllocator : IRegisterAllocator class LinearScanAllocator : IRegisterAllocator
{ {
private const int InstructionGap = 2; private const int InstructionGap = 2;
private const int InstructionGapMask = InstructionGap - 1; private const int InstructionGapMask = InstructionGap - 1;
private HashSet<int> _blockEdges; private HashSet<int> _blockEdges;
@ -33,7 +33,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
public StackAllocator StackAlloc { get; } public StackAllocator StackAlloc { get; }
public BitMap Active { get; } public BitMap Active { get; }
public BitMap Inactive { get; } public BitMap Inactive { get; }
public int IntUsedRegisters { get; set; } public int IntUsedRegisters { get; set; }
@ -47,9 +47,9 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
public AllocationContext(StackAllocator stackAlloc, RegisterMasks masks, int intervalsCount) public AllocationContext(StackAllocator stackAlloc, RegisterMasks masks, int intervalsCount)
{ {
StackAlloc = stackAlloc; StackAlloc = stackAlloc;
Masks = masks; Masks = masks;
Active = new BitMap(Allocators.Default, intervalsCount); Active = new BitMap(Allocators.Default, intervalsCount);
Inactive = new BitMap(Allocators.Default, intervalsCount); Inactive = new BitMap(Allocators.Default, intervalsCount);
PopulateFreePositions(RegisterType.Integer, out _intFreePositions, out _intFreePositionsCount); PopulateFreePositions(RegisterType.Integer, out _intFreePositions, out _intFreePositionsCount);
@ -443,7 +443,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
if (highest < current) if (highest < current)
{ {
highest = current; highest = current;
selected = index; selected = index;
if (current == int.MaxValue) if (current == int.MaxValue)
@ -485,9 +485,9 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private void SplitAndSpillOverlappingInterval( private void SplitAndSpillOverlappingInterval(
AllocationContext context, AllocationContext context,
LiveInterval current, LiveInterval current,
LiveInterval interval, LiveInterval interval,
int registersCount) int registersCount)
{ {
// If there's a next use after the start of the current interval, // If there's a next use after the start of the current interval,
// we need to split the spilled interval twice, and re-insert it // we need to split the spilled interval twice, and re-insert it
@ -530,8 +530,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private void InsertInterval(LiveInterval interval, int registersCount) private void InsertInterval(LiveInterval interval, int registersCount)
{ {
Debug.Assert(interval.UsesCount != 0, "Trying to insert a interval without uses."); Debug.Assert(interval.UsesCount != 0, "Trying to insert a interval without uses.");
Debug.Assert(!interval.IsEmpty, "Trying to insert a empty interval."); Debug.Assert(!interval.IsEmpty, "Trying to insert a empty interval.");
Debug.Assert(!interval.IsSpilled, "Trying to insert a spilled interval."); Debug.Assert(!interval.IsSpilled, "Trying to insert a spilled interval.");
int startIndex = registersCount * 2; int startIndex = registersCount * 2;
@ -545,9 +545,9 @@ 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.");
// We first check if any of the siblings were spilled, if so we can reuse // We first check if any of the siblings were spilled, if so we can reuse
@ -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)
{ {
@ -668,18 +668,15 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
continue; continue;
} }
int lEnd = _blockRanges[block.Index].End - 1; int lEnd = _blockRanges[block.Index].End - 1;
int rStart = _blockRanges[succIndex].Start; int rStart = _blockRanges[succIndex].Start;
LiveInterval left = interval.GetSplitChild(lEnd); LiveInterval left = interval.GetSplitChild(lEnd);
LiveInterval right = interval.GetSplitChild(rStart); LiveInterval right = interval.GetSplitChild(rStart);
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);
} }
@ -856,14 +853,14 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
int mapSize = _intervals.Count; int mapSize = _intervals.Count;
BitMap[] blkLiveGen = new BitMap[cfg.Blocks.Count]; BitMap[] blkLiveGen = new BitMap[cfg.Blocks.Count];
BitMap[] blkLiveKill = new BitMap[cfg.Blocks.Count]; BitMap[] blkLiveKill = new BitMap[cfg.Blocks.Count];
// 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)
{ {
@ -910,17 +907,17 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
} }
} }
blkLiveGen [block.Index] = liveGen; blkLiveGen[block.Index] = liveGen;
blkLiveKill[block.Index] = liveKill; blkLiveKill[block.Index] = liveKill;
} }
// Compute global live sets. // Compute global live sets.
BitMap[] blkLiveIn = new BitMap[cfg.Blocks.Count]; BitMap[] blkLiveIn = new BitMap[cfg.Blocks.Count];
BitMap[] blkLiveOut = new BitMap[cfg.Blocks.Count]; BitMap[] blkLiveOut = new BitMap[cfg.Blocks.Count];
for (int index = 0; index < cfg.Blocks.Count; index++) for (int index = 0; index < cfg.Blocks.Count; index++)
{ {
blkLiveIn [index] = new BitMap(Allocators.Default, mapSize); blkLiveIn[index] = new BitMap(Allocators.Default, mapSize);
blkLiveOut[index] = new BitMap(Allocators.Default, mapSize); blkLiveOut[index] = new BitMap(Allocators.Default, mapSize);
} }
@ -945,9 +942,9 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
BitMap liveIn = blkLiveIn[block.Index]; BitMap liveIn = blkLiveIn[block.Index];
liveIn.Set (liveOut); liveIn.Set(liveOut);
liveIn.Clear(blkLiveKill[block.Index]); liveIn.Clear(blkLiveKill[block.Index]);
liveIn.Set (blkLiveGen [block.Index]); liveIn.Set(blkLiveGen[block.Index]);
} }
} }
while (modified); while (modified);
@ -969,7 +966,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
int instCount = Math.Max(block.Operations.Count, 1); int instCount = Math.Max(block.Operations.Count, 1);
int blockStart = operationPos - instCount * InstructionGap; int blockStart = operationPos - instCount * InstructionGap;
int blockEnd = operationPos; int blockEnd = operationPos;
_blockRanges[block.Index] = new LiveRange(blockStart, blockEnd); _blockRanges[block.Index] = new LiveRange(blockStart, blockEnd);
@ -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

@ -5,8 +5,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{ {
readonly struct RegisterMasks readonly struct RegisterMasks
{ {
public int IntAvailableRegisters { get; } public int IntAvailableRegisters { get; }
public int VecAvailableRegisters { get; } public int VecAvailableRegisters { get; }
public int IntCallerSavedRegisters { get; } public int IntCallerSavedRegisters { get; }
public int VecCallerSavedRegisters { get; } public int VecCallerSavedRegisters { get; }
public int IntCalleeSavedRegisters { get; } public int IntCalleeSavedRegisters { get; }
@ -22,13 +22,13 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
int vecCalleeSavedRegisters, int vecCalleeSavedRegisters,
int registersCount) int registersCount)
{ {
IntAvailableRegisters = intAvailableRegisters; IntAvailableRegisters = intAvailableRegisters;
VecAvailableRegisters = vecAvailableRegisters; VecAvailableRegisters = vecAvailableRegisters;
IntCallerSavedRegisters = intCallerSavedRegisters; IntCallerSavedRegisters = intCallerSavedRegisters;
VecCallerSavedRegisters = vecCallerSavedRegisters; VecCallerSavedRegisters = vecCallerSavedRegisters;
IntCalleeSavedRegisters = intCalleeSavedRegisters; IntCalleeSavedRegisters = intCalleeSavedRegisters;
VecCalleeSavedRegisters = vecCalleeSavedRegisters; VecCalleeSavedRegisters = vecCalleeSavedRegisters;
RegistersCount = registersCount; RegistersCount = registersCount;
} }
public int GetAvailableRegisters(RegisterType type) public int GetAvailableRegisters(RegisterType type)

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

@ -2,10 +2,10 @@ namespace ARMeilleure.CodeGen.Unwinding
{ {
enum UnwindPseudoOp enum UnwindPseudoOp
{ {
PushReg = 0, PushReg = 0,
SetFrame = 1, SetFrame = 1,
AllocStack = 2, AllocStack = 2,
SaveReg = 3, SaveReg = 3,
SaveXmm128 = 4 SaveXmm128 = 4,
} }
} }

View file

@ -15,7 +15,7 @@ namespace ARMeilleure.CodeGen.X86
private const int OpModRMBits = 24; private const int OpModRMBits = 24;
private const byte RexPrefix = 0x40; private const byte RexPrefix = 0x40;
private const byte RexWPrefix = 0x48; private const byte RexWPrefix = 0x48;
private const byte LockPrefix = 0xf0; private const byte LockPrefix = 0xf0;
@ -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,
}); });
} }
@ -959,7 +959,7 @@ namespace ARMeilleure.CodeGen.X86
} }
} }
bool needsSibByte = false; bool needsSibByte = false;
bool needsDisplacement = false; bool needsDisplacement = false;
int sib = 0; int sib = 0;
@ -971,7 +971,7 @@ namespace ARMeilleure.CodeGen.X86
X86Register baseRegLow = (X86Register)(baseReg.Index & 0b111); X86Register baseRegLow = (X86Register)(baseReg.Index & 0b111);
needsSibByte = memOp.Index != default || baseRegLow == X86Register.Rsp; needsSibByte = memOp.Index != default || baseRegLow == X86Register.Rsp;
needsDisplacement = memOp.Displacement != 0 || baseRegLow == X86Register.Rbp; needsDisplacement = memOp.Displacement != 0 || baseRegLow == X86Register.Rbp;
if (needsDisplacement) if (needsDisplacement)
@ -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,47 +13,48 @@ 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,
RegOnly = 1 << 0, RegOnly = 1 << 0,
Reg8Src = 1 << 1, Reg8Src = 1 << 1,
Reg8Dest = 1 << 2, Reg8Dest = 1 << 2,
RexW = 1 << 3, RexW = 1 << 3,
Vex = 1 << 4, Vex = 1 << 4,
Evex = 1 << 5, Evex = 1 << 5,
PrefixBit = 16, PrefixBit = 16,
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
{ {
public int OpRMR { get; } public int OpRMR { get; }
public int OpRMImm8 { get; } public int OpRMImm8 { get; }
public int OpRMImm32 { get; } public int OpRMImm32 { get; }
public int OpRImm64 { get; } public int OpRImm64 { get; }
public int OpRRM { get; } public int OpRRM { get; }
public InstructionFlags Flags { get; } public InstructionFlags Flags { get; }
public InstructionInfo( public InstructionInfo(
int opRMR, int opRMR,
int opRMImm8, int opRMImm8,
int opRMImm32, int opRMImm32,
int opRImm64, int opRImm64,
int opRRM, int opRRM,
InstructionFlags flags) InstructionFlags flags)
{ {
OpRMR = opRMR; OpRMR = opRMR;
OpRMImm8 = opRMImm8; OpRMImm8 = opRMImm8;
OpRMImm32 = opRMImm32; OpRMImm32 = opRMImm32;
OpRImm64 = opRImm64; OpRImm64 = opRImm64;
OpRRM = opRRM; OpRRM = opRRM;
Flags = flags; Flags = flags;
} }
} }
@ -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

@ -30,7 +30,7 @@ namespace ARMeilleure.CodeGen.X86
Assembler = new Assembler(_stream, relocatable); Assembler = new Assembler(_stream, relocatable);
CallArgsRegionSize = GetCallArgsRegionSize(allocResult, maxCallArgs, out int xmmSaveRegionSize); CallArgsRegionSize = GetCallArgsRegionSize(allocResult, maxCallArgs, out int xmmSaveRegionSize);
XmmSaveRegionSize = xmmSaveRegionSize; XmmSaveRegionSize = xmmSaveRegionSize;
} }
private static int GetCallArgsRegionSize(AllocationResult allocResult, int maxCallArgs, out int xmmSaveRegionSize) private static int GetCallArgsRegionSize(AllocationResult allocResult, int maxCallArgs, out int xmmSaveRegionSize)

View file

@ -17,7 +17,7 @@ namespace ARMeilleure.CodeGen.X86
static class CodeGenerator static class CodeGenerator
{ {
private const int RegistersCount = 16; private const int RegistersCount = 16;
private const int PageSize = 0x1000; private const int PageSize = 0x1000;
private const int StackGuardSize = 0x2000; private const int StackGuardSize = 0x2000;
private static readonly Action<CodeGenContext, Operation>[] _instTable; private static readonly Action<CodeGenContext, Operation>[] _instTable;
@ -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)
{ {
@ -203,290 +205,290 @@ namespace ARMeilleure.CodeGen.X86
switch (info.Type) switch (info.Type)
{ {
case IntrinsicType.Comis_: case IntrinsicType.Comis_:
{
Operand dest = operation.Destination;
Operand src1 = operation.GetSource(0);
Operand src2 = operation.GetSource(1);
switch (operation.Intrinsic)
{
case Intrinsic.X86Comisdeq:
context.Assembler.Comisd(src1, src2);
context.Assembler.Setcc(dest, X86Condition.Equal);
break;
case Intrinsic.X86Comisdge:
context.Assembler.Comisd(src1, src2);
context.Assembler.Setcc(dest, X86Condition.AboveOrEqual);
break;
case Intrinsic.X86Comisdlt:
context.Assembler.Comisd(src1, src2);
context.Assembler.Setcc(dest, X86Condition.Below);
break;
case Intrinsic.X86Comisseq:
context.Assembler.Comiss(src1, src2);
context.Assembler.Setcc(dest, X86Condition.Equal);
break;
case Intrinsic.X86Comissge:
context.Assembler.Comiss(src1, src2);
context.Assembler.Setcc(dest, X86Condition.AboveOrEqual);
break;
case Intrinsic.X86Comisslt:
context.Assembler.Comiss(src1, src2);
context.Assembler.Setcc(dest, X86Condition.Below);
break;
}
context.Assembler.Movzx8(dest, dest, OperandType.I32);
break;
}
case IntrinsicType.Mxcsr:
{
Operand offset = operation.GetSource(0);
Debug.Assert(offset.Kind == OperandKind.Constant);
Debug.Assert(offset.Type == OperandType.I32);
int offs = offset.AsInt32() + context.CallArgsRegionSize;
Operand rsp = Register(X86Register.Rsp);
Operand memOp = MemoryOp(OperandType.I32, rsp, default, Multiplier.x1, offs);
Debug.Assert(HardwareCapabilities.SupportsSse || HardwareCapabilities.SupportsVexEncoding);
if (operation.Intrinsic == Intrinsic.X86Ldmxcsr)
{
Operand bits = operation.GetSource(1);
Debug.Assert(bits.Type == OperandType.I32);
context.Assembler.Mov(memOp, bits, OperandType.I32);
context.Assembler.Ldmxcsr(memOp);
}
else if (operation.Intrinsic == Intrinsic.X86Stmxcsr)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Debug.Assert(dest.Type == OperandType.I32); Operand src1 = operation.GetSource(0);
Operand src2 = operation.GetSource(1);
context.Assembler.Stmxcsr(memOp); switch (operation.Intrinsic)
context.Assembler.Mov(dest, memOp, OperandType.I32); {
case Intrinsic.X86Comisdeq:
context.Assembler.Comisd(src1, src2);
context.Assembler.Setcc(dest, X86Condition.Equal);
break;
case Intrinsic.X86Comisdge:
context.Assembler.Comisd(src1, src2);
context.Assembler.Setcc(dest, X86Condition.AboveOrEqual);
break;
case Intrinsic.X86Comisdlt:
context.Assembler.Comisd(src1, src2);
context.Assembler.Setcc(dest, X86Condition.Below);
break;
case Intrinsic.X86Comisseq:
context.Assembler.Comiss(src1, src2);
context.Assembler.Setcc(dest, X86Condition.Equal);
break;
case Intrinsic.X86Comissge:
context.Assembler.Comiss(src1, src2);
context.Assembler.Setcc(dest, X86Condition.AboveOrEqual);
break;
case Intrinsic.X86Comisslt:
context.Assembler.Comiss(src1, src2);
context.Assembler.Setcc(dest, X86Condition.Below);
break;
}
context.Assembler.Movzx8(dest, dest, OperandType.I32);
break;
} }
break; case IntrinsicType.Mxcsr:
} {
Operand offset = operation.GetSource(0);
Debug.Assert(offset.Kind == OperandKind.Constant);
Debug.Assert(offset.Type == OperandType.I32);
int offs = offset.AsInt32() + context.CallArgsRegionSize;
Operand rsp = Register(X86Register.Rsp);
Operand memOp = MemoryOp(OperandType.I32, rsp, default, Multiplier.x1, offs);
Debug.Assert(HardwareCapabilities.SupportsSse || HardwareCapabilities.SupportsVexEncoding);
if (operation.Intrinsic == Intrinsic.X86Ldmxcsr)
{
Operand bits = operation.GetSource(1);
Debug.Assert(bits.Type == OperandType.I32);
context.Assembler.Mov(memOp, bits, OperandType.I32);
context.Assembler.Ldmxcsr(memOp);
}
else if (operation.Intrinsic == Intrinsic.X86Stmxcsr)
{
Operand dest = operation.Destination;
Debug.Assert(dest.Type == OperandType.I32);
context.Assembler.Stmxcsr(memOp);
context.Assembler.Mov(dest, memOp, OperandType.I32);
}
break;
}
case IntrinsicType.PopCount: case IntrinsicType.PopCount:
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
EnsureSameType(dest, source); EnsureSameType(dest, source);
Debug.Assert(dest.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger());
context.Assembler.Popcnt(dest, source, dest.Type); context.Assembler.Popcnt(dest, source, dest.Type);
break; break;
} }
case IntrinsicType.Unary: case IntrinsicType.Unary:
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
EnsureSameType(dest, source); EnsureSameType(dest, source);
Debug.Assert(!dest.Type.IsInteger()); Debug.Assert(!dest.Type.IsInteger());
context.Assembler.WriteInstruction(info.Inst, dest, source); context.Assembler.WriteInstruction(info.Inst, dest, source);
break; break;
} }
case IntrinsicType.UnaryToGpr: case IntrinsicType.UnaryToGpr:
{
Operand dest = operation.Destination;
Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && !source.Type.IsInteger());
if (operation.Intrinsic == Intrinsic.X86Cvtsi2si)
{ {
if (dest.Type == OperandType.I32) Operand dest = operation.Destination;
{ Operand source = operation.GetSource(0);
context.Assembler.Movd(dest, source); // int _mm_cvtsi128_si32(__m128i a)
}
else /* if (dest.Type == OperandType.I64) */
{
context.Assembler.Movq(dest, source); // __int64 _mm_cvtsi128_si64(__m128i a)
}
}
else
{
context.Assembler.WriteInstruction(info.Inst, dest, source, dest.Type);
}
break; Debug.Assert(dest.Type.IsInteger() && !source.Type.IsInteger());
}
if (operation.Intrinsic == Intrinsic.X86Cvtsi2si)
{
if (dest.Type == OperandType.I32)
{
context.Assembler.Movd(dest, source); // int _mm_cvtsi128_si32(__m128i a)
}
else /* if (dest.Type == OperandType.I64) */
{
context.Assembler.Movq(dest, source); // __int64 _mm_cvtsi128_si64(__m128i a)
}
}
else
{
context.Assembler.WriteInstruction(info.Inst, dest, source, dest.Type);
}
break;
}
case IntrinsicType.Binary: case IntrinsicType.Binary:
{
Operand dest = operation.Destination;
Operand src1 = operation.GetSource(0);
Operand src2 = operation.GetSource(1);
EnsureSameType(dest, src1);
if (!HardwareCapabilities.SupportsVexEncoding)
{ {
EnsureSameReg(dest, src1); Operand dest = operation.Destination;
} Operand src1 = operation.GetSource(0);
Operand src2 = operation.GetSource(1);
Debug.Assert(!dest.Type.IsInteger()); EnsureSameType(dest, src1);
Debug.Assert(!src2.Type.IsInteger() || src2.Kind == OperandKind.Constant);
context.Assembler.WriteInstruction(info.Inst, dest, src1, src2); if (!HardwareCapabilities.SupportsVexEncoding)
{
EnsureSameReg(dest, src1);
}
break; Debug.Assert(!dest.Type.IsInteger());
} Debug.Assert(!src2.Type.IsInteger() || src2.Kind == OperandKind.Constant);
case IntrinsicType.BinaryGpr:
{
Operand dest = operation.Destination;
Operand src1 = operation.GetSource(0);
Operand src2 = operation.GetSource(1);
EnsureSameType(dest, src1);
if (!HardwareCapabilities.SupportsVexEncoding)
{
EnsureSameReg(dest, src1);
}
Debug.Assert(!dest.Type.IsInteger() && src2.Type.IsInteger());
context.Assembler.WriteInstruction(info.Inst, dest, src1, src2, src2.Type);
break;
}
case IntrinsicType.Crc32:
{
Operand dest = operation.Destination;
Operand src1 = operation.GetSource(0);
Operand src2 = operation.GetSource(1);
EnsureSameReg(dest, src1);
Debug.Assert(dest.Type.IsInteger() && src1.Type.IsInteger() && src2.Type.IsInteger());
context.Assembler.WriteInstruction(info.Inst, dest, src2, dest.Type);
break;
}
case IntrinsicType.BinaryImm:
{
Operand dest = operation.Destination;
Operand src1 = operation.GetSource(0);
Operand src2 = operation.GetSource(1);
EnsureSameType(dest, src1);
if (!HardwareCapabilities.SupportsVexEncoding)
{
EnsureSameReg(dest, src1);
}
Debug.Assert(!dest.Type.IsInteger() && src2.Kind == OperandKind.Constant);
context.Assembler.WriteInstruction(info.Inst, dest, src1, src2.AsByte());
break;
}
case IntrinsicType.Ternary:
{
Operand dest = operation.Destination;
Operand src1 = operation.GetSource(0);
Operand src2 = operation.GetSource(1);
Operand src3 = operation.GetSource(2);
EnsureSameType(dest, src1, src2, src3);
Debug.Assert(!dest.Type.IsInteger());
if (info.Inst == X86Instruction.Blendvpd && HardwareCapabilities.SupportsVexEncoding)
{
context.Assembler.WriteInstruction(X86Instruction.Vblendvpd, dest, src1, src2, src3);
}
else if (info.Inst == X86Instruction.Blendvps && HardwareCapabilities.SupportsVexEncoding)
{
context.Assembler.WriteInstruction(X86Instruction.Vblendvps, dest, src1, src2, src3);
}
else if (info.Inst == X86Instruction.Pblendvb && HardwareCapabilities.SupportsVexEncoding)
{
context.Assembler.WriteInstruction(X86Instruction.Vpblendvb, dest, src1, src2, src3);
}
else
{
EnsureSameReg(dest, src1);
Debug.Assert(src3.GetRegister().Index == 0);
context.Assembler.WriteInstruction(info.Inst, dest, src1, src2); context.Assembler.WriteInstruction(info.Inst, dest, src1, src2);
break;
} }
break; case IntrinsicType.BinaryGpr:
} {
Operand dest = operation.Destination;
Operand src1 = operation.GetSource(0);
Operand src2 = operation.GetSource(1);
EnsureSameType(dest, src1);
if (!HardwareCapabilities.SupportsVexEncoding)
{
EnsureSameReg(dest, src1);
}
Debug.Assert(!dest.Type.IsInteger() && src2.Type.IsInteger());
context.Assembler.WriteInstruction(info.Inst, dest, src1, src2, src2.Type);
break;
}
case IntrinsicType.Crc32:
{
Operand dest = operation.Destination;
Operand src1 = operation.GetSource(0);
Operand src2 = operation.GetSource(1);
EnsureSameReg(dest, src1);
Debug.Assert(dest.Type.IsInteger() && src1.Type.IsInteger() && src2.Type.IsInteger());
context.Assembler.WriteInstruction(info.Inst, dest, src2, dest.Type);
break;
}
case IntrinsicType.BinaryImm:
{
Operand dest = operation.Destination;
Operand src1 = operation.GetSource(0);
Operand src2 = operation.GetSource(1);
EnsureSameType(dest, src1);
if (!HardwareCapabilities.SupportsVexEncoding)
{
EnsureSameReg(dest, src1);
}
Debug.Assert(!dest.Type.IsInteger() && src2.Kind == OperandKind.Constant);
context.Assembler.WriteInstruction(info.Inst, dest, src1, src2.AsByte());
break;
}
case IntrinsicType.Ternary:
{
Operand dest = operation.Destination;
Operand src1 = operation.GetSource(0);
Operand src2 = operation.GetSource(1);
Operand src3 = operation.GetSource(2);
EnsureSameType(dest, src1, src2, src3);
Debug.Assert(!dest.Type.IsInteger());
if (info.Inst == X86Instruction.Blendvpd && HardwareCapabilities.SupportsVexEncoding)
{
context.Assembler.WriteInstruction(X86Instruction.Vblendvpd, dest, src1, src2, src3);
}
else if (info.Inst == X86Instruction.Blendvps && HardwareCapabilities.SupportsVexEncoding)
{
context.Assembler.WriteInstruction(X86Instruction.Vblendvps, dest, src1, src2, src3);
}
else if (info.Inst == X86Instruction.Pblendvb && HardwareCapabilities.SupportsVexEncoding)
{
context.Assembler.WriteInstruction(X86Instruction.Vpblendvb, dest, src1, src2, src3);
}
else
{
EnsureSameReg(dest, src1);
Debug.Assert(src3.GetRegister().Index == 0);
context.Assembler.WriteInstruction(info.Inst, dest, src1, src2);
}
break;
}
case IntrinsicType.TernaryImm: case IntrinsicType.TernaryImm:
{
Operand dest = operation.Destination;
Operand src1 = operation.GetSource(0);
Operand src2 = operation.GetSource(1);
Operand src3 = operation.GetSource(2);
EnsureSameType(dest, src1, src2);
if (!HardwareCapabilities.SupportsVexEncoding)
{ {
EnsureSameReg(dest, src1); Operand dest = operation.Destination;
Operand src1 = operation.GetSource(0);
Operand src2 = operation.GetSource(1);
Operand src3 = operation.GetSource(2);
EnsureSameType(dest, src1, src2);
if (!HardwareCapabilities.SupportsVexEncoding)
{
EnsureSameReg(dest, src1);
}
Debug.Assert(!dest.Type.IsInteger() && src3.Kind == OperandKind.Constant);
context.Assembler.WriteInstruction(info.Inst, dest, src1, src2, src3.AsByte());
break;
} }
Debug.Assert(!dest.Type.IsInteger() && src3.Kind == OperandKind.Constant);
context.Assembler.WriteInstruction(info.Inst, dest, src1, src2, src3.AsByte());
break;
}
case IntrinsicType.Fma: case IntrinsicType.Fma:
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand src1 = operation.GetSource(0); Operand src1 = operation.GetSource(0);
Operand src2 = operation.GetSource(1); Operand src2 = operation.GetSource(1);
Operand src3 = operation.GetSource(2); Operand src3 = operation.GetSource(2);
Debug.Assert(HardwareCapabilities.SupportsVexEncoding); Debug.Assert(HardwareCapabilities.SupportsVexEncoding);
Debug.Assert(dest.Kind == OperandKind.Register && src1.Kind == OperandKind.Register && src2.Kind == OperandKind.Register); Debug.Assert(dest.Kind == OperandKind.Register && src1.Kind == OperandKind.Register && src2.Kind == OperandKind.Register);
Debug.Assert(src3.Kind == OperandKind.Register || src3.Kind == OperandKind.Memory); Debug.Assert(src3.Kind == OperandKind.Register || src3.Kind == OperandKind.Memory);
EnsureSameType(dest, src1, src2, src3); EnsureSameType(dest, src1, src2, src3);
Debug.Assert(dest.Type == OperandType.V128); Debug.Assert(dest.Type == OperandType.V128);
Debug.Assert(dest.Value == src1.Value); Debug.Assert(dest.Value == src1.Value);
context.Assembler.WriteInstruction(info.Inst, dest, src2, src3); context.Assembler.WriteInstruction(info.Inst, dest, src2, src3);
break; break;
} }
} }
} }
else else
@ -592,7 +594,7 @@ namespace ARMeilleure.CodeGen.X86
private static void GenerateBitwiseNot(CodeGenContext context, Operation operation) private static void GenerateBitwiseNot(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
ValidateUnOp(dest, source); ValidateUnOp(dest, source);
@ -630,7 +632,7 @@ namespace ARMeilleure.CodeGen.X86
private static void GenerateByteSwap(CodeGenContext context, Operation operation) private static void GenerateByteSwap(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
ValidateUnOp(dest, source); ValidateUnOp(dest, source);
@ -761,19 +763,19 @@ namespace ARMeilleure.CodeGen.X86
Operand src2 = operation.GetSource(1); Operand src2 = operation.GetSource(1);
Operand src3 = operation.GetSource(2); Operand src3 = operation.GetSource(2);
EnsureSameReg (dest, src3); EnsureSameReg(dest, src3);
EnsureSameType(dest, src2, src3); EnsureSameType(dest, src2, src3);
Debug.Assert(dest.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger());
Debug.Assert(src1.Type == OperandType.I32); Debug.Assert(src1.Type == OperandType.I32);
context.Assembler.Test (src1, src1, src1.Type); context.Assembler.Test(src1, src1, src1.Type);
context.Assembler.Cmovcc(dest, src2, dest.Type, X86Condition.NotEqual); context.Assembler.Cmovcc(dest, src2, dest.Type, X86Condition.NotEqual);
} }
private static void GenerateConvertI64ToI32(CodeGenContext context, Operation operation) private static void GenerateConvertI64ToI32(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type == OperandType.I32 && source.Type == OperandType.I64); Debug.Assert(dest.Type == OperandType.I32 && source.Type == OperandType.I64);
@ -783,7 +785,7 @@ namespace ARMeilleure.CodeGen.X86
private static void GenerateConvertToFP(CodeGenContext context, Operation operation) private static void GenerateConvertToFP(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type == OperandType.FP32 || dest.Type == OperandType.FP64); Debug.Assert(dest.Type == OperandType.FP32 || dest.Type == OperandType.FP64);
@ -794,7 +796,7 @@ namespace ARMeilleure.CodeGen.X86
if (source.Type.IsInteger()) if (source.Type.IsInteger())
{ {
context.Assembler.Xorps (dest, dest, dest); context.Assembler.Xorps(dest, dest, dest);
context.Assembler.Cvtsi2ss(dest, dest, source, source.Type); context.Assembler.Cvtsi2ss(dest, dest, source, source.Type);
} }
else /* if (source.Type == OperandType.FP64) */ else /* if (source.Type == OperandType.FP64) */
@ -810,7 +812,7 @@ namespace ARMeilleure.CodeGen.X86
if (source.Type.IsInteger()) if (source.Type.IsInteger())
{ {
context.Assembler.Xorps (dest, dest, dest); context.Assembler.Xorps(dest, dest, dest);
context.Assembler.Cvtsi2sd(dest, dest, source, source.Type); context.Assembler.Cvtsi2sd(dest, dest, source, source.Type);
} }
else /* if (source.Type == OperandType.FP32) */ else /* if (source.Type == OperandType.FP32) */
@ -824,7 +826,7 @@ namespace ARMeilleure.CodeGen.X86
private static void GenerateCopy(CodeGenContext context, Operation operation) private static void GenerateCopy(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
EnsureSameType(dest, source); EnsureSameType(dest, source);
@ -837,7 +839,7 @@ namespace ARMeilleure.CodeGen.X86
return; return;
} }
if (dest.Kind == OperandKind.Register && if (dest.Kind == OperandKind.Register &&
source.Kind == OperandKind.Constant && source.Value == 0) source.Kind == OperandKind.Constant && source.Value == 0)
{ {
// Assemble "mov reg, 0" as "xor reg, reg" as the later is more efficient. // Assemble "mov reg, 0" as "xor reg, reg" as the later is more efficient.
@ -855,7 +857,7 @@ namespace ARMeilleure.CodeGen.X86
private static void GenerateCountLeadingZeros(CodeGenContext context, Operation operation) private static void GenerateCountLeadingZeros(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
EnsureSameType(dest, source); EnsureSameType(dest, source);
@ -888,9 +890,9 @@ namespace ARMeilleure.CodeGen.X86
private static void GenerateDivide(CodeGenContext context, Operation operation) private static void GenerateDivide(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand dividend = operation.GetSource(0); Operand dividend = operation.GetSource(0);
Operand divisor = operation.GetSource(1); Operand divisor = operation.GetSource(1);
if (!dest.Type.IsInteger()) if (!dest.Type.IsInteger())
{ {
@ -938,7 +940,7 @@ namespace ARMeilleure.CodeGen.X86
private static void GenerateFill(CodeGenContext context, Operation operation) private static void GenerateFill(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand offset = operation.GetSource(0); Operand offset = operation.GetSource(0);
Debug.Assert(offset.Kind == OperandKind.Constant); Debug.Assert(offset.Kind == OperandKind.Constant);
@ -954,7 +956,7 @@ namespace ARMeilleure.CodeGen.X86
private static void GenerateLoad(CodeGenContext context, Operation operation) private static void GenerateLoad(CodeGenContext context, Operation operation)
{ {
Operand value = operation.Destination; Operand value = operation.Destination;
Operand address = Memory(operation.GetSource(0), value.Type); Operand address = Memory(operation.GetSource(0), value.Type);
GenerateLoad(context, address, value); GenerateLoad(context, address, value);
@ -962,7 +964,7 @@ namespace ARMeilleure.CodeGen.X86
private static void GenerateLoad16(CodeGenContext context, Operation operation) private static void GenerateLoad16(CodeGenContext context, Operation operation)
{ {
Operand value = operation.Destination; Operand value = operation.Destination;
Operand address = Memory(operation.GetSource(0), value.Type); Operand address = Memory(operation.GetSource(0), value.Type);
Debug.Assert(value.Type.IsInteger()); Debug.Assert(value.Type.IsInteger());
@ -972,7 +974,7 @@ namespace ARMeilleure.CodeGen.X86
private static void GenerateLoad8(CodeGenContext context, Operation operation) private static void GenerateLoad8(CodeGenContext context, Operation operation)
{ {
Operand value = operation.Destination; Operand value = operation.Destination;
Operand address = Memory(operation.GetSource(0), value.Type); Operand address = Memory(operation.GetSource(0), value.Type);
Debug.Assert(value.Type.IsInteger()); Debug.Assert(value.Type.IsInteger());
@ -1039,7 +1041,7 @@ namespace ARMeilleure.CodeGen.X86
private static void GenerateNegate(CodeGenContext context, Operation operation) private static void GenerateNegate(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
ValidateUnOp(dest, source); ValidateUnOp(dest, source);
@ -1102,7 +1104,7 @@ namespace ARMeilleure.CodeGen.X86
private static void GenerateSignExtend16(CodeGenContext context, Operation operation) private static void GenerateSignExtend16(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
@ -1112,7 +1114,7 @@ namespace ARMeilleure.CodeGen.X86
private static void GenerateSignExtend32(CodeGenContext context, Operation operation) private static void GenerateSignExtend32(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
@ -1122,7 +1124,7 @@ namespace ARMeilleure.CodeGen.X86
private static void GenerateSignExtend8(CodeGenContext context, Operation operation) private static void GenerateSignExtend8(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
@ -1158,7 +1160,7 @@ namespace ARMeilleure.CodeGen.X86
private static void GenerateStackAlloc(CodeGenContext context, Operation operation) private static void GenerateStackAlloc(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand offset = operation.GetSource(0); Operand offset = operation.GetSource(0);
Debug.Assert(offset.Kind == OperandKind.Constant); Debug.Assert(offset.Kind == OperandKind.Constant);
@ -1174,7 +1176,7 @@ namespace ARMeilleure.CodeGen.X86
private static void GenerateStore(CodeGenContext context, Operation operation) private static void GenerateStore(CodeGenContext context, Operation operation)
{ {
Operand value = operation.GetSource(1); Operand value = operation.GetSource(1);
Operand address = Memory(operation.GetSource(0), value.Type); Operand address = Memory(operation.GetSource(0), value.Type);
GenerateStore(context, address, value); GenerateStore(context, address, value);
@ -1182,7 +1184,7 @@ namespace ARMeilleure.CodeGen.X86
private static void GenerateStore16(CodeGenContext context, Operation operation) private static void GenerateStore16(CodeGenContext context, Operation operation)
{ {
Operand value = operation.GetSource(1); Operand value = operation.GetSource(1);
Operand address = Memory(operation.GetSource(0), value.Type); Operand address = Memory(operation.GetSource(0), value.Type);
Debug.Assert(value.Type.IsInteger()); Debug.Assert(value.Type.IsInteger());
@ -1192,7 +1194,7 @@ namespace ARMeilleure.CodeGen.X86
private static void GenerateStore8(CodeGenContext context, Operation operation) private static void GenerateStore8(CodeGenContext context, Operation operation)
{ {
Operand value = operation.GetSource(1); Operand value = operation.GetSource(1);
Operand address = Memory(operation.GetSource(0), value.Type); Operand address = Memory(operation.GetSource(0), value.Type);
Debug.Assert(value.Type.IsInteger()); Debug.Assert(value.Type.IsInteger());
@ -1231,7 +1233,7 @@ namespace ARMeilleure.CodeGen.X86
private static void GenerateVectorCreateScalar(CodeGenContext context, Operation operation) private static void GenerateVectorCreateScalar(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(!dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(!dest.Type.IsInteger() && source.Type.IsInteger());
@ -1278,7 +1280,7 @@ namespace ARMeilleure.CodeGen.X86
mask1 = BitUtils.RotateRight(mask1, 8 - index * 2, 8); mask1 = BitUtils.RotateRight(mask1, 8 - index * 2, 8);
context.Assembler.Pshufd(src1, src1, (byte)mask0); context.Assembler.Pshufd(src1, src1, (byte)mask0);
context.Assembler.Movd (dest, src1); context.Assembler.Movd(dest, src1);
context.Assembler.Pshufd(src1, src1, (byte)mask1); context.Assembler.Pshufd(src1, src1, (byte)mask1);
} }
} }
@ -1297,7 +1299,7 @@ namespace ARMeilleure.CodeGen.X86
const byte mask = 0b01_00_11_10; const byte mask = 0b01_00_11_10;
context.Assembler.Pshufd(src1, src1, mask); context.Assembler.Pshufd(src1, src1, mask);
context.Assembler.Movq (dest, src1); context.Assembler.Movq(dest, src1);
context.Assembler.Pshufd(src1, src1, mask); context.Assembler.Pshufd(src1, src1, mask);
} }
} }
@ -1308,7 +1310,7 @@ namespace ARMeilleure.CodeGen.X86
(index == 1 && dest.Type == OperandType.FP64)) (index == 1 && dest.Type == OperandType.FP64))
{ {
context.Assembler.Movhlps(dest, dest, src1); context.Assembler.Movhlps(dest, dest, src1);
context.Assembler.Movq (dest, dest); context.Assembler.Movq(dest, dest);
} }
else else
{ {
@ -1455,11 +1457,11 @@ namespace ARMeilleure.CodeGen.X86
int mask0 = 0b11_10_01_00; int mask0 = 0b11_10_01_00;
int mask1 = 0b11_10_01_00; int mask1 = 0b11_10_01_00;
mask0 = BitUtils.RotateRight(mask0, index * 2, 8); mask0 = BitUtils.RotateRight(mask0, index * 2, 8);
mask1 = BitUtils.RotateRight(mask1, 8 - index * 2, 8); mask1 = BitUtils.RotateRight(mask1, 8 - index * 2, 8);
context.Assembler.Pshufd(src1, src1, (byte)mask0); // Lane to be inserted in position 0. context.Assembler.Pshufd(src1, src1, (byte)mask0); // Lane to be inserted in position 0.
context.Assembler.Movss (dest, src1, src2); // dest[127:0] = src1[127:32] | src2[31:0] context.Assembler.Movss(dest, src1, src2); // dest[127:0] = src1[127:32] | src2[31:0]
context.Assembler.Pshufd(dest, dest, (byte)mask1); // Inserted lane in original position. context.Assembler.Pshufd(dest, dest, (byte)mask1); // Inserted lane in original position.
if (dest.GetRegister() != src1.GetRegister()) if (dest.GetRegister() != src1.GetRegister())
@ -1555,7 +1557,7 @@ namespace ARMeilleure.CodeGen.X86
private static void GenerateVectorZeroUpper64(CodeGenContext context, Operation operation) private static void GenerateVectorZeroUpper64(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type == OperandType.V128 && source.Type == OperandType.V128); Debug.Assert(dest.Type == OperandType.V128 && source.Type == OperandType.V128);
@ -1565,7 +1567,7 @@ namespace ARMeilleure.CodeGen.X86
private static void GenerateVectorZeroUpper96(CodeGenContext context, Operation operation) private static void GenerateVectorZeroUpper96(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type == OperandType.V128 && source.Type == OperandType.V128); Debug.Assert(dest.Type == OperandType.V128 && source.Type == OperandType.V128);
@ -1575,7 +1577,7 @@ namespace ARMeilleure.CodeGen.X86
private static void GenerateZeroExtend16(CodeGenContext context, Operation operation) private static void GenerateZeroExtend16(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
@ -1585,7 +1587,7 @@ namespace ARMeilleure.CodeGen.X86
private static void GenerateZeroExtend32(CodeGenContext context, Operation operation) private static void GenerateZeroExtend32(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
@ -1601,7 +1603,7 @@ namespace ARMeilleure.CodeGen.X86
private static void GenerateZeroExtend8(CodeGenContext context, Operation operation) private static void GenerateZeroExtend8(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Destination; Operand dest = operation.Destination;
Operand source = operation.GetSource(0); Operand source = operation.GetSource(0);
Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger()); Debug.Assert(dest.Type.IsInteger() && source.Type.IsInteger());
@ -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;
} }
} }
@ -1670,21 +1696,21 @@ namespace ARMeilleure.CodeGen.X86
[Conditional("DEBUG")] [Conditional("DEBUG")]
private static void ValidateUnOp(Operand dest, Operand source) private static void ValidateUnOp(Operand dest, Operand source)
{ {
EnsureSameReg (dest, source); EnsureSameReg(dest, source);
EnsureSameType(dest, source); EnsureSameType(dest, source);
} }
[Conditional("DEBUG")] [Conditional("DEBUG")]
private static void ValidateBinOp(Operand dest, Operand src1, Operand src2) private static void ValidateBinOp(Operand dest, Operand src1, Operand src2)
{ {
EnsureSameReg (dest, src1); EnsureSameReg(dest, src1);
EnsureSameType(dest, src1, src2); EnsureSameType(dest, src1, src2);
} }
[Conditional("DEBUG")] [Conditional("DEBUG")]
private static void ValidateShift(Operand dest, Operand src1, Operand src2) private static void ValidateShift(Operand dest, Operand src1, Operand src2)
{ {
EnsureSameReg (dest, src1); EnsureSameReg(dest, src1);
EnsureSameType(dest, src1); EnsureSameType(dest, src1);
Debug.Assert(dest.Type.IsInteger() && src2.Type == OperandType.I32); Debug.Assert(dest.Type.IsInteger() && src2.Type == OperandType.I32);
@ -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);
@ -1831,7 +1857,7 @@ namespace ARMeilleure.CodeGen.X86
size = (size + pageMask) & ~pageMask; size = (size + pageMask) & ~pageMask;
Operand rsp = Register(X86Register.Rsp); Operand rsp = Register(X86Register.Rsp);
Operand temp = Register(CallingConvention.GetIntReturnRegister()); Operand temp = Register(CallingConvention.GetIntReturnRegister());
for (int offset = PageSize; offset < size; offset += PageSize) for (int offset = PageSize; offset < size; offset += PageSize)

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

@ -3,7 +3,7 @@ namespace ARMeilleure.CodeGen.X86
readonly struct IntrinsicInfo readonly struct IntrinsicInfo
{ {
public X86Instruction Inst { get; } public X86Instruction Inst { get; }
public IntrinsicType Type { get; } public IntrinsicType Type { get; }
public IntrinsicInfo(X86Instruction inst, IntrinsicType type) public IntrinsicInfo(X86Instruction inst, IntrinsicType type)
{ {

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);
@ -228,151 +225,151 @@ namespace ARMeilleure.CodeGen.X86
case Instruction.CompareAndSwap: case Instruction.CompareAndSwap:
case Instruction.CompareAndSwap16: case Instruction.CompareAndSwap16:
case Instruction.CompareAndSwap8: case Instruction.CompareAndSwap8:
{
OperandType type = node.GetSource(1).Type;
if (type == OperandType.V128)
{ {
// Handle the many restrictions of the compare and exchange (16 bytes) instruction: OperandType type = node.GetSource(1).Type;
// - The expected value should be in RDX:RAX.
// - The new value to be written should be in RCX:RBX. if (type == OperandType.V128)
// - The value at the memory location is loaded to RDX:RAX.
void SplitOperand(Operand source, Operand lr, Operand hr)
{ {
nodes.AddBefore(node, Operation(Instruction.VectorExtract, lr, source, Const(0))); // Handle the many restrictions of the compare and exchange (16 bytes) instruction:
nodes.AddBefore(node, Operation(Instruction.VectorExtract, hr, source, Const(1))); // - The expected value should be in RDX:RAX.
// - The new value to be written should be in RCX:RBX.
// - The value at the memory location is loaded to RDX:RAX.
void SplitOperand(Operand source, Operand lr, Operand hr)
{
nodes.AddBefore(node, Operation(Instruction.VectorExtract, lr, source, Const(0)));
nodes.AddBefore(node, Operation(Instruction.VectorExtract, hr, source, Const(1)));
}
Operand rax = Gpr(X86Register.Rax, OperandType.I64);
Operand rbx = Gpr(X86Register.Rbx, OperandType.I64);
Operand rcx = Gpr(X86Register.Rcx, OperandType.I64);
Operand rdx = Gpr(X86Register.Rdx, OperandType.I64);
SplitOperand(node.GetSource(1), rax, rdx);
SplitOperand(node.GetSource(2), rbx, rcx);
Operation operation = node;
node = nodes.AddAfter(node, Operation(Instruction.VectorCreateScalar, dest, rax));
nodes.AddAfter(node, Operation(Instruction.VectorInsert, dest, dest, rdx, Const(1)));
operation.SetDestinations(new Operand[] { rdx, rax });
operation.SetSources(new Operand[] { operation.GetSource(0), rdx, rax, rcx, rbx });
}
else
{
// Handle the many restrictions of the compare and exchange (32/64) instruction:
// - The expected value should be in (E/R)AX.
// - The value at the memory location is loaded to (E/R)AX.
Operand expected = node.GetSource(1);
Operand newValue = node.GetSource(2);
Operand rax = Gpr(X86Register.Rax, expected.Type);
nodes.AddBefore(node, Operation(Instruction.Copy, rax, expected));
// We need to store the new value into a temp, since it may
// be a constant, and this instruction does not support immediate operands.
Operand temp = Local(newValue.Type);
nodes.AddBefore(node, Operation(Instruction.Copy, temp, newValue));
node.SetSources(new Operand[] { node.GetSource(0), rax, temp });
nodes.AddAfter(node, Operation(Instruction.Copy, dest, rax));
node.Destination = rax;
} }
Operand rax = Gpr(X86Register.Rax, OperandType.I64); break;
Operand rbx = Gpr(X86Register.Rbx, OperandType.I64);
Operand rcx = Gpr(X86Register.Rcx, OperandType.I64);
Operand rdx = Gpr(X86Register.Rdx, OperandType.I64);
SplitOperand(node.GetSource(1), rax, rdx);
SplitOperand(node.GetSource(2), rbx, rcx);
Operation operation = node;
node = nodes.AddAfter(node, Operation(Instruction.VectorCreateScalar, dest, rax));
nodes.AddAfter(node, Operation(Instruction.VectorInsert, dest, dest, rdx, Const(1)));
operation.SetDestinations(new Operand[] { rdx, rax });
operation.SetSources(new Operand[] { operation.GetSource(0), rdx, rax, rcx, rbx });
} }
else
{
// Handle the many restrictions of the compare and exchange (32/64) instruction:
// - The expected value should be in (E/R)AX.
// - The value at the memory location is loaded to (E/R)AX.
Operand expected = node.GetSource(1);
Operand newValue = node.GetSource(2);
Operand rax = Gpr(X86Register.Rax, expected.Type);
nodes.AddBefore(node, Operation(Instruction.Copy, rax, expected));
// We need to store the new value into a temp, since it may
// be a constant, and this instruction does not support immediate operands.
Operand temp = Local(newValue.Type);
nodes.AddBefore(node, Operation(Instruction.Copy, temp, newValue));
node.SetSources(new Operand[] { node.GetSource(0), rax, temp });
nodes.AddAfter(node, Operation(Instruction.Copy, dest, rax));
node.Destination = rax;
}
break;
}
case Instruction.Divide: case Instruction.Divide:
case Instruction.DivideUI: case Instruction.DivideUI:
{
// Handle the many restrictions of the division instructions:
// - The dividend is always in RDX:RAX.
// - The result is always in RAX.
// - Additionally it also writes the remainder in RDX.
if (dest.Type.IsInteger())
{ {
// Handle the many restrictions of the division instructions:
// - The dividend is always in RDX:RAX.
// - The result is always in RAX.
// - Additionally it also writes the remainder in RDX.
if (dest.Type.IsInteger())
{
Operand src1 = node.GetSource(0);
Operand rax = Gpr(X86Register.Rax, src1.Type);
Operand rdx = Gpr(X86Register.Rdx, src1.Type);
nodes.AddBefore(node, Operation(Instruction.Copy, rax, src1));
nodes.AddBefore(node, Operation(Instruction.Clobber, rdx));
nodes.AddAfter(node, Operation(Instruction.Copy, dest, rax));
node.SetSources(new Operand[] { rdx, rax, node.GetSource(1) });
node.Destination = rax;
}
break;
}
case Instruction.Extended:
{
bool isBlend = node.Intrinsic == Intrinsic.X86Blendvpd ||
node.Intrinsic == Intrinsic.X86Blendvps ||
node.Intrinsic == Intrinsic.X86Pblendvb;
// BLENDVPD, BLENDVPS, PBLENDVB last operand is always implied to be XMM0 when VEX is not supported.
// SHA256RNDS2 always has an implied XMM0 as a last operand.
if ((isBlend && !HardwareCapabilities.SupportsVexEncoding) || node.Intrinsic == Intrinsic.X86Sha256Rnds2)
{
Operand xmm0 = Xmm(X86Register.Xmm0, OperandType.V128);
nodes.AddBefore(node, Operation(Instruction.Copy, xmm0, node.GetSource(2)));
node.SetSource(2, xmm0);
}
break;
}
case Instruction.Multiply64HighSI:
case Instruction.Multiply64HighUI:
{
// Handle the many restrictions of the i64 * i64 = i128 multiply instructions:
// - The multiplicand is always in RAX.
// - The lower 64-bits of the result is always in RAX.
// - The higher 64-bits of the result is always in RDX.
Operand src1 = node.GetSource(0); Operand src1 = node.GetSource(0);
Operand rax = Gpr(X86Register.Rax, src1.Type); Operand rax = Gpr(X86Register.Rax, src1.Type);
Operand rdx = Gpr(X86Register.Rdx, src1.Type); Operand rdx = Gpr(X86Register.Rdx, src1.Type);
nodes.AddBefore(node, Operation(Instruction.Copy, rax, src1)); nodes.AddBefore(node, Operation(Instruction.Copy, rax, src1));
nodes.AddBefore(node, Operation(Instruction.Clobber, rdx));
nodes.AddAfter(node, Operation(Instruction.Copy, dest, rax)); node.SetSource(0, rax);
node.SetSources(new Operand[] { rdx, rax, node.GetSource(1) }); nodes.AddAfter(node, Operation(Instruction.Copy, dest, rdx));
node.Destination = rax;
node.SetDestinations(new Operand[] { rdx, rax });
break;
} }
break;
}
case Instruction.Extended:
{
bool isBlend = node.Intrinsic == Intrinsic.X86Blendvpd ||
node.Intrinsic == Intrinsic.X86Blendvps ||
node.Intrinsic == Intrinsic.X86Pblendvb;
// BLENDVPD, BLENDVPS, PBLENDVB last operand is always implied to be XMM0 when VEX is not supported.
// SHA256RNDS2 always has an implied XMM0 as a last operand.
if ((isBlend && !HardwareCapabilities.SupportsVexEncoding) || node.Intrinsic == Intrinsic.X86Sha256Rnds2)
{
Operand xmm0 = Xmm(X86Register.Xmm0, OperandType.V128);
nodes.AddBefore(node, Operation(Instruction.Copy, xmm0, node.GetSource(2)));
node.SetSource(2, xmm0);
}
break;
}
case Instruction.Multiply64HighSI:
case Instruction.Multiply64HighUI:
{
// Handle the many restrictions of the i64 * i64 = i128 multiply instructions:
// - The multiplicand is always in RAX.
// - The lower 64-bits of the result is always in RAX.
// - The higher 64-bits of the result is always in RDX.
Operand src1 = node.GetSource(0);
Operand rax = Gpr(X86Register.Rax, src1.Type);
Operand rdx = Gpr(X86Register.Rdx, src1.Type);
nodes.AddBefore(node, Operation(Instruction.Copy, rax, src1));
node.SetSource(0, rax);
nodes.AddAfter(node, Operation(Instruction.Copy, dest, rdx));
node.SetDestinations(new Operand[] { rdx, rax });
break;
}
case Instruction.RotateRight: case Instruction.RotateRight:
case Instruction.ShiftLeft: case Instruction.ShiftLeft:
case Instruction.ShiftRightSI: case Instruction.ShiftRightSI:
case Instruction.ShiftRightUI: case Instruction.ShiftRightUI:
{
// The shift register is always implied to be CL (low 8-bits of RCX or ECX).
if (node.GetSource(1).Kind == OperandKind.LocalVariable)
{ {
Operand rcx = Gpr(X86Register.Rcx, OperandType.I32); // The shift register is always implied to be CL (low 8-bits of RCX or ECX).
if (node.GetSource(1).Kind == OperandKind.LocalVariable)
{
Operand rcx = Gpr(X86Register.Rcx, OperandType.I32);
nodes.AddBefore(node, Operation(Instruction.Copy, rcx, node.GetSource(1))); nodes.AddBefore(node, Operation(Instruction.Copy, rcx, node.GetSource(1)));
node.SetSource(1, rcx); node.SetSource(1, rcx);
}
break;
} }
break;
}
} }
} }
@ -459,7 +456,7 @@ namespace ARMeilleure.CodeGen.X86
// Unsigned integer to FP conversions are not supported on X86. // Unsigned integer to FP conversions are not supported on X86.
// We need to turn them into signed integer to FP conversions, and // We need to turn them into signed integer to FP conversions, and
// adjust the final result. // adjust the final result.
Operand dest = node.Destination; Operand dest = node.Destination;
Operand source = node.GetSource(0); Operand source = node.GetSource(0);
Debug.Assert(source.Type.IsInteger(), $"Invalid source type \"{source.Type}\"."); Debug.Assert(source.Type.IsInteger(), $"Invalid source type \"{source.Type}\".");
@ -472,8 +469,8 @@ namespace ARMeilleure.CodeGen.X86
// and then use the 64-bits signed conversion instructions. // and then use the 64-bits signed conversion instructions.
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) */
{ {
@ -487,15 +484,15 @@ namespace ARMeilleure.CodeGen.X86
// --- This can be done efficiently by adding the result to itself. // --- This can be done efficiently by adding the result to itself.
// -- Then, we need to add the least significant bit that was shifted out. // -- Then, we need to add the least significant bit that was shifted out.
// --- We can convert the least significant bit to float, and add it to the result. // --- We can convert the least significant bit to float, and add it to the result.
Operand lsb = Local(OperandType.I64); Operand lsb = Local(OperandType.I64);
Operand half = Local(OperandType.I64); Operand half = Local(OperandType.I64);
Operand lsbF = Local(dest.Type); Operand lsbF = Local(dest.Type);
node = nodes.AddAfter(node, Operation(Instruction.Copy, lsb, source)); node = nodes.AddAfter(node, Operation(Instruction.Copy, lsb, source));
node = nodes.AddAfter(node, Operation(Instruction.Copy, half, source)); node = nodes.AddAfter(node, Operation(Instruction.Copy, half, source));
node = nodes.AddAfter(node, Operation(Instruction.BitwiseAnd, lsb, lsb, Const(1L))); node = nodes.AddAfter(node, Operation(Instruction.BitwiseAnd, lsb, lsb, Const(1L)));
node = nodes.AddAfter(node, Operation(Instruction.ShiftRightUI, half, half, Const(1))); node = nodes.AddAfter(node, Operation(Instruction.ShiftRightUI, half, half, Const(1)));
node = nodes.AddAfter(node, Operation(Instruction.ConvertToFP, lsbF, lsb)); node = nodes.AddAfter(node, Operation(Instruction.ConvertToFP, lsbF, lsb));
@ -513,7 +510,7 @@ namespace ARMeilleure.CodeGen.X86
// There's no SSE FP negate instruction, so we need to transform that into // There's no SSE FP negate instruction, so we need to transform that into
// a XOR of the value to be negated with a mask with the highest bit set. // a XOR of the value to be negated with a mask with the highest bit set.
// This also produces -0 for a negation of the value 0. // This also produces -0 for a negation of the value 0.
Operand dest = node.Destination; Operand dest = node.Destination;
Operand source = node.GetSource(0); Operand source = node.GetSource(0);
Debug.Assert(dest.Type == OperandType.FP32 || Debug.Assert(dest.Type == OperandType.FP32 ||
@ -569,14 +566,14 @@ namespace ARMeilleure.CodeGen.X86
if ((index & 1) != 0) if ((index & 1) != 0)
{ {
node = nodes.AddAfter(node, Operation(Instruction.ZeroExtend8, temp1, temp1)); node = nodes.AddAfter(node, Operation(Instruction.ZeroExtend8, temp1, temp1));
node = nodes.AddAfter(node, Operation(Instruction.ShiftLeft, temp2, temp2, Const(8))); node = nodes.AddAfter(node, Operation(Instruction.ShiftLeft, temp2, temp2, Const(8)));
node = nodes.AddAfter(node, Operation(Instruction.BitwiseOr, temp1, temp1, temp2)); node = nodes.AddAfter(node, Operation(Instruction.BitwiseOr, temp1, temp1, temp2));
} }
else else
{ {
node = nodes.AddAfter(node, Operation(Instruction.ZeroExtend8, temp2, temp2)); node = nodes.AddAfter(node, Operation(Instruction.ZeroExtend8, temp2, temp2));
node = nodes.AddAfter(node, Operation(Instruction.BitwiseAnd, temp1, temp1, Const(0xff00))); node = nodes.AddAfter(node, Operation(Instruction.BitwiseAnd, temp1, temp1, Const(0xff00)));
node = nodes.AddAfter(node, Operation(Instruction.BitwiseOr, temp1, temp1, temp2)); node = nodes.AddAfter(node, Operation(Instruction.BitwiseOr, temp1, temp1, temp2));
} }
Operation vinsOp = Operation(Instruction.VectorInsert16, dest, src1, temp1, Const(index >> 1)); Operation vinsOp = Operation(Instruction.VectorInsert16, dest, src1, temp1, Const(index >> 1));
@ -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)
@ -762,15 +754,15 @@ namespace ARMeilleure.CodeGen.X86
case Instruction.BranchIf: case Instruction.BranchIf:
case Instruction.Compare: case Instruction.Compare:
{ {
Operand comp = operation.GetSource(2); Operand comp = operation.GetSource(2);
Debug.Assert(comp.Kind == OperandKind.Constant); Debug.Assert(comp.Kind == OperandKind.Constant);
var compType = (Comparison)comp.AsInt32(); var compType = (Comparison)comp.AsInt32();
return compType == Comparison.Equal || compType == Comparison.NotEqual; return compType == Comparison.Equal || compType == Comparison.NotEqual;
} }
} }
return false; return false;

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;
@ -52,10 +51,10 @@ namespace ARMeilleure.CodeGen.X86
if (source.Type == OperandType.V128 && passOnReg) if (source.Type == OperandType.V128 && passOnReg)
{ {
// V128 is a struct, we pass each half on a GPR if possible. // V128 is a struct, we pass each half on a GPR if possible.
Operand argReg = Gpr(CallingConvention.GetIntArgumentRegister(intCount++), OperandType.I64); Operand argReg = Gpr(CallingConvention.GetIntArgumentRegister(intCount++), OperandType.I64);
Operand argReg2 = Gpr(CallingConvention.GetIntArgumentRegister(intCount++), OperandType.I64); Operand argReg2 = Gpr(CallingConvention.GetIntArgumentRegister(intCount++), OperandType.I64);
nodes.AddBefore(node, Operation(Instruction.VectorExtract, argReg, source, Const(0))); nodes.AddBefore(node, Operation(Instruction.VectorExtract, argReg, source, Const(0)));
nodes.AddBefore(node, Operation(Instruction.VectorExtract, argReg2, source, Const(1))); nodes.AddBefore(node, Operation(Instruction.VectorExtract, argReg2, source, Const(1)));
continue; continue;
@ -91,7 +90,7 @@ namespace ARMeilleure.CodeGen.X86
{ {
if (dest.Type == OperandType.V128) if (dest.Type == OperandType.V128)
{ {
Operand retLReg = Gpr(CallingConvention.GetIntReturnRegister(), OperandType.I64); Operand retLReg = Gpr(CallingConvention.GetIntReturnRegister(), OperandType.I64);
Operand retHReg = Gpr(CallingConvention.GetIntReturnRegisterHigh(), OperandType.I64); Operand retHReg = Gpr(CallingConvention.GetIntReturnRegisterHigh(), OperandType.I64);
Operation operation = node; Operation operation = node;
@ -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;
@ -251,11 +250,11 @@ namespace ARMeilleure.CodeGen.X86
// V128 is a struct, we pass each half on a GPR if possible. // V128 is a struct, we pass each half on a GPR if possible.
Operand pArg = Local(OperandType.V128); Operand pArg = Local(OperandType.V128);
Operand argLReg = Gpr(CallingConvention.GetIntArgumentRegister(intCount), OperandType.I64); Operand argLReg = Gpr(CallingConvention.GetIntArgumentRegister(intCount), OperandType.I64);
Operand argHReg = Gpr(CallingConvention.GetIntArgumentRegister(intCount + 1), OperandType.I64); Operand argHReg = Gpr(CallingConvention.GetIntArgumentRegister(intCount + 1), OperandType.I64);
Operation copyL = Operation(Instruction.VectorCreateScalar, pArg, argLReg); Operation copyL = Operation(Instruction.VectorCreateScalar, pArg, argLReg);
Operation copyH = Operation(Instruction.VectorInsert, pArg, pArg, argHReg, Const(1)); Operation copyH = Operation(Instruction.VectorInsert, pArg, pArg, argHReg, Const(1));
cctx.Cfg.Entry.Operations.AddFirst(copyH); cctx.Cfg.Entry.Operations.AddFirst(copyH);
cctx.Cfg.Entry.Operations.AddFirst(copyL); cctx.Cfg.Entry.Operations.AddFirst(copyL);
@ -313,7 +312,7 @@ namespace ARMeilleure.CodeGen.X86
if (source.Type == OperandType.V128) if (source.Type == OperandType.V128)
{ {
Operand retLReg = Gpr(CallingConvention.GetIntReturnRegister(), OperandType.I64); Operand retLReg = Gpr(CallingConvention.GetIntReturnRegister(), OperandType.I64);
Operand retHReg = Gpr(CallingConvention.GetIntReturnRegisterHigh(), OperandType.I64); Operand retHReg = Gpr(CallingConvention.GetIntReturnRegisterHigh(), OperandType.I64);
nodes.AddBefore(node, Operation(Instruction.VectorExtract, retLReg, source, Const(0))); nodes.AddBefore(node, Operation(Instruction.VectorExtract, retLReg, source, Const(0)));

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

@ -5,22 +5,22 @@ namespace ARMeilleure.CodeGen.X86
{ {
enum X86Condition enum X86Condition
{ {
Overflow = 0x0, Overflow = 0x0,
NotOverflow = 0x1, NotOverflow = 0x1,
Below = 0x2, Below = 0x2,
AboveOrEqual = 0x3, AboveOrEqual = 0x3,
Equal = 0x4, Equal = 0x4,
NotEqual = 0x5, NotEqual = 0x5,
BelowOrEqual = 0x6, BelowOrEqual = 0x6,
Above = 0x7, Above = 0x7,
Sign = 0x8, Sign = 0x8,
NotSign = 0x9, NotSign = 0x9,
ParityEven = 0xa, ParityEven = 0xa,
ParityOdd = 0xb, ParityOdd = 0xb,
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,
@ -12,8 +15,8 @@ namespace ARMeilleure.CodeGen.X86
Rbp = 5, Rbp = 5,
Rsi = 6, Rsi = 6,
Rdi = 7, Rdi = 7,
R8 = 8, R8 = 8,
R9 = 9, R9 = 9,
R10 = 10, R10 = 10,
R11 = 11, R11 = 11,
R12 = 12, R12 = 12,
@ -21,21 +24,21 @@ namespace ARMeilleure.CodeGen.X86
R14 = 14, R14 = 14,
R15 = 15, R15 = 15,
Xmm0 = 0, Xmm0 = 0,
Xmm1 = 1, Xmm1 = 1,
Xmm2 = 2, Xmm2 = 2,
Xmm3 = 3, Xmm3 = 3,
Xmm4 = 4, Xmm4 = 4,
Xmm5 = 5, Xmm5 = 5,
Xmm6 = 6, Xmm6 = 6,
Xmm7 = 7, Xmm7 = 7,
Xmm8 = 8, Xmm8 = 8,
Xmm9 = 9, Xmm9 = 9,
Xmm10 = 10, Xmm10 = 10,
Xmm11 = 11, Xmm11 = 11,
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

@ -5,10 +5,10 @@ namespace ARMeilleure.Decoders
{ {
class Block class Block
{ {
public ulong Address { get; set; } public ulong Address { get; set; }
public ulong EndAddress { get; set; } public ulong EndAddress { get; set; }
public Block Next { get; set; } public Block Next { get; set; }
public Block Branch { get; set; } public Block Branch { get; set; }
public bool Exit { get; set; } public bool Exit { get; set; }
@ -43,14 +43,14 @@ namespace ARMeilleure.Decoders
rightBlock.EndAddress = EndAddress; rightBlock.EndAddress = EndAddress;
rightBlock.Next = Next; rightBlock.Next = Next;
rightBlock.Branch = Branch; rightBlock.Branch = Branch;
rightBlock.OpCodes.AddRange(OpCodes.GetRange(splitIndex, splitCount)); rightBlock.OpCodes.AddRange(OpCodes.GetRange(splitIndex, splitCount));
EndAddress = rightBlock.Address; EndAddress = rightBlock.Address;
Next = rightBlock; Next = rightBlock;
Branch = null; Branch = null;
OpCodes.RemoveRange(splitIndex, splitCount); OpCodes.RemoveRange(splitIndex, splitCount);
@ -58,9 +58,9 @@ namespace ARMeilleure.Decoders
private static int BinarySearch(List<OpCode> opCodes, ulong address) private static int BinarySearch(List<OpCode> opCodes, ulong address)
{ {
int left = 0; int left = 0;
int middle = 0; int middle = 0;
int right = opCodes.Count - 1; int right = opCodes.Count - 1;
while (left <= right) while (left <= right)
{ {
@ -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

@ -2,22 +2,22 @@ namespace ARMeilleure.Decoders
{ {
enum Condition enum Condition
{ {
Eq = 0, Eq = 0,
Ne = 1, Ne = 1,
GeUn = 2, GeUn = 2,
LtUn = 3, LtUn = 3,
Mi = 4, Mi = 4,
Pl = 5, Pl = 5,
Vs = 6, Vs = 6,
Vc = 7, Vc = 7,
GtUn = 8, GtUn = 8,
LeUn = 9, LeUn = 9,
Ge = 10, Ge = 10,
Lt = 11, Lt = 11,
Gt = 12, Gt = 12,
Le = 13, Le = 13,
Al = 14, Al = 14,
Nv = 15 Nv = 15,
} }
static class ConditionExtensions static class ConditionExtensions

View file

@ -2,9 +2,9 @@ namespace ARMeilleure.Decoders
{ {
enum DataOp enum DataOp
{ {
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);
@ -163,7 +163,7 @@ namespace ARMeilleure.Decoders
{ {
index = 0; index = 0;
int left = 0; int left = 0;
int right = blocks.Count - 1; int right = blocks.Count - 1;
while (left <= right) while (left <= right)
@ -196,9 +196,9 @@ namespace ARMeilleure.Decoders
private static void FillBlock( private static void FillBlock(
IMemoryManager memory, IMemoryManager memory,
ExecutionMode mode, ExecutionMode mode,
Block block, Block block,
ulong limitAddress) ulong limitAddress)
{ {
ulong address = block.Address; ulong address = block.Address;
int itBlockSize = 0; int itBlockSize = 0;
@ -241,12 +241,12 @@ namespace ARMeilleure.Decoders
private static bool IsUnconditionalBranch(OpCode opCode) private static bool IsUnconditionalBranch(OpCode opCode)
{ {
return opCode is OpCodeBImmAl || return opCode is OpCodeBImmAl ||
opCode is OpCodeBReg || IsAarch32UnconditionalBranch(opCode); opCode is OpCodeBReg || IsAarch32UnconditionalBranch(opCode);
} }
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;
} }
@ -290,9 +290,9 @@ namespace ARMeilleure.Decoders
if (opCode is IOpCode32Mem opMem) if (opCode is IOpCode32Mem opMem)
{ {
rt = opMem.Rt; rt = opMem.Rt;
rn = opMem.Rn; rn = opMem.Rn;
wBack = opMem.WBack; wBack = opMem.WBack;
isLoad = opMem.IsLoad; isLoad = opMem.IsLoad;
// For the dual load, we also need to take into account the // For the dual load, we also need to take into account the
@ -306,10 +306,10 @@ namespace ARMeilleure.Decoders
{ {
const int pcMask = 1 << RegisterAlias.Aarch32Pc; const int pcMask = 1 << RegisterAlias.Aarch32Pc;
rt = (opMemMult.RegisterMask & pcMask) != 0 ? RegisterAlias.Aarch32Pc : 0; rt = (opMemMult.RegisterMask & pcMask) != 0 ? RegisterAlias.Aarch32Pc : 0;
rn = opMemMult.Rn; rn = opMemMult.Rn;
wBack = opMemMult.PostOffset != 0; wBack = opMemMult.PostOffset != 0;
isLoad = opMemMult.IsLoad; isLoad = opMemMult.IsLoad;
} }
else else
{ {

View file

@ -10,7 +10,7 @@ namespace ARMeilleure.Decoders
Imm8ToFP64Table = BuildImm8ToFP64Table(); Imm8ToFP64Table = BuildImm8ToFP64Table();
} }
public static readonly uint[] Imm8ToFP32Table; public static readonly uint[] Imm8ToFP32Table;
public static readonly ulong[] Imm8ToFP64Table; public static readonly ulong[] Imm8ToFP64Table;
private static uint[] BuildImm8ToFP32Table() private static uint[] BuildImm8ToFP32Table()
@ -40,47 +40,47 @@ 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;
} }
return MoveBit(imm, 7, 31) | MoveBit(~imm, 6, 30) | return MoveBit(imm, 7, 31) | MoveBit(~imm, 6, 30) |
MoveBit(imm, 6, 29) | MoveBit( imm, 6, 28) | MoveBit(imm, 6, 29) | MoveBit(imm, 6, 28) |
MoveBit(imm, 6, 27) | MoveBit( imm, 6, 26) | MoveBit(imm, 6, 27) | MoveBit(imm, 6, 26) |
MoveBit(imm, 6, 25) | MoveBit( imm, 5, 24) | MoveBit(imm, 6, 25) | MoveBit(imm, 5, 24) |
MoveBit(imm, 4, 23) | MoveBit( imm, 3, 22) | MoveBit(imm, 4, 23) | MoveBit(imm, 3, 22) |
MoveBit(imm, 2, 21) | MoveBit( imm, 1, 20) | MoveBit(imm, 2, 21) | MoveBit(imm, 1, 20) |
MoveBit(imm, 0, 19); MoveBit(imm, 0, 19);
} }
// 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;
} }
return MoveBit(imm, 7, 63) | MoveBit(~imm, 6, 62) | return MoveBit(imm, 7, 63) | MoveBit(~imm, 6, 62) |
MoveBit(imm, 6, 61) | MoveBit( imm, 6, 60) | MoveBit(imm, 6, 61) | MoveBit(imm, 6, 60) |
MoveBit(imm, 6, 59) | MoveBit( imm, 6, 58) | MoveBit(imm, 6, 59) | MoveBit(imm, 6, 58) |
MoveBit(imm, 6, 57) | MoveBit( imm, 6, 56) | MoveBit(imm, 6, 57) | MoveBit(imm, 6, 56) |
MoveBit(imm, 6, 55) | MoveBit( imm, 6, 54) | MoveBit(imm, 6, 55) | MoveBit(imm, 6, 54) |
MoveBit(imm, 5, 53) | MoveBit( imm, 4, 52) | MoveBit(imm, 5, 53) | MoveBit(imm, 4, 52) |
MoveBit(imm, 3, 51) | MoveBit( imm, 2, 50) | MoveBit(imm, 3, 51) | MoveBit(imm, 2, 50) |
MoveBit(imm, 1, 49) | MoveBit( imm, 0, 48); MoveBit(imm, 1, 49) | MoveBit(imm, 0, 48);
} }
public struct BitMask public struct BitMask
{ {
public long WMask; public long WMask;
public long TMask; public long TMask;
public int Pos; public int Pos;
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)
@ -88,7 +88,7 @@ namespace ARMeilleure.Decoders
int immS = (opCode >> 10) & 0x3f; int immS = (opCode >> 10) & 0x3f;
int immR = (opCode >> 16) & 0x3f; int immR = (opCode >> 16) & 0x3f;
int n = (opCode >> 22) & 1; int n = (opCode >> 22) & 1;
int sf = (opCode >> 31) & 1; int sf = (opCode >> 31) & 1;
int length = BitUtils.HighestBitSet((~immS & 0x3f) | (n << 6)); int length = BitUtils.HighestBitSet((~immS & 0x3f) | (n << 6));
@ -115,7 +115,7 @@ namespace ARMeilleure.Decoders
if (r > 0) if (r > 0)
{ {
wMask = BitUtils.RotateRight(wMask, r, size); wMask = BitUtils.RotateRight(wMask, r, size);
wMask &= BitUtils.FillWithOnes(size); wMask &= BitUtils.FillWithOnes(size);
} }
@ -124,8 +124,8 @@ namespace ARMeilleure.Decoders
WMask = BitUtils.Replicate(wMask, size), WMask = BitUtils.Replicate(wMask, size),
TMask = BitUtils.Replicate(tMask, size), TMask = BitUtils.Replicate(tMask, size),
Pos = immS, Pos = immS,
Shift = immR Shift = immR,
}; };
} }

View file

@ -3,7 +3,7 @@ namespace ARMeilleure.Decoders
interface IOpCodeAluRs : IOpCodeAlu interface IOpCodeAluRs : IOpCodeAlu
{ {
int Shift { get; } int Shift { get; }
int Rm { get; } int Rm { get; }
ShiftType ShiftType { get; } ShiftType ShiftType { get; }
} }

View file

@ -3,7 +3,7 @@ namespace ARMeilleure.Decoders
interface IOpCodeAluRx : IOpCodeAlu interface IOpCodeAluRx : IOpCodeAlu
{ {
int Shift { get; } int Shift { get; }
int Rm { get; } int Rm { get; }
IntType IntType { get; } IntType IntType { get; }
} }

View file

@ -2,10 +2,10 @@ namespace ARMeilleure.Decoders
{ {
interface IOpCodeLit : IOpCode interface IOpCodeLit : IOpCode
{ {
int Rt { get; } int Rt { get; }
long Immediate { get; } long Immediate { get; }
int Size { get; } int Size { get; }
bool Signed { get; } bool Signed { get; }
bool Prefetch { get; } bool Prefetch { get; }
} }
} }

View file

@ -4,14 +4,14 @@ 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; }
public InstDescriptor(InstName name, InstEmitter emitter) public InstDescriptor(InstName name, InstEmitter emitter)
{ {
Name = name; Name = name;
Emitter = emitter; Emitter = emitter;
} }
} }

View file

@ -2,13 +2,13 @@ namespace ARMeilleure.Decoders
{ {
enum IntType enum IntType
{ {
UInt8 = 0, UInt8 = 0,
UInt16 = 1, UInt16 = 1,
UInt32 = 2, UInt32 = 2,
UInt64 = 3, UInt64 = 3,
Int8 = 4, Int8 = 4,
Int16 = 5, Int16 = 5,
Int32 = 6, Int32 = 6,
Int64 = 7 Int64 = 7,
} }
} }

View file

@ -5,8 +5,8 @@ namespace ARMeilleure.Decoders
{ {
class OpCode : IOpCode class OpCode : IOpCode
{ {
public ulong Address { get; } public ulong Address { get; }
public int RawOpCode { get; } public int RawOpCode { get; }
public int OpCodeSizeInBytes { get; protected set; } = 4; public int OpCodeSizeInBytes { get; protected set; } = 4;
@ -14,13 +14,13 @@ 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)
{ {
Instruction = inst; Instruction = inst;
Address = address; Address = address;
RawOpCode = opCode; RawOpCode = opCode;
RegisterSize = RegisterSize.Int64; RegisterSize = RegisterSize.Int64;
} }
@ -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

@ -2,7 +2,7 @@ namespace ARMeilleure.Decoders
{ {
class OpCode32AluRsImm : OpCode32Alu, IOpCode32AluRsImm class OpCode32AluRsImm : OpCode32Alu, IOpCode32AluRsImm
{ {
public int Rm { get; } public int Rm { get; }
public int Immediate { get; } public int Immediate { get; }
public ShiftType ShiftType { get; } public ShiftType ShiftType { get; }
@ -11,7 +11,7 @@ namespace ARMeilleure.Decoders
public OpCode32AluRsImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCode32AluRsImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {
Rm = (opCode >> 0) & 0xf; Rm = (opCode >> 0) & 0xf;
Immediate = (opCode >> 7) & 0x1f; Immediate = (opCode >> 7) & 0x1f;
ShiftType = (ShiftType)((opCode >> 5) & 3); ShiftType = (ShiftType)((opCode >> 5) & 3);

View file

@ -9,9 +9,9 @@ namespace ARMeilleure.Decoders
public int Immediate { get; protected set; } public int Immediate { get; protected set; }
public bool Index { get; } public bool Index { get; }
public bool Add { get; } public bool Add { get; }
public bool WBack { get; } public bool WBack { get; }
public bool Unprivileged { get; } public bool Unprivileged { get; }
public bool IsLoad { get; } public bool IsLoad { get; }
@ -24,13 +24,13 @@ namespace ARMeilleure.Decoders
Rn = (opCode >> 16) & 0xf; Rn = (opCode >> 16) & 0xf;
bool isLoad = (opCode & (1 << 20)) != 0; bool isLoad = (opCode & (1 << 20)) != 0;
bool w = (opCode & (1 << 21)) != 0; bool w = (opCode & (1 << 21)) != 0;
bool u = (opCode & (1 << 23)) != 0; bool u = (opCode & (1 << 23)) != 0;
bool p = (opCode & (1 << 24)) != 0; bool p = (opCode & (1 << 24)) != 0;
Index = p; Index = p;
Add = u; Add = u;
WBack = !p || w; WBack = !p || w;
Unprivileged = !p && w; Unprivileged = !p && w;
IsLoad = isLoad || inst.Name == InstName.Ldrd; IsLoad = isLoad || inst.Name == InstName.Ldrd;

View file

@ -7,8 +7,8 @@ namespace ARMeilleure.Decoders
public int Rn { get; } public int Rn { get; }
public int RegisterMask { get; } public int RegisterMask { get; }
public int Offset { get; } public int Offset { get; }
public int PostOffset { get; } public int PostOffset { get; }
public bool IsLoad { get; } public bool IsLoad { get; }
@ -19,9 +19,9 @@ namespace ARMeilleure.Decoders
Rn = (opCode >> 16) & 0xf; Rn = (opCode >> 16) & 0xf;
bool isLoad = (opCode & (1 << 20)) != 0; bool isLoad = (opCode & (1 << 20)) != 0;
bool w = (opCode & (1 << 21)) != 0; bool w = (opCode & (1 << 21)) != 0;
bool u = (opCode & (1 << 23)) != 0; bool u = (opCode & (1 << 23)) != 0;
bool p = (opCode & (1 << 24)) != 0; bool p = (opCode & (1 << 24)) != 0;
RegisterMask = opCode & 0xffff; RegisterMask = opCode & 0xffff;

View file

@ -2,8 +2,8 @@ namespace ARMeilleure.Decoders
{ {
class OpCode32Mrs : OpCode32 class OpCode32Mrs : OpCode32
{ {
public bool R { get; } public bool R { get; }
public int Rd { get; } public int Rd { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32Mrs(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32Mrs(inst, address, opCode);

View file

@ -4,11 +4,11 @@ namespace ARMeilleure.Decoders
{ {
class OpCode32MsrReg : OpCode32 class OpCode32MsrReg : OpCode32
{ {
public bool R { get; } public bool R { get; }
public int Mask { get; } public int Mask { get; }
public int Rd { get; } public int Rd { get; }
public bool Banked { get; } public bool Banked { get; }
public int Rn { get; } public int Rn { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32MsrReg(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32MsrReg(inst, address, opCode);

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

@ -15,8 +15,8 @@ namespace ARMeilleure.Decoders
{ {
IsThumb = isThumb; IsThumb = isThumb;
Op = ((opCode >> 16) & 0x1) != 0; Op = ((opCode >> 16) & 0x1) != 0;
T = ((opCode >> 7) & 0x1) != 0; T = ((opCode >> 7) & 0x1) != 0;
Size = ((opCode >> 8) & 0x1); Size = ((opCode >> 8) & 0x1);
RegisterSize = Size == 1 ? RegisterSize.Int64 : RegisterSize.Int32; RegisterSize = Size == 1 ? RegisterSize.Int64 : RegisterSize.Int32;

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

@ -6,13 +6,13 @@ namespace ARMeilleure.Decoders
public long Immediate { get; } public long Immediate { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeAdr(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeAdr(inst, address, opCode);
public OpCodeAdr(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCodeAdr(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {
Rd = opCode & 0x1f; Rd = opCode & 0x1f;
Immediate = DecoderHelper.DecodeImmS19_2(opCode); Immediate = DecoderHelper.DecodeImmS19_2(opCode);
Immediate |= ((long)opCode >> 29) & 3; Immediate |= ((long)opCode >> 29) & 3;
} }
} }

View file

@ -11,8 +11,8 @@ namespace ARMeilleure.Decoders
public OpCodeAlu(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCodeAlu(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {
Rd = (opCode >> 0) & 0x1f; Rd = (opCode >> 0) & 0x1f;
Rn = (opCode >> 5) & 0x1f; Rn = (opCode >> 5) & 0x1f;
DataOp = (DataOp)((opCode >> 24) & 0x3); DataOp = (DataOp)((opCode >> 24) & 0x3);
RegisterSize = (opCode >> 31) != 0 RegisterSize = (opCode >> 31) != 0

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

@ -3,7 +3,7 @@ namespace ARMeilleure.Decoders
class OpCodeAluRs : OpCodeAlu, IOpCodeAluRs class OpCodeAluRs : OpCodeAlu, IOpCodeAluRs
{ {
public int Shift { get; } public int Shift { get; }
public int Rm { get; } public int Rm { get; }
public ShiftType ShiftType { get; } public ShiftType ShiftType { get; }
@ -22,7 +22,7 @@ namespace ARMeilleure.Decoders
Shift = shift; Shift = shift;
Rm = (opCode >> 16) & 0x1f; Rm = (opCode >> 16) & 0x1f;
ShiftType = (ShiftType)((opCode >> 22) & 0x3); ShiftType = (ShiftType)((opCode >> 22) & 0x3);
} }
} }

View file

@ -3,7 +3,7 @@ namespace ARMeilleure.Decoders
class OpCodeAluRx : OpCodeAlu, IOpCodeAluRx class OpCodeAluRx : OpCodeAlu, IOpCodeAluRx
{ {
public int Shift { get; } public int Shift { get; }
public int Rm { get; } public int Rm { get; }
public IntType IntType { get; } public IntType IntType { get; }
@ -11,9 +11,9 @@ namespace ARMeilleure.Decoders
public OpCodeAluRx(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCodeAluRx(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {
Shift = (opCode >> 10) & 0x7; Shift = (opCode >> 10) & 0x7;
IntType = (IntType)((opCode >> 13) & 0x7); IntType = (IntType)((opCode >> 13) & 0x7);
Rm = (opCode >> 16) & 0x1f; Rm = (opCode >> 16) & 0x1f;
} }
} }
} }

View file

@ -2,7 +2,7 @@ namespace ARMeilleure.Decoders
{ {
class OpCodeBImmTest : OpCodeBImm class OpCodeBImmTest : OpCodeBImm
{ {
public int Rt { get; } public int Rt { get; }
public int Bit { get; } public int Bit { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeBImmTest(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeBImmTest(inst, address, opCode);
@ -13,7 +13,7 @@ namespace ARMeilleure.Decoders
Immediate = (long)address + DecoderHelper.DecodeImmS14_2(opCode); Immediate = (long)address + DecoderHelper.DecodeImmS14_2(opCode);
Bit = (opCode >> 19) & 0x1f; Bit = (opCode >> 19) & 0x1f;
Bit |= (opCode >> 26) & 0x20; Bit |= (opCode >> 26) & 0x20;
} }
} }

View file

@ -8,7 +8,7 @@ namespace ARMeilleure.Decoders
public OpCodeBReg(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCodeBReg(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {
int op4 = (opCode >> 0) & 0x1f; int op4 = (opCode >> 0) & 0x1f;
int op2 = (opCode >> 16) & 0x1f; int op2 = (opCode >> 16) & 0x1f;
if (op2 != 0b11111 || op4 != 0b00000) if (op2 != 0b11111 || op4 != 0b00000)

View file

@ -4,8 +4,8 @@ namespace ARMeilleure.Decoders
{ {
public long WMask { get; } public long WMask { get; }
public long TMask { get; } public long TMask { get; }
public int Pos { get; } public int Pos { get; }
public int Shift { get; } public int Shift { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeBfm(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeBfm(inst, address, opCode);
@ -22,7 +22,7 @@ namespace ARMeilleure.Decoders
WMask = bm.WMask; WMask = bm.WMask;
TMask = bm.TMask; TMask = bm.TMask;
Pos = bm.Pos; Pos = bm.Pos;
Shift = bm.Shift; Shift = bm.Shift;
} }
} }

View file

@ -4,7 +4,7 @@ namespace ARMeilleure.Decoders
{ {
class OpCodeCcmp : OpCodeAlu, IOpCodeCond class OpCodeCcmp : OpCodeAlu, IOpCodeCond
{ {
public int Nzcv { get; } public int Nzcv { get; }
protected int RmImm; protected int RmImm;
public Condition Cond { get; } public Condition Cond { get; }
@ -22,9 +22,9 @@ namespace ARMeilleure.Decoders
return; return;
} }
Nzcv = (opCode >> 0) & 0xf; Nzcv = (opCode >> 0) & 0xf;
Cond = (Condition)((opCode >> 12) & 0xf); Cond = (Condition)((opCode >> 12) & 0xf);
RmImm = (opCode >> 16) & 0x1f; RmImm = (opCode >> 16) & 0x1f;
Rd = RegisterAlias.Zr; Rd = RegisterAlias.Zr;
} }

View file

@ -10,7 +10,7 @@ namespace ARMeilleure.Decoders
public OpCodeCsel(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCodeCsel(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {
Rm = (opCode >> 16) & 0x1f; Rm = (opCode >> 16) & 0x1f;
Cond = (Condition)((opCode >> 12) & 0xf); Cond = (Condition)((opCode >> 12) & 0xf);
} }
} }

View file

@ -2,17 +2,17 @@ namespace ARMeilleure.Decoders
{ {
class OpCodeMem : OpCode class OpCodeMem : OpCode
{ {
public int Rt { get; protected set; } public int Rt { get; protected set; }
public int Rn { get; protected set; } public int Rn { get; protected set; }
public int Size { get; protected set; } public int Size { get; protected set; }
public bool Extend64 { get; protected set; } public bool Extend64 { get; protected set; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeMem(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeMem(inst, address, opCode);
public OpCodeMem(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCodeMem(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {
Rt = (opCode >> 0) & 0x1f; Rt = (opCode >> 0) & 0x1f;
Rn = (opCode >> 5) & 0x1f; Rn = (opCode >> 5) & 0x1f;
Size = (opCode >> 30) & 0x3; Size = (opCode >> 30) & 0x3;
} }
} }

View file

@ -3,14 +3,14 @@ namespace ARMeilleure.Decoders
class OpCodeMemEx : OpCodeMem class OpCodeMemEx : OpCodeMem
{ {
public int Rt2 { get; } public int Rt2 { get; }
public int Rs { get; } public int Rs { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeMemEx(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeMemEx(inst, address, opCode);
public OpCodeMemEx(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCodeMemEx(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {
Rt2 = (opCode >> 10) & 0x1f; Rt2 = (opCode >> 10) & 0x1f;
Rs = (opCode >> 16) & 0x1f; Rs = (opCode >> 16) & 0x1f;
} }
} }
} }

View file

@ -2,18 +2,18 @@ namespace ARMeilleure.Decoders
{ {
class OpCodeMemImm : OpCodeMem class OpCodeMemImm : OpCodeMem
{ {
public long Immediate { get; protected set; } public long Immediate { get; protected set; }
public bool WBack { get; protected set; } public bool WBack { get; protected set; }
public bool PostIdx { get; protected set; } public bool PostIdx { get; protected set; }
protected bool Unscaled { get; } protected bool Unscaled { get; }
private enum MemOp private enum MemOp
{ {
Unscaled = 0, Unscaled = 0,
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);
@ -21,13 +21,13 @@ namespace ARMeilleure.Decoders
public OpCodeMemImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCodeMemImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {
Extend64 = ((opCode >> 22) & 3) == 2; Extend64 = ((opCode >> 22) & 3) == 2;
WBack = ((opCode >> 24) & 1) == 0; WBack = ((opCode >> 24) & 1) == 0;
// The type is not valid for the Unsigned Immediate 12-bits encoding, // The type is not valid for the Unsigned Immediate 12-bits encoding,
// because the bits 11:10 are used for the larger Immediate offset. // because the bits 11:10 are used for the larger Immediate offset.
MemOp type = WBack ? (MemOp)((opCode >> 10) & 3) : MemOp.Unsigned; MemOp type = WBack ? (MemOp)((opCode >> 10) & 3) : MemOp.Unsigned;
PostIdx = type == MemOp.PostIndexed; PostIdx = type == MemOp.PostIndexed;
Unscaled = type == MemOp.Unscaled || Unscaled = type == MemOp.Unscaled ||
type == MemOp.Unprivileged; type == MemOp.Unprivileged;

View file

@ -2,11 +2,11 @@ namespace ARMeilleure.Decoders
{ {
class OpCodeMemLit : OpCode, IOpCodeLit class OpCodeMemLit : OpCode, IOpCodeLit
{ {
public int Rt { get; } public int Rt { get; }
public long Immediate { get; } public long Immediate { get; }
public int Size { get; } public int Size { get; }
public bool Signed { get; } public bool Signed { get; }
public bool Prefetch { get; } public bool Prefetch { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeMemLit(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeMemLit(inst, address, opCode);
@ -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

@ -8,11 +8,11 @@ namespace ARMeilleure.Decoders
public OpCodeMemPair(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCodeMemPair(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {
Rt2 = (opCode >> 10) & 0x1f; Rt2 = (opCode >> 10) & 0x1f;
WBack = ((opCode >> 23) & 0x1) != 0; WBack = ((opCode >> 23) & 0x1) != 0;
PostIdx = ((opCode >> 23) & 0x3) == 1; PostIdx = ((opCode >> 23) & 0x3) == 1;
Extend64 = ((opCode >> 30) & 0x3) == 1; Extend64 = ((opCode >> 30) & 0x3) == 1;
Size = ((opCode >> 31) & 0x1) | 2; Size = ((opCode >> 31) & 0x1) | 2;
DecodeImm(opCode); DecodeImm(opCode);
} }

View file

@ -3,7 +3,7 @@ namespace ARMeilleure.Decoders
class OpCodeMemReg : OpCodeMem class OpCodeMemReg : OpCodeMem
{ {
public bool Shift { get; } public bool Shift { get; }
public int Rm { get; } public int Rm { get; }
public IntType IntType { get; } public IntType IntType { get; }
@ -11,10 +11,10 @@ namespace ARMeilleure.Decoders
public OpCodeMemReg(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCodeMemReg(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {
Shift = ((opCode >> 12) & 0x1) != 0; Shift = ((opCode >> 12) & 0x1) != 0;
IntType = (IntType)((opCode >> 13) & 0x7); IntType = (IntType)((opCode >> 13) & 0x7);
Rm = (opCode >> 16) & 0x1f; Rm = (opCode >> 16) & 0x1f;
Extend64 = ((opCode >> 22) & 0x3) == 2; Extend64 = ((opCode >> 22) & 0x3) == 2;
} }
} }
} }

View file

@ -22,9 +22,9 @@ namespace ARMeilleure.Decoders
return; return;
} }
Rd = (opCode >> 0) & 0x1f; Rd = (opCode >> 0) & 0x1f;
Immediate = (opCode >> 5) & 0xffff; Immediate = (opCode >> 5) & 0xffff;
Bit = (opCode >> 21) & 0x3; Bit = (opCode >> 21) & 0x3;
Bit <<= 4; Bit <<= 4;

View file

@ -2,18 +2,18 @@ namespace ARMeilleure.Decoders
{ {
class OpCodeSimd : OpCode, IOpCodeSimd class OpCodeSimd : OpCode, IOpCodeSimd
{ {
public int Rd { get; } public int Rd { get; }
public int Rn { get; } public int Rn { get; }
public int Opc { get; } public int Opc { get; }
public int Size { get; protected set; } public int Size { get; protected set; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeSimd(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeSimd(inst, address, opCode);
public OpCodeSimd(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCodeSimd(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {
Rd = (opCode >> 0) & 0x1f; Rd = (opCode >> 0) & 0x1f;
Rn = (opCode >> 5) & 0x1f; Rn = (opCode >> 5) & 0x1f;
Opc = (opCode >> 15) & 0x3; Opc = (opCode >> 15) & 0x3;
Size = (opCode >> 22) & 0x3; Size = (opCode >> 22) & 0x3;
RegisterSize = ((opCode >> 30) & 1) != 0 RegisterSize = ((opCode >> 30) & 1) != 0

View file

@ -9,7 +9,7 @@ namespace ARMeilleure.Decoders
public OpCodeSimdCvt(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCodeSimdCvt(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {
int scale = (opCode >> 10) & 0x3f; int scale = (opCode >> 10) & 0x3f;
int sf = (opCode >> 31) & 0x1; int sf = (opCode >> 31) & 0x1;
FBits = 64 - scale; FBits = 64 - scale;

View file

@ -10,7 +10,7 @@ namespace ARMeilleure.Decoders
public OpCodeSimdFcond(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCodeSimdFcond(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {
Nzcv = (opCode >> 0) & 0xf; Nzcv = (opCode >> 0) & 0xf;
Cond = (Condition)((opCode >> 12) & 0xf); Cond = (Condition)((opCode >> 12) & 0xf);
} }
} }

View file

@ -2,9 +2,9 @@ namespace ARMeilleure.Decoders
{ {
class OpCodeSimdFmov : OpCode, IOpCodeSimd class OpCodeSimdFmov : OpCode, IOpCodeSimd
{ {
public int Rd { get; } public int Rd { get; }
public long Immediate { get; } public long Immediate { get; }
public int Size { get; } public int Size { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeSimdFmov(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeSimdFmov(inst, address, opCode);
@ -16,7 +16,7 @@ namespace ARMeilleure.Decoders
long imm; long imm;
Rd = (opCode >> 0) & 0x1f; Rd = (opCode >> 0) & 0x1f;
imm = (opCode >> 13) & 0xff; imm = (opCode >> 13) & 0xff;
if (type == 0) if (type == 0)

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

@ -2,9 +2,9 @@ namespace ARMeilleure.Decoders
{ {
class OpCodeSimdImm : OpCode, IOpCodeSimd class OpCodeSimdImm : OpCode, IOpCodeSimd
{ {
public int Rd { get; } public int Rd { get; }
public long Immediate { get; } public long Immediate { get; }
public int Size { get; } public int Size { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeSimdImm(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeSimdImm(inst, address, opCode);
@ -13,14 +13,14 @@ namespace ARMeilleure.Decoders
Rd = opCode & 0x1f; Rd = opCode & 0x1f;
int cMode = (opCode >> 12) & 0xf; int cMode = (opCode >> 12) & 0xf;
int op = (opCode >> 29) & 0x1; int op = (opCode >> 29) & 0x1;
int modeLow = cMode & 1; int modeLow = cMode & 1;
int modeHigh = cMode >> 1; int modeHigh = cMode >> 1;
long imm; long imm;
imm = ((uint)opCode >> 5) & 0x1f; imm = ((uint)opCode >> 5) & 0x1f;
imm |= ((uint)opCode >> 11) & 0xe0; imm |= ((uint)opCode >> 11) & 0xe0;
if (modeHigh == 0b111) if (modeHigh == 0b111)
@ -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,13 +23,21 @@ 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;
DstIndex = imm5 >> (Size + 1); DstIndex = imm5 >> (Size + 1);
} }
} }

View file

@ -2,10 +2,10 @@ namespace ARMeilleure.Decoders
{ {
class OpCodeSimdMemLit : OpCode, IOpCodeSimd, IOpCodeLit class OpCodeSimdMemLit : OpCode, IOpCodeSimd, IOpCodeLit
{ {
public int Rt { get; } public int Rt { get; }
public long Immediate { get; } public long Immediate { get; }
public int Size { get; } public int Size { get; }
public bool Signed => false; public bool Signed => false;
public bool Prefetch => false; public bool Prefetch => false;
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeSimdMemLit(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeSimdMemLit(inst, address, opCode);

View file

@ -2,10 +2,10 @@ namespace ARMeilleure.Decoders
{ {
class OpCodeSimdMemMs : OpCodeMemReg, IOpCodeSimd class OpCodeSimdMemMs : OpCodeMemReg, IOpCodeSimd
{ {
public int Reps { get; } public int Reps { get; }
public int SElems { get; } public int SElems { get; }
public int Elems { get; } public int Elems { get; }
public bool WBack { get; } public bool WBack { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeSimdMemMs(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeSimdMemMs(inst, address, opCode);
@ -13,18 +13,41 @@ 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;
WBack = ((opCode >> 23) & 1) != 0; WBack = ((opCode >> 23) & 1) != 0;
bool q = ((opCode >> 30) & 1) != 0; bool q = ((opCode >> 30) & 1) != 0;

View file

@ -2,21 +2,21 @@ namespace ARMeilleure.Decoders
{ {
class OpCodeSimdMemSs : OpCodeMemReg, IOpCodeSimd class OpCodeSimdMemSs : OpCodeMemReg, IOpCodeSimd
{ {
public int SElems { get; } public int SElems { get; }
public int Index { get; } public int Index { get; }
public bool Replicate { get; } public bool Replicate { get; }
public bool WBack { get; } public bool WBack { get; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeSimdMemSs(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeSimdMemSs(inst, address, opCode);
public OpCodeSimdMemSs(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCodeSimdMemSs(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {
int size = (opCode >> 10) & 3; int size = (opCode >> 10) & 3;
int s = (opCode >> 12) & 1; int s = (opCode >> 12) & 1;
int sElems = (opCode >> 12) & 2; int sElems = (opCode >> 12) & 2;
int scale = (opCode >> 14) & 3; int scale = (opCode >> 14) & 3;
int l = (opCode >> 22) & 1; int l = (opCode >> 22) & 1;
int q = (opCode >> 30) & 1; int q = (opCode >> 30) & 1;
sElems |= (opCode >> 21) & 1; sElems |= (opCode >> 21) & 1;
@ -27,63 +27,63 @@ namespace ARMeilleure.Decoders
switch (scale) switch (scale)
{ {
case 1: case 1:
{
if ((size & 1) != 0)
{ {
Instruction = InstDescriptor.Undefined; if ((size & 1) != 0)
{
Instruction = InstDescriptor.Undefined;
return; return;
}
index >>= 1;
break;
} }
index >>= 1;
break;
}
case 2: case 2:
{
if ((size & 2) != 0 ||
((size & 1) != 0 && s != 0))
{ {
Instruction = InstDescriptor.Undefined; if ((size & 2) != 0 ||
((size & 1) != 0 && s != 0))
{
Instruction = InstDescriptor.Undefined;
return; return;
}
if ((size & 1) != 0)
{
index >>= 3;
scale = 3;
}
else
{
index >>= 2;
}
break;
} }
if ((size & 1) != 0)
{
index >>= 3;
scale = 3;
}
else
{
index >>= 2;
}
break;
}
case 3: case 3:
{
if (l == 0 || s != 0)
{ {
Instruction = InstDescriptor.Undefined; if (l == 0 || s != 0)
{
Instruction = InstDescriptor.Undefined;
return; return;
}
scale = size;
Replicate = true;
break;
} }
scale = size;
Replicate = true;
break;
}
} }
Index = index; Index = index;
SElems = sElems; SElems = sElems;
Size = scale; Size = scale;
Extend64 = false; Extend64 = false;

View file

@ -3,16 +3,16 @@ namespace ARMeilleure.Decoders
class OpCodeSimdReg : OpCodeSimd class OpCodeSimdReg : OpCodeSimd
{ {
public bool Bit3 { get; } public bool Bit3 { get; }
public int Ra { get; } public int Ra { get; }
public int Rm { get; protected set; } public int Rm { get; protected set; }
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeSimdReg(inst, address, opCode); public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeSimdReg(inst, address, opCode);
public OpCodeSimdReg(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCodeSimdReg(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {
Bit3 = ((opCode >> 3) & 0x1) != 0; Bit3 = ((opCode >> 3) & 0x1) != 0;
Ra = (opCode >> 10) & 0x1f; Ra = (opCode >> 10) & 0x1f;
Rm = (opCode >> 16) & 0x1f; Rm = (opCode >> 16) & 0x1f;
} }
} }
} }

View file

@ -12,7 +12,7 @@ namespace ARMeilleure.Decoders
{ {
case 1: case 1:
Index = (opCode >> 20) & 3 | Index = (opCode >> 20) & 3 |
(opCode >> 9) & 4; (opCode >> 9) & 4;
Rm &= 0xf; Rm &= 0xf;
@ -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

@ -2,7 +2,7 @@ namespace ARMeilleure.Decoders
{ {
class OpCodeSystem : OpCode class OpCodeSystem : OpCode
{ {
public int Rt { get; } public int Rt { get; }
public int Op2 { get; } public int Op2 { get; }
public int CRm { get; } public int CRm { get; }
public int CRn { get; } public int CRn { get; }
@ -13,11 +13,11 @@ namespace ARMeilleure.Decoders
public OpCodeSystem(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCodeSystem(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {
Rt = (opCode >> 0) & 0x1f; Rt = (opCode >> 0) & 0x1f;
Op2 = (opCode >> 5) & 0x7; Op2 = (opCode >> 5) & 0x7;
CRm = (opCode >> 8) & 0xf; CRm = (opCode >> 8) & 0xf;
CRn = (opCode >> 12) & 0xf; CRn = (opCode >> 12) & 0xf;
Op1 = (opCode >> 16) & 0x7; Op1 = (opCode >> 16) & 0x7;
Op0 = ((opCode >> 19) & 0x1) | 2; Op0 = ((opCode >> 19) & 0x1) | 2;
} }
} }

View file

@ -1,6 +1,6 @@
namespace ARMeilleure.Decoders namespace ARMeilleure.Decoders
{ {
class OpCodeT16AddSubImm3: OpCodeT16, IOpCode32AluImm class OpCodeT16AddSubImm3 : OpCodeT16, IOpCode32AluImm
{ {
public int Rd { get; } public int Rd { get; }
public int Rn { get; } public int Rn { get; }
@ -15,8 +15,8 @@
public OpCodeT16AddSubImm3(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode) public OpCodeT16AddSubImm3(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{ {
Rd = (opCode >> 0) & 0x7; Rd = (opCode >> 0) & 0x7;
Rn = (opCode >> 3) & 0x7; Rn = (opCode >> 3) & 0x7;
Immediate = (opCode >> 6) & 0x7; Immediate = (opCode >> 6) & 0x7;
IsRotated = false; IsRotated = false;
} }

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