mirror of
https://git.naxdy.org/Mirror/Ryujinx.git
synced 2025-01-13 14:19:12 +00:00
Merge branch 'Ryujinx:master' into features/crash-verification-ex
This commit is contained in:
commit
96e1cb51af
640 changed files with 7718 additions and 7156 deletions
|
@ -21,7 +21,7 @@
|
|||
<PackageVersion Include="LibHac" Version="0.18.0" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
|
||||
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.5.0" />
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.6.2" />
|
||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.6.3" />
|
||||
<PackageVersion Include="Microsoft.IO.RecyclableMemoryStream" Version="2.3.2" />
|
||||
<PackageVersion Include="MsgPack.Cli" Version="1.0.1" />
|
||||
<PackageVersion Include="NUnit" Version="3.13.3" />
|
||||
|
|
|
@ -23,10 +23,7 @@ namespace ARMeilleure
|
|||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static ArenaAllocator GetAllocator(ref ArenaAllocator alloc, uint pageSize, uint pageCount)
|
||||
{
|
||||
if (alloc == null)
|
||||
{
|
||||
alloc = new ArenaAllocator(pageSize, pageCount);
|
||||
}
|
||||
alloc ??= new ArenaAllocator(pageSize, pageCount);
|
||||
|
||||
return alloc;
|
||||
}
|
||||
|
|
|
@ -221,7 +221,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
2 => Multiplier.x4,
|
||||
3 => Multiplier.x8,
|
||||
4 => Multiplier.x16,
|
||||
_ => Multiplier.x1
|
||||
_ => Multiplier.x1,
|
||||
};
|
||||
|
||||
baseOp = indexOnSrc2 ? src1 : src2;
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
Gt = 12,
|
||||
Le = 13,
|
||||
Al = 14,
|
||||
Nv = 15
|
||||
Nv = 15,
|
||||
}
|
||||
|
||||
static class ComparisonArm64Extensions
|
||||
|
@ -29,6 +29,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
{
|
||||
return comp switch
|
||||
{
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
Comparison.Equal => ArmCondition.Eq,
|
||||
Comparison.NotEqual => ArmCondition.Ne,
|
||||
Comparison.Greater => ArmCondition.Gt,
|
||||
|
@ -39,8 +40,9 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
Comparison.Less => ArmCondition.Lt,
|
||||
Comparison.GreaterOrEqualUI => ArmCondition.GeUn,
|
||||
Comparison.LessUI => ArmCondition.LtUn,
|
||||
#pragma warning restore IDE0055
|
||||
|
||||
_ => throw new ArgumentException(null, nameof(comp))
|
||||
_ => throw new ArgumentException(null, nameof(comp)),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,6 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
Sxtb = 4,
|
||||
Sxth = 5,
|
||||
Sxtw = 6,
|
||||
Sxtx = 7
|
||||
Sxtx = 7,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,6 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
Lsl = 0,
|
||||
Lsr = 1,
|
||||
Asr = 2,
|
||||
Ror = 3
|
||||
Ror = 3,
|
||||
}
|
||||
}
|
|
@ -992,7 +992,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
{
|
||||
OperandType.FP32 => 0,
|
||||
OperandType.FP64 => 1,
|
||||
_ => 2
|
||||
_ => 2,
|
||||
};
|
||||
|
||||
instruction = vecInst | ((uint)opc << 30);
|
||||
|
@ -1124,10 +1124,11 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
OperandType.FP32 => 2,
|
||||
OperandType.FP64 => 3,
|
||||
OperandType.V128 => 4,
|
||||
_ => throw new ArgumentException($"Invalid type {type}.")
|
||||
_ => throw new ArgumentException($"Invalid type {type}."),
|
||||
};
|
||||
}
|
||||
|
||||
#pragma warning disable IDE0051 // Remove unused private member
|
||||
private void WriteInt16(short value)
|
||||
{
|
||||
WriteUInt16((ushort)value);
|
||||
|
@ -1142,6 +1143,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
{
|
||||
_stream.WriteByte(value);
|
||||
}
|
||||
#pragma warning restore IDE0051
|
||||
|
||||
private void WriteUInt16(ushort value)
|
||||
{
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
private const int CbnzInstLength = 4;
|
||||
private const int LdrLitInstLength = 4;
|
||||
|
||||
private Stream _stream;
|
||||
private readonly Stream _stream;
|
||||
|
||||
public int StreamOffset => (int)_stream.Length;
|
||||
|
||||
|
@ -32,7 +32,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
private readonly Dictionary<BasicBlock, long> _visitedBlocks;
|
||||
private readonly Dictionary<BasicBlock, List<(ArmCondition Condition, long BranchPos)>> _pendingBranches;
|
||||
|
||||
private struct ConstantPoolEntry
|
||||
private readonly struct ConstantPoolEntry
|
||||
{
|
||||
public readonly int Offset;
|
||||
public readonly Symbol Symbol;
|
||||
|
@ -58,7 +58,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
|
||||
private readonly bool _relocatable;
|
||||
|
||||
public CodeGenContext(AllocationResult allocResult, int maxCallArgs, int blocksCount, bool relocatable)
|
||||
public CodeGenContext(AllocationResult allocResult, int maxCallArgs, bool relocatable)
|
||||
{
|
||||
_stream = MemoryStreamManager.Shared.GetStream();
|
||||
|
||||
|
@ -93,10 +93,10 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
|
||||
if (_pendingBranches.TryGetValue(block, out var list))
|
||||
{
|
||||
foreach (var tuple in list)
|
||||
foreach ((ArmCondition condition, long branchPos) in list)
|
||||
{
|
||||
_stream.Seek(tuple.BranchPos, SeekOrigin.Begin);
|
||||
WriteBranch(tuple.Condition, target);
|
||||
_stream.Seek(branchPos, SeekOrigin.Begin);
|
||||
WriteBranch(condition, target);
|
||||
}
|
||||
|
||||
_stream.Seek(target, SeekOrigin.Begin);
|
||||
|
|
|
@ -10,7 +10,6 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Numerics;
|
||||
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
||||
|
@ -31,15 +30,16 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
{
|
||||
Byte,
|
||||
Hword,
|
||||
Auto
|
||||
Auto,
|
||||
}
|
||||
|
||||
private static Action<CodeGenContext, Operation>[] _instTable;
|
||||
private static readonly Action<CodeGenContext, Operation>[] _instTable;
|
||||
|
||||
static CodeGenerator()
|
||||
{
|
||||
_instTable = new Action<CodeGenContext, Operation>[EnumUtils.GetCount(typeof(Instruction))];
|
||||
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
Add(Instruction.Add, GenerateAdd);
|
||||
Add(Instruction.BitwiseAnd, GenerateBitwiseAnd);
|
||||
Add(Instruction.BitwiseExclusiveOr, GenerateBitwiseExclusiveOr);
|
||||
|
@ -100,6 +100,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
Add(Instruction.ZeroExtend16, GenerateZeroExtend16);
|
||||
Add(Instruction.ZeroExtend32, GenerateZeroExtend32);
|
||||
Add(Instruction.ZeroExtend8, GenerateZeroExtend8);
|
||||
#pragma warning restore IDE0055
|
||||
|
||||
static void Add(Instruction inst, Action<CodeGenContext, Operation> func)
|
||||
{
|
||||
|
@ -131,7 +132,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
|
||||
StackAllocator stackAlloc = new();
|
||||
|
||||
PreAllocator.RunPass(cctx, stackAlloc, out int maxCallArgs);
|
||||
PreAllocator.RunPass(cctx, out int maxCallArgs);
|
||||
|
||||
Logger.EndPass(PassName.PreAllocation, cfg);
|
||||
|
||||
|
@ -170,7 +171,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
|
||||
bool relocatable = (cctx.Options & CompilerOptions.Relocatable) != 0;
|
||||
|
||||
CodeGenContext context = new(allocResult, maxCallArgs, cfg.Blocks.Count, relocatable);
|
||||
CodeGenContext context = new(allocResult, maxCallArgs, relocatable);
|
||||
|
||||
UnwindInfo unwindInfo = WritePrologue(context);
|
||||
|
||||
|
@ -1078,7 +1079,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
|
||||
private static UnwindInfo WritePrologue(CodeGenContext context)
|
||||
{
|
||||
List<UnwindPushEntry> pushEntries = new List<UnwindPushEntry>();
|
||||
List<UnwindPushEntry> pushEntries = new();
|
||||
|
||||
Operand rsp = Register(SpRegister);
|
||||
|
||||
|
@ -1568,11 +1569,13 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
Debug.Assert(op1.Type == op3.Type);
|
||||
}
|
||||
|
||||
#pragma warning disable IDE0051 // Remove unused private member
|
||||
private static void EnsureSameType(Operand op1, Operand op2, Operand op3, Operand op4)
|
||||
{
|
||||
Debug.Assert(op1.Type == op2.Type);
|
||||
Debug.Assert(op1.Type == op3.Type);
|
||||
Debug.Assert(op1.Type == op4.Type);
|
||||
}
|
||||
#pragma warning restore IDE0051
|
||||
}
|
||||
}
|
|
@ -1,7 +1,4 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Runtime.Intrinsics.Arm;
|
||||
using System.Runtime.Versioning;
|
||||
|
@ -77,7 +74,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
Ssbs = 1 << 28,
|
||||
Sb = 1 << 29,
|
||||
Paca = 1 << 30,
|
||||
Pacg = 1UL << 31
|
||||
Pacg = 1UL << 31,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
|
@ -119,7 +116,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
Sve_Ebf16 = 1UL << 33,
|
||||
Cssc = 1UL << 34,
|
||||
Rprfm = 1UL << 35,
|
||||
Sve2p1 = 1UL << 36
|
||||
Sve2p1 = 1UL << 36,
|
||||
}
|
||||
|
||||
public static LinuxFeatureFlagsHwCap LinuxFeatureInfoHwCap { get; } = 0;
|
||||
|
@ -143,7 +140,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
return false;
|
||||
}
|
||||
|
||||
private static string[] _sysctlNames = new string[]
|
||||
private static readonly string[] _sysctlNames = new string[]
|
||||
{
|
||||
"hw.optional.floatingpoint",
|
||||
"hw.optional.AdvSIMD",
|
||||
|
@ -153,7 +150,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
"hw.optional.arm.FEAT_LSE",
|
||||
"hw.optional.armv8_crc32",
|
||||
"hw.optional.arm.FEAT_SHA1",
|
||||
"hw.optional.arm.FEAT_SHA256"
|
||||
"hw.optional.arm.FEAT_SHA256",
|
||||
};
|
||||
|
||||
[Flags]
|
||||
|
@ -167,7 +164,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
Lse = 1 << 5,
|
||||
Crc32 = 1 << 6,
|
||||
Sha1 = 1 << 7,
|
||||
Sha256 = 1 << 8
|
||||
Sha256 = 1 << 8,
|
||||
}
|
||||
|
||||
public static MacOsFeatureFlags MacOsFeatureInfo { get; } = 0;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
namespace ARMeilleure.CodeGen.Arm64
|
||||
{
|
||||
struct IntrinsicInfo
|
||||
readonly struct IntrinsicInfo
|
||||
{
|
||||
public uint Inst { get; }
|
||||
public IntrinsicType Type { get; }
|
||||
|
|
|
@ -5,12 +5,13 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
{
|
||||
static class IntrinsicTable
|
||||
{
|
||||
private static IntrinsicInfo[] _intrinTable;
|
||||
private static readonly IntrinsicInfo[] _intrinTable;
|
||||
|
||||
static IntrinsicTable()
|
||||
{
|
||||
_intrinTable = new IntrinsicInfo[EnumUtils.GetCount(typeof(Intrinsic))];
|
||||
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
Add(Intrinsic.Arm64AbsS, new IntrinsicInfo(0x5e20b800u, IntrinsicType.ScalarUnary));
|
||||
Add(Intrinsic.Arm64AbsV, new IntrinsicInfo(0x0e20b800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64AddhnV, new IntrinsicInfo(0x0e204000u, IntrinsicType.VectorTernaryRd));
|
||||
|
@ -448,6 +449,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
Add(Intrinsic.Arm64XtnV, new IntrinsicInfo(0x0e212800u, IntrinsicType.VectorUnary));
|
||||
Add(Intrinsic.Arm64Zip1V, new IntrinsicInfo(0x0e003800u, IntrinsicType.VectorBinary));
|
||||
Add(Intrinsic.Arm64Zip2V, new IntrinsicInfo(0x0e007800u, IntrinsicType.VectorBinary));
|
||||
#pragma warning restore IDE0055
|
||||
}
|
||||
|
||||
private static void Add(Intrinsic intrin, IntrinsicInfo info)
|
||||
|
|
|
@ -55,6 +55,6 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
VectorTernaryShrRd,
|
||||
|
||||
GetRegister,
|
||||
SetRegister
|
||||
SetRegister,
|
||||
}
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
using ARMeilleure.CodeGen.RegisterAllocators;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
|
@ -31,7 +30,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
}
|
||||
}
|
||||
|
||||
public static void RunPass(CompilerContext cctx, StackAllocator stackAlloc, out int maxCallArgs)
|
||||
public static void RunPass(CompilerContext cctx, out int maxCallArgs)
|
||||
{
|
||||
maxCallArgs = -1;
|
||||
|
||||
|
@ -41,7 +40,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
|
||||
for (BasicBlock block = cctx.Cfg.Blocks.First; block != null; block = block.ListNext)
|
||||
{
|
||||
ConstantDict constants = new ConstantDict();
|
||||
ConstantDict constants = new();
|
||||
|
||||
Operation nextNode;
|
||||
|
||||
|
@ -92,7 +91,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
InsertReturnCopy(block.Operations, node);
|
||||
break;
|
||||
case Instruction.Tailcall:
|
||||
InsertTailcallCopies(constants, block.Operations, stackAlloc, node, node);
|
||||
InsertTailcallCopies(constants, block.Operations, node, node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -138,10 +137,7 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
{
|
||||
src2 = node.GetSource(1);
|
||||
|
||||
Operand temp = src1;
|
||||
|
||||
src1 = src2;
|
||||
src2 = temp;
|
||||
(src2, src1) = (src1, src2);
|
||||
|
||||
node.SetSource(0, src1);
|
||||
node.SetSource(1, src2);
|
||||
|
@ -265,9 +261,9 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
|
||||
Operand dest = operation.Destination;
|
||||
|
||||
List<Operand> sources = new List<Operand>
|
||||
List<Operand> sources = new()
|
||||
{
|
||||
operation.GetSource(0)
|
||||
operation.GetSource(0),
|
||||
};
|
||||
|
||||
int argsCount = operation.SourcesCount - 1;
|
||||
|
@ -364,16 +360,14 @@ namespace ARMeilleure.CodeGen.Arm64
|
|||
operation.SetSources(sources.ToArray());
|
||||
}
|
||||
|
||||
private static void InsertTailcallCopies(
|
||||
ConstantDict constants,
|
||||
private static void InsertTailcallCopies(ConstantDict constants,
|
||||
IntrusiveList<Operation> nodes,
|
||||
StackAllocator stackAlloc,
|
||||
Operation node,
|
||||
Operation operation)
|
||||
{
|
||||
List<Operand> sources = new List<Operand>
|
||||
List<Operand> sources = new()
|
||||
{
|
||||
operation.GetSource(0)
|
||||
operation.GetSource(0),
|
||||
};
|
||||
|
||||
int argsCount = operation.SourcesCount - 1;
|
||||
|
|
|
@ -23,6 +23,6 @@
|
|||
/// <summary>
|
||||
/// Refers to a special symbol which is handled by <see cref="Translation.PTC.Ptc.PatchCode"/>.
|
||||
/// </summary>
|
||||
Special
|
||||
Special,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -171,13 +171,12 @@ namespace ARMeilleure.CodeGen.Optimizations
|
|||
|
||||
private static ulong AllOnes(OperandType type)
|
||||
{
|
||||
switch (type)
|
||||
return type switch
|
||||
{
|
||||
case OperandType.I32: return ~0U;
|
||||
case OperandType.I64: return ~0UL;
|
||||
}
|
||||
|
||||
throw new ArgumentException("Invalid operand type \"" + type + "\".");
|
||||
OperandType.I32 => ~0U,
|
||||
OperandType.I64 => ~0UL,
|
||||
_ => throw new ArgumentException("Invalid operand type \"" + type + "\"."),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
using ARMeilleure.IntermediateRepresentation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operation.Factory;
|
||||
|
||||
|
@ -42,13 +41,13 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
public void Sequence(List<Operation> sequence)
|
||||
{
|
||||
Dictionary<Register, Register> locations = new Dictionary<Register, Register>();
|
||||
Dictionary<Register, Register> sources = new Dictionary<Register, Register>();
|
||||
Dictionary<Register, Register> locations = new();
|
||||
Dictionary<Register, Register> sources = new();
|
||||
|
||||
Dictionary<Register, OperandType> types = new Dictionary<Register, OperandType>();
|
||||
Dictionary<Register, OperandType> types = new();
|
||||
|
||||
Queue<Register> pendingQueue = new Queue<Register>();
|
||||
Queue<Register> readyQueue = new Queue<Register>();
|
||||
Queue<Register> pendingQueue = new();
|
||||
Queue<Register> readyQueue = new();
|
||||
|
||||
foreach (Copy copy in _copies)
|
||||
{
|
||||
|
@ -186,10 +185,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
private void AddSplitFill(LiveInterval left, LiveInterval right, OperandType type)
|
||||
{
|
||||
if (_fillQueue == null)
|
||||
{
|
||||
_fillQueue = new Queue<Operation>();
|
||||
}
|
||||
_fillQueue ??= new Queue<Operation>();
|
||||
|
||||
Operand register = GetRegister(right.Register, type);
|
||||
Operand offset = Const(left.SpillOffset);
|
||||
|
@ -201,10 +197,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
private void AddSplitSpill(LiveInterval left, LiveInterval right, OperandType type)
|
||||
{
|
||||
if (_spillQueue == null)
|
||||
{
|
||||
_spillQueue = new Queue<Operation>();
|
||||
}
|
||||
_spillQueue ??= new Queue<Operation>();
|
||||
|
||||
Operand offset = Const(right.SpillOffset);
|
||||
Operand register = GetRegister(left.Register, type);
|
||||
|
@ -216,10 +209,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
private void AddSplitCopy(LiveInterval left, LiveInterval right, OperandType type)
|
||||
{
|
||||
if (_parallelCopy == null)
|
||||
{
|
||||
_parallelCopy = new ParallelCopy();
|
||||
}
|
||||
_parallelCopy ??= new ParallelCopy();
|
||||
|
||||
_parallelCopy.AddCopy(right.Register, left.Register, type);
|
||||
|
||||
|
@ -228,7 +218,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
public Operation[] Sequence()
|
||||
{
|
||||
List<Operation> sequence = new List<Operation>();
|
||||
List<Operation> sequence = new();
|
||||
|
||||
if (_spillQueue != null)
|
||||
{
|
||||
|
|
|
@ -39,7 +39,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
private int _first;
|
||||
private int _last;
|
||||
|
||||
public bool IsBlockLocal => _first == _last;
|
||||
public readonly bool IsBlockLocal => _first == _last;
|
||||
|
||||
public LocalInfo(OperandType type, int uses, int blkIndex)
|
||||
{
|
||||
|
|
|
@ -545,7 +545,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
_intervals.Insert(insertIndex, interval);
|
||||
}
|
||||
|
||||
private void Spill(AllocationContext context, LiveInterval interval)
|
||||
private static void Spill(AllocationContext context, LiveInterval interval)
|
||||
{
|
||||
Debug.Assert(!interval.IsFixed, "Trying to spill a fixed interval.");
|
||||
Debug.Assert(interval.UsesCount == 0, "Trying to spill a interval with uses.");
|
||||
|
@ -561,7 +561,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
private void InsertSplitCopies()
|
||||
{
|
||||
Dictionary<int, CopyResolver> copyResolvers = new Dictionary<int, CopyResolver>();
|
||||
Dictionary<int, CopyResolver> copyResolvers = new();
|
||||
|
||||
CopyResolver GetCopyResolver(int position)
|
||||
{
|
||||
|
@ -676,10 +676,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
if (left != default && right != default && left != right)
|
||||
{
|
||||
if (copyResolver == null)
|
||||
{
|
||||
copyResolver = new CopyResolver();
|
||||
}
|
||||
copyResolver ??= new CopyResolver();
|
||||
|
||||
copyResolver.AddSplit(left, right);
|
||||
}
|
||||
|
@ -862,8 +859,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
// Compute local live sets.
|
||||
for (BasicBlock block = cfg.Blocks.First; block != null; block = block.ListNext)
|
||||
{
|
||||
BitMap liveGen = new BitMap(Allocators.Default, mapSize);
|
||||
BitMap liveKill = new BitMap(Allocators.Default, mapSize);
|
||||
BitMap liveGen = new(Allocators.Default, mapSize);
|
||||
BitMap liveKill = new(Allocators.Default, mapSize);
|
||||
|
||||
for (Operation node = block.Operations.First; node != default; node = node.ListNext)
|
||||
{
|
||||
|
@ -1061,7 +1058,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
{
|
||||
int regIndex = BitOperations.TrailingZeroCount(mask);
|
||||
|
||||
Register callerSavedReg = new Register(regIndex, regType);
|
||||
Register callerSavedReg = new(regIndex, regType);
|
||||
|
||||
LiveInterval interval = _intervals[GetRegisterId(callerSavedReg)];
|
||||
|
||||
|
|
|
@ -240,8 +240,10 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
public LiveInterval Split(int position)
|
||||
{
|
||||
LiveInterval result = new(Local, Parent);
|
||||
result.End = End;
|
||||
LiveInterval result = new(Local, Parent)
|
||||
{
|
||||
End = End,
|
||||
};
|
||||
|
||||
LiveRange prev = PrevRange;
|
||||
LiveRange curr = CurrRange;
|
||||
|
|
|
@ -8,8 +8,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
private int _count;
|
||||
private int _capacity;
|
||||
|
||||
public int Count => _count;
|
||||
public Span<LiveInterval> Span => new(_items, _count);
|
||||
public readonly int Count => _count;
|
||||
public readonly Span<LiveInterval> Span => new(_items, _count);
|
||||
|
||||
public void Add(LiveInterval interval)
|
||||
{
|
||||
|
|
|
@ -6,15 +6,15 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
{
|
||||
private int* _items;
|
||||
private int _capacity;
|
||||
private int _count;
|
||||
|
||||
public int Count => _count;
|
||||
public int FirstUse => _count > 0 ? _items[_count - 1] : LiveInterval.NotFound;
|
||||
public Span<int> Span => new(_items, _count);
|
||||
public int Count { get; private set; }
|
||||
|
||||
public readonly int FirstUse => Count > 0 ? _items[Count - 1] : LiveInterval.NotFound;
|
||||
public readonly Span<int> Span => new(_items, Count);
|
||||
|
||||
public void Add(int position)
|
||||
{
|
||||
if (_count + 1 > _capacity)
|
||||
if (Count + 1 > _capacity)
|
||||
{
|
||||
var oldSpan = Span;
|
||||
|
||||
|
@ -28,7 +28,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
// Use positions are usually inserted in descending order, so inserting in descending order is faster,
|
||||
// since the number of half exchanges is reduced.
|
||||
int i = _count - 1;
|
||||
int i = Count - 1;
|
||||
|
||||
while (i >= 0 && _items[i] < position)
|
||||
{
|
||||
|
@ -36,19 +36,19 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
}
|
||||
|
||||
_items[i + 1] = position;
|
||||
_count++;
|
||||
Count++;
|
||||
}
|
||||
|
||||
public int NextUse(int position)
|
||||
public readonly int NextUse(int position)
|
||||
{
|
||||
int index = NextUseIndex(position);
|
||||
|
||||
return index != LiveInterval.NotFound ? _items[index] : LiveInterval.NotFound;
|
||||
}
|
||||
|
||||
public int NextUseIndex(int position)
|
||||
public readonly int NextUseIndex(int position)
|
||||
{
|
||||
int i = _count - 1;
|
||||
int i = Count - 1;
|
||||
|
||||
if (i == -1 || position > _items[0])
|
||||
{
|
||||
|
@ -69,14 +69,16 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
// Since the list is in descending order, the new split list takes the front of the list and the current
|
||||
// list takes the back of the list.
|
||||
UseList result = new();
|
||||
result._count = index + 1;
|
||||
result._capacity = result._count;
|
||||
UseList result = new()
|
||||
{
|
||||
Count = index + 1,
|
||||
};
|
||||
result._capacity = result.Count;
|
||||
result._items = _items;
|
||||
|
||||
_count = _count - result._count;
|
||||
_capacity = _count;
|
||||
_items = _items + result._count;
|
||||
Count -= result.Count;
|
||||
_capacity = Count;
|
||||
_items += result.Count;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,6 @@ namespace ARMeilleure.CodeGen.Unwinding
|
|||
SetFrame = 1,
|
||||
AllocStack = 2,
|
||||
SaveReg = 3,
|
||||
SaveXmm128 = 4
|
||||
SaveXmm128 = 4,
|
||||
}
|
||||
}
|
|
@ -799,7 +799,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
{
|
||||
JumpIndex = _jumps.Count - 1,
|
||||
Position = (int)_stream.Position,
|
||||
Symbol = source.Symbol
|
||||
Symbol = source.Symbol,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1049,7 +1049,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
InstructionFlags.Prefix66 => 1,
|
||||
InstructionFlags.PrefixF3 => 2,
|
||||
InstructionFlags.PrefixF2 => 3,
|
||||
_ => 0
|
||||
_ => 0,
|
||||
};
|
||||
|
||||
if (src1 != default)
|
||||
|
@ -1081,11 +1081,19 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
switch (opCodeHigh)
|
||||
{
|
||||
case 0xf: vexByte1 |= 1; break;
|
||||
case 0xf38: vexByte1 |= 2; break;
|
||||
case 0xf3a: vexByte1 |= 3; break;
|
||||
case 0xf:
|
||||
vexByte1 |= 1;
|
||||
break;
|
||||
case 0xf38:
|
||||
vexByte1 |= 2;
|
||||
break;
|
||||
case 0xf3a:
|
||||
vexByte1 |= 3;
|
||||
break;
|
||||
|
||||
default: Debug.Assert(false, $"Failed to VEX encode opcode 0x{opCode:X}."); break;
|
||||
default:
|
||||
Debug.Assert(false, $"Failed to VEX encode opcode 0x{opCode:X}.");
|
||||
break;
|
||||
}
|
||||
|
||||
vexByte2 |= (rexPrefix & 8) << 4;
|
||||
|
@ -1191,11 +1199,19 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
switch ((ushort)(opCode >> 8))
|
||||
{
|
||||
case 0xf00: mm = 0b01; break;
|
||||
case 0xf38: mm = 0b10; break;
|
||||
case 0xf3a: mm = 0b11; break;
|
||||
case 0xf00:
|
||||
mm = 0b01;
|
||||
break;
|
||||
case 0xf38:
|
||||
mm = 0b10;
|
||||
break;
|
||||
case 0xf3a:
|
||||
mm = 0b11;
|
||||
break;
|
||||
|
||||
default: Debug.Fail($"Failed to EVEX encode opcode 0x{opCode:X}."); break;
|
||||
default:
|
||||
Debug.Fail($"Failed to EVEX encode opcode 0x{opCode:X}.");
|
||||
break;
|
||||
}
|
||||
|
||||
WriteByte(
|
||||
|
@ -1217,7 +1233,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
InstructionFlags.Prefix66 => 0b01,
|
||||
InstructionFlags.PrefixF3 => 0b10,
|
||||
InstructionFlags.PrefixF2 => 0b11,
|
||||
_ => 0
|
||||
_ => 0,
|
||||
};
|
||||
WriteByte(
|
||||
(byte)(
|
||||
|
@ -1233,11 +1249,19 @@ namespace ARMeilleure.CodeGen.X86
|
|||
byte ll = 0b00;
|
||||
switch (registerWidth)
|
||||
{
|
||||
case 128: ll = 0b00; break;
|
||||
case 256: ll = 0b01; break;
|
||||
case 512: ll = 0b10; break;
|
||||
case 128:
|
||||
ll = 0b00;
|
||||
break;
|
||||
case 256:
|
||||
ll = 0b01;
|
||||
break;
|
||||
case 512:
|
||||
ll = 0b10;
|
||||
break;
|
||||
|
||||
default: Debug.Fail($"Invalid EVEX vector register width {registerWidth}."); break;
|
||||
default:
|
||||
Debug.Fail($"Invalid EVEX vector register width {registerWidth}.");
|
||||
break;
|
||||
}
|
||||
// Embedded broadcast in the case of a memory operand
|
||||
bool bcast = broadcast;
|
||||
|
@ -1315,10 +1339,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
ref Jump jump = ref jumps[i];
|
||||
|
||||
// If jump target not resolved yet, resolve it.
|
||||
if (jump.JumpTarget == null)
|
||||
{
|
||||
jump.JumpTarget = _labels[jump.JumpLabel];
|
||||
}
|
||||
jump.JumpTarget ??= _labels[jump.JumpLabel];
|
||||
|
||||
long jumpTarget = jump.JumpTarget.Value;
|
||||
long offset = jumpTarget - jump.JumpPosition;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace ARMeilleure.CodeGen.X86
|
||||
{
|
||||
|
@ -12,6 +13,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
private const int BadOp = 0;
|
||||
|
||||
[Flags]
|
||||
[SuppressMessage("Design", "CA1069: Enums values should not be duplicated")]
|
||||
private enum InstructionFlags
|
||||
{
|
||||
None = 0,
|
||||
|
@ -26,7 +28,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
PrefixMask = 7 << PrefixBit,
|
||||
Prefix66 = 1 << PrefixBit,
|
||||
PrefixF3 = 2 << PrefixBit,
|
||||
PrefixF2 = 4 << PrefixBit
|
||||
PrefixF2 = 4 << PrefixBit,
|
||||
}
|
||||
|
||||
private readonly struct InstructionInfo
|
||||
|
@ -62,6 +64,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
{
|
||||
_instTable = new InstructionInfo[(int)X86Instruction.Count];
|
||||
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
// Name RM/R RM/I8 RM/I32 R/I64 R/RM Flags
|
||||
Add(X86Instruction.Add, new InstructionInfo(0x00000001, 0x00000083, 0x00000081, BadOp, 0x00000003, InstructionFlags.None));
|
||||
Add(X86Instruction.Addpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
|
@ -285,6 +288,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
Add(X86Instruction.Xor, new InstructionInfo(0x00000031, 0x06000083, 0x06000081, BadOp, 0x00000033, InstructionFlags.None));
|
||||
Add(X86Instruction.Xorpd, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f57, InstructionFlags.Vex | InstructionFlags.Prefix66));
|
||||
Add(X86Instruction.Xorps, new InstructionInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f57, InstructionFlags.Vex));
|
||||
#pragma warning restore IDE0055
|
||||
|
||||
static void Add(X86Instruction inst, in InstructionInfo info)
|
||||
{
|
||||
|
|
|
@ -3,6 +3,6 @@ namespace ARMeilleure.CodeGen.X86
|
|||
enum CallConvName
|
||||
{
|
||||
SystemV,
|
||||
Windows
|
||||
Windows,
|
||||
}
|
||||
}
|
|
@ -20,6 +20,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
{
|
||||
if (GetCurrentCallConv() == CallConvName.Windows)
|
||||
{
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
return (1 << (int)X86Register.Rax) |
|
||||
(1 << (int)X86Register.Rcx) |
|
||||
(1 << (int)X86Register.Rdx) |
|
||||
|
@ -39,6 +40,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
(1 << (int)X86Register.R9) |
|
||||
(1 << (int)X86Register.R10) |
|
||||
(1 << (int)X86Register.R11);
|
||||
#pragma warning restore IDE0055
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,22 +92,32 @@ namespace ARMeilleure.CodeGen.X86
|
|||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0: return X86Register.Rcx;
|
||||
case 1: return X86Register.Rdx;
|
||||
case 2: return X86Register.R8;
|
||||
case 3: return X86Register.R9;
|
||||
case 0:
|
||||
return X86Register.Rcx;
|
||||
case 1:
|
||||
return X86Register.Rdx;
|
||||
case 2:
|
||||
return X86Register.R8;
|
||||
case 3:
|
||||
return X86Register.R9;
|
||||
}
|
||||
}
|
||||
else /* if (GetCurrentCallConv() == CallConvName.SystemV) */
|
||||
{
|
||||
switch (index)
|
||||
{
|
||||
case 0: return X86Register.Rdi;
|
||||
case 1: return X86Register.Rsi;
|
||||
case 2: return X86Register.Rdx;
|
||||
case 3: return X86Register.Rcx;
|
||||
case 4: return X86Register.R8;
|
||||
case 5: return X86Register.R9;
|
||||
case 0:
|
||||
return X86Register.Rdi;
|
||||
case 1:
|
||||
return X86Register.Rsi;
|
||||
case 2:
|
||||
return X86Register.Rdx;
|
||||
case 3:
|
||||
return X86Register.Rcx;
|
||||
case 4:
|
||||
return X86Register.R8;
|
||||
case 5:
|
||||
return X86Register.R9;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
{
|
||||
_instTable = new Action<CodeGenContext, Operation>[EnumUtils.GetCount(typeof(Instruction))];
|
||||
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
Add(Instruction.Add, GenerateAdd);
|
||||
Add(Instruction.BitwiseAnd, GenerateBitwiseAnd);
|
||||
Add(Instruction.BitwiseExclusiveOr, GenerateBitwiseExclusiveOr);
|
||||
|
@ -85,6 +86,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
Add(Instruction.ZeroExtend16, GenerateZeroExtend16);
|
||||
Add(Instruction.ZeroExtend32, GenerateZeroExtend32);
|
||||
Add(Instruction.ZeroExtend8, GenerateZeroExtend8);
|
||||
#pragma warning restore IDE0055
|
||||
|
||||
static void Add(Instruction inst, Action<CodeGenContext, Operation> func)
|
||||
{
|
||||
|
@ -1294,11 +1296,11 @@ namespace ARMeilleure.CodeGen.X86
|
|||
}
|
||||
else
|
||||
{
|
||||
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.Pshufd(src1, src1, mask);
|
||||
context.Assembler.Pshufd(src1, src1, Mask);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1613,13 +1615,25 @@ namespace ARMeilleure.CodeGen.X86
|
|||
{
|
||||
switch (value.Type)
|
||||
{
|
||||
case OperandType.I32: context.Assembler.Mov (value, address, OperandType.I32); break;
|
||||
case OperandType.I64: context.Assembler.Mov (value, address, OperandType.I64); break;
|
||||
case OperandType.FP32: context.Assembler.Movd (value, address); break;
|
||||
case OperandType.FP64: context.Assembler.Movq (value, address); break;
|
||||
case OperandType.V128: context.Assembler.Movdqu(value, address); break;
|
||||
case OperandType.I32:
|
||||
context.Assembler.Mov(value, address, OperandType.I32);
|
||||
break;
|
||||
case OperandType.I64:
|
||||
context.Assembler.Mov(value, address, OperandType.I64);
|
||||
break;
|
||||
case OperandType.FP32:
|
||||
context.Assembler.Movd(value, address);
|
||||
break;
|
||||
case OperandType.FP64:
|
||||
context.Assembler.Movq(value, address);
|
||||
break;
|
||||
case OperandType.V128:
|
||||
context.Assembler.Movdqu(value, address);
|
||||
break;
|
||||
|
||||
default: Debug.Assert(false); break;
|
||||
default:
|
||||
Debug.Assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1627,13 +1641,25 @@ namespace ARMeilleure.CodeGen.X86
|
|||
{
|
||||
switch (value.Type)
|
||||
{
|
||||
case OperandType.I32: context.Assembler.Mov (address, value, OperandType.I32); break;
|
||||
case OperandType.I64: context.Assembler.Mov (address, value, OperandType.I64); break;
|
||||
case OperandType.FP32: context.Assembler.Movd (address, value); break;
|
||||
case OperandType.FP64: context.Assembler.Movq (address, value); break;
|
||||
case OperandType.V128: context.Assembler.Movdqu(address, value); break;
|
||||
case OperandType.I32:
|
||||
context.Assembler.Mov(address, value, OperandType.I32);
|
||||
break;
|
||||
case OperandType.I64:
|
||||
context.Assembler.Mov(address, value, OperandType.I64);
|
||||
break;
|
||||
case OperandType.FP32:
|
||||
context.Assembler.Movd(address, value);
|
||||
break;
|
||||
case OperandType.FP64:
|
||||
context.Assembler.Movq(address, value);
|
||||
break;
|
||||
case OperandType.V128:
|
||||
context.Assembler.Movdqu(address, value);
|
||||
break;
|
||||
|
||||
default: Debug.Assert(false); break;
|
||||
default:
|
||||
Debug.Assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1722,7 +1748,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
private static UnwindInfo WritePrologue(CodeGenContext context)
|
||||
{
|
||||
List<UnwindPushEntry> pushEntries = new List<UnwindPushEntry>();
|
||||
List<UnwindPushEntry> pushEntries = new();
|
||||
|
||||
Operand rsp = Register(X86Register.Rsp);
|
||||
|
||||
|
@ -1827,9 +1853,9 @@ namespace ARMeilleure.CodeGen.X86
|
|||
// that the OS will map all pages that we'll use. We do that by
|
||||
// doing a dummy read on those pages, forcing a page fault and
|
||||
// the OS to map them. If they are already mapped, nothing happens.
|
||||
const int pageMask = PageSize - 1;
|
||||
const int PageMask = PageSize - 1;
|
||||
|
||||
size = (size + pageMask) & ~pageMask;
|
||||
size = (size + PageMask) & ~PageMask;
|
||||
|
||||
Operand rsp = Register(X86Register.Rsp);
|
||||
Operand temp = Register(CallingConvention.GetIntReturnRegister());
|
||||
|
|
|
@ -47,7 +47,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
0xc3, // ret
|
||||
};
|
||||
|
||||
using MemoryBlock memGetXcr0 = new MemoryBlock((ulong)asmGetXcr0.Length);
|
||||
using MemoryBlock memGetXcr0 = new((ulong)asmGetXcr0.Length);
|
||||
|
||||
memGetXcr0.Write(0, asmGetXcr0);
|
||||
|
||||
|
@ -62,7 +62,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
public enum FeatureFlags1Edx
|
||||
{
|
||||
Sse = 1 << 25,
|
||||
Sse2 = 1 << 26
|
||||
Sse2 = 1 << 26,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
|
@ -79,7 +79,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
Xsave = 1 << 26,
|
||||
Osxsave = 1 << 27,
|
||||
Avx = 1 << 28,
|
||||
F16c = 1 << 29
|
||||
F16c = 1 << 29,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
|
@ -90,7 +90,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
Avx512dq = 1 << 17,
|
||||
Sha = 1 << 29,
|
||||
Avx512bw = 1 << 30,
|
||||
Avx512vl = 1 << 31
|
||||
Avx512vl = 1 << 31,
|
||||
}
|
||||
|
||||
[Flags]
|
||||
|
@ -106,7 +106,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
YmmHi128 = 1 << 2,
|
||||
Opmask = 1 << 5,
|
||||
ZmmHi256 = 1 << 6,
|
||||
Hi16Zmm = 1 << 7
|
||||
Hi16Zmm = 1 << 7,
|
||||
}
|
||||
|
||||
public static FeatureFlags1Edx FeatureInfo1Edx { get; }
|
||||
|
|
|
@ -5,12 +5,13 @@ namespace ARMeilleure.CodeGen.X86
|
|||
{
|
||||
static class IntrinsicTable
|
||||
{
|
||||
private static IntrinsicInfo[] _intrinTable;
|
||||
private static readonly IntrinsicInfo[] _intrinTable;
|
||||
|
||||
static IntrinsicTable()
|
||||
{
|
||||
_intrinTable = new IntrinsicInfo[EnumUtils.GetCount(typeof(Intrinsic))];
|
||||
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
Add(Intrinsic.X86Addpd, new IntrinsicInfo(X86Instruction.Addpd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Addps, new IntrinsicInfo(X86Instruction.Addps, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Addsd, new IntrinsicInfo(X86Instruction.Addsd, IntrinsicType.Binary));
|
||||
|
@ -185,6 +186,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
Add(Intrinsic.X86Vpternlogd, new IntrinsicInfo(X86Instruction.Vpternlogd, IntrinsicType.TernaryImm));
|
||||
Add(Intrinsic.X86Xorpd, new IntrinsicInfo(X86Instruction.Xorpd, IntrinsicType.Binary));
|
||||
Add(Intrinsic.X86Xorps, new IntrinsicInfo(X86Instruction.Xorps, IntrinsicType.Binary));
|
||||
#pragma warning restore IDE0055
|
||||
}
|
||||
|
||||
private static void Add(Intrinsic intrin, IntrinsicInfo info)
|
||||
|
|
|
@ -13,6 +13,6 @@ namespace ARMeilleure.CodeGen.X86
|
|||
Crc32,
|
||||
Ternary,
|
||||
TernaryImm,
|
||||
Fma
|
||||
Fma,
|
||||
}
|
||||
}
|
|
@ -10,6 +10,6 @@ namespace ARMeilleure.CodeGen.X86
|
|||
Rlo = 1 << 13, // Round Mode low bit.
|
||||
Um = 1 << 11, // Underflow Mask.
|
||||
Dm = 1 << 8, // Denormal Mask.
|
||||
Daz = 1 << 6 // Denormals Are Zero.
|
||||
Daz = 1 << 6, // Denormals Are Zero.
|
||||
}
|
||||
}
|
||||
|
|
|
@ -104,11 +104,11 @@ namespace ARMeilleure.CodeGen.X86
|
|||
case Instruction.Tailcall:
|
||||
if (callConv == CallConvName.Windows)
|
||||
{
|
||||
PreAllocatorWindows.InsertTailcallCopies(block.Operations, stackAlloc, node);
|
||||
PreAllocatorWindows.InsertTailcallCopies(block.Operations, node);
|
||||
}
|
||||
else
|
||||
{
|
||||
PreAllocatorSystemV.InsertTailcallCopies(block.Operations, stackAlloc, node);
|
||||
PreAllocatorSystemV.InsertTailcallCopies(block.Operations, node);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -177,10 +177,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
{
|
||||
src2 = node.GetSource(1);
|
||||
|
||||
Operand temp = src1;
|
||||
|
||||
src1 = src2;
|
||||
src2 = temp;
|
||||
(src2, src1) = (src1, src2);
|
||||
|
||||
node.SetSource(0, src1);
|
||||
node.SetSource(1, src2);
|
||||
|
@ -473,7 +470,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
Operand zex = Local(OperandType.I64);
|
||||
|
||||
node = nodes.AddAfter(node, Operation(Instruction.ZeroExtend32, zex, source));
|
||||
node = nodes.AddAfter(node, Operation(Instruction.ConvertToFP, dest, zex));
|
||||
nodes.AddAfter(node, Operation(Instruction.ConvertToFP, dest, zex));
|
||||
}
|
||||
else /* if (source.Type == OperandType.I64) */
|
||||
{
|
||||
|
@ -709,16 +706,11 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
private static bool HasConstSrc1(Instruction inst)
|
||||
{
|
||||
switch (inst)
|
||||
return inst switch
|
||||
{
|
||||
case Instruction.Copy:
|
||||
case Instruction.LoadArgument:
|
||||
case Instruction.Spill:
|
||||
case Instruction.SpillArg:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
Instruction.Copy or Instruction.LoadArgument or Instruction.Spill or Instruction.SpillArg => true,
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
private static bool HasConstSrc2(Instruction inst)
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
using ARMeilleure.CodeGen.RegisterAllocators;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
|
@ -15,9 +14,9 @@ namespace ARMeilleure.CodeGen.X86
|
|||
{
|
||||
Operand dest = node.Destination;
|
||||
|
||||
List<Operand> sources = new List<Operand>
|
||||
List<Operand> sources = new()
|
||||
{
|
||||
node.GetSource(0)
|
||||
node.GetSource(0),
|
||||
};
|
||||
|
||||
int argsCount = node.SourcesCount - 1;
|
||||
|
@ -116,11 +115,11 @@ namespace ARMeilleure.CodeGen.X86
|
|||
}
|
||||
}
|
||||
|
||||
public static void InsertTailcallCopies(IntrusiveList<Operation> nodes, StackAllocator stackAlloc, Operation node)
|
||||
public static void InsertTailcallCopies(IntrusiveList<Operation> nodes, Operation node)
|
||||
{
|
||||
List<Operand> sources = new List<Operand>
|
||||
List<Operand> sources = new()
|
||||
{
|
||||
node.GetSource(0)
|
||||
node.GetSource(0),
|
||||
};
|
||||
|
||||
int argsCount = node.SourcesCount - 1;
|
||||
|
|
|
@ -155,7 +155,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
node.SetSources(sources);
|
||||
}
|
||||
|
||||
public static void InsertTailcallCopies(IntrusiveList<Operation> nodes, StackAllocator stackAlloc, Operation node)
|
||||
public static void InsertTailcallCopies(IntrusiveList<Operation> nodes, Operation node)
|
||||
{
|
||||
int argsCount = node.SourcesCount - 1;
|
||||
int maxArgs = CallingConvention.GetArgumentsOnRegsCount();
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
Less = 0xc,
|
||||
GreaterOrEqual = 0xd,
|
||||
LessOrEqual = 0xe,
|
||||
Greater = 0xf
|
||||
Greater = 0xf,
|
||||
}
|
||||
|
||||
static class ComparisonX86Extensions
|
||||
|
@ -29,6 +29,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
{
|
||||
return comp switch
|
||||
{
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
Comparison.Equal => X86Condition.Equal,
|
||||
Comparison.NotEqual => X86Condition.NotEqual,
|
||||
Comparison.Greater => X86Condition.Greater,
|
||||
|
@ -39,8 +40,9 @@ namespace ARMeilleure.CodeGen.X86
|
|||
Comparison.Less => X86Condition.Less,
|
||||
Comparison.GreaterOrEqualUI => X86Condition.AboveOrEqual,
|
||||
Comparison.LessUI => X86Condition.Below,
|
||||
#pragma warning restore IDE0055
|
||||
|
||||
_ => throw new ArgumentException(null, nameof(comp))
|
||||
_ => throw new ArgumentException(null, nameof(comp)),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -226,6 +226,6 @@ namespace ARMeilleure.CodeGen.X86
|
|||
Xorpd,
|
||||
Xorps,
|
||||
|
||||
Count
|
||||
Count,
|
||||
}
|
||||
}
|
|
@ -215,7 +215,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
1 => Multiplier.x2,
|
||||
2 => Multiplier.x4,
|
||||
3 => Multiplier.x8,
|
||||
_ => Multiplier.x1
|
||||
_ => Multiplier.x1,
|
||||
};
|
||||
|
||||
baseOp = indexOnSrc2 ? src1 : src2;
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace ARMeilleure.CodeGen.X86
|
||||
{
|
||||
[SuppressMessage("Design", "CA1069: Enums values should not be duplicated")]
|
||||
enum X86Register
|
||||
{
|
||||
Invalid = -1,
|
||||
|
@ -36,6 +39,6 @@ namespace ARMeilleure.CodeGen.X86
|
|||
Xmm12 = 12,
|
||||
Xmm13 = 13,
|
||||
Xmm14 = 14,
|
||||
Xmm15 = 15
|
||||
Xmm15 = 15,
|
||||
}
|
||||
}
|
|
@ -82,8 +82,10 @@ namespace ARMeilleure.Common
|
|||
}
|
||||
else
|
||||
{
|
||||
_page = new PageInfo();
|
||||
_page.Pointer = (byte*)NativeAllocator.Instance.Allocate(_pageSize);
|
||||
_page = new PageInfo
|
||||
{
|
||||
Pointer = (byte*)NativeAllocator.Instance.Allocate(_pageSize),
|
||||
};
|
||||
|
||||
_pages.Add(_page);
|
||||
}
|
||||
|
@ -106,7 +108,7 @@ namespace ARMeilleure.Common
|
|||
// Free excess pages that was allocated.
|
||||
while (_pages.Count > _pageCount)
|
||||
{
|
||||
NativeAllocator.Instance.Free(_pages[_pages.Count - 1].Pointer);
|
||||
NativeAllocator.Instance.Free(_pages[^1].Pointer);
|
||||
|
||||
_pages.RemoveAt(_pages.Count - 1);
|
||||
}
|
||||
|
@ -125,12 +127,13 @@ namespace ARMeilleure.Common
|
|||
|
||||
// If arena is used frequently, keep pages for longer. Otherwise keep pages for a shorter amount of time.
|
||||
int now = Environment.TickCount;
|
||||
int count = (now - _lastReset) switch {
|
||||
int count = (now - _lastReset) switch
|
||||
{
|
||||
>= 5000 => 0,
|
||||
>= 2500 => 50,
|
||||
>= 1000 => 100,
|
||||
>= 10 => 1500,
|
||||
_ => 5000
|
||||
_ => 5000,
|
||||
};
|
||||
|
||||
for (int i = _pages.Count - 1; i >= 0; i--)
|
||||
|
|
|
@ -138,7 +138,7 @@ namespace ARMeilleure.Common
|
|||
var newSpan = new Span<long>(_masks, _count);
|
||||
|
||||
oldSpan.CopyTo(newSpan);
|
||||
newSpan.Slice(oldSpan.Length).Clear();
|
||||
newSpan[oldSpan.Length..].Clear();
|
||||
|
||||
_allocator.Free(oldMask);
|
||||
}
|
||||
|
@ -176,8 +176,8 @@ namespace ARMeilleure.Common
|
|||
private int _bit;
|
||||
private readonly BitMap _map;
|
||||
|
||||
public int Current => (int)_index * IntSize + _bit;
|
||||
object IEnumerator.Current => Current;
|
||||
public readonly int Current => (int)_index * IntSize + _bit;
|
||||
readonly object IEnumerator.Current => Current;
|
||||
|
||||
public Enumerator(BitMap map)
|
||||
{
|
||||
|
@ -214,9 +214,9 @@ namespace ARMeilleure.Common
|
|||
return true;
|
||||
}
|
||||
|
||||
public void Reset() { }
|
||||
public readonly void Reset() { }
|
||||
|
||||
public void Dispose() { }
|
||||
public readonly void Dispose() { }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -92,7 +92,7 @@ namespace ARMeilleure.Decoders
|
|||
{
|
||||
if (OpCodes.Count > 0)
|
||||
{
|
||||
return OpCodes[OpCodes.Count - 1];
|
||||
return OpCodes[^1];
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace ARMeilleure.Decoders
|
|||
Gt = 12,
|
||||
Le = 13,
|
||||
Al = 14,
|
||||
Nv = 15
|
||||
Nv = 15,
|
||||
}
|
||||
|
||||
static class ConditionExtensions
|
||||
|
|
|
@ -5,6 +5,6 @@ namespace ARMeilleure.Decoders
|
|||
Adr = 0,
|
||||
Arithmetic = 1,
|
||||
Logical = 2,
|
||||
BitField = 3
|
||||
BitField = 3,
|
||||
}
|
||||
}
|
|
@ -20,11 +20,11 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
public static Block[] Decode(IMemoryManager memory, ulong address, ExecutionMode mode, bool highCq, DecoderMode dMode)
|
||||
{
|
||||
List<Block> blocks = new List<Block>();
|
||||
List<Block> blocks = new();
|
||||
|
||||
Queue<Block> workQueue = new Queue<Block>();
|
||||
Queue<Block> workQueue = new();
|
||||
|
||||
Dictionary<ulong, Block> visited = new Dictionary<ulong, Block>();
|
||||
Dictionary<ulong, Block> visited = new();
|
||||
|
||||
Debug.Assert(MaxInstsPerFunctionLowCq <= MaxInstsPerFunction);
|
||||
|
||||
|
@ -246,7 +246,7 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
private static bool IsAarch32UnconditionalBranch(OpCode opCode)
|
||||
{
|
||||
if (!(opCode is OpCode32 op))
|
||||
if (opCode is not OpCode32 op)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -304,9 +304,9 @@ namespace ARMeilleure.Decoders
|
|||
}
|
||||
else if (opCode is IOpCode32MemMult opMemMult)
|
||||
{
|
||||
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;
|
||||
wBack = opMemMult.PostOffset != 0;
|
||||
isLoad = opMemMult.IsLoad;
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace ARMeilleure.Decoders
|
|||
// abcdefgh -> aBbbbbbc defgh000 00000000 00000000 (B = ~b)
|
||||
private static uint ExpandImm8ToFP32(uint imm)
|
||||
{
|
||||
uint MoveBit(uint bits, int from, int to)
|
||||
static uint MoveBit(uint bits, int from, int to)
|
||||
{
|
||||
return ((bits >> from) & 1U) << to;
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ namespace ARMeilleure.Decoders
|
|||
// abcdefgh -> aBbbbbbb bbcdefgh 00000000 00000000 00000000 00000000 00000000 00000000 (B = ~b)
|
||||
private static ulong ExpandImm8ToFP64(ulong imm)
|
||||
{
|
||||
ulong MoveBit(ulong bits, int from, int to)
|
||||
static ulong MoveBit(ulong bits, int from, int to)
|
||||
{
|
||||
return ((bits >> from) & 1UL) << to;
|
||||
}
|
||||
|
@ -80,7 +80,7 @@ namespace ARMeilleure.Decoders
|
|||
public int Shift;
|
||||
public bool IsUndefined;
|
||||
|
||||
public static BitMask Invalid => new BitMask { IsUndefined = true };
|
||||
public static BitMask Invalid => new() { IsUndefined = true };
|
||||
}
|
||||
|
||||
public static BitMask DecodeBitMask(int opCode, bool immediate)
|
||||
|
@ -125,7 +125,7 @@ namespace ARMeilleure.Decoders
|
|||
TMask = BitUtils.Replicate(tMask, size),
|
||||
|
||||
Pos = immS,
|
||||
Shift = immR
|
||||
Shift = immR,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ namespace ARMeilleure.Decoders
|
|||
{
|
||||
readonly struct InstDescriptor
|
||||
{
|
||||
public static InstDescriptor Undefined => new InstDescriptor(InstName.Und, InstEmit.Und);
|
||||
public static InstDescriptor Undefined => new(InstName.Und, InstEmit.Und);
|
||||
|
||||
public InstName Name { get; }
|
||||
public InstEmitter Emitter { get; }
|
||||
|
|
|
@ -9,6 +9,6 @@ namespace ARMeilleure.Decoders
|
|||
Int8 = 4,
|
||||
Int16 = 5,
|
||||
Int32 = 6,
|
||||
Int64 = 7
|
||||
Int64 = 7,
|
||||
}
|
||||
}
|
|
@ -14,7 +14,7 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
public RegisterSize RegisterSize { get; protected set; }
|
||||
|
||||
public static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode(inst, address, opCode);
|
||||
public static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new(inst, address, opCode);
|
||||
|
||||
public OpCode(InstDescriptor inst, ulong address, int opCode)
|
||||
{
|
||||
|
@ -30,15 +30,14 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
public int GetBitsCount()
|
||||
{
|
||||
switch (RegisterSize)
|
||||
return RegisterSize switch
|
||||
{
|
||||
case RegisterSize.Int32: return 32;
|
||||
case RegisterSize.Int64: return 64;
|
||||
case RegisterSize.Simd64: return 64;
|
||||
case RegisterSize.Simd128: return 128;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException();
|
||||
RegisterSize.Int32 => 32,
|
||||
RegisterSize.Int64 => 64,
|
||||
RegisterSize.Simd64 => 64,
|
||||
RegisterSize.Simd128 => 128,
|
||||
_ => throw new InvalidOperationException(),
|
||||
};
|
||||
}
|
||||
|
||||
public OperandType GetOperandType()
|
||||
|
|
|
@ -24,27 +24,21 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
protected int GetQuadwordIndex(int index)
|
||||
{
|
||||
switch (RegisterSize)
|
||||
return RegisterSize switch
|
||||
{
|
||||
case RegisterSize.Simd128:
|
||||
case RegisterSize.Simd64:
|
||||
return index >> 1;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException();
|
||||
RegisterSize.Simd128 or RegisterSize.Simd64 => index >> 1,
|
||||
_ => throw new InvalidOperationException(),
|
||||
};
|
||||
}
|
||||
|
||||
protected int GetQuadwordSubindex(int index)
|
||||
{
|
||||
switch (RegisterSize)
|
||||
return RegisterSize switch
|
||||
{
|
||||
case RegisterSize.Simd128:
|
||||
return 0;
|
||||
case RegisterSize.Simd64:
|
||||
return index & 1;
|
||||
}
|
||||
|
||||
throw new InvalidOperationException();
|
||||
RegisterSize.Simd128 => 0,
|
||||
RegisterSize.Simd64 => index & 1,
|
||||
_ => throw new InvalidOperationException(),
|
||||
};
|
||||
}
|
||||
|
||||
protected OpCode32SimdBase(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode)
|
||||
|
|
23
src/ARMeilleure/Decoders/OpCode32SimdCvtFFixed.cs
Normal file
23
src/ARMeilleure/Decoders/OpCode32SimdCvtFFixed.cs
Normal file
|
@ -0,0 +1,23 @@
|
|||
namespace ARMeilleure.Decoders
|
||||
{
|
||||
class OpCode32SimdCvtFFixed : OpCode32Simd
|
||||
{
|
||||
public int Fbits { get; protected set; }
|
||||
|
||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdCvtFFixed(inst, address, opCode, false);
|
||||
public new static OpCode CreateT32(InstDescriptor inst, ulong address, int opCode) => new OpCode32SimdCvtFFixed(inst, address, opCode, true);
|
||||
|
||||
public OpCode32SimdCvtFFixed(InstDescriptor inst, ulong address, int opCode, bool isThumb) : base(inst, address, opCode, isThumb)
|
||||
{
|
||||
Opc = (opCode >> 8) & 0x1;
|
||||
|
||||
Size = Opc == 1 ? 0 : 2;
|
||||
Fbits = 64 - ((opCode >> 16) & 0x3f);
|
||||
|
||||
if (DecoderHelper.VectorArgumentsInvalid(Q, Vd, Vm))
|
||||
{
|
||||
Instruction = InstDescriptor.Undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,9 +14,15 @@
|
|||
// The value must be a power of 2, otherwise it is the encoding of another instruction.
|
||||
switch (imm3h)
|
||||
{
|
||||
case 1: Size = 0; break;
|
||||
case 2: Size = 1; break;
|
||||
case 4: Size = 2; break;
|
||||
case 1:
|
||||
Size = 0;
|
||||
break;
|
||||
case 2:
|
||||
Size = 1;
|
||||
break;
|
||||
case 4:
|
||||
Size = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
U = ((opCode >> (isThumb ? 28 : 24)) & 0x1) != 0;
|
||||
|
|
|
@ -4,12 +4,12 @@ namespace ARMeilleure.Decoders
|
|||
{
|
||||
class OpCode32SimdMemPair : OpCode32, IOpCode32Simd
|
||||
{
|
||||
private static int[] _regsMap =
|
||||
private static readonly int[] _regsMap =
|
||||
{
|
||||
1, 1, 4, 2,
|
||||
1, 1, 3, 1,
|
||||
1, 1, 2, 1,
|
||||
1, 1, 1, 1
|
||||
1, 1, 1, 1,
|
||||
};
|
||||
|
||||
public int Vd { get; }
|
||||
|
|
|
@ -18,6 +18,6 @@
|
|||
Eq = 0,
|
||||
Vs,
|
||||
Ge,
|
||||
Gt
|
||||
Gt,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace ARMeilleure.Decoders
|
|||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException(nameof(opCode));
|
||||
throw new ArgumentException($"Invalid data operation: {DataOp}", nameof(opCode));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace ARMeilleure.Decoders
|
|||
PostIndexed = 1,
|
||||
Unprivileged = 2,
|
||||
PreIndexed = 3,
|
||||
Unsigned
|
||||
Unsigned,
|
||||
}
|
||||
|
||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeMemImm(inst, address, opCode);
|
||||
|
|
|
@ -18,10 +18,26 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
switch ((opCode >> 30) & 3)
|
||||
{
|
||||
case 0: Size = 2; Signed = false; Prefetch = false; break;
|
||||
case 1: Size = 3; Signed = false; Prefetch = false; break;
|
||||
case 2: Size = 2; Signed = true; Prefetch = false; break;
|
||||
case 3: Size = 0; Signed = false; Prefetch = true; break;
|
||||
case 0:
|
||||
Size = 2;
|
||||
Signed = false;
|
||||
Prefetch = false;
|
||||
break;
|
||||
case 1:
|
||||
Size = 3;
|
||||
Signed = false;
|
||||
Prefetch = false;
|
||||
break;
|
||||
case 2:
|
||||
Size = 2;
|
||||
Signed = true;
|
||||
Prefetch = false;
|
||||
break;
|
||||
case 3:
|
||||
Size = 0;
|
||||
Signed = false;
|
||||
Prefetch = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,17 +52,20 @@
|
|||
else if ((modeHigh & 0b110) == 0b100)
|
||||
{
|
||||
// 16-bits shifted Immediate.
|
||||
size = 1; imm <<= (modeHigh & 1) << 3;
|
||||
size = 1;
|
||||
imm <<= (modeHigh & 1) << 3;
|
||||
}
|
||||
else if ((modeHigh & 0b100) == 0b000)
|
||||
{
|
||||
// 32-bits shifted Immediate.
|
||||
size = 2; imm <<= modeHigh << 3;
|
||||
size = 2;
|
||||
imm <<= modeHigh << 3;
|
||||
}
|
||||
else if ((modeHigh & 0b111) == 0b110)
|
||||
{
|
||||
// 32-bits shifted Immediate (fill with ones).
|
||||
size = 2; imm = ShlOnes(imm, 8 << modeLow);
|
||||
size = 2;
|
||||
imm = ShlOnes(imm, 8 << modeLow);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -67,17 +67,20 @@ namespace ARMeilleure.Decoders
|
|||
else if ((modeHigh & 0b110) == 0b100)
|
||||
{
|
||||
// 16-bits shifted Immediate.
|
||||
Size = 1; imm <<= (modeHigh & 1) << 3;
|
||||
Size = 1;
|
||||
imm <<= (modeHigh & 1) << 3;
|
||||
}
|
||||
else if ((modeHigh & 0b100) == 0b000)
|
||||
{
|
||||
// 32-bits shifted Immediate.
|
||||
Size = 2; imm <<= modeHigh << 3;
|
||||
Size = 2;
|
||||
imm <<= modeHigh << 3;
|
||||
}
|
||||
else if ((modeHigh & 0b111) == 0b110)
|
||||
{
|
||||
// 32-bits shifted Immediate (fill with ones).
|
||||
Size = 2; imm = ShlOnes(imm, 8 << modeLow);
|
||||
Size = 2;
|
||||
imm = ShlOnes(imm, 8 << modeLow);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -23,10 +23,18 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
switch (Size)
|
||||
{
|
||||
case 1: Size = 0; break;
|
||||
case 2: Size = 1; break;
|
||||
case 4: Size = 2; break;
|
||||
case 8: Size = 3; break;
|
||||
case 1:
|
||||
Size = 0;
|
||||
break;
|
||||
case 2:
|
||||
Size = 1;
|
||||
break;
|
||||
case 4:
|
||||
Size = 2;
|
||||
break;
|
||||
case 8:
|
||||
Size = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
SrcIndex = imm4 >> Size;
|
||||
|
|
|
@ -13,15 +13,38 @@ namespace ARMeilleure.Decoders
|
|||
{
|
||||
switch ((opCode >> 12) & 0xf)
|
||||
{
|
||||
case 0b0000: Reps = 1; SElems = 4; break;
|
||||
case 0b0010: Reps = 4; SElems = 1; break;
|
||||
case 0b0100: Reps = 1; SElems = 3; break;
|
||||
case 0b0110: Reps = 3; SElems = 1; break;
|
||||
case 0b0111: Reps = 1; SElems = 1; break;
|
||||
case 0b1000: Reps = 1; SElems = 2; break;
|
||||
case 0b1010: Reps = 2; SElems = 1; break;
|
||||
case 0b0000:
|
||||
Reps = 1;
|
||||
SElems = 4;
|
||||
break;
|
||||
case 0b0010:
|
||||
Reps = 4;
|
||||
SElems = 1;
|
||||
break;
|
||||
case 0b0100:
|
||||
Reps = 1;
|
||||
SElems = 3;
|
||||
break;
|
||||
case 0b0110:
|
||||
Reps = 3;
|
||||
SElems = 1;
|
||||
break;
|
||||
case 0b0111:
|
||||
Reps = 1;
|
||||
SElems = 1;
|
||||
break;
|
||||
case 0b1000:
|
||||
Reps = 1;
|
||||
SElems = 2;
|
||||
break;
|
||||
case 0b1010:
|
||||
Reps = 2;
|
||||
SElems = 1;
|
||||
break;
|
||||
|
||||
default: Instruction = InstDescriptor.Undefined; return;
|
||||
default:
|
||||
Instruction = InstDescriptor.Undefined;
|
||||
return;
|
||||
}
|
||||
|
||||
Size = (opCode >> 10) & 3;
|
||||
|
|
|
@ -24,7 +24,9 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
break;
|
||||
|
||||
default: Instruction = InstDescriptor.Undefined; break;
|
||||
default:
|
||||
Instruction = InstDescriptor.Undefined;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,9 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
break;
|
||||
|
||||
default: Instruction = InstDescriptor.Undefined; break;
|
||||
default:
|
||||
Instruction = InstDescriptor.Undefined;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,23 +36,13 @@ namespace ARMeilleure.Decoders
|
|||
break;
|
||||
}
|
||||
|
||||
switch (inst.Name)
|
||||
Immediate = inst.Name switch
|
||||
{
|
||||
case InstName.Str:
|
||||
case InstName.Ldr:
|
||||
Immediate = ((opCode >> 6) & 0x1f) << 2;
|
||||
break;
|
||||
case InstName.Strb:
|
||||
case InstName.Ldrb:
|
||||
Immediate = ((opCode >> 6) & 0x1f);
|
||||
break;
|
||||
case InstName.Strh:
|
||||
case InstName.Ldrh:
|
||||
Immediate = ((opCode >> 6) & 0x1f) << 1;
|
||||
break;
|
||||
default:
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
InstName.Str or InstName.Ldr => ((opCode >> 6) & 0x1f) << 2,
|
||||
InstName.Strb or InstName.Ldrb => ((opCode >> 6) & 0x1f),
|
||||
InstName.Strh or InstName.Ldrh => ((opCode >> 6) & 0x1f) << 1,
|
||||
_ => throw new InvalidOperationException(),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace ARMeilleure.Decoders
|
|||
{
|
||||
InstName.Ldm => true,
|
||||
InstName.Stm => false,
|
||||
_ => throw new InvalidOperationException()
|
||||
_ => throw new InvalidOperationException(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,8 +4,6 @@ namespace ARMeilleure.Decoders
|
|||
{
|
||||
public int Immediate { get; }
|
||||
|
||||
public bool IsRotated => false;
|
||||
|
||||
public new static OpCode Create(InstDescriptor inst, ulong address, int opCode) => new OpCodeT32MovImm16(inst, address, opCode);
|
||||
|
||||
public OpCodeT32MovImm16(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
||||
|
|
|
@ -29,16 +29,17 @@ namespace ARMeilleure.Decoders
|
|||
}
|
||||
}
|
||||
|
||||
private static List<InstInfo> AllInstA32 = new();
|
||||
private static List<InstInfo> AllInstT32 = new();
|
||||
private static List<InstInfo> AllInstA64 = new();
|
||||
private static readonly List<InstInfo> _allInstA32 = new();
|
||||
private static readonly List<InstInfo> _allInstT32 = new();
|
||||
private static readonly List<InstInfo> _allInstA64 = new();
|
||||
|
||||
private static InstInfo[][] InstA32FastLookup = new InstInfo[FastLookupSize][];
|
||||
private static InstInfo[][] InstT32FastLookup = new InstInfo[FastLookupSize][];
|
||||
private static InstInfo[][] InstA64FastLookup = new InstInfo[FastLookupSize][];
|
||||
private static readonly InstInfo[][] _instA32FastLookup = new InstInfo[FastLookupSize][];
|
||||
private static readonly InstInfo[][] _instT32FastLookup = new InstInfo[FastLookupSize][];
|
||||
private static readonly InstInfo[][] _instA64FastLookup = new InstInfo[FastLookupSize][];
|
||||
|
||||
static OpCodeTable()
|
||||
{
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
#region "OpCode Table (AArch64)"
|
||||
// Base
|
||||
SetA64("x0011010000xxxxx000000xxxxxxxxxx", InstName.Adc, InstEmit.Adc, OpCodeAluRs.Create);
|
||||
|
@ -917,6 +918,7 @@ namespace ARMeilleure.Decoders
|
|||
SetAsimd("111100111x11xx01xxxx0x100xx0xxxx", InstName.Vclt, InstEmit32.Vclt_Z, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
|
||||
SetAsimd("111100111x110000xxxx01010xx0xxxx", InstName.Vcnt, InstEmit32.Vcnt, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32);
|
||||
SetAsimd("111100111x111011xxxx011xxxx0xxxx", InstName.Vcvt, InstEmit32.Vcvt_V, OpCode32SimdCmpZ.Create, OpCode32SimdCmpZ.CreateT32); // FP and integer, vector.
|
||||
SetAsimd("1111001x1x1xxxxxxxxx111x0xx1xxxx", InstName.Vcvt, InstEmit32.Vcvt_V_Fixed, OpCode32SimdCvtFFixed.Create, OpCode32SimdCvtFFixed.CreateT32); // Between floating point and fixed point, vector.
|
||||
SetAsimd("111100111x11xxxxxxxx11000xx0xxxx", InstName.Vdup, InstEmit32.Vdup_1, OpCode32SimdDupElem.Create, OpCode32SimdDupElem.CreateT32);
|
||||
SetAsimd("111100110x00xxxxxxxx0001xxx1xxxx", InstName.Veor, InstEmit32.Veor_I, OpCode32SimdBinary.Create, OpCode32SimdBinary.CreateT32);
|
||||
SetAsimd("111100101x11xxxxxxxxxxxxxxx0xxxx", InstName.Vext, InstEmit32.Vext, OpCode32SimdExt.Create, OpCode32SimdExt.CreateT32);
|
||||
|
@ -1299,12 +1301,13 @@ namespace ARMeilleure.Decoders
|
|||
SetT32("11110011101011111000000000000001", InstName.Yield, InstEmit32.Nop, OpCodeT32.Create);
|
||||
#endregion
|
||||
|
||||
FillFastLookupTable(InstA32FastLookup, AllInstA32, ToFastLookupIndexA);
|
||||
FillFastLookupTable(InstT32FastLookup, AllInstT32, ToFastLookupIndexT);
|
||||
FillFastLookupTable(InstA64FastLookup, AllInstA64, ToFastLookupIndexA);
|
||||
FillFastLookupTable(_instA32FastLookup, _allInstA32, ToFastLookupIndexA);
|
||||
FillFastLookupTable(_instT32FastLookup, _allInstT32, ToFastLookupIndexT);
|
||||
FillFastLookupTable(_instA64FastLookup, _allInstA64, ToFastLookupIndexA);
|
||||
#pragma warning restore IDE0055
|
||||
}
|
||||
|
||||
private static void FillFastLookupTable(InstInfo[][] table, List<InstInfo> allInsts, Func<int, int> ToFastLookupIndex)
|
||||
private static void FillFastLookupTable(InstInfo[][] table, List<InstInfo> allInsts, Func<int, int> toFastLookupIndex)
|
||||
{
|
||||
List<InstInfo>[] temp = new List<InstInfo>[FastLookupSize];
|
||||
|
||||
|
@ -1315,8 +1318,8 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
foreach (InstInfo inst in allInsts)
|
||||
{
|
||||
int mask = ToFastLookupIndex(inst.Mask);
|
||||
int value = ToFastLookupIndex(inst.Value);
|
||||
int mask = toFastLookupIndex(inst.Mask);
|
||||
int value = toFastLookupIndex(inst.Value);
|
||||
|
||||
for (int index = 0; index < temp.Length; index++)
|
||||
{
|
||||
|
@ -1335,22 +1338,21 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
private static void SetA32(string encoding, InstName name, InstEmitter emitter, MakeOp makeOp)
|
||||
{
|
||||
Set(encoding, AllInstA32, new InstDescriptor(name, emitter), makeOp);
|
||||
Set(encoding, _allInstA32, new InstDescriptor(name, emitter), makeOp);
|
||||
}
|
||||
|
||||
private static void SetT16(string encoding, InstName name, InstEmitter emitter, MakeOp makeOp)
|
||||
{
|
||||
encoding = "xxxxxxxxxxxxxxxx" + encoding;
|
||||
Set(encoding, AllInstT32, new InstDescriptor(name, emitter), makeOp);
|
||||
Set(encoding, _allInstT32, new InstDescriptor(name, emitter), makeOp);
|
||||
}
|
||||
|
||||
private static void SetT32(string encoding, InstName name, InstEmitter emitter, MakeOp makeOp)
|
||||
{
|
||||
string reversedEncoding = $"{encoding.AsSpan(16)}{encoding.AsSpan(0, 16)}";
|
||||
MakeOp reversedMakeOp =
|
||||
(inst, address, opCode)
|
||||
OpCode ReversedMakeOp(InstDescriptor inst, ulong address, int opCode)
|
||||
=> makeOp(inst, address, (int)BitOperations.RotateRight((uint)opCode, 16));
|
||||
Set(reversedEncoding, AllInstT32, new InstDescriptor(name, emitter), reversedMakeOp);
|
||||
Set(reversedEncoding, _allInstT32, new InstDescriptor(name, emitter), ReversedMakeOp);
|
||||
}
|
||||
|
||||
private static void SetVfp(string encoding, InstName name, InstEmitter emitter, MakeOp makeOpA32, MakeOp makeOpT32)
|
||||
|
@ -1395,7 +1397,7 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
private static void SetA64(string encoding, InstName name, InstEmitter emitter, MakeOp makeOp)
|
||||
{
|
||||
Set(encoding, AllInstA64, new InstDescriptor(name, emitter), makeOp);
|
||||
Set(encoding, _allInstA64, new InstDescriptor(name, emitter), makeOp);
|
||||
}
|
||||
|
||||
private static void Set(string encoding, List<InstInfo> list, InstDescriptor inst, MakeOp makeOp)
|
||||
|
@ -1439,7 +1441,7 @@ namespace ARMeilleure.Decoders
|
|||
}
|
||||
else if (chr != '0')
|
||||
{
|
||||
throw new ArgumentException(nameof(encoding));
|
||||
throw new ArgumentException($"Invalid encoding: {encoding}", nameof(encoding));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1470,17 +1472,17 @@ namespace ARMeilleure.Decoders
|
|||
|
||||
public static (InstDescriptor inst, MakeOp makeOp) GetInstA32(int opCode)
|
||||
{
|
||||
return GetInstFromList(InstA32FastLookup[ToFastLookupIndexA(opCode)], opCode);
|
||||
return GetInstFromList(_instA32FastLookup[ToFastLookupIndexA(opCode)], opCode);
|
||||
}
|
||||
|
||||
public static (InstDescriptor inst, MakeOp makeOp) GetInstT32(int opCode)
|
||||
{
|
||||
return GetInstFromList(InstT32FastLookup[ToFastLookupIndexT(opCode)], opCode);
|
||||
return GetInstFromList(_instT32FastLookup[ToFastLookupIndexT(opCode)], opCode);
|
||||
}
|
||||
|
||||
public static (InstDescriptor inst, MakeOp makeOp) GetInstA64(int opCode)
|
||||
{
|
||||
return GetInstFromList(InstA64FastLookup[ToFastLookupIndexA(opCode)], opCode);
|
||||
return GetInstFromList(_instA64FastLookup[ToFastLookupIndexA(opCode)], opCode);
|
||||
}
|
||||
|
||||
private static (InstDescriptor inst, MakeOp makeOp) GetInstFromList(InstInfo[] insts, int opCode)
|
||||
|
|
|
@ -17,7 +17,7 @@ namespace ARMeilleure.Decoders.Optimizations
|
|||
throw new InvalidOperationException("Function entry point is not contained in a block.");
|
||||
}
|
||||
|
||||
const ulong allowance = 4;
|
||||
const ulong Allowance = 4;
|
||||
|
||||
Block entryBlock = blocks[entryBlockId];
|
||||
|
||||
|
@ -31,7 +31,7 @@ namespace ARMeilleure.Decoders.Optimizations
|
|||
{
|
||||
Block block = blocks[i];
|
||||
|
||||
if (endBlock.EndAddress < block.Address - allowance)
|
||||
if (endBlock.EndAddress < block.Address - Allowance)
|
||||
{
|
||||
break; // End of contiguous function.
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ namespace ARMeilleure.Decoders.Optimizations
|
|||
{
|
||||
Block block = blocks[i];
|
||||
|
||||
if (startBlock.Address > block.EndAddress + allowance)
|
||||
if (startBlock.Address > block.EndAddress + Allowance)
|
||||
{
|
||||
break; // End of contiguous function.
|
||||
}
|
||||
|
|
|
@ -5,6 +5,6 @@ namespace ARMeilleure.Decoders
|
|||
Int32,
|
||||
Int64,
|
||||
Simd64,
|
||||
Simd128
|
||||
Simd128,
|
||||
}
|
||||
}
|
|
@ -5,6 +5,6 @@ namespace ARMeilleure.Decoders
|
|||
Lsl = 0,
|
||||
Lsr = 1,
|
||||
Asr = 2,
|
||||
Ror = 3
|
||||
Ror = 3,
|
||||
}
|
||||
}
|
|
@ -34,7 +34,9 @@ namespace ARMeilleure.Diagnostics
|
|||
|
||||
for (int index = 0; index < _indentLevel; index++)
|
||||
{
|
||||
#pragma warning disable CA1834 // Use StringBuilder.Append(char) for single character strings
|
||||
_builder.Append(Indentation);
|
||||
#pragma warning restore CA1834
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -110,10 +112,18 @@ namespace ARMeilleure.Diagnostics
|
|||
|
||||
switch (reg.Type)
|
||||
{
|
||||
case RegisterType.Flag: _builder.Append('b'); break;
|
||||
case RegisterType.FpFlag: _builder.Append('f'); break;
|
||||
case RegisterType.Integer: _builder.Append('r'); break;
|
||||
case RegisterType.Vector: _builder.Append('v'); break;
|
||||
case RegisterType.Flag:
|
||||
_builder.Append('b');
|
||||
break;
|
||||
case RegisterType.FpFlag:
|
||||
_builder.Append('f');
|
||||
break;
|
||||
case RegisterType.Integer:
|
||||
_builder.Append('r');
|
||||
break;
|
||||
case RegisterType.Vector:
|
||||
_builder.Append('v');
|
||||
break;
|
||||
}
|
||||
|
||||
_builder.Append(reg.Index);
|
||||
|
@ -145,9 +155,15 @@ namespace ARMeilleure.Diagnostics
|
|||
|
||||
switch (memOp.Scale)
|
||||
{
|
||||
case Multiplier.x2: _builder.Append("*2"); break;
|
||||
case Multiplier.x4: _builder.Append("*4"); break;
|
||||
case Multiplier.x8: _builder.Append("*8"); break;
|
||||
case Multiplier.x2:
|
||||
_builder.Append("*2");
|
||||
break;
|
||||
case Multiplier.x4:
|
||||
_builder.Append("*4");
|
||||
break;
|
||||
case Multiplier.x8:
|
||||
_builder.Append("*8");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ namespace ARMeilleure.Diagnostics
|
|||
{
|
||||
private static long _startTime;
|
||||
|
||||
private static long[] _accumulatedTime;
|
||||
private static readonly long[] _accumulatedTime;
|
||||
|
||||
static Logger()
|
||||
{
|
||||
|
|
|
@ -14,6 +14,6 @@ namespace ARMeilleure.Diagnostics
|
|||
RegisterAllocation,
|
||||
CodeGeneration,
|
||||
|
||||
Count
|
||||
Count,
|
||||
}
|
||||
}
|
|
@ -33,9 +33,8 @@ namespace ARMeilleure.Diagnostics
|
|||
|
||||
public static string Get(ulong address)
|
||||
{
|
||||
string result;
|
||||
|
||||
if (_symbols.TryGetValue(address, out result))
|
||||
if (_symbols.TryGetValue(address, out string result))
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -19,19 +19,19 @@ namespace ARMeilleure.Diagnostics
|
|||
{
|
||||
_rejitQueueCounter = new PollingCounter("rejit-queue-length", this, () => _rejitQueue)
|
||||
{
|
||||
DisplayName = "Rejit Queue Length"
|
||||
DisplayName = "Rejit Queue Length",
|
||||
};
|
||||
|
||||
_funcTabSizeCounter = new PollingCounter("addr-tab-alloc", this, () => _funcTabSize / 1024d / 1024d)
|
||||
{
|
||||
DisplayName = "AddressTable Total Bytes Allocated",
|
||||
DisplayUnits = "MiB"
|
||||
DisplayUnits = "MiB",
|
||||
};
|
||||
|
||||
_funcTabLeafSizeCounter = new PollingCounter("addr-tab-leaf-alloc", this, () => _funcTabLeafSize / 1024d / 1024d)
|
||||
{
|
||||
DisplayName = "AddressTable Total Leaf Bytes Allocated",
|
||||
DisplayUnits = "MiB"
|
||||
DisplayUnits = "MiB",
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ namespace ARMeilleure.Instructions
|
|||
static class CryptoHelper
|
||||
{
|
||||
#region "LookUp Tables"
|
||||
#pragma warning disable IDE1006 // Naming rule violation
|
||||
private static ReadOnlySpan<byte> _sBox => new byte[]
|
||||
{
|
||||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
|
||||
|
@ -25,7 +26,7 @@ namespace ARMeilleure.Instructions
|
|||
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
|
||||
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
|
||||
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16,
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> _invSBox => new byte[]
|
||||
|
@ -45,7 +46,7 @@ namespace ARMeilleure.Instructions
|
|||
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
|
||||
0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
|
||||
0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
|
||||
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d
|
||||
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d,
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> _gfMul02 => new byte[]
|
||||
|
@ -65,7 +66,7 @@ namespace ARMeilleure.Instructions
|
|||
0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85,
|
||||
0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5,
|
||||
0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5,
|
||||
0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5
|
||||
0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5,
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> _gfMul03 => new byte[]
|
||||
|
@ -85,7 +86,7 @@ namespace ARMeilleure.Instructions
|
|||
0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, 0x4f, 0x4c, 0x49, 0x4a,
|
||||
0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a,
|
||||
0x3b, 0x38, 0x3d, 0x3e, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a,
|
||||
0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a
|
||||
0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a,
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> _gfMul09 => new byte[]
|
||||
|
@ -105,7 +106,7 @@ namespace ARMeilleure.Instructions
|
|||
0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed,
|
||||
0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d,
|
||||
0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6,
|
||||
0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46
|
||||
0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46,
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> _gfMul0B => new byte[]
|
||||
|
@ -125,7 +126,7 @@ namespace ARMeilleure.Instructions
|
|||
0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68,
|
||||
0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8,
|
||||
0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13,
|
||||
0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3
|
||||
0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3,
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> _gfMul0D => new byte[]
|
||||
|
@ -145,7 +146,7 @@ namespace ARMeilleure.Instructions
|
|||
0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc,
|
||||
0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c,
|
||||
0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47,
|
||||
0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97
|
||||
0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97,
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> _gfMul0E => new byte[]
|
||||
|
@ -165,18 +166,19 @@ namespace ARMeilleure.Instructions
|
|||
0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6,
|
||||
0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56,
|
||||
0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d,
|
||||
0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d
|
||||
0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d,
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> _srPerm => new byte[]
|
||||
{
|
||||
0, 13, 10, 7, 4, 1, 14, 11, 8, 5, 2, 15, 12, 9, 6, 3
|
||||
0, 13, 10, 7, 4, 1, 14, 11, 8, 5, 2, 15, 12, 9, 6, 3,
|
||||
};
|
||||
|
||||
private static ReadOnlySpan<byte> _isrPerm => new byte[]
|
||||
{
|
||||
0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11
|
||||
0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11,
|
||||
};
|
||||
#pragma warning restore IDE1006
|
||||
#endregion
|
||||
|
||||
public static V128 AesInvMixColumns(V128 op)
|
||||
|
|
|
@ -3,7 +3,6 @@ using ARMeilleure.IntermediateRepresentation;
|
|||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
using System.Diagnostics;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitAluHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
|
|
@ -2,13 +2,14 @@ using ARMeilleure.Decoders;
|
|||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using static ARMeilleure.Instructions.InstEmitAluHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
||||
namespace ARMeilleure.Instructions
|
||||
{
|
||||
[SuppressMessage("Style", "IDE0059: Remove unnecessary value assignment")]
|
||||
static partial class InstEmit32
|
||||
{
|
||||
public static void Add(ArmEmitterContext context)
|
||||
|
|
|
@ -205,12 +205,16 @@ namespace ARMeilleure.Instructions
|
|||
return Const(op.Immediate);
|
||||
}
|
||||
|
||||
case IOpCode32AluImm16 op: return Const(op.Immediate);
|
||||
case IOpCode32AluImm16 op:
|
||||
return Const(op.Immediate);
|
||||
|
||||
case IOpCode32AluRsImm op: return GetMShiftedByImmediate(context, op, setCarry);
|
||||
case IOpCode32AluRsReg op: return GetMShiftedByReg(context, op, setCarry);
|
||||
case IOpCode32AluRsImm op:
|
||||
return GetMShiftedByImmediate(context, op, setCarry);
|
||||
case IOpCode32AluRsReg op:
|
||||
return GetMShiftedByReg(context, op, setCarry);
|
||||
|
||||
case IOpCode32AluReg op: return GetIntA32(context, op.Rm);
|
||||
case IOpCode32AluReg op:
|
||||
return GetIntA32(context, op.Rm);
|
||||
|
||||
// ARM64.
|
||||
case IOpCodeAluImm op:
|
||||
|
@ -231,10 +235,18 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (op.ShiftType)
|
||||
{
|
||||
case ShiftType.Lsl: value = context.ShiftLeft (value, Const(op.Shift)); break;
|
||||
case ShiftType.Lsr: value = context.ShiftRightUI(value, Const(op.Shift)); break;
|
||||
case ShiftType.Asr: value = context.ShiftRightSI(value, Const(op.Shift)); break;
|
||||
case ShiftType.Ror: value = context.RotateRight (value, Const(op.Shift)); break;
|
||||
case ShiftType.Lsl:
|
||||
value = context.ShiftLeft(value, Const(op.Shift));
|
||||
break;
|
||||
case ShiftType.Lsr:
|
||||
value = context.ShiftRightUI(value, Const(op.Shift));
|
||||
break;
|
||||
case ShiftType.Asr:
|
||||
value = context.ShiftRightSI(value, Const(op.Shift));
|
||||
break;
|
||||
case ShiftType.Ror:
|
||||
value = context.RotateRight(value, Const(op.Shift));
|
||||
break;
|
||||
}
|
||||
|
||||
return value;
|
||||
|
@ -249,7 +261,8 @@ namespace ARMeilleure.Instructions
|
|||
return value;
|
||||
}
|
||||
|
||||
default: throw InvalidOpCodeType(context.CurrOp);
|
||||
default:
|
||||
throw InvalidOpCodeType(context.CurrOp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -269,9 +282,15 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
switch (op.ShiftType)
|
||||
{
|
||||
case ShiftType.Lsr: shift = 32; break;
|
||||
case ShiftType.Asr: shift = 32; break;
|
||||
case ShiftType.Ror: shift = 1; break;
|
||||
case ShiftType.Lsr:
|
||||
shift = 32;
|
||||
break;
|
||||
case ShiftType.Asr:
|
||||
shift = 32;
|
||||
break;
|
||||
case ShiftType.Ror:
|
||||
shift = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -281,9 +300,15 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (op.ShiftType)
|
||||
{
|
||||
case ShiftType.Lsl: m = GetLslC(context, m, setCarry, shift); break;
|
||||
case ShiftType.Lsr: m = GetLsrC(context, m, setCarry, shift); break;
|
||||
case ShiftType.Asr: m = GetAsrC(context, m, setCarry, shift); break;
|
||||
case ShiftType.Lsl:
|
||||
m = GetLslC(context, m, setCarry, shift);
|
||||
break;
|
||||
case ShiftType.Lsr:
|
||||
m = GetLsrC(context, m, setCarry, shift);
|
||||
break;
|
||||
case ShiftType.Asr:
|
||||
m = GetAsrC(context, m, setCarry, shift);
|
||||
break;
|
||||
case ShiftType.Ror:
|
||||
if (op.Immediate != 0)
|
||||
{
|
||||
|
@ -306,9 +331,15 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
switch (shiftType)
|
||||
{
|
||||
case ShiftType.Lsr: shift = 32; break;
|
||||
case ShiftType.Asr: shift = 32; break;
|
||||
case ShiftType.Ror: shift = 1; break;
|
||||
case ShiftType.Lsr:
|
||||
shift = 32;
|
||||
break;
|
||||
case ShiftType.Asr:
|
||||
shift = 32;
|
||||
break;
|
||||
case ShiftType.Ror:
|
||||
shift = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -328,10 +359,18 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (op.ShiftType)
|
||||
{
|
||||
case ShiftType.Lsl: shiftResult = EmitLslC(context, m, setCarry, s, shiftIsZero); break;
|
||||
case ShiftType.Lsr: shiftResult = EmitLsrC(context, m, setCarry, s, shiftIsZero); break;
|
||||
case ShiftType.Asr: shiftResult = EmitAsrC(context, m, setCarry, s, shiftIsZero); break;
|
||||
case ShiftType.Ror: shiftResult = EmitRorC(context, m, setCarry, s, shiftIsZero); break;
|
||||
case ShiftType.Lsl:
|
||||
shiftResult = EmitLslC(context, m, setCarry, s, shiftIsZero);
|
||||
break;
|
||||
case ShiftType.Lsr:
|
||||
shiftResult = EmitLsrC(context, m, setCarry, s, shiftIsZero);
|
||||
break;
|
||||
case ShiftType.Asr:
|
||||
shiftResult = EmitAsrC(context, m, setCarry, s, shiftIsZero);
|
||||
break;
|
||||
case ShiftType.Ror:
|
||||
shiftResult = EmitRorC(context, m, setCarry, s, shiftIsZero);
|
||||
break;
|
||||
}
|
||||
|
||||
return context.ConditionalSelect(shiftIsZero, zeroResult, shiftResult);
|
||||
|
|
|
@ -2,7 +2,6 @@ using ARMeilleure.Decoders;
|
|||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitAluHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitFlowHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using ARMeilleure.Decoders;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitFlowHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
@ -15,7 +14,7 @@ namespace ARMeilleure.Instructions
|
|||
None,
|
||||
Increment,
|
||||
Invert,
|
||||
Negate
|
||||
Negate,
|
||||
}
|
||||
|
||||
public static void Csel(ArmEmitterContext context) => EmitCsel(context, CselOperation.None);
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using ARMeilleure.Decoders;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ namespace ARMeilleure.Instructions
|
|||
(1, true) => nameof(SoftFallback.Crc32ch),
|
||||
(2, true) => nameof(SoftFallback.Crc32cw),
|
||||
(3, true) => nameof(SoftFallback.Crc32cx),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(size))
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(size)),
|
||||
};
|
||||
|
||||
return context.Call(typeof(SoftFallback).GetMethod(name), crc, value);
|
||||
|
@ -71,9 +71,15 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0: data = context.VectorInsert8(context.VectorZero(), data, 0); break;
|
||||
case 1: data = context.VectorInsert16(context.VectorZero(), data, 0); break;
|
||||
case 2: data = context.VectorInsert(context.VectorZero(), data, 0); break;
|
||||
case 0:
|
||||
data = context.VectorInsert8(context.VectorZero(), data, 0);
|
||||
break;
|
||||
case 1:
|
||||
data = context.VectorInsert16(context.VectorZero(), data, 0);
|
||||
break;
|
||||
case 2:
|
||||
data = context.VectorInsert(context.VectorZero(), data, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
int bitsize = 8 << size;
|
||||
|
|
|
@ -16,13 +16,25 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (type)
|
||||
{
|
||||
case IntType.UInt8: value = context.ZeroExtend8 (value.Type, value); break;
|
||||
case IntType.UInt16: value = context.ZeroExtend16(value.Type, value); break;
|
||||
case IntType.UInt32: value = context.ZeroExtend32(value.Type, value); break;
|
||||
case IntType.UInt8:
|
||||
value = context.ZeroExtend8(value.Type, value);
|
||||
break;
|
||||
case IntType.UInt16:
|
||||
value = context.ZeroExtend16(value.Type, value);
|
||||
break;
|
||||
case IntType.UInt32:
|
||||
value = context.ZeroExtend32(value.Type, value);
|
||||
break;
|
||||
|
||||
case IntType.Int8: value = context.SignExtend8 (value.Type, value); break;
|
||||
case IntType.Int16: value = context.SignExtend16(value.Type, value); break;
|
||||
case IntType.Int32: value = context.SignExtend32(value.Type, value); break;
|
||||
case IntType.Int8:
|
||||
value = context.SignExtend8(value.Type, value);
|
||||
break;
|
||||
case IntType.Int16:
|
||||
value = context.SignExtend16(value.Type, value);
|
||||
break;
|
||||
case IntType.Int32:
|
||||
value = context.SignExtend32(value.Type, value);
|
||||
break;
|
||||
}
|
||||
|
||||
return value;
|
||||
|
@ -100,78 +112,51 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static int GetBankedRegisterAlias(Aarch32Mode mode, int regIndex)
|
||||
{
|
||||
switch (regIndex)
|
||||
return regIndex switch
|
||||
{
|
||||
case 8: return mode == Aarch32Mode.Fiq
|
||||
? RegisterAlias.R8Fiq
|
||||
: RegisterAlias.R8Usr;
|
||||
|
||||
case 9: return mode == Aarch32Mode.Fiq
|
||||
? RegisterAlias.R9Fiq
|
||||
: RegisterAlias.R9Usr;
|
||||
|
||||
case 10: return mode == Aarch32Mode.Fiq
|
||||
? RegisterAlias.R10Fiq
|
||||
: RegisterAlias.R10Usr;
|
||||
|
||||
case 11: return mode == Aarch32Mode.Fiq
|
||||
? RegisterAlias.R11Fiq
|
||||
: RegisterAlias.R11Usr;
|
||||
|
||||
case 12: return mode == Aarch32Mode.Fiq
|
||||
? RegisterAlias.R12Fiq
|
||||
: RegisterAlias.R12Usr;
|
||||
|
||||
case 13:
|
||||
switch (mode)
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
8 => mode == Aarch32Mode.Fiq ? RegisterAlias.R8Fiq : RegisterAlias.R8Usr,
|
||||
9 => mode == Aarch32Mode.Fiq ? RegisterAlias.R9Fiq : RegisterAlias.R9Usr,
|
||||
10 => mode == Aarch32Mode.Fiq ? RegisterAlias.R10Fiq : RegisterAlias.R10Usr,
|
||||
11 => mode == Aarch32Mode.Fiq ? RegisterAlias.R11Fiq : RegisterAlias.R11Usr,
|
||||
12 => mode == Aarch32Mode.Fiq ? RegisterAlias.R12Fiq : RegisterAlias.R12Usr,
|
||||
13 => mode switch
|
||||
{
|
||||
case Aarch32Mode.User:
|
||||
case Aarch32Mode.System: return RegisterAlias.SpUsr;
|
||||
case Aarch32Mode.Fiq: return RegisterAlias.SpFiq;
|
||||
case Aarch32Mode.Irq: return RegisterAlias.SpIrq;
|
||||
case Aarch32Mode.Supervisor: return RegisterAlias.SpSvc;
|
||||
case Aarch32Mode.Abort: return RegisterAlias.SpAbt;
|
||||
case Aarch32Mode.Hypervisor: return RegisterAlias.SpHyp;
|
||||
case Aarch32Mode.Undefined: return RegisterAlias.SpUnd;
|
||||
|
||||
default: throw new ArgumentException(nameof(mode));
|
||||
}
|
||||
|
||||
case 14:
|
||||
switch (mode)
|
||||
Aarch32Mode.User or Aarch32Mode.System => RegisterAlias.SpUsr,
|
||||
Aarch32Mode.Fiq => RegisterAlias.SpFiq,
|
||||
Aarch32Mode.Irq => RegisterAlias.SpIrq,
|
||||
Aarch32Mode.Supervisor => RegisterAlias.SpSvc,
|
||||
Aarch32Mode.Abort => RegisterAlias.SpAbt,
|
||||
Aarch32Mode.Hypervisor => RegisterAlias.SpHyp,
|
||||
Aarch32Mode.Undefined => RegisterAlias.SpUnd,
|
||||
_ => throw new ArgumentException($"No such AArch32Mode: {mode}", nameof(mode)),
|
||||
},
|
||||
14 => mode switch
|
||||
{
|
||||
case Aarch32Mode.User:
|
||||
case Aarch32Mode.Hypervisor:
|
||||
case Aarch32Mode.System: return RegisterAlias.LrUsr;
|
||||
case Aarch32Mode.Fiq: return RegisterAlias.LrFiq;
|
||||
case Aarch32Mode.Irq: return RegisterAlias.LrIrq;
|
||||
case Aarch32Mode.Supervisor: return RegisterAlias.LrSvc;
|
||||
case Aarch32Mode.Abort: return RegisterAlias.LrAbt;
|
||||
case Aarch32Mode.Undefined: return RegisterAlias.LrUnd;
|
||||
|
||||
default: throw new ArgumentException(nameof(mode));
|
||||
}
|
||||
|
||||
default: throw new ArgumentOutOfRangeException(nameof(regIndex));
|
||||
}
|
||||
Aarch32Mode.User or Aarch32Mode.Hypervisor or Aarch32Mode.System => RegisterAlias.LrUsr,
|
||||
Aarch32Mode.Fiq => RegisterAlias.LrFiq,
|
||||
Aarch32Mode.Irq => RegisterAlias.LrIrq,
|
||||
Aarch32Mode.Supervisor => RegisterAlias.LrSvc,
|
||||
Aarch32Mode.Abort => RegisterAlias.LrAbt,
|
||||
Aarch32Mode.Undefined => RegisterAlias.LrUnd,
|
||||
_ => throw new ArgumentException($"No such AArch32Mode: {mode}", nameof(mode)),
|
||||
},
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(regIndex), regIndex, null),
|
||||
#pragma warning restore IDE0055
|
||||
};
|
||||
}
|
||||
|
||||
public static bool IsA32Return(ArmEmitterContext context)
|
||||
{
|
||||
switch (context.CurrOp)
|
||||
return context.CurrOp switch
|
||||
{
|
||||
case IOpCode32MemMult op:
|
||||
return true; // Setting PC using LDM is nearly always a return.
|
||||
case OpCode32AluRsImm op:
|
||||
return op.Rm == RegisterAlias.Aarch32Lr;
|
||||
case OpCode32AluRsReg op:
|
||||
return op.Rm == RegisterAlias.Aarch32Lr;
|
||||
case OpCode32AluReg op:
|
||||
return op.Rm == RegisterAlias.Aarch32Lr;
|
||||
case OpCode32Mem op:
|
||||
return op.Rn == RegisterAlias.Aarch32Sp && op.WBack && !op.Index; // Setting PC to an address stored on the stack is nearly always a return.
|
||||
}
|
||||
return false;
|
||||
IOpCode32MemMult => true, // Setting PC using LDM is nearly always a return.
|
||||
OpCode32AluRsImm op => op.Rm == RegisterAlias.Aarch32Lr,
|
||||
OpCode32AluRsReg op => op.Rm == RegisterAlias.Aarch32Lr,
|
||||
OpCode32AluReg op => op.Rm == RegisterAlias.Aarch32Lr,
|
||||
OpCode32Mem op => op.Rn == RegisterAlias.Aarch32Sp && op.WBack && !op.Index, // Setting PC to an address stored on the stack is nearly always a return.
|
||||
_ => false,
|
||||
};
|
||||
}
|
||||
|
||||
public static void EmitBxWritePc(ArmEmitterContext context, Operand pc, int sourceRegister = 0)
|
||||
|
|
|
@ -3,7 +3,6 @@ using ARMeilleure.IntermediateRepresentation;
|
|||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitMemoryHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
|
|
@ -3,7 +3,6 @@ using ARMeilleure.IntermediateRepresentation;
|
|||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitMemoryExHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
@ -18,7 +17,7 @@ namespace ARMeilleure.Instructions
|
|||
None = 0,
|
||||
Ordered = 1,
|
||||
Exclusive = 2,
|
||||
OrderedEx = Ordered | Exclusive
|
||||
OrderedEx = Ordered | Exclusive,
|
||||
}
|
||||
|
||||
public static void Clrex(ArmEmitterContext context)
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
||||
|
@ -118,14 +117,14 @@ namespace ARMeilleure.Instructions
|
|||
1 => context.Load16(exValuePtr),
|
||||
2 => context.Load(OperandType.I32, exValuePtr),
|
||||
3 => context.Load(OperandType.I64, exValuePtr),
|
||||
_ => context.Load(OperandType.V128, exValuePtr)
|
||||
_ => context.Load(OperandType.V128, exValuePtr),
|
||||
};
|
||||
|
||||
Operand currValue = size switch
|
||||
{
|
||||
0 => context.CompareAndSwap8(physAddr, exValue, value),
|
||||
1 => context.CompareAndSwap16(physAddr, exValue, value),
|
||||
_ => context.CompareAndSwap(physAddr, exValue, value)
|
||||
_ => context.CompareAndSwap(physAddr, exValue, value),
|
||||
};
|
||||
|
||||
// STEP 3: Check if we succeeded by comparing expected and in-memory values.
|
||||
|
|
|
@ -5,7 +5,6 @@ using ARMeilleure.Translation;
|
|||
using ARMeilleure.Translation.PTC;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
||||
|
@ -20,7 +19,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
Zx,
|
||||
Sx32,
|
||||
Sx64
|
||||
Sx64,
|
||||
}
|
||||
|
||||
public static void EmitLoadZx(ArmEmitterContext context, Operand address, int rt, int size)
|
||||
|
@ -66,9 +65,15 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0: value = context.SignExtend8 (destType, value); break;
|
||||
case 1: value = context.SignExtend16(destType, value); break;
|
||||
case 2: value = context.SignExtend32(destType, value); break;
|
||||
case 0:
|
||||
value = context.SignExtend8(destType, value);
|
||||
break;
|
||||
case 1:
|
||||
value = context.SignExtend16(destType, value);
|
||||
break;
|
||||
case 2:
|
||||
value = context.SignExtend32(destType, value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -136,10 +141,18 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0: value = context.Load8 (physAddr); break;
|
||||
case 1: value = context.Load16(physAddr); break;
|
||||
case 2: value = context.Load (OperandType.I32, physAddr); break;
|
||||
case 3: value = context.Load (OperandType.I64, physAddr); break;
|
||||
case 0:
|
||||
value = context.Load8(physAddr);
|
||||
break;
|
||||
case 1:
|
||||
value = context.Load16(physAddr);
|
||||
break;
|
||||
case 2:
|
||||
value = context.Load(OperandType.I32, physAddr);
|
||||
break;
|
||||
case 3:
|
||||
value = context.Load(OperandType.I64, physAddr);
|
||||
break;
|
||||
}
|
||||
|
||||
context.Copy(temp, value);
|
||||
|
@ -169,10 +182,18 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0: value = context.Load8 (physAddr); break;
|
||||
case 1: value = context.Load16(physAddr); break;
|
||||
case 2: value = context.Load (OperandType.I32, physAddr); break;
|
||||
case 3: value = context.Load (OperandType.I64, physAddr); break;
|
||||
case 0:
|
||||
value = context.Load8(physAddr);
|
||||
break;
|
||||
case 1:
|
||||
value = context.Load16(physAddr);
|
||||
break;
|
||||
case 2:
|
||||
value = context.Load(OperandType.I32, physAddr);
|
||||
break;
|
||||
case 3:
|
||||
value = context.Load(OperandType.I64, physAddr);
|
||||
break;
|
||||
}
|
||||
|
||||
SetInt(context, rt, value);
|
||||
|
@ -204,7 +225,7 @@ namespace ARMeilleure.Instructions
|
|||
1 => context.Load16(physAddr),
|
||||
2 => context.Load(OperandType.I32, physAddr),
|
||||
3 => context.Load(OperandType.I64, physAddr),
|
||||
_ => context.Load(OperandType.V128, physAddr)
|
||||
_ => context.Load(OperandType.V128, physAddr),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -225,11 +246,21 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0: value = context.VectorInsert8 (vector, context.Load8(physAddr), elem); break;
|
||||
case 1: value = context.VectorInsert16(vector, context.Load16(physAddr), elem); break;
|
||||
case 2: value = context.VectorInsert (vector, context.Load(OperandType.I32, physAddr), elem); break;
|
||||
case 3: value = context.VectorInsert (vector, context.Load(OperandType.I64, physAddr), elem); break;
|
||||
case 4: value = context.Load (OperandType.V128, physAddr); break;
|
||||
case 0:
|
||||
value = context.VectorInsert8(vector, context.Load8(physAddr), elem);
|
||||
break;
|
||||
case 1:
|
||||
value = context.VectorInsert16(vector, context.Load16(physAddr), elem);
|
||||
break;
|
||||
case 2:
|
||||
value = context.VectorInsert(vector, context.Load(OperandType.I32, physAddr), elem);
|
||||
break;
|
||||
case 3:
|
||||
value = context.VectorInsert(vector, context.Load(OperandType.I64, physAddr), elem);
|
||||
break;
|
||||
case 4:
|
||||
value = context.Load(OperandType.V128, physAddr);
|
||||
break;
|
||||
}
|
||||
|
||||
context.Copy(GetVec(rt), value);
|
||||
|
@ -267,10 +298,18 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0: context.Store8 (physAddr, value); break;
|
||||
case 1: context.Store16(physAddr, value); break;
|
||||
case 2: context.Store (physAddr, value); break;
|
||||
case 3: context.Store (physAddr, value); break;
|
||||
case 0:
|
||||
context.Store8(physAddr, value);
|
||||
break;
|
||||
case 1:
|
||||
context.Store16(physAddr, value);
|
||||
break;
|
||||
case 2:
|
||||
context.Store(physAddr, value);
|
||||
break;
|
||||
case 3:
|
||||
context.Store(physAddr, value);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!context.Memory.Type.IsHostMapped())
|
||||
|
@ -329,11 +368,21 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0: context.Store8 (physAddr, context.VectorExtract8(value, elem)); break;
|
||||
case 1: context.Store16(physAddr, context.VectorExtract16(value, elem)); break;
|
||||
case 2: context.Store (physAddr, context.VectorExtract(OperandType.I32, value, elem)); break;
|
||||
case 3: context.Store (physAddr, context.VectorExtract(OperandType.I64, value, elem)); break;
|
||||
case 4: context.Store (physAddr, value); break;
|
||||
case 0:
|
||||
context.Store8(physAddr, context.VectorExtract8(value, elem));
|
||||
break;
|
||||
case 1:
|
||||
context.Store16(physAddr, context.VectorExtract16(value, elem));
|
||||
break;
|
||||
case 2:
|
||||
context.Store(physAddr, context.VectorExtract(OperandType.I32, value, elem));
|
||||
break;
|
||||
case 3:
|
||||
context.Store(physAddr, context.VectorExtract(OperandType.I64, value, elem));
|
||||
break;
|
||||
case 4:
|
||||
context.Store(physAddr, value);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!context.Memory.Type.IsHostMapped())
|
||||
|
@ -464,10 +513,18 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadByte)); break;
|
||||
case 1: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt16)); break;
|
||||
case 2: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt32)); break;
|
||||
case 3: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64)); break;
|
||||
case 0:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadByte));
|
||||
break;
|
||||
case 1:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt16));
|
||||
break;
|
||||
case 2:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt32));
|
||||
break;
|
||||
case 3:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64));
|
||||
break;
|
||||
}
|
||||
|
||||
return context.Call(info, address);
|
||||
|
@ -485,21 +542,39 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadByte)); break;
|
||||
case 1: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt16)); break;
|
||||
case 2: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt32)); break;
|
||||
case 3: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64)); break;
|
||||
case 4: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadVector128)); break;
|
||||
case 0:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadByte));
|
||||
break;
|
||||
case 1:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt16));
|
||||
break;
|
||||
case 2:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt32));
|
||||
break;
|
||||
case 3:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadUInt64));
|
||||
break;
|
||||
case 4:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.ReadVector128));
|
||||
break;
|
||||
}
|
||||
|
||||
Operand value = context.Call(info, address);
|
||||
|
||||
switch (size)
|
||||
{
|
||||
case 0: value = context.VectorInsert8 (vector, value, elem); break;
|
||||
case 1: value = context.VectorInsert16(vector, value, elem); break;
|
||||
case 2: value = context.VectorInsert (vector, value, elem); break;
|
||||
case 3: value = context.VectorInsert (vector, value, elem); break;
|
||||
case 0:
|
||||
value = context.VectorInsert8(vector, value, elem);
|
||||
break;
|
||||
case 1:
|
||||
value = context.VectorInsert16(vector, value, elem);
|
||||
break;
|
||||
case 2:
|
||||
value = context.VectorInsert(vector, value, elem);
|
||||
break;
|
||||
case 3:
|
||||
value = context.VectorInsert(vector, value, elem);
|
||||
break;
|
||||
}
|
||||
|
||||
context.Copy(GetVec(rt), value);
|
||||
|
@ -511,10 +586,18 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteByte)); break;
|
||||
case 1: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt16)); break;
|
||||
case 2: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt32)); break;
|
||||
case 3: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt64)); break;
|
||||
case 0:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteByte));
|
||||
break;
|
||||
case 1:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt16));
|
||||
break;
|
||||
case 2:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt32));
|
||||
break;
|
||||
case 3:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt64));
|
||||
break;
|
||||
}
|
||||
|
||||
Operand value = GetInt(context, rt);
|
||||
|
@ -538,11 +621,21 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteByte)); break;
|
||||
case 1: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt16)); break;
|
||||
case 2: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt32)); break;
|
||||
case 3: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt64)); break;
|
||||
case 4: info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteVector128)); break;
|
||||
case 0:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteByte));
|
||||
break;
|
||||
case 1:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt16));
|
||||
break;
|
||||
case 2:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt32));
|
||||
break;
|
||||
case 3:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt64));
|
||||
break;
|
||||
case 4:
|
||||
info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteVector128));
|
||||
break;
|
||||
}
|
||||
|
||||
Operand value = default;
|
||||
|
@ -551,10 +644,18 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
switch (size)
|
||||
{
|
||||
case 0: value = context.VectorExtract8 (GetVec(rt), elem); break;
|
||||
case 1: value = context.VectorExtract16(GetVec(rt), elem); break;
|
||||
case 2: value = context.VectorExtract (OperandType.I32, GetVec(rt), elem); break;
|
||||
case 3: value = context.VectorExtract (OperandType.I64, GetVec(rt), elem); break;
|
||||
case 0:
|
||||
value = context.VectorExtract8(GetVec(rt), elem);
|
||||
break;
|
||||
case 1:
|
||||
value = context.VectorExtract16(GetVec(rt), elem);
|
||||
break;
|
||||
case 2:
|
||||
value = context.VectorExtract(OperandType.I32, GetVec(rt), elem);
|
||||
break;
|
||||
case 3:
|
||||
value = context.VectorExtract(OperandType.I64, GetVec(rt), elem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -585,18 +686,14 @@ namespace ARMeilleure.Instructions
|
|||
// ARM32 helpers.
|
||||
public static Operand GetMemM(ArmEmitterContext context, bool setCarry = true)
|
||||
{
|
||||
switch (context.CurrOp)
|
||||
return context.CurrOp switch
|
||||
{
|
||||
case IOpCode32MemRsImm op: return GetMShiftedByImmediate(context, op, setCarry);
|
||||
|
||||
case IOpCode32MemReg op: return GetIntA32(context, op.Rm);
|
||||
|
||||
case IOpCode32Mem op: return Const(op.Immediate);
|
||||
|
||||
case OpCode32SimdMemImm op: return Const(op.Immediate);
|
||||
|
||||
default: throw InvalidOpCodeType(context.CurrOp);
|
||||
}
|
||||
IOpCode32MemRsImm op => GetMShiftedByImmediate(context, op, setCarry),
|
||||
IOpCode32MemReg op => GetIntA32(context, op.Rm),
|
||||
IOpCode32Mem op => Const(op.Immediate),
|
||||
OpCode32SimdMemImm op => Const(op.Immediate),
|
||||
_ => throw InvalidOpCodeType(context.CurrOp),
|
||||
};
|
||||
}
|
||||
|
||||
private static Exception InvalidOpCodeType(OpCode opCode)
|
||||
|
@ -614,9 +711,15 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
switch (op.ShiftType)
|
||||
{
|
||||
case ShiftType.Lsr: shift = 32; break;
|
||||
case ShiftType.Asr: shift = 32; break;
|
||||
case ShiftType.Ror: shift = 1; break;
|
||||
case ShiftType.Lsr:
|
||||
shift = 32;
|
||||
break;
|
||||
case ShiftType.Asr:
|
||||
shift = 32;
|
||||
break;
|
||||
case ShiftType.Ror:
|
||||
shift = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -626,9 +729,15 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (op.ShiftType)
|
||||
{
|
||||
case ShiftType.Lsl: m = InstEmitAluHelper.GetLslC(context, m, setCarry, shift); break;
|
||||
case ShiftType.Lsr: m = InstEmitAluHelper.GetLsrC(context, m, setCarry, shift); break;
|
||||
case ShiftType.Asr: m = InstEmitAluHelper.GetAsrC(context, m, setCarry, shift); break;
|
||||
case ShiftType.Lsl:
|
||||
m = InstEmitAluHelper.GetLslC(context, m, setCarry, shift);
|
||||
break;
|
||||
case ShiftType.Lsr:
|
||||
m = InstEmitAluHelper.GetLsrC(context, m, setCarry, shift);
|
||||
break;
|
||||
case ShiftType.Asr:
|
||||
m = InstEmitAluHelper.GetAsrC(context, m, setCarry, shift);
|
||||
break;
|
||||
case ShiftType.Ror:
|
||||
if (op.Immediate != 0)
|
||||
{
|
||||
|
|
|
@ -2,7 +2,7 @@ using ARMeilleure.Decoders;
|
|||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
|
||||
namespace ARMeilleure.Instructions
|
||||
|
@ -33,6 +33,7 @@ namespace ARMeilleure.Instructions
|
|||
public static void Umsubl(ArmEmitterContext context) => EmitMull(context, MullFlags.Subtract);
|
||||
|
||||
[Flags]
|
||||
[SuppressMessage("Design", "CA1069: Enums values should not be duplicated")]
|
||||
private enum MullFlags
|
||||
{
|
||||
Subtract = 0,
|
||||
|
@ -40,7 +41,7 @@ namespace ARMeilleure.Instructions
|
|||
Signed = 1 << 1,
|
||||
|
||||
SignedAdd = Signed | Add,
|
||||
SignedSubtract = Signed | Subtract
|
||||
SignedSubtract = Signed | Subtract,
|
||||
}
|
||||
|
||||
private static void EmitMull(ArmEmitterContext context, MullFlags flags)
|
||||
|
|
|
@ -3,7 +3,6 @@ using ARMeilleure.IntermediateRepresentation;
|
|||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitAluHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
@ -20,7 +19,7 @@ namespace ARMeilleure.Instructions
|
|||
Signed = 1 << 2,
|
||||
|
||||
SignedAdd = Signed | Add,
|
||||
SignedSubtract = Signed | Subtract
|
||||
SignedSubtract = Signed | Subtract,
|
||||
}
|
||||
|
||||
public static void Mla(ArmEmitterContext context)
|
||||
|
|
|
@ -7,7 +7,6 @@ using ARMeilleure.State;
|
|||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper32;
|
||||
|
@ -185,11 +184,12 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
int eSize = 8 << op.Size;
|
||||
|
||||
Operand res = eSize switch {
|
||||
Operand res = eSize switch
|
||||
{
|
||||
8 => Clz_V_I8(context, GetVec(op.Rn)),
|
||||
16 => Clz_V_I16(context, GetVec(op.Rn)),
|
||||
32 => Clz_V_I32(context, GetVec(op.Rn)),
|
||||
_ => default
|
||||
_ => default,
|
||||
};
|
||||
|
||||
if (res != default)
|
||||
|
@ -282,12 +282,14 @@ namespace ARMeilleure.Instructions
|
|||
return default;
|
||||
}
|
||||
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
Operand AddVectorI32(Operand op0, Operand op1) => context.AddIntrinsic(Intrinsic.X86Paddd, op0, op1);
|
||||
Operand SubVectorI32(Operand op0, Operand op1) => context.AddIntrinsic(Intrinsic.X86Psubd, op0, op1);
|
||||
Operand ShiftRightVectorUI32(Operand op0, int imm8) => context.AddIntrinsic(Intrinsic.X86Psrld, op0, Const(imm8));
|
||||
Operand OrVector(Operand op0, Operand op1) => context.AddIntrinsic(Intrinsic.X86Por, op0, op1);
|
||||
Operand AndVector(Operand op0, Operand op1) => context.AddIntrinsic(Intrinsic.X86Pand, op0, op1);
|
||||
Operand NotVector(Operand op0) => context.AddIntrinsic(Intrinsic.X86Pandn, op0, context.VectorOne());
|
||||
#pragma warning restore IDE0055
|
||||
|
||||
Operand c55555555 = X86GetAllElements(context, 0x55555555);
|
||||
Operand c33333333 = X86GetAllElements(context, 0x33333333);
|
||||
|
@ -5072,7 +5074,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
None,
|
||||
Add,
|
||||
Subtract
|
||||
Subtract,
|
||||
}
|
||||
|
||||
private static void EmitSse41VectorMul_AddSub(ArmEmitterContext context, AddSub addSub)
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitFlowHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
|
@ -190,7 +189,7 @@ namespace ARMeilleure.Instructions
|
|||
2 => context.Multiply(context.ZeroExtend32(OperandType.I64, insert), Const(0x0000000100000001u)),
|
||||
1 => context.Multiply(context.ZeroExtend16(OperandType.I64, insert), Const(0x0001000100010001u)),
|
||||
0 => context.Multiply(context.ZeroExtend8(OperandType.I64, insert), Const(0x0101010101010101u)),
|
||||
_ => throw new InvalidOperationException($"Invalid Vdup size \"{op.Size}\".")
|
||||
_ => throw new InvalidOperationException($"Invalid Vdup size \"{op.Size}\"."),
|
||||
};
|
||||
|
||||
InsertScalar(context, op.Vd, insert);
|
||||
|
@ -212,7 +211,7 @@ namespace ARMeilleure.Instructions
|
|||
2 => context.Multiply(context.ZeroExtend32(OperandType.I64, insert), Const(0x0000000100000001u)),
|
||||
1 => context.Multiply(context.ZeroExtend16(OperandType.I64, insert), Const(0x0001000100010001u)),
|
||||
0 => context.Multiply(context.ZeroExtend8(OperandType.I64, insert), Const(0x0101010101010101u)),
|
||||
_ => throw new InvalidOperationException($"Invalid Vdup size \"{op.Size}\".")
|
||||
_ => throw new InvalidOperationException($"Invalid Vdup size \"{op.Size}\"."),
|
||||
};
|
||||
|
||||
InsertScalar(context, op.Vd, insert);
|
||||
|
@ -1654,7 +1653,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
IOpCode32Simd op = (IOpCode32Simd)context.CurrOp;
|
||||
|
||||
Func<Operand, Operand, Operand> genericEmit = (n, m) =>
|
||||
Operand genericEmit(Operand n, Operand m)
|
||||
{
|
||||
Operand nNum = context.Copy(n);
|
||||
Operand mNum = context.Copy(m);
|
||||
|
@ -1688,7 +1687,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
return context.AddIntrinsic(isMaxNum ? Intrinsic.X86Maxpd : Intrinsic.X86Minpd, nNum, mNum);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (scalar)
|
||||
{
|
||||
|
|
|
@ -3,7 +3,6 @@ using ARMeilleure.IntermediateRepresentation;
|
|||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
@ -510,7 +509,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
private static void EmitSetNzcv(ArmEmitterContext context, int nzcv)
|
||||
{
|
||||
Operand Extract(int value, int bit)
|
||||
static Operand Extract(int value, int bit)
|
||||
{
|
||||
if (bit != 0)
|
||||
{
|
||||
|
@ -532,7 +531,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
||||
bool cmpWithZero = !(op is OpCodeSimdFcond) ? op.Bit3 : false;
|
||||
bool cmpWithZero = op is not OpCodeSimdFcond && op.Bit3;
|
||||
|
||||
if (Optimizations.FastFP && (signalNaNs ? Optimizations.UseAvx : Optimizations.UseSse2))
|
||||
{
|
||||
|
|
|
@ -5,7 +5,6 @@ using ARMeilleure.Translation;
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
|
|
@ -5,7 +5,6 @@ using ARMeilleure.Translation;
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper32;
|
||||
|
@ -115,6 +114,35 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
}
|
||||
|
||||
public static void Vcvt_V_Fixed(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32SimdCvtFFixed op = (OpCode32SimdCvtFFixed)context.CurrOp;
|
||||
|
||||
var toFixed = op.Opc == 1;
|
||||
int fracBits = op.Fbits;
|
||||
var unsigned = op.U;
|
||||
|
||||
if (toFixed) // F32 to S32 or U32 (fixed)
|
||||
{
|
||||
EmitVectorUnaryOpF32(context, (op1) =>
|
||||
{
|
||||
var scaledValue = context.Multiply(op1, ConstF(MathF.Pow(2f, fracBits)));
|
||||
MethodInfo info = unsigned ? typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToU32)) : typeof(SoftFallback).GetMethod(nameof(SoftFallback.SatF32ToS32));
|
||||
|
||||
return context.Call(info, scaledValue);
|
||||
});
|
||||
}
|
||||
else // S32 or U32 (fixed) to F32
|
||||
{
|
||||
EmitVectorUnaryOpI32(context, (op1) =>
|
||||
{
|
||||
var floatValue = unsigned ? context.ConvertToFPUI(OperandType.FP32, op1) : context.ConvertToFP(OperandType.FP32, op1);
|
||||
|
||||
return context.Multiply(floatValue, ConstF(1f / MathF.Pow(2f, fracBits)));
|
||||
}, !unsigned);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Vcvt_FD(ArmEmitterContext context)
|
||||
{
|
||||
OpCode32SimdS op = (OpCode32SimdS)context.CurrOp;
|
||||
|
@ -225,25 +253,14 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
private static FPRoundingMode RMToRoundMode(int rm)
|
||||
{
|
||||
FPRoundingMode roundMode;
|
||||
switch (rm)
|
||||
return rm switch
|
||||
{
|
||||
case 0b00:
|
||||
roundMode = FPRoundingMode.ToNearestAway;
|
||||
break;
|
||||
case 0b01:
|
||||
roundMode = FPRoundingMode.ToNearest;
|
||||
break;
|
||||
case 0b10:
|
||||
roundMode = FPRoundingMode.TowardsPlusInfinity;
|
||||
break;
|
||||
case 0b11:
|
||||
roundMode = FPRoundingMode.TowardsMinusInfinity;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(rm));
|
||||
}
|
||||
return roundMode;
|
||||
0b00 => FPRoundingMode.ToNearestAway,
|
||||
0b01 => FPRoundingMode.ToNearest,
|
||||
0b10 => FPRoundingMode.TowardsPlusInfinity,
|
||||
0b11 => FPRoundingMode.TowardsMinusInfinity,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(rm)),
|
||||
};
|
||||
}
|
||||
|
||||
// VCVTA/M/N/P (floating-point).
|
||||
|
@ -270,22 +287,24 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (unsigned)
|
||||
{
|
||||
inst = rm switch {
|
||||
inst = rm switch
|
||||
{
|
||||
0b00 => Intrinsic.Arm64FcvtauGp,
|
||||
0b01 => Intrinsic.Arm64FcvtnuGp,
|
||||
0b10 => Intrinsic.Arm64FcvtpuGp,
|
||||
0b11 => Intrinsic.Arm64FcvtmuGp,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(rm))
|
||||
_ => throw new InvalidOperationException($"{nameof(rm)} contains an invalid value: {rm}"),
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
inst = rm switch {
|
||||
inst = rm switch
|
||||
{
|
||||
0b00 => Intrinsic.Arm64FcvtasGp,
|
||||
0b01 => Intrinsic.Arm64FcvtnsGp,
|
||||
0b10 => Intrinsic.Arm64FcvtpsGp,
|
||||
0b11 => Intrinsic.Arm64FcvtmsGp,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(rm))
|
||||
_ => throw new InvalidOperationException($"{nameof(rm)} contains an invalid value: {rm}"),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -297,22 +316,24 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (unsigned)
|
||||
{
|
||||
inst = rm switch {
|
||||
inst = rm switch
|
||||
{
|
||||
0b00 => Intrinsic.Arm64FcvtauS,
|
||||
0b01 => Intrinsic.Arm64FcvtnuS,
|
||||
0b10 => Intrinsic.Arm64FcvtpuS,
|
||||
0b11 => Intrinsic.Arm64FcvtmuS,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(rm))
|
||||
_ => throw new InvalidOperationException($"{nameof(rm)} contains an invalid value: {rm}"),
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
inst = rm switch {
|
||||
inst = rm switch
|
||||
{
|
||||
0b00 => Intrinsic.Arm64FcvtasS,
|
||||
0b01 => Intrinsic.Arm64FcvtnsS,
|
||||
0b10 => Intrinsic.Arm64FcvtpsS,
|
||||
0b11 => Intrinsic.Arm64FcvtmsS,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(rm))
|
||||
_ => throw new InvalidOperationException($"{nameof(rm)} contains an invalid value: {rm}"),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -432,12 +453,13 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (Optimizations.UseAdvSimd)
|
||||
{
|
||||
Intrinsic inst = rm switch {
|
||||
Intrinsic inst = rm switch
|
||||
{
|
||||
0b00 => Intrinsic.Arm64FrintaS,
|
||||
0b01 => Intrinsic.Arm64FrintnS,
|
||||
0b10 => Intrinsic.Arm64FrintpS,
|
||||
0b11 => Intrinsic.Arm64FrintmS,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(rm))
|
||||
_ => throw new InvalidOperationException($"{nameof(rm)} contains an invalid value: {rm}"),
|
||||
};
|
||||
|
||||
InstEmitSimdHelper32Arm64.EmitScalarUnaryOpF32(context, inst);
|
||||
|
|
|
@ -6,7 +6,6 @@ using ARMeilleure.Translation;
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
||||
|
@ -23,14 +22,14 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
14L << 56 | 12L << 48 | 10L << 40 | 08L << 32 | 06L << 24 | 04L << 16 | 02L << 8 | 00L << 0, // B
|
||||
13L << 56 | 12L << 48 | 09L << 40 | 08L << 32 | 05L << 24 | 04L << 16 | 01L << 8 | 00L << 0, // H
|
||||
11L << 56 | 10L << 48 | 09L << 40 | 08L << 32 | 03L << 24 | 02L << 16 | 01L << 8 | 00L << 0 // S
|
||||
11L << 56 | 10L << 48 | 09L << 40 | 08L << 32 | 03L << 24 | 02L << 16 | 01L << 8 | 00L << 0, // S
|
||||
};
|
||||
|
||||
public static readonly long[] OddMasks = new long[]
|
||||
{
|
||||
15L << 56 | 13L << 48 | 11L << 40 | 09L << 32 | 07L << 24 | 05L << 16 | 03L << 8 | 01L << 0, // B
|
||||
15L << 56 | 14L << 48 | 11L << 40 | 10L << 32 | 07L << 24 | 06L << 16 | 03L << 8 | 02L << 0, // H
|
||||
15L << 56 | 14L << 48 | 13L << 40 | 12L << 32 | 07L << 24 | 06L << 16 | 05L << 8 | 04L << 0 // S
|
||||
15L << 56 | 14L << 48 | 13L << 40 | 12L << 32 | 07L << 24 | 06L << 16 | 05L << 8 | 04L << 0, // S
|
||||
};
|
||||
|
||||
public static readonly long ZeroMask = 128L << 56 | 128L << 48 | 128L << 40 | 128L << 32 | 128L << 24 | 128L << 16 | 128L << 8 | 128L << 0;
|
||||
|
@ -50,7 +49,7 @@ namespace ARMeilleure.Instructions
|
|||
Intrinsic.X86Paddb,
|
||||
Intrinsic.X86Paddw,
|
||||
Intrinsic.X86Paddd,
|
||||
Intrinsic.X86Paddq
|
||||
Intrinsic.X86Paddq,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PcmpeqInstruction = new Intrinsic[]
|
||||
|
@ -58,7 +57,7 @@ namespace ARMeilleure.Instructions
|
|||
Intrinsic.X86Pcmpeqb,
|
||||
Intrinsic.X86Pcmpeqw,
|
||||
Intrinsic.X86Pcmpeqd,
|
||||
Intrinsic.X86Pcmpeqq
|
||||
Intrinsic.X86Pcmpeqq,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PcmpgtInstruction = new Intrinsic[]
|
||||
|
@ -66,49 +65,49 @@ namespace ARMeilleure.Instructions
|
|||
Intrinsic.X86Pcmpgtb,
|
||||
Intrinsic.X86Pcmpgtw,
|
||||
Intrinsic.X86Pcmpgtd,
|
||||
Intrinsic.X86Pcmpgtq
|
||||
Intrinsic.X86Pcmpgtq,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PmaxsInstruction = new Intrinsic[]
|
||||
{
|
||||
Intrinsic.X86Pmaxsb,
|
||||
Intrinsic.X86Pmaxsw,
|
||||
Intrinsic.X86Pmaxsd
|
||||
Intrinsic.X86Pmaxsd,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PmaxuInstruction = new Intrinsic[]
|
||||
{
|
||||
Intrinsic.X86Pmaxub,
|
||||
Intrinsic.X86Pmaxuw,
|
||||
Intrinsic.X86Pmaxud
|
||||
Intrinsic.X86Pmaxud,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PminsInstruction = new Intrinsic[]
|
||||
{
|
||||
Intrinsic.X86Pminsb,
|
||||
Intrinsic.X86Pminsw,
|
||||
Intrinsic.X86Pminsd
|
||||
Intrinsic.X86Pminsd,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PminuInstruction = new Intrinsic[]
|
||||
{
|
||||
Intrinsic.X86Pminub,
|
||||
Intrinsic.X86Pminuw,
|
||||
Intrinsic.X86Pminud
|
||||
Intrinsic.X86Pminud,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PmovsxInstruction = new Intrinsic[]
|
||||
{
|
||||
Intrinsic.X86Pmovsxbw,
|
||||
Intrinsic.X86Pmovsxwd,
|
||||
Intrinsic.X86Pmovsxdq
|
||||
Intrinsic.X86Pmovsxdq,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PmovzxInstruction = new Intrinsic[]
|
||||
{
|
||||
Intrinsic.X86Pmovzxbw,
|
||||
Intrinsic.X86Pmovzxwd,
|
||||
Intrinsic.X86Pmovzxdq
|
||||
Intrinsic.X86Pmovzxdq,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PsllInstruction = new Intrinsic[]
|
||||
|
@ -116,14 +115,14 @@ namespace ARMeilleure.Instructions
|
|||
0,
|
||||
Intrinsic.X86Psllw,
|
||||
Intrinsic.X86Pslld,
|
||||
Intrinsic.X86Psllq
|
||||
Intrinsic.X86Psllq,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PsraInstruction = new Intrinsic[]
|
||||
{
|
||||
0,
|
||||
Intrinsic.X86Psraw,
|
||||
Intrinsic.X86Psrad
|
||||
Intrinsic.X86Psrad,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PsrlInstruction = new Intrinsic[]
|
||||
|
@ -131,7 +130,7 @@ namespace ARMeilleure.Instructions
|
|||
0,
|
||||
Intrinsic.X86Psrlw,
|
||||
Intrinsic.X86Psrld,
|
||||
Intrinsic.X86Psrlq
|
||||
Intrinsic.X86Psrlq,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PsubInstruction = new Intrinsic[]
|
||||
|
@ -139,7 +138,7 @@ namespace ARMeilleure.Instructions
|
|||
Intrinsic.X86Psubb,
|
||||
Intrinsic.X86Psubw,
|
||||
Intrinsic.X86Psubd,
|
||||
Intrinsic.X86Psubq
|
||||
Intrinsic.X86Psubq,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PunpckhInstruction = new Intrinsic[]
|
||||
|
@ -147,7 +146,7 @@ namespace ARMeilleure.Instructions
|
|||
Intrinsic.X86Punpckhbw,
|
||||
Intrinsic.X86Punpckhwd,
|
||||
Intrinsic.X86Punpckhdq,
|
||||
Intrinsic.X86Punpckhqdq
|
||||
Intrinsic.X86Punpckhqdq,
|
||||
};
|
||||
|
||||
public static readonly Intrinsic[] X86PunpcklInstruction = new Intrinsic[]
|
||||
|
@ -155,7 +154,7 @@ namespace ARMeilleure.Instructions
|
|||
Intrinsic.X86Punpcklbw,
|
||||
Intrinsic.X86Punpcklwd,
|
||||
Intrinsic.X86Punpckldq,
|
||||
Intrinsic.X86Punpcklqdq
|
||||
Intrinsic.X86Punpcklqdq,
|
||||
};
|
||||
#endregion
|
||||
|
||||
|
@ -310,15 +309,16 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static int X86GetRoundControl(FPRoundingMode roundMode)
|
||||
{
|
||||
switch (roundMode)
|
||||
return roundMode switch
|
||||
{
|
||||
case FPRoundingMode.ToNearest: return 8 | 0; // even
|
||||
case FPRoundingMode.TowardsPlusInfinity: return 8 | 2;
|
||||
case FPRoundingMode.TowardsMinusInfinity: return 8 | 1;
|
||||
case FPRoundingMode.TowardsZero: return 8 | 3;
|
||||
}
|
||||
|
||||
throw new ArgumentException($"Invalid rounding mode \"{roundMode}\".");
|
||||
#pragma warning disable IDE0055 // Disable formatting
|
||||
FPRoundingMode.ToNearest => 8 | 0, // even
|
||||
FPRoundingMode.TowardsPlusInfinity => 8 | 2,
|
||||
FPRoundingMode.TowardsMinusInfinity => 8 | 1,
|
||||
FPRoundingMode.TowardsZero => 8 | 3,
|
||||
_ => throw new ArgumentException($"Invalid rounding mode \"{roundMode}\"."),
|
||||
#pragma warning restore IDE0055
|
||||
};
|
||||
}
|
||||
|
||||
public static Operand EmitSse41RoundToNearestWithTiesToAwayOpF(ArmEmitterContext context, Operand n, bool scalar)
|
||||
|
@ -1299,17 +1299,17 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Debug.Assert((op.Size & 1) == 0 && op.RegisterSize == RegisterSize.Simd128);
|
||||
|
||||
const int sm0 = 0 << 6 | 0 << 4 | 0 << 2 | 0 << 0;
|
||||
const int sm1 = 1 << 6 | 1 << 4 | 1 << 2 | 1 << 0;
|
||||
const int sm2 = 2 << 6 | 2 << 4 | 2 << 2 | 2 << 0;
|
||||
const int sm3 = 3 << 6 | 3 << 4 | 3 << 2 | 3 << 0;
|
||||
const int SM0 = 0 << 6 | 0 << 4 | 0 << 2 | 0 << 0;
|
||||
const int SM1 = 1 << 6 | 1 << 4 | 1 << 2 | 1 << 0;
|
||||
const int SM2 = 2 << 6 | 2 << 4 | 2 << 2 | 2 << 0;
|
||||
const int SM3 = 3 << 6 | 3 << 4 | 3 << 2 | 3 << 0;
|
||||
|
||||
Operand nCopy = context.Copy(GetVec(op.Rn));
|
||||
|
||||
Operand part0 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, nCopy, Const(sm0));
|
||||
Operand part1 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, nCopy, Const(sm1));
|
||||
Operand part2 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, nCopy, Const(sm2));
|
||||
Operand part3 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, nCopy, Const(sm3));
|
||||
Operand part0 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, nCopy, Const(SM0));
|
||||
Operand part1 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, nCopy, Const(SM1));
|
||||
Operand part2 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, nCopy, Const(SM2));
|
||||
Operand part3 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, nCopy, Const(SM3));
|
||||
|
||||
Operand res = emit(emit(part0, part1), emit(part2, part3));
|
||||
|
||||
|
@ -1340,13 +1340,13 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if ((op.Size & 1) == 0)
|
||||
{
|
||||
const int sm0 = 2 << 6 | 2 << 4 | 2 << 2 | 0 << 0;
|
||||
const int sm1 = 2 << 6 | 2 << 4 | 2 << 2 | 1 << 0;
|
||||
const int SM0 = 2 << 6 | 2 << 4 | 2 << 2 | 0 << 0;
|
||||
const int SM1 = 2 << 6 | 2 << 4 | 2 << 2 | 1 << 0;
|
||||
|
||||
Operand zeroN = context.VectorZeroUpper64(n);
|
||||
|
||||
op0 = context.AddIntrinsic(Intrinsic.X86Pshufd, zeroN, Const(sm0));
|
||||
op1 = context.AddIntrinsic(Intrinsic.X86Pshufd, zeroN, Const(sm1));
|
||||
op0 = context.AddIntrinsic(Intrinsic.X86Pshufd, zeroN, Const(SM0));
|
||||
op1 = context.AddIntrinsic(Intrinsic.X86Pshufd, zeroN, Const(SM1));
|
||||
}
|
||||
else /* if ((op.Size & 1) == 1) */
|
||||
{
|
||||
|
@ -1412,11 +1412,11 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else /* if (op.RegisterSize == RegisterSize.Simd128) */
|
||||
{
|
||||
const int sm0 = 2 << 6 | 0 << 4 | 2 << 2 | 0 << 0;
|
||||
const int sm1 = 3 << 6 | 1 << 4 | 3 << 2 | 1 << 0;
|
||||
const int SM0 = 2 << 6 | 0 << 4 | 2 << 2 | 0 << 0;
|
||||
const int SM1 = 3 << 6 | 1 << 4 | 3 << 2 | 1 << 0;
|
||||
|
||||
Operand part0 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, mCopy, Const(sm0));
|
||||
Operand part1 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, mCopy, Const(sm1));
|
||||
Operand part0 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, mCopy, Const(SM0));
|
||||
Operand part1 = context.AddIntrinsic(Intrinsic.X86Shufps, nCopy, mCopy, Const(SM1));
|
||||
|
||||
context.Copy(GetVec(op.Rd), emit(part0, part1));
|
||||
}
|
||||
|
@ -1444,7 +1444,7 @@ namespace ARMeilleure.Instructions
|
|||
// Vex.
|
||||
GreaterThanOrEqual = 13, // Ordered, signaling.
|
||||
GreaterThan = 14, // Ordered, signaling.
|
||||
OrderedS = 23 // Signaling.
|
||||
OrderedS = 23, // Signaling.
|
||||
}
|
||||
|
||||
[Flags]
|
||||
|
@ -1459,7 +1459,7 @@ namespace ARMeilleure.Instructions
|
|||
Add = 1 << 3,
|
||||
Sub = 1 << 4,
|
||||
|
||||
Accumulate = 1 << 5
|
||||
Accumulate = 1 << 5,
|
||||
}
|
||||
|
||||
public static void EmitScalarSaturatingUnaryOpSx(ArmEmitterContext context, Func1I emit)
|
||||
|
@ -1637,7 +1637,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
VectorSxSx = SignedSrc | SignedDst,
|
||||
VectorSxZx = SignedSrc,
|
||||
VectorZxZx = 0
|
||||
VectorZxZx = 0,
|
||||
}
|
||||
|
||||
public static void EmitSaturatingNarrowOp(ArmEmitterContext context, SaturatingNarrowFlags flags)
|
||||
|
@ -2034,18 +2034,30 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
switch (size)
|
||||
{
|
||||
case 0: res = context.SignExtend8 (OperandType.I64, res); break;
|
||||
case 1: res = context.SignExtend16(OperandType.I64, res); break;
|
||||
case 2: res = context.SignExtend32(OperandType.I64, res); break;
|
||||
case 0:
|
||||
res = context.SignExtend8(OperandType.I64, res);
|
||||
break;
|
||||
case 1:
|
||||
res = context.SignExtend16(OperandType.I64, res);
|
||||
break;
|
||||
case 2:
|
||||
res = context.SignExtend32(OperandType.I64, res);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (size)
|
||||
{
|
||||
case 0: res = context.ZeroExtend8 (OperandType.I64, res); break;
|
||||
case 1: res = context.ZeroExtend16(OperandType.I64, res); break;
|
||||
case 2: res = context.ZeroExtend32(OperandType.I64, res); break;
|
||||
case 0:
|
||||
res = context.ZeroExtend8(OperandType.I64, res);
|
||||
break;
|
||||
case 1:
|
||||
res = context.ZeroExtend16(OperandType.I64, res);
|
||||
break;
|
||||
case 2:
|
||||
res = context.ZeroExtend32(OperandType.I64, res);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2063,10 +2075,18 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
switch (size)
|
||||
{
|
||||
case 0: vector = context.VectorInsert8 (vector, value, index); break;
|
||||
case 1: vector = context.VectorInsert16(vector, value, index); break;
|
||||
case 2: vector = context.VectorInsert (vector, value, index); break;
|
||||
case 3: vector = context.VectorInsert (vector, value, index); break;
|
||||
case 0:
|
||||
vector = context.VectorInsert8(vector, value, index);
|
||||
break;
|
||||
case 1:
|
||||
vector = context.VectorInsert16(vector, value, index);
|
||||
break;
|
||||
case 2:
|
||||
vector = context.VectorInsert(vector, value, index);
|
||||
break;
|
||||
case 3:
|
||||
vector = context.VectorInsert(vector, value, index);
|
||||
break;
|
||||
}
|
||||
|
||||
return vector;
|
||||
|
|
|
@ -4,7 +4,6 @@ using ARMeilleure.Translation;
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
@ -19,18 +18,13 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
public static (int, int) GetQuadwordAndSubindex(int index, RegisterSize size)
|
||||
{
|
||||
switch (size)
|
||||
return size switch
|
||||
{
|
||||
case RegisterSize.Simd128:
|
||||
return (index >> 1, 0);
|
||||
case RegisterSize.Simd64:
|
||||
case RegisterSize.Int64:
|
||||
return (index >> 1, index & 1);
|
||||
case RegisterSize.Int32:
|
||||
return (index >> 2, index & 3);
|
||||
}
|
||||
|
||||
throw new ArgumentException("Unrecognized Vector Register Size.");
|
||||
RegisterSize.Simd128 => (index >> 1, 0),
|
||||
RegisterSize.Simd64 or RegisterSize.Int64 => (index >> 1, index & 1),
|
||||
RegisterSize.Int32 => (index >> 2, index & 3),
|
||||
_ => throw new ArgumentException("Unrecognized Vector Register Size."),
|
||||
};
|
||||
}
|
||||
|
||||
public static Operand ExtractScalar(ArmEmitterContext context, OperandType type, int reg)
|
||||
|
@ -778,7 +772,10 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
// Index into 0, 0 into index. This swap happens at the start of an A32 scalar op if required.
|
||||
int index = reg & (doubleWidth ? 1 : 3);
|
||||
if (index == 0) return target;
|
||||
if (index == 0)
|
||||
{
|
||||
return target;
|
||||
}
|
||||
|
||||
if (doubleWidth)
|
||||
{
|
||||
|
@ -1195,7 +1192,7 @@ namespace ARMeilleure.Instructions
|
|||
: typeof(SoftFloat64).GetMethod(name);
|
||||
|
||||
Array.Resize(ref callArgs, callArgs.Length + 1);
|
||||
callArgs[callArgs.Length - 1] = Const(1);
|
||||
callArgs[^1] = Const(1);
|
||||
|
||||
context.ExitArmFpMode();
|
||||
context.StoreToContext();
|
||||
|
@ -1245,16 +1242,24 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
switch (size)
|
||||
{
|
||||
case 0: res = context.SignExtend8(OperandType.I32, res); break;
|
||||
case 1: res = context.SignExtend16(OperandType.I32, res); break;
|
||||
case 0:
|
||||
res = context.SignExtend8(OperandType.I32, res);
|
||||
break;
|
||||
case 1:
|
||||
res = context.SignExtend16(OperandType.I32, res);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (size)
|
||||
{
|
||||
case 0: res = context.ZeroExtend8(OperandType.I32, res); break;
|
||||
case 1: res = context.ZeroExtend16(OperandType.I32, res); break;
|
||||
case 0:
|
||||
res = context.ZeroExtend8(OperandType.I32, res);
|
||||
break;
|
||||
case 1:
|
||||
res = context.ZeroExtend16(OperandType.I32, res);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
|
||||
using ARMeilleure.Decoders;
|
||||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
@ -74,7 +72,10 @@ namespace ARMeilleure.Instructions
|
|||
public static Operand EmitExtractScalar(ArmEmitterContext context, Operand target, int reg, bool doubleWidth)
|
||||
{
|
||||
int index = reg & (doubleWidth ? 1 : 3);
|
||||
if (index == 0) return target; // Element is already at index 0, so just return the vector directly.
|
||||
if (index == 0)
|
||||
{
|
||||
return target; // Element is already at index 0, so just return the vector directly.
|
||||
}
|
||||
|
||||
if (doubleWidth)
|
||||
{
|
||||
|
@ -336,16 +337,17 @@ namespace ARMeilleure.Instructions
|
|||
CmpCondition.GreaterThanOrEqual => Intrinsic.Arm64FcmgeVz,
|
||||
CmpCondition.LessThan => Intrinsic.Arm64FcmltVz,
|
||||
CmpCondition.LessThanOrEqual => Intrinsic.Arm64FcmleVz,
|
||||
_ => throw new InvalidOperationException()
|
||||
_ => throw new InvalidOperationException(),
|
||||
};
|
||||
}
|
||||
else {
|
||||
else
|
||||
{
|
||||
inst = cond switch
|
||||
{
|
||||
CmpCondition.Equal => Intrinsic.Arm64FcmeqV,
|
||||
CmpCondition.GreaterThan => Intrinsic.Arm64FcmgtV,
|
||||
CmpCondition.GreaterThanOrEqual => Intrinsic.Arm64FcmgeV,
|
||||
_ => throw new InvalidOperationException()
|
||||
_ => throw new InvalidOperationException(),
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -695,7 +695,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeSimdReg op = (OpCodeSimdReg)context.CurrOp;
|
||||
|
||||
bool cmpWithZero = !(op is OpCodeSimdFcond) ? op.Bit3 : false;
|
||||
bool cmpWithZero = op is not OpCodeSimdFcond && op.Bit3;
|
||||
|
||||
Intrinsic inst = signalNaNs ? Intrinsic.Arm64FcmpeS : Intrinsic.Arm64FcmpS;
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@ using ARMeilleure.IntermediateRepresentation;
|
|||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
|
||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||
using static ARMeilleure.Instructions.InstEmitSimdHelper;
|
||||
using static ARMeilleure.IntermediateRepresentation.Operand.Factory;
|
||||
|
@ -80,10 +79,11 @@ namespace ARMeilleure.Instructions
|
|||
int eSize = 8 << op.Size;
|
||||
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand imm = eSize switch {
|
||||
Operand imm = eSize switch
|
||||
{
|
||||
16 => X86GetAllElements(context, (short)~op.Immediate),
|
||||
32 => X86GetAllElements(context, (int)~op.Immediate),
|
||||
_ => throw new InvalidOperationException($"Invalid element size {eSize}.")
|
||||
_ => throw new InvalidOperationException($"Invalid element size {eSize}."),
|
||||
};
|
||||
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Pand, d, imm);
|
||||
|
@ -380,10 +380,11 @@ namespace ARMeilleure.Instructions
|
|||
int eSize = 8 << op.Size;
|
||||
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand imm = eSize switch {
|
||||
Operand imm = eSize switch
|
||||
{
|
||||
16 => X86GetAllElements(context, (short)op.Immediate),
|
||||
32 => X86GetAllElements(context, (int)op.Immediate),
|
||||
_ => throw new InvalidOperationException($"Invalid element size {eSize}.")
|
||||
_ => throw new InvalidOperationException($"Invalid element size {eSize}."),
|
||||
};
|
||||
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Por, d, imm);
|
||||
|
@ -407,7 +408,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (Optimizations.UseGfni)
|
||||
{
|
||||
const long bitMatrix =
|
||||
const long BitMatrix =
|
||||
(0b10000000L << 56) |
|
||||
(0b01000000L << 48) |
|
||||
(0b00100000L << 40) |
|
||||
|
@ -417,7 +418,7 @@ namespace ARMeilleure.Instructions
|
|||
(0b00000010L << 8) |
|
||||
(0b00000001L << 0);
|
||||
|
||||
Operand vBitMatrix = X86GetAllElements(context, bitMatrix);
|
||||
Operand vBitMatrix = X86GetAllElements(context, BitMatrix);
|
||||
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Gf2p8affineqb, GetVec(op.Rn), vBitMatrix, Const(0));
|
||||
|
||||
|
@ -468,12 +469,12 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand n = GetVec(op.Rn);
|
||||
|
||||
const long maskE0 = 06L << 56 | 07L << 48 | 04L << 40 | 05L << 32 | 02L << 24 | 03L << 16 | 00L << 8 | 01L << 0;
|
||||
const long maskE1 = 14L << 56 | 15L << 48 | 12L << 40 | 13L << 32 | 10L << 24 | 11L << 16 | 08L << 8 | 09L << 0;
|
||||
const long MaskE0 = 06L << 56 | 07L << 48 | 04L << 40 | 05L << 32 | 02L << 24 | 03L << 16 | 00L << 8 | 01L << 0;
|
||||
const long MaskE1 = 14L << 56 | 15L << 48 | 12L << 40 | 13L << 32 | 10L << 24 | 11L << 16 | 08L << 8 | 09L << 0;
|
||||
|
||||
Operand mask = X86GetScalar(context, maskE0);
|
||||
Operand mask = X86GetScalar(context, MaskE0);
|
||||
|
||||
mask = EmitVectorInsert(context, mask, Const(maskE1), 1, 3);
|
||||
mask = EmitVectorInsert(context, mask, Const(MaskE1), 1, 3);
|
||||
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Pshufb, n, mask);
|
||||
|
||||
|
@ -502,21 +503,21 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (op.Size == 0)
|
||||
{
|
||||
const long maskE0 = 04L << 56 | 05L << 48 | 06L << 40 | 07L << 32 | 00L << 24 | 01L << 16 | 02L << 8 | 03L << 0;
|
||||
const long maskE1 = 12L << 56 | 13L << 48 | 14L << 40 | 15L << 32 | 08L << 24 | 09L << 16 | 10L << 8 | 11L << 0;
|
||||
const long MaskE0 = 04L << 56 | 05L << 48 | 06L << 40 | 07L << 32 | 00L << 24 | 01L << 16 | 02L << 8 | 03L << 0;
|
||||
const long MaskE1 = 12L << 56 | 13L << 48 | 14L << 40 | 15L << 32 | 08L << 24 | 09L << 16 | 10L << 8 | 11L << 0;
|
||||
|
||||
mask = X86GetScalar(context, maskE0);
|
||||
mask = X86GetScalar(context, MaskE0);
|
||||
|
||||
mask = EmitVectorInsert(context, mask, Const(maskE1), 1, 3);
|
||||
mask = EmitVectorInsert(context, mask, Const(MaskE1), 1, 3);
|
||||
}
|
||||
else /* if (op.Size == 1) */
|
||||
{
|
||||
const long maskE0 = 05L << 56 | 04L << 48 | 07L << 40 | 06L << 32 | 01L << 24 | 00L << 16 | 03L << 8 | 02L << 0;
|
||||
const long maskE1 = 13L << 56 | 12L << 48 | 15L << 40 | 14L << 32 | 09L << 24 | 08L << 16 | 11L << 8 | 10L << 0;
|
||||
const long MaskE0 = 05L << 56 | 04L << 48 | 07L << 40 | 06L << 32 | 01L << 24 | 00L << 16 | 03L << 8 | 02L << 0;
|
||||
const long MaskE1 = 13L << 56 | 12L << 48 | 15L << 40 | 14L << 32 | 09L << 24 | 08L << 16 | 11L << 8 | 10L << 0;
|
||||
|
||||
mask = X86GetScalar(context, maskE0);
|
||||
mask = X86GetScalar(context, MaskE0);
|
||||
|
||||
mask = EmitVectorInsert(context, mask, Const(maskE1), 1, 3);
|
||||
mask = EmitVectorInsert(context, mask, Const(MaskE1), 1, 3);
|
||||
}
|
||||
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Pshufb, n, mask);
|
||||
|
@ -546,30 +547,30 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (op.Size == 0)
|
||||
{
|
||||
const long maskE0 = 00L << 56 | 01L << 48 | 02L << 40 | 03L << 32 | 04L << 24 | 05L << 16 | 06L << 8 | 07L << 0;
|
||||
const long maskE1 = 08L << 56 | 09L << 48 | 10L << 40 | 11L << 32 | 12L << 24 | 13L << 16 | 14L << 8 | 15L << 0;
|
||||
const long MaskE0 = 00L << 56 | 01L << 48 | 02L << 40 | 03L << 32 | 04L << 24 | 05L << 16 | 06L << 8 | 07L << 0;
|
||||
const long MaskE1 = 08L << 56 | 09L << 48 | 10L << 40 | 11L << 32 | 12L << 24 | 13L << 16 | 14L << 8 | 15L << 0;
|
||||
|
||||
mask = X86GetScalar(context, maskE0);
|
||||
mask = X86GetScalar(context, MaskE0);
|
||||
|
||||
mask = EmitVectorInsert(context, mask, Const(maskE1), 1, 3);
|
||||
mask = EmitVectorInsert(context, mask, Const(MaskE1), 1, 3);
|
||||
}
|
||||
else if (op.Size == 1)
|
||||
{
|
||||
const long maskE0 = 01L << 56 | 00L << 48 | 03L << 40 | 02L << 32 | 05L << 24 | 04L << 16 | 07L << 8 | 06L << 0;
|
||||
const long maskE1 = 09L << 56 | 08L << 48 | 11L << 40 | 10L << 32 | 13L << 24 | 12L << 16 | 15L << 8 | 14L << 0;
|
||||
const long MaskE0 = 01L << 56 | 00L << 48 | 03L << 40 | 02L << 32 | 05L << 24 | 04L << 16 | 07L << 8 | 06L << 0;
|
||||
const long MaskE1 = 09L << 56 | 08L << 48 | 11L << 40 | 10L << 32 | 13L << 24 | 12L << 16 | 15L << 8 | 14L << 0;
|
||||
|
||||
mask = X86GetScalar(context, maskE0);
|
||||
mask = X86GetScalar(context, MaskE0);
|
||||
|
||||
mask = EmitVectorInsert(context, mask, Const(maskE1), 1, 3);
|
||||
mask = EmitVectorInsert(context, mask, Const(MaskE1), 1, 3);
|
||||
}
|
||||
else /* if (op.Size == 2) */
|
||||
{
|
||||
const long maskE0 = 03L << 56 | 02L << 48 | 01L << 40 | 00L << 32 | 07L << 24 | 06L << 16 | 05L << 8 | 04L << 0;
|
||||
const long maskE1 = 11L << 56 | 10L << 48 | 09L << 40 | 08L << 32 | 15L << 24 | 14L << 16 | 13L << 8 | 12L << 0;
|
||||
const long MaskE0 = 03L << 56 | 02L << 48 | 01L << 40 | 00L << 32 | 07L << 24 | 06L << 16 | 05L << 8 | 04L << 0;
|
||||
const long MaskE1 = 11L << 56 | 10L << 48 | 09L << 40 | 08L << 32 | 15L << 24 | 14L << 16 | 13L << 8 | 12L << 0;
|
||||
|
||||
mask = X86GetScalar(context, maskE0);
|
||||
mask = X86GetScalar(context, MaskE0);
|
||||
|
||||
mask = EmitVectorInsert(context, mask, Const(maskE1), 1, 3);
|
||||
mask = EmitVectorInsert(context, mask, Const(MaskE1), 1, 3);
|
||||
}
|
||||
|
||||
Operand res = context.AddIntrinsic(Intrinsic.X86Pshufb, n, mask);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue