diff --git a/ARMeilleure/CodeGen/Optimizations/Optimizer.cs b/ARMeilleure/CodeGen/Optimizations/Optimizer.cs index 6038cc40ae..e18341503c 100644 --- a/ARMeilleure/CodeGen/Optimizations/Optimizer.cs +++ b/ARMeilleure/CodeGen/Optimizations/Optimizer.cs @@ -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 nodes = new Queue(); + 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) diff --git a/ARMeilleure/CodeGen/RegisterAllocators/CopyResolver.cs b/ARMeilleure/CodeGen/RegisterAllocators/CopyResolver.cs index e9c343e62b..7f8e420c97 100644 --- a/ARMeilleure/CodeGen/RegisterAllocators/CopyResolver.cs +++ b/ARMeilleure/CodeGen/RegisterAllocators/CopyResolver.cs @@ -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; diff --git a/ARMeilleure/CodeGen/RegisterAllocators/LinearScan.cs b/ARMeilleure/CodeGen/RegisterAllocators/LinearScan.cs index 681de68e69..6fd79643b9 100644 --- a/ARMeilleure/CodeGen/RegisterAllocators/LinearScan.cs +++ b/ARMeilleure/CodeGen/RegisterAllocators/LinearScan.cs @@ -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 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); } diff --git a/ARMeilleure/CodeGen/RegisterAllocators/LiveInterval.cs b/ARMeilleure/CodeGen/RegisterAllocators/LiveInterval.cs index efc9f902e4..9448b0ac61 100644 --- a/ARMeilleure/CodeGen/RegisterAllocators/LiveInterval.cs +++ b/ARMeilleure/CodeGen/RegisterAllocators/LiveInterval.cs @@ -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; } diff --git a/ARMeilleure/CodeGen/RegisterAllocators/PhiFunctions.cs b/ARMeilleure/CodeGen/RegisterAllocators/PhiFunctions.cs index bd72740ed9..53ada2abaf 100644 --- a/ARMeilleure/CodeGen/RegisterAllocators/PhiFunctions.cs +++ b/ARMeilleure/CodeGen/RegisterAllocators/PhiFunctions.cs @@ -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 defBlocks = new List(); - - HashSet visited = new HashSet(); - - //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 = 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> defBlocksPerSrc = new Dictionary>(); - - List phiSources = new List(); - - 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 defBlocks)) - { - defBlocks = new HashSet(); - - 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; - } } } \ No newline at end of file diff --git a/ARMeilleure/CodeGen/X86/Assembler.cs b/ARMeilleure/CodeGen/X86/Assembler.cs index 158e155a3b..5656fbb6ea 100644 --- a/ARMeilleure/CodeGen/X86/Assembler.cs +++ b/ARMeilleure/CodeGen/X86/Assembler.cs @@ -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) diff --git a/ARMeilleure/CodeGen/X86/CodeGenContext.cs b/ARMeilleure/CodeGen/X86/CodeGenContext.cs index 5c0330fe60..198e8a8386 100644 --- a/ARMeilleure/CodeGen/X86/CodeGenContext.cs +++ b/ARMeilleure/CodeGen/X86/CodeGenContext.cs @@ -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; } diff --git a/ARMeilleure/CodeGen/X86/CodeGenerator.cs b/ARMeilleure/CodeGen/X86/CodeGenerator.cs index 748a70a006..fac111e9d5 100644 --- a/ARMeilleure/CodeGen/X86/CodeGenerator.cs +++ b/ARMeilleure/CodeGen/X86/CodeGenerator.cs @@ -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)); diff --git a/ARMeilleure/CodeGen/X86/PreAllocator.cs b/ARMeilleure/CodeGen/X86/PreAllocator.cs index 507154e005..e526f57ad2 100644 --- a/ARMeilleure/CodeGen/X86/PreAllocator.cs +++ b/ARMeilleure/CodeGen/X86/PreAllocator.cs @@ -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) { diff --git a/ARMeilleure/Decoders/Decoder.cs b/ARMeilleure/Decoders/Decoder.cs index 75b4d7d27c..361b2dbd3d 100644 --- a/ARMeilleure/Decoders/Decoder.cs +++ b/ARMeilleure/Decoders/Decoder.cs @@ -19,6 +19,15 @@ namespace ARMeilleure.Decoders _opActivators = new ConcurrentDictionary(); } + 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 blocks = new List(); diff --git a/ARMeilleure/Decoders/OpCodeTable.cs b/ARMeilleure/Decoders/OpCodeTable.cs index 2d7985c591..f136a3f0c8 100644 --- a/ARMeilleure/Decoders/OpCodeTable.cs +++ b/ARMeilleure/Decoders/OpCodeTable.cs @@ -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<0011101<1xxxxx110011xxxxxxxxxx", InstName.Fmls_V, InstEmit.Fmls_V, typeof(OpCodeSimdReg)); SetA64("0>0011111>>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) diff --git a/ARMeilleure/Diagnostics/IRDumper.cs b/ARMeilleure/Diagnostics/IRDumper.cs index b9c30eb642..d156351967 100644 --- a/ARMeilleure/Diagnostics/IRDumper.cs +++ b/ARMeilleure/Diagnostics/IRDumper.cs @@ -109,6 +109,11 @@ namespace ARMeilleure.Diagnostics private static string GetOperandName(Operand operand, Dictionary localNames) { + if (operand == null) + { + return ""; + } + string name = string.Empty; if (operand.Kind == OperandKind.LocalVariable) diff --git a/ARMeilleure/Instructions/InstEmitAlu.cs b/ARMeilleure/Instructions/InstEmitAlu.cs index 79f8224d29..87880e9132 100644 --- a/ARMeilleure/Instructions/InstEmitAlu.cs +++ b/ARMeilleure/Instructions/InstEmitAlu.cs @@ -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); } } } diff --git a/ARMeilleure/Instructions/InstEmitAluHelper.cs b/ARMeilleure/Instructions/InstEmitAluHelper.cs index 8e60013263..7a822dd312 100644 --- a/ARMeilleure/Instructions/InstEmitAluHelper.cs +++ b/ARMeilleure/Instructions/InstEmitAluHelper.cs @@ -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) { diff --git a/ARMeilleure/Instructions/InstEmitBfm.cs b/ARMeilleure/Instructions/InstEmitBfm.cs index e0baa7ac2f..8d0b5aa03e 100644 --- a/ARMeilleure/Instructions/InstEmitBfm.cs +++ b/ARMeilleure/Instructions/InstEmitBfm.cs @@ -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; diff --git a/ARMeilleure/Instructions/InstEmitCsel.cs b/ARMeilleure/Instructions/InstEmitCsel.cs index a894e69bd3..63edba3452 100644 --- a/ARMeilleure/Instructions/InstEmitCsel.cs +++ b/ARMeilleure/Instructions/InstEmitCsel.cs @@ -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) { diff --git a/ARMeilleure/Instructions/InstEmitDiv.cs b/ARMeilleure/Instructions/InstEmitDiv.cs index 82b2f9e3a4..8e7f99fd54 100644 --- a/ARMeilleure/Instructions/InstEmitDiv.cs +++ b/ARMeilleure/Instructions/InstEmitDiv.cs @@ -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)); diff --git a/ARMeilleure/Instructions/InstEmitException.cs b/ARMeilleure/Instructions/InstEmitException.cs index 396dda4243..7a85a0b656 100644 --- a/ARMeilleure/Instructions/InstEmitException.cs +++ b/ARMeilleure/Instructions/InstEmitException.cs @@ -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)); diff --git a/ARMeilleure/Instructions/InstEmitFlow.cs b/ARMeilleure/Instructions/InstEmitFlow.cs index 778561e947..8c4d6e1f1f 100644 --- a/ARMeilleure/Instructions/InstEmitFlow.cs +++ b/ARMeilleure/Instructions/InstEmitFlow.cs @@ -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); } diff --git a/ARMeilleure/Instructions/InstEmitHash.cs b/ARMeilleure/Instructions/InstEmitHash.cs index 1662db9e27..23faf2691b 100644 --- a/ARMeilleure/Instructions/InstEmitHash.cs +++ b/ARMeilleure/Instructions/InstEmitHash.cs @@ -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); diff --git a/ARMeilleure/Instructions/InstEmitHelper.cs b/ARMeilleure/Instructions/InstEmitHelper.cs index 9aedefec55..9a215dae76 100644 --- a/ARMeilleure/Instructions/InstEmitHelper.cs +++ b/ARMeilleure/Instructions/InstEmitHelper.cs @@ -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) diff --git a/ARMeilleure/Instructions/InstEmitMemory.cs b/ARMeilleure/Instructions/InstEmitMemory.cs index 6bdcc5a800..d9abffd477 100644 --- a/ARMeilleure/Instructions/InstEmitMemory.cs +++ b/ARMeilleure/Instructions/InstEmitMemory.cs @@ -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); } } } diff --git a/ARMeilleure/Instructions/InstEmitMemoryEx.cs b/ARMeilleure/Instructions/InstEmitMemoryEx.cs index 2be90efd14..38565a2433 100644 --- a/ARMeilleure/Instructions/InstEmitMemoryEx.cs +++ b/ARMeilleure/Instructions/InstEmitMemoryEx.cs @@ -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; } } diff --git a/ARMeilleure/Instructions/InstEmitMemoryHelper.cs b/ARMeilleure/Instructions/InstEmitMemoryHelper.cs index f76710a98f..188dee2a6a 100644 --- a/ARMeilleure/Instructions/InstEmitMemoryHelper.cs +++ b/ARMeilleure/Instructions/InstEmitMemoryHelper.cs @@ -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); - } - } } } \ No newline at end of file diff --git a/ARMeilleure/Instructions/InstEmitMove.cs b/ARMeilleure/Instructions/InstEmitMove.cs index 4307152936..db2306fcc5 100644 --- a/ARMeilleure/Instructions/InstEmitMove.cs +++ b/ARMeilleure/Instructions/InstEmitMove.cs @@ -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))); diff --git a/ARMeilleure/Instructions/InstEmitMul.cs b/ARMeilleure/Instructions/InstEmitMul.cs index 99ad0a7851..783f97992a 100644 --- a/ARMeilleure/Instructions/InstEmitMul.cs +++ b/ARMeilleure/Instructions/InstEmitMul.cs @@ -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); diff --git a/ARMeilleure/Instructions/InstEmitSimdCvt.cs b/ARMeilleure/Instructions/InstEmitSimdCvt.cs index 9053c382ab..132cfdbf17 100644 --- a/ARMeilleure/Instructions/InstEmitSimdCvt.cs +++ b/ARMeilleure/Instructions/InstEmitSimdCvt.cs @@ -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); } diff --git a/ARMeilleure/Instructions/InstEmitSimdHelper.cs b/ARMeilleure/Instructions/InstEmitSimdHelper.cs index b6ee6f6ec8..17fecbcee6 100644 --- a/ARMeilleure/Instructions/InstEmitSimdHelper.cs +++ b/ARMeilleure/Instructions/InstEmitSimdHelper.cs @@ -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) diff --git a/ARMeilleure/Instructions/InstEmitSimdLogical.cs b/ARMeilleure/Instructions/InstEmitSimdLogical.cs index b37335e6f8..9435033166 100644 --- a/ARMeilleure/Instructions/InstEmitSimdLogical.cs +++ b/ARMeilleure/Instructions/InstEmitSimdLogical.cs @@ -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); } diff --git a/ARMeilleure/Instructions/InstEmitSimdMemory.cs b/ARMeilleure/Instructions/InstEmitSimdMemory.cs index 32afb5bebf..6dfc280c1b 100644 --- a/ARMeilleure/Instructions/InstEmitSimdMemory.cs +++ b/ARMeilleure/Instructions/InstEmitSimdMemory.cs @@ -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 { diff --git a/ARMeilleure/Instructions/InstEmitSimdMove.cs b/ARMeilleure/Instructions/InstEmitSimdMove.cs index c260e42b63..e6feaad98d 100644 --- a/ARMeilleure/Instructions/InstEmitSimdMove.cs +++ b/ARMeilleure/Instructions/InstEmitSimdMove.cs @@ -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); } diff --git a/ARMeilleure/Instructions/InstEmitSystem.cs b/ARMeilleure/Instructions/InstEmitSystem.cs index 5e86274ef7..7ddacd1f18 100644 --- a/ARMeilleure/Instructions/InstEmitSystem.cs +++ b/ARMeilleure/Instructions/InstEmitSystem.cs @@ -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)); diff --git a/ARMeilleure/Instructions/InstName.cs b/ARMeilleure/Instructions/InstName.cs index 5d49436c00..33e2763b97 100644 --- a/ARMeilleure/Instructions/InstName.cs +++ b/ARMeilleure/Instructions/InstName.cs @@ -212,7 +212,7 @@ namespace ARMeilleure.Instructions Fmls_Ve, Fmov_S, Fmov_Si, - Fmov_V, + Fmov_Vi, Fmov_Ftoi, Fmov_Itof, Fmov_Ftoi1, diff --git a/ARMeilleure/Instructions/NativeInterface.cs b/ARMeilleure/Instructions/NativeInterface.cs index 46f2e1b08f..0e802e4b8f 100644 --- a/ARMeilleure/Instructions/NativeInterface.cs +++ b/ARMeilleure/Instructions/NativeInterface.cs @@ -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]; diff --git a/ARMeilleure/IntermediateRepresentation/BasicBlock.cs b/ARMeilleure/IntermediateRepresentation/BasicBlock.cs index 14f42efd37..937e74228e 100644 --- a/ARMeilleure/IntermediateRepresentation/BasicBlock.cs +++ b/ARMeilleure/IntermediateRepresentation/BasicBlock.cs @@ -38,6 +38,8 @@ namespace ARMeilleure.IntermediateRepresentation Predecessors = new List(); DominanceFrontiers = new HashSet(); + + Index = -1; } public BasicBlock(int index) : this() diff --git a/ARMeilleure/IntermediateRepresentation/Instruction.cs b/ARMeilleure/IntermediateRepresentation/Instruction.cs index 0f6a004af5..8e86cc74c5 100644 --- a/ARMeilleure/IntermediateRepresentation/Instruction.cs +++ b/ARMeilleure/IntermediateRepresentation/Instruction.cs @@ -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, diff --git a/ARMeilleure/IntermediateRepresentation/Operand.cs b/ARMeilleure/IntermediateRepresentation/Operand.cs index 7dbefcbde9..3e8cfb1532 100644 --- a/ARMeilleure/IntermediateRepresentation/Operand.cs +++ b/ARMeilleure/IntermediateRepresentation/Operand.cs @@ -1,10 +1,9 @@ -using ARMeilleure.State; using System; using System.Collections.Generic; namespace ARMeilleure.IntermediateRepresentation { - class Operand //: IEquatable + 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) { diff --git a/ARMeilleure/State/ExecutionContext.cs b/ARMeilleure/State/ExecutionContext.cs index 2c1dbd73b7..c6c0a58a26 100644 --- a/ARMeilleure/State/ExecutionContext.cs +++ b/ARMeilleure/State/ExecutionContext.cs @@ -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 Interrupt; public event EventHandler Break; public event EventHandler SupervisorCall; public event EventHandler 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)); diff --git a/ARMeilleure/State/NativeContext.cs b/ARMeilleure/State/NativeContext.cs index 963818c1b8..e868b13b9b 100644 --- a/ARMeilleure/State/NativeContext.cs +++ b/ARMeilleure/State/NativeContext.cs @@ -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); diff --git a/ARMeilleure/Translation/ControlFlowGraph.cs b/ARMeilleure/Translation/ControlFlowGraph.cs index 94c4d488d8..03d3e7d4aa 100644 --- a/ARMeilleure/Translation/ControlFlowGraph.cs +++ b/ARMeilleure/Translation/ControlFlowGraph.cs @@ -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); diff --git a/ARMeilleure/Translation/Dominance.cs b/ARMeilleure/Translation/Dominance.cs index dec51a2990..fa76ab78f7 100644 --- a/ARMeilleure/Translation/Dominance.cs +++ b/ARMeilleure/Translation/Dominance.cs @@ -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 diff --git a/ARMeilleure/Translation/EmitterContext.cs b/ARMeilleure/Translation/EmitterContext.cs index b32d5f9f46..a2d5551d2a 100644 --- a/ARMeilleure/Translation/EmitterContext.cs +++ b/ARMeilleure/Translation/EmitterContext.cs @@ -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)) diff --git a/ARMeilleure/Translation/RegisterUsage.cs b/ARMeilleure/Translation/RegisterUsage.cs index e7e00d33fb..f30693c677 100644 --- a/ARMeilleure/Translation/RegisterUsage.cs +++ b/ARMeilleure/Translation/RegisterUsage.cs @@ -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)) { diff --git a/ARMeilleure/Translation/Ssa.cs b/ARMeilleure/Translation/Ssa.cs index eee5e2f092..022d83ced0 100644 --- a/ARMeilleure/Translation/Ssa.cs +++ b/ARMeilleure/Translation/Ssa.cs @@ -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; } diff --git a/ARMeilleure/Translation/Translator.cs b/ARMeilleure/Translation/Translator.cs index 2d1a8766ca..0c219ba55c 100644 --- a/ARMeilleure/Translation/Translator.cs +++ b/ARMeilleure/Translation/Translator.cs @@ -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 _funcs; + public Translator(MemoryManager memory) { _memory = memory; _cache = new TranslatedCache(); + + _funcs = new ConcurrentDictionary(); } 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); + } } } \ No newline at end of file