Misc. fixes and integrate LDj3SNuD fixes

This commit is contained in:
gdkchan 2019-06-29 22:43:56 -03:00
parent c306809b0b
commit ba9ff58d94
45 changed files with 905 additions and 788 deletions

View file

@ -1,6 +1,7 @@
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Translation;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace ARMeilleure.CodeGen.Optimizations
@ -61,8 +62,7 @@ namespace ARMeilleure.CodeGen.Optimizations
private static void PropagateCopy(Operation copyOp)
{
//Propagate copy source operand to all uses of
//the destination operand.
//Propagate copy source operand to all uses of the destination operand.
Operand dest = copyOp.Dest;
Operand source = copyOp.GetSource(0);
@ -86,35 +86,21 @@ namespace ARMeilleure.CodeGen.Optimizations
//from all the use lists on the operands that this node uses.
block.Operations.Remove(llNode);
Queue<Node> nodes = new Queue<Node>();
Node node = llNode.Value;
nodes.Enqueue(llNode.Value);
while (nodes.TryDequeue(out Node node))
for (int index = 0; index < node.SourcesCount; index++)
{
for (int index = 0; index < node.SourcesCount; index++)
{
Operand src = node.GetSource(index);
if (src.Kind != OperandKind.LocalVariable)
{
continue;
}
if (src.Uses.Remove(node) && src.Uses.Count == 0)
{
foreach (Node assignment in src.Assignments)
{
nodes.Enqueue(assignment);
}
}
}
node.SetSource(index, null);
}
Debug.Assert(node.Dest == null || node.Dest.Uses.Count == 0);
node.Dest = null;
}
private static bool IsUnused(Node node)
{
return DestIsLocalVar(node) && node.Dest.Uses.Count == 0;
return DestIsLocalVar(node) && node.Dest.Uses.Count == 0 && !HasSideEffects(node);
}
private static bool DestIsLocalVar(Node node)
@ -122,6 +108,11 @@ namespace ARMeilleure.CodeGen.Optimizations
return node.Dest != null && node.Dest.Kind == OperandKind.LocalVariable;
}
private static bool HasSideEffects(Node node)
{
return (node is Operation operation) && operation.Inst == Instruction.Call;
}
private static bool IsPropagableCopy(Operation operation)
{
if (operation.Inst != Instruction.Copy)

View file

@ -1,5 +1,4 @@
using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State;
using System;
using System.Collections.Generic;
@ -100,6 +99,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
OperandType type = types[copyDest];
type = type.IsInteger() ? OperandType.I64 : OperandType.V128;
EmitXorSwap(sequence, GetRegister(copyDest, type), GetRegister(copySource, type));
locations[origSource] = copyDest;

View file

@ -201,17 +201,28 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
int selectedNextUse = freePositions[selectedReg];
if (GetSplitPosition(selectedNextUse) <= current.GetStart())
//Intervals starts and ends at odd positions, unless they span an entire
//block, in this case they will have ranges at even position.
//When a interval is loaded from the stack to a register, we can only
//do the split at a odd position, because otherwise the split interval
//that is inserted on the list to be processed may clobber a register
//used by the instruction at the same position as the split.
//The problem only happens when a interval ends exactly at this instruction,
//because otherwise they would interfere, and the register wouldn't be selected.
//When the interval is aligned and the above happens, there's no problem as
//the instruction that is actually with the last use is the one
//before that position.
selectedNextUse &= ~InstructionGapMask;
if (selectedNextUse <= current.GetStart())
{
return false;
}
else if (selectedNextUse < current.GetEnd())
{
int splitPosition = GetSplitPosition(selectedNextUse);
Debug.Assert(selectedNextUse > current.GetStart(), "Trying to split interval at the start.");
Debug.Assert(splitPosition > current.GetStart(), "Trying to split interval at the start.");
LiveInterval splitChild = current.Split(splitPosition);
LiveInterval splitChild = current.Split(selectedNextUse);
if (splitChild.UsesCount != 0)
{
@ -340,7 +351,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
//so spill the current interval.
Debug.Assert(currentFirstUse > current.GetStart(), "Trying to spill a interval currently being used.");
LiveInterval splitChild = current.Split(GetSplitPosition(currentFirstUse));
LiveInterval splitChild = current.Split(currentFirstUse);
Debug.Assert(splitChild.GetStart() > current.GetStart(), "Split interval has an invalid start position.");
@ -365,7 +376,11 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
//the first fixed register use.
current.Register = new Register(selectedReg, regType);
LiveInterval splitChild = current.Split(GetSplitPosition(blockedPositions[selectedReg]));
int splitPosition = blockedPositions[selectedReg] & ~InstructionGapMask;
Debug.Assert(splitPosition > current.GetStart(), "Trying to split a interval at a invalid position.");
LiveInterval splitChild = current.Split(splitPosition);
if (splitChild.UsesCount != 0)
{
@ -457,7 +472,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
if (interval.GetStart() < current.GetStart())
{
splitChild = interval.Split(GetSplitPosition(current.GetStart()));
splitChild = interval.Split(current.GetStart());
}
else
{
@ -468,27 +483,16 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
Debug.Assert(nextUse > current.GetStart(), "Trying to spill a interval currently being used.");
if (GetSplitPosition(nextUse) > splitChild.GetStart())
if (nextUse > splitChild.GetStart())
{
LiveInterval right = splitChild.Split(GetSplitPosition(nextUse));
LiveInterval right = splitChild.Split(nextUse);
Spill(context, splitChild);
Debug.Assert(right.GetStart() > current.GetStart(), "Split interval has an invalid start position.");
InsertInterval(right);
splitChild = right;
}
else
{
if (nextUse == splitChild.GetStart())
{
splitChild.SetStart(GetSplitPosition(nextUse));
}
Debug.Assert(splitChild.GetStart() > current.GetStart(), "Split interval has an invalid start position.");
InsertInterval(splitChild);
}
InsertInterval(splitChild);
}
else
{
@ -502,7 +506,9 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
Debug.Assert(!interval.IsEmpty, "Trying to insert a empty interval.");
Debug.Assert(!interval.IsSpilled, "Trying to insert a spilled interval.");
int insertIndex = _intervals.BinarySearch(interval);
int startIndex = RegistersCount * 2;
int insertIndex = _intervals.BinarySearch(startIndex, _intervals.Count - startIndex, interval, null);
if (insertIndex < 0)
{
@ -550,9 +556,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
int splitPosition = splitChild.GetStart();
int alignedSplitPosition = GetAlignedSplitPosition(splitPosition);
if (!_blockEdges.Contains(alignedSplitPosition) && previous.GetEnd() == splitPosition)
if (!_blockEdges.Contains(splitPosition) && previous.GetEnd() == splitPosition)
{
GetCopyResolver(splitPosition).AddSplit(previous, splitChild);
}
@ -576,7 +580,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
Operation[] sequence = copyResolver.Sequence();
node = node.List.AddAfter(node, sequence[0]);
node = node.List.AddBefore(node, sequence[0]);
for (int index = 1; index < sequence.Length; index++)
{
@ -627,13 +631,13 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
continue;
}
int lEnd = _blockRanges[block.Index].End - InstructionGap;
int lEnd = _blockRanges[block.Index].End - 1;
int rStart = _blockRanges[succIndex].Start;
LiveInterval left = interval.GetSplitChild(lEnd);
LiveInterval right = interval.GetSplitChild(rStart);
if (left != right)
if (left != null && right != null && left != right)
{
copyResolver.AddSplit(left, right);
}
@ -705,10 +709,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private static Operand GetRegister(LiveInterval interval)
{
if (interval.IsSpilled)
{
throw new ArgumentException("Spilled intervals are not allowed.");
}
Debug.Assert(!interval.IsSpilled, "Spilled intervals are not allowed.");
return new Operand(
interval.Register.Index,
@ -716,16 +717,6 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
interval.Local.Type);
}
private static int GetSplitPosition(int position)
{
return (position & InstructionGapMask) == 0 ? position - 1 : position;
}
private static int GetAlignedSplitPosition(int position)
{
return (position + InstructionGapMask) & ~InstructionGapMask;
}
private LinkedListNode<Node> GetOperationNode(int position)
{
return _operationNodes[position / InstructionGap];
@ -768,6 +759,14 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
}
_operationsCount += block.Operations.Count * InstructionGap;
if (block.Operations.Count == 0)
{
//Pretend we have a dummy instruction on the empty block.
_operationNodes.Add(null);
_operationsCount += InstructionGap;
}
}
_parentIntervals = _intervals.ToArray();
@ -860,14 +859,12 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
BasicBlock block = cfg.PostOrderBlocks[index];
if (block.Operations.Count == 0)
{
_blockRanges[block.Index] = new LiveRange(operationPos, operationPos + InstructionGap);
//We handle empty blocks by pretending they have a dummy instruction,
//because otherwise the block would have the same start and end position,
//and this is not valid.
int instCount = Math.Max(block.Operations.Count, 1);
continue;
}
int blockStart = operationPos - block.Operations.Count * InstructionGap;
int blockStart = operationPos - instCount * InstructionGap;
int blockEnd = operationPos;
_blockRanges[block.Index] = new LiveRange(blockStart, blockEnd);
@ -881,17 +878,16 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
_intervals[id].AddRange(blockStart, blockEnd);
}
foreach (Node node in BottomOperations(block))
if (block.Operations.Count == 0)
{
operationPos -= InstructionGap;
foreach (Operand source in Operands(node))
{
LiveInterval interval = _intervals[GetOperandId(source)];
continue;
}
interval.AddRange(blockStart, operationPos);
interval.AddUsePosition(operationPos);
}
foreach (Node node in BottomOperations(block))
{
operationPos -= InstructionGap;
Operand dest = node.Dest;
@ -899,7 +895,15 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
LiveInterval interval = _intervals[GetOperandId(dest)];
interval.SetStart(operationPos);
interval.SetStart(operationPos + 1);
interval.AddUsePosition(operationPos + 1);
}
foreach (Operand source in Operands(node))
{
LiveInterval interval = _intervals[GetOperandId(source)];
interval.AddRange(blockStart, operationPos + 1);
interval.AddUsePosition(operationPos);
}
@ -937,7 +941,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
LiveInterval interval = _intervals[GetRegisterId(callerSavedReg)];
interval.AddRange(operationPos, operationPos + 1);
interval.AddRange(operationPos + 1, operationPos + InstructionGap);
mask &= ~(1 << regIndex);
}

View file

@ -73,11 +73,13 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
if (_ranges.Count != 0)
{
Debug.Assert(position != _ranges[0].End);
_ranges[0] = new LiveRange(position, _ranges[0].End);
}
else
{
_ranges.Add(new LiveRange(position, position));
_ranges.Add(new LiveRange(position, position + 1));
}
}
@ -103,6 +105,11 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
public void AddRange(int start, int end)
{
if (start >= end)
{
throw new ArgumentException("Invalid range start position " + start + ", " + end);
}
int index = _ranges.BinarySearch(new LiveRange(start, end));
if (index >= 0)
@ -329,27 +336,19 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
public LiveInterval GetSplitChild(int position)
{
//Try to find the interval among the split intervals that
//contains the given position. The end is technically exclusive,
//so if we have a interval where position == start, and other
//where position == end, we should prefer the former.
//To achieve that, we can just check the split childs backwards,
//as they are sorted by start/end position, and there are no overlaps.
for (int index = _childs.Count - 1; index >= 0; index--)
if (Overlaps(position))
{
LiveInterval splitChild = _childs.Values[index];
return this;
}
if (position >= splitChild.GetStart() && position <= splitChild.GetEnd())
foreach (LiveInterval splitChild in _childs.Values)
{
if (splitChild.Overlaps(position))
{
return splitChild;
}
}
if (position >= GetStart() && position <= GetEnd())
{
return this;
}
return null;
}

View file

@ -8,38 +8,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{
static class PhiFunctions
{
private struct PhiEntry
{
public BasicBlock Predecessor { get; }
public Operand Source { get; }
public PhiEntry(BasicBlock predecessor, Operand source)
{
Predecessor = predecessor;
Source = source;
}
}
public static void Remove(ControlFlowGraph cfg)
{
List<int> defBlocks = new List<int>();
HashSet<Operand> visited = new HashSet<Operand>();
//Build a list with the index of the block where each variable
//is defined, and additionally number all the variables.
foreach (BasicBlock block in cfg.Blocks)
{
foreach (Node node in block.Operations)
{
if (node.Dest != null && node.Dest.Kind == OperandKind.LocalVariable && visited.Add(node.Dest))
{
node.Dest.NumberLocal(defBlocks.Count);
defBlocks.Add(block.Index);
}
}
}
foreach (BasicBlock block in cfg.Blocks)
{
LinkedListNode<Node> node = block.Operations.First;
@ -50,19 +20,14 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
Operand local = Local(phi.Dest.Type);
PhiEntry[] phiSources = GetPhiSources(phi);
for (int srcIndex = 0; srcIndex < phiSources.Length; srcIndex++)
{
BasicBlock predecessor = phiSources[srcIndex].Predecessor;
Operand source = phiSources[srcIndex].Source;
predecessor.Append(new Operation(Instruction.Copy, local, source));
}
for (int index = 0; index < phi.SourcesCount; index++)
{
BasicBlock predecessor = phi.GetBlock(index);
Operand source = phi.GetSource(index);
predecessor.Append(new Operation(Instruction.Copy, local, source));
phi.SetSource(index, null);
}
@ -78,66 +43,5 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
}
}
}
private static PhiEntry[] GetPhiSources(PhiNode phi)
{
Dictionary<Operand, HashSet<BasicBlock>> defBlocksPerSrc = new Dictionary<Operand, HashSet<BasicBlock>>();
List<PhiEntry> phiSources = new List<PhiEntry>();
for (int index = 0; index < phi.SourcesCount; index++)
{
Operand source = phi.GetSource(index);
BasicBlock predecessor = phi.GetBlock(index);
BasicBlock defBlock = FindDefBlock(source, predecessor);
if (defBlock != null)
{
if (!defBlocksPerSrc.TryGetValue(source, out HashSet<BasicBlock> defBlocks))
{
defBlocks = new HashSet<BasicBlock>();
defBlocksPerSrc.Add(source, defBlocks);
}
if (!defBlocks.Add(defBlock))
{
continue;
}
}
phiSources.Add(new PhiEntry(defBlock ?? predecessor, source));
}
return phiSources.ToArray();
}
private static BasicBlock FindDefBlock(Operand source, BasicBlock predecessor)
{
if (source.Kind == OperandKind.LocalVariable)
{
while (true)
{
foreach (Node node in predecessor.Operations)
{
if (node.Dest == source)
{
return predecessor;
}
}
if (predecessor == predecessor.ImmediateDominator)
{
break;
}
predecessor = predecessor.ImmediateDominator;
}
}
return null;
}
}
}

View file

@ -14,11 +14,13 @@ namespace ARMeilleure.CodeGen.X86
[Flags]
private enum InstFlags
{
None = 0,
RegOnly = 1 << 0,
Reg8 = 1 << 1,
NoRexW = 1 << 2,
Vex = 1 << 3,
None = 0,
RegOnly = 1 << 0,
Reg8Src = 1 << 1,
Reg8Dest = 1 << 2,
NoRexW = 1 << 3,
RexW = 1 << 4,
Vex = 1 << 5,
PrefixBit = 16,
PrefixMask = 3 << PrefixBit,
@ -64,182 +66,182 @@ namespace ARMeilleure.CodeGen.X86
// Name RM/R RM/I8 RM/I32 R/I64 R/RM Flags
Add(X86Instruction.Add, new InstInfo(0x00000001, 0x00000083, 0x00000081, BadOp, 0x00000003, InstFlags.None));
Add(X86Instruction.Addpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Addps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstFlags.Vex));
Add(X86Instruction.Addsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstFlags.Vex | InstFlags.PrefixF2));
Add(X86Instruction.Addss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstFlags.Vex | InstFlags.PrefixF3));
Add(X86Instruction.Addpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Addps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstFlags.Vex | InstFlags.NoRexW));
Add(X86Instruction.Addsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF2));
Add(X86Instruction.Addss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF3));
Add(X86Instruction.And, new InstInfo(0x00000021, 0x04000083, 0x04000081, BadOp, 0x00000023, InstFlags.None));
Add(X86Instruction.Andnpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f55, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Andnps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f55, InstFlags.Vex));
Add(X86Instruction.Andnpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f55, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Andnps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f55, InstFlags.Vex | InstFlags.NoRexW));
Add(X86Instruction.Bsr, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fbd, InstFlags.None));
Add(X86Instruction.Bswap, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc8, InstFlags.RegOnly));
Add(X86Instruction.Bswap, new InstInfo(0x00000fc8, BadOp, BadOp, BadOp, BadOp, InstFlags.RegOnly));
Add(X86Instruction.Call, new InstInfo(0x020000ff, BadOp, BadOp, BadOp, BadOp, InstFlags.NoRexW));
Add(X86Instruction.Cmovcc, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f40, InstFlags.None));
Add(X86Instruction.Cmp, new InstInfo(0x00000039, 0x07000083, 0x07000081, BadOp, 0x0000003b, InstFlags.None));
Add(X86Instruction.Cmppd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Cmpps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstFlags.Vex));
Add(X86Instruction.Cmpsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstFlags.Vex | InstFlags.PrefixF2));
Add(X86Instruction.Cmpss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstFlags.Vex | InstFlags.PrefixF3));
Add(X86Instruction.Comisd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2f, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Comiss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2f, InstFlags.Vex));
Add(X86Instruction.Cvtdq2pd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fe6, InstFlags.Vex | InstFlags.PrefixF3));
Add(X86Instruction.Cvtdq2ps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5b, InstFlags.Vex));
Add(X86Instruction.Cvtpd2dq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fe6, InstFlags.Vex | InstFlags.PrefixF2));
Add(X86Instruction.Cvtpd2ps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5a, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Cvtps2dq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5b, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Cvtps2pd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5a, InstFlags.Vex));
Add(X86Instruction.Cmppd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Cmpps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstFlags.Vex | InstFlags.NoRexW));
Add(X86Instruction.Cmpsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF2));
Add(X86Instruction.Cmpss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF3));
Add(X86Instruction.Comisd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2f, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Comiss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2f, InstFlags.Vex | InstFlags.NoRexW));
Add(X86Instruction.Cvtdq2pd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fe6, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF3));
Add(X86Instruction.Cvtdq2ps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5b, InstFlags.Vex | InstFlags.NoRexW));
Add(X86Instruction.Cvtpd2dq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fe6, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF2));
Add(X86Instruction.Cvtpd2ps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5a, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Cvtps2dq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5b, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Cvtps2pd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5a, InstFlags.Vex | InstFlags.NoRexW));
Add(X86Instruction.Cvtsd2si, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2c, InstFlags.Vex | InstFlags.PrefixF2));
Add(X86Instruction.Cvtsd2ss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5a, InstFlags.Vex | InstFlags.PrefixF2));
Add(X86Instruction.Cvtsd2ss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5a, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF2));
Add(X86Instruction.Cvtsi2sd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2a, InstFlags.Vex | InstFlags.PrefixF2));
Add(X86Instruction.Cvtsi2ss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2a, InstFlags.Vex | InstFlags.PrefixF3));
Add(X86Instruction.Cvtss2sd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5a, InstFlags.Vex | InstFlags.PrefixF3));
Add(X86Instruction.Cvtss2sd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5a, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF3));
Add(X86Instruction.Div, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x060000f7, InstFlags.None));
Add(X86Instruction.Divpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Divps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstFlags.Vex));
Add(X86Instruction.Divsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstFlags.Vex | InstFlags.PrefixF2));
Add(X86Instruction.Divss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstFlags.Vex | InstFlags.PrefixF3));
Add(X86Instruction.Haddpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f7c, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Haddps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f7c, InstFlags.Vex | InstFlags.PrefixF2));
Add(X86Instruction.Divpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Divps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstFlags.Vex | InstFlags.NoRexW));
Add(X86Instruction.Divsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF2));
Add(X86Instruction.Divss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF3));
Add(X86Instruction.Haddpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f7c, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Haddps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f7c, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF2));
Add(X86Instruction.Idiv, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x070000f7, InstFlags.None));
Add(X86Instruction.Imul, new InstInfo(BadOp, 0x0000006b, 0x00000069, BadOp, 0x00000faf, InstFlags.None));
Add(X86Instruction.Imul128, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x050000f7, InstFlags.None));
Add(X86Instruction.Insertps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a21, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Insertps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a21, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Lea, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x0000008d, InstFlags.None));
Add(X86Instruction.Maxpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5f, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Maxps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5f, InstFlags.Vex));
Add(X86Instruction.Maxsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5f, InstFlags.Vex | InstFlags.PrefixF2));
Add(X86Instruction.Maxss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5f, InstFlags.Vex | InstFlags.PrefixF3));
Add(X86Instruction.Minpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5d, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Minps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5d, InstFlags.Vex));
Add(X86Instruction.Minsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5d, InstFlags.Vex | InstFlags.PrefixF2));
Add(X86Instruction.Minss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5d, InstFlags.Vex | InstFlags.PrefixF3));
Add(X86Instruction.Maxpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5f, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Maxps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5f, InstFlags.Vex | InstFlags.NoRexW));
Add(X86Instruction.Maxsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5f, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF2));
Add(X86Instruction.Maxss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5f, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF3));
Add(X86Instruction.Minpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5d, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Minps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5d, InstFlags.Vex | InstFlags.NoRexW));
Add(X86Instruction.Minsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5d, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF2));
Add(X86Instruction.Minss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5d, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF3));
Add(X86Instruction.Mov, new InstInfo(0x00000089, BadOp, 0x000000c7, 0x000000b8, 0x0000008b, InstFlags.None));
Add(X86Instruction.Mov16, new InstInfo(0x00000089, BadOp, 0x000000c7, BadOp, 0x0000008b, InstFlags.Prefix66));
Add(X86Instruction.Mov8, new InstInfo(0x00000088, 0x000000c6, BadOp, BadOp, 0x0000008a, InstFlags.None));
Add(X86Instruction.Movd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f6e, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Movdqu, new InstInfo(0x00000f7f, BadOp, BadOp, BadOp, 0x00000f6f, InstFlags.Vex | InstFlags.PrefixF3));
Add(X86Instruction.Movhlps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f12, InstFlags.Vex));
Add(X86Instruction.Movlhps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f16, InstFlags.Vex));
Add(X86Instruction.Movq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f7e, InstFlags.Vex | InstFlags.PrefixF3));
Add(X86Instruction.Movsd, new InstInfo(0x00000f11, BadOp, BadOp, BadOp, 0x00000f10, InstFlags.Vex | InstFlags.PrefixF2));
Add(X86Instruction.Movss, new InstInfo(0x00000f11, BadOp, BadOp, BadOp, 0x00000f10, InstFlags.Vex | InstFlags.PrefixF3));
Add(X86Instruction.Mov8, new InstInfo(0x00000088, 0x000000c6, BadOp, BadOp, 0x0000008a, InstFlags.Reg8Src | InstFlags.Reg8Dest));
Add(X86Instruction.Movd, new InstInfo(0x00000f7e, BadOp, BadOp, BadOp, 0x00000f6e, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Movdqu, new InstInfo(0x00000f7f, BadOp, BadOp, BadOp, 0x00000f6f, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF3));
Add(X86Instruction.Movhlps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f12, InstFlags.Vex | InstFlags.NoRexW));
Add(X86Instruction.Movlhps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f16, InstFlags.Vex | InstFlags.NoRexW));
Add(X86Instruction.Movq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f7e, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF3));
Add(X86Instruction.Movsd, new InstInfo(0x00000f11, BadOp, BadOp, BadOp, 0x00000f10, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF2));
Add(X86Instruction.Movss, new InstInfo(0x00000f11, BadOp, BadOp, BadOp, 0x00000f10, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF3));
Add(X86Instruction.Movsx16, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fbf, InstFlags.None));
Add(X86Instruction.Movsx32, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000063, InstFlags.None));
Add(X86Instruction.Movsx8, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fbe, InstFlags.None));
Add(X86Instruction.Movsx8, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fbe, InstFlags.Reg8Src));
Add(X86Instruction.Movzx16, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fb7, InstFlags.None));
Add(X86Instruction.Movzx8, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fb6, InstFlags.None));
Add(X86Instruction.Movzx8, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fb6, InstFlags.Reg8Src));
Add(X86Instruction.Mul128, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x040000f7, InstFlags.None));
Add(X86Instruction.Mulpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f59, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Mulps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f59, InstFlags.Vex));
Add(X86Instruction.Mulsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f59, InstFlags.Vex | InstFlags.PrefixF2));
Add(X86Instruction.Mulss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f59, InstFlags.Vex | InstFlags.PrefixF3));
Add(X86Instruction.Mulpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f59, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Mulps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f59, InstFlags.Vex | InstFlags.NoRexW));
Add(X86Instruction.Mulsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f59, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF2));
Add(X86Instruction.Mulss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f59, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF3));
Add(X86Instruction.Neg, new InstInfo(0x030000f7, BadOp, BadOp, BadOp, BadOp, InstFlags.None));
Add(X86Instruction.Not, new InstInfo(0x020000f7, BadOp, BadOp, BadOp, BadOp, InstFlags.None));
Add(X86Instruction.Or, new InstInfo(0x00000009, 0x01000083, 0x01000081, BadOp, 0x0000000b, InstFlags.None));
Add(X86Instruction.Paddb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffc, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Paddd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffe, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Paddq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fd4, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Paddw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffd, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pand, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fdb, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pandn, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fdf, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pavgb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fe0, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pavgw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fe3, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pblendvb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a4c, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pcmpeqb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f74, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pcmpeqd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f76, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pcmpeqq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3829, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pcmpeqw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f75, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pcmpgtb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f64, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pcmpgtd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f66, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pcmpgtq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3837, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pcmpgtw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f65, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pextrb, new InstInfo(0x000f3a14, BadOp, BadOp, BadOp, BadOp, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Paddb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffc, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Paddd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffe, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Paddq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fd4, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Paddw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffd, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pand, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fdb, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pandn, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fdf, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pavgb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fe0, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pavgw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fe3, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pblendvb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a4c, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pcmpeqb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f74, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pcmpeqd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f76, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pcmpeqq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3829, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pcmpeqw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f75, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pcmpgtb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f64, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pcmpgtd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f66, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pcmpgtq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3837, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pcmpgtw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f65, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pextrb, new InstInfo(0x000f3a14, BadOp, BadOp, BadOp, BadOp, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pextrd, new InstInfo(0x000f3a16, BadOp, BadOp, BadOp, BadOp, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pextrw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc5, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pinsrb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a20, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pextrw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc5, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pinsrb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a20, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pinsrd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a22, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pinsrw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc4, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pmaxsb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383c, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pmaxsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383d, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pmaxsw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fee, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pmaxub, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fde, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pmaxud, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383f, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pmaxuw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383e, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pminsb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3838, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pminsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3839, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pminsw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fea, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pminub, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fda, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pminud, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383b, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pminuw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383a, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pmovsxbw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3820, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pmovsxdq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3825, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pmovsxwd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3823, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pmovzxbw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3830, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pmovzxdq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3835, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pmovzxwd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3833, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pmulld, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3840, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pmullw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fd5, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pinsrw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc4, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pmaxsb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383c, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pmaxsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383d, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pmaxsw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fee, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pmaxub, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fde, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pmaxud, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383f, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pmaxuw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383e, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pminsb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3838, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pminsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3839, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pminsw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fea, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pminub, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fda, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pminud, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383b, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pminuw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383a, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pmovsxbw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3820, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pmovsxdq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3825, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pmovsxwd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3823, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pmovzxbw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3830, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pmovzxdq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3835, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pmovzxwd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3833, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pmulld, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3840, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pmullw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fd5, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pop, new InstInfo(0x0000008f, BadOp, BadOp, BadOp, BadOp, InstFlags.None));
Add(X86Instruction.Popcnt, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fb8, InstFlags.PrefixF3));
Add(X86Instruction.Por, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000feb, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pshufb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3800, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pshufd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f70, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pslld, new InstInfo(BadOp, 0x06000f72, BadOp, BadOp, 0x00000ff2, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Pslldq, new InstInfo(BadOp, 0x07000f73, BadOp, BadOp, BadOp, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Psllq, new InstInfo(BadOp, 0x06000f73, BadOp, BadOp, 0x00000ff3, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Psllw, new InstInfo(BadOp, 0x06000f71, BadOp, BadOp, 0x00000ff1, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Psrad, new InstInfo(BadOp, 0x04000f72, BadOp, BadOp, 0x00000fe2, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Psraw, new InstInfo(BadOp, 0x04000f71, BadOp, BadOp, 0x00000fe1, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Psrld, new InstInfo(BadOp, 0x02000f72, BadOp, BadOp, 0x00000fd2, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Psrlq, new InstInfo(BadOp, 0x02000f73, BadOp, BadOp, 0x00000fd3, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Psrldq, new InstInfo(BadOp, 0x03000f73, BadOp, BadOp, BadOp, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Psrlw, new InstInfo(BadOp, 0x02000f71, BadOp, BadOp, 0x00000fd1, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Psubb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ff8, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Psubd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffa, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Psubq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffb, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Psubw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ff9, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Punpckhbw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f68, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Punpckhdq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f6a, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Punpckhqdq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f6d, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Punpckhwd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f69, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Punpcklbw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f60, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Punpckldq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f62, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Punpcklqdq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f6c, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Punpcklwd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f61, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Por, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000feb, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pshufb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3800, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pshufd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f70, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pslld, new InstInfo(BadOp, 0x06000f72, BadOp, BadOp, 0x00000ff2, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Pslldq, new InstInfo(BadOp, 0x07000f73, BadOp, BadOp, BadOp, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Psllq, new InstInfo(BadOp, 0x06000f73, BadOp, BadOp, 0x00000ff3, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Psllw, new InstInfo(BadOp, 0x06000f71, BadOp, BadOp, 0x00000ff1, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Psrad, new InstInfo(BadOp, 0x04000f72, BadOp, BadOp, 0x00000fe2, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Psraw, new InstInfo(BadOp, 0x04000f71, BadOp, BadOp, 0x00000fe1, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Psrld, new InstInfo(BadOp, 0x02000f72, BadOp, BadOp, 0x00000fd2, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Psrlq, new InstInfo(BadOp, 0x02000f73, BadOp, BadOp, 0x00000fd3, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Psrldq, new InstInfo(BadOp, 0x03000f73, BadOp, BadOp, BadOp, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Psrlw, new InstInfo(BadOp, 0x02000f71, BadOp, BadOp, 0x00000fd1, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Psubb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ff8, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Psubd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffa, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Psubq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffb, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Psubw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ff9, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Punpckhbw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f68, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Punpckhdq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f6a, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Punpckhqdq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f6d, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Punpckhwd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f69, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Punpcklbw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f60, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Punpckldq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f62, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Punpcklqdq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f6c, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Punpcklwd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f61, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Push, new InstInfo(BadOp, 0x0000006a, 0x00000068, BadOp, 0x060000ff, InstFlags.None));
Add(X86Instruction.Pxor, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fef, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Rcpps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f53, InstFlags.Vex));
Add(X86Instruction.Rcpss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f53, InstFlags.Vex | InstFlags.PrefixF3));
Add(X86Instruction.Pxor, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fef, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Rcpps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f53, InstFlags.Vex | InstFlags.NoRexW));
Add(X86Instruction.Rcpss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f53, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF3));
Add(X86Instruction.Ror, new InstInfo(0x010000d3, 0x010000c1, BadOp, BadOp, BadOp, InstFlags.None));
Add(X86Instruction.Roundpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a09, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Roundps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a08, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Roundsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a0b, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Roundss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a0a, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Rsqrtps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f52, InstFlags.Vex));
Add(X86Instruction.Rsqrtss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f52, InstFlags.Vex | InstFlags.PrefixF3));
Add(X86Instruction.Roundpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a09, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Roundps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a08, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Roundsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a0b, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Roundss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a0a, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Rsqrtps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f52, InstFlags.Vex | InstFlags.NoRexW));
Add(X86Instruction.Rsqrtss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f52, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF3));
Add(X86Instruction.Sar, new InstInfo(0x070000d3, 0x070000c1, BadOp, BadOp, BadOp, InstFlags.None));
Add(X86Instruction.Setcc, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f90, InstFlags.Reg8));
Add(X86Instruction.Setcc, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f90, InstFlags.Reg8Dest));
Add(X86Instruction.Shl, new InstInfo(0x040000d3, 0x040000c1, BadOp, BadOp, BadOp, InstFlags.None));
Add(X86Instruction.Shr, new InstInfo(0x050000d3, 0x050000c1, BadOp, BadOp, BadOp, InstFlags.None));
Add(X86Instruction.Shufpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc6, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Shufps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc6, InstFlags.Vex));
Add(X86Instruction.Sqrtpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f51, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Sqrtps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f51, InstFlags.Vex));
Add(X86Instruction.Sqrtsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f51, InstFlags.Vex | InstFlags.PrefixF2));
Add(X86Instruction.Sqrtss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f51, InstFlags.Vex | InstFlags.PrefixF3));
Add(X86Instruction.Shufpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc6, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Shufps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc6, InstFlags.Vex | InstFlags.NoRexW));
Add(X86Instruction.Sqrtpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f51, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Sqrtps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f51, InstFlags.Vex | InstFlags.NoRexW));
Add(X86Instruction.Sqrtsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f51, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF2));
Add(X86Instruction.Sqrtss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f51, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF3));
Add(X86Instruction.Sub, new InstInfo(0x00000029, 0x05000083, 0x05000081, BadOp, 0x0000002b, InstFlags.None));
Add(X86Instruction.Subpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5c, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Subps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5c, InstFlags.Vex));
Add(X86Instruction.Subsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5c, InstFlags.Vex | InstFlags.PrefixF2));
Add(X86Instruction.Subss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5c, InstFlags.Vex | InstFlags.PrefixF3));
Add(X86Instruction.Subpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5c, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Subps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5c, InstFlags.Vex | InstFlags.NoRexW));
Add(X86Instruction.Subsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5c, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF2));
Add(X86Instruction.Subss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5c, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF3));
Add(X86Instruction.Test, new InstInfo(0x00000085, BadOp, 0x000000f7, BadOp, BadOp, InstFlags.None));
Add(X86Instruction.Unpckhpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f15, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Unpckhps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f15, InstFlags.Vex));
Add(X86Instruction.Unpcklpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f14, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Unpcklps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f14, InstFlags.Vex));
Add(X86Instruction.Unpckhpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f15, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Unpckhps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f15, InstFlags.Vex | InstFlags.NoRexW));
Add(X86Instruction.Unpcklpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f14, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Unpcklps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f14, InstFlags.Vex | InstFlags.NoRexW));
Add(X86Instruction.Xor, new InstInfo(0x00000031, 0x06000083, 0x06000081, BadOp, 0x00000033, InstFlags.None));
Add(X86Instruction.Xorpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f57, InstFlags.Vex | InstFlags.Prefix66));
Add(X86Instruction.Xorps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f57, InstFlags.Vex));
Add(X86Instruction.Xorpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f57, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
Add(X86Instruction.Xorps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f57, InstFlags.Vex | InstFlags.NoRexW));
}
private static void Add(X86Instruction inst, InstInfo info)
@ -615,7 +617,16 @@ namespace ARMeilleure.CodeGen.X86
public void Movd(Operand dest, Operand source)
{
WriteInstruction(dest, source, X86Instruction.Movd);
InstInfo info = _instTable[(int)X86Instruction.Movd];
if (dest.GetRegister().Type == RegisterType.Vector || source.Kind == OperandKind.Memory)
{
WriteRRMOpCode(dest, source, info.Flags, info.OpRRM);
}
else
{
WriteOpCode(dest, source, info.Flags, info.OpRMR);
}
}
public void Movdqu(Operand dest, Operand source)
@ -1411,7 +1422,7 @@ namespace ARMeilleure.CodeGen.X86
modRM |= (regIndex & 0b111) << (rrm ? 3 : 0);
if ((flags & InstFlags.Reg8) != 0 && regIndex >= 4)
if ((flags & InstFlags.Reg8Dest) != 0 && regIndex >= 4)
{
rexPrefix |= 0x40;
}
@ -1430,7 +1441,14 @@ namespace ARMeilleure.CodeGen.X86
{
if (source.Kind == OperandKind.Register)
{
modRM |= (source.GetRegister().Index & 0b111) << (rrm ? 0 : 3);
int regIndex = source.GetRegister().Index;
modRM |= (regIndex & 0b111) << (rrm ? 0 : 3);
if ((flags & InstFlags.Reg8Src) != 0 && regIndex >= 4)
{
rexPrefix |= 0x40;
}
}
else if (source.Kind == OperandKind.Memory && memOp == null)
{
@ -1581,6 +1599,11 @@ namespace ARMeilleure.CodeGen.X86
}
}
if ((flags & InstFlags.RegOnly) != 0)
{
opCode += dest.GetRegister().Index & 7;
}
if ((opCode & 0xff0000) != 0)
{
WriteByte((byte)(opCode >> 16));
@ -1642,7 +1665,7 @@ namespace ARMeilleure.CodeGen.X86
if (dest != null)
{
if (dest.Type == OperandType.I64 && rexW)
if (Is64Bits(dest.Type) && rexW)
{
rexPrefix = 0x48;
}
@ -1655,7 +1678,7 @@ namespace ARMeilleure.CodeGen.X86
if (source != null)
{
if (source.Type == OperandType.I64 && rexW)
if (Is64Bits(source.Type) && rexW)
{
rexPrefix |= 0x48;
}
@ -1671,8 +1694,12 @@ namespace ARMeilleure.CodeGen.X86
private static bool IsR64(Operand operand)
{
return operand.Kind == OperandKind.Register &&
operand.Type == OperandType.I64;
return operand.Kind == OperandKind.Register && operand.Type == OperandType.I64;
}
private static bool Is64Bits(OperandType type)
{
return type == OperandType.I64 || type == OperandType.FP64;
}
private static bool IsImm8(Operand operand)

View file

@ -105,7 +105,7 @@ namespace ARMeilleure.CodeGen.X86
//The ABI mandates that the space for at least 4 arguments
//is reserved on the stack (this is called shadow space).
if (argsCount < 4 && argsCount != 0)
if (argsCount < 4 && maxCallArgs != -1)
{
argsCount = 4;
}

View file

@ -40,6 +40,7 @@ namespace ARMeilleure.CodeGen.X86
Add(Instruction.CompareLessUI, GenerateCompareLessUI);
Add(Instruction.CompareNotEqual, GenerateCompareNotEqual);
Add(Instruction.ConditionalSelect, GenerateConditionalSelect);
Add(Instruction.ConvertI64ToI32, GenerateConvertI64ToI32);
Add(Instruction.ConvertToFP, GenerateConvertToFP);
Add(Instruction.Copy, GenerateCopy);
Add(Instruction.CountLeadingZeros, GenerateCountLeadingZeros);
@ -79,9 +80,13 @@ namespace ARMeilleure.CodeGen.X86
Add(Instruction.VectorInsert, GenerateVectorInsert);
Add(Instruction.VectorInsert16, GenerateVectorInsert16);
Add(Instruction.VectorInsert8, GenerateVectorInsert8);
Add(Instruction.VectorOne, GenerateVectorOne);
Add(Instruction.VectorZero, GenerateVectorZero);
Add(Instruction.VectorZeroUpper64, GenerateVectorZeroUpper64);
Add(Instruction.VectorZeroUpper96, GenerateVectorZeroUpper96);
Add(Instruction.ZeroExtend16, GenerateZeroExtend16);
Add(Instruction.ZeroExtend32, GenerateZeroExtend32);
Add(Instruction.ZeroExtend8, GenerateZeroExtend8);
Add(Instruction.X86Addpd, GenerateX86Addpd);
Add(Instruction.X86Addps, GenerateX86Addps);
Add(Instruction.X86Addsd, GenerateX86Addsd);
@ -227,7 +232,7 @@ namespace ARMeilleure.CodeGen.X86
Optimizer.RunPass(cfg);
Logger.EndPass(PassName.Optimization);
Logger.EndPass(PassName.Optimization, cfg);
Logger.StartPass(PassName.PreAllocation);
@ -323,7 +328,14 @@ namespace ARMeilleure.CodeGen.X86
{
ValidateDestSrc1(operation);
context.Assembler.Xor(operation.Dest, operation.GetSource(1));
if (operation.Dest.Type.IsInteger())
{
context.Assembler.Xor(operation.Dest, operation.GetSource(1));
}
else
{
context.Assembler.Xorps(operation.Dest, operation.GetSource(1), operation.GetSource(0));
}
}
private static void GenerateBitwiseNot(CodeGenContext context, Operation operation)
@ -423,6 +435,14 @@ namespace ARMeilleure.CodeGen.X86
context.Assembler.Cmovcc(operation.Dest, operation.GetSource(1), X86Condition.NotEqual);
}
private static void GenerateConvertI64ToI32(CodeGenContext context, Operation operation)
{
Operand dest = operation.Dest;
Operand source = operation.GetSource(0);
context.Assembler.Mov(dest, Get32BitsRegister(source.GetRegister()));
}
private static void GenerateConvertToFP(CodeGenContext context, Operation operation)
{
Operand dest = operation.Dest;
@ -486,25 +506,10 @@ namespace ARMeilleure.CodeGen.X86
context.Assembler.Xor(dest, dest);
}
else if (dest.Type == OperandType.I64 && source.Type == OperandType.I32)
{
//I32 -> I64 zero-extension.
if (dest.Kind == OperandKind.Register && source.Kind == OperandKind.Register)
{
dest = Get32BitsRegister(dest.GetRegister());
}
else if (source.Kind == OperandKind.Constant)
{
source = new Operand(source.Value);
}
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
@ -512,6 +517,10 @@ namespace ARMeilleure.CodeGen.X86
context.Assembler.Movdqu(dest, source);
}
}
else if (dest.Type == OperandType.I32 && source.Kind == OperandKind.Register)
{
context.Assembler.Mov(dest, Get32BitsRegister(source.GetRegister()));
}
else
{
context.Assembler.Mov(dest, source);
@ -614,13 +623,25 @@ namespace ARMeilleure.CodeGen.X86
Operand value = operation.Dest;
Operand address = GetMemoryOperand(operation.GetSource(0), value.Type);
if (value.GetRegister().Type == RegisterType.Integer)
switch (value.Type)
{
context.Assembler.Mov(value, address);
}
else
{
context.Assembler.Movdqu(value, address);
case OperandType.I32:
case OperandType.I64:
context.Assembler.Mov(value, address);
break;
case OperandType.FP32:
case OperandType.FP64:
context.Assembler.Movd(value, address);
break;
case OperandType.V128:
context.Assembler.Movdqu(value, address);
break;
default:
Debug.Assert(false);
break;
}
}
@ -813,13 +834,25 @@ namespace ARMeilleure.CodeGen.X86
Operand value = operation.GetSource(1);
Operand address = GetMemoryOperand(operation.GetSource(0), value.Type);
if (value.GetRegister().Type == RegisterType.Integer)
switch (value.Type)
{
context.Assembler.Mov(address, value);
}
else
{
context.Assembler.Movdqu(address, value);
case OperandType.I32:
case OperandType.I64:
context.Assembler.Mov(address, value);
break;
case OperandType.FP32:
case OperandType.FP64:
context.Assembler.Movd(address, value);
break;
case OperandType.V128:
context.Assembler.Movdqu(address, value);
break;
default:
Debug.Assert(false);
break;
}
}
@ -1017,6 +1050,11 @@ namespace ARMeilleure.CodeGen.X86
context.Assembler.Pinsrb(dest, src2, src1, index);
}
private static void GenerateVectorOne(CodeGenContext context, Operation operation)
{
context.Assembler.Pcmpeqw(operation.Dest, operation.Dest, operation.Dest);
}
private static void GenerateVectorZero(CodeGenContext context, Operation operation)
{
context.Assembler.Xorps(operation.Dest, operation.Dest, operation.Dest);
@ -1032,6 +1070,23 @@ namespace ARMeilleure.CodeGen.X86
ZeroUpper96(context, operation.Dest, operation.GetSource(0));
}
private static void GenerateZeroExtend16(CodeGenContext context, Operation operation)
{
context.Assembler.Movzx16(operation.Dest, Get32BitsRegister(operation.GetSource(0).GetRegister()));
}
private static void GenerateZeroExtend32(CodeGenContext context, Operation operation)
{
context.Assembler.Mov(
Get32BitsRegister(operation.Dest.GetRegister()),
Get32BitsRegister(operation.GetSource(0).GetRegister()));
}
private static void GenerateZeroExtend8(CodeGenContext context, Operation operation)
{
context.Assembler.Movzx8(operation.Dest, Get32BitsRegister(operation.GetSource(0).GetRegister()));
}
private static void GenerateX86Addpd(CodeGenContext context, Operation operation)
{
context.Assembler.Addpd(operation.Dest, operation.GetSource(1), operation.GetSource(0));

View file

@ -12,7 +12,7 @@ namespace ARMeilleure.CodeGen.X86
{
public static void RunPass(ControlFlowGraph cfg, MemoryManager memory, out int maxCallArgs)
{
maxCallArgs = 0;
maxCallArgs = -1;
foreach (BasicBlock block in cfg.Blocks)
{
@ -199,17 +199,19 @@ namespace ARMeilleure.CodeGen.X86
//--- This can be done efficiently by adding the result to itself.
//-- Then, we need to add the least significant bit that was shifted out.
//--- We can convert the least significant bit to float, and add it to the result.
Operand lsb = Local(OperandType.I64);
Operand lsb = Local(OperandType.I64);
Operand half = Local(OperandType.I64);
Operand lsbF = Local(dest.Type);
temp = nodes.AddAfter(temp, new Operation(Instruction.Copy, lsb, source));
temp = nodes.AddAfter(temp, new Operation(Instruction.Copy, lsb, source));
temp = nodes.AddAfter(temp, new Operation(Instruction.Copy, half, source));
temp = nodes.AddAfter(temp, new Operation(Instruction.BitwiseAnd, lsb, lsb, Const(1L)));
temp = nodes.AddAfter(temp, new Operation(Instruction.ShiftRightUI, source, source, Const(1)));
temp = nodes.AddAfter(temp, new Operation(Instruction.BitwiseAnd, lsb, lsb, Const(1L)));
temp = nodes.AddAfter(temp, new Operation(Instruction.ShiftRightUI, half, half, Const(1)));
temp = nodes.AddAfter(temp, new Operation(Instruction.ConvertToFP, lsbF, lsb));
temp = nodes.AddAfter(temp, new Operation(Instruction.ConvertToFP, dest, source));
temp = nodes.AddAfter(temp, new Operation(Instruction.ConvertToFP, dest, half));
temp = nodes.AddAfter(temp, new Operation(Instruction.Add, dest, dest, dest));
temp = nodes.AddAfter(temp, new Operation(Instruction.Add, dest, dest, lsbF));
@ -232,7 +234,7 @@ namespace ARMeilleure.CodeGen.X86
Operand res = Local(dest.Type);
temp = nodes.AddAfter(temp, new Operation(Instruction.X86Pcmpeqw, res, res, res));
temp = nodes.AddAfter(temp, new Operation(Instruction.VectorOne, res));
if (dest.Type == OperandType.FP32)
{

View file

@ -19,6 +19,15 @@ namespace ARMeilleure.Decoders
_opActivators = new ConcurrentDictionary<Type, MakeOp>();
}
public static Block[] DecodeBasicBlock(MemoryManager memory, ulong address, ExecutionMode mode)
{
Block block = new Block(address);
FillBlock(memory, mode, block, ulong.MaxValue);
return new Block[] { block };
}
public static Block[] DecodeFunction(MemoryManager memory, ulong address, ExecutionMode mode)
{
List<Block> blocks = new List<Block>();

View file

@ -205,7 +205,8 @@ namespace ARMeilleure.Decoders
SetA64("0100111000101000011010xxxxxxxxxx", InstName.Aesmc_V, InstEmit.Aesmc_V, typeof(OpCodeSimd));
SetA64("0x001110001xxxxx000111xxxxxxxxxx", InstName.And_V, InstEmit.And_V, typeof(OpCodeSimdReg));
SetA64("0x001110011xxxxx000111xxxxxxxxxx", InstName.Bic_V, InstEmit.Bic_V, typeof(OpCodeSimdReg));
SetA64("0x10111100000xxx<<x101xxxxxxxxxx", InstName.Bic_Vi, InstEmit.Bic_Vi, typeof(OpCodeSimdImm));
SetA64("0x10111100000xxx0xx101xxxxxxxxxx", InstName.Bic_Vi, InstEmit.Bic_Vi, typeof(OpCodeSimdImm));
SetA64("0x10111100000xxx10x101xxxxxxxxxx", InstName.Bic_Vi, InstEmit.Bic_Vi, typeof(OpCodeSimdImm));
SetA64("0x101110111xxxxx000111xxxxxxxxxx", InstName.Bif_V, InstEmit.Bif_V, typeof(OpCodeSimdReg));
SetA64("0x101110101xxxxx000111xxxxxxxxxx", InstName.Bit_V, InstEmit.Bit_V, typeof(OpCodeSimdReg));
SetA64("0x101110011xxxxx000111xxxxxxxxxx", InstName.Bsl_V, InstEmit.Bsl_V, typeof(OpCodeSimdReg));
@ -313,12 +314,15 @@ namespace ARMeilleure.Decoders
SetA64("0>0011101<1xxxxx110011xxxxxxxxxx", InstName.Fmls_V, InstEmit.Fmls_V, typeof(OpCodeSimdReg));
SetA64("0>0011111<xxxxxx0101x0xxxxxxxxxx", InstName.Fmls_Ve, InstEmit.Fmls_Ve, typeof(OpCodeSimdRegElemF));
SetA64("000111100x100000010000xxxxxxxxxx", InstName.Fmov_S, InstEmit.Fmov_S, typeof(OpCodeSimd));
SetA64("00011110xx1xxxxxxxx100xxxxxxxxxx", InstName.Fmov_Si, InstEmit.Fmov_Si, typeof(OpCodeSimdFmov));
SetA64("0xx0111100000xxx111101xxxxxxxxxx", InstName.Fmov_V, InstEmit.Fmov_V, typeof(OpCodeSimdImm));
SetA64("x00111100x100110000000xxxxxxxxxx", InstName.Fmov_Ftoi, InstEmit.Fmov_Ftoi, typeof(OpCodeSimdCvt));
SetA64("x00111100x100111000000xxxxxxxxxx", InstName.Fmov_Itof, InstEmit.Fmov_Itof, typeof(OpCodeSimdCvt));
SetA64("1001111010101110000000xxxxxxxxxx", InstName.Fmov_Ftoi1, InstEmit.Fmov_Ftoi1, typeof(OpCodeSimdCvt));
SetA64("1001111010101111000000xxxxxxxxxx", InstName.Fmov_Itof1, InstEmit.Fmov_Itof1, typeof(OpCodeSimdCvt));
SetA64("000111100x1xxxxxxxx10000000xxxxx", InstName.Fmov_Si, InstEmit.Fmov_Si, typeof(OpCodeSimdFmov));
SetA64("0x00111100000xxx111101xxxxxxxxxx", InstName.Fmov_Vi, InstEmit.Fmov_Vi, typeof(OpCodeSimdImm));
SetA64("0110111100000xxx111101xxxxxxxxxx", InstName.Fmov_Vi, InstEmit.Fmov_Vi, typeof(OpCodeSimdImm));
SetA64("0001111000100110000000xxxxxxxxxx", InstName.Fmov_Ftoi, InstEmit.Fmov_Ftoi, typeof(OpCodeSimd));
SetA64("1001111001100110000000xxxxxxxxxx", InstName.Fmov_Ftoi, InstEmit.Fmov_Ftoi, typeof(OpCodeSimd));
SetA64("0001111000100111000000xxxxxxxxxx", InstName.Fmov_Itof, InstEmit.Fmov_Itof, typeof(OpCodeSimd));
SetA64("1001111001100111000000xxxxxxxxxx", InstName.Fmov_Itof, InstEmit.Fmov_Itof, typeof(OpCodeSimd));
SetA64("1001111010101110000000xxxxxxxxxx", InstName.Fmov_Ftoi1, InstEmit.Fmov_Ftoi1, typeof(OpCodeSimd));
SetA64("1001111010101111000000xxxxxxxxxx", InstName.Fmov_Itof1, InstEmit.Fmov_Itof1, typeof(OpCodeSimd));
SetA64("000111110x0xxxxx1xxxxxxxxxxxxxxx", InstName.Fmsub_S, InstEmit.Fmsub_S, typeof(OpCodeSimdReg));
SetA64("000111100x1xxxxx000010xxxxxxxxxx", InstName.Fmul_S, InstEmit.Fmul_S, typeof(OpCodeSimdReg));
SetA64("010111111xxxxxxx1001x0xxxxxxxxxx", InstName.Fmul_Se, InstEmit.Fmul_Se, typeof(OpCodeSimdRegElemF));
@ -391,7 +395,8 @@ namespace ARMeilleure.Decoders
SetA64("0x10111000100000010110xxxxxxxxxx", InstName.Not_V, InstEmit.Not_V, typeof(OpCodeSimd));
SetA64("0x001110111xxxxx000111xxxxxxxxxx", InstName.Orn_V, InstEmit.Orn_V, typeof(OpCodeSimdReg));
SetA64("0x001110101xxxxx000111xxxxxxxxxx", InstName.Orr_V, InstEmit.Orr_V, typeof(OpCodeSimdReg));
SetA64("0x00111100000xxx<<x101xxxxxxxxxx", InstName.Orr_Vi, InstEmit.Orr_Vi, typeof(OpCodeSimdImm));
SetA64("0x00111100000xxx0xx101xxxxxxxxxx", InstName.Orr_Vi, InstEmit.Orr_Vi, typeof(OpCodeSimdImm));
SetA64("0x00111100000xxx10x101xxxxxxxxxx", InstName.Orr_Vi, InstEmit.Orr_Vi, typeof(OpCodeSimdImm));
SetA64("0x101110<<1xxxxx010000xxxxxxxxxx", InstName.Raddhn_V, InstEmit.Raddhn_V, typeof(OpCodeSimdReg));
SetA64("0x10111001100000010110xxxxxxxxxx", InstName.Rbit_V, InstEmit.Rbit_V, typeof(OpCodeSimd));
SetA64("0x00111000100000000110xxxxxxxxxx", InstName.Rev16_V, InstEmit.Rev16_V, typeof(OpCodeSimd));
@ -432,7 +437,8 @@ namespace ARMeilleure.Decoders
SetA64("0x101110<<100001001110xxxxxxxxxx", InstName.Shll_V, InstEmit.Shll_V, typeof(OpCodeSimd));
SetA64("0x00111100>>>xxx100001xxxxxxxxxx", InstName.Shrn_V, InstEmit.Shrn_V, typeof(OpCodeSimdShImm));
SetA64("0x001110<<1xxxxx001001xxxxxxxxxx", InstName.Shsub_V, InstEmit.Shsub_V, typeof(OpCodeSimdReg));
SetA64("0x1011110>>>>xxx010101xxxxxxxxxx", InstName.Sli_V, InstEmit.Sli_V, typeof(OpCodeSimdShImm));
SetA64("0x10111100>>>xxx010101xxxxxxxxxx", InstName.Sli_V, InstEmit.Sli_V, typeof(OpCodeSimdShImm));
SetA64("0110111101xxxxxx010101xxxxxxxxxx", InstName.Sli_V, InstEmit.Sli_V, typeof(OpCodeSimdShImm));
SetA64("0x001110<<1xxxxx011001xxxxxxxxxx", InstName.Smax_V, InstEmit.Smax_V, typeof(OpCodeSimdReg));
SetA64("0x001110<<1xxxxx101001xxxxxxxxxx", InstName.Smaxp_V, InstEmit.Smaxp_V, typeof(OpCodeSimdReg));
SetA64("000011100x110000101010xxxxxxxxxx", InstName.Smaxv_V, InstEmit.Smaxv_V, typeof(OpCodeSimd));
@ -770,8 +776,7 @@ namespace ARMeilleure.Decoders
}
}
//TODO: Change null with Und impl.
return (new InstDescriptor(InstName.Und, null), typeof(OpCode));
return (new InstDescriptor(InstName.Und, InstEmit.Und), typeof(OpCode));
}
private static int ToFastLookupIndex(int value)

View file

@ -109,6 +109,11 @@ namespace ARMeilleure.Diagnostics
private static string GetOperandName(Operand operand, Dictionary<Operand, string> localNames)
{
if (operand == null)
{
return "<NULL>";
}
string name = string.Empty;
if (operand.Kind == OperandKind.LocalVariable)

View file

@ -25,7 +25,7 @@ namespace ARMeilleure.Instructions
if (context.CurrOp.RegisterSize == RegisterSize.Int64)
{
carry = context.Copy(Local(OperandType.I64), carry);
carry = context.ZeroExtend32(OperandType.I64, carry);
}
d = context.Add(d, carry);
@ -107,7 +107,7 @@ namespace ARMeilleure.Instructions
{
OpCodeAlu op = (OpCodeAlu)context.CurrOp;
Operand n = GetIntOrZR(op, op.Rn);
Operand n = GetIntOrZR(context, op.Rn);
Operand nHigh = context.ShiftRightUI(n, Const(1));
@ -128,7 +128,7 @@ namespace ARMeilleure.Instructions
{
OpCodeAlu op = (OpCodeAlu)context.CurrOp;
Operand n = GetIntOrZR(op, op.Rn);
Operand n = GetIntOrZR(context, op.Rn);
Operand d = context.CountLeadingZeros(n);
@ -154,7 +154,7 @@ namespace ARMeilleure.Instructions
{
OpCodeAluRs op = (OpCodeAluRs)context.CurrOp;
Operand res = GetIntOrZR(op, op.Rm);
Operand res = GetIntOrZR(context, op.Rm);
if (op.Shift != 0)
{
@ -166,7 +166,7 @@ namespace ARMeilleure.Instructions
{
res = context.ShiftRightUI(res, Const(op.Shift));
Operand n = GetIntOrZR(op, op.Rn);
Operand n = GetIntOrZR(context, op.Rn);
int invShift = op.GetBitsCount() - op.Shift;
@ -201,7 +201,7 @@ namespace ARMeilleure.Instructions
if (context.CurrOp.RegisterSize == RegisterSize.Int64)
{
borrow = context.Copy(Local(OperandType.I64), borrow);
borrow = context.ZeroExtend32(OperandType.I64, borrow);
}
d = context.Subtract(d, borrow);
@ -264,7 +264,7 @@ namespace ARMeilleure.Instructions
{
OpCodeAlu op = (OpCodeAlu)context.CurrOp;
Operand n = GetIntOrZR(op, op.Rn);
Operand n = GetIntOrZR(context, op.Rn);
if (op.RegisterSize == RegisterSize.Int32)
{
@ -280,7 +280,7 @@ namespace ARMeilleure.Instructions
{
OpCodeAlu op = (OpCodeAlu)context.CurrOp;
Operand n = GetIntOrZR(op, op.Rn);
Operand n = GetIntOrZR(context, op.Rn);
Operand d;
if (op.RegisterSize == RegisterSize.Int32)
@ -299,7 +299,7 @@ namespace ARMeilleure.Instructions
{
OpCodeAlu op = (OpCodeAlu)context.CurrOp;
SetAluDOrZR(context, context.ByteSwap(GetIntOrZR(op, op.Rn)));
SetAluDOrZR(context, context.ByteSwap(GetIntOrZR(context, op.Rn)));
}
public static void Rorv(EmitterContext context)
@ -311,11 +311,11 @@ namespace ARMeilleure.Instructions
{
IOpCodeAluRs op = (IOpCodeAluRs)context.CurrOp;
Operand m = GetIntOrZR(op, op.Rm);
Operand m = GetIntOrZR(context, op.Rm);
if (op.RegisterSize == RegisterSize.Int64)
{
m = context.Copy(Local(OperandType.I32), m);
m = context.ConvertI64ToI32(m);
}
return context.BitwiseAnd(m, Const(context.CurrOp.GetBitsCount() - 1));
@ -352,7 +352,7 @@ namespace ARMeilleure.Instructions
return;
}
context.Copy(GetIntOrSP(op, op.Rd), d);
SetIntOrSP(context, op.Rd, d);
}
}
}

View file

@ -77,11 +77,11 @@ namespace ARMeilleure.Instructions
{
if (op.DataOp == DataOp.Logical || op is IOpCodeAluRs)
{
return GetIntOrZR(op, op.Rn);
return GetIntOrZR(context, op.Rn);
}
else
{
return GetIntOrSP(op, op.Rn);
return GetIntOrSP(context, op.Rn);
}
}
else if (context.CurrOp is IOpCode32Alu op32)
@ -128,7 +128,7 @@ namespace ARMeilleure.Instructions
case IOpCodeAluRs op:
{
Operand value = GetIntOrZR(op, op.Rm);
Operand value = GetIntOrZR(context, op.Rm);
switch (op.ShiftType)
{

View file

@ -13,8 +13,8 @@ namespace ARMeilleure.Instructions
{
OpCodeBfm op = (OpCodeBfm)context.CurrOp;
Operand d = GetIntOrZR(op, op.Rd);
Operand n = GetIntOrZR(op, op.Rn);
Operand d = GetIntOrZR(context, op.Rd);
Operand n = GetIntOrZR(context, op.Rn);
Operand res;
@ -64,25 +64,25 @@ namespace ARMeilleure.Instructions
}
else if (op.Pos == 7 && op.Shift == 0)
{
Operand n = GetIntOrZR(op, op.Rn);
Operand n = GetIntOrZR(context, op.Rn);
SetIntOrZR(context, op.Rd, context.SignExtend8(n));
SetIntOrZR(context, op.Rd, context.SignExtend8(n.Type, n));
}
else if (op.Pos == 15 && op.Shift == 0)
{
Operand n = GetIntOrZR(op, op.Rn);
Operand n = GetIntOrZR(context, op.Rn);
SetIntOrZR(context, op.Rd, context.SignExtend16(n));
SetIntOrZR(context, op.Rd, context.SignExtend16(n.Type, n));
}
else if (op.Pos == 31 && op.Shift == 0)
{
Operand n = GetIntOrZR(op, op.Rn);
Operand n = GetIntOrZR(context, op.Rn);
SetIntOrZR(context, op.Rd, context.SignExtend32(n));
SetIntOrZR(context, op.Rd, context.SignExtend32(n.Type, n));
}
else
{
Operand res = GetIntOrZR(op, op.Rn);
Operand res = GetIntOrZR(context, op.Rn);
res = context.ShiftLeft (res, Const(bitsCount - 1 - op.Pos));
res = context.ShiftRightSI(res, Const(bitsCount - 1));
@ -112,13 +112,13 @@ namespace ARMeilleure.Instructions
}
else if (op.Pos == 7 && op.Shift == 0)
{
Operand n = GetIntOrZR(op, op.Rn);
Operand n = GetIntOrZR(context, op.Rn);
SetIntOrZR(context, op.Rd, context.BitwiseAnd(n, Const(n.Type, 0xff)));
}
else if (op.Pos == 15 && op.Shift == 0)
{
Operand n = GetIntOrZR(op, op.Rn);
Operand n = GetIntOrZR(context, op.Rn);
SetIntOrZR(context, op.Rd, context.BitwiseAnd(n, Const(n.Type, 0xffff)));
}
@ -137,7 +137,7 @@ namespace ARMeilleure.Instructions
int width = op.Pos + 1;
Operand res = GetIntOrZR(op, op.Rn);
Operand res = GetIntOrZR(context, op.Rn);
res = context.ShiftLeft(res, Const(op.GetBitsCount() - width));
@ -162,7 +162,7 @@ namespace ARMeilleure.Instructions
{
OpCodeBfm op = (OpCodeBfm)context.CurrOp;
Operand res = GetIntOrZR(op, op.Rn);
Operand res = GetIntOrZR(context, op.Rn);
res = signed
? context.ShiftRightSI(res, Const(op.Shift))
@ -175,7 +175,7 @@ namespace ARMeilleure.Instructions
{
OpCodeBfm op = (OpCodeBfm)context.CurrOp;
Operand res = GetIntOrZR(op, op.Rn);
Operand res = GetIntOrZR(context, op.Rn);
int shift = op.GetBitsCount() - op.Shift;
@ -186,7 +186,7 @@ namespace ARMeilleure.Instructions
{
OpCodeBfm op = (OpCodeBfm)context.CurrOp;
Operand res = GetIntOrZR(op, op.Rn);
Operand res = GetIntOrZR(context, op.Rn);
long mask = op.WMask & op.TMask;

View file

@ -27,8 +27,8 @@ namespace ARMeilleure.Instructions
{
OpCodeCsel op = (OpCodeCsel)context.CurrOp;
Operand n = GetIntOrZR(op, op.Rn);
Operand m = GetIntOrZR(op, op.Rm);
Operand n = GetIntOrZR(context, op.Rn);
Operand m = GetIntOrZR(context, op.Rm);
if (cselOp == CselOperation.Increment)
{

View file

@ -17,8 +17,8 @@ namespace ARMeilleure.Instructions
OpCodeAluBinary op = (OpCodeAluBinary)context.CurrOp;
//If Rm == 0, Rd = 0 (division by zero).
Operand n = GetIntOrZR(op, op.Rn);
Operand m = GetIntOrZR(op, op.Rm);
Operand n = GetIntOrZR(context, op.Rn);
Operand m = GetIntOrZR(context, op.Rm);
Operand divisorIsZero = context.ICompareEqual(m, Const(m.Type, 0));

View file

@ -24,8 +24,12 @@ namespace ARMeilleure.Instructions
MethodInfo info = typeof(NativeInterface).GetMethod(mthdName);
context.StoreToContext();
context.Call(info, Const(op.Address), Const(op.Id));
context.LoadFromContext();
if (context.CurrBlock.Next == null)
{
context.Return(Const(op.Address + 4));
@ -38,8 +42,12 @@ namespace ARMeilleure.Instructions
MethodInfo info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.Undefined));
context.StoreToContext();
context.Call(info, Const(op.Address), Const(op.RawOpCode));
context.LoadFromContext();
if (context.CurrBlock.Next == null)
{
context.Return(Const(op.Address + 4));

View file

@ -36,7 +36,7 @@ namespace ARMeilleure.Instructions
{
OpCodeBImmAl op = (OpCodeBImmAl)context.CurrOp;
context.Copy(GetIntOrZR(op, RegisterAlias.Lr), Const(op.Address + 4));
context.Copy(GetIntOrZR(context, RegisterAlias.Lr), Const(op.Address + 4));
EmitCall(context, (ulong)op.Immediate);
}
@ -45,9 +45,9 @@ namespace ARMeilleure.Instructions
{
OpCodeBReg op = (OpCodeBReg)context.CurrOp;
Operand n = context.Copy(GetIntOrZR(op, op.Rn));
Operand n = context.Copy(GetIntOrZR(context, op.Rn));
context.Copy(GetIntOrZR(op, RegisterAlias.Lr), Const(op.Address + 4));
context.Copy(GetIntOrZR(context, RegisterAlias.Lr), Const(op.Address + 4));
EmitVirtualCall(context, n);
}
@ -56,7 +56,7 @@ namespace ARMeilleure.Instructions
{
OpCodeBReg op = (OpCodeBReg)context.CurrOp;
EmitVirtualJump(context, GetIntOrZR(op, op.Rn));
EmitVirtualJump(context, GetIntOrZR(context, op.Rn));
}
public static void Cbnz(EmitterContext context) => EmitCb(context, onNotZero: true);
@ -66,12 +66,12 @@ namespace ARMeilleure.Instructions
{
OpCodeBImmCmp op = (OpCodeBImmCmp)context.CurrOp;
EmitBranch(context, GetIntOrZR(op, op.Rt), onNotZero);
EmitBranch(context, GetIntOrZR(context, op.Rt), onNotZero);
}
public static void Ret(EmitterContext context)
{
context.Return(GetIntOrZR(context.CurrOp, RegisterAlias.Lr));
context.Return(GetIntOrZR(context, RegisterAlias.Lr));
}
public static void Tbnz(EmitterContext context) => EmitTb(context, onNotZero: true);
@ -81,7 +81,7 @@ namespace ARMeilleure.Instructions
{
OpCodeBImmTest op = (OpCodeBImmTest)context.CurrOp;
Operand value = context.BitwiseAnd(GetIntOrZR(op, op.Rt), Const(1L << op.Bit));
Operand value = context.BitwiseAnd(GetIntOrZR(context, op.Rt), Const(1L << op.Bit));
EmitBranch(context, value, onNotZero);
}

View file

@ -55,8 +55,8 @@ namespace ARMeilleure.Instructions
MethodInfo info = typeof(SoftFallback).GetMethod(name);
Operand n = GetIntOrZR(op, op.Rn);
Operand m = GetIntOrZR(op, op.Rm);
Operand n = GetIntOrZR(context, op.Rn);
Operand m = GetIntOrZR(context, op.Rm);
Operand d = context.Call(info, n, m);

View file

@ -3,6 +3,7 @@ using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State;
using ARMeilleure.Translation;
using System;
using System.Reflection;
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
@ -17,37 +18,22 @@ namespace ARMeilleure.Instructions
public static Operand GetExtendedM(EmitterContext context, int rm, IntType type)
{
Operand value = GetIntOrZR(context.CurrOp, rm);
Operand value = GetIntOrZR(context, rm);
switch (type)
{
case IntType.UInt8: value = ZeroExtend8 (context, value); break;
case IntType.UInt16: value = ZeroExtend16(context, value); break;
case IntType.UInt32: value = ZeroExtend32(context, value); break;
case IntType.UInt8: value = context.ZeroExtend8 (value.Type, value); break;
case IntType.UInt16: value = context.ZeroExtend16(value.Type, value); break;
case IntType.UInt32: value = context.ZeroExtend32(value.Type, value); break;
case IntType.Int8: value = context.SignExtend8 (value); break;
case IntType.Int16: value = context.SignExtend16(value); break;
case IntType.Int32: value = context.SignExtend32(value); break;
case IntType.Int8: value = context.SignExtend8 (value.Type, value); break;
case IntType.Int16: value = context.SignExtend16(value.Type, value); break;
case IntType.Int32: value = context.SignExtend32(value.Type, value); break;
}
return value;
}
public static Operand ZeroExtend8(EmitterContext context, Operand value)
{
return context.BitwiseAnd(value, Const(value.Type, 0xff));
}
public static Operand ZeroExtend16(EmitterContext context, Operand value)
{
return context.BitwiseAnd(value, Const(value.Type, 0xffff));
}
public static Operand ZeroExtend32(EmitterContext context, Operand value)
{
return context.BitwiseAnd(value, Const(value.Type, 0xffffffff));
}
public static Operand GetIntA32(EmitterContext context, int register)
{
if (register == RegisterAlias.Aarch32Pc)
@ -58,7 +44,7 @@ namespace ARMeilleure.Instructions
}
else
{
return GetIntOrSP(context.CurrOp, GetRegisterAlias(context.Mode, register));
return GetIntOrSP(context, GetRegisterAlias(context.Mode, register));
}
}
@ -146,20 +132,22 @@ namespace ARMeilleure.Instructions
}
}
public static Operand GetIntOrZR(IOpCode op, int regIndex)
public static Operand GetIntOrZR(EmitterContext context, int regIndex)
{
OperandType type = op.GetOperandType();
if (regIndex == RegisterConsts.ZeroIndex)
{
OperandType type = context.CurrOp.GetOperandType();
return type == OperandType.I32 ? Const(0) : Const(0L);
}
else
{
return Register(regIndex, RegisterType.Integer, type);
return GetIntOrSP(context, regIndex);
}
}
public static bool FullDebug = false;
public static void SetIntOrZR(EmitterContext context, int regIndex, Operand value)
{
if (regIndex == RegisterConsts.ZeroIndex)
@ -167,12 +155,31 @@ namespace ARMeilleure.Instructions
return;
}
context.Copy(GetIntOrSP(context.CurrOp, regIndex), value);
SetIntOrSP(context, regIndex, value);
}
public static Operand GetIntOrSP(IOpCode op, int regIndex)
public static Operand GetIntOrSP(EmitterContext context, int regIndex)
{
return Register(regIndex, RegisterType.Integer, op.GetOperandType());
Operand value = Register(regIndex, RegisterType.Integer, OperandType.I64);
if (context.CurrOp.RegisterSize == RegisterSize.Int32)
{
value = context.ConvertI64ToI32(value);
}
return value;
}
public static void SetIntOrSP(EmitterContext context, int regIndex, Operand value)
{
Operand reg = Register(regIndex, RegisterType.Integer, OperandType.I64);
if (value.Type == OperandType.I32)
{
value = context.ZeroExtend32(OperandType.I64, value);
}
context.Copy(reg, value);
}
public static Operand GetVec(int regIndex)

View file

@ -129,7 +129,7 @@ namespace ARMeilleure.Instructions
{
case OpCodeMemImm op:
{
address = context.Copy(GetIntOrSP(op, op.Rn));
address = context.Copy(GetIntOrSP(context, op.Rn));
//Pre-indexing.
if (!op.PostIdx)
@ -142,7 +142,7 @@ namespace ARMeilleure.Instructions
case OpCodeMemReg op:
{
Operand n = GetIntOrSP(op, op.Rn);
Operand n = GetIntOrSP(context, op.Rn);
Operand m = GetExtendedM(context, op.Rm, op.IntType);
@ -170,7 +170,7 @@ namespace ARMeilleure.Instructions
address = context.Add(address, Const(op.Immediate));
}
context.Copy(GetIntOrSP(op, op.Rn), address);
SetIntOrSP(context, op.Rn, address);
}
}
}

View file

@ -59,7 +59,7 @@ namespace ARMeilleure.Instructions
EmitBarrier(context);
}
Operand address = context.Copy(GetIntOrSP(op, op.Rn));
Operand address = context.Copy(GetIntOrSP(context, op.Rn));
if (pair)
{
@ -71,9 +71,9 @@ namespace ARMeilleure.Instructions
{
Operand value = EmitLoad(context, address, exclusive, 3);
Operand valueLow = context.Copy(Local(OperandType.I32), value);
Operand valueLow = context.ConvertI64ToI32(value);
valueLow = context.Copy(Local(OperandType.I64), valueLow);
valueLow = context.ZeroExtend32(OperandType.I64, valueLow);
Operand valueHigh = context.ShiftRightUI(value, Const(32));
@ -173,9 +173,9 @@ namespace ARMeilleure.Instructions
EmitBarrier(context);
}
Operand address = context.Copy(GetIntOrSP(op, op.Rn));
Operand address = context.Copy(GetIntOrSP(context, op.Rn));
Operand t = GetIntOrZR(op, op.Rt);
Operand t = GetIntOrZR(context, op.Rt);
Operand s = null;
@ -183,7 +183,7 @@ namespace ARMeilleure.Instructions
{
Debug.Assert(op.Size == 2 || op.Size == 3, "Invalid size for pairwise store.");
Operand t2 = GetIntOrZR(op, op.Rt2);
Operand t2 = GetIntOrZR(context, op.Rt2);
Operand value;
@ -221,7 +221,7 @@ namespace ARMeilleure.Instructions
{
if (size < 3)
{
value = context.Copy(Local(OperandType.I32), value);
value = context.ConvertI64ToI32(value);
}
string fallbackMethodName = null;
@ -254,6 +254,8 @@ namespace ARMeilleure.Instructions
MethodInfo info = typeof(NativeInterface).GetMethod(fallbackMethodName);
context.Call(info, address, value);
return null;
}
}

View file

@ -13,8 +13,6 @@ namespace ARMeilleure.Instructions
{
static class InstEmitMemoryHelper
{
private static bool ForceFallback = true;
private enum Extension
{
Zx,
@ -48,47 +46,30 @@ namespace ARMeilleure.Instructions
if (isSimd)
{
if (ForceFallback || !Optimizations.UseSse2 || size < 2)
{
EmitReadVectorFallback(context, address, context.VectorZero(), rt, 0, size);
}
else
{
EmitReadVector(context, address, context.VectorZero(), rt, 0, size);
}
EmitReadVector(context, address, context.VectorZero(), rt, 0, size);
}
else
{
if (ForceFallback)
{
EmitReadIntFallback(context, address, rt, size);
}
else
{
EmitReadInt(context, address, rt, size);
}
EmitReadInt(context, address, rt, size);
}
if (!isSimd)
{
Operand value = GetT(context, rt);
if (ext == Extension.Sx64)
{
value = context.Copy(Local(OperandType.I64), value);
}
Operand value = GetIntOrZR(context, rt);
if (ext == Extension.Sx32 || ext == Extension.Sx64)
{
OperandType destType = ext == Extension.Sx64 ? OperandType.I64 : OperandType.I32;
switch (size)
{
case 0: value = context.SignExtend8 (value); break;
case 1: value = context.SignExtend16(value); break;
case 2: value = context.SignExtend32(value); break;
case 0: value = context.SignExtend8 (destType, value); break;
case 1: value = context.SignExtend16(destType, value); break;
case 2: value = context.SignExtend32(destType, value); break;
}
}
context.Copy(GetT(context, rt), value);
SetIntOrZR(context, rt, value);
}
}
@ -100,14 +81,7 @@ namespace ARMeilleure.Instructions
int elem,
int size)
{
if (ForceFallback || !Optimizations.UseSse2 || size < 2)
{
EmitReadVectorFallback(context, address, vector, rt, elem, size);
}
else
{
EmitReadVector(context, address, vector, rt, elem, size);
}
EmitReadVector(context, address, vector, rt, elem, size);
}
public static void EmitStore(EmitterContext context, Operand address, int rt, int size)
@ -121,25 +95,11 @@ namespace ARMeilleure.Instructions
if (isSimd)
{
if (ForceFallback || !Optimizations.UseSse2 || size < 2)
{
EmitWriteVectorFallback(context, address, rt, 0, size);
}
else
{
EmitWriteVector(context, address, rt, 0, size);
}
EmitWriteVector(context, address, rt, 0, size);
}
else
{
if (ForceFallback)
{
EmitWriteIntFallback(context, address, rt, size);
}
else
{
EmitWriteInt(context, address, rt, size);
}
EmitWriteInt(context, address, rt, size);
}
}
@ -150,14 +110,7 @@ namespace ARMeilleure.Instructions
int elem,
int size)
{
if (ForceFallback || !Optimizations.UseSse2 || size < 2)
{
EmitWriteVectorFallback(context, address, rt, elem, size);
}
else
{
EmitWriteVector(context, address, rt, elem, size);
}
EmitWriteVector(context, address, rt, elem, size);
}
private static bool IsSimd(EmitterContext context)
@ -197,7 +150,7 @@ namespace ARMeilleure.Instructions
case 3: value = context.Load (Local(OperandType.I64), physAddr); break;
}
context.Copy(GetT(context, rt), value);
SetIntOrZR(context, rt, value);
context.MarkLabel(lblEnd);
}
@ -230,29 +183,39 @@ namespace ARMeilleure.Instructions
Operand value = null;
/*switch (size)
switch (size)
{
case 2: context.EmitCall(typeof(Sse), nameof(Sse.LoadScalarVector128)); break;
case 0:
value = context.VectorInsert8(vector, context.LoadZx8(Local(OperandType.I32), physAddr), elem);
break;
case 1:
value = context.VectorInsert16(vector, context.LoadZx16(Local(OperandType.I32), physAddr), elem);
break;
case 2:
value = context.VectorInsert(vector, context.Load(Local(OperandType.I32), physAddr), elem);
break;
case 3:
{
Type[] types = new Type[] { typeof(double*) };
context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.LoadScalarVector128), types));
value = context.VectorInsert(vector, context.Load(Local(OperandType.I64), physAddr), elem);
break;
}
case 4: context.EmitCall(typeof(Sse), nameof(Sse.LoadAlignedVector128)); break;
throw new InvalidOperationException($"Invalid vector load size of {1 << size} bytes.");
}*/
case 4:
value = context.Load(Local(OperandType.V128), physAddr);
break;
}
context.Copy(GetVec(rt), value);
context.MarkLabel(lblEnd);
}
private static Operand VectorCreate(EmitterContext context, Operand value)
{
return context.VectorInsert(context.VectorZero(), value, 0);
}
private static void EmitWriteInt(EmitterContext context, Operand address, int rt, int size)
{
Operand isUnalignedAddr = EmitAddressCheck(context, address, size);
@ -273,11 +236,11 @@ namespace ARMeilleure.Instructions
Operand physAddr = EmitPtPointerLoad(context, address, lblSlowPath);
Operand value = GetT(context, rt);
Operand value = GetIntOrZR(context, rt);
if (size < 3)
{
value = context.Copy(Local(OperandType.I32), value);
value = context.ConvertI64ToI32(value);
}
switch (size)
@ -318,14 +281,28 @@ namespace ARMeilleure.Instructions
Operand value = GetVec(rt);
/*switch (size)
switch (size)
{
case 2: context.EmitCall(typeof(Sse), nameof(Sse.StoreScalar)); break;
case 3: context.EmitCall(typeof(Sse2), nameof(Sse2.StoreScalar)); break;
case 4: context.EmitCall(typeof(Sse), nameof(Sse.StoreAligned)); break;
case 0:
context.Store8(physAddr, context.VectorExtract8(value, Local(OperandType.I32), elem));
break;
default: throw new InvalidOperationException($"Invalid vector store size of {1 << size} bytes.");
}*/
case 1:
context.Store16(physAddr, context.VectorExtract16(value, Local(OperandType.I32), elem));
break;
case 2:
context.Store(physAddr, context.VectorExtract(value, Local(OperandType.FP32), elem));
break;
case 3:
context.Store(physAddr, context.VectorExtract(value, Local(OperandType.FP64), elem));
break;
case 4:
context.Store(physAddr, value);
break;
}
context.MarkLabel(lblEnd);
}
@ -392,7 +369,7 @@ namespace ARMeilleure.Instructions
MethodInfo info = typeof(NativeInterface).GetMethod(fallbackMethodName);
context.Copy(GetT(context, rt), context.Call(info, address));
SetIntOrZR(context, rt, context.Call(info, address));
}
private static void EmitReadVectorFallback(
@ -420,7 +397,7 @@ namespace ARMeilleure.Instructions
if (size < 3)
{
value = context.Copy(Local(OperandType.I32), value);
value = context.ConvertI64ToI32(value);
}
switch (size)
@ -448,11 +425,11 @@ namespace ARMeilleure.Instructions
MethodInfo info = typeof(NativeInterface).GetMethod(fallbackMethodName);
Operand value = GetT(context, rt);
Operand value = GetIntOrZR(context, rt);
if (size < 3)
{
value = context.Copy(Local(OperandType.I32), value);
value = context.ConvertI64ToI32(value);
}
context.Call(info, address, value);
@ -499,32 +476,5 @@ namespace ARMeilleure.Instructions
context.Call(info, address, value);
}
private static Operand GetT(EmitterContext context, int rt)
{
OpCode op = context.CurrOp;
if (op is IOpCodeSimd)
{
return GetVec(rt);
}
else if (op is OpCodeMem opMem)
{
bool is32Bits = opMem.Size < 3 && !opMem.Extend64;
OperandType type = is32Bits ? OperandType.I32 : OperandType.I64;
if (rt == RegisterConsts.ZeroIndex)
{
return Const(type, 0);
}
return Register(rt, RegisterType.Integer, type);
}
else
{
return GetIntOrZR(context.CurrOp, rt);
}
}
}
}

View file

@ -15,7 +15,7 @@ namespace ARMeilleure.Instructions
OperandType type = op.GetOperandType();
Operand res = GetIntOrZR(op, op.Rd);
Operand res = GetIntOrZR(context, op.Rd);
res = context.BitwiseAnd(res, Const(type, ~(0xffffL << op.Bit)));

View file

@ -16,9 +16,9 @@ namespace ARMeilleure.Instructions
{
OpCodeMul op = (OpCodeMul)context.CurrOp;
Operand a = GetIntOrZR(op, op.Ra);
Operand n = GetIntOrZR(op, op.Rn);
Operand m = GetIntOrZR(op, op.Rm);
Operand a = GetIntOrZR(context, op.Ra);
Operand n = GetIntOrZR(context, op.Rn);
Operand m = GetIntOrZR(context, op.Rm);
Operand res = context.Multiply(n, m);
@ -49,19 +49,19 @@ namespace ARMeilleure.Instructions
Operand GetExtendedRegister32(int index)
{
Operand value = GetIntOrZR(op, index);
Operand value = GetIntOrZR(context, index);
if ((flags & MullFlags.Signed) != 0)
{
return context.SignExtend32(value);
return context.SignExtend32(value.Type, value);
}
else
{
return ZeroExtend32(context, value);
return context.ZeroExtend32(value.Type, value);
}
}
Operand a = GetIntOrZR(op, op.Ra);
Operand a = GetIntOrZR(context, op.Ra);
Operand n = GetExtendedRegister32(op.Rn);
Operand m = GetExtendedRegister32(op.Rm);
@ -77,8 +77,8 @@ namespace ARMeilleure.Instructions
{
OpCodeMul op = (OpCodeMul)context.CurrOp;
Operand n = GetIntOrZR(op, op.Rn);
Operand m = GetIntOrZR(op, op.Rm);
Operand n = GetIntOrZR(context, op.Rn);
Operand m = GetIntOrZR(context, op.Rm);
Operand d = context.Multiply64HighSI(n, m);
@ -89,8 +89,8 @@ namespace ARMeilleure.Instructions
{
OpCodeMul op = (OpCodeMul)context.CurrOp;
Operand n = GetIntOrZR(op, op.Rn);
Operand m = GetIntOrZR(op, op.Rm);
Operand n = GetIntOrZR(context, op.Rn);
Operand m = GetIntOrZR(context, op.Rm);
Operand d = context.Multiply64HighUI(n, m);

View file

@ -66,7 +66,7 @@ namespace ARMeilleure.Instructions
Operand res = context.Call(info, ne);
res = context.Copy(Local(OperandType.I64), res);
res = context.ZeroExtend16(OperandType.I64, res);
context.Copy(GetVec(op.Rd), EmitVectorInsert(context, context.VectorZero(), res, 0, 1));
}
@ -217,7 +217,7 @@ namespace ARMeilleure.Instructions
Operand e = context.Call(info, ne);
e = context.Copy(Local(OperandType.I64), e);
e = context.ZeroExtend16(OperandType.I64, e);
res = EmitVectorInsert(context, res, e, part + index, 1);
}
@ -387,7 +387,7 @@ namespace ARMeilleure.Instructions
{
OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
Operand res = GetIntOrZR(op, op.Rn);
Operand res = GetIntOrZR(context, op.Rn);
res = EmitFPConvert(context, res, op.Size, signed: true);
@ -398,7 +398,7 @@ namespace ARMeilleure.Instructions
{
OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
Operand res = GetIntOrZR(op, op.Rn);
Operand res = GetIntOrZR(context, op.Rn);
res = EmitFPConvert(context, res, op.Size, signed: true);
@ -464,7 +464,7 @@ namespace ARMeilleure.Instructions
{
OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
Operand res = GetIntOrZR(op, op.Rn);
Operand res = GetIntOrZR(context, op.Rn);
res = EmitFPConvert(context, res, op.Size, signed: false);
@ -475,7 +475,7 @@ namespace ARMeilleure.Instructions
{
OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
Operand res = GetIntOrZR(op, op.Rn);
Operand res = GetIntOrZR(context, op.Rn);
res = EmitFPConvert(context, res, op.Size, signed: false);
@ -568,7 +568,7 @@ namespace ARMeilleure.Instructions
e = context.Call(info, e);
e = context.Copy(Local(OperandType.I64), e);
e = context.ZeroExtend32(OperandType.I64, e);
}
else /* if (sizeF == 1) */
{
@ -620,7 +620,7 @@ namespace ARMeilleure.Instructions
e = context.Call(info, e);
e = context.Copy(Local(OperandType.I64), e);
e = context.ZeroExtend32(OperandType.I64, e);
}
else /* if (sizeF == 1) */
{
@ -661,11 +661,6 @@ namespace ARMeilleure.Instructions
? EmitScalarFcvts(context, emit(ne), 0)
: EmitScalarFcvtu(context, emit(ne), 0);
if (context.CurrOp.RegisterSize == RegisterSize.Int32)
{
res = context.Copy(Local(OperandType.I64), res);
}
SetIntOrZR(context, op.Rd, res);
}
@ -691,11 +686,6 @@ namespace ARMeilleure.Instructions
? EmitScalarFcvts(context, ne, op.FBits)
: EmitScalarFcvtu(context, ne, op.FBits);
if (context.CurrOp.RegisterSize == RegisterSize.Int32)
{
res = context.Copy(Local(OperandType.I64), res);
}
SetIntOrZR(context, op.Rd, res);
}

View file

@ -1402,30 +1402,6 @@ namespace ARMeilleure.Instructions
return context.Call(typeof(SoftFallback).GetMethod(name), op1, op2);
}
public static Operand EmitVectorExtractSx32(EmitterContext context, int reg, int index, int size)
{
ThrowIfInvalid(index, size);
Operand res = Local(OperandType.I32);
switch (size)
{
case 0: context.VectorExtract8 (GetVec(reg), res, index); break;
case 1: context.VectorExtract16(GetVec(reg), res, index); break;
case 2: context.VectorExtract (GetVec(reg), res, index); break;
case 3: context.VectorExtract (GetVec(reg), res, index); break;
}
switch (size)
{
case 0: res = context.SignExtend8 (res); break;
case 1: res = context.SignExtend16(res); break;
case 2: res = context.SignExtend32(res); break;
}
return res;
}
public static Operand EmitVectorExtractSx(EmitterContext context, int reg, int index, int size)
{
return EmitVectorExtract(context, reg, index, size, true);
@ -1450,15 +1426,22 @@ namespace ARMeilleure.Instructions
case 3: context.VectorExtract (GetVec(reg), res, index); break;
}
res = context.Copy(Local(OperandType.I64), res);
if (signed)
{
switch (size)
{
case 0: res = context.SignExtend8 (res); break;
case 1: res = context.SignExtend16(res); break;
case 2: res = context.SignExtend32(res); break;
case 0: res = context.SignExtend8 (OperandType.I64, res); break;
case 1: res = context.SignExtend16(OperandType.I64, res); break;
case 2: res = context.SignExtend32(OperandType.I64, res); break;
}
}
else
{
switch (size)
{
case 0: res = context.ZeroExtend8 (OperandType.I64, res); break;
case 1: res = context.ZeroExtend16(OperandType.I64, res); break;
case 2: res = context.ZeroExtend32(OperandType.I64, res); break;
}
}
@ -1471,7 +1454,7 @@ namespace ARMeilleure.Instructions
if (size < 3)
{
value = context.Copy(Local(OperandType.I32), value);
value = context.ConvertI64ToI32(value);
}
switch (size)

View file

@ -293,13 +293,13 @@ namespace ARMeilleure.Instructions
{
Operand ne = EmitVectorExtractZx(context, op.Rn, index, 0);
ne = context.Copy(Local(OperandType.I32), ne);
ne = context.ConvertI64ToI32(ne);
MethodInfo info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.ReverseBits8));
Operand de = context.Call(info, ne);
de = context.Copy(Local(OperandType.I64), de);
de = context.ZeroExtend32(OperandType.I64, de);
res = EmitVectorInsert(context, res, de, index, 0);
}

View file

@ -36,7 +36,7 @@ namespace ARMeilleure.Instructions
{
OpCodeSimdMemMs op = (OpCodeSimdMemMs)context.CurrOp;
Operand n = GetIntOrSP(op, op.Rn);
Operand n = GetIntOrSP(context, op.Rn);
long offset = 0;
@ -77,7 +77,7 @@ namespace ARMeilleure.Instructions
{
OpCodeSimdMemSs op = (OpCodeSimdMemSs)context.CurrOp;
Operand n = GetIntOrSP(op, op.Rn);
Operand n = GetIntOrSP(context, op.Rn);
long offset = 0;
@ -142,12 +142,12 @@ namespace ARMeilleure.Instructions
{
OpCodeMemReg op = (OpCodeMemReg)context.CurrOp;
Operand n = GetIntOrSP(op, op.Rn);
Operand n = GetIntOrSP(context, op.Rn);
Operand m;
if (op.Rm != RegisterAlias.Zr)
{
m = GetIntOrZR(op, op.Rm);
m = GetIntOrZR(context, op.Rm);
}
else
{

View file

@ -42,15 +42,15 @@ namespace ARMeilleure.Instructions
{
OpCodeSimdIns op = (OpCodeSimdIns)context.CurrOp;
Operand n = GetIntOrZR(op, op.Rn);
Operand n = GetIntOrZR(context, op.Rn);
if (Optimizations.UseSse2)
{
switch (op.Size)
{
case 0: n = ZeroExtend8 (context, n); n = context.Multiply(n, Const(0x01010101)); break;
case 1: n = ZeroExtend16(context, n); n = context.Multiply(n, Const(0x00010001)); break;
case 2: n = ZeroExtend32(context, n); break;
case 0: n = context.ZeroExtend8 (n.Type, n); n = context.Multiply(n, Const(0x01010101)); break;
case 1: n = context.ZeroExtend16(n.Type, n); n = context.Multiply(n, Const(0x00010001)); break;
case 2: n = context.ZeroExtend32(n.Type, n); break;
}
Operand res = context.VectorInsert(context.VectorZero(), n, 0);
@ -225,10 +225,9 @@ namespace ARMeilleure.Instructions
Operand isTrue = InstEmitFlowHelper.GetCondTrue(context, op.Cond);
context.BranchIfTrue(isTrue, lblTrue);
context.BranchIfTrue(lblTrue, isTrue);
OperandType type = op.Size != 0 ? OperandType.FP32
: OperandType.FP64;
OperandType type = op.Size == 0 ? OperandType.FP32 : OperandType.FP64;
Operand me = context.VectorExtract(GetVec(op.Rm), Local(type), 0);
@ -247,46 +246,45 @@ namespace ARMeilleure.Instructions
public static void Fmov_Ftoi(EmitterContext context)
{
OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
Operand ne = EmitVectorExtractZx(context, op.Rn, 0, 3);
Operand ne = EmitVectorExtractZx(context, op.Rn, 0, op.Size + 2);
SetIntOrZR(context, op.Rd, EmitIntZeroUpperIfNeeded(context, ne));
SetIntOrZR(context, op.Rd, ne);
}
public static void Fmov_Ftoi1(EmitterContext context)
{
OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
Operand ne = EmitVectorExtractZx(context, op.Rn, 1, 3);
SetIntOrZR(context, op.Rd, EmitIntZeroUpperIfNeeded(context, ne));
SetIntOrZR(context, op.Rd, ne);
}
public static void Fmov_Itof(EmitterContext context)
{
OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
Operand n = EmitIntZeroUpperIfNeeded(context, GetIntOrZR(op, op.Rn));
Operand n = GetIntOrZR(context, op.Rn);
context.Copy(GetVec(op.Rd), EmitVectorInsert(context, context.VectorZero(), n, 0, 3));
context.Copy(GetVec(op.Rd), EmitVectorInsert(context, context.VectorZero(), n, 0, op.Size + 2));
}
public static void Fmov_Itof1(EmitterContext context)
{
OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
Operand n = EmitIntZeroUpperIfNeeded(context, GetIntOrZR(op, op.Rn));
Operand n = GetIntOrZR(context, op.Rn);
context.Copy(GetVec(op.Rd), EmitVectorInsert(context, context.VectorZero(), n, 1, 3));
context.Copy(GetVec(op.Rd), EmitVectorInsert(context, GetVec(op.Rd), n, 1, 3));
}
public static void Fmov_S(EmitterContext context)
{
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
OperandType type = op.Size != 0 ? OperandType.FP32
: OperandType.FP64;
OperandType type = op.Size == 0 ? OperandType.FP32 : OperandType.FP64;
Operand ne = context.VectorExtract(GetVec(op.Rn), Local(type), 0);
@ -307,20 +305,11 @@ namespace ARMeilleure.Instructions
}
}
public static void Fmov_V(EmitterContext context)
public static void Fmov_Vi(EmitterContext context)
{
OpCodeSimdImm op = (OpCodeSimdImm)context.CurrOp;
Operand e;
if (op.Size == 0)
{
e = Const((int)op.Immediate);
}
else
{
e = Const(op.Immediate);
}
Operand e = Const(op.Immediate);
Operand res = context.VectorZero();
@ -331,25 +320,27 @@ namespace ARMeilleure.Instructions
res = EmitVectorInsert(context, res, e, index, op.Size + 2);
}
context.Copy(GetVec(op.Rd), e);
context.Copy(GetVec(op.Rd), res);
}
public static void Ins_Gp(EmitterContext context)
{
OpCodeSimdIns op = (OpCodeSimdIns)context.CurrOp;
Operand n = GetIntOrZR(op, op.Rn);
Operand d = GetVec(op.Rd);
Operand n = GetIntOrZR(context, op.Rn);
context.Copy(GetVec(op.Rd), EmitVectorInsert(context, context.VectorZero(), n, op.DstIndex, op.Size));
context.Copy(d, EmitVectorInsert(context, d, n, op.DstIndex, op.Size));
}
public static void Ins_V(EmitterContext context)
{
OpCodeSimdIns op = (OpCodeSimdIns)context.CurrOp;
Operand d = GetVec(op.Rd);
Operand ne = EmitVectorExtractZx(context, op.Rn, op.SrcIndex, op.Size);
context.Copy(GetVec(op.Rd), EmitVectorInsert(context, context.VectorZero(), ne, op.DstIndex, op.Size));
context.Copy(d, EmitVectorInsert(context, d, ne, op.DstIndex, op.Size));
}
public static void Movi_V(EmitterContext context)
@ -382,7 +373,12 @@ namespace ARMeilleure.Instructions
Operand ne = EmitVectorExtractSx(context, op.Rn, op.DstIndex, op.Size);
SetIntOrZR(context, op.Rd, EmitIntZeroUpperIfNeeded(context, ne));
if (op.RegisterSize == RegisterSize.Simd64)
{
ne = context.ZeroExtend32(OperandType.I64, ne);
}
SetIntOrZR(context, op.Rd, ne);
}
public static void Tbl_V(EmitterContext context)
@ -544,17 +540,6 @@ namespace ARMeilleure.Instructions
EmitVectorZip(context, part: 1);
}
private static Operand EmitIntZeroUpperIfNeeded(EmitterContext context, Operand value)
{
if (context.CurrOp.RegisterSize == RegisterSize.Int32 ||
context.CurrOp.RegisterSize == RegisterSize.Simd64)
{
return ZeroExtend32(context, value);
}
return value;
}
private static void EmitMoviMvni(EmitterContext context, bool not)
{
OpCodeSimdImm op = (OpCodeSimdImm)context.CurrOp;
@ -761,7 +746,11 @@ namespace ARMeilleure.Instructions
if (op.RegisterSize == RegisterSize.Simd128)
{
Operand res = context.AddIntrinsic(X86PunpcklInstruction[op.Size], n, m);
Instruction punpckInst = part == 0
? X86PunpcklInstruction[op.Size]
: X86PunpckhInstruction[op.Size];
Operand res = context.AddIntrinsic(punpckInst, n, m);
context.Copy(GetVec(op.Rd), res);
}

View file

@ -65,7 +65,7 @@ namespace ARMeilleure.Instructions
MethodInfo info = typeof(NativeInterface).GetMethod(name);
context.Call(info, GetIntOrZR(op, op.Rt));
context.Call(info, GetIntOrZR(context, op.Rt));
}
public static void Nop(EmitterContext context)
@ -85,7 +85,7 @@ namespace ARMeilleure.Instructions
case 0b11_011_0111_0100_001:
{
//DC ZVA
Operand t = GetIntOrZR(op, op.Rt);
Operand t = GetIntOrZR(context, op.Rt);
MethodInfo info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt64));

View file

@ -212,7 +212,7 @@ namespace ARMeilleure.Instructions
Fmls_Ve,
Fmov_S,
Fmov_Si,
Fmov_V,
Fmov_Vi,
Fmov_Ftoi,
Fmov_Itof,
Fmov_Ftoi1,

View file

@ -249,8 +249,8 @@ namespace ARMeilleure.Instructions
{
success = context.Memory.AtomicCompareExchangeByte(
(long)address,
(byte)value,
(byte)context.ExclusiveValueLow);
(byte)context.ExclusiveValueLow,
(byte)value);
if (success)
{
@ -271,8 +271,8 @@ namespace ARMeilleure.Instructions
{
success = context.Memory.AtomicCompareExchangeInt16(
(long)address,
(short)value,
(short)context.ExclusiveValueLow);
(short)context.ExclusiveValueLow,
(short)value);
if (success)
{
@ -293,8 +293,8 @@ namespace ARMeilleure.Instructions
{
success = context.Memory.AtomicCompareExchangeInt32(
(long)address,
(int)value,
(int)context.ExclusiveValueLow);
(int)context.ExclusiveValueLow,
(int)value);
if (success)
{
@ -315,8 +315,8 @@ namespace ARMeilleure.Instructions
{
success = context.Memory.AtomicCompareExchangeInt64(
(long)address,
(long)value,
(long)context.ExclusiveValueLow);
(long)context.ExclusiveValueLow,
(long)value);
if (success)
{
@ -337,10 +337,10 @@ namespace ARMeilleure.Instructions
{
success = context.Memory.AtomicCompareExchangeInt128(
(long)address,
value.GetUInt64(0),
value.GetUInt64(1),
context.ExclusiveValueLow,
context.ExclusiveValueHigh);
context.ExclusiveValueHigh,
value.GetUInt64(0),
value.GetUInt64(1));
if (success)
{
@ -362,6 +362,11 @@ namespace ARMeilleure.Instructions
GetCurrentContext().ExclusiveAddress = ulong.MaxValue;
}
public static void CheckSynchronization()
{
GetContext().CheckInterrupt();
}
private static ThreadContext GetCurrentContext()
{
return _contexts[Thread.CurrentThread];

View file

@ -38,6 +38,8 @@ namespace ARMeilleure.IntermediateRepresentation
Predecessors = new List<BasicBlock>();
DominanceFrontiers = new HashSet<BasicBlock>();
Index = -1;
}
public BasicBlock(int index) : this()

View file

@ -23,6 +23,7 @@ namespace ARMeilleure.IntermediateRepresentation
CompareLessUI,
CompareNotEqual,
ConditionalSelect,
ConvertI64ToI32,
ConvertToFP,
ConvertToFPUI,
Copy,
@ -46,9 +47,9 @@ namespace ARMeilleure.IntermediateRepresentation
ShiftLeft,
ShiftRightSI,
ShiftRightUI,
SignExtend8,
SignExtend16,
SignExtend32,
SignExtend8,
Spill,
SpillArg,
StackAlloc,
@ -63,9 +64,13 @@ namespace ARMeilleure.IntermediateRepresentation
VectorInsert,
VectorInsert16,
VectorInsert8,
VectorOne,
VectorZero,
VectorZeroUpper64,
VectorZeroUpper96,
ZeroExtend16,
ZeroExtend32,
ZeroExtend8,
//Intrinsics
X86Intrinsic_Start,

View file

@ -1,10 +1,9 @@
using ARMeilleure.State;
using System;
using System.Collections.Generic;
namespace ARMeilleure.IntermediateRepresentation
{
class Operand //: IEquatable<Operand>
class Operand
{
public OperandKind Kind { get; }
@ -29,11 +28,6 @@ namespace ARMeilleure.IntermediateRepresentation
Type = type;
}
public Operand(OperandType type, int offset) : this(OperandKind.Memory, type)
{
Value = (uint)offset;
}
public Operand(int value) : this(OperandKind.Constant, OperandType.I32)
{
Value = (uint)value;
@ -107,7 +101,7 @@ namespace ARMeilleure.IntermediateRepresentation
return BitConverter.Int64BitsToDouble((long)Value);
}
public void NumberLocal(int number)
internal void NumberLocal(int number)
{
if (Kind != OperandKind.LocalVariable)
{

View file

@ -5,10 +5,14 @@ namespace ARMeilleure.State
{
public class ExecutionContext : IDisposable
{
private const int MinCountForCheck = 40000;
private NativeContext _nativeContext;
internal IntPtr NativeContextPtr => _nativeContext.BasePtr;
private bool _interrupted;
private static Stopwatch _tickCounter;
private static double _hostTickFreq;
@ -33,6 +37,9 @@ namespace ARMeilleure.State
public FPCR Fpcr { get; set; }
public FPSR Fpsr { get; set; }
public bool Running { get; set; }
public event EventHandler<EventArgs> Interrupt;
public event EventHandler<InstExceptionEventArgs> Break;
public event EventHandler<InstExceptionEventArgs> SupervisorCall;
public event EventHandler<InstUndefinedEventArgs> Undefined;
@ -49,6 +56,10 @@ namespace ARMeilleure.State
public ExecutionContext()
{
_nativeContext = new NativeContext();
Running = true;
_nativeContext.SetCounter(MinCountForCheck);
}
public ulong GetX(int index) => _nativeContext.GetX(index);
@ -60,6 +71,23 @@ namespace ARMeilleure.State
public bool GetPstateFlag(PState flag) => _nativeContext.GetPstateFlag(flag);
public void SetPstateFlag(PState flag, bool value) => _nativeContext.SetPstateFlag(flag, value);
public void CheckInterrupt()
{
if (_interrupted)
{
_interrupted = false;
Interrupt?.Invoke(this, EventArgs.Empty);
}
_nativeContext.SetCounter(MinCountForCheck);
}
public void RequestInterrupt()
{
_interrupted = true;
}
internal void OnBreak(ulong address, int imm)
{
Break?.Invoke(this, new InstExceptionEventArgs(address, imm));

View file

@ -7,13 +7,14 @@ namespace ARMeilleure.State
{
class NativeContext : IDisposable
{
private const int IntSize = 8;
private const int VecSize = 16;
private const int FlagSize = 4;
private const int IntSize = 8;
private const int VecSize = 16;
private const int FlagSize = 4;
private const int ExtraSize = 4;
private const int TotalSize = RegisterConsts.IntRegsCount * IntSize +
RegisterConsts.VecRegsCount * VecSize +
RegisterConsts.FlagsCount * FlagSize;
private const int TotalSize = RegisterConsts.IntRegsCount * IntSize +
RegisterConsts.VecRegsCount * VecSize +
RegisterConsts.FlagsCount * FlagSize + ExtraSize;
public IntPtr BasePtr { get; }
@ -99,6 +100,16 @@ namespace ARMeilleure.State
Marshal.WriteInt32(BasePtr, offset, value ? 1 : 0);
}
public int GetCounter()
{
return Marshal.ReadInt32(BasePtr, GetCounterOffset());
}
public void SetCounter(int value)
{
Marshal.WriteInt32(BasePtr, GetCounterOffset(), value);
}
public static int GetRegisterOffset(Register reg)
{
if (reg.Type == RegisterType.Integer)
@ -116,6 +127,13 @@ namespace ARMeilleure.State
}
}
public static int GetCounterOffset()
{
return RegisterConsts.IntRegsCount * IntSize +
RegisterConsts.VecRegsCount * VecSize +
RegisterConsts.FlagsCount * FlagSize;
}
public void Dispose()
{
MemoryManagement.Free(BasePtr);

View file

@ -1,6 +1,7 @@
using ARMeilleure.IntermediateRepresentation;
using System;
using System.Collections.Generic;
using System.Diagnostics;
namespace ARMeilleure.Translation
{
@ -68,6 +69,8 @@ namespace ARMeilleure.Translation
while (workQueue.TryDequeue(out BasicBlock block))
{
Debug.Assert(block.Index != -1, "Invalid block index.");
if (block.Next != null && visited.Add(block.Next))
{
workQueue.Enqueue(block.Next);

View file

@ -1,4 +1,5 @@
using ARMeilleure.IntermediateRepresentation;
using System.Diagnostics;
namespace ARMeilleure.Translation
{
@ -28,6 +29,8 @@ namespace ARMeilleure.Translation
cfg.Entry.ImmediateDominator = cfg.Entry;
Debug.Assert(cfg.Entry == cfg.PostOrderBlocks[cfg.PostOrderBlocks.Length - 1]);
bool modified;
do

View file

@ -5,6 +5,7 @@ using ARMeilleure.State;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
@ -93,6 +94,8 @@ namespace ARMeilleure.Translation
public Operand Call(MethodInfo info, params Operand[] callArgs)
{
RuntimeHelpers.PrepareMethod(info.MethodHandle);
long methodPtr = info.MethodHandle.GetFunctionPointer().ToInt64();
Operand[] args = new Operand[callArgs.Length + 1];
@ -156,6 +159,11 @@ namespace ARMeilleure.Translation
return Add(Instruction.ConditionalSelect, Local(b.Type), a, b, c);
}
public Operand ConvertI64ToI32(Operand a)
{
return Add(Instruction.ConvertI64ToI32, Local(OperandType.I32), a);
}
public Operand ConvertToFP(OperandType type, Operand a)
{
return Add(Instruction.ConvertToFP, Local(type), a);
@ -246,6 +254,30 @@ namespace ARMeilleure.Translation
return Add(Instruction.Load, value, address);
}
public Operand LoadFromContext(int offset)
{
return Add(Instruction.LoadFromContext, Local(OperandType.I32), Const(offset));
}
public void LoadFromContext()
{
_needsNewBlock = true;
Add(Instruction.LoadFromContext);
}
public void StoreToContext(int offset, Operand value)
{
Add(Instruction.StoreToContext, null, Const(offset), value);
}
public void StoreToContext()
{
Add(Instruction.StoreToContext);
_needsNewBlock = true;
}
public Operand LoadSx16(Operand value, Operand address)
{
return Add(Instruction.LoadSx16, value, address);
@ -293,12 +325,20 @@ namespace ARMeilleure.Translation
public Operand Return()
{
return Add(Instruction.Return);
Operand returnValue = Add(Instruction.Return);
_needsNewBlock = true;
return returnValue;
}
public Operand Return(Operand a)
{
return Add(Instruction.Return, null, a);
Operand returnValue = Add(Instruction.Return, null, a);
_needsNewBlock = true;
return returnValue;
}
public Operand RotateRight(Operand a, Operand b)
@ -321,19 +361,19 @@ namespace ARMeilleure.Translation
return Add(Instruction.ShiftRightUI, Local(a.Type), a, b);
}
public Operand SignExtend8(Operand a)
public Operand SignExtend16(OperandType type, Operand a)
{
return Add(Instruction.SignExtend8, Local(a.Type), a);
return Add(Instruction.SignExtend16, Local(type), a);
}
public Operand SignExtend16(Operand a)
public Operand SignExtend32(OperandType type, Operand a)
{
return Add(Instruction.SignExtend16, Local(a.Type), a);
return Add(Instruction.SignExtend32, Local(type), a);
}
public Operand SignExtend32(Operand a)
public Operand SignExtend8(OperandType type, Operand a)
{
return Add(Instruction.SignExtend32, Local(a.Type), a);
return Add(Instruction.SignExtend8, Local(type), a);
}
public void Store(Operand address, Operand value)
@ -401,6 +441,21 @@ namespace ARMeilleure.Translation
return Add(Instruction.VectorZeroUpper96, Local(OperandType.V128), vector);
}
public Operand ZeroExtend16(OperandType type, Operand a)
{
return Add(Instruction.ZeroExtend16, Local(type), a);
}
public Operand ZeroExtend32(OperandType type, Operand a)
{
return Add(Instruction.ZeroExtend32, Local(type), a);
}
public Operand ZeroExtend8(OperandType type, Operand a)
{
return Add(Instruction.ZeroExtend8, Local(type), a);
}
public Operand AddIntrinsic(Instruction inst, params Operand[] args)
{
return Add(inst, Local(OperandType.V128), args);
@ -444,11 +499,6 @@ namespace ARMeilleure.Translation
_needsNewBlock = true;
}
public void Synchronize()
{
}
public void MarkLabel(Operand label)
{
if (_irLabels.TryGetValue(label, out BasicBlock nextBlock))

View file

@ -68,7 +68,7 @@ namespace ARMeilleure.Translation
}
}
public static void InsertContext(ControlFlowGraph cfg)
public static void RunPass(ControlFlowGraph cfg)
{
//Computer local register inputs and outputs used inside blocks.
RegisterMask[] localInputs = new RegisterMask[cfg.Blocks.Count];
@ -120,7 +120,7 @@ namespace ARMeilleure.Translation
{
BasicBlock block = cfg.PostOrderBlocks[index];
if (block.Predecessors.Count != 0)
if (block.Predecessors.Count != 0 && !HasContextLoad(block))
{
BasicBlock predecessor = block.Predecessors[0];
@ -194,15 +194,29 @@ namespace ARMeilleure.Translation
//Insert load and store context instructions where needed.
foreach (BasicBlock block in cfg.Blocks)
{
bool hasContextLoad = HasContextLoad(block);
if (hasContextLoad)
{
block.Operations.RemoveFirst();
}
//The only block without any predecessor should be the entry block.
//It always needs a context load as it is the first block to run.
if (block.Predecessors.Count == 0)
if (block.Predecessors.Count == 0 || hasContextLoad)
{
LoadLocals(block, globalInputs[block.Index].VecMask, RegisterType.Vector);
LoadLocals(block, globalInputs[block.Index].IntMask, RegisterType.Integer);
}
if (HasContextStore(block))
bool hasContextStore = HasContextStore(block);
if (hasContextStore)
{
block.Operations.RemoveLast();
}
if (EndsWithReturn(block) || hasContextStore)
{
StoreLocals(block, globalOutputs[block.Index].IntMask, RegisterType.Integer);
StoreLocals(block, globalOutputs[block.Index].VecMask, RegisterType.Vector);
@ -210,6 +224,36 @@ namespace ARMeilleure.Translation
}
}
private static bool HasContextLoad(BasicBlock block)
{
return StartsWith(block, Instruction.LoadFromContext) && block.Operations.First.Value.SourcesCount == 0;
}
private static bool HasContextStore(BasicBlock block)
{
return EndsWith(block, Instruction.StoreToContext) && block.GetLastOp().SourcesCount == 0;
}
private static bool StartsWith(BasicBlock block, Instruction inst)
{
if (block.Operations.Count == 0)
{
return false;
}
return block.Operations.First.Value is Operation operation && operation.Inst == inst;
}
private static bool EndsWith(BasicBlock block, Instruction inst)
{
if (block.Operations.Count == 0)
{
return false;
}
return block.Operations.Last.Value is Operation operation && operation.Inst == inst;
}
private static RegisterMask GetMask(Register register)
{
long intMask = 0;
@ -316,7 +360,7 @@ namespace ARMeilleure.Translation
throw new ArgumentException($"Invalid register type \"{type}\".");
}
private static bool HasContextStore(BasicBlock block)
private static bool EndsWithReturn(BasicBlock block)
{
if (!(block.GetLastOp() is Operation operation))
{

View file

@ -67,17 +67,6 @@ namespace ARMeilleure.Translation
{
Operand local = localDefs[GetIdFromRegister(operand.GetRegister())];
if (local != null && local.Type != operand.Type)
{
Operand temp = Local(operand.Type);
Operation castOp = new Operation(Instruction.Copy, temp, local);
block.Operations.AddBefore(node, castOp);
local = temp;
}
operand = local ?? operand;
}
@ -158,17 +147,6 @@ namespace ARMeilleure.Translation
localDefs[key] = local;
}
if (local.Kind == OperandKind.LocalVariable && local.Type != operand.Type)
{
Operand temp = Local(operand.Type);
Operation castOp = new Operation(Instruction.Copy, temp, local);
block.Operations.AddBefore(node, castOp);
local = temp;
}
operand = local;
}

View file

@ -6,6 +6,8 @@ using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Memory;
using ARMeilleure.State;
using System;
using System.Collections.Concurrent;
using System.Reflection;
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
@ -17,11 +19,15 @@ namespace ARMeilleure.Translation
private TranslatedCache _cache;
private ConcurrentDictionary<ulong, TranslatedFunction> _funcs;
public Translator(MemoryManager memory)
{
_memory = memory;
_cache = new TranslatedCache();
_funcs = new ConcurrentDictionary<ulong, TranslatedFunction>();
}
public void Execute(ExecutionContext context, ulong address)
@ -30,15 +36,37 @@ namespace ARMeilleure.Translation
do
{
TranslatedFunction func = Translate(address, ExecutionMode.Aarch64);
address = func.Execute(context);
address = ExecuteSingle(context, address);
}
while (address != 0);
while (context.Running && address != 0);
NativeInterface.UnregisterThread();
}
public void SelfRegister(ExecutionContext context)
{
NativeInterface.RegisterThread(context, _memory);
}
public ulong ExecuteSingle(ExecutionContext context, ulong address)
{
TranslatedFunction func = GetOrTranslate(address, ExecutionMode.Aarch64);
return func.Execute(context);
}
private TranslatedFunction GetOrTranslate(ulong address, ExecutionMode mode)
{
if (!_funcs.TryGetValue(address, out TranslatedFunction func))
{
func = Translate(address, mode);
_funcs.TryAdd(address, func);
}
return func;
}
private TranslatedFunction Translate(ulong address, ExecutionMode mode)
{
EmitterContext context = new EmitterContext();
@ -47,9 +75,16 @@ namespace ARMeilleure.Translation
Block[] blocks = Decoder.DecodeFunction(_memory, address, ExecutionMode.Aarch64);
EmitSynchronization(context);
if (blocks[0].Address != address)
{
context.Branch(context.GetLabel(address));
}
ControlFlowGraph cfg = EmitAndGetCFG(context, blocks);
RegisterUsage.InsertContext(cfg);
RegisterUsage.RunPass(cfg);
Dominance.FindDominators(cfg);
@ -86,7 +121,7 @@ namespace ARMeilleure.Translation
if (isLastOp && block.Branch != null && block.Branch.Address <= block.Address)
{
context.Synchronize();
EmitSynchronization(context);
}
Operand lblPredicateSkip = null;
@ -126,5 +161,26 @@ namespace ARMeilleure.Translation
return context.GetControlFlowGraph();
}
private static void EmitSynchronization(EmitterContext context)
{
int cntOffset = NativeContext.GetCounterOffset();
Operand count = context.LoadFromContext(cntOffset);
Operand lblNonZero = Label();
context.BranchIfTrue(lblNonZero, count);
MethodInfo info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.CheckSynchronization));
context.Call(info);
context.MarkLabel(lblNonZero);
count = context.Subtract(count, Const(1));
context.StoreToContext(cntOffset, count);
}
}
}