Start adding support for SIMD & FP types, along with some of the related ARM instructions

This commit is contained in:
gdkchan 2019-06-11 21:41:31 -03:00
parent 1d3e1d929e
commit f056709136
52 changed files with 10972 additions and 466 deletions

View file

@ -2,15 +2,21 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
struct AllocationResult
{
public int UsedRegisters { get; }
public int SpillRegionSize { get; }
public int MaxCallArgs { get; }
public int IntUsedRegisters { get; }
public int VecUsedRegisters { get; }
public int SpillRegionSize { get; }
public int MaxCallArgs { get; }
public AllocationResult(int usedRegisters, int spillRegionSize, int maxCallArgs)
public AllocationResult(
int intUsedRegisters,
int vecUsedRegisters,
int spillRegionSize,
int maxCallArgs)
{
UsedRegisters = usedRegisters;
SpillRegionSize = spillRegionSize;
MaxCallArgs = maxCallArgs;
IntUsedRegisters = intUsedRegisters;
VecUsedRegisters = vecUsedRegisters;
SpillRegionSize = spillRegionSize;
MaxCallArgs = maxCallArgs;
}
}
}

View file

@ -1,7 +1,6 @@
using ARMeilleure.CodeGen.X86;
using ARMeilleure.Common;
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State;
using ARMeilleure.Translation;
using System;
using System.Collections.Generic;
@ -40,7 +39,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
public BitMap Active { get; }
public BitMap Inactive { get; }
public int UsedRegisters { get; set; }
public int IntUsedRegisters { get; set; }
public int VecUsedRegisters { get; set; }
public AllocationContext(RegisterMasks masks, int intervalsCount)
{
@ -102,7 +102,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
}
}
for (int index = RegistersCount; index < _intervals.Count; index++)
for (int index = RegistersCount * 2; index < _intervals.Count; index++)
{
if (!_intervals[index].IsSpilled)
{
@ -113,7 +113,11 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
InsertSplitCopies();
InsertSplitCopiesAtEdges(cfg);
return new AllocationResult(context.UsedRegisters, context.StackAlloc.TotalSize, maxCallArgs);
return new AllocationResult(
context.IntUsedRegisters,
context.VecUsedRegisters,
context.StackAlloc.TotalSize,
maxCallArgs);
}
private void AllocateInterval(AllocationContext context, LiveInterval current, int cIndex)
@ -148,23 +152,6 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
}
}
int availableRegs = context.Masks.IntAvailableRegisters;
foreach (int iIndex in context.Active)
{
availableRegs &= ~(1 << GetInterval(iIndex).Register.Index);
}
foreach (int iIndex in context.Inactive)
{
LiveInterval interval = GetInterval(iIndex);
if (interval.Overlaps(current))
{
availableRegs &= ~(1 << interval.Register.Index);
}
}
if (!TryAllocateRegWithoutSpill(context, current, cIndex))
{
AllocateRegWithSpill(context, current, cIndex);
@ -173,11 +160,15 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private bool TryAllocateRegWithoutSpill(AllocationContext context, LiveInterval current, int cIndex)
{
RegisterType regType = current.Local.Type.ToRegisterType();
int availableRegisters = context.Masks.GetAvailableRegisters(regType);
int[] freePositions = new int[RegistersCount];
for (int index = 0; index < RegistersCount; index++)
{
if ((context.Masks.IntAvailableRegisters & (1 << index)) != 0)
if ((availableRegisters & (1 << index)) != 0)
{
freePositions[index] = int.MaxValue;
}
@ -187,14 +178,17 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
LiveInterval interval = GetInterval(iIndex);
freePositions[interval.Register.Index] = 0;
if (interval.Register.Type == regType)
{
freePositions[interval.Register.Index] = 0;
}
}
foreach (int iIndex in context.Inactive)
{
LiveInterval interval = GetInterval(iIndex);
if (interval.Overlaps(current))
if (interval.Register.Type == regType && interval.Overlaps(current))
{
int nextOverlap = interval.NextOverlap(current);
@ -233,9 +227,16 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
}
}
current.Register = new Register(selectedReg, RegisterType.Integer);
current.Register = new Register(selectedReg, regType);
context.UsedRegisters |= 1 << selectedReg;
if (regType == RegisterType.Integer)
{
context.IntUsedRegisters |= 1 << selectedReg;
}
else /* if (regType == RegisterType.Vector) */
{
context.VecUsedRegisters |= 1 << selectedReg;
}
context.Active.Set(cIndex);
@ -244,13 +245,17 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private void AllocateRegWithSpill(AllocationContext context, LiveInterval current, int cIndex)
{
RegisterType regType = current.Local.Type.ToRegisterType();
int availableRegisters = context.Masks.GetAvailableRegisters(regType);
int[] usePositions = new int[RegistersCount];
int[] blockedPositions = new int[RegistersCount];
for (int index = 0; index < RegistersCount; index++)
{
if ((context.Masks.IntAvailableRegisters & (1 << index)) != 0)
if ((availableRegisters & (1 << index)) != 0)
{
usePositions[index] = int.MaxValue;
@ -274,7 +279,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
LiveInterval interval = GetInterval(iIndex);
if (!interval.IsFixed)
if (!interval.IsFixed && interval.Register.Type == regType)
{
int nextUse = interval.NextUseAfter(current.Start);
@ -289,7 +294,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
LiveInterval interval = GetInterval(iIndex);
if (!interval.IsFixed && interval.Overlaps(current))
if (!interval.IsFixed && interval.Register.Type == regType && interval.Overlaps(current))
{
int nextUse = interval.NextUseAfter(current.Start);
@ -304,7 +309,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
LiveInterval interval = GetInterval(iIndex);
if (interval.IsFixed)
if (interval.IsFixed && interval.Register.Type == regType)
{
SetBlockedPosition(interval.Register.Index, 0);
}
@ -314,7 +319,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
LiveInterval interval = GetInterval(iIndex);
if (interval.IsFixed && interval.Overlaps(current))
if (interval.IsFixed && interval.Register.Type == regType && interval.Overlaps(current))
{
SetBlockedPosition(interval.Register.Index, interval.NextOverlap(current));
}
@ -344,7 +349,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
//Spill made the register available for the entire current lifetime,
//so we only need to split the intervals using the selected register.
current.Register = new Register(selectedReg, RegisterType.Integer);
current.Register = new Register(selectedReg, regType);
SplitAndSpillOverlappingIntervals(context, current);
@ -355,7 +360,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
//There are conflicts even after spill due to the use of fixed registers
//that can't be spilled, so we need to also split current at the point of
//the first fixed register use.
current.Register = new Register(selectedReg, RegisterType.Integer);
current.Register = new Register(selectedReg, regType);
LiveInterval splitChild = current.Split(GetSplitPosition(blockedPositions[selectedReg]));
@ -745,7 +750,10 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
throw new ArgumentException("Spilled intervals are not allowed.");
}
return new Operand(interval.Register.Index, RegisterType.Integer, interval.Local.Type);
return new Operand(
interval.Register.Index,
interval.Register.Type,
interval.Local.Type);
}
private static int GetSplitPosition(int position)
@ -771,9 +779,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
for (int index = 0; index < RegistersCount; index++)
{
LiveInterval interval = new LiveInterval(new Register(index, RegisterType.Integer));
_intervals.Add(interval);
_intervals.Add(new LiveInterval(new Register(index, RegisterType.Integer)));
_intervals.Add(new LiveInterval(new Register(index, RegisterType.Vector)));
}
HashSet<Operand> visited = new HashSet<Operand>();
@ -812,7 +819,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
_blockRanges = new LiveRange[cfg.Blocks.Count];
int mapSize = _intervals.Count + RegistersCount;
int mapSize = _intervals.Count;
BitMap[] blkLiveGen = new BitMap[cfg.Blocks.Count];
BitMap[] blkLiveKill = new BitMap[cfg.Blocks.Count];
@ -940,18 +947,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
if (node is Operation operation && operation.Inst == Instruction.Call)
{
int callerSavedRegs = regMasks.IntCallerSavedRegisters;
while (callerSavedRegs != 0)
{
int callerSavedReg = BitUtils.LowestBitSet(callerSavedRegs);
LiveInterval interval = _intervals[callerSavedReg];
interval.AddRange(operationPos, operationPos + 1);
callerSavedRegs &= ~(1 << callerSavedReg);
}
AddIntervalCallerSavedReg(regMasks.IntCallerSavedRegisters, operationPos, RegisterType.Integer);
AddIntervalCallerSavedReg(regMasks.VecCallerSavedRegisters, operationPos, RegisterType.Vector);
if (maxCallArgs < operation.SourcesCount - 1)
{
@ -962,6 +959,24 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
}
}
private void AddIntervalCallerSavedReg(int mask, int operationPos, RegisterType regType)
{
while (mask != 0)
{
int regIndex = BitUtils.LowestBitSet(mask);
Debug.Assert(regIndex < RegistersCount, "Invalid register index.");
Register callerSavedReg = new Register(regIndex, regType);
LiveInterval interval = _intervals[GetRegisterId(callerSavedReg)];
interval.AddRange(operationPos, operationPos + 1);
mask &= ~(1 << regIndex);
}
}
private static int GetOperandId(Operand operand)
{
if (operand.Kind == OperandKind.LocalVariable)
@ -970,7 +985,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
}
else if (operand.Kind == OperandKind.Register)
{
return operand.GetRegister().Index;
return GetRegisterId(operand.GetRegister());
}
else
{
@ -978,6 +993,11 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
}
}
private static int GetRegisterId(Register register)
{
return (register.Index << 1) | (register.Type == RegisterType.Vector ? 1 : 0);
}
private void CoalesceCopies(BasicBlock[] blocks)
{
foreach (BasicBlock block in blocks)

View file

@ -1,5 +1,4 @@
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State;
using System;
using System.Collections.Generic;
using System.Diagnostics;

View file

@ -1,19 +1,47 @@
using ARMeilleure.IntermediateRepresentation;
using System;
namespace ARMeilleure.CodeGen.RegisterAllocators
{
struct RegisterMasks
{
public int IntAvailableRegisters { get; }
public int VecAvailableRegisters { get; }
public int IntCallerSavedRegisters { get; }
public int VecCallerSavedRegisters { get; }
public int IntCalleeSavedRegisters { get; }
public int VecCalleeSavedRegisters { get; }
public RegisterMasks(
int intAvailableRegisters,
int vecAvailableRegisters,
int intCallerSavedRegisters,
int intCalleeSavedRegisters)
int vecCallerSavedRegisters,
int intCalleeSavedRegisters,
int vecCalleeSavedRegisters)
{
IntAvailableRegisters = intAvailableRegisters;
VecAvailableRegisters = vecAvailableRegisters;
IntCallerSavedRegisters = intCallerSavedRegisters;
VecCallerSavedRegisters = vecCallerSavedRegisters;
IntCalleeSavedRegisters = intCalleeSavedRegisters;
VecCalleeSavedRegisters = vecCalleeSavedRegisters;
}
public int GetAvailableRegisters(RegisterType type)
{
if (type == RegisterType.Integer)
{
return IntAvailableRegisters;
}
else if (type == RegisterType.Vector)
{
return VecAvailableRegisters;
}
else
{
throw new ArgumentException($"Invalid register type \"{type}\".");
}
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -4,9 +4,11 @@ namespace ARMeilleure.CodeGen.X86
{
static class CallingConvention
{
private const int RegistersMask = 0xffff;
public static int GetIntAvailableRegisters()
{
int mask = 0xffff;
int mask = RegistersMask;
mask &= ~(1 << (int)X86Register.Rbp);
mask &= ~(1 << (int)X86Register.Rsp);
@ -14,6 +16,11 @@ namespace ARMeilleure.CodeGen.X86
return mask;
}
public static int GetVecAvailableRegisters()
{
return RegistersMask;
}
public static int GetIntCallerSavedRegisters()
{
return (1 << (int)X86Register.Rax) |
@ -25,6 +32,16 @@ namespace ARMeilleure.CodeGen.X86
(1 << (int)X86Register.R11);
}
public static int GetVecCallerSavedRegisters()
{
return (1 << (int)X86Register.Xmm0) |
(1 << (int)X86Register.Xmm1) |
(1 << (int)X86Register.Xmm2) |
(1 << (int)X86Register.Xmm3) |
(1 << (int)X86Register.Xmm4) |
(1 << (int)X86Register.Xmm5);
}
public static int GetIntCalleeSavedRegisters()
{
return (1 << (int)X86Register.Rbx) |
@ -38,7 +55,12 @@ namespace ARMeilleure.CodeGen.X86
(1 << (int)X86Register.R15);
}
public static int GetIntArgumentsOnRegsCount()
public static int GetVecCalleeSavedRegisters()
{
return GetVecCallerSavedRegisters() ^ RegistersMask;
}
public static int GetArgumentsOnRegsCount()
{
return 4;
}
@ -56,9 +78,27 @@ namespace ARMeilleure.CodeGen.X86
throw new ArgumentOutOfRangeException(nameof(index));
}
public static X86Register GetVecArgumentRegister(int index)
{
switch (index)
{
case 0: return X86Register.Xmm0;
case 1: return X86Register.Xmm1;
case 2: return X86Register.Xmm2;
case 3: return X86Register.Xmm3;
}
throw new ArgumentOutOfRangeException(nameof(index));
}
public static X86Register GetIntReturnRegister()
{
return X86Register.Rax;
}
public static X86Register GetVecReturnRegister()
{
return X86Register.Xmm0;
}
}
}

View file

@ -87,7 +87,7 @@ namespace ARMeilleure.CodeGen.X86
{
//We need to add 8 bytes to the total size, as the call to this
//function already pushed 8 bytes (the return address).
int mask = CallingConvention.GetIntCalleeSavedRegisters() & allocResult.UsedRegisters;
int mask = CallingConvention.GetIntCalleeSavedRegisters() & allocResult.IntUsedRegisters;
mask |= 1 << (int)X86Register.Rbp;
@ -97,7 +97,7 @@ namespace ARMeilleure.CodeGen.X86
//The ABI mandates that the space for at least 4 arguments
//is reserved on the stack (this is called shadow space).
if (argsCount < 4)
if (argsCount < 4 && argsCount != 0)
{
argsCount = 4;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,7 @@
namespace ARMeilleure.CodeGen.X86
{
static class HardwareCapabilities
{
public const bool SupportsVexEncoding = true;
}
}

View file

@ -1,7 +1,6 @@
using ARMeilleure.CodeGen.Optimizations;
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Memory;
using ARMeilleure.State;
using ARMeilleure.Translation;
using System.Collections.Generic;
@ -118,51 +117,93 @@ namespace ARMeilleure.CodeGen.X86
private static void AddConstantCopy(LinkedListNode<Node> node, Operation operation)
{
if (operation.SourcesCount == 0)
if (operation.SourcesCount == 0 || HasFixedConst(operation.Inst))
{
return;
}
Instruction inst = operation.Inst;
Operand dest = operation.Dest;
Operand src1 = operation.GetSource(0);
Operand src2;
if (src1.Kind == OperandKind.Constant && !HasConstSrc1(inst))
if (src1.Type.IsInteger())
{
if (IsComutative(inst))
//Handle integer types.
//Most ALU instructions accepts a 32-bits immediate on the second operand.
//We need to ensure the following:
//- If the constant is on operand 1, we need to move it.
//-- But first, we try to swap operand 1 and 2 if the instruction is comutative.
//-- Doing so may allow us to encode the constant as operand 2 and avoid a copy.
//- If the constant is on operand 2, we check if the instruction supports it,
//if not, we also add a copy. 64-bits constants are usually not supported.
bool isVecCopy = inst == Instruction.Copy && !dest.Type.IsInteger();
if (src1.Kind == OperandKind.Constant && (!HasConstSrc1(inst) || isVecCopy))
{
src2 = operation.GetSource(1);
if (IsComutative(inst))
{
src2 = operation.GetSource(1);
Operand temp = src1;
Operand temp = src1;
src1 = src2;
src2 = temp;
src1 = src2;
src2 = temp;
operation.SetSource(0, src1);
operation.SetSource(1, src2);
}
if (src1.Kind == OperandKind.Constant)
{
src1 = AddCopy(node, src1);
operation.SetSource(0, src1);
}
}
if (operation.SourcesCount < 2)
{
return;
}
src2 = operation.GetSource(1);
if (src2.Kind == OperandKind.Constant && (!HasConstSrc2(inst) || IsLongConst(src2)))
{
src2 = AddCopy(node, src2);
operation.SetSource(0, src1);
operation.SetSource(1, src2);
}
if (src1.Kind == OperandKind.Constant)
}
else
{
//Handle non-integer types (FP32, FP64 and V128).
//For instructions without an immediate operand, we do the following:
//- Insert a copy with the constant value (as integer) to a GPR.
//- Insert a copy from the GPR to a XMM register.
//- Replace the constant use with the XMM register.
if (src1.Kind == OperandKind.Constant && src1.Type.IsInteger())
{
src1 = AddCopy(node, src1);
src1 = AddXmmCopy(node, src1);
operation.SetSource(0, src1);
}
}
if (operation.SourcesCount < 2)
{
return;
}
if (operation.SourcesCount < 2)
{
return;
}
src2 = operation.GetSource(1);
src2 = operation.GetSource(1);
if (src2.Kind == OperandKind.Constant && (!HasConstSrc2(inst) || IsLongConst(src2)))
{
src2 = AddCopy(node, src2);
if (src2.Kind == OperandKind.Constant && src2.Type.IsInteger())
{
src2 = AddXmmCopy(node, src2);
operation.SetSource(1, src2);
operation.SetSource(1, src2);
}
}
}
@ -248,7 +289,7 @@ namespace ARMeilleure.CodeGen.X86
{
int argsCount = operation.SourcesCount;
int maxArgs = CallingConvention.GetIntArgumentsOnRegsCount();
int maxArgs = CallingConvention.GetArgumentsOnRegsCount();
if (argsCount > maxArgs + 1)
{
@ -259,7 +300,18 @@ namespace ARMeilleure.CodeGen.X86
{
Operand source = operation.GetSource(index);
Operand argReg = Gpr(CallingConvention.GetIntArgumentRegister(index - 1), source.Type);
RegisterType regType = source.Type.ToRegisterType();
Operand argReg;
if (regType == RegisterType.Integer)
{
argReg = Gpr(CallingConvention.GetIntArgumentRegister(index - 1), source.Type);
}
else /* if (regType == RegisterType.Vector) */
{
argReg = Xmm(CallingConvention.GetVecArgumentRegister(index - 1), source.Type);
}
Operation srcCopyOp = new Operation(Instruction.Copy, argReg, source);
@ -285,7 +337,18 @@ namespace ARMeilleure.CodeGen.X86
if (dest != null)
{
Operand retReg = Gpr(CallingConvention.GetIntReturnRegister(), dest.Type);
RegisterType regType = dest.Type.ToRegisterType();
Operand retReg;
if (regType == RegisterType.Integer)
{
retReg = Gpr(CallingConvention.GetIntReturnRegister(), dest.Type);
}
else /* if (regType == RegisterType.Vector) */
{
retReg = Xmm(CallingConvention.GetVecReturnRegister(), dest.Type);
}
Operation destCopyOp = new Operation(Instruction.Copy, dest, retReg);
@ -312,7 +375,7 @@ namespace ARMeilleure.CodeGen.X86
//a three operand form where the second source is a immediate value.
bool threeOperandForm = inst == Instruction.Multiply && operation.GetSource(1).Kind == OperandKind.Constant;
if (IsSameOperandDestSrc1(inst) && src1.Kind == OperandKind.LocalVariable && !threeOperandForm)
if (IsSameOperandDestSrc1(operation) && src1.Kind == OperandKind.LocalVariable && !threeOperandForm)
{
Operation copyOp = new Operation(Instruction.Copy, dest, src1);
@ -332,6 +395,17 @@ namespace ARMeilleure.CodeGen.X86
}
}
private static Operand AddXmmCopy(LinkedListNode<Node> node, Operand source)
{
Operand temp = Local(source.Type);
Operation copyOp = new Operation(Instruction.Copy, temp, AddCopy(node, GetIntConst(source)));
node.List.AddBefore(node, copyOp);
return temp;
}
private static Operand AddCopy(LinkedListNode<Node> node, Operand source)
{
Operand temp = Local(source.Type);
@ -343,6 +417,20 @@ namespace ARMeilleure.CodeGen.X86
return temp;
}
private static Operand GetIntConst(Operand value)
{
if (value.Type == OperandType.FP32)
{
return Const(value.AsInt32());
}
else if (value.Type == OperandType.FP64)
{
return Const(value.AsInt64());
}
return value;
}
private static bool IsLongConst(Operand operand)
{
long value = operand.Type == OperandType.I32 ? operand.AsInt32()
@ -405,9 +493,14 @@ namespace ARMeilleure.CodeGen.X86
return Register((int)register, RegisterType.Integer, type);
}
private static bool IsSameOperandDestSrc1(Instruction inst)
private static Operand Xmm(X86Register register, OperandType type)
{
switch (inst)
return Register((int)register, RegisterType.Vector, type);
}
private static bool IsSameOperandDestSrc1(Operation operation)
{
switch (operation.Inst)
{
case Instruction.Add:
case Instruction.BitwiseAnd:
@ -423,6 +516,23 @@ namespace ARMeilleure.CodeGen.X86
case Instruction.ShiftRightUI:
case Instruction.Subtract:
return true;
case Instruction.VectorInsert:
case Instruction.VectorInsert16:
case Instruction.VectorInsert8:
return !HardwareCapabilities.SupportsVexEncoding;
}
return IsVexSameOperandDestSrc1(operation);
}
private static bool IsVexSameOperandDestSrc1(Operation operation)
{
if (IsIntrinsic(operation.Inst))
{
bool isUnary = operation.SourcesCount < 2;
return !HardwareCapabilities.SupportsVexEncoding && !isUnary;
}
return false;
@ -464,6 +574,9 @@ namespace ARMeilleure.CodeGen.X86
case Instruction.ShiftRightSI:
case Instruction.ShiftRightUI:
case Instruction.Subtract:
case Instruction.VectorExtract:
case Instruction.VectorExtract16:
case Instruction.VectorExtract8:
return true;
}
@ -486,5 +599,29 @@ namespace ARMeilleure.CodeGen.X86
return false;
}
private static bool HasFixedConst(Instruction inst)
{
switch (inst)
{
case Instruction.LoadFromContext:
case Instruction.StoreToContext:
case Instruction.VectorExtract:
case Instruction.VectorExtract16:
case Instruction.VectorExtract8:
case Instruction.VectorInsert:
case Instruction.VectorInsert16:
case Instruction.VectorInsert8:
return true;
}
return IsIntrinsic(inst);
}
private static bool IsIntrinsic(Instruction inst)
{
return inst > Instruction.X86Intrinsic_Start &&
inst < Instruction.X86Intrinsic_End;
}
}
}

View file

@ -3,38 +3,152 @@ namespace ARMeilleure.CodeGen.X86
enum X86Instruction
{
Add,
Addpd,
Addps,
Addsd,
Addss,
And,
Andnpd,
Andnps,
Bsr,
Bswap,
Call,
Cmovcc,
Cmp,
Div,
Divpd,
Divps,
Divsd,
Divss,
Haddpd,
Haddps,
Idiv,
Imul,
Imul128,
Insertps,
Maxpd,
Maxps,
Maxsd,
Maxss,
Minpd,
Minps,
Minsd,
Minss,
Mov,
Mov16,
Mov8,
Movd,
Movdqu,
Movhlps,
Movlhps,
Movq,
Movsd,
Movss,
Movsx16,
Movsx32,
Movsx8,
Movzx16,
Movzx8,
Mul128,
Mulpd,
Mulps,
Mulsd,
Mulss,
Neg,
Not,
Or,
Paddb,
Paddd,
Paddq,
Paddw,
Pand,
Pandn,
Pavgb,
Pavgw,
Pblendvb,
Pcmpeqb,
Pcmpeqd,
Pcmpeqq,
Pcmpeqw,
Pcmpgtb,
Pcmpgtd,
Pcmpgtq,
Pcmpgtw,
Pextrb,
Pextrd,
Pextrw,
Pinsrb,
Pinsrd,
Pinsrw,
Pmaxsb,
Pmaxsd,
Pmaxsw,
Pmaxub,
Pmaxud,
Pmaxuw,
Pminsb,
Pminsd,
Pminsw,
Pminub,
Pminud,
Pminuw,
Pmovsxbw,
Pmovsxdq,
Pmovsxwd,
Pmovzxbw,
Pmovzxdq,
Pmovzxwd,
Pmulld,
Pmullw,
Pop,
Popcnt,
Por,
Pshufd,
Psllw,
Psrad,
Psraw,
Psrld,
Psrlq,
Psrldq,
Psrlw,
Psubb,
Psubd,
Psubq,
Psubw,
Push,
Pxor,
Rcpps,
Rcpss,
Ror,
Roundpd,
Roundps,
Roundsd,
Roundss,
Rsqrtps,
Rsqrtss,
Sar,
Setcc,
Shl,
Shr,
Shufpd,
Shufps,
Sqrtpd,
Sqrtps,
Sqrtsd,
Sqrtss,
Sub,
Subpd,
Subps,
Subsd,
Subss,
Test,
Unpckhpd,
Unpckhps,
Unpcklpd,
Unpcklps,
Xor,
Xorpd,
Xorps,
Count
}

View file

@ -17,6 +17,23 @@ namespace ARMeilleure.CodeGen.X86
R12 = 12,
R13 = 13,
R14 = 14,
R15 = 15
R15 = 15,
Xmm0 = 0,
Xmm1 = 1,
Xmm2 = 2,
Xmm3 = 3,
Xmm4 = 4,
Xmm5 = 5,
Xmm6 = 6,
Xmm7 = 7,
Xmm8 = 8,
Xmm9 = 9,
Xmm10 = 10,
Xmm11 = 11,
Xmm12 = 12,
Xmm13 = 13,
Xmm14 = 14,
Xmm15 = 15
}
}

View file

@ -24,6 +24,9 @@ namespace ARMeilleure.Decoders
RegisterSize = RegisterSize.Int64;
}
public int GetPairsCount() => GetBitsCount() / 16;
public int GetBytesCount() => GetBitsCount() / 8;
public int GetBitsCount()
{
switch (RegisterSize)

View file

@ -2,9 +2,9 @@ namespace ARMeilleure.Decoders
{
class OpCodeSimdFmov : OpCode, IOpCodeSimd
{
public int Rd { get; private set; }
public long Imm { get; private set; }
public int Size { get; private set; }
public int Rd { get; private set; }
public long Immediate { get; private set; }
public int Size { get; private set; }
public OpCodeSimdFmov(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
@ -25,7 +25,7 @@ namespace ARMeilleure.Decoders
Rd = (opCode >> 0) & 0x1f;
imm = (opCode >> 13) & 0xff;
Imm = DecoderHelper.DecodeImm8Float(imm, type);
Immediate = DecoderHelper.DecodeImm8Float(imm, type);
}
}
}

View file

@ -2,9 +2,9 @@ namespace ARMeilleure.Decoders
{
class OpCodeSimdImm : OpCode, IOpCodeSimd
{
public int Rd { get; private set; }
public long Imm { get; private set; }
public int Size { get; private set; }
public int Rd { get; private set; }
public long Immediate { get; private set; }
public int Size { get; private set; }
public OpCodeSimdImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
{
@ -76,7 +76,7 @@ namespace ARMeilleure.Decoders
Size = 0;
}
Imm = imm;
Immediate = imm;
RegisterSize = ((opCode >> 30) & 1) != 0
? RegisterSize.Simd128

View file

@ -190,27 +190,27 @@ namespace ARMeilleure.Decoders
SetA64("10011011110xxxxx0xxxxxxxxxxxxxxx", InstName.Umulh, InstEmit.Umulh, typeof(OpCodeMul));
//FP & SIMD
SetA64("0101111011100000101110xxxxxxxxxx", InstName.Abs_S, null, typeof(OpCodeSimd));
SetA64("0>001110<<100000101110xxxxxxxxxx", InstName.Abs_V, null, typeof(OpCodeSimd));
SetA64("01011110111xxxxx100001xxxxxxxxxx", InstName.Add_S, null, typeof(OpCodeSimdReg));
SetA64("0>001110<<1xxxxx100001xxxxxxxxxx", InstName.Add_V, null, typeof(OpCodeSimdReg));
SetA64("0x001110<<1xxxxx010000xxxxxxxxxx", InstName.Addhn_V, null, typeof(OpCodeSimdReg));
SetA64("0101111011110001101110xxxxxxxxxx", InstName.Addp_S, null, typeof(OpCodeSimd));
SetA64("0>001110<<1xxxxx101111xxxxxxxxxx", InstName.Addp_V, null, typeof(OpCodeSimdReg));
SetA64("000011100x110001101110xxxxxxxxxx", InstName.Addv_V, null, typeof(OpCodeSimd));
SetA64("01001110<<110001101110xxxxxxxxxx", InstName.Addv_V, null, typeof(OpCodeSimd));
SetA64("0100111000101000010110xxxxxxxxxx", InstName.Aesd_V, null, typeof(OpCodeSimd));
SetA64("0100111000101000010010xxxxxxxxxx", InstName.Aese_V, null, typeof(OpCodeSimd));
SetA64("0100111000101000011110xxxxxxxxxx", InstName.Aesimc_V, null, typeof(OpCodeSimd));
SetA64("0100111000101000011010xxxxxxxxxx", InstName.Aesmc_V, null, typeof(OpCodeSimd));
SetA64("0101111011100000101110xxxxxxxxxx", InstName.Abs_S, InstEmit.Abs_S, typeof(OpCodeSimd));
SetA64("0>001110<<100000101110xxxxxxxxxx", InstName.Abs_V, InstEmit.Abs_V, typeof(OpCodeSimd));
SetA64("01011110111xxxxx100001xxxxxxxxxx", InstName.Add_S, InstEmit.Add_S, typeof(OpCodeSimdReg));
SetA64("0>001110<<1xxxxx100001xxxxxxxxxx", InstName.Add_V, InstEmit.Add_V, typeof(OpCodeSimdReg));
SetA64("0x001110<<1xxxxx010000xxxxxxxxxx", InstName.Addhn_V, InstEmit.Addhn_V, typeof(OpCodeSimdReg));
SetA64("0101111011110001101110xxxxxxxxxx", InstName.Addp_S, InstEmit.Addp_S, typeof(OpCodeSimd));
SetA64("0>001110<<1xxxxx101111xxxxxxxxxx", InstName.Addp_V, InstEmit.Addp_V, typeof(OpCodeSimdReg));
SetA64("000011100x110001101110xxxxxxxxxx", InstName.Addv_V, InstEmit.Addv_V, typeof(OpCodeSimd));
SetA64("01001110<<110001101110xxxxxxxxxx", InstName.Addv_V, InstEmit.Addv_V, typeof(OpCodeSimd));
SetA64("0100111000101000010110xxxxxxxxxx", InstName.Aesd_V, InstEmit.Aesd_V, typeof(OpCodeSimd));
SetA64("0100111000101000010010xxxxxxxxxx", InstName.Aese_V, InstEmit.Aese_V, typeof(OpCodeSimd));
SetA64("0100111000101000011110xxxxxxxxxx", InstName.Aesimc_V, InstEmit.Aesimc_V, typeof(OpCodeSimd));
SetA64("0100111000101000011010xxxxxxxxxx", InstName.Aesmc_V, InstEmit.Aesmc_V, typeof(OpCodeSimd));
SetA64("0x001110001xxxxx000111xxxxxxxxxx", InstName.And_V, null, typeof(OpCodeSimdReg));
SetA64("0x001110011xxxxx000111xxxxxxxxxx", InstName.Bic_V, null, typeof(OpCodeSimdReg));
SetA64("0x10111100000xxx<<x101xxxxxxxxxx", InstName.Bic_Vi, null, typeof(OpCodeSimdImm));
SetA64("0x101110111xxxxx000111xxxxxxxxxx", InstName.Bif_V, null, typeof(OpCodeSimdReg));
SetA64("0x101110101xxxxx000111xxxxxxxxxx", InstName.Bit_V, null, typeof(OpCodeSimdReg));
SetA64("0x101110011xxxxx000111xxxxxxxxxx", InstName.Bsl_V, null, typeof(OpCodeSimdReg));
SetA64("0x001110<<100000010010xxxxxxxxxx", InstName.Cls_V, null, typeof(OpCodeSimd));
SetA64("0x101110<<100000010010xxxxxxxxxx", InstName.Clz_V, null, typeof(OpCodeSimd));
SetA64("0x001110<<100000010010xxxxxxxxxx", InstName.Cls_V, InstEmit.Cls_V, typeof(OpCodeSimd));
SetA64("0x101110<<100000010010xxxxxxxxxx", InstName.Clz_V, InstEmit.Clz_V, typeof(OpCodeSimd));
SetA64("01111110111xxxxx100011xxxxxxxxxx", InstName.Cmeq_S, null, typeof(OpCodeSimdReg));
SetA64("0101111011100000100110xxxxxxxxxx", InstName.Cmeq_S, null, typeof(OpCodeSimd));
SetA64("0>101110<<1xxxxx100011xxxxxxxxxx", InstName.Cmeq_V, null, typeof(OpCodeSimdReg));
@ -233,20 +233,20 @@ namespace ARMeilleure.Decoders
SetA64("0>001110<<100000101010xxxxxxxxxx", InstName.Cmlt_V, null, typeof(OpCodeSimd));
SetA64("01011110111xxxxx100011xxxxxxxxxx", InstName.Cmtst_S, null, typeof(OpCodeSimdReg));
SetA64("0>001110<<1xxxxx100011xxxxxxxxxx", InstName.Cmtst_V, null, typeof(OpCodeSimdReg));
SetA64("0x00111000100000010110xxxxxxxxxx", InstName.Cnt_V, null, typeof(OpCodeSimd));
SetA64("0x00111000100000010110xxxxxxxxxx", InstName.Cnt_V, InstEmit.Cnt_V, typeof(OpCodeSimd));
SetA64("0>001110000x<>>>000011xxxxxxxxxx", InstName.Dup_Gp, null, typeof(OpCodeSimdIns));
SetA64("01011110000xxxxx000001xxxxxxxxxx", InstName.Dup_S, null, typeof(OpCodeSimdIns));
SetA64("0>001110000x<>>>000001xxxxxxxxxx", InstName.Dup_V, null, typeof(OpCodeSimdIns));
SetA64("0x101110001xxxxx000111xxxxxxxxxx", InstName.Eor_V, null, typeof(OpCodeSimdReg));
SetA64("0>101110000xxxxx0<xxx0xxxxxxxxxx", InstName.Ext_V, null, typeof(OpCodeSimdExt));
SetA64("011111101x1xxxxx110101xxxxxxxxxx", InstName.Fabd_S, null, typeof(OpCodeSimdReg));
SetA64("0>1011101<1xxxxx110101xxxxxxxxxx", InstName.Fabd_V, null, typeof(OpCodeSimdReg));
SetA64("000111100x100000110000xxxxxxxxxx", InstName.Fabs_S, null, typeof(OpCodeSimd));
SetA64("0>0011101<100000111110xxxxxxxxxx", InstName.Fabs_V, null, typeof(OpCodeSimd));
SetA64("000111100x1xxxxx001010xxxxxxxxxx", InstName.Fadd_S, null, typeof(OpCodeSimdReg));
SetA64("0>0011100<1xxxxx110101xxxxxxxxxx", InstName.Fadd_V, null, typeof(OpCodeSimdReg));
SetA64("011111100x110000110110xxxxxxxxxx", InstName.Faddp_S, null, typeof(OpCodeSimd));
SetA64("0>1011100<1xxxxx110101xxxxxxxxxx", InstName.Faddp_V, null, typeof(OpCodeSimdReg));
SetA64("011111101x1xxxxx110101xxxxxxxxxx", InstName.Fabd_S, InstEmit.Fabd_S, typeof(OpCodeSimdReg));
SetA64("0>1011101<1xxxxx110101xxxxxxxxxx", InstName.Fabd_V, InstEmit.Fabd_V, typeof(OpCodeSimdReg));
SetA64("000111100x100000110000xxxxxxxxxx", InstName.Fabs_S, InstEmit.Fabs_S, typeof(OpCodeSimd));
SetA64("0>0011101<100000111110xxxxxxxxxx", InstName.Fabs_V, InstEmit.Fabs_V, typeof(OpCodeSimd));
SetA64("000111100x1xxxxx001010xxxxxxxxxx", InstName.Fadd_S, InstEmit.Fadd_S, typeof(OpCodeSimdReg));
SetA64("0>0011100<1xxxxx110101xxxxxxxxxx", InstName.Fadd_V, InstEmit.Fadd_V, typeof(OpCodeSimdReg));
SetA64("011111100x110000110110xxxxxxxxxx", InstName.Faddp_S, InstEmit.Faddp_S, typeof(OpCodeSimd));
SetA64("0>1011100<1xxxxx110101xxxxxxxxxx", InstName.Faddp_V, InstEmit.Faddp_V, typeof(OpCodeSimdReg));
SetA64("000111100x1xxxxxxxxx01xxxxx0xxxx", InstName.Fccmp_S, null, typeof(OpCodeSimdFcond));
SetA64("000111100x1xxxxxxxxx01xxxxx1xxxx", InstName.Fccmpe_S, null, typeof(OpCodeSimdFcond));
SetA64("010111100x1xxxxx111001xxxxxxxxxx", InstName.Fcmeq_S, null, typeof(OpCodeSimdReg));
@ -293,73 +293,73 @@ namespace ARMeilleure.Decoders
SetA64("0>1011101<100001101110xxxxxxxxxx", InstName.Fcvtzu_V, null, typeof(OpCodeSimd));
SetA64("0x101111001xxxxx111111xxxxxxxxxx", InstName.Fcvtzu_V_Fixed, null, typeof(OpCodeSimdShImm));
SetA64("0110111101xxxxxx111111xxxxxxxxxx", InstName.Fcvtzu_V_Fixed, null, typeof(OpCodeSimdShImm));
SetA64("000111100x1xxxxx000110xxxxxxxxxx", InstName.Fdiv_S, null, typeof(OpCodeSimdReg));
SetA64("0>1011100<1xxxxx111111xxxxxxxxxx", InstName.Fdiv_V, null, typeof(OpCodeSimdReg));
SetA64("000111110x0xxxxx0xxxxxxxxxxxxxxx", InstName.Fmadd_S, null, typeof(OpCodeSimdReg));
SetA64("000111100x1xxxxx010010xxxxxxxxxx", InstName.Fmax_S, null, typeof(OpCodeSimdReg));
SetA64("0>0011100<1xxxxx111101xxxxxxxxxx", InstName.Fmax_V, null, typeof(OpCodeSimdReg));
SetA64("000111100x1xxxxx011010xxxxxxxxxx", InstName.Fmaxnm_S, null, typeof(OpCodeSimdReg));
SetA64("0>0011100<1xxxxx110001xxxxxxxxxx", InstName.Fmaxnm_V, null, typeof(OpCodeSimdReg));
SetA64("0>1011100<1xxxxx111101xxxxxxxxxx", InstName.Fmaxp_V, null, typeof(OpCodeSimdReg));
SetA64("000111100x1xxxxx010110xxxxxxxxxx", InstName.Fmin_S, null, typeof(OpCodeSimdReg));
SetA64("0>0011101<1xxxxx111101xxxxxxxxxx", InstName.Fmin_V, null, typeof(OpCodeSimdReg));
SetA64("000111100x1xxxxx011110xxxxxxxxxx", InstName.Fminnm_S, null, typeof(OpCodeSimdReg));
SetA64("0>0011101<1xxxxx110001xxxxxxxxxx", InstName.Fminnm_V, null, typeof(OpCodeSimdReg));
SetA64("0>1011101<1xxxxx111101xxxxxxxxxx", InstName.Fminp_V, null, typeof(OpCodeSimdReg));
SetA64("010111111xxxxxxx0001x0xxxxxxxxxx", InstName.Fmla_Se, null, typeof(OpCodeSimdRegElemF));
SetA64("0>0011100<1xxxxx110011xxxxxxxxxx", InstName.Fmla_V, null, typeof(OpCodeSimdReg));
SetA64("0>0011111<xxxxxx0001x0xxxxxxxxxx", InstName.Fmla_Ve, null, typeof(OpCodeSimdRegElemF));
SetA64("010111111xxxxxxx0101x0xxxxxxxxxx", InstName.Fmls_Se, null, typeof(OpCodeSimdRegElemF));
SetA64("0>0011101<1xxxxx110011xxxxxxxxxx", InstName.Fmls_V, null, typeof(OpCodeSimdReg));
SetA64("0>0011111<xxxxxx0101x0xxxxxxxxxx", InstName.Fmls_Ve, null, typeof(OpCodeSimdRegElemF));
SetA64("000111100x1xxxxx000110xxxxxxxxxx", InstName.Fdiv_S, InstEmit.Fdiv_S, typeof(OpCodeSimdReg));
SetA64("0>1011100<1xxxxx111111xxxxxxxxxx", InstName.Fdiv_V, InstEmit.Fdiv_V, typeof(OpCodeSimdReg));
SetA64("000111110x0xxxxx0xxxxxxxxxxxxxxx", InstName.Fmadd_S, InstEmit.Fmadd_S, typeof(OpCodeSimdReg));
SetA64("000111100x1xxxxx010010xxxxxxxxxx", InstName.Fmax_S, InstEmit.Fmax_S, typeof(OpCodeSimdReg));
SetA64("0>0011100<1xxxxx111101xxxxxxxxxx", InstName.Fmax_V, InstEmit.Fmax_V, typeof(OpCodeSimdReg));
SetA64("000111100x1xxxxx011010xxxxxxxxxx", InstName.Fmaxnm_S, InstEmit.Fmaxnm_S, typeof(OpCodeSimdReg));
SetA64("0>0011100<1xxxxx110001xxxxxxxxxx", InstName.Fmaxnm_V, InstEmit.Fmaxnm_V, typeof(OpCodeSimdReg));
SetA64("0>1011100<1xxxxx111101xxxxxxxxxx", InstName.Fmaxp_V, InstEmit.Fmaxp_V, typeof(OpCodeSimdReg));
SetA64("000111100x1xxxxx010110xxxxxxxxxx", InstName.Fmin_S, InstEmit.Fmin_S, typeof(OpCodeSimdReg));
SetA64("0>0011101<1xxxxx111101xxxxxxxxxx", InstName.Fmin_V, InstEmit.Fmin_V, typeof(OpCodeSimdReg));
SetA64("000111100x1xxxxx011110xxxxxxxxxx", InstName.Fminnm_S, InstEmit.Fminnm_S, typeof(OpCodeSimdReg));
SetA64("0>0011101<1xxxxx110001xxxxxxxxxx", InstName.Fminnm_V, InstEmit.Fminnm_V, typeof(OpCodeSimdReg));
SetA64("0>1011101<1xxxxx111101xxxxxxxxxx", InstName.Fminp_V, InstEmit.Fminp_V, typeof(OpCodeSimdReg));
SetA64("010111111xxxxxxx0001x0xxxxxxxxxx", InstName.Fmla_Se, InstEmit.Fmla_Se, typeof(OpCodeSimdRegElemF));
SetA64("0>0011100<1xxxxx110011xxxxxxxxxx", InstName.Fmla_V, InstEmit.Fmla_V, typeof(OpCodeSimdReg));
SetA64("0>0011111<xxxxxx0001x0xxxxxxxxxx", InstName.Fmla_Ve, InstEmit.Fmla_Ve, typeof(OpCodeSimdRegElemF));
SetA64("010111111xxxxxxx0101x0xxxxxxxxxx", InstName.Fmls_Se, InstEmit.Fmls_Se, typeof(OpCodeSimdRegElemF));
SetA64("0>0011101<1xxxxx110011xxxxxxxxxx", InstName.Fmls_V, InstEmit.Fmls_V, typeof(OpCodeSimdReg));
SetA64("0>0011111<xxxxxx0101x0xxxxxxxxxx", InstName.Fmls_Ve, InstEmit.Fmls_Ve, typeof(OpCodeSimdRegElemF));
SetA64("000111100x100000010000xxxxxxxxxx", InstName.Fmov_S, null, typeof(OpCodeSimd));
SetA64("00011110xx1xxxxxxxx100xxxxxxxxxx", InstName.Fmov_Si, null, typeof(OpCodeSimdFmov));
SetA64("00011110xx1xxxxxxxx100xxxxxxxxxx", InstName.Fmov_Si, InstEmit.Fmov_Si, typeof(OpCodeSimdFmov));
SetA64("0xx0111100000xxx111101xxxxxxxxxx", InstName.Fmov_V, null, typeof(OpCodeSimdImm));
SetA64("x00111100x100110000000xxxxxxxxxx", InstName.Fmov_Ftoi, null, typeof(OpCodeSimdCvt));
SetA64("x00111100x100111000000xxxxxxxxxx", InstName.Fmov_Itof, null, typeof(OpCodeSimdCvt));
SetA64("1001111010101110000000xxxxxxxxxx", InstName.Fmov_Ftoi1, null, typeof(OpCodeSimdCvt));
SetA64("1001111010101111000000xxxxxxxxxx", InstName.Fmov_Itof1, null, typeof(OpCodeSimdCvt));
SetA64("000111110x0xxxxx1xxxxxxxxxxxxxxx", InstName.Fmsub_S, null, typeof(OpCodeSimdReg));
SetA64("000111100x1xxxxx000010xxxxxxxxxx", InstName.Fmul_S, null, typeof(OpCodeSimdReg));
SetA64("010111111xxxxxxx1001x0xxxxxxxxxx", InstName.Fmul_Se, null, typeof(OpCodeSimdRegElemF));
SetA64("0>1011100<1xxxxx110111xxxxxxxxxx", InstName.Fmul_V, null, typeof(OpCodeSimdReg));
SetA64("0>0011111<xxxxxx1001x0xxxxxxxxxx", InstName.Fmul_Ve, null, typeof(OpCodeSimdRegElemF));
SetA64("010111100x1xxxxx110111xxxxxxxxxx", InstName.Fmulx_S, null, typeof(OpCodeSimdReg));
SetA64("011111111xxxxxxx1001x0xxxxxxxxxx", InstName.Fmulx_Se, null, typeof(OpCodeSimdRegElemF));
SetA64("0>0011100<1xxxxx110111xxxxxxxxxx", InstName.Fmulx_V, null, typeof(OpCodeSimdReg));
SetA64("0>1011111<xxxxxx1001x0xxxxxxxxxx", InstName.Fmulx_Ve, null, typeof(OpCodeSimdRegElemF));
SetA64("000111100x100001010000xxxxxxxxxx", InstName.Fneg_S, null, typeof(OpCodeSimd));
SetA64("0>1011101<100000111110xxxxxxxxxx", InstName.Fneg_V, null, typeof(OpCodeSimd));
SetA64("000111110x1xxxxx0xxxxxxxxxxxxxxx", InstName.Fnmadd_S, null, typeof(OpCodeSimdReg));
SetA64("000111110x1xxxxx1xxxxxxxxxxxxxxx", InstName.Fnmsub_S, null, typeof(OpCodeSimdReg));
SetA64("000111100x1xxxxx100010xxxxxxxxxx", InstName.Fnmul_S, null, typeof(OpCodeSimdReg));
SetA64("010111101x100001110110xxxxxxxxxx", InstName.Frecpe_S, null, typeof(OpCodeSimd));
SetA64("0>0011101<100001110110xxxxxxxxxx", InstName.Frecpe_V, null, typeof(OpCodeSimd));
SetA64("010111100x1xxxxx111111xxxxxxxxxx", InstName.Frecps_S, null, typeof(OpCodeSimdReg));
SetA64("0>0011100<1xxxxx111111xxxxxxxxxx", InstName.Frecps_V, null, typeof(OpCodeSimdReg));
SetA64("010111101x100001111110xxxxxxxxxx", InstName.Frecpx_S, null, typeof(OpCodeSimd));
SetA64("000111100x100110010000xxxxxxxxxx", InstName.Frinta_S, null, typeof(OpCodeSimd));
SetA64("0>1011100<100001100010xxxxxxxxxx", InstName.Frinta_V, null, typeof(OpCodeSimd));
SetA64("000111100x100111110000xxxxxxxxxx", InstName.Frinti_S, null, typeof(OpCodeSimd));
SetA64("0>1011101<100001100110xxxxxxxxxx", InstName.Frinti_V, null, typeof(OpCodeSimd));
SetA64("000111100x100101010000xxxxxxxxxx", InstName.Frintm_S, null, typeof(OpCodeSimd));
SetA64("0>0011100<100001100110xxxxxxxxxx", InstName.Frintm_V, null, typeof(OpCodeSimd));
SetA64("000111100x100100010000xxxxxxxxxx", InstName.Frintn_S, null, typeof(OpCodeSimd));
SetA64("0>0011100<100001100010xxxxxxxxxx", InstName.Frintn_V, null, typeof(OpCodeSimd));
SetA64("000111100x100100110000xxxxxxxxxx", InstName.Frintp_S, null, typeof(OpCodeSimd));
SetA64("0>0011101<100001100010xxxxxxxxxx", InstName.Frintp_V, null, typeof(OpCodeSimd));
SetA64("000111100x100111010000xxxxxxxxxx", InstName.Frintx_S, null, typeof(OpCodeSimd));
SetA64("0>1011100<100001100110xxxxxxxxxx", InstName.Frintx_V, null, typeof(OpCodeSimd));
SetA64("000111100x100101110000xxxxxxxxxx", InstName.Frintz_S, null, typeof(OpCodeSimd));
SetA64("0>0011101<100001100110xxxxxxxxxx", InstName.Frintz_V, null, typeof(OpCodeSimd));
SetA64("011111101x100001110110xxxxxxxxxx", InstName.Frsqrte_S, null, typeof(OpCodeSimd));
SetA64("0>1011101<100001110110xxxxxxxxxx", InstName.Frsqrte_V, null, typeof(OpCodeSimd));
SetA64("010111101x1xxxxx111111xxxxxxxxxx", InstName.Frsqrts_S, null, typeof(OpCodeSimdReg));
SetA64("0>0011101<1xxxxx111111xxxxxxxxxx", InstName.Frsqrts_V, null, typeof(OpCodeSimdReg));
SetA64("000111100x100001110000xxxxxxxxxx", InstName.Fsqrt_S, null, typeof(OpCodeSimd));
SetA64("0>1011101<100001111110xxxxxxxxxx", InstName.Fsqrt_V, null, typeof(OpCodeSimd));
SetA64("000111100x1xxxxx001110xxxxxxxxxx", InstName.Fsub_S, null, typeof(OpCodeSimdReg));
SetA64("0>0011101<1xxxxx110101xxxxxxxxxx", InstName.Fsub_V, null, typeof(OpCodeSimdReg));
SetA64("000111110x0xxxxx1xxxxxxxxxxxxxxx", InstName.Fmsub_S, InstEmit.Fmsub_S, typeof(OpCodeSimdReg));
SetA64("000111100x1xxxxx000010xxxxxxxxxx", InstName.Fmul_S, InstEmit.Fmul_S, typeof(OpCodeSimdReg));
SetA64("010111111xxxxxxx1001x0xxxxxxxxxx", InstName.Fmul_Se, InstEmit.Fmul_Se, typeof(OpCodeSimdRegElemF));
SetA64("0>1011100<1xxxxx110111xxxxxxxxxx", InstName.Fmul_V, InstEmit.Fmul_V, typeof(OpCodeSimdReg));
SetA64("0>0011111<xxxxxx1001x0xxxxxxxxxx", InstName.Fmul_Ve, InstEmit.Fmul_Ve, typeof(OpCodeSimdRegElemF));
SetA64("010111100x1xxxxx110111xxxxxxxxxx", InstName.Fmulx_S, InstEmit.Fmulx_S, typeof(OpCodeSimdReg));
SetA64("011111111xxxxxxx1001x0xxxxxxxxxx", InstName.Fmulx_Se, InstEmit.Fmulx_Se, typeof(OpCodeSimdRegElemF));
SetA64("0>0011100<1xxxxx110111xxxxxxxxxx", InstName.Fmulx_V, InstEmit.Fmulx_V, typeof(OpCodeSimdReg));
SetA64("0>1011111<xxxxxx1001x0xxxxxxxxxx", InstName.Fmulx_Ve, InstEmit.Fmulx_Ve, typeof(OpCodeSimdRegElemF));
SetA64("000111100x100001010000xxxxxxxxxx", InstName.Fneg_S, InstEmit.Fneg_S, typeof(OpCodeSimd));
SetA64("0>1011101<100000111110xxxxxxxxxx", InstName.Fneg_V, InstEmit.Fneg_V, typeof(OpCodeSimd));
SetA64("000111110x1xxxxx0xxxxxxxxxxxxxxx", InstName.Fnmadd_S, InstEmit.Fnmadd_S, typeof(OpCodeSimdReg));
SetA64("000111110x1xxxxx1xxxxxxxxxxxxxxx", InstName.Fnmsub_S, InstEmit.Fnmsub_S, typeof(OpCodeSimdReg));
SetA64("000111100x1xxxxx100010xxxxxxxxxx", InstName.Fnmul_S, InstEmit.Fnmul_S, typeof(OpCodeSimdReg));
SetA64("010111101x100001110110xxxxxxxxxx", InstName.Frecpe_S, InstEmit.Frecpe_S, typeof(OpCodeSimd));
SetA64("0>0011101<100001110110xxxxxxxxxx", InstName.Frecpe_V, InstEmit.Frecpe_V, typeof(OpCodeSimd));
SetA64("010111100x1xxxxx111111xxxxxxxxxx", InstName.Frecps_S, InstEmit.Frecps_S, typeof(OpCodeSimdReg));
SetA64("0>0011100<1xxxxx111111xxxxxxxxxx", InstName.Frecps_V, InstEmit.Frecps_V, typeof(OpCodeSimdReg));
SetA64("010111101x100001111110xxxxxxxxxx", InstName.Frecpx_S, InstEmit.Frecpx_S, typeof(OpCodeSimd));
SetA64("000111100x100110010000xxxxxxxxxx", InstName.Frinta_S, InstEmit.Frinta_S, typeof(OpCodeSimd));
SetA64("0>1011100<100001100010xxxxxxxxxx", InstName.Frinta_V, InstEmit.Frinta_V, typeof(OpCodeSimd));
SetA64("000111100x100111110000xxxxxxxxxx", InstName.Frinti_S, InstEmit.Frinti_S, typeof(OpCodeSimd));
SetA64("0>1011101<100001100110xxxxxxxxxx", InstName.Frinti_V, InstEmit.Frinti_V, typeof(OpCodeSimd));
SetA64("000111100x100101010000xxxxxxxxxx", InstName.Frintm_S, InstEmit.Frintm_S, typeof(OpCodeSimd));
SetA64("0>0011100<100001100110xxxxxxxxxx", InstName.Frintm_V, InstEmit.Frintm_V, typeof(OpCodeSimd));
SetA64("000111100x100100010000xxxxxxxxxx", InstName.Frintn_S, InstEmit.Frintn_S, typeof(OpCodeSimd));
SetA64("0>0011100<100001100010xxxxxxxxxx", InstName.Frintn_V, InstEmit.Frintn_V, typeof(OpCodeSimd));
SetA64("000111100x100100110000xxxxxxxxxx", InstName.Frintp_S, InstEmit.Frintp_S, typeof(OpCodeSimd));
SetA64("0>0011101<100001100010xxxxxxxxxx", InstName.Frintp_V, InstEmit.Frintp_V, typeof(OpCodeSimd));
SetA64("000111100x100111010000xxxxxxxxxx", InstName.Frintx_S, InstEmit.Frintx_S, typeof(OpCodeSimd));
SetA64("0>1011100<100001100110xxxxxxxxxx", InstName.Frintx_V, InstEmit.Frintx_V, typeof(OpCodeSimd));
SetA64("000111100x100101110000xxxxxxxxxx", InstName.Frintz_S, InstEmit.Frintz_S, typeof(OpCodeSimd));
SetA64("0>0011101<100001100110xxxxxxxxxx", InstName.Frintz_V, InstEmit.Frintz_V, typeof(OpCodeSimd));
SetA64("011111101x100001110110xxxxxxxxxx", InstName.Frsqrte_S, InstEmit.Frsqrte_S, typeof(OpCodeSimd));
SetA64("0>1011101<100001110110xxxxxxxxxx", InstName.Frsqrte_V, InstEmit.Frsqrte_V, typeof(OpCodeSimd));
SetA64("010111101x1xxxxx111111xxxxxxxxxx", InstName.Frsqrts_S, InstEmit.Frsqrts_S, typeof(OpCodeSimdReg));
SetA64("0>0011101<1xxxxx111111xxxxxxxxxx", InstName.Frsqrts_V, InstEmit.Frsqrts_V, typeof(OpCodeSimdReg));
SetA64("000111100x100001110000xxxxxxxxxx", InstName.Fsqrt_S, InstEmit.Fsqrt_S, typeof(OpCodeSimd));
SetA64("0>1011101<100001111110xxxxxxxxxx", InstName.Fsqrt_V, InstEmit.Fsqrt_V, typeof(OpCodeSimd));
SetA64("000111100x1xxxxx001110xxxxxxxxxx", InstName.Fsub_S, InstEmit.Fsub_S, typeof(OpCodeSimdReg));
SetA64("0>0011101<1xxxxx110101xxxxxxxxxx", InstName.Fsub_V, InstEmit.Fsub_V, typeof(OpCodeSimdReg));
SetA64("01001110000xxxxx000111xxxxxxxxxx", InstName.Ins_Gp, null, typeof(OpCodeSimdIns));
SetA64("01101110000xxxxx0xxxx1xxxxxxxxxx", InstName.Ins_V, null, typeof(OpCodeSimdIns));
SetA64("0x00110001000000xxxxxxxxxxxxxxxx", InstName.Ld__Vms, null, typeof(OpCodeSimdMemMs));
@ -373,40 +373,40 @@ namespace ARMeilleure.Decoders
SetA64("xx111101x1xxxxxxxxxxxxxxxxxxxxxx", InstName.Ldr, null, typeof(OpCodeSimdMemImm));
SetA64("xx111100x11xxxxxxxxx10xxxxxxxxxx", InstName.Ldr, null, typeof(OpCodeSimdMemReg));
SetA64("xx011100xxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ldr_Literal, null, typeof(OpCodeSimdMemLit));
SetA64("0x001110<<1xxxxx100101xxxxxxxxxx", InstName.Mla_V, null, typeof(OpCodeSimdReg));
SetA64("0x101111xxxxxxxx0000x0xxxxxxxxxx", InstName.Mla_Ve, null, typeof(OpCodeSimdRegElem));
SetA64("0x101110<<1xxxxx100101xxxxxxxxxx", InstName.Mls_V, null, typeof(OpCodeSimdReg));
SetA64("0x101111xxxxxxxx0100x0xxxxxxxxxx", InstName.Mls_Ve, null, typeof(OpCodeSimdRegElem));
SetA64("0x001110<<1xxxxx100101xxxxxxxxxx", InstName.Mla_V, InstEmit.Mla_V, typeof(OpCodeSimdReg));
SetA64("0x101111xxxxxxxx0000x0xxxxxxxxxx", InstName.Mla_Ve, InstEmit.Mla_Ve, typeof(OpCodeSimdRegElem));
SetA64("0x101110<<1xxxxx100101xxxxxxxxxx", InstName.Mls_V, InstEmit.Mls_V, typeof(OpCodeSimdReg));
SetA64("0x101111xxxxxxxx0100x0xxxxxxxxxx", InstName.Mls_Ve, InstEmit.Mls_Ve, typeof(OpCodeSimdRegElem));
SetA64("0x00111100000xxx0xx001xxxxxxxxxx", InstName.Movi_V, null, typeof(OpCodeSimdImm));
SetA64("0x00111100000xxx10x001xxxxxxxxxx", InstName.Movi_V, null, typeof(OpCodeSimdImm));
SetA64("0x00111100000xxx110x01xxxxxxxxxx", InstName.Movi_V, null, typeof(OpCodeSimdImm));
SetA64("0xx0111100000xxx111001xxxxxxxxxx", InstName.Movi_V, null, typeof(OpCodeSimdImm));
SetA64("0x001110<<1xxxxx100111xxxxxxxxxx", InstName.Mul_V, null, typeof(OpCodeSimdReg));
SetA64("0x001111xxxxxxxx1000x0xxxxxxxxxx", InstName.Mul_Ve, null, typeof(OpCodeSimdRegElem));
SetA64("0x001110<<1xxxxx100111xxxxxxxxxx", InstName.Mul_V, InstEmit.Mul_V, typeof(OpCodeSimdReg));
SetA64("0x001111xxxxxxxx1000x0xxxxxxxxxx", InstName.Mul_Ve, InstEmit.Mul_Ve, typeof(OpCodeSimdRegElem));
SetA64("0x10111100000xxx0xx001xxxxxxxxxx", InstName.Mvni_V, null, typeof(OpCodeSimdImm));
SetA64("0x10111100000xxx10x001xxxxxxxxxx", InstName.Mvni_V, null, typeof(OpCodeSimdImm));
SetA64("0x10111100000xxx110x01xxxxxxxxxx", InstName.Mvni_V, null, typeof(OpCodeSimdImm));
SetA64("0111111011100000101110xxxxxxxxxx", InstName.Neg_S, null, typeof(OpCodeSimd));
SetA64("0>101110<<100000101110xxxxxxxxxx", InstName.Neg_V, null, typeof(OpCodeSimd));
SetA64("0111111011100000101110xxxxxxxxxx", InstName.Neg_S, InstEmit.Neg_S, typeof(OpCodeSimd));
SetA64("0>101110<<100000101110xxxxxxxxxx", InstName.Neg_V, InstEmit.Neg_V, typeof(OpCodeSimd));
SetA64("0x10111000100000010110xxxxxxxxxx", InstName.Not_V, null, typeof(OpCodeSimd));
SetA64("0x001110111xxxxx000111xxxxxxxxxx", InstName.Orn_V, null, typeof(OpCodeSimdReg));
SetA64("0x001110101xxxxx000111xxxxxxxxxx", InstName.Orr_V, null, typeof(OpCodeSimdReg));
SetA64("0x00111100000xxx<<x101xxxxxxxxxx", InstName.Orr_Vi, null, typeof(OpCodeSimdImm));
SetA64("0x101110<<1xxxxx010000xxxxxxxxxx", InstName.Raddhn_V, null, typeof(OpCodeSimdReg));
SetA64("0x101110<<1xxxxx010000xxxxxxxxxx", InstName.Raddhn_V, InstEmit.Raddhn_V, typeof(OpCodeSimdReg));
SetA64("0x10111001100000010110xxxxxxxxxx", InstName.Rbit_V, null, typeof(OpCodeSimd));
SetA64("0x00111000100000000110xxxxxxxxxx", InstName.Rev16_V, null, typeof(OpCodeSimd));
SetA64("0x1011100x100000000010xxxxxxxxxx", InstName.Rev32_V, null, typeof(OpCodeSimd));
SetA64("0x001110<<100000000010xxxxxxxxxx", InstName.Rev64_V, null, typeof(OpCodeSimd));
SetA64("0x00111100>>>xxx100011xxxxxxxxxx", InstName.Rshrn_V, null, typeof(OpCodeSimdShImm));
SetA64("0x101110<<1xxxxx011000xxxxxxxxxx", InstName.Rsubhn_V, null, typeof(OpCodeSimdReg));
SetA64("0x001110<<1xxxxx011111xxxxxxxxxx", InstName.Saba_V, null, typeof(OpCodeSimdReg));
SetA64("0x001110<<1xxxxx010100xxxxxxxxxx", InstName.Sabal_V, null, typeof(OpCodeSimdReg));
SetA64("0x001110<<1xxxxx011101xxxxxxxxxx", InstName.Sabd_V, null, typeof(OpCodeSimdReg));
SetA64("0x001110<<1xxxxx011100xxxxxxxxxx", InstName.Sabdl_V, null, typeof(OpCodeSimdReg));
SetA64("0x001110<<100000011010xxxxxxxxxx", InstName.Sadalp_V, null, typeof(OpCodeSimd));
SetA64("0x001110<<1xxxxx000000xxxxxxxxxx", InstName.Saddl_V, null, typeof(OpCodeSimdReg));
SetA64("0x001110<<100000001010xxxxxxxxxx", InstName.Saddlp_V, null, typeof(OpCodeSimd));
SetA64("0x001110<<1xxxxx000100xxxxxxxxxx", InstName.Saddw_V, null, typeof(OpCodeSimdReg));
SetA64("0x101110<<1xxxxx011000xxxxxxxxxx", InstName.Rsubhn_V, InstEmit.Rsubhn_V, typeof(OpCodeSimdReg));
SetA64("0x001110<<1xxxxx011111xxxxxxxxxx", InstName.Saba_V, InstEmit.Saba_V, typeof(OpCodeSimdReg));
SetA64("0x001110<<1xxxxx010100xxxxxxxxxx", InstName.Sabal_V, InstEmit.Sabal_V, typeof(OpCodeSimdReg));
SetA64("0x001110<<1xxxxx011101xxxxxxxxxx", InstName.Sabd_V, InstEmit.Sabd_V, typeof(OpCodeSimdReg));
SetA64("0x001110<<1xxxxx011100xxxxxxxxxx", InstName.Sabdl_V, InstEmit.Sabdl_V, typeof(OpCodeSimdReg));
SetA64("0x001110<<100000011010xxxxxxxxxx", InstName.Sadalp_V, InstEmit.Sadalp_V, typeof(OpCodeSimd));
SetA64("0x001110<<1xxxxx000000xxxxxxxxxx", InstName.Saddl_V, InstEmit.Saddl_V, typeof(OpCodeSimdReg));
SetA64("0x001110<<100000001010xxxxxxxxxx", InstName.Saddlp_V, InstEmit.Saddlp_V, typeof(OpCodeSimd));
SetA64("0x001110<<1xxxxx000100xxxxxxxxxx", InstName.Saddw_V, InstEmit.Saddw_V, typeof(OpCodeSimdReg));
SetA64("x00111100x100010000000xxxxxxxxxx", InstName.Scvtf_Gp, null, typeof(OpCodeSimdCvt));
SetA64(">00111100x000010>xxxxxxxxxxxxxxx", InstName.Scvtf_Gp_Fixed, null, typeof(OpCodeSimdCvt));
SetA64("010111100x100001110110xxxxxxxxxx", InstName.Scvtf_S, null, typeof(OpCodeSimd));
@ -421,39 +421,43 @@ namespace ARMeilleure.Decoders
SetA64("01011110000xxxxx010100xxxxxxxxxx", InstName.Sha256h2_V, null, typeof(OpCodeSimdReg));
SetA64("0101111000101000001010xxxxxxxxxx", InstName.Sha256su0_V, null, typeof(OpCodeSimd));
SetA64("01011110000xxxxx011000xxxxxxxxxx", InstName.Sha256su1_V, null, typeof(OpCodeSimdReg));
SetA64("0x001110<<1xxxxx000001xxxxxxxxxx", InstName.Shadd_V, null, typeof(OpCodeSimdReg));
SetA64("0x001110<<1xxxxx000001xxxxxxxxxx", InstName.Shadd_V, InstEmit.Shadd_V, typeof(OpCodeSimdReg));
SetA64("0101111101xxxxxx010101xxxxxxxxxx", InstName.Shl_S, null, typeof(OpCodeSimdShImm));
SetA64("0x00111100>>>xxx010101xxxxxxxxxx", InstName.Shl_V, null, typeof(OpCodeSimdShImm));
SetA64("0100111101xxxxxx010101xxxxxxxxxx", InstName.Shl_V, null, typeof(OpCodeSimdShImm));
SetA64("0x101110<<100001001110xxxxxxxxxx", InstName.Shll_V, null, typeof(OpCodeSimd));
SetA64("0x00111100>>>xxx100001xxxxxxxxxx", InstName.Shrn_V, null, typeof(OpCodeSimdShImm));
SetA64("0x001110<<1xxxxx001001xxxxxxxxxx", InstName.Shsub_V, null, typeof(OpCodeSimdReg));
SetA64("0x001110<<1xxxxx001001xxxxxxxxxx", InstName.Shsub_V, InstEmit.Shsub_V, typeof(OpCodeSimdReg));
SetA64("0x1011110>>>>xxx010101xxxxxxxxxx", InstName.Sli_V, null, typeof(OpCodeSimdShImm));
SetA64("0x001110<<1xxxxx011001xxxxxxxxxx", InstName.Smax_V, null, typeof(OpCodeSimdReg));
SetA64("0x001110<<1xxxxx101001xxxxxxxxxx", InstName.Smaxp_V, null, typeof(OpCodeSimdReg));
SetA64("0x001110<<1xxxxx011011xxxxxxxxxx", InstName.Smin_V, null, typeof(OpCodeSimdReg));
SetA64("0x001110<<1xxxxx101011xxxxxxxxxx", InstName.Sminp_V, null, typeof(OpCodeSimdReg));
SetA64("0x001110<<1xxxxx100000xxxxxxxxxx", InstName.Smlal_V, null, typeof(OpCodeSimdReg));
SetA64("0x001111xxxxxxxx0010x0xxxxxxxxxx", InstName.Smlal_Ve, null, typeof(OpCodeSimdRegElem));
SetA64("0x001110<<1xxxxx101000xxxxxxxxxx", InstName.Smlsl_V, null, typeof(OpCodeSimdReg));
SetA64("0x001111xxxxxxxx0110x0xxxxxxxxxx", InstName.Smlsl_Ve, null, typeof(OpCodeSimdRegElem));
SetA64("0x001110<<1xxxxx011001xxxxxxxxxx", InstName.Smax_V, InstEmit.Smax_V, typeof(OpCodeSimdReg));
SetA64("0x001110<<1xxxxx101001xxxxxxxxxx", InstName.Smaxp_V, InstEmit.Smaxp_V, typeof(OpCodeSimdReg));
SetA64("000011100x110000101010xxxxxxxxxx", InstName.Smaxv_V, InstEmit.Smaxv_V, typeof(OpCodeSimd));
SetA64("01001110<<110000101010xxxxxxxxxx", InstName.Smaxv_V, InstEmit.Smaxv_V, typeof(OpCodeSimd));
SetA64("0x001110<<1xxxxx011011xxxxxxxxxx", InstName.Smin_V, InstEmit.Smin_V, typeof(OpCodeSimdReg));
SetA64("0x001110<<1xxxxx101011xxxxxxxxxx", InstName.Sminp_V, InstEmit.Sminp_V, typeof(OpCodeSimdReg));
SetA64("000011100x110001101010xxxxxxxxxx", InstName.Sminv_V, InstEmit.Sminv_V, typeof(OpCodeSimd));
SetA64("01001110<<110001101010xxxxxxxxxx", InstName.Sminv_V, InstEmit.Sminv_V, typeof(OpCodeSimd));
SetA64("0x001110<<1xxxxx100000xxxxxxxxxx", InstName.Smlal_V, InstEmit.Smlal_V, typeof(OpCodeSimdReg));
SetA64("0x001111xxxxxxxx0010x0xxxxxxxxxx", InstName.Smlal_Ve, InstEmit.Smlal_Ve, typeof(OpCodeSimdRegElem));
SetA64("0x001110<<1xxxxx101000xxxxxxxxxx", InstName.Smlsl_V, InstEmit.Smlsl_V, typeof(OpCodeSimdReg));
SetA64("0x001111xxxxxxxx0110x0xxxxxxxxxx", InstName.Smlsl_Ve, InstEmit.Smlsl_Ve, typeof(OpCodeSimdRegElem));
SetA64("0x001110000xxxxx001011xxxxxxxxxx", InstName.Smov_S, null, typeof(OpCodeSimdIns));
SetA64("0x001110<<1xxxxx110000xxxxxxxxxx", InstName.Smull_V, null, typeof(OpCodeSimdReg));
SetA64("0x001111xxxxxxxx1010x0xxxxxxxxxx", InstName.Smull_Ve, null, typeof(OpCodeSimdRegElem));
SetA64("01011110xx100000011110xxxxxxxxxx", InstName.Sqabs_S, null, typeof(OpCodeSimd));
SetA64("0>001110<<100000011110xxxxxxxxxx", InstName.Sqabs_V, null, typeof(OpCodeSimd));
SetA64("01011110xx1xxxxx000011xxxxxxxxxx", InstName.Sqadd_S, null, typeof(OpCodeSimdReg));
SetA64("0>001110<<1xxxxx000011xxxxxxxxxx", InstName.Sqadd_V, null, typeof(OpCodeSimdReg));
SetA64("01011110011xxxxx101101xxxxxxxxxx", InstName.Sqdmulh_S, null, typeof(OpCodeSimdReg));
SetA64("01011110101xxxxx101101xxxxxxxxxx", InstName.Sqdmulh_S, null, typeof(OpCodeSimdReg));
SetA64("0x001110011xxxxx101101xxxxxxxxxx", InstName.Sqdmulh_V, null, typeof(OpCodeSimdReg));
SetA64("0x001110101xxxxx101101xxxxxxxxxx", InstName.Sqdmulh_V, null, typeof(OpCodeSimdReg));
SetA64("01111110xx100000011110xxxxxxxxxx", InstName.Sqneg_S, null, typeof(OpCodeSimd));
SetA64("0>101110<<100000011110xxxxxxxxxx", InstName.Sqneg_V, null, typeof(OpCodeSimd));
SetA64("01111110011xxxxx101101xxxxxxxxxx", InstName.Sqrdmulh_S, null, typeof(OpCodeSimdReg));
SetA64("01111110101xxxxx101101xxxxxxxxxx", InstName.Sqrdmulh_S, null, typeof(OpCodeSimdReg));
SetA64("0x101110011xxxxx101101xxxxxxxxxx", InstName.Sqrdmulh_V, null, typeof(OpCodeSimdReg));
SetA64("0x101110101xxxxx101101xxxxxxxxxx", InstName.Sqrdmulh_V, null, typeof(OpCodeSimdReg));
SetA64("0x001110<<1xxxxx110000xxxxxxxxxx", InstName.Smull_V, InstEmit.Smull_V, typeof(OpCodeSimdReg));
SetA64("0x001111xxxxxxxx1010x0xxxxxxxxxx", InstName.Smull_Ve, InstEmit.Smull_Ve, typeof(OpCodeSimdRegElem));
SetA64("01011110xx100000011110xxxxxxxxxx", InstName.Sqabs_S, InstEmit.Sqabs_S, typeof(OpCodeSimd));
SetA64("0>001110<<100000011110xxxxxxxxxx", InstName.Sqabs_V, InstEmit.Sqabs_V, typeof(OpCodeSimd));
SetA64("01011110xx1xxxxx000011xxxxxxxxxx", InstName.Sqadd_S, InstEmit.Sqadd_S, typeof(OpCodeSimdReg));
SetA64("0>001110<<1xxxxx000011xxxxxxxxxx", InstName.Sqadd_V, InstEmit.Sqadd_V, typeof(OpCodeSimdReg));
SetA64("01011110011xxxxx101101xxxxxxxxxx", InstName.Sqdmulh_S, InstEmit.Sqdmulh_S, typeof(OpCodeSimdReg));
SetA64("01011110101xxxxx101101xxxxxxxxxx", InstName.Sqdmulh_S, InstEmit.Sqdmulh_S, typeof(OpCodeSimdReg));
SetA64("0x001110011xxxxx101101xxxxxxxxxx", InstName.Sqdmulh_V, InstEmit.Sqdmulh_V, typeof(OpCodeSimdReg));
SetA64("0x001110101xxxxx101101xxxxxxxxxx", InstName.Sqdmulh_V, InstEmit.Sqdmulh_V, typeof(OpCodeSimdReg));
SetA64("01111110xx100000011110xxxxxxxxxx", InstName.Sqneg_S, InstEmit.Sqneg_S, typeof(OpCodeSimd));
SetA64("0>101110<<100000011110xxxxxxxxxx", InstName.Sqneg_V, InstEmit.Sqneg_V, typeof(OpCodeSimd));
SetA64("01111110011xxxxx101101xxxxxxxxxx", InstName.Sqrdmulh_S, InstEmit.Sqrdmulh_S, typeof(OpCodeSimdReg));
SetA64("01111110101xxxxx101101xxxxxxxxxx", InstName.Sqrdmulh_S, InstEmit.Sqrdmulh_S, typeof(OpCodeSimdReg));
SetA64("0x101110011xxxxx101101xxxxxxxxxx", InstName.Sqrdmulh_V, InstEmit.Sqrdmulh_V, typeof(OpCodeSimdReg));
SetA64("0x101110101xxxxx101101xxxxxxxxxx", InstName.Sqrdmulh_V, InstEmit.Sqrdmulh_V, typeof(OpCodeSimdReg));
SetA64("0>001110<<1xxxxx010111xxxxxxxxxx", InstName.Sqrshl_V, null, typeof(OpCodeSimdReg));
SetA64("0101111100>>>xxx100111xxxxxxxxxx", InstName.Sqrshrn_S, null, typeof(OpCodeSimdShImm));
SetA64("0x00111100>>>xxx100111xxxxxxxxxx", InstName.Sqrshrn_V, null, typeof(OpCodeSimdShImm));
@ -464,13 +468,13 @@ namespace ARMeilleure.Decoders
SetA64("0x00111100>>>xxx100101xxxxxxxxxx", InstName.Sqshrn_V, null, typeof(OpCodeSimdShImm));
SetA64("0111111100>>>xxx100001xxxxxxxxxx", InstName.Sqshrun_S, null, typeof(OpCodeSimdShImm));
SetA64("0x10111100>>>xxx100001xxxxxxxxxx", InstName.Sqshrun_V, null, typeof(OpCodeSimdShImm));
SetA64("01011110xx1xxxxx001011xxxxxxxxxx", InstName.Sqsub_S, null, typeof(OpCodeSimdReg));
SetA64("0>001110<<1xxxxx001011xxxxxxxxxx", InstName.Sqsub_V, null, typeof(OpCodeSimdReg));
SetA64("01011110<<100001010010xxxxxxxxxx", InstName.Sqxtn_S, null, typeof(OpCodeSimd));
SetA64("0x001110<<100001010010xxxxxxxxxx", InstName.Sqxtn_V, null, typeof(OpCodeSimd));
SetA64("01111110<<100001001010xxxxxxxxxx", InstName.Sqxtun_S, null, typeof(OpCodeSimd));
SetA64("0x101110<<100001001010xxxxxxxxxx", InstName.Sqxtun_V, null, typeof(OpCodeSimd));
SetA64("0x001110<<1xxxxx000101xxxxxxxxxx", InstName.Srhadd_V, null, typeof(OpCodeSimdReg));
SetA64("01011110xx1xxxxx001011xxxxxxxxxx", InstName.Sqsub_S, InstEmit.Sqsub_S, typeof(OpCodeSimdReg));
SetA64("0>001110<<1xxxxx001011xxxxxxxxxx", InstName.Sqsub_V, InstEmit.Sqsub_V, typeof(OpCodeSimdReg));
SetA64("01011110<<100001010010xxxxxxxxxx", InstName.Sqxtn_S, InstEmit.Sqxtn_S, typeof(OpCodeSimd));
SetA64("0x001110<<100001010010xxxxxxxxxx", InstName.Sqxtn_V, InstEmit.Sqxtn_V, typeof(OpCodeSimd));
SetA64("01111110<<100001001010xxxxxxxxxx", InstName.Sqxtun_S, InstEmit.Sqxtun_S, typeof(OpCodeSimd));
SetA64("0x101110<<100001001010xxxxxxxxxx", InstName.Sqxtun_V, InstEmit.Sqxtun_V, typeof(OpCodeSimd));
SetA64("0x001110<<1xxxxx000101xxxxxxxxxx", InstName.Srhadd_V, InstEmit.Srhadd_V, typeof(OpCodeSimdReg));
SetA64("0>001110<<1xxxxx010101xxxxxxxxxx", InstName.Srshl_V, null, typeof(OpCodeSimdReg));
SetA64("0101111101xxxxxx001001xxxxxxxxxx", InstName.Srshr_S, null, typeof(OpCodeSimdShImm));
SetA64("0x00111100>>>xxx001001xxxxxxxxxx", InstName.Srshr_V, null, typeof(OpCodeSimdShImm));
@ -486,8 +490,8 @@ namespace ARMeilleure.Decoders
SetA64("0101111101xxxxxx000101xxxxxxxxxx", InstName.Ssra_S, null, typeof(OpCodeSimdShImm));
SetA64("0x00111100>>>xxx000101xxxxxxxxxx", InstName.Ssra_V, null, typeof(OpCodeSimdShImm));
SetA64("0100111101xxxxxx000101xxxxxxxxxx", InstName.Ssra_V, null, typeof(OpCodeSimdShImm));
SetA64("0x001110<<1xxxxx001000xxxxxxxxxx", InstName.Ssubl_V, null, typeof(OpCodeSimdReg));
SetA64("0x001110<<1xxxxx001100xxxxxxxxxx", InstName.Ssubw_V, null, typeof(OpCodeSimdReg));
SetA64("0x001110<<1xxxxx001000xxxxxxxxxx", InstName.Ssubl_V, InstEmit.Ssubl_V, typeof(OpCodeSimdReg));
SetA64("0x001110<<1xxxxx001100xxxxxxxxxx", InstName.Ssubw_V, InstEmit.Ssubw_V, typeof(OpCodeSimdReg));
SetA64("0x00110000000000xxxxxxxxxxxxxxxx", InstName.St__Vms, null, typeof(OpCodeSimdMemMs));
SetA64("0x001100100xxxxxxxxxxxxxxxxxxxxx", InstName.St__Vms, null, typeof(OpCodeSimdMemMs));
SetA64("0x00110100x00000xxxxxxxxxxxxxxxx", InstName.St__Vss, null, typeof(OpCodeSimdMemSs));
@ -498,54 +502,58 @@ namespace ARMeilleure.Decoders
SetA64("xx111100x00xxxxxxxxx11xxxxxxxxxx", InstName.Str, null, typeof(OpCodeSimdMemImm));
SetA64("xx111101x0xxxxxxxxxxxxxxxxxxxxxx", InstName.Str, null, typeof(OpCodeSimdMemImm));
SetA64("xx111100x01xxxxxxxxx10xxxxxxxxxx", InstName.Str, null, typeof(OpCodeSimdMemReg));
SetA64("01111110111xxxxx100001xxxxxxxxxx", InstName.Sub_S, null, typeof(OpCodeSimdReg));
SetA64("0>101110<<1xxxxx100001xxxxxxxxxx", InstName.Sub_V, null, typeof(OpCodeSimdReg));
SetA64("0x001110<<1xxxxx011000xxxxxxxxxx", InstName.Subhn_V, null, typeof(OpCodeSimdReg));
SetA64("01011110xx100000001110xxxxxxxxxx", InstName.Suqadd_S, null, typeof(OpCodeSimd));
SetA64("0>001110<<100000001110xxxxxxxxxx", InstName.Suqadd_V, null, typeof(OpCodeSimd));
SetA64("01111110111xxxxx100001xxxxxxxxxx", InstName.Sub_S, InstEmit.Sub_S, typeof(OpCodeSimdReg));
SetA64("0>101110<<1xxxxx100001xxxxxxxxxx", InstName.Sub_V, InstEmit.Sub_V, typeof(OpCodeSimdReg));
SetA64("0x001110<<1xxxxx011000xxxxxxxxxx", InstName.Subhn_V, InstEmit.Subhn_V, typeof(OpCodeSimdReg));
SetA64("01011110xx100000001110xxxxxxxxxx", InstName.Suqadd_S, InstEmit.Suqadd_S, typeof(OpCodeSimd));
SetA64("0>001110<<100000001110xxxxxxxxxx", InstName.Suqadd_V, InstEmit.Suqadd_V, typeof(OpCodeSimd));
SetA64("0x001110000xxxxx0xx000xxxxxxxxxx", InstName.Tbl_V, null, typeof(OpCodeSimdTbl));
SetA64("0>001110<<0xxxxx001010xxxxxxxxxx", InstName.Trn1_V, null, typeof(OpCodeSimdReg));
SetA64("0>001110<<0xxxxx011010xxxxxxxxxx", InstName.Trn2_V, null, typeof(OpCodeSimdReg));
SetA64("0x101110<<1xxxxx011111xxxxxxxxxx", InstName.Uaba_V, null, typeof(OpCodeSimdReg));
SetA64("0x101110<<1xxxxx010100xxxxxxxxxx", InstName.Uabal_V, null, typeof(OpCodeSimdReg));
SetA64("0x101110<<1xxxxx011101xxxxxxxxxx", InstName.Uabd_V, null, typeof(OpCodeSimdReg));
SetA64("0x101110<<1xxxxx011100xxxxxxxxxx", InstName.Uabdl_V, null, typeof(OpCodeSimdReg));
SetA64("0x101110<<100000011010xxxxxxxxxx", InstName.Uadalp_V, null, typeof(OpCodeSimd));
SetA64("0x101110<<1xxxxx000000xxxxxxxxxx", InstName.Uaddl_V, null, typeof(OpCodeSimdReg));
SetA64("0x101110<<100000001010xxxxxxxxxx", InstName.Uaddlp_V, null, typeof(OpCodeSimd));
SetA64("001011100x110000001110xxxxxxxxxx", InstName.Uaddlv_V, null, typeof(OpCodeSimd));
SetA64("01101110<<110000001110xxxxxxxxxx", InstName.Uaddlv_V, null, typeof(OpCodeSimd));
SetA64("0x101110<<1xxxxx000100xxxxxxxxxx", InstName.Uaddw_V, null, typeof(OpCodeSimdReg));
SetA64("0x101110<<1xxxxx011111xxxxxxxxxx", InstName.Uaba_V, InstEmit.Uaba_V, typeof(OpCodeSimdReg));
SetA64("0x101110<<1xxxxx010100xxxxxxxxxx", InstName.Uabal_V, InstEmit.Uabal_V, typeof(OpCodeSimdReg));
SetA64("0x101110<<1xxxxx011101xxxxxxxxxx", InstName.Uabd_V, InstEmit.Uabd_V, typeof(OpCodeSimdReg));
SetA64("0x101110<<1xxxxx011100xxxxxxxxxx", InstName.Uabdl_V, InstEmit.Uabdl_V, typeof(OpCodeSimdReg));
SetA64("0x101110<<100000011010xxxxxxxxxx", InstName.Uadalp_V, InstEmit.Uadalp_V, typeof(OpCodeSimd));
SetA64("0x101110<<1xxxxx000000xxxxxxxxxx", InstName.Uaddl_V, InstEmit.Uaddl_V, typeof(OpCodeSimdReg));
SetA64("0x101110<<100000001010xxxxxxxxxx", InstName.Uaddlp_V, InstEmit.Uaddlp_V, typeof(OpCodeSimd));
SetA64("001011100x110000001110xxxxxxxxxx", InstName.Uaddlv_V, InstEmit.Uaddlv_V, typeof(OpCodeSimd));
SetA64("01101110<<110000001110xxxxxxxxxx", InstName.Uaddlv_V, InstEmit.Uaddlv_V, typeof(OpCodeSimd));
SetA64("0x101110<<1xxxxx000100xxxxxxxxxx", InstName.Uaddw_V, InstEmit.Uaddw_V, typeof(OpCodeSimdReg));
SetA64("x00111100x100011000000xxxxxxxxxx", InstName.Ucvtf_Gp, null, typeof(OpCodeSimdCvt));
SetA64(">00111100x000011>xxxxxxxxxxxxxxx", InstName.Ucvtf_Gp_Fixed, null, typeof(OpCodeSimdCvt));
SetA64("011111100x100001110110xxxxxxxxxx", InstName.Ucvtf_S, null, typeof(OpCodeSimd));
SetA64("0>1011100<100001110110xxxxxxxxxx", InstName.Ucvtf_V, null, typeof(OpCodeSimd));
SetA64("0x101110<<1xxxxx000001xxxxxxxxxx", InstName.Uhadd_V, null, typeof(OpCodeSimdReg));
SetA64("0x101110<<1xxxxx001001xxxxxxxxxx", InstName.Uhsub_V, null, typeof(OpCodeSimdReg));
SetA64("0x101110<<1xxxxx011001xxxxxxxxxx", InstName.Umax_V, null, typeof(OpCodeSimdReg));
SetA64("0x101110<<1xxxxx101001xxxxxxxxxx", InstName.Umaxp_V, null, typeof(OpCodeSimdReg));
SetA64("0x101110<<1xxxxx011011xxxxxxxxxx", InstName.Umin_V, null, typeof(OpCodeSimdReg));
SetA64("0x101110<<1xxxxx101011xxxxxxxxxx", InstName.Uminp_V, null, typeof(OpCodeSimdReg));
SetA64("0x101110<<1xxxxx100000xxxxxxxxxx", InstName.Umlal_V, null, typeof(OpCodeSimdReg));
SetA64("0x101111xxxxxxxx0010x0xxxxxxxxxx", InstName.Umlal_Ve, null, typeof(OpCodeSimdRegElem));
SetA64("0x101110<<1xxxxx101000xxxxxxxxxx", InstName.Umlsl_V, null, typeof(OpCodeSimdReg));
SetA64("0x101111xxxxxxxx0110x0xxxxxxxxxx", InstName.Umlsl_Ve, null, typeof(OpCodeSimdRegElem));
SetA64("0x101110<<1xxxxx000001xxxxxxxxxx", InstName.Uhadd_V, InstEmit.Uhadd_V, typeof(OpCodeSimdReg));
SetA64("0x101110<<1xxxxx001001xxxxxxxxxx", InstName.Uhsub_V, InstEmit.Uhsub_V, typeof(OpCodeSimdReg));
SetA64("0x101110<<1xxxxx011001xxxxxxxxxx", InstName.Umax_V, InstEmit.Umax_V, typeof(OpCodeSimdReg));
SetA64("0x101110<<1xxxxx101001xxxxxxxxxx", InstName.Umaxp_V, InstEmit.Umaxp_V, typeof(OpCodeSimdReg));
SetA64("001011100x110000101010xxxxxxxxxx", InstName.Umaxv_V, InstEmit.Umaxv_V, typeof(OpCodeSimd));
SetA64("01101110<<110000101010xxxxxxxxxx", InstName.Umaxv_V, InstEmit.Umaxv_V, typeof(OpCodeSimd));
SetA64("0x101110<<1xxxxx011011xxxxxxxxxx", InstName.Umin_V, InstEmit.Umin_V, typeof(OpCodeSimdReg));
SetA64("0x101110<<1xxxxx101011xxxxxxxxxx", InstName.Uminp_V, InstEmit.Uminp_V, typeof(OpCodeSimdReg));
SetA64("001011100x110001101010xxxxxxxxxx", InstName.Uminv_V, InstEmit.Uminv_V, typeof(OpCodeSimd));
SetA64("01101110<<110001101010xxxxxxxxxx", InstName.Uminv_V, InstEmit.Uminv_V, typeof(OpCodeSimd));
SetA64("0x101110<<1xxxxx100000xxxxxxxxxx", InstName.Umlal_V, InstEmit.Umlal_V, typeof(OpCodeSimdReg));
SetA64("0x101111xxxxxxxx0010x0xxxxxxxxxx", InstName.Umlal_Ve, InstEmit.Umlal_Ve, typeof(OpCodeSimdRegElem));
SetA64("0x101110<<1xxxxx101000xxxxxxxxxx", InstName.Umlsl_V, InstEmit.Umlsl_V, typeof(OpCodeSimdReg));
SetA64("0x101111xxxxxxxx0110x0xxxxxxxxxx", InstName.Umlsl_Ve, InstEmit.Umlsl_Ve, typeof(OpCodeSimdRegElem));
SetA64("0x001110000xxxxx001111xxxxxxxxxx", InstName.Umov_S, null, typeof(OpCodeSimdIns));
SetA64("0x101110<<1xxxxx110000xxxxxxxxxx", InstName.Umull_V, null, typeof(OpCodeSimdReg));
SetA64("0x101111xxxxxxxx1010x0xxxxxxxxxx", InstName.Umull_Ve, null, typeof(OpCodeSimdRegElem));
SetA64("01111110xx1xxxxx000011xxxxxxxxxx", InstName.Uqadd_S, null, typeof(OpCodeSimdReg));
SetA64("0>101110<<1xxxxx000011xxxxxxxxxx", InstName.Uqadd_V, null, typeof(OpCodeSimdReg));
SetA64("0x101110<<1xxxxx110000xxxxxxxxxx", InstName.Umull_V, InstEmit.Umull_V, typeof(OpCodeSimdReg));
SetA64("0x101111xxxxxxxx1010x0xxxxxxxxxx", InstName.Umull_Ve, InstEmit.Umull_Ve, typeof(OpCodeSimdRegElem));
SetA64("01111110xx1xxxxx000011xxxxxxxxxx", InstName.Uqadd_S, InstEmit.Uqadd_S, typeof(OpCodeSimdReg));
SetA64("0>101110<<1xxxxx000011xxxxxxxxxx", InstName.Uqadd_V, InstEmit.Uqadd_V, typeof(OpCodeSimdReg));
SetA64("0>101110<<1xxxxx010111xxxxxxxxxx", InstName.Uqrshl_V, null, typeof(OpCodeSimdReg));
SetA64("0111111100>>>xxx100111xxxxxxxxxx", InstName.Uqrshrn_S, null, typeof(OpCodeSimdShImm));
SetA64("0x10111100>>>xxx100111xxxxxxxxxx", InstName.Uqrshrn_V, null, typeof(OpCodeSimdShImm));
SetA64("0>101110<<1xxxxx010011xxxxxxxxxx", InstName.Uqshl_V, null, typeof(OpCodeSimdReg));
SetA64("0111111100>>>xxx100101xxxxxxxxxx", InstName.Uqshrn_S, null, typeof(OpCodeSimdShImm));
SetA64("0x10111100>>>xxx100101xxxxxxxxxx", InstName.Uqshrn_V, null, typeof(OpCodeSimdShImm));
SetA64("01111110xx1xxxxx001011xxxxxxxxxx", InstName.Uqsub_S, null, typeof(OpCodeSimdReg));
SetA64("0>101110<<1xxxxx001011xxxxxxxxxx", InstName.Uqsub_V, null, typeof(OpCodeSimdReg));
SetA64("01111110<<100001010010xxxxxxxxxx", InstName.Uqxtn_S, null, typeof(OpCodeSimd));
SetA64("0x101110<<100001010010xxxxxxxxxx", InstName.Uqxtn_V, null, typeof(OpCodeSimd));
SetA64("0x101110<<1xxxxx000101xxxxxxxxxx", InstName.Urhadd_V, null, typeof(OpCodeSimdReg));
SetA64("01111110xx1xxxxx001011xxxxxxxxxx", InstName.Uqsub_S, InstEmit.Uqsub_S, typeof(OpCodeSimdReg));
SetA64("0>101110<<1xxxxx001011xxxxxxxxxx", InstName.Uqsub_V, InstEmit.Uqsub_V, typeof(OpCodeSimdReg));
SetA64("01111110<<100001010010xxxxxxxxxx", InstName.Uqxtn_S, InstEmit.Uqxtn_S, typeof(OpCodeSimd));
SetA64("0x101110<<100001010010xxxxxxxxxx", InstName.Uqxtn_V, InstEmit.Uqxtn_V, typeof(OpCodeSimd));
SetA64("0x101110<<1xxxxx000101xxxxxxxxxx", InstName.Urhadd_V, InstEmit.Urhadd_V, typeof(OpCodeSimdReg));
SetA64("0>101110<<1xxxxx010101xxxxxxxxxx", InstName.Urshl_V, null, typeof(OpCodeSimdReg));
SetA64("0111111101xxxxxx001001xxxxxxxxxx", InstName.Urshr_S, null, typeof(OpCodeSimdShImm));
SetA64("0x10111100>>>xxx001001xxxxxxxxxx", InstName.Urshr_V, null, typeof(OpCodeSimdShImm));
@ -558,13 +566,13 @@ namespace ARMeilleure.Decoders
SetA64("0111111101xxxxxx000001xxxxxxxxxx", InstName.Ushr_S, null, typeof(OpCodeSimdShImm));
SetA64("0x10111100>>>xxx000001xxxxxxxxxx", InstName.Ushr_V, null, typeof(OpCodeSimdShImm));
SetA64("0110111101xxxxxx000001xxxxxxxxxx", InstName.Ushr_V, null, typeof(OpCodeSimdShImm));
SetA64("01111110xx100000001110xxxxxxxxxx", InstName.Usqadd_S, null, typeof(OpCodeSimd));
SetA64("0>101110<<100000001110xxxxxxxxxx", InstName.Usqadd_V, null, typeof(OpCodeSimd));
SetA64("01111110xx100000001110xxxxxxxxxx", InstName.Usqadd_S, InstEmit.Usqadd_S, typeof(OpCodeSimd));
SetA64("0>101110<<100000001110xxxxxxxxxx", InstName.Usqadd_V, InstEmit.Usqadd_V, typeof(OpCodeSimd));
SetA64("0111111101xxxxxx000101xxxxxxxxxx", InstName.Usra_S, null, typeof(OpCodeSimdShImm));
SetA64("0x10111100>>>xxx000101xxxxxxxxxx", InstName.Usra_V, null, typeof(OpCodeSimdShImm));
SetA64("0110111101xxxxxx000101xxxxxxxxxx", InstName.Usra_V, null, typeof(OpCodeSimdShImm));
SetA64("0x101110<<1xxxxx001000xxxxxxxxxx", InstName.Usubl_V, null, typeof(OpCodeSimdReg));
SetA64("0x101110<<1xxxxx001100xxxxxxxxxx", InstName.Usubw_V, null, typeof(OpCodeSimdReg));
SetA64("0x101110<<1xxxxx001000xxxxxxxxxx", InstName.Usubl_V, InstEmit.Usubl_V, typeof(OpCodeSimdReg));
SetA64("0x101110<<1xxxxx001100xxxxxxxxxx", InstName.Usubw_V, InstEmit.Usubw_V, typeof(OpCodeSimdReg));
SetA64("0>001110<<0xxxxx000110xxxxxxxxxx", InstName.Uzp1_V, null, typeof(OpCodeSimdReg));
SetA64("0>001110<<0xxxxx010110xxxxxxxxxx", InstName.Uzp2_V, null, typeof(OpCodeSimdReg));
SetA64("0x001110<<100001001010xxxxxxxxxx", InstName.Xtn_V, null, typeof(OpCodeSimd));

View file

@ -3,16 +3,16 @@ using System;
namespace ARMeilleure.Diagnostics
{
class Logger
static class Logger
{
public void StartPass(PassName name)
public static void StartPass(PassName name)
{
#if DEBUG
WriteOutput(name + " pass started...");
#endif
}
public void EndPass(PassName name, ControlFlowGraph cfg)
public static void EndPass(PassName name, ControlFlowGraph cfg)
{
#if DEBUG
EndPass(name);
@ -23,14 +23,14 @@ namespace ARMeilleure.Diagnostics
#endif
}
public void EndPass(PassName name)
public static void EndPass(PassName name)
{
#if DEBUG
WriteOutput(name + " pass ended...");
#endif
}
private void WriteOutput(string text)
private static void WriteOutput(string text)
{
Console.WriteLine(text);
}

View file

@ -3,6 +3,8 @@ namespace ARMeilleure.Diagnostics
enum PassName
{
Translation,
SsaConstruction
SsaConstruction,
PreAllocation,
RegisterAllocation
}
}

View file

@ -0,0 +1,279 @@
// https://www.intel.com/content/dam/doc/white-paper/advanced-encryption-standard-new-instructions-set-paper.pdf
using ARMeilleure.State;
namespace ARMeilleure.Instructions
{
static class CryptoHelper
{
#region "LookUp Tables"
private static readonly byte[] _sBox = new byte[]
{
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
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
};
private static readonly byte[] _invSBox = new byte[]
{
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
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
};
private static readonly byte[] _gfMul02 = new byte[]
{
0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e,
0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e,
0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e,
0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e,
0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe,
0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe,
0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05,
0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25,
0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45,
0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65,
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
};
private static readonly byte[] _gfMul03 = new byte[]
{
0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11,
0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21,
0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71,
0x50, 0x53, 0x56, 0x55, 0x5c, 0x5f, 0x5a, 0x59, 0x48, 0x4b, 0x4e, 0x4d, 0x44, 0x47, 0x42, 0x41,
0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9, 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1,
0xf0, 0xf3, 0xf6, 0xf5, 0xfc, 0xff, 0xfa, 0xf9, 0xe8, 0xeb, 0xee, 0xed, 0xe4, 0xe7, 0xe2, 0xe1,
0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, 0xaa, 0xa9, 0xb8, 0xbb, 0xbe, 0xbd, 0xb4, 0xb7, 0xb2, 0xb1,
0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99, 0x88, 0x8b, 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81,
0x9b, 0x98, 0x9d, 0x9e, 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86, 0x8f, 0x8c, 0x89, 0x8a,
0xab, 0xa8, 0xad, 0xae, 0xa7, 0xa4, 0xa1, 0xa2, 0xb3, 0xb0, 0xb5, 0xb6, 0xbf, 0xbc, 0xb9, 0xba,
0xfb, 0xf8, 0xfd, 0xfe, 0xf7, 0xf4, 0xf1, 0xf2, 0xe3, 0xe0, 0xe5, 0xe6, 0xef, 0xec, 0xe9, 0xea,
0xcb, 0xc8, 0xcd, 0xce, 0xc7, 0xc4, 0xc1, 0xc2, 0xd3, 0xd0, 0xd5, 0xd6, 0xdf, 0xdc, 0xd9, 0xda,
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
};
private static readonly byte[] _gfMul09 = new byte[]
{
0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77,
0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7,
0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c,
0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94, 0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc,
0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49, 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01,
0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91,
0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72, 0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a,
0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2, 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa,
0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b,
0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43, 0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b,
0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8, 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0,
0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30,
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
};
private static readonly byte[] _gfMul0B = new byte[]
{
0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69,
0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9,
0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12,
0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa, 0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2,
0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7, 0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f,
0x46, 0x4d, 0x50, 0x5b, 0x6a, 0x61, 0x7c, 0x77, 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f,
0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc, 0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4,
0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c, 0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54,
0xf7, 0xfc, 0xe1, 0xea, 0xdb, 0xd0, 0xcd, 0xc6, 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e,
0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76, 0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e,
0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd, 0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5,
0x3c, 0x37, 0x2a, 0x21, 0x10, 0x1b, 0x06, 0x0d, 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55,
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
};
private static readonly byte[] _gfMul0D = new byte[]
{
0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b,
0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b,
0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0,
0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48, 0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20,
0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e, 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26,
0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6,
0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5, 0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d,
0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25, 0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d,
0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91,
0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41,
0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42, 0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a,
0xb1, 0xbc, 0xab, 0xa6, 0x85, 0x88, 0x9f, 0x92, 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa,
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
};
private static readonly byte[] _gfMul0E = new byte[]
{
0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a,
0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba,
0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81,
0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11, 0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61,
0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87, 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7,
0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17,
0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c, 0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c,
0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc, 0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc,
0x41, 0x4f, 0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b,
0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b, 0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb,
0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0, 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0,
0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20,
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
};
private static readonly byte[] _srPerm = new byte[]
{
0, 13, 10, 7, 4, 1, 14, 11, 8, 5, 2, 15, 12, 9, 6, 3
};
private static readonly byte[] _isrPerm = new byte[]
{
0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, 1, 6, 11
};
#endregion
public static V128 AesInvMixColumns(V128 op)
{
byte[] inState = op.ToArray();
byte[] outState = new byte[16];
for (int columns = 0; columns <= 3; columns++)
{
int idx = columns << 2;
byte row0 = inState[idx + 0]; // A, E, I, M: [row0, col0-col3]
byte row1 = inState[idx + 1]; // B, F, J, N: [row1, col0-col3]
byte row2 = inState[idx + 2]; // C, G, K, O: [row2, col0-col3]
byte row3 = inState[idx + 3]; // D, H, L, P: [row3, col0-col3]
outState[idx + 0] = (byte)((uint)_gfMul0E[row0] ^ _gfMul0B[row1] ^ _gfMul0D[row2] ^ _gfMul09[row3]);
outState[idx + 1] = (byte)((uint)_gfMul09[row0] ^ _gfMul0E[row1] ^ _gfMul0B[row2] ^ _gfMul0D[row3]);
outState[idx + 2] = (byte)((uint)_gfMul0D[row0] ^ _gfMul09[row1] ^ _gfMul0E[row2] ^ _gfMul0B[row3]);
outState[idx + 3] = (byte)((uint)_gfMul0B[row0] ^ _gfMul0D[row1] ^ _gfMul09[row2] ^ _gfMul0E[row3]);
}
return new V128(outState);
}
public static V128 AesInvShiftRows(V128 op)
{
byte[] inState = op.ToArray();
byte[] outState = new byte[16];
for (int idx = 0; idx <= 15; idx++)
{
outState[_isrPerm[idx]] = inState[idx];
}
return new V128(outState);
}
public static V128 AesInvSubBytes(V128 op)
{
byte[] inState = op.ToArray();
byte[] outState = new byte[16];
for (int idx = 0; idx <= 15; idx++)
{
outState[idx] = _invSBox[inState[idx]];
}
return new V128(outState);
}
public static V128 AesMixColumns(V128 op)
{
byte[] inState = op.ToArray();
byte[] outState = new byte[16];
for (int columns = 0; columns <= 3; columns++)
{
int idx = columns << 2;
byte row0 = inState[idx + 0]; // A, E, I, M: [row0, col0-col3]
byte row1 = inState[idx + 1]; // B, F, J, N: [row1, col0-col3]
byte row2 = inState[idx + 2]; // C, G, K, O: [row2, col0-col3]
byte row3 = inState[idx + 3]; // D, H, L, P: [row3, col0-col3]
outState[idx + 0] = (byte)((uint)_gfMul02[row0] ^ _gfMul03[row1] ^ row2 ^ row3);
outState[idx + 1] = (byte)((uint)row0 ^ _gfMul02[row1] ^ _gfMul03[row2] ^ row3);
outState[idx + 2] = (byte)((uint)row0 ^ row1 ^ _gfMul02[row2] ^ _gfMul03[row3]);
outState[idx + 3] = (byte)((uint)_gfMul03[row0] ^ row1 ^ row2 ^ _gfMul02[row3]);
}
return new V128(outState);
}
public static V128 AesShiftRows(V128 op)
{
byte[] inState = op.ToArray();
byte[] outState = new byte[16];
for (int idx = 0; idx <= 15; idx++)
{
outState[_srPerm[idx]] = inState[idx];
}
return new V128(outState);
}
public static V128 AesSubBytes(V128 op)
{
byte[] inState = op.ToArray();
byte[] outState = new byte[16];
for (int idx = 0; idx <= 15; idx++)
{
outState[idx] = _sBox[inState[idx]];
}
return new V128(outState);
}
}
}

View file

@ -19,7 +19,7 @@ namespace ARMeilleure.Instructions
Operand n = GetAluN(context);
Operand m = GetAluM(context);
Operand d = context.IAdd(n, m);
Operand d = context.Add(n, m);
Operand carry = GetFlag(PState.CFlag);
@ -28,7 +28,7 @@ namespace ARMeilleure.Instructions
carry = context.Copy(Local(OperandType.I64), carry);
}
d = context.IAdd(d, carry);
d = context.Add(d, carry);
if (setFlags)
{
@ -43,7 +43,7 @@ namespace ARMeilleure.Instructions
public static void Add(EmitterContext context)
{
SetAluD(context, context.IAdd(GetAluN(context), GetAluM(context)));
SetAluD(context, context.Add(GetAluN(context), GetAluM(context)));
}
public static void Adds(EmitterContext context)
@ -51,7 +51,7 @@ namespace ARMeilleure.Instructions
Operand n = GetAluN(context);
Operand m = GetAluM(context);
Operand d = context.IAdd(n, m);
Operand d = context.Add(n, m);
EmitNZFlagsCheck(context, d);
@ -119,7 +119,7 @@ namespace ARMeilleure.Instructions
Operand res = context.CountLeadingZeros(context.BitwiseExclusiveOr(nHigh, nLow));
res = context.ISubtract(res, Const(res.Type, 1));
res = context.Subtract(res, Const(res.Type, 1));
SetAluDOrZR(context, res);
}
@ -195,7 +195,7 @@ namespace ARMeilleure.Instructions
Operand n = GetAluN(context);
Operand m = GetAluM(context);
Operand d = context.ISubtract(n, m);
Operand d = context.Subtract(n, m);
Operand borrow = context.BitwiseExclusiveOr(GetFlag(PState.CFlag), Const(1));
@ -204,7 +204,7 @@ namespace ARMeilleure.Instructions
borrow = context.Copy(Local(OperandType.I64), borrow);
}
d = context.ISubtract(d, borrow);
d = context.Subtract(d, borrow);
if (setFlags)
{
@ -219,7 +219,7 @@ namespace ARMeilleure.Instructions
public static void Sub(EmitterContext context)
{
SetAluD(context, context.ISubtract(GetAluN(context), GetAluM(context)));
SetAluD(context, context.Subtract(GetAluN(context), GetAluM(context)));
}
public static void Subs(EmitterContext context)
@ -227,7 +227,7 @@ namespace ARMeilleure.Instructions
Operand n = GetAluN(context);
Operand m = GetAluM(context);
Operand d = context.ISubtract(n, m);
Operand d = context.Subtract(n, m);
EmitNZFlagsCheck(context, d);

View file

@ -38,7 +38,7 @@ namespace ARMeilleure.Instructions
if (isNegated)
{
Operand d = context.IAdd(n, m);
Operand d = context.Add(n, m);
EmitNZFlagsCheck(context, d);
@ -47,7 +47,7 @@ namespace ARMeilleure.Instructions
}
else
{
Operand d = context.ISubtract(n, m);
Operand d = context.Subtract(n, m);
EmitNZFlagsCheck(context, d);

View file

@ -0,0 +1,58 @@
using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation;
using System.Reflection;
using static ARMeilleure.Instructions.InstEmitHelper;
namespace ARMeilleure.Instructions
{
static partial class InstEmit
{
public static void Aesd_V(EmitterContext context)
{
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
Operand d = GetVec(op.Rd);
Operand n = GetVec(op.Rn);
MethodInfo info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Decrypt));
context.Copy(d, context.Call(info, d, n));
}
public static void Aese_V(EmitterContext context)
{
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
Operand d = GetVec(op.Rd);
Operand n = GetVec(op.Rn);
MethodInfo info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.Encrypt));
context.Copy(d, context.Call(info, d, n));
}
public static void Aesimc_V(EmitterContext context)
{
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
Operand n = GetVec(op.Rn);
MethodInfo info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.InverseMixColumns));
context.Copy(GetVec(op.Rd), context.Call(info, n));
}
public static void Aesmc_V(EmitterContext context)
{
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
Operand n = GetVec(op.Rn);
MethodInfo info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.MixColumns));
context.Copy(GetVec(op.Rd), context.Call(info, n));
}
}
}

View file

@ -32,7 +32,7 @@ namespace ARMeilleure.Instructions
if (cselOp == CselOperation.Increment)
{
m = context.IAdd(m, Const(m.Type, 1));
m = context.Add(m, Const(m.Type, 1));
}
else if (cselOp == CselOperation.Invert)
{
@ -40,7 +40,7 @@ namespace ARMeilleure.Instructions
}
else if (cselOp == CselOperation.Negate)
{
m = context.INegate(m);
m = context.Negate(m);
}
Operand condTrue = GetCondTrue(context, op.Cond);

View file

@ -50,8 +50,8 @@ namespace ARMeilleure.Instructions
}
Operand d = unsigned
? context.IDivideUI(n, m)
: context.IDivide (n, m);
? context.DivideUI(n, m)
: context.Divide (n, m);
SetAluDOrZR(context, d);

View file

@ -90,7 +90,7 @@ namespace ARMeilleure.Instructions
Operand address = GetAddress(context);
Operand address2 = context.IAdd(address, Const(1L << op.Size));
Operand address2 = context.Add(address, Const(1L << op.Size));
EmitLoad(op.Rt, address);
EmitLoad(op.Rt2, address2);
@ -117,7 +117,7 @@ namespace ARMeilleure.Instructions
Operand address = GetAddress(context);
Operand address2 = context.IAdd(address, Const(1L << op.Size));
Operand address2 = context.Add(address, Const(1L << op.Size));
Operand t = GetT(context, op.Rt);
Operand t2 = GetT(context, op.Rt2);
@ -141,7 +141,7 @@ namespace ARMeilleure.Instructions
//Pre-indexing.
if (!op.PostIdx)
{
address = context.IAdd(address, Const(op.Immediate));
address = context.Add(address, Const(op.Immediate));
}
break;
@ -158,7 +158,7 @@ namespace ARMeilleure.Instructions
m = context.ShiftLeft(m, Const(op.Size));
}
address = context.IAdd(n, m);
address = context.Add(n, m);
break;
}
@ -174,7 +174,7 @@ namespace ARMeilleure.Instructions
{
if (op.PostIdx)
{
address = context.IAdd(address, Const(op.Immediate));
address = context.Add(address, Const(op.Immediate));
}
context.Copy(GetIntOrSP(op, op.Rn), address);

View file

@ -4,7 +4,6 @@ using ARMeilleure.Translation;
using System;
using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
namespace ARMeilleure.Instructions
{
@ -21,9 +20,9 @@ namespace ARMeilleure.Instructions
Operand n = GetIntOrZR(op, op.Rn);
Operand m = GetIntOrZR(op, op.Rm);
Operand res = context.IMultiply(n, m);
Operand res = context.Multiply(n, m);
res = isAdd ? context.IAdd(a, res) : context.ISubtract(a, res);
res = isAdd ? context.Add(a, res) : context.Subtract(a, res);
SetIntOrZR(context, op.Rd, res);
}
@ -67,9 +66,9 @@ namespace ARMeilleure.Instructions
Operand n = GetExtendedRegister32(op.Rn);
Operand m = GetExtendedRegister32(op.Rm);
Operand res = context.IMultiply(n, m);
Operand res = context.Multiply(n, m);
res = (flags & MullFlags.Add) != 0 ? context.IAdd(a, res) : context.ISubtract(a, res);
res = (flags & MullFlags.Add) != 0 ? context.Add(a, res) : context.Subtract(a, res);
SetIntOrZR(context, op.Rd, res);
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,35 @@
using ARMeilleure.Decoders;
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State;
using ARMeilleure.Translation;
using System;
using System.Reflection;
using static ARMeilleure.Instructions.InstEmitHelper;
using static ARMeilleure.Instructions.InstEmitMemoryHelper;
using static ARMeilleure.Instructions.InstEmitSimdHelper;
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
namespace ARMeilleure.Instructions
{
static partial class InstEmit
{
public static void Fmov_Si(EmitterContext context)
{
OpCodeSimdFmov op = (OpCodeSimdFmov)context.CurrOp;
Operand imm;
if (op.Size != 0)
{
imm = Const(op.Immediate);
}
else
{
imm = Const((int)op.Immediate);
}
context.Copy(GetVec(op.Rd), imm);
}
}
}

View file

@ -314,8 +314,10 @@ namespace ARMeilleure.Instructions
Sli_V,
Smax_V,
Smaxp_V,
Smaxv_V,
Smin_V,
Sminp_V,
Sminv_V,
Smlal_V,
Smlal_Ve,
Smlsl_V,
@ -390,8 +392,10 @@ namespace ARMeilleure.Instructions
Uhsub_V,
Umax_V,
Umaxp_V,
Umaxv_V,
Umin_V,
Uminp_V,
Uminv_V,
Umlal_V,
Umlal_Ve,
Umlsl_V,

View file

@ -39,7 +39,7 @@ namespace ARMeilleure.Instructions
GetContext().OnUndefined(address, opCode);
}
private static ExecutionContext GetContext()
public static ExecutionContext GetContext()
{
return _contexts[Thread.CurrentThread];
}

View file

@ -1,3 +1,4 @@
using ARMeilleure.State;
using System;
namespace ARMeilleure.Instructions
@ -12,7 +13,395 @@ namespace ARMeilleure.Instructions
#endregion
#region "Rounding"
public static double Round(double value)
{
ExecutionContext context = NativeInterface.GetContext();
FPRoundingMode roundMode = context.Fpcr.GetRoundingMode();
if (roundMode == FPRoundingMode.ToNearest)
{
return Math.Round(value); // even
}
else if (roundMode == FPRoundingMode.TowardsPlusInfinity)
{
return Math.Ceiling(value);
}
else if (roundMode == FPRoundingMode.TowardsMinusInfinity)
{
return Math.Floor(value);
}
else /* if (roundMode == FPRoundingMode.TowardsZero) */
{
return Math.Truncate(value);
}
}
public static float RoundF(float value)
{
ExecutionContext context = NativeInterface.GetContext();
FPRoundingMode roundMode = context.Fpcr.GetRoundingMode();
if (roundMode == FPRoundingMode.ToNearest)
{
return MathF.Round(value); // even
}
else if (roundMode == FPRoundingMode.TowardsPlusInfinity)
{
return MathF.Ceiling(value);
}
else if (roundMode == FPRoundingMode.TowardsMinusInfinity)
{
return MathF.Floor(value);
}
else /* if (roundMode == FPRoundingMode.TowardsZero) */
{
return MathF.Truncate(value);
}
}
#endregion
#region "Saturating"
public static long SignedSrcSignedDstSatQ(long op, int size)
{
ExecutionContext context = NativeInterface.GetContext();
int eSize = 8 << size;
long tMaxValue = (1L << (eSize - 1)) - 1L;
long tMinValue = -(1L << (eSize - 1));
if (op > tMaxValue)
{
context.Fpsr |= FPSR.Qc;
return tMaxValue;
}
else if (op < tMinValue)
{
context.Fpsr |= FPSR.Qc;
return tMinValue;
}
else
{
return op;
}
}
public static ulong SignedSrcUnsignedDstSatQ(long op, int size)
{
ExecutionContext context = NativeInterface.GetContext();
int eSize = 8 << size;
ulong tMaxValue = (1UL << eSize) - 1UL;
ulong tMinValue = 0UL;
if (op > (long)tMaxValue)
{
context.Fpsr |= FPSR.Qc;
return tMaxValue;
}
else if (op < (long)tMinValue)
{
context.Fpsr |= FPSR.Qc;
return tMinValue;
}
else
{
return (ulong)op;
}
}
public static long UnsignedSrcSignedDstSatQ(ulong op, int size)
{
ExecutionContext context = NativeInterface.GetContext();
int eSize = 8 << size;
long tMaxValue = (1L << (eSize - 1)) - 1L;
if (op > (ulong)tMaxValue)
{
context.Fpsr |= FPSR.Qc;
return tMaxValue;
}
else
{
return (long)op;
}
}
public static ulong UnsignedSrcUnsignedDstSatQ(ulong op, int size)
{
ExecutionContext context = NativeInterface.GetContext();
int eSize = 8 << size;
ulong tMaxValue = (1UL << eSize) - 1UL;
if (op > tMaxValue)
{
context.Fpsr |= FPSR.Qc;
return tMaxValue;
}
else
{
return op;
}
}
public static long UnarySignedSatQAbsOrNeg(long op)
{
ExecutionContext context = NativeInterface.GetContext();
if (op == long.MinValue)
{
context.Fpsr |= FPSR.Qc;
return long.MaxValue;
}
else
{
return op;
}
}
public static long BinarySignedSatQAdd(long op1, long op2)
{
ExecutionContext context = NativeInterface.GetContext();
long add = op1 + op2;
if ((~(op1 ^ op2) & (op1 ^ add)) < 0L)
{
context.Fpsr |= FPSR.Qc;
if (op1 < 0L)
{
return long.MinValue;
}
else
{
return long.MaxValue;
}
}
else
{
return add;
}
}
public static ulong BinaryUnsignedSatQAdd(ulong op1, ulong op2)
{
ExecutionContext context = NativeInterface.GetContext();
ulong add = op1 + op2;
if ((add < op1) && (add < op2))
{
context.Fpsr |= FPSR.Qc;
return ulong.MaxValue;
}
else
{
return add;
}
}
public static long BinarySignedSatQSub(long op1, long op2)
{
ExecutionContext context = NativeInterface.GetContext();
long sub = op1 - op2;
if (((op1 ^ op2) & (op1 ^ sub)) < 0L)
{
context.Fpsr |= FPSR.Qc;
if (op1 < 0L)
{
return long.MinValue;
}
else
{
return long.MaxValue;
}
}
else
{
return sub;
}
}
public static ulong BinaryUnsignedSatQSub(ulong op1, ulong op2)
{
ExecutionContext context = NativeInterface.GetContext();
ulong sub = op1 - op2;
if (op1 < op2)
{
context.Fpsr |= FPSR.Qc;
return ulong.MinValue;
}
else
{
return sub;
}
}
public static long BinarySignedSatQAcc(ulong op1, long op2)
{
ExecutionContext context = NativeInterface.GetContext();
if (op1 <= (ulong)long.MaxValue)
{
// op1 from ulong.MinValue to (ulong)long.MaxValue
// op2 from long.MinValue to long.MaxValue
long add = (long)op1 + op2;
if ((~op2 & add) < 0L)
{
context.Fpsr |= FPSR.Qc;
return long.MaxValue;
}
else
{
return add;
}
}
else if (op2 >= 0L)
{
// op1 from (ulong)long.MaxValue + 1UL to ulong.MaxValue
// op2 from (long)ulong.MinValue to long.MaxValue
context.Fpsr |= FPSR.Qc;
return long.MaxValue;
}
else
{
// op1 from (ulong)long.MaxValue + 1UL to ulong.MaxValue
// op2 from long.MinValue to (long)ulong.MinValue - 1L
ulong add = op1 + (ulong)op2;
if (add > (ulong)long.MaxValue)
{
context.Fpsr |= FPSR.Qc;
return long.MaxValue;
}
else
{
return (long)add;
}
}
}
public static ulong BinaryUnsignedSatQAcc(long op1, ulong op2)
{
ExecutionContext context = NativeInterface.GetContext();
if (op1 >= 0L)
{
// op1 from (long)ulong.MinValue to long.MaxValue
// op2 from ulong.MinValue to ulong.MaxValue
ulong add = (ulong)op1 + op2;
if ((add < (ulong)op1) && (add < op2))
{
context.Fpsr |= FPSR.Qc;
return ulong.MaxValue;
}
else
{
return add;
}
}
else if (op2 > (ulong)long.MaxValue)
{
// op1 from long.MinValue to (long)ulong.MinValue - 1L
// op2 from (ulong)long.MaxValue + 1UL to ulong.MaxValue
return (ulong)op1 + op2;
}
else
{
// op1 from long.MinValue to (long)ulong.MinValue - 1L
// op2 from ulong.MinValue to (ulong)long.MaxValue
long add = op1 + (long)op2;
if (add < (long)ulong.MinValue)
{
context.Fpsr |= FPSR.Qc;
return ulong.MinValue;
}
else
{
return (ulong)add;
}
}
}
#endregion
#region "Count"
public static ulong CountLeadingSigns(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
{
value ^= value >> 1;
int highBit = size - 2;
for (int bit = highBit; bit >= 0; bit--)
{
if (((int)(value >> bit) & 0b1) != 0)
{
return (ulong)(highBit - bit);
}
}
return (ulong)(size - 1);
}
private static readonly byte[] ClzNibbleTbl = { 4, 3, 2, 2, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 };
public static ulong CountLeadingZeros(ulong value, int size) // size is 8, 16, 32 or 64 (SIMD&FP or Base Inst.).
{
if (value == 0ul)
{
return (ulong)size;
}
int nibbleIdx = size;
int preCount, count = 0;
do
{
nibbleIdx -= 4;
preCount = ClzNibbleTbl[(int)(value >> nibbleIdx) & 0b1111];
count += preCount;
}
while (preCount == 4);
return (ulong)count;
}
public static ulong CountSetBits8(ulong value) // "size" is 8 (SIMD&FP Inst.).
{
value = ((value >> 1) & 0x55ul) + (value & 0x55ul);
@ -26,15 +415,15 @@ namespace ARMeilleure.Instructions
private const uint Crc32RevPoly = 0xedb88320;
private const uint Crc32cRevPoly = 0x82f63b78;
public static uint Crc32b(uint crc, byte val) => Crc32 (crc, Crc32RevPoly, val);
public static uint Crc32h(uint crc, ushort val) => Crc32h(crc, Crc32RevPoly, val);
public static uint Crc32w(uint crc, uint val) => Crc32w(crc, Crc32RevPoly, val);
public static uint Crc32x(uint crc, ulong val) => Crc32x(crc, Crc32RevPoly, val);
public static uint Crc32b(uint crc, byte value) => Crc32 (crc, Crc32RevPoly, value);
public static uint Crc32h(uint crc, ushort value) => Crc32h(crc, Crc32RevPoly, value);
public static uint Crc32w(uint crc, uint value) => Crc32w(crc, Crc32RevPoly, value);
public static uint Crc32x(uint crc, ulong value) => Crc32x(crc, Crc32RevPoly, value);
public static uint Crc32cb(uint crc, byte val) => Crc32 (crc, Crc32cRevPoly, val);
public static uint Crc32ch(uint crc, ushort val) => Crc32h(crc, Crc32cRevPoly, val);
public static uint Crc32cw(uint crc, uint val) => Crc32w(crc, Crc32cRevPoly, val);
public static uint Crc32cx(uint crc, ulong val) => Crc32x(crc, Crc32cRevPoly, val);
public static uint Crc32cb(uint crc, byte value) => Crc32 (crc, Crc32cRevPoly, value);
public static uint Crc32ch(uint crc, ushort value) => Crc32h(crc, Crc32cRevPoly, value);
public static uint Crc32cw(uint crc, uint value) => Crc32w(crc, Crc32cRevPoly, value);
public static uint Crc32cx(uint crc, ulong value) => Crc32x(crc, Crc32cRevPoly, value);
private static uint Crc32h(uint crc, uint poly, ushort val)
{
@ -84,7 +473,25 @@ namespace ARMeilleure.Instructions
#endregion
#region "Aes"
public static V128 Decrypt(V128 value, V128 roundKey)
{
return CryptoHelper.AesInvSubBytes(CryptoHelper.AesInvShiftRows(value ^ roundKey));
}
public static V128 Encrypt(V128 value, V128 roundKey)
{
return CryptoHelper.AesSubBytes(CryptoHelper.AesShiftRows(value ^ roundKey));
}
public static V128 InverseMixColumns(V128 value)
{
return CryptoHelper.AesInvMixColumns(value);
}
public static V128 MixColumns(V128 value)
{
return CryptoHelper.AesMixColumns(value);
}
#endregion
#region "Sha1"

File diff suppressed because it is too large Load diff

View file

@ -54,6 +54,120 @@ namespace ARMeilleure.IntermediateRepresentation
Store8,
StoreToContext,
Subtract,
VectorExtract,
VectorExtract16,
VectorExtract8,
VectorInsert,
VectorInsert16,
VectorInsert8,
VectorZero,
VectorZeroUpper64,
VectorZeroUpper96,
//Intrinsics
X86Intrinsic_Start,
X86Addpd,
X86Addps,
X86Addsd,
X86Addss,
X86Andnpd,
X86Andnps,
X86Divpd,
X86Divps,
X86Divsd,
X86Divss,
X86Haddpd,
X86Haddps,
X86Maxpd,
X86Maxps,
X86Maxsd,
X86Maxss,
X86Minpd,
X86Minps,
X86Minsd,
X86Minss,
X86Movhlps,
X86Movlhps,
X86Mulpd,
X86Mulps,
X86Mulsd,
X86Mulss,
X86Paddb,
X86Paddd,
X86Paddq,
X86Paddw,
X86Pand,
X86Pandn,
X86Pavgb,
X86Pavgw,
X86Pblendvb,
X86Pcmpeqb,
X86Pcmpeqd,
X86Pcmpeqq,
X86Pcmpeqw,
X86Pcmpgtb,
X86Pcmpgtd,
X86Pcmpgtq,
X86Pcmpgtw,
X86Pmaxsb,
X86Pmaxsd,
X86Pmaxsw,
X86Pmaxub,
X86Pmaxud,
X86Pmaxuw,
X86Pminsb,
X86Pminsd,
X86Pminsw,
X86Pminub,
X86Pminud,
X86Pminuw,
X86Pmovsxbw,
X86Pmovsxdq,
X86Pmovsxwd,
X86Pmovzxbw,
X86Pmovzxdq,
X86Pmovzxwd,
X86Pmulld,
X86Pmullw,
X86Popcnt,
X86Por,
X86Psllw,
X86Psrad,
X86Psraw,
X86Psrld,
X86Psrlq,
X86Psrldq,
X86Psrlw,
X86Psubb,
X86Psubd,
X86Psubq,
X86Psubw,
X86Pxor,
X86Rcpps,
X86Rcpss,
X86Roundpd,
X86Roundps,
X86Roundsd,
X86Roundss,
X86Rsqrtps,
X86Rsqrtss,
X86Shufpd,
X86Shufps,
X86Sqrtpd,
X86Sqrtps,
X86Sqrtsd,
X86Sqrtss,
X86Subpd,
X86Subps,
X86Subsd,
X86Subss,
X86Unpckhpd,
X86Unpckhps,
X86Unpcklpd,
X86Unpcklps,
X86Xorpd,
X86Xorps,
X86Intrinsic_End,
Count
}

View file

@ -35,6 +35,11 @@ namespace ARMeilleure.IntermediateRepresentation
return new Operand(BitConverter.SingleToInt32Bits(value));
}
public static Operand ConstF(double value)
{
return new Operand(BitConverter.DoubleToInt64Bits(value));
}
public static Operand Label()
{
return new Operand(OperandKind.Label);

View file

@ -1,3 +1,5 @@
using System;
namespace ARMeilleure.IntermediateRepresentation
{
enum OperandType
@ -17,5 +19,19 @@ namespace ARMeilleure.IntermediateRepresentation
return type == OperandType.I32 ||
type == OperandType.I64;
}
public static RegisterType ToRegisterType(this OperandType type)
{
switch (type)
{
case OperandType.FP32: return RegisterType.Vector;
case OperandType.FP64: return RegisterType.Vector;
case OperandType.I32: return RegisterType.Integer;
case OperandType.I64: return RegisterType.Integer;
case OperandType.V128: return RegisterType.Vector;
}
throw new InvalidOperationException($"Invalid operand type \"{type}\".");
}
}
}

