Start adding support for SIMD & FP types, along with some of the related ARM instructions
This commit is contained in:
parent
1d3e1d929e
commit
f056709136
52 changed files with 10972 additions and 466 deletions
|
@ -2,13 +2,19 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
{
|
{
|
||||||
struct AllocationResult
|
struct AllocationResult
|
||||||
{
|
{
|
||||||
public int UsedRegisters { get; }
|
public int IntUsedRegisters { get; }
|
||||||
|
public int VecUsedRegisters { get; }
|
||||||
public int SpillRegionSize { get; }
|
public int SpillRegionSize { get; }
|
||||||
public int MaxCallArgs { 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;
|
IntUsedRegisters = intUsedRegisters;
|
||||||
|
VecUsedRegisters = vecUsedRegisters;
|
||||||
SpillRegionSize = spillRegionSize;
|
SpillRegionSize = spillRegionSize;
|
||||||
MaxCallArgs = maxCallArgs;
|
MaxCallArgs = maxCallArgs;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
using ARMeilleure.CodeGen.X86;
|
using ARMeilleure.CodeGen.X86;
|
||||||
using ARMeilleure.Common;
|
using ARMeilleure.Common;
|
||||||
using ARMeilleure.IntermediateRepresentation;
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
using ARMeilleure.State;
|
|
||||||
using ARMeilleure.Translation;
|
using ARMeilleure.Translation;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
@ -40,7 +39,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
public BitMap Active { get; }
|
public BitMap Active { get; }
|
||||||
public BitMap Inactive { 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)
|
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)
|
if (!_intervals[index].IsSpilled)
|
||||||
{
|
{
|
||||||
|
@ -113,7 +113,11 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
InsertSplitCopies();
|
InsertSplitCopies();
|
||||||
InsertSplitCopiesAtEdges(cfg);
|
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)
|
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))
|
if (!TryAllocateRegWithoutSpill(context, current, cIndex))
|
||||||
{
|
{
|
||||||
AllocateRegWithSpill(context, current, cIndex);
|
AllocateRegWithSpill(context, current, cIndex);
|
||||||
|
@ -173,11 +160,15 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
|
|
||||||
private bool TryAllocateRegWithoutSpill(AllocationContext context, LiveInterval current, int cIndex)
|
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];
|
int[] freePositions = new int[RegistersCount];
|
||||||
|
|
||||||
for (int index = 0; index < RegistersCount; index++)
|
for (int index = 0; index < RegistersCount; index++)
|
||||||
{
|
{
|
||||||
if ((context.Masks.IntAvailableRegisters & (1 << index)) != 0)
|
if ((availableRegisters & (1 << index)) != 0)
|
||||||
{
|
{
|
||||||
freePositions[index] = int.MaxValue;
|
freePositions[index] = int.MaxValue;
|
||||||
}
|
}
|
||||||
|
@ -187,14 +178,17 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
{
|
{
|
||||||
LiveInterval interval = GetInterval(iIndex);
|
LiveInterval interval = GetInterval(iIndex);
|
||||||
|
|
||||||
|
if (interval.Register.Type == regType)
|
||||||
|
{
|
||||||
freePositions[interval.Register.Index] = 0;
|
freePositions[interval.Register.Index] = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach (int iIndex in context.Inactive)
|
foreach (int iIndex in context.Inactive)
|
||||||
{
|
{
|
||||||
LiveInterval interval = GetInterval(iIndex);
|
LiveInterval interval = GetInterval(iIndex);
|
||||||
|
|
||||||
if (interval.Overlaps(current))
|
if (interval.Register.Type == regType && interval.Overlaps(current))
|
||||||
{
|
{
|
||||||
int nextOverlap = interval.NextOverlap(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);
|
context.Active.Set(cIndex);
|
||||||
|
|
||||||
|
@ -244,13 +245,17 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
|
|
||||||
private void AllocateRegWithSpill(AllocationContext context, LiveInterval current, int cIndex)
|
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[] usePositions = new int[RegistersCount];
|
||||||
|
|
||||||
int[] blockedPositions = new int[RegistersCount];
|
int[] blockedPositions = new int[RegistersCount];
|
||||||
|
|
||||||
for (int index = 0; index < RegistersCount; index++)
|
for (int index = 0; index < RegistersCount; index++)
|
||||||
{
|
{
|
||||||
if ((context.Masks.IntAvailableRegisters & (1 << index)) != 0)
|
if ((availableRegisters & (1 << index)) != 0)
|
||||||
{
|
{
|
||||||
usePositions[index] = int.MaxValue;
|
usePositions[index] = int.MaxValue;
|
||||||
|
|
||||||
|
@ -274,7 +279,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
{
|
{
|
||||||
LiveInterval interval = GetInterval(iIndex);
|
LiveInterval interval = GetInterval(iIndex);
|
||||||
|
|
||||||
if (!interval.IsFixed)
|
if (!interval.IsFixed && interval.Register.Type == regType)
|
||||||
{
|
{
|
||||||
int nextUse = interval.NextUseAfter(current.Start);
|
int nextUse = interval.NextUseAfter(current.Start);
|
||||||
|
|
||||||
|
@ -289,7 +294,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
{
|
{
|
||||||
LiveInterval interval = GetInterval(iIndex);
|
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);
|
int nextUse = interval.NextUseAfter(current.Start);
|
||||||
|
|
||||||
|
@ -304,7 +309,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
{
|
{
|
||||||
LiveInterval interval = GetInterval(iIndex);
|
LiveInterval interval = GetInterval(iIndex);
|
||||||
|
|
||||||
if (interval.IsFixed)
|
if (interval.IsFixed && interval.Register.Type == regType)
|
||||||
{
|
{
|
||||||
SetBlockedPosition(interval.Register.Index, 0);
|
SetBlockedPosition(interval.Register.Index, 0);
|
||||||
}
|
}
|
||||||
|
@ -314,7 +319,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
{
|
{
|
||||||
LiveInterval interval = GetInterval(iIndex);
|
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));
|
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,
|
//Spill made the register available for the entire current lifetime,
|
||||||
//so we only need to split the intervals using the selected register.
|
//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);
|
SplitAndSpillOverlappingIntervals(context, current);
|
||||||
|
|
||||||
|
@ -355,7 +360,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
//There are conflicts even after spill due to the use of fixed registers
|
//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
|
//that can't be spilled, so we need to also split current at the point of
|
||||||
//the first fixed register use.
|
//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]));
|
LiveInterval splitChild = current.Split(GetSplitPosition(blockedPositions[selectedReg]));
|
||||||
|
|
||||||
|
@ -745,7 +750,10 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
throw new ArgumentException("Spilled intervals are not allowed.");
|
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)
|
private static int GetSplitPosition(int position)
|
||||||
|
@ -771,9 +779,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
|
|
||||||
for (int index = 0; index < RegistersCount; index++)
|
for (int index = 0; index < RegistersCount; index++)
|
||||||
{
|
{
|
||||||
LiveInterval interval = new LiveInterval(new Register(index, RegisterType.Integer));
|
_intervals.Add(new LiveInterval(new Register(index, RegisterType.Integer)));
|
||||||
|
_intervals.Add(new LiveInterval(new Register(index, RegisterType.Vector)));
|
||||||
_intervals.Add(interval);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HashSet<Operand> visited = new HashSet<Operand>();
|
HashSet<Operand> visited = new HashSet<Operand>();
|
||||||
|
@ -812,7 +819,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
|
|
||||||
_blockRanges = new LiveRange[cfg.Blocks.Count];
|
_blockRanges = new LiveRange[cfg.Blocks.Count];
|
||||||
|
|
||||||
int mapSize = _intervals.Count + RegistersCount;
|
int mapSize = _intervals.Count;
|
||||||
|
|
||||||
BitMap[] blkLiveGen = new BitMap[cfg.Blocks.Count];
|
BitMap[] blkLiveGen = new BitMap[cfg.Blocks.Count];
|
||||||
BitMap[] blkLiveKill = new BitMap[cfg.Blocks.Count];
|
BitMap[] blkLiveKill = new BitMap[cfg.Blocks.Count];
|
||||||
|
@ -940,18 +947,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
|
|
||||||
if (node is Operation operation && operation.Inst == Instruction.Call)
|
if (node is Operation operation && operation.Inst == Instruction.Call)
|
||||||
{
|
{
|
||||||
int callerSavedRegs = regMasks.IntCallerSavedRegisters;
|
AddIntervalCallerSavedReg(regMasks.IntCallerSavedRegisters, operationPos, RegisterType.Integer);
|
||||||
|
AddIntervalCallerSavedReg(regMasks.VecCallerSavedRegisters, operationPos, RegisterType.Vector);
|
||||||
while (callerSavedRegs != 0)
|
|
||||||
{
|
|
||||||
int callerSavedReg = BitUtils.LowestBitSet(callerSavedRegs);
|
|
||||||
|
|
||||||
LiveInterval interval = _intervals[callerSavedReg];
|
|
||||||
|
|
||||||
interval.AddRange(operationPos, operationPos + 1);
|
|
||||||
|
|
||||||
callerSavedRegs &= ~(1 << callerSavedReg);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (maxCallArgs < operation.SourcesCount - 1)
|
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)
|
private static int GetOperandId(Operand operand)
|
||||||
{
|
{
|
||||||
if (operand.Kind == OperandKind.LocalVariable)
|
if (operand.Kind == OperandKind.LocalVariable)
|
||||||
|
@ -970,7 +985,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
}
|
}
|
||||||
else if (operand.Kind == OperandKind.Register)
|
else if (operand.Kind == OperandKind.Register)
|
||||||
{
|
{
|
||||||
return operand.GetRegister().Index;
|
return GetRegisterId(operand.GetRegister());
|
||||||
}
|
}
|
||||||
else
|
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)
|
private void CoalesceCopies(BasicBlock[] blocks)
|
||||||
{
|
{
|
||||||
foreach (BasicBlock block in blocks)
|
foreach (BasicBlock block in blocks)
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
using ARMeilleure.IntermediateRepresentation;
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
using ARMeilleure.State;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
|
@ -1,19 +1,47 @@
|
||||||
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace ARMeilleure.CodeGen.RegisterAllocators
|
namespace ARMeilleure.CodeGen.RegisterAllocators
|
||||||
{
|
{
|
||||||
struct RegisterMasks
|
struct RegisterMasks
|
||||||
{
|
{
|
||||||
public int IntAvailableRegisters { get; }
|
public int IntAvailableRegisters { get; }
|
||||||
|
public int VecAvailableRegisters { get; }
|
||||||
public int IntCallerSavedRegisters { get; }
|
public int IntCallerSavedRegisters { get; }
|
||||||
|
public int VecCallerSavedRegisters { get; }
|
||||||
public int IntCalleeSavedRegisters { get; }
|
public int IntCalleeSavedRegisters { get; }
|
||||||
|
public int VecCalleeSavedRegisters { get; }
|
||||||
|
|
||||||
public RegisterMasks(
|
public RegisterMasks(
|
||||||
int intAvailableRegisters,
|
int intAvailableRegisters,
|
||||||
|
int vecAvailableRegisters,
|
||||||
int intCallerSavedRegisters,
|
int intCallerSavedRegisters,
|
||||||
int intCalleeSavedRegisters)
|
int vecCallerSavedRegisters,
|
||||||
|
int intCalleeSavedRegisters,
|
||||||
|
int vecCalleeSavedRegisters)
|
||||||
{
|
{
|
||||||
IntAvailableRegisters = intAvailableRegisters;
|
IntAvailableRegisters = intAvailableRegisters;
|
||||||
|
VecAvailableRegisters = vecAvailableRegisters;
|
||||||
IntCallerSavedRegisters = intCallerSavedRegisters;
|
IntCallerSavedRegisters = intCallerSavedRegisters;
|
||||||
|
VecCallerSavedRegisters = vecCallerSavedRegisters;
|
||||||
IntCalleeSavedRegisters = intCalleeSavedRegisters;
|
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
|
@ -4,9 +4,11 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
{
|
{
|
||||||
static class CallingConvention
|
static class CallingConvention
|
||||||
{
|
{
|
||||||
|
private const int RegistersMask = 0xffff;
|
||||||
|
|
||||||
public static int GetIntAvailableRegisters()
|
public static int GetIntAvailableRegisters()
|
||||||
{
|
{
|
||||||
int mask = 0xffff;
|
int mask = RegistersMask;
|
||||||
|
|
||||||
mask &= ~(1 << (int)X86Register.Rbp);
|
mask &= ~(1 << (int)X86Register.Rbp);
|
||||||
mask &= ~(1 << (int)X86Register.Rsp);
|
mask &= ~(1 << (int)X86Register.Rsp);
|
||||||
|
@ -14,6 +16,11 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
return mask;
|
return mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int GetVecAvailableRegisters()
|
||||||
|
{
|
||||||
|
return RegistersMask;
|
||||||
|
}
|
||||||
|
|
||||||
public static int GetIntCallerSavedRegisters()
|
public static int GetIntCallerSavedRegisters()
|
||||||
{
|
{
|
||||||
return (1 << (int)X86Register.Rax) |
|
return (1 << (int)X86Register.Rax) |
|
||||||
|
@ -25,6 +32,16 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
(1 << (int)X86Register.R11);
|
(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()
|
public static int GetIntCalleeSavedRegisters()
|
||||||
{
|
{
|
||||||
return (1 << (int)X86Register.Rbx) |
|
return (1 << (int)X86Register.Rbx) |
|
||||||
|
@ -38,7 +55,12 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
(1 << (int)X86Register.R15);
|
(1 << (int)X86Register.R15);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int GetIntArgumentsOnRegsCount()
|
public static int GetVecCalleeSavedRegisters()
|
||||||
|
{
|
||||||
|
return GetVecCallerSavedRegisters() ^ RegistersMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetArgumentsOnRegsCount()
|
||||||
{
|
{
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
@ -56,9 +78,27 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
throw new ArgumentOutOfRangeException(nameof(index));
|
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()
|
public static X86Register GetIntReturnRegister()
|
||||||
{
|
{
|
||||||
return X86Register.Rax;
|
return X86Register.Rax;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static X86Register GetVecReturnRegister()
|
||||||
|
{
|
||||||
|
return X86Register.Xmm0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -87,7 +87,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
{
|
{
|
||||||
//We need to add 8 bytes to the total size, as the call to this
|
//We need to add 8 bytes to the total size, as the call to this
|
||||||
//function already pushed 8 bytes (the return address).
|
//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;
|
mask |= 1 << (int)X86Register.Rbp;
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
//The ABI mandates that the space for at least 4 arguments
|
//The ABI mandates that the space for at least 4 arguments
|
||||||
//is reserved on the stack (this is called shadow space).
|
//is reserved on the stack (this is called shadow space).
|
||||||
if (argsCount < 4)
|
if (argsCount < 4 && argsCount != 0)
|
||||||
{
|
{
|
||||||
argsCount = 4;
|
argsCount = 4;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
using ARMeilleure.CodeGen.RegisterAllocators;
|
using ARMeilleure.CodeGen.RegisterAllocators;
|
||||||
using ARMeilleure.Common;
|
using ARMeilleure.Common;
|
||||||
|
using ARMeilleure.Diagnostics;
|
||||||
using ARMeilleure.IntermediateRepresentation;
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
using ARMeilleure.Memory;
|
using ARMeilleure.Memory;
|
||||||
using ARMeilleure.State;
|
|
||||||
using ARMeilleure.Translation;
|
using ARMeilleure.Translation;
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
|
||||||
namespace ARMeilleure.CodeGen.X86
|
namespace ARMeilleure.CodeGen.X86
|
||||||
|
@ -69,6 +70,116 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
Add(Instruction.Store8, GenerateStore8);
|
Add(Instruction.Store8, GenerateStore8);
|
||||||
Add(Instruction.StoreToContext, GenerateStoreToContext);
|
Add(Instruction.StoreToContext, GenerateStoreToContext);
|
||||||
Add(Instruction.Subtract, GenerateSubtract);
|
Add(Instruction.Subtract, GenerateSubtract);
|
||||||
|
Add(Instruction.VectorExtract, GenerateVectorExtract);
|
||||||
|
Add(Instruction.VectorExtract16, GenerateVectorExtract16);
|
||||||
|
Add(Instruction.VectorExtract8, GenerateVectorExtract8);
|
||||||
|
Add(Instruction.VectorInsert, GenerateVectorInsert);
|
||||||
|
Add(Instruction.VectorInsert16, GenerateVectorInsert16);
|
||||||
|
Add(Instruction.VectorInsert8, GenerateVectorInsert8);
|
||||||
|
Add(Instruction.VectorZero, GenerateVectorZero);
|
||||||
|
Add(Instruction.VectorZeroUpper64, GenerateVectorZeroUpper64);
|
||||||
|
Add(Instruction.VectorZeroUpper96, GenerateVectorZeroUpper96);
|
||||||
|
Add(Instruction.X86Addpd, GenerateX86Addpd);
|
||||||
|
Add(Instruction.X86Addps, GenerateX86Addps);
|
||||||
|
Add(Instruction.X86Addsd, GenerateX86Addsd);
|
||||||
|
Add(Instruction.X86Addss, GenerateX86Addss);
|
||||||
|
Add(Instruction.X86Andnpd, GenerateX86Andnpd);
|
||||||
|
Add(Instruction.X86Andnps, GenerateX86Andnps);
|
||||||
|
Add(Instruction.X86Divpd, GenerateX86Divpd);
|
||||||
|
Add(Instruction.X86Divps, GenerateX86Divps);
|
||||||
|
Add(Instruction.X86Divsd, GenerateX86Divsd);
|
||||||
|
Add(Instruction.X86Divss, GenerateX86Divss);
|
||||||
|
Add(Instruction.X86Haddpd, GenerateX86Haddpd);
|
||||||
|
Add(Instruction.X86Haddps, GenerateX86Haddps);
|
||||||
|
Add(Instruction.X86Maxpd, GenerateX86Maxpd);
|
||||||
|
Add(Instruction.X86Maxps, GenerateX86Maxps);
|
||||||
|
Add(Instruction.X86Maxsd, GenerateX86Maxsd);
|
||||||
|
Add(Instruction.X86Maxss, GenerateX86Maxss);
|
||||||
|
Add(Instruction.X86Minpd, GenerateX86Minpd);
|
||||||
|
Add(Instruction.X86Minps, GenerateX86Minps);
|
||||||
|
Add(Instruction.X86Minsd, GenerateX86Minsd);
|
||||||
|
Add(Instruction.X86Minss, GenerateX86Minss);
|
||||||
|
Add(Instruction.X86Movhlps, GenerateX86Movhlps);
|
||||||
|
Add(Instruction.X86Movlhps, GenerateX86Movlhps);
|
||||||
|
Add(Instruction.X86Mulpd, GenerateX86Mulpd);
|
||||||
|
Add(Instruction.X86Mulps, GenerateX86Mulps);
|
||||||
|
Add(Instruction.X86Mulsd, GenerateX86Mulsd);
|
||||||
|
Add(Instruction.X86Mulss, GenerateX86Mulss);
|
||||||
|
Add(Instruction.X86Paddb, GenerateX86Paddb);
|
||||||
|
Add(Instruction.X86Paddd, GenerateX86Paddd);
|
||||||
|
Add(Instruction.X86Paddq, GenerateX86Paddq);
|
||||||
|
Add(Instruction.X86Paddw, GenerateX86Paddw);
|
||||||
|
Add(Instruction.X86Pand, GenerateX86Pand);
|
||||||
|
Add(Instruction.X86Pandn, GenerateX86Pandn);
|
||||||
|
Add(Instruction.X86Pavgb, GenerateX86Pavgb);
|
||||||
|
Add(Instruction.X86Pavgw, GenerateX86Pavgw);
|
||||||
|
Add(Instruction.X86Pblendvb, GenerateX86Pblendvb);
|
||||||
|
Add(Instruction.X86Pcmpeqb, GenerateX86Pcmpeqb);
|
||||||
|
Add(Instruction.X86Pcmpeqd, GenerateX86Pcmpeqd);
|
||||||
|
Add(Instruction.X86Pcmpeqq, GenerateX86Pcmpeqq);
|
||||||
|
Add(Instruction.X86Pcmpeqw, GenerateX86Pcmpeqw);
|
||||||
|
Add(Instruction.X86Pcmpgtb, GenerateX86Pcmpgtb);
|
||||||
|
Add(Instruction.X86Pcmpgtd, GenerateX86Pcmpgtd);
|
||||||
|
Add(Instruction.X86Pcmpgtq, GenerateX86Pcmpgtq);
|
||||||
|
Add(Instruction.X86Pcmpgtw, GenerateX86Pcmpgtw);
|
||||||
|
Add(Instruction.X86Pmaxsb, GenerateX86Pmaxsb);
|
||||||
|
Add(Instruction.X86Pmaxsd, GenerateX86Pmaxsd);
|
||||||
|
Add(Instruction.X86Pmaxsw, GenerateX86Pmaxsw);
|
||||||
|
Add(Instruction.X86Pmaxub, GenerateX86Pmaxub);
|
||||||
|
Add(Instruction.X86Pmaxud, GenerateX86Pmaxud);
|
||||||
|
Add(Instruction.X86Pmaxuw, GenerateX86Pmaxuw);
|
||||||
|
Add(Instruction.X86Pminsb, GenerateX86Pminsb);
|
||||||
|
Add(Instruction.X86Pminsd, GenerateX86Pminsd);
|
||||||
|
Add(Instruction.X86Pminsw, GenerateX86Pminsw);
|
||||||
|
Add(Instruction.X86Pminub, GenerateX86Pminub);
|
||||||
|
Add(Instruction.X86Pminud, GenerateX86Pminud);
|
||||||
|
Add(Instruction.X86Pminuw, GenerateX86Pminuw);
|
||||||
|
Add(Instruction.X86Pmovsxbw, GenerateX86Pmovsxbw);
|
||||||
|
Add(Instruction.X86Pmovsxdq, GenerateX86Pmovsxdq);
|
||||||
|
Add(Instruction.X86Pmovsxwd, GenerateX86Pmovsxwd);
|
||||||
|
Add(Instruction.X86Pmovzxbw, GenerateX86Pmovzxbw);
|
||||||
|
Add(Instruction.X86Pmovzxdq, GenerateX86Pmovzxdq);
|
||||||
|
Add(Instruction.X86Pmovzxwd, GenerateX86Pmovzxwd);
|
||||||
|
Add(Instruction.X86Pmulld, GenerateX86Pmulld);
|
||||||
|
Add(Instruction.X86Pmullw, GenerateX86Pmullw);
|
||||||
|
Add(Instruction.X86Popcnt, GenerateX86Popcnt);
|
||||||
|
Add(Instruction.X86Por, GenerateX86Por);
|
||||||
|
Add(Instruction.X86Psllw, GenerateX86Psllw);
|
||||||
|
Add(Instruction.X86Psrad, GenerateX86Psrad);
|
||||||
|
Add(Instruction.X86Psraw, GenerateX86Psraw);
|
||||||
|
Add(Instruction.X86Psrld, GenerateX86Psrld);
|
||||||
|
Add(Instruction.X86Psrlq, GenerateX86Psrlq);
|
||||||
|
Add(Instruction.X86Psrldq, GenerateX86Psrldq);
|
||||||
|
Add(Instruction.X86Psrlw, GenerateX86Psrlw);
|
||||||
|
Add(Instruction.X86Psubb, GenerateX86Psubb);
|
||||||
|
Add(Instruction.X86Psubd, GenerateX86Psubd);
|
||||||
|
Add(Instruction.X86Psubq, GenerateX86Psubq);
|
||||||
|
Add(Instruction.X86Psubw, GenerateX86Psubw);
|
||||||
|
Add(Instruction.X86Pxor, GenerateX86Pxor);
|
||||||
|
Add(Instruction.X86Rcpps, GenerateX86Rcpps);
|
||||||
|
Add(Instruction.X86Rcpss, GenerateX86Rcpss);
|
||||||
|
Add(Instruction.X86Roundpd, GenerateX86Roundpd);
|
||||||
|
Add(Instruction.X86Roundps, GenerateX86Roundps);
|
||||||
|
Add(Instruction.X86Roundsd, GenerateX86Roundsd);
|
||||||
|
Add(Instruction.X86Roundss, GenerateX86Roundss);
|
||||||
|
Add(Instruction.X86Rsqrtps, GenerateX86Rsqrtps);
|
||||||
|
Add(Instruction.X86Rsqrtss, GenerateX86Rsqrtss);
|
||||||
|
Add(Instruction.X86Shufpd, GenerateX86Shufpd);
|
||||||
|
Add(Instruction.X86Shufps, GenerateX86Shufps);
|
||||||
|
Add(Instruction.X86Sqrtpd, GenerateX86Sqrtpd);
|
||||||
|
Add(Instruction.X86Sqrtps, GenerateX86Sqrtps);
|
||||||
|
Add(Instruction.X86Sqrtsd, GenerateX86Sqrtsd);
|
||||||
|
Add(Instruction.X86Sqrtss, GenerateX86Sqrtss);
|
||||||
|
Add(Instruction.X86Subpd, GenerateX86Subpd);
|
||||||
|
Add(Instruction.X86Subps, GenerateX86Subps);
|
||||||
|
Add(Instruction.X86Subsd, GenerateX86Subsd);
|
||||||
|
Add(Instruction.X86Subss, GenerateX86Subss);
|
||||||
|
Add(Instruction.X86Unpckhpd, GenerateX86Unpckhpd);
|
||||||
|
Add(Instruction.X86Unpckhps, GenerateX86Unpckhps);
|
||||||
|
Add(Instruction.X86Unpcklpd, GenerateX86Unpcklpd);
|
||||||
|
Add(Instruction.X86Unpcklps, GenerateX86Unpcklps);
|
||||||
|
Add(Instruction.X86Xorpd, GenerateX86Xorpd);
|
||||||
|
Add(Instruction.X86Xorps, GenerateX86Xorps);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Add(Instruction inst, Action<CodeGenContext, Operation> func)
|
private static void Add(Instruction inst, Action<CodeGenContext, Operation> func)
|
||||||
|
@ -78,17 +189,28 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
public static byte[] Generate(ControlFlowGraph cfg, MemoryManager memory)
|
public static byte[] Generate(ControlFlowGraph cfg, MemoryManager memory)
|
||||||
{
|
{
|
||||||
|
Logger.StartPass(PassName.PreAllocation);
|
||||||
|
|
||||||
PreAllocator.RunPass(cfg, memory);
|
PreAllocator.RunPass(cfg, memory);
|
||||||
|
|
||||||
|
Logger.EndPass(PassName.PreAllocation);
|
||||||
|
|
||||||
|
Logger.StartPass(PassName.RegisterAllocation);
|
||||||
|
|
||||||
LinearScan regAlloc = new LinearScan();
|
LinearScan regAlloc = new LinearScan();
|
||||||
|
|
||||||
RegisterMasks regMasks = new RegisterMasks(
|
RegisterMasks regMasks = new RegisterMasks(
|
||||||
CallingConvention.GetIntAvailableRegisters(),
|
CallingConvention.GetIntAvailableRegisters(),
|
||||||
|
CallingConvention.GetVecAvailableRegisters(),
|
||||||
CallingConvention.GetIntCallerSavedRegisters(),
|
CallingConvention.GetIntCallerSavedRegisters(),
|
||||||
CallingConvention.GetIntCalleeSavedRegisters());
|
CallingConvention.GetVecCallerSavedRegisters(),
|
||||||
|
CallingConvention.GetIntCalleeSavedRegisters(),
|
||||||
|
CallingConvention.GetVecCalleeSavedRegisters());
|
||||||
|
|
||||||
AllocationResult allocResult = regAlloc.RunPass(cfg, regMasks);
|
AllocationResult allocResult = regAlloc.RunPass(cfg, regMasks);
|
||||||
|
|
||||||
|
Logger.EndPass(PassName.RegisterAllocation, cfg);
|
||||||
|
|
||||||
using (MemoryStream stream = new MemoryStream())
|
using (MemoryStream stream = new MemoryStream())
|
||||||
{
|
{
|
||||||
CodeGenContext context = new CodeGenContext(stream, allocResult, cfg.Blocks.Count);
|
CodeGenContext context = new CodeGenContext(stream, allocResult, cfg.Blocks.Count);
|
||||||
|
@ -132,7 +254,22 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
{
|
{
|
||||||
ValidateDestSrc1(operation);
|
ValidateDestSrc1(operation);
|
||||||
|
|
||||||
context.Assembler.Add(operation.Dest, operation.GetSource(1));
|
Operand dest = operation.Dest;
|
||||||
|
Operand src1 = operation.GetSource(0);
|
||||||
|
Operand src2 = operation.GetSource(1);
|
||||||
|
|
||||||
|
if (dest.Type.IsInteger())
|
||||||
|
{
|
||||||
|
context.Assembler.Add(dest, src2);
|
||||||
|
}
|
||||||
|
else if (dest.Type == OperandType.FP32)
|
||||||
|
{
|
||||||
|
context.Assembler.Addss(dest, src2, src1);
|
||||||
|
}
|
||||||
|
else /* if (dest.Type == OperandType.FP64) */
|
||||||
|
{
|
||||||
|
context.Assembler.Addsd(dest, src2, src1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void GenerateBitwiseAnd(CodeGenContext context, Operation operation)
|
private static void GenerateBitwiseAnd(CodeGenContext context, Operation operation)
|
||||||
|
@ -282,6 +419,18 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
context.Assembler.Mov(dest, source);
|
context.Assembler.Mov(dest, source);
|
||||||
}
|
}
|
||||||
|
else if (dest.GetRegister().Type == RegisterType.Vector)
|
||||||
|
{
|
||||||
|
if (source.GetRegister().Type == RegisterType.Integer)
|
||||||
|
{
|
||||||
|
//FIXME.
|
||||||
|
context.Assembler.Movd(dest, source);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
context.Assembler.Movdqu(dest, source);
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
context.Assembler.Mov(dest, source);
|
context.Assembler.Mov(dest, source);
|
||||||
|
@ -318,8 +467,12 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
private static void GenerateDivide(CodeGenContext context, Operation operation)
|
private static void GenerateDivide(CodeGenContext context, Operation operation)
|
||||||
{
|
{
|
||||||
|
Operand dest = operation.Dest;
|
||||||
|
Operand dividend = operation.GetSource(0);
|
||||||
Operand divisor = operation.GetSource(1);
|
Operand divisor = operation.GetSource(1);
|
||||||
|
|
||||||
|
if (dest.Type.IsInteger())
|
||||||
|
{
|
||||||
if (divisor.Type == OperandType.I32)
|
if (divisor.Type == OperandType.I32)
|
||||||
{
|
{
|
||||||
context.Assembler.Cdq();
|
context.Assembler.Cdq();
|
||||||
|
@ -331,6 +484,15 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
context.Assembler.Idiv(divisor);
|
context.Assembler.Idiv(divisor);
|
||||||
}
|
}
|
||||||
|
else if (dest.Type == OperandType.FP32)
|
||||||
|
{
|
||||||
|
context.Assembler.Subss(dest, divisor, dividend);
|
||||||
|
}
|
||||||
|
else /* if (dest.Type == OperandType.FP64) */
|
||||||
|
{
|
||||||
|
context.Assembler.Subsd(dest, divisor, dividend);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void GenerateDivideUI(CodeGenContext context, Operation operation)
|
private static void GenerateDivideUI(CodeGenContext context, Operation operation)
|
||||||
{
|
{
|
||||||
|
@ -378,8 +540,15 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
X86MemoryOperand memOp = new X86MemoryOperand(dest.Type, rbp, null, Scale.x1, offset.AsInt32());
|
X86MemoryOperand memOp = new X86MemoryOperand(dest.Type, rbp, null, Scale.x1, offset.AsInt32());
|
||||||
|
|
||||||
|
if (dest.GetRegister().Type == RegisterType.Vector)
|
||||||
|
{
|
||||||
|
context.Assembler.Movdqu(dest, memOp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
context.Assembler.Mov(dest, memOp);
|
context.Assembler.Mov(dest, memOp);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void GenerateLoadSx16(CodeGenContext context, Operation operation)
|
private static void GenerateLoadSx16(CodeGenContext context, Operation operation)
|
||||||
{
|
{
|
||||||
|
@ -412,6 +581,8 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
Operand src1 = operation.GetSource(0);
|
Operand src1 = operation.GetSource(0);
|
||||||
Operand src2 = operation.GetSource(1);
|
Operand src2 = operation.GetSource(1);
|
||||||
|
|
||||||
|
if (dest.Type.IsInteger())
|
||||||
|
{
|
||||||
if (src2.Kind == OperandKind.Constant)
|
if (src2.Kind == OperandKind.Constant)
|
||||||
{
|
{
|
||||||
context.Assembler.Imul(dest, src1, src2);
|
context.Assembler.Imul(dest, src1, src2);
|
||||||
|
@ -421,6 +592,15 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
context.Assembler.Imul(dest, src2);
|
context.Assembler.Imul(dest, src2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (dest.Type == OperandType.FP32)
|
||||||
|
{
|
||||||
|
context.Assembler.Mulss(dest, src2, src1);
|
||||||
|
}
|
||||||
|
else /* if (dest.Type == OperandType.FP64) */
|
||||||
|
{
|
||||||
|
context.Assembler.Mulsd(dest, src2, src1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void GenerateMultiply64HighSI(CodeGenContext context, Operation operation)
|
private static void GenerateMultiply64HighSI(CodeGenContext context, Operation operation)
|
||||||
{
|
{
|
||||||
|
@ -554,14 +734,707 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
X86MemoryOperand memOp = new X86MemoryOperand(source.Type, rbp, null, Scale.x1, offset.AsInt32());
|
X86MemoryOperand memOp = new X86MemoryOperand(source.Type, rbp, null, Scale.x1, offset.AsInt32());
|
||||||
|
|
||||||
|
if (source.GetRegister().Type == RegisterType.Vector)
|
||||||
|
{
|
||||||
|
context.Assembler.Movdqu(memOp, source);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
context.Assembler.Mov(memOp, source);
|
context.Assembler.Mov(memOp, source);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void GenerateSubtract(CodeGenContext context, Operation operation)
|
private static void GenerateSubtract(CodeGenContext context, Operation operation)
|
||||||
{
|
{
|
||||||
ValidateDestSrc1(operation);
|
ValidateDestSrc1(operation);
|
||||||
|
|
||||||
context.Assembler.Sub(operation.Dest, operation.GetSource(1));
|
Operand dest = operation.Dest;
|
||||||
|
Operand src1 = operation.GetSource(0);
|
||||||
|
Operand src2 = operation.GetSource(1);
|
||||||
|
|
||||||
|
if (dest.Type.IsInteger())
|
||||||
|
{
|
||||||
|
context.Assembler.Sub(dest, src2);
|
||||||
|
}
|
||||||
|
else if (dest.Type == OperandType.FP32)
|
||||||
|
{
|
||||||
|
context.Assembler.Subss(dest, src2, src1);
|
||||||
|
}
|
||||||
|
else /* if (dest.Type == OperandType.FP64) */
|
||||||
|
{
|
||||||
|
context.Assembler.Subsd(dest, src2, src1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateVectorExtract(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
Operand dest = operation.Dest; //Value
|
||||||
|
Operand src1 = operation.GetSource(0); //Vector
|
||||||
|
Operand src2 = operation.GetSource(1); //Index
|
||||||
|
|
||||||
|
Debug.Assert(src2.Kind == OperandKind.Constant, "Index is not constant.");
|
||||||
|
|
||||||
|
byte index = src2.AsByte();
|
||||||
|
|
||||||
|
if (dest.Type.IsInteger())
|
||||||
|
{
|
||||||
|
context.Assembler.Pextrd(dest, src1, index);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Floating-point type.
|
||||||
|
if ((index >= 2 && dest.Type == OperandType.FP32) ||
|
||||||
|
(index == 1 && dest.Type == OperandType.FP64))
|
||||||
|
{
|
||||||
|
context.Assembler.Movhlps(dest, src1, dest);
|
||||||
|
context.Assembler.Movq(dest, dest);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
context.Assembler.Movq(dest, src1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dest.Type == OperandType.FP32)
|
||||||
|
{
|
||||||
|
context.Assembler.Pshufd(dest, dest, (byte)(0xfc | (index & 1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateVectorExtract16(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
Operand dest = operation.Dest; //Value
|
||||||
|
Operand src1 = operation.GetSource(0); //Vector
|
||||||
|
Operand src2 = operation.GetSource(1); //Index
|
||||||
|
|
||||||
|
Debug.Assert(src2.Kind == OperandKind.Constant, "Index is not constant.");
|
||||||
|
|
||||||
|
byte index = src2.AsByte();
|
||||||
|
|
||||||
|
context.Assembler.Pextrw(dest, src1, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateVectorExtract8(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
Operand dest = operation.Dest; //Value
|
||||||
|
Operand src1 = operation.GetSource(0); //Vector
|
||||||
|
Operand src2 = operation.GetSource(1); //Index
|
||||||
|
|
||||||
|
Debug.Assert(src2.Kind == OperandKind.Constant, "Index is not constant.");
|
||||||
|
|
||||||
|
byte index = src2.AsByte();
|
||||||
|
|
||||||
|
//TODO: SSE/SSE2 version.
|
||||||
|
context.Assembler.Pextrb(dest, src1, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateVectorInsert(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
Operand dest = operation.Dest;
|
||||||
|
Operand src1 = operation.GetSource(0); //Vector
|
||||||
|
Operand src2 = operation.GetSource(1); //Value
|
||||||
|
Operand src3 = operation.GetSource(2); //Index
|
||||||
|
|
||||||
|
Debug.Assert(src3.Kind == OperandKind.Constant, "Index is not constant.");
|
||||||
|
|
||||||
|
byte index = src3.AsByte();
|
||||||
|
|
||||||
|
if (src2.Type.IsInteger())
|
||||||
|
{
|
||||||
|
//TODO: SSE/SSE2 version.
|
||||||
|
context.Assembler.Pinsrd(dest, src2, src1, index);
|
||||||
|
}
|
||||||
|
else if (src2.Type == OperandType.FP32)
|
||||||
|
{
|
||||||
|
if (index != 0)
|
||||||
|
{
|
||||||
|
//TODO: SSE/SSE2 version.
|
||||||
|
context.Assembler.Insertps(dest, src2, src1, (byte)(index << 4));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
context.Assembler.Movss(dest, src2, src1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else /* if (src2.Type == OperandType.FP64) */
|
||||||
|
{
|
||||||
|
if (index != 0)
|
||||||
|
{
|
||||||
|
context.Assembler.Movlhps(dest, src2, src1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
context.Assembler.Movsd(dest, src2, src1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateVectorInsert16(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
Operand dest = operation.Dest;
|
||||||
|
Operand src1 = operation.GetSource(0); //Vector
|
||||||
|
Operand src2 = operation.GetSource(1); //Value
|
||||||
|
Operand src3 = operation.GetSource(2); //Index
|
||||||
|
|
||||||
|
Debug.Assert(src3.Kind == OperandKind.Constant, "Index is not constant.");
|
||||||
|
|
||||||
|
byte index = src3.AsByte();
|
||||||
|
|
||||||
|
context.Assembler.Pinsrw(dest, src2, src1, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateVectorInsert8(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
Operand dest = operation.Dest;
|
||||||
|
Operand src1 = operation.GetSource(0); //Vector
|
||||||
|
Operand src2 = operation.GetSource(1); //Value
|
||||||
|
Operand src3 = operation.GetSource(2); //Index
|
||||||
|
|
||||||
|
Debug.Assert(src3.Kind == OperandKind.Constant, "Index is not constant.");
|
||||||
|
|
||||||
|
byte index = src3.AsByte();
|
||||||
|
|
||||||
|
//TODO: SSE/SSE2 version.
|
||||||
|
context.Assembler.Pinsrb(dest, src2, src1, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateVectorZero(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Xorps(operation.Dest, operation.Dest, operation.Dest);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateVectorZeroUpper64(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
Operand dest = operation.Dest;
|
||||||
|
Operand src1 = operation.GetSource(0);
|
||||||
|
|
||||||
|
context.Assembler.Movq(dest, src1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateVectorZeroUpper96(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
Operand dest = operation.Dest;
|
||||||
|
Operand src1 = operation.GetSource(0);
|
||||||
|
|
||||||
|
context.Assembler.Movq(dest, src1);
|
||||||
|
context.Assembler.Pshufd(dest, dest, 0xfc);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Addpd(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Addpd(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Addps(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Addps(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Addsd(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Addsd(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Addss(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Addss(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Andnpd(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Andnpd(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Andnps(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Andnps(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Divpd(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Divpd(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Divps(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Divps(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Divsd(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Divsd(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Divss(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Divss(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Haddpd(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Addpd(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Haddps(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Addps(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Maxpd(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Maxpd(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Maxps(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Maxps(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Maxsd(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Maxsd(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Maxss(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Maxss(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Minpd(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Minpd(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Minps(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Minps(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Minsd(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Minsd(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Minss(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Minss(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Movhlps(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Movhlps(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Movlhps(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Movlhps(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Mulpd(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Mulpd(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Mulps(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Mulps(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Mulsd(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Mulsd(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Mulss(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Mulss(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Paddb(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Paddb(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Paddd(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Paddd(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Paddq(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Paddq(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Paddw(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Paddw(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pand(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pand(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pandn(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pandn(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pavgb(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pavgb(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pavgw(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pavgw(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pblendvb(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pblendvb(
|
||||||
|
operation.Dest,
|
||||||
|
operation.GetSource(0),
|
||||||
|
operation.GetSource(1),
|
||||||
|
operation.GetSource(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pcmpeqb(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pcmpeqb(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pcmpeqd(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pcmpeqd(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pcmpeqq(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pcmpeqq(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pcmpeqw(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pcmpeqw(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pcmpgtb(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pcmpgtb(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pcmpgtd(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pcmpgtd(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pcmpgtq(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pcmpgtq(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pcmpgtw(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pcmpgtw(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pmaxsb(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pmaxsb(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pmaxsd(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pmaxsd(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pmaxsw(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pmaxsw(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pmaxub(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pmaxub(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pmaxud(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pmaxud(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pmaxuw(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pmaxuw(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pminsb(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pminsb(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pminsd(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pminsd(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pminsw(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pminsw(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pminub(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pminub(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pminud(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pminud(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pminuw(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pminuw(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pmovsxbw(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pmovsxbw(operation.Dest, operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pmovsxdq(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pmovsxdq(operation.Dest, operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pmovsxwd(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pmovsxwd(operation.Dest, operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pmovzxbw(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pmovzxbw(operation.Dest, operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pmovzxdq(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pmovzxdq(operation.Dest, operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pmovzxwd(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pmovzxwd(operation.Dest, operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pmulld(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pmulld(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pmullw(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pmullw(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Popcnt(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Popcnt(operation.Dest, operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Por(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Por(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Psllw(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Psllw(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Psrad(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Psrad(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Psraw(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Psraw(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Psrld(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Psrld(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Psrlq(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Psrlq(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Psrldq(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Psrldq(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Psrlw(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Psrlw(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Psubb(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Psubb(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Psubd(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Psubd(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Psubq(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Psubq(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Psubw(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Psubw(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Pxor(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Pxor(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Rcpps(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Rcpps(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Rcpss(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Rcpss(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Roundpd(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Roundpd(operation.Dest, operation.GetSource(0), operation.GetSource(1).AsByte());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Roundps(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Roundps(operation.Dest, operation.GetSource(0), operation.GetSource(1).AsByte());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Roundsd(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Roundsd(operation.Dest, operation.GetSource(0), operation.GetSource(1).AsByte());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Roundss(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Roundss(operation.Dest, operation.GetSource(0), operation.GetSource(1).AsByte());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Rsqrtps(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Rsqrtps(operation.Dest, operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Rsqrtss(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Rsqrtss(operation.Dest, operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Shufpd(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Shufpd(
|
||||||
|
operation.Dest,
|
||||||
|
operation.GetSource(1),
|
||||||
|
operation.GetSource(2).AsByte(),
|
||||||
|
operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Shufps(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Shufps(
|
||||||
|
operation.Dest,
|
||||||
|
operation.GetSource(1),
|
||||||
|
operation.GetSource(2).AsByte(),
|
||||||
|
operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Sqrtpd(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Sqrtpd(operation.Dest, operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Sqrtps(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Sqrtps(operation.Dest, operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Sqrtsd(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Sqrtsd(operation.Dest, operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Sqrtss(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Sqrtss(operation.Dest, operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Subpd(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Subpd(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Subps(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Subps(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Subsd(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Subsd(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Subss(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Subss(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Unpckhpd(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Unpckhpd(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Unpckhps(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Unpckhps(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Unpcklpd(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Unpcklpd(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Unpcklps(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Unpcklps(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Xorpd(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Xorpd(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void GenerateX86Xorps(CodeGenContext context, Operation operation)
|
||||||
|
{
|
||||||
|
context.Assembler.Xorps(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void GenerateCompare(CodeGenContext context, Operation operation, X86Condition condition)
|
private static void GenerateCompare(CodeGenContext context, Operation operation, X86Condition condition)
|
||||||
|
@ -604,7 +1477,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
private static void WritePrologue(CodeGenContext context)
|
private static void WritePrologue(CodeGenContext context)
|
||||||
{
|
{
|
||||||
int mask = CallingConvention.GetIntCalleeSavedRegisters() & context.AllocResult.UsedRegisters;
|
int mask = CallingConvention.GetIntCalleeSavedRegisters() & context.AllocResult.IntUsedRegisters;
|
||||||
|
|
||||||
mask |= 1 << (int)X86Register.Rbp;
|
mask |= 1 << (int)X86Register.Rbp;
|
||||||
|
|
||||||
|
@ -627,7 +1500,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
private static void WriteEpilogue(CodeGenContext context)
|
private static void WriteEpilogue(CodeGenContext context)
|
||||||
{
|
{
|
||||||
int mask = CallingConvention.GetIntCalleeSavedRegisters() & context.AllocResult.UsedRegisters;
|
int mask = CallingConvention.GetIntCalleeSavedRegisters() & context.AllocResult.IntUsedRegisters;
|
||||||
|
|
||||||
mask |= 1 << (int)X86Register.Rbp;
|
mask |= 1 << (int)X86Register.Rbp;
|
||||||
|
|
||||||
|
|
7
ARMeilleure/CodeGen/X86/HardwareCapabilities.cs
Normal file
7
ARMeilleure/CodeGen/X86/HardwareCapabilities.cs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
namespace ARMeilleure.CodeGen.X86
|
||||||
|
{
|
||||||
|
static class HardwareCapabilities
|
||||||
|
{
|
||||||
|
public const bool SupportsVexEncoding = true;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
using ARMeilleure.CodeGen.Optimizations;
|
using ARMeilleure.CodeGen.Optimizations;
|
||||||
using ARMeilleure.IntermediateRepresentation;
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
using ARMeilleure.Memory;
|
using ARMeilleure.Memory;
|
||||||
using ARMeilleure.State;
|
|
||||||
using ARMeilleure.Translation;
|
using ARMeilleure.Translation;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
@ -118,17 +117,30 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
private static void AddConstantCopy(LinkedListNode<Node> node, Operation operation)
|
private static void AddConstantCopy(LinkedListNode<Node> node, Operation operation)
|
||||||
{
|
{
|
||||||
if (operation.SourcesCount == 0)
|
if (operation.SourcesCount == 0 || HasFixedConst(operation.Inst))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Instruction inst = operation.Inst;
|
Instruction inst = operation.Inst;
|
||||||
|
|
||||||
|
Operand dest = operation.Dest;
|
||||||
Operand src1 = operation.GetSource(0);
|
Operand src1 = operation.GetSource(0);
|
||||||
Operand src2;
|
Operand src2;
|
||||||
|
|
||||||
if (src1.Kind == OperandKind.Constant && !HasConstSrc1(inst))
|
if (src1.Type.IsInteger())
|
||||||
|
{
|
||||||
|
//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))
|
||||||
{
|
{
|
||||||
if (IsComutative(inst))
|
if (IsComutative(inst))
|
||||||
{
|
{
|
||||||
|
@ -165,6 +177,35 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
operation.SetSource(1, src2);
|
operation.SetSource(1, src2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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 = AddXmmCopy(node, src1);
|
||||||
|
|
||||||
|
operation.SetSource(0, src1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (operation.SourcesCount < 2)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
src2 = operation.GetSource(1);
|
||||||
|
|
||||||
|
if (src2.Kind == OperandKind.Constant && src2.Type.IsInteger())
|
||||||
|
{
|
||||||
|
src2 = AddXmmCopy(node, src2);
|
||||||
|
|
||||||
|
operation.SetSource(1, src2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void AddFixedRegisterCopy(LinkedListNode<Node> node, Operation operation)
|
private static void AddFixedRegisterCopy(LinkedListNode<Node> node, Operation operation)
|
||||||
{
|
{
|
||||||
|
@ -248,7 +289,7 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
{
|
{
|
||||||
int argsCount = operation.SourcesCount;
|
int argsCount = operation.SourcesCount;
|
||||||
|
|
||||||
int maxArgs = CallingConvention.GetIntArgumentsOnRegsCount();
|
int maxArgs = CallingConvention.GetArgumentsOnRegsCount();
|
||||||
|
|
||||||
if (argsCount > maxArgs + 1)
|
if (argsCount > maxArgs + 1)
|
||||||
{
|
{
|
||||||
|
@ -259,7 +300,18 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
{
|
{
|
||||||
Operand source = operation.GetSource(index);
|
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);
|
Operation srcCopyOp = new Operation(Instruction.Copy, argReg, source);
|
||||||
|
|
||||||
|
@ -285,7 +337,18 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
if (dest != null)
|
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);
|
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.
|
//a three operand form where the second source is a immediate value.
|
||||||
bool threeOperandForm = inst == Instruction.Multiply && operation.GetSource(1).Kind == OperandKind.Constant;
|
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);
|
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)
|
private static Operand AddCopy(LinkedListNode<Node> node, Operand source)
|
||||||
{
|
{
|
||||||
Operand temp = Local(source.Type);
|
Operand temp = Local(source.Type);
|
||||||
|
@ -343,6 +417,20 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
return temp;
|
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)
|
private static bool IsLongConst(Operand operand)
|
||||||
{
|
{
|
||||||
long value = operand.Type == OperandType.I32 ? operand.AsInt32()
|
long value = operand.Type == OperandType.I32 ? operand.AsInt32()
|
||||||
|
@ -405,9 +493,14 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
return Register((int)register, RegisterType.Integer, type);
|
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.Add:
|
||||||
case Instruction.BitwiseAnd:
|
case Instruction.BitwiseAnd:
|
||||||
|
@ -423,6 +516,23 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
case Instruction.ShiftRightUI:
|
case Instruction.ShiftRightUI:
|
||||||
case Instruction.Subtract:
|
case Instruction.Subtract:
|
||||||
return true;
|
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;
|
return false;
|
||||||
|
@ -464,6 +574,9 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
case Instruction.ShiftRightSI:
|
case Instruction.ShiftRightSI:
|
||||||
case Instruction.ShiftRightUI:
|
case Instruction.ShiftRightUI:
|
||||||
case Instruction.Subtract:
|
case Instruction.Subtract:
|
||||||
|
case Instruction.VectorExtract:
|
||||||
|
case Instruction.VectorExtract16:
|
||||||
|
case Instruction.VectorExtract8:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -486,5 +599,29 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
|
|
||||||
return false;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,38 +3,152 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
enum X86Instruction
|
enum X86Instruction
|
||||||
{
|
{
|
||||||
Add,
|
Add,
|
||||||
|
Addpd,
|
||||||
|
Addps,
|
||||||
|
Addsd,
|
||||||
|
Addss,
|
||||||
And,
|
And,
|
||||||
|
Andnpd,
|
||||||
|
Andnps,
|
||||||
Bsr,
|
Bsr,
|
||||||
Bswap,
|
Bswap,
|
||||||
Call,
|
Call,
|
||||||
Cmovcc,
|
Cmovcc,
|
||||||
Cmp,
|
Cmp,
|
||||||
Div,
|
Div,
|
||||||
|
Divpd,
|
||||||
|
Divps,
|
||||||
|
Divsd,
|
||||||
|
Divss,
|
||||||
|
Haddpd,
|
||||||
|
Haddps,
|
||||||
Idiv,
|
Idiv,
|
||||||
Imul,
|
Imul,
|
||||||
Imul128,
|
Imul128,
|
||||||
|
Insertps,
|
||||||
|
Maxpd,
|
||||||
|
Maxps,
|
||||||
|
Maxsd,
|
||||||
|
Maxss,
|
||||||
|
Minpd,
|
||||||
|
Minps,
|
||||||
|
Minsd,
|
||||||
|
Minss,
|
||||||
Mov,
|
Mov,
|
||||||
Mov16,
|
Mov16,
|
||||||
Mov8,
|
Mov8,
|
||||||
|
Movd,
|
||||||
|
Movdqu,
|
||||||
|
Movhlps,
|
||||||
|
Movlhps,
|
||||||
|
Movq,
|
||||||
|
Movsd,
|
||||||
|
Movss,
|
||||||
Movsx16,
|
Movsx16,
|
||||||
Movsx32,
|
Movsx32,
|
||||||
Movsx8,
|
Movsx8,
|
||||||
Movzx16,
|
Movzx16,
|
||||||
Movzx8,
|
Movzx8,
|
||||||
Mul128,
|
Mul128,
|
||||||
|
Mulpd,
|
||||||
|
Mulps,
|
||||||
|
Mulsd,
|
||||||
|
Mulss,
|
||||||
Neg,
|
Neg,
|
||||||
Not,
|
Not,
|
||||||
Or,
|
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,
|
Pop,
|
||||||
|
Popcnt,
|
||||||
|
Por,
|
||||||
|
Pshufd,
|
||||||
|
Psllw,
|
||||||
|
Psrad,
|
||||||
|
Psraw,
|
||||||
|
Psrld,
|
||||||
|
Psrlq,
|
||||||
|
Psrldq,
|
||||||
|
Psrlw,
|
||||||
|
Psubb,
|
||||||
|
Psubd,
|
||||||
|
Psubq,
|
||||||
|
Psubw,
|
||||||
Push,
|
Push,
|
||||||
|
Pxor,
|
||||||
|
Rcpps,
|
||||||
|
Rcpss,
|
||||||
Ror,
|
Ror,
|
||||||
|
Roundpd,
|
||||||
|
Roundps,
|
||||||
|
Roundsd,
|
||||||
|
Roundss,
|
||||||
|
Rsqrtps,
|
||||||
|
Rsqrtss,
|
||||||
Sar,
|
Sar,
|
||||||
Setcc,
|
Setcc,
|
||||||
Shl,
|
Shl,
|
||||||
Shr,
|
Shr,
|
||||||
|
Shufpd,
|
||||||
|
Shufps,
|
||||||
|
Sqrtpd,
|
||||||
|
Sqrtps,
|
||||||
|
Sqrtsd,
|
||||||
|
Sqrtss,
|
||||||
Sub,
|
Sub,
|
||||||
|
Subpd,
|
||||||
|
Subps,
|
||||||
|
Subsd,
|
||||||
|
Subss,
|
||||||
Test,
|
Test,
|
||||||
|
Unpckhpd,
|
||||||
|
Unpckhps,
|
||||||
|
Unpcklpd,
|
||||||
|
Unpcklps,
|
||||||
Xor,
|
Xor,
|
||||||
|
Xorpd,
|
||||||
|
Xorps,
|
||||||
|
|
||||||
Count
|
Count
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,23 @@ namespace ARMeilleure.CodeGen.X86
|
||||||
R12 = 12,
|
R12 = 12,
|
||||||
R13 = 13,
|
R13 = 13,
|
||||||
R14 = 14,
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -24,6 +24,9 @@ namespace ARMeilleure.Decoders
|
||||||
RegisterSize = RegisterSize.Int64;
|
RegisterSize = RegisterSize.Int64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int GetPairsCount() => GetBitsCount() / 16;
|
||||||
|
public int GetBytesCount() => GetBitsCount() / 8;
|
||||||
|
|
||||||
public int GetBitsCount()
|
public int GetBitsCount()
|
||||||
{
|
{
|
||||||
switch (RegisterSize)
|
switch (RegisterSize)
|
||||||
|
|
|
@ -3,7 +3,7 @@ namespace ARMeilleure.Decoders
|
||||||
class OpCodeSimdFmov : OpCode, IOpCodeSimd
|
class OpCodeSimdFmov : OpCode, IOpCodeSimd
|
||||||
{
|
{
|
||||||
public int Rd { get; private set; }
|
public int Rd { get; private set; }
|
||||||
public long Imm { get; private set; }
|
public long Immediate { get; private set; }
|
||||||
public int Size { get; private set; }
|
public int Size { get; private set; }
|
||||||
|
|
||||||
public OpCodeSimdFmov(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCodeSimdFmov(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
||||||
|
@ -25,7 +25,7 @@ namespace ARMeilleure.Decoders
|
||||||
Rd = (opCode >> 0) & 0x1f;
|
Rd = (opCode >> 0) & 0x1f;
|
||||||
imm = (opCode >> 13) & 0xff;
|
imm = (opCode >> 13) & 0xff;
|
||||||
|
|
||||||
Imm = DecoderHelper.DecodeImm8Float(imm, type);
|
Immediate = DecoderHelper.DecodeImm8Float(imm, type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,7 +3,7 @@ namespace ARMeilleure.Decoders
|
||||||
class OpCodeSimdImm : OpCode, IOpCodeSimd
|
class OpCodeSimdImm : OpCode, IOpCodeSimd
|
||||||
{
|
{
|
||||||
public int Rd { get; private set; }
|
public int Rd { get; private set; }
|
||||||
public long Imm { get; private set; }
|
public long Immediate { get; private set; }
|
||||||
public int Size { get; private set; }
|
public int Size { get; private set; }
|
||||||
|
|
||||||
public OpCodeSimdImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
public OpCodeSimdImm(InstDescriptor inst, ulong address, int opCode) : base(inst, address, opCode)
|
||||||
|
@ -76,7 +76,7 @@ namespace ARMeilleure.Decoders
|
||||||
Size = 0;
|
Size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Imm = imm;
|
Immediate = imm;
|
||||||
|
|
||||||
RegisterSize = ((opCode >> 30) & 1) != 0
|
RegisterSize = ((opCode >> 30) & 1) != 0
|
||||||
? RegisterSize.Simd128
|
? RegisterSize.Simd128
|
||||||
|
|
|
@ -190,27 +190,27 @@ namespace ARMeilleure.Decoders
|
||||||
SetA64("10011011110xxxxx0xxxxxxxxxxxxxxx", InstName.Umulh, InstEmit.Umulh, typeof(OpCodeMul));
|
SetA64("10011011110xxxxx0xxxxxxxxxxxxxxx", InstName.Umulh, InstEmit.Umulh, typeof(OpCodeMul));
|
||||||
|
|
||||||
//FP & SIMD
|
//FP & SIMD
|
||||||
SetA64("0101111011100000101110xxxxxxxxxx", InstName.Abs_S, null, typeof(OpCodeSimd));
|
SetA64("0101111011100000101110xxxxxxxxxx", InstName.Abs_S, InstEmit.Abs_S, typeof(OpCodeSimd));
|
||||||
SetA64("0>001110<<100000101110xxxxxxxxxx", InstName.Abs_V, null, typeof(OpCodeSimd));
|
SetA64("0>001110<<100000101110xxxxxxxxxx", InstName.Abs_V, InstEmit.Abs_V, typeof(OpCodeSimd));
|
||||||
SetA64("01011110111xxxxx100001xxxxxxxxxx", InstName.Add_S, null, typeof(OpCodeSimdReg));
|
SetA64("01011110111xxxxx100001xxxxxxxxxx", InstName.Add_S, InstEmit.Add_S, typeof(OpCodeSimdReg));
|
||||||
SetA64("0>001110<<1xxxxx100001xxxxxxxxxx", InstName.Add_V, null, typeof(OpCodeSimdReg));
|
SetA64("0>001110<<1xxxxx100001xxxxxxxxxx", InstName.Add_V, InstEmit.Add_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x001110<<1xxxxx010000xxxxxxxxxx", InstName.Addhn_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x001110<<1xxxxx010000xxxxxxxxxx", InstName.Addhn_V, InstEmit.Addhn_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0101111011110001101110xxxxxxxxxx", InstName.Addp_S, null, typeof(OpCodeSimd));
|
SetA64("0101111011110001101110xxxxxxxxxx", InstName.Addp_S, InstEmit.Addp_S, typeof(OpCodeSimd));
|
||||||
SetA64("0>001110<<1xxxxx101111xxxxxxxxxx", InstName.Addp_V, null, typeof(OpCodeSimdReg));
|
SetA64("0>001110<<1xxxxx101111xxxxxxxxxx", InstName.Addp_V, InstEmit.Addp_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("000011100x110001101110xxxxxxxxxx", InstName.Addv_V, null, typeof(OpCodeSimd));
|
SetA64("000011100x110001101110xxxxxxxxxx", InstName.Addv_V, InstEmit.Addv_V, typeof(OpCodeSimd));
|
||||||
SetA64("01001110<<110001101110xxxxxxxxxx", InstName.Addv_V, null, typeof(OpCodeSimd));
|
SetA64("01001110<<110001101110xxxxxxxxxx", InstName.Addv_V, InstEmit.Addv_V, typeof(OpCodeSimd));
|
||||||
SetA64("0100111000101000010110xxxxxxxxxx", InstName.Aesd_V, null, typeof(OpCodeSimd));
|
SetA64("0100111000101000010110xxxxxxxxxx", InstName.Aesd_V, InstEmit.Aesd_V, typeof(OpCodeSimd));
|
||||||
SetA64("0100111000101000010010xxxxxxxxxx", InstName.Aese_V, null, typeof(OpCodeSimd));
|
SetA64("0100111000101000010010xxxxxxxxxx", InstName.Aese_V, InstEmit.Aese_V, typeof(OpCodeSimd));
|
||||||
SetA64("0100111000101000011110xxxxxxxxxx", InstName.Aesimc_V, null, typeof(OpCodeSimd));
|
SetA64("0100111000101000011110xxxxxxxxxx", InstName.Aesimc_V, InstEmit.Aesimc_V, typeof(OpCodeSimd));
|
||||||
SetA64("0100111000101000011010xxxxxxxxxx", InstName.Aesmc_V, null, typeof(OpCodeSimd));
|
SetA64("0100111000101000011010xxxxxxxxxx", InstName.Aesmc_V, InstEmit.Aesmc_V, typeof(OpCodeSimd));
|
||||||
SetA64("0x001110001xxxxx000111xxxxxxxxxx", InstName.And_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x001110001xxxxx000111xxxxxxxxxx", InstName.And_V, null, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x001110011xxxxx000111xxxxxxxxxx", InstName.Bic_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x001110011xxxxx000111xxxxxxxxxx", InstName.Bic_V, null, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x10111100000xxx<<x101xxxxxxxxxx", InstName.Bic_Vi, null, typeof(OpCodeSimdImm));
|
SetA64("0x10111100000xxx<<x101xxxxxxxxxx", InstName.Bic_Vi, null, typeof(OpCodeSimdImm));
|
||||||
SetA64("0x101110111xxxxx000111xxxxxxxxxx", InstName.Bif_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x101110111xxxxx000111xxxxxxxxxx", InstName.Bif_V, null, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x101110101xxxxx000111xxxxxxxxxx", InstName.Bit_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x101110101xxxxx000111xxxxxxxxxx", InstName.Bit_V, null, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x101110011xxxxx000111xxxxxxxxxx", InstName.Bsl_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x101110011xxxxx000111xxxxxxxxxx", InstName.Bsl_V, null, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x001110<<100000010010xxxxxxxxxx", InstName.Cls_V, null, typeof(OpCodeSimd));
|
SetA64("0x001110<<100000010010xxxxxxxxxx", InstName.Cls_V, InstEmit.Cls_V, typeof(OpCodeSimd));
|
||||||
SetA64("0x101110<<100000010010xxxxxxxxxx", InstName.Clz_V, null, typeof(OpCodeSimd));
|
SetA64("0x101110<<100000010010xxxxxxxxxx", InstName.Clz_V, InstEmit.Clz_V, typeof(OpCodeSimd));
|
||||||
SetA64("01111110111xxxxx100011xxxxxxxxxx", InstName.Cmeq_S, null, typeof(OpCodeSimdReg));
|
SetA64("01111110111xxxxx100011xxxxxxxxxx", InstName.Cmeq_S, null, typeof(OpCodeSimdReg));
|
||||||
SetA64("0101111011100000100110xxxxxxxxxx", InstName.Cmeq_S, null, typeof(OpCodeSimd));
|
SetA64("0101111011100000100110xxxxxxxxxx", InstName.Cmeq_S, null, typeof(OpCodeSimd));
|
||||||
SetA64("0>101110<<1xxxxx100011xxxxxxxxxx", InstName.Cmeq_V, null, typeof(OpCodeSimdReg));
|
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("0>001110<<100000101010xxxxxxxxxx", InstName.Cmlt_V, null, typeof(OpCodeSimd));
|
||||||
SetA64("01011110111xxxxx100011xxxxxxxxxx", InstName.Cmtst_S, null, typeof(OpCodeSimdReg));
|
SetA64("01011110111xxxxx100011xxxxxxxxxx", InstName.Cmtst_S, null, typeof(OpCodeSimdReg));
|
||||||
SetA64("0>001110<<1xxxxx100011xxxxxxxxxx", InstName.Cmtst_V, 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("0>001110000x<>>>000011xxxxxxxxxx", InstName.Dup_Gp, null, typeof(OpCodeSimdIns));
|
||||||
SetA64("01011110000xxxxx000001xxxxxxxxxx", InstName.Dup_S, null, typeof(OpCodeSimdIns));
|
SetA64("01011110000xxxxx000001xxxxxxxxxx", InstName.Dup_S, null, typeof(OpCodeSimdIns));
|
||||||
SetA64("0>001110000x<>>>000001xxxxxxxxxx", InstName.Dup_V, null, typeof(OpCodeSimdIns));
|
SetA64("0>001110000x<>>>000001xxxxxxxxxx", InstName.Dup_V, null, typeof(OpCodeSimdIns));
|
||||||
SetA64("0x101110001xxxxx000111xxxxxxxxxx", InstName.Eor_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x101110001xxxxx000111xxxxxxxxxx", InstName.Eor_V, null, typeof(OpCodeSimdReg));
|
||||||
SetA64("0>101110000xxxxx0<xxx0xxxxxxxxxx", InstName.Ext_V, null, typeof(OpCodeSimdExt));
|
SetA64("0>101110000xxxxx0<xxx0xxxxxxxxxx", InstName.Ext_V, null, typeof(OpCodeSimdExt));
|
||||||
SetA64("011111101x1xxxxx110101xxxxxxxxxx", InstName.Fabd_S, null, typeof(OpCodeSimdReg));
|
SetA64("011111101x1xxxxx110101xxxxxxxxxx", InstName.Fabd_S, InstEmit.Fabd_S, typeof(OpCodeSimdReg));
|
||||||
SetA64("0>1011101<1xxxxx110101xxxxxxxxxx", InstName.Fabd_V, null, typeof(OpCodeSimdReg));
|
SetA64("0>1011101<1xxxxx110101xxxxxxxxxx", InstName.Fabd_V, InstEmit.Fabd_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("000111100x100000110000xxxxxxxxxx", InstName.Fabs_S, null, typeof(OpCodeSimd));
|
SetA64("000111100x100000110000xxxxxxxxxx", InstName.Fabs_S, InstEmit.Fabs_S, typeof(OpCodeSimd));
|
||||||
SetA64("0>0011101<100000111110xxxxxxxxxx", InstName.Fabs_V, null, typeof(OpCodeSimd));
|
SetA64("0>0011101<100000111110xxxxxxxxxx", InstName.Fabs_V, InstEmit.Fabs_V, typeof(OpCodeSimd));
|
||||||
SetA64("000111100x1xxxxx001010xxxxxxxxxx", InstName.Fadd_S, null, typeof(OpCodeSimdReg));
|
SetA64("000111100x1xxxxx001010xxxxxxxxxx", InstName.Fadd_S, InstEmit.Fadd_S, typeof(OpCodeSimdReg));
|
||||||
SetA64("0>0011100<1xxxxx110101xxxxxxxxxx", InstName.Fadd_V, null, typeof(OpCodeSimdReg));
|
SetA64("0>0011100<1xxxxx110101xxxxxxxxxx", InstName.Fadd_V, InstEmit.Fadd_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("011111100x110000110110xxxxxxxxxx", InstName.Faddp_S, null, typeof(OpCodeSimd));
|
SetA64("011111100x110000110110xxxxxxxxxx", InstName.Faddp_S, InstEmit.Faddp_S, typeof(OpCodeSimd));
|
||||||
SetA64("0>1011100<1xxxxx110101xxxxxxxxxx", InstName.Faddp_V, null, typeof(OpCodeSimdReg));
|
SetA64("0>1011100<1xxxxx110101xxxxxxxxxx", InstName.Faddp_V, InstEmit.Faddp_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("000111100x1xxxxxxxxx01xxxxx0xxxx", InstName.Fccmp_S, null, typeof(OpCodeSimdFcond));
|
SetA64("000111100x1xxxxxxxxx01xxxxx0xxxx", InstName.Fccmp_S, null, typeof(OpCodeSimdFcond));
|
||||||
SetA64("000111100x1xxxxxxxxx01xxxxx1xxxx", InstName.Fccmpe_S, null, typeof(OpCodeSimdFcond));
|
SetA64("000111100x1xxxxxxxxx01xxxxx1xxxx", InstName.Fccmpe_S, null, typeof(OpCodeSimdFcond));
|
||||||
SetA64("010111100x1xxxxx111001xxxxxxxxxx", InstName.Fcmeq_S, null, typeof(OpCodeSimdReg));
|
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("0>1011101<100001101110xxxxxxxxxx", InstName.Fcvtzu_V, null, typeof(OpCodeSimd));
|
||||||
SetA64("0x101111001xxxxx111111xxxxxxxxxx", InstName.Fcvtzu_V_Fixed, null, typeof(OpCodeSimdShImm));
|
SetA64("0x101111001xxxxx111111xxxxxxxxxx", InstName.Fcvtzu_V_Fixed, null, typeof(OpCodeSimdShImm));
|
||||||
SetA64("0110111101xxxxxx111111xxxxxxxxxx", 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("000111100x1xxxxx000110xxxxxxxxxx", InstName.Fdiv_S, InstEmit.Fdiv_S, typeof(OpCodeSimdReg));
|
||||||
SetA64("0>1011100<1xxxxx111111xxxxxxxxxx", InstName.Fdiv_V, null, typeof(OpCodeSimdReg));
|
SetA64("0>1011100<1xxxxx111111xxxxxxxxxx", InstName.Fdiv_V, InstEmit.Fdiv_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("000111110x0xxxxx0xxxxxxxxxxxxxxx", InstName.Fmadd_S, null, typeof(OpCodeSimdReg));
|
SetA64("000111110x0xxxxx0xxxxxxxxxxxxxxx", InstName.Fmadd_S, InstEmit.Fmadd_S, typeof(OpCodeSimdReg));
|
||||||
SetA64("000111100x1xxxxx010010xxxxxxxxxx", InstName.Fmax_S, null, typeof(OpCodeSimdReg));
|
SetA64("000111100x1xxxxx010010xxxxxxxxxx", InstName.Fmax_S, InstEmit.Fmax_S, typeof(OpCodeSimdReg));
|
||||||
SetA64("0>0011100<1xxxxx111101xxxxxxxxxx", InstName.Fmax_V, null, typeof(OpCodeSimdReg));
|
SetA64("0>0011100<1xxxxx111101xxxxxxxxxx", InstName.Fmax_V, InstEmit.Fmax_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("000111100x1xxxxx011010xxxxxxxxxx", InstName.Fmaxnm_S, null, typeof(OpCodeSimdReg));
|
SetA64("000111100x1xxxxx011010xxxxxxxxxx", InstName.Fmaxnm_S, InstEmit.Fmaxnm_S, typeof(OpCodeSimdReg));
|
||||||
SetA64("0>0011100<1xxxxx110001xxxxxxxxxx", InstName.Fmaxnm_V, null, typeof(OpCodeSimdReg));
|
SetA64("0>0011100<1xxxxx110001xxxxxxxxxx", InstName.Fmaxnm_V, InstEmit.Fmaxnm_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0>1011100<1xxxxx111101xxxxxxxxxx", InstName.Fmaxp_V, null, typeof(OpCodeSimdReg));
|
SetA64("0>1011100<1xxxxx111101xxxxxxxxxx", InstName.Fmaxp_V, InstEmit.Fmaxp_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("000111100x1xxxxx010110xxxxxxxxxx", InstName.Fmin_S, null, typeof(OpCodeSimdReg));
|
SetA64("000111100x1xxxxx010110xxxxxxxxxx", InstName.Fmin_S, InstEmit.Fmin_S, typeof(OpCodeSimdReg));
|
||||||
SetA64("0>0011101<1xxxxx111101xxxxxxxxxx", InstName.Fmin_V, null, typeof(OpCodeSimdReg));
|
SetA64("0>0011101<1xxxxx111101xxxxxxxxxx", InstName.Fmin_V, InstEmit.Fmin_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("000111100x1xxxxx011110xxxxxxxxxx", InstName.Fminnm_S, null, typeof(OpCodeSimdReg));
|
SetA64("000111100x1xxxxx011110xxxxxxxxxx", InstName.Fminnm_S, InstEmit.Fminnm_S, typeof(OpCodeSimdReg));
|
||||||
SetA64("0>0011101<1xxxxx110001xxxxxxxxxx", InstName.Fminnm_V, null, typeof(OpCodeSimdReg));
|
SetA64("0>0011101<1xxxxx110001xxxxxxxxxx", InstName.Fminnm_V, InstEmit.Fminnm_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0>1011101<1xxxxx111101xxxxxxxxxx", InstName.Fminp_V, null, typeof(OpCodeSimdReg));
|
SetA64("0>1011101<1xxxxx111101xxxxxxxxxx", InstName.Fminp_V, InstEmit.Fminp_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("010111111xxxxxxx0001x0xxxxxxxxxx", InstName.Fmla_Se, null, typeof(OpCodeSimdRegElemF));
|
SetA64("010111111xxxxxxx0001x0xxxxxxxxxx", InstName.Fmla_Se, InstEmit.Fmla_Se, typeof(OpCodeSimdRegElemF));
|
||||||
SetA64("0>0011100<1xxxxx110011xxxxxxxxxx", InstName.Fmla_V, null, typeof(OpCodeSimdReg));
|
SetA64("0>0011100<1xxxxx110011xxxxxxxxxx", InstName.Fmla_V, InstEmit.Fmla_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0>0011111<xxxxxx0001x0xxxxxxxxxx", InstName.Fmla_Ve, null, typeof(OpCodeSimdRegElemF));
|
SetA64("0>0011111<xxxxxx0001x0xxxxxxxxxx", InstName.Fmla_Ve, InstEmit.Fmla_Ve, typeof(OpCodeSimdRegElemF));
|
||||||
SetA64("010111111xxxxxxx0101x0xxxxxxxxxx", InstName.Fmls_Se, null, typeof(OpCodeSimdRegElemF));
|
SetA64("010111111xxxxxxx0101x0xxxxxxxxxx", InstName.Fmls_Se, InstEmit.Fmls_Se, typeof(OpCodeSimdRegElemF));
|
||||||
SetA64("0>0011101<1xxxxx110011xxxxxxxxxx", InstName.Fmls_V, null, typeof(OpCodeSimdReg));
|
SetA64("0>0011101<1xxxxx110011xxxxxxxxxx", InstName.Fmls_V, InstEmit.Fmls_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0>0011111<xxxxxx0101x0xxxxxxxxxx", InstName.Fmls_Ve, null, typeof(OpCodeSimdRegElemF));
|
SetA64("0>0011111<xxxxxx0101x0xxxxxxxxxx", InstName.Fmls_Ve, InstEmit.Fmls_Ve, typeof(OpCodeSimdRegElemF));
|
||||||
SetA64("000111100x100000010000xxxxxxxxxx", InstName.Fmov_S, null, typeof(OpCodeSimd));
|
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("0xx0111100000xxx111101xxxxxxxxxx", InstName.Fmov_V, null, typeof(OpCodeSimdImm));
|
||||||
SetA64("x00111100x100110000000xxxxxxxxxx", InstName.Fmov_Ftoi, null, typeof(OpCodeSimdCvt));
|
SetA64("x00111100x100110000000xxxxxxxxxx", InstName.Fmov_Ftoi, null, typeof(OpCodeSimdCvt));
|
||||||
SetA64("x00111100x100111000000xxxxxxxxxx", InstName.Fmov_Itof, null, typeof(OpCodeSimdCvt));
|
SetA64("x00111100x100111000000xxxxxxxxxx", InstName.Fmov_Itof, null, typeof(OpCodeSimdCvt));
|
||||||
SetA64("1001111010101110000000xxxxxxxxxx", InstName.Fmov_Ftoi1, null, typeof(OpCodeSimdCvt));
|
SetA64("1001111010101110000000xxxxxxxxxx", InstName.Fmov_Ftoi1, null, typeof(OpCodeSimdCvt));
|
||||||
SetA64("1001111010101111000000xxxxxxxxxx", InstName.Fmov_Itof1, null, typeof(OpCodeSimdCvt));
|
SetA64("1001111010101111000000xxxxxxxxxx", InstName.Fmov_Itof1, null, typeof(OpCodeSimdCvt));
|
||||||
SetA64("000111110x0xxxxx1xxxxxxxxxxxxxxx", InstName.Fmsub_S, null, typeof(OpCodeSimdReg));
|
SetA64("000111110x0xxxxx1xxxxxxxxxxxxxxx", InstName.Fmsub_S, InstEmit.Fmsub_S, typeof(OpCodeSimdReg));
|
||||||
SetA64("000111100x1xxxxx000010xxxxxxxxxx", InstName.Fmul_S, null, typeof(OpCodeSimdReg));
|
SetA64("000111100x1xxxxx000010xxxxxxxxxx", InstName.Fmul_S, InstEmit.Fmul_S, typeof(OpCodeSimdReg));
|
||||||
SetA64("010111111xxxxxxx1001x0xxxxxxxxxx", InstName.Fmul_Se, null, typeof(OpCodeSimdRegElemF));
|
SetA64("010111111xxxxxxx1001x0xxxxxxxxxx", InstName.Fmul_Se, InstEmit.Fmul_Se, typeof(OpCodeSimdRegElemF));
|
||||||
SetA64("0>1011100<1xxxxx110111xxxxxxxxxx", InstName.Fmul_V, null, typeof(OpCodeSimdReg));
|
SetA64("0>1011100<1xxxxx110111xxxxxxxxxx", InstName.Fmul_V, InstEmit.Fmul_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0>0011111<xxxxxx1001x0xxxxxxxxxx", InstName.Fmul_Ve, null, typeof(OpCodeSimdRegElemF));
|
SetA64("0>0011111<xxxxxx1001x0xxxxxxxxxx", InstName.Fmul_Ve, InstEmit.Fmul_Ve, typeof(OpCodeSimdRegElemF));
|
||||||
SetA64("010111100x1xxxxx110111xxxxxxxxxx", InstName.Fmulx_S, null, typeof(OpCodeSimdReg));
|
SetA64("010111100x1xxxxx110111xxxxxxxxxx", InstName.Fmulx_S, InstEmit.Fmulx_S, typeof(OpCodeSimdReg));
|
||||||
SetA64("011111111xxxxxxx1001x0xxxxxxxxxx", InstName.Fmulx_Se, null, typeof(OpCodeSimdRegElemF));
|
SetA64("011111111xxxxxxx1001x0xxxxxxxxxx", InstName.Fmulx_Se, InstEmit.Fmulx_Se, typeof(OpCodeSimdRegElemF));
|
||||||
SetA64("0>0011100<1xxxxx110111xxxxxxxxxx", InstName.Fmulx_V, null, typeof(OpCodeSimdReg));
|
SetA64("0>0011100<1xxxxx110111xxxxxxxxxx", InstName.Fmulx_V, InstEmit.Fmulx_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0>1011111<xxxxxx1001x0xxxxxxxxxx", InstName.Fmulx_Ve, null, typeof(OpCodeSimdRegElemF));
|
SetA64("0>1011111<xxxxxx1001x0xxxxxxxxxx", InstName.Fmulx_Ve, InstEmit.Fmulx_Ve, typeof(OpCodeSimdRegElemF));
|
||||||
SetA64("000111100x100001010000xxxxxxxxxx", InstName.Fneg_S, null, typeof(OpCodeSimd));
|
SetA64("000111100x100001010000xxxxxxxxxx", InstName.Fneg_S, InstEmit.Fneg_S, typeof(OpCodeSimd));
|
||||||
SetA64("0>1011101<100000111110xxxxxxxxxx", InstName.Fneg_V, null, typeof(OpCodeSimd));
|
SetA64("0>1011101<100000111110xxxxxxxxxx", InstName.Fneg_V, InstEmit.Fneg_V, typeof(OpCodeSimd));
|
||||||
SetA64("000111110x1xxxxx0xxxxxxxxxxxxxxx", InstName.Fnmadd_S, null, typeof(OpCodeSimdReg));
|
SetA64("000111110x1xxxxx0xxxxxxxxxxxxxxx", InstName.Fnmadd_S, InstEmit.Fnmadd_S, typeof(OpCodeSimdReg));
|
||||||
SetA64("000111110x1xxxxx1xxxxxxxxxxxxxxx", InstName.Fnmsub_S, null, typeof(OpCodeSimdReg));
|
SetA64("000111110x1xxxxx1xxxxxxxxxxxxxxx", InstName.Fnmsub_S, InstEmit.Fnmsub_S, typeof(OpCodeSimdReg));
|
||||||
SetA64("000111100x1xxxxx100010xxxxxxxxxx", InstName.Fnmul_S, null, typeof(OpCodeSimdReg));
|
SetA64("000111100x1xxxxx100010xxxxxxxxxx", InstName.Fnmul_S, InstEmit.Fnmul_S, typeof(OpCodeSimdReg));
|
||||||
SetA64("010111101x100001110110xxxxxxxxxx", InstName.Frecpe_S, null, typeof(OpCodeSimd));
|
SetA64("010111101x100001110110xxxxxxxxxx", InstName.Frecpe_S, InstEmit.Frecpe_S, typeof(OpCodeSimd));
|
||||||
SetA64("0>0011101<100001110110xxxxxxxxxx", InstName.Frecpe_V, null, typeof(OpCodeSimd));
|
SetA64("0>0011101<100001110110xxxxxxxxxx", InstName.Frecpe_V, InstEmit.Frecpe_V, typeof(OpCodeSimd));
|
||||||
SetA64("010111100x1xxxxx111111xxxxxxxxxx", InstName.Frecps_S, null, typeof(OpCodeSimdReg));
|
SetA64("010111100x1xxxxx111111xxxxxxxxxx", InstName.Frecps_S, InstEmit.Frecps_S, typeof(OpCodeSimdReg));
|
||||||
SetA64("0>0011100<1xxxxx111111xxxxxxxxxx", InstName.Frecps_V, null, typeof(OpCodeSimdReg));
|
SetA64("0>0011100<1xxxxx111111xxxxxxxxxx", InstName.Frecps_V, InstEmit.Frecps_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("010111101x100001111110xxxxxxxxxx", InstName.Frecpx_S, null, typeof(OpCodeSimd));
|
SetA64("010111101x100001111110xxxxxxxxxx", InstName.Frecpx_S, InstEmit.Frecpx_S, typeof(OpCodeSimd));
|
||||||
SetA64("000111100x100110010000xxxxxxxxxx", InstName.Frinta_S, null, typeof(OpCodeSimd));
|
SetA64("000111100x100110010000xxxxxxxxxx", InstName.Frinta_S, InstEmit.Frinta_S, typeof(OpCodeSimd));
|
||||||
SetA64("0>1011100<100001100010xxxxxxxxxx", InstName.Frinta_V, null, typeof(OpCodeSimd));
|
SetA64("0>1011100<100001100010xxxxxxxxxx", InstName.Frinta_V, InstEmit.Frinta_V, typeof(OpCodeSimd));
|
||||||
SetA64("000111100x100111110000xxxxxxxxxx", InstName.Frinti_S, null, typeof(OpCodeSimd));
|
SetA64("000111100x100111110000xxxxxxxxxx", InstName.Frinti_S, InstEmit.Frinti_S, typeof(OpCodeSimd));
|
||||||
SetA64("0>1011101<100001100110xxxxxxxxxx", InstName.Frinti_V, null, typeof(OpCodeSimd));
|
SetA64("0>1011101<100001100110xxxxxxxxxx", InstName.Frinti_V, InstEmit.Frinti_V, typeof(OpCodeSimd));
|
||||||
SetA64("000111100x100101010000xxxxxxxxxx", InstName.Frintm_S, null, typeof(OpCodeSimd));
|
SetA64("000111100x100101010000xxxxxxxxxx", InstName.Frintm_S, InstEmit.Frintm_S, typeof(OpCodeSimd));
|
||||||
SetA64("0>0011100<100001100110xxxxxxxxxx", InstName.Frintm_V, null, typeof(OpCodeSimd));
|
SetA64("0>0011100<100001100110xxxxxxxxxx", InstName.Frintm_V, InstEmit.Frintm_V, typeof(OpCodeSimd));
|
||||||
SetA64("000111100x100100010000xxxxxxxxxx", InstName.Frintn_S, null, typeof(OpCodeSimd));
|
SetA64("000111100x100100010000xxxxxxxxxx", InstName.Frintn_S, InstEmit.Frintn_S, typeof(OpCodeSimd));
|
||||||
SetA64("0>0011100<100001100010xxxxxxxxxx", InstName.Frintn_V, null, typeof(OpCodeSimd));
|
SetA64("0>0011100<100001100010xxxxxxxxxx", InstName.Frintn_V, InstEmit.Frintn_V, typeof(OpCodeSimd));
|
||||||
SetA64("000111100x100100110000xxxxxxxxxx", InstName.Frintp_S, null, typeof(OpCodeSimd));
|
SetA64("000111100x100100110000xxxxxxxxxx", InstName.Frintp_S, InstEmit.Frintp_S, typeof(OpCodeSimd));
|
||||||
SetA64("0>0011101<100001100010xxxxxxxxxx", InstName.Frintp_V, null, typeof(OpCodeSimd));
|
SetA64("0>0011101<100001100010xxxxxxxxxx", InstName.Frintp_V, InstEmit.Frintp_V, typeof(OpCodeSimd));
|
||||||
SetA64("000111100x100111010000xxxxxxxxxx", InstName.Frintx_S, null, typeof(OpCodeSimd));
|
SetA64("000111100x100111010000xxxxxxxxxx", InstName.Frintx_S, InstEmit.Frintx_S, typeof(OpCodeSimd));
|
||||||
SetA64("0>1011100<100001100110xxxxxxxxxx", InstName.Frintx_V, null, typeof(OpCodeSimd));
|
SetA64("0>1011100<100001100110xxxxxxxxxx", InstName.Frintx_V, InstEmit.Frintx_V, typeof(OpCodeSimd));
|
||||||
SetA64("000111100x100101110000xxxxxxxxxx", InstName.Frintz_S, null, typeof(OpCodeSimd));
|
SetA64("000111100x100101110000xxxxxxxxxx", InstName.Frintz_S, InstEmit.Frintz_S, typeof(OpCodeSimd));
|
||||||
SetA64("0>0011101<100001100110xxxxxxxxxx", InstName.Frintz_V, null, typeof(OpCodeSimd));
|
SetA64("0>0011101<100001100110xxxxxxxxxx", InstName.Frintz_V, InstEmit.Frintz_V, typeof(OpCodeSimd));
|
||||||
SetA64("011111101x100001110110xxxxxxxxxx", InstName.Frsqrte_S, null, typeof(OpCodeSimd));
|
SetA64("011111101x100001110110xxxxxxxxxx", InstName.Frsqrte_S, InstEmit.Frsqrte_S, typeof(OpCodeSimd));
|
||||||
SetA64("0>1011101<100001110110xxxxxxxxxx", InstName.Frsqrte_V, null, typeof(OpCodeSimd));
|
SetA64("0>1011101<100001110110xxxxxxxxxx", InstName.Frsqrte_V, InstEmit.Frsqrte_V, typeof(OpCodeSimd));
|
||||||
SetA64("010111101x1xxxxx111111xxxxxxxxxx", InstName.Frsqrts_S, null, typeof(OpCodeSimdReg));
|
SetA64("010111101x1xxxxx111111xxxxxxxxxx", InstName.Frsqrts_S, InstEmit.Frsqrts_S, typeof(OpCodeSimdReg));
|
||||||
SetA64("0>0011101<1xxxxx111111xxxxxxxxxx", InstName.Frsqrts_V, null, typeof(OpCodeSimdReg));
|
SetA64("0>0011101<1xxxxx111111xxxxxxxxxx", InstName.Frsqrts_V, InstEmit.Frsqrts_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("000111100x100001110000xxxxxxxxxx", InstName.Fsqrt_S, null, typeof(OpCodeSimd));
|
SetA64("000111100x100001110000xxxxxxxxxx", InstName.Fsqrt_S, InstEmit.Fsqrt_S, typeof(OpCodeSimd));
|
||||||
SetA64("0>1011101<100001111110xxxxxxxxxx", InstName.Fsqrt_V, null, typeof(OpCodeSimd));
|
SetA64("0>1011101<100001111110xxxxxxxxxx", InstName.Fsqrt_V, InstEmit.Fsqrt_V, typeof(OpCodeSimd));
|
||||||
SetA64("000111100x1xxxxx001110xxxxxxxxxx", InstName.Fsub_S, null, typeof(OpCodeSimdReg));
|
SetA64("000111100x1xxxxx001110xxxxxxxxxx", InstName.Fsub_S, InstEmit.Fsub_S, typeof(OpCodeSimdReg));
|
||||||
SetA64("0>0011101<1xxxxx110101xxxxxxxxxx", InstName.Fsub_V, null, typeof(OpCodeSimdReg));
|
SetA64("0>0011101<1xxxxx110101xxxxxxxxxx", InstName.Fsub_V, InstEmit.Fsub_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("01001110000xxxxx000111xxxxxxxxxx", InstName.Ins_Gp, null, typeof(OpCodeSimdIns));
|
SetA64("01001110000xxxxx000111xxxxxxxxxx", InstName.Ins_Gp, null, typeof(OpCodeSimdIns));
|
||||||
SetA64("01101110000xxxxx0xxxx1xxxxxxxxxx", InstName.Ins_V, null, typeof(OpCodeSimdIns));
|
SetA64("01101110000xxxxx0xxxx1xxxxxxxxxx", InstName.Ins_V, null, typeof(OpCodeSimdIns));
|
||||||
SetA64("0x00110001000000xxxxxxxxxxxxxxxx", InstName.Ld__Vms, null, typeof(OpCodeSimdMemMs));
|
SetA64("0x00110001000000xxxxxxxxxxxxxxxx", InstName.Ld__Vms, null, typeof(OpCodeSimdMemMs));
|
||||||
|
@ -373,40 +373,40 @@ namespace ARMeilleure.Decoders
|
||||||
SetA64("xx111101x1xxxxxxxxxxxxxxxxxxxxxx", InstName.Ldr, null, typeof(OpCodeSimdMemImm));
|
SetA64("xx111101x1xxxxxxxxxxxxxxxxxxxxxx", InstName.Ldr, null, typeof(OpCodeSimdMemImm));
|
||||||
SetA64("xx111100x11xxxxxxxxx10xxxxxxxxxx", InstName.Ldr, null, typeof(OpCodeSimdMemReg));
|
SetA64("xx111100x11xxxxxxxxx10xxxxxxxxxx", InstName.Ldr, null, typeof(OpCodeSimdMemReg));
|
||||||
SetA64("xx011100xxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ldr_Literal, null, typeof(OpCodeSimdMemLit));
|
SetA64("xx011100xxxxxxxxxxxxxxxxxxxxxxxx", InstName.Ldr_Literal, null, typeof(OpCodeSimdMemLit));
|
||||||
SetA64("0x001110<<1xxxxx100101xxxxxxxxxx", InstName.Mla_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x001110<<1xxxxx100101xxxxxxxxxx", InstName.Mla_V, InstEmit.Mla_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x101111xxxxxxxx0000x0xxxxxxxxxx", InstName.Mla_Ve, null, typeof(OpCodeSimdRegElem));
|
SetA64("0x101111xxxxxxxx0000x0xxxxxxxxxx", InstName.Mla_Ve, InstEmit.Mla_Ve, typeof(OpCodeSimdRegElem));
|
||||||
SetA64("0x101110<<1xxxxx100101xxxxxxxxxx", InstName.Mls_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x101110<<1xxxxx100101xxxxxxxxxx", InstName.Mls_V, InstEmit.Mls_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x101111xxxxxxxx0100x0xxxxxxxxxx", InstName.Mls_Ve, null, typeof(OpCodeSimdRegElem));
|
SetA64("0x101111xxxxxxxx0100x0xxxxxxxxxx", InstName.Mls_Ve, InstEmit.Mls_Ve, typeof(OpCodeSimdRegElem));
|
||||||
SetA64("0x00111100000xxx0xx001xxxxxxxxxx", InstName.Movi_V, null, typeof(OpCodeSimdImm));
|
SetA64("0x00111100000xxx0xx001xxxxxxxxxx", InstName.Movi_V, null, typeof(OpCodeSimdImm));
|
||||||
SetA64("0x00111100000xxx10x001xxxxxxxxxx", InstName.Movi_V, null, typeof(OpCodeSimdImm));
|
SetA64("0x00111100000xxx10x001xxxxxxxxxx", InstName.Movi_V, null, typeof(OpCodeSimdImm));
|
||||||
SetA64("0x00111100000xxx110x01xxxxxxxxxx", InstName.Movi_V, null, typeof(OpCodeSimdImm));
|
SetA64("0x00111100000xxx110x01xxxxxxxxxx", InstName.Movi_V, null, typeof(OpCodeSimdImm));
|
||||||
SetA64("0xx0111100000xxx111001xxxxxxxxxx", InstName.Movi_V, null, typeof(OpCodeSimdImm));
|
SetA64("0xx0111100000xxx111001xxxxxxxxxx", InstName.Movi_V, null, typeof(OpCodeSimdImm));
|
||||||
SetA64("0x001110<<1xxxxx100111xxxxxxxxxx", InstName.Mul_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x001110<<1xxxxx100111xxxxxxxxxx", InstName.Mul_V, InstEmit.Mul_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x001111xxxxxxxx1000x0xxxxxxxxxx", InstName.Mul_Ve, null, typeof(OpCodeSimdRegElem));
|
SetA64("0x001111xxxxxxxx1000x0xxxxxxxxxx", InstName.Mul_Ve, InstEmit.Mul_Ve, typeof(OpCodeSimdRegElem));
|
||||||
SetA64("0x10111100000xxx0xx001xxxxxxxxxx", InstName.Mvni_V, null, typeof(OpCodeSimdImm));
|
SetA64("0x10111100000xxx0xx001xxxxxxxxxx", InstName.Mvni_V, null, typeof(OpCodeSimdImm));
|
||||||
SetA64("0x10111100000xxx10x001xxxxxxxxxx", InstName.Mvni_V, null, typeof(OpCodeSimdImm));
|
SetA64("0x10111100000xxx10x001xxxxxxxxxx", InstName.Mvni_V, null, typeof(OpCodeSimdImm));
|
||||||
SetA64("0x10111100000xxx110x01xxxxxxxxxx", InstName.Mvni_V, null, typeof(OpCodeSimdImm));
|
SetA64("0x10111100000xxx110x01xxxxxxxxxx", InstName.Mvni_V, null, typeof(OpCodeSimdImm));
|
||||||
SetA64("0111111011100000101110xxxxxxxxxx", InstName.Neg_S, null, typeof(OpCodeSimd));
|
SetA64("0111111011100000101110xxxxxxxxxx", InstName.Neg_S, InstEmit.Neg_S, typeof(OpCodeSimd));
|
||||||
SetA64("0>101110<<100000101110xxxxxxxxxx", InstName.Neg_V, null, typeof(OpCodeSimd));
|
SetA64("0>101110<<100000101110xxxxxxxxxx", InstName.Neg_V, InstEmit.Neg_V, typeof(OpCodeSimd));
|
||||||
SetA64("0x10111000100000010110xxxxxxxxxx", InstName.Not_V, null, typeof(OpCodeSimd));
|
SetA64("0x10111000100000010110xxxxxxxxxx", InstName.Not_V, null, typeof(OpCodeSimd));
|
||||||
SetA64("0x001110111xxxxx000111xxxxxxxxxx", InstName.Orn_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x001110111xxxxx000111xxxxxxxxxx", InstName.Orn_V, null, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x001110101xxxxx000111xxxxxxxxxx", InstName.Orr_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x001110101xxxxx000111xxxxxxxxxx", InstName.Orr_V, null, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x00111100000xxx<<x101xxxxxxxxxx", InstName.Orr_Vi, null, typeof(OpCodeSimdImm));
|
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("0x10111001100000010110xxxxxxxxxx", InstName.Rbit_V, null, typeof(OpCodeSimd));
|
||||||
SetA64("0x00111000100000000110xxxxxxxxxx", InstName.Rev16_V, null, typeof(OpCodeSimd));
|
SetA64("0x00111000100000000110xxxxxxxxxx", InstName.Rev16_V, null, typeof(OpCodeSimd));
|
||||||
SetA64("0x1011100x100000000010xxxxxxxxxx", InstName.Rev32_V, null, typeof(OpCodeSimd));
|
SetA64("0x1011100x100000000010xxxxxxxxxx", InstName.Rev32_V, null, typeof(OpCodeSimd));
|
||||||
SetA64("0x001110<<100000000010xxxxxxxxxx", InstName.Rev64_V, null, typeof(OpCodeSimd));
|
SetA64("0x001110<<100000000010xxxxxxxxxx", InstName.Rev64_V, null, typeof(OpCodeSimd));
|
||||||
SetA64("0x00111100>>>xxx100011xxxxxxxxxx", InstName.Rshrn_V, null, typeof(OpCodeSimdShImm));
|
SetA64("0x00111100>>>xxx100011xxxxxxxxxx", InstName.Rshrn_V, null, typeof(OpCodeSimdShImm));
|
||||||
SetA64("0x101110<<1xxxxx011000xxxxxxxxxx", InstName.Rsubhn_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x101110<<1xxxxx011000xxxxxxxxxx", InstName.Rsubhn_V, InstEmit.Rsubhn_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x001110<<1xxxxx011111xxxxxxxxxx", InstName.Saba_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x001110<<1xxxxx011111xxxxxxxxxx", InstName.Saba_V, InstEmit.Saba_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x001110<<1xxxxx010100xxxxxxxxxx", InstName.Sabal_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x001110<<1xxxxx010100xxxxxxxxxx", InstName.Sabal_V, InstEmit.Sabal_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x001110<<1xxxxx011101xxxxxxxxxx", InstName.Sabd_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x001110<<1xxxxx011101xxxxxxxxxx", InstName.Sabd_V, InstEmit.Sabd_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x001110<<1xxxxx011100xxxxxxxxxx", InstName.Sabdl_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x001110<<1xxxxx011100xxxxxxxxxx", InstName.Sabdl_V, InstEmit.Sabdl_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x001110<<100000011010xxxxxxxxxx", InstName.Sadalp_V, null, typeof(OpCodeSimd));
|
SetA64("0x001110<<100000011010xxxxxxxxxx", InstName.Sadalp_V, InstEmit.Sadalp_V, typeof(OpCodeSimd));
|
||||||
SetA64("0x001110<<1xxxxx000000xxxxxxxxxx", InstName.Saddl_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x001110<<1xxxxx000000xxxxxxxxxx", InstName.Saddl_V, InstEmit.Saddl_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x001110<<100000001010xxxxxxxxxx", InstName.Saddlp_V, null, typeof(OpCodeSimd));
|
SetA64("0x001110<<100000001010xxxxxxxxxx", InstName.Saddlp_V, InstEmit.Saddlp_V, typeof(OpCodeSimd));
|
||||||
SetA64("0x001110<<1xxxxx000100xxxxxxxxxx", InstName.Saddw_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x001110<<1xxxxx000100xxxxxxxxxx", InstName.Saddw_V, InstEmit.Saddw_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("x00111100x100010000000xxxxxxxxxx", InstName.Scvtf_Gp, null, typeof(OpCodeSimdCvt));
|
SetA64("x00111100x100010000000xxxxxxxxxx", InstName.Scvtf_Gp, null, typeof(OpCodeSimdCvt));
|
||||||
SetA64(">00111100x000010>xxxxxxxxxxxxxxx", InstName.Scvtf_Gp_Fixed, null, typeof(OpCodeSimdCvt));
|
SetA64(">00111100x000010>xxxxxxxxxxxxxxx", InstName.Scvtf_Gp_Fixed, null, typeof(OpCodeSimdCvt));
|
||||||
SetA64("010111100x100001110110xxxxxxxxxx", InstName.Scvtf_S, null, typeof(OpCodeSimd));
|
SetA64("010111100x100001110110xxxxxxxxxx", InstName.Scvtf_S, null, typeof(OpCodeSimd));
|
||||||
|
@ -421,39 +421,43 @@ namespace ARMeilleure.Decoders
|
||||||
SetA64("01011110000xxxxx010100xxxxxxxxxx", InstName.Sha256h2_V, null, typeof(OpCodeSimdReg));
|
SetA64("01011110000xxxxx010100xxxxxxxxxx", InstName.Sha256h2_V, null, typeof(OpCodeSimdReg));
|
||||||
SetA64("0101111000101000001010xxxxxxxxxx", InstName.Sha256su0_V, null, typeof(OpCodeSimd));
|
SetA64("0101111000101000001010xxxxxxxxxx", InstName.Sha256su0_V, null, typeof(OpCodeSimd));
|
||||||
SetA64("01011110000xxxxx011000xxxxxxxxxx", InstName.Sha256su1_V, null, typeof(OpCodeSimdReg));
|
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("0101111101xxxxxx010101xxxxxxxxxx", InstName.Shl_S, null, typeof(OpCodeSimdShImm));
|
||||||
SetA64("0x00111100>>>xxx010101xxxxxxxxxx", InstName.Shl_V, null, typeof(OpCodeSimdShImm));
|
SetA64("0x00111100>>>xxx010101xxxxxxxxxx", InstName.Shl_V, null, typeof(OpCodeSimdShImm));
|
||||||
SetA64("0100111101xxxxxx010101xxxxxxxxxx", InstName.Shl_V, null, typeof(OpCodeSimdShImm));
|
SetA64("0100111101xxxxxx010101xxxxxxxxxx", InstName.Shl_V, null, typeof(OpCodeSimdShImm));
|
||||||
SetA64("0x101110<<100001001110xxxxxxxxxx", InstName.Shll_V, null, typeof(OpCodeSimd));
|
SetA64("0x101110<<100001001110xxxxxxxxxx", InstName.Shll_V, null, typeof(OpCodeSimd));
|
||||||
SetA64("0x00111100>>>xxx100001xxxxxxxxxx", InstName.Shrn_V, null, typeof(OpCodeSimdShImm));
|
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("0x1011110>>>>xxx010101xxxxxxxxxx", InstName.Sli_V, null, typeof(OpCodeSimdShImm));
|
||||||
SetA64("0x001110<<1xxxxx011001xxxxxxxxxx", InstName.Smax_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x001110<<1xxxxx011001xxxxxxxxxx", InstName.Smax_V, InstEmit.Smax_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x001110<<1xxxxx101001xxxxxxxxxx", InstName.Smaxp_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x001110<<1xxxxx101001xxxxxxxxxx", InstName.Smaxp_V, InstEmit.Smaxp_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x001110<<1xxxxx011011xxxxxxxxxx", InstName.Smin_V, null, typeof(OpCodeSimdReg));
|
SetA64("000011100x110000101010xxxxxxxxxx", InstName.Smaxv_V, InstEmit.Smaxv_V, typeof(OpCodeSimd));
|
||||||
SetA64("0x001110<<1xxxxx101011xxxxxxxxxx", InstName.Sminp_V, null, typeof(OpCodeSimdReg));
|
SetA64("01001110<<110000101010xxxxxxxxxx", InstName.Smaxv_V, InstEmit.Smaxv_V, typeof(OpCodeSimd));
|
||||||
SetA64("0x001110<<1xxxxx100000xxxxxxxxxx", InstName.Smlal_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x001110<<1xxxxx011011xxxxxxxxxx", InstName.Smin_V, InstEmit.Smin_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x001111xxxxxxxx0010x0xxxxxxxxxx", InstName.Smlal_Ve, null, typeof(OpCodeSimdRegElem));
|
SetA64("0x001110<<1xxxxx101011xxxxxxxxxx", InstName.Sminp_V, InstEmit.Sminp_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x001110<<1xxxxx101000xxxxxxxxxx", InstName.Smlsl_V, null, typeof(OpCodeSimdReg));
|
SetA64("000011100x110001101010xxxxxxxxxx", InstName.Sminv_V, InstEmit.Sminv_V, typeof(OpCodeSimd));
|
||||||
SetA64("0x001111xxxxxxxx0110x0xxxxxxxxxx", InstName.Smlsl_Ve, null, typeof(OpCodeSimdRegElem));
|
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("0x001110000xxxxx001011xxxxxxxxxx", InstName.Smov_S, null, typeof(OpCodeSimdIns));
|
||||||
SetA64("0x001110<<1xxxxx110000xxxxxxxxxx", InstName.Smull_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x001110<<1xxxxx110000xxxxxxxxxx", InstName.Smull_V, InstEmit.Smull_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x001111xxxxxxxx1010x0xxxxxxxxxx", InstName.Smull_Ve, null, typeof(OpCodeSimdRegElem));
|
SetA64("0x001111xxxxxxxx1010x0xxxxxxxxxx", InstName.Smull_Ve, InstEmit.Smull_Ve, typeof(OpCodeSimdRegElem));
|
||||||
SetA64("01011110xx100000011110xxxxxxxxxx", InstName.Sqabs_S, null, typeof(OpCodeSimd));
|
SetA64("01011110xx100000011110xxxxxxxxxx", InstName.Sqabs_S, InstEmit.Sqabs_S, typeof(OpCodeSimd));
|
||||||
SetA64("0>001110<<100000011110xxxxxxxxxx", InstName.Sqabs_V, null, typeof(OpCodeSimd));
|
SetA64("0>001110<<100000011110xxxxxxxxxx", InstName.Sqabs_V, InstEmit.Sqabs_V, typeof(OpCodeSimd));
|
||||||
SetA64("01011110xx1xxxxx000011xxxxxxxxxx", InstName.Sqadd_S, null, typeof(OpCodeSimdReg));
|
SetA64("01011110xx1xxxxx000011xxxxxxxxxx", InstName.Sqadd_S, InstEmit.Sqadd_S, typeof(OpCodeSimdReg));
|
||||||
SetA64("0>001110<<1xxxxx000011xxxxxxxxxx", InstName.Sqadd_V, null, typeof(OpCodeSimdReg));
|
SetA64("0>001110<<1xxxxx000011xxxxxxxxxx", InstName.Sqadd_V, InstEmit.Sqadd_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("01011110011xxxxx101101xxxxxxxxxx", InstName.Sqdmulh_S, null, typeof(OpCodeSimdReg));
|
SetA64("01011110011xxxxx101101xxxxxxxxxx", InstName.Sqdmulh_S, InstEmit.Sqdmulh_S, typeof(OpCodeSimdReg));
|
||||||
SetA64("01011110101xxxxx101101xxxxxxxxxx", InstName.Sqdmulh_S, null, typeof(OpCodeSimdReg));
|
SetA64("01011110101xxxxx101101xxxxxxxxxx", InstName.Sqdmulh_S, InstEmit.Sqdmulh_S, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x001110011xxxxx101101xxxxxxxxxx", InstName.Sqdmulh_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x001110011xxxxx101101xxxxxxxxxx", InstName.Sqdmulh_V, InstEmit.Sqdmulh_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x001110101xxxxx101101xxxxxxxxxx", InstName.Sqdmulh_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x001110101xxxxx101101xxxxxxxxxx", InstName.Sqdmulh_V, InstEmit.Sqdmulh_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("01111110xx100000011110xxxxxxxxxx", InstName.Sqneg_S, null, typeof(OpCodeSimd));
|
SetA64("01111110xx100000011110xxxxxxxxxx", InstName.Sqneg_S, InstEmit.Sqneg_S, typeof(OpCodeSimd));
|
||||||
SetA64("0>101110<<100000011110xxxxxxxxxx", InstName.Sqneg_V, null, typeof(OpCodeSimd));
|
SetA64("0>101110<<100000011110xxxxxxxxxx", InstName.Sqneg_V, InstEmit.Sqneg_V, typeof(OpCodeSimd));
|
||||||
SetA64("01111110011xxxxx101101xxxxxxxxxx", InstName.Sqrdmulh_S, null, typeof(OpCodeSimdReg));
|
SetA64("01111110011xxxxx101101xxxxxxxxxx", InstName.Sqrdmulh_S, InstEmit.Sqrdmulh_S, typeof(OpCodeSimdReg));
|
||||||
SetA64("01111110101xxxxx101101xxxxxxxxxx", InstName.Sqrdmulh_S, null, typeof(OpCodeSimdReg));
|
SetA64("01111110101xxxxx101101xxxxxxxxxx", InstName.Sqrdmulh_S, InstEmit.Sqrdmulh_S, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x101110011xxxxx101101xxxxxxxxxx", InstName.Sqrdmulh_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x101110011xxxxx101101xxxxxxxxxx", InstName.Sqrdmulh_V, InstEmit.Sqrdmulh_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x101110101xxxxx101101xxxxxxxxxx", InstName.Sqrdmulh_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x101110101xxxxx101101xxxxxxxxxx", InstName.Sqrdmulh_V, InstEmit.Sqrdmulh_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0>001110<<1xxxxx010111xxxxxxxxxx", InstName.Sqrshl_V, null, typeof(OpCodeSimdReg));
|
SetA64("0>001110<<1xxxxx010111xxxxxxxxxx", InstName.Sqrshl_V, null, typeof(OpCodeSimdReg));
|
||||||
SetA64("0101111100>>>xxx100111xxxxxxxxxx", InstName.Sqrshrn_S, null, typeof(OpCodeSimdShImm));
|
SetA64("0101111100>>>xxx100111xxxxxxxxxx", InstName.Sqrshrn_S, null, typeof(OpCodeSimdShImm));
|
||||||
SetA64("0x00111100>>>xxx100111xxxxxxxxxx", InstName.Sqrshrn_V, 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("0x00111100>>>xxx100101xxxxxxxxxx", InstName.Sqshrn_V, null, typeof(OpCodeSimdShImm));
|
||||||
SetA64("0111111100>>>xxx100001xxxxxxxxxx", InstName.Sqshrun_S, null, typeof(OpCodeSimdShImm));
|
SetA64("0111111100>>>xxx100001xxxxxxxxxx", InstName.Sqshrun_S, null, typeof(OpCodeSimdShImm));
|
||||||
SetA64("0x10111100>>>xxx100001xxxxxxxxxx", InstName.Sqshrun_V, null, typeof(OpCodeSimdShImm));
|
SetA64("0x10111100>>>xxx100001xxxxxxxxxx", InstName.Sqshrun_V, null, typeof(OpCodeSimdShImm));
|
||||||
SetA64("01011110xx1xxxxx001011xxxxxxxxxx", InstName.Sqsub_S, null, typeof(OpCodeSimdReg));
|
SetA64("01011110xx1xxxxx001011xxxxxxxxxx", InstName.Sqsub_S, InstEmit.Sqsub_S, typeof(OpCodeSimdReg));
|
||||||
SetA64("0>001110<<1xxxxx001011xxxxxxxxxx", InstName.Sqsub_V, null, typeof(OpCodeSimdReg));
|
SetA64("0>001110<<1xxxxx001011xxxxxxxxxx", InstName.Sqsub_V, InstEmit.Sqsub_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("01011110<<100001010010xxxxxxxxxx", InstName.Sqxtn_S, null, typeof(OpCodeSimd));
|
SetA64("01011110<<100001010010xxxxxxxxxx", InstName.Sqxtn_S, InstEmit.Sqxtn_S, typeof(OpCodeSimd));
|
||||||
SetA64("0x001110<<100001010010xxxxxxxxxx", InstName.Sqxtn_V, null, typeof(OpCodeSimd));
|
SetA64("0x001110<<100001010010xxxxxxxxxx", InstName.Sqxtn_V, InstEmit.Sqxtn_V, typeof(OpCodeSimd));
|
||||||
SetA64("01111110<<100001001010xxxxxxxxxx", InstName.Sqxtun_S, null, typeof(OpCodeSimd));
|
SetA64("01111110<<100001001010xxxxxxxxxx", InstName.Sqxtun_S, InstEmit.Sqxtun_S, typeof(OpCodeSimd));
|
||||||
SetA64("0x101110<<100001001010xxxxxxxxxx", InstName.Sqxtun_V, null, typeof(OpCodeSimd));
|
SetA64("0x101110<<100001001010xxxxxxxxxx", InstName.Sqxtun_V, InstEmit.Sqxtun_V, typeof(OpCodeSimd));
|
||||||
SetA64("0x001110<<1xxxxx000101xxxxxxxxxx", InstName.Srhadd_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x001110<<1xxxxx000101xxxxxxxxxx", InstName.Srhadd_V, InstEmit.Srhadd_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0>001110<<1xxxxx010101xxxxxxxxxx", InstName.Srshl_V, null, typeof(OpCodeSimdReg));
|
SetA64("0>001110<<1xxxxx010101xxxxxxxxxx", InstName.Srshl_V, null, typeof(OpCodeSimdReg));
|
||||||
SetA64("0101111101xxxxxx001001xxxxxxxxxx", InstName.Srshr_S, null, typeof(OpCodeSimdShImm));
|
SetA64("0101111101xxxxxx001001xxxxxxxxxx", InstName.Srshr_S, null, typeof(OpCodeSimdShImm));
|
||||||
SetA64("0x00111100>>>xxx001001xxxxxxxxxx", InstName.Srshr_V, 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("0101111101xxxxxx000101xxxxxxxxxx", InstName.Ssra_S, null, typeof(OpCodeSimdShImm));
|
||||||
SetA64("0x00111100>>>xxx000101xxxxxxxxxx", InstName.Ssra_V, null, typeof(OpCodeSimdShImm));
|
SetA64("0x00111100>>>xxx000101xxxxxxxxxx", InstName.Ssra_V, null, typeof(OpCodeSimdShImm));
|
||||||
SetA64("0100111101xxxxxx000101xxxxxxxxxx", 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<<1xxxxx001000xxxxxxxxxx", InstName.Ssubl_V, InstEmit.Ssubl_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x001110<<1xxxxx001100xxxxxxxxxx", InstName.Ssubw_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x001110<<1xxxxx001100xxxxxxxxxx", InstName.Ssubw_V, InstEmit.Ssubw_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x00110000000000xxxxxxxxxxxxxxxx", InstName.St__Vms, null, typeof(OpCodeSimdMemMs));
|
SetA64("0x00110000000000xxxxxxxxxxxxxxxx", InstName.St__Vms, null, typeof(OpCodeSimdMemMs));
|
||||||
SetA64("0x001100100xxxxxxxxxxxxxxxxxxxxx", InstName.St__Vms, null, typeof(OpCodeSimdMemMs));
|
SetA64("0x001100100xxxxxxxxxxxxxxxxxxxxx", InstName.St__Vms, null, typeof(OpCodeSimdMemMs));
|
||||||
SetA64("0x00110100x00000xxxxxxxxxxxxxxxx", InstName.St__Vss, null, typeof(OpCodeSimdMemSs));
|
SetA64("0x00110100x00000xxxxxxxxxxxxxxxx", InstName.St__Vss, null, typeof(OpCodeSimdMemSs));
|
||||||
|
@ -498,54 +502,58 @@ namespace ARMeilleure.Decoders
|
||||||
SetA64("xx111100x00xxxxxxxxx11xxxxxxxxxx", InstName.Str, null, typeof(OpCodeSimdMemImm));
|
SetA64("xx111100x00xxxxxxxxx11xxxxxxxxxx", InstName.Str, null, typeof(OpCodeSimdMemImm));
|
||||||
SetA64("xx111101x0xxxxxxxxxxxxxxxxxxxxxx", InstName.Str, null, typeof(OpCodeSimdMemImm));
|
SetA64("xx111101x0xxxxxxxxxxxxxxxxxxxxxx", InstName.Str, null, typeof(OpCodeSimdMemImm));
|
||||||
SetA64("xx111100x01xxxxxxxxx10xxxxxxxxxx", InstName.Str, null, typeof(OpCodeSimdMemReg));
|
SetA64("xx111100x01xxxxxxxxx10xxxxxxxxxx", InstName.Str, null, typeof(OpCodeSimdMemReg));
|
||||||
SetA64("01111110111xxxxx100001xxxxxxxxxx", InstName.Sub_S, null, typeof(OpCodeSimdReg));
|
SetA64("01111110111xxxxx100001xxxxxxxxxx", InstName.Sub_S, InstEmit.Sub_S, typeof(OpCodeSimdReg));
|
||||||
SetA64("0>101110<<1xxxxx100001xxxxxxxxxx", InstName.Sub_V, null, typeof(OpCodeSimdReg));
|
SetA64("0>101110<<1xxxxx100001xxxxxxxxxx", InstName.Sub_V, InstEmit.Sub_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x001110<<1xxxxx011000xxxxxxxxxx", InstName.Subhn_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x001110<<1xxxxx011000xxxxxxxxxx", InstName.Subhn_V, InstEmit.Subhn_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("01011110xx100000001110xxxxxxxxxx", InstName.Suqadd_S, null, typeof(OpCodeSimd));
|
SetA64("01011110xx100000001110xxxxxxxxxx", InstName.Suqadd_S, InstEmit.Suqadd_S, typeof(OpCodeSimd));
|
||||||
SetA64("0>001110<<100000001110xxxxxxxxxx", InstName.Suqadd_V, null, typeof(OpCodeSimd));
|
SetA64("0>001110<<100000001110xxxxxxxxxx", InstName.Suqadd_V, InstEmit.Suqadd_V, typeof(OpCodeSimd));
|
||||||
SetA64("0x001110000xxxxx0xx000xxxxxxxxxx", InstName.Tbl_V, null, typeof(OpCodeSimdTbl));
|
SetA64("0x001110000xxxxx0xx000xxxxxxxxxx", InstName.Tbl_V, null, typeof(OpCodeSimdTbl));
|
||||||
SetA64("0>001110<<0xxxxx001010xxxxxxxxxx", InstName.Trn1_V, null, typeof(OpCodeSimdReg));
|
SetA64("0>001110<<0xxxxx001010xxxxxxxxxx", InstName.Trn1_V, null, typeof(OpCodeSimdReg));
|
||||||
SetA64("0>001110<<0xxxxx011010xxxxxxxxxx", InstName.Trn2_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<<1xxxxx011111xxxxxxxxxx", InstName.Uaba_V, InstEmit.Uaba_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x101110<<1xxxxx010100xxxxxxxxxx", InstName.Uabal_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x101110<<1xxxxx010100xxxxxxxxxx", InstName.Uabal_V, InstEmit.Uabal_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x101110<<1xxxxx011101xxxxxxxxxx", InstName.Uabd_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x101110<<1xxxxx011101xxxxxxxxxx", InstName.Uabd_V, InstEmit.Uabd_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x101110<<1xxxxx011100xxxxxxxxxx", InstName.Uabdl_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x101110<<1xxxxx011100xxxxxxxxxx", InstName.Uabdl_V, InstEmit.Uabdl_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x101110<<100000011010xxxxxxxxxx", InstName.Uadalp_V, null, typeof(OpCodeSimd));
|
SetA64("0x101110<<100000011010xxxxxxxxxx", InstName.Uadalp_V, InstEmit.Uadalp_V, typeof(OpCodeSimd));
|
||||||
SetA64("0x101110<<1xxxxx000000xxxxxxxxxx", InstName.Uaddl_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x101110<<1xxxxx000000xxxxxxxxxx", InstName.Uaddl_V, InstEmit.Uaddl_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x101110<<100000001010xxxxxxxxxx", InstName.Uaddlp_V, null, typeof(OpCodeSimd));
|
SetA64("0x101110<<100000001010xxxxxxxxxx", InstName.Uaddlp_V, InstEmit.Uaddlp_V, typeof(OpCodeSimd));
|
||||||
SetA64("001011100x110000001110xxxxxxxxxx", InstName.Uaddlv_V, null, typeof(OpCodeSimd));
|
SetA64("001011100x110000001110xxxxxxxxxx", InstName.Uaddlv_V, InstEmit.Uaddlv_V, typeof(OpCodeSimd));
|
||||||
SetA64("01101110<<110000001110xxxxxxxxxx", InstName.Uaddlv_V, null, typeof(OpCodeSimd));
|
SetA64("01101110<<110000001110xxxxxxxxxx", InstName.Uaddlv_V, InstEmit.Uaddlv_V, typeof(OpCodeSimd));
|
||||||
SetA64("0x101110<<1xxxxx000100xxxxxxxxxx", InstName.Uaddw_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x101110<<1xxxxx000100xxxxxxxxxx", InstName.Uaddw_V, InstEmit.Uaddw_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("x00111100x100011000000xxxxxxxxxx", InstName.Ucvtf_Gp, null, typeof(OpCodeSimdCvt));
|
SetA64("x00111100x100011000000xxxxxxxxxx", InstName.Ucvtf_Gp, null, typeof(OpCodeSimdCvt));
|
||||||
SetA64(">00111100x000011>xxxxxxxxxxxxxxx", InstName.Ucvtf_Gp_Fixed, null, typeof(OpCodeSimdCvt));
|
SetA64(">00111100x000011>xxxxxxxxxxxxxxx", InstName.Ucvtf_Gp_Fixed, null, typeof(OpCodeSimdCvt));
|
||||||
SetA64("011111100x100001110110xxxxxxxxxx", InstName.Ucvtf_S, null, typeof(OpCodeSimd));
|
SetA64("011111100x100001110110xxxxxxxxxx", InstName.Ucvtf_S, null, typeof(OpCodeSimd));
|
||||||
SetA64("0>1011100<100001110110xxxxxxxxxx", InstName.Ucvtf_V, null, typeof(OpCodeSimd));
|
SetA64("0>1011100<100001110110xxxxxxxxxx", InstName.Ucvtf_V, null, typeof(OpCodeSimd));
|
||||||
SetA64("0x101110<<1xxxxx000001xxxxxxxxxx", InstName.Uhadd_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x101110<<1xxxxx000001xxxxxxxxxx", InstName.Uhadd_V, InstEmit.Uhadd_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x101110<<1xxxxx001001xxxxxxxxxx", InstName.Uhsub_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x101110<<1xxxxx001001xxxxxxxxxx", InstName.Uhsub_V, InstEmit.Uhsub_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x101110<<1xxxxx011001xxxxxxxxxx", InstName.Umax_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x101110<<1xxxxx011001xxxxxxxxxx", InstName.Umax_V, InstEmit.Umax_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x101110<<1xxxxx101001xxxxxxxxxx", InstName.Umaxp_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x101110<<1xxxxx101001xxxxxxxxxx", InstName.Umaxp_V, InstEmit.Umaxp_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x101110<<1xxxxx011011xxxxxxxxxx", InstName.Umin_V, null, typeof(OpCodeSimdReg));
|
SetA64("001011100x110000101010xxxxxxxxxx", InstName.Umaxv_V, InstEmit.Umaxv_V, typeof(OpCodeSimd));
|
||||||
SetA64("0x101110<<1xxxxx101011xxxxxxxxxx", InstName.Uminp_V, null, typeof(OpCodeSimdReg));
|
SetA64("01101110<<110000101010xxxxxxxxxx", InstName.Umaxv_V, InstEmit.Umaxv_V, typeof(OpCodeSimd));
|
||||||
SetA64("0x101110<<1xxxxx100000xxxxxxxxxx", InstName.Umlal_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x101110<<1xxxxx011011xxxxxxxxxx", InstName.Umin_V, InstEmit.Umin_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x101111xxxxxxxx0010x0xxxxxxxxxx", InstName.Umlal_Ve, null, typeof(OpCodeSimdRegElem));
|
SetA64("0x101110<<1xxxxx101011xxxxxxxxxx", InstName.Uminp_V, InstEmit.Uminp_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x101110<<1xxxxx101000xxxxxxxxxx", InstName.Umlsl_V, null, typeof(OpCodeSimdReg));
|
SetA64("001011100x110001101010xxxxxxxxxx", InstName.Uminv_V, InstEmit.Uminv_V, typeof(OpCodeSimd));
|
||||||
SetA64("0x101111xxxxxxxx0110x0xxxxxxxxxx", InstName.Umlsl_Ve, null, typeof(OpCodeSimdRegElem));
|
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("0x001110000xxxxx001111xxxxxxxxxx", InstName.Umov_S, null, typeof(OpCodeSimdIns));
|
||||||
SetA64("0x101110<<1xxxxx110000xxxxxxxxxx", InstName.Umull_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x101110<<1xxxxx110000xxxxxxxxxx", InstName.Umull_V, InstEmit.Umull_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x101111xxxxxxxx1010x0xxxxxxxxxx", InstName.Umull_Ve, null, typeof(OpCodeSimdRegElem));
|
SetA64("0x101111xxxxxxxx1010x0xxxxxxxxxx", InstName.Umull_Ve, InstEmit.Umull_Ve, typeof(OpCodeSimdRegElem));
|
||||||
SetA64("01111110xx1xxxxx000011xxxxxxxxxx", InstName.Uqadd_S, null, typeof(OpCodeSimdReg));
|
SetA64("01111110xx1xxxxx000011xxxxxxxxxx", InstName.Uqadd_S, InstEmit.Uqadd_S, typeof(OpCodeSimdReg));
|
||||||
SetA64("0>101110<<1xxxxx000011xxxxxxxxxx", InstName.Uqadd_V, null, 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("0>101110<<1xxxxx010111xxxxxxxxxx", InstName.Uqrshl_V, null, typeof(OpCodeSimdReg));
|
||||||
SetA64("0111111100>>>xxx100111xxxxxxxxxx", InstName.Uqrshrn_S, null, typeof(OpCodeSimdShImm));
|
SetA64("0111111100>>>xxx100111xxxxxxxxxx", InstName.Uqrshrn_S, null, typeof(OpCodeSimdShImm));
|
||||||
SetA64("0x10111100>>>xxx100111xxxxxxxxxx", InstName.Uqrshrn_V, null, typeof(OpCodeSimdShImm));
|
SetA64("0x10111100>>>xxx100111xxxxxxxxxx", InstName.Uqrshrn_V, null, typeof(OpCodeSimdShImm));
|
||||||
SetA64("0>101110<<1xxxxx010011xxxxxxxxxx", InstName.Uqshl_V, null, typeof(OpCodeSimdReg));
|
SetA64("0>101110<<1xxxxx010011xxxxxxxxxx", InstName.Uqshl_V, null, typeof(OpCodeSimdReg));
|
||||||
SetA64("0111111100>>>xxx100101xxxxxxxxxx", InstName.Uqshrn_S, null, typeof(OpCodeSimdShImm));
|
SetA64("0111111100>>>xxx100101xxxxxxxxxx", InstName.Uqshrn_S, null, typeof(OpCodeSimdShImm));
|
||||||
SetA64("0x10111100>>>xxx100101xxxxxxxxxx", InstName.Uqshrn_V, null, typeof(OpCodeSimdShImm));
|
SetA64("0x10111100>>>xxx100101xxxxxxxxxx", InstName.Uqshrn_V, null, typeof(OpCodeSimdShImm));
|
||||||
SetA64("01111110xx1xxxxx001011xxxxxxxxxx", InstName.Uqsub_S, null, typeof(OpCodeSimdReg));
|
SetA64("01111110xx1xxxxx001011xxxxxxxxxx", InstName.Uqsub_S, InstEmit.Uqsub_S, typeof(OpCodeSimdReg));
|
||||||
SetA64("0>101110<<1xxxxx001011xxxxxxxxxx", InstName.Uqsub_V, null, typeof(OpCodeSimdReg));
|
SetA64("0>101110<<1xxxxx001011xxxxxxxxxx", InstName.Uqsub_V, InstEmit.Uqsub_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("01111110<<100001010010xxxxxxxxxx", InstName.Uqxtn_S, null, typeof(OpCodeSimd));
|
SetA64("01111110<<100001010010xxxxxxxxxx", InstName.Uqxtn_S, InstEmit.Uqxtn_S, typeof(OpCodeSimd));
|
||||||
SetA64("0x101110<<100001010010xxxxxxxxxx", InstName.Uqxtn_V, null, typeof(OpCodeSimd));
|
SetA64("0x101110<<100001010010xxxxxxxxxx", InstName.Uqxtn_V, InstEmit.Uqxtn_V, typeof(OpCodeSimd));
|
||||||
SetA64("0x101110<<1xxxxx000101xxxxxxxxxx", InstName.Urhadd_V, null, typeof(OpCodeSimdReg));
|
SetA64("0x101110<<1xxxxx000101xxxxxxxxxx", InstName.Urhadd_V, InstEmit.Urhadd_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0>101110<<1xxxxx010101xxxxxxxxxx", InstName.Urshl_V, null, typeof(OpCodeSimdReg));
|
SetA64("0>101110<<1xxxxx010101xxxxxxxxxx", InstName.Urshl_V, null, typeof(OpCodeSimdReg));
|
||||||
SetA64("0111111101xxxxxx001001xxxxxxxxxx", InstName.Urshr_S, null, typeof(OpCodeSimdShImm));
|
SetA64("0111111101xxxxxx001001xxxxxxxxxx", InstName.Urshr_S, null, typeof(OpCodeSimdShImm));
|
||||||
SetA64("0x10111100>>>xxx001001xxxxxxxxxx", InstName.Urshr_V, 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("0111111101xxxxxx000001xxxxxxxxxx", InstName.Ushr_S, null, typeof(OpCodeSimdShImm));
|
||||||
SetA64("0x10111100>>>xxx000001xxxxxxxxxx", InstName.Ushr_V, null, typeof(OpCodeSimdShImm));
|
SetA64("0x10111100>>>xxx000001xxxxxxxxxx", InstName.Ushr_V, null, typeof(OpCodeSimdShImm));
|
||||||
SetA64("0110111101xxxxxx000001xxxxxxxxxx", InstName.Ushr_V, null, typeof(OpCodeSimdShImm));
|
SetA64("0110111101xxxxxx000001xxxxxxxxxx", InstName.Ushr_V, null, typeof(OpCodeSimdShImm));
|
||||||
SetA64("01111110xx100000001110xxxxxxxxxx", InstName.Usqadd_S, null, typeof(OpCodeSimd));
|
SetA64("01111110xx100000001110xxxxxxxxxx", InstName.Usqadd_S, InstEmit.Usqadd_S, typeof(OpCodeSimd));
|
||||||
SetA64("0>101110<<100000001110xxxxxxxxxx", InstName.Usqadd_V, null, typeof(OpCodeSimd));
|
SetA64("0>101110<<100000001110xxxxxxxxxx", InstName.Usqadd_V, InstEmit.Usqadd_V, typeof(OpCodeSimd));
|
||||||
SetA64("0111111101xxxxxx000101xxxxxxxxxx", InstName.Usra_S, null, typeof(OpCodeSimdShImm));
|
SetA64("0111111101xxxxxx000101xxxxxxxxxx", InstName.Usra_S, null, typeof(OpCodeSimdShImm));
|
||||||
SetA64("0x10111100>>>xxx000101xxxxxxxxxx", InstName.Usra_V, null, typeof(OpCodeSimdShImm));
|
SetA64("0x10111100>>>xxx000101xxxxxxxxxx", InstName.Usra_V, null, typeof(OpCodeSimdShImm));
|
||||||
SetA64("0110111101xxxxxx000101xxxxxxxxxx", 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<<1xxxxx001000xxxxxxxxxx", InstName.Usubl_V, InstEmit.Usubl_V, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x101110<<1xxxxx001100xxxxxxxxxx", InstName.Usubw_V, null, 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<<0xxxxx000110xxxxxxxxxx", InstName.Uzp1_V, null, typeof(OpCodeSimdReg));
|
||||||
SetA64("0>001110<<0xxxxx010110xxxxxxxxxx", InstName.Uzp2_V, null, typeof(OpCodeSimdReg));
|
SetA64("0>001110<<0xxxxx010110xxxxxxxxxx", InstName.Uzp2_V, null, typeof(OpCodeSimdReg));
|
||||||
SetA64("0x001110<<100001001010xxxxxxxxxx", InstName.Xtn_V, null, typeof(OpCodeSimd));
|
SetA64("0x001110<<100001001010xxxxxxxxxx", InstName.Xtn_V, null, typeof(OpCodeSimd));
|
||||||
|
|
|
@ -3,16 +3,16 @@ using System;
|
||||||
|
|
||||||
namespace ARMeilleure.Diagnostics
|
namespace ARMeilleure.Diagnostics
|
||||||
{
|
{
|
||||||
class Logger
|
static class Logger
|
||||||
{
|
{
|
||||||
public void StartPass(PassName name)
|
public static void StartPass(PassName name)
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
WriteOutput(name + " pass started...");
|
WriteOutput(name + " pass started...");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EndPass(PassName name, ControlFlowGraph cfg)
|
public static void EndPass(PassName name, ControlFlowGraph cfg)
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
EndPass(name);
|
EndPass(name);
|
||||||
|
@ -23,14 +23,14 @@ namespace ARMeilleure.Diagnostics
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EndPass(PassName name)
|
public static void EndPass(PassName name)
|
||||||
{
|
{
|
||||||
#if DEBUG
|
#if DEBUG
|
||||||
WriteOutput(name + " pass ended...");
|
WriteOutput(name + " pass ended...");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
private void WriteOutput(string text)
|
private static void WriteOutput(string text)
|
||||||
{
|
{
|
||||||
Console.WriteLine(text);
|
Console.WriteLine(text);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,8 @@ namespace ARMeilleure.Diagnostics
|
||||||
enum PassName
|
enum PassName
|
||||||
{
|
{
|
||||||
Translation,
|
Translation,
|
||||||
SsaConstruction
|
SsaConstruction,
|
||||||
|
PreAllocation,
|
||||||
|
RegisterAllocation
|
||||||
}
|
}
|
||||||
}
|
}
|
279
ARMeilleure/Instructions/CryptoHelper.cs
Normal file
279
ARMeilleure/Instructions/CryptoHelper.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,7 +19,7 @@ namespace ARMeilleure.Instructions
|
||||||
Operand n = GetAluN(context);
|
Operand n = GetAluN(context);
|
||||||
Operand m = GetAluM(context);
|
Operand m = GetAluM(context);
|
||||||
|
|
||||||
Operand d = context.IAdd(n, m);
|
Operand d = context.Add(n, m);
|
||||||
|
|
||||||
Operand carry = GetFlag(PState.CFlag);
|
Operand carry = GetFlag(PState.CFlag);
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ namespace ARMeilleure.Instructions
|
||||||
carry = context.Copy(Local(OperandType.I64), carry);
|
carry = context.Copy(Local(OperandType.I64), carry);
|
||||||
}
|
}
|
||||||
|
|
||||||
d = context.IAdd(d, carry);
|
d = context.Add(d, carry);
|
||||||
|
|
||||||
if (setFlags)
|
if (setFlags)
|
||||||
{
|
{
|
||||||
|
@ -43,7 +43,7 @@ namespace ARMeilleure.Instructions
|
||||||
|
|
||||||
public static void Add(EmitterContext context)
|
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)
|
public static void Adds(EmitterContext context)
|
||||||
|
@ -51,7 +51,7 @@ namespace ARMeilleure.Instructions
|
||||||
Operand n = GetAluN(context);
|
Operand n = GetAluN(context);
|
||||||
Operand m = GetAluM(context);
|
Operand m = GetAluM(context);
|
||||||
|
|
||||||
Operand d = context.IAdd(n, m);
|
Operand d = context.Add(n, m);
|
||||||
|
|
||||||
EmitNZFlagsCheck(context, d);
|
EmitNZFlagsCheck(context, d);
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ namespace ARMeilleure.Instructions
|
||||||
|
|
||||||
Operand res = context.CountLeadingZeros(context.BitwiseExclusiveOr(nHigh, nLow));
|
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);
|
SetAluDOrZR(context, res);
|
||||||
}
|
}
|
||||||
|
@ -195,7 +195,7 @@ namespace ARMeilleure.Instructions
|
||||||
Operand n = GetAluN(context);
|
Operand n = GetAluN(context);
|
||||||
Operand m = GetAluM(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));
|
Operand borrow = context.BitwiseExclusiveOr(GetFlag(PState.CFlag), Const(1));
|
||||||
|
|
||||||
|
@ -204,7 +204,7 @@ namespace ARMeilleure.Instructions
|
||||||
borrow = context.Copy(Local(OperandType.I64), borrow);
|
borrow = context.Copy(Local(OperandType.I64), borrow);
|
||||||
}
|
}
|
||||||
|
|
||||||
d = context.ISubtract(d, borrow);
|
d = context.Subtract(d, borrow);
|
||||||
|
|
||||||
if (setFlags)
|
if (setFlags)
|
||||||
{
|
{
|
||||||
|
@ -219,7 +219,7 @@ namespace ARMeilleure.Instructions
|
||||||
|
|
||||||
public static void Sub(EmitterContext context)
|
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)
|
public static void Subs(EmitterContext context)
|
||||||
|
@ -227,7 +227,7 @@ namespace ARMeilleure.Instructions
|
||||||
Operand n = GetAluN(context);
|
Operand n = GetAluN(context);
|
||||||
Operand m = GetAluM(context);
|
Operand m = GetAluM(context);
|
||||||
|
|
||||||
Operand d = context.ISubtract(n, m);
|
Operand d = context.Subtract(n, m);
|
||||||
|
|
||||||
EmitNZFlagsCheck(context, d);
|
EmitNZFlagsCheck(context, d);
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ namespace ARMeilleure.Instructions
|
||||||
|
|
||||||
if (isNegated)
|
if (isNegated)
|
||||||
{
|
{
|
||||||
Operand d = context.IAdd(n, m);
|
Operand d = context.Add(n, m);
|
||||||
|
|
||||||
EmitNZFlagsCheck(context, d);
|
EmitNZFlagsCheck(context, d);
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ namespace ARMeilleure.Instructions
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Operand d = context.ISubtract(n, m);
|
Operand d = context.Subtract(n, m);
|
||||||
|
|
||||||
EmitNZFlagsCheck(context, d);
|
EmitNZFlagsCheck(context, d);
|
||||||
|
|
||||||
|
|
58
ARMeilleure/Instructions/InstEmitCrypto.cs
Normal file
58
ARMeilleure/Instructions/InstEmitCrypto.cs
Normal 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -32,7 +32,7 @@ namespace ARMeilleure.Instructions
|
||||||
|
|
||||||
if (cselOp == CselOperation.Increment)
|
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)
|
else if (cselOp == CselOperation.Invert)
|
||||||
{
|
{
|
||||||
|
@ -40,7 +40,7 @@ namespace ARMeilleure.Instructions
|
||||||
}
|
}
|
||||||
else if (cselOp == CselOperation.Negate)
|
else if (cselOp == CselOperation.Negate)
|
||||||
{
|
{
|
||||||
m = context.INegate(m);
|
m = context.Negate(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
Operand condTrue = GetCondTrue(context, op.Cond);
|
Operand condTrue = GetCondTrue(context, op.Cond);
|
||||||
|
|
|
@ -50,8 +50,8 @@ namespace ARMeilleure.Instructions
|
||||||
}
|
}
|
||||||
|
|
||||||
Operand d = unsigned
|
Operand d = unsigned
|
||||||
? context.IDivideUI(n, m)
|
? context.DivideUI(n, m)
|
||||||
: context.IDivide (n, m);
|
: context.Divide (n, m);
|
||||||
|
|
||||||
SetAluDOrZR(context, d);
|
SetAluDOrZR(context, d);
|
||||||
|
|
||||||
|
|
|
@ -90,7 +90,7 @@ namespace ARMeilleure.Instructions
|
||||||
|
|
||||||
Operand address = GetAddress(context);
|
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.Rt, address);
|
||||||
EmitLoad(op.Rt2, address2);
|
EmitLoad(op.Rt2, address2);
|
||||||
|
@ -117,7 +117,7 @@ namespace ARMeilleure.Instructions
|
||||||
|
|
||||||
Operand address = GetAddress(context);
|
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 t = GetT(context, op.Rt);
|
||||||
Operand t2 = GetT(context, op.Rt2);
|
Operand t2 = GetT(context, op.Rt2);
|
||||||
|
@ -141,7 +141,7 @@ namespace ARMeilleure.Instructions
|
||||||
//Pre-indexing.
|
//Pre-indexing.
|
||||||
if (!op.PostIdx)
|
if (!op.PostIdx)
|
||||||
{
|
{
|
||||||
address = context.IAdd(address, Const(op.Immediate));
|
address = context.Add(address, Const(op.Immediate));
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -158,7 +158,7 @@ namespace ARMeilleure.Instructions
|
||||||
m = context.ShiftLeft(m, Const(op.Size));
|
m = context.ShiftLeft(m, Const(op.Size));
|
||||||
}
|
}
|
||||||
|
|
||||||
address = context.IAdd(n, m);
|
address = context.Add(n, m);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -174,7 +174,7 @@ namespace ARMeilleure.Instructions
|
||||||
{
|
{
|
||||||
if (op.PostIdx)
|
if (op.PostIdx)
|
||||||
{
|
{
|
||||||
address = context.IAdd(address, Const(op.Immediate));
|
address = context.Add(address, Const(op.Immediate));
|
||||||
}
|
}
|
||||||
|
|
||||||
context.Copy(GetIntOrSP(op, op.Rn), address);
|
context.Copy(GetIntOrSP(op, op.Rn), address);
|
||||||
|
|
|
@ -4,7 +4,6 @@ using ARMeilleure.Translation;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
using static ARMeilleure.Instructions.InstEmitHelper;
|
using static ARMeilleure.Instructions.InstEmitHelper;
|
||||||
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
|
|
||||||
|
|
||||||
namespace ARMeilleure.Instructions
|
namespace ARMeilleure.Instructions
|
||||||
{
|
{
|
||||||
|
@ -21,9 +20,9 @@ namespace ARMeilleure.Instructions
|
||||||
Operand n = GetIntOrZR(op, op.Rn);
|
Operand n = GetIntOrZR(op, op.Rn);
|
||||||
Operand m = GetIntOrZR(op, op.Rm);
|
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);
|
SetIntOrZR(context, op.Rd, res);
|
||||||
}
|
}
|
||||||
|
@ -67,9 +66,9 @@ namespace ARMeilleure.Instructions
|
||||||
Operand n = GetExtendedRegister32(op.Rn);
|
Operand n = GetExtendedRegister32(op.Rn);
|
||||||
Operand m = GetExtendedRegister32(op.Rm);
|
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);
|
SetIntOrZR(context, op.Rd, res);
|
||||||
}
|
}
|
||||||
|
|
3153
ARMeilleure/Instructions/InstEmitSimdArithmetic.cs
Normal file
3153
ARMeilleure/Instructions/InstEmitSimdArithmetic.cs
Normal file
File diff suppressed because it is too large
Load diff
1413
ARMeilleure/Instructions/InstEmitSimdHelper.cs
Normal file
1413
ARMeilleure/Instructions/InstEmitSimdHelper.cs
Normal file
File diff suppressed because it is too large
Load diff
35
ARMeilleure/Instructions/InstEmitSimdMove.cs
Normal file
35
ARMeilleure/Instructions/InstEmitSimdMove.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -314,8 +314,10 @@ namespace ARMeilleure.Instructions
|
||||||
Sli_V,
|
Sli_V,
|
||||||
Smax_V,
|
Smax_V,
|
||||||
Smaxp_V,
|
Smaxp_V,
|
||||||
|
Smaxv_V,
|
||||||
Smin_V,
|
Smin_V,
|
||||||
Sminp_V,
|
Sminp_V,
|
||||||
|
Sminv_V,
|
||||||
Smlal_V,
|
Smlal_V,
|
||||||
Smlal_Ve,
|
Smlal_Ve,
|
||||||
Smlsl_V,
|
Smlsl_V,
|
||||||
|
@ -390,8 +392,10 @@ namespace ARMeilleure.Instructions
|
||||||
Uhsub_V,
|
Uhsub_V,
|
||||||
Umax_V,
|
Umax_V,
|
||||||
Umaxp_V,
|
Umaxp_V,
|
||||||
|
Umaxv_V,
|
||||||
Umin_V,
|
Umin_V,
|
||||||
Uminp_V,
|
Uminp_V,
|
||||||
|
Uminv_V,
|
||||||
Umlal_V,
|
Umlal_V,
|
||||||
Umlal_Ve,
|
Umlal_Ve,
|
||||||
Umlsl_V,
|
Umlsl_V,
|
||||||
|
|
|
@ -39,7 +39,7 @@ namespace ARMeilleure.Instructions
|
||||||
GetContext().OnUndefined(address, opCode);
|
GetContext().OnUndefined(address, opCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ExecutionContext GetContext()
|
public static ExecutionContext GetContext()
|
||||||
{
|
{
|
||||||
return _contexts[Thread.CurrentThread];
|
return _contexts[Thread.CurrentThread];
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using ARMeilleure.State;
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace ARMeilleure.Instructions
|
namespace ARMeilleure.Instructions
|
||||||
|
@ -12,7 +13,395 @@ namespace ARMeilleure.Instructions
|
||||||
|
|
||||||
#endregion
|
#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"
|
#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.).
|
public static ulong CountSetBits8(ulong value) // "size" is 8 (SIMD&FP Inst.).
|
||||||
{
|
{
|
||||||
value = ((value >> 1) & 0x55ul) + (value & 0x55ul);
|
value = ((value >> 1) & 0x55ul) + (value & 0x55ul);
|
||||||
|
@ -26,15 +415,15 @@ namespace ARMeilleure.Instructions
|
||||||
private const uint Crc32RevPoly = 0xedb88320;
|
private const uint Crc32RevPoly = 0xedb88320;
|
||||||
private const uint Crc32cRevPoly = 0x82f63b78;
|
private const uint Crc32cRevPoly = 0x82f63b78;
|
||||||
|
|
||||||
public static uint Crc32b(uint crc, byte val) => Crc32 (crc, Crc32RevPoly, val);
|
public static uint Crc32b(uint crc, byte value) => Crc32 (crc, Crc32RevPoly, value);
|
||||||
public static uint Crc32h(uint crc, ushort val) => Crc32h(crc, Crc32RevPoly, val);
|
public static uint Crc32h(uint crc, ushort value) => Crc32h(crc, Crc32RevPoly, value);
|
||||||
public static uint Crc32w(uint crc, uint val) => Crc32w(crc, Crc32RevPoly, val);
|
public static uint Crc32w(uint crc, uint value) => Crc32w(crc, Crc32RevPoly, value);
|
||||||
public static uint Crc32x(uint crc, ulong val) => Crc32x(crc, Crc32RevPoly, val);
|
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 Crc32cb(uint crc, byte value) => Crc32 (crc, Crc32cRevPoly, value);
|
||||||
public static uint Crc32ch(uint crc, ushort val) => Crc32h(crc, Crc32cRevPoly, val);
|
public static uint Crc32ch(uint crc, ushort value) => Crc32h(crc, Crc32cRevPoly, value);
|
||||||
public static uint Crc32cw(uint crc, uint val) => Crc32w(crc, Crc32cRevPoly, val);
|
public static uint Crc32cw(uint crc, uint value) => Crc32w(crc, Crc32cRevPoly, value);
|
||||||
public static uint Crc32cx(uint crc, ulong val) => Crc32x(crc, Crc32cRevPoly, val);
|
public static uint Crc32cx(uint crc, ulong value) => Crc32x(crc, Crc32cRevPoly, value);
|
||||||
|
|
||||||
private static uint Crc32h(uint crc, uint poly, ushort val)
|
private static uint Crc32h(uint crc, uint poly, ushort val)
|
||||||
{
|
{
|
||||||
|
@ -84,7 +473,25 @@ namespace ARMeilleure.Instructions
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region "Aes"
|
#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
|
#endregion
|
||||||
|
|
||||||
#region "Sha1"
|
#region "Sha1"
|
||||||
|
|
2741
ARMeilleure/Instructions/SoftFloat.cs
Normal file
2741
ARMeilleure/Instructions/SoftFloat.cs
Normal file
File diff suppressed because it is too large
Load diff
|
@ -54,6 +54,120 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||||
Store8,
|
Store8,
|
||||||
StoreToContext,
|
StoreToContext,
|
||||||
Subtract,
|
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
|
Count
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,11 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||||
return new Operand(BitConverter.SingleToInt32Bits(value));
|
return new Operand(BitConverter.SingleToInt32Bits(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Operand ConstF(double value)
|
||||||
|
{
|
||||||
|
return new Operand(BitConverter.DoubleToInt64Bits(value));
|
||||||
|
}
|
||||||
|
|
||||||
public static Operand Label()
|
public static Operand Label()
|
||||||
{
|
{
|
||||||
return new Operand(OperandKind.Label);
|
return new Operand(OperandKind.Label);
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace ARMeilleure.IntermediateRepresentation
|
namespace ARMeilleure.IntermediateRepresentation
|
||||||
{
|
{
|
||||||
enum OperandType
|
enum OperandType
|
||||||
|
@ -17,5 +19,19 @@ namespace ARMeilleure.IntermediateRepresentation
|
||||||
return type == OperandType.I32 ||
|
return type == OperandType.I32 ||
|
||||||
type == OperandType.I64;
|
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}\".");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace ARMeilleure.State
|
namespace ARMeilleure.IntermediateRepresentation
|
||||||
{
|
{
|
||||||
struct Register : IEquatable<Register>
|
struct Register : IEquatable<Register>
|
||||||
{
|
{
|
|
@ -1,4 +1,4 @@
|
||||||
namespace ARMeilleure.State
|
namespace ARMeilleure.IntermediateRepresentation
|
||||||
{
|
{
|
||||||
enum RegisterType
|
enum RegisterType
|
||||||
{
|
{
|
|
@ -4,7 +4,7 @@ namespace ARMeilleure
|
||||||
{
|
{
|
||||||
public static bool AssumeStrictAbiCompliance { get; set; }
|
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 UseSseIfAvailable { get; set; }
|
||||||
public static bool UseSse2IfAvailable { get; set; }
|
public static bool UseSse2IfAvailable { get; set; }
|
||||||
|
@ -12,5 +12,14 @@ namespace ARMeilleure
|
||||||
public static bool UseSsse3IfAvailable { get; set; }
|
public static bool UseSsse3IfAvailable { get; set; }
|
||||||
public static bool UseSse41IfAvailable { 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; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -8,6 +8,9 @@ namespace ARMeilleure.State
|
||||||
|
|
||||||
internal IntPtr NativeContextPtr => _nativeContext.BasePtr;
|
internal IntPtr NativeContextPtr => _nativeContext.BasePtr;
|
||||||
|
|
||||||
|
public FPCR Fpcr { get; set; }
|
||||||
|
public FPSR Fpsr { get; set; }
|
||||||
|
|
||||||
public event EventHandler<InstExceptionEventArgs> Break;
|
public event EventHandler<InstExceptionEventArgs> Break;
|
||||||
public event EventHandler<InstExceptionEventArgs> SupervisorCall;
|
public event EventHandler<InstExceptionEventArgs> SupervisorCall;
|
||||||
public event EventHandler<InstUndefinedEventArgs> Undefined;
|
public event EventHandler<InstUndefinedEventArgs> Undefined;
|
||||||
|
|
23
ARMeilleure/State/FPCR.cs
Normal file
23
ARMeilleure/State/FPCR.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
12
ARMeilleure/State/FPException.cs
Normal file
12
ARMeilleure/State/FPException.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
namespace ARMeilleure.State
|
||||||
|
{
|
||||||
|
enum FPException
|
||||||
|
{
|
||||||
|
InvalidOp = 0,
|
||||||
|
DivideByZero = 1,
|
||||||
|
Overflow = 2,
|
||||||
|
Underflow = 3,
|
||||||
|
Inexact = 4,
|
||||||
|
InputDenorm = 7
|
||||||
|
}
|
||||||
|
}
|
10
ARMeilleure/State/FPRoundingMode.cs
Normal file
10
ARMeilleure/State/FPRoundingMode.cs
Normal 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
11
ARMeilleure/State/FPSR.cs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace ARMeilleure.State
|
||||||
|
{
|
||||||
|
[Flags]
|
||||||
|
public enum FPSR
|
||||||
|
{
|
||||||
|
Ufc = 1 << 3,
|
||||||
|
Qc = 1 << 27
|
||||||
|
}
|
||||||
|
}
|
11
ARMeilleure/State/FPType.cs
Normal file
11
ARMeilleure/State/FPType.cs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
namespace ARMeilleure.State
|
||||||
|
{
|
||||||
|
enum FPType
|
||||||
|
{
|
||||||
|
Nonzero,
|
||||||
|
Zero,
|
||||||
|
Infinity,
|
||||||
|
QNaN,
|
||||||
|
SNaN
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
using ARMeilleure.IntermediateRepresentation;
|
||||||
using ARMeilleure.Memory;
|
using ARMeilleure.Memory;
|
||||||
using System;
|
using System;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
|
@ -7,19 +7,45 @@ namespace ARMeilleure.State
|
||||||
private ulong _e0;
|
private ulong _e0;
|
||||||
private ulong _e1;
|
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);
|
_e0 = (ulong)(uint)BitConverter.SingleToInt32Bits(e0) << 0;
|
||||||
_e1 = 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);
|
_e0 = (ulong)BitConverter.DoubleToInt64Bits(e0);
|
||||||
_e1 = 0;
|
_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)
|
public V128(ulong e0, ulong e1)
|
||||||
{
|
{
|
||||||
|
@ -27,6 +53,12 @@ namespace ARMeilleure.State
|
||||||
_e1 = e1;
|
_e1 = e1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public V128(byte[] data)
|
||||||
|
{
|
||||||
|
_e0 = (ulong)BitConverter.ToInt64(data, 0);
|
||||||
|
_e1 = (ulong)BitConverter.ToInt64(data, 8);
|
||||||
|
}
|
||||||
|
|
||||||
public float AsFloat()
|
public float AsFloat()
|
||||||
{
|
{
|
||||||
return GetFloat(0);
|
return GetFloat(0);
|
||||||
|
@ -48,6 +80,7 @@ namespace ARMeilleure.State
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
public uint GetUInt32(int index)
|
||||||
{
|
{
|
||||||
|
@ -56,11 +89,9 @@ namespace ARMeilleure.State
|
||||||
throw new ArgumentOutOfRangeException(nameof(index));
|
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)
|
public ulong GetUInt64(int index)
|
||||||
{
|
{
|
||||||
switch (index)
|
switch (index)
|
||||||
|
@ -72,11 +103,44 @@ namespace ARMeilleure.State
|
||||||
throw new ArgumentOutOfRangeException(nameof(index));
|
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()
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
return HashCode.Combine(_e0, _e1);
|
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)
|
public static bool operator ==(V128 x, V128 y)
|
||||||
{
|
{
|
||||||
return x.Equals(y);
|
return x.Equals(y);
|
||||||
|
@ -96,5 +160,10 @@ namespace ARMeilleure.State
|
||||||
{
|
{
|
||||||
return other._e0 == _e0 && other._e1 == _e1;
|
return other._e0 == _e0 && other._e1 == _e1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"0x{_e1:X16}{_e0:X16}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -37,6 +37,11 @@ namespace ARMeilleure.Translation
|
||||||
_needsNewBlock = true;
|
_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)
|
public Operand BitwiseAnd(Operand a, Operand b)
|
||||||
{
|
{
|
||||||
return Add(Instruction.BitwiseAnd, Local(a.Type), a, 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);
|
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)
|
public Operand ICompareEqual(Operand a, Operand b)
|
||||||
|
@ -213,31 +223,6 @@ namespace ARMeilleure.Translation
|
||||||
return Add(Instruction.CompareNotEqual, Local(OperandType.I32), a, b);
|
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)
|
public Operand Load(Operand value, Operand address)
|
||||||
{
|
{
|
||||||
return Add(Instruction.Load, value, address);
|
return Add(Instruction.Load, value, address);
|
||||||
|
@ -268,6 +253,11 @@ namespace ARMeilleure.Translation
|
||||||
return Add(Instruction.LoadZx8, value, address);
|
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)
|
public Operand Multiply64HighSI(Operand a, Operand b)
|
||||||
{
|
{
|
||||||
return Add(Instruction.Multiply64HighSI, Local(OperandType.I64), a, 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);
|
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()
|
public Operand Return()
|
||||||
{
|
{
|
||||||
return Add(Instruction.Return);
|
return Add(Instruction.Return);
|
||||||
|
@ -338,6 +333,61 @@ namespace ARMeilleure.Translation
|
||||||
Add(Instruction.Store8, null, address, value);
|
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)
|
private Operand Add(Instruction inst, Operand dest = null, params Operand[] sources)
|
||||||
{
|
{
|
||||||
if (_needsNewBlock)
|
if (_needsNewBlock)
|
||||||
|
|
|
@ -41,8 +41,6 @@ namespace ARMeilleure.Translation
|
||||||
|
|
||||||
private TranslatedFunction Translate(ulong address, ExecutionMode mode)
|
private TranslatedFunction Translate(ulong address, ExecutionMode mode)
|
||||||
{
|
{
|
||||||
Logger logger = new Logger();
|
|
||||||
|
|
||||||
EmitterContext context = new EmitterContext();
|
EmitterContext context = new EmitterContext();
|
||||||
|
|
||||||
Block[] blocks = Decoder.DecodeFunction(_memory, address, ExecutionMode.Aarch64);
|
Block[] blocks = Decoder.DecodeFunction(_memory, address, ExecutionMode.Aarch64);
|
||||||
|
@ -55,11 +53,11 @@ namespace ARMeilleure.Translation
|
||||||
|
|
||||||
Dominance.FindDominanceFrontiers(cfg);
|
Dominance.FindDominanceFrontiers(cfg);
|
||||||
|
|
||||||
logger.StartPass(PassName.SsaConstruction);
|
Logger.StartPass(PassName.SsaConstruction);
|
||||||
|
|
||||||
Ssa.Rename(cfg);
|
Ssa.Rename(cfg);
|
||||||
|
|
||||||
logger.EndPass(PassName.SsaConstruction, cfg);
|
Logger.EndPass(PassName.SsaConstruction, cfg);
|
||||||
|
|
||||||
byte[] code = CodeGenerator.Generate(cfg, _memory);
|
byte[] code = CodeGenerator.Generate(cfg, _memory);
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,46 @@ namespace Ryujinx.Tests.Unicorn
|
||||||
private ulong _e0;
|
private ulong _e0;
|
||||||
private ulong _e1;
|
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)
|
public SimdValue(ulong e0, ulong e1)
|
||||||
{
|
{
|
||||||
_e0 = e0;
|
_e0 = e0;
|
||||||
|
@ -19,19 +59,6 @@ namespace Ryujinx.Tests.Unicorn
|
||||||
_e1 = (ulong)BitConverter.ToInt64(data, 8);
|
_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()
|
public float AsFloat()
|
||||||
{
|
{
|
||||||
return GetFloat(0);
|
return GetFloat(0);
|
||||||
|
@ -53,6 +80,7 @@ namespace Ryujinx.Tests.Unicorn
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
public uint GetUInt32(int index)
|
||||||
{
|
{
|
||||||
|
@ -61,11 +89,9 @@ namespace Ryujinx.Tests.Unicorn
|
||||||
throw new ArgumentOutOfRangeException(nameof(index));
|
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)
|
public ulong GetUInt64(int index)
|
||||||
{
|
{
|
||||||
switch (index)
|
switch (index)
|
||||||
|
@ -77,6 +103,19 @@ namespace Ryujinx.Tests.Unicorn
|
||||||
throw new ArgumentOutOfRangeException(nameof(index));
|
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()
|
public override int GetHashCode()
|
||||||
{
|
{
|
||||||
return HashCode.Combine(_e0, _e1);
|
return HashCode.Combine(_e0, _e1);
|
||||||
|
@ -94,12 +133,17 @@ namespace Ryujinx.Tests.Unicorn
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
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)
|
public bool Equals(SimdValue other)
|
||||||
{
|
{
|
||||||
return other._e0 == _e0 && other._e1 == _e1;
|
return other._e0 == _e0 && other._e1 == _e1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"0x{_e1:X16}{_e0:X16}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -135,8 +135,8 @@ namespace Ryujinx.Tests.Cpu
|
||||||
_context.SetPstateFlag(PState.ZFlag, zero);
|
_context.SetPstateFlag(PState.ZFlag, zero);
|
||||||
_context.SetPstateFlag(PState.NFlag, negative);
|
_context.SetPstateFlag(PState.NFlag, negative);
|
||||||
|
|
||||||
//_thread.ThreadState.Fpcr = fpcr;
|
_context.Fpcr = (FPCR)fpcr;
|
||||||
//_thread.ThreadState.Fpsr = fpsr;
|
_context.Fpsr = (FPSR)fpsr;
|
||||||
|
|
||||||
if (_unicornAvailable)
|
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(30)), Is.EqualTo(_unicornEmu.Q[30]));
|
||||||
Assert.That(V128ToSimdValue(_context.GetV(31)), Is.EqualTo(_unicornEmu.Q[31]));
|
Assert.That(V128ToSimdValue(_context.GetV(31)), Is.EqualTo(_unicornEmu.Q[31]));
|
||||||
|
|
||||||
//Assert.That(_thread.ThreadState.Fpcr, Is.EqualTo(_unicornEmu.Fpcr));
|
Assert.That((int)_context.Fpcr, Is.EqualTo(_unicornEmu.Fpcr));
|
||||||
//Assert.That(_thread.ThreadState.Fpsr & (int)fpsrMask, Is.EqualTo(_unicornEmu.Fpsr & (int)fpsrMask));
|
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.VFlag), Is.EqualTo(_unicornEmu.OverflowFlag));
|
||||||
Assert.That(_context.GetPstateFlag(PState.CFlag), Is.EqualTo(_unicornEmu.CarryFlag));
|
Assert.That(_context.GetPstateFlag(PState.CFlag), Is.EqualTo(_unicornEmu.CarryFlag));
|
||||||
|
|
|
@ -190,7 +190,7 @@ namespace Ryujinx.Tests.Cpu
|
||||||
Opcode(0xD65F03C0);
|
Opcode(0xD65F03C0);
|
||||||
ExecuteOpcodes();
|
ExecuteOpcodes();
|
||||||
|
|
||||||
Assert.That(GetVectorE0(GetContext().GetV(0)), Is.EqualTo(16f));
|
Assert.That(GetContext().GetV(0).AsFloat(), Is.EqualTo(16f));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Explicit]
|
[Explicit]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue