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; }
public bool IsEncodableWithDisplacementSize(DisplacementSize size) { return size >= MinimumDisplacementSize && (size == DisplacementSize._16) == (AddressSize == AddressSize._16); }