Misc. fixes and integrate LDj3SNuD fixes

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

View file

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

View file

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

View file

@ -201,17 +201,28 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
int selectedNextUse = freePositions[selectedReg]; 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; return false;
} }
else if (selectedNextUse < current.GetEnd()) 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(selectedNextUse);
LiveInterval splitChild = current.Split(splitPosition);
if (splitChild.UsesCount != 0) if (splitChild.UsesCount != 0)
{ {
@ -340,7 +351,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
//so spill the current interval. //so spill the current interval.
Debug.Assert(currentFirstUse > current.GetStart(), "Trying to spill a interval currently being used."); 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."); 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. //the first fixed register use.
current.Register = new Register(selectedReg, regType); 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) if (splitChild.UsesCount != 0)
{ {
@ -457,7 +472,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
if (interval.GetStart() < current.GetStart()) if (interval.GetStart() < current.GetStart())
{ {
splitChild = interval.Split(GetSplitPosition(current.GetStart())); splitChild = interval.Split(current.GetStart());
} }
else else
{ {
@ -468,28 +483,17 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{ {
Debug.Assert(nextUse > current.GetStart(), "Trying to spill a interval currently being used."); 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); Spill(context, splitChild);
Debug.Assert(right.GetStart() > current.GetStart(), "Split interval has an invalid start position."); splitChild = right;
InsertInterval(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 else
{ {
Spill(context, splitChild); Spill(context, splitChild);
@ -502,7 +506,9 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
Debug.Assert(!interval.IsEmpty, "Trying to insert a empty interval."); Debug.Assert(!interval.IsEmpty, "Trying to insert a empty interval.");
Debug.Assert(!interval.IsSpilled, "Trying to insert a spilled interval."); Debug.Assert(!interval.IsSpilled, "Trying to insert a spilled interval.");
int insertIndex = _intervals.BinarySearch(interval); int startIndex = RegistersCount * 2;
int insertIndex = _intervals.BinarySearch(startIndex, _intervals.Count - startIndex, interval, null);
if (insertIndex < 0) if (insertIndex < 0)
{ {
@ -550,9 +556,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{ {
int splitPosition = splitChild.GetStart(); int splitPosition = splitChild.GetStart();
int alignedSplitPosition = GetAlignedSplitPosition(splitPosition); if (!_blockEdges.Contains(splitPosition) && previous.GetEnd() == splitPosition)
if (!_blockEdges.Contains(alignedSplitPosition) && previous.GetEnd() == splitPosition)
{ {
GetCopyResolver(splitPosition).AddSplit(previous, splitChild); GetCopyResolver(splitPosition).AddSplit(previous, splitChild);
} }
@ -576,7 +580,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
Operation[] sequence = copyResolver.Sequence(); 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++) for (int index = 1; index < sequence.Length; index++)
{ {
@ -627,13 +631,13 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
continue; continue;
} }
int lEnd = _blockRanges[block.Index].End - InstructionGap; int lEnd = _blockRanges[block.Index].End - 1;
int rStart = _blockRanges[succIndex].Start; int rStart = _blockRanges[succIndex].Start;
LiveInterval left = interval.GetSplitChild(lEnd); LiveInterval left = interval.GetSplitChild(lEnd);
LiveInterval right = interval.GetSplitChild(rStart); LiveInterval right = interval.GetSplitChild(rStart);
if (left != right) if (left != null && right != null && left != right)
{ {
copyResolver.AddSplit(left, right); copyResolver.AddSplit(left, right);
} }
@ -705,10 +709,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
private static Operand GetRegister(LiveInterval interval) private static Operand GetRegister(LiveInterval interval)
{ {
if (interval.IsSpilled) Debug.Assert(!interval.IsSpilled, "Spilled intervals are not allowed.");
{
throw new ArgumentException("Spilled intervals are not allowed.");
}
return new Operand( return new Operand(
interval.Register.Index, interval.Register.Index,
@ -716,16 +717,6 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
interval.Local.Type); 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) private LinkedListNode<Node> GetOperationNode(int position)
{ {
return _operationNodes[position / InstructionGap]; return _operationNodes[position / InstructionGap];
@ -768,6 +759,14 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
} }
_operationsCount += block.Operations.Count * InstructionGap; _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(); _parentIntervals = _intervals.ToArray();
@ -860,14 +859,12 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{ {
BasicBlock block = cfg.PostOrderBlocks[index]; BasicBlock block = cfg.PostOrderBlocks[index];
if (block.Operations.Count == 0) //We handle empty blocks by pretending they have a dummy instruction,
{ //because otherwise the block would have the same start and end position,
_blockRanges[block.Index] = new LiveRange(operationPos, operationPos + InstructionGap); //and this is not valid.
int instCount = Math.Max(block.Operations.Count, 1);
continue; int blockStart = operationPos - instCount * InstructionGap;
}
int blockStart = operationPos - block.Operations.Count * InstructionGap;
int blockEnd = operationPos; int blockEnd = operationPos;
_blockRanges[block.Index] = new LiveRange(blockStart, blockEnd); _blockRanges[block.Index] = new LiveRange(blockStart, blockEnd);
@ -881,25 +878,32 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
_intervals[id].AddRange(blockStart, blockEnd); _intervals[id].AddRange(blockStart, blockEnd);
} }
foreach (Node node in BottomOperations(block)) if (block.Operations.Count == 0)
{ {
operationPos -= InstructionGap; operationPos -= InstructionGap;
foreach (Operand source in Operands(node)) continue;
{
LiveInterval interval = _intervals[GetOperandId(source)];
interval.AddRange(blockStart, operationPos);
interval.AddUsePosition(operationPos);
} }
foreach (Node node in BottomOperations(block))
{
operationPos -= InstructionGap;
Operand dest = node.Dest; Operand dest = node.Dest;
if (dest != null && IsLocalOrRegister(dest.Kind)) if (dest != null && IsLocalOrRegister(dest.Kind))
{ {
LiveInterval interval = _intervals[GetOperandId(dest)]; 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); interval.AddUsePosition(operationPos);
} }
@ -937,7 +941,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
LiveInterval interval = _intervals[GetRegisterId(callerSavedReg)]; LiveInterval interval = _intervals[GetRegisterId(callerSavedReg)];
interval.AddRange(operationPos, operationPos + 1); interval.AddRange(operationPos + 1, operationPos + InstructionGap);
mask &= ~(1 << regIndex); mask &= ~(1 << regIndex);
} }

View file

@ -73,11 +73,13 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{ {
if (_ranges.Count != 0) if (_ranges.Count != 0)
{ {
Debug.Assert(position != _ranges[0].End);
_ranges[0] = new LiveRange(position, _ranges[0].End); _ranges[0] = new LiveRange(position, _ranges[0].End);
} }
else 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) 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)); int index = _ranges.BinarySearch(new LiveRange(start, end));
if (index >= 0) if (index >= 0)
@ -329,27 +336,19 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
public LiveInterval GetSplitChild(int position) public LiveInterval GetSplitChild(int position)
{ {
//Try to find the interval among the split intervals that if (Overlaps(position))
//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--)
{ {
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; return splitChild;
} }
} }
if (position >= GetStart() && position <= GetEnd())
{
return this;
}
return null; return null;
} }

View file

@ -8,38 +8,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
{ {
static class PhiFunctions 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) 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) foreach (BasicBlock block in cfg.Blocks)
{ {
LinkedListNode<Node> node = block.Operations.First; LinkedListNode<Node> node = block.Operations.First;
@ -50,19 +20,14 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
Operand local = Local(phi.Dest.Type); 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++) 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); 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

@ -16,9 +16,11 @@ namespace ARMeilleure.CodeGen.X86
{ {
None = 0, None = 0,
RegOnly = 1 << 0, RegOnly = 1 << 0,
Reg8 = 1 << 1, Reg8Src = 1 << 1,
NoRexW = 1 << 2, Reg8Dest = 1 << 2,
Vex = 1 << 3, NoRexW = 1 << 3,
RexW = 1 << 4,
Vex = 1 << 5,
PrefixBit = 16, PrefixBit = 16,
PrefixMask = 3 << PrefixBit, PrefixMask = 3 << PrefixBit,
@ -64,182 +66,182 @@ namespace ARMeilleure.CodeGen.X86
// Name RM/R RM/I8 RM/I32 R/I64 R/RM Flags // Name RM/R RM/I8 RM/I32 R/I64 R/RM Flags
Add(X86Instruction.Add, new InstInfo(0x00000001, 0x00000083, 0x00000081, BadOp, 0x00000003, InstFlags.None)); 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.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)); 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.PrefixF2)); 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.PrefixF3)); 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.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.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)); 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.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.Call, new InstInfo(0x020000ff, BadOp, BadOp, BadOp, BadOp, InstFlags.NoRexW));
Add(X86Instruction.Cmovcc, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f40, InstFlags.None)); 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.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.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)); 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.PrefixF2)); 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.PrefixF3)); 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.Prefix66)); 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)); 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.PrefixF3)); 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)); 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.PrefixF2)); 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.Prefix66)); 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.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)); 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.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.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.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.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.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)); 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.PrefixF2)); 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.PrefixF3)); 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.Prefix66)); 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.PrefixF2)); 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.Idiv, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x070000f7, InstFlags.None));
Add(X86Instruction.Imul, new InstInfo(BadOp, 0x0000006b, 0x00000069, BadOp, 0x00000faf, 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.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.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.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)); 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.PrefixF2)); 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.PrefixF3)); 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.Prefix66)); 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)); 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.PrefixF2)); 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.PrefixF3)); 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.Mov, new InstInfo(0x00000089, BadOp, 0x000000c7, 0x000000b8, 0x0000008b, InstFlags.None));
Add(X86Instruction.Mov16, new InstInfo(0x00000089, BadOp, 0x000000c7, BadOp, 0x0000008b, InstFlags.Prefix66)); 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.Mov8, new InstInfo(0x00000088, 0x000000c6, BadOp, BadOp, 0x0000008a, InstFlags.Reg8Src | InstFlags.Reg8Dest));
Add(X86Instruction.Movd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f6e, InstFlags.Vex | InstFlags.Prefix66)); 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.PrefixF3)); 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)); 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)); 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.PrefixF3)); 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.PrefixF2)); 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.PrefixF3)); 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.Movsx16, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fbf, InstFlags.None));
Add(X86Instruction.Movsx32, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000063, 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.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.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.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)); 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.PrefixF2)); 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.PrefixF3)); 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.Neg, new InstInfo(0x030000f7, BadOp, BadOp, BadOp, BadOp, InstFlags.None));
Add(X86Instruction.Not, new InstInfo(0x020000f7, 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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.Pop, new InstInfo(0x0000008f, BadOp, BadOp, BadOp, BadOp, InstFlags.None));
Add(X86Instruction.Popcnt, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fb8, InstFlags.PrefixF3)); 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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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.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)); 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.PrefixF3)); 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.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.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.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.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.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)); 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.PrefixF3)); 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.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.Shl, new InstInfo(0x040000d3, 0x040000c1, BadOp, BadOp, BadOp, InstFlags.None));
Add(X86Instruction.Shr, new InstInfo(0x050000d3, 0x050000c1, 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.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)); 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.Prefix66)); 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)); 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.PrefixF2)); 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.PrefixF3)); 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.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.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)); 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.PrefixF2)); 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.PrefixF3)); 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.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.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)); 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.Prefix66)); 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)); 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.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.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)); Add(X86Instruction.Xorps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f57, InstFlags.Vex | InstFlags.NoRexW));
} }
private static void Add(X86Instruction inst, InstInfo info) private static void Add(X86Instruction inst, InstInfo info)
@ -615,7 +617,16 @@ namespace ARMeilleure.CodeGen.X86
public void Movd(Operand dest, Operand source) 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) public void Movdqu(Operand dest, Operand source)
@ -1411,7 +1422,7 @@ namespace ARMeilleure.CodeGen.X86
modRM |= (regIndex & 0b111) << (rrm ? 3 : 0); modRM |= (regIndex & 0b111) << (rrm ? 3 : 0);
if ((flags & InstFlags.Reg8) != 0 && regIndex >= 4) if ((flags & InstFlags.Reg8Dest) != 0 && regIndex >= 4)
{ {
rexPrefix |= 0x40; rexPrefix |= 0x40;
} }
@ -1430,7 +1441,14 @@ namespace ARMeilleure.CodeGen.X86
{ {
if (source.Kind == OperandKind.Register) 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) 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) if ((opCode & 0xff0000) != 0)
{ {
WriteByte((byte)(opCode >> 16)); WriteByte((byte)(opCode >> 16));
@ -1642,7 +1665,7 @@ namespace ARMeilleure.CodeGen.X86
if (dest != null) if (dest != null)
{ {
if (dest.Type == OperandType.I64 && rexW) if (Is64Bits(dest.Type) && rexW)
{ {
rexPrefix = 0x48; rexPrefix = 0x48;
} }
@ -1655,7 +1678,7 @@ namespace ARMeilleure.CodeGen.X86
if (source != null) if (source != null)
{ {
if (source.Type == OperandType.I64 && rexW) if (Is64Bits(source.Type) && rexW)
{ {
rexPrefix |= 0x48; rexPrefix |= 0x48;
} }
@ -1671,8 +1694,12 @@ namespace ARMeilleure.CodeGen.X86
private static bool IsR64(Operand operand) private static bool IsR64(Operand operand)
{ {
return operand.Kind == OperandKind.Register && return operand.Kind == OperandKind.Register && operand.Type == OperandType.I64;
operand.Type == OperandType.I64; }
private static bool Is64Bits(OperandType type)
{
return type == OperandType.I64 || type == OperandType.FP64;
} }
private static bool IsImm8(Operand operand) 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 //The ABI mandates that the space for at least 4 arguments
//is reserved on the stack (this is called shadow space). //is reserved on the stack (this is called shadow space).
if (argsCount < 4 && argsCount != 0) if (argsCount < 4 && maxCallArgs != -1)
{ {
argsCount = 4; argsCount = 4;
} }

View file

@ -40,6 +40,7 @@ namespace ARMeilleure.CodeGen.X86
Add(Instruction.CompareLessUI, GenerateCompareLessUI); Add(Instruction.CompareLessUI, GenerateCompareLessUI);
Add(Instruction.CompareNotEqual, GenerateCompareNotEqual); Add(Instruction.CompareNotEqual, GenerateCompareNotEqual);
Add(Instruction.ConditionalSelect, GenerateConditionalSelect); Add(Instruction.ConditionalSelect, GenerateConditionalSelect);
Add(Instruction.ConvertI64ToI32, GenerateConvertI64ToI32);
Add(Instruction.ConvertToFP, GenerateConvertToFP); Add(Instruction.ConvertToFP, GenerateConvertToFP);
Add(Instruction.Copy, GenerateCopy); Add(Instruction.Copy, GenerateCopy);
Add(Instruction.CountLeadingZeros, GenerateCountLeadingZeros); Add(Instruction.CountLeadingZeros, GenerateCountLeadingZeros);
@ -79,9 +80,13 @@ namespace ARMeilleure.CodeGen.X86
Add(Instruction.VectorInsert, GenerateVectorInsert); Add(Instruction.VectorInsert, GenerateVectorInsert);
Add(Instruction.VectorInsert16, GenerateVectorInsert16); Add(Instruction.VectorInsert16, GenerateVectorInsert16);
Add(Instruction.VectorInsert8, GenerateVectorInsert8); Add(Instruction.VectorInsert8, GenerateVectorInsert8);
Add(Instruction.VectorOne, GenerateVectorOne);
Add(Instruction.VectorZero, GenerateVectorZero); Add(Instruction.VectorZero, GenerateVectorZero);
Add(Instruction.VectorZeroUpper64, GenerateVectorZeroUpper64); Add(Instruction.VectorZeroUpper64, GenerateVectorZeroUpper64);
Add(Instruction.VectorZeroUpper96, GenerateVectorZeroUpper96); Add(Instruction.VectorZeroUpper96, GenerateVectorZeroUpper96);
Add(Instruction.ZeroExtend16, GenerateZeroExtend16);
Add(Instruction.ZeroExtend32, GenerateZeroExtend32);
Add(Instruction.ZeroExtend8, GenerateZeroExtend8);
Add(Instruction.X86Addpd, GenerateX86Addpd); Add(Instruction.X86Addpd, GenerateX86Addpd);
Add(Instruction.X86Addps, GenerateX86Addps); Add(Instruction.X86Addps, GenerateX86Addps);
Add(Instruction.X86Addsd, GenerateX86Addsd); Add(Instruction.X86Addsd, GenerateX86Addsd);
@ -227,7 +232,7 @@ namespace ARMeilleure.CodeGen.X86
Optimizer.RunPass(cfg); Optimizer.RunPass(cfg);
Logger.EndPass(PassName.Optimization); Logger.EndPass(PassName.Optimization, cfg);
Logger.StartPass(PassName.PreAllocation); Logger.StartPass(PassName.PreAllocation);
@ -323,8 +328,15 @@ namespace ARMeilleure.CodeGen.X86
{ {
ValidateDestSrc1(operation); ValidateDestSrc1(operation);
if (operation.Dest.Type.IsInteger())
{
context.Assembler.Xor(operation.Dest, operation.GetSource(1)); 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) 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); 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) private static void GenerateConvertToFP(CodeGenContext context, Operation operation)
{ {
Operand dest = operation.Dest; Operand dest = operation.Dest;
@ -486,25 +506,10 @@ namespace ARMeilleure.CodeGen.X86
context.Assembler.Xor(dest, dest); 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) else if (dest.GetRegister().Type == RegisterType.Vector)
{ {
if (source.GetRegister().Type == RegisterType.Integer) if (source.GetRegister().Type == RegisterType.Integer)
{ {
//FIXME.
context.Assembler.Movd(dest, source); context.Assembler.Movd(dest, source);
} }
else else
@ -512,6 +517,10 @@ namespace ARMeilleure.CodeGen.X86
context.Assembler.Movdqu(dest, source); context.Assembler.Movdqu(dest, source);
} }
} }
else if (dest.Type == OperandType.I32 && source.Kind == OperandKind.Register)
{
context.Assembler.Mov(dest, Get32BitsRegister(source.GetRegister()));
}
else else
{ {
context.Assembler.Mov(dest, source); context.Assembler.Mov(dest, source);
@ -614,13 +623,25 @@ namespace ARMeilleure.CodeGen.X86
Operand value = operation.Dest; Operand value = operation.Dest;
Operand address = GetMemoryOperand(operation.GetSource(0), value.Type); Operand address = GetMemoryOperand(operation.GetSource(0), value.Type);
if (value.GetRegister().Type == RegisterType.Integer) switch (value.Type)
{ {
case OperandType.I32:
case OperandType.I64:
context.Assembler.Mov(value, address); context.Assembler.Mov(value, address);
} break;
else
{ case OperandType.FP32:
case OperandType.FP64:
context.Assembler.Movd(value, address);
break;
case OperandType.V128:
context.Assembler.Movdqu(value, address); 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 value = operation.GetSource(1);
Operand address = GetMemoryOperand(operation.GetSource(0), value.Type); Operand address = GetMemoryOperand(operation.GetSource(0), value.Type);
if (value.GetRegister().Type == RegisterType.Integer) switch (value.Type)
{ {
case OperandType.I32:
case OperandType.I64:
context.Assembler.Mov(address, value); context.Assembler.Mov(address, value);
} break;
else
{ case OperandType.FP32:
case OperandType.FP64:
context.Assembler.Movd(address, value);
break;
case OperandType.V128:
context.Assembler.Movdqu(address, value); 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); 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) private static void GenerateVectorZero(CodeGenContext context, Operation operation)
{ {
context.Assembler.Xorps(operation.Dest, operation.Dest, operation.Dest); context.Assembler.Xorps(operation.Dest, operation.Dest, operation.Dest);
@ -1032,6 +1070,23 @@ namespace ARMeilleure.CodeGen.X86
ZeroUpper96(context, operation.Dest, operation.GetSource(0)); 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) private static void GenerateX86Addpd(CodeGenContext context, Operation operation)
{ {
context.Assembler.Addpd(operation.Dest, operation.GetSource(1), operation.GetSource(0)); 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) public static void RunPass(ControlFlowGraph cfg, MemoryManager memory, out int maxCallArgs)
{ {
maxCallArgs = 0; maxCallArgs = -1;
foreach (BasicBlock block in cfg.Blocks) foreach (BasicBlock block in cfg.Blocks)
{ {
@ -200,16 +200,18 @@ namespace ARMeilleure.CodeGen.X86
//-- Then, we need to add the least significant bit that was shifted out. //-- Then, we need to add the least significant bit that was shifted out.
//--- We can convert the least significant bit to float, and add it to the result. //--- We can convert the least significant bit to float, and add it to the result.
Operand lsb = Local(OperandType.I64); Operand lsb = Local(OperandType.I64);
Operand half = Local(OperandType.I64);
Operand lsbF = Local(dest.Type); 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.BitwiseAnd, lsb, lsb, Const(1L)));
temp = nodes.AddAfter(temp, new Operation(Instruction.ShiftRightUI, source, source, Const(1))); 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, 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, dest));
temp = nodes.AddAfter(temp, new Operation(Instruction.Add, dest, dest, lsbF)); temp = nodes.AddAfter(temp, new Operation(Instruction.Add, dest, dest, lsbF));
@ -232,7 +234,7 @@ namespace ARMeilleure.CodeGen.X86
Operand res = Local(dest.Type); 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) if (dest.Type == OperandType.FP32)
{ {

View file

@ -19,6 +19,15 @@ namespace ARMeilleure.Decoders
_opActivators = new ConcurrentDictionary<Type, MakeOp>(); _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) public static Block[] DecodeFunction(MemoryManager memory, ulong address, ExecutionMode mode)
{ {
List<Block> blocks = new List<Block>(); 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("0100111000101000011010xxxxxxxxxx", InstName.Aesmc_V, InstEmit.Aesmc_V, typeof(OpCodeSimd));
SetA64("0x001110001xxxxx000111xxxxxxxxxx", InstName.And_V, InstEmit.And_V, typeof(OpCodeSimdReg)); SetA64("0x001110001xxxxx000111xxxxxxxxxx", InstName.And_V, InstEmit.And_V, typeof(OpCodeSimdReg));
SetA64("0x001110011xxxxx000111xxxxxxxxxx", InstName.Bic_V, InstEmit.Bic_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("0x101110111xxxxx000111xxxxxxxxxx", InstName.Bif_V, InstEmit.Bif_V, typeof(OpCodeSimdReg));
SetA64("0x101110101xxxxx000111xxxxxxxxxx", InstName.Bit_V, InstEmit.Bit_V, typeof(OpCodeSimdReg)); SetA64("0x101110101xxxxx000111xxxxxxxxxx", InstName.Bit_V, InstEmit.Bit_V, typeof(OpCodeSimdReg));
SetA64("0x101110011xxxxx000111xxxxxxxxxx", InstName.Bsl_V, InstEmit.Bsl_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>0011101<1xxxxx110011xxxxxxxxxx", InstName.Fmls_V, InstEmit.Fmls_V, typeof(OpCodeSimdReg));
SetA64("0>0011111<xxxxxx0101x0xxxxxxxxxx", InstName.Fmls_Ve, InstEmit.Fmls_Ve, typeof(OpCodeSimdRegElemF)); SetA64("0>0011111<xxxxxx0101x0xxxxxxxxxx", InstName.Fmls_Ve, InstEmit.Fmls_Ve, typeof(OpCodeSimdRegElemF));
SetA64("000111100x100000010000xxxxxxxxxx", InstName.Fmov_S, InstEmit.Fmov_S, typeof(OpCodeSimd)); SetA64("000111100x100000010000xxxxxxxxxx", InstName.Fmov_S, InstEmit.Fmov_S, typeof(OpCodeSimd));
SetA64("00011110xx1xxxxxxxx100xxxxxxxxxx", InstName.Fmov_Si, InstEmit.Fmov_Si, typeof(OpCodeSimdFmov)); SetA64("000111100x1xxxxxxxx10000000xxxxx", InstName.Fmov_Si, InstEmit.Fmov_Si, typeof(OpCodeSimdFmov));
SetA64("0xx0111100000xxx111101xxxxxxxxxx", InstName.Fmov_V, InstEmit.Fmov_V, typeof(OpCodeSimdImm)); SetA64("0x00111100000xxx111101xxxxxxxxxx", InstName.Fmov_Vi, InstEmit.Fmov_Vi, typeof(OpCodeSimdImm));
SetA64("x00111100x100110000000xxxxxxxxxx", InstName.Fmov_Ftoi, InstEmit.Fmov_Ftoi, typeof(OpCodeSimdCvt)); SetA64("0110111100000xxx111101xxxxxxxxxx", InstName.Fmov_Vi, InstEmit.Fmov_Vi, typeof(OpCodeSimdImm));
SetA64("x00111100x100111000000xxxxxxxxxx", InstName.Fmov_Itof, InstEmit.Fmov_Itof, typeof(OpCodeSimdCvt)); SetA64("0001111000100110000000xxxxxxxxxx", InstName.Fmov_Ftoi, InstEmit.Fmov_Ftoi, typeof(OpCodeSimd));
SetA64("1001111010101110000000xxxxxxxxxx", InstName.Fmov_Ftoi1, InstEmit.Fmov_Ftoi1, typeof(OpCodeSimdCvt)); SetA64("1001111001100110000000xxxxxxxxxx", InstName.Fmov_Ftoi, InstEmit.Fmov_Ftoi, typeof(OpCodeSimd));
SetA64("1001111010101111000000xxxxxxxxxx", InstName.Fmov_Itof1, InstEmit.Fmov_Itof1, typeof(OpCodeSimdCvt)); 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("000111110x0xxxxx1xxxxxxxxxxxxxxx", InstName.Fmsub_S, InstEmit.Fmsub_S, typeof(OpCodeSimdReg));
SetA64("000111100x1xxxxx000010xxxxxxxxxx", InstName.Fmul_S, InstEmit.Fmul_S, typeof(OpCodeSimdReg)); SetA64("000111100x1xxxxx000010xxxxxxxxxx", InstName.Fmul_S, InstEmit.Fmul_S, typeof(OpCodeSimdReg));
SetA64("010111111xxxxxxx1001x0xxxxxxxxxx", InstName.Fmul_Se, InstEmit.Fmul_Se, typeof(OpCodeSimdRegElemF)); 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("0x10111000100000010110xxxxxxxxxx", InstName.Not_V, InstEmit.Not_V, typeof(OpCodeSimd));
SetA64("0x001110111xxxxx000111xxxxxxxxxx", InstName.Orn_V, InstEmit.Orn_V, typeof(OpCodeSimdReg)); SetA64("0x001110111xxxxx000111xxxxxxxxxx", InstName.Orn_V, InstEmit.Orn_V, typeof(OpCodeSimdReg));
SetA64("0x001110101xxxxx000111xxxxxxxxxx", InstName.Orr_V, InstEmit.Orr_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("0x101110<<1xxxxx010000xxxxxxxxxx", InstName.Raddhn_V, InstEmit.Raddhn_V, typeof(OpCodeSimdReg));
SetA64("0x10111001100000010110xxxxxxxxxx", InstName.Rbit_V, InstEmit.Rbit_V, typeof(OpCodeSimd)); SetA64("0x10111001100000010110xxxxxxxxxx", InstName.Rbit_V, InstEmit.Rbit_V, typeof(OpCodeSimd));
SetA64("0x00111000100000000110xxxxxxxxxx", InstName.Rev16_V, InstEmit.Rev16_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("0x101110<<100001001110xxxxxxxxxx", InstName.Shll_V, InstEmit.Shll_V, typeof(OpCodeSimd));
SetA64("0x00111100>>>xxx100001xxxxxxxxxx", InstName.Shrn_V, InstEmit.Shrn_V, typeof(OpCodeSimdShImm)); SetA64("0x00111100>>>xxx100001xxxxxxxxxx", InstName.Shrn_V, InstEmit.Shrn_V, typeof(OpCodeSimdShImm));
SetA64("0x001110<<1xxxxx001001xxxxxxxxxx", InstName.Shsub_V, InstEmit.Shsub_V, typeof(OpCodeSimdReg)); 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<<1xxxxx011001xxxxxxxxxx", InstName.Smax_V, InstEmit.Smax_V, typeof(OpCodeSimdReg));
SetA64("0x001110<<1xxxxx101001xxxxxxxxxx", InstName.Smaxp_V, InstEmit.Smaxp_V, typeof(OpCodeSimdReg)); SetA64("0x001110<<1xxxxx101001xxxxxxxxxx", InstName.Smaxp_V, InstEmit.Smaxp_V, typeof(OpCodeSimdReg));
SetA64("000011100x110000101010xxxxxxxxxx", InstName.Smaxv_V, InstEmit.Smaxv_V, typeof(OpCodeSimd)); SetA64("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, InstEmit.Und), typeof(OpCode));
return (new InstDescriptor(InstName.Und, null), typeof(OpCode));
} }
private static int ToFastLookupIndex(int value) 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) private static string GetOperandName(Operand operand, Dictionary<Operand, string> localNames)
{ {
if (operand == null)
{
return "<NULL>";
}
string name = string.Empty; string name = string.Empty;
if (operand.Kind == OperandKind.LocalVariable) if (operand.Kind == OperandKind.LocalVariable)

View file

@ -25,7 +25,7 @@ namespace ARMeilleure.Instructions
if (context.CurrOp.RegisterSize == RegisterSize.Int64) if (context.CurrOp.RegisterSize == RegisterSize.Int64)
{ {
carry = context.Copy(Local(OperandType.I64), carry); carry = context.ZeroExtend32(OperandType.I64, carry);
} }
d = context.Add(d, carry); d = context.Add(d, carry);
@ -107,7 +107,7 @@ namespace ARMeilleure.Instructions
{ {
OpCodeAlu op = (OpCodeAlu)context.CurrOp; OpCodeAlu op = (OpCodeAlu)context.CurrOp;
Operand n = GetIntOrZR(op, op.Rn); Operand n = GetIntOrZR(context, op.Rn);
Operand nHigh = context.ShiftRightUI(n, Const(1)); Operand nHigh = context.ShiftRightUI(n, Const(1));
@ -128,7 +128,7 @@ namespace ARMeilleure.Instructions
{ {
OpCodeAlu op = (OpCodeAlu)context.CurrOp; OpCodeAlu op = (OpCodeAlu)context.CurrOp;
Operand n = GetIntOrZR(op, op.Rn); Operand n = GetIntOrZR(context, op.Rn);
Operand d = context.CountLeadingZeros(n); Operand d = context.CountLeadingZeros(n);
@ -154,7 +154,7 @@ namespace ARMeilleure.Instructions
{ {
OpCodeAluRs op = (OpCodeAluRs)context.CurrOp; OpCodeAluRs op = (OpCodeAluRs)context.CurrOp;
Operand res = GetIntOrZR(op, op.Rm); Operand res = GetIntOrZR(context, op.Rm);
if (op.Shift != 0) if (op.Shift != 0)
{ {
@ -166,7 +166,7 @@ namespace ARMeilleure.Instructions
{ {
res = context.ShiftRightUI(res, Const(op.Shift)); 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; int invShift = op.GetBitsCount() - op.Shift;
@ -201,7 +201,7 @@ namespace ARMeilleure.Instructions
if (context.CurrOp.RegisterSize == RegisterSize.Int64) if (context.CurrOp.RegisterSize == RegisterSize.Int64)
{ {
borrow = context.Copy(Local(OperandType.I64), borrow); borrow = context.ZeroExtend32(OperandType.I64, borrow);
} }
d = context.Subtract(d, borrow); d = context.Subtract(d, borrow);
@ -264,7 +264,7 @@ namespace ARMeilleure.Instructions
{ {
OpCodeAlu op = (OpCodeAlu)context.CurrOp; OpCodeAlu op = (OpCodeAlu)context.CurrOp;
Operand n = GetIntOrZR(op, op.Rn); Operand n = GetIntOrZR(context, op.Rn);
if (op.RegisterSize == RegisterSize.Int32) if (op.RegisterSize == RegisterSize.Int32)
{ {
@ -280,7 +280,7 @@ namespace ARMeilleure.Instructions
{ {
OpCodeAlu op = (OpCodeAlu)context.CurrOp; OpCodeAlu op = (OpCodeAlu)context.CurrOp;
Operand n = GetIntOrZR(op, op.Rn); Operand n = GetIntOrZR(context, op.Rn);
Operand d; Operand d;
if (op.RegisterSize == RegisterSize.Int32) if (op.RegisterSize == RegisterSize.Int32)
@ -299,7 +299,7 @@ namespace ARMeilleure.Instructions
{ {
OpCodeAlu op = (OpCodeAlu)context.CurrOp; 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) public static void Rorv(EmitterContext context)
@ -311,11 +311,11 @@ namespace ARMeilleure.Instructions
{ {
IOpCodeAluRs op = (IOpCodeAluRs)context.CurrOp; IOpCodeAluRs op = (IOpCodeAluRs)context.CurrOp;
Operand m = GetIntOrZR(op, op.Rm); Operand m = GetIntOrZR(context, op.Rm);
if (op.RegisterSize == RegisterSize.Int64) 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)); return context.BitwiseAnd(m, Const(context.CurrOp.GetBitsCount() - 1));
@ -352,7 +352,7 @@ namespace ARMeilleure.Instructions
return; 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) if (op.DataOp == DataOp.Logical || op is IOpCodeAluRs)
{ {
return GetIntOrZR(op, op.Rn); return GetIntOrZR(context, op.Rn);
} }
else else
{ {
return GetIntOrSP(op, op.Rn); return GetIntOrSP(context, op.Rn);
} }
} }
else if (context.CurrOp is IOpCode32Alu op32) else if (context.CurrOp is IOpCode32Alu op32)
@ -128,7 +128,7 @@ namespace ARMeilleure.Instructions
case IOpCodeAluRs op: case IOpCodeAluRs op:
{ {
Operand value = GetIntOrZR(op, op.Rm); Operand value = GetIntOrZR(context, op.Rm);
switch (op.ShiftType) switch (op.ShiftType)
{ {

View file

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

View file

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

View file

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

View file

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

View file

@ -36,7 +36,7 @@ namespace ARMeilleure.Instructions
{ {
OpCodeBImmAl op = (OpCodeBImmAl)context.CurrOp; 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); EmitCall(context, (ulong)op.Immediate);
} }
@ -45,9 +45,9 @@ namespace ARMeilleure.Instructions
{ {
OpCodeBReg op = (OpCodeBReg)context.CurrOp; 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); EmitVirtualCall(context, n);
} }
@ -56,7 +56,7 @@ namespace ARMeilleure.Instructions
{ {
OpCodeBReg op = (OpCodeBReg)context.CurrOp; 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); public static void Cbnz(EmitterContext context) => EmitCb(context, onNotZero: true);
@ -66,12 +66,12 @@ namespace ARMeilleure.Instructions
{ {
OpCodeBImmCmp op = (OpCodeBImmCmp)context.CurrOp; 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) 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); public static void Tbnz(EmitterContext context) => EmitTb(context, onNotZero: true);
@ -81,7 +81,7 @@ namespace ARMeilleure.Instructions
{ {
OpCodeBImmTest op = (OpCodeBImmTest)context.CurrOp; 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); EmitBranch(context, value, onNotZero);
} }

View file

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

View file

@ -3,6 +3,7 @@ using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.State; using ARMeilleure.State;
using ARMeilleure.Translation; using ARMeilleure.Translation;
using System; using System;
using System.Reflection;
using static ARMeilleure.IntermediateRepresentation.OperandHelper; using static ARMeilleure.IntermediateRepresentation.OperandHelper;
@ -17,37 +18,22 @@ namespace ARMeilleure.Instructions
public static Operand GetExtendedM(EmitterContext context, int rm, IntType type) public static Operand GetExtendedM(EmitterContext context, int rm, IntType type)
{ {
Operand value = GetIntOrZR(context.CurrOp, rm); Operand value = GetIntOrZR(context, rm);
switch (type) switch (type)
{ {
case IntType.UInt8: value = ZeroExtend8 (context, value); break; case IntType.UInt8: value = context.ZeroExtend8 (value.Type, value); break;
case IntType.UInt16: value = ZeroExtend16(context, value); break; case IntType.UInt16: value = context.ZeroExtend16(value.Type, value); break;
case IntType.UInt32: value = ZeroExtend32(context, value); break; case IntType.UInt32: value = context.ZeroExtend32(value.Type, value); break;
case IntType.Int8: value = context.SignExtend8 (value); break; case IntType.Int8: value = context.SignExtend8 (value.Type, value); break;
case IntType.Int16: value = context.SignExtend16(value); break; case IntType.Int16: value = context.SignExtend16(value.Type, value); break;
case IntType.Int32: value = context.SignExtend32(value); break; case IntType.Int32: value = context.SignExtend32(value.Type, value); break;
} }
return value; 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) public static Operand GetIntA32(EmitterContext context, int register)
{ {
if (register == RegisterAlias.Aarch32Pc) if (register == RegisterAlias.Aarch32Pc)
@ -58,7 +44,7 @@ namespace ARMeilleure.Instructions
} }
else 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) if (regIndex == RegisterConsts.ZeroIndex)
{ {
OperandType type = context.CurrOp.GetOperandType();
return type == OperandType.I32 ? Const(0) : Const(0L); return type == OperandType.I32 ? Const(0) : Const(0L);
} }
else 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) public static void SetIntOrZR(EmitterContext context, int regIndex, Operand value)
{ {
if (regIndex == RegisterConsts.ZeroIndex) if (regIndex == RegisterConsts.ZeroIndex)
@ -167,12 +155,31 @@ namespace ARMeilleure.Instructions
return; 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) public static Operand GetVec(int regIndex)

View file

@ -129,7 +129,7 @@ namespace ARMeilleure.Instructions
{ {
case OpCodeMemImm op: case OpCodeMemImm op:
{ {
address = context.Copy(GetIntOrSP(op, op.Rn)); address = context.Copy(GetIntOrSP(context, op.Rn));
//Pre-indexing. //Pre-indexing.
if (!op.PostIdx) if (!op.PostIdx)
@ -142,7 +142,7 @@ namespace ARMeilleure.Instructions
case OpCodeMemReg op: case OpCodeMemReg op:
{ {
Operand n = GetIntOrSP(op, op.Rn); Operand n = GetIntOrSP(context, op.Rn);
Operand m = GetExtendedM(context, op.Rm, op.IntType); Operand m = GetExtendedM(context, op.Rm, op.IntType);
@ -170,7 +170,7 @@ namespace ARMeilleure.Instructions
address = context.Add(address, Const(op.Immediate)); 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); EmitBarrier(context);
} }
Operand address = context.Copy(GetIntOrSP(op, op.Rn)); Operand address = context.Copy(GetIntOrSP(context, op.Rn));
if (pair) if (pair)
{ {
@ -71,9 +71,9 @@ namespace ARMeilleure.Instructions
{ {
Operand value = EmitLoad(context, address, exclusive, 3); 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)); Operand valueHigh = context.ShiftRightUI(value, Const(32));
@ -173,9 +173,9 @@ namespace ARMeilleure.Instructions
EmitBarrier(context); 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; Operand s = null;
@ -183,7 +183,7 @@ namespace ARMeilleure.Instructions
{ {
Debug.Assert(op.Size == 2 || op.Size == 3, "Invalid size for pairwise store."); 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; Operand value;
@ -221,7 +221,7 @@ namespace ARMeilleure.Instructions
{ {
if (size < 3) if (size < 3)
{ {
value = context.Copy(Local(OperandType.I32), value); value = context.ConvertI64ToI32(value);
} }
string fallbackMethodName = null; string fallbackMethodName = null;
@ -254,6 +254,8 @@ namespace ARMeilleure.Instructions
MethodInfo info = typeof(NativeInterface).GetMethod(fallbackMethodName); MethodInfo info = typeof(NativeInterface).GetMethod(fallbackMethodName);
context.Call(info, address, value);
return null; return null;
} }
} }

View file

@ -13,8 +13,6 @@ namespace ARMeilleure.Instructions
{ {
static class InstEmitMemoryHelper static class InstEmitMemoryHelper
{ {
private static bool ForceFallback = true;
private enum Extension private enum Extension
{ {
Zx, Zx,
@ -47,48 +45,31 @@ namespace ARMeilleure.Instructions
} }
if (isSimd) 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 else
{ {
EmitReadInt(context, address, rt, size); EmitReadInt(context, address, rt, size);
} }
}
if (!isSimd) if (!isSimd)
{ {
Operand value = GetT(context, rt); Operand value = GetIntOrZR(context, rt);
if (ext == Extension.Sx64)
{
value = context.Copy(Local(OperandType.I64), value);
}
if (ext == Extension.Sx32 || ext == Extension.Sx64) if (ext == Extension.Sx32 || ext == Extension.Sx64)
{ {
OperandType destType = ext == Extension.Sx64 ? OperandType.I64 : OperandType.I32;
switch (size) switch (size)
{ {
case 0: value = context.SignExtend8 (value); break; case 0: value = context.SignExtend8 (destType, value); break;
case 1: value = context.SignExtend16(value); break; case 1: value = context.SignExtend16(destType, value); break;
case 2: value = context.SignExtend32(value); break; case 2: value = context.SignExtend32(destType, value); break;
} }
} }
context.Copy(GetT(context, rt), value); SetIntOrZR(context, rt, value);
} }
} }
@ -99,16 +80,9 @@ namespace ARMeilleure.Instructions
int rt, int rt,
int elem, int elem,
int size) 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) public static void EmitStore(EmitterContext context, Operand address, int rt, int size)
{ {
@ -120,28 +94,14 @@ namespace ARMeilleure.Instructions
} }
if (isSimd) 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 else
{ {
EmitWriteInt(context, address, rt, size); EmitWriteInt(context, address, rt, size);
} }
} }
}
public static void EmitStoreSimd( public static void EmitStoreSimd(
EmitterContext context, EmitterContext context,
@ -149,16 +109,9 @@ namespace ARMeilleure.Instructions
int rt, int rt,
int elem, int elem,
int size) 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) private static bool IsSimd(EmitterContext context)
{ {
@ -197,7 +150,7 @@ namespace ARMeilleure.Instructions
case 3: value = context.Load (Local(OperandType.I64), physAddr); break; case 3: value = context.Load (Local(OperandType.I64), physAddr); break;
} }
context.Copy(GetT(context, rt), value); SetIntOrZR(context, rt, value);
context.MarkLabel(lblEnd); context.MarkLabel(lblEnd);
} }
@ -230,29 +183,39 @@ namespace ARMeilleure.Instructions
Operand value = null; 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: case 3:
{ value = context.VectorInsert(vector, context.Load(Local(OperandType.I64), physAddr), elem);
Type[] types = new Type[] { typeof(double*) }; break;
context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.LoadScalarVector128), types));
case 4:
value = context.Load(Local(OperandType.V128), physAddr);
break; break;
} }
case 4: context.EmitCall(typeof(Sse), nameof(Sse.LoadAlignedVector128)); break;
throw new InvalidOperationException($"Invalid vector load size of {1 << size} bytes.");
}*/
context.Copy(GetVec(rt), value); context.Copy(GetVec(rt), value);
context.MarkLabel(lblEnd); 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) private static void EmitWriteInt(EmitterContext context, Operand address, int rt, int size)
{ {
Operand isUnalignedAddr = EmitAddressCheck(context, address, size); Operand isUnalignedAddr = EmitAddressCheck(context, address, size);
@ -273,11 +236,11 @@ namespace ARMeilleure.Instructions
Operand physAddr = EmitPtPointerLoad(context, address, lblSlowPath); Operand physAddr = EmitPtPointerLoad(context, address, lblSlowPath);
Operand value = GetT(context, rt); Operand value = GetIntOrZR(context, rt);
if (size < 3) if (size < 3)
{ {
value = context.Copy(Local(OperandType.I32), value); value = context.ConvertI64ToI32(value);
} }
switch (size) switch (size)
@ -318,14 +281,28 @@ namespace ARMeilleure.Instructions
Operand value = GetVec(rt); Operand value = GetVec(rt);
/*switch (size) switch (size)
{ {
case 2: context.EmitCall(typeof(Sse), nameof(Sse.StoreScalar)); break; case 0:
case 3: context.EmitCall(typeof(Sse2), nameof(Sse2.StoreScalar)); break; context.Store8(physAddr, context.VectorExtract8(value, Local(OperandType.I32), elem));
case 4: context.EmitCall(typeof(Sse), nameof(Sse.StoreAligned)); break; 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); context.MarkLabel(lblEnd);
} }
@ -392,7 +369,7 @@ namespace ARMeilleure.Instructions
MethodInfo info = typeof(NativeInterface).GetMethod(fallbackMethodName); 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( private static void EmitReadVectorFallback(
@ -420,7 +397,7 @@ namespace ARMeilleure.Instructions
if (size < 3) if (size < 3)
{ {
value = context.Copy(Local(OperandType.I32), value); value = context.ConvertI64ToI32(value);
} }
switch (size) switch (size)
@ -448,11 +425,11 @@ namespace ARMeilleure.Instructions
MethodInfo info = typeof(NativeInterface).GetMethod(fallbackMethodName); MethodInfo info = typeof(NativeInterface).GetMethod(fallbackMethodName);
Operand value = GetT(context, rt); Operand value = GetIntOrZR(context, rt);
if (size < 3) if (size < 3)
{ {
value = context.Copy(Local(OperandType.I32), value); value = context.ConvertI64ToI32(value);
} }
context.Call(info, address, value); context.Call(info, address, value);
@ -499,32 +476,5 @@ namespace ARMeilleure.Instructions
context.Call(info, address, value); 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(); 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))); res = context.BitwiseAnd(res, Const(type, ~(0xffffL << op.Bit)));

View file

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

View file

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

View file

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

View file

@ -293,13 +293,13 @@ namespace ARMeilleure.Instructions
{ {
Operand ne = EmitVectorExtractZx(context, op.Rn, index, 0); 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)); MethodInfo info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.ReverseBits8));
Operand de = context.Call(info, ne); 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); res = EmitVectorInsert(context, res, de, index, 0);
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -10,10 +10,11 @@ namespace ARMeilleure.State
private const int IntSize = 8; private const int IntSize = 8;
private const int VecSize = 16; private const int VecSize = 16;
private const int FlagSize = 4; private const int FlagSize = 4;
private const int ExtraSize = 4;
private const int TotalSize = RegisterConsts.IntRegsCount * IntSize + private const int TotalSize = RegisterConsts.IntRegsCount * IntSize +
RegisterConsts.VecRegsCount * VecSize + RegisterConsts.VecRegsCount * VecSize +
RegisterConsts.FlagsCount * FlagSize; RegisterConsts.FlagsCount * FlagSize + ExtraSize;
public IntPtr BasePtr { get; } public IntPtr BasePtr { get; }
@ -99,6 +100,16 @@ namespace ARMeilleure.State
Marshal.WriteInt32(BasePtr, offset, value ? 1 : 0); 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) public static int GetRegisterOffset(Register reg)
{ {
if (reg.Type == RegisterType.Integer) 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() public void Dispose()
{ {
MemoryManagement.Free(BasePtr); MemoryManagement.Free(BasePtr);

View file

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

View file

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

View file

@ -5,6 +5,7 @@ using ARMeilleure.State;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using System.Runtime.CompilerServices;
using static ARMeilleure.IntermediateRepresentation.OperandHelper; using static ARMeilleure.IntermediateRepresentation.OperandHelper;
@ -93,6 +94,8 @@ namespace ARMeilleure.Translation
public Operand Call(MethodInfo info, params Operand[] callArgs) public Operand Call(MethodInfo info, params Operand[] callArgs)
{ {
RuntimeHelpers.PrepareMethod(info.MethodHandle);
long methodPtr = info.MethodHandle.GetFunctionPointer().ToInt64(); long methodPtr = info.MethodHandle.GetFunctionPointer().ToInt64();
Operand[] args = new Operand[callArgs.Length + 1]; Operand[] args = new Operand[callArgs.Length + 1];
@ -156,6 +159,11 @@ namespace ARMeilleure.Translation
return Add(Instruction.ConditionalSelect, Local(b.Type), a, b, c); 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) public Operand ConvertToFP(OperandType type, Operand a)
{ {
return Add(Instruction.ConvertToFP, Local(type), a); return Add(Instruction.ConvertToFP, Local(type), a);
@ -246,6 +254,30 @@ namespace ARMeilleure.Translation
return Add(Instruction.Load, value, address); 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) public Operand LoadSx16(Operand value, Operand address)
{ {
return Add(Instruction.LoadSx16, value, address); return Add(Instruction.LoadSx16, value, address);
@ -293,12 +325,20 @@ namespace ARMeilleure.Translation
public Operand Return() public Operand Return()
{ {
return Add(Instruction.Return); Operand returnValue = Add(Instruction.Return);
_needsNewBlock = true;
return returnValue;
} }
public Operand Return(Operand a) 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) public Operand RotateRight(Operand a, Operand b)
@ -321,19 +361,19 @@ namespace ARMeilleure.Translation
return Add(Instruction.ShiftRightUI, Local(a.Type), a, b); 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) public void Store(Operand address, Operand value)
@ -401,6 +441,21 @@ namespace ARMeilleure.Translation
return Add(Instruction.VectorZeroUpper96, Local(OperandType.V128), vector); 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) public Operand AddIntrinsic(Instruction inst, params Operand[] args)
{ {
return Add(inst, Local(OperandType.V128), args); return Add(inst, Local(OperandType.V128), args);
@ -444,11 +499,6 @@ namespace ARMeilleure.Translation
_needsNewBlock = true; _needsNewBlock = true;
} }
public void Synchronize()
{
}
public void MarkLabel(Operand label) public void MarkLabel(Operand label)
{ {
if (_irLabels.TryGetValue(label, out BasicBlock nextBlock)) 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. //Computer local register inputs and outputs used inside blocks.
RegisterMask[] localInputs = new RegisterMask[cfg.Blocks.Count]; RegisterMask[] localInputs = new RegisterMask[cfg.Blocks.Count];
@ -120,7 +120,7 @@ namespace ARMeilleure.Translation
{ {
BasicBlock block = cfg.PostOrderBlocks[index]; BasicBlock block = cfg.PostOrderBlocks[index];
if (block.Predecessors.Count != 0) if (block.Predecessors.Count != 0 && !HasContextLoad(block))
{ {
BasicBlock predecessor = block.Predecessors[0]; BasicBlock predecessor = block.Predecessors[0];
@ -194,15 +194,29 @@ namespace ARMeilleure.Translation
//Insert load and store context instructions where needed. //Insert load and store context instructions where needed.
foreach (BasicBlock block in cfg.Blocks) 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. //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. //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].VecMask, RegisterType.Vector);
LoadLocals(block, globalInputs[block.Index].IntMask, RegisterType.Integer); 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].IntMask, RegisterType.Integer);
StoreLocals(block, globalOutputs[block.Index].VecMask, RegisterType.Vector); 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) private static RegisterMask GetMask(Register register)
{ {
long intMask = 0; long intMask = 0;
@ -316,7 +360,7 @@ namespace ARMeilleure.Translation
throw new ArgumentException($"Invalid register type \"{type}\"."); 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)) if (!(block.GetLastOp() is Operation operation))
{ {

View file

@ -67,17 +67,6 @@ namespace ARMeilleure.Translation
{ {
Operand local = localDefs[GetIdFromRegister(operand.GetRegister())]; 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; operand = local ?? operand;
} }
@ -158,17 +147,6 @@ namespace ARMeilleure.Translation
localDefs[key] = local; 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; operand = local;
} }

View file

@ -6,6 +6,8 @@ using ARMeilleure.IntermediateRepresentation;
using ARMeilleure.Memory; using ARMeilleure.Memory;
using ARMeilleure.State; using ARMeilleure.State;
using System; using System;
using System.Collections.Concurrent;
using System.Reflection;
using static ARMeilleure.IntermediateRepresentation.OperandHelper; using static ARMeilleure.IntermediateRepresentation.OperandHelper;
@ -17,11 +19,15 @@ namespace ARMeilleure.Translation
private TranslatedCache _cache; private TranslatedCache _cache;
private ConcurrentDictionary<ulong, TranslatedFunction> _funcs;
public Translator(MemoryManager memory) public Translator(MemoryManager memory)
{ {
_memory = memory; _memory = memory;
_cache = new TranslatedCache(); _cache = new TranslatedCache();
_funcs = new ConcurrentDictionary<ulong, TranslatedFunction>();
} }
public void Execute(ExecutionContext context, ulong address) public void Execute(ExecutionContext context, ulong address)
@ -30,15 +36,37 @@ namespace ARMeilleure.Translation
do do
{ {
TranslatedFunction func = Translate(address, ExecutionMode.Aarch64); address = ExecuteSingle(context, address);
address = func.Execute(context);
} }
while (address != 0); while (context.Running && address != 0);
NativeInterface.UnregisterThread(); 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) private TranslatedFunction Translate(ulong address, ExecutionMode mode)
{ {
EmitterContext context = new EmitterContext(); EmitterContext context = new EmitterContext();
@ -47,9 +75,16 @@ namespace ARMeilleure.Translation
Block[] blocks = Decoder.DecodeFunction(_memory, address, ExecutionMode.Aarch64); 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); ControlFlowGraph cfg = EmitAndGetCFG(context, blocks);
RegisterUsage.InsertContext(cfg); RegisterUsage.RunPass(cfg);
Dominance.FindDominators(cfg); Dominance.FindDominators(cfg);
@ -86,7 +121,7 @@ namespace ARMeilleure.Translation
if (isLastOp && block.Branch != null && block.Branch.Address <= block.Address) if (isLastOp && block.Branch != null && block.Branch.Address <= block.Address)
{ {
context.Synchronize(); EmitSynchronization(context);
} }
Operand lblPredicateSkip = null; Operand lblPredicateSkip = null;
@ -126,5 +161,26 @@ namespace ARMeilleure.Translation
return context.GetControlFlowGraph(); 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);
}
} }
} }