ulong registerAddress; // _ADR public GenericRegisterDescriptor(AddressSpace addressSpace, byte registerBitWidth, byte registerBitOffset, AddressSize addressSize, ulong registerAddress) { this.addressSpace = addressSpace; this.registerBitWidth = registerBitWidth; this.registerBitOffset = registerBitOffset; this.addressSize = addressSize; this.registerAddress = registerAddress; }
protected EncoderOpCodeHandler(Code code, uint opCode, int groupIndex, Encodable encodable, OperandSize opSize, AddressSize addrSize, TryConvertToDisp8N tryConvertToDisp8N, Op[] operands) { TEST_Code = code; OpCode = opCode; GroupIndex = groupIndex; Encodable = encodable; OpSize = opSize; AddrSize = addrSize; TryConvertToDisp8N = tryConvertToDisp8N; Operands = operands; }
protected OpCodeHandler(uint opCode, int groupIndex, OpCodeHandlerFlags flags, Encodable encodable, OperandSize opSize, AddressSize addrSize, TryConvertToDisp8N?tryConvertToDisp8N, Op[] operands) { OpCode = opCode; GroupIndex = groupIndex; Flags = flags; Encodable = encodable; OpSize = opSize; AddrSize = addrSize; TryConvertToDisp8N = tryConvertToDisp8N; Operands = operands; }
public LegacyOpCodeInfo(EnumValue code, MandatoryPrefix mandatoryPrefix, OpCodeTableKind table, uint opCode, int groupIndex, OperandSize operandSize, AddressSize addressSize, OpCodeFlags flags, LegacyOpKind[] opKinds) { Code = code; MandatoryPrefix = mandatoryPrefix; Table = table; OpCode = opCode; GroupIndex = groupIndex; Flags = flags; OperandSize = operandSize; AddressSize = addressSize; OpKinds = opKinds; }
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); }
public static int InBytes(this ImmediateSize size, OperandSize operandSize, AddressSize addressSize) { Contract.Requires(operandSize >= OperandSize.Word && operandSize <= OperandSize.Qword); switch (size) { case ImmediateSize.Zero: return 0; case ImmediateSize.Fixed8: return 1; case ImmediateSize.Fixed16: return 2; case ImmediateSize.Fixed32: return 4; case ImmediateSize.Fixed64: return 8; case ImmediateSize.Operand16Or32: return operandSize == OperandSize.Word ? 2 : 4; case ImmediateSize.Operand16Or32Or64: return operandSize == OperandSize.Qword ? 8 : 4; case ImmediateSize.Address16Or32: return addressSize == AddressSize._16 ? 2 : 4; default: throw new ArgumentException(nameof(size)); } }
public static DisplacementSize GetDisplacementSize(this ModRM modRM, Sib sib, AddressSize addressSize) { switch (modRM & ModRM.Mod_Mask) { case ModRM.Mod_IndirectDisplacement8: return DisplacementSize._8; case ModRM.Mod_IndirectLongDisplacement: return addressSize == AddressSize._16 ? DisplacementSize._16 : DisplacementSize._32; case ModRM.Mod_Direct: return 0; } // Mod = 0 if (addressSize == AddressSize._16) return GetRM(modRM) == 6 ? DisplacementSize._16 : DisplacementSize._0; if (GetRM(modRM) == 5) return DisplacementSize._32; // 32-bit mode, mod = 0, RM = 6 (sib byte) return (sib & Sib.Base_Mask) == Sib.Base_Special ? DisplacementSize._32 : DisplacementSize._0; }
public static EffectiveAddress Indirect( AddressSize addressSize, SegmentRegister? segment, GprCode @base, int displacement = 0) => Indirect(addressSize, segment, (AddressBaseRegister)@base, displacement);
public static EffectiveAddress Indirect( AddressSize addressSize, SegmentRegister? segment, AddressBaseRegister @base, int displacement = 0) => Indirect(addressSize, segment, @base, index: null, scale: 1, displacement: displacement);
public static bool IsEncodable(this DisplacementSize size, AddressSize addressSize) => (size == DisplacementSize._16) == (addressSize == AddressSize._16);
public static int GetImmediatesSizeInBytes(this InstructionEncoding encoding, OperandSize operandSize, AddressSize addressSize) { Contract.Requires(operandSize >= OperandSize.Word && operandSize <= OperandSize.Qword); return GetFirstImmediateSize(encoding).InBytes(operandSize, addressSize) + GetSecondImmediateSize(encoding).InBytes(operandSize, addressSize); }
public bool IsEncodableWithDefaultAddressSize(AddressSize defaultAddressSize) { var effectiveAddressSize = AddressSize; if (defaultAddressSize == AddressSize._16 && effectiveAddressSize == AddressSize._64) return false; if (defaultAddressSize == AddressSize._64) return effectiveAddressSize != AddressSize._16; // default size = 16 or 32 var baseFlags = flags & Flags.BaseReg_Mask; return (baseFlags < Flags.BaseReg_R8 || baseFlags == Flags.BaseReg_None) || (flags & Flags.IndexReg_Mask) < Flags.IndexReg_R8; }
public static CodeContext GetIA32e(AddressSize defaultAddressSize) { switch (defaultAddressSize) { case AddressSize._16: return CodeContext.Compatibility_Default16; case AddressSize._32: return CodeContext.Compatibility_Default32; case AddressSize._64: return CodeContext.SixtyFourBit; default: throw new ArgumentOutOfRangeException(nameof(defaultAddressSize)); } }
public static bool ImpliesSib(this ModRM modRM, AddressSize addressSize) => addressSize >= AddressSize._32 && GetRM(modRM) == 4 && GetMod(modRM) != 3;
public static EffectiveAddress RipRelative( AddressSize addressSize, SegmentRegister? segment, int displacement) { Contract.Requires(addressSize != AddressSize._16); return Indirect(addressSize, segment, AddressBaseRegister.Rip, displacement); }
public static EffectiveAddress FromEncoding(AddressSize defaultAddressSize, Encoding encoding) { if ((encoding.ModRM & ModRM.Mod_Mask) == ModRM.Mod_Direct) throw new ArgumentException("ModRM does not encode a memory operand."); var addressSize = defaultAddressSize.GetEffective(encoding.AddressSizeOverride); // Mod in { 0, 1, 2 } if (addressSize == AddressSize._16) { Contract.Assert(unchecked((short)encoding.Displacement) == encoding.Displacement); if (encoding.ModRM.GetMod() == 0 && encoding.ModRM.GetRM() == 6) return Absolute(addressSize, encoding.Displacement); int displacementSize = encoding.ModRM.GetMod(); Contract.Assert(displacementSize != 0 || encoding.Displacement == 0); Contract.Assert(displacementSize != 1 || unchecked((sbyte)encoding.Displacement) == encoding.Displacement); return FromIndirect16Encoding(encoding.Segment, encoding.ModRM.GetRM(), (short)encoding.Displacement); } else { if (encoding.ModRM.GetMod() == 0 && encoding.ModRM.GetRM() == 5) { return defaultAddressSize == AddressSize._64 ? RipRelative(addressSize, encoding.Segment, encoding.Displacement) : Absolute(addressSize, encoding.Displacement); } var displacementSize = encoding.ModRM.GetDisplacementSize(encoding.Sib.GetValueOrDefault(), addressSize); Contract.Assert(displacementSize.CanEncodeValue(encoding.Displacement)); GprCode? baseReg = (GprCode)encoding.ModRM.GetRM(); if (baseReg != GprCode.Esp) return Indirect(addressSize, encoding.Segment, baseReg.Value, encoding.Displacement); // Sib byte if (!encoding.Sib.HasValue) throw new ArgumentException(); baseReg = encoding.Sib.Value.GetBaseReg(encoding.ModRM); var index = encoding.Sib.Value.GetIndexReg(); int scale = encoding.Sib.Value.GetScale(); return Indirect(addressSize, encoding.Segment, baseReg, index, (byte)scale, encoding.Displacement); } }
private static Flags BaseFlags(AddressSize size) { switch (size) { case AddressSize._16: return Flags.AddressSize_16; case AddressSize._32: return Flags.AddressSize_32; case AddressSize._64: return Flags.AddressSize_64; default: throw new UnreachableException(); } }
public Encoding Encode(AddressSize defaultAddressSize, byte modReg, DisplacementSize displacementSize) { if ((defaultAddressSize == AddressSize._16 && AddressSize == AddressSize._64) || (defaultAddressSize == AddressSize._64 && AddressSize == AddressSize._16)) throw new ArgumentException(nameof(defaultAddressSize)); if (modReg >= 8) throw new ArgumentException(nameof(modReg)); if (!IsEncodableWithDisplacementSize(displacementSize)) throw new ArgumentException(nameof(displacementSize)); var encoding = new Encoding() { Segment = RequiresSegmentOverride ? Segment : (SegmentRegister?)null, AddressSizeOverride = AddressSize != defaultAddressSize, BaseRegExtension = BaseAsGprCode >= GprCode.R8, IndexRegExtension = IndexAsGprCode >= GprCode.R8, Displacement = displacement }; if (AddressSize == AddressSize._16) throw new NotImplementedException(); byte mod; switch (displacementSize) { case DisplacementSize._0: mod = 0; break; case DisplacementSize._8: mod = 1; break; default: mod = 2; break; } var @base = Base; bool needsSib = false; if (AddressSize == AddressSize._64) { // Same as 32-bit except that [disp32] encodes [rip + disp32] if ([email protected]) needsSib = true; if (@base == AddressBaseRegister.Rip) @base = null; } if (@base == AddressBaseRegister.SP || (mod == 0 && @base == AddressBaseRegister.BP)) needsSib = true; if (needsSib) { if (@base == AddressBaseRegister.BP) throw new NotImplementedException(); encoding.ModRM = ModRMEnum.FromComponents(mod, modReg, 0) | ModRM.RM_Sib; encoding.Sib = SibEnum.FromComponents( ss: (byte)((int)(flags & Flags.Scale_Mask) >> (int)Flags.Scale_Shift), index: (IndexAsGprCode ?? GprCode.SP).GetLow3Bits(), @base: (BaseAsGprCode ?? GprCode.BP).GetLow3Bits()); } else { encoding.ModRM = ModRMEnum.FromComponents(mod, modReg, (byte)((byte)@base.Value & 0x7)); } return encoding; }
private static Flags BaseFlags(AddressSize size, SegmentRegister segment) { var flags = BaseFlags(size); switch (segment) { case SegmentRegister.CS: flags |= Flags.Segment_C; break; case SegmentRegister.DS: flags |= Flags.Segment_D; break; case SegmentRegister.ES: flags |= Flags.Segment_E; break; case SegmentRegister.FS: flags |= Flags.Segment_F; break; case SegmentRegister.GS: flags |= Flags.Segment_G; break; case SegmentRegister.SS: flags |= Flags.Segment_S; break; default: throw new UnreachableException(); } return flags; }
private static Instruction DecodeSingle_IA32e(AddressSize defaultAddressSize, params byte[] bytes) => DecodeSingle(CodeContextEnum.GetIA32e(defaultAddressSize), bytes);
public static EffectiveAddress Absolute(AddressSize size, SegmentRegister segment, int address) { Contract.Requires(size > AddressSize._16 || (short)address == address); return new EffectiveAddress(BaseFlags(size, segment) | Flags.BaseReg_None | Flags.IndexReg_None, address); }
public static EffectiveAddress Indirect( AddressSize addressSize, SegmentRegister? segment, AddressBaseRegister? @base, GprCode? index = null, byte scale = 1, int displacement = 0) { Contract.Requires(scale == 1 || scale == 2 || scale == 4 || scale == 8 || (scale == 0 && !index.HasValue)); Contract.Requires(@base != AddressBaseRegister.Rip || (addressSize != AddressSize._16 && index.HasValue)); if (addressSize == AddressSize._16) { Contract.Requires(!(@base >= AddressBaseRegister.R8)); Contract.Requires(!(index >= GprCode.R8)); Contract.Requires((short)displacement == displacement); if (@base.HasValue) { if (index.HasValue) { Contract.Requires(@base == AddressBaseRegister.B || @base == AddressBaseRegister.BP); Contract.Requires(index.Value == GprCode.SI || index.Value == GprCode.DI); } else { Contract.Requires(@base == AddressBaseRegister.SI || @base == AddressBaseRegister.DI || @base == AddressBaseRegister.BP || @base == AddressBaseRegister.B); } } else { Contract.Requires(!index.HasValue); } } else { Contract.Requires(index != GprCode.Esp); } // Segment defaults to D, or S if we are using a stack-pointing register if (!segment.HasValue) { segment = (@base == AddressBaseRegister.SP || @base == AddressBaseRegister.BP) ? SegmentRegister.SS : SegmentRegister.DS; } var flags = BaseFlags(addressSize, segment.Value); if (@base.HasValue) flags |= (Flags)(((int)@base + 1) << (int)Flags.BaseReg_Shift); if (index.HasValue) { // Swap eax and esp (esp meaning "none") if (index.Value == GprCode.Eax) flags |= Flags.IndexReg_Eax; else flags |= (Flags)((int)index.Value << (int)Flags.IndexReg_Shift); } if (scale == 2) flags |= Flags.Scale_2x; else if (scale == 4) flags |= Flags.Scale_4x; else if (scale == 8) flags |= Flags.Scale_8x; return new EffectiveAddress(flags, displacement); }
public static EffectiveAddress Indirect( AddressSize addressSize, SegmentRegister? segment, GprCode? @base, GprCode? index = null, byte scale = 1, int displacement = 0) => Indirect(addressSize, segment, (AddressBaseRegister?)@base, index, scale, displacement);
public LegacyOpCodeInfo(EnumValue code, MandatoryPrefix mandatoryPrefix, OpCodeTableKind table, uint opCode, int groupIndex, OperandSize operandSize, AddressSize addressSize, OpCodeFlags flags, LegacyOpKind[] opKinds) : this(code, mandatoryPrefix, table, opCode, groupIndex, -1, operandSize, addressSize, flags, opKinds) { }
public static DisplacementSize GetMaximum(AddressSize addressSize) => addressSize == AddressSize._16 ? DisplacementSize._16 : DisplacementSize._32;