public object TryLookup( CodeContext mode, ImmutableLegacyPrefixList legacyPrefixes, Xex xex, byte opcode, out bool hasModRM, out int immediateSizeInBytes) { hasModRM = false; immediateSizeInBytes = 0; NasmInsnsEntry match = null; foreach (var entry in entries) { bool entryHasModRM; int entryImmediateSize; if (entry.Match(mode.GetDefaultAddressSize(), legacyPrefixes, xex, opcode, out entryHasModRM, out entryImmediateSize)) { if (match != null) { // If we match multiple, we should have the same response for each if (entryHasModRM != hasModRM) return false; if (entryImmediateSize != immediateSizeInBytes) return false; } hasModRM = entryHasModRM; immediateSizeInBytes = entryImmediateSize; match = entry; } } return match; }
public static OperandSize GetEffectiveOperandSize(this CodeContext context, ImmutableLegacyPrefixList legacyPrefixes, Xex xex) { return GetEffectiveOperandSize(context, @override: legacyPrefixes.HasOperandSizeOverride, rexW: xex.OperandSize64); }
public object TryLookup(CodeContext mode, ImmutableLegacyPrefixList legacyPrefixes, Xex xex, byte opcode, out bool hasModRM, out int immediateSizeInBytes) { if (xex.OpcodeMap == OpcodeMap.Default && opcode == 0x90) { // NOP hasModRM = false; immediateSizeInBytes = 0; return found; } else if (xex.OpcodeMap == OpcodeMap.Escape0F && opcode == 0x1F) { // 3+ byte nop form hasModRM = true; immediateSizeInBytes = 0; return found; } else if (xex.OpcodeMap == OpcodeMap.Default && (opcode & 0xF8) == 0xB0) { // MOV x8, imm8 hasModRM = false; immediateSizeInBytes = 1; return found; } else if (xex.OpcodeMap == OpcodeMap.Default && (opcode & 0xF8) == 0xB8) { // Mov r(16|32|64), imm(16|32|64) OperandSize operandSize; if (mode == CodeContext.SixtyFourBit) operandSize = xex.OperandSize64 ? OperandSize.Qword : OperandSize.Dword; else operandSize = mode.GetDefaultOperandSize().OverrideWordDword( legacyPrefixes.HasOperandSizeOverride); hasModRM = false; immediateSizeInBytes = operandSize.InBytes(); return found; } else if (xex.OpcodeMap == OpcodeMap.Escape0F && (xex.SimdPrefix ?? legacyPrefixes.GetSimdPrefix(xex.OpcodeMap)) == SimdPrefix._66 && opcode == 0x58) { hasModRM = true; immediateSizeInBytes = 0; return found; } else { hasModRM = false; immediateSizeInBytes = 0; return null; } }
public Encoding(ImmutableLegacyPrefixList legacyPrefixes, Xex xex, ModRM modRM, Sib? sib = null, int displacement = 0) { this.Segment = legacyPrefixes.SegmentOverride; this.AddressSizeOverride = legacyPrefixes.HasAddressSizeOverride; this.BaseRegExtension = xex.BaseRegExtension; this.IndexRegExtension = xex.IndexRegExtension; this.ModRM = modRM; this.Sib = sib; this.Displacement = displacement; }
public bool Match( AddressSize defaultAddressSize, ImmutableLegacyPrefixList legacyPrefixes, Xex xex, byte opcode, out bool hasModRM, out int immediateSize) { var partialInstruction = new Instruction.Builder { DefaultAddressSize = defaultAddressSize, LegacyPrefixes = legacyPrefixes, Xex = xex, OpcodeByte = opcode }.Build(); return Match(partialInstruction, upToOpcode: true, hasModRM: out hasModRM, immediateSize: out immediateSize); }
private readonly ulong immediate; // 8 bytes #endregion #region Constructors private Instruction(Builder builder) { legacyPrefixes = builder.LegacyPrefixes; xex = builder.Xex; // Validate if redundant with prefixes mainByte = builder.OpcodeByte; modRM = builder.ModRM.GetValueOrDefault(); sib = builder.Sib.GetValueOrDefault(); // Validate if necessary displacement = builder.Displacement; // Validate with mod/sib immediate = builder.Immediate; // Truncate to size flags = 0; flags |= (Flags)((int)builder.DefaultAddressSize << (int)Flags.DefaultAddressSize_Shift); if (builder.ModRM.HasValue) flags |= Flags.HasModRM; flags |= (Flags)(builder.ImmediateSizeInBytes << (int)Flags.ImmediateSizeInBytes_Shift); }
object IInstructionDecoderLookup.TryLookup( CodeContext mode, ImmutableLegacyPrefixList legacyPrefixes, Xex xex, byte opcode, out bool hasModRM, out int immediateSizeInBytes) { var operandSize = mode.GetEffectiveOperandSize(legacyPrefixes, xex); var addressSize = mode.GetEffectiveAddressSize(legacyPrefixes); InstructionDefinition bestMatch = null; int bestOperandSizeMatchLevel = -1; var lookupKey = OpcodeEnum.MakeLookupKey(legacyPrefixes.GetSimdPrefix(xex.OpcodeMap), xex.OpcodeMap, opcode); foreach (var instruction in byOpcodeKey[lookupKey]) { var encoding = instruction.Encoding; // Ensure we match the RexW requirements if ((encoding & InstructionEncoding.RexW_Mask) == InstructionEncoding.RexW_Fixed && xex.OperandSize64 != ((instruction.Opcode & Opcode.RexW) != 0)) { continue; } // Ensure we match the opcode if ((opcode & encoding.GetOpcodeMainByteFixedMask()) != instruction.Opcode.GetMainByte()) continue; // Record the candidate, favoring more specific operand size matches var operandSizeMatchLevel = GetOperandSizeMatchLevel(encoding, operandSize); if (operandSizeMatchLevel > bestOperandSizeMatchLevel) { bestMatch = instruction; bestOperandSizeMatchLevel = operandSizeMatchLevel; } } if (bestMatch == null) { hasModRM = false; immediateSizeInBytes = 0; return null; } hasModRM = bestMatch.Encoding.HasModRM(); immediateSizeInBytes = bestMatch.Encoding.GetImmediatesSizeInBytes(operandSize, addressSize); return bestMatch; }
public void SetLegacyPrefixes(ImmutableLegacyPrefixList prefixes) { Segment = prefixes.SegmentOverride; AddressSizeOverride = prefixes.HasAddressSizeOverride; }
public static AddressSize GetEffectiveAddressSize(this CodeContext mode, ImmutableLegacyPrefixList legacyPrefixes) => GetEffectiveAddressSize(mode, @override: legacyPrefixes.HasAddressSizeOverride);