Skip to main content

isa_lang/x86_64/
decode.rs

1//! The decoder: interprets form records to turn bytes back into an [`Inst`].
2//!
3//! Prefixes are read (`66`, then an optional REX), the opcode selects a
4//! bucket of candidate forms from the build-time index, and the first
5//! candidate whose prefixes, ModRM extension, register-or-memory constraint,
6//! and REX usage all match decodes the operands through its slots. Every read
7//! is bounds-checked, so no input can make it panic; anything the table does
8//! not describe is a [`DecodeError`] naming the byte at fault.
9
10use core::fmt;
11use core::iter::FusedIterator;
12
13use super::error::DecodeError;
14use super::flags::FlagEffects;
15use super::form::{ATTR_D64, ATTR_NOT_R0, Form, ModRmSpec, OpcodeField, OperandKind, Slot};
16use super::inst::{Inst, MAX_OPERANDS, Mnemonic};
17use super::operand::{Cond, Mem, Operand, Scale};
18use super::reg::{Reg, Size};
19use super::table;
20
21/// A decoded instruction: the [`Inst`], how many bytes it took, and the form
22/// it matched.
23///
24/// # Examples
25///
26/// ```
27/// use isa_lang::x86_64::decode;
28///
29/// let d = decode(&[0x48, 0x8B, 0x44, 0x24, 0x08, 0xC3])?;
30/// assert_eq!(d.len(), 5);
31/// assert_eq!(d.inst().to_string(), "mov rax, qword ptr [rsp+0x8]");
32/// assert_eq!(d.form().syntax(), "MOV r64, r/m64");
33/// # Ok::<(), isa_lang::x86_64::DecodeError>(())
34/// ```
35#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
36pub struct Decoded {
37    inst: Inst,
38    flags: FlagEffects,
39    form: u16,
40    len: u8,
41}
42
43impl Decoded {
44    /// The instruction.
45    ///
46    /// # Examples
47    ///
48    /// ```
49    /// use isa_lang::x86_64::{decode, Inst, Mnemonic};
50    ///
51    /// assert_eq!(decode(&[0xCC])?.inst(), Inst::new(Mnemonic::Int3, []));
52    /// # Ok::<(), isa_lang::x86_64::DecodeError>(())
53    /// ```
54    #[inline]
55    #[must_use]
56    pub const fn inst(&self) -> Inst {
57        self.inst
58    }
59
60    /// The number of bytes the instruction occupies (1 to 15).
61    ///
62    /// # Examples
63    ///
64    /// ```
65    /// use isa_lang::x86_64::decode;
66    ///
67    /// assert_eq!(decode(&[0x0F, 0x1F, 0x44, 0x00, 0x00])?.len(), 5);
68    /// # Ok::<(), isa_lang::x86_64::DecodeError>(())
69    /// ```
70    #[allow(clippy::len_without_is_empty)] // A decoded instruction is never empty.
71    #[inline]
72    #[must_use]
73    pub const fn len(&self) -> usize {
74        self.len as usize
75    }
76
77    /// The table row the bytes matched.
78    ///
79    /// # Examples
80    ///
81    /// ```
82    /// use isa_lang::x86_64::decode;
83    ///
84    /// assert_eq!(decode(&[0x05, 1, 0, 0, 0])?.form().syntax(), "ADD EAX, imm32");
85    /// # Ok::<(), isa_lang::x86_64::DecodeError>(())
86    /// ```
87    #[must_use]
88    pub fn form(&self) -> &'static Form {
89        // Every `Decoded` is built from a table form, so the lookup succeeds;
90        // the fallback keeps this total without a panic path.
91        table::form(self.form).unwrap_or(&table::FORMS[0])
92    }
93
94    /// What the instruction does to the flags, with a condition code's reads
95    /// filled in.
96    ///
97    /// # Examples
98    ///
99    /// ```
100    /// use isa_lang::x86_64::{decode, Flags};
101    ///
102    /// // sete al
103    /// assert_eq!(decode(&[0x0F, 0x94, 0xC0])?.flags().read(), Flags::ZF);
104    /// # Ok::<(), isa_lang::x86_64::DecodeError>(())
105    /// ```
106    #[inline]
107    #[must_use]
108    pub const fn flags(&self) -> FlagEffects {
109        self.flags
110    }
111}
112
113/// Decodes the instruction at the start of `bytes`.
114///
115/// Trailing bytes are ignored; [`Decoded::len`] says how many were used.
116///
117/// # Errors
118///
119/// A [`DecodeError`] naming the offending byte when the bytes do not start
120/// with an instruction the form table describes, or end too soon.
121///
122/// # Examples
123///
124/// ```
125/// use isa_lang::x86_64::{decode, encode, DecodeError, Inst, Mnemonic, Operand, Reg};
126///
127/// let inst = Inst::new(Mnemonic::Sub, [Reg::RSP.into(), Operand::Imm(40)]);
128/// let bytes = encode(&inst).unwrap();
129/// assert_eq!(decode(&bytes)?.inst(), inst);
130///
131/// assert_eq!(decode(&[]), Err(DecodeError::Truncated { at: 0 }));
132/// # Ok::<(), DecodeError>(())
133/// ```
134pub fn decode(bytes: &[u8]) -> Result<Decoded, DecodeError> {
135    Decoder { bytes, pos: 0 }.run()
136}
137
138/// Bounds-checked little-endian reads.
139struct Decoder<'a> {
140    bytes: &'a [u8],
141    pos: usize,
142}
143
144impl Decoder<'_> {
145    #[inline]
146    fn peek(&self) -> Result<u8, DecodeError> {
147        self.bytes
148            .get(self.pos)
149            .copied()
150            .ok_or(DecodeError::Truncated { at: self.pos })
151    }
152
153    #[inline]
154    fn byte(&mut self) -> Result<u8, DecodeError> {
155        let b = self.peek()?;
156        self.pos += 1;
157        Ok(b)
158    }
159
160    /// Reads `n` (1, 2, 4, or 8) bytes as a little-endian integer, sign- or
161    /// zero-extended to 64 bits.
162    fn int(&mut self, n: usize, signed: bool) -> Result<i64, DecodeError> {
163        let end = self
164            .pos
165            .checked_add(n)
166            .ok_or(DecodeError::Truncated { at: self.pos })?;
167        let Some(field) = self.bytes.get(self.pos..end) else {
168            return Err(DecodeError::Truncated {
169                at: self.bytes.len().max(self.pos),
170            });
171        };
172        let mut raw = [0u8; 8];
173        for (dst, src) in raw.iter_mut().zip(field) {
174            *dst = *src;
175        }
176        self.pos = end;
177        let value = u64::from_le_bytes(raw);
178        let bits = (n * 8) as u32;
179        Ok(if bits >= 64 {
180            value as i64
181        } else if signed {
182            let shift = 64 - bits;
183            ((value << shift) as i64) >> shift
184        } else {
185            value as i64
186        })
187    }
188
189    fn run(mut self) -> Result<Decoded, DecodeError> {
190        let mut p66 = false;
191        loop {
192            let b = self.peek()?;
193            match b {
194                0x66 if p66 => return Err(DecodeError::RepeatedPrefix { at: self.pos }),
195                0x66 => p66 = true,
196                0xF0 | 0xF2 | 0xF3 | 0x2E | 0x36 | 0x3E | 0x26 | 0x64 | 0x65 | 0x67 => {
197                    return Err(DecodeError::UnsupportedPrefix {
198                        at: self.pos,
199                        byte: b,
200                    });
201                }
202                _ => break,
203            }
204            self.pos += 1;
205        }
206        let mut rex = Rex::NONE;
207        if self.peek()? & 0xF0 == 0x40 {
208            rex = Rex {
209                bits: self.byte()?,
210                at: self.pos - 1,
211            };
212            if is_prefix(self.peek()?) {
213                return Err(DecodeError::MisplacedRex { at: rex.at });
214            }
215        }
216        let mut map = 0u8;
217        if self.peek()? == 0x0F {
218            map = 1;
219            self.pos += 1;
220        }
221        let opcode_at = self.pos;
222        let opcode = self.byte()?;
223        let candidates = table::by_opcode(map, opcode);
224        if candidates.is_empty() {
225            return Err(DecodeError::UnknownOpcode {
226                at: opcode_at,
227                escaped: map == 1,
228                opcode,
229            });
230        }
231        let mut modrm: Option<ModRm> = None;
232        let mut miss = Miss::Size;
233        for &id in candidates {
234            let Some(form) = table::form(id) else {
235                continue;
236            };
237            if !size_matches(form, p66, rex) || !opreg_allowed(form, opcode, rex) {
238                continue;
239            }
240            if !matches!(form.modrm, ModRmSpec::Absent) && modrm.is_none() {
241                let at = self.pos;
242                let byte = self.byte()?;
243                modrm = Some(ModRm {
244                    md: byte >> 6,
245                    reg: (byte >> 3) & 7,
246                    rm: byte & 7,
247                    at,
248                });
249            }
250            match check(form, modrm, rex, &mut self)? {
251                Ok(()) => return self.operands(form, opcode, modrm, rex),
252                Err(m) => miss = miss.closer(m),
253            }
254        }
255        Err(miss.into_error(opcode_at, modrm, rex))
256    }
257
258    /// Decodes the operands of the form that matched.
259    fn operands(
260        mut self,
261        form: &Form,
262        opcode: u8,
263        modrm: Option<ModRm>,
264        rex: Rex,
265    ) -> Result<Decoded, DecodeError> {
266        let has_rex = rex.present();
267        let rm_operand = match modrm {
268            Some(m) if m.md == 3 => RmOperand::Reg(rex.b() | m.rm),
269            Some(m) => RmOperand::Mem(self.address(m, rex)?),
270            None => RmOperand::None,
271        };
272        let mut ops = [Operand::Imm(0); MAX_OPERANDS];
273        let mut rel_slot = None;
274        let count = usize::from(form.count).min(MAX_OPERANDS);
275        for i in 0..count {
276            let (Some(&kind), Some(&slot)) = (form.kinds.get(i), form.slots.get(i)) else {
277                continue;
278            };
279            let size = kind_size(kind);
280            let op = match (slot, kind) {
281                (Slot::Implied, OperandKind::Fixed(r)) => Operand::Reg(r),
282                (Slot::Implied, _) => Operand::Imm(1),
283                (Slot::Reg, _) => {
284                    let num = rex.r() | modrm.map_or(0, |m| m.reg);
285                    Operand::Reg(Reg::decode(size, num, has_rex))
286                }
287                (Slot::Opcode, _) => {
288                    Operand::Reg(Reg::decode(size, rex.b() | (opcode & 7), has_rex))
289                }
290                (Slot::Rm, _) => match rm_operand {
291                    RmOperand::Reg(num) => Operand::Reg(Reg::decode(size, num, has_rex)),
292                    RmOperand::Mem(addr) => Operand::Mem(addr.with_size(size)),
293                    RmOperand::None => Operand::Imm(0),
294                },
295                (Slot::Imm, OperandKind::Rel { .. }) => {
296                    rel_slot = Some(i);
297                    Operand::Rel(self.int(usize::from(form.imm_bytes), true)?)
298                }
299                (Slot::Imm, OperandKind::Imm { signed, .. }) => {
300                    Operand::Imm(self.int(usize::from(form.imm_bytes), signed)?)
301                }
302                (Slot::Imm, _) => Operand::Imm(0),
303            };
304            if let Some(o) = ops.get_mut(i) {
305                *o = op;
306            }
307        }
308        let len = self.pos;
309        // A relative target is stored from the start of the instruction.
310        if let Some(Operand::Rel(r)) = rel_slot.and_then(|i| ops.get_mut(i)) {
311            *r += len as i64;
312        }
313        let cond = Cond::from_code(opcode & 15).unwrap_or(Cond::O);
314        let mnemonic = Mnemonic::from_parts(form.op, cond);
315        let inst = Inst::from_slice(mnemonic, ops.get(..count).unwrap_or(&[]))
316            .unwrap_or(Inst::new(mnemonic, []));
317        let mut flags = form.flags;
318        if form.reads_cond {
319            flags = flags.with_read(cond.reads());
320        }
321        Ok(Decoded {
322            inst,
323            flags,
324            form: form.id,
325            len: len.min(15) as u8,
326        })
327    }
328
329    /// Decodes a ModRM memory operand (mod != 11), with SIB and displacement.
330    /// The size is filled in by the caller.
331    fn address(&mut self, m: ModRm, rex: Rex) -> Result<Mem, DecodeError> {
332        if m.md == 0 && m.rm == 0b101 {
333            let disp = self.int(4, true)? as i32;
334            return Ok(Mem::rip(Size::Qword, disp));
335        }
336        let (base, index, scale) = if m.rm == 0b100 {
337            let sib = self.byte()?;
338            let index_num = rex.x() | ((sib >> 3) & 7);
339            let index = (index_num != 0b100).then(|| Reg::decode(Size::Qword, index_num, true));
340            let base_low = sib & 7;
341            let base = if base_low == 0b101 && m.md == 0 {
342                None
343            } else {
344                Some(Reg::decode(Size::Qword, rex.b() | base_low, true))
345            };
346            (base, index, Scale::from_bits(sib >> 6))
347        } else {
348            (
349                Some(Reg::decode(Size::Qword, rex.b() | m.rm, true)),
350                None,
351                Scale::X1,
352            )
353        };
354        let disp = match (m.md, base) {
355            (0, None) | (2, _) => self.int(4, true)? as i32,
356            (1, _) => self.int(1, true)? as i32,
357            _ => 0,
358        };
359        Ok(Mem::decoded(Size::Qword, base, index, scale, disp))
360    }
361}
362
363/// The ModRM byte, split.
364#[derive(Clone, Copy)]
365struct ModRm {
366    md: u8,
367    reg: u8,
368    rm: u8,
369    at: usize,
370}
371
372/// The REX prefix, if any.
373#[derive(Clone, Copy)]
374struct Rex {
375    bits: u8,
376    at: usize,
377}
378
379impl Rex {
380    const NONE: Rex = Rex {
381        bits: 0,
382        at: usize::MAX,
383    };
384
385    fn present(self) -> bool {
386        self.bits != 0
387    }
388    fn w(self) -> bool {
389        self.bits & 8 != 0
390    }
391    fn r(self) -> u8 {
392        (self.bits & 4) << 1
393    }
394    fn x(self) -> u8 {
395        (self.bits & 2) << 2
396    }
397    fn b(self) -> u8 {
398        (self.bits & 1) << 3
399    }
400}
401
402enum RmOperand {
403    None,
404    Reg(u8),
405    Mem(Mem),
406}
407
408/// Why a candidate form did not match, ordered from farthest to closest.
409#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
410enum Miss {
411    Size,
412    Extension,
413    Register,
414    Rex,
415}
416
417impl Miss {
418    fn closer(self, other: Miss) -> Miss {
419        self.max(other)
420    }
421
422    fn into_error(self, opcode_at: usize, modrm: Option<ModRm>, rex: Rex) -> DecodeError {
423        match (self, modrm) {
424            (Miss::Extension, Some(m)) => DecodeError::UnknownExtension {
425                at: m.at,
426                ext: m.reg,
427            },
428            (Miss::Register, Some(m)) => DecodeError::RegisterOperand { at: m.at },
429            (Miss::Rex, _) => DecodeError::UnusedRex { at: rex.at },
430            _ => DecodeError::InvalidOperandSize { at: opcode_at },
431        }
432    }
433}
434
435fn is_prefix(b: u8) -> bool {
436    matches!(
437        b,
438        0x66 | 0xF0 | 0xF2 | 0xF3 | 0x2E | 0x36 | 0x3E | 0x26 | 0x64 | 0x65 | 0x67
439    ) || b & 0xF0 == 0x40
440}
441
442/// `66` must be present exactly when the form has it; REX.W likewise, except
443/// that default-64 forms accept a redundant REX.W.
444fn size_matches(form: &Form, p66: bool, rex: Rex) -> bool {
445    p66 == form.p66 && (rex.w() == form.rex_w || (form.attrs & ATTR_D64 != 0 && !form.rex_w))
446}
447
448/// The `XCHG r, eAX` forms exclude register 0: `90` is `NOP`.
449fn opreg_allowed(form: &Form, opcode: u8, rex: Rex) -> bool {
450    !(matches!(form.field, OpcodeField::Reg)
451        && form.attrs & ATTR_NOT_R0 != 0
452        && opcode & 7 == 0
453        && rex.b() == 0)
454}
455
456/// Checks the ModRM-dependent conditions. The outer `Result` is a hard
457/// error (truncation while reading the SIB byte); the inner one says whether
458/// this form matches.
459fn check(
460    form: &Form,
461    modrm: Option<ModRm>,
462    rex: Rex,
463    decoder: &mut Decoder<'_>,
464) -> Result<Result<(), Miss>, DecodeError> {
465    let mut uses_r = false;
466    let mut uses_x = false;
467    let mut uses_b = matches!(form.field, OpcodeField::Reg);
468    if let Some(m) = modrm.filter(|_| !matches!(form.modrm, ModRmSpec::Absent)) {
469        if let ModRmSpec::Ext(n) = form.modrm {
470            if m.reg != n {
471                return Ok(Err(Miss::Extension));
472            }
473        } else {
474            uses_r = true;
475        }
476        if m.md == 3 {
477            if form.rm_mem_only {
478                return Ok(Err(Miss::Register));
479            }
480            uses_b = true;
481        } else if m.rm == 0b100 {
482            // The SIB byte decides whether X and B are used; peek at it.
483            let sib = decoder.peek()?;
484            uses_x = true;
485            uses_b = !(sib & 7 == 0b101 && m.md == 0);
486        } else {
487            uses_b = !(m.rm == 0b101 && m.md == 0);
488        }
489    }
490    let unused = (rex.bits & 4 != 0 && !uses_r)
491        || (rex.bits & 2 != 0 && !uses_x)
492        || (rex.bits & 1 != 0 && !uses_b);
493    Ok(if unused { Err(Miss::Rex) } else { Ok(()) })
494}
495
496/// The register width an operand kind decodes to.
497fn kind_size(kind: OperandKind) -> Size {
498    match kind {
499        OperandKind::Reg(s) | OperandKind::RegMem(s) | OperandKind::Mem(s) => s,
500        OperandKind::Fixed(r) => r.size(),
501        OperandKind::One | OperandKind::Imm { .. } | OperandKind::Rel { .. } => Size::Qword,
502    }
503}
504
505/// An iterator that decodes instructions one after another from a byte
506/// slice, yielding each with its offset. It stops after the first error.
507///
508/// # Examples
509///
510/// ```
511/// use isa_lang::x86_64::decode_all;
512///
513/// let code = [0x55, 0x48, 0x89, 0xE5, 0x5D, 0xC3];
514/// let text: Vec<String> = decode_all(&code)
515///     .map(|r| r.map(|(_, d)| d.inst().to_string()))
516///     .collect::<Result<_, _>>()?;
517/// assert_eq!(text, ["push rbp", "mov rbp, rsp", "pop rbp", "ret"]);
518/// # Ok::<(), isa_lang::x86_64::DecodeError>(())
519/// ```
520#[derive(Clone, Debug)]
521pub struct Instructions<'a> {
522    bytes: &'a [u8],
523    offset: usize,
524    failed: bool,
525}
526
527/// Decodes every instruction in `bytes`, in order. See [`Instructions`].
528///
529/// # Examples
530///
531/// ```
532/// use isa_lang::x86_64::decode_all;
533///
534/// assert_eq!(decode_all(&[0x90, 0x90, 0xC3]).count(), 3);
535/// // An error ends the sequence, with the offset of the bad byte.
536/// let last = decode_all(&[0x90, 0x0F, 0xFF]).last().unwrap();
537/// assert_eq!(last.unwrap_err().at(), 2);
538/// ```
539#[must_use]
540pub fn decode_all(bytes: &[u8]) -> Instructions<'_> {
541    Instructions {
542        bytes,
543        offset: 0,
544        failed: false,
545    }
546}
547
548impl Iterator for Instructions<'_> {
549    type Item = Result<(usize, Decoded), DecodeError>;
550
551    fn next(&mut self) -> Option<Self::Item> {
552        if self.failed {
553            return None;
554        }
555        let rest = self.bytes.get(self.offset..).filter(|r| !r.is_empty())?;
556        match decode(rest) {
557            Ok(d) => {
558                let at = self.offset;
559                self.offset += d.len();
560                Some(Ok((at, d)))
561            }
562            Err(e) => {
563                self.failed = true;
564                Some(Err(rebase(e, self.offset)))
565            }
566        }
567    }
568}
569
570impl FusedIterator for Instructions<'_> {}
571
572/// Shifts an error's offset from the start of a sub-slice to the start of
573/// the whole input.
574fn rebase(e: DecodeError, by: usize) -> DecodeError {
575    match e {
576        DecodeError::Truncated { at } => DecodeError::Truncated { at: at + by },
577        DecodeError::UnsupportedPrefix { at, byte } => {
578            DecodeError::UnsupportedPrefix { at: at + by, byte }
579        }
580        DecodeError::RepeatedPrefix { at } => DecodeError::RepeatedPrefix { at: at + by },
581        DecodeError::MisplacedRex { at } => DecodeError::MisplacedRex { at: at + by },
582        DecodeError::UnknownOpcode {
583            at,
584            escaped,
585            opcode,
586        } => DecodeError::UnknownOpcode {
587            at: at + by,
588            escaped,
589            opcode,
590        },
591        DecodeError::InvalidOperandSize { at } => DecodeError::InvalidOperandSize { at: at + by },
592        DecodeError::UnknownExtension { at, ext } => {
593            DecodeError::UnknownExtension { at: at + by, ext }
594        }
595        DecodeError::RegisterOperand { at } => DecodeError::RegisterOperand { at: at + by },
596        DecodeError::UnusedRex { at } => DecodeError::UnusedRex { at: at + by },
597    }
598}
599
600/// A disassembly listing: one line per instruction with its address, its
601/// bytes, and its Intel-syntax text. Bytes that do not decode are listed one
602/// at a time as `(bad)` and the listing carries on.
603///
604/// The output is deterministic: same bytes and address, same text.
605///
606/// # Examples
607///
608/// ```
609/// use isa_lang::x86_64::disassemble;
610///
611/// let code = [0x31, 0xC0, 0x74, 0x00, 0x0F, 0xC3];
612/// let text = disassemble(&code, 0x1000).to_string();
613/// assert_eq!(
614///     text,
615///     "0000000000001000  31 c0                    xor eax, eax\n\
616///      0000000000001002  74 00                    je 0x1004\n\
617///      0000000000001004  0f                       (bad)\n\
618///      0000000000001005  c3                       ret\n",
619/// );
620/// ```
621#[derive(Clone, Copy, Debug)]
622pub struct Disassembly<'a> {
623    bytes: &'a [u8],
624    ip: u64,
625}
626
627/// Lists `bytes` as instructions starting at address `ip`. See
628/// [`Disassembly`].
629///
630/// # Examples
631///
632/// ```
633/// use isa_lang::x86_64::disassemble;
634///
635/// assert_eq!(disassemble(&[0xC3], 0).to_string(), "0000000000000000  c3                       ret\n");
636/// ```
637#[must_use]
638pub fn disassemble(bytes: &[u8], ip: u64) -> Disassembly<'_> {
639    Disassembly { bytes, ip }
640}
641
642/// Width of the byte column: room for 8 bytes before the text starts.
643const BYTE_COLUMN: usize = 25;
644
645impl fmt::Display for Disassembly<'_> {
646    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
647        let mut offset = 0usize;
648        while let Some(rest) = self.bytes.get(offset..).filter(|r| !r.is_empty()) {
649            let ip = self.ip.wrapping_add(offset as u64);
650            let (len, decoded) = match decode(rest) {
651                Ok(d) => (d.len(), Some(d)),
652                Err(_) => (1, None),
653            };
654            write!(f, "{ip:016x}  ")?;
655            let mut written = 0;
656            for b in rest.iter().take(len) {
657                write!(f, "{b:02x} ")?;
658                written += 3;
659            }
660            for _ in written..BYTE_COLUMN {
661                f.write_str(" ")?;
662            }
663            match decoded {
664                Some(d) => writeln!(f, "{}", d.inst().display_at(ip))?,
665                None => f.write_str("(bad)\n")?,
666            }
667            offset += len;
668        }
669        Ok(())
670    }
671}
672
673#[cfg(test)]
674mod tests {
675    use super::*;
676
677    fn text(bytes: &[u8]) -> alloc::string::String {
678        use alloc::string::ToString;
679        decode(bytes)
680            .map(|d| d.inst().to_string())
681            .unwrap_or_else(|e| e.to_string())
682    }
683
684    #[test]
685    fn test_decode_prefix_errors() {
686        assert_eq!(decode(&[0x66]), Err(DecodeError::Truncated { at: 1 }));
687        assert_eq!(
688            decode(&[0x66, 0x66, 0x01, 0xC0]),
689            Err(DecodeError::RepeatedPrefix { at: 1 })
690        );
691        assert_eq!(
692            decode(&[0x48, 0x66, 0x01, 0xC0]),
693            Err(DecodeError::MisplacedRex { at: 0 })
694        );
695        assert_eq!(
696            decode(&[0x48, 0x41, 0x01, 0xC0]),
697            Err(DecodeError::MisplacedRex { at: 0 })
698        );
699        assert_eq!(
700            decode(&[0x67, 0x8B, 0x00]),
701            Err(DecodeError::UnsupportedPrefix { at: 0, byte: 0x67 })
702        );
703        assert_eq!(decode(&[0x48]), Err(DecodeError::Truncated { at: 1 }));
704        assert_eq!(decode(&[0x0F]), Err(DecodeError::Truncated { at: 1 }));
705    }
706
707    #[test]
708    fn test_decode_form_errors() {
709        // F7 /1 is not defined.
710        assert_eq!(
711            decode(&[0xF7, 0xC8]),
712            Err(DecodeError::UnknownExtension { at: 1, ext: 1 })
713        );
714        // lea eax, eax
715        assert_eq!(
716            decode(&[0x8D, 0xC0]),
717            Err(DecodeError::RegisterOperand { at: 1 })
718        );
719        // REX.B on ret
720        assert_eq!(decode(&[0x41, 0xC3]), Err(DecodeError::UnusedRex { at: 0 }));
721        // REX.X without a SIB byte
722        assert_eq!(
723            decode(&[0x42, 0x01, 0xC0]),
724            Err(DecodeError::UnusedRex { at: 0 })
725        );
726        // 66 on movsxd has no form
727        assert_eq!(
728            decode(&[0x66, 0x63, 0xC0]),
729            Err(DecodeError::InvalidOperandSize { at: 1 })
730        );
731        // Truncated SIB, displacement, immediate
732        assert_eq!(decode(&[0x8B, 0x04]), Err(DecodeError::Truncated { at: 2 }));
733        assert_eq!(
734            decode(&[0x8B, 0x80, 1, 2]),
735            Err(DecodeError::Truncated { at: 4 })
736        );
737        assert_eq!(decode(&[0x05, 1]), Err(DecodeError::Truncated { at: 2 }));
738    }
739
740    #[test]
741    fn test_decode_nop_and_xchg_share_90() {
742        assert_eq!(text(&[0x90]), "nop");
743        assert_eq!(text(&[0x66, 0x90]), "nop");
744        assert_eq!(text(&[0x48, 0x90]), "nop");
745        assert_eq!(text(&[0x40, 0x90]), "nop");
746        assert_eq!(text(&[0x41, 0x90]), "xchg r8d, eax");
747        assert_eq!(text(&[0x49, 0x90]), "xchg r8, rax");
748        assert_eq!(text(&[0x93]), "xchg ebx, eax");
749        assert_eq!(text(&[0x66, 0x93]), "xchg bx, ax");
750    }
751
752    #[test]
753    fn test_decode_byte_registers_depend_on_rex() {
754        assert_eq!(text(&[0x88, 0xE0]), "mov al, ah");
755        assert_eq!(text(&[0x40, 0x88, 0xE0]), "mov al, spl");
756        assert_eq!(text(&[0x0F, 0xB6, 0xC4]), "movzx eax, ah");
757        assert_eq!(text(&[0x48, 0x0F, 0xB6, 0xC4]), "movzx rax, spl");
758    }
759
760    #[test]
761    fn test_decode_d64_accepts_redundant_rex_w() {
762        assert_eq!(text(&[0x48, 0xFF, 0xE0]), "jmp rax");
763        assert_eq!(text(&[0x48, 0x50]), "push rax");
764        assert_eq!(text(&[0x48, 0xFF, 0x25, 0, 0, 0, 0]), "jmp qword ptr [rip]");
765        assert_eq!(
766            text(&[0x66, 0x50]),
767            "opcode at byte 1 has no form with this operand size"
768        );
769    }
770
771    #[test]
772    fn test_decode_rel_is_from_instruction_start() {
773        assert_eq!(text(&[0xEB, 0xFE]), "jmp $+0x0");
774        assert_eq!(text(&[0xE9, 0, 0, 0, 0]), "jmp $+0x5");
775        assert_eq!(text(&[0x0F, 0x84, 0xFA, 0xFF, 0xFF, 0xFF]), "je $+0x0");
776    }
777
778    #[test]
779    fn test_rebase_shifts_every_variant() {
780        let all = [
781            DecodeError::Truncated { at: 1 },
782            DecodeError::UnsupportedPrefix { at: 1, byte: 0xF0 },
783            DecodeError::RepeatedPrefix { at: 1 },
784            DecodeError::MisplacedRex { at: 1 },
785            DecodeError::UnknownOpcode {
786                at: 1,
787                escaped: false,
788                opcode: 6,
789            },
790            DecodeError::InvalidOperandSize { at: 1 },
791            DecodeError::UnknownExtension { at: 1, ext: 1 },
792            DecodeError::RegisterOperand { at: 1 },
793            DecodeError::UnusedRex { at: 1 },
794        ];
795        for e in all {
796            assert_eq!(rebase(e, 10).at(), 11);
797        }
798    }
799}