View file

@ -1,6 +1,6 @@
using System;
namespace ARMeilleure.State
namespace ARMeilleure.IntermediateRepresentation
{
struct Register : IEquatable<Register>
{

View file

@ -1,4 +1,4 @@
namespace ARMeilleure.State
namespace ARMeilleure.IntermediateRepresentation
{
enum RegisterType
{

View file

@ -4,13 +4,22 @@ namespace ARMeilleure
{
public static bool AssumeStrictAbiCompliance { get; set; }
public static bool FastFP { get; set; } = true;
public static bool FastFP { get; set; } = false;
public static bool UseSseIfAvailable { get; set; }
public static bool UseSse2IfAvailable { get; set; }
public static bool UseSse3IfAvailable { get; set; }
public static bool UseSsse3IfAvailable { get; set; }
public static bool UseSseIfAvailable { get; set; }
public static bool UseSse2IfAvailable { get; set; }
public static bool UseSse3IfAvailable { get; set; }
public static bool UseSsse3IfAvailable { get; set; }
public static bool UseSse41IfAvailable { get; set; }
public static bool UseSse42IfAvailable { get; set; }
public static bool UseSse42IfAvailable { get; set; }
public static bool UsePopCntIfAvailable { get; set; }
internal static bool UseSse { get; set; } = true;
internal static bool UseSse2 { get; set; } = true;
internal static bool UseSse3 { get; set; } = true;
internal static bool UseSsse3 { get; set; } = true;
internal static bool UseSse41 { get; set; } = true;
internal static bool UseSse42 { get; set; }
internal static bool UsePopCnt { get; set; }
}
}

View file

@ -8,6 +8,9 @@ namespace ARMeilleure.State
internal IntPtr NativeContextPtr => _nativeContext.BasePtr;
public FPCR Fpcr { get; set; }
public FPSR Fpsr { get; set; }
public event EventHandler<InstExceptionEventArgs> Break;
public event EventHandler<InstExceptionEventArgs> SupervisorCall;
public event EventHandler<InstUndefinedEventArgs> Undefined;

23
ARMeilleure/State/FPCR.cs Normal file
View file

@ -0,0 +1,23 @@
using System;
namespace ARMeilleure.State
{
[Flags]
public enum FPCR
{
Ufe = 1 << 11,
Fz = 1 << 24,
Dn = 1 << 25,
Ahp = 1 << 26
}
public static class FPCRExtensions
{
private const int RModeShift = 22;
public static FPRoundingMode GetRoundingMode(this FPCR fpcr)
{
return (FPRoundingMode)(((int)fpcr >> RModeShift) & 3);
}
}
}

View file

@ -0,0 +1,12 @@
namespace ARMeilleure.State
{
enum FPException
{
InvalidOp = 0,
DivideByZero = 1,
Overflow = 2,
Underflow = 3,
Inexact = 4,
InputDenorm = 7
}
}

View file

@ -0,0 +1,10 @@
namespace ARMeilleure.State
{
public enum FPRoundingMode
{
ToNearest = 0,
TowardsPlusInfinity = 1,
TowardsMinusInfinity = 2,
TowardsZero = 3
}
}

11
ARMeilleure/State/FPSR.cs Normal file
View file

@ -0,0 +1,11 @@
using System;
namespace ARMeilleure.State
{
[Flags]
public enum FPSR
{
Ufc = 1 << 3,
Qc = 1 << 27
}
}

View file

@ -0,0 +1,11 @@
namespace ARMeilleure.State
{
enum FPType
{
Nonzero,
Zero,
Infinity,
QNaN,
SNaN
}
}

View file

@ -1,3 +1,4 @@
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Memory;
using System;
using System.Runtime.InteropServices;

View file

@ -7,19 +7,45 @@ namespace ARMeilleure.State
private ulong _e0;
private ulong _e1;
public V128(float value)
public V128(float value) : this(value, value, value, value) { }
public V128(double value) : this(value, value) { }
public V128(float e0, float e1, float e2, float e3)
{
_e0 = (uint)BitConverter.SingleToInt32Bits(value);
_e1 = 0;
_e0 = (ulong)(uint)BitConverter.SingleToInt32Bits(e0) << 0;
_e0 |= (ulong)(uint)BitConverter.SingleToInt32Bits(e1) << 32;
_e1 = (ulong)(uint)BitConverter.SingleToInt32Bits(e2) << 0;
_e1 |= (ulong)(uint)BitConverter.SingleToInt32Bits(e3) << 32;
}
public V128(double value)
public V128(double e0, double e1)
{
_e0 = (ulong)BitConverter.DoubleToInt64Bits(value);
_e1 = 0;
_e0 = (ulong)BitConverter.DoubleToInt64Bits(e0);
_e1 = (ulong)BitConverter.DoubleToInt64Bits(e1);
}
public V128(long e0, long e1) : this((ulong)e0, (ulong)e1) { }
public V128(int e0, int e1, int e2, int e3)
{
_e0 = (ulong)(uint)e0 << 0;
_e0 |= (ulong)(uint)e1 << 32;
_e1 = (ulong)(uint)e2 << 0;
_e1 |= (ulong)(uint)e3 << 32;
}
public V128(uint e0, uint e1, uint e2, uint e3)
{
_e0 = (ulong)e0 << 0;
_e0 |= (ulong)e1 << 32;
_e1 = (ulong)e2 << 0;
_e1 |= (ulong)e3 << 32;
}
public V128(long e0, long e1)
{
_e0 = (ulong)e0;
_e1 = (ulong)e1;
}
public V128(ulong e0, ulong e1)
{
@ -27,6 +53,12 @@ namespace ARMeilleure.State
_e1 = e1;
}
public V128(byte[] data)
{
_e0 = (ulong)BitConverter.ToInt64(data, 0);
_e1 = (ulong)BitConverter.ToInt64(data, 8);
}
public float AsFloat()
{
return GetFloat(0);
@ -47,7 +79,8 @@ namespace ARMeilleure.State
return BitConverter.Int64BitsToDouble(GetInt64(index));
}
public int GetInt32(int index) => (int)GetUInt32(index);
public int GetInt32(int index) => (int)GetUInt32(index);
public long GetInt64(int index) => (long)GetUInt64(index);
public uint GetUInt32(int index)
{
@ -56,11 +89,9 @@ namespace ARMeilleure.State
throw new ArgumentOutOfRangeException(nameof(index));
}
return (uint)((((index & 2) != 0) ? _e1 : _e0) >> (index & 1));
return (uint)(GetUInt64(index >> 1) >> (index & 1));
}
public long GetInt64(int index) => (long)GetUInt64(index);
public ulong GetUInt64(int index)
{
switch (index)
@ -72,11 +103,44 @@ namespace ARMeilleure.State
throw new ArgumentOutOfRangeException(nameof(index));
}
public byte[] ToArray()
{
byte[] e0Data = BitConverter.GetBytes(_e0);
byte[] e1Data = BitConverter.GetBytes(_e1);
byte[] data = new byte[16];
Buffer.BlockCopy(e0Data, 0, data, 0, 8);
Buffer.BlockCopy(e1Data, 0, data, 8, 8);
return data;
}
public override int GetHashCode()
{
return HashCode.Combine(_e0, _e1);
}
public static V128 operator ~(V128 x)
{
return new V128(~x._e0, ~x._e1);
}
public static V128 operator &(V128 x, V128 y)
{
return new V128(x._e0 & y._e0, x._e1 & y._e1);
}
public static V128 operator |(V128 x, V128 y)
{
return new V128(x._e0 | y._e0, x._e1 | y._e1);
}
public static V128 operator ^(V128 x, V128 y)
{
return new V128(x._e0 ^ y._e0, x._e1 ^ y._e1);
}
public static bool operator ==(V128 x, V128 y)
{
return x.Equals(y);
@ -96,5 +160,10 @@ namespace ARMeilleure.State
{
return other._e0 == _e0 && other._e1 == _e1;
}
public override string ToString()
{
return $"0x{_e1:X16}{_e0:X16}";
}
}
}

View file

@ -37,6 +37,11 @@ namespace ARMeilleure.Translation
_needsNewBlock = true;
}
public Operand Add(Operand a, Operand b)
{
return Add(Instruction.Add, Local(a.Type), a, b);
}
public Operand BitwiseAnd(Operand a, Operand b)
{
return Add(Instruction.BitwiseAnd, Local(a.Type), a, b);
@ -158,9 +163,14 @@ namespace ARMeilleure.Translation
return Add(Instruction.CountLeadingZeros, Local(a.Type), a);
}
public Operand IAdd(Operand a, Operand b)
public Operand Divide(Operand a, Operand b)
{
return Add(Instruction.Add, Local(a.Type), a, b);
return Add(Instruction.Divide, Local(a.Type), a, b);
}
public Operand DivideUI(Operand a, Operand b)
{
return Add(Instruction.DivideUI, Local(a.Type), a, b);
}
public Operand ICompareEqual(Operand a, Operand b)
@ -213,31 +223,6 @@ namespace ARMeilleure.Translation
return Add(Instruction.CompareNotEqual, Local(OperandType.I32), a, b);
}
public Operand IDivide(Operand a, Operand b)
{
return Add(Instruction.Divide, Local(a.Type), a, b);
}
public Operand IDivideUI(Operand a, Operand b)
{
return Add(Instruction.DivideUI, Local(a.Type), a, b);
}
public Operand IMultiply(Operand a, Operand b)
{
return Add(Instruction.Multiply, Local(a.Type), a, b);
}
public Operand INegate(Operand a)
{
return Add(Instruction.Negate, Local(a.Type), a);
}
public Operand ISubtract(Operand a, Operand b)
{
return Add(Instruction.Subtract, Local(a.Type), a, b);
}
public Operand Load(Operand value, Operand address)
{
return Add(Instruction.Load, value, address);
@ -268,6 +253,11 @@ namespace ARMeilleure.Translation
return Add(Instruction.LoadZx8, value, address);
}
public Operand Multiply(Operand a, Operand b)
{
return Add(Instruction.Multiply, Local(a.Type), a, b);
}
public Operand Multiply64HighSI(Operand a, Operand b)
{
return Add(Instruction.Multiply64HighSI, Local(OperandType.I64), a, b);
@ -278,6 +268,11 @@ namespace ARMeilleure.Translation
return Add(Instruction.Multiply64HighUI, Local(OperandType.I64), a, b);
}
public Operand Negate(Operand a)
{
return Add(Instruction.Negate, Local(a.Type), a);
}
public Operand Return()
{
return Add(Instruction.Return);
@ -338,6 +333,61 @@ namespace ARMeilleure.Translation
Add(Instruction.Store8, null, address, value);
}
public Operand Subtract(Operand a, Operand b)
{
return Add(Instruction.Subtract, Local(a.Type), a, b);
}
public Operand VectorExtract(Operand vector, Operand value, int index)
{
return Add(Instruction.VectorExtract, value, vector, Const(index));
}
public Operand VectorExtract16(Operand vector, Operand value, int index)
{
return Add(Instruction.VectorExtract16, value, vector, Const(index));
}
public Operand VectorExtract8(Operand vector, Operand value, int index)
{
return Add(Instruction.VectorExtract8, value, vector, Const(index));
}
public Operand VectorInsert(Operand vector, Operand value, int index)
{
return Add(Instruction.VectorInsert, Local(OperandType.V128), vector, value, Const(index));
}
public Operand VectorInsert16(Operand vector, Operand value, int index)
{
return Add(Instruction.VectorInsert16, Local(OperandType.V128), vector, value, Const(index));
}
public Operand VectorInsert8(Operand vector, Operand value, int index)
{
return Add(Instruction.VectorInsert8, Local(OperandType.V128), vector, value, Const(index));
}
public Operand VectorZero()
{
return Add(Instruction.VectorZero, Local(OperandType.V128));
}
public Operand VectorZeroUpper64(Operand vector)
{
return Add(Instruction.VectorZeroUpper64, Local(OperandType.V128), vector);
}
public Operand VectorZeroUpper96(Operand vector)
{
return Add(Instruction.VectorZeroUpper96, Local(OperandType.V128), vector);
}
public Operand AddIntrinsic(Instruction inst, params Operand[] args)
{
return Add(inst, Local(OperandType.V128), args);
}
private Operand Add(Instruction inst, Operand dest = null, params Operand[] sources)
{
if (_needsNewBlock)

View file

@ -41,8 +41,6 @@ namespace ARMeilleure.Translation
private TranslatedFunction Translate(ulong address, ExecutionMode mode)
{
Logger logger = new Logger();
EmitterContext context = new EmitterContext();
Block[] blocks = Decoder.DecodeFunction(_memory, address, ExecutionMode.Aarch64);
@ -55,11 +53,11 @@ namespace ARMeilleure.Translation
Dominance.FindDominanceFrontiers(cfg);
logger.StartPass(PassName.SsaConstruction);
Logger.StartPass(PassName.SsaConstruction);
Ssa.Rename(cfg);
logger.EndPass(PassName.SsaConstruction, cfg);
Logger.EndPass(PassName.SsaConstruction, cfg);
byte[] code = CodeGenerator.Generate(cfg, _memory);

View file

@ -7,6 +7,46 @@ namespace Ryujinx.Tests.Unicorn
private ulong _e0;
private ulong _e1;
public SimdValue(float value) : this(value, value, value, value) { }
public SimdValue(double value) : this(value, value) { }
public SimdValue(float e0, float e1, float e2, float e3)
{
_e0 = (ulong)(uint)BitConverter.SingleToInt32Bits(e0) << 0;
_e0 |= (ulong)(uint)BitConverter.SingleToInt32Bits(e1) << 32;
_e1 = (ulong)(uint)BitConverter.SingleToInt32Bits(e2) << 0;
_e1 |= (ulong)(uint)BitConverter.SingleToInt32Bits(e3) << 32;
}
public SimdValue(double e0, double e1)
{
_e0 = (ulong)BitConverter.DoubleToInt64Bits(e0);
_e1 = (ulong)BitConverter.DoubleToInt64Bits(e1);
}
public SimdValue(int e0, int e1, int e2, int e3)
{
_e0 = (ulong)(uint)e0 << 0;
_e0 |= (ulong)(uint)e1 << 32;
_e1 = (ulong)(uint)e2 << 0;
_e1 |= (ulong)(uint)e3 << 32;
}
public SimdValue(uint e0, uint e1, uint e2, uint e3)
{
_e0 = (ulong)e0 << 0;
_e0 |= (ulong)e1 << 32;
_e1 = (ulong)e2 << 0;
_e1 |= (ulong)e3 << 32;
}
public SimdValue(long e0, long e1)
{
_e0 = (ulong)e0;
_e1 = (ulong)e1;
}
public SimdValue(ulong e0, ulong e1)
{
_e0 = e0;
@ -19,19 +59,6 @@ namespace Ryujinx.Tests.Unicorn
_e1 = (ulong)BitConverter.ToInt64(data, 8);
}
public byte[] ToArray()
{
byte[] e0Data = BitConverter.GetBytes(_e0);
byte[] e1Data = BitConverter.GetBytes(_e1);
byte[] data = new byte[16];
Buffer.BlockCopy(e0Data, 0, data, 0, 8);
Buffer.BlockCopy(e1Data, 0, data, 8, 8);
return data;
}
public float AsFloat()
{
return GetFloat(0);
@ -52,7 +79,8 @@ namespace Ryujinx.Tests.Unicorn
return BitConverter.Int64BitsToDouble(GetInt64(index));
}
public int GetInt32(int index) => (int)GetUInt32(index);
public int GetInt32(int index) => (int)GetUInt32(index);
public long GetInt64(int index) => (long)GetUInt64(index);
public uint GetUInt32(int index)
{
@ -61,11 +89,9 @@ namespace Ryujinx.Tests.Unicorn
throw new ArgumentOutOfRangeException(nameof(index));
}
return (uint)((((index & 2) != 0) ? _e1 : _e0) >> (index & 1));
return (uint)(GetUInt64(index >> 1) >> (index & 1));
}
public long GetInt64(int index) => (long)GetUInt64(index);
public ulong GetUInt64(int index)
{
switch (index)
@ -77,6 +103,19 @@ namespace Ryujinx.Tests.Unicorn
throw new ArgumentOutOfRangeException(nameof(index));
}
public byte[] ToArray()
{
byte[] e0Data = BitConverter.GetBytes(_e0);
byte[] e1Data = BitConverter.GetBytes(_e1);
byte[] data = new byte[16];
Buffer.BlockCopy(e0Data, 0, data, 0, 8);
Buffer.BlockCopy(e1Data, 0, data, 8, 8);
return data;
}
public override int GetHashCode()
{
return HashCode.Combine(_e0, _e1);
@ -94,12 +133,17 @@ namespace Ryujinx.Tests.Unicorn
public override bool Equals(object obj)
{
return obj is SimdValue simdValue && Equals(simdValue);
return obj is SimdValue vector && Equals(vector);
}
public bool Equals(SimdValue other)
{
return other._e0 == _e0 && other._e1 == _e1;
}
public override string ToString()
{
return $"0x{_e1:X16}{_e0:X16}";
}
}
}

