arch_ops/x86/
insn.rs

1use std::io::{Read, Write};
2
3use crate::traits::{Address, InsnRead, InsnWrite, Reloc};
4
5use super::{X86Register, X86RegisterClass};
6
7#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
8pub enum Prefix {
9    Lock,
10    Rep,
11    Repnz,
12    Repz,
13}
14
15#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
16pub enum X86Mode {
17    Real,
18    Protected,
19    Virtual8086,
20    Compatibility,
21    Long,
22}
23
24impl X86Mode {
25    pub fn default_mode_for(target: &Target) -> Option<X86Mode> {
26        match target.arch() {
27            target_tuples::Architecture::I86 => Some(X86Mode::Real),
28            target_tuples::Architecture::I8086 => Some(X86Mode::Real),
29            target_tuples::Architecture::I086 => Some(X86Mode::Real),
30            target_tuples::Architecture::I186 => Some(X86Mode::Real),
31            target_tuples::Architecture::I286 => Some(X86Mode::Real),
32            target_tuples::Architecture::I386 => Some(X86Mode::Protected),
33            target_tuples::Architecture::I486 => Some(X86Mode::Protected),
34            target_tuples::Architecture::I586 => Some(X86Mode::Protected),
35            target_tuples::Architecture::I686 => Some(X86Mode::Protected),
36            target_tuples::Architecture::X86_64 => Some(X86Mode::Long),
37            _ => None,
38        }
39    }
40
41    pub fn largest_gpr(&self) -> X86RegisterClass {
42        match self {
43            Self::Real | Self::Virtual8086 => X86RegisterClass::Word,
44            Self::Protected | Self::Compatibility => X86RegisterClass::Double,
45            Self::Long => X86RegisterClass::Quad,
46        }
47    }
48}
49
50#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
51pub enum X86OperandType {
52    /// The Mod and R/M portions of a ModR/M byte (potentially with a trailing SIB byte)
53    /// If an 1-byte register is used, use the class Byte. REX prefix will correctly shift it to ByteRex
54    ModRM(X86RegisterClass),
55    /// The Mod and R/M portions of a ModR/M Byte, except that no registers cannot be used and size checking should not be performed
56    ModRMMem,
57    /// The R portion of a ModR/M byte
58    /// If an 1-byte register is used, use the class Byte. REX prefix will correctly shift it to ByteRex
59    Reg(X86RegisterClass),
60    /// A Register Number embedded in the Opcode
61    /// If an 1-byte register is used, use the class Byte. REX prefix will correctly shift it to ByteRex
62    OpReg(X86RegisterClass),
63
64    /// m/r16/32/64 depending on mode and prefixes
65    ModRMGeneral,
66
67    /// m/r16/32/64 depending on mode and 66h prefix
68    ModRMMode,
69
70    /// A memory operand that must be encoded in an SIB byte
71    ModRMSib(X86RegisterClass),
72
73    /// Either STi or a memory reference with a given size
74    ModRMReal(X86RegisterClass),
75
76    /// A register encoded in the r/m field of the ModRM byte
77    ModRMReg(X86RegisterClass),
78
79    // xmm/m32/64
80    ModRMScalar(X86RegisterClass),
81
82    // xmm/ymm/zmm
83    VexReg,
84    // xmm/ymm/zmm/m128/m256/m512
85    VexModRM,
86    // x/y/zmm/m32/64
87    VexModRMScalar(X86RegisterClass),
88
89    // Instruction uses VEX/EVEX encoding, even if no vector registers are present
90    // Class indicates the Size field for the VEX/EVEX prefix (EVEX forced if [`X86RegisterClass::Zmm`])
91    VexPrefix(X86RegisterClass),
92
93    /// r16/32/64 depending on mode and prefixes
94    RegGeneral,
95
96    /// A register Number embedded in the opcode, with size depending on mode and prefix
97    OpRegGeneral,
98
99    /// A register number emebedded in the opcode, with size depending on the mode and 66h prefix
100    OpRegMode,
101
102    /// AL/rAX depending on class
103    /// Note: Suprising results may occur if a class other than Byte, Word, Double, or Quad is Used
104    AReg(X86RegisterClass),
105
106    /// rAX depending on mode and prefixes
107    ARegGeneral,
108
109    /// rAX depening on the mode only
110    ARegMode,
111
112    DReg(X86RegisterClass),
113
114    DRegGeneral,
115
116    CReg(X86RegisterClass),
117
118    CRegGeneral,
119
120    Flags(X86RegisterClass),
121
122    FlagsMode,
123
124    /// A trailing Instruciton (prefix opcode other than 0x0F or VEX)
125    Insn,
126    /// Vector Instruction (VEX prefix)
127    VecInsn,
128    /// Immediate value
129    Imm(usize),
130
131    /// Immediate value depending on prefix and mode (no REX.W)
132    ImmGeneral,
133
134    /// Immediate value depending on prefix and mode (respects REX.W in 64-bit mode)
135    ImmGeneralWide,
136
137    /// A relative Word with a given Instruction Address size
138    Rel(usize),
139
140    /// A relative address with size given by mode and 66h prefix
141    RelGeneral,
142
143    /// Sets bits in the R field of the ModR/M byte.
144    RControlBits(u8),
145
146    // 16-bit segment value or GDT offset
147    Seg,
148
149    /// xmm/ymm/zmm depending on prefixes and control bits in prefixes
150    AvxReg,
151
152    /// m128/256/512 depending on prefixes and control bits in prefixes
153    AvxMem,
154
155    Moff(X86RegisterClass),
156    MoffGeneral,
157
158    /// Memory Reference referring to the destination address, which is always es:eDI or rDI depending on mode.
159    /// In legacy mode, es is not controlled by any segment override prefix
160    MemDest(X86RegisterClass),
161    /// m16/32/64, which is always es:eDI or rDI depending on mode. In legacy mode, es is not controlled by any segment override prefix
162    MemDestGeneral,
163    /// Memory Reference referring to the source address, which is always ds:eSI or rSI depending on mode.
164    /// In legacy mode, ds is controlled by the segment override prefix.
165    MemSrc(X86RegisterClass),
166    // m16/32/64, which is always ds:eSI or rSI depending on mode. In legacy mode, ds is controlled by the segment override prefix
167    MemSrcGeneral,
168}
169
170macro_rules! define_x86_instructions {
171    {
172        $(($enum:ident, $mnemonic:literal, $opcode:literal, [$($operand:expr),*] $(, [$($mode:ident),*] $(, [$($feature:ident),*])?)?)),* $(,)?
173    } => {
174        #[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
175        #[non_exhaustive]
176        pub enum X86Opcode {
177            $($enum,)* __NoMoreOpcodes
178        }
179
180        impl X86Opcode{
181            pub fn opcode(&self) -> u64 {
182                match self {
183                    $(Self::$enum => $opcode,)*
184                    Self::__NoMoreOpcodes => unreachable!(),
185                }
186            }
187
188            pub fn operands(&self) -> &'static [X86OperandType] {
189                match self {
190                    $(Self::$enum => &[$($operand),*],)*
191                    Self::__NoMoreOpcodes => unreachable!(),
192                }
193            }
194
195            pub fn mnemonic(&self) -> &'static str {
196                match self {
197                    $(Self:: $enum => $mnemonic,)*
198                    Self::__NoMoreOpcodes => unreachable!(),
199                }
200            }
201
202            pub fn valid_in_mode(&self, modes: &X86Mode) -> bool {
203                #[allow(unreachable_code)] // it's not unreachable in all expansions, and we want the default expansion to return true
204                match self{
205                    $(Self:: $enum =>{ $(return match modes {
206                        $(X86Mode:: $mode => true,)*
207                        _ => false
208                    };)? true}),*
209                    Self::__NoMoreOpcodes => unreachable!(),
210                }
211            }
212
213        }
214
215        impl std::fmt::Display for X86Opcode {
216            fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
217                match self {
218                    $(Self::$enum => f.write_str($mnemonic),)*
219                    Self::__NoMoreOpcodes => unreachable!(),
220                }
221            }
222        }
223
224        pub const X86_OPCODES: [X86Opcode; X86Opcode::__NoMoreOpcodes as usize] = [ $(X86Opcode::$enum,)* ];
225    }
226}
227
228use target_tuples::Target;
229use X86OperandType::*;
230use X86RegisterClass::*;
231
232define_x86_instructions! {
233    (AddMR8,  "add", 0x00, [ModRM(Byte), Reg(Byte)]),
234    (AddMR,   "add", 0x01, [ModRMGeneral, RegGeneral]),
235    (AddRM8,  "add", 0x02, [Reg(Byte), ModRM(Byte)]),
236    (AddRM,   "add", 0x03, [RegGeneral, ModRMGeneral]),
237    (AddAImm8,"add", 0x04, [AReg(Byte), Imm(1)]),
238    (AddAImm, "add", 0x05, [ARegGeneral, ImmGeneral]),
239    (OrMR8,   "or",  0x08, [ModRM(Byte), Reg(Byte)]),
240    (OrMR,    "or",  0x09, [ModRMGeneral, RegGeneral]),
241    (OrRM8,   "or",  0x0A, [Reg(Byte), ModRM(Byte)]),
242    (OrRM,    "or",  0x0B, [RegGeneral, ModRMGeneral]),
243    (OrAImm8, "or",  0x0C, [AReg(Byte), Imm(1)]),
244    (OrAImm,  "or",  0x0D, [ARegGeneral, ImmGeneral]),
245    (AdcMR8,  "adc", 0x10, [ModRM(Byte), Reg(Byte)]),
246    (AdcMR,   "adc", 0x11, [ModRMGeneral, RegGeneral]),
247    (AdcRM8,  "adc", 0x12, [Reg(Byte), ModRM(Byte)]),
248    (AdcRM,   "adc", 0x13, [RegGeneral, ModRMGeneral]),
249    (AdcAImm8,"adc", 0x14, [AReg(Byte), Imm(1)]),
250    (AdcAImm, "adc", 0x15, [ARegGeneral, ImmGeneral]),
251    (SbbMR8,  "sbb", 0x18, [ModRM(Byte), Reg(Byte)]),
252    (SbbMR,   "sbb", 0x19, [ModRMGeneral, RegGeneral]),
253    (SbbRM8,  "sbb", 0x1A, [Reg(Byte), ModRM(Byte)]),
254    (SbbRM,   "sbb", 0x1B, [RegGeneral, ModRMGeneral]),
255    (SbbAImm8,"sbb", 0x1C, [AReg(Byte), Imm(1)]),
256    (SbbaImm, "sbb", 0x1D, [ARegGeneral, ImmGeneral]),
257    (AndMR8,  "and", 0x20, [ModRM(Byte), Reg(Byte)]),
258    (AndMR,   "and", 0x21, [ModRMGeneral, RegGeneral]),
259    (AndRM8,  "and", 0x22, [Reg(Byte), ModRM(Byte)]),
260    (AndRM,   "and", 0x23, [RegGeneral, ModRMGeneral]),
261    (AndAImm8,"and", 0x24, [AReg(Byte), Imm(1)]),
262    (AndAImm, "and", 0x25, [ARegGeneral, ImmGeneral]),
263    (SubMR8,  "sub", 0x28, [ModRM(Byte), Reg(Byte)]),
264    (SubMR,   "sub", 0x29, [ModRMGeneral, RegGeneral]),
265    (SubRM8,  "sub", 0x2A, [Reg(Byte), ModRM(Byte)]),
266    (SubRM,   "sub", 0x2B, [RegGeneral, ModRMGeneral]),
267    (SubAImm8,"sub", 0x2C, [AReg(Byte), Imm(1)]),
268    (SubAImm, "sub", 0x2D, [ARegGeneral, ImmGeneral]),
269    (XorMR8,  "xor", 0x30, [ModRM(Byte), Reg(Byte)]),
270    (XorMR,   "xor", 0x31, [ModRMGeneral, RegGeneral]),
271    (XorRM8,  "xor", 0x32, [Reg(Byte), ModRM(Byte)]),
272    (XorRM,   "xor", 0x33, [RegGeneral, ModRMGeneral]),
273    (XorAImm8,"xor", 0x34, [AReg(Byte), Imm(1)]),
274    (XorAImm, "xor", 0x35, [ARegGeneral, ImmGeneral]),
275    (CmpMR8,  "cmp", 0x38, [ModRM(Byte), Reg(Byte)]),
276    (CmpMR,   "cmp", 0x39, [ModRMGeneral, RegGeneral]),
277    (CmpRM8,  "cmp", 0x3A, [Reg(Byte), ModRM(Byte)]),
278    (CmpRM,   "cmp", 0x3B, [RegGeneral, ModRMGeneral]),
279    (CmpAImm8,"cmp", 0x3C, [AReg(Byte), Imm(1)]),
280    (CmpAImm, "cmp", 0x3D, [ARegGeneral, ImmGeneral]),
281    (IncR,    "inc", 0x40, [OpRegMode], [Real, Protected, Virtual8086, Compatibility]),
282    (Rex,     "rex", 0x40, [Insn], [Long]),
283    (RexB,    "rex.b",0x41, [Insn], [Long]),
284    (RexX,    "rex.x",0x42, [Insn], [Long]),
285    (RexXB,   "rex.xb",0x43, [Insn], [Long]),
286    (RexR,    "rex.r", 0x44, [Insn], [Long]),
287    (RexRB,   "rex.rb",0x45, [Insn], [Long]),
288    (RexRX,   "rex.rx",0x46, [Insn], [Long]),
289    (RexRXB,  "rex.rxb", 0x47, [Insn], [Long]),
290    (DecR,    "dec", 0x48, [OpRegMode], [Real, Protected, Virtual8086, Compatibility]),
291    (RexW,    "rex.w", 0x48, [Insn], [Long]),
292    (RexWB,   "rex.wb",0x49, [Insn], [Long]),
293    (RexWX,   "rex.wx",0x4A, [Insn], [Long]),
294    (RexWXB,  "rex.wxb",0x4B, [Insn], [Long]),
295    (RexWR,   "rex.wr", 0x4C, [Insn], [Long]),
296    (RexWRB,  "rex.wrb",0x4D, [Insn], [Long]),
297    (RexWRX,  "rex.wrx",0x4E, [Insn], [Long]),
298    (RexWRXB, "rex.wrxb", 0x4F, [Insn], [Long]),
299    (Push,    "push",0x50, [OpRegMode]),
300    (Pop,     "pop", 0x58, [OpRegMode]),
301    (Movsxd,  "movsxd",0x63, [RegGeneral, ModRM(Double)]),
302    (FsSeg,   "fs",  0x64, [Insn]),
303    (GsSeg,   "gs",  0x65, [Insn]),
304    (OpSize,  "66h", 0x66, [Insn]),
305    (AddrSize,"67h", 0x67, [Insn]),
306    (PushImm, "push",0x68, [ImmGeneral]),
307    (IMul,    "imul",0x69, [RegGeneral, ModRMGeneral, ImmGeneral]),
308    (PushImm8,"push",0x6A, [Imm(8)]),
309    (IMul8,   "imul",0x6B, [RegGeneral, ModRMGeneral, Imm(8)]),
310    (Insb,    "ins", 0x6C, [ModRM(Byte), DReg(Byte)]),
311    (Ins,     "ins", 0x6D, [ModRMGeneral, DRegGeneral]),
312    (Outsb,   "outs",0x6E, [DReg(Byte), ModRM(Byte)]),
313    (Outs,    "outs",0x6F, [DRegGeneral, ModRMGeneral]),
314    (Jo,      "jo",  0x70, [Rel(8)]),
315    (Jno,     "jno", 0x71, [Rel(8)]),
316    (Jb,      "jb",  0x72, [Rel(8)]),
317    (Jae,     "jae", 0x73, [Rel(8)]),
318    (Jz,      "jz",  0x74, [Rel(8)]),
319    (Jnz,     "jnz", 0x75, [Rel(8)]),
320    (Jbe,     "jbe", 0x76, [Rel(8)]),
321    (Ja,      "ja",  0x77, [Rel(8)]),
322    (Js,      "js",  0x78, [Rel(8)]),
323    (Jns,     "jns", 0x79, [Rel(8)]),
324    (Jp,      "jp",  0x7A, [Rel(8)]),
325    (Jnp,     "jnp", 0x7B, [Rel(8)]),
326    (Jl,      "jl",  0x7C, [Rel(8)]),
327    (Jge,     "jge", 0x7D, [Rel(8)]),
328    (Jle,     "jle", 0x7E, [Rel(8)]),
329    (Jg,      "jg",  0x7F, [Rel(8)]),
330    (AddImm8, "add", 0x80, [RControlBits(0), ModRM(Byte), Imm(8)]),
331    (OrImm8,  "or",  0x80, [RControlBits(1), ModRM(Byte), Imm(8)]),
332    (AdcImm8, "adc", 0x80, [RControlBits(2), ModRM(Byte), Imm(8)]),
333    (SbbImm8, "sbb", 0x80, [RControlBits(3), ModRM(Byte), Imm(8)]),
334    (AndImm8, "and", 0x80, [RControlBits(4), ModRM(Byte), Imm(8)]),
335    (SubImm8, "sub", 0x80, [RControlBits(5), ModRM(Byte), Imm(8)]),
336    (XorImm8, "xor", 0x80, [RControlBits(6), ModRM(Byte), Imm(8)]),
337    (CmpImm8, "cmp", 0x80, [RControlBits(6), ModRM(Byte), Imm(8)]),
338    (AddImm,  "add", 0x81, [RControlBits(0), ModRMGeneral, ImmGeneral]),
339    (OrImm,   "or",  0x81, [RControlBits(1), ModRMGeneral, ImmGeneral]),
340    (AdcImm,  "adc", 0x81, [RControlBits(2), ModRMGeneral, ImmGeneral]),
341    (SbbImm,  "sbb", 0x81, [RControlBits(3), ModRMGeneral, ImmGeneral]),
342    (AndImm,  "and", 0x81, [RControlBits(4), ModRMGeneral, ImmGeneral]),
343    (SubImm,  "sub", 0x81, [RControlBits(5), ModRMGeneral, ImmGeneral]),
344    (XorImm,  "xor", 0x81, [RControlBits(6), ModRMGeneral, ImmGeneral]),
345    (CmpImm,  "cmp", 0x81, [RControlBits(7), ModRMGeneral, ImmGeneral]),
346    (AddGImm8,"add", 0x83, [RControlBits(0), ModRMGeneral, Imm(8)]),
347    (OrGImm8, "or",  0x83, [RControlBits(1), ModRMGeneral, Imm(8)]),
348    (AdcGImm8,"adc", 0x83, [RControlBits(2), ModRMGeneral, Imm(8)]),
349    (SbbGImm8,"sbb", 0x83, [RControlBits(3), ModRMGeneral, Imm(8)]),
350    (AndGImm8,"and", 0x83, [RControlBits(4), ModRMGeneral, Imm(8)]),
351    (SubGImm8,"sub", 0x83, [RControlBits(5), ModRMGeneral, Imm(8)]),
352    (XorGImm8,"xor", 0x83, [RControlBits(6), ModRMGeneral, Imm(8)]),
353    (CmpGImm8,"cmp", 0x83, [RControlBits(7), ModRMGeneral, Imm(8)]),
354    (Test8,   "test",0x84, [ModRM(Byte),Reg(Byte)]),
355    (Test,    "test",0x85, [ModRMGeneral, RegGeneral]),
356    (Xchg8,   "xchg",0x86, [Reg(Byte), ModRM(Byte)]),
357    (Xchg,    "xchg",0x87, [RegGeneral, ModRMGeneral]),
358    (MovMR8,  "mov", 0x88, [ModRM(Byte),Reg(Byte)]),
359    (MovMR,   "mov", 0x89, [ModRMGeneral, RegGeneral]),
360    (MovRM8,  "mov", 0x8A, [Reg(Byte), ModRM(Byte)]),
361    (MovRM,   "mov", 0x8B, [RegGeneral, ModRMGeneral]),
362    (MovRMS,  "mov", 0x8C, [ModRMGeneral, Reg(Sreg)]),
363    (Lea,     "lea", 0x8D, [RegGeneral, ModRMGeneral]),
364    (MovSRM,  "mov", 0x8E, [Reg(Sreg), ModRM(Word)]),
365    (PopMR,   "pop", 0x8F, [ModRMMode]),
366    (Nop90,   "nop", 0x90, []),
367    (XchgReg, "xchg",0x90, [OpRegGeneral,ARegGeneral]),
368    (Cbw, "cbw", 0x98, [AReg(Word), AReg(Byte)]),
369    (Cwde, "cwde", 0x98, [AReg(Double), AReg(Word)]),
370    (Cdqe, "cdqe", 0x98, [AReg(Quad), AReg(Word)]),
371    (Cwd, "cwd", 0x99, [DReg(Word), AReg(Word)]),
372    (Cdq, "cdq", 0x99, [DReg(Double), DReg(Double)]),
373    (Cdo, "cqo", 0x99, [DReg(Quad),DReg(Quad)]),
374    (Fwait, "fwait", 0x9B, []),
375    (Pushf, "pushf", 0x9C, [FlagsMode]),
376    (Popf, "popf", 0x9D, [FlagsMode]),
377    (Sahf,"sahf",0x9E, []),
378    (Lahf, "lahf", 0x9F, []),
379    (MovAlM, "mov", 0xA0, [AReg(Byte), Moff(Byte)]),
380    (MovAregM, "mov", 0xA1, [ARegGeneral, MoffGeneral]),
381    (MovMAl, "mov", 0xA2, [Moff(Byte), AReg(Byte)]),
382    (MovMAreg, "mov", 0xA3, [MoffGeneral, ARegGeneral]),
383    (Movsb,"movs", 0xA4, [MemDest(Byte),MemSrc(Byte)]),
384    (Movs, "movs", 0xA5, [MemDestGeneral, MemSrcGeneral]),
385    (Cmpsb, "cmps", 0xA6, [MemDest(Byte),MemSrc(Byte)]),
386    (Cmps, "cmps", 0xA7, [MemDestGeneral, MemSrcGeneral]),
387    (TestAreg8, "test", 0xA8, [AReg(Byte),Imm(8)]),
388    (TestAreg, "test", 0xA9, [ARegGeneral,ImmGeneral]),
389    (Stosb, "stos", 0xAA, [MemDest(Byte),AReg(Byte)]),
390    (Stos, "stos", 0xAB,[MemDestGeneral,ARegGeneral]),
391    (Lodsb, "lods",0xAC, [AReg(Byte),MemSrc(Byte)]),
392    (Lods, "lods", 0xAD, [ARegGeneral, MemSrcGeneral]),
393    (Scasb, "scas", 0xAE, [MemDest(Byte), AReg(Byte)]),
394    (Scas, "scas", 0xAF, [MemDestGeneral, ARegGeneral]),
395    (MovImm8, "mov", 0xB0, [OpReg(Byte),Imm(8)]),
396    (MovImm, "mov", 0xB8, [OpRegGeneral, ImmGeneralWide]),
397    (RolImm8, "rol", 0xC0, [RControlBits(0),ModRM(Byte),Imm(8)]),
398    (RorImm8, "ror", 0xC0, [RControlBits(1),ModRM(Byte),Imm(8)]),
399    (RclImm8, "rcl", 0xC0, [RControlBits(2),ModRM(Byte),Imm(8)]),
400    (RcrImm8, "rcr", 0xC0, [RControlBits(3),ModRM(Byte), Imm(8)]),
401    (ShlImm8, "shl", 0xC0, [RControlBits(4), ModRM(Byte), Imm(8)]),
402    (ShrImm8, "shr", 0xC0, [RControlBits(5),ModRM(Byte),Imm(8)]),
403    (Shl2Imm8, "shl", 0xC0, [RControlBits(6), ModRM(Byte), Imm(8)]),
404    (SarImm8, "sar", 0xC0, [RControlBits(7), ModRM(Byte), Imm(8)]),
405    (RolImm, "rol", 0xC1, [RControlBits(0), ModRMGeneral,Imm(8)]),
406    (RorImm, "ror", 0xC1, [RControlBits(1), ModRMGeneral,Imm(8)]),
407    (RclImm, "rcl", 0xC1, [RControlBits(2), ModRMGeneral,Imm(8)]),
408    (RcrImm, "rcr", 0xC1, [RControlBits(3), ModRMGeneral, Imm(8)]),
409    (ShlImm, "shl", 0xC1, [RControlBits(4), ModRMGeneral, Imm(8)]),
410    (ShrImm, "shr", 0xC1, [RControlBits(5), ModRMGeneral,Imm(8)]),
411    (Shl2Imm, "shl", 0xC1, [RControlBits(6), ModRMGeneral, Imm(8)]),
412    (SarImm, "sar", 0xC1, [RControlBits(7), ModRMGeneral, Imm(8)]),
413    (RetnPop, "retn", 0xC2, [Imm(16)]),
414    (Retn, "retn", 0xC3, []),
415    (MovImmM8, "mov", 0xC6, [RControlBits(0),ModRM(Byte), Imm(8)]),
416    (MovImmM, "mov", 0xC7, [RControlBits(0),ModRMGeneral, ImmGeneral]),
417    (Enter, "enter", 0xC8, [Imm(16),Imm(8)]),
418    (Leave,"leave", 0xC9, []),
419    (RetfPop, "retf", 0xCA, [Imm(16)]),
420    (Retf, "retf", 0xCB, []),
421    (Int3, "int3", 0xCC, []),
422    (Int,"int", 0xCD, [Imm(8)]),
423    (IntO, "into",0xCE,[]),
424    (IRet,"iret",0xCF, []),
425    (Rol8, "rol", 0xD0, [RControlBits(0),ModRM(Byte)]),
426    (Ror8, "ror", 0xD0, [RControlBits(1),ModRM(Byte)]),
427    (Rcl8, "rcl", 0xD0, [RControlBits(2),ModRM(Byte)]),
428    (Rcr8, "rcr", 0xD0, [RControlBits(3),ModRM(Byte)]),
429    (Shl8, "shl", 0xD0, [RControlBits(4), ModRM(Byte)]),
430    (Shr8, "shr", 0xD0, [RControlBits(5),ModRM(Byte)]),
431    (Shl2_8, "shl", 0xD0, [RControlBits(6), ModRM(Byte)]),
432    (Sar8, "sar", 0xD0, [RControlBits(7), ModRM(Byte)]),
433    (Rol, "rol", 0xD1, [RControlBits(0), ModRMGeneral]),
434    (Ror, "ror", 0xD1, [RControlBits(1), ModRMGeneral]),
435    (Rcl, "rcl", 0xD1, [RControlBits(2), ModRMGeneral]),
436    (Rcr, "rcr", 0xD1, [RControlBits(3), ModRMGeneral]),
437    (Shl, "shl", 0xD1, [RControlBits(4), ModRMGeneral]),
438    (Shr, "shr", 0xD1, [RControlBits(5), ModRMGeneral]),
439    (Shl2, "shl", 0xD1, [RControlBits(6), ModRMGeneral]),
440    (Sar, "sar", 0xD1, [RControlBits(7), ModRMGeneral]),
441    (RolCL8, "rol", 0xD2, [RControlBits(0),  ModRM(Byte) , CReg(Byte)]),
442    (RorCL8, "ror", 0xD2, [RControlBits(1),  ModRM(Byte) , CReg(Byte)]),
443    (RclCL8, "rcl", 0xD2, [RControlBits(2),  ModRM(Byte) , CReg(Byte)]),
444    (RcrCL8, "rcr", 0xD2, [RControlBits(3),  ModRM(Byte) , CReg(Byte)]),
445    (ShlCL8, "shl", 0xD2, [RControlBits(4),  ModRM(Byte) , CReg(Byte)]),
446    (ShrCL8, "shr", 0xD2, [RControlBits(5),  ModRM(Byte) , CReg(Byte)]),
447    (Shl2CL8, "shl", 0xD2, [RControlBits(6), ModRM(Byte) , CReg(Byte)]),
448    (SarCL8, "sar", 0xD2, [RControlBits(7),  ModRM(Byte) , CReg(Byte)]),
449    (RolCL, "rol", 0xD3, [RControlBits(0),   ModRMGeneral, CReg(Byte)]),
450    (RorCL, "ror", 0xD3, [RControlBits(1),   ModRMGeneral, CReg(Byte)]),
451    (RclCL, "rcl", 0xD3, [RControlBits(2),   ModRMGeneral, CReg(Byte)]),
452    (RcrCL, "rcr", 0xD3, [RControlBits(3),   ModRMGeneral, CReg(Byte)]),
453    (ShlCL, "shl", 0xD3, [RControlBits(4),   ModRMGeneral, CReg(Byte)]),
454    (ShrCL, "shr", 0xD3, [RControlBits(5),   ModRMGeneral, CReg(Byte)]),
455    (Shl2CL, "shl", 0xD3, [RControlBits(6),  ModRMGeneral, CReg(Byte)]),
456    (SarCL, "sar", 0xD3, [RControlBits(7),   ModRMGeneral, CReg(Byte)]),
457    (Xlat, "xlat", 0xD7, [ModRM(Byte)]),
458    // Note: Double here is still X86RegisterClass::Double (dword), as in a 32-byte memory reference (m32real), not a double precision floating-point value
459    (Fadd, "fadd", 0xD8, [RControlBits(0), ModRMReal(Double)]),
460    (Fmul, "fmul", 0xD8, [RControlBits(1), ModRMReal(Double)]),
461    (Fcom, "fcom", 0xD8, [RControlBits(2),ModRMReal(Double)]),
462    (Fcomp, "fcomp",0xD8, [RControlBits(3), ModRMReal(Double)]),
463    (Fsub, "fsub", 0xD8, [RControlBits(4), ModRMReal(Double)]),
464    (Fsubr, "fsubr", 0xD8, [RControlBits(5), ModRMReal(Double)]),
465    (Fdiv, "fdiv", 0xD8, [RControlBits(6), ModRMReal(Double)]),
466    (Fdivr, "fdivr", 0xD8, [RControlBits(7), ModRMReal(Double)]),
467    (Fld, "fld", 0xD9, [RControlBits(0), ModRMReal(Double)]),
468    (Fxch, "fxch", 0xD9, [RControlBits(1),ModRM(St)]),
469    (Fst, "fst",0xD9, [RControlBits(2),ModRMReal(Double)]),
470    (Fstp, "fstp", 0xD9, [RControlBits(3), ModRMReal(Double)]),
471    (Fldenv, "fldenv",0xD9, [RControlBits(4),ModRMMem]),
472    (Fchs, "fchs", 0xD9E0, []),
473    (Fabs, "fabs", 0xD9E1, []),
474    (Ftst, "ftst", 0xD9E4, []),
475    (Fxam, "fxam", 0xD9E5, []),
476    (Fldcw, "fldcw", 0xD9, [RControlBits(5),ModRMMem]),
477    (Fld1, "fld1", 0xD9E8,[]),
478    (FldL2T, "fldl2t", 0xD9E9, []),
479    (FldL2E, "fldl2e", 0xD9EA, []),
480    (FldPi, "fldpi", 0xD9EB, []),
481    (Fldlg2, "fldlg2", 0xD9EC, []),
482    (Fldln2, "fldln2", 0xD9ED, []),
483    (Fldz, "fldz", 0xD9EE, []),
484    (Fnstenv, "fnstenv", 0xD9, [RControlBits(6), ModRMMem]),
485    (Fstenv, "fstenv", 0x9BD9, [RControlBits(6), ModRMMem]),
486    (F2Xm1, "f2xm1", 0xD9F0, []),
487    (FYl2x, "fyl2x", 0xD9F1, []),
488    (Fptan, "fptan", 0xD9F2, []),
489    (Fpatan, "fpatan", 0xD9F3, []),
490    (Fxtract, "fxtract", 0xD9F4, []),
491    (Fprem1, "fprem1", 0xD9F5, []),
492    (FDecStp, "fdecstp", 0xD9F6, []),
493    (FIncStp, "fincstp", 0xD9F7, []),
494    (Fnstcw, "fnstcw", 0xD9, [RControlBits(6), ModRMMem]),
495    (Fstcw, "fstcw", 0x9BD9, [RControlBits(6), ModRMMem]),
496    (Fprem, "fprem", 0xD9F8, []),
497    (FYl2Xp1, "fyl2xp1", 0xD9F9, []),
498    (Fsqrt, "fsqrt", 0xD9FA, []),
499    (Fsincos, "fsincos", 0xD9FB, []),
500    (Frndint, "frndint", 0xD9FC, []),
501    (Fscale, "fscale", 0xD9FD, []),
502    (Fsin, "fsin", 0xD9FE, []),
503    (Fcos, "fcos", 0xD9FF, []),
504    (FCmovB, "fcmovb", 0xDA, [RControlBits(0),ModRMReg(St)]),
505    (FIadd, "fiadd", 0xDA, [RControlBits(0),ModRMReal(Double)]),
506    (FCmovE, "fcmove", 0xDA, [RControlBits(1), ModRMReg(St)]),
507    (FImul, "fimul", 0xDA, [RControlBits(1), ModRMReal(Double)]),
508    (FCmovBE, "fcmovbe", 0xDA, [RControlBits(2),ModRMReg(St)]),
509    (FIcom, "ficom", 0xDA, [RControlBits(2), ModRMReal(Double)]),
510    (FCmovU, "fcmovu", 0xDA, [RControlBits(3), ModRMReg(St)]),
511    (FIcomp, "ficomp", 0xDA, [RControlBits(3), ModRMReal(Double)]),
512    (FISub, "fisub", 0xDA, [RControlBits(4), ModRMReal(Double)]),
513    (FUcompp, "fucompp", 0xDA, [RControlBits(5), ModRMReg(St)]),
514    (FISubr, "fisubr", 0xDA, [RControlBits(5), ModRMReal(Double)]),
515    (FIdiv, "fidiv", 0xDA, [RControlBits(6), ModRMReal(Double)]),
516    (FIdivr, "fidivr", 0xDA, [RControlBits(7), ModRMReal(Double)]),
517    (FCmovNb, "fcmovnb", 0xDA, [RControlBits(0), ModRMReg(St)]),
518    (FIld, "fild", 0xDB, [RControlBits(0), ModRMReal(Double)]),
519    (FCmovNe, "fcmovne", 0xDB, [RControlBits(1), ModRMReg(St)]),
520    (FISttp, "fisttp", 0xDB, [RControlBits(1), ModRMReal(Double)]),
521    (FCmovNbe, "fcmovnbe", 0xDB, [RControlBits(2), ModRMReg(St)]),
522    (FIst, "fist", 0xDB, [RControlBits(2), ModRMReal(Double)]),
523    (FCMovNu, "fcmovnu", 0xDB, [RControlBits(3), ModRMReg(St)]),
524    (FIstp, "fistp", 0xDB, [RControlBits(3), ModRMReal(Double)]),
525    (Fneni, "fneni", 0xDBE0, []),
526    (Fndisi, "fndisi", 0xDBE1, []),
527    (Fnclex, "fnclex", 0xDBE2, []),
528    (Fclex, "fclex", 0x9BDBE2, []),
529    (Fninit, "fninit", 0xDBE3, []),
530    (Finit, "finit", 0x9BDBE3, []),
531    (Fnsetpm, "fnsetpm", 0xDBE4, []),
532    (Fld80, "fld", 0xDB, [RControlBits(5), ModRMReal(St)]),
533    (Fucmpi, "fucmpi", 0xDB, [RControlBits(6), ModRMReg(St)]),
534    (Fcmpi, "fcmpi", 0xDB, [RControlBits(7), ModRMReg(St)]),
535    (Fadd64, "fadd", 0xDC, [RControlBits(0), ModRMReal(Quad)]),
536    (Fmul64, "fmul", 0xDC, [RControlBits(1), ModRMReal(Quad)]),
537    (Fcom64, "fcom", 0xDC, [RControlBits(2), ModRMReal(Quad)]),
538    (Fcomp64, "fcomp", 0xDC, [RControlBits(3), ModRMReal(Quad)]),
539    (Fsub64, "fsub", 0xDC, [RControlBits(4), ModRMReal(Quad)]),
540    (Fsubr64, "fsubr", 0xDC, [RControlBits(5), ModRMReal(Quad)]),
541    (Fdiv64, "fdiv", 0xDC, [RControlBits(6), ModRMReal(Quad)]),
542    (Fdivr64, "fdivr",0xDC, [RControlBits(7), ModRMReal(Quad)]),
543    (LoopNz, "loopnz", 0xE0, [CRegGeneral, Rel(8)]),
544    (LoopZ, "loopz", 0xE1, [CRegGeneral, Rel(8)]),
545    (Loop, "loop", 0xE2, [CRegGeneral, Rel(8)]),
546    (Jcxz, "jcxz", 0xE3, [CRegGeneral, Rel(8)]),
547    (InImm8, "in", 0xE4, [AReg(Byte), Imm(8)]),
548    (InImm, "in", 0xE5, [ARegGeneral, Imm(8)]),
549    (OutImm8, "out", 0xE6, [AReg(Byte),Imm(8)]),
550    (OutImm, "out", 0xE7, [ARegGeneral, Imm(8)]),
551    (Call, "call", 0xE8, [RelGeneral]),
552    (Jmp, "jmp", 0xE9, [RelGeneral]),
553    (Jmpf, "jmpf", 0xEA, [Seg, RelGeneral]),
554    (Jmp8, "jmp", 0xEB, [Rel(8)]),
555    (In8, "in", 0xEC, [AReg(Byte), DReg(Word)]),
556    (In, "in", 0xED, [ARegGeneral, DReg(Word)]),
557    (Out8, "out", 0xEE, [AReg(Byte), DReg(Word)]),
558    (Out, "out", 0xEF, [ARegGeneral, DReg(Word)]),
559    (Int1, "int1", 0xF1, []),
560    (Hlt, "hlt", 0xF4, []),
561    (Cmc, "cmc", 0xF5, []),
562    (TestImm8, "test", 0xF6, [RControlBits(0), ModRM(Byte), Imm(8)]),
563    (TestImm82, "test", 0xF6, [RControlBits(0), ModRM(Byte), Imm(8)]),
564    (Not8, "not", 0xF6, [RControlBits(2), ModRM(Byte)]),
565    (Neg8, "neg", 0xF6, [RControlBits(3), ModRM(Byte)]),
566    (MulAl8, "mul",0xF6, [RControlBits(4), ModRM(Byte)]),
567    (IMulAl8, "imul", 0xF6, [RControlBits(5), ModRM(Byte)]),
568    (DivAx8, "div", 0xF6, [RControlBits(6), ModRM(Byte)]),
569    (IDivAx8, "idiv", 0xF6, [RControlBits(7), ModRM(Byte)]),
570    (TestImm, "test", 0xF7, [RControlBits(0), ModRMGeneral, ImmGeneral]),
571    (TestImm2, "test", 0xF7, [RControlBits(0), ModRMGeneral, ImmGeneral]),
572    (Not, "not", 0xF7, [RControlBits(2), ModRMGeneral]),
573    (Neg, "neg", 0xF7, [RControlBits(3), ModRMGeneral]),
574    (MulAreg, "mul",0xF7, [RControlBits(4), ARegGeneral, DRegGeneral, ModRMGeneral]),
575    (IMulAreg, "imul", 0xF7, [RControlBits(5), ARegGeneral, DRegGeneral, ModRMGeneral]),
576    (Div, "div", 0xF7, [RControlBits(6), ARegGeneral, DRegGeneral, ModRMGeneral]),
577    (IDiv, "idiv", 0xF7, [RControlBits(7), ARegGeneral, DRegGeneral, ModRMGeneral]),
578    (Clc, "clc", 0xF8, []),
579    (Stc, "stc", 0xF9, []),
580    (Cli, "cli", 0xFA, []),
581    (Sti, "sti", 0xFB, []),
582    (Cld, "cld", 0xFC, []),
583    (Std, "std", 0xFD, []),
584    (Inc8, "inc", 0xFE, [RControlBits(0), ModRM(Byte)]),
585    (Dec8, "dec", 0xFE, [RControlBits(1), ModRM(Byte)]),
586    (Inc, "inc", 0xFF, [RControlBits(0), ModRMGeneral]),
587    (Dec, "dec", 0xFF, [RControlBits(1), ModRMGeneral]),
588    (CallInd, "call", 0xFF, [RControlBits(2), ModRMGeneral]),
589    (Callf, "callf", 0xFF, [RControlBits(3), ModRMMem]),
590    (JmpInd, "jmp", 0xFF, [RControlBits(4), ModRMGeneral]),
591    (JmpfInd, "jmp", 0xFF, [RControlBits(5), ModRMMem]),
592    (PushRM, "push", 0xFF, [RControlBits(6), ModRMMode]),
593    (Ud2, "ud2", 0x0F0B, []),
594    (MovUpsRM, "movups", 0x0F10, [Reg(Xmm),ModRM(Xmm)]),
595    (MovSsRM, "movss", 0xF30F10, [Reg(Xmm), ModRMScalar(Double)]),
596    (MovUpdRM, "movupd", 0x660F10, [Reg(Xmm), ModRM(Xmm)]),
597    (MovSdRM, "movsd", 0xF20F10, [Reg(Xmm), ModRMScalar(Quad)]),
598    (VMovUpsRM, "vmovups", 0x0F10, [VexReg,VexModRM]),
599    (VMovSsRM, "vmovss", 0xF30F10, [VexReg, VexModRMScalar(Double)]),
600    (VMovUpdRM, "vmovupd", 0x660F10, [VexReg, VexModRM]),
601    (VMovSdRM, "vmovsd", 0xF20F10, [VexReg, VexModRMScalar(Quad)]),
602    (MovUpsMR, "movups", 0x0F11, [ModRM(Xmm),Reg(Xmm)]),
603    (MovSsMR, "movss", 0xF30F11, [ModRMScalar(Double),Reg(Xmm)]),
604    (MovUpdMR, "movupd", 0x660F11, [ModRM(Xmm),Reg(Xmm)]),
605    (MovSdMR, "movsd", 0xF20F11, [ModRMScalar(Quad), Reg(Xmm)]),
606    (VMovUpsMR, "vmovups", 0x0F11, [VexModRM,VexReg]),
607    (VMovSsMR, "vmovss", 0xF30F11, [VexModRMScalar(Double),VexReg]),
608    (VMovUpdMR, "vmovupd", 0x660F11, [VexModRM,VexReg]),
609    (VMovSdMR, "vmovsd", 0xF20F11, [VexModRMScalar(Quad),VexReg]),
610    (MovDRM, "movd", 0x0F6E, [Reg(Mmx),ModRM(Double)]),
611    (MovQRM, "movq", 0x0F6F, [Reg(Mmx),ModRM(Quad)]),
612    (MovDMR, "movd", 0x0F7E, [Reg(Mmx),ModRM(Double)]),
613    (MovQMR, "movq", 0x0F7F, [ModRM(Quad),Reg(Mmx)]),
614    (MFence, "mfence", 0x0FAE, []),
615
616    (TileLoadD, "tileloadd", 0xF20F384B,[VexPrefix(Xmm), Reg(Tmm), ModRMSib(Tmm)], [Long]),
617    (TileLoadDT1, "tileloaddt1", 0x660F384B,[VexPrefix(Xmm), Reg(Tmm), ModRMSib(Tmm)], [Long]),
618    (TileStoreD, "tilestored", 0xF30F384B, [VexPrefix(Xmm),ModRMSib(Tmm),Reg(Tmm)], [Long]),
619
620}
621
622#[derive(Clone, Debug, Hash, PartialEq, Eq)]
623pub enum ModRMRegOrSib {
624    Reg(X86Register),
625    Abs(Address),
626    RipRel(Address),
627    Sib {
628        scale: u32,
629        index: X86Register,
630        base: X86Register,
631    },
632    Index16 {
633        base: X86Register,
634        index: X86Register,
635    },
636}
637
638#[derive(Clone, Debug, Hash, PartialEq, Eq)]
639pub enum ModRM {
640    Indirect {
641        size: X86RegisterClass,
642        mode: ModRMRegOrSib,
643    },
644    IndirectDisp8 {
645        size: X86RegisterClass,
646        mode: ModRMRegOrSib,
647        disp8: i8,
648    },
649    IndirectDisp32 {
650        size: X86RegisterClass,
651        mode: ModRMRegOrSib,
652        disp32: i32,
653    },
654    Direct(X86Register),
655}
656
657impl ModRM {
658    pub fn with_disp32(self, disp: i32) -> Option<Self> {
659        match self {
660            ModRM::Indirect {
661                mode: ModRMRegOrSib::RipRel(_),
662                ..
663            }
664            | ModRM::Indirect {
665                mode: ModRMRegOrSib::Abs(_),
666                ..
667            } => todo!("[disp32]/[rIP+disp32]"),
668            ModRM::Indirect { size, mode } => Some(Self::IndirectDisp32 {
669                size,
670                mode,
671                disp32: disp,
672            }),
673            ModRM::IndirectDisp8 { size, mode, disp8 } => Some(ModRM::IndirectDisp32 {
674                size,
675                mode,
676                disp32: (disp8 as i32) + disp,
677            }),
678            ModRM::IndirectDisp32 { size, mode, disp32 } => Some(ModRM::IndirectDisp32 {
679                size,
680                mode,
681                disp32: disp32 + disp,
682            }),
683            ModRM::Direct(_) => None,
684        }
685    }
686
687    pub fn resize(self, size: X86RegisterClass) -> Option<ModRM> {
688        match self {
689            ModRM::Indirect { mode, .. } => Some(ModRM::Indirect { size, mode }),
690            ModRM::IndirectDisp8 { disp8, mode, .. } => {
691                Some(ModRM::IndirectDisp8 { size, mode, disp8 })
692            }
693            ModRM::IndirectDisp32 { mode, disp32, .. } => {
694                Some(ModRM::IndirectDisp32 { size, mode, disp32 })
695            }
696            ModRM::Direct(_) => None,
697        }
698    }
699}
700
701#[derive(Clone, Debug, Hash, PartialEq, Eq)]
702pub enum X86Operand {
703    Register(X86Register),
704    ModRM(ModRM),
705    Immediate(u64),
706    RelAddr(Address),
707    AbsAddr(Address),
708    FarAddr { sreg: X86Register, addr: Address },
709    FarRelAddr { sreg: X86Register, addr: Address },
710    FarModRM { sreg: X86Register, modrm: ModRM },
711}
712
713#[derive(Clone, Debug)]
714pub struct X86Instruction {
715    opc: X86Opcode,
716    operands: Vec<X86Operand>,
717    mode_override: Option<X86Mode>,
718}
719
720impl X86Instruction {
721    pub const fn new(opc: X86Opcode, operands: Vec<X86Operand>) -> Self {
722        Self {
723            opc,
724            operands,
725            mode_override: None,
726        }
727    }
728
729    pub const fn new_in_mode(opc: X86Opcode, operands: Vec<X86Operand>, mode: X86Mode) -> Self {
730        Self {
731            opc,
732            operands,
733            mode_override: Some(mode),
734        }
735    }
736
737    pub const fn opcode(&self) -> X86Opcode {
738        self.opc
739    }
740
741    pub fn operands(&self) -> &[X86Operand] {
742        &self.operands
743    }
744
745    pub fn mode_override(&self) -> Option<X86Mode> {
746        self.mode_override
747    }
748}
749
750macro_rules! zop_insns{
751    [$($name:ident),* $(,)?] => {
752        #[allow(non_upper_case_globals)]
753        impl X86Instruction{
754            $(pub const $name: X86Instruction = X86Instruction::new(X86Opcode:: $name, Vec::new());)*
755        }
756    }
757}
758
759zop_insns! {
760    Nop90,
761    Retn,
762    Leave,
763    Retf,
764    IRet,
765    Fneni,
766    Fndisi,
767    Hlt,
768    Cmc,
769    Clc,
770    Stc,
771    Cli,
772    Sti,
773    Cld,
774    Std,
775    Ud2,
776    Int3,
777    MFence
778}
779
780#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
781pub struct X86Decoder<R> {
782    reader: R,
783    mode: X86Mode,
784}
785
786impl<R> X86Decoder<R> {
787    pub const fn new(reader: R, defmode: X86Mode) -> Self {
788        Self {
789            reader,
790            mode: defmode,
791        }
792    }
793
794    pub fn into_inner(self) -> R {
795        self.reader
796    }
797
798    pub fn reader_mut(&mut self) -> &mut R {
799        &mut self.reader
800    }
801
802    pub fn mode(&self) -> X86Mode {
803        self.mode
804    }
805
806    pub fn set_mode(&mut self, mode: X86Mode) {
807        self.mode = mode;
808    }
809}
810
811impl<R: Read> Read for X86Decoder<R> {
812    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
813        self.reader.read(buf)
814    }
815}
816
817impl<R: InsnRead> InsnRead for X86Decoder<R> {
818    fn read_addr(&mut self, size: usize, rel: bool) -> std::io::Result<Address> {
819        self.reader.read_addr(size, rel)
820    }
821
822    fn read_reloc(
823        &mut self,
824        size: usize,
825        rel: bool,
826        offset: Option<isize>,
827    ) -> std::io::Result<Option<Address>> {
828        self.reader.read_reloc(size, rel, offset)
829    }
830}
831
832impl<R: InsnRead> X86Decoder<R> {
833    pub fn read_insn(&mut self) -> std::io::Result<X86Instruction> {
834        todo!()
835    }
836}
837
838#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
839pub struct X86Encoder<W> {
840    writer: W,
841    mode: X86Mode,
842}
843
844impl<W> X86Encoder<W> {
845    pub const fn new(writer: W, defmode: X86Mode) -> Self {
846        Self {
847            writer,
848            mode: defmode,
849        }
850    }
851
852    pub fn into_inner(self) -> W {
853        self.writer
854    }
855
856    pub fn writer_mut(&mut self) -> &mut W {
857        &mut self.writer
858    }
859
860    pub fn mode(&self) -> X86Mode {
861        self.mode
862    }
863
864    pub fn set_mode(&mut self, mode: X86Mode) {
865        self.mode = mode;
866    }
867}
868
869impl<W: Write> Write for X86Encoder<W> {
870    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
871        self.writer.write(buf)
872    }
873
874    fn flush(&mut self) -> std::io::Result<()> {
875        self.writer.flush()
876    }
877}
878
879impl<W: InsnWrite> InsnWrite for X86Encoder<W> {
880    fn write_addr(&mut self, size: usize, addr: Address, rel: bool) -> std::io::Result<()> {
881        self.writer.write_addr(size, addr, rel)
882    }
883
884    fn offset(&self) -> usize {
885        self.writer.offset()
886    }
887
888    fn write_reloc(&mut self, reloc: Reloc) -> std::io::Result<()> {
889        self.writer.write_reloc(reloc)
890    }
891}
892
893pub struct ModRMAndPrefixes {
894    pub rex: Option<u8>,
895    pub size_override: Option<u8>,
896    pub addr_override: Option<u8>,
897    pub modrm: u8,
898    pub sib: Option<u8>,
899    pub disp: Option<(usize, i64)>,
900    pub addr: Option<(usize, Address, bool)>,
901}
902
903pub fn encode_modrm(modrm: ModRM, r: u8, mode: X86Mode) -> ModRMAndPrefixes {
904    let mut output = ModRMAndPrefixes {
905        rex: None,
906        size_override: None,
907        addr_override: None,
908        modrm: 0,
909        sib: None,
910        disp: None,
911        addr: None,
912    };
913    if r > 8 {
914        *output.rex.get_or_insert(0x40) |= 0x04;
915    }
916
917    // Compute Size
918    // Gets REX.W and 66h prefix
919    let size = match modrm {
920        ModRM::Indirect { size, .. }
921        | ModRM::IndirectDisp8 { size, .. }
922        | ModRM::IndirectDisp32 { size, .. } => size,
923        ModRM::Direct(r) => r.class(),
924    };
925
926    // Compute REX.XB and Addr size
927    let addr_size = match modrm {
928        ModRM::Direct(_) => {
929            mode.largest_gpr() // doesn't matter, don't insert anything extra
930        }
931        ModRM::Indirect {
932            mode: ModRMRegOrSib::Reg(r),
933            ..
934        }
935        | ModRM::IndirectDisp8 {
936            mode: ModRMRegOrSib::Reg(r),
937            ..
938        }
939        | ModRM::IndirectDisp32 {
940            mode: ModRMRegOrSib::Reg(r),
941            ..
942        } => {
943            if r.regnum() >= 8 {
944                *output.rex.get_or_insert(0x40) |= 0x0;
945            }
946            r.class()
947        }
948        ModRM::Indirect {
949            mode: ModRMRegOrSib::Sib { index, base, .. },
950            ..
951        }
952        | ModRM::IndirectDisp8 {
953            mode: ModRMRegOrSib::Sib { index, base, .. },
954            ..
955        }
956        | ModRM::IndirectDisp32 {
957            mode: ModRMRegOrSib::Sib { index, base, .. },
958            ..
959        } => {
960            if base.regnum() >= 8 {
961                *output.rex.get_or_insert(0x40) |= 0x01;
962            }
963            if index.regnum() >= 8 {
964                *output.rex.get_or_insert(0x40) |= 0x02;
965            }
966            assert!(base.class() == index.class());
967            base.class()
968        }
969        ModRM::Indirect {
970            mode: ModRMRegOrSib::Index16 { .. },
971            ..
972        }
973        | ModRM::IndirectDisp8 {
974            mode: ModRMRegOrSib::Index16 { .. },
975            ..
976        }
977        | ModRM::IndirectDisp32 {
978            mode: ModRMRegOrSib::Index16 { .. },
979            ..
980        } => X86RegisterClass::Word,
981        ModRM::Indirect {
982            mode: ModRMRegOrSib::Abs(_),
983            ..
984        }
985        | ModRM::Indirect {
986            mode: ModRMRegOrSib::RipRel(_),
987            ..
988        } => mode.largest_gpr(),
989        mode => panic!("Invalid ModRM byte {:?}", mode),
990    };
991
992    // Compute 66h REX.W
993    match (size, mode) {
994        (X86RegisterClass::Byte, _) => {}
995        (X86RegisterClass::ByteRex, X86Mode::Long) => {}
996        (X86RegisterClass::Word, X86Mode::Real | X86Mode::Virtual8086) => {}
997        (X86RegisterClass::Double, X86Mode::Real | X86Mode::Virtual8086)
998        | (X86RegisterClass::Word, _) => {
999            output.size_override = Some(0x66);
1000        }
1001        (X86RegisterClass::Double, _) => {}
1002        (X86RegisterClass::Quad, X86Mode::Long) => {
1003            *output.rex.get_or_insert(0x40) |= 0x08;
1004        }
1005        (
1006            X86RegisterClass::Xmm
1007            | X86RegisterClass::Ymm
1008            | X86RegisterClass::Zmm
1009            | X86RegisterClass::St
1010            | X86RegisterClass::Mmx,
1011            _,
1012        )
1013        | (X86RegisterClass::Tmm, X86Mode::Long) => {}
1014        (size, mode) => panic!("Operand size {:?} not supported in mode {:?}", size, mode),
1015    };
1016
1017    match (addr_size, mode) {
1018        (X86RegisterClass::Word, X86Mode::Real | X86Mode::Virtual8086)
1019        | (X86RegisterClass::Double, X86Mode::Protected | X86Mode::Compatibility)
1020        | (X86RegisterClass::Quad, X86Mode::Long) => {}
1021        (X86RegisterClass::Double, X86Mode::Real | X86Mode::Virtual8086 | X86Mode::Long)
1022        | (X86RegisterClass::Word, X86Mode::Protected | X86Mode::Compatibility) => {
1023            output.addr_override = Some(0x67)
1024        }
1025        (size, mode) => panic!("Operand size {:?} not supported in mode {:?}", size, mode),
1026    }
1027
1028    // Finally, construct the ModRM (and possibly SIB) byte(s) + displacement
1029    match modrm {
1030        ModRM::Direct(reg) => {
1031            if reg.class() == X86RegisterClass::Byte && reg.regnum() > 3 && output.rex.is_some() {
1032                panic!("Cannot encode register {:?} with a REX prefix", reg);
1033            } else if reg.class() == X86RegisterClass::ByteRex {
1034                output.rex.get_or_insert(0x40);
1035            }
1036            output.modrm = 0xC0 | ((r & 0x7) << 3) | (reg.regnum() & 0x7);
1037        }
1038        ModRM::Indirect {
1039            mode: ModRMRegOrSib::Index16 { base, index },
1040            ..
1041        } => {
1042            output.modrm = match (base, index) {
1043                (X86Register::Bx, X86Register::Si) => (r & 0x7) << 3,
1044                (X86Register::Bx, X86Register::Di) => 0x01 | ((r & 0x7) << 3),
1045                (X86Register::Bp, X86Register::Si) => 0x02 | ((r & 0x7) << 3),
1046                (X86Register::Bp, X86Register::Di) => 0x03 | ((r & 0x7) << 3),
1047                (base, index) => panic!("16-bit addresses cannot encode [{}+{}]", base, index),
1048            };
1049        }
1050        ModRM::IndirectDisp8 {
1051            mode: ModRMRegOrSib::Index16 { base, index },
1052            disp8,
1053            ..
1054        } => {
1055            output.disp = Some((1, disp8.into()));
1056            output.modrm = match (base, index) {
1057                (X86Register::Bx, X86Register::Si) => 0x40 | ((r & 0x7) << 3),
1058                (X86Register::Bx, X86Register::Di) => 0x41 | ((r & 0x7) << 3),
1059                (X86Register::Bp, X86Register::Si) => 0x42 | ((r & 0x7) << 3),
1060                (X86Register::Bp, X86Register::Di) => 0x43 | ((r & 0x7) << 3),
1061                (base, index) => panic!("16-bit addresses cannot encode [{}+{}]", base, index),
1062            };
1063        }
1064        ModRM::IndirectDisp32 {
1065            mode: ModRMRegOrSib::Index16 { base, index },
1066            disp32,
1067            ..
1068        } => {
1069            output.disp = Some((2, disp32.into()));
1070            output.modrm = match (base, index) {
1071                (X86Register::Bx, X86Register::Si) => 0x80 | ((r & 0x7) << 3),
1072                (X86Register::Bx, X86Register::Di) => 0x81 | ((r & 0x7) << 3),
1073                (X86Register::Bp, X86Register::Si) => 0x82 | ((r & 0x7) << 3),
1074                (X86Register::Bp, X86Register::Di) => 0x83 | ((r & 0x7) << 3),
1075                (base, index) => panic!("16-bit addresses cannot encode [{}+{}]", base, index),
1076            };
1077        }
1078        ModRM::Indirect {
1079            mode: ModRMRegOrSib::Reg(reg),
1080            ..
1081        } if addr_size == X86RegisterClass::Word => {
1082            output.modrm = match reg {
1083                X86Register::Si => 0x04 | ((r & 0x7) << 3),
1084                X86Register::Di => 0x05 | ((r & 0x7) << 3),
1085                X86Register::Bx => 0x07 | ((r & 0x7) << 3),
1086                reg => panic!("16-bit addresses cannot encode [{}]", reg),
1087            }
1088        }
1089        ModRM::IndirectDisp8 {
1090            mode: ModRMRegOrSib::Reg(reg),
1091            disp8,
1092            ..
1093        } if addr_size == X86RegisterClass::Word => {
1094            output.disp = Some((1, disp8.into()));
1095            output.modrm = match reg {
1096                X86Register::Si => 0x44 | ((r & 0x7) << 3),
1097                X86Register::Di => 0x45 | ((r & 0x7) << 3),
1098                X86Register::Bp => 0x46 | ((r & 0x7) << 3),
1099                X86Register::Bx => 0x47 | ((r & 0x7) << 3),
1100                reg => panic!("16-bit addresses cannot encode [{}]", reg),
1101            }
1102        }
1103        ModRM::IndirectDisp32 {
1104            mode: ModRMRegOrSib::Reg(reg),
1105            disp32,
1106            ..
1107        } if addr_size == X86RegisterClass::Word => {
1108            output.disp = Some((2, disp32.into()));
1109            output.modrm = match reg {
1110                X86Register::Si => 0x84 | ((r & 0x7) << 3),
1111                X86Register::Di => 0x85 | ((r & 0x7) << 3),
1112                X86Register::Bp => 0x86 | ((r & 0x7) << 3),
1113                X86Register::Bx => 0x87 | ((r & 0x7) << 3),
1114                reg => panic!("16-bit addresses cannot encode [{}]", reg),
1115            }
1116        }
1117        ModRM::Indirect {
1118            mode: ModRMRegOrSib::Reg(reg),
1119            ..
1120        } => {
1121            match reg.regnum() & 0x7 {
1122                4 => {
1123                    // r/m encoding 0x04 is always an SIB byte
1124                    output.modrm = 0x04 | ((r & 0x7) << 3);
1125                    output.sib = Some(0x24)
1126                }
1127                5 => {
1128                    // r/m encoding 0x05 in mod 00
1129                    output.modrm = 0x45 | ((r & 0x7) << 3);
1130                    output.disp = Some((1, 0));
1131                }
1132                n => output.modrm = ((r & 0x7) << 3) | n,
1133            }
1134        }
1135        ModRM::Indirect {
1136            mode: ModRMRegOrSib::RipRel(addr),
1137            ..
1138        } => {
1139            if mode == X86Mode::Long {
1140                output.modrm = 0x05 | ((r & 0x7) << 3);
1141                output.addr = Some((4, addr, true));
1142            } else {
1143                panic!("[rip+{:?}] is not supported in this mode", addr)
1144            }
1145        }
1146        ModRM::Indirect {
1147            mode: ModRMRegOrSib::Abs(addr),
1148            ..
1149        } => {
1150            if mode == X86Mode::Long {
1151                // ModR/M can only encode [rip+disp32] in 64-bit mode
1152                // Use an SIB byte instead
1153                output.modrm = 0x04 | ((r & 0x7) << 3);
1154                output.sib = Some(0x25);
1155                output.addr = Some((4, addr, false));
1156            } else if addr_size == X86RegisterClass::Word {
1157                output.modrm = 0x06 | ((r & 0x7) << 3);
1158                output.addr = Some((2, addr, false));
1159            } else {
1160                output.modrm = 0x05 | ((r & 0x7) << 3);
1161                output.addr = Some((4, addr, false))
1162            }
1163        }
1164        ModRM::Indirect {
1165            mode: ModRMRegOrSib::Sib { scale, index, base },
1166            ..
1167        } => {
1168            output.modrm = 0x04 | ((r & 0x7) << 3);
1169            if index.regnum() == 4 {
1170                panic!("Cannot encode SIB byte with {:?} as index", index);
1171            }
1172            if base.regnum() & 0x7 == 5 {
1173                output.modrm |= 0x40;
1174                output.sib = Some(
1175                    ((scale.trailing_zeros() as u8 + 1) << 6)
1176                        | ((index.regnum() & 0x7) << 3)
1177                        | (0x05),
1178                );
1179                output.disp = Some((1, 0));
1180            } else {
1181                output.sib = Some(
1182                    ((scale.trailing_zeros() as u8 + 1) << 6)
1183                        | ((index.regnum() & 0x7) << 3)
1184                        | (base.regnum()),
1185                )
1186            }
1187        }
1188        ModRM::IndirectDisp8 {
1189            mode: ModRMRegOrSib::Sib { scale, index, base },
1190            disp8,
1191            ..
1192        } => {
1193            output.modrm = 0x44 | ((r & 0x7) << 3);
1194            output.disp = Some((1, disp8.into()));
1195            if index.regnum() == 4 {
1196                panic!("Cannot encode SIB byte with {:?} as index", index);
1197            }
1198            output.sib = Some(
1199                ((scale.trailing_zeros() as u8 + 1) << 6)
1200                    | ((index.regnum() & 0x7) << 3)
1201                    | (base.regnum()),
1202            )
1203        }
1204        ModRM::IndirectDisp32 {
1205            mode: ModRMRegOrSib::Sib { scale, index, base },
1206            disp32,
1207            ..
1208        } => {
1209            output.modrm = 0x84 | ((r & 0x7) << 3);
1210            output.disp = Some((4, disp32.into()));
1211            if index.regnum() == 4 {
1212                panic!("Cannot encode SIB byte with {:?} as index", index);
1213            }
1214            output.sib = Some(
1215                ((scale.trailing_zeros() as u8 + 1) << 6)
1216                    | ((index.regnum() & 0x7) << 3)
1217                    | (base.regnum()),
1218            )
1219        }
1220        ModRM::IndirectDisp8 {
1221            mode: ModRMRegOrSib::Reg(reg),
1222            disp8,
1223            ..
1224        } => {
1225            if reg.regnum() & 0x7 == 4 {
1226                // r/m encoding 0x04 is always an SIB byte
1227                output.modrm = 0x44 | ((r & 0x7) << 3);
1228                output.sib = Some(0x24)
1229            } else {
1230                output.modrm = 0x40 | (reg.regnum() & 0x7) | ((r & 0x7) << 3)
1231            }
1232            output.disp = Some((1, disp8.into()))
1233        }
1234        ModRM::IndirectDisp32 {
1235            mode: ModRMRegOrSib::Reg(reg),
1236            disp32,
1237            ..
1238        } => {
1239            if reg.regnum() & 0x7 == 4 {
1240                // r/m encoding 0x04 is always an SIB byte
1241                output.modrm = 0x84 | ((r & 0x7) << 3);
1242                output.sib = Some(0x24)
1243            } else {
1244                output.modrm = 0x80 | (reg.regnum() & 0x7) | ((r & 0x7) << 3)
1245            }
1246            output.disp = Some((4, disp32.into()))
1247        }
1248        modrm => todo!("{:?}", modrm),
1249    }
1250
1251    output
1252}
1253
1254impl<W: InsnWrite> X86Encoder<W> {
1255    pub fn write_insn(&mut self, insn: X86Instruction) -> std::io::Result<()> {
1256        let mode = insn.mode_override().unwrap_or(self.mode);
1257        let opcode_long = insn.opcode().opcode();
1258        let mut opcode = if opcode_long < 0x100 {
1259            vec![opcode_long as u8]
1260        } else if opcode_long < 0x10000 {
1261            vec![(opcode_long >> 8) as u8, opcode_long as u8]
1262        } else if opcode_long < 0x1000000 {
1263            vec![
1264                (opcode_long >> 16) as u8,
1265                (opcode_long >> 8) as u8,
1266                opcode_long as u8,
1267            ]
1268        } else {
1269            vec![
1270                (opcode_long >> 24) as u8,
1271                (opcode_long >> 16) as u8,
1272                (opcode_long >> 8) as u8,
1273                opcode_long as u8,
1274            ]
1275        };
1276        match insn.opcode().operands() {
1277            [] => {
1278                assert!(insn.operands.is_empty());
1279                self.writer.write_all(&opcode)
1280            }
1281            [Imm(n)] => {
1282                assert_eq!(insn.operands.len(), 1);
1283
1284                self.writer.write_all(&opcode)?;
1285
1286                match &insn.operands[0] {
1287                    X86Operand::Immediate(imm) => self.writer.write_all(&imm.to_ne_bytes()[..*n]),
1288                    X86Operand::AbsAddr(addr) => {
1289                        self.writer.write_addr(*n / 8, addr.clone(), false)
1290                    }
1291                    op => panic!("Invalid operand {:?} for Immediate", op),
1292                }
1293            }
1294            [Rel(n)] => {
1295                let n = *n;
1296                assert_eq!(insn.operands.len(), 1);
1297
1298                self.writer.write_all(&opcode)?;
1299
1300                match &insn.operands[0] {
1301                    X86Operand::Immediate(imm) => self.writer.write_all(&imm.to_ne_bytes()[..n]),
1302                    X86Operand::AbsAddr(addr) => self.writer.write_addr(n, addr.clone(), true),
1303                    op => panic!("Invalid operand {:?} for Immediate", op),
1304                }
1305            }
1306            [Insn] => todo!(),
1307            [OpRegMode] => {
1308                let reg = match &insn.operands[0] {
1309                    X86Operand::Register(r) => r,
1310                    op => panic!("Invalid operand {:?} for OpRegMode", op),
1311                };
1312
1313                match (reg.class(), mode) {
1314                    (X86RegisterClass::Word, X86Mode::Real | X86Mode::Virtual8086)
1315                    | (X86RegisterClass::Double, X86Mode::Protected | X86Mode::Compatibility)
1316                    | (X86RegisterClass::Quad, X86Mode::Long) => {}
1317                    (X86RegisterClass::Word, _)
1318                    | (X86RegisterClass::Double, X86Mode::Real | X86Mode::Virtual8086) => {
1319                        self.writer.write_all(&[0x66])?;
1320                    }
1321                    (_, mode) => panic!("Register {} is not valid in mode {:?}", reg, mode),
1322                }
1323
1324                *opcode.last_mut().unwrap() += reg.regnum() & 0x7;
1325                let mut opcode = &opcode[..];
1326                let sse_prefix = opcode[0];
1327
1328                match sse_prefix {
1329                    0x66 | 0xF2 | 0xF3 => {
1330                        self.writer.write_all(core::slice::from_ref(&sse_prefix))?;
1331                        opcode = &opcode[1..]
1332                    }
1333                    _ => {}
1334                }
1335
1336                if reg.regnum() > 8 {
1337                    self.writer.write_all(&[0x41])?;
1338                }
1339
1340                self.writer.write_all(opcode)
1341            }
1342            [ModRM(cl1), Reg(cl2)] if cl1 == cl2 => {
1343                let reg = match &insn.operands[1] {
1344                    X86Operand::Register(r) => *r,
1345                    op => panic!("Invalid operand {:?} for Reg({:?})", op, cl2),
1346                };
1347
1348                let modrm = match &insn.operands[0] {
1349                    X86Operand::Register(r) => ModRM::Direct(*r),
1350                    X86Operand::ModRM(modrm) => modrm.clone(),
1351                    X86Operand::RelAddr(addr) => ModRM::Indirect {
1352                        size: *cl1,
1353                        mode: ModRMRegOrSib::RipRel(addr.clone()),
1354                    },
1355                    X86Operand::AbsAddr(addr) => ModRM::Indirect {
1356                        size: *cl1,
1357                        mode: ModRMRegOrSib::Abs(addr.clone()),
1358                    },
1359                    op => panic!("Invalid operand {:?} for ModRM({:?})", op, cl1),
1360                };
1361
1362                let mut encoding = encode_modrm(modrm, reg.regnum(), mode);
1363
1364                if reg.class() == X86RegisterClass::Byte
1365                    && encoding.rex.is_some()
1366                    && reg.regnum() > 3
1367                {
1368                    panic!("Cannot encode {} with a rex prefix", reg);
1369                } else if reg.class() == X86RegisterClass::ByteRex {
1370                    encoding.rex.get_or_insert(0x40); // Put in a null REX prefix if we have spl/bpl/sil/dil
1371                }
1372                let mut opcode = &opcode[..];
1373                let sse_prefix = opcode[0];
1374
1375                self.writer.write_all(
1376                    encoding
1377                        .size_override
1378                        .as_ref()
1379                        .map(core::slice::from_ref)
1380                        .unwrap_or(&[]),
1381                )?;
1382                self.writer.write_all(
1383                    encoding
1384                        .addr_override
1385                        .as_ref()
1386                        .map(core::slice::from_ref)
1387                        .unwrap_or(&[]),
1388                )?;
1389
1390                match sse_prefix {
1391                    0x66 | 0xF2 | 0xF3 => {
1392                        self.writer.write_all(core::slice::from_ref(&sse_prefix))?;
1393                        opcode = &opcode[1..]
1394                    }
1395                    _ => {}
1396                }
1397
1398                self.writer.write_all(
1399                    encoding
1400                        .rex
1401                        .as_ref()
1402                        .map(core::slice::from_ref)
1403                        .unwrap_or(&[]),
1404                )?;
1405
1406                self.writer.write_all(opcode)?;
1407                self.writer
1408                    .write_all(core::slice::from_ref(&encoding.modrm))?;
1409                self.writer.write_all(
1410                    encoding
1411                        .sib
1412                        .as_ref()
1413                        .map(core::slice::from_ref)
1414                        .unwrap_or(&[]),
1415                )?;
1416                match (encoding.disp, encoding.addr) {
1417                    (Some((size, disp)), None) => {
1418                        self.writer.write_all(&disp.to_ne_bytes()[..size])?
1419                    }
1420                    (None, Some((size, addr, pcrel))) => {
1421                        self.writer.write_addr(size * 8, addr, pcrel)?
1422                    }
1423                    (None, None) => {}
1424                    (Some(_), Some(_)) => {
1425                        panic!("Cannot encode both an address and a displacement")
1426                    }
1427                }
1428                Ok(())
1429            }
1430            [Reg(cl2), ModRM(cl1)] if cl1 == cl2 => {
1431                let reg = match &insn.operands[0] {
1432                    X86Operand::Register(r) => *r,
1433                    op => panic!("Invalid operand {:?} for Reg({:?})", op, cl2),
1434                };
1435
1436                let modrm = match &insn.operands[1] {
1437                    X86Operand::Register(r) => ModRM::Direct(*r),
1438                    X86Operand::ModRM(modrm) => modrm.clone(),
1439                    X86Operand::RelAddr(addr) => ModRM::Indirect {
1440                        size: *cl1,
1441                        mode: ModRMRegOrSib::RipRel(addr.clone()),
1442                    },
1443                    X86Operand::AbsAddr(addr) => ModRM::Indirect {
1444                        size: *cl1,
1445                        mode: ModRMRegOrSib::Abs(addr.clone()),
1446                    },
1447                    op => panic!("Invalid operand {:?} for ModRM({:?})", op, cl1),
1448                };
1449
1450                let mut encoding = encode_modrm(modrm, reg.regnum(), mode);
1451
1452                if reg.class() == X86RegisterClass::Byte
1453                    && encoding.rex.is_some()
1454                    && reg.regnum() > 3
1455                {
1456                    panic!("Cannot encode {} with a rex prefix", reg);
1457                } else if reg.class() == X86RegisterClass::ByteRex {
1458                    encoding.rex.get_or_insert(0x40); // Put in a null REX prefix if we have spl/bpl/sil/dil
1459                }
1460                let mut opcode = &opcode[..];
1461                let sse_prefix = opcode[0];
1462
1463                self.writer.write_all(
1464                    encoding
1465                        .size_override
1466                        .as_ref()
1467                        .map(core::slice::from_ref)
1468                        .unwrap_or(&[]),
1469                )?;
1470                self.writer.write_all(
1471                    encoding
1472                        .addr_override
1473                        .as_ref()
1474                        .map(core::slice::from_ref)
1475                        .unwrap_or(&[]),
1476                )?;
1477
1478                match sse_prefix {
1479                    0x66 | 0xF2 | 0xF3 => {
1480                        self.writer.write_all(core::slice::from_ref(&sse_prefix))?;
1481                        opcode = &opcode[1..]
1482                    }
1483                    _ => {}
1484                }
1485
1486                self.writer.write_all(
1487                    encoding
1488                        .rex
1489                        .as_ref()
1490                        .map(core::slice::from_ref)
1491                        .unwrap_or(&[]),
1492                )?;
1493
1494                self.writer.write_all(opcode)?;
1495                self.writer
1496                    .write_all(core::slice::from_ref(&encoding.modrm))?;
1497                self.writer.write_all(
1498                    encoding
1499                        .sib
1500                        .as_ref()
1501                        .map(core::slice::from_ref)
1502                        .unwrap_or(&[]),
1503                )?;
1504                match (encoding.disp, encoding.addr) {
1505                    (Some((size, disp)), None) => {
1506                        self.writer.write_all(&disp.to_ne_bytes()[..size])?
1507                    }
1508                    (None, Some((size, addr, pcrel))) => {
1509                        self.writer.write_addr(size, addr, pcrel)?
1510                    }
1511                    (None, None) => {}
1512                    (Some(_), Some(_)) => {
1513                        panic!("Cannot encode both an address and a displacement")
1514                    }
1515                }
1516                Ok(())
1517            }
1518            [ModRMGeneral, RegGeneral] => {
1519                let reg = match &insn.operands[1] {
1520                    X86Operand::Register(r) => *r,
1521                    op => panic!("Invalid operand {:?} for RegGeneral", op),
1522                };
1523
1524                let modrm = match &insn.operands[0] {
1525                    X86Operand::Register(r) => ModRM::Direct(*r),
1526                    X86Operand::ModRM(modrm) => modrm.clone(),
1527                    X86Operand::RelAddr(addr) => ModRM::Indirect {
1528                        size: reg.class(),
1529                        mode: ModRMRegOrSib::RipRel(addr.clone()),
1530                    },
1531                    X86Operand::AbsAddr(addr) => ModRM::Indirect {
1532                        size: reg.class(),
1533                        mode: ModRMRegOrSib::Abs(addr.clone()),
1534                    },
1535                    op => panic!("Invalid operand {:?} for ModRMGeneral", op),
1536                };
1537
1538                let encoding = encode_modrm(modrm, reg.regnum(), mode);
1539
1540                let mut opcode = &opcode[..];
1541                let sse_prefix = opcode[0];
1542
1543                self.writer.write_all(
1544                    encoding
1545                        .size_override
1546                        .as_ref()
1547                        .map(core::slice::from_ref)
1548                        .unwrap_or(&[]),
1549                )?;
1550                self.writer.write_all(
1551                    encoding
1552                        .addr_override
1553                        .as_ref()
1554                        .map(core::slice::from_ref)
1555                        .unwrap_or(&[]),
1556                )?;
1557
1558                match sse_prefix {
1559                    0x66 | 0xF2 | 0xF3 => {
1560                        self.writer.write_all(core::slice::from_ref(&sse_prefix))?;
1561                        opcode = &opcode[1..]
1562                    }
1563                    _ => {}
1564                }
1565
1566                self.writer.write_all(
1567                    encoding
1568                        .rex
1569                        .as_ref()
1570                        .map(core::slice::from_ref)
1571                        .unwrap_or(&[]),
1572                )?;
1573
1574                self.writer.write_all(opcode)?;
1575                self.writer
1576                    .write_all(core::slice::from_ref(&encoding.modrm))?;
1577                self.writer.write_all(
1578                    encoding
1579                        .sib
1580                        .as_ref()
1581                        .map(core::slice::from_ref)
1582                        .unwrap_or(&[]),
1583                )?;
1584                match (encoding.disp, encoding.addr) {
1585                    (Some((size, disp)), None) => {
1586                        self.writer.write_all(&disp.to_ne_bytes()[..size])?
1587                    }
1588                    (None, Some((size, addr, pcrel))) => {
1589                        self.writer.write_addr(size, addr, pcrel)?
1590                    }
1591                    (None, None) => {}
1592                    (Some(_), Some(_)) => {
1593                        panic!("Cannot encode both an address and a displacement")
1594                    }
1595                }
1596                Ok(())
1597            }
1598            [RegGeneral, ModRMGeneral] => {
1599                let reg = match &insn.operands[0] {
1600                    X86Operand::Register(r) => *r,
1601                    op => panic!("Invalid operand {:?} for RegGeneral", op),
1602                };
1603
1604                let modrm = match &insn.operands[1] {
1605                    X86Operand::Register(r) => ModRM::Direct(*r),
1606                    X86Operand::ModRM(modrm) => modrm.clone(),
1607                    X86Operand::RelAddr(addr) => ModRM::Indirect {
1608                        size: reg.class(),
1609                        mode: ModRMRegOrSib::RipRel(addr.clone()),
1610                    },
1611                    X86Operand::AbsAddr(addr) => ModRM::Indirect {
1612                        size: reg.class(),
1613                        mode: ModRMRegOrSib::Abs(addr.clone()),
1614                    },
1615                    op => panic!("Invalid operand {:?} for ModRMGeneral", op),
1616                };
1617
1618                let encoding = encode_modrm(modrm, reg.regnum(), mode);
1619
1620                let mut opcode = &opcode[..];
1621                let sse_prefix = opcode[0];
1622
1623                self.writer.write_all(
1624                    encoding
1625                        .size_override
1626                        .as_ref()
1627                        .map(core::slice::from_ref)
1628                        .unwrap_or(&[]),
1629                )?;
1630                self.writer.write_all(
1631                    encoding
1632                        .addr_override
1633                        .as_ref()
1634                        .map(core::slice::from_ref)
1635                        .unwrap_or(&[]),
1636                )?;
1637
1638                match sse_prefix {
1639                    0x66 | 0xF2 | 0xF3 => {
1640                        self.writer.write_all(core::slice::from_ref(&sse_prefix))?;
1641                        opcode = &opcode[1..]
1642                    }
1643                    _ => {}
1644                }
1645
1646                self.writer.write_all(
1647                    encoding
1648                        .rex
1649                        .as_ref()
1650                        .map(core::slice::from_ref)
1651                        .unwrap_or(&[]),
1652                )?;
1653
1654                self.writer.write_all(opcode)?;
1655                self.writer
1656                    .write_all(core::slice::from_ref(&encoding.modrm))?;
1657                self.writer.write_all(
1658                    encoding
1659                        .sib
1660                        .as_ref()
1661                        .map(core::slice::from_ref)
1662                        .unwrap_or(&[]),
1663                )?;
1664                match (encoding.disp, encoding.addr) {
1665                    (Some((size, disp)), None) => {
1666                        self.writer.write_all(&disp.to_ne_bytes()[..size])?
1667                    }
1668                    (None, Some((size, addr, pcrel))) => {
1669                        self.writer.write_addr(size * 8, addr, pcrel)?
1670                    }
1671                    (None, None) => {}
1672                    (Some(_), Some(_)) => {
1673                        panic!("Cannot encode both an address and a displacement")
1674                    }
1675                }
1676                Ok(())
1677            }
1678            [RControlBits(b), ModRMGeneral, ImmGeneral] => {
1679                let modrm = match &insn.operands[0] {
1680                    X86Operand::Register(r) => ModRM::Direct(*r),
1681                    X86Operand::ModRM(modrm) => modrm.clone(),
1682                    X86Operand::RelAddr(addr) => ModRM::Indirect {
1683                        size: mode.largest_gpr(),
1684                        mode: ModRMRegOrSib::RipRel(addr.clone()),
1685                    },
1686                    X86Operand::AbsAddr(addr) => ModRM::Indirect {
1687                        size: mode.largest_gpr(),
1688                        mode: ModRMRegOrSib::Abs(addr.clone()),
1689                    },
1690                    op => panic!("Invalid operand {:?} for ModRMGeneral", op),
1691                };
1692
1693                let size = match modrm {
1694                    ModRM::Indirect { size, .. } => size,
1695                    ModRM::IndirectDisp8 { size, .. } => size,
1696                    ModRM::IndirectDisp32 { size, .. } => size,
1697                    ModRM::Direct(r) => r.class(),
1698                };
1699
1700                let encoding = encode_modrm(modrm, *b, mode);
1701
1702                let mut opcode = &opcode[..];
1703                let sse_prefix = opcode[0];
1704
1705                self.writer.write_all(
1706                    encoding
1707                        .size_override
1708                        .as_ref()
1709                        .map(core::slice::from_ref)
1710                        .unwrap_or(&[]),
1711                )?;
1712                self.writer.write_all(
1713                    encoding
1714                        .addr_override
1715                        .as_ref()
1716                        .map(core::slice::from_ref)
1717                        .unwrap_or(&[]),
1718                )?;
1719
1720                match sse_prefix {
1721                    0x66 | 0xF2 | 0xF3 => {
1722                        self.writer.write_all(core::slice::from_ref(&sse_prefix))?;
1723                        opcode = &opcode[1..]
1724                    }
1725                    _ => {}
1726                }
1727
1728                self.writer.write_all(
1729                    encoding
1730                        .rex
1731                        .as_ref()
1732                        .map(core::slice::from_ref)
1733                        .unwrap_or(&[]),
1734                )?;
1735
1736                self.writer.write_all(opcode)?;
1737                self.writer
1738                    .write_all(core::slice::from_ref(&encoding.modrm))?;
1739                self.writer.write_all(
1740                    encoding
1741                        .sib
1742                        .as_ref()
1743                        .map(core::slice::from_ref)
1744                        .unwrap_or(&[]),
1745                )?;
1746
1747                match (encoding.disp, encoding.addr) {
1748                    (Some((size, disp)), None) => {
1749                        self.writer.write_all(&disp.to_ne_bytes()[..size])?;
1750                    }
1751                    (None, Some((size, addr, pcrel))) => {
1752                        self.writer.write_addr(size * 8, addr, pcrel)?;
1753                    }
1754                    (None, None) => {}
1755                    (Some(_), Some(_)) => {
1756                        panic!("Cannot encode both an address and a displacement")
1757                    }
1758                }
1759
1760                let n = match size {
1761                    X86RegisterClass::Word => 2,
1762                    _ => 4,
1763                };
1764
1765                match &insn.operands[1] {
1766                    X86Operand::Immediate(imm) => self.writer.write_all(&imm.to_ne_bytes()[..n]),
1767                    X86Operand::AbsAddr(addr) => self.writer.write_addr(n * 8, addr.clone(), false),
1768                    op => panic!("Invalid operand {:?} for Immediate", op),
1769                }
1770            }
1771            [RControlBits(b), ModRM(Byte), Imm(8)] => {
1772                let modrm = match &insn.operands[0] {
1773                    X86Operand::Register(r) => ModRM::Direct(*r),
1774                    X86Operand::ModRM(modrm) => modrm.clone(),
1775                    X86Operand::RelAddr(addr) => ModRM::Indirect {
1776                        size: mode.largest_gpr(),
1777                        mode: ModRMRegOrSib::RipRel(addr.clone()),
1778                    },
1779                    X86Operand::AbsAddr(addr) => ModRM::Indirect {
1780                        size: mode.largest_gpr(),
1781                        mode: ModRMRegOrSib::Abs(addr.clone()),
1782                    },
1783                    op => panic!("Invalid operand {:?} for ModRMGeneral", op),
1784                };
1785
1786                let encoding = encode_modrm(modrm, *b, mode);
1787
1788                let mut opcode = &opcode[..];
1789                let sse_prefix = opcode[0];
1790
1791                self.writer.write_all(
1792                    encoding
1793                        .size_override
1794                        .as_ref()
1795                        .map(core::slice::from_ref)
1796                        .unwrap_or(&[]),
1797                )?;
1798                self.writer.write_all(
1799                    encoding
1800                        .addr_override
1801                        .as_ref()
1802                        .map(core::slice::from_ref)
1803                        .unwrap_or(&[]),
1804                )?;
1805
1806                match sse_prefix {
1807                    0x66 | 0xF2 | 0xF3 => {
1808                        self.writer.write_all(core::slice::from_ref(&sse_prefix))?;
1809                        opcode = &opcode[1..]
1810                    }
1811                    _ => {}
1812                }
1813
1814                self.writer.write_all(
1815                    encoding
1816                        .rex
1817                        .as_ref()
1818                        .map(core::slice::from_ref)
1819                        .unwrap_or(&[]),
1820                )?;
1821
1822                self.writer.write_all(opcode)?;
1823                self.writer
1824                    .write_all(core::slice::from_ref(&encoding.modrm))?;
1825                self.writer.write_all(
1826                    encoding
1827                        .sib
1828                        .as_ref()
1829                        .map(core::slice::from_ref)
1830                        .unwrap_or(&[]),
1831                )?;
1832
1833                match (encoding.disp, encoding.addr) {
1834                    (Some((size, disp)), None) => {
1835                        self.writer.write_all(&disp.to_ne_bytes()[..size])?;
1836                    }
1837                    (None, Some((size, addr, pcrel))) => {
1838                        self.writer.write_addr(size * 8, addr, pcrel)?;
1839                    }
1840                    (None, None) => {}
1841                    (Some(_), Some(_)) => {
1842                        panic!("Cannot encode both an address and a displacement")
1843                    }
1844                }
1845
1846                match &insn.operands[1] {
1847                    X86Operand::Immediate(imm) => self.writer.write_all(&imm.to_ne_bytes()[..1]),
1848                    X86Operand::AbsAddr(addr) => self.writer.write_addr(8, addr.clone(), false),
1849                    op => panic!("Invalid operand {:?} for Immediate", op),
1850                }
1851            }
1852            [RControlBits(b), ModRMGeneral, Imm(8)] => {
1853                let modrm = match &insn.operands[0] {
1854                    X86Operand::Register(r) => ModRM::Direct(*r),
1855                    X86Operand::ModRM(modrm) => modrm.clone(),
1856                    X86Operand::RelAddr(addr) => ModRM::Indirect {
1857                        size: mode.largest_gpr(),
1858                        mode: ModRMRegOrSib::RipRel(addr.clone()),
1859                    },
1860                    X86Operand::AbsAddr(addr) => ModRM::Indirect {
1861                        size: mode.largest_gpr(),
1862                        mode: ModRMRegOrSib::Abs(addr.clone()),
1863                    },
1864                    op => panic!("Invalid operand {:?} for ModRMGeneral", op),
1865                };
1866
1867                let encoding = encode_modrm(modrm, *b, mode);
1868
1869                let mut opcode = &opcode[..];
1870                let sse_prefix = opcode[0];
1871
1872                self.writer.write_all(
1873                    encoding
1874                        .size_override
1875                        .as_ref()
1876                        .map(core::slice::from_ref)
1877                        .unwrap_or(&[]),
1878                )?;
1879                self.writer.write_all(
1880                    encoding
1881                        .addr_override
1882                        .as_ref()
1883                        .map(core::slice::from_ref)
1884                        .unwrap_or(&[]),
1885                )?;
1886
1887                match sse_prefix {
1888                    0x66 | 0xF2 | 0xF3 => {
1889                        self.writer.write_all(core::slice::from_ref(&sse_prefix))?;
1890                        opcode = &opcode[1..]
1891                    }
1892                    _ => {}
1893                }
1894
1895                self.writer.write_all(
1896                    encoding
1897                        .rex
1898                        .as_ref()
1899                        .map(core::slice::from_ref)
1900                        .unwrap_or(&[]),
1901                )?;
1902
1903                self.writer.write_all(opcode)?;
1904                self.writer
1905                    .write_all(core::slice::from_ref(&encoding.modrm))?;
1906                self.writer.write_all(
1907                    encoding
1908                        .sib
1909                        .as_ref()
1910                        .map(core::slice::from_ref)
1911                        .unwrap_or(&[]),
1912                )?;
1913
1914                match (encoding.disp, encoding.addr) {
1915                    (Some((size, disp)), None) => {
1916                        self.writer.write_all(&disp.to_ne_bytes()[..size])?;
1917                    }
1918                    (None, Some((size, addr, pcrel))) => {
1919                        self.writer.write_addr(size * 8, addr, pcrel)?;
1920                    }
1921                    (None, None) => {}
1922                    (Some(_), Some(_)) => {
1923                        panic!("Cannot encode both an address and a displacement")
1924                    }
1925                }
1926
1927                match &insn.operands[1] {
1928                    X86Operand::Immediate(imm) => self.writer.write_all(&imm.to_ne_bytes()[..1]),
1929                    X86Operand::AbsAddr(addr) => self.writer.write_addr(8, addr.clone(), false),
1930                    op => panic!("Invalid operand {:?} for Immediate", op),
1931                }
1932            }
1933            [RelGeneral] => {
1934                let size = match mode {
1935                    X86Mode::Virtual8086 | X86Mode::Real => 2,
1936                    _ => 4,
1937                };
1938
1939                let mut opcode = &opcode[..];
1940                let sse_prefix = opcode[0];
1941
1942                match sse_prefix {
1943                    0x66 | 0xF2 | 0xF3 => {
1944                        self.writer.write_all(core::slice::from_ref(&sse_prefix))?;
1945                        opcode = &opcode[1..]
1946                    }
1947                    _ => {}
1948                }
1949
1950                self.writer.write_all(opcode)?;
1951
1952                match &insn.operands[0] {
1953                    X86Operand::RelAddr(addr) => {
1954                        self.writer.write_addr(size * 8, addr.clone(), true)
1955                    }
1956                    op => panic!("Invalid Operand for RelGeneral {:?}", op),
1957                }
1958            }
1959            [OpRegGeneral, ImmGeneralWide] => {
1960                let reg = match &insn.operands[0] {
1961                    X86Operand::Register(r) => r,
1962                    op => panic!("Invalid Operand for {:?}", op),
1963                };
1964
1965                let mut rex = None;
1966                if reg.regnum() > 7 {
1967                    *rex.get_or_insert(0x40) |= 0x1;
1968                }
1969
1970                let opsize = match (reg.class(), mode) {
1971                    (X86RegisterClass::Word, X86Mode::Real | X86Mode::Virtual8086)
1972                    | (
1973                        X86RegisterClass::Double,
1974                        X86Mode::Protected | X86Mode::Compatibility | X86Mode::Long,
1975                    ) => None,
1976                    (X86RegisterClass::Word, _)
1977                    | (X86RegisterClass::Double, X86Mode::Real | X86Mode::Virtual8086) => {
1978                        Some(0x66)
1979                    }
1980                    (X86RegisterClass::Quad, X86Mode::Long) => None,
1981                    (class, mode) => {
1982                        panic!("Unsupported register class {:?} in mode {:?}", class, mode)
1983                    }
1984                };
1985
1986                let immsize = reg.class().size(mode);
1987
1988                self.writer
1989                    .write_all(opsize.as_ref().map(core::slice::from_ref).unwrap_or(&[]))?;
1990
1991                *opcode.last_mut().unwrap() += reg.regnum() & 0x7;
1992                let mut opcode = &opcode[..];
1993                let sse_prefix = opcode[0];
1994
1995                match sse_prefix {
1996                    0x66 | 0xF2 | 0xF3 => {
1997                        self.writer.write_all(core::slice::from_ref(&sse_prefix))?;
1998                        opcode = &opcode[1..]
1999                    }
2000                    _ => {}
2001                }
2002
2003                self.writer
2004                    .write_all(rex.as_ref().map(core::slice::from_ref).unwrap_or(&[]))?;
2005
2006                self.writer.write_all(opcode)?;
2007                match &insn.operands[1] {
2008                    X86Operand::Immediate(i) => self.writer.write_all(&i.to_le_bytes()[0..immsize]),
2009                    X86Operand::AbsAddr(addr) => {
2010                        self.writer.write_addr(immsize * 8, addr.clone(), false)
2011                    }
2012                    op => panic!("Invalid operand {:?} for ImmGeneralWide", op),
2013                }
2014            }
2015            m => panic!("Unsupported Addressing Mode {:?}", m),
2016        }
2017    }
2018}
2019
2020#[cfg(test)]
2021mod test {
2022
2023    use crate::x86::X86Register;
2024
2025    use super::{ModRM, X86Encoder, X86Instruction, X86Mode, X86Opcode, X86Operand};
2026
2027    use crate::test::TestWriter;
2028
2029    #[test]
2030    fn test_encoder_simple() {
2031        let mut enc = X86Encoder::new(TestWriter { inner: Vec::new() }, X86Mode::Protected);
2032        enc.write_insn(X86Instruction::Retn).unwrap();
2033        assert_eq!(&*enc.writer_mut().inner, &[0xC3]);
2034    }
2035
2036    #[test]
2037    fn test_encoder_modrm_reg32() {
2038        let mut enc = X86Encoder::new(TestWriter { inner: Vec::new() }, X86Mode::Protected);
2039        enc.write_insn(X86Instruction::new(
2040            X86Opcode::XorMR,
2041            vec![
2042                X86Operand::ModRM(ModRM::Direct(X86Register::Eax)),
2043                X86Operand::Register(X86Register::Eax),
2044            ],
2045        ))
2046        .unwrap();
2047
2048        assert_eq!(&*enc.writer_mut().inner, &[0x31, 0xC0]);
2049    }
2050
2051    #[test]
2052    fn test_encoder_modrm_reg32_long() {
2053        let mut enc = X86Encoder::new(TestWriter { inner: Vec::new() }, X86Mode::Long);
2054        enc.write_insn(X86Instruction::new(
2055            X86Opcode::XorMR,
2056            vec![
2057                X86Operand::ModRM(ModRM::Direct(X86Register::Eax)),
2058                X86Operand::Register(X86Register::Eax),
2059            ],
2060        ))
2061        .unwrap();
2062
2063        assert_eq!(&*enc.writer_mut().inner, &[0x31, 0xC0]);
2064    }
2065
2066    #[test]
2067    fn test_encoder_modrm_reg32_real() {
2068        let mut enc = X86Encoder::new(TestWriter { inner: Vec::new() }, X86Mode::Real);
2069        enc.write_insn(X86Instruction::new(
2070            X86Opcode::XorMR,
2071            vec![
2072                X86Operand::ModRM(ModRM::Direct(X86Register::Eax)),
2073                X86Operand::Register(X86Register::Eax),
2074            ],
2075        ))
2076        .unwrap();
2077
2078        assert_eq!(&*enc.writer_mut().inner, &[0x66, 0x31, 0xC0]);
2079    }
2080
2081    #[test]
2082    fn test_encoder_modrm_reg16_real() {
2083        let mut enc = X86Encoder::new(TestWriter { inner: Vec::new() }, X86Mode::Real);
2084        enc.write_insn(X86Instruction::new(
2085            X86Opcode::XorMR,
2086            vec![
2087                X86Operand::ModRM(ModRM::Direct(X86Register::Ax)),
2088                X86Operand::Register(X86Register::Ax),
2089            ],
2090        ))
2091        .unwrap();
2092
2093        assert_eq!(&*enc.writer_mut().inner, &[0x31, 0xC0]);
2094    }
2095
2096    #[test]
2097    fn test_encoder_modrm_reg16_protected() {
2098        let mut enc = X86Encoder::new(TestWriter { inner: Vec::new() }, X86Mode::Protected);
2099        enc.write_insn(X86Instruction::new(
2100            X86Opcode::XorMR,
2101            vec![
2102                X86Operand::ModRM(ModRM::Direct(X86Register::Ax)),
2103                X86Operand::Register(X86Register::Ax),
2104            ],
2105        ))
2106        .unwrap();
2107
2108        assert_eq!(&*enc.writer_mut().inner, &[0x66, 0x31, 0xC0]);
2109    }
2110
2111    #[test]
2112    fn test_encoder_modrm_reg16_long() {
2113        let mut enc = X86Encoder::new(TestWriter { inner: Vec::new() }, X86Mode::Long);
2114        enc.write_insn(X86Instruction::new(
2115            X86Opcode::XorMR,
2116            vec![
2117                X86Operand::ModRM(ModRM::Direct(X86Register::Ax)),
2118                X86Operand::Register(X86Register::Ax),
2119            ],
2120        ))
2121        .unwrap();
2122
2123        assert_eq!(&*enc.writer_mut().inner, &[0x66, 0x31, 0xC0]);
2124    }
2125
2126    #[test]
2127    fn test_encoder_modrm_reg64_long() {
2128        let mut enc = X86Encoder::new(TestWriter { inner: Vec::new() }, X86Mode::Long);
2129        enc.write_insn(X86Instruction::new(
2130            X86Opcode::XorMR,
2131            vec![
2132                X86Operand::ModRM(ModRM::Direct(X86Register::Rax)),
2133                X86Operand::Register(X86Register::Rax),
2134            ],
2135        ))
2136        .unwrap();
2137
2138        assert_eq!(&*enc.writer_mut().inner, &[0x48, 0x31, 0xC0]);
2139    }
2140
2141    #[test]
2142    fn test_encoder_opreg_mode() {
2143        let mut enc = X86Encoder::new(TestWriter { inner: Vec::new() }, X86Mode::Protected);
2144        enc.write_insn(X86Instruction::new(
2145            X86Opcode::Push,
2146            vec![X86Operand::Register(X86Register::Eax)],
2147        ))
2148        .unwrap();
2149        assert_eq!(&*enc.writer_mut().inner, &[0x50]);
2150    }
2151
2152    #[test]
2153    fn test_encoder_opreg_mode_long() {
2154        let mut enc = X86Encoder::new(TestWriter { inner: Vec::new() }, X86Mode::Long);
2155        enc.write_insn(X86Instruction::new(
2156            X86Opcode::Push,
2157            vec![X86Operand::Register(X86Register::Rax)],
2158        ))
2159        .unwrap();
2160        assert_eq!(&*enc.writer_mut().inner, &[0x50]);
2161    }
2162
2163    #[test]
2164    fn test_encoder_opreg_mode_protected_r16() {
2165        let mut enc = X86Encoder::new(TestWriter { inner: Vec::new() }, X86Mode::Protected);
2166        enc.write_insn(X86Instruction::new(
2167            X86Opcode::Push,
2168            vec![X86Operand::Register(X86Register::Ax)],
2169        ))
2170        .unwrap();
2171        assert_eq!(&*enc.writer_mut().inner, &[0x66, 0x50]);
2172    }
2173
2174    #[test]
2175    fn test_encoder_opreg_mode_long_r16() {
2176        let mut enc = X86Encoder::new(TestWriter { inner: Vec::new() }, X86Mode::Long);
2177        enc.write_insn(X86Instruction::new(
2178            X86Opcode::Push,
2179            vec![X86Operand::Register(X86Register::Ax)],
2180        ))
2181        .unwrap();
2182        assert_eq!(&*enc.writer_mut().inner, &[0x66, 0x50]);
2183    }
2184
2185    #[test]
2186    fn test_encoder_opreg_mode_real_r32() {
2187        let mut enc = X86Encoder::new(TestWriter { inner: Vec::new() }, X86Mode::Real);
2188        enc.write_insn(X86Instruction::new(
2189            X86Opcode::Push,
2190            vec![X86Operand::Register(X86Register::Eax)],
2191        ))
2192        .unwrap();
2193        assert_eq!(&*enc.writer_mut().inner, &[0x66, 0x50]);
2194    }
2195
2196    #[test]
2197    #[should_panic]
2198    fn test_encoder_opreg_mode_long_r32() {
2199        let mut enc = X86Encoder::new(TestWriter { inner: Vec::new() }, X86Mode::Long);
2200        let _ = enc.write_insn(X86Instruction::new(
2201            X86Opcode::Push,
2202            vec![X86Operand::Register(X86Register::Eax)],
2203        ));
2204    }
2205}