private void Emit(OpcodeMap map, byte opcode8, byte opcode, Gpr reg, EffectiveAddress rm) { WritePrefixes(reg, rm); Emit(map, reg.Size == OperandSize.Byte ? opcode8 : opcode); var displacementSize = rm.MinimumDisplacementSize; var encoding = rm.Encode( context.GetDefaultAddressSize(), reg.Code.GetLow3Bits(), displacementSize); Write(encoding.ModRM); if (encoding.Sib.HasValue) Write(encoding.Sib.Value); switch (displacementSize) { case DisplacementSize._8: Write((sbyte)encoding.Displacement); break; case DisplacementSize._16: Write((short)encoding.Displacement); break; case DisplacementSize._32: Write(encoding.Displacement); break; } }
private void WritePrefixes(Gpr reg, EffectiveAddress effectiveAddress) { if (effectiveAddress.RequiresSegmentOverride) Write(LegacyPrefixEnum.GetSegmentOverride(effectiveAddress.Segment)); var effectiveAddressSize = effectiveAddress.AddressSize; if (effectiveAddressSize != context.GetDefaultAddressSize()) { if (effectiveAddressSize != context.GetEffectiveAddressSize(@override: true)) throw new InvalidDataException(); Write(LegacyPrefix.AddressSizeOverride); } // Rex Rex? rex = null; if (reg.Part == GprPart.Qword) { if (context != CodeContext.SixtyFourBit) throw new ArgumentException("reg"); rex = rex.GetValueOrDefault() | Rex.OperandSize64; } else if (reg.Size == OperandSize.Byte) { // Might require rex for low byte throw new NotImplementedException(); } if (reg.Code >= GprCode.R8) rex = rex.GetValueOrDefault() | Rex.ModRegExtension; if (effectiveAddress.BaseAsGprCode >= GprCode.R8) rex = rex.GetValueOrDefault() | Rex.BaseRegExtension; if (effectiveAddress.IndexAsGprCode >= GprCode.R8) rex = rex.GetValueOrDefault() | Rex.IndexRegExtension; if (rex.HasValue) Write(rex.Value); }
private void Emit(byte opcode8, byte opcode, Gpr reg, EffectiveAddress rm) => Emit(OpcodeMap.Default, opcode8, opcode, reg, rm);
public void Mov(Gpr dest, EffectiveAddress src) => Emit(0x8A, 0x8B, dest, src);
public void Mov(EffectiveAddress dest, Gpr src) => Emit(0x88, 0x89, src, dest);