View file

@ -135,8 +135,8 @@ namespace Ryujinx.Tests.Cpu
_context.SetPstateFlag(PState.ZFlag, zero);
_context.SetPstateFlag(PState.NFlag, negative);
//_thread.ThreadState.Fpcr = fpcr;
//_thread.ThreadState.Fpsr = fpsr;
_context.Fpcr = (FPCR)fpcr;
_context.Fpsr = (FPSR)fpsr;
if (_unicornAvailable)
{
@ -361,8 +361,8 @@ namespace Ryujinx.Tests.Cpu
Assert.That(V128ToSimdValue(_context.GetV(30)), Is.EqualTo(_unicornEmu.Q[30]));
Assert.That(V128ToSimdValue(_context.GetV(31)), Is.EqualTo(_unicornEmu.Q[31]));
//Assert.That(_thread.ThreadState.Fpcr, Is.EqualTo(_unicornEmu.Fpcr));
//Assert.That(_thread.ThreadState.Fpsr & (int)fpsrMask, Is.EqualTo(_unicornEmu.Fpsr & (int)fpsrMask));
Assert.That((int)_context.Fpcr, Is.EqualTo(_unicornEmu.Fpcr));
Assert.That((int)_context.Fpsr & (int)fpsrMask, Is.EqualTo(_unicornEmu.Fpsr & (int)fpsrMask));
Assert.That(_context.GetPstateFlag(PState.VFlag), Is.EqualTo(_unicornEmu.OverflowFlag));
Assert.That(_context.GetPstateFlag(PState.CFlag), Is.EqualTo(_unicornEmu.CarryFlag));

View file

@ -190,7 +190,7 @@ namespace Ryujinx.Tests.Cpu
Opcode(0xD65F03C0);
ExecuteOpcodes();
Assert.That(GetVectorE0(GetContext().GetV(0)), Is.EqualTo(16f));
Assert.That(GetContext().GetV(0).AsFloat(), Is.EqualTo(16f));
}
[Explicit]