Misc. fixes and integrate LDj3SNuD fixes
This commit is contained in:
parent
c306809b0b
commit
ba9ff58d94
45 changed files with 905 additions and 788 deletions
|
@ -1,6 +1,7 @@
|
|||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.Translation;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
|
||||
namespace ARMeilleure.CodeGen.Optimizations
|
||||
|
@ -61,8 +62,7 @@ namespace ARMeilleure.CodeGen.Optimizations
|
|||
|
||||
private static void PropagateCopy(Operation copyOp)
|
||||
{
|
||||
//Propagate copy source operand to all uses of
|
||||
//the destination operand.
|
||||
//Propagate copy source operand to all uses of the destination operand.
|
||||
Operand dest = copyOp.Dest;
|
||||
Operand source = copyOp.GetSource(0);
|
||||
|
||||
|
@ -86,35 +86,21 @@ namespace ARMeilleure.CodeGen.Optimizations
|
|||
//from all the use lists on the operands that this node uses.
|
||||
block.Operations.Remove(llNode);
|
||||
|
||||
Queue<Node> nodes = new Queue<Node>();
|
||||
Node node = llNode.Value;
|
||||
|
||||
nodes.Enqueue(llNode.Value);
|
||||
|
||||
while (nodes.TryDequeue(out Node node))
|
||||
for (int index = 0; index < node.SourcesCount; index++)
|
||||
{
|
||||
for (int index = 0; index < node.SourcesCount; index++)
|
||||
{
|
||||
Operand src = node.GetSource(index);
|
||||
|
||||
if (src.Kind != OperandKind.LocalVariable)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (src.Uses.Remove(node) && src.Uses.Count == 0)
|
||||
{
|
||||
foreach (Node assignment in src.Assignments)
|
||||
{
|
||||
nodes.Enqueue(assignment);
|
||||
}
|
||||
}
|
||||
}
|
||||
node.SetSource(index, null);
|
||||
}
|
||||
|
||||
Debug.Assert(node.Dest == null || node.Dest.Uses.Count == 0);
|
||||
|
||||
node.Dest = null;
|
||||
}
|
||||
|
||||
private static bool IsUnused(Node node)
|
||||
{
|
||||
return DestIsLocalVar(node) && node.Dest.Uses.Count == 0;
|
||||
return DestIsLocalVar(node) && node.Dest.Uses.Count == 0 && !HasSideEffects(node);
|
||||
}
|
||||
|
||||
private static bool DestIsLocalVar(Node node)
|
||||
|
@ -122,6 +108,11 @@ namespace ARMeilleure.CodeGen.Optimizations
|
|||
return node.Dest != null && node.Dest.Kind == OperandKind.LocalVariable;
|
||||
}
|
||||
|
||||
private static bool HasSideEffects(Node node)
|
||||
{
|
||||
return (node is Operation operation) && operation.Inst == Instruction.Call;
|
||||
}
|
||||
|
||||
private static bool IsPropagableCopy(Operation operation)
|
||||
{
|
||||
if (operation.Inst != Instruction.Copy)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.State;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
@ -100,6 +99,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
{
|
||||
OperandType type = types[copyDest];
|
||||
|
||||
type = type.IsInteger() ? OperandType.I64 : OperandType.V128;
|
||||
|
||||
EmitXorSwap(sequence, GetRegister(copyDest, type), GetRegister(copySource, type));
|
||||
|
||||
locations[origSource] = copyDest;
|
||||
|
|
|
@ -201,17 +201,28 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
int selectedNextUse = freePositions[selectedReg];
|
||||
|
||||
if (GetSplitPosition(selectedNextUse) <= current.GetStart())
|
||||
//Intervals starts and ends at odd positions, unless they span an entire
|
||||
//block, in this case they will have ranges at even position.
|
||||
//When a interval is loaded from the stack to a register, we can only
|
||||
//do the split at a odd position, because otherwise the split interval
|
||||
//that is inserted on the list to be processed may clobber a register
|
||||
//used by the instruction at the same position as the split.
|
||||
//The problem only happens when a interval ends exactly at this instruction,
|
||||
//because otherwise they would interfere, and the register wouldn't be selected.
|
||||
//When the interval is aligned and the above happens, there's no problem as
|
||||
//the instruction that is actually with the last use is the one
|
||||
//before that position.
|
||||
selectedNextUse &= ~InstructionGapMask;
|
||||
|
||||
if (selectedNextUse <= current.GetStart())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (selectedNextUse < current.GetEnd())
|
||||
{
|
||||
int splitPosition = GetSplitPosition(selectedNextUse);
|
||||
Debug.Assert(selectedNextUse > current.GetStart(), "Trying to split interval at the start.");
|
||||
|
||||
Debug.Assert(splitPosition > current.GetStart(), "Trying to split interval at the start.");
|
||||
|
||||
LiveInterval splitChild = current.Split(splitPosition);
|
||||
LiveInterval splitChild = current.Split(selectedNextUse);
|
||||
|
||||
if (splitChild.UsesCount != 0)
|
||||
{
|
||||
|
@ -340,7 +351,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
//so spill the current interval.
|
||||
Debug.Assert(currentFirstUse > current.GetStart(), "Trying to spill a interval currently being used.");
|
||||
|
||||
LiveInterval splitChild = current.Split(GetSplitPosition(currentFirstUse));
|
||||
LiveInterval splitChild = current.Split(currentFirstUse);
|
||||
|
||||
Debug.Assert(splitChild.GetStart() > current.GetStart(), "Split interval has an invalid start position.");
|
||||
|
||||
|
@ -365,7 +376,11 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
//the first fixed register use.
|
||||
current.Register = new Register(selectedReg, regType);
|
||||
|
||||
LiveInterval splitChild = current.Split(GetSplitPosition(blockedPositions[selectedReg]));
|
||||
int splitPosition = blockedPositions[selectedReg] & ~InstructionGapMask;
|
||||
|
||||
Debug.Assert(splitPosition > current.GetStart(), "Trying to split a interval at a invalid position.");
|
||||
|
||||
LiveInterval splitChild = current.Split(splitPosition);
|
||||
|
||||
if (splitChild.UsesCount != 0)
|
||||
{
|
||||
|
@ -457,7 +472,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
if (interval.GetStart() < current.GetStart())
|
||||
{
|
||||
splitChild = interval.Split(GetSplitPosition(current.GetStart()));
|
||||
splitChild = interval.Split(current.GetStart());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -468,27 +483,16 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
{
|
||||
Debug.Assert(nextUse > current.GetStart(), "Trying to spill a interval currently being used.");
|
||||
|
||||
if (GetSplitPosition(nextUse) > splitChild.GetStart())
|
||||
if (nextUse > splitChild.GetStart())
|
||||
{
|
||||
LiveInterval right = splitChild.Split(GetSplitPosition(nextUse));
|
||||
LiveInterval right = splitChild.Split(nextUse);
|
||||
|
||||
Spill(context, splitChild);
|
||||
|
||||
Debug.Assert(right.GetStart() > current.GetStart(), "Split interval has an invalid start position.");
|
||||
|
||||
InsertInterval(right);
|
||||
splitChild = right;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nextUse == splitChild.GetStart())
|
||||
{
|
||||
splitChild.SetStart(GetSplitPosition(nextUse));
|
||||
}
|
||||
|
||||
Debug.Assert(splitChild.GetStart() > current.GetStart(), "Split interval has an invalid start position.");
|
||||
|
||||
InsertInterval(splitChild);
|
||||
}
|
||||
InsertInterval(splitChild);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -502,7 +506,9 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
Debug.Assert(!interval.IsEmpty, "Trying to insert a empty interval.");
|
||||
Debug.Assert(!interval.IsSpilled, "Trying to insert a spilled interval.");
|
||||
|
||||
int insertIndex = _intervals.BinarySearch(interval);
|
||||
int startIndex = RegistersCount * 2;
|
||||
|
||||
int insertIndex = _intervals.BinarySearch(startIndex, _intervals.Count - startIndex, interval, null);
|
||||
|
||||
if (insertIndex < 0)
|
||||
{
|
||||
|
@ -550,9 +556,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
{
|
||||
int splitPosition = splitChild.GetStart();
|
||||
|
||||
int alignedSplitPosition = GetAlignedSplitPosition(splitPosition);
|
||||
|
||||
if (!_blockEdges.Contains(alignedSplitPosition) && previous.GetEnd() == splitPosition)
|
||||
if (!_blockEdges.Contains(splitPosition) && previous.GetEnd() == splitPosition)
|
||||
{
|
||||
GetCopyResolver(splitPosition).AddSplit(previous, splitChild);
|
||||
}
|
||||
|
@ -576,7 +580,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
Operation[] sequence = copyResolver.Sequence();
|
||||
|
||||
node = node.List.AddAfter(node, sequence[0]);
|
||||
node = node.List.AddBefore(node, sequence[0]);
|
||||
|
||||
for (int index = 1; index < sequence.Length; index++)
|
||||
{
|
||||
|
@ -627,13 +631,13 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
continue;
|
||||
}
|
||||
|
||||
int lEnd = _blockRanges[block.Index].End - InstructionGap;
|
||||
int lEnd = _blockRanges[block.Index].End - 1;
|
||||
int rStart = _blockRanges[succIndex].Start;
|
||||
|
||||
LiveInterval left = interval.GetSplitChild(lEnd);
|
||||
LiveInterval right = interval.GetSplitChild(rStart);
|
||||
|
||||
if (left != right)
|
||||
if (left != null && right != null && left != right)
|
||||
{
|
||||
copyResolver.AddSplit(left, right);
|
||||
}
|
||||
|
@ -705,10 +709,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
private static Operand GetRegister(LiveInterval interval)
|
||||
{
|
||||
if (interval.IsSpilled)
|
||||
{
|
||||
throw new ArgumentException("Spilled intervals are not allowed.");
|
||||
}
|
||||
Debug.Assert(!interval.IsSpilled, "Spilled intervals are not allowed.");
|
||||
|
||||
return new Operand(
|
||||
interval.Register.Index,
|
||||
|
@ -716,16 +717,6 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
interval.Local.Type);
|
||||
}
|
||||
|
||||
private static int GetSplitPosition(int position)
|
||||
{
|
||||
return (position & InstructionGapMask) == 0 ? position - 1 : position;
|
||||
}
|
||||
|
||||
private static int GetAlignedSplitPosition(int position)
|
||||
{
|
||||
return (position + InstructionGapMask) & ~InstructionGapMask;
|
||||
}
|
||||
|
||||
private LinkedListNode<Node> GetOperationNode(int position)
|
||||
{
|
||||
return _operationNodes[position / InstructionGap];
|
||||
|
@ -768,6 +759,14 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
}
|
||||
|
||||
_operationsCount += block.Operations.Count * InstructionGap;
|
||||
|
||||
if (block.Operations.Count == 0)
|
||||
{
|
||||
//Pretend we have a dummy instruction on the empty block.
|
||||
_operationNodes.Add(null);
|
||||
|
||||
_operationsCount += InstructionGap;
|
||||
}
|
||||
}
|
||||
|
||||
_parentIntervals = _intervals.ToArray();
|
||||
|
@ -860,14 +859,12 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
{
|
||||
BasicBlock block = cfg.PostOrderBlocks[index];
|
||||
|
||||
if (block.Operations.Count == 0)
|
||||
{
|
||||
_blockRanges[block.Index] = new LiveRange(operationPos, operationPos + InstructionGap);
|
||||
//We handle empty blocks by pretending they have a dummy instruction,
|
||||
//because otherwise the block would have the same start and end position,
|
||||
//and this is not valid.
|
||||
int instCount = Math.Max(block.Operations.Count, 1);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
int blockStart = operationPos - block.Operations.Count * InstructionGap;
|
||||
int blockStart = operationPos - instCount * InstructionGap;
|
||||
int blockEnd = operationPos;
|
||||
|
||||
_blockRanges[block.Index] = new LiveRange(blockStart, blockEnd);
|
||||
|
@ -881,17 +878,16 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
_intervals[id].AddRange(blockStart, blockEnd);
|
||||
}
|
||||
|
||||
foreach (Node node in BottomOperations(block))
|
||||
if (block.Operations.Count == 0)
|
||||
{
|
||||
operationPos -= InstructionGap;
|
||||
|
||||
foreach (Operand source in Operands(node))
|
||||
{
|
||||
LiveInterval interval = _intervals[GetOperandId(source)];
|
||||
continue;
|
||||
}
|
||||
|
||||
interval.AddRange(blockStart, operationPos);
|
||||
interval.AddUsePosition(operationPos);
|
||||
}
|
||||
foreach (Node node in BottomOperations(block))
|
||||
{
|
||||
operationPos -= InstructionGap;
|
||||
|
||||
Operand dest = node.Dest;
|
||||
|
||||
|
@ -899,7 +895,15 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
{
|
||||
LiveInterval interval = _intervals[GetOperandId(dest)];
|
||||
|
||||
interval.SetStart(operationPos);
|
||||
interval.SetStart(operationPos + 1);
|
||||
interval.AddUsePosition(operationPos + 1);
|
||||
}
|
||||
|
||||
foreach (Operand source in Operands(node))
|
||||
{
|
||||
LiveInterval interval = _intervals[GetOperandId(source)];
|
||||
|
||||
interval.AddRange(blockStart, operationPos + 1);
|
||||
interval.AddUsePosition(operationPos);
|
||||
}
|
||||
|
||||
|
@ -937,7 +941,7 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
LiveInterval interval = _intervals[GetRegisterId(callerSavedReg)];
|
||||
|
||||
interval.AddRange(operationPos, operationPos + 1);
|
||||
interval.AddRange(operationPos + 1, operationPos + InstructionGap);
|
||||
|
||||
mask &= ~(1 << regIndex);
|
||||
}
|
||||
|
|
|
@ -73,11 +73,13 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
{
|
||||
if (_ranges.Count != 0)
|
||||
{
|
||||
Debug.Assert(position != _ranges[0].End);
|
||||
|
||||
_ranges[0] = new LiveRange(position, _ranges[0].End);
|
||||
}
|
||||
else
|
||||
{
|
||||
_ranges.Add(new LiveRange(position, position));
|
||||
_ranges.Add(new LiveRange(position, position + 1));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -103,6 +105,11 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
public void AddRange(int start, int end)
|
||||
{
|
||||
if (start >= end)
|
||||
{
|
||||
throw new ArgumentException("Invalid range start position " + start + ", " + end);
|
||||
}
|
||||
|
||||
int index = _ranges.BinarySearch(new LiveRange(start, end));
|
||||
|
||||
if (index >= 0)
|
||||
|
@ -329,27 +336,19 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
public LiveInterval GetSplitChild(int position)
|
||||
{
|
||||
//Try to find the interval among the split intervals that
|
||||
//contains the given position. The end is technically exclusive,
|
||||
//so if we have a interval where position == start, and other
|
||||
//where position == end, we should prefer the former.
|
||||
//To achieve that, we can just check the split childs backwards,
|
||||
//as they are sorted by start/end position, and there are no overlaps.
|
||||
for (int index = _childs.Count - 1; index >= 0; index--)
|
||||
if (Overlaps(position))
|
||||
{
|
||||
LiveInterval splitChild = _childs.Values[index];
|
||||
return this;
|
||||
}
|
||||
|
||||
if (position >= splitChild.GetStart() && position <= splitChild.GetEnd())
|
||||
foreach (LiveInterval splitChild in _childs.Values)
|
||||
{
|
||||
if (splitChild.Overlaps(position))
|
||||
{
|
||||
return splitChild;
|
||||
}
|
||||
}
|
||||
|
||||
if (position >= GetStart() && position <= GetEnd())
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,38 +8,8 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
{
|
||||
static class PhiFunctions
|
||||
{
|
||||
private struct PhiEntry
|
||||
{
|
||||
public BasicBlock Predecessor { get; }
|
||||
public Operand Source { get; }
|
||||
|
||||
public PhiEntry(BasicBlock predecessor, Operand source)
|
||||
{
|
||||
Predecessor = predecessor;
|
||||
Source = source;
|
||||
}
|
||||
}
|
||||
public static void Remove(ControlFlowGraph cfg)
|
||||
{
|
||||
List<int> defBlocks = new List<int>();
|
||||
|
||||
HashSet<Operand> visited = new HashSet<Operand>();
|
||||
|
||||
//Build a list with the index of the block where each variable
|
||||
//is defined, and additionally number all the variables.
|
||||
foreach (BasicBlock block in cfg.Blocks)
|
||||
{
|
||||
foreach (Node node in block.Operations)
|
||||
{
|
||||
if (node.Dest != null && node.Dest.Kind == OperandKind.LocalVariable && visited.Add(node.Dest))
|
||||
{
|
||||
node.Dest.NumberLocal(defBlocks.Count);
|
||||
|
||||
defBlocks.Add(block.Index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (BasicBlock block in cfg.Blocks)
|
||||
{
|
||||
LinkedListNode<Node> node = block.Operations.First;
|
||||
|
@ -50,19 +20,14 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
|
||||
Operand local = Local(phi.Dest.Type);
|
||||
|
||||
PhiEntry[] phiSources = GetPhiSources(phi);
|
||||
|
||||
for (int srcIndex = 0; srcIndex < phiSources.Length; srcIndex++)
|
||||
{
|
||||
BasicBlock predecessor = phiSources[srcIndex].Predecessor;
|
||||
|
||||
Operand source = phiSources[srcIndex].Source;
|
||||
|
||||
predecessor.Append(new Operation(Instruction.Copy, local, source));
|
||||
}
|
||||
|
||||
for (int index = 0; index < phi.SourcesCount; index++)
|
||||
{
|
||||
BasicBlock predecessor = phi.GetBlock(index);
|
||||
|
||||
Operand source = phi.GetSource(index);
|
||||
|
||||
predecessor.Append(new Operation(Instruction.Copy, local, source));
|
||||
|
||||
phi.SetSource(index, null);
|
||||
}
|
||||
|
||||
|
@ -78,66 +43,5 @@ namespace ARMeilleure.CodeGen.RegisterAllocators
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static PhiEntry[] GetPhiSources(PhiNode phi)
|
||||
{
|
||||
Dictionary<Operand, HashSet<BasicBlock>> defBlocksPerSrc = new Dictionary<Operand, HashSet<BasicBlock>>();
|
||||
|
||||
List<PhiEntry> phiSources = new List<PhiEntry>();
|
||||
|
||||
for (int index = 0; index < phi.SourcesCount; index++)
|
||||
{
|
||||
Operand source = phi.GetSource(index);
|
||||
|
||||
BasicBlock predecessor = phi.GetBlock(index);
|
||||
|
||||
BasicBlock defBlock = FindDefBlock(source, predecessor);
|
||||
|
||||
if (defBlock != null)
|
||||
{
|
||||
if (!defBlocksPerSrc.TryGetValue(source, out HashSet<BasicBlock> defBlocks))
|
||||
{
|
||||
defBlocks = new HashSet<BasicBlock>();
|
||||
|
||||
defBlocksPerSrc.Add(source, defBlocks);
|
||||
}
|
||||
|
||||
if (!defBlocks.Add(defBlock))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
phiSources.Add(new PhiEntry(defBlock ?? predecessor, source));
|
||||
}
|
||||
|
||||
return phiSources.ToArray();
|
||||
}
|
||||
|
||||
private static BasicBlock FindDefBlock(Operand source, BasicBlock predecessor)
|
||||
{
|
||||
if (source.Kind == OperandKind.LocalVariable)
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
foreach (Node node in predecessor.Operations)
|
||||
{
|
||||
if (node.Dest == source)
|
||||
{
|
||||
return predecessor;
|
||||
}
|
||||
}
|
||||
|
||||
if (predecessor == predecessor.ImmediateDominator)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
predecessor = predecessor.ImmediateDominator;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,11 +14,13 @@ namespace ARMeilleure.CodeGen.X86
|
|||
[Flags]
|
||||
private enum InstFlags
|
||||
{
|
||||
None = 0,
|
||||
RegOnly = 1 << 0,
|
||||
Reg8 = 1 << 1,
|
||||
NoRexW = 1 << 2,
|
||||
Vex = 1 << 3,
|
||||
None = 0,
|
||||
RegOnly = 1 << 0,
|
||||
Reg8Src = 1 << 1,
|
||||
Reg8Dest = 1 << 2,
|
||||
NoRexW = 1 << 3,
|
||||
RexW = 1 << 4,
|
||||
Vex = 1 << 5,
|
||||
|
||||
PrefixBit = 16,
|
||||
PrefixMask = 3 << PrefixBit,
|
||||
|
@ -64,182 +66,182 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
// Name RM/R RM/I8 RM/I32 R/I64 R/RM Flags
|
||||
Add(X86Instruction.Add, new InstInfo(0x00000001, 0x00000083, 0x00000081, BadOp, 0x00000003, InstFlags.None));
|
||||
Add(X86Instruction.Addpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Addps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstFlags.Vex));
|
||||
Add(X86Instruction.Addsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstFlags.Vex | InstFlags.PrefixF2));
|
||||
Add(X86Instruction.Addss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstFlags.Vex | InstFlags.PrefixF3));
|
||||
Add(X86Instruction.Addpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Addps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstFlags.Vex | InstFlags.NoRexW));
|
||||
Add(X86Instruction.Addsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF2));
|
||||
Add(X86Instruction.Addss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f58, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF3));
|
||||
Add(X86Instruction.And, new InstInfo(0x00000021, 0x04000083, 0x04000081, BadOp, 0x00000023, InstFlags.None));
|
||||
Add(X86Instruction.Andnpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f55, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Andnps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f55, InstFlags.Vex));
|
||||
Add(X86Instruction.Andnpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f55, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Andnps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f55, InstFlags.Vex | InstFlags.NoRexW));
|
||||
Add(X86Instruction.Bsr, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fbd, InstFlags.None));
|
||||
Add(X86Instruction.Bswap, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc8, InstFlags.RegOnly));
|
||||
Add(X86Instruction.Bswap, new InstInfo(0x00000fc8, BadOp, BadOp, BadOp, BadOp, InstFlags.RegOnly));
|
||||
Add(X86Instruction.Call, new InstInfo(0x020000ff, BadOp, BadOp, BadOp, BadOp, InstFlags.NoRexW));
|
||||
Add(X86Instruction.Cmovcc, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f40, InstFlags.None));
|
||||
Add(X86Instruction.Cmp, new InstInfo(0x00000039, 0x07000083, 0x07000081, BadOp, 0x0000003b, InstFlags.None));
|
||||
Add(X86Instruction.Cmppd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Cmpps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstFlags.Vex));
|
||||
Add(X86Instruction.Cmpsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstFlags.Vex | InstFlags.PrefixF2));
|
||||
Add(X86Instruction.Cmpss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstFlags.Vex | InstFlags.PrefixF3));
|
||||
Add(X86Instruction.Comisd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2f, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Comiss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2f, InstFlags.Vex));
|
||||
Add(X86Instruction.Cvtdq2pd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fe6, InstFlags.Vex | InstFlags.PrefixF3));
|
||||
Add(X86Instruction.Cvtdq2ps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5b, InstFlags.Vex));
|
||||
Add(X86Instruction.Cvtpd2dq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fe6, InstFlags.Vex | InstFlags.PrefixF2));
|
||||
Add(X86Instruction.Cvtpd2ps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5a, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Cvtps2dq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5b, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Cvtps2pd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5a, InstFlags.Vex));
|
||||
Add(X86Instruction.Cmppd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Cmpps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstFlags.Vex | InstFlags.NoRexW));
|
||||
Add(X86Instruction.Cmpsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF2));
|
||||
Add(X86Instruction.Cmpss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc2, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF3));
|
||||
Add(X86Instruction.Comisd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2f, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Comiss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2f, InstFlags.Vex | InstFlags.NoRexW));
|
||||
Add(X86Instruction.Cvtdq2pd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fe6, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF3));
|
||||
Add(X86Instruction.Cvtdq2ps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5b, InstFlags.Vex | InstFlags.NoRexW));
|
||||
Add(X86Instruction.Cvtpd2dq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fe6, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF2));
|
||||
Add(X86Instruction.Cvtpd2ps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5a, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Cvtps2dq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5b, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Cvtps2pd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5a, InstFlags.Vex | InstFlags.NoRexW));
|
||||
Add(X86Instruction.Cvtsd2si, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2c, InstFlags.Vex | InstFlags.PrefixF2));
|
||||
Add(X86Instruction.Cvtsd2ss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5a, InstFlags.Vex | InstFlags.PrefixF2));
|
||||
Add(X86Instruction.Cvtsd2ss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5a, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF2));
|
||||
Add(X86Instruction.Cvtsi2sd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2a, InstFlags.Vex | InstFlags.PrefixF2));
|
||||
Add(X86Instruction.Cvtsi2ss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f2a, InstFlags.Vex | InstFlags.PrefixF3));
|
||||
Add(X86Instruction.Cvtss2sd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5a, InstFlags.Vex | InstFlags.PrefixF3));
|
||||
Add(X86Instruction.Cvtss2sd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5a, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF3));
|
||||
Add(X86Instruction.Div, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x060000f7, InstFlags.None));
|
||||
Add(X86Instruction.Divpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Divps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstFlags.Vex));
|
||||
Add(X86Instruction.Divsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstFlags.Vex | InstFlags.PrefixF2));
|
||||
Add(X86Instruction.Divss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstFlags.Vex | InstFlags.PrefixF3));
|
||||
Add(X86Instruction.Haddpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f7c, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Haddps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f7c, InstFlags.Vex | InstFlags.PrefixF2));
|
||||
Add(X86Instruction.Divpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Divps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstFlags.Vex | InstFlags.NoRexW));
|
||||
Add(X86Instruction.Divsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF2));
|
||||
Add(X86Instruction.Divss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5e, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF3));
|
||||
Add(X86Instruction.Haddpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f7c, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Haddps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f7c, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF2));
|
||||
Add(X86Instruction.Idiv, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x070000f7, InstFlags.None));
|
||||
Add(X86Instruction.Imul, new InstInfo(BadOp, 0x0000006b, 0x00000069, BadOp, 0x00000faf, InstFlags.None));
|
||||
Add(X86Instruction.Imul128, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x050000f7, InstFlags.None));
|
||||
Add(X86Instruction.Insertps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a21, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Insertps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a21, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Lea, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x0000008d, InstFlags.None));
|
||||
Add(X86Instruction.Maxpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5f, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Maxps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5f, InstFlags.Vex));
|
||||
Add(X86Instruction.Maxsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5f, InstFlags.Vex | InstFlags.PrefixF2));
|
||||
Add(X86Instruction.Maxss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5f, InstFlags.Vex | InstFlags.PrefixF3));
|
||||
Add(X86Instruction.Minpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5d, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Minps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5d, InstFlags.Vex));
|
||||
Add(X86Instruction.Minsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5d, InstFlags.Vex | InstFlags.PrefixF2));
|
||||
Add(X86Instruction.Minss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5d, InstFlags.Vex | InstFlags.PrefixF3));
|
||||
Add(X86Instruction.Maxpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5f, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Maxps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5f, InstFlags.Vex | InstFlags.NoRexW));
|
||||
Add(X86Instruction.Maxsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5f, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF2));
|
||||
Add(X86Instruction.Maxss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5f, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF3));
|
||||
Add(X86Instruction.Minpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5d, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Minps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5d, InstFlags.Vex | InstFlags.NoRexW));
|
||||
Add(X86Instruction.Minsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5d, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF2));
|
||||
Add(X86Instruction.Minss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5d, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF3));
|
||||
Add(X86Instruction.Mov, new InstInfo(0x00000089, BadOp, 0x000000c7, 0x000000b8, 0x0000008b, InstFlags.None));
|
||||
Add(X86Instruction.Mov16, new InstInfo(0x00000089, BadOp, 0x000000c7, BadOp, 0x0000008b, InstFlags.Prefix66));
|
||||
Add(X86Instruction.Mov8, new InstInfo(0x00000088, 0x000000c6, BadOp, BadOp, 0x0000008a, InstFlags.None));
|
||||
Add(X86Instruction.Movd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f6e, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Movdqu, new InstInfo(0x00000f7f, BadOp, BadOp, BadOp, 0x00000f6f, InstFlags.Vex | InstFlags.PrefixF3));
|
||||
Add(X86Instruction.Movhlps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f12, InstFlags.Vex));
|
||||
Add(X86Instruction.Movlhps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f16, InstFlags.Vex));
|
||||
Add(X86Instruction.Movq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f7e, InstFlags.Vex | InstFlags.PrefixF3));
|
||||
Add(X86Instruction.Movsd, new InstInfo(0x00000f11, BadOp, BadOp, BadOp, 0x00000f10, InstFlags.Vex | InstFlags.PrefixF2));
|
||||
Add(X86Instruction.Movss, new InstInfo(0x00000f11, BadOp, BadOp, BadOp, 0x00000f10, InstFlags.Vex | InstFlags.PrefixF3));
|
||||
Add(X86Instruction.Mov8, new InstInfo(0x00000088, 0x000000c6, BadOp, BadOp, 0x0000008a, InstFlags.Reg8Src | InstFlags.Reg8Dest));
|
||||
Add(X86Instruction.Movd, new InstInfo(0x00000f7e, BadOp, BadOp, BadOp, 0x00000f6e, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Movdqu, new InstInfo(0x00000f7f, BadOp, BadOp, BadOp, 0x00000f6f, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF3));
|
||||
Add(X86Instruction.Movhlps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f12, InstFlags.Vex | InstFlags.NoRexW));
|
||||
Add(X86Instruction.Movlhps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f16, InstFlags.Vex | InstFlags.NoRexW));
|
||||
Add(X86Instruction.Movq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f7e, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF3));
|
||||
Add(X86Instruction.Movsd, new InstInfo(0x00000f11, BadOp, BadOp, BadOp, 0x00000f10, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF2));
|
||||
Add(X86Instruction.Movss, new InstInfo(0x00000f11, BadOp, BadOp, BadOp, 0x00000f10, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF3));
|
||||
Add(X86Instruction.Movsx16, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fbf, InstFlags.None));
|
||||
Add(X86Instruction.Movsx32, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000063, InstFlags.None));
|
||||
Add(X86Instruction.Movsx8, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fbe, InstFlags.None));
|
||||
Add(X86Instruction.Movsx8, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fbe, InstFlags.Reg8Src));
|
||||
Add(X86Instruction.Movzx16, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fb7, InstFlags.None));
|
||||
Add(X86Instruction.Movzx8, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fb6, InstFlags.None));
|
||||
Add(X86Instruction.Movzx8, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fb6, InstFlags.Reg8Src));
|
||||
Add(X86Instruction.Mul128, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x040000f7, InstFlags.None));
|
||||
Add(X86Instruction.Mulpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f59, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Mulps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f59, InstFlags.Vex));
|
||||
Add(X86Instruction.Mulsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f59, InstFlags.Vex | InstFlags.PrefixF2));
|
||||
Add(X86Instruction.Mulss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f59, InstFlags.Vex | InstFlags.PrefixF3));
|
||||
Add(X86Instruction.Mulpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f59, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Mulps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f59, InstFlags.Vex | InstFlags.NoRexW));
|
||||
Add(X86Instruction.Mulsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f59, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF2));
|
||||
Add(X86Instruction.Mulss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f59, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF3));
|
||||
Add(X86Instruction.Neg, new InstInfo(0x030000f7, BadOp, BadOp, BadOp, BadOp, InstFlags.None));
|
||||
Add(X86Instruction.Not, new InstInfo(0x020000f7, BadOp, BadOp, BadOp, BadOp, InstFlags.None));
|
||||
Add(X86Instruction.Or, new InstInfo(0x00000009, 0x01000083, 0x01000081, BadOp, 0x0000000b, InstFlags.None));
|
||||
Add(X86Instruction.Paddb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffc, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Paddd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffe, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Paddq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fd4, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Paddw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffd, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pand, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fdb, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pandn, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fdf, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pavgb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fe0, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pavgw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fe3, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pblendvb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a4c, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pcmpeqb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f74, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pcmpeqd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f76, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pcmpeqq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3829, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pcmpeqw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f75, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pcmpgtb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f64, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pcmpgtd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f66, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pcmpgtq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3837, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pcmpgtw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f65, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pextrb, new InstInfo(0x000f3a14, BadOp, BadOp, BadOp, BadOp, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Paddb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffc, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Paddd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffe, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Paddq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fd4, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Paddw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffd, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pand, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fdb, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pandn, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fdf, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pavgb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fe0, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pavgw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fe3, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pblendvb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a4c, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pcmpeqb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f74, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pcmpeqd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f76, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pcmpeqq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3829, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pcmpeqw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f75, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pcmpgtb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f64, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pcmpgtd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f66, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pcmpgtq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3837, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pcmpgtw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f65, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pextrb, new InstInfo(0x000f3a14, BadOp, BadOp, BadOp, BadOp, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pextrd, new InstInfo(0x000f3a16, BadOp, BadOp, BadOp, BadOp, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pextrw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc5, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pinsrb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a20, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pextrw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc5, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pinsrb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a20, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pinsrd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a22, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pinsrw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc4, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pmaxsb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383c, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pmaxsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383d, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pmaxsw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fee, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pmaxub, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fde, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pmaxud, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383f, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pmaxuw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383e, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pminsb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3838, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pminsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3839, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pminsw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fea, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pminub, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fda, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pminud, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383b, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pminuw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383a, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pmovsxbw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3820, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pmovsxdq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3825, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pmovsxwd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3823, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pmovzxbw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3830, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pmovzxdq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3835, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pmovzxwd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3833, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pmulld, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3840, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pmullw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fd5, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pinsrw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc4, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pmaxsb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383c, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pmaxsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383d, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pmaxsw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fee, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pmaxub, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fde, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pmaxud, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383f, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pmaxuw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383e, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pminsb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3838, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pminsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3839, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pminsw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fea, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pminub, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fda, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pminud, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383b, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pminuw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f383a, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pmovsxbw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3820, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pmovsxdq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3825, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pmovsxwd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3823, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pmovzxbw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3830, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pmovzxdq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3835, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pmovzxwd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3833, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pmulld, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3840, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pmullw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fd5, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pop, new InstInfo(0x0000008f, BadOp, BadOp, BadOp, BadOp, InstFlags.None));
|
||||
Add(X86Instruction.Popcnt, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fb8, InstFlags.PrefixF3));
|
||||
Add(X86Instruction.Por, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000feb, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pshufb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3800, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pshufd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f70, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pslld, new InstInfo(BadOp, 0x06000f72, BadOp, BadOp, 0x00000ff2, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pslldq, new InstInfo(BadOp, 0x07000f73, BadOp, BadOp, BadOp, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Psllq, new InstInfo(BadOp, 0x06000f73, BadOp, BadOp, 0x00000ff3, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Psllw, new InstInfo(BadOp, 0x06000f71, BadOp, BadOp, 0x00000ff1, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Psrad, new InstInfo(BadOp, 0x04000f72, BadOp, BadOp, 0x00000fe2, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Psraw, new InstInfo(BadOp, 0x04000f71, BadOp, BadOp, 0x00000fe1, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Psrld, new InstInfo(BadOp, 0x02000f72, BadOp, BadOp, 0x00000fd2, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Psrlq, new InstInfo(BadOp, 0x02000f73, BadOp, BadOp, 0x00000fd3, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Psrldq, new InstInfo(BadOp, 0x03000f73, BadOp, BadOp, BadOp, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Psrlw, new InstInfo(BadOp, 0x02000f71, BadOp, BadOp, 0x00000fd1, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Psubb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ff8, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Psubd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffa, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Psubq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffb, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Psubw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ff9, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Punpckhbw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f68, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Punpckhdq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f6a, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Punpckhqdq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f6d, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Punpckhwd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f69, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Punpcklbw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f60, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Punpckldq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f62, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Punpcklqdq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f6c, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Punpcklwd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f61, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Por, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000feb, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pshufb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3800, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pshufd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f70, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pslld, new InstInfo(BadOp, 0x06000f72, BadOp, BadOp, 0x00000ff2, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Pslldq, new InstInfo(BadOp, 0x07000f73, BadOp, BadOp, BadOp, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Psllq, new InstInfo(BadOp, 0x06000f73, BadOp, BadOp, 0x00000ff3, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Psllw, new InstInfo(BadOp, 0x06000f71, BadOp, BadOp, 0x00000ff1, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Psrad, new InstInfo(BadOp, 0x04000f72, BadOp, BadOp, 0x00000fe2, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Psraw, new InstInfo(BadOp, 0x04000f71, BadOp, BadOp, 0x00000fe1, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Psrld, new InstInfo(BadOp, 0x02000f72, BadOp, BadOp, 0x00000fd2, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Psrlq, new InstInfo(BadOp, 0x02000f73, BadOp, BadOp, 0x00000fd3, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Psrldq, new InstInfo(BadOp, 0x03000f73, BadOp, BadOp, BadOp, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Psrlw, new InstInfo(BadOp, 0x02000f71, BadOp, BadOp, 0x00000fd1, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Psubb, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ff8, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Psubd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffa, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Psubq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ffb, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Psubw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000ff9, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Punpckhbw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f68, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Punpckhdq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f6a, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Punpckhqdq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f6d, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Punpckhwd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f69, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Punpcklbw, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f60, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Punpckldq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f62, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Punpcklqdq, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f6c, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Punpcklwd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f61, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Push, new InstInfo(BadOp, 0x0000006a, 0x00000068, BadOp, 0x060000ff, InstFlags.None));
|
||||
Add(X86Instruction.Pxor, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fef, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Rcpps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f53, InstFlags.Vex));
|
||||
Add(X86Instruction.Rcpss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f53, InstFlags.Vex | InstFlags.PrefixF3));
|
||||
Add(X86Instruction.Pxor, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fef, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Rcpps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f53, InstFlags.Vex | InstFlags.NoRexW));
|
||||
Add(X86Instruction.Rcpss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f53, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF3));
|
||||
Add(X86Instruction.Ror, new InstInfo(0x010000d3, 0x010000c1, BadOp, BadOp, BadOp, InstFlags.None));
|
||||
Add(X86Instruction.Roundpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a09, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Roundps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a08, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Roundsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a0b, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Roundss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a0a, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Rsqrtps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f52, InstFlags.Vex));
|
||||
Add(X86Instruction.Rsqrtss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f52, InstFlags.Vex | InstFlags.PrefixF3));
|
||||
Add(X86Instruction.Roundpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a09, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Roundps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a08, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Roundsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a0b, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Roundss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x000f3a0a, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Rsqrtps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f52, InstFlags.Vex | InstFlags.NoRexW));
|
||||
Add(X86Instruction.Rsqrtss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f52, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF3));
|
||||
Add(X86Instruction.Sar, new InstInfo(0x070000d3, 0x070000c1, BadOp, BadOp, BadOp, InstFlags.None));
|
||||
Add(X86Instruction.Setcc, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f90, InstFlags.Reg8));
|
||||
Add(X86Instruction.Setcc, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f90, InstFlags.Reg8Dest));
|
||||
Add(X86Instruction.Shl, new InstInfo(0x040000d3, 0x040000c1, BadOp, BadOp, BadOp, InstFlags.None));
|
||||
Add(X86Instruction.Shr, new InstInfo(0x050000d3, 0x050000c1, BadOp, BadOp, BadOp, InstFlags.None));
|
||||
Add(X86Instruction.Shufpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc6, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Shufps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc6, InstFlags.Vex));
|
||||
Add(X86Instruction.Sqrtpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f51, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Sqrtps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f51, InstFlags.Vex));
|
||||
Add(X86Instruction.Sqrtsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f51, InstFlags.Vex | InstFlags.PrefixF2));
|
||||
Add(X86Instruction.Sqrtss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f51, InstFlags.Vex | InstFlags.PrefixF3));
|
||||
Add(X86Instruction.Shufpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc6, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Shufps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000fc6, InstFlags.Vex | InstFlags.NoRexW));
|
||||
Add(X86Instruction.Sqrtpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f51, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Sqrtps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f51, InstFlags.Vex | InstFlags.NoRexW));
|
||||
Add(X86Instruction.Sqrtsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f51, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF2));
|
||||
Add(X86Instruction.Sqrtss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f51, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF3));
|
||||
Add(X86Instruction.Sub, new InstInfo(0x00000029, 0x05000083, 0x05000081, BadOp, 0x0000002b, InstFlags.None));
|
||||
Add(X86Instruction.Subpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5c, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Subps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5c, InstFlags.Vex));
|
||||
Add(X86Instruction.Subsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5c, InstFlags.Vex | InstFlags.PrefixF2));
|
||||
Add(X86Instruction.Subss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5c, InstFlags.Vex | InstFlags.PrefixF3));
|
||||
Add(X86Instruction.Subpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5c, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Subps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5c, InstFlags.Vex | InstFlags.NoRexW));
|
||||
Add(X86Instruction.Subsd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5c, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF2));
|
||||
Add(X86Instruction.Subss, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f5c, InstFlags.Vex | InstFlags.NoRexW | InstFlags.PrefixF3));
|
||||
Add(X86Instruction.Test, new InstInfo(0x00000085, BadOp, 0x000000f7, BadOp, BadOp, InstFlags.None));
|
||||
Add(X86Instruction.Unpckhpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f15, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Unpckhps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f15, InstFlags.Vex));
|
||||
Add(X86Instruction.Unpcklpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f14, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Unpcklps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f14, InstFlags.Vex));
|
||||
Add(X86Instruction.Unpckhpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f15, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Unpckhps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f15, InstFlags.Vex | InstFlags.NoRexW));
|
||||
Add(X86Instruction.Unpcklpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f14, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Unpcklps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f14, InstFlags.Vex | InstFlags.NoRexW));
|
||||
Add(X86Instruction.Xor, new InstInfo(0x00000031, 0x06000083, 0x06000081, BadOp, 0x00000033, InstFlags.None));
|
||||
Add(X86Instruction.Xorpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f57, InstFlags.Vex | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Xorps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f57, InstFlags.Vex));
|
||||
Add(X86Instruction.Xorpd, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f57, InstFlags.Vex | InstFlags.NoRexW | InstFlags.Prefix66));
|
||||
Add(X86Instruction.Xorps, new InstInfo(BadOp, BadOp, BadOp, BadOp, 0x00000f57, InstFlags.Vex | InstFlags.NoRexW));
|
||||
}
|
||||
|
||||
private static void Add(X86Instruction inst, InstInfo info)
|
||||
|
@ -615,7 +617,16 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
public void Movd(Operand dest, Operand source)
|
||||
{
|
||||
WriteInstruction(dest, source, X86Instruction.Movd);
|
||||
InstInfo info = _instTable[(int)X86Instruction.Movd];
|
||||
|
||||
if (dest.GetRegister().Type == RegisterType.Vector || source.Kind == OperandKind.Memory)
|
||||
{
|
||||
WriteRRMOpCode(dest, source, info.Flags, info.OpRRM);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteOpCode(dest, source, info.Flags, info.OpRMR);
|
||||
}
|
||||
}
|
||||
|
||||
public void Movdqu(Operand dest, Operand source)
|
||||
|
@ -1411,7 +1422,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
modRM |= (regIndex & 0b111) << (rrm ? 3 : 0);
|
||||
|
||||
if ((flags & InstFlags.Reg8) != 0 && regIndex >= 4)
|
||||
if ((flags & InstFlags.Reg8Dest) != 0 && regIndex >= 4)
|
||||
{
|
||||
rexPrefix |= 0x40;
|
||||
}
|
||||
|
@ -1430,7 +1441,14 @@ namespace ARMeilleure.CodeGen.X86
|
|||
{
|
||||
if (source.Kind == OperandKind.Register)
|
||||
{
|
||||
modRM |= (source.GetRegister().Index & 0b111) << (rrm ? 0 : 3);
|
||||
int regIndex = source.GetRegister().Index;
|
||||
|
||||
modRM |= (regIndex & 0b111) << (rrm ? 0 : 3);
|
||||
|
||||
if ((flags & InstFlags.Reg8Src) != 0 && regIndex >= 4)
|
||||
{
|
||||
rexPrefix |= 0x40;
|
||||
}
|
||||
}
|
||||
else if (source.Kind == OperandKind.Memory && memOp == null)
|
||||
{
|
||||
|
@ -1581,6 +1599,11 @@ namespace ARMeilleure.CodeGen.X86
|
|||
}
|
||||
}
|
||||
|
||||
if ((flags & InstFlags.RegOnly) != 0)
|
||||
{
|
||||
opCode += dest.GetRegister().Index & 7;
|
||||
}
|
||||
|
||||
if ((opCode & 0xff0000) != 0)
|
||||
{
|
||||
WriteByte((byte)(opCode >> 16));
|
||||
|
@ -1642,7 +1665,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
if (dest != null)
|
||||
{
|
||||
if (dest.Type == OperandType.I64 && rexW)
|
||||
if (Is64Bits(dest.Type) && rexW)
|
||||
{
|
||||
rexPrefix = 0x48;
|
||||
}
|
||||
|
@ -1655,7 +1678,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
if (source != null)
|
||||
{
|
||||
if (source.Type == OperandType.I64 && rexW)
|
||||
if (Is64Bits(source.Type) && rexW)
|
||||
{
|
||||
rexPrefix |= 0x48;
|
||||
}
|
||||
|
@ -1671,8 +1694,12 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
private static bool IsR64(Operand operand)
|
||||
{
|
||||
return operand.Kind == OperandKind.Register &&
|
||||
operand.Type == OperandType.I64;
|
||||
return operand.Kind == OperandKind.Register && operand.Type == OperandType.I64;
|
||||
}
|
||||
|
||||
private static bool Is64Bits(OperandType type)
|
||||
{
|
||||
return type == OperandType.I64 || type == OperandType.FP64;
|
||||
}
|
||||
|
||||
private static bool IsImm8(Operand operand)
|
||||
|
|
|
@ -105,7 +105,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
//The ABI mandates that the space for at least 4 arguments
|
||||
//is reserved on the stack (this is called shadow space).
|
||||
if (argsCount < 4 && argsCount != 0)
|
||||
if (argsCount < 4 && maxCallArgs != -1)
|
||||
{
|
||||
argsCount = 4;
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
Add(Instruction.CompareLessUI, GenerateCompareLessUI);
|
||||
Add(Instruction.CompareNotEqual, GenerateCompareNotEqual);
|
||||
Add(Instruction.ConditionalSelect, GenerateConditionalSelect);
|
||||
Add(Instruction.ConvertI64ToI32, GenerateConvertI64ToI32);
|
||||
Add(Instruction.ConvertToFP, GenerateConvertToFP);
|
||||
Add(Instruction.Copy, GenerateCopy);
|
||||
Add(Instruction.CountLeadingZeros, GenerateCountLeadingZeros);
|
||||
|
@ -79,9 +80,13 @@ namespace ARMeilleure.CodeGen.X86
|
|||
Add(Instruction.VectorInsert, GenerateVectorInsert);
|
||||
Add(Instruction.VectorInsert16, GenerateVectorInsert16);
|
||||
Add(Instruction.VectorInsert8, GenerateVectorInsert8);
|
||||
Add(Instruction.VectorOne, GenerateVectorOne);
|
||||
Add(Instruction.VectorZero, GenerateVectorZero);
|
||||
Add(Instruction.VectorZeroUpper64, GenerateVectorZeroUpper64);
|
||||
Add(Instruction.VectorZeroUpper96, GenerateVectorZeroUpper96);
|
||||
Add(Instruction.ZeroExtend16, GenerateZeroExtend16);
|
||||
Add(Instruction.ZeroExtend32, GenerateZeroExtend32);
|
||||
Add(Instruction.ZeroExtend8, GenerateZeroExtend8);
|
||||
Add(Instruction.X86Addpd, GenerateX86Addpd);
|
||||
Add(Instruction.X86Addps, GenerateX86Addps);
|
||||
Add(Instruction.X86Addsd, GenerateX86Addsd);
|
||||
|
@ -227,7 +232,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
Optimizer.RunPass(cfg);
|
||||
|
||||
Logger.EndPass(PassName.Optimization);
|
||||
Logger.EndPass(PassName.Optimization, cfg);
|
||||
|
||||
Logger.StartPass(PassName.PreAllocation);
|
||||
|
||||
|
@ -323,7 +328,14 @@ namespace ARMeilleure.CodeGen.X86
|
|||
{
|
||||
ValidateDestSrc1(operation);
|
||||
|
||||
context.Assembler.Xor(operation.Dest, operation.GetSource(1));
|
||||
if (operation.Dest.Type.IsInteger())
|
||||
{
|
||||
context.Assembler.Xor(operation.Dest, operation.GetSource(1));
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Assembler.Xorps(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||
}
|
||||
}
|
||||
|
||||
private static void GenerateBitwiseNot(CodeGenContext context, Operation operation)
|
||||
|
@ -423,6 +435,14 @@ namespace ARMeilleure.CodeGen.X86
|
|||
context.Assembler.Cmovcc(operation.Dest, operation.GetSource(1), X86Condition.NotEqual);
|
||||
}
|
||||
|
||||
private static void GenerateConvertI64ToI32(CodeGenContext context, Operation operation)
|
||||
{
|
||||
Operand dest = operation.Dest;
|
||||
Operand source = operation.GetSource(0);
|
||||
|
||||
context.Assembler.Mov(dest, Get32BitsRegister(source.GetRegister()));
|
||||
}
|
||||
|
||||
private static void GenerateConvertToFP(CodeGenContext context, Operation operation)
|
||||
{
|
||||
Operand dest = operation.Dest;
|
||||
|
@ -486,25 +506,10 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
context.Assembler.Xor(dest, dest);
|
||||
}
|
||||
else if (dest.Type == OperandType.I64 && source.Type == OperandType.I32)
|
||||
{
|
||||
//I32 -> I64 zero-extension.
|
||||
if (dest.Kind == OperandKind.Register && source.Kind == OperandKind.Register)
|
||||
{
|
||||
dest = Get32BitsRegister(dest.GetRegister());
|
||||
}
|
||||
else if (source.Kind == OperandKind.Constant)
|
||||
{
|
||||
source = new Operand(source.Value);
|
||||
}
|
||||
|
||||
context.Assembler.Mov(dest, source);
|
||||
}
|
||||
else if (dest.GetRegister().Type == RegisterType.Vector)
|
||||
{
|
||||
if (source.GetRegister().Type == RegisterType.Integer)
|
||||
{
|
||||
//FIXME.
|
||||
context.Assembler.Movd(dest, source);
|
||||
}
|
||||
else
|
||||
|
@ -512,6 +517,10 @@ namespace ARMeilleure.CodeGen.X86
|
|||
context.Assembler.Movdqu(dest, source);
|
||||
}
|
||||
}
|
||||
else if (dest.Type == OperandType.I32 && source.Kind == OperandKind.Register)
|
||||
{
|
||||
context.Assembler.Mov(dest, Get32BitsRegister(source.GetRegister()));
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Assembler.Mov(dest, source);
|
||||
|
@ -614,13 +623,25 @@ namespace ARMeilleure.CodeGen.X86
|
|||
Operand value = operation.Dest;
|
||||
Operand address = GetMemoryOperand(operation.GetSource(0), value.Type);
|
||||
|
||||
if (value.GetRegister().Type == RegisterType.Integer)
|
||||
switch (value.Type)
|
||||
{
|
||||
context.Assembler.Mov(value, address);
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Assembler.Movdqu(value, address);
|
||||
case OperandType.I32:
|
||||
case OperandType.I64:
|
||||
context.Assembler.Mov(value, address);
|
||||
break;
|
||||
|
||||
case OperandType.FP32:
|
||||
case OperandType.FP64:
|
||||
context.Assembler.Movd(value, address);
|
||||
break;
|
||||
|
||||
case OperandType.V128:
|
||||
context.Assembler.Movdqu(value, address);
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug.Assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -813,13 +834,25 @@ namespace ARMeilleure.CodeGen.X86
|
|||
Operand value = operation.GetSource(1);
|
||||
Operand address = GetMemoryOperand(operation.GetSource(0), value.Type);
|
||||
|
||||
if (value.GetRegister().Type == RegisterType.Integer)
|
||||
switch (value.Type)
|
||||
{
|
||||
context.Assembler.Mov(address, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
context.Assembler.Movdqu(address, value);
|
||||
case OperandType.I32:
|
||||
case OperandType.I64:
|
||||
context.Assembler.Mov(address, value);
|
||||
break;
|
||||
|
||||
case OperandType.FP32:
|
||||
case OperandType.FP64:
|
||||
context.Assembler.Movd(address, value);
|
||||
break;
|
||||
|
||||
case OperandType.V128:
|
||||
context.Assembler.Movdqu(address, value);
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug.Assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1017,6 +1050,11 @@ namespace ARMeilleure.CodeGen.X86
|
|||
context.Assembler.Pinsrb(dest, src2, src1, index);
|
||||
}
|
||||
|
||||
private static void GenerateVectorOne(CodeGenContext context, Operation operation)
|
||||
{
|
||||
context.Assembler.Pcmpeqw(operation.Dest, operation.Dest, operation.Dest);
|
||||
}
|
||||
|
||||
private static void GenerateVectorZero(CodeGenContext context, Operation operation)
|
||||
{
|
||||
context.Assembler.Xorps(operation.Dest, operation.Dest, operation.Dest);
|
||||
|
@ -1032,6 +1070,23 @@ namespace ARMeilleure.CodeGen.X86
|
|||
ZeroUpper96(context, operation.Dest, operation.GetSource(0));
|
||||
}
|
||||
|
||||
private static void GenerateZeroExtend16(CodeGenContext context, Operation operation)
|
||||
{
|
||||
context.Assembler.Movzx16(operation.Dest, Get32BitsRegister(operation.GetSource(0).GetRegister()));
|
||||
}
|
||||
|
||||
private static void GenerateZeroExtend32(CodeGenContext context, Operation operation)
|
||||
{
|
||||
context.Assembler.Mov(
|
||||
Get32BitsRegister(operation.Dest.GetRegister()),
|
||||
Get32BitsRegister(operation.GetSource(0).GetRegister()));
|
||||
}
|
||||
|
||||
private static void GenerateZeroExtend8(CodeGenContext context, Operation operation)
|
||||
{
|
||||
context.Assembler.Movzx8(operation.Dest, Get32BitsRegister(operation.GetSource(0).GetRegister()));
|
||||
}
|
||||
|
||||
private static void GenerateX86Addpd(CodeGenContext context, Operation operation)
|
||||
{
|
||||
context.Assembler.Addpd(operation.Dest, operation.GetSource(1), operation.GetSource(0));
|
||||
|
|
|
@ -12,7 +12,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
{
|
||||
public static void RunPass(ControlFlowGraph cfg, MemoryManager memory, out int maxCallArgs)
|
||||
{
|
||||
maxCallArgs = 0;
|
||||
maxCallArgs = -1;
|
||||
|
||||
foreach (BasicBlock block in cfg.Blocks)
|
||||
{
|
||||
|
@ -199,17 +199,19 @@ namespace ARMeilleure.CodeGen.X86
|
|||
//--- This can be done efficiently by adding the result to itself.
|
||||
//-- Then, we need to add the least significant bit that was shifted out.
|
||||
//--- We can convert the least significant bit to float, and add it to the result.
|
||||
Operand lsb = Local(OperandType.I64);
|
||||
Operand lsb = Local(OperandType.I64);
|
||||
Operand half = Local(OperandType.I64);
|
||||
|
||||
Operand lsbF = Local(dest.Type);
|
||||
|
||||
temp = nodes.AddAfter(temp, new Operation(Instruction.Copy, lsb, source));
|
||||
temp = nodes.AddAfter(temp, new Operation(Instruction.Copy, lsb, source));
|
||||
temp = nodes.AddAfter(temp, new Operation(Instruction.Copy, half, source));
|
||||
|
||||
temp = nodes.AddAfter(temp, new Operation(Instruction.BitwiseAnd, lsb, lsb, Const(1L)));
|
||||
temp = nodes.AddAfter(temp, new Operation(Instruction.ShiftRightUI, source, source, Const(1)));
|
||||
temp = nodes.AddAfter(temp, new Operation(Instruction.BitwiseAnd, lsb, lsb, Const(1L)));
|
||||
temp = nodes.AddAfter(temp, new Operation(Instruction.ShiftRightUI, half, half, Const(1)));
|
||||
|
||||
temp = nodes.AddAfter(temp, new Operation(Instruction.ConvertToFP, lsbF, lsb));
|
||||
temp = nodes.AddAfter(temp, new Operation(Instruction.ConvertToFP, dest, source));
|
||||
temp = nodes.AddAfter(temp, new Operation(Instruction.ConvertToFP, dest, half));
|
||||
|
||||
temp = nodes.AddAfter(temp, new Operation(Instruction.Add, dest, dest, dest));
|
||||
temp = nodes.AddAfter(temp, new Operation(Instruction.Add, dest, dest, lsbF));
|
||||
|
@ -232,7 +234,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
Operand res = Local(dest.Type);
|
||||
|
||||
temp = nodes.AddAfter(temp, new Operation(Instruction.X86Pcmpeqw, res, res, res));
|
||||
temp = nodes.AddAfter(temp, new Operation(Instruction.VectorOne, res));
|
||||
|
||||
if (dest.Type == OperandType.FP32)
|
||||
{
|
||||
|
|
|
@ -19,6 +19,15 @@ namespace ARMeilleure.Decoders
|
|||
_opActivators = new ConcurrentDictionary<Type, MakeOp>();
|
||||
}
|
||||
|
||||
public static Block[] DecodeBasicBlock(MemoryManager memory, ulong address, ExecutionMode mode)
|
||||
{
|
||||
Block block = new Block(address);
|
||||
|
||||
FillBlock(memory, mode, block, ulong.MaxValue);
|
||||
|
||||
return new Block[] { block };
|
||||
}
|
||||
|
||||
public static Block[] DecodeFunction(MemoryManager memory, ulong address, ExecutionMode mode)
|
||||
{
|
||||
List<Block> blocks = new List<Block>();
|
||||
|
|
|
@ -205,7 +205,8 @@ namespace ARMeilleure.Decoders
|
|||
SetA64("0100111000101000011010xxxxxxxxxx", InstName.Aesmc_V, InstEmit.Aesmc_V, typeof(OpCodeSimd));
|
||||
SetA64("0x001110001xxxxx000111xxxxxxxxxx", InstName.And_V, InstEmit.And_V, typeof(OpCodeSimdReg));
|
||||
SetA64("0x001110011xxxxx000111xxxxxxxxxx", InstName.Bic_V, InstEmit.Bic_V, typeof(OpCodeSimdReg));
|
||||
SetA64("0x10111100000xxx<<x101xxxxxxxxxx", InstName.Bic_Vi, InstEmit.Bic_Vi, typeof(OpCodeSimdImm));
|
||||
SetA64("0x10111100000xxx0xx101xxxxxxxxxx", InstName.Bic_Vi, InstEmit.Bic_Vi, typeof(OpCodeSimdImm));
|
||||
SetA64("0x10111100000xxx10x101xxxxxxxxxx", InstName.Bic_Vi, InstEmit.Bic_Vi, typeof(OpCodeSimdImm));
|
||||
SetA64("0x101110111xxxxx000111xxxxxxxxxx", InstName.Bif_V, InstEmit.Bif_V, typeof(OpCodeSimdReg));
|
||||
SetA64("0x101110101xxxxx000111xxxxxxxxxx", InstName.Bit_V, InstEmit.Bit_V, typeof(OpCodeSimdReg));
|
||||
SetA64("0x101110011xxxxx000111xxxxxxxxxx", InstName.Bsl_V, InstEmit.Bsl_V, typeof(OpCodeSimdReg));
|
||||
|
@ -313,12 +314,15 @@ namespace ARMeilleure.Decoders
|
|||
SetA64("0>0011101<1xxxxx110011xxxxxxxxxx", InstName.Fmls_V, InstEmit.Fmls_V, typeof(OpCodeSimdReg));
|
||||
SetA64("0>0011111<xxxxxx0101x0xxxxxxxxxx", InstName.Fmls_Ve, InstEmit.Fmls_Ve, typeof(OpCodeSimdRegElemF));
|
||||
SetA64("000111100x100000010000xxxxxxxxxx", InstName.Fmov_S, InstEmit.Fmov_S, typeof(OpCodeSimd));
|
||||
SetA64("00011110xx1xxxxxxxx100xxxxxxxxxx", InstName.Fmov_Si, InstEmit.Fmov_Si, typeof(OpCodeSimdFmov));
|
||||
SetA64("0xx0111100000xxx111101xxxxxxxxxx", InstName.Fmov_V, InstEmit.Fmov_V, typeof(OpCodeSimdImm));
|
||||
SetA64("x00111100x100110000000xxxxxxxxxx", InstName.Fmov_Ftoi, InstEmit.Fmov_Ftoi, typeof(OpCodeSimdCvt));
|
||||
SetA64("x00111100x100111000000xxxxxxxxxx", InstName.Fmov_Itof, InstEmit.Fmov_Itof, typeof(OpCodeSimdCvt));
|
||||
SetA64("1001111010101110000000xxxxxxxxxx", InstName.Fmov_Ftoi1, InstEmit.Fmov_Ftoi1, typeof(OpCodeSimdCvt));
|
||||
SetA64("1001111010101111000000xxxxxxxxxx", InstName.Fmov_Itof1, InstEmit.Fmov_Itof1, typeof(OpCodeSimdCvt));
|
||||
SetA64("000111100x1xxxxxxxx10000000xxxxx", InstName.Fmov_Si, InstEmit.Fmov_Si, typeof(OpCodeSimdFmov));
|
||||
SetA64("0x00111100000xxx111101xxxxxxxxxx", InstName.Fmov_Vi, InstEmit.Fmov_Vi, typeof(OpCodeSimdImm));
|
||||
SetA64("0110111100000xxx111101xxxxxxxxxx", InstName.Fmov_Vi, InstEmit.Fmov_Vi, typeof(OpCodeSimdImm));
|
||||
SetA64("0001111000100110000000xxxxxxxxxx", InstName.Fmov_Ftoi, InstEmit.Fmov_Ftoi, typeof(OpCodeSimd));
|
||||
SetA64("1001111001100110000000xxxxxxxxxx", InstName.Fmov_Ftoi, InstEmit.Fmov_Ftoi, typeof(OpCodeSimd));
|
||||
SetA64("0001111000100111000000xxxxxxxxxx", InstName.Fmov_Itof, InstEmit.Fmov_Itof, typeof(OpCodeSimd));
|
||||
SetA64("1001111001100111000000xxxxxxxxxx", InstName.Fmov_Itof, InstEmit.Fmov_Itof, typeof(OpCodeSimd));
|
||||
SetA64("1001111010101110000000xxxxxxxxxx", InstName.Fmov_Ftoi1, InstEmit.Fmov_Ftoi1, typeof(OpCodeSimd));
|
||||
SetA64("1001111010101111000000xxxxxxxxxx", InstName.Fmov_Itof1, InstEmit.Fmov_Itof1, typeof(OpCodeSimd));
|
||||
SetA64("000111110x0xxxxx1xxxxxxxxxxxxxxx", InstName.Fmsub_S, InstEmit.Fmsub_S, typeof(OpCodeSimdReg));
|
||||
SetA64("000111100x1xxxxx000010xxxxxxxxxx", InstName.Fmul_S, InstEmit.Fmul_S, typeof(OpCodeSimdReg));
|
||||
SetA64("010111111xxxxxxx1001x0xxxxxxxxxx", InstName.Fmul_Se, InstEmit.Fmul_Se, typeof(OpCodeSimdRegElemF));
|
||||
|
@ -391,7 +395,8 @@ namespace ARMeilleure.Decoders
|
|||
SetA64("0x10111000100000010110xxxxxxxxxx", InstName.Not_V, InstEmit.Not_V, typeof(OpCodeSimd));
|
||||
SetA64("0x001110111xxxxx000111xxxxxxxxxx", InstName.Orn_V, InstEmit.Orn_V, typeof(OpCodeSimdReg));
|
||||
SetA64("0x001110101xxxxx000111xxxxxxxxxx", InstName.Orr_V, InstEmit.Orr_V, typeof(OpCodeSimdReg));
|
||||
SetA64("0x00111100000xxx<<x101xxxxxxxxxx", InstName.Orr_Vi, InstEmit.Orr_Vi, typeof(OpCodeSimdImm));
|
||||
SetA64("0x00111100000xxx0xx101xxxxxxxxxx", InstName.Orr_Vi, InstEmit.Orr_Vi, typeof(OpCodeSimdImm));
|
||||
SetA64("0x00111100000xxx10x101xxxxxxxxxx", InstName.Orr_Vi, InstEmit.Orr_Vi, typeof(OpCodeSimdImm));
|
||||
SetA64("0x101110<<1xxxxx010000xxxxxxxxxx", InstName.Raddhn_V, InstEmit.Raddhn_V, typeof(OpCodeSimdReg));
|
||||
SetA64("0x10111001100000010110xxxxxxxxxx", InstName.Rbit_V, InstEmit.Rbit_V, typeof(OpCodeSimd));
|
||||
SetA64("0x00111000100000000110xxxxxxxxxx", InstName.Rev16_V, InstEmit.Rev16_V, typeof(OpCodeSimd));
|
||||
|
@ -432,7 +437,8 @@ namespace ARMeilleure.Decoders
|
|||
SetA64("0x101110<<100001001110xxxxxxxxxx", InstName.Shll_V, InstEmit.Shll_V, typeof(OpCodeSimd));
|
||||
SetA64("0x00111100>>>xxx100001xxxxxxxxxx", InstName.Shrn_V, InstEmit.Shrn_V, typeof(OpCodeSimdShImm));
|
||||
SetA64("0x001110<<1xxxxx001001xxxxxxxxxx", InstName.Shsub_V, InstEmit.Shsub_V, typeof(OpCodeSimdReg));
|
||||
SetA64("0x1011110>>>>xxx010101xxxxxxxxxx", InstName.Sli_V, InstEmit.Sli_V, typeof(OpCodeSimdShImm));
|
||||
SetA64("0x10111100>>>xxx010101xxxxxxxxxx", InstName.Sli_V, InstEmit.Sli_V, typeof(OpCodeSimdShImm));
|
||||
SetA64("0110111101xxxxxx010101xxxxxxxxxx", InstName.Sli_V, InstEmit.Sli_V, typeof(OpCodeSimdShImm));
|
||||
SetA64("0x001110<<1xxxxx011001xxxxxxxxxx", InstName.Smax_V, InstEmit.Smax_V, typeof(OpCodeSimdReg));
|
||||
SetA64("0x001110<<1xxxxx101001xxxxxxxxxx", InstName.Smaxp_V, InstEmit.Smaxp_V, typeof(OpCodeSimdReg));
|
||||
SetA64("000011100x110000101010xxxxxxxxxx", InstName.Smaxv_V, InstEmit.Smaxv_V, typeof(OpCodeSimd));
|
||||
|
@ -770,8 +776,7 @@ namespace ARMeilleure.Decoders
|
|||
}
|
||||
}
|
||||
|
||||
//TODO: Change null with Und impl.
|
||||
return (new InstDescriptor(InstName.Und, null), typeof(OpCode));
|
||||
return (new InstDescriptor(InstName.Und, InstEmit.Und), typeof(OpCode));
|
||||
}
|
||||
|
||||
private static int ToFastLookupIndex(int value)
|
||||
|
|
|
@ -109,6 +109,11 @@ namespace ARMeilleure.Diagnostics
|
|||
|
||||
private static string GetOperandName(Operand operand, Dictionary<Operand, string> localNames)
|
||||
{
|
||||
if (operand == null)
|
||||
{
|
||||
return "<NULL>";
|
||||
}
|
||||
|
||||
string name = string.Empty;
|
||||
|
||||
if (operand.Kind == OperandKind.LocalVariable)
|
||||
|
|
|
@ -25,7 +25,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (context.CurrOp.RegisterSize == RegisterSize.Int64)
|
||||
{
|
||||
carry = context.Copy(Local(OperandType.I64), carry);
|
||||
carry = context.ZeroExtend32(OperandType.I64, carry);
|
||||
}
|
||||
|
||||
d = context.Add(d, carry);
|
||||
|
@ -107,7 +107,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeAlu op = (OpCodeAlu)context.CurrOp;
|
||||
|
||||
Operand n = GetIntOrZR(op, op.Rn);
|
||||
Operand n = GetIntOrZR(context, op.Rn);
|
||||
|
||||
Operand nHigh = context.ShiftRightUI(n, Const(1));
|
||||
|
||||
|
@ -128,7 +128,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeAlu op = (OpCodeAlu)context.CurrOp;
|
||||
|
||||
Operand n = GetIntOrZR(op, op.Rn);
|
||||
Operand n = GetIntOrZR(context, op.Rn);
|
||||
|
||||
Operand d = context.CountLeadingZeros(n);
|
||||
|
||||
|
@ -154,7 +154,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeAluRs op = (OpCodeAluRs)context.CurrOp;
|
||||
|
||||
Operand res = GetIntOrZR(op, op.Rm);
|
||||
Operand res = GetIntOrZR(context, op.Rm);
|
||||
|
||||
if (op.Shift != 0)
|
||||
{
|
||||
|
@ -166,7 +166,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
res = context.ShiftRightUI(res, Const(op.Shift));
|
||||
|
||||
Operand n = GetIntOrZR(op, op.Rn);
|
||||
Operand n = GetIntOrZR(context, op.Rn);
|
||||
|
||||
int invShift = op.GetBitsCount() - op.Shift;
|
||||
|
||||
|
@ -201,7 +201,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (context.CurrOp.RegisterSize == RegisterSize.Int64)
|
||||
{
|
||||
borrow = context.Copy(Local(OperandType.I64), borrow);
|
||||
borrow = context.ZeroExtend32(OperandType.I64, borrow);
|
||||
}
|
||||
|
||||
d = context.Subtract(d, borrow);
|
||||
|
@ -264,7 +264,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeAlu op = (OpCodeAlu)context.CurrOp;
|
||||
|
||||
Operand n = GetIntOrZR(op, op.Rn);
|
||||
Operand n = GetIntOrZR(context, op.Rn);
|
||||
|
||||
if (op.RegisterSize == RegisterSize.Int32)
|
||||
{
|
||||
|
@ -280,7 +280,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeAlu op = (OpCodeAlu)context.CurrOp;
|
||||
|
||||
Operand n = GetIntOrZR(op, op.Rn);
|
||||
Operand n = GetIntOrZR(context, op.Rn);
|
||||
Operand d;
|
||||
|
||||
if (op.RegisterSize == RegisterSize.Int32)
|
||||
|
@ -299,7 +299,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeAlu op = (OpCodeAlu)context.CurrOp;
|
||||
|
||||
SetAluDOrZR(context, context.ByteSwap(GetIntOrZR(op, op.Rn)));
|
||||
SetAluDOrZR(context, context.ByteSwap(GetIntOrZR(context, op.Rn)));
|
||||
}
|
||||
|
||||
public static void Rorv(EmitterContext context)
|
||||
|
@ -311,11 +311,11 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
IOpCodeAluRs op = (IOpCodeAluRs)context.CurrOp;
|
||||
|
||||
Operand m = GetIntOrZR(op, op.Rm);
|
||||
Operand m = GetIntOrZR(context, op.Rm);
|
||||
|
||||
if (op.RegisterSize == RegisterSize.Int64)
|
||||
{
|
||||
m = context.Copy(Local(OperandType.I32), m);
|
||||
m = context.ConvertI64ToI32(m);
|
||||
}
|
||||
|
||||
return context.BitwiseAnd(m, Const(context.CurrOp.GetBitsCount() - 1));
|
||||
|
@ -352,7 +352,7 @@ namespace ARMeilleure.Instructions
|
|||
return;
|
||||
}
|
||||
|
||||
context.Copy(GetIntOrSP(op, op.Rd), d);
|
||||
SetIntOrSP(context, op.Rd, d);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,11 +77,11 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (op.DataOp == DataOp.Logical || op is IOpCodeAluRs)
|
||||
{
|
||||
return GetIntOrZR(op, op.Rn);
|
||||
return GetIntOrZR(context, op.Rn);
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetIntOrSP(op, op.Rn);
|
||||
return GetIntOrSP(context, op.Rn);
|
||||
}
|
||||
}
|
||||
else if (context.CurrOp is IOpCode32Alu op32)
|
||||
|
@ -128,7 +128,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
case IOpCodeAluRs op:
|
||||
{
|
||||
Operand value = GetIntOrZR(op, op.Rm);
|
||||
Operand value = GetIntOrZR(context, op.Rm);
|
||||
|
||||
switch (op.ShiftType)
|
||||
{
|
||||
|
|
|
@ -13,8 +13,8 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeBfm op = (OpCodeBfm)context.CurrOp;
|
||||
|
||||
Operand d = GetIntOrZR(op, op.Rd);
|
||||
Operand n = GetIntOrZR(op, op.Rn);
|
||||
Operand d = GetIntOrZR(context, op.Rd);
|
||||
Operand n = GetIntOrZR(context, op.Rn);
|
||||
|
||||
Operand res;
|
||||
|
||||
|
@ -64,25 +64,25 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else if (op.Pos == 7 && op.Shift == 0)
|
||||
{
|
||||
Operand n = GetIntOrZR(op, op.Rn);
|
||||
Operand n = GetIntOrZR(context, op.Rn);
|
||||
|
||||
SetIntOrZR(context, op.Rd, context.SignExtend8(n));
|
||||
SetIntOrZR(context, op.Rd, context.SignExtend8(n.Type, n));
|
||||
}
|
||||
else if (op.Pos == 15 && op.Shift == 0)
|
||||
{
|
||||
Operand n = GetIntOrZR(op, op.Rn);
|
||||
Operand n = GetIntOrZR(context, op.Rn);
|
||||
|
||||
SetIntOrZR(context, op.Rd, context.SignExtend16(n));
|
||||
SetIntOrZR(context, op.Rd, context.SignExtend16(n.Type, n));
|
||||
}
|
||||
else if (op.Pos == 31 && op.Shift == 0)
|
||||
{
|
||||
Operand n = GetIntOrZR(op, op.Rn);
|
||||
Operand n = GetIntOrZR(context, op.Rn);
|
||||
|
||||
SetIntOrZR(context, op.Rd, context.SignExtend32(n));
|
||||
SetIntOrZR(context, op.Rd, context.SignExtend32(n.Type, n));
|
||||
}
|
||||
else
|
||||
{
|
||||
Operand res = GetIntOrZR(op, op.Rn);
|
||||
Operand res = GetIntOrZR(context, op.Rn);
|
||||
|
||||
res = context.ShiftLeft (res, Const(bitsCount - 1 - op.Pos));
|
||||
res = context.ShiftRightSI(res, Const(bitsCount - 1));
|
||||
|
@ -112,13 +112,13 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else if (op.Pos == 7 && op.Shift == 0)
|
||||
{
|
||||
Operand n = GetIntOrZR(op, op.Rn);
|
||||
Operand n = GetIntOrZR(context, op.Rn);
|
||||
|
||||
SetIntOrZR(context, op.Rd, context.BitwiseAnd(n, Const(n.Type, 0xff)));
|
||||
}
|
||||
else if (op.Pos == 15 && op.Shift == 0)
|
||||
{
|
||||
Operand n = GetIntOrZR(op, op.Rn);
|
||||
Operand n = GetIntOrZR(context, op.Rn);
|
||||
|
||||
SetIntOrZR(context, op.Rd, context.BitwiseAnd(n, Const(n.Type, 0xffff)));
|
||||
}
|
||||
|
@ -137,7 +137,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
int width = op.Pos + 1;
|
||||
|
||||
Operand res = GetIntOrZR(op, op.Rn);
|
||||
Operand res = GetIntOrZR(context, op.Rn);
|
||||
|
||||
res = context.ShiftLeft(res, Const(op.GetBitsCount() - width));
|
||||
|
||||
|
@ -162,7 +162,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeBfm op = (OpCodeBfm)context.CurrOp;
|
||||
|
||||
Operand res = GetIntOrZR(op, op.Rn);
|
||||
Operand res = GetIntOrZR(context, op.Rn);
|
||||
|
||||
res = signed
|
||||
? context.ShiftRightSI(res, Const(op.Shift))
|
||||
|
@ -175,7 +175,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeBfm op = (OpCodeBfm)context.CurrOp;
|
||||
|
||||
Operand res = GetIntOrZR(op, op.Rn);
|
||||
Operand res = GetIntOrZR(context, op.Rn);
|
||||
|
||||
int shift = op.GetBitsCount() - op.Shift;
|
||||
|
||||
|
@ -186,7 +186,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeBfm op = (OpCodeBfm)context.CurrOp;
|
||||
|
||||
Operand res = GetIntOrZR(op, op.Rn);
|
||||
Operand res = GetIntOrZR(context, op.Rn);
|
||||
|
||||
long mask = op.WMask & op.TMask;
|
||||
|
||||
|
|
|
@ -27,8 +27,8 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeCsel op = (OpCodeCsel)context.CurrOp;
|
||||
|
||||
Operand n = GetIntOrZR(op, op.Rn);
|
||||
Operand m = GetIntOrZR(op, op.Rm);
|
||||
Operand n = GetIntOrZR(context, op.Rn);
|
||||
Operand m = GetIntOrZR(context, op.Rm);
|
||||
|
||||
if (cselOp == CselOperation.Increment)
|
||||
{
|
||||
|
|
|
@ -17,8 +17,8 @@ namespace ARMeilleure.Instructions
|
|||
OpCodeAluBinary op = (OpCodeAluBinary)context.CurrOp;
|
||||
|
||||
//If Rm == 0, Rd = 0 (division by zero).
|
||||
Operand n = GetIntOrZR(op, op.Rn);
|
||||
Operand m = GetIntOrZR(op, op.Rm);
|
||||
Operand n = GetIntOrZR(context, op.Rn);
|
||||
Operand m = GetIntOrZR(context, op.Rm);
|
||||
|
||||
Operand divisorIsZero = context.ICompareEqual(m, Const(m.Type, 0));
|
||||
|
||||
|
|
|
@ -24,8 +24,12 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
MethodInfo info = typeof(NativeInterface).GetMethod(mthdName);
|
||||
|
||||
context.StoreToContext();
|
||||
|
||||
context.Call(info, Const(op.Address), Const(op.Id));
|
||||
|
||||
context.LoadFromContext();
|
||||
|
||||
if (context.CurrBlock.Next == null)
|
||||
{
|
||||
context.Return(Const(op.Address + 4));
|
||||
|
@ -38,8 +42,12 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
MethodInfo info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.Undefined));
|
||||
|
||||
context.StoreToContext();
|
||||
|
||||
context.Call(info, Const(op.Address), Const(op.RawOpCode));
|
||||
|
||||
context.LoadFromContext();
|
||||
|
||||
if (context.CurrBlock.Next == null)
|
||||
{
|
||||
context.Return(Const(op.Address + 4));
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeBImmAl op = (OpCodeBImmAl)context.CurrOp;
|
||||
|
||||
context.Copy(GetIntOrZR(op, RegisterAlias.Lr), Const(op.Address + 4));
|
||||
context.Copy(GetIntOrZR(context, RegisterAlias.Lr), Const(op.Address + 4));
|
||||
|
||||
EmitCall(context, (ulong)op.Immediate);
|
||||
}
|
||||
|
@ -45,9 +45,9 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeBReg op = (OpCodeBReg)context.CurrOp;
|
||||
|
||||
Operand n = context.Copy(GetIntOrZR(op, op.Rn));
|
||||
Operand n = context.Copy(GetIntOrZR(context, op.Rn));
|
||||
|
||||
context.Copy(GetIntOrZR(op, RegisterAlias.Lr), Const(op.Address + 4));
|
||||
context.Copy(GetIntOrZR(context, RegisterAlias.Lr), Const(op.Address + 4));
|
||||
|
||||
EmitVirtualCall(context, n);
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeBReg op = (OpCodeBReg)context.CurrOp;
|
||||
|
||||
EmitVirtualJump(context, GetIntOrZR(op, op.Rn));
|
||||
EmitVirtualJump(context, GetIntOrZR(context, op.Rn));
|
||||
}
|
||||
|
||||
public static void Cbnz(EmitterContext context) => EmitCb(context, onNotZero: true);
|
||||
|
@ -66,12 +66,12 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeBImmCmp op = (OpCodeBImmCmp)context.CurrOp;
|
||||
|
||||
EmitBranch(context, GetIntOrZR(op, op.Rt), onNotZero);
|
||||
EmitBranch(context, GetIntOrZR(context, op.Rt), onNotZero);
|
||||
}
|
||||
|
||||
public static void Ret(EmitterContext context)
|
||||
{
|
||||
context.Return(GetIntOrZR(context.CurrOp, RegisterAlias.Lr));
|
||||
context.Return(GetIntOrZR(context, RegisterAlias.Lr));
|
||||
}
|
||||
|
||||
public static void Tbnz(EmitterContext context) => EmitTb(context, onNotZero: true);
|
||||
|
@ -81,7 +81,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeBImmTest op = (OpCodeBImmTest)context.CurrOp;
|
||||
|
||||
Operand value = context.BitwiseAnd(GetIntOrZR(op, op.Rt), Const(1L << op.Bit));
|
||||
Operand value = context.BitwiseAnd(GetIntOrZR(context, op.Rt), Const(1L << op.Bit));
|
||||
|
||||
EmitBranch(context, value, onNotZero);
|
||||
}
|
||||
|
|
|
@ -55,8 +55,8 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
MethodInfo info = typeof(SoftFallback).GetMethod(name);
|
||||
|
||||
Operand n = GetIntOrZR(op, op.Rn);
|
||||
Operand m = GetIntOrZR(op, op.Rm);
|
||||
Operand n = GetIntOrZR(context, op.Rn);
|
||||
Operand m = GetIntOrZR(context, op.Rm);
|
||||
|
||||
Operand d = context.Call(info, n, m);
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ using ARMeilleure.IntermediateRepresentation;
|
|||
using ARMeilleure.State;
|
||||
using ARMeilleure.Translation;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
|
||||
|
||||
|
@ -17,37 +18,22 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static Operand GetExtendedM(EmitterContext context, int rm, IntType type)
|
||||
{
|
||||
Operand value = GetIntOrZR(context.CurrOp, rm);
|
||||
Operand value = GetIntOrZR(context, rm);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case IntType.UInt8: value = ZeroExtend8 (context, value); break;
|
||||
case IntType.UInt16: value = ZeroExtend16(context, value); break;
|
||||
case IntType.UInt32: value = ZeroExtend32(context, value); break;
|
||||
case IntType.UInt8: value = context.ZeroExtend8 (value.Type, value); break;
|
||||
case IntType.UInt16: value = context.ZeroExtend16(value.Type, value); break;
|
||||
case IntType.UInt32: value = context.ZeroExtend32(value.Type, value); break;
|
||||
|
||||
case IntType.Int8: value = context.SignExtend8 (value); break;
|
||||
case IntType.Int16: value = context.SignExtend16(value); break;
|
||||
case IntType.Int32: value = context.SignExtend32(value); break;
|
||||
case IntType.Int8: value = context.SignExtend8 (value.Type, value); break;
|
||||
case IntType.Int16: value = context.SignExtend16(value.Type, value); break;
|
||||
case IntType.Int32: value = context.SignExtend32(value.Type, value); break;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public static Operand ZeroExtend8(EmitterContext context, Operand value)
|
||||
{
|
||||
return context.BitwiseAnd(value, Const(value.Type, 0xff));
|
||||
}
|
||||
|
||||
public static Operand ZeroExtend16(EmitterContext context, Operand value)
|
||||
{
|
||||
return context.BitwiseAnd(value, Const(value.Type, 0xffff));
|
||||
}
|
||||
|
||||
public static Operand ZeroExtend32(EmitterContext context, Operand value)
|
||||
{
|
||||
return context.BitwiseAnd(value, Const(value.Type, 0xffffffff));
|
||||
}
|
||||
|
||||
public static Operand GetIntA32(EmitterContext context, int register)
|
||||
{
|
||||
if (register == RegisterAlias.Aarch32Pc)
|
||||
|
@ -58,7 +44,7 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
else
|
||||
{
|
||||
return GetIntOrSP(context.CurrOp, GetRegisterAlias(context.Mode, register));
|
||||
return GetIntOrSP(context, GetRegisterAlias(context.Mode, register));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,20 +132,22 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
}
|
||||
|
||||
public static Operand GetIntOrZR(IOpCode op, int regIndex)
|
||||
public static Operand GetIntOrZR(EmitterContext context, int regIndex)
|
||||
{
|
||||
OperandType type = op.GetOperandType();
|
||||
|
||||
if (regIndex == RegisterConsts.ZeroIndex)
|
||||
{
|
||||
OperandType type = context.CurrOp.GetOperandType();
|
||||
|
||||
return type == OperandType.I32 ? Const(0) : Const(0L);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Register(regIndex, RegisterType.Integer, type);
|
||||
return GetIntOrSP(context, regIndex);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool FullDebug = false;
|
||||
|
||||
public static void SetIntOrZR(EmitterContext context, int regIndex, Operand value)
|
||||
{
|
||||
if (regIndex == RegisterConsts.ZeroIndex)
|
||||
|
@ -167,12 +155,31 @@ namespace ARMeilleure.Instructions
|
|||
return;
|
||||
}
|
||||
|
||||
context.Copy(GetIntOrSP(context.CurrOp, regIndex), value);
|
||||
SetIntOrSP(context, regIndex, value);
|
||||
}
|
||||
|
||||
public static Operand GetIntOrSP(IOpCode op, int regIndex)
|
||||
public static Operand GetIntOrSP(EmitterContext context, int regIndex)
|
||||
{
|
||||
return Register(regIndex, RegisterType.Integer, op.GetOperandType());
|
||||
Operand value = Register(regIndex, RegisterType.Integer, OperandType.I64);
|
||||
|
||||
if (context.CurrOp.RegisterSize == RegisterSize.Int32)
|
||||
{
|
||||
value = context.ConvertI64ToI32(value);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public static void SetIntOrSP(EmitterContext context, int regIndex, Operand value)
|
||||
{
|
||||
Operand reg = Register(regIndex, RegisterType.Integer, OperandType.I64);
|
||||
|
||||
if (value.Type == OperandType.I32)
|
||||
{
|
||||
value = context.ZeroExtend32(OperandType.I64, value);
|
||||
}
|
||||
|
||||
context.Copy(reg, value);
|
||||
}
|
||||
|
||||
public static Operand GetVec(int regIndex)
|
||||
|
|
|
@ -129,7 +129,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
case OpCodeMemImm op:
|
||||
{
|
||||
address = context.Copy(GetIntOrSP(op, op.Rn));
|
||||
address = context.Copy(GetIntOrSP(context, op.Rn));
|
||||
|
||||
//Pre-indexing.
|
||||
if (!op.PostIdx)
|
||||
|
@ -142,7 +142,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
case OpCodeMemReg op:
|
||||
{
|
||||
Operand n = GetIntOrSP(op, op.Rn);
|
||||
Operand n = GetIntOrSP(context, op.Rn);
|
||||
|
||||
Operand m = GetExtendedM(context, op.Rm, op.IntType);
|
||||
|
||||
|
@ -170,7 +170,7 @@ namespace ARMeilleure.Instructions
|
|||
address = context.Add(address, Const(op.Immediate));
|
||||
}
|
||||
|
||||
context.Copy(GetIntOrSP(op, op.Rn), address);
|
||||
SetIntOrSP(context, op.Rn, address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ namespace ARMeilleure.Instructions
|
|||
EmitBarrier(context);
|
||||
}
|
||||
|
||||
Operand address = context.Copy(GetIntOrSP(op, op.Rn));
|
||||
Operand address = context.Copy(GetIntOrSP(context, op.Rn));
|
||||
|
||||
if (pair)
|
||||
{
|
||||
|
@ -71,9 +71,9 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
Operand value = EmitLoad(context, address, exclusive, 3);
|
||||
|
||||
Operand valueLow = context.Copy(Local(OperandType.I32), value);
|
||||
Operand valueLow = context.ConvertI64ToI32(value);
|
||||
|
||||
valueLow = context.Copy(Local(OperandType.I64), valueLow);
|
||||
valueLow = context.ZeroExtend32(OperandType.I64, valueLow);
|
||||
|
||||
Operand valueHigh = context.ShiftRightUI(value, Const(32));
|
||||
|
||||
|
@ -173,9 +173,9 @@ namespace ARMeilleure.Instructions
|
|||
EmitBarrier(context);
|
||||
}
|
||||
|
||||
Operand address = context.Copy(GetIntOrSP(op, op.Rn));
|
||||
Operand address = context.Copy(GetIntOrSP(context, op.Rn));
|
||||
|
||||
Operand t = GetIntOrZR(op, op.Rt);
|
||||
Operand t = GetIntOrZR(context, op.Rt);
|
||||
|
||||
Operand s = null;
|
||||
|
||||
|
@ -183,7 +183,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
Debug.Assert(op.Size == 2 || op.Size == 3, "Invalid size for pairwise store.");
|
||||
|
||||
Operand t2 = GetIntOrZR(op, op.Rt2);
|
||||
Operand t2 = GetIntOrZR(context, op.Rt2);
|
||||
|
||||
Operand value;
|
||||
|
||||
|
@ -221,7 +221,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
if (size < 3)
|
||||
{
|
||||
value = context.Copy(Local(OperandType.I32), value);
|
||||
value = context.ConvertI64ToI32(value);
|
||||
}
|
||||
|
||||
string fallbackMethodName = null;
|
||||
|
@ -254,6 +254,8 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
MethodInfo info = typeof(NativeInterface).GetMethod(fallbackMethodName);
|
||||
|
||||
context.Call(info, address, value);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,8 +13,6 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
static class InstEmitMemoryHelper
|
||||
{
|
||||
private static bool ForceFallback = true;
|
||||
|
||||
private enum Extension
|
||||
{
|
||||
Zx,
|
||||
|
@ -48,47 +46,30 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (isSimd)
|
||||
{
|
||||
if (ForceFallback || !Optimizations.UseSse2 || size < 2)
|
||||
{
|
||||
EmitReadVectorFallback(context, address, context.VectorZero(), rt, 0, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitReadVector(context, address, context.VectorZero(), rt, 0, size);
|
||||
}
|
||||
EmitReadVector(context, address, context.VectorZero(), rt, 0, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ForceFallback)
|
||||
{
|
||||
EmitReadIntFallback(context, address, rt, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitReadInt(context, address, rt, size);
|
||||
}
|
||||
EmitReadInt(context, address, rt, size);
|
||||
}
|
||||
|
||||
if (!isSimd)
|
||||
{
|
||||
Operand value = GetT(context, rt);
|
||||
|
||||
if (ext == Extension.Sx64)
|
||||
{
|
||||
value = context.Copy(Local(OperandType.I64), value);
|
||||
}
|
||||
Operand value = GetIntOrZR(context, rt);
|
||||
|
||||
if (ext == Extension.Sx32 || ext == Extension.Sx64)
|
||||
{
|
||||
OperandType destType = ext == Extension.Sx64 ? OperandType.I64 : OperandType.I32;
|
||||
|
||||
switch (size)
|
||||
{
|
||||
case 0: value = context.SignExtend8 (value); break;
|
||||
case 1: value = context.SignExtend16(value); break;
|
||||
case 2: value = context.SignExtend32(value); break;
|
||||
case 0: value = context.SignExtend8 (destType, value); break;
|
||||
case 1: value = context.SignExtend16(destType, value); break;
|
||||
case 2: value = context.SignExtend32(destType, value); break;
|
||||
}
|
||||
}
|
||||
|
||||
context.Copy(GetT(context, rt), value);
|
||||
SetIntOrZR(context, rt, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,14 +81,7 @@ namespace ARMeilleure.Instructions
|
|||
int elem,
|
||||
int size)
|
||||
{
|
||||
if (ForceFallback || !Optimizations.UseSse2 || size < 2)
|
||||
{
|
||||
EmitReadVectorFallback(context, address, vector, rt, elem, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitReadVector(context, address, vector, rt, elem, size);
|
||||
}
|
||||
EmitReadVector(context, address, vector, rt, elem, size);
|
||||
}
|
||||
|
||||
public static void EmitStore(EmitterContext context, Operand address, int rt, int size)
|
||||
|
@ -121,25 +95,11 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (isSimd)
|
||||
{
|
||||
if (ForceFallback || !Optimizations.UseSse2 || size < 2)
|
||||
{
|
||||
EmitWriteVectorFallback(context, address, rt, 0, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitWriteVector(context, address, rt, 0, size);
|
||||
}
|
||||
EmitWriteVector(context, address, rt, 0, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ForceFallback)
|
||||
{
|
||||
EmitWriteIntFallback(context, address, rt, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitWriteInt(context, address, rt, size);
|
||||
}
|
||||
EmitWriteInt(context, address, rt, size);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -150,14 +110,7 @@ namespace ARMeilleure.Instructions
|
|||
int elem,
|
||||
int size)
|
||||
{
|
||||
if (ForceFallback || !Optimizations.UseSse2 || size < 2)
|
||||
{
|
||||
EmitWriteVectorFallback(context, address, rt, elem, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
EmitWriteVector(context, address, rt, elem, size);
|
||||
}
|
||||
EmitWriteVector(context, address, rt, elem, size);
|
||||
}
|
||||
|
||||
private static bool IsSimd(EmitterContext context)
|
||||
|
@ -197,7 +150,7 @@ namespace ARMeilleure.Instructions
|
|||
case 3: value = context.Load (Local(OperandType.I64), physAddr); break;
|
||||
}
|
||||
|
||||
context.Copy(GetT(context, rt), value);
|
||||
SetIntOrZR(context, rt, value);
|
||||
|
||||
context.MarkLabel(lblEnd);
|
||||
}
|
||||
|
@ -230,29 +183,39 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand value = null;
|
||||
|
||||
/*switch (size)
|
||||
switch (size)
|
||||
{
|
||||
case 2: context.EmitCall(typeof(Sse), nameof(Sse.LoadScalarVector128)); break;
|
||||
case 0:
|
||||
value = context.VectorInsert8(vector, context.LoadZx8(Local(OperandType.I32), physAddr), elem);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
value = context.VectorInsert16(vector, context.LoadZx16(Local(OperandType.I32), physAddr), elem);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
value = context.VectorInsert(vector, context.Load(Local(OperandType.I32), physAddr), elem);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
{
|
||||
Type[] types = new Type[] { typeof(double*) };
|
||||
|
||||
context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.LoadScalarVector128), types));
|
||||
|
||||
value = context.VectorInsert(vector, context.Load(Local(OperandType.I64), physAddr), elem);
|
||||
break;
|
||||
}
|
||||
|
||||
case 4: context.EmitCall(typeof(Sse), nameof(Sse.LoadAlignedVector128)); break;
|
||||
|
||||
throw new InvalidOperationException($"Invalid vector load size of {1 << size} bytes.");
|
||||
}*/
|
||||
case 4:
|
||||
value = context.Load(Local(OperandType.V128), physAddr);
|
||||
break;
|
||||
}
|
||||
|
||||
context.Copy(GetVec(rt), value);
|
||||
|
||||
context.MarkLabel(lblEnd);
|
||||
}
|
||||
|
||||
private static Operand VectorCreate(EmitterContext context, Operand value)
|
||||
{
|
||||
return context.VectorInsert(context.VectorZero(), value, 0);
|
||||
}
|
||||
|
||||
private static void EmitWriteInt(EmitterContext context, Operand address, int rt, int size)
|
||||
{
|
||||
Operand isUnalignedAddr = EmitAddressCheck(context, address, size);
|
||||
|
@ -273,11 +236,11 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand physAddr = EmitPtPointerLoad(context, address, lblSlowPath);
|
||||
|
||||
Operand value = GetT(context, rt);
|
||||
Operand value = GetIntOrZR(context, rt);
|
||||
|
||||
if (size < 3)
|
||||
{
|
||||
value = context.Copy(Local(OperandType.I32), value);
|
||||
value = context.ConvertI64ToI32(value);
|
||||
}
|
||||
|
||||
switch (size)
|
||||
|
@ -318,14 +281,28 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand value = GetVec(rt);
|
||||
|
||||
/*switch (size)
|
||||
switch (size)
|
||||
{
|
||||
case 2: context.EmitCall(typeof(Sse), nameof(Sse.StoreScalar)); break;
|
||||
case 3: context.EmitCall(typeof(Sse2), nameof(Sse2.StoreScalar)); break;
|
||||
case 4: context.EmitCall(typeof(Sse), nameof(Sse.StoreAligned)); break;
|
||||
case 0:
|
||||
context.Store8(physAddr, context.VectorExtract8(value, Local(OperandType.I32), elem));
|
||||
break;
|
||||
|
||||
default: throw new InvalidOperationException($"Invalid vector store size of {1 << size} bytes.");
|
||||
}*/
|
||||
case 1:
|
||||
context.Store16(physAddr, context.VectorExtract16(value, Local(OperandType.I32), elem));
|
||||
break;
|
||||
|
||||
case 2:
|
||||
context.Store(physAddr, context.VectorExtract(value, Local(OperandType.FP32), elem));
|
||||
break;
|
||||
|
||||
case 3:
|
||||
context.Store(physAddr, context.VectorExtract(value, Local(OperandType.FP64), elem));
|
||||
break;
|
||||
|
||||
case 4:
|
||||
context.Store(physAddr, value);
|
||||
break;
|
||||
}
|
||||
|
||||
context.MarkLabel(lblEnd);
|
||||
}
|
||||
|
@ -392,7 +369,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
MethodInfo info = typeof(NativeInterface).GetMethod(fallbackMethodName);
|
||||
|
||||
context.Copy(GetT(context, rt), context.Call(info, address));
|
||||
SetIntOrZR(context, rt, context.Call(info, address));
|
||||
}
|
||||
|
||||
private static void EmitReadVectorFallback(
|
||||
|
@ -420,7 +397,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (size < 3)
|
||||
{
|
||||
value = context.Copy(Local(OperandType.I32), value);
|
||||
value = context.ConvertI64ToI32(value);
|
||||
}
|
||||
|
||||
switch (size)
|
||||
|
@ -448,11 +425,11 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
MethodInfo info = typeof(NativeInterface).GetMethod(fallbackMethodName);
|
||||
|
||||
Operand value = GetT(context, rt);
|
||||
Operand value = GetIntOrZR(context, rt);
|
||||
|
||||
if (size < 3)
|
||||
{
|
||||
value = context.Copy(Local(OperandType.I32), value);
|
||||
value = context.ConvertI64ToI32(value);
|
||||
}
|
||||
|
||||
context.Call(info, address, value);
|
||||
|
@ -499,32 +476,5 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
context.Call(info, address, value);
|
||||
}
|
||||
|
||||
private static Operand GetT(EmitterContext context, int rt)
|
||||
{
|
||||
OpCode op = context.CurrOp;
|
||||
|
||||
if (op is IOpCodeSimd)
|
||||
{
|
||||
return GetVec(rt);
|
||||
}
|
||||
else if (op is OpCodeMem opMem)
|
||||
{
|
||||
bool is32Bits = opMem.Size < 3 && !opMem.Extend64;
|
||||
|
||||
OperandType type = is32Bits ? OperandType.I32 : OperandType.I64;
|
||||
|
||||
if (rt == RegisterConsts.ZeroIndex)
|
||||
{
|
||||
return Const(type, 0);
|
||||
}
|
||||
|
||||
return Register(rt, RegisterType.Integer, type);
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetIntOrZR(context.CurrOp, rt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,7 +15,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
OperandType type = op.GetOperandType();
|
||||
|
||||
Operand res = GetIntOrZR(op, op.Rd);
|
||||
Operand res = GetIntOrZR(context, op.Rd);
|
||||
|
||||
res = context.BitwiseAnd(res, Const(type, ~(0xffffL << op.Bit)));
|
||||
|
||||
|
|
|
@ -16,9 +16,9 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeMul op = (OpCodeMul)context.CurrOp;
|
||||
|
||||
Operand a = GetIntOrZR(op, op.Ra);
|
||||
Operand n = GetIntOrZR(op, op.Rn);
|
||||
Operand m = GetIntOrZR(op, op.Rm);
|
||||
Operand a = GetIntOrZR(context, op.Ra);
|
||||
Operand n = GetIntOrZR(context, op.Rn);
|
||||
Operand m = GetIntOrZR(context, op.Rm);
|
||||
|
||||
Operand res = context.Multiply(n, m);
|
||||
|
||||
|
@ -49,19 +49,19 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand GetExtendedRegister32(int index)
|
||||
{
|
||||
Operand value = GetIntOrZR(op, index);
|
||||
Operand value = GetIntOrZR(context, index);
|
||||
|
||||
if ((flags & MullFlags.Signed) != 0)
|
||||
{
|
||||
return context.SignExtend32(value);
|
||||
return context.SignExtend32(value.Type, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ZeroExtend32(context, value);
|
||||
return context.ZeroExtend32(value.Type, value);
|
||||
}
|
||||
}
|
||||
|
||||
Operand a = GetIntOrZR(op, op.Ra);
|
||||
Operand a = GetIntOrZR(context, op.Ra);
|
||||
|
||||
Operand n = GetExtendedRegister32(op.Rn);
|
||||
Operand m = GetExtendedRegister32(op.Rm);
|
||||
|
@ -77,8 +77,8 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeMul op = (OpCodeMul)context.CurrOp;
|
||||
|
||||
Operand n = GetIntOrZR(op, op.Rn);
|
||||
Operand m = GetIntOrZR(op, op.Rm);
|
||||
Operand n = GetIntOrZR(context, op.Rn);
|
||||
Operand m = GetIntOrZR(context, op.Rm);
|
||||
|
||||
Operand d = context.Multiply64HighSI(n, m);
|
||||
|
||||
|
@ -89,8 +89,8 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeMul op = (OpCodeMul)context.CurrOp;
|
||||
|
||||
Operand n = GetIntOrZR(op, op.Rn);
|
||||
Operand m = GetIntOrZR(op, op.Rm);
|
||||
Operand n = GetIntOrZR(context, op.Rn);
|
||||
Operand m = GetIntOrZR(context, op.Rm);
|
||||
|
||||
Operand d = context.Multiply64HighUI(n, m);
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand res = context.Call(info, ne);
|
||||
|
||||
res = context.Copy(Local(OperandType.I64), res);
|
||||
res = context.ZeroExtend16(OperandType.I64, res);
|
||||
|
||||
context.Copy(GetVec(op.Rd), EmitVectorInsert(context, context.VectorZero(), res, 0, 1));
|
||||
}
|
||||
|
@ -217,7 +217,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand e = context.Call(info, ne);
|
||||
|
||||
e = context.Copy(Local(OperandType.I64), e);
|
||||
e = context.ZeroExtend16(OperandType.I64, e);
|
||||
|
||||
res = EmitVectorInsert(context, res, e, part + index, 1);
|
||||
}
|
||||
|
@ -387,7 +387,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
|
||||
|
||||
Operand res = GetIntOrZR(op, op.Rn);
|
||||
Operand res = GetIntOrZR(context, op.Rn);
|
||||
|
||||
res = EmitFPConvert(context, res, op.Size, signed: true);
|
||||
|
||||
|
@ -398,7 +398,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
|
||||
|
||||
Operand res = GetIntOrZR(op, op.Rn);
|
||||
Operand res = GetIntOrZR(context, op.Rn);
|
||||
|
||||
res = EmitFPConvert(context, res, op.Size, signed: true);
|
||||
|
||||
|
@ -464,7 +464,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
|
||||
|
||||
Operand res = GetIntOrZR(op, op.Rn);
|
||||
Operand res = GetIntOrZR(context, op.Rn);
|
||||
|
||||
res = EmitFPConvert(context, res, op.Size, signed: false);
|
||||
|
||||
|
@ -475,7 +475,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
|
||||
|
||||
Operand res = GetIntOrZR(op, op.Rn);
|
||||
Operand res = GetIntOrZR(context, op.Rn);
|
||||
|
||||
res = EmitFPConvert(context, res, op.Size, signed: false);
|
||||
|
||||
|
@ -568,7 +568,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
e = context.Call(info, e);
|
||||
|
||||
e = context.Copy(Local(OperandType.I64), e);
|
||||
e = context.ZeroExtend32(OperandType.I64, e);
|
||||
}
|
||||
else /* if (sizeF == 1) */
|
||||
{
|
||||
|
@ -620,7 +620,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
e = context.Call(info, e);
|
||||
|
||||
e = context.Copy(Local(OperandType.I64), e);
|
||||
e = context.ZeroExtend32(OperandType.I64, e);
|
||||
}
|
||||
else /* if (sizeF == 1) */
|
||||
{
|
||||
|
@ -661,11 +661,6 @@ namespace ARMeilleure.Instructions
|
|||
? EmitScalarFcvts(context, emit(ne), 0)
|
||||
: EmitScalarFcvtu(context, emit(ne), 0);
|
||||
|
||||
if (context.CurrOp.RegisterSize == RegisterSize.Int32)
|
||||
{
|
||||
res = context.Copy(Local(OperandType.I64), res);
|
||||
}
|
||||
|
||||
SetIntOrZR(context, op.Rd, res);
|
||||
}
|
||||
|
||||
|
@ -691,11 +686,6 @@ namespace ARMeilleure.Instructions
|
|||
? EmitScalarFcvts(context, ne, op.FBits)
|
||||
: EmitScalarFcvtu(context, ne, op.FBits);
|
||||
|
||||
if (context.CurrOp.RegisterSize == RegisterSize.Int32)
|
||||
{
|
||||
res = context.Copy(Local(OperandType.I64), res);
|
||||
}
|
||||
|
||||
SetIntOrZR(context, op.Rd, res);
|
||||
}
|
||||
|
||||
|
|
|
@ -1402,30 +1402,6 @@ namespace ARMeilleure.Instructions
|
|||
return context.Call(typeof(SoftFallback).GetMethod(name), op1, op2);
|
||||
}
|
||||
|
||||
public static Operand EmitVectorExtractSx32(EmitterContext context, int reg, int index, int size)
|
||||
{
|
||||
ThrowIfInvalid(index, size);
|
||||
|
||||
Operand res = Local(OperandType.I32);
|
||||
|
||||
switch (size)
|
||||
{
|
||||
case 0: context.VectorExtract8 (GetVec(reg), res, index); break;
|
||||
case 1: context.VectorExtract16(GetVec(reg), res, index); break;
|
||||
case 2: context.VectorExtract (GetVec(reg), res, index); break;
|
||||
case 3: context.VectorExtract (GetVec(reg), res, index); break;
|
||||
}
|
||||
|
||||
switch (size)
|
||||
{
|
||||
case 0: res = context.SignExtend8 (res); break;
|
||||
case 1: res = context.SignExtend16(res); break;
|
||||
case 2: res = context.SignExtend32(res); break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
public static Operand EmitVectorExtractSx(EmitterContext context, int reg, int index, int size)
|
||||
{
|
||||
return EmitVectorExtract(context, reg, index, size, true);
|
||||
|
@ -1450,15 +1426,22 @@ namespace ARMeilleure.Instructions
|
|||
case 3: context.VectorExtract (GetVec(reg), res, index); break;
|
||||
}
|
||||
|
||||
res = context.Copy(Local(OperandType.I64), res);
|
||||
|
||||
if (signed)
|
||||
{
|
||||
switch (size)
|
||||
{
|
||||
case 0: res = context.SignExtend8 (res); break;
|
||||
case 1: res = context.SignExtend16(res); break;
|
||||
case 2: res = context.SignExtend32(res); break;
|
||||
case 0: res = context.SignExtend8 (OperandType.I64, res); break;
|
||||
case 1: res = context.SignExtend16(OperandType.I64, res); break;
|
||||
case 2: res = context.SignExtend32(OperandType.I64, res); break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (size)
|
||||
{
|
||||
case 0: res = context.ZeroExtend8 (OperandType.I64, res); break;
|
||||
case 1: res = context.ZeroExtend16(OperandType.I64, res); break;
|
||||
case 2: res = context.ZeroExtend32(OperandType.I64, res); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1471,7 +1454,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (size < 3)
|
||||
{
|
||||
value = context.Copy(Local(OperandType.I32), value);
|
||||
value = context.ConvertI64ToI32(value);
|
||||
}
|
||||
|
||||
switch (size)
|
||||
|
|
|
@ -293,13 +293,13 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
Operand ne = EmitVectorExtractZx(context, op.Rn, index, 0);
|
||||
|
||||
ne = context.Copy(Local(OperandType.I32), ne);
|
||||
ne = context.ConvertI64ToI32(ne);
|
||||
|
||||
MethodInfo info = typeof(SoftFallback).GetMethod(nameof(SoftFallback.ReverseBits8));
|
||||
|
||||
Operand de = context.Call(info, ne);
|
||||
|
||||
de = context.Copy(Local(OperandType.I64), de);
|
||||
de = context.ZeroExtend32(OperandType.I64, de);
|
||||
|
||||
res = EmitVectorInsert(context, res, de, index, 0);
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeSimdMemMs op = (OpCodeSimdMemMs)context.CurrOp;
|
||||
|
||||
Operand n = GetIntOrSP(op, op.Rn);
|
||||
Operand n = GetIntOrSP(context, op.Rn);
|
||||
|
||||
long offset = 0;
|
||||
|
||||
|
@ -77,7 +77,7 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeSimdMemSs op = (OpCodeSimdMemSs)context.CurrOp;
|
||||
|
||||
Operand n = GetIntOrSP(op, op.Rn);
|
||||
Operand n = GetIntOrSP(context, op.Rn);
|
||||
|
||||
long offset = 0;
|
||||
|
||||
|
@ -142,12 +142,12 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeMemReg op = (OpCodeMemReg)context.CurrOp;
|
||||
|
||||
Operand n = GetIntOrSP(op, op.Rn);
|
||||
Operand n = GetIntOrSP(context, op.Rn);
|
||||
Operand m;
|
||||
|
||||
if (op.Rm != RegisterAlias.Zr)
|
||||
{
|
||||
m = GetIntOrZR(op, op.Rm);
|
||||
m = GetIntOrZR(context, op.Rm);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -42,15 +42,15 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
OpCodeSimdIns op = (OpCodeSimdIns)context.CurrOp;
|
||||
|
||||
Operand n = GetIntOrZR(op, op.Rn);
|
||||
Operand n = GetIntOrZR(context, op.Rn);
|
||||
|
||||
if (Optimizations.UseSse2)
|
||||
{
|
||||
switch (op.Size)
|
||||
{
|
||||
case 0: n = ZeroExtend8 (context, n); n = context.Multiply(n, Const(0x01010101)); break;
|
||||
case 1: n = ZeroExtend16(context, n); n = context.Multiply(n, Const(0x00010001)); break;
|
||||
case 2: n = ZeroExtend32(context, n); break;
|
||||
case 0: n = context.ZeroExtend8 (n.Type, n); n = context.Multiply(n, Const(0x01010101)); break;
|
||||
case 1: n = context.ZeroExtend16(n.Type, n); n = context.Multiply(n, Const(0x00010001)); break;
|
||||
case 2: n = context.ZeroExtend32(n.Type, n); break;
|
||||
}
|
||||
|
||||
Operand res = context.VectorInsert(context.VectorZero(), n, 0);
|
||||
|
@ -225,10 +225,9 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand isTrue = InstEmitFlowHelper.GetCondTrue(context, op.Cond);
|
||||
|
||||
context.BranchIfTrue(isTrue, lblTrue);
|
||||
context.BranchIfTrue(lblTrue, isTrue);
|
||||
|
||||
OperandType type = op.Size != 0 ? OperandType.FP32
|
||||
: OperandType.FP64;
|
||||
OperandType type = op.Size == 0 ? OperandType.FP32 : OperandType.FP64;
|
||||
|
||||
Operand me = context.VectorExtract(GetVec(op.Rm), Local(type), 0);
|
||||
|
||||
|
@ -247,46 +246,45 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
public static void Fmov_Ftoi(EmitterContext context)
|
||||
{
|
||||
OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
Operand ne = EmitVectorExtractZx(context, op.Rn, 0, 3);
|
||||
Operand ne = EmitVectorExtractZx(context, op.Rn, 0, op.Size + 2);
|
||||
|
||||
SetIntOrZR(context, op.Rd, EmitIntZeroUpperIfNeeded(context, ne));
|
||||
SetIntOrZR(context, op.Rd, ne);
|
||||
}
|
||||
|
||||
public static void Fmov_Ftoi1(EmitterContext context)
|
||||
{
|
||||
OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
Operand ne = EmitVectorExtractZx(context, op.Rn, 1, 3);
|
||||
|
||||
SetIntOrZR(context, op.Rd, EmitIntZeroUpperIfNeeded(context, ne));
|
||||
SetIntOrZR(context, op.Rd, ne);
|
||||
}
|
||||
|
||||
public static void Fmov_Itof(EmitterContext context)
|
||||
{
|
||||
OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
Operand n = EmitIntZeroUpperIfNeeded(context, GetIntOrZR(op, op.Rn));
|
||||
Operand n = GetIntOrZR(context, op.Rn);
|
||||
|
||||
context.Copy(GetVec(op.Rd), EmitVectorInsert(context, context.VectorZero(), n, 0, 3));
|
||||
context.Copy(GetVec(op.Rd), EmitVectorInsert(context, context.VectorZero(), n, 0, op.Size + 2));
|
||||
}
|
||||
|
||||
public static void Fmov_Itof1(EmitterContext context)
|
||||
{
|
||||
OpCodeSimdCvt op = (OpCodeSimdCvt)context.CurrOp;
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
Operand n = EmitIntZeroUpperIfNeeded(context, GetIntOrZR(op, op.Rn));
|
||||
Operand n = GetIntOrZR(context, op.Rn);
|
||||
|
||||
context.Copy(GetVec(op.Rd), EmitVectorInsert(context, context.VectorZero(), n, 1, 3));
|
||||
context.Copy(GetVec(op.Rd), EmitVectorInsert(context, GetVec(op.Rd), n, 1, 3));
|
||||
}
|
||||
|
||||
public static void Fmov_S(EmitterContext context)
|
||||
{
|
||||
OpCodeSimd op = (OpCodeSimd)context.CurrOp;
|
||||
|
||||
OperandType type = op.Size != 0 ? OperandType.FP32
|
||||
: OperandType.FP64;
|
||||
OperandType type = op.Size == 0 ? OperandType.FP32 : OperandType.FP64;
|
||||
|
||||
Operand ne = context.VectorExtract(GetVec(op.Rn), Local(type), 0);
|
||||
|
||||
|
@ -307,20 +305,11 @@ namespace ARMeilleure.Instructions
|
|||
}
|
||||
}
|
||||
|
||||
public static void Fmov_V(EmitterContext context)
|
||||
public static void Fmov_Vi(EmitterContext context)
|
||||
{
|
||||
OpCodeSimdImm op = (OpCodeSimdImm)context.CurrOp;
|
||||
|
||||
Operand e;
|
||||
|
||||
if (op.Size == 0)
|
||||
{
|
||||
e = Const((int)op.Immediate);
|
||||
}
|
||||
else
|
||||
{
|
||||
e = Const(op.Immediate);
|
||||
}
|
||||
Operand e = Const(op.Immediate);
|
||||
|
||||
Operand res = context.VectorZero();
|
||||
|
||||
|
@ -331,25 +320,27 @@ namespace ARMeilleure.Instructions
|
|||
res = EmitVectorInsert(context, res, e, index, op.Size + 2);
|
||||
}
|
||||
|
||||
context.Copy(GetVec(op.Rd), e);
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
|
||||
public static void Ins_Gp(EmitterContext context)
|
||||
{
|
||||
OpCodeSimdIns op = (OpCodeSimdIns)context.CurrOp;
|
||||
|
||||
Operand n = GetIntOrZR(op, op.Rn);
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand n = GetIntOrZR(context, op.Rn);
|
||||
|
||||
context.Copy(GetVec(op.Rd), EmitVectorInsert(context, context.VectorZero(), n, op.DstIndex, op.Size));
|
||||
context.Copy(d, EmitVectorInsert(context, d, n, op.DstIndex, op.Size));
|
||||
}
|
||||
|
||||
public static void Ins_V(EmitterContext context)
|
||||
{
|
||||
OpCodeSimdIns op = (OpCodeSimdIns)context.CurrOp;
|
||||
|
||||
Operand d = GetVec(op.Rd);
|
||||
Operand ne = EmitVectorExtractZx(context, op.Rn, op.SrcIndex, op.Size);
|
||||
|
||||
context.Copy(GetVec(op.Rd), EmitVectorInsert(context, context.VectorZero(), ne, op.DstIndex, op.Size));
|
||||
context.Copy(d, EmitVectorInsert(context, d, ne, op.DstIndex, op.Size));
|
||||
}
|
||||
|
||||
public static void Movi_V(EmitterContext context)
|
||||
|
@ -382,7 +373,12 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
Operand ne = EmitVectorExtractSx(context, op.Rn, op.DstIndex, op.Size);
|
||||
|
||||
SetIntOrZR(context, op.Rd, EmitIntZeroUpperIfNeeded(context, ne));
|
||||
if (op.RegisterSize == RegisterSize.Simd64)
|
||||
{
|
||||
ne = context.ZeroExtend32(OperandType.I64, ne);
|
||||
}
|
||||
|
||||
SetIntOrZR(context, op.Rd, ne);
|
||||
}
|
||||
|
||||
public static void Tbl_V(EmitterContext context)
|
||||
|
@ -544,17 +540,6 @@ namespace ARMeilleure.Instructions
|
|||
EmitVectorZip(context, part: 1);
|
||||
}
|
||||
|
||||
private static Operand EmitIntZeroUpperIfNeeded(EmitterContext context, Operand value)
|
||||
{
|
||||
if (context.CurrOp.RegisterSize == RegisterSize.Int32 ||
|
||||
context.CurrOp.RegisterSize == RegisterSize.Simd64)
|
||||
{
|
||||
return ZeroExtend32(context, value);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private static void EmitMoviMvni(EmitterContext context, bool not)
|
||||
{
|
||||
OpCodeSimdImm op = (OpCodeSimdImm)context.CurrOp;
|
||||
|
@ -761,7 +746,11 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
if (op.RegisterSize == RegisterSize.Simd128)
|
||||
{
|
||||
Operand res = context.AddIntrinsic(X86PunpcklInstruction[op.Size], n, m);
|
||||
Instruction punpckInst = part == 0
|
||||
? X86PunpcklInstruction[op.Size]
|
||||
: X86PunpckhInstruction[op.Size];
|
||||
|
||||
Operand res = context.AddIntrinsic(punpckInst, n, m);
|
||||
|
||||
context.Copy(GetVec(op.Rd), res);
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
MethodInfo info = typeof(NativeInterface).GetMethod(name);
|
||||
|
||||
context.Call(info, GetIntOrZR(op, op.Rt));
|
||||
context.Call(info, GetIntOrZR(context, op.Rt));
|
||||
}
|
||||
|
||||
public static void Nop(EmitterContext context)
|
||||
|
@ -85,7 +85,7 @@ namespace ARMeilleure.Instructions
|
|||
case 0b11_011_0111_0100_001:
|
||||
{
|
||||
//DC ZVA
|
||||
Operand t = GetIntOrZR(op, op.Rt);
|
||||
Operand t = GetIntOrZR(context, op.Rt);
|
||||
|
||||
MethodInfo info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.WriteUInt64));
|
||||
|
||||
|
|
|
@ -212,7 +212,7 @@ namespace ARMeilleure.Instructions
|
|||
Fmls_Ve,
|
||||
Fmov_S,
|
||||
Fmov_Si,
|
||||
Fmov_V,
|
||||
Fmov_Vi,
|
||||
Fmov_Ftoi,
|
||||
Fmov_Itof,
|
||||
Fmov_Ftoi1,
|
||||
|
|
|
@ -249,8 +249,8 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
success = context.Memory.AtomicCompareExchangeByte(
|
||||
(long)address,
|
||||
(byte)value,
|
||||
(byte)context.ExclusiveValueLow);
|
||||
(byte)context.ExclusiveValueLow,
|
||||
(byte)value);
|
||||
|
||||
if (success)
|
||||
{
|
||||
|
@ -271,8 +271,8 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
success = context.Memory.AtomicCompareExchangeInt16(
|
||||
(long)address,
|
||||
(short)value,
|
||||
(short)context.ExclusiveValueLow);
|
||||
(short)context.ExclusiveValueLow,
|
||||
(short)value);
|
||||
|
||||
if (success)
|
||||
{
|
||||
|
@ -293,8 +293,8 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
success = context.Memory.AtomicCompareExchangeInt32(
|
||||
(long)address,
|
||||
(int)value,
|
||||
(int)context.ExclusiveValueLow);
|
||||
(int)context.ExclusiveValueLow,
|
||||
(int)value);
|
||||
|
||||
if (success)
|
||||
{
|
||||
|
@ -315,8 +315,8 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
success = context.Memory.AtomicCompareExchangeInt64(
|
||||
(long)address,
|
||||
(long)value,
|
||||
(long)context.ExclusiveValueLow);
|
||||
(long)context.ExclusiveValueLow,
|
||||
(long)value);
|
||||
|
||||
if (success)
|
||||
{
|
||||
|
@ -337,10 +337,10 @@ namespace ARMeilleure.Instructions
|
|||
{
|
||||
success = context.Memory.AtomicCompareExchangeInt128(
|
||||
(long)address,
|
||||
value.GetUInt64(0),
|
||||
value.GetUInt64(1),
|
||||
context.ExclusiveValueLow,
|
||||
context.ExclusiveValueHigh);
|
||||
context.ExclusiveValueHigh,
|
||||
value.GetUInt64(0),
|
||||
value.GetUInt64(1));
|
||||
|
||||
if (success)
|
||||
{
|
||||
|
@ -362,6 +362,11 @@ namespace ARMeilleure.Instructions
|
|||
GetCurrentContext().ExclusiveAddress = ulong.MaxValue;
|
||||
}
|
||||
|
||||
public static void CheckSynchronization()
|
||||
{
|
||||
GetContext().CheckInterrupt();
|
||||
}
|
||||
|
||||
private static ThreadContext GetCurrentContext()
|
||||
{
|
||||
return _contexts[Thread.CurrentThread];
|
||||
|
|
|
@ -38,6 +38,8 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||
Predecessors = new List<BasicBlock>();
|
||||
|
||||
DominanceFrontiers = new HashSet<BasicBlock>();
|
||||
|
||||
Index = -1;
|
||||
}
|
||||
|
||||
public BasicBlock(int index) : this()
|
||||
|
|
|
@ -23,6 +23,7 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||
CompareLessUI,
|
||||
CompareNotEqual,
|
||||
ConditionalSelect,
|
||||
ConvertI64ToI32,
|
||||
ConvertToFP,
|
||||
ConvertToFPUI,
|
||||
Copy,
|
||||
|
@ -46,9 +47,9 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||
ShiftLeft,
|
||||
ShiftRightSI,
|
||||
ShiftRightUI,
|
||||
SignExtend8,
|
||||
SignExtend16,
|
||||
SignExtend32,
|
||||
SignExtend8,
|
||||
Spill,
|
||||
SpillArg,
|
||||
StackAlloc,
|
||||
|
@ -63,9 +64,13 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||
VectorInsert,
|
||||
VectorInsert16,
|
||||
VectorInsert8,
|
||||
VectorOne,
|
||||
VectorZero,
|
||||
VectorZeroUpper64,
|
||||
VectorZeroUpper96,
|
||||
ZeroExtend16,
|
||||
ZeroExtend32,
|
||||
ZeroExtend8,
|
||||
|
||||
//Intrinsics
|
||||
X86Intrinsic_Start,
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
using ARMeilleure.State;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ARMeilleure.IntermediateRepresentation
|
||||
{
|
||||
class Operand //: IEquatable<Operand>
|
||||
class Operand
|
||||
{
|
||||
public OperandKind Kind { get; }
|
||||
|
||||
|
@ -29,11 +28,6 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||
Type = type;
|
||||
}
|
||||
|
||||
public Operand(OperandType type, int offset) : this(OperandKind.Memory, type)
|
||||
{
|
||||
Value = (uint)offset;
|
||||
}
|
||||
|
||||
public Operand(int value) : this(OperandKind.Constant, OperandType.I32)
|
||||
{
|
||||
Value = (uint)value;
|
||||
|
@ -107,7 +101,7 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||
return BitConverter.Int64BitsToDouble((long)Value);
|
||||
}
|
||||
|
||||
public void NumberLocal(int number)
|
||||
internal void NumberLocal(int number)
|
||||
{
|
||||
if (Kind != OperandKind.LocalVariable)
|
||||
{
|
||||
|
|
|
@ -5,10 +5,14 @@ namespace ARMeilleure.State
|
|||
{
|
||||
public class ExecutionContext : IDisposable
|
||||
{
|
||||
private const int MinCountForCheck = 40000;
|
||||
|
||||
private NativeContext _nativeContext;
|
||||
|
||||
internal IntPtr NativeContextPtr => _nativeContext.BasePtr;
|
||||
|
||||
private bool _interrupted;
|
||||
|
||||
private static Stopwatch _tickCounter;
|
||||
|
||||
private static double _hostTickFreq;
|
||||
|
@ -33,6 +37,9 @@ namespace ARMeilleure.State
|
|||
public FPCR Fpcr { get; set; }
|
||||
public FPSR Fpsr { get; set; }
|
||||
|
||||
public bool Running { get; set; }
|
||||
|
||||
public event EventHandler<EventArgs> Interrupt;
|
||||
public event EventHandler<InstExceptionEventArgs> Break;
|
||||
public event EventHandler<InstExceptionEventArgs> SupervisorCall;
|
||||
public event EventHandler<InstUndefinedEventArgs> Undefined;
|
||||
|
@ -49,6 +56,10 @@ namespace ARMeilleure.State
|
|||
public ExecutionContext()
|
||||
{
|
||||
_nativeContext = new NativeContext();
|
||||
|
||||
Running = true;
|
||||
|
||||
_nativeContext.SetCounter(MinCountForCheck);
|
||||
}
|
||||
|
||||
public ulong GetX(int index) => _nativeContext.GetX(index);
|
||||
|
@ -60,6 +71,23 @@ namespace ARMeilleure.State
|
|||
public bool GetPstateFlag(PState flag) => _nativeContext.GetPstateFlag(flag);
|
||||
public void SetPstateFlag(PState flag, bool value) => _nativeContext.SetPstateFlag(flag, value);
|
||||
|
||||
public void CheckInterrupt()
|
||||
{
|
||||
if (_interrupted)
|
||||
{
|
||||
_interrupted = false;
|
||||
|
||||
Interrupt?.Invoke(this, EventArgs.Empty);
|
||||
}
|
||||
|
||||
_nativeContext.SetCounter(MinCountForCheck);
|
||||
}
|
||||
|
||||
public void RequestInterrupt()
|
||||
{
|
||||
_interrupted = true;
|
||||
}
|
||||
|
||||
internal void OnBreak(ulong address, int imm)
|
||||
{
|
||||
Break?.Invoke(this, new InstExceptionEventArgs(address, imm));
|
||||
|
|
|
@ -7,13 +7,14 @@ namespace ARMeilleure.State
|
|||
{
|
||||
class NativeContext : IDisposable
|
||||
{
|
||||
private const int IntSize = 8;
|
||||
private const int VecSize = 16;
|
||||
private const int FlagSize = 4;
|
||||
private const int IntSize = 8;
|
||||
private const int VecSize = 16;
|
||||
private const int FlagSize = 4;
|
||||
private const int ExtraSize = 4;
|
||||
|
||||
private const int TotalSize = RegisterConsts.IntRegsCount * IntSize +
|
||||
RegisterConsts.VecRegsCount * VecSize +
|
||||
RegisterConsts.FlagsCount * FlagSize;
|
||||
private const int TotalSize = RegisterConsts.IntRegsCount * IntSize +
|
||||
RegisterConsts.VecRegsCount * VecSize +
|
||||
RegisterConsts.FlagsCount * FlagSize + ExtraSize;
|
||||
|
||||
public IntPtr BasePtr { get; }
|
||||
|
||||
|
@ -99,6 +100,16 @@ namespace ARMeilleure.State
|
|||
Marshal.WriteInt32(BasePtr, offset, value ? 1 : 0);
|
||||
}
|
||||
|
||||
public int GetCounter()
|
||||
{
|
||||
return Marshal.ReadInt32(BasePtr, GetCounterOffset());
|
||||
}
|
||||
|
||||
public void SetCounter(int value)
|
||||
{
|
||||
Marshal.WriteInt32(BasePtr, GetCounterOffset(), value);
|
||||
}
|
||||
|
||||
public static int GetRegisterOffset(Register reg)
|
||||
{
|
||||
if (reg.Type == RegisterType.Integer)
|
||||
|
@ -116,6 +127,13 @@ namespace ARMeilleure.State
|
|||
}
|
||||
}
|
||||
|
||||
public static int GetCounterOffset()
|
||||
{
|
||||
return RegisterConsts.IntRegsCount * IntSize +
|
||||
RegisterConsts.VecRegsCount * VecSize +
|
||||
RegisterConsts.FlagsCount * FlagSize;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
MemoryManagement.Free(BasePtr);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using ARMeilleure.IntermediateRepresentation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace ARMeilleure.Translation
|
||||
{
|
||||
|
@ -68,6 +69,8 @@ namespace ARMeilleure.Translation
|
|||
|
||||
while (workQueue.TryDequeue(out BasicBlock block))
|
||||
{
|
||||
Debug.Assert(block.Index != -1, "Invalid block index.");
|
||||
|
||||
if (block.Next != null && visited.Add(block.Next))
|
||||
{
|
||||
workQueue.Enqueue(block.Next);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using ARMeilleure.IntermediateRepresentation;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace ARMeilleure.Translation
|
||||
{
|
||||
|
@ -28,6 +29,8 @@ namespace ARMeilleure.Translation
|
|||
|
||||
cfg.Entry.ImmediateDominator = cfg.Entry;
|
||||
|
||||
Debug.Assert(cfg.Entry == cfg.PostOrderBlocks[cfg.PostOrderBlocks.Length - 1]);
|
||||
|
||||
bool modified;
|
||||
|
||||
do
|
||||
|
|
|
@ -5,6 +5,7 @@ using ARMeilleure.State;
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
|
||||
|
||||
|
@ -93,6 +94,8 @@ namespace ARMeilleure.Translation
|
|||
|
||||
public Operand Call(MethodInfo info, params Operand[] callArgs)
|
||||
{
|
||||
RuntimeHelpers.PrepareMethod(info.MethodHandle);
|
||||
|
||||
long methodPtr = info.MethodHandle.GetFunctionPointer().ToInt64();
|
||||
|
||||
Operand[] args = new Operand[callArgs.Length + 1];
|
||||
|
@ -156,6 +159,11 @@ namespace ARMeilleure.Translation
|
|||
return Add(Instruction.ConditionalSelect, Local(b.Type), a, b, c);
|
||||
}
|
||||
|
||||
public Operand ConvertI64ToI32(Operand a)
|
||||
{
|
||||
return Add(Instruction.ConvertI64ToI32, Local(OperandType.I32), a);
|
||||
}
|
||||
|
||||
public Operand ConvertToFP(OperandType type, Operand a)
|
||||
{
|
||||
return Add(Instruction.ConvertToFP, Local(type), a);
|
||||
|
@ -246,6 +254,30 @@ namespace ARMeilleure.Translation
|
|||
return Add(Instruction.Load, value, address);
|
||||
}
|
||||
|
||||
public Operand LoadFromContext(int offset)
|
||||
{
|
||||
return Add(Instruction.LoadFromContext, Local(OperandType.I32), Const(offset));
|
||||
}
|
||||
|
||||
public void LoadFromContext()
|
||||
{
|
||||
_needsNewBlock = true;
|
||||
|
||||
Add(Instruction.LoadFromContext);
|
||||
}
|
||||
|
||||
public void StoreToContext(int offset, Operand value)
|
||||
{
|
||||
Add(Instruction.StoreToContext, null, Const(offset), value);
|
||||
}
|
||||
|
||||
public void StoreToContext()
|
||||
{
|
||||
Add(Instruction.StoreToContext);
|
||||
|
||||
_needsNewBlock = true;
|
||||
}
|
||||
|
||||
public Operand LoadSx16(Operand value, Operand address)
|
||||
{
|
||||
return Add(Instruction.LoadSx16, value, address);
|
||||
|
@ -293,12 +325,20 @@ namespace ARMeilleure.Translation
|
|||
|
||||
public Operand Return()
|
||||
{
|
||||
return Add(Instruction.Return);
|
||||
Operand returnValue = Add(Instruction.Return);
|
||||
|
||||
_needsNewBlock = true;
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public Operand Return(Operand a)
|
||||
{
|
||||
return Add(Instruction.Return, null, a);
|
||||
Operand returnValue = Add(Instruction.Return, null, a);
|
||||
|
||||
_needsNewBlock = true;
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public Operand RotateRight(Operand a, Operand b)
|
||||
|
@ -321,19 +361,19 @@ namespace ARMeilleure.Translation
|
|||
return Add(Instruction.ShiftRightUI, Local(a.Type), a, b);
|
||||
}
|
||||
|
||||
public Operand SignExtend8(Operand a)
|
||||
public Operand SignExtend16(OperandType type, Operand a)
|
||||
{
|
||||
return Add(Instruction.SignExtend8, Local(a.Type), a);
|
||||
return Add(Instruction.SignExtend16, Local(type), a);
|
||||
}
|
||||
|
||||
public Operand SignExtend16(Operand a)
|
||||
public Operand SignExtend32(OperandType type, Operand a)
|
||||
{
|
||||
return Add(Instruction.SignExtend16, Local(a.Type), a);
|
||||
return Add(Instruction.SignExtend32, Local(type), a);
|
||||
}
|
||||
|
||||
public Operand SignExtend32(Operand a)
|
||||
public Operand SignExtend8(OperandType type, Operand a)
|
||||
{
|
||||
return Add(Instruction.SignExtend32, Local(a.Type), a);
|
||||
return Add(Instruction.SignExtend8, Local(type), a);
|
||||
}
|
||||
|
||||
public void Store(Operand address, Operand value)
|
||||
|
@ -401,6 +441,21 @@ namespace ARMeilleure.Translation
|
|||
return Add(Instruction.VectorZeroUpper96, Local(OperandType.V128), vector);
|
||||
}
|
||||
|
||||
public Operand ZeroExtend16(OperandType type, Operand a)
|
||||
{
|
||||
return Add(Instruction.ZeroExtend16, Local(type), a);
|
||||
}
|
||||
|
||||
public Operand ZeroExtend32(OperandType type, Operand a)
|
||||
{
|
||||
return Add(Instruction.ZeroExtend32, Local(type), a);
|
||||
}
|
||||
|
||||
public Operand ZeroExtend8(OperandType type, Operand a)
|
||||
{
|
||||
return Add(Instruction.ZeroExtend8, Local(type), a);
|
||||
}
|
||||
|
||||
public Operand AddIntrinsic(Instruction inst, params Operand[] args)
|
||||
{
|
||||
return Add(inst, Local(OperandType.V128), args);
|
||||
|
@ -444,11 +499,6 @@ namespace ARMeilleure.Translation
|
|||
_needsNewBlock = true;
|
||||
}
|
||||
|
||||
public void Synchronize()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void MarkLabel(Operand label)
|
||||
{
|
||||
if (_irLabels.TryGetValue(label, out BasicBlock nextBlock))
|
||||
|
|
|
@ -68,7 +68,7 @@ namespace ARMeilleure.Translation
|
|||
}
|
||||
}
|
||||
|
||||
public static void InsertContext(ControlFlowGraph cfg)
|
||||
public static void RunPass(ControlFlowGraph cfg)
|
||||
{
|
||||
//Computer local register inputs and outputs used inside blocks.
|
||||
RegisterMask[] localInputs = new RegisterMask[cfg.Blocks.Count];
|
||||
|
@ -120,7 +120,7 @@ namespace ARMeilleure.Translation
|
|||
{
|
||||
BasicBlock block = cfg.PostOrderBlocks[index];
|
||||
|
||||
if (block.Predecessors.Count != 0)
|
||||
if (block.Predecessors.Count != 0 && !HasContextLoad(block))
|
||||
{
|
||||
BasicBlock predecessor = block.Predecessors[0];
|
||||
|
||||
|
@ -194,15 +194,29 @@ namespace ARMeilleure.Translation
|
|||
//Insert load and store context instructions where needed.
|
||||
foreach (BasicBlock block in cfg.Blocks)
|
||||
{
|
||||
bool hasContextLoad = HasContextLoad(block);
|
||||
|
||||
if (hasContextLoad)
|
||||
{
|
||||
block.Operations.RemoveFirst();
|
||||
}
|
||||
|
||||
//The only block without any predecessor should be the entry block.
|
||||
//It always needs a context load as it is the first block to run.
|
||||
if (block.Predecessors.Count == 0)
|
||||
if (block.Predecessors.Count == 0 || hasContextLoad)
|
||||
{
|
||||
LoadLocals(block, globalInputs[block.Index].VecMask, RegisterType.Vector);
|
||||
LoadLocals(block, globalInputs[block.Index].IntMask, RegisterType.Integer);
|
||||
}
|
||||
|
||||
if (HasContextStore(block))
|
||||
bool hasContextStore = HasContextStore(block);
|
||||
|
||||
if (hasContextStore)
|
||||
{
|
||||
block.Operations.RemoveLast();
|
||||
}
|
||||
|
||||
if (EndsWithReturn(block) || hasContextStore)
|
||||
{
|
||||
StoreLocals(block, globalOutputs[block.Index].IntMask, RegisterType.Integer);
|
||||
StoreLocals(block, globalOutputs[block.Index].VecMask, RegisterType.Vector);
|
||||
|
@ -210,6 +224,36 @@ namespace ARMeilleure.Translation
|
|||
}
|
||||
}
|
||||
|
||||
private static bool HasContextLoad(BasicBlock block)
|
||||
{
|
||||
return StartsWith(block, Instruction.LoadFromContext) && block.Operations.First.Value.SourcesCount == 0;
|
||||
}
|
||||
|
||||
private static bool HasContextStore(BasicBlock block)
|
||||
{
|
||||
return EndsWith(block, Instruction.StoreToContext) && block.GetLastOp().SourcesCount == 0;
|
||||
}
|
||||
|
||||
private static bool StartsWith(BasicBlock block, Instruction inst)
|
||||
{
|
||||
if (block.Operations.Count == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return block.Operations.First.Value is Operation operation && operation.Inst == inst;
|
||||
}
|
||||
|
||||
private static bool EndsWith(BasicBlock block, Instruction inst)
|
||||
{
|
||||
if (block.Operations.Count == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return block.Operations.Last.Value is Operation operation && operation.Inst == inst;
|
||||
}
|
||||
|
||||
private static RegisterMask GetMask(Register register)
|
||||
{
|
||||
long intMask = 0;
|
||||
|
@ -316,7 +360,7 @@ namespace ARMeilleure.Translation
|
|||
throw new ArgumentException($"Invalid register type \"{type}\".");
|
||||
}
|
||||
|
||||
private static bool HasContextStore(BasicBlock block)
|
||||
private static bool EndsWithReturn(BasicBlock block)
|
||||
{
|
||||
if (!(block.GetLastOp() is Operation operation))
|
||||
{
|
||||
|
|
|
@ -67,17 +67,6 @@ namespace ARMeilleure.Translation
|
|||
{
|
||||
Operand local = localDefs[GetIdFromRegister(operand.GetRegister())];
|
||||
|
||||
if (local != null && local.Type != operand.Type)
|
||||
{
|
||||
Operand temp = Local(operand.Type);
|
||||
|
||||
Operation castOp = new Operation(Instruction.Copy, temp, local);
|
||||
|
||||
block.Operations.AddBefore(node, castOp);
|
||||
|
||||
local = temp;
|
||||
}
|
||||
|
||||
operand = local ?? operand;
|
||||
}
|
||||
|
||||
|
@ -158,17 +147,6 @@ namespace ARMeilleure.Translation
|
|||
localDefs[key] = local;
|
||||
}
|
||||
|
||||
if (local.Kind == OperandKind.LocalVariable && local.Type != operand.Type)
|
||||
{
|
||||
Operand temp = Local(operand.Type);
|
||||
|
||||
Operation castOp = new Operation(Instruction.Copy, temp, local);
|
||||
|
||||
block.Operations.AddBefore(node, castOp);
|
||||
|
||||
local = temp;
|
||||
}
|
||||
|
||||
operand = local;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,8 @@ using ARMeilleure.IntermediateRepresentation;
|
|||
using ARMeilleure.Memory;
|
||||
using ARMeilleure.State;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Reflection;
|
||||
|
||||
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
|
||||
|
||||
|
@ -17,11 +19,15 @@ namespace ARMeilleure.Translation
|
|||
|
||||
private TranslatedCache _cache;
|
||||
|
||||
private ConcurrentDictionary<ulong, TranslatedFunction> _funcs;
|
||||
|
||||
public Translator(MemoryManager memory)
|
||||
{
|
||||
_memory = memory;
|
||||
|
||||
_cache = new TranslatedCache();
|
||||
|
||||
_funcs = new ConcurrentDictionary<ulong, TranslatedFunction>();
|
||||
}
|
||||
|
||||
public void Execute(ExecutionContext context, ulong address)
|
||||
|
@ -30,15 +36,37 @@ namespace ARMeilleure.Translation
|
|||
|
||||
do
|
||||
{
|
||||
TranslatedFunction func = Translate(address, ExecutionMode.Aarch64);
|
||||
|
||||
address = func.Execute(context);
|
||||
address = ExecuteSingle(context, address);
|
||||
}
|
||||
while (address != 0);
|
||||
while (context.Running && address != 0);
|
||||
|
||||
NativeInterface.UnregisterThread();
|
||||
}
|
||||
|
||||
public void SelfRegister(ExecutionContext context)
|
||||
{
|
||||
NativeInterface.RegisterThread(context, _memory);
|
||||
}
|
||||
|
||||
public ulong ExecuteSingle(ExecutionContext context, ulong address)
|
||||
{
|
||||
TranslatedFunction func = GetOrTranslate(address, ExecutionMode.Aarch64);
|
||||
|
||||
return func.Execute(context);
|
||||
}
|
||||
|
||||
private TranslatedFunction GetOrTranslate(ulong address, ExecutionMode mode)
|
||||
{
|
||||
if (!_funcs.TryGetValue(address, out TranslatedFunction func))
|
||||
{
|
||||
func = Translate(address, mode);
|
||||
|
||||
_funcs.TryAdd(address, func);
|
||||
}
|
||||
|
||||
return func;
|
||||
}
|
||||
|
||||
private TranslatedFunction Translate(ulong address, ExecutionMode mode)
|
||||
{
|
||||
EmitterContext context = new EmitterContext();
|
||||
|
@ -47,9 +75,16 @@ namespace ARMeilleure.Translation
|
|||
|
||||
Block[] blocks = Decoder.DecodeFunction(_memory, address, ExecutionMode.Aarch64);
|
||||
|
||||
EmitSynchronization(context);
|
||||
|
||||
if (blocks[0].Address != address)
|
||||
{
|
||||
context.Branch(context.GetLabel(address));
|
||||
}
|
||||
|
||||
ControlFlowGraph cfg = EmitAndGetCFG(context, blocks);
|
||||
|
||||
RegisterUsage.InsertContext(cfg);
|
||||
RegisterUsage.RunPass(cfg);
|
||||
|
||||
Dominance.FindDominators(cfg);
|
||||
|
||||
|
@ -86,7 +121,7 @@ namespace ARMeilleure.Translation
|
|||
|
||||
if (isLastOp && block.Branch != null && block.Branch.Address <= block.Address)
|
||||
{
|
||||
context.Synchronize();
|
||||
EmitSynchronization(context);
|
||||
}
|
||||
|
||||
Operand lblPredicateSkip = null;
|
||||
|
@ -126,5 +161,26 @@ namespace ARMeilleure.Translation
|
|||
|
||||
return context.GetControlFlowGraph();
|
||||
}
|
||||
|
||||
private static void EmitSynchronization(EmitterContext context)
|
||||
{
|
||||
int cntOffset = NativeContext.GetCounterOffset();
|
||||
|
||||
Operand count = context.LoadFromContext(cntOffset);
|
||||
|
||||
Operand lblNonZero = Label();
|
||||
|
||||
context.BranchIfTrue(lblNonZero, count);
|
||||
|
||||
MethodInfo info = typeof(NativeInterface).GetMethod(nameof(NativeInterface.CheckSynchronization));
|
||||
|
||||
context.Call(info);
|
||||
|
||||
context.MarkLabel(lblNonZero);
|
||||
|
||||
count = context.Subtract(count, Const(1));
|
||||
|
||||
context.StoreToContext(cntOffset, count);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue