Coverage Report

Created: 2026-02-14 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/iced-x86-1.21.0/src/instruction.rs
Line
Count
Source
1
// SPDX-License-Identifier: MIT
2
// Copyright (C) 2018-present iced project and contributors
3
4
use crate::iced_constants::IcedConstants;
5
use crate::iced_error::IcedError;
6
#[cfg(feature = "instr_info")]
7
use crate::info::enums::*;
8
use crate::instruction_internal;
9
use crate::*;
10
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm", feature = "fast_fmt", feature = "serde"))]
11
use core::fmt;
12
use core::hash::{Hash, Hasher};
13
use core::iter::{ExactSizeIterator, FusedIterator};
14
use core::{mem, slice};
15
16
// GENERATOR-BEGIN: InstrFlags1
17
// ⚠️This was generated by GENERATOR!🦹‍♂️
18
pub(crate) struct InstrFlags1;
19
#[allow(dead_code)]
20
impl InstrFlags1 {
21
  pub(crate) const SEGMENT_PREFIX_MASK: u32 = 0x0000_0007;
22
  pub(crate) const SEGMENT_PREFIX_SHIFT: u32 = 0x0000_0005;
23
  pub(crate) const DATA_LENGTH_MASK: u32 = 0x0000_000F;
24
  pub(crate) const DATA_LENGTH_SHIFT: u32 = 0x0000_0008;
25
  pub(crate) const ROUNDING_CONTROL_MASK: u32 = 0x0000_0007;
26
  pub(crate) const ROUNDING_CONTROL_SHIFT: u32 = 0x0000_000C;
27
  pub(crate) const OP_MASK_MASK: u32 = 0x0000_0007;
28
  pub(crate) const OP_MASK_SHIFT: u32 = 0x0000_000F;
29
  pub(crate) const CODE_SIZE_MASK: u32 = 0x0000_0003;
30
  pub(crate) const CODE_SIZE_SHIFT: u32 = 0x0000_0012;
31
  pub(crate) const BROADCAST: u32 = 0x0400_0000;
32
  pub(crate) const SUPPRESS_ALL_EXCEPTIONS: u32 = 0x0800_0000;
33
  pub(crate) const ZEROING_MASKING: u32 = 0x1000_0000;
34
  pub(crate) const REPE_PREFIX: u32 = 0x2000_0000;
35
  pub(crate) const REPNE_PREFIX: u32 = 0x4000_0000;
36
  pub(crate) const LOCK_PREFIX: u32 = 0x8000_0000;
37
  pub(crate) const EQUALS_IGNORE_MASK: u32 = 0x000C_0000;
38
}
39
// GENERATOR-END: InstrFlags1
40
41
// GENERATOR-BEGIN: MvexInstrFlags
42
// ⚠️This was generated by GENERATOR!🦹‍♂️
43
pub(crate) struct MvexInstrFlags;
44
#[allow(dead_code)]
45
impl MvexInstrFlags {
46
  pub(crate) const MVEX_REG_MEM_CONV_SHIFT: u32 = 0x0000_0010;
47
  pub(crate) const MVEX_REG_MEM_CONV_MASK: u32 = 0x0000_001F;
48
  pub(crate) const EVICTION_HINT: u32 = 0x8000_0000;
49
}
50
// GENERATOR-END: MvexInstrFlags
51
52
/// A 16/32/64-bit x86 instruction. Created by [`Decoder`], by [`CodeAssembler`] or by `Instruction::with*()` methods.
53
///
54
/// [`CodeAssembler`]: code_asm/struct.CodeAssembler.html
55
/// [`Decoder`]: struct.Decoder.html
56
#[derive(Debug, Default, Copy, Clone)]
57
pub struct Instruction {
58
  pub(crate) next_rip: u64,
59
  pub(crate) mem_displ: u64,
60
  pub(crate) flags1: u32, // InstrFlags1
61
  pub(crate) immediate: u32,
62
  pub(crate) code: Code,
63
  pub(crate) mem_base_reg: Register,
64
  pub(crate) mem_index_reg: Register,
65
  pub(crate) regs: [Register; 4],
66
  pub(crate) op_kinds: [OpKind; 4],
67
  pub(crate) scale: InstrScale,
68
  pub(crate) displ_size: u8,
69
  pub(crate) len: u8,
70
  pad: u8,
71
}
72
#[cfg(test)]
73
#[allow(dead_code)]
74
pub(crate) const INSTRUCTION_TOTAL_SIZE: usize = 40;
75
76
#[allow(clippy::len_without_is_empty)]
77
impl Instruction {
78
  /// Creates an empty `Instruction` (all fields are cleared). See also the `with_*()` constructor methods.
79
  #[must_use]
80
  #[inline]
81
0
  pub fn new() -> Self {
82
0
    Instruction::default()
83
0
  }
84
85
  /// Checks if two instructions are equal, comparing all bits, not ignoring anything. `==` ignores some fields.
86
  #[must_use]
87
  #[allow(trivial_casts)]
88
  #[allow(clippy::missing_inline_in_public_items)]
89
0
  pub fn eq_all_bits(&self, other: &Self) -> bool {
90
    // The compiler generated better code than if we compare all fields one at a time.
91
    // SAFETY: see `slice::from_raw_parts()`
92
    unsafe {
93
0
      let a: *const u8 = self as *const Self as *const u8;
94
0
      let b: *const u8 = other as *const Self as *const u8;
95
0
      let sa = slice::from_raw_parts(a, mem::size_of::<Self>());
96
0
      let sb = slice::from_raw_parts(b, mem::size_of::<Self>());
97
0
      sa == sb
98
    }
99
0
  }
100
101
  /// Gets the 16-bit IP of the instruction, see also [`next_ip16()`]
102
  ///
103
  /// [`next_ip16()`]: #method.next_ip16
104
  #[must_use]
105
  #[inline]
106
0
  pub const fn ip16(&self) -> u16 {
107
0
    (self.next_rip as u16).wrapping_sub(self.len() as u16)
108
0
  }
109
110
  /// Sets the 16-bit IP of the instruction, see also [`set_next_ip16()`]
111
  ///
112
  /// [`set_next_ip16()`]: #method.set_next_ip16
113
  ///
114
  /// # Arguments
115
  ///
116
  /// * `new_value`: new value
117
  #[inline]
118
0
  pub fn set_ip16(&mut self, new_value: u16) {
119
0
    self.next_rip = (new_value as u64).wrapping_add(self.len() as u64);
120
0
  }
121
122
  /// Gets the 32-bit IP of the instruction, see also [`next_ip32()`]
123
  ///
124
  /// [`next_ip32()`]: #method.next_ip32
125
  #[must_use]
126
  #[inline]
127
0
  pub const fn ip32(&self) -> u32 {
128
0
    (self.next_rip as u32).wrapping_sub(self.len() as u32)
129
0
  }
130
131
  /// Sets the 32-bit IP of the instruction, see also [`set_next_ip32()`]
132
  ///
133
  /// [`set_next_ip32()`]: #method.set_next_ip32
134
  ///
135
  /// # Arguments
136
  ///
137
  /// * `new_value`: new value
138
  #[inline]
139
0
  pub fn set_ip32(&mut self, new_value: u32) {
140
0
    self.next_rip = (new_value as u64).wrapping_add(self.len() as u64);
141
0
  }
142
143
  /// Gets the 64-bit IP of the instruction, see also [`next_ip()`]
144
  ///
145
  /// [`next_ip()`]: #method.next_ip
146
  #[must_use]
147
  #[inline]
148
0
  pub const fn ip(&self) -> u64 {
149
0
    self.next_rip.wrapping_sub(self.len() as u64)
150
0
  }
151
152
  /// Sets the 64-bit IP of the instruction, see also [`set_next_ip()`]
153
  ///
154
  /// [`set_next_ip()`]: #method.set_next_ip
155
  ///
156
  /// # Arguments
157
  ///
158
  /// * `new_value`: new value
159
  #[inline]
160
0
  pub fn set_ip(&mut self, new_value: u64) {
161
0
    self.next_rip = new_value.wrapping_add(self.len() as u64);
162
0
  }
163
164
  /// Gets the 16-bit IP of the next instruction, see also [`ip16()`]
165
  ///
166
  /// [`ip16()`]: #method.ip16
167
  #[must_use]
168
  #[inline]
169
0
  pub const fn next_ip16(&self) -> u16 {
170
0
    self.next_rip as u16
171
0
  }
172
173
  /// Sets the 16-bit IP of the next instruction, see also [`set_ip16()`]
174
  ///
175
  /// [`set_ip16()`]: #method.set_ip16
176
  ///
177
  /// # Arguments
178
  ///
179
  /// * `new_value`: new value
180
  #[inline]
181
0
  pub fn set_next_ip16(&mut self, new_value: u16) {
182
0
    self.next_rip = new_value as u64;
183
0
  }
184
185
  /// Gets the 32-bit IP of the next instruction, see also [`ip32()`]
186
  ///
187
  /// [`ip32()`]: #method.ip32
188
  #[must_use]
189
  #[inline]
190
0
  pub const fn next_ip32(&self) -> u32 {
191
0
    self.next_rip as u32
192
0
  }
193
194
  /// Sets the 32-bit IP of the next instruction, see also [`set_ip32()`]
195
  ///
196
  /// [`set_ip32()`]: #method.set_ip32
197
  ///
198
  /// # Arguments
199
  ///
200
  /// * `new_value`: new value
201
  #[inline]
202
0
  pub fn set_next_ip32(&mut self, new_value: u32) {
203
0
    self.next_rip = new_value as u64;
204
0
  }
205
206
  /// Gets the 64-bit IP of the next instruction, see also [`ip()`]
207
  ///
208
  /// [`ip()`]: #method.ip
209
  #[must_use]
210
  #[inline]
211
0
  pub const fn next_ip(&self) -> u64 {
212
0
    self.next_rip
213
0
  }
214
215
  /// Sets the 64-bit IP of the next instruction, see also [`set_ip()`]
216
  ///
217
  /// [`set_ip()`]: #method.set_ip
218
  ///
219
  /// # Arguments
220
  ///
221
  /// * `new_value`: new value
222
  #[inline]
223
2.26k
  pub fn set_next_ip(&mut self, new_value: u64) {
224
2.26k
    self.next_rip = new_value;
225
2.26k
  }
226
227
  /// Gets the code size when the instruction was decoded. This value is informational and can
228
  /// be used by a formatter.
229
  #[must_use]
230
  #[inline]
231
0
  pub fn code_size(&self) -> CodeSize {
232
0
    unsafe { mem::transmute(((self.flags1 >> InstrFlags1::CODE_SIZE_SHIFT) & InstrFlags1::CODE_SIZE_MASK) as CodeSizeUnderlyingType) }
233
0
  }
234
235
  /// Sets the code size when the instruction was decoded. This value is informational and can
236
  /// be used by a formatter.
237
  ///
238
  /// # Arguments
239
  ///
240
  /// * `new_value`: new value
241
  #[inline]
242
0
  pub fn set_code_size(&mut self, new_value: CodeSize) {
243
0
    self.flags1 = (self.flags1 & !(InstrFlags1::CODE_SIZE_MASK << InstrFlags1::CODE_SIZE_SHIFT))
244
0
      | (((new_value as u32) & InstrFlags1::CODE_SIZE_MASK) << InstrFlags1::CODE_SIZE_SHIFT);
245
0
  }
246
247
  /// Checks if it's an invalid instruction ([`code()`] == [`Code::INVALID`])
248
  ///
249
  /// [`code()`]: #method.code
250
  /// [`Code::INVALID`]: enum.Code.html#variant.INVALID
251
  #[must_use]
252
  #[inline]
253
0
  pub fn is_invalid(&self) -> bool {
254
0
    self.code == Code::INVALID
255
0
  }
256
257
  /// Gets the instruction code, see also [`mnemonic()`]
258
  ///
259
  /// [`mnemonic()`]: #method.mnemonic
260
  #[must_use]
261
  #[inline]
262
5.52k
  pub const fn code(&self) -> Code {
263
5.52k
    self.code
264
5.52k
  }
<iced_x86::instruction::Instruction>::code
Line
Count
Source
262
5.52k
  pub const fn code(&self) -> Code {
263
5.52k
    self.code
264
5.52k
  }
Unexecuted instantiation: <iced_x86::instruction::Instruction>::code
265
266
  /// Sets the instruction code
267
  ///
268
  /// # Arguments
269
  ///
270
  /// * `new_value`: new value
271
  #[inline]
272
2.01k
  pub fn set_code(&mut self, new_value: Code) {
273
2.01k
    self.code = new_value
274
2.01k
  }
275
276
  /// Gets the mnemonic, see also [`code()`]
277
  ///
278
  /// [`code()`]: #method.code
279
  #[must_use]
280
  #[inline]
281
0
  pub fn mnemonic(&self) -> Mnemonic {
282
0
    self.code().mnemonic()
283
0
  }
284
285
  /// Gets the operand count. An instruction can have 0-5 operands.
286
  ///
287
  /// # Examples
288
  ///
289
  /// ```
290
  /// use iced_x86::*;
291
  ///
292
  /// // add [rax],ebx
293
  /// let bytes = b"\x01\x18";
294
  /// let mut decoder = Decoder::new(64, bytes, DecoderOptions::NONE);
295
  /// let instr = decoder.decode();
296
  ///
297
  /// assert_eq!(instr.op_count(), 2);
298
  /// ```
299
  #[must_use]
300
  #[inline]
301
1.42k
  pub fn op_count(&self) -> u32 {
302
1.42k
    instruction_op_counts::OP_COUNT[self.code() as usize] as u32
303
1.42k
  }
<iced_x86::instruction::Instruction>::op_count
Line
Count
Source
301
1.42k
  pub fn op_count(&self) -> u32 {
302
1.42k
    instruction_op_counts::OP_COUNT[self.code() as usize] as u32
303
1.42k
  }
Unexecuted instantiation: <iced_x86::instruction::Instruction>::op_count
304
305
  /// Gets the length of the instruction, 0-15 bytes. This is just informational. If you modify the instruction
306
  /// or create a new one, this method could return the wrong value.
307
  #[must_use]
308
  #[inline]
309
0
  pub const fn len(&self) -> usize {
310
0
    self.len as usize
311
0
  }
312
313
  /// Sets the length of the instruction, 0-15 bytes. This is just informational. If you modify the instruction
314
  /// or create a new one, this method could return the wrong value.
315
  ///
316
  /// # Arguments
317
  ///
318
  /// * `new_value`: new value
319
  #[inline]
320
0
  pub fn set_len(&mut self, new_value: usize) {
321
0
    self.len = new_value as u8
322
0
  }
323
324
  #[inline]
325
0
  fn is_xacquire_instr(&self) -> bool {
326
    // This method can return true even if it's not an xacquire/xrelease instruction. This only happens if
327
    // it has an invalid LOCK prefix though.
328
0
    if self.op0_kind() != OpKind::Memory {
329
0
      false
330
0
    } else if self.has_lock_prefix() {
331
0
      self.code() != Code::Cmpxchg16b_m128
332
    } else {
333
0
      self.mnemonic() == Mnemonic::Xchg
334
    }
335
0
  }
336
337
  #[inline]
338
0
  fn is_xrelease_instr(&self) -> bool {
339
    // This method can return true even if it's not an xacquire/xrelease instruction. This only happens if
340
    // it has an invalid LOCK prefix though.
341
0
    if self.op0_kind() != OpKind::Memory {
342
0
      false
343
0
    } else if self.has_lock_prefix() {
344
0
      self.code() != Code::Cmpxchg16b_m128
345
    } else {
346
0
      matches!(
347
0
        self.code(),
348
        Code::Xchg_rm8_r8
349
          | Code::Xchg_rm16_r16
350
          | Code::Xchg_rm32_r32
351
          | Code::Xchg_rm64_r64
352
          | Code::Mov_rm8_r8 | Code::Mov_rm16_r16
353
          | Code::Mov_rm32_r32 | Code::Mov_rm64_r64
354
          | Code::Mov_rm8_imm8 | Code::Mov_rm16_imm16
355
          | Code::Mov_rm32_imm32
356
          | Code::Mov_rm64_imm32
357
      )
358
    }
359
0
  }
360
361
  /// `true` if the instruction has the `XACQUIRE` prefix (`F2`)
362
  #[must_use]
363
  #[inline]
364
0
  pub fn has_xacquire_prefix(&self) -> bool {
365
0
    (self.flags1 & InstrFlags1::REPNE_PREFIX) != 0 && self.is_xacquire_instr()
366
0
  }
367
368
  /// `true` if the instruction has the `XACQUIRE` prefix (`F2`)
369
  ///
370
  /// # Arguments
371
  ///
372
  /// * `new_value`: new value
373
  #[inline]
374
0
  pub fn set_has_xacquire_prefix(&mut self, new_value: bool) {
375
0
    if new_value {
376
0
      self.flags1 |= InstrFlags1::REPNE_PREFIX;
377
0
    } else {
378
0
      self.flags1 &= !InstrFlags1::REPNE_PREFIX;
379
0
    }
380
0
  }
381
382
  /// `true` if the instruction has the `XRELEASE` prefix (`F3`)
383
  #[must_use]
384
  #[inline]
385
0
  pub fn has_xrelease_prefix(&self) -> bool {
386
0
    (self.flags1 & InstrFlags1::REPE_PREFIX) != 0 && self.is_xrelease_instr()
387
0
  }
388
389
  /// `true` if the instruction has the `XRELEASE` prefix (`F3`)
390
  ///
391
  /// # Arguments
392
  ///
393
  /// * `new_value`: new value
394
  #[inline]
395
0
  pub fn set_has_xrelease_prefix(&mut self, new_value: bool) {
396
0
    if new_value {
397
0
      self.flags1 |= InstrFlags1::REPE_PREFIX;
398
0
    } else {
399
0
      self.flags1 &= !InstrFlags1::REPE_PREFIX;
400
0
    }
401
0
  }
402
403
  /// `true` if the instruction has the `REPE` or `REP` prefix (`F3`)
404
  #[must_use]
405
  #[inline]
406
699
  pub const fn has_rep_prefix(&self) -> bool {
407
699
    (self.flags1 & InstrFlags1::REPE_PREFIX) != 0
408
699
  }
<iced_x86::instruction::Instruction>::has_rep_prefix
Line
Count
Source
406
699
  pub const fn has_rep_prefix(&self) -> bool {
407
699
    (self.flags1 & InstrFlags1::REPE_PREFIX) != 0
408
699
  }
Unexecuted instantiation: <iced_x86::instruction::Instruction>::has_rep_prefix
409
410
  /// `true` if the instruction has the `REPE` or `REP` prefix (`F3`)
411
  ///
412
  /// # Arguments
413
  ///
414
  /// * `new_value`: new value
415
  #[inline]
416
0
  pub fn set_has_rep_prefix(&mut self, new_value: bool) {
417
0
    if new_value {
418
0
      self.flags1 |= InstrFlags1::REPE_PREFIX;
419
0
    } else {
420
0
      self.flags1 &= !InstrFlags1::REPE_PREFIX;
421
0
    }
422
0
  }
423
424
  /// `true` if the instruction has the `REPE` or `REP` prefix (`F3`)
425
  #[must_use]
426
  #[inline]
427
0
  pub const fn has_repe_prefix(&self) -> bool {
428
0
    (self.flags1 & InstrFlags1::REPE_PREFIX) != 0
429
0
  }
430
431
  /// `true` if the instruction has the `REPE` or `REP` prefix (`F3`)
432
  ///
433
  /// # Arguments
434
  ///
435
  /// * `new_value`: new value
436
  #[inline]
437
1
  pub fn set_has_repe_prefix(&mut self, new_value: bool) {
438
1
    if new_value {
439
0
      self.flags1 |= InstrFlags1::REPE_PREFIX;
440
1
    } else {
441
1
      self.flags1 &= !InstrFlags1::REPE_PREFIX;
442
1
    }
443
1
  }
444
445
  /// `true` if the instruction has the `REPNE` prefix (`F2`)
446
  #[must_use]
447
  #[inline]
448
0
  pub const fn has_repne_prefix(&self) -> bool {
449
0
    (self.flags1 & InstrFlags1::REPNE_PREFIX) != 0
450
0
  }
451
452
  /// `true` if the instruction has the `REPNE` prefix (`F2`)
453
  ///
454
  /// # Arguments
455
  ///
456
  /// * `new_value`: new value
457
  #[inline]
458
0
  pub fn set_has_repne_prefix(&mut self, new_value: bool) {
459
0
    if new_value {
460
0
      self.flags1 |= InstrFlags1::REPNE_PREFIX;
461
0
    } else {
462
0
      self.flags1 &= !InstrFlags1::REPNE_PREFIX;
463
0
    }
464
0
  }
465
466
  /// `true` if the instruction has the `LOCK` prefix (`F0`)
467
  #[must_use]
468
  #[inline]
469
6
  pub const fn has_lock_prefix(&self) -> bool {
470
6
    (self.flags1 & InstrFlags1::LOCK_PREFIX) != 0
471
6
  }
472
473
  /// `true` if the instruction has the `LOCK` prefix (`F0`)
474
  ///
475
  /// # Arguments
476
  ///
477
  /// * `new_value`: new value
478
  #[inline]
479
182
  pub fn set_has_lock_prefix(&mut self, new_value: bool) {
480
182
    if new_value {
481
182
      self.flags1 |= InstrFlags1::LOCK_PREFIX;
482
182
    } else {
483
0
      self.flags1 &= !InstrFlags1::LOCK_PREFIX;
484
0
    }
485
182
  }
486
487
  /// Gets operand #0's kind if the operand exists (see [`op_count()`] and [`try_op_kind()`])
488
  ///
489
  /// [`op_count()`]: #method.op_count
490
  /// [`try_op_kind()`]: #method.try_op_kind
491
  #[must_use]
492
  #[inline]
493
0
  pub const fn op0_kind(&self) -> OpKind {
494
0
    self.op_kinds[0]
495
0
  }
496
497
  /// Sets operand #0's kind if the operand exists (see [`op_count()`] and [`try_set_op_kind()`])
498
  ///
499
  /// [`op_count()`]: #method.op_count
500
  /// [`try_set_op_kind()`]: #method.try_set_op_kind
501
  ///
502
  /// # Arguments
503
  ///
504
  /// * `new_value`: new value
505
  #[inline]
506
1.32k
  pub fn set_op0_kind(&mut self, new_value: OpKind) {
507
1.32k
    self.op_kinds[0] = new_value
508
1.32k
  }
509
510
  /// Gets operand #1's kind if the operand exists (see [`op_count()`] and [`try_op_kind()`])
511
  ///
512
  /// [`op_count()`]: #method.op_count
513
  /// [`try_op_kind()`]: #method.try_op_kind
514
  #[must_use]
515
  #[inline]
516
0
  pub const fn op1_kind(&self) -> OpKind {
517
0
    self.op_kinds[1]
518
0
  }
519
520
  /// Sets operand #1's kind if the operand exists (see [`op_count()`] and [`try_set_op_kind()`])
521
  ///
522
  /// [`op_count()`]: #method.op_count
523
  /// [`try_set_op_kind()`]: #method.try_set_op_kind
524
  ///
525
  /// # Arguments
526
  ///
527
  /// * `new_value`: new value
528
  #[inline]
529
817
  pub fn set_op1_kind(&mut self, new_value: OpKind) {
530
817
    self.op_kinds[1] = new_value
531
817
  }
532
533
  /// Gets operand #2's kind if the operand exists (see [`op_count()`] and [`try_op_kind()`])
534
  ///
535
  /// [`op_count()`]: #method.op_count
536
  /// [`try_op_kind()`]: #method.try_op_kind
537
  #[must_use]
538
  #[inline]
539
0
  pub const fn op2_kind(&self) -> OpKind {
540
0
    self.op_kinds[2]
541
0
  }
542
543
  /// Sets operand #2's kind if the operand exists (see [`op_count()`] and [`try_set_op_kind()`])
544
  ///
545
  /// [`op_count()`]: #method.op_count
546
  /// [`try_set_op_kind()`]: #method.try_set_op_kind
547
  ///
548
  /// # Arguments
549
  ///
550
  /// * `new_value`: new value
551
  #[inline]
552
65
  pub fn set_op2_kind(&mut self, new_value: OpKind) {
553
65
    self.op_kinds[2] = new_value
554
65
  }
555
556
  /// Gets operand #3's kind if the operand exists (see [`op_count()`] and [`try_op_kind()`])
557
  ///
558
  /// [`op_count()`]: #method.op_count
559
  /// [`try_op_kind()`]: #method.try_op_kind
560
  #[must_use]
561
  #[inline]
562
0
  pub const fn op3_kind(&self) -> OpKind {
563
0
    self.op_kinds[3]
564
0
  }
565
566
  /// Sets operand #3's kind if the operand exists (see [`op_count()`] and [`try_set_op_kind()`])
567
  ///
568
  /// [`op_count()`]: #method.op_count
569
  /// [`try_set_op_kind()`]: #method.try_set_op_kind
570
  ///
571
  /// # Arguments
572
  ///
573
  /// * `new_value`: new value
574
  #[inline]
575
0
  pub fn set_op3_kind(&mut self, new_value: OpKind) {
576
0
    self.op_kinds[3] = new_value
577
0
  }
578
579
  /// Gets operand #4's kind if the operand exists (see [`op_count()`] and [`try_op_kind()`])
580
  ///
581
  /// [`op_count()`]: #method.op_count
582
  /// [`try_op_kind()`]: #method.try_op_kind
583
  #[allow(clippy::unused_self)]
584
  #[must_use]
585
  #[inline]
586
0
  pub const fn op4_kind(&self) -> OpKind {
587
0
    OpKind::Immediate8
588
0
  }
Unexecuted instantiation: <iced_x86::instruction::Instruction>::op4_kind
Unexecuted instantiation: <iced_x86::instruction::Instruction>::op4_kind
589
590
  /// Sets operand #4's kind if the operand exists (see [`op_count()`] and [`try_set_op_kind()`])
591
  ///
592
  /// [`op_count()`]: #method.op_count
593
  /// [`try_set_op_kind()`]: #method.try_set_op_kind
594
  ///
595
  /// # Arguments
596
  ///
597
  /// * `new_value`: new value
598
  #[allow(clippy::unused_self)]
599
  #[inline]
600
0
  pub fn set_op4_kind(&mut self, new_value: OpKind) {
601
0
    debug_assert_eq!(new_value, OpKind::Immediate8);
602
0
  }
603
604
  #[allow(clippy::unused_self)]
605
  #[inline]
606
  #[doc(hidden)]
607
0
  pub fn try_set_op4_kind(&mut self, new_value: OpKind) -> Result<(), IcedError> {
608
0
    if new_value != OpKind::Immediate8 {
609
0
      Err(IcedError::new("Invalid opkind"))
610
    } else {
611
0
      Ok(())
612
    }
613
0
  }
614
615
  /// Gets all op kinds ([`op_count()`] values)
616
  ///
617
  /// [`op_count()`]: #method.op_count
618
  ///
619
  /// # Examples
620
  ///
621
  /// ```
622
  /// use iced_x86::*;
623
  ///
624
  /// // add [rax],ebx
625
  /// let bytes = b"\x01\x18";
626
  /// let mut decoder = Decoder::new(64, bytes, DecoderOptions::NONE);
627
  /// let instr = decoder.decode();
628
  ///
629
  /// for (i, op_kind) in instr.op_kinds().enumerate() {
630
  ///     println!("op kind #{} = {:?}", i, op_kind);
631
  /// }
632
  /// ```
633
  #[inline]
634
0
  pub fn op_kinds(&self) -> impl Iterator<Item = OpKind> + ExactSizeIterator + FusedIterator {
635
0
    OpKindIterator::new(self)
636
0
  }
637
638
  /// Gets an operand's kind if it exists (see [`op_count()`])
639
  ///
640
  /// [`op_count()`]: #method.op_count
641
  ///
642
  /// # Arguments
643
  ///
644
  /// * `operand`: Operand number, 0-4
645
  ///
646
  /// # Examples
647
  ///
648
  /// ```
649
  /// use iced_x86::*;
650
  ///
651
  /// // add [rax],ebx
652
  /// let bytes = b"\x01\x18";
653
  /// let mut decoder = Decoder::new(64, bytes, DecoderOptions::NONE);
654
  /// let instr = decoder.decode();
655
  ///
656
  /// assert_eq!(instr.op_count(), 2);
657
  /// assert_eq!(instr.op_kind(0), OpKind::Memory);
658
  /// assert_eq!(instr.memory_base(), Register::RAX);
659
  /// assert_eq!(instr.memory_index(), Register::None);
660
  /// assert_eq!(instr.op_kind(1), OpKind::Register);
661
  /// assert_eq!(instr.op_register(1), Register::EBX);
662
  /// ```
663
  #[must_use]
664
  #[inline]
665
0
  pub fn op_kind(&self, operand: u32) -> OpKind {
666
    const _: () = assert!(IcedConstants::MAX_OP_COUNT == 5);
667
0
    if let Some(&op_kind) = self.op_kinds.get(operand as usize) {
668
0
      op_kind
669
0
    } else if operand == 4 {
670
0
      self.op4_kind()
671
    } else {
672
0
      debug_assert!(false, "Invalid operand: {}", operand);
673
0
      OpKind::default()
674
    }
675
0
  }
676
677
  #[doc(hidden)]
678
  #[inline]
679
1.42k
  pub fn try_op_kind(&self, operand: u32) -> Result<OpKind, IcedError> {
680
    const _: () = assert!(IcedConstants::MAX_OP_COUNT == 5);
681
1.42k
    if let Some(&op_kind) = self.op_kinds.get(operand as usize) {
682
1.42k
      Ok(op_kind)
683
0
    } else if operand == 4 {
684
0
      Ok(self.op4_kind())
685
    } else {
686
0
      Err(IcedError::new("Invalid operand"))
687
    }
688
1.42k
  }
<iced_x86::instruction::Instruction>::try_op_kind
Line
Count
Source
679
1.42k
  pub fn try_op_kind(&self, operand: u32) -> Result<OpKind, IcedError> {
680
    const _: () = assert!(IcedConstants::MAX_OP_COUNT == 5);
681
1.42k
    if let Some(&op_kind) = self.op_kinds.get(operand as usize) {
682
1.42k
      Ok(op_kind)
683
0
    } else if operand == 4 {
684
0
      Ok(self.op4_kind())
685
    } else {
686
0
      Err(IcedError::new("Invalid operand"))
687
    }
688
1.42k
  }
Unexecuted instantiation: <iced_x86::instruction::Instruction>::try_op_kind
689
690
  /// Sets an operand's kind
691
  ///
692
  /// # Arguments
693
  ///
694
  /// * `operand`: Operand number, 0-4
695
  /// * `op_kind`: Operand kind
696
  #[inline]
697
0
  pub fn set_op_kind(&mut self, operand: u32, op_kind: OpKind) {
698
    const _: () = assert!(IcedConstants::MAX_OP_COUNT == 5);
699
0
    if let Some(field) = self.op_kinds.get_mut(operand as usize) {
700
0
      *field = op_kind;
701
0
    } else if operand == 4 {
702
0
      self.set_op4_kind(op_kind)
703
    } else {
704
0
      debug_assert!(false, "Invalid operand: {}", operand);
705
    }
706
0
  }
707
708
  #[doc(hidden)]
709
  #[inline]
710
0
  pub fn try_set_op_kind(&mut self, operand: u32, op_kind: OpKind) -> Result<(), IcedError> {
711
    const _: () = assert!(IcedConstants::MAX_OP_COUNT == 5);
712
0
    if let Some(field) = self.op_kinds.get_mut(operand as usize) {
713
0
      *field = op_kind;
714
0
      Ok(())
715
0
    } else if operand == 4 {
716
0
      self.try_set_op4_kind(op_kind)
717
    } else {
718
0
      Err(IcedError::new("Invalid operand"))
719
    }
720
0
  }
721
722
  /// Checks if the instruction has a segment override prefix, see [`segment_prefix()`]
723
  ///
724
  /// [`segment_prefix()`]: #method.segment_prefix
725
  #[must_use]
726
  #[inline]
727
0
  pub const fn has_segment_prefix(&self) -> bool {
728
0
    ((self.flags1 >> InstrFlags1::SEGMENT_PREFIX_SHIFT) & InstrFlags1::SEGMENT_PREFIX_MASK).wrapping_sub(1) < 6
729
0
  }
730
731
  /// Gets the segment override prefix or [`Register::None`] if none. See also [`memory_segment()`].
732
  /// Use this method if the operand has kind [`OpKind::Memory`],
733
  /// [`OpKind::MemorySegSI`], [`OpKind::MemorySegESI`], [`OpKind::MemorySegRSI`]
734
  ///
735
  /// [`Register::None`]: enum.Register.html#variant.None
736
  /// [`memory_segment()`]: #method.memory_segment
737
  /// [`OpKind::Memory`]: enum.OpKind.html#variant.Memory
738
  /// [`OpKind::MemorySegSI`]: enum.OpKind.html#variant.MemorySegSI
739
  /// [`OpKind::MemorySegESI`]: enum.OpKind.html#variant.MemorySegESI
740
  /// [`OpKind::MemorySegESI`]: enum.OpKind.html#variant.MemorySegESI
741
  /// [`OpKind::MemorySegRSI`]: enum.OpKind.html#variant.MemorySegRSI
742
  #[must_use]
743
  #[inline]
744
561
  pub fn segment_prefix(&self) -> Register {
745
561
    let index = ((self.flags1 >> InstrFlags1::SEGMENT_PREFIX_SHIFT) & InstrFlags1::SEGMENT_PREFIX_MASK).wrapping_sub(1);
746
    const _: () = assert!(Register::ES as u32 + 1 == Register::CS as u32);
747
    const _: () = assert!(Register::ES as u32 + 2 == Register::SS as u32);
748
    const _: () = assert!(Register::ES as u32 + 3 == Register::DS as u32);
749
    const _: () = assert!(Register::ES as u32 + 4 == Register::FS as u32);
750
    const _: () = assert!(Register::ES as u32 + 5 == Register::GS as u32);
751
561
    if index < 6 {
752
      // SAFETY: ES+index is a valid enum variant, see above const assert!()'s
753
41
      unsafe { mem::transmute((Register::ES as u32 + index) as RegisterUnderlyingType) }
754
    } else {
755
520
      Register::None
756
    }
757
561
  }
758
759
  /// Sets the segment override prefix or [`Register::None`] if none. See also [`memory_segment()`].
760
  /// Use this method if the operand has kind [`OpKind::Memory`],
761
  /// [`OpKind::MemorySegSI`], [`OpKind::MemorySegESI`], [`OpKind::MemorySegRSI`]
762
  ///
763
  /// [`Register::None`]: enum.Register.html#variant.None
764
  /// [`memory_segment()`]: #method.memory_segment
765
  /// [`OpKind::Memory`]: enum.OpKind.html#variant.Memory
766
  /// [`OpKind::MemorySegSI`]: enum.OpKind.html#variant.MemorySegSI
767
  /// [`OpKind::MemorySegESI`]: enum.OpKind.html#variant.MemorySegESI
768
  /// [`OpKind::MemorySegESI`]: enum.OpKind.html#variant.MemorySegESI
769
  /// [`OpKind::MemorySegRSI`]: enum.OpKind.html#variant.MemorySegRSI
770
  ///
771
  /// # Arguments
772
  ///
773
  /// * `new_value`: Segment register prefix
774
  #[allow(clippy::missing_inline_in_public_items)]
775
496
  pub fn set_segment_prefix(&mut self, new_value: Register) {
776
496
    debug_assert!(new_value == Register::None || (Register::ES <= new_value && new_value <= Register::GS));
777
496
    let enc_value =
778
496
      if new_value == Register::None { 0 } else { (((new_value as u32) - (Register::ES as u32)) + 1) & InstrFlags1::SEGMENT_PREFIX_MASK };
779
496
    self.flags1 = (self.flags1 & !(InstrFlags1::SEGMENT_PREFIX_MASK << InstrFlags1::SEGMENT_PREFIX_SHIFT))
780
496
      | (enc_value << InstrFlags1::SEGMENT_PREFIX_SHIFT);
781
496
  }
782
783
  /// Gets the effective segment register used to reference the memory location.
784
  /// Use this method if the operand has kind [`OpKind::Memory`],
785
  /// [`OpKind::MemorySegSI`], [`OpKind::MemorySegESI`], [`OpKind::MemorySegRSI`]
786
  ///
787
  /// [`OpKind::Memory`]: enum.OpKind.html#variant.Memory
788
  /// [`OpKind::MemorySegSI`]: enum.OpKind.html#variant.MemorySegSI
789
  /// [`OpKind::MemorySegESI`]: enum.OpKind.html#variant.MemorySegESI
790
  /// [`OpKind::MemorySegRSI`]: enum.OpKind.html#variant.MemorySegRSI
791
  #[must_use]
792
  #[allow(clippy::missing_inline_in_public_items)]
793
561
  pub fn memory_segment(&self) -> Register {
794
561
    let seg_reg = self.segment_prefix();
795
561
    if seg_reg != Register::None {
796
41
      return seg_reg;
797
520
    }
798
520
    match self.memory_base() {
799
30
      Register::BP | Register::EBP | Register::ESP | Register::RBP | Register::RSP => Register::SS,
800
490
      _ => Register::DS,
801
    }
802
561
  }
803
804
  /// Gets the size of the memory displacement in bytes. Valid values are `0`, `1` (16/32/64-bit), `2` (16-bit), `4` (32-bit), `8` (64-bit).
805
  /// Note that the return value can be 1 and [`memory_displacement64()`] may still not fit in
806
  /// a signed byte if it's an EVEX/MVEX encoded instruction.
807
  /// Use this method if the operand has kind [`OpKind::Memory`]
808
  ///
809
  /// [`memory_displacement64()`]: #method.memory_displacement64
810
  /// [`OpKind::Memory`]: enum.OpKind.html#variant.Memory
811
  #[must_use]
812
  #[inline]
813
0
  pub const fn memory_displ_size(&self) -> u32 {
814
0
    let size = self.displ_size as u32;
815
0
    if size <= 2 {
816
0
      size
817
0
    } else if size == 3 {
818
0
      4
819
    } else {
820
0
      8
821
    }
822
0
  }
823
824
  /// Sets the size of the memory displacement in bytes. Valid values are `0`, `1` (16/32/64-bit), `2` (16-bit), `4` (32-bit), `8` (64-bit).
825
  /// Note that the return value can be 1 and [`memory_displacement64()`] may still not fit in
826
  /// a signed byte if it's an EVEX/MVEX encoded instruction.
827
  /// Use this method if the operand has kind [`OpKind::Memory`]
828
  ///
829
  /// [`memory_displacement64()`]: #method.memory_displacement64
830
  /// [`OpKind::Memory`]: enum.OpKind.html#variant.Memory
831
  ///
832
  /// # Arguments
833
  ///
834
  /// * `new_value`: Displacement size
835
  #[allow(clippy::missing_inline_in_public_items)]
836
0
  pub fn set_memory_displ_size(&mut self, new_value: u32) {
837
0
    self.displ_size = match new_value {
838
0
      0 => 0,
839
0
      1 => 1,
840
0
      2 => 2,
841
0
      4 => 3,
842
0
      _ => 4,
843
    };
844
0
  }
845
846
  /// `true` if the data is broadcast (EVEX instructions only)
847
  #[must_use]
848
  #[inline]
849
0
  pub const fn is_broadcast(&self) -> bool {
850
0
    (self.flags1 & InstrFlags1::BROADCAST) != 0
851
0
  }
852
853
  /// Sets the is broadcast flag (EVEX instructions only)
854
  ///
855
  /// # Arguments
856
  ///
857
  /// * `new_value`: New value
858
  #[inline]
859
0
  pub fn set_is_broadcast(&mut self, new_value: bool) {
860
0
    if new_value {
861
0
      self.flags1 |= InstrFlags1::BROADCAST;
862
0
    } else {
863
0
      self.flags1 &= !InstrFlags1::BROADCAST;
864
0
    }
865
0
  }
866
867
  /// `true` if eviction hint bit is set (`{eh}`) (MVEX instructions only)
868
  #[must_use]
869
  #[inline]
870
  #[cfg(feature = "mvex")]
871
  pub const fn is_mvex_eviction_hint(&self) -> bool {
872
    IcedConstants::is_mvex(self.code()) && (self.immediate & MvexInstrFlags::EVICTION_HINT) != 0
873
  }
874
875
  /// `true` if eviction hint bit is set (`{eh}`) (MVEX instructions only)
876
  ///
877
  /// # Arguments
878
  ///
879
  /// * `new_value`: New value
880
  #[inline]
881
  #[cfg(feature = "mvex")]
882
  pub fn set_is_mvex_eviction_hint(&mut self, new_value: bool) {
883
    if new_value {
884
      self.immediate |= MvexInstrFlags::EVICTION_HINT;
885
    } else {
886
      self.immediate &= !MvexInstrFlags::EVICTION_HINT;
887
    }
888
  }
889
890
  /// (MVEX) Register/memory operand conversion function
891
  #[must_use]
892
  #[inline]
893
  #[cfg(feature = "mvex")]
894
  pub fn mvex_reg_mem_conv(&self) -> MvexRegMemConv {
895
    if !IcedConstants::is_mvex(self.code()) {
896
      MvexRegMemConv::None
897
    } else {
898
      <MvexRegMemConv as core::convert::TryFrom<_>>::try_from(
899
        ((self.immediate >> MvexInstrFlags::MVEX_REG_MEM_CONV_SHIFT) & MvexInstrFlags::MVEX_REG_MEM_CONV_MASK) as usize,
900
      )
901
      .ok()
902
      .unwrap_or_default()
903
    }
904
  }
905
906
  /// (MVEX) Register/memory operand conversion function
907
  ///
908
  /// # Arguments
909
  ///
910
  /// * `new_value`: New value
911
  #[inline]
912
  #[cfg(feature = "mvex")]
913
  pub fn set_mvex_reg_mem_conv(&mut self, new_value: MvexRegMemConv) {
914
    self.immediate = (self.immediate & !(MvexInstrFlags::MVEX_REG_MEM_CONV_MASK << MvexInstrFlags::MVEX_REG_MEM_CONV_SHIFT))
915
      | ((new_value as u32) << MvexInstrFlags::MVEX_REG_MEM_CONV_SHIFT);
916
  }
917
918
  /// Gets the size of the memory location that is referenced by the operand. See also [`is_broadcast()`].
919
  /// Use this method if the operand has kind [`OpKind::Memory`],
920
  /// [`OpKind::MemorySegSI`], [`OpKind::MemorySegESI`], [`OpKind::MemorySegRSI`],
921
  /// [`OpKind::MemoryESDI`], [`OpKind::MemoryESEDI`], [`OpKind::MemoryESRDI`]
922
  ///
923
  /// [`is_broadcast()`]: #method.is_broadcast
924
  /// [`OpKind::Memory`]: enum.OpKind.html#variant.Memory
925
  /// [`OpKind::MemorySegSI`]: enum.OpKind.html#variant.MemorySegSI
926
  /// [`OpKind::MemorySegESI`]: enum.OpKind.html#variant.MemorySegESI
927
  /// [`OpKind::MemorySegRSI`]: enum.OpKind.html#variant.MemorySegRSI
928
  /// [`OpKind::MemoryESDI`]: enum.OpKind.html#variant.MemoryESDI
929
  /// [`OpKind::MemoryESEDI`]: enum.OpKind.html#variant.MemoryESEDI
930
  /// [`OpKind::MemoryESRDI`]: enum.OpKind.html#variant.MemoryESRDI
931
  #[must_use]
932
  #[inline]
933
0
  pub fn memory_size(&self) -> MemorySize {
934
0
    let code = self.code();
935
    #[cfg(feature = "mvex")]
936
    {
937
      if IcedConstants::is_mvex(code) {
938
        let mvex = crate::mvex::get_mvex_info(code);
939
        const _: () = assert!(MvexRegMemConv::MemConvNone as u32 + 1 == MvexRegMemConv::MemConvBroadcast1 as u32);
940
        const _: () = assert!(MvexRegMemConv::MemConvNone as u32 + 2 == MvexRegMemConv::MemConvBroadcast4 as u32);
941
        const _: () = assert!(MvexRegMemConv::MemConvNone as u32 + 3 == MvexRegMemConv::MemConvFloat16 as u32);
942
        const _: () = assert!(MvexRegMemConv::MemConvNone as u32 + 4 == MvexRegMemConv::MemConvUint8 as u32);
943
        const _: () = assert!(MvexRegMemConv::MemConvNone as u32 + 5 == MvexRegMemConv::MemConvSint8 as u32);
944
        const _: () = assert!(MvexRegMemConv::MemConvNone as u32 + 6 == MvexRegMemConv::MemConvUint16 as u32);
945
        const _: () = assert!(MvexRegMemConv::MemConvNone as u32 + 7 == MvexRegMemConv::MemConvSint16 as u32);
946
        let sss = ((self.mvex_reg_mem_conv() as u32).wrapping_sub(MvexRegMemConv::MemConvNone as u32) & 7) as usize;
947
        return crate::mvex::mvex_memsz_lut::MVEX_MEMSZ_LUT[(mvex.tuple_type_lut_kind as usize) * 8 + sss];
948
      }
949
    }
950
0
    if !self.is_broadcast() {
951
0
      instruction_memory_sizes::SIZES_NORMAL[code as usize]
952
    } else {
953
0
      instruction_memory_sizes::SIZES_BCST[code as usize]
954
    }
955
0
  }
956
957
  /// Gets the index register scale value, valid values are `*1`, `*2`, `*4`, `*8`. Use this method if the operand has kind [`OpKind::Memory`]
958
  ///
959
  /// [`OpKind::Memory`]: enum.OpKind.html#variant.Memory
960
  #[must_use]
961
  #[inline]
962
148
  pub const fn memory_index_scale(&self) -> u32 {
963
148
    1 << (self.scale as u8)
964
148
  }
<iced_x86::instruction::Instruction>::memory_index_scale
Line
Count
Source
962
148
  pub const fn memory_index_scale(&self) -> u32 {
963
148
    1 << (self.scale as u8)
964
148
  }
Unexecuted instantiation: <iced_x86::instruction::Instruction>::memory_index_scale
965
966
  /// Sets the index register scale value, valid values are `*1`, `*2`, `*4`, `*8`. Use this method if the operand has kind [`OpKind::Memory`]
967
  ///
968
  /// [`OpKind::Memory`]: enum.OpKind.html#variant.Memory
969
  ///
970
  /// # Arguments
971
  ///
972
  /// * `new_value`: New value (1, 2, 4 or 8)
973
  #[allow(clippy::missing_inline_in_public_items)]
974
0
  pub fn set_memory_index_scale(&mut self, new_value: u32) {
975
0
    match new_value {
976
0
      1 => self.scale = InstrScale::Scale1,
977
0
      2 => self.scale = InstrScale::Scale2,
978
0
      4 => self.scale = InstrScale::Scale4,
979
      _ => {
980
0
        debug_assert_eq!(new_value, 8);
981
0
        self.scale = InstrScale::Scale8;
982
      }
983
    }
984
0
  }
985
986
  /// Gets the memory operand's displacement or the 32-bit absolute address if it's
987
  /// an `EIP` or `RIP` relative memory operand.
988
  /// Use this method if the operand has kind [`OpKind::Memory`]
989
  ///
990
  /// [`OpKind::Memory`]: enum.OpKind.html#variant.Memory
991
  #[must_use]
992
  #[inline]
993
0
  pub const fn memory_displacement32(&self) -> u32 {
994
0
    self.mem_displ as u32
995
0
  }
996
997
  /// Gets the memory operand's displacement or the 32-bit absolute address if it's
998
  /// an `EIP` or `RIP` relative memory operand.
999
  /// Use this method if the operand has kind [`OpKind::Memory`]
1000
  ///
1001
  /// [`OpKind::Memory`]: enum.OpKind.html#variant.Memory
1002
  ///
1003
  /// # Arguments
1004
  ///
1005
  /// * `new_value`: New value
1006
  #[inline]
1007
0
  pub fn set_memory_displacement32(&mut self, new_value: u32) {
1008
0
    self.mem_displ = new_value as u64;
1009
0
  }
1010
1011
  /// Gets the memory operand's displacement or the 64-bit absolute address if it's
1012
  /// an `EIP` or `RIP` relative memory operand.
1013
  /// Use this method if the operand has kind [`OpKind::Memory`]
1014
  ///
1015
  /// [`OpKind::Memory`]: enum.OpKind.html#variant.Memory
1016
  #[must_use]
1017
  #[inline]
1018
846
  pub const fn memory_displacement64(&self) -> u64 {
1019
846
    self.mem_displ
1020
846
  }
<iced_x86::instruction::Instruction>::memory_displacement64
Line
Count
Source
1018
561
  pub const fn memory_displacement64(&self) -> u64 {
1019
561
    self.mem_displ
1020
561
  }
<iced_x86::instruction::Instruction>::memory_displacement64
Line
Count
Source
1018
285
  pub const fn memory_displacement64(&self) -> u64 {
1019
285
    self.mem_displ
1020
285
  }
1021
1022
  /// Gets the memory operand's displacement or the 64-bit absolute address if it's
1023
  /// an `EIP` or `RIP` relative memory operand.
1024
  /// Use this method if the operand has kind [`OpKind::Memory`]
1025
  ///
1026
  /// [`OpKind::Memory`]: enum.OpKind.html#variant.Memory
1027
  ///
1028
  /// # Arguments
1029
  ///
1030
  /// * `new_value`: New value
1031
  #[inline]
1032
1.00k
  pub fn set_memory_displacement64(&mut self, new_value: u64) {
1033
1.00k
    self.mem_displ = new_value;
1034
1.00k
  }
1035
1036
  /// Tries to get an operand's immediate value.
1037
  /// Can only be called if the operand has kind [`OpKind::Immediate8`],
1038
  /// [`OpKind::Immediate8_2nd`], [`OpKind::Immediate16`], [`OpKind::Immediate32`],
1039
  /// [`OpKind::Immediate64`], [`OpKind::Immediate8to16`], [`OpKind::Immediate8to32`],
1040
  /// [`OpKind::Immediate8to64`], [`OpKind::Immediate32to64`]
1041
  ///
1042
  /// # Errors
1043
  ///
1044
  /// - Fails if the operand is not one of those listed above
1045
  ///
1046
  /// # Arguments
1047
  ///
1048
  /// * `operand`: Operand number, 0-4
1049
  #[allow(clippy::missing_inline_in_public_items)]
1050
0
  pub fn try_immediate(&self, operand: u32) -> Result<u64, IcedError> {
1051
0
    Ok(match self.try_op_kind(operand)? {
1052
0
      OpKind::Immediate8 => self.immediate8() as u64,
1053
0
      OpKind::Immediate8_2nd => self.immediate8_2nd() as u64,
1054
0
      OpKind::Immediate16 => self.immediate16() as u64,
1055
0
      OpKind::Immediate32 => self.immediate32() as u64,
1056
0
      OpKind::Immediate64 => self.immediate64(),
1057
0
      OpKind::Immediate8to16 => self.immediate8to16() as u64,
1058
0
      OpKind::Immediate8to32 => self.immediate8to32() as u64,
1059
0
      OpKind::Immediate8to64 => self.immediate8to64() as u64,
1060
0
      OpKind::Immediate32to64 => self.immediate32to64() as u64,
1061
0
      _ => return Err(IcedError::new("Not an immediate operand")),
1062
    })
1063
0
  }
1064
1065
  /// Gets an operand's immediate value
1066
  ///
1067
  /// # Arguments
1068
  ///
1069
  /// * `operand`: Operand number, 0-4
1070
  #[must_use]
1071
  #[inline]
1072
0
  pub fn immediate(&self, operand: u32) -> u64 {
1073
0
    match self.try_immediate(operand) {
1074
0
      Ok(value) => value,
1075
      Err(_) => {
1076
0
        debug_assert!(false, "Invalid operand: {}", operand);
1077
0
        0
1078
      }
1079
    }
1080
0
  }
1081
1082
  /// Sets an operand's immediate value
1083
  ///
1084
  /// # Arguments
1085
  ///
1086
  /// * `operand`: Operand number, 0-4
1087
  /// * `new_value`: Immediate
1088
  #[inline]
1089
0
  pub fn set_immediate_i32(&mut self, operand: u32, new_value: i32) {
1090
0
    match self.try_set_immediate_i32(operand, new_value) {
1091
0
      Ok(()) => {}
1092
0
      Err(_) => debug_assert!(false, "Invalid operand: {}", operand),
1093
    }
1094
0
  }
1095
1096
  #[inline]
1097
  #[doc(hidden)]
1098
0
  pub fn try_set_immediate_i32(&mut self, operand: u32, new_value: i32) -> Result<(), IcedError> {
1099
0
    self.try_set_immediate_u64(operand, new_value as u64)
1100
0
  }
1101
1102
  /// Sets an operand's immediate value
1103
  ///
1104
  /// # Arguments
1105
  ///
1106
  /// * `operand`: Operand number, 0-4
1107
  /// * `new_value`: Immediate
1108
  #[inline]
1109
0
  pub fn set_immediate_u32(&mut self, operand: u32, new_value: u32) {
1110
0
    match self.try_set_immediate_u32(operand, new_value) {
1111
0
      Ok(()) => {}
1112
0
      Err(_) => debug_assert!(false, "Invalid operand: {}", operand),
1113
    }
1114
0
  }
1115
1116
  #[inline]
1117
  #[doc(hidden)]
1118
0
  pub fn try_set_immediate_u32(&mut self, operand: u32, new_value: u32) -> Result<(), IcedError> {
1119
0
    self.try_set_immediate_u64(operand, new_value as u64)
1120
0
  }
1121
1122
  /// Sets an operand's immediate value
1123
  ///
1124
  /// # Arguments
1125
  ///
1126
  /// * `operand`: Operand number, 0-4
1127
  /// * `new_value`: Immediate
1128
  #[inline]
1129
0
  pub fn set_immediate_i64(&mut self, operand: u32, new_value: i64) {
1130
0
    match self.try_set_immediate_i64(operand, new_value) {
1131
0
      Ok(()) => {}
1132
0
      Err(_) => debug_assert!(false, "Invalid operand: {}", operand),
1133
    }
1134
0
  }
1135
1136
  #[inline]
1137
  #[doc(hidden)]
1138
0
  pub fn try_set_immediate_i64(&mut self, operand: u32, new_value: i64) -> Result<(), IcedError> {
1139
0
    self.try_set_immediate_u64(operand, new_value as u64)
1140
0
  }
1141
1142
  /// Sets an operand's immediate value
1143
  ///
1144
  /// # Arguments
1145
  ///
1146
  /// * `operand`: Operand number, 0-4
1147
  /// * `new_value`: Immediate
1148
  #[inline]
1149
0
  pub fn set_immediate_u64(&mut self, operand: u32, new_value: u64) {
1150
0
    match self.try_set_immediate_u64(operand, new_value) {
1151
0
      Ok(()) => {}
1152
0
      Err(_) => debug_assert!(false, "Invalid operand: {}", operand),
1153
    }
1154
0
  }
1155
1156
  #[allow(clippy::missing_inline_in_public_items)]
1157
  #[doc(hidden)]
1158
0
  pub fn try_set_immediate_u64(&mut self, operand: u32, new_value: u64) -> Result<(), IcedError> {
1159
0
    match self.try_op_kind(operand)? {
1160
0
      OpKind::Immediate8 => self.set_immediate8(new_value as u8),
1161
0
      OpKind::Immediate8to16 => self.set_immediate8to16(new_value as i16),
1162
0
      OpKind::Immediate8to32 => self.set_immediate8to32(new_value as i32),
1163
0
      OpKind::Immediate8to64 => self.set_immediate8to64(new_value as i64),
1164
0
      OpKind::Immediate8_2nd => self.set_immediate8_2nd(new_value as u8),
1165
0
      OpKind::Immediate16 => self.set_immediate16(new_value as u16),
1166
0
      OpKind::Immediate32to64 => self.set_immediate32to64(new_value as i64),
1167
0
      OpKind::Immediate32 => self.set_immediate32(new_value as u32),
1168
0
      OpKind::Immediate64 => self.set_immediate64(new_value),
1169
0
      _ => return Err(IcedError::new("Not an immediate operand")),
1170
    }
1171
0
    Ok(())
1172
0
  }
1173
1174
  /// Gets the operand's immediate value. Use this method if the operand has kind [`OpKind::Immediate8`]
1175
  ///
1176
  /// [`OpKind::Immediate8`]: enum.OpKind.html#variant.Immediate8
1177
  #[must_use]
1178
  #[inline]
1179
62
  pub const fn immediate8(&self) -> u8 {
1180
62
    self.immediate as u8
1181
62
  }
<iced_x86::instruction::Instruction>::immediate8
Line
Count
Source
1179
62
  pub const fn immediate8(&self) -> u8 {
1180
62
    self.immediate as u8
1181
62
  }
Unexecuted instantiation: <iced_x86::instruction::Instruction>::immediate8
1182
1183
  /// Sets the operand's immediate value. Use this method if the operand has kind [`OpKind::Immediate8`]
1184
  ///
1185
  /// [`OpKind::Immediate8`]: enum.OpKind.html#variant.Immediate8
1186
  ///
1187
  /// # Arguments
1188
  ///
1189
  /// * `new_value`: New value
1190
  #[inline]
1191
0
  pub fn set_immediate8(&mut self, new_value: u8) {
1192
    #[cfg(feature = "mvex")]
1193
    {
1194
      self.immediate = (self.immediate & 0xFFFF_FF00) | (new_value as u32);
1195
    }
1196
    #[cfg(not(feature = "mvex"))]
1197
0
    {
1198
0
      self.immediate = new_value as u32;
1199
0
    }
1200
0
  }
1201
1202
  /// Gets the operand's immediate value. Use this method if the operand has kind [`OpKind::Immediate8_2nd`]
1203
  ///
1204
  /// [`OpKind::Immediate8_2nd`]: enum.OpKind.html#variant.Immediate8_2nd
1205
  #[must_use]
1206
  #[inline]
1207
0
  pub const fn immediate8_2nd(&self) -> u8 {
1208
0
    self.mem_displ as u8
1209
0
  }
1210
1211
  /// Sets the operand's immediate value. Use this method if the operand has kind [`OpKind::Immediate8_2nd`]
1212
  ///
1213
  /// [`OpKind::Immediate8_2nd`]: enum.OpKind.html#variant.Immediate8_2nd
1214
  ///
1215
  /// # Arguments
1216
  ///
1217
  /// * `new_value`: New value
1218
  #[inline]
1219
0
  pub fn set_immediate8_2nd(&mut self, new_value: u8) {
1220
0
    self.mem_displ = new_value as u64;
1221
0
  }
1222
1223
  /// Gets the operand's immediate value. Use this method if the operand has kind [`OpKind::Immediate16`]
1224
  ///
1225
  /// [`OpKind::Immediate16`]: enum.OpKind.html#variant.Immediate16
1226
  #[must_use]
1227
  #[inline]
1228
21
  pub const fn immediate16(&self) -> u16 {
1229
21
    self.immediate as u16
1230
21
  }
<iced_x86::instruction::Instruction>::immediate16
Line
Count
Source
1228
21
  pub const fn immediate16(&self) -> u16 {
1229
21
    self.immediate as u16
1230
21
  }
Unexecuted instantiation: <iced_x86::instruction::Instruction>::immediate16
1231
1232
  /// Sets the operand's immediate value. Use this method if the operand has kind [`OpKind::Immediate16`]
1233
  ///
1234
  /// [`OpKind::Immediate16`]: enum.OpKind.html#variant.Immediate16
1235
  ///
1236
  /// # Arguments
1237
  ///
1238
  /// * `new_value`: New value
1239
  #[inline]
1240
0
  pub fn set_immediate16(&mut self, new_value: u16) {
1241
0
    self.immediate = new_value as u32;
1242
0
  }
1243
1244
  /// Gets the operand's immediate value. Use this method if the operand has kind [`OpKind::Immediate32`]
1245
  ///
1246
  /// [`OpKind::Immediate32`]: enum.OpKind.html#variant.Immediate32
1247
  #[must_use]
1248
  #[inline]
1249
43
  pub const fn immediate32(&self) -> u32 {
1250
43
    self.immediate
1251
43
  }
<iced_x86::instruction::Instruction>::immediate32
Line
Count
Source
1249
43
  pub const fn immediate32(&self) -> u32 {
1250
43
    self.immediate
1251
43
  }
Unexecuted instantiation: <iced_x86::instruction::Instruction>::immediate32
1252
1253
  /// Sets the operand's immediate value. Use this method if the operand has kind [`OpKind::Immediate32`]
1254
  ///
1255
  /// [`OpKind::Immediate32`]: enum.OpKind.html#variant.Immediate32
1256
  ///
1257
  /// # Arguments
1258
  ///
1259
  /// * `new_value`: New value
1260
  #[inline]
1261
111
  pub fn set_immediate32(&mut self, new_value: u32) {
1262
111
    self.immediate = new_value;
1263
111
  }
1264
1265
  /// Gets the operand's immediate value. Use this method if the operand has kind [`OpKind::Immediate64`]
1266
  ///
1267
  /// [`OpKind::Immediate64`]: enum.OpKind.html#variant.Immediate64
1268
  #[must_use]
1269
  #[inline]
1270
14
  pub const fn immediate64(&self) -> u64 {
1271
14
    (self.mem_displ << 32) | (self.immediate as u64)
1272
14
  }
<iced_x86::instruction::Instruction>::immediate64
Line
Count
Source
1270
14
  pub const fn immediate64(&self) -> u64 {
1271
14
    (self.mem_displ << 32) | (self.immediate as u64)
1272
14
  }
Unexecuted instantiation: <iced_x86::instruction::Instruction>::immediate64
1273
1274
  /// Sets the operand's immediate value. Use this method if the operand has kind [`OpKind::Immediate64`]
1275
  ///
1276
  /// [`OpKind::Immediate64`]: enum.OpKind.html#variant.Immediate64
1277
  ///
1278
  /// # Arguments
1279
  ///
1280
  /// * `new_value`: New value
1281
  #[inline]
1282
0
  pub fn set_immediate64(&mut self, new_value: u64) {
1283
0
    self.immediate = new_value as u32;
1284
0
    self.mem_displ = new_value >> 32;
1285
0
  }
1286
1287
  /// Gets the operand's immediate value. Use this method if the operand has kind [`OpKind::Immediate8to16`]
1288
  ///
1289
  /// [`OpKind::Immediate8to16`]: enum.OpKind.html#variant.Immediate8to16
1290
  #[must_use]
1291
  #[inline]
1292
0
  pub const fn immediate8to16(&self) -> i16 {
1293
0
    self.immediate as i8 as i16
1294
0
  }
Unexecuted instantiation: <iced_x86::instruction::Instruction>::immediate8to16
Unexecuted instantiation: <iced_x86::instruction::Instruction>::immediate8to16
1295
1296
  /// Sets the operand's immediate value. Use this method if the operand has kind [`OpKind::Immediate8to16`]
1297
  ///
1298
  /// [`OpKind::Immediate8to16`]: enum.OpKind.html#variant.Immediate8to16
1299
  ///
1300
  /// # Arguments
1301
  ///
1302
  /// * `new_value`: New value
1303
  #[inline]
1304
0
  pub fn set_immediate8to16(&mut self, new_value: i16) {
1305
0
    self.immediate = new_value as i8 as u32;
1306
0
  }
1307
1308
  /// Gets the operand's immediate value. Use this method if the operand has kind [`OpKind::Immediate8to32`]
1309
  ///
1310
  /// [`OpKind::Immediate8to32`]: enum.OpKind.html#variant.Immediate8to32
1311
  #[must_use]
1312
  #[inline]
1313
32
  pub const fn immediate8to32(&self) -> i32 {
1314
32
    self.immediate as i8 as i32
1315
32
  }
<iced_x86::instruction::Instruction>::immediate8to32
Line
Count
Source
1313
32
  pub const fn immediate8to32(&self) -> i32 {
1314
32
    self.immediate as i8 as i32
1315
32
  }
Unexecuted instantiation: <iced_x86::instruction::Instruction>::immediate8to32
1316
1317
  /// Sets the operand's immediate value. Use this method if the operand has kind [`OpKind::Immediate8to32`]
1318
  ///
1319
  /// [`OpKind::Immediate8to32`]: enum.OpKind.html#variant.Immediate8to32
1320
  ///
1321
  /// # Arguments
1322
  ///
1323
  /// * `new_value`: New value
1324
  #[inline]
1325
0
  pub fn set_immediate8to32(&mut self, new_value: i32) {
1326
0
    self.immediate = new_value as i8 as u32;
1327
0
  }
1328
1329
  /// Gets the operand's immediate value. Use this method if the operand has kind [`OpKind::Immediate8to64`]
1330
  ///
1331
  /// [`OpKind::Immediate8to64`]: enum.OpKind.html#variant.Immediate8to64
1332
  #[must_use]
1333
  #[inline]
1334
0
  pub const fn immediate8to64(&self) -> i64 {
1335
0
    self.immediate as i8 as i64
1336
0
  }
Unexecuted instantiation: <iced_x86::instruction::Instruction>::immediate8to64
Unexecuted instantiation: <iced_x86::instruction::Instruction>::immediate8to64
1337
1338
  /// Sets the operand's immediate value. Use this method if the operand has kind [`OpKind::Immediate8to64`]
1339
  ///
1340
  /// [`OpKind::Immediate8to64`]: enum.OpKind.html#variant.Immediate8to64
1341
  ///
1342
  /// # Arguments
1343
  ///
1344
  /// * `new_value`: New value
1345
  #[inline]
1346
0
  pub fn set_immediate8to64(&mut self, new_value: i64) {
1347
0
    self.immediate = new_value as i8 as u32;
1348
0
  }
1349
1350
  /// Gets the operand's immediate value. Use this method if the operand has kind [`OpKind::Immediate32to64`]
1351
  ///
1352
  /// [`OpKind::Immediate32to64`]: enum.OpKind.html#variant.Immediate32to64
1353
  #[must_use]
1354
  #[inline]
1355
2
  pub const fn immediate32to64(&self) -> i64 {
1356
2
    self.immediate as i32 as i64
1357
2
  }
<iced_x86::instruction::Instruction>::immediate32to64
Line
Count
Source
1355
2
  pub const fn immediate32to64(&self) -> i64 {
1356
2
    self.immediate as i32 as i64
1357
2
  }
Unexecuted instantiation: <iced_x86::instruction::Instruction>::immediate32to64
1358
1359
  /// Sets the operand's immediate value. Use this method if the operand has kind [`OpKind::Immediate32to64`]
1360
  ///
1361
  /// [`OpKind::Immediate32to64`]: enum.OpKind.html#variant.Immediate32to64
1362
  ///
1363
  /// # Arguments
1364
  ///
1365
  /// * `new_value`: New value
1366
  #[inline]
1367
0
  pub fn set_immediate32to64(&mut self, new_value: i64) {
1368
0
    self.immediate = new_value as u32;
1369
0
  }
1370
1371
  /// Gets the operand's branch target. Use this method if the operand has kind [`OpKind::NearBranch16`]
1372
  ///
1373
  /// [`OpKind::NearBranch16`]: enum.OpKind.html#variant.NearBranch16
1374
  #[must_use]
1375
  #[inline]
1376
0
  pub const fn near_branch16(&self) -> u16 {
1377
0
    self.mem_displ as u16
1378
0
  }
1379
1380
  /// Sets the operand's branch target. Use this method if the operand has kind [`OpKind::NearBranch16`]
1381
  ///
1382
  /// [`OpKind::NearBranch16`]: enum.OpKind.html#variant.NearBranch16
1383
  ///
1384
  /// # Arguments
1385
  ///
1386
  /// * `new_value`: New value
1387
  #[inline]
1388
0
  pub fn set_near_branch16(&mut self, new_value: u16) {
1389
0
    self.mem_displ = new_value as u64;
1390
0
  }
1391
1392
  /// Gets the operand's branch target. Use this method if the operand has kind [`OpKind::NearBranch32`]
1393
  ///
1394
  /// [`OpKind::NearBranch32`]: enum.OpKind.html#variant.NearBranch32
1395
  #[must_use]
1396
  #[inline]
1397
0
  pub const fn near_branch32(&self) -> u32 {
1398
0
    self.mem_displ as u32
1399
0
  }
1400
1401
  /// Sets the operand's branch target. Use this method if the operand has kind [`OpKind::NearBranch32`]
1402
  ///
1403
  /// [`OpKind::NearBranch32`]: enum.OpKind.html#variant.NearBranch32
1404
  ///
1405
  /// # Arguments
1406
  ///
1407
  /// * `new_value`: New value
1408
  #[inline]
1409
0
  pub fn set_near_branch32(&mut self, new_value: u32) {
1410
0
    self.mem_displ = new_value as u64;
1411
0
  }
1412
1413
  /// Gets the operand's branch target. Use this method if the operand has kind [`OpKind::NearBranch64`]
1414
  ///
1415
  /// [`OpKind::NearBranch64`]: enum.OpKind.html#variant.NearBranch64
1416
  #[must_use]
1417
  #[inline]
1418
0
  pub const fn near_branch64(&self) -> u64 {
1419
0
    self.mem_displ
1420
0
  }
1421
1422
  /// Sets the operand's branch target. Use this method if the operand has kind [`OpKind::NearBranch64`]
1423
  ///
1424
  /// [`OpKind::NearBranch64`]: enum.OpKind.html#variant.NearBranch64
1425
  ///
1426
  /// # Arguments
1427
  ///
1428
  /// * `new_value`: New value
1429
  #[inline]
1430
28
  pub fn set_near_branch64(&mut self, new_value: u64) {
1431
28
    self.mem_displ = new_value
1432
28
  }
1433
1434
  /// Gets the near branch target if it's a `CALL`/`JMP`/`Jcc` near branch instruction
1435
  /// (i.e., if [`op0_kind()`] is [`OpKind::NearBranch16`], [`OpKind::NearBranch32`] or [`OpKind::NearBranch64`])
1436
  ///
1437
  /// [`op0_kind()`]: #method.op0_kind
1438
  /// [`OpKind::NearBranch16`]: enum.OpKind.html#variant.NearBranch16
1439
  /// [`OpKind::NearBranch32`]: enum.OpKind.html#variant.NearBranch32
1440
  /// [`OpKind::NearBranch64`]: enum.OpKind.html#variant.NearBranch64
1441
  #[must_use]
1442
  #[allow(clippy::missing_inline_in_public_items)]
1443
  #[allow(unused_mut)]
1444
0
  pub fn near_branch_target(&self) -> u64 {
1445
0
    let mut op_kind = self.op0_kind();
1446
    #[cfg(feature = "mvex")]
1447
    {
1448
      // Check if JKZD/JKNZD
1449
      if self.op_count() == 2 {
1450
        op_kind = self.op1_kind();
1451
      }
1452
    }
1453
0
    match op_kind {
1454
0
      OpKind::NearBranch16 => self.near_branch16() as u64,
1455
0
      OpKind::NearBranch32 => self.near_branch32() as u64,
1456
0
      OpKind::NearBranch64 => self.near_branch64(),
1457
0
      _ => 0,
1458
    }
1459
0
  }
1460
1461
  /// Gets the operand's branch target. Use this method if the operand has kind [`OpKind::FarBranch16`]
1462
  ///
1463
  /// [`OpKind::FarBranch16`]: enum.OpKind.html#variant.FarBranch16
1464
  #[must_use]
1465
  #[inline]
1466
0
  pub const fn far_branch16(&self) -> u16 {
1467
0
    self.immediate as u16
1468
0
  }
1469
1470
  /// Sets the operand's branch target. Use this method if the operand has kind [`OpKind::FarBranch16`]
1471
  ///
1472
  /// [`OpKind::FarBranch16`]: enum.OpKind.html#variant.FarBranch16
1473
  ///
1474
  /// # Arguments
1475
  ///
1476
  /// * `new_value`: New value
1477
  #[inline]
1478
0
  pub fn set_far_branch16(&mut self, new_value: u16) {
1479
0
    self.immediate = new_value as u32;
1480
0
  }
1481
1482
  /// Gets the operand's branch target. Use this method if the operand has kind [`OpKind::FarBranch32`]
1483
  ///
1484
  /// [`OpKind::FarBranch32`]: enum.OpKind.html#variant.FarBranch32
1485
  #[must_use]
1486
  #[inline]
1487
0
  pub const fn far_branch32(&self) -> u32 {
1488
0
    self.immediate
1489
0
  }
1490
1491
  /// Sets the operand's branch target. Use this method if the operand has kind [`OpKind::FarBranch32`]
1492
  ///
1493
  /// [`OpKind::FarBranch32`]: enum.OpKind.html#variant.FarBranch32
1494
  ///
1495
  /// # Arguments
1496
  ///
1497
  /// * `new_value`: New value
1498
  #[inline]
1499
0
  pub fn set_far_branch32(&mut self, new_value: u32) {
1500
0
    self.immediate = new_value;
1501
0
  }
1502
1503
  /// Gets the operand's branch target selector. Use this method if the operand has kind [`OpKind::FarBranch16`] or [`OpKind::FarBranch32`]
1504
  ///
1505
  /// [`OpKind::FarBranch16`]: enum.OpKind.html#variant.FarBranch16
1506
  /// [`OpKind::FarBranch32`]: enum.OpKind.html#variant.FarBranch32
1507
  #[must_use]
1508
  #[inline]
1509
0
  pub const fn far_branch_selector(&self) -> u16 {
1510
0
    self.mem_displ as u16
1511
0
  }
1512
1513
  /// Sets the operand's branch target selector. Use this method if the operand has kind [`OpKind::FarBranch16`] or [`OpKind::FarBranch32`]
1514
  ///
1515
  /// [`OpKind::FarBranch16`]: enum.OpKind.html#variant.FarBranch16
1516
  /// [`OpKind::FarBranch32`]: enum.OpKind.html#variant.FarBranch32
1517
  ///
1518
  /// # Arguments
1519
  ///
1520
  /// * `new_value`: New value
1521
  #[inline]
1522
0
  pub fn set_far_branch_selector(&mut self, new_value: u16) {
1523
0
    self.mem_displ = new_value as u64;
1524
0
  }
1525
1526
  /// Gets the memory operand's base register or [`Register::None`] if none. Use this method if the operand has kind [`OpKind::Memory`]
1527
  ///
1528
  /// [`Register::None`]: enum.Register.html#variant.None
1529
  /// [`OpKind::Memory`]: enum.OpKind.html#variant.Memory
1530
  #[must_use]
1531
  #[inline]
1532
1.63k
  pub const fn memory_base(&self) -> Register {
1533
1.63k
    self.mem_base_reg
1534
1.63k
  }
<iced_x86::instruction::Instruction>::memory_base
Line
Count
Source
1532
1.11k
  pub const fn memory_base(&self) -> Register {
1533
1.11k
    self.mem_base_reg
1534
1.11k
  }
<iced_x86::instruction::Instruction>::memory_base
Line
Count
Source
1532
520
  pub const fn memory_base(&self) -> Register {
1533
520
    self.mem_base_reg
1534
520
  }
1535
1536
  /// Sets the memory operand's base register or [`Register::None`] if none. Use this method if the operand has kind [`OpKind::Memory`]
1537
  ///
1538
  /// [`Register::None`]: enum.Register.html#variant.None
1539
  /// [`OpKind::Memory`]: enum.OpKind.html#variant.Memory
1540
  ///
1541
  /// # Arguments
1542
  ///
1543
  /// * `new_value`: New value
1544
  #[inline]
1545
976
  pub fn set_memory_base(&mut self, new_value: Register) {
1546
976
    self.mem_base_reg = new_value;
1547
976
  }
1548
1549
  /// Gets the memory operand's index register or [`Register::None`] if none. Use this method if the operand has kind [`OpKind::Memory`]
1550
  ///
1551
  /// [`Register::None`]: enum.Register.html#variant.None
1552
  /// [`OpKind::Memory`]: enum.OpKind.html#variant.Memory
1553
  #[must_use]
1554
  #[inline]
1555
709
  pub const fn memory_index(&self) -> Register {
1556
709
    self.mem_index_reg
1557
709
  }
<iced_x86::instruction::Instruction>::memory_index
Line
Count
Source
1555
709
  pub const fn memory_index(&self) -> Register {
1556
709
    self.mem_index_reg
1557
709
  }
Unexecuted instantiation: <iced_x86::instruction::Instruction>::memory_index
1558
1559
  /// Sets the memory operand's index register or [`Register::None`] if none. Use this method if the operand has kind [`OpKind::Memory`]
1560
  ///
1561
  /// [`Register::None`]: enum.Register.html#variant.None
1562
  /// [`OpKind::Memory`]: enum.OpKind.html#variant.Memory
1563
  ///
1564
  /// # Arguments
1565
  ///
1566
  /// * `new_value`: New value
1567
  #[inline]
1568
174
  pub fn set_memory_index(&mut self, new_value: Register) {
1569
174
    self.mem_index_reg = new_value;
1570
174
  }
1571
1572
  /// Gets operand #0's register value. Use this method if operand #0 ([`op0_kind()`]) has kind [`OpKind::Register`], see [`op_count()`] and [`try_op_register()`]
1573
  ///
1574
  /// [`op0_kind()`]: #method.op0_kind
1575
  /// [`op_count()`]: #method.op_count
1576
  /// [`try_op_register()`]: #method.try_op_register
1577
  /// [`Register::None`]: enum.Register.html#variant.None
1578
  /// [`OpKind::Register`]: enum.OpKind.html#variant.Register
1579
  #[must_use]
1580
  #[inline]
1581
0
  pub const fn op0_register(&self) -> Register {
1582
0
    self.regs[0]
1583
0
  }
1584
1585
  /// Sets operand #0's register value. Use this method if operand #0 ([`op0_kind()`]) has kind [`OpKind::Register`], see [`op_count()`] and [`try_op_register()`]
1586
  ///
1587
  /// [`op0_kind()`]: #method.op0_kind
1588
  /// [`op_count()`]: #method.op_count
1589
  /// [`try_op_register()`]: #method.try_op_register
1590
  /// [`Register::None`]: enum.Register.html#variant.None
1591
  /// [`OpKind::Register`]: enum.OpKind.html#variant.Register
1592
  ///
1593
  /// # Arguments
1594
  ///
1595
  /// * `new_value`: New value
1596
  #[inline]
1597
641
  pub fn set_op0_register(&mut self, new_value: Register) {
1598
641
    self.regs[0] = new_value;
1599
641
  }
1600
1601
  /// Gets operand #1's register value. Use this method if operand #1 ([`op0_kind()`]) has kind [`OpKind::Register`], see [`op_count()`] and [`try_op_register()`]
1602
  ///
1603
  /// [`op0_kind()`]: #method.op0_kind
1604
  /// [`op_count()`]: #method.op_count
1605
  /// [`try_op_register()`]: #method.try_op_register
1606
  /// [`Register::None`]: enum.Register.html#variant.None
1607
  /// [`OpKind::Register`]: enum.OpKind.html#variant.Register
1608
  #[must_use]
1609
  #[inline]
1610
0
  pub const fn op1_register(&self) -> Register {
1611
0
    self.regs[1]
1612
0
  }
1613
1614
  /// Sets operand #1's register value. Use this method if operand #1 ([`op0_kind()`]) has kind [`OpKind::Register`], see [`op_count()`] and [`try_op_register()`]
1615
  ///
1616
  /// [`op0_kind()`]: #method.op0_kind
1617
  /// [`op_count()`]: #method.op_count
1618
  /// [`try_op_register()`]: #method.try_op_register
1619
  /// [`Register::None`]: enum.Register.html#variant.None
1620
  /// [`OpKind::Register`]: enum.OpKind.html#variant.Register
1621
  ///
1622
  /// # Arguments
1623
  ///
1624
  /// * `new_value`: New value
1625
  #[inline]
1626
953
  pub fn set_op1_register(&mut self, new_value: Register) {
1627
953
    self.regs[1] = new_value;
1628
953
  }
1629
1630
  /// Gets operand #2's register value. Use this method if operand #2 ([`op0_kind()`]) has kind [`OpKind::Register`], see [`op_count()`] and [`try_op_register()`]
1631
  ///
1632
  /// [`op0_kind()`]: #method.op0_kind
1633
  /// [`op_count()`]: #method.op_count
1634
  /// [`try_op_register()`]: #method.try_op_register
1635
  /// [`Register::None`]: enum.Register.html#variant.None
1636
  /// [`OpKind::Register`]: enum.OpKind.html#variant.Register
1637
  #[must_use]
1638
  #[inline]
1639
0
  pub const fn op2_register(&self) -> Register {
1640
0
    self.regs[2]
1641
0
  }
1642
1643
  /// Sets operand #2's register value. Use this method if operand #2 ([`op0_kind()`]) has kind [`OpKind::Register`], see [`op_count()`] and [`try_op_register()`]
1644
  ///
1645
  /// [`op0_kind()`]: #method.op0_kind
1646
  /// [`op_count()`]: #method.op_count
1647
  /// [`try_op_register()`]: #method.try_op_register
1648
  /// [`Register::None`]: enum.Register.html#variant.None
1649
  /// [`OpKind::Register`]: enum.OpKind.html#variant.Register
1650
  ///
1651
  /// # Arguments
1652
  ///
1653
  /// * `new_value`: New value
1654
  #[inline]
1655
8
  pub fn set_op2_register(&mut self, new_value: Register) {
1656
8
    self.regs[2] = new_value;
1657
8
  }
1658
1659
  /// Gets operand #3's register value. Use this method if operand #3 ([`op0_kind()`]) has kind [`OpKind::Register`], see [`op_count()`] and [`try_op_register()`]
1660
  ///
1661
  /// [`op0_kind()`]: #method.op0_kind
1662
  /// [`op_count()`]: #method.op_count
1663
  /// [`try_op_register()`]: #method.try_op_register
1664
  /// [`Register::None`]: enum.Register.html#variant.None
1665
  /// [`OpKind::Register`]: enum.OpKind.html#variant.Register
1666
  #[must_use]
1667
  #[inline]
1668
0
  pub const fn op3_register(&self) -> Register {
1669
0
    self.regs[3]
1670
0
  }
1671
1672
  /// Sets operand #3's register value. Use this method if operand #3 ([`op0_kind()`]) has kind [`OpKind::Register`], see [`op_count()`] and [`try_op_register()`]
1673
  ///
1674
  /// [`op0_kind()`]: #method.op0_kind
1675
  /// [`op_count()`]: #method.op_count
1676
  /// [`try_op_register()`]: #method.try_op_register
1677
  /// [`Register::None`]: enum.Register.html#variant.None
1678
  /// [`OpKind::Register`]: enum.OpKind.html#variant.Register
1679
  ///
1680
  /// # Arguments
1681
  ///
1682
  /// * `new_value`: New value
1683
  #[inline]
1684
0
  pub fn set_op3_register(&mut self, new_value: Register) {
1685
0
    self.regs[3] = new_value;
1686
0
  }
1687
1688
  /// Gets operand #4's register value. Use this method if operand #4 ([`op0_kind()`]) has kind [`OpKind::Register`], see [`op_count()`] and [`try_op_register()`]
1689
  ///
1690
  /// [`op0_kind()`]: #method.op0_kind
1691
  /// [`op_count()`]: #method.op_count
1692
  /// [`try_op_register()`]: #method.try_op_register
1693
  /// [`Register::None`]: enum.Register.html#variant.None
1694
  /// [`OpKind::Register`]: enum.OpKind.html#variant.Register
1695
  #[allow(clippy::unused_self)]
1696
  #[must_use]
1697
  #[inline]
1698
0
  pub const fn op4_register(&self) -> Register {
1699
0
    Register::None
1700
0
  }
Unexecuted instantiation: <iced_x86::instruction::Instruction>::op4_register
Unexecuted instantiation: <iced_x86::instruction::Instruction>::op4_register
1701
1702
  /// Sets operand #4's register value. Use this method if operand #4 ([`op0_kind()`]) has kind [`OpKind::Register`], see [`op_count()`] and [`try_op_register()`]
1703
  ///
1704
  /// [`op0_kind()`]: #method.op0_kind
1705
  /// [`op_count()`]: #method.op_count
1706
  /// [`try_op_register()`]: #method.try_op_register
1707
  /// [`Register::None`]: enum.Register.html#variant.None
1708
  /// [`OpKind::Register`]: enum.OpKind.html#variant.Register
1709
  ///
1710
  /// # Arguments
1711
  ///
1712
  /// * `new_value`: New value
1713
  #[allow(clippy::unused_self)]
1714
  #[inline]
1715
0
  pub fn set_op4_register(&mut self, new_value: Register) {
1716
0
    debug_assert_eq!(new_value, Register::None);
1717
0
  }
1718
1719
  #[allow(clippy::unused_self)]
1720
  #[inline]
1721
  #[doc(hidden)]
1722
0
  pub fn try_set_op4_register(&mut self, new_value: Register) -> Result<(), IcedError> {
1723
0
    if new_value != Register::None {
1724
0
      Err(IcedError::new("Invalid register"))
1725
    } else {
1726
0
      Ok(())
1727
    }
1728
0
  }
1729
1730
  /// Gets the operand's register value. Use this method if the operand has kind [`OpKind::Register`]
1731
  ///
1732
  /// [`OpKind::Register`]: enum.OpKind.html#variant.Register
1733
  ///
1734
  /// # Arguments
1735
  ///
1736
  /// * `operand`: Operand number, 0-4
1737
  ///
1738
  /// # Examples
1739
  ///
1740
  /// ```
1741
  /// use iced_x86::*;
1742
  ///
1743
  /// // add [rax],ebx
1744
  /// let bytes = b"\x01\x18";
1745
  /// let mut decoder = Decoder::new(64, bytes, DecoderOptions::NONE);
1746
  /// let instr = decoder.decode();
1747
  ///
1748
  /// assert_eq!(instr.op_count(), 2);
1749
  /// assert_eq!(instr.op_kind(0), OpKind::Memory);
1750
  /// assert_eq!(instr.op_kind(1), OpKind::Register);
1751
  /// assert_eq!(instr.op_register(1), Register::EBX);
1752
  /// ```
1753
  #[must_use]
1754
  #[inline]
1755
0
  pub fn op_register(&self, operand: u32) -> Register {
1756
    const _: () = assert!(IcedConstants::MAX_OP_COUNT == 5);
1757
0
    if let Some(&reg) = self.regs.get(operand as usize) {
1758
0
      reg
1759
0
    } else if operand == 4 {
1760
0
      self.op4_register()
1761
    } else {
1762
0
      debug_assert!(false, "Invalid operand: {}", operand);
1763
0
      Register::default()
1764
    }
1765
0
  }
1766
1767
  #[inline]
1768
  #[doc(hidden)]
1769
681
  pub fn try_op_register(&self, operand: u32) -> Result<Register, IcedError> {
1770
    const _: () = assert!(IcedConstants::MAX_OP_COUNT == 5);
1771
681
    if let Some(&reg) = self.regs.get(operand as usize) {
1772
681
      Ok(reg)
1773
0
    } else if operand == 4 {
1774
0
      Ok(self.op4_register())
1775
    } else {
1776
0
      Err(IcedError::new("Invalid operand"))
1777
    }
1778
681
  }
<iced_x86::instruction::Instruction>::try_op_register
Line
Count
Source
1769
681
  pub fn try_op_register(&self, operand: u32) -> Result<Register, IcedError> {
1770
    const _: () = assert!(IcedConstants::MAX_OP_COUNT == 5);
1771
681
    if let Some(&reg) = self.regs.get(operand as usize) {
1772
681
      Ok(reg)
1773
0
    } else if operand == 4 {
1774
0
      Ok(self.op4_register())
1775
    } else {
1776
0
      Err(IcedError::new("Invalid operand"))
1777
    }
1778
681
  }
Unexecuted instantiation: <iced_x86::instruction::Instruction>::try_op_register
1779
1780
  /// Sets the operand's register value. Use this method if the operand has kind [`OpKind::Register`]
1781
  ///
1782
  /// [`OpKind::Register`]: enum.OpKind.html#variant.Register
1783
  ///
1784
  /// # Arguments
1785
  ///
1786
  /// * `operand`: Operand number, 0-4
1787
  /// * `new_value`: New value
1788
  #[inline]
1789
0
  pub fn set_op_register(&mut self, operand: u32, new_value: Register) {
1790
    const _: () = assert!(IcedConstants::MAX_OP_COUNT == 5);
1791
0
    match operand {
1792
0
      0 => self.set_op0_register(new_value),
1793
0
      1 => self.set_op1_register(new_value),
1794
0
      2 => self.set_op2_register(new_value),
1795
0
      3 => self.set_op3_register(new_value),
1796
0
      4 => self.set_op4_register(new_value),
1797
0
      _ => debug_assert!(false, "Invalid operand: {}", operand),
1798
    }
1799
0
  }
1800
1801
  #[inline]
1802
  #[doc(hidden)]
1803
0
  pub fn try_set_op_register(&mut self, operand: u32, new_value: Register) -> Result<(), IcedError> {
1804
    const _: () = assert!(IcedConstants::MAX_OP_COUNT == 5);
1805
0
    match operand {
1806
0
      0 => self.set_op0_register(new_value),
1807
0
      1 => self.set_op1_register(new_value),
1808
0
      2 => self.set_op2_register(new_value),
1809
0
      3 => self.set_op3_register(new_value),
1810
0
      4 => return self.try_set_op4_register(new_value),
1811
0
      _ => return Err(IcedError::new("Invalid operand")),
1812
    }
1813
0
    Ok(())
1814
0
  }
1815
1816
  /// Gets the opmask register ([`Register::K1`] - [`Register::K7`]) or [`Register::None`] if none
1817
  ///
1818
  /// [`Register::K1`]: enum.Register.html#variant.K1
1819
  /// [`Register::K7`]: enum.Register.html#variant.K7
1820
  /// [`Register::None`]: enum.Register.html#variant.None
1821
  #[must_use]
1822
  #[inline]
1823
0
  pub fn op_mask(&self) -> Register {
1824
0
    let r = (self.flags1 >> InstrFlags1::OP_MASK_SHIFT) & InstrFlags1::OP_MASK_MASK;
1825
0
    if r == 0 {
1826
0
      Register::None
1827
    } else {
1828
      const _: () = assert!(InstrFlags1::OP_MASK_MASK == 7);
1829
      const _: () = assert!(Register::K0 as u32 + 1 == Register::K1 as u32);
1830
      const _: () = assert!(Register::K0 as u32 + 2 == Register::K2 as u32);
1831
      const _: () = assert!(Register::K0 as u32 + 3 == Register::K3 as u32);
1832
      const _: () = assert!(Register::K0 as u32 + 4 == Register::K4 as u32);
1833
      const _: () = assert!(Register::K0 as u32 + 5 == Register::K5 as u32);
1834
      const _: () = assert!(Register::K0 as u32 + 6 == Register::K6 as u32);
1835
      const _: () = assert!(Register::K0 as u32 + 7 == Register::K7 as u32);
1836
      // SAFETY: r+K0 is a valid Register variant since 1<=r<=7
1837
0
      unsafe { mem::transmute((r + Register::K0 as u32) as RegisterUnderlyingType) }
1838
    }
1839
0
  }
1840
1841
  /// Sets the opmask register ([`Register::K1`] - [`Register::K7`]) or [`Register::None`] if none
1842
  ///
1843
  /// [`Register::K1`]: enum.Register.html#variant.K1
1844
  /// [`Register::K7`]: enum.Register.html#variant.K7
1845
  /// [`Register::None`]: enum.Register.html#variant.None
1846
  ///
1847
  /// # Arguments
1848
  ///
1849
  /// * `new_value`: New value
1850
  #[allow(clippy::missing_inline_in_public_items)]
1851
0
  pub fn set_op_mask(&mut self, new_value: Register) {
1852
0
    debug_assert!(new_value == Register::None || (Register::K1 <= new_value && new_value <= Register::K7));
1853
0
    let r = if new_value == Register::None { 0 } else { (new_value as u32 - Register::K0 as u32) & InstrFlags1::OP_MASK_MASK };
1854
0
    self.flags1 = (self.flags1 & !(InstrFlags1::OP_MASK_MASK << InstrFlags1::OP_MASK_SHIFT)) | (r << InstrFlags1::OP_MASK_SHIFT);
1855
0
  }
1856
1857
  /// Checks if there's an opmask register ([`op_mask()`])
1858
  ///
1859
  /// [`op_mask()`]: #method.op_mask
1860
  #[must_use]
1861
  #[inline]
1862
0
  pub const fn has_op_mask(&self) -> bool {
1863
0
    (self.flags1 & (InstrFlags1::OP_MASK_MASK << InstrFlags1::OP_MASK_SHIFT)) != 0
1864
0
  }
1865
1866
  /// `true` if zeroing-masking, `false` if merging-masking.
1867
  /// Only used by most EVEX encoded instructions that use opmask registers.
1868
  #[must_use]
1869
  #[inline]
1870
0
  pub const fn zeroing_masking(&self) -> bool {
1871
0
    (self.flags1 & InstrFlags1::ZEROING_MASKING) != 0
1872
0
  }
1873
1874
  /// `true` if zeroing-masking, `false` if merging-masking.
1875
  /// Only used by most EVEX encoded instructions that use opmask registers.
1876
  ///
1877
  /// # Arguments
1878
  ///
1879
  /// * `new_value`: New value
1880
  #[inline]
1881
0
  pub fn set_zeroing_masking(&mut self, new_value: bool) {
1882
0
    if new_value {
1883
0
      self.flags1 |= InstrFlags1::ZEROING_MASKING;
1884
0
    } else {
1885
0
      self.flags1 &= !InstrFlags1::ZEROING_MASKING;
1886
0
    }
1887
0
  }
1888
1889
  /// `true` if merging-masking, `false` if zeroing-masking.
1890
  /// Only used by most EVEX encoded instructions that use opmask registers.
1891
  #[must_use]
1892
  #[inline]
1893
0
  pub const fn merging_masking(&self) -> bool {
1894
0
    (self.flags1 & InstrFlags1::ZEROING_MASKING) == 0
1895
0
  }
1896
1897
  /// `true` if merging-masking, `false` if zeroing-masking.
1898
  /// Only used by most EVEX encoded instructions that use opmask registers.
1899
  ///
1900
  /// # Arguments
1901
  ///
1902
  /// * `new_value`: New value
1903
  #[inline]
1904
0
  pub fn set_merging_masking(&mut self, new_value: bool) {
1905
0
    if new_value {
1906
0
      self.flags1 &= !InstrFlags1::ZEROING_MASKING;
1907
0
    } else {
1908
0
      self.flags1 |= InstrFlags1::ZEROING_MASKING;
1909
0
    }
1910
0
  }
1911
1912
  /// Gets the rounding control (SAE is implied but [`suppress_all_exceptions()`] still returns `false`)
1913
  /// or [`RoundingControl::None`] if the instruction doesn't use it.
1914
  ///
1915
  /// [`suppress_all_exceptions()`]: #method.suppress_all_exceptions
1916
  /// [`RoundingControl::None`]: enum.RoundingControl.html#variant.None
1917
  #[must_use]
1918
  #[inline]
1919
0
  pub fn rounding_control(&self) -> RoundingControl {
1920
    unsafe {
1921
0
      mem::transmute(
1922
0
        ((self.flags1 >> InstrFlags1::ROUNDING_CONTROL_SHIFT) & InstrFlags1::ROUNDING_CONTROL_MASK) as RoundingControlUnderlyingType,
1923
      )
1924
    }
1925
0
  }
1926
1927
  /// Sets the rounding control (SAE is implied but [`suppress_all_exceptions()`] still returns `false`)
1928
  /// or [`RoundingControl::None`] if the instruction doesn't use it.
1929
  ///
1930
  /// [`suppress_all_exceptions()`]: #method.suppress_all_exceptions
1931
  /// [`RoundingControl::None`]: enum.RoundingControl.html#variant.None
1932
  ///
1933
  /// # Arguments
1934
  ///
1935
  /// * `new_value`: New value
1936
  #[inline]
1937
0
  pub fn set_rounding_control(&mut self, new_value: RoundingControl) {
1938
0
    self.flags1 = (self.flags1 & !(InstrFlags1::ROUNDING_CONTROL_MASK << InstrFlags1::ROUNDING_CONTROL_SHIFT))
1939
0
      | ((new_value as u32) << InstrFlags1::ROUNDING_CONTROL_SHIFT);
1940
0
  }
1941
1942
  /// Gets the number of elements in a `db`/`dw`/`dd`/`dq` directive.
1943
  /// Can only be called if [`code()`] is [`Code::DeclareByte`], [`Code::DeclareWord`], [`Code::DeclareDword`], [`Code::DeclareQword`]
1944
  ///
1945
  /// [`code()`]: #method.code
1946
  /// [`Code::DeclareByte`]: enum.Code.html#variant.DeclareByte
1947
  /// [`Code::DeclareWord`]: enum.Code.html#variant.DeclareWord
1948
  /// [`Code::DeclareDword`]: enum.Code.html#variant.DeclareDword
1949
  /// [`Code::DeclareQword`]: enum.Code.html#variant.DeclareQword
1950
  #[must_use]
1951
  #[inline]
1952
0
  pub const fn declare_data_len(&self) -> usize {
1953
0
    (((self.flags1 >> InstrFlags1::DATA_LENGTH_SHIFT) & InstrFlags1::DATA_LENGTH_MASK) + 1) as usize
1954
0
  }
1955
1956
  /// Sets the number of elements in a `db`/`dw`/`dd`/`dq` directive.
1957
  /// Can only be called if [`code()`] is [`Code::DeclareByte`], [`Code::DeclareWord`], [`Code::DeclareDword`], [`Code::DeclareQword`]
1958
  ///
1959
  /// [`code()`]: #method.code
1960
  /// [`Code::DeclareByte`]: enum.Code.html#variant.DeclareByte
1961
  /// [`Code::DeclareWord`]: enum.Code.html#variant.DeclareWord
1962
  /// [`Code::DeclareDword`]: enum.Code.html#variant.DeclareDword
1963
  /// [`Code::DeclareQword`]: enum.Code.html#variant.DeclareQword
1964
  ///
1965
  /// # Arguments
1966
  ///
1967
  /// * `new_value`: New value: `db`: 1-16; `dw`: 1-8; `dd`: 1-4; `dq`: 1-2
1968
  #[inline]
1969
0
  pub fn set_declare_data_len(&mut self, new_value: usize) {
1970
0
    debug_assert!(1 <= new_value && new_value <= 0x10);
1971
0
    self.flags1 = (self.flags1 & !(InstrFlags1::DATA_LENGTH_MASK << InstrFlags1::DATA_LENGTH_SHIFT))
1972
0
      | ((((new_value as u32) - 1) & InstrFlags1::DATA_LENGTH_MASK) << InstrFlags1::DATA_LENGTH_SHIFT);
1973
0
  }
1974
1975
  /// Sets a new `db` value, see also [`declare_data_len()`].
1976
  /// Can only be called if [`code()`] is [`Code::DeclareByte`]
1977
  ///
1978
  /// [`declare_data_len()`]: #method.declare_data_len
1979
  /// [`code()`]: #method.code
1980
  /// [`Code::DeclareByte`]: enum.Code.html#variant.DeclareByte
1981
  ///
1982
  /// # Arguments
1983
  ///
1984
  /// * `index`: Index (0-15)
1985
  /// * `new_value`: New value
1986
  #[inline]
1987
0
  pub fn set_declare_byte_value_i8(&mut self, index: usize, new_value: i8) {
1988
0
    match self.try_set_declare_byte_value_i8(index, new_value) {
1989
0
      Ok(()) => {}
1990
0
      Err(_) => debug_assert!(false, "Invalid index: {}", index),
1991
    }
1992
0
  }
1993
1994
  /// Sets a new `db` value, see also [`declare_data_len()`].
1995
  /// Can only be called if [`code()`] is [`Code::DeclareByte`]
1996
  ///
1997
  /// [`declare_data_len()`]: #method.declare_data_len
1998
  /// [`code()`]: #method.code
1999
  /// [`Code::DeclareByte`]: enum.Code.html#variant.DeclareByte
2000
  ///
2001
  /// # Errors
2002
  ///
2003
  /// - Fails if `index` is invalid
2004
  ///
2005
  /// # Arguments
2006
  ///
2007
  /// * `index`: Index (0-15)
2008
  /// * `new_value`: New value
2009
  #[inline]
2010
0
  pub fn try_set_declare_byte_value_i8(&mut self, index: usize, new_value: i8) -> Result<(), IcedError> {
2011
0
    self.try_set_declare_byte_value(index, new_value as u8)
2012
0
  }
2013
2014
  /// Sets a new `db` value, see also [`declare_data_len()`].
2015
  /// Can only be called if [`code()`] is [`Code::DeclareByte`]
2016
  ///
2017
  /// [`declare_data_len()`]: #method.declare_data_len
2018
  /// [`code()`]: #method.code
2019
  /// [`Code::DeclareByte`]: enum.Code.html#variant.DeclareByte
2020
  ///
2021
  /// # Arguments
2022
  ///
2023
  /// * `index`: Index (0-15)
2024
  /// * `new_value`: New value
2025
  #[inline]
2026
0
  pub fn set_declare_byte_value(&mut self, index: usize, new_value: u8) {
2027
0
    match self.try_set_declare_byte_value(index, new_value) {
2028
0
      Ok(()) => {}
2029
0
      Err(_) => debug_assert!(false, "Invalid index: {}", index),
2030
    }
2031
0
  }
2032
2033
  #[allow(clippy::missing_inline_in_public_items)]
2034
  #[doc(hidden)]
2035
0
  pub fn try_set_declare_byte_value(&mut self, index: usize, new_value: u8) -> Result<(), IcedError> {
2036
0
    match index {
2037
0
      0 => self.regs[0] = Register::from_u8(new_value),
2038
0
      1 => self.regs[1] = Register::from_u8(new_value),
2039
0
      2 => self.regs[2] = Register::from_u8(new_value),
2040
0
      3 => self.regs[3] = Register::from_u8(new_value),
2041
0
      4 => self.immediate = (self.immediate & 0xFFFF_FF00) | new_value as u32,
2042
0
      5 => self.immediate = (self.immediate & 0xFFFF_00FF) | ((new_value as u32) << 8),
2043
0
      6 => self.immediate = (self.immediate & 0xFF00_FFFF) | ((new_value as u32) << 16),
2044
0
      7 => self.immediate = (self.immediate & 0x00FF_FFFF) | ((new_value as u32) << 24),
2045
0
      8 => self.mem_displ = (self.mem_displ & 0xFFFF_FFFF_FFFF_FF00) | new_value as u64,
2046
0
      9 => self.mem_displ = (self.mem_displ & 0xFFFF_FFFF_FFFF_00FF) | ((new_value as u64) << 8),
2047
0
      10 => self.mem_displ = (self.mem_displ & 0xFFFF_FFFF_FF00_FFFF) | ((new_value as u64) << 16),
2048
0
      11 => self.mem_displ = (self.mem_displ & 0xFFFF_FFFF_00FF_FFFF) | ((new_value as u64) << 24),
2049
0
      12 => self.mem_displ = (self.mem_displ & 0xFFFF_FF00_FFFF_FFFF) | ((new_value as u64) << 32),
2050
0
      13 => self.mem_displ = (self.mem_displ & 0xFFFF_00FF_FFFF_FFFF) | ((new_value as u64) << 40),
2051
0
      14 => self.mem_displ = (self.mem_displ & 0xFF00_FFFF_FFFF_FFFF) | ((new_value as u64) << 48),
2052
0
      15 => self.mem_displ = (self.mem_displ & 0x00FF_FFFF_FFFF_FFFF) | ((new_value as u64) << 56),
2053
0
      _ => return Err(IcedError::new("Invalid index")),
2054
    }
2055
0
    Ok(())
2056
0
  }
2057
2058
  /// Gets a `db` value, see also [`declare_data_len()`].
2059
  /// Can only be called if [`code()`] is [`Code::DeclareByte`]
2060
  ///
2061
  /// [`declare_data_len()`]: #method.declare_data_len
2062
  /// [`code()`]: #method.code
2063
  /// [`Code::DeclareByte`]: enum.Code.html#variant.DeclareByte
2064
  ///
2065
  /// # Arguments
2066
  ///
2067
  /// * `index`: Index (0-15)
2068
  #[must_use]
2069
  #[inline]
2070
0
  pub fn get_declare_byte_value(&self, index: usize) -> u8 {
2071
0
    match self.try_get_declare_byte_value(index) {
2072
0
      Ok(value) => value,
2073
      Err(_) => {
2074
0
        debug_assert!(false, "Invalid index: {}", index);
2075
0
        0
2076
      }
2077
    }
2078
0
  }
2079
2080
  #[allow(clippy::missing_inline_in_public_items)]
2081
  #[doc(hidden)]
2082
0
  pub const fn try_get_declare_byte_value(&self, index: usize) -> Result<u8, IcedError> {
2083
0
    Ok(match index {
2084
0
      0 => self.regs[0] as u8,
2085
0
      1 => self.regs[1] as u8,
2086
0
      2 => self.regs[2] as u8,
2087
0
      3 => self.regs[3] as u8,
2088
0
      4 => self.immediate as u8,
2089
0
      5 => (self.immediate >> 8) as u8,
2090
0
      6 => (self.immediate >> 16) as u8,
2091
0
      7 => (self.immediate >> 24) as u8,
2092
0
      8 => self.mem_displ as u8,
2093
0
      9 => ((self.mem_displ as u32) >> 8) as u8,
2094
0
      10 => ((self.mem_displ as u32) >> 16) as u8,
2095
0
      11 => ((self.mem_displ as u32) >> 24) as u8,
2096
0
      12 => (self.mem_displ >> 32) as u8,
2097
0
      13 => (self.mem_displ >> 40) as u8,
2098
0
      14 => (self.mem_displ >> 48) as u8,
2099
0
      15 => (self.mem_displ >> 56) as u8,
2100
0
      _ => return Err(IcedError::new("Invalid index")),
2101
    })
2102
0
  }
2103
2104
  /// Sets a new `dw` value, see also [`declare_data_len()`].
2105
  /// Can only be called if [`code()`] is [`Code::DeclareWord`]
2106
  ///
2107
  /// [`declare_data_len()`]: #method.declare_data_len
2108
  /// [`code()`]: #method.code
2109
  /// [`Code::DeclareWord`]: enum.Code.html#variant.DeclareWord
2110
  ///
2111
  /// # Arguments
2112
  ///
2113
  /// * `index`: Index (0-7)
2114
  /// * `new_value`: New value
2115
  #[inline]
2116
0
  pub fn set_declare_word_value_i16(&mut self, index: usize, new_value: i16) {
2117
0
    match self.try_set_declare_word_value_i16(index, new_value) {
2118
0
      Ok(()) => {}
2119
0
      Err(_) => debug_assert!(false, "Invalid index: {}", index),
2120
    }
2121
0
  }
2122
2123
  #[inline]
2124
  #[doc(hidden)]
2125
0
  pub fn try_set_declare_word_value_i16(&mut self, index: usize, new_value: i16) -> Result<(), IcedError> {
2126
0
    self.try_set_declare_word_value(index, new_value as u16)
2127
0
  }
2128
2129
  /// Sets a new `dw` value, see also [`declare_data_len()`].
2130
  /// Can only be called if [`code()`] is [`Code::DeclareWord`]
2131
  ///
2132
  /// [`declare_data_len()`]: #method.declare_data_len
2133
  /// [`code()`]: #method.code
2134
  /// [`Code::DeclareWord`]: enum.Code.html#variant.DeclareWord
2135
  ///
2136
  /// # Arguments
2137
  ///
2138
  /// * `index`: Index (0-7)
2139
  /// * `new_value`: New value
2140
  #[inline]
2141
0
  pub fn set_declare_word_value(&mut self, index: usize, new_value: u16) {
2142
0
    match self.try_set_declare_word_value(index, new_value) {
2143
0
      Ok(()) => {}
2144
0
      Err(_) => debug_assert!(false, "Invalid index: {}", index),
2145
    }
2146
0
  }
2147
2148
  #[allow(clippy::missing_inline_in_public_items)]
2149
  #[doc(hidden)]
2150
0
  pub fn try_set_declare_word_value(&mut self, index: usize, new_value: u16) -> Result<(), IcedError> {
2151
0
    match index {
2152
0
      0 => {
2153
0
        self.regs[0] = Register::from_u8(new_value as u8);
2154
0
        self.regs[1] = Register::from_u8((new_value >> 8) as u8);
2155
0
      }
2156
0
      1 => {
2157
0
        self.regs[2] = Register::from_u8(new_value as u8);
2158
0
        self.regs[3] = Register::from_u8((new_value >> 8) as u8);
2159
0
      }
2160
0
      2 => self.immediate = (self.immediate & 0xFFFF_0000) | new_value as u32,
2161
0
      3 => self.immediate = self.immediate as u16 as u32 | (new_value as u32) << 16,
2162
0
      4 => self.mem_displ = (self.mem_displ & 0xFFFF_FFFF_FFFF_0000) | new_value as u64,
2163
0
      5 => self.mem_displ = (self.mem_displ & 0xFFFF_FFFF_0000_FFFF) | ((new_value as u64) << 16),
2164
0
      6 => self.mem_displ = (self.mem_displ & 0xFFFF_0000_FFFF_FFFF) | ((new_value as u64) << 32),
2165
0
      7 => self.mem_displ = (self.mem_displ & 0x0000_FFFF_FFFF_FFFF) | ((new_value as u64) << 48),
2166
0
      _ => return Err(IcedError::new("Invalid index")),
2167
    }
2168
0
    Ok(())
2169
0
  }
2170
2171
  /// Gets a `dw` value, see also [`declare_data_len()`].
2172
  /// Can only be called if [`code()`] is [`Code::DeclareWord`]
2173
  ///
2174
  /// [`declare_data_len()`]: #method.declare_data_len
2175
  /// [`code()`]: #method.code
2176
  /// [`Code::DeclareWord`]: enum.Code.html#variant.DeclareWord
2177
  ///
2178
  /// # Arguments
2179
  ///
2180
  /// * `index`: Index (0-7)
2181
  #[must_use]
2182
  #[inline]
2183
0
  pub fn get_declare_word_value(&self, index: usize) -> u16 {
2184
0
    match self.try_get_declare_word_value(index) {
2185
0
      Ok(value) => value,
2186
      Err(_) => {
2187
0
        debug_assert!(false, "Invalid index: {}", index);
2188
0
        0
2189
      }
2190
    }
2191
0
  }
2192
2193
  #[allow(clippy::missing_inline_in_public_items)]
2194
  #[doc(hidden)]
2195
0
  pub const fn try_get_declare_word_value(&self, index: usize) -> Result<u16, IcedError> {
2196
0
    Ok(match index {
2197
0
      0 => self.regs[0] as u16 | ((self.regs[1] as u16) << 8),
2198
0
      1 => self.regs[2] as u16 | ((self.regs[3] as u16) << 8),
2199
0
      2 => self.immediate as u16,
2200
0
      3 => (self.immediate >> 16) as u16,
2201
0
      4 => self.mem_displ as u16,
2202
0
      5 => ((self.mem_displ as u32) >> 16) as u16,
2203
0
      6 => (self.mem_displ >> 32) as u16,
2204
0
      7 => (self.mem_displ >> 48) as u16,
2205
0
      _ => return Err(IcedError::new("Invalid index")),
2206
    })
2207
0
  }
2208
2209
  /// Sets a new `dd` value, see also [`declare_data_len()`].
2210
  /// Can only be called if [`code()`] is [`Code::DeclareDword`]
2211
  ///
2212
  /// [`declare_data_len()`]: #method.declare_data_len
2213
  /// [`code()`]: #method.code
2214
  /// [`Code::DeclareDword`]: enum.Code.html#variant.DeclareDword
2215
  ///
2216
  /// # Arguments
2217
  ///
2218
  /// * `index`: Index (0-3)
2219
  /// * `new_value`: New value
2220
  #[inline]
2221
0
  pub fn set_declare_dword_value_i32(&mut self, index: usize, new_value: i32) {
2222
0
    match self.try_set_declare_dword_value_i32(index, new_value) {
2223
0
      Ok(()) => {}
2224
0
      Err(_) => debug_assert!(false, "Invalid index: {}", index),
2225
    }
2226
0
  }
2227
2228
  #[inline]
2229
  #[doc(hidden)]
2230
0
  pub fn try_set_declare_dword_value_i32(&mut self, index: usize, new_value: i32) -> Result<(), IcedError> {
2231
0
    self.try_set_declare_dword_value(index, new_value as u32)
2232
0
  }
2233
2234
  /// Sets a new `dd` value, see also [`declare_data_len()`].
2235
  /// Can only be called if [`code()`] is [`Code::DeclareDword`]
2236
  ///
2237
  /// [`declare_data_len()`]: #method.declare_data_len
2238
  /// [`code()`]: #method.code
2239
  /// [`Code::DeclareDword`]: enum.Code.html#variant.DeclareDword
2240
  ///
2241
  /// # Arguments
2242
  ///
2243
  /// * `index`: Index (0-3)
2244
  /// * `new_value`: New value
2245
  #[inline]
2246
0
  pub fn set_declare_dword_value(&mut self, index: usize, new_value: u32) {
2247
0
    match self.try_set_declare_dword_value(index, new_value) {
2248
0
      Ok(()) => {}
2249
0
      Err(_) => debug_assert!(false, "Invalid index: {}", index),
2250
    }
2251
0
  }
2252
2253
  #[allow(clippy::missing_inline_in_public_items)]
2254
  #[doc(hidden)]
2255
0
  pub fn try_set_declare_dword_value(&mut self, index: usize, new_value: u32) -> Result<(), IcedError> {
2256
0
    match index {
2257
0
      0 => {
2258
0
        self.regs[0] = Register::from_u8(new_value as u8);
2259
0
        self.regs[1] = Register::from_u8((new_value >> 8) as u8);
2260
0
        self.regs[2] = Register::from_u8((new_value >> 16) as u8);
2261
0
        self.regs[3] = Register::from_u8((new_value >> 24) as u8);
2262
0
      }
2263
0
      1 => self.immediate = new_value,
2264
0
      2 => self.mem_displ = (self.mem_displ & 0xFFFF_FFFF_0000_0000) | new_value as u64,
2265
0
      3 => self.mem_displ = (self.mem_displ & 0x0000_0000_FFFF_FFFF) | (new_value as u64) << 32,
2266
0
      _ => return Err(IcedError::new("Invalid index")),
2267
    }
2268
0
    Ok(())
2269
0
  }
2270
2271
  /// Gets a `dd` value, see also [`declare_data_len()`].
2272
  /// Can only be called if [`code()`] is [`Code::DeclareDword`]
2273
  ///
2274
  /// [`declare_data_len()`]: #method.declare_data_len
2275
  /// [`code()`]: #method.code
2276
  /// [`Code::DeclareDword`]: enum.Code.html#variant.DeclareDword
2277
  ///
2278
  /// # Arguments
2279
  ///
2280
  /// * `index`: Index (0-3)
2281
  #[must_use]
2282
  #[inline]
2283
0
  pub fn get_declare_dword_value(&self, index: usize) -> u32 {
2284
0
    match self.try_get_declare_dword_value(index) {
2285
0
      Ok(value) => value,
2286
      Err(_) => {
2287
0
        debug_assert!(false, "Invalid index: {}", index);
2288
0
        0
2289
      }
2290
    }
2291
0
  }
2292
2293
  #[allow(clippy::missing_inline_in_public_items)]
2294
  #[doc(hidden)]
2295
0
  pub const fn try_get_declare_dword_value(&self, index: usize) -> Result<u32, IcedError> {
2296
0
    Ok(match index {
2297
0
      0 => self.regs[0] as u32 | ((self.regs[1] as u32) << 8) | ((self.regs[2] as u32) << 16) | ((self.regs[3] as u32) << 24),
2298
0
      1 => self.immediate,
2299
0
      2 => self.mem_displ as u32,
2300
0
      3 => (self.mem_displ >> 32) as u32,
2301
0
      _ => return Err(IcedError::new("Invalid index")),
2302
    })
2303
0
  }
2304
2305
  /// Sets a new `dq` value, see also [`declare_data_len()`].
2306
  /// Can only be called if [`code()`] is [`Code::DeclareQword`]
2307
  ///
2308
  /// [`declare_data_len()`]: #method.declare_data_len
2309
  /// [`code()`]: #method.code
2310
  /// [`Code::DeclareQword`]: enum.Code.html#variant.DeclareQword
2311
  ///
2312
  /// # Arguments
2313
  ///
2314
  /// * `index`: Index (0-1)
2315
  /// * `new_value`: New value
2316
  #[inline]
2317
0
  pub fn set_declare_qword_value_i64(&mut self, index: usize, new_value: i64) {
2318
0
    match self.try_set_declare_qword_value_i64(index, new_value) {
2319
0
      Ok(()) => {}
2320
0
      Err(_) => debug_assert!(false, "Invalid index: {}", index),
2321
    }
2322
0
  }
2323
2324
  #[inline]
2325
  #[doc(hidden)]
2326
0
  pub fn try_set_declare_qword_value_i64(&mut self, index: usize, new_value: i64) -> Result<(), IcedError> {
2327
0
    self.try_set_declare_qword_value(index, new_value as u64)
2328
0
  }
2329
2330
  /// Sets a new `dq` value, see also [`declare_data_len()`].
2331
  /// Can only be called if [`code()`] is [`Code::DeclareQword`]
2332
  ///
2333
  /// [`declare_data_len()`]: #method.declare_data_len
2334
  /// [`code()`]: #method.code
2335
  /// [`Code::DeclareQword`]: enum.Code.html#variant.DeclareQword
2336
  ///
2337
  /// # Arguments
2338
  ///
2339
  /// * `index`: Index (0-1)
2340
  /// * `new_value`: New value
2341
  #[inline]
2342
0
  pub fn set_declare_qword_value(&mut self, index: usize, new_value: u64) {
2343
0
    match self.try_set_declare_qword_value(index, new_value) {
2344
0
      Ok(()) => {}
2345
0
      Err(_) => debug_assert!(false, "Invalid index: {}", index),
2346
    }
2347
0
  }
2348
2349
  #[allow(clippy::missing_inline_in_public_items)]
2350
  #[doc(hidden)]
2351
0
  pub fn try_set_declare_qword_value(&mut self, index: usize, new_value: u64) -> Result<(), IcedError> {
2352
0
    match index {
2353
0
      0 => {
2354
0
        self.regs[0] = Register::from_u8(new_value as u8);
2355
0
        self.regs[1] = Register::from_u8((new_value >> 8) as u8);
2356
0
        self.regs[2] = Register::from_u8((new_value >> 16) as u8);
2357
0
        self.regs[3] = Register::from_u8((new_value >> 24) as u8);
2358
0
        self.immediate = (new_value >> 32) as u32;
2359
0
      }
2360
0
      1 => self.mem_displ = new_value,
2361
0
      _ => return Err(IcedError::new("Invalid index")),
2362
    }
2363
0
    Ok(())
2364
0
  }
2365
2366
  /// Gets a `dq` value, see also [`declare_data_len()`].
2367
  /// Can only be called if [`code()`] is [`Code::DeclareQword`]
2368
  ///
2369
  /// [`declare_data_len()`]: #method.declare_data_len
2370
  /// [`code()`]: #method.code
2371
  /// [`Code::DeclareQword`]: enum.Code.html#variant.DeclareQword
2372
  ///
2373
  /// # Arguments
2374
  ///
2375
  /// * `index`: Index (0-1)
2376
  #[must_use]
2377
  #[inline]
2378
0
  pub fn get_declare_qword_value(&self, index: usize) -> u64 {
2379
0
    match self.try_get_declare_qword_value(index) {
2380
0
      Ok(value) => value,
2381
      Err(_) => {
2382
0
        debug_assert!(false, "Invalid index: {}", index);
2383
0
        0
2384
      }
2385
    }
2386
0
  }
2387
2388
  #[allow(clippy::missing_inline_in_public_items)]
2389
  #[doc(hidden)]
2390
0
  pub const fn try_get_declare_qword_value(&self, index: usize) -> Result<u64, IcedError> {
2391
0
    Ok(match index {
2392
      0 => {
2393
0
        self.regs[0] as u64
2394
0
          | ((self.regs[1] as u64) << 8)
2395
0
          | ((self.regs[2] as u64) << 16)
2396
0
          | ((self.regs[3] as u64) << 24)
2397
0
          | ((self.immediate as u64) << 32)
2398
      }
2399
0
      1 => self.mem_displ,
2400
0
      _ => return Err(IcedError::new("Invalid index")),
2401
    })
2402
0
  }
2403
2404
  /// Checks if this is a VSIB instruction, see also [`is_vsib32()`], [`is_vsib64()`]
2405
  ///
2406
  /// [`is_vsib32()`]: #method.is_vsib32
2407
  /// [`is_vsib64()`]: #method.is_vsib64
2408
  #[must_use]
2409
  #[inline]
2410
0
  pub const fn is_vsib(&self) -> bool {
2411
0
    self.vsib().is_some()
2412
0
  }
2413
2414
  /// VSIB instructions only ([`is_vsib()`]): `true` if it's using 32-bit indexes, `false` if it's using 64-bit indexes
2415
  ///
2416
  /// [`is_vsib()`]: #method.is_vsib
2417
  #[must_use]
2418
  #[inline]
2419
0
  pub const fn is_vsib32(&self) -> bool {
2420
0
    if let Some(is_vsib64) = self.vsib() {
2421
0
      !is_vsib64
2422
    } else {
2423
0
      false
2424
    }
2425
0
  }
2426
2427
  /// VSIB instructions only ([`is_vsib()`]): `true` if it's using 64-bit indexes, `false` if it's using 32-bit indexes
2428
  ///
2429
  /// [`is_vsib()`]: #method.is_vsib
2430
  #[must_use]
2431
  #[inline]
2432
0
  pub const fn is_vsib64(&self) -> bool {
2433
0
    if let Some(is_vsib64) = self.vsib() {
2434
0
      is_vsib64
2435
    } else {
2436
0
      false
2437
    }
2438
0
  }
2439
2440
  /// Checks if it's a vsib instruction.
2441
  ///
2442
  /// # Returns
2443
  ///
2444
  /// * `Some(true)` if it's a VSIB instruction with 64-bit indexes
2445
  /// * `Some(false)` if it's a VSIB instruction with 32-bit indexes
2446
  /// * `None` if it's not a VSIB instruction.
2447
  #[must_use]
2448
  #[allow(clippy::missing_inline_in_public_items)]
2449
  #[allow(clippy::match_single_binding)]
2450
0
  pub const fn vsib(&self) -> Option<bool> {
2451
    #[cfg_attr(feature = "cargo-fmt", rustfmt::skip)]
2452
0
    match self.code() {
2453
      // GENERATOR-BEGIN: Vsib32
2454
      // ⚠️This was generated by GENERATOR!🦹‍♂️
2455
      Code::VEX_Vpgatherdd_xmm_vm32x_xmm
2456
      | Code::VEX_Vpgatherdd_ymm_vm32y_ymm
2457
      | Code::VEX_Vpgatherdq_xmm_vm32x_xmm
2458
      | Code::VEX_Vpgatherdq_ymm_vm32x_ymm
2459
      | Code::EVEX_Vpgatherdd_xmm_k1_vm32x
2460
      | Code::EVEX_Vpgatherdd_ymm_k1_vm32y
2461
      | Code::EVEX_Vpgatherdd_zmm_k1_vm32z
2462
      | Code::EVEX_Vpgatherdq_xmm_k1_vm32x
2463
      | Code::EVEX_Vpgatherdq_ymm_k1_vm32x
2464
      | Code::EVEX_Vpgatherdq_zmm_k1_vm32y
2465
      | Code::VEX_Vgatherdps_xmm_vm32x_xmm
2466
      | Code::VEX_Vgatherdps_ymm_vm32y_ymm
2467
      | Code::VEX_Vgatherdpd_xmm_vm32x_xmm
2468
      | Code::VEX_Vgatherdpd_ymm_vm32x_ymm
2469
      | Code::EVEX_Vgatherdps_xmm_k1_vm32x
2470
      | Code::EVEX_Vgatherdps_ymm_k1_vm32y
2471
      | Code::EVEX_Vgatherdps_zmm_k1_vm32z
2472
      | Code::EVEX_Vgatherdpd_xmm_k1_vm32x
2473
      | Code::EVEX_Vgatherdpd_ymm_k1_vm32x
2474
      | Code::EVEX_Vgatherdpd_zmm_k1_vm32y
2475
      | Code::EVEX_Vpscatterdd_vm32x_k1_xmm
2476
      | Code::EVEX_Vpscatterdd_vm32y_k1_ymm
2477
      | Code::EVEX_Vpscatterdd_vm32z_k1_zmm
2478
      | Code::EVEX_Vpscatterdq_vm32x_k1_xmm
2479
      | Code::EVEX_Vpscatterdq_vm32x_k1_ymm
2480
      | Code::EVEX_Vpscatterdq_vm32y_k1_zmm
2481
      | Code::EVEX_Vscatterdps_vm32x_k1_xmm
2482
      | Code::EVEX_Vscatterdps_vm32y_k1_ymm
2483
      | Code::EVEX_Vscatterdps_vm32z_k1_zmm
2484
      | Code::EVEX_Vscatterdpd_vm32x_k1_xmm
2485
      | Code::EVEX_Vscatterdpd_vm32x_k1_ymm
2486
      | Code::EVEX_Vscatterdpd_vm32y_k1_zmm
2487
      | Code::EVEX_Vgatherpf0dps_vm32z_k1
2488
      | Code::EVEX_Vgatherpf0dpd_vm32y_k1
2489
      | Code::EVEX_Vgatherpf1dps_vm32z_k1
2490
      | Code::EVEX_Vgatherpf1dpd_vm32y_k1
2491
      | Code::EVEX_Vscatterpf0dps_vm32z_k1
2492
      | Code::EVEX_Vscatterpf0dpd_vm32y_k1
2493
      | Code::EVEX_Vscatterpf1dps_vm32z_k1
2494
      | Code::EVEX_Vscatterpf1dpd_vm32y_k1
2495
      | Code::MVEX_Vpgatherdd_zmm_k1_mvt
2496
      | Code::MVEX_Vpgatherdq_zmm_k1_mvt
2497
      | Code::MVEX_Vgatherdps_zmm_k1_mvt
2498
      | Code::MVEX_Vgatherdpd_zmm_k1_mvt
2499
      | Code::MVEX_Vpscatterdd_mvt_k1_zmm
2500
      | Code::MVEX_Vpscatterdq_mvt_k1_zmm
2501
      | Code::MVEX_Vscatterdps_mvt_k1_zmm
2502
      | Code::MVEX_Vscatterdpd_mvt_k1_zmm
2503
      | Code::MVEX_Undoc_zmm_k1_mvt_512_66_0F38_W0_B0
2504
      | Code::MVEX_Undoc_zmm_k1_mvt_512_66_0F38_W0_B2
2505
      | Code::MVEX_Undoc_zmm_k1_mvt_512_66_0F38_W0_C0
2506
      | Code::MVEX_Vgatherpf0hintdps_mvt_k1
2507
      | Code::MVEX_Vgatherpf0hintdpd_mvt_k1
2508
      | Code::MVEX_Vgatherpf0dps_mvt_k1
2509
      | Code::MVEX_Vgatherpf1dps_mvt_k1
2510
      | Code::MVEX_Vscatterpf0hintdps_mvt_k1
2511
      | Code::MVEX_Vscatterpf0hintdpd_mvt_k1
2512
      | Code::MVEX_Vscatterpf0dps_mvt_k1
2513
      | Code::MVEX_Vscatterpf1dps_mvt_k1
2514
0
      => Some(false),
2515
      // GENERATOR-END: Vsib32
2516
2517
      // GENERATOR-BEGIN: Vsib64
2518
      // ⚠️This was generated by GENERATOR!🦹‍♂️
2519
      Code::VEX_Vpgatherqd_xmm_vm64x_xmm
2520
      | Code::VEX_Vpgatherqd_xmm_vm64y_xmm
2521
      | Code::VEX_Vpgatherqq_xmm_vm64x_xmm
2522
      | Code::VEX_Vpgatherqq_ymm_vm64y_ymm
2523
      | Code::EVEX_Vpgatherqd_xmm_k1_vm64x
2524
      | Code::EVEX_Vpgatherqd_xmm_k1_vm64y
2525
      | Code::EVEX_Vpgatherqd_ymm_k1_vm64z
2526
      | Code::EVEX_Vpgatherqq_xmm_k1_vm64x
2527
      | Code::EVEX_Vpgatherqq_ymm_k1_vm64y
2528
      | Code::EVEX_Vpgatherqq_zmm_k1_vm64z
2529
      | Code::VEX_Vgatherqps_xmm_vm64x_xmm
2530
      | Code::VEX_Vgatherqps_xmm_vm64y_xmm
2531
      | Code::VEX_Vgatherqpd_xmm_vm64x_xmm
2532
      | Code::VEX_Vgatherqpd_ymm_vm64y_ymm
2533
      | Code::EVEX_Vgatherqps_xmm_k1_vm64x
2534
      | Code::EVEX_Vgatherqps_xmm_k1_vm64y
2535
      | Code::EVEX_Vgatherqps_ymm_k1_vm64z
2536
      | Code::EVEX_Vgatherqpd_xmm_k1_vm64x
2537
      | Code::EVEX_Vgatherqpd_ymm_k1_vm64y
2538
      | Code::EVEX_Vgatherqpd_zmm_k1_vm64z
2539
      | Code::EVEX_Vpscatterqd_vm64x_k1_xmm
2540
      | Code::EVEX_Vpscatterqd_vm64y_k1_xmm
2541
      | Code::EVEX_Vpscatterqd_vm64z_k1_ymm
2542
      | Code::EVEX_Vpscatterqq_vm64x_k1_xmm
2543
      | Code::EVEX_Vpscatterqq_vm64y_k1_ymm
2544
      | Code::EVEX_Vpscatterqq_vm64z_k1_zmm
2545
      | Code::EVEX_Vscatterqps_vm64x_k1_xmm
2546
      | Code::EVEX_Vscatterqps_vm64y_k1_xmm
2547
      | Code::EVEX_Vscatterqps_vm64z_k1_ymm
2548
      | Code::EVEX_Vscatterqpd_vm64x_k1_xmm
2549
      | Code::EVEX_Vscatterqpd_vm64y_k1_ymm
2550
      | Code::EVEX_Vscatterqpd_vm64z_k1_zmm
2551
      | Code::EVEX_Vgatherpf0qps_vm64z_k1
2552
      | Code::EVEX_Vgatherpf0qpd_vm64z_k1
2553
      | Code::EVEX_Vgatherpf1qps_vm64z_k1
2554
      | Code::EVEX_Vgatherpf1qpd_vm64z_k1
2555
      | Code::EVEX_Vscatterpf0qps_vm64z_k1
2556
      | Code::EVEX_Vscatterpf0qpd_vm64z_k1
2557
      | Code::EVEX_Vscatterpf1qps_vm64z_k1
2558
      | Code::EVEX_Vscatterpf1qpd_vm64z_k1
2559
0
      => Some(true),
2560
      // GENERATOR-END: Vsib64
2561
2562
0
      _ => None,
2563
    }
2564
0
  }
2565
2566
  /// Gets the suppress all exceptions flag (EVEX/MVEX encoded instructions). Note that if [`rounding_control()`] is
2567
  /// not [`RoundingControl::None`], SAE is implied but this method will still return `false`.
2568
  ///
2569
  /// [`rounding_control()`]: #method.rounding_control
2570
  /// [`RoundingControl::None`]: enum.RoundingControl.html#variant.None
2571
  #[must_use]
2572
  #[inline]
2573
0
  pub const fn suppress_all_exceptions(&self) -> bool {
2574
0
    (self.flags1 & InstrFlags1::SUPPRESS_ALL_EXCEPTIONS) != 0
2575
0
  }
2576
2577
  /// Sets the suppress all exceptions flag (EVEX/MVEX encoded instructions). Note that if [`rounding_control()`] is
2578
  /// not [`RoundingControl::None`], SAE is implied but this method will still return `false`.
2579
  ///
2580
  /// [`rounding_control()`]: #method.rounding_control
2581
  /// [`RoundingControl::None`]: enum.RoundingControl.html#variant.None
2582
  ///
2583
  /// # Arguments
2584
  ///
2585
  /// * `new_value`: New value
2586
  #[inline]
2587
0
  pub fn set_suppress_all_exceptions(&mut self, new_value: bool) {
2588
0
    if new_value {
2589
0
      self.flags1 |= InstrFlags1::SUPPRESS_ALL_EXCEPTIONS;
2590
0
    } else {
2591
0
      self.flags1 &= !InstrFlags1::SUPPRESS_ALL_EXCEPTIONS;
2592
0
    }
2593
0
  }
2594
2595
  /// Checks if the memory operand is `RIP`/`EIP` relative
2596
  #[must_use]
2597
  #[inline]
2598
0
  pub fn is_ip_rel_memory_operand(&self) -> bool {
2599
0
    let base_reg = self.memory_base();
2600
0
    base_reg == Register::RIP || base_reg == Register::EIP
2601
0
  }
2602
2603
  /// Gets the `RIP`/`EIP` releative address ([`memory_displacement32()`] or [`memory_displacement64()`]).
2604
  /// This method is only valid if there's a memory operand with `RIP`/`EIP` relative addressing, see [`is_ip_rel_memory_operand()`]
2605
  ///
2606
  /// [`memory_displacement32()`]: #method.memory_displacement32
2607
  /// [`memory_displacement64()`]: #method.memory_displacement64
2608
  /// [`is_ip_rel_memory_operand()`]: #method.is_ip_rel_memory_operand
2609
  #[must_use]
2610
  #[inline]
2611
0
  pub fn ip_rel_memory_address(&self) -> u64 {
2612
0
    if self.memory_base() == Register::RIP {
2613
0
      self.memory_displacement64()
2614
    } else {
2615
0
      self.memory_displacement32() as u64
2616
    }
2617
0
  }
2618
2619
  /// Gets the virtual address of a memory operand
2620
  ///
2621
  /// # Arguments
2622
  ///
2623
  /// * `operand`: Operand number, 0-4, must be a memory operand
2624
  /// * `element_index`: Only used if it's a vsib memory operand. This is the element index of the vector index register.
2625
  /// * `get_register_value`: Function that returns the value of a register or the base address of a segment register, or `None` for unsupported
2626
  ///    registers.
2627
  ///
2628
  /// # Call-back function args
2629
  ///
2630
  /// * Arg 1: `register`: Register (GPR8, GPR16, GPR32, GPR64, XMM, YMM, ZMM, seg). If it's a segment register, the call-back function should return the segment's base address, not the segment's register value.
2631
  /// * Arg 2: `element_index`: Only used if it's a vsib memory operand. This is the element index of the vector index register.
2632
  /// * Arg 3: `element_size`: Only used if it's a vsib memory operand. Size in bytes of elements in vector index register (4 or 8).
2633
  ///
2634
  /// # Examples
2635
  ///
2636
  /// ```
2637
  /// use iced_x86::*;
2638
  ///
2639
  /// // add [rdi+r12*8-5AA5EDCCh],esi
2640
  /// let bytes = b"\x42\x01\xB4\xE7\x34\x12\x5A\xA5";
2641
  /// let mut decoder = Decoder::new(64, bytes, DecoderOptions::NONE);
2642
  /// let instr = decoder.decode();
2643
  ///
2644
  /// let va = instr.virtual_address(0, 0, |register, _element_index, _element_size| {
2645
  ///     match register {
2646
  ///         // The base address of ES, CS, SS and DS is always 0 in 64-bit mode
2647
  ///         Register::DS => Some(0x0000_0000_0000_0000),
2648
  ///         Register::RDI => Some(0x0000_0000_1000_0000),
2649
  ///         Register::R12 => Some(0x0000_0004_0000_0000),
2650
  ///         _ => None,
2651
  ///     }
2652
  /// });
2653
  /// assert_eq!(va, Some(0x0000_001F_B55A_1234));
2654
  /// ```
2655
  #[must_use]
2656
  #[inline]
2657
0
  pub fn virtual_address<F>(&self, operand: u32, element_index: usize, get_register_value: F) -> Option<u64>
2658
0
  where
2659
0
    F: FnMut(Register, usize, usize) -> Option<u64>,
2660
  {
2661
0
    self.try_virtual_address(operand, element_index, get_register_value)
2662
0
  }
2663
2664
  #[must_use]
2665
  #[allow(clippy::missing_inline_in_public_items)]
2666
  #[doc(hidden)]
2667
0
  pub fn try_virtual_address<F>(&self, operand: u32, element_index: usize, mut get_register_value: F) -> Option<u64>
2668
0
  where
2669
0
    F: FnMut(Register, usize, usize) -> Option<u64>,
2670
  {
2671
0
    let op_kind = self.op_kind(operand);
2672
0
    Some(match op_kind {
2673
      OpKind::Register
2674
      | OpKind::NearBranch16
2675
      | OpKind::NearBranch32
2676
      | OpKind::NearBranch64
2677
      | OpKind::FarBranch16
2678
      | OpKind::FarBranch32
2679
      | OpKind::Immediate8
2680
      | OpKind::Immediate8_2nd
2681
      | OpKind::Immediate16
2682
      | OpKind::Immediate32
2683
      | OpKind::Immediate64
2684
      | OpKind::Immediate8to16
2685
      | OpKind::Immediate8to32
2686
      | OpKind::Immediate8to64
2687
0
      | OpKind::Immediate32to64 => 0,
2688
2689
      OpKind::MemorySegSI => {
2690
0
        get_register_value(self.memory_segment(), 0, 0)?.wrapping_add(get_register_value(Register::SI, 0, 0)? as u16 as u64)
2691
      }
2692
      OpKind::MemorySegESI => {
2693
0
        get_register_value(self.memory_segment(), 0, 0)?.wrapping_add(get_register_value(Register::ESI, 0, 0)? as u32 as u64)
2694
      }
2695
0
      OpKind::MemorySegRSI => get_register_value(self.memory_segment(), 0, 0)?.wrapping_add(get_register_value(Register::RSI, 0, 0)?),
2696
      OpKind::MemorySegDI => {
2697
0
        get_register_value(self.memory_segment(), 0, 0)?.wrapping_add(get_register_value(Register::DI, 0, 0)? as u16 as u64)
2698
      }
2699
      OpKind::MemorySegEDI => {
2700
0
        get_register_value(self.memory_segment(), 0, 0)?.wrapping_add(get_register_value(Register::EDI, 0, 0)? as u32 as u64)
2701
      }
2702
0
      OpKind::MemorySegRDI => get_register_value(self.memory_segment(), 0, 0)?.wrapping_add(get_register_value(Register::RDI, 0, 0)?),
2703
0
      OpKind::MemoryESDI => get_register_value(Register::ES, 0, 0)?.wrapping_add(get_register_value(Register::DI, 0, 0)? as u16 as u64),
2704
0
      OpKind::MemoryESEDI => get_register_value(Register::ES, 0, 0)?.wrapping_add(get_register_value(Register::EDI, 0, 0)? as u32 as u64),
2705
0
      OpKind::MemoryESRDI => get_register_value(Register::ES, 0, 0)?.wrapping_add(get_register_value(Register::RDI, 0, 0)?),
2706
      OpKind::Memory => {
2707
0
        let base_reg = self.memory_base();
2708
0
        let index_reg = self.memory_index();
2709
0
        let addr_size = instruction_internal::get_address_size_in_bytes(base_reg, index_reg, self.memory_displ_size(), self.code_size());
2710
0
        let mut offset = self.memory_displacement64();
2711
0
        let offset_mask = match addr_size {
2712
0
          8 => u64::MAX,
2713
0
          4 => u32::MAX as u64,
2714
          _ => {
2715
0
            debug_assert_eq!(addr_size, 2);
2716
0
            u16::MAX as u64
2717
          }
2718
        };
2719
0
        match base_reg {
2720
0
          Register::None | Register::EIP | Register::RIP => {}
2721
0
          _ => offset = offset.wrapping_add(get_register_value(base_reg, 0, 0)?),
2722
        }
2723
0
        let code = self.code();
2724
0
        if index_reg != Register::None && !code.ignores_index() && !code.is_tile_stride_index() {
2725
0
          if let Some(is_vsib64) = self.vsib() {
2726
0
            if is_vsib64 {
2727
0
              offset = offset.wrapping_add(
2728
0
                get_register_value(index_reg, element_index, 8)? << instruction_internal::internal_get_memory_index_scale(self),
2729
              );
2730
            } else {
2731
0
              offset = offset.wrapping_add(
2732
0
                (get_register_value(index_reg, element_index, 4)? as i32 as u64)
2733
0
                  << instruction_internal::internal_get_memory_index_scale(self),
2734
              );
2735
            }
2736
          } else {
2737
            offset =
2738
0
              offset.wrapping_add(get_register_value(index_reg, 0, 0)? << instruction_internal::internal_get_memory_index_scale(self));
2739
          }
2740
0
        }
2741
        #[cfg(feature = "mvex")]
2742
        {
2743
          const _: () = assert!(Code::MVEX_Vloadunpackhd_zmm_k1_mt as u32 + 1 == Code::MVEX_Vloadunpackhq_zmm_k1_mt as u32);
2744
          const _: () = assert!(Code::MVEX_Vloadunpackhd_zmm_k1_mt as u32 + 2 == Code::MVEX_Vpackstorehd_mt_k1_zmm as u32);
2745
          const _: () = assert!(Code::MVEX_Vloadunpackhd_zmm_k1_mt as u32 + 3 == Code::MVEX_Vpackstorehq_mt_k1_zmm as u32);
2746
          const _: () = assert!(Code::MVEX_Vloadunpackhd_zmm_k1_mt as u32 + 4 == Code::MVEX_Vloadunpackhps_zmm_k1_mt as u32);
2747
          const _: () = assert!(Code::MVEX_Vloadunpackhd_zmm_k1_mt as u32 + 5 == Code::MVEX_Vloadunpackhpd_zmm_k1_mt as u32);
2748
          const _: () = assert!(Code::MVEX_Vloadunpackhd_zmm_k1_mt as u32 + 6 == Code::MVEX_Vpackstorehps_mt_k1_zmm as u32);
2749
          const _: () = assert!(Code::MVEX_Vloadunpackhd_zmm_k1_mt as u32 + 7 == Code::MVEX_Vpackstorehpd_mt_k1_zmm as u32);
2750
          if code >= Code::MVEX_Vloadunpackhd_zmm_k1_mt && code <= Code::MVEX_Vpackstorehpd_mt_k1_zmm {
2751
            offset = offset.wrapping_sub(0x40);
2752
          }
2753
        }
2754
0
        offset &= offset_mask;
2755
0
        if !code.ignores_segment() {
2756
0
          get_register_value(self.memory_segment(), 0, 0)?.wrapping_add(offset)
2757
        } else {
2758
0
          offset
2759
        }
2760
      }
2761
    })
2762
0
  }
2763
}
2764
2765
/// Contains the FPU `TOP` increment, whether it's conditional and whether the instruction writes to `TOP`
2766
#[cfg(feature = "instr_info")]
2767
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Hash)]
2768
pub struct FpuStackIncrementInfo {
2769
  increment: i32,
2770
  conditional: bool,
2771
  writes_top: bool,
2772
}
2773
2774
#[cfg(feature = "instr_info")]
2775
impl FpuStackIncrementInfo {
2776
  /// Constructor
2777
  #[must_use]
2778
  #[inline]
2779
0
  pub const fn new(increment: i32, conditional: bool, writes_top: bool) -> Self {
2780
0
    Self { increment, conditional, writes_top }
2781
0
  }
2782
2783
  /// Used if [`writes_top()`] is `true`:
2784
  ///
2785
  /// Value added to `TOP`.
2786
  ///
2787
  /// This is negative if it pushes one or more values and positive if it pops one or more values
2788
  /// and `0` if it writes to `TOP` (eg. `FLDENV`, etc) without pushing/popping anything.
2789
  ///
2790
  /// [`writes_top()`]: #method.writes_top
2791
  #[must_use]
2792
  #[inline]
2793
0
  pub const fn increment(&self) -> i32 {
2794
0
    self.increment
2795
0
  }
2796
2797
  /// `true` if it's a conditional push/pop (eg. `FPTAN` or `FSINCOS`)
2798
  #[must_use]
2799
  #[inline]
2800
0
  pub const fn conditional(&self) -> bool {
2801
0
    self.conditional
2802
0
  }
2803
2804
  /// `true` if `TOP` is written (it's a conditional/unconditional push/pop, `FNSAVE`, `FLDENV`, etc)
2805
  #[must_use]
2806
  #[inline]
2807
0
  pub const fn writes_top(&self) -> bool {
2808
0
    self.writes_top
2809
0
  }
2810
}
2811
2812
#[cfg(feature = "instr_info")]
2813
impl Instruction {
2814
  /// Gets the number of bytes added to `SP`/`ESP`/`RSP` or 0 if it's not an instruction that pushes or pops data. This method assumes
2815
  /// the instruction doesn't change the privilege level (eg. `IRET/D/Q`). If it's the `LEAVE` instruction, this method returns 0.
2816
  ///
2817
  /// # Examples
2818
  ///
2819
  /// ```
2820
  /// use iced_x86::*;
2821
  ///
2822
  /// // pushfq
2823
  /// let bytes = b"\x9C";
2824
  /// let mut decoder = Decoder::new(64, bytes, DecoderOptions::NONE);
2825
  /// let instr = decoder.decode();
2826
  ///
2827
  /// assert!(instr.is_stack_instruction());
2828
  /// assert_eq!(instr.stack_pointer_increment(), -8);
2829
  /// ```
2830
  #[must_use]
2831
  #[allow(clippy::missing_inline_in_public_items)]
2832
0
  pub fn stack_pointer_increment(&self) -> i32 {
2833
    #[cfg_attr(feature = "cargo-fmt", rustfmt::skip)]
2834
    #[allow(clippy::match_single_binding)]
2835
0
    match self.code() {
2836
      // GENERATOR-BEGIN: StackPointerIncrementTable
2837
      // ⚠️This was generated by GENERATOR!🦹‍♂️
2838
0
      Code::Pushad => -32,
2839
      Code::Pushaw
2840
0
      | Code::Call_m1664 => -16,
2841
      Code::Push_r64
2842
      | Code::Pushq_imm32
2843
      | Code::Pushq_imm8
2844
      | Code::Call_ptr1632
2845
      | Code::Pushfq
2846
      | Code::Call_rel32_64
2847
      | Code::Call_rm64
2848
      | Code::Call_m1632
2849
      | Code::Push_rm64
2850
      | Code::Pushq_FS
2851
0
      | Code::Pushq_GS => -8,
2852
      Code::Pushd_ES
2853
      | Code::Pushd_CS
2854
      | Code::Pushd_SS
2855
      | Code::Pushd_DS
2856
      | Code::Push_r32
2857
      | Code::Pushd_imm32
2858
      | Code::Pushd_imm8
2859
      | Code::Call_ptr1616
2860
      | Code::Pushfd
2861
      | Code::Call_rel32_32
2862
      | Code::Call_rm32
2863
      | Code::Call_m1616
2864
      | Code::Push_rm32
2865
      | Code::Pushd_FS
2866
0
      | Code::Pushd_GS => -4,
2867
      Code::Pushw_ES
2868
      | Code::Pushw_CS
2869
      | Code::Pushw_SS
2870
      | Code::Pushw_DS
2871
      | Code::Push_r16
2872
      | Code::Push_imm16
2873
      | Code::Pushw_imm8
2874
      | Code::Pushfw
2875
      | Code::Call_rel16
2876
      | Code::Call_rm16
2877
      | Code::Push_rm16
2878
      | Code::Pushw_FS
2879
0
      | Code::Pushw_GS => -2,
2880
      Code::Popw_ES
2881
      | Code::Popw_CS
2882
      | Code::Popw_SS
2883
      | Code::Popw_DS
2884
      | Code::Pop_r16
2885
      | Code::Pop_rm16
2886
      | Code::Popfw
2887
      | Code::Retnw
2888
      | Code::Popw_FS
2889
0
      | Code::Popw_GS => 2,
2890
      Code::Popd_ES
2891
      | Code::Popd_SS
2892
      | Code::Popd_DS
2893
      | Code::Pop_r32
2894
      | Code::Pop_rm32
2895
      | Code::Popfd
2896
      | Code::Retnd
2897
      | Code::Retfw
2898
      | Code::Popd_FS
2899
0
      | Code::Popd_GS => 4,
2900
      Code::Pop_r64
2901
      | Code::Pop_rm64
2902
      | Code::Popfq
2903
      | Code::Retnq
2904
      | Code::Retfd
2905
      | Code::Popq_FS
2906
0
      | Code::Popq_GS => 8,
2907
      Code::Popaw
2908
0
      | Code::Retfq => 16,
2909
0
      Code::Uiret => 24,
2910
0
      Code::Popad => 32,
2911
0
      Code::Iretq => 40,
2912
      Code::Eretu
2913
0
      | Code::Erets => 48,
2914
0
      Code::Enterw_imm16_imm8 => -(2 + (self.immediate8_2nd() as i32 & 0x1F) * 2 + self.immediate16() as i32),
2915
0
      Code::Enterd_imm16_imm8 => -(4 + (self.immediate8_2nd() as i32 & 0x1F) * 4 + self.immediate16() as i32),
2916
0
      Code::Enterq_imm16_imm8 => -(8 + (self.immediate8_2nd() as i32 & 0x1F) * 8 + self.immediate16() as i32),
2917
0
      Code::Iretw => if self.code_size() == CodeSize::Code64 { 2 * 5 } else { 2 * 3 },
2918
0
      Code::Iretd => if self.code_size() == CodeSize::Code64 { 4 * 5 } else { 4 * 3 },
2919
0
      Code::Retnw_imm16 => 2 + self.immediate16() as i32,
2920
      Code::Retnd_imm16
2921
0
      | Code::Retfw_imm16 => 4 + self.immediate16() as i32,
2922
      Code::Retnq_imm16
2923
0
      | Code::Retfd_imm16 => 8 + self.immediate16() as i32,
2924
0
      Code::Retfq_imm16 => 16 + self.immediate16() as i32,
2925
      // GENERATOR-END: StackPointerIncrementTable
2926
0
      _ => 0,
2927
    }
2928
0
  }
2929
2930
  /// Gets the FPU status word's `TOP` increment value and whether it's a conditional or unconditional push/pop
2931
  /// and whether `TOP` is written.
2932
  ///
2933
  /// # Examples
2934
  ///
2935
  /// ```
2936
  /// use iced_x86::*;
2937
  ///
2938
  /// // ficomp dword ptr [rax]
2939
  /// let bytes = b"\xDA\x18";
2940
  /// let mut decoder = Decoder::new(64, bytes, DecoderOptions::NONE);
2941
  /// let instr = decoder.decode();
2942
  ///
2943
  /// let info = instr.fpu_stack_increment_info();
2944
  /// // It pops the stack once
2945
  /// assert_eq!(info.increment(), 1);
2946
  /// assert!(!info.conditional());
2947
  /// assert!(info.writes_top());
2948
  /// ```
2949
  #[must_use]
2950
  #[allow(clippy::missing_inline_in_public_items)]
2951
0
  pub fn fpu_stack_increment_info(&self) -> FpuStackIncrementInfo {
2952
    #[cfg_attr(feature = "cargo-fmt", rustfmt::skip)]
2953
    #[allow(clippy::match_single_binding)]
2954
0
    match self.code() {
2955
      // GENERATOR-BEGIN: FpuStackIncrementInfoTable
2956
      // ⚠️This was generated by GENERATOR!🦹‍♂️
2957
      Code::Fld_m32fp
2958
      | Code::Fld_sti
2959
      | Code::Fld1
2960
      | Code::Fldl2t
2961
      | Code::Fldl2e
2962
      | Code::Fldpi
2963
      | Code::Fldlg2
2964
      | Code::Fldln2
2965
      | Code::Fldz
2966
      | Code::Fxtract
2967
      | Code::Fdecstp
2968
      | Code::Fild_m32int
2969
      | Code::Fld_m80fp
2970
      | Code::Fld_m64fp
2971
      | Code::Fild_m16int
2972
      | Code::Fbld_m80bcd
2973
      | Code::Fild_m64int
2974
0
      => FpuStackIncrementInfo { increment: -1, conditional: false, writes_top: true },
2975
      Code::Fptan
2976
      | Code::Fsincos
2977
0
      => FpuStackIncrementInfo { increment: -1, conditional: true, writes_top: true },
2978
      Code::Fldenv_m14byte
2979
      | Code::Fldenv_m28byte
2980
      | Code::Fninit
2981
      | Code::Finit
2982
      | Code::Frstor_m94byte
2983
      | Code::Frstor_m108byte
2984
      | Code::Fnsave_m94byte
2985
      | Code::Fsave_m94byte
2986
      | Code::Fnsave_m108byte
2987
      | Code::Fsave_m108byte
2988
0
      => FpuStackIncrementInfo { increment: 0, conditional: false, writes_top: true },
2989
      Code::Fcomp_m32fp
2990
      | Code::Fcomp_st0_sti
2991
      | Code::Fstp_m32fp
2992
      | Code::Fstpnce_sti
2993
      | Code::Fyl2x
2994
      | Code::Fpatan
2995
      | Code::Fincstp
2996
      | Code::Fyl2xp1
2997
      | Code::Ficomp_m32int
2998
      | Code::Fisttp_m32int
2999
      | Code::Fistp_m32int
3000
      | Code::Fstp_m80fp
3001
      | Code::Fcomp_m64fp
3002
      | Code::Fcomp_st0_sti_DCD8
3003
      | Code::Fisttp_m64int
3004
      | Code::Fstp_m64fp
3005
      | Code::Fstp_sti
3006
      | Code::Fucomp_st0_sti
3007
      | Code::Ficomp_m16int
3008
      | Code::Faddp_sti_st0
3009
      | Code::Fmulp_sti_st0
3010
      | Code::Fcomp_st0_sti_DED0
3011
      | Code::Fsubrp_sti_st0
3012
      | Code::Fsubp_sti_st0
3013
      | Code::Fdivrp_sti_st0
3014
      | Code::Fdivp_sti_st0
3015
      | Code::Fisttp_m16int
3016
      | Code::Fistp_m16int
3017
      | Code::Fbstp_m80bcd
3018
      | Code::Fistp_m64int
3019
      | Code::Ffreep_sti
3020
      | Code::Fstp_sti_DFD0
3021
      | Code::Fstp_sti_DFD8
3022
      | Code::Fucomip_st0_sti
3023
      | Code::Fcomip_st0_sti
3024
      | Code::Ftstp
3025
0
      => FpuStackIncrementInfo { increment: 1, conditional: false, writes_top: true },
3026
      Code::Fucompp
3027
      | Code::Fcompp
3028
0
      => FpuStackIncrementInfo { increment: 2, conditional: false, writes_top: true },
3029
      // GENERATOR-END: FpuStackIncrementInfoTable
3030
0
      _ => FpuStackIncrementInfo::default(),
3031
    }
3032
0
  }
3033
3034
  /// Instruction encoding, eg. Legacy, 3DNow!, VEX, EVEX, XOP
3035
  ///
3036
  /// # Examples
3037
  ///
3038
  /// ```
3039
  /// use iced_x86::*;
3040
  ///
3041
  /// // vmovaps xmm1,xmm5
3042
  /// let bytes = b"\xC5\xF8\x28\xCD";
3043
  /// let mut decoder = Decoder::new(64, bytes, DecoderOptions::NONE);
3044
  /// let instr = decoder.decode();
3045
  ///
3046
  /// assert_eq!(instr.encoding(), EncodingKind::VEX);
3047
  /// ```
3048
  #[must_use]
3049
  #[inline]
3050
0
  pub fn encoding(&self) -> EncodingKind {
3051
0
    self.code().encoding()
3052
0
  }
3053
3054
  /// Gets the CPU or CPUID feature flags
3055
  ///
3056
  /// # Examples
3057
  ///
3058
  /// ```
3059
  /// use iced_x86::*;
3060
  ///
3061
  /// // vmovaps xmm1,xmm5
3062
  /// // vmovaps xmm10{k3}{z},xmm19
3063
  /// let bytes = b"\xC5\xF8\x28\xCD\x62\x31\x7C\x8B\x28\xD3";
3064
  /// let mut decoder = Decoder::new(64, bytes, DecoderOptions::NONE);
3065
  ///
3066
  /// // vmovaps xmm1,xmm5
3067
  /// let instr = decoder.decode();
3068
  /// let cpuid = instr.cpuid_features();
3069
  /// assert_eq!(cpuid.len(), 1);
3070
  /// assert_eq!(cpuid[0], CpuidFeature::AVX);
3071
  ///
3072
  /// // vmovaps xmm10{k3}{z},xmm19
3073
  /// let instr = decoder.decode();
3074
  /// let cpuid = instr.cpuid_features();
3075
  /// assert_eq!(cpuid.len(), 2);
3076
  /// assert_eq!(cpuid[0], CpuidFeature::AVX512VL);
3077
  /// assert_eq!(cpuid[1], CpuidFeature::AVX512F);
3078
  /// ```
3079
  #[must_use]
3080
  #[allow(clippy::missing_inline_in_public_items)]
3081
0
  pub fn cpuid_features(&self) -> &'static [CpuidFeature] {
3082
0
    self.code().cpuid_features()
3083
0
  }
3084
3085
  /// Control flow info
3086
  ///
3087
  /// # Examples
3088
  ///
3089
  /// ```
3090
  /// use iced_x86::*;
3091
  ///
3092
  /// // or ecx,esi
3093
  /// // ud0 rcx,rsi
3094
  /// // call rcx
3095
  /// let bytes = b"\x0B\xCE\x48\x0F\xFF\xCE\xFF\xD1";
3096
  /// let mut decoder = Decoder::new(64, bytes, DecoderOptions::NONE);
3097
  ///
3098
  /// // or ecx,esi
3099
  /// let instr = decoder.decode();
3100
  /// assert_eq!(instr.flow_control(), FlowControl::Next);
3101
  ///
3102
  /// // ud0 rcx,rsi
3103
  /// let instr = decoder.decode();
3104
  /// assert_eq!(instr.flow_control(), FlowControl::Exception);
3105
  ///
3106
  /// // call rcx
3107
  /// let instr = decoder.decode();
3108
  /// assert_eq!(instr.flow_control(), FlowControl::IndirectCall);
3109
  /// ```
3110
  #[must_use]
3111
  #[inline]
3112
0
  pub fn flow_control(&self) -> FlowControl {
3113
0
    self.code().flow_control()
3114
0
  }
3115
3116
  /// `true` if it's a privileged instruction (all CPL=0 instructions (except `VMCALL`) and IOPL instructions `IN`, `INS`, `OUT`, `OUTS`, `CLI`, `STI`)
3117
  #[must_use]
3118
  #[inline]
3119
0
  pub fn is_privileged(&self) -> bool {
3120
0
    self.code().is_privileged()
3121
0
  }
3122
3123
  /// `true` if this is an instruction that implicitly uses the stack pointer (`SP`/`ESP`/`RSP`), eg. `CALL`, `PUSH`, `POP`, `RET`, etc.
3124
  /// See also [`stack_pointer_increment()`]
3125
  ///
3126
  /// [`stack_pointer_increment()`]: #method.stack_pointer_increment
3127
  ///
3128
  /// # Examples
3129
  ///
3130
  /// ```
3131
  /// use iced_x86::*;
3132
  ///
3133
  /// // or ecx,esi
3134
  /// // push rax
3135
  /// let bytes = b"\x0B\xCE\x50";
3136
  /// let mut decoder = Decoder::new(64, bytes, DecoderOptions::NONE);
3137
  ///
3138
  /// // or ecx,esi
3139
  /// let instr = decoder.decode();
3140
  /// assert!(!instr.is_stack_instruction());
3141
  ///
3142
  /// // push rax
3143
  /// let instr = decoder.decode();
3144
  /// assert!(instr.is_stack_instruction());
3145
  /// assert_eq!(instr.stack_pointer_increment(), -8);
3146
  /// ```
3147
  #[must_use]
3148
  #[inline]
3149
0
  pub fn is_stack_instruction(&self) -> bool {
3150
0
    self.code().is_stack_instruction()
3151
0
  }
3152
3153
  /// `true` if it's an instruction that saves or restores too many registers (eg. `FXRSTOR`, `XSAVE`, etc).
3154
  #[must_use]
3155
  #[inline]
3156
0
  pub fn is_save_restore_instruction(&self) -> bool {
3157
0
    self.code().is_save_restore_instruction()
3158
0
  }
3159
3160
  /// `true` if it's a "string" instruction, such as `MOVS`, `LODS`, `SCAS`, etc.
3161
  #[must_use]
3162
  #[inline]
3163
0
  pub const fn is_string_instruction(&self) -> bool {
3164
0
    self.code().is_string_instruction()
3165
0
  }
3166
3167
  #[must_use]
3168
0
  fn rflags_info(&self) -> RflagsInfo {
3169
0
    let flags1 = crate::info::info_table::TABLE[self.code() as usize].0;
3170
0
    let implied_access = (flags1 >> InfoFlags1::IMPLIED_ACCESS_SHIFT) & InfoFlags1::IMPLIED_ACCESS_MASK;
3171
    const _: () = assert!(ImpliedAccess::Shift_Ib_MASK1FMOD9 as u32 + 1 == ImpliedAccess::Shift_Ib_MASK1FMOD11 as u32);
3172
    const _: () = assert!(ImpliedAccess::Shift_Ib_MASK1FMOD9 as u32 + 2 == ImpliedAccess::Shift_Ib_MASK1F as u32);
3173
    const _: () = assert!(ImpliedAccess::Shift_Ib_MASK1FMOD9 as u32 + 3 == ImpliedAccess::Shift_Ib_MASK3F as u32);
3174
    const _: () = assert!(ImpliedAccess::Shift_Ib_MASK1FMOD9 as u32 + 4 == ImpliedAccess::Clear_rflags as u32);
3175
    // SAFETY: The table is generated and only contains valid enum variants
3176
0
    let result = unsafe { mem::transmute(((flags1 >> InfoFlags1::RFLAGS_INFO_SHIFT) & InfoFlags1::RFLAGS_INFO_MASK) as u8) };
3177
0
    let e = implied_access.wrapping_sub(ImpliedAccess::Shift_Ib_MASK1FMOD9 as u32);
3178
0
    match e {
3179
      0 | 1 => {
3180
        #[allow(clippy::eq_op)]
3181
        const _: () = assert!(ImpliedAccess::Shift_Ib_MASK1FMOD9 as u32 - ImpliedAccess::Shift_Ib_MASK1FMOD9 as u32 == 0);
3182
        const _: () = assert!(ImpliedAccess::Shift_Ib_MASK1FMOD11 as u32 - ImpliedAccess::Shift_Ib_MASK1FMOD9 as u32 == 1);
3183
0
        let m = if e == 0 { 9 } else { 17 };
3184
0
        match (self.immediate8() & 0x1F) % m {
3185
0
          0 => return RflagsInfo::None,
3186
0
          1 => return RflagsInfo::R_c_W_co,
3187
0
          _ => {}
3188
        }
3189
      }
3190
      2 | 3 => {
3191
        const _: () = assert!(ImpliedAccess::Shift_Ib_MASK1F as u32 - ImpliedAccess::Shift_Ib_MASK1FMOD9 as u32 == 2);
3192
        const _: () = assert!(ImpliedAccess::Shift_Ib_MASK3F as u32 - ImpliedAccess::Shift_Ib_MASK1FMOD9 as u32 == 3);
3193
0
        let mask = if e == 2 { 0x1F } else { 0x3F };
3194
0
        match self.immediate8() & mask {
3195
0
          0 => return RflagsInfo::None,
3196
          1 => {
3197
0
            if result == RflagsInfo::W_c_U_o {
3198
0
              return RflagsInfo::W_co;
3199
0
            } else if result == RflagsInfo::R_c_W_c_U_o {
3200
0
              return RflagsInfo::R_c_W_co;
3201
            } else {
3202
0
              debug_assert_eq!(result, RflagsInfo::W_cpsz_U_ao);
3203
0
              return RflagsInfo::W_copsz_U_a;
3204
            }
3205
          }
3206
0
          _ => {}
3207
        }
3208
      }
3209
      4 => {
3210
        const _: () = assert!(ImpliedAccess::Clear_rflags as u32 - ImpliedAccess::Shift_Ib_MASK1FMOD9 as u32 == 4);
3211
0
        if self.op0_register() == self.op1_register() && self.op0_kind() == OpKind::Register && self.op1_kind() == OpKind::Register {
3212
0
          if self.mnemonic() == Mnemonic::Xor {
3213
0
            return RflagsInfo::C_cos_S_pz_U_a;
3214
          } else {
3215
0
            return RflagsInfo::C_acos_S_pz;
3216
          }
3217
0
        }
3218
      }
3219
0
      _ => {}
3220
    }
3221
0
    result
3222
0
  }
3223
3224
  /// All flags that are read by the CPU when executing the instruction.
3225
  /// This method returns an [`RflagsBits`] value. See also [`rflags_modified()`].
3226
  ///
3227
  /// [`RflagsBits`]: struct.RflagsBits.html
3228
  /// [`rflags_modified()`]: #method.rflags_modified
3229
  ///
3230
  /// # Examples
3231
  ///
3232
  /// ```
3233
  /// use iced_x86::*;
3234
  ///
3235
  /// // adc rsi,rcx
3236
  /// // xor rdi,5Ah
3237
  /// let bytes = b"\x48\x11\xCE\x48\x83\xF7\x5A";
3238
  /// let mut decoder = Decoder::new(64, bytes, DecoderOptions::NONE);
3239
  ///
3240
  /// // adc rsi,rcx
3241
  /// let instr = decoder.decode();
3242
  /// assert_eq!(instr.rflags_read(), RflagsBits::CF);
3243
  /// assert_eq!(instr.rflags_written(), RflagsBits::OF | RflagsBits::SF | RflagsBits::ZF | RflagsBits::AF | RflagsBits::CF | RflagsBits::PF);
3244
  /// assert_eq!(instr.rflags_cleared(), RflagsBits::NONE);
3245
  /// assert_eq!(instr.rflags_set(), RflagsBits::NONE);
3246
  /// assert_eq!(instr.rflags_undefined(), RflagsBits::NONE);
3247
  /// assert_eq!(instr.rflags_modified(), RflagsBits::OF | RflagsBits::SF | RflagsBits::ZF | RflagsBits::AF | RflagsBits::CF | RflagsBits::PF);
3248
  ///
3249
  /// // xor rdi,5Ah
3250
  /// let instr = decoder.decode();
3251
  /// assert_eq!(instr.rflags_read(), RflagsBits::NONE);
3252
  /// assert_eq!(instr.rflags_written(), RflagsBits::SF | RflagsBits::ZF | RflagsBits::PF);
3253
  /// assert_eq!(instr.rflags_cleared(), RflagsBits::OF | RflagsBits::CF);
3254
  /// assert_eq!(instr.rflags_set(), RflagsBits::NONE);
3255
  /// assert_eq!(instr.rflags_undefined(), RflagsBits::AF);
3256
  /// assert_eq!(instr.rflags_modified(), RflagsBits::OF | RflagsBits::SF | RflagsBits::ZF | RflagsBits::AF | RflagsBits::CF | RflagsBits::PF);
3257
  /// ```
3258
  #[must_use]
3259
  #[inline]
3260
0
  pub fn rflags_read(&self) -> u32 {
3261
0
    crate::info::rflags_table::FLAGS_READ[self.rflags_info() as usize] as u32
3262
0
  }
3263
3264
  /// All flags that are written by the CPU, except those flags that are known to be undefined, always set or always cleared.
3265
  /// This method returns an [`RflagsBits`] value. See also [`rflags_modified()`].
3266
  ///
3267
  /// [`RflagsBits`]: struct.RflagsBits.html
3268
  /// [`rflags_modified()`]: #method.rflags_modified
3269
  ///
3270
  /// # Examples
3271
  ///
3272
  /// ```
3273
  /// use iced_x86::*;
3274
  ///
3275
  /// // adc rsi,rcx
3276
  /// // xor rdi,5Ah
3277
  /// let bytes = b"\x48\x11\xCE\x48\x83\xF7\x5A";
3278
  /// let mut decoder = Decoder::new(64, bytes, DecoderOptions::NONE);
3279
  ///
3280
  /// // adc rsi,rcx
3281
  /// let instr = decoder.decode();
3282
  /// assert_eq!(instr.rflags_read(), RflagsBits::CF);
3283
  /// assert_eq!(instr.rflags_written(), RflagsBits::OF | RflagsBits::SF | RflagsBits::ZF | RflagsBits::AF | RflagsBits::CF | RflagsBits::PF);
3284
  /// assert_eq!(instr.rflags_cleared(), RflagsBits::NONE);
3285
  /// assert_eq!(instr.rflags_set(), RflagsBits::NONE);
3286
  /// assert_eq!(instr.rflags_undefined(), RflagsBits::NONE);
3287
  /// assert_eq!(instr.rflags_modified(), RflagsBits::OF | RflagsBits::SF | RflagsBits::ZF | RflagsBits::AF | RflagsBits::CF | RflagsBits::PF);
3288
  ///
3289
  /// // xor rdi,5Ah
3290
  /// let instr = decoder.decode();
3291
  /// assert_eq!(instr.rflags_read(), RflagsBits::NONE);
3292
  /// assert_eq!(instr.rflags_written(), RflagsBits::SF | RflagsBits::ZF | RflagsBits::PF);
3293
  /// assert_eq!(instr.rflags_cleared(), RflagsBits::OF | RflagsBits::CF);
3294
  /// assert_eq!(instr.rflags_set(), RflagsBits::NONE);
3295
  /// assert_eq!(instr.rflags_undefined(), RflagsBits::AF);
3296
  /// assert_eq!(instr.rflags_modified(), RflagsBits::OF | RflagsBits::SF | RflagsBits::ZF | RflagsBits::AF | RflagsBits::CF | RflagsBits::PF);
3297
  /// ```
3298
  #[must_use]
3299
  #[inline]
3300
0
  pub fn rflags_written(&self) -> u32 {
3301
0
    crate::info::rflags_table::FLAGS_WRITTEN[self.rflags_info() as usize] as u32
3302
0
  }
3303
3304
  /// All flags that are always cleared by the CPU.
3305
  /// This method returns an [`RflagsBits`] value. See also [`rflags_modified()`].
3306
  ///
3307
  /// [`RflagsBits`]: struct.RflagsBits.html
3308
  /// [`rflags_modified()`]: #method.rflags_modified
3309
  ///
3310
  /// # Examples
3311
  ///
3312
  /// ```
3313
  /// use iced_x86::*;
3314
  ///
3315
  /// // adc rsi,rcx
3316
  /// // xor rdi,5Ah
3317
  /// let bytes = b"\x48\x11\xCE\x48\x83\xF7\x5A";
3318
  /// let mut decoder = Decoder::new(64, bytes, DecoderOptions::NONE);
3319
  ///
3320
  /// // adc rsi,rcx
3321
  /// let instr = decoder.decode();
3322
  /// assert_eq!(instr.rflags_read(), RflagsBits::CF);
3323
  /// assert_eq!(instr.rflags_written(), RflagsBits::OF | RflagsBits::SF | RflagsBits::ZF | RflagsBits::AF | RflagsBits::CF | RflagsBits::PF);
3324
  /// assert_eq!(instr.rflags_cleared(), RflagsBits::NONE);
3325
  /// assert_eq!(instr.rflags_set(), RflagsBits::NONE);
3326
  /// assert_eq!(instr.rflags_undefined(), RflagsBits::NONE);
3327
  /// assert_eq!(instr.rflags_modified(), RflagsBits::OF | RflagsBits::SF | RflagsBits::ZF | RflagsBits::AF | RflagsBits::CF | RflagsBits::PF);
3328
  ///
3329
  /// // xor rdi,5Ah
3330
  /// let instr = decoder.decode();
3331
  /// assert_eq!(instr.rflags_read(), RflagsBits::NONE);
3332
  /// assert_eq!(instr.rflags_written(), RflagsBits::SF | RflagsBits::ZF | RflagsBits::PF);
3333
  /// assert_eq!(instr.rflags_cleared(), RflagsBits::OF | RflagsBits::CF);
3334
  /// assert_eq!(instr.rflags_set(), RflagsBits::NONE);
3335
  /// assert_eq!(instr.rflags_undefined(), RflagsBits::AF);
3336
  /// assert_eq!(instr.rflags_modified(), RflagsBits::OF | RflagsBits::SF | RflagsBits::ZF | RflagsBits::AF | RflagsBits::CF | RflagsBits::PF);
3337
  /// ```
3338
  #[must_use]
3339
  #[inline]
3340
0
  pub fn rflags_cleared(&self) -> u32 {
3341
0
    crate::info::rflags_table::FLAGS_CLEARED[self.rflags_info() as usize] as u32
3342
0
  }
3343
3344
  /// All flags that are always set by the CPU.
3345
  /// This method returns an [`RflagsBits`] value. See also [`rflags_modified()`].
3346
  ///
3347
  /// [`RflagsBits`]: struct.RflagsBits.html
3348
  /// [`rflags_modified()`]: #method.rflags_modified
3349
  ///
3350
  /// # Examples
3351
  ///
3352
  /// ```
3353
  /// use iced_x86::*;
3354
  ///
3355
  /// // adc rsi,rcx
3356
  /// // xor rdi,5Ah
3357
  /// let bytes = b"\x48\x11\xCE\x48\x83\xF7\x5A";
3358
  /// let mut decoder = Decoder::new(64, bytes, DecoderOptions::NONE);
3359
  ///
3360
  /// // adc rsi,rcx
3361
  /// let instr = decoder.decode();
3362
  /// assert_eq!(instr.rflags_read(), RflagsBits::CF);
3363
  /// assert_eq!(instr.rflags_written(), RflagsBits::OF | RflagsBits::SF | RflagsBits::ZF | RflagsBits::AF | RflagsBits::CF | RflagsBits::PF);
3364
  /// assert_eq!(instr.rflags_cleared(), RflagsBits::NONE);
3365
  /// assert_eq!(instr.rflags_set(), RflagsBits::NONE);
3366
  /// assert_eq!(instr.rflags_undefined(), RflagsBits::NONE);
3367
  /// assert_eq!(instr.rflags_modified(), RflagsBits::OF | RflagsBits::SF | RflagsBits::ZF | RflagsBits::AF | RflagsBits::CF | RflagsBits::PF);
3368
  ///
3369
  /// // xor rdi,5Ah
3370
  /// let instr = decoder.decode();
3371
  /// assert_eq!(instr.rflags_read(), RflagsBits::NONE);
3372
  /// assert_eq!(instr.rflags_written(), RflagsBits::SF | RflagsBits::ZF | RflagsBits::PF);
3373
  /// assert_eq!(instr.rflags_cleared(), RflagsBits::OF | RflagsBits::CF);
3374
  /// assert_eq!(instr.rflags_set(), RflagsBits::NONE);
3375
  /// assert_eq!(instr.rflags_undefined(), RflagsBits::AF);
3376
  /// assert_eq!(instr.rflags_modified(), RflagsBits::OF | RflagsBits::SF | RflagsBits::ZF | RflagsBits::AF | RflagsBits::CF | RflagsBits::PF);
3377
  /// ```
3378
  #[must_use]
3379
  #[inline]
3380
0
  pub fn rflags_set(&self) -> u32 {
3381
0
    crate::info::rflags_table::FLAGS_SET[self.rflags_info() as usize] as u32
3382
0
  }
3383
3384
  /// All flags that are undefined after executing the instruction.
3385
  /// This method returns an [`RflagsBits`] value. See also [`rflags_modified()`].
3386
  ///
3387
  /// [`RflagsBits`]: struct.RflagsBits.html
3388
  /// [`rflags_modified()`]: #method.rflags_modified
3389
  ///
3390
  /// # Examples
3391
  ///
3392
  /// ```
3393
  /// use iced_x86::*;
3394
  ///
3395
  /// // adc rsi,rcx
3396
  /// // xor rdi,5Ah
3397
  /// let bytes = b"\x48\x11\xCE\x48\x83\xF7\x5A";
3398
  /// let mut decoder = Decoder::new(64, bytes, DecoderOptions::NONE);
3399
  ///
3400
  /// // adc rsi,rcx
3401
  /// let instr = decoder.decode();
3402
  /// assert_eq!(instr.rflags_read(), RflagsBits::CF);
3403
  /// assert_eq!(instr.rflags_written(), RflagsBits::OF | RflagsBits::SF | RflagsBits::ZF | RflagsBits::AF | RflagsBits::CF | RflagsBits::PF);
3404
  /// assert_eq!(instr.rflags_cleared(), RflagsBits::NONE);
3405
  /// assert_eq!(instr.rflags_set(), RflagsBits::NONE);
3406
  /// assert_eq!(instr.rflags_undefined(), RflagsBits::NONE);
3407
  /// assert_eq!(instr.rflags_modified(), RflagsBits::OF | RflagsBits::SF | RflagsBits::ZF | RflagsBits::AF | RflagsBits::CF | RflagsBits::PF);
3408
  ///
3409
  /// // xor rdi,5Ah
3410
  /// let instr = decoder.decode();
3411
  /// assert_eq!(instr.rflags_read(), RflagsBits::NONE);
3412
  /// assert_eq!(instr.rflags_written(), RflagsBits::SF | RflagsBits::ZF | RflagsBits::PF);
3413
  /// assert_eq!(instr.rflags_cleared(), RflagsBits::OF | RflagsBits::CF);
3414
  /// assert_eq!(instr.rflags_set(), RflagsBits::NONE);
3415
  /// assert_eq!(instr.rflags_undefined(), RflagsBits::AF);
3416
  /// assert_eq!(instr.rflags_modified(), RflagsBits::OF | RflagsBits::SF | RflagsBits::ZF | RflagsBits::AF | RflagsBits::CF | RflagsBits::PF);
3417
  /// ```
3418
  #[must_use]
3419
  #[inline]
3420
0
  pub fn rflags_undefined(&self) -> u32 {
3421
0
    crate::info::rflags_table::FLAGS_UNDEFINED[self.rflags_info() as usize] as u32
3422
0
  }
3423
3424
  /// All flags that are modified by the CPU. This is `rflags_written() + rflags_cleared() + rflags_set() + rflags_undefined()`. This method returns an [`RflagsBits`] value.
3425
  ///
3426
  /// [`RflagsBits`]: struct.RflagsBits.html
3427
  ///
3428
  /// # Examples
3429
  ///
3430
  /// ```
3431
  /// use iced_x86::*;
3432
  ///
3433
  /// // adc rsi,rcx
3434
  /// // xor rdi,5Ah
3435
  /// let bytes = b"\x48\x11\xCE\x48\x83\xF7\x5A";
3436
  /// let mut decoder = Decoder::new(64, bytes, DecoderOptions::NONE);
3437
  ///
3438
  /// // adc rsi,rcx
3439
  /// let instr = decoder.decode();
3440
  /// assert_eq!(instr.rflags_read(), RflagsBits::CF);
3441
  /// assert_eq!(instr.rflags_written(), RflagsBits::OF | RflagsBits::SF | RflagsBits::ZF | RflagsBits::AF | RflagsBits::CF | RflagsBits::PF);
3442
  /// assert_eq!(instr.rflags_cleared(), RflagsBits::NONE);
3443
  /// assert_eq!(instr.rflags_set(), RflagsBits::NONE);
3444
  /// assert_eq!(instr.rflags_undefined(), RflagsBits::NONE);
3445
  /// assert_eq!(instr.rflags_modified(), RflagsBits::OF | RflagsBits::SF | RflagsBits::ZF | RflagsBits::AF | RflagsBits::CF | RflagsBits::PF);
3446
  ///
3447
  /// // xor rdi,5Ah
3448
  /// let instr = decoder.decode();
3449
  /// assert_eq!(instr.rflags_read(), RflagsBits::NONE);
3450
  /// assert_eq!(instr.rflags_written(), RflagsBits::SF | RflagsBits::ZF | RflagsBits::PF);
3451
  /// assert_eq!(instr.rflags_cleared(), RflagsBits::OF | RflagsBits::CF);
3452
  /// assert_eq!(instr.rflags_set(), RflagsBits::NONE);
3453
  /// assert_eq!(instr.rflags_undefined(), RflagsBits::AF);
3454
  /// assert_eq!(instr.rflags_modified(), RflagsBits::OF | RflagsBits::SF | RflagsBits::ZF | RflagsBits::AF | RflagsBits::CF | RflagsBits::PF);
3455
  /// ```
3456
  #[must_use]
3457
  #[inline]
3458
0
  pub fn rflags_modified(&self) -> u32 {
3459
0
    crate::info::rflags_table::FLAGS_MODIFIED[self.rflags_info() as usize] as u32
3460
0
  }
3461
3462
  /// Checks if it's a `Jcc SHORT` or `Jcc NEAR` instruction
3463
  #[must_use]
3464
  #[inline]
3465
0
  pub const fn is_jcc_short_or_near(&self) -> bool {
3466
0
    self.code().is_jcc_short_or_near()
3467
0
  }
3468
3469
  /// Checks if it's a `Jcc NEAR` instruction
3470
  #[must_use]
3471
  #[inline]
3472
0
  pub const fn is_jcc_near(&self) -> bool {
3473
0
    self.code().is_jcc_near()
3474
0
  }
3475
3476
  /// Checks if it's a `Jcc SHORT` instruction
3477
  #[must_use]
3478
  #[inline]
3479
0
  pub const fn is_jcc_short(&self) -> bool {
3480
0
    self.code().is_jcc_short()
3481
0
  }
3482
3483
  /// Checks if it's a `JMP SHORT` instruction
3484
  #[must_use]
3485
  #[inline]
3486
0
  pub const fn is_jmp_short(&self) -> bool {
3487
0
    self.code().is_jmp_short()
3488
0
  }
3489
3490
  /// Checks if it's a `JMP NEAR` instruction
3491
  #[must_use]
3492
  #[inline]
3493
0
  pub const fn is_jmp_near(&self) -> bool {
3494
0
    self.code().is_jmp_near()
3495
0
  }
3496
3497
  /// Checks if it's a `JMP SHORT` or a `JMP NEAR` instruction
3498
  #[must_use]
3499
  #[inline]
3500
0
  pub const fn is_jmp_short_or_near(&self) -> bool {
3501
0
    self.code().is_jmp_short_or_near()
3502
0
  }
3503
3504
  /// Checks if it's a `JMP FAR` instruction
3505
  #[must_use]
3506
  #[inline]
3507
0
  pub const fn is_jmp_far(&self) -> bool {
3508
0
    self.code().is_jmp_far()
3509
0
  }
3510
3511
  /// Checks if it's a `CALL NEAR` instruction
3512
  #[must_use]
3513
  #[inline]
3514
0
  pub const fn is_call_near(&self) -> bool {
3515
0
    self.code().is_call_near()
3516
0
  }
3517
3518
  /// Checks if it's a `CALL FAR` instruction
3519
  #[must_use]
3520
  #[inline]
3521
0
  pub const fn is_call_far(&self) -> bool {
3522
0
    self.code().is_call_far()
3523
0
  }
3524
3525
  /// Checks if it's a `JMP NEAR reg/[mem]` instruction
3526
  #[must_use]
3527
  #[inline]
3528
0
  pub const fn is_jmp_near_indirect(&self) -> bool {
3529
0
    self.code().is_jmp_near_indirect()
3530
0
  }
3531
3532
  /// Checks if it's a `JMP FAR [mem]` instruction
3533
  #[must_use]
3534
  #[inline]
3535
0
  pub const fn is_jmp_far_indirect(&self) -> bool {
3536
0
    self.code().is_jmp_far_indirect()
3537
0
  }
3538
3539
  /// Checks if it's a `CALL NEAR reg/[mem]` instruction
3540
  #[must_use]
3541
  #[inline]
3542
0
  pub const fn is_call_near_indirect(&self) -> bool {
3543
0
    self.code().is_call_near_indirect()
3544
0
  }
3545
3546
  /// Checks if it's a `CALL FAR [mem]` instruction
3547
  #[must_use]
3548
  #[inline]
3549
0
  pub const fn is_call_far_indirect(&self) -> bool {
3550
0
    self.code().is_call_far_indirect()
3551
0
  }
3552
3553
  /// Checks if it's a `JKccD SHORT` or `JKccD NEAR` instruction
3554
  #[must_use]
3555
  #[inline]
3556
  #[cfg(feature = "mvex")]
3557
  pub const fn is_jkcc_short_or_near(&self) -> bool {
3558
    self.code().is_jkcc_short_or_near()
3559
  }
3560
3561
  /// Checks if it's a `JKccD NEAR` instruction
3562
  #[must_use]
3563
  #[inline]
3564
  #[cfg(feature = "mvex")]
3565
  pub const fn is_jkcc_near(&self) -> bool {
3566
    self.code().is_jkcc_near()
3567
  }
3568
3569
  /// Checks if it's a `JKccD SHORT` instruction
3570
  #[must_use]
3571
  #[inline]
3572
  #[cfg(feature = "mvex")]
3573
  pub const fn is_jkcc_short(&self) -> bool {
3574
    self.code().is_jkcc_short()
3575
  }
3576
3577
  /// Checks if it's a `JCXZ SHORT`, `JECXZ SHORT` or `JRCXZ SHORT` instruction
3578
  #[must_use]
3579
  #[inline]
3580
0
  pub const fn is_jcx_short(&self) -> bool {
3581
0
    self.code().is_jcx_short()
3582
0
  }
3583
3584
  /// Checks if it's a `LOOPcc SHORT` instruction
3585
  #[must_use]
3586
  #[inline]
3587
0
  pub const fn is_loopcc(&self) -> bool {
3588
0
    self.code().is_loopcc()
3589
0
  }
3590
3591
  /// Checks if it's a `LOOP SHORT` instruction
3592
  #[must_use]
3593
  #[inline]
3594
0
  pub const fn is_loop(&self) -> bool {
3595
0
    self.code().is_loop()
3596
0
  }
3597
3598
  /// Negates the condition code, eg. `JE` -> `JNE`. Can be used if it's `Jcc`, `SETcc`, `CMOVcc`, `CMPccXADD`, `LOOPcc`
3599
  /// and does nothing if the instruction doesn't have a condition code.
3600
  ///
3601
  /// # Examples
3602
  ///
3603
  /// ```
3604
  /// use iced_x86::*;
3605
  ///
3606
  /// // setbe al
3607
  /// let bytes = b"\x0F\x96\xC0";
3608
  /// let mut decoder = Decoder::new(64, bytes, DecoderOptions::NONE);
3609
  ///
3610
  /// let mut instr = decoder.decode();
3611
  /// assert_eq!(instr.code(), Code::Setbe_rm8);
3612
  /// assert_eq!(instr.condition_code(), ConditionCode::be);
3613
  /// instr.negate_condition_code();
3614
  /// assert_eq!(instr.code(), Code::Seta_rm8);
3615
  /// assert_eq!(instr.condition_code(), ConditionCode::a);
3616
  /// ```
3617
  #[inline]
3618
0
  pub fn negate_condition_code(&mut self) {
3619
0
    self.set_code(self.code().negate_condition_code())
3620
0
  }
3621
3622
  /// Converts `Jcc/JMP NEAR` to `Jcc/JMP SHORT` and does nothing if it's not a `Jcc/JMP NEAR` instruction
3623
  ///
3624
  /// # Examples
3625
  ///
3626
  /// ```
3627
  /// use iced_x86::*;
3628
  ///
3629
  /// // jbe near ptr label
3630
  /// let bytes = b"\x0F\x86\x5A\xA5\x12\x34";
3631
  /// let mut decoder = Decoder::new(64, bytes, DecoderOptions::NONE);
3632
  ///
3633
  /// let mut instr = decoder.decode();
3634
  /// assert_eq!(instr.code(), Code::Jbe_rel32_64);
3635
  /// instr.as_short_branch();
3636
  /// assert_eq!(instr.code(), Code::Jbe_rel8_64);
3637
  /// instr.as_short_branch();
3638
  /// assert_eq!(instr.code(), Code::Jbe_rel8_64);
3639
  /// ```
3640
  #[inline]
3641
0
  pub fn as_short_branch(&mut self) {
3642
0
    self.set_code(self.code().as_short_branch())
3643
0
  }
3644
3645
  /// Converts `Jcc/JMP SHORT` to `Jcc/JMP NEAR` and does nothing if it's not a `Jcc/JMP SHORT` instruction
3646
  ///
3647
  /// # Examples
3648
  ///
3649
  /// ```
3650
  /// use iced_x86::*;
3651
  ///
3652
  /// // jbe short label
3653
  /// let bytes = b"\x76\x5A";
3654
  /// let mut decoder = Decoder::new(64, bytes, DecoderOptions::NONE);
3655
  ///
3656
  /// let mut instr = decoder.decode();
3657
  /// assert_eq!(instr.code(), Code::Jbe_rel8_64);
3658
  /// instr.as_near_branch();
3659
  /// assert_eq!(instr.code(), Code::Jbe_rel32_64);
3660
  /// instr.as_near_branch();
3661
  /// assert_eq!(instr.code(), Code::Jbe_rel32_64);
3662
  /// ```
3663
  #[inline]
3664
0
  pub fn as_near_branch(&mut self) {
3665
0
    self.set_code(self.code().as_near_branch())
3666
0
  }
3667
3668
  /// Gets the condition code if it's `Jcc`, `SETcc`, `CMOVcc`, `CMPccXADD`, `LOOPcc` else [`ConditionCode::None`] is returned
3669
  ///
3670
  /// [`ConditionCode::None`]: enum.ConditionCode.html#variant.None
3671
  ///
3672
  /// # Examples
3673
  ///
3674
  /// ```
3675
  /// use iced_x86::*;
3676
  ///
3677
  /// // setbe al
3678
  /// // jl short label
3679
  /// // cmovne ecx,esi
3680
  /// // nop
3681
  /// let bytes = b"\x0F\x96\xC0\x7C\x5A\x0F\x45\xCE\x90";
3682
  /// let mut decoder = Decoder::new(64, bytes, DecoderOptions::NONE);
3683
  ///
3684
  /// // setbe al
3685
  /// let instr = decoder.decode();
3686
  /// assert_eq!(instr.condition_code(), ConditionCode::be);
3687
  ///
3688
  /// // jl short label
3689
  /// let instr = decoder.decode();
3690
  /// assert_eq!(instr.condition_code(), ConditionCode::l);
3691
  ///
3692
  /// // cmovne ecx,esi
3693
  /// let instr = decoder.decode();
3694
  /// assert_eq!(instr.condition_code(), ConditionCode::ne);
3695
  ///
3696
  /// // nop
3697
  /// let instr = decoder.decode();
3698
  /// assert_eq!(instr.condition_code(), ConditionCode::None);
3699
  /// ```
3700
  #[must_use]
3701
  #[inline]
3702
0
  pub fn condition_code(&self) -> ConditionCode {
3703
0
    self.code().condition_code()
3704
0
  }
3705
}
3706
3707
#[cfg(all(feature = "encoder", feature = "op_code_info"))]
3708
impl Instruction {
3709
  /// Gets the [`OpCodeInfo`]
3710
  ///
3711
  /// [`OpCodeInfo`]: struct.OpCodeInfo.html
3712
  #[must_use]
3713
  #[inline]
3714
0
  pub fn op_code(&self) -> &'static OpCodeInfo {
3715
0
    self.code().op_code()
3716
0
  }
3717
}
3718
3719
impl Eq for Instruction {}
3720
3721
impl PartialEq<Instruction> for Instruction {
3722
  #[must_use]
3723
  #[allow(clippy::missing_inline_in_public_items)]
3724
0
  fn eq(&self, other: &Self) -> bool {
3725
0
    self.mem_displ == other.mem_displ
3726
0
      && ((self.flags1 ^ other.flags1) & !InstrFlags1::EQUALS_IGNORE_MASK) == 0
3727
0
      && self.immediate == other.immediate
3728
0
      && self.code == other.code
3729
0
      && self.mem_base_reg == other.mem_base_reg
3730
0
      && self.mem_index_reg == other.mem_index_reg
3731
0
      && self.regs == other.regs
3732
0
      && self.op_kinds == other.op_kinds
3733
0
      && self.scale == other.scale
3734
0
      && self.displ_size == other.displ_size
3735
0
      && self.pad == other.pad
3736
0
  }
3737
}
3738
3739
impl Hash for Instruction {
3740
  #[allow(clippy::missing_inline_in_public_items)]
3741
0
  fn hash<H: Hasher>(&self, state: &mut H) {
3742
0
    self.mem_displ.hash(state);
3743
0
    (self.flags1 & !InstrFlags1::EQUALS_IGNORE_MASK).hash(state);
3744
0
    self.immediate.hash(state);
3745
0
    self.code.hash(state);
3746
0
    self.mem_base_reg.hash(state);
3747
0
    self.mem_index_reg.hash(state);
3748
0
    self.regs.hash(state);
3749
0
    self.op_kinds.hash(state);
3750
0
    self.scale.hash(state);
3751
0
    self.displ_size.hash(state);
3752
0
    self.pad.hash(state);
3753
0
  }
3754
}
3755
3756
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
3757
struct FmtFormatterOutput<'a, 'b> {
3758
  f: &'a mut fmt::Formatter<'b>,
3759
  result: fmt::Result,
3760
}
3761
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
3762
impl<'a, 'b> FmtFormatterOutput<'a, 'b> {
3763
  fn new(f: &'a mut fmt::Formatter<'b>) -> Self {
3764
    Self { f, result: Ok(()) }
3765
  }
3766
}
3767
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
3768
impl FormatterOutput for FmtFormatterOutput<'_, '_> {
3769
  fn write(&mut self, text: &str, _kind: FormatterTextKind) {
3770
    if self.result.is_ok() {
3771
      self.result = self.f.write_str(text);
3772
    }
3773
  }
3774
}
3775
3776
#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm", feature = "fast_fmt"))]
3777
impl fmt::Display for Instruction {
3778
  #[allow(clippy::missing_inline_in_public_items)]
3779
  fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3780
    //
3781
    // if the order of #[cfg()] checks gets updated, also update the `display_trait()` test method
3782
    //
3783
    #[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
3784
    {
3785
      #[cfg(feature = "masm")]
3786
      let mut formatter = MasmFormatter::new();
3787
3788
      #[cfg(all(not(feature = "masm"), feature = "nasm"))]
3789
      let mut formatter = NasmFormatter::new();
3790
3791
      #[cfg(all(not(feature = "masm"), not(feature = "nasm"), feature = "intel"))]
3792
      let mut formatter = IntelFormatter::new();
3793
3794
      #[cfg(all(not(feature = "masm"), not(feature = "nasm"), not(feature = "intel"), feature = "gas"))]
3795
      let mut formatter = GasFormatter::new();
3796
3797
      let mut output = FmtFormatterOutput::new(f);
3798
      formatter.format(self, &mut output);
3799
      output.result
3800
    }
3801
    #[cfg(not(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm")))]
3802
    {
3803
      let mut formatter = FastFormatter::new();
3804
3805
      let mut output = alloc::string::String::new();
3806
      formatter.format(self, &mut output);
3807
      f.write_str(&output)
3808
    }
3809
  }
3810
}
3811
3812
struct OpKindIterator {
3813
  count: u8,
3814
  index: u8,
3815
  op_kinds: [OpKind; IcedConstants::MAX_OP_COUNT],
3816
}
3817
3818
impl OpKindIterator {
3819
0
  fn new(instruction: &Instruction) -> Self {
3820
    // `index`/`count` are `u8`
3821
    const _: () = assert!(IcedConstants::MAX_OP_COUNT <= core::u8::MAX as usize);
3822
0
    OpKindIterator {
3823
0
      count: instruction.op_count() as u8,
3824
0
      index: 0,
3825
0
      op_kinds: [instruction.op0_kind(), instruction.op1_kind(), instruction.op2_kind(), instruction.op3_kind(), instruction.op4_kind()],
3826
0
    }
3827
0
  }
3828
}
3829
3830
impl Iterator for OpKindIterator {
3831
  type Item = OpKind;
3832
3833
  #[inline]
3834
0
  fn next(&mut self) -> Option<Self::Item> {
3835
0
    let index = self.index;
3836
0
    if index < self.count {
3837
0
      self.index = index + 1;
3838
0
      Some(self.op_kinds[index as usize])
3839
    } else {
3840
0
      None
3841
    }
3842
0
  }
3843
3844
  #[inline]
3845
0
  fn size_hint(&self) -> (usize, Option<usize>) {
3846
0
    let len = self.count as usize - self.index as usize;
3847
0
    (len, Some(len))
3848
0
  }
3849
}
3850
3851
impl ExactSizeIterator for OpKindIterator {}
3852
impl FusedIterator for OpKindIterator {}
3853
3854
// We've documented that we only support serializing and deserializing data created by the same version of iced.
3855
// That means we can optimize bincode serialized instructions. It's wasting 35 bytes per serialized instruction
3856
// because it stores each enum variant in a u32. That's almost a full instruction instance wasted with padding.
3857
#[cfg(feature = "serde")]
3858
const _: () = {
3859
  #[cfg(not(feature = "std"))]
3860
  use alloc::string::String;
3861
  use core::marker::PhantomData;
3862
  use serde::de;
3863
  use serde::ser::SerializeStruct;
3864
  use serde::{Deserialize, Deserializer, Serialize, Serializer};
3865
3866
  // eg. json
3867
  const NUM_FIELDS_READABLE: usize = 13;
3868
  // eg. bincode
3869
  const NUM_FIELDS_BINARY: usize = 19;
3870
3871
  #[inline]
3872
  const fn is_human_readable(value: bool) -> bool {
3873
    // This feature is used to test the other code paths
3874
    if cfg!(feature = "__internal_flip") {
3875
      value ^ true
3876
    } else {
3877
      value
3878
    }
3879
  }
3880
3881
  impl Serialize for Instruction {
3882
    #[allow(clippy::missing_inline_in_public_items)]
3883
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
3884
    where
3885
      S: Serializer,
3886
    {
3887
      if is_human_readable(serializer.is_human_readable()) {
3888
        let mut serde_state = serializer.serialize_struct("Instruction", NUM_FIELDS_READABLE)?;
3889
        let mut fields = 0;
3890
        macro_rules! serialize {
3891
          ($field:ident) => {
3892
            serde_state.serialize_field(stringify!($field), &self.$field)?;
3893
            fields += 1;
3894
          };
3895
        }
3896
        serialize!(next_rip);
3897
        serialize!(mem_displ);
3898
        serialize!(flags1);
3899
        serialize!(immediate);
3900
        serialize!(code);
3901
        serialize!(mem_base_reg);
3902
        serialize!(mem_index_reg);
3903
        serialize!(regs);
3904
        serialize!(op_kinds);
3905
        serialize!(scale);
3906
        serialize!(displ_size);
3907
        serialize!(len);
3908
        serialize!(pad);
3909
        debug_assert_eq!(fields, NUM_FIELDS_READABLE);
3910
        serde_state.end()
3911
      } else {
3912
        let mut serde_state = serializer.serialize_struct("Instruction", NUM_FIELDS_BINARY)?;
3913
        let mut fields = 0;
3914
        macro_rules! serialize {
3915
          ($field:ident) => {
3916
            serde_state.serialize_field(stringify!($field), &self.$field)?;
3917
            fields += 1;
3918
          };
3919
          ($field:ident, $underlying_ty:ty) => {
3920
            serde_state.serialize_field(stringify!($field), &(self.$field as $underlying_ty))?;
3921
            fields += 1;
3922
          };
3923
          ($field:ident, $index:literal, $underlying_ty:ty) => {
3924
            serde_state.serialize_field(concat!(stringify!($field), stringify!($index)), &(self.$field[$index] as $underlying_ty))?;
3925
            fields += 1;
3926
          };
3927
        }
3928
        serialize!(next_rip);
3929
        serialize!(mem_displ);
3930
        serialize!(flags1);
3931
        serialize!(immediate);
3932
        serialize!(code, CodeUnderlyingType);
3933
        serialize!(mem_base_reg, RegisterUnderlyingType);
3934
        serialize!(mem_index_reg, RegisterUnderlyingType);
3935
        debug_assert_eq!(self.regs.len(), 4);
3936
        serialize!(regs, 0, RegisterUnderlyingType);
3937
        serialize!(regs, 1, RegisterUnderlyingType);
3938
        serialize!(regs, 2, RegisterUnderlyingType);
3939
        serialize!(regs, 3, RegisterUnderlyingType);
3940
        debug_assert_eq!(self.op_kinds.len(), 4);
3941
        serialize!(op_kinds, 0, OpKindUnderlyingType);
3942
        serialize!(op_kinds, 1, OpKindUnderlyingType);
3943
        serialize!(op_kinds, 2, OpKindUnderlyingType);
3944
        serialize!(op_kinds, 3, OpKindUnderlyingType);
3945
        serialize!(scale, InstrScaleUnderlyingType);
3946
        serialize!(displ_size);
3947
        serialize!(len);
3948
        serialize!(pad);
3949
        debug_assert_eq!(fields, NUM_FIELDS_BINARY);
3950
        serde_state.end()
3951
      }
3952
    }
3953
  }
3954
3955
  macro_rules! mk_struct_field_visitor {
3956
    () => {
3957
      struct StructFieldVisitor;
3958
      impl<'de> de::Visitor<'de> for StructFieldVisitor {
3959
        type Value = StructField;
3960
        #[inline]
3961
        fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
3962
          formatter.write_str("field identifier")
3963
        }
3964
        #[inline]
3965
        fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
3966
        where
3967
          E: de::Error,
3968
        {
3969
          if let Ok(v) = <usize as TryFrom<_>>::try_from(v) {
3970
            if let Ok(value) = <StructField as TryFrom<_>>::try_from(v) {
3971
              return Ok(value);
3972
            }
3973
          }
3974
          Err(de::Error::invalid_value(de::Unexpected::Unsigned(v), &"Invalid Instruction field value"))
3975
        }
3976
        #[inline]
3977
        fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
3978
        where
3979
          E: de::Error,
3980
        {
3981
          StructFieldVisitor::deserialize_name(v.as_bytes())
3982
        }
3983
        #[inline]
3984
        fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
3985
        where
3986
          E: de::Error,
3987
        {
3988
          StructFieldVisitor::deserialize_name(v)
3989
        }
3990
      }
3991
      impl StructFieldVisitor {
3992
        #[inline]
3993
        fn deserialize_name<E>(v: &[u8]) -> Result<StructField, E>
3994
        where
3995
          E: de::Error,
3996
        {
3997
          for (&name, value) in FIELDS.iter().zip(StructField::values()) {
3998
            if name.as_bytes() == v {
3999
              return Ok(value);
4000
            }
4001
          }
4002
          Err(de::Error::unknown_field(&String::from_utf8_lossy(v), &["Instruction fields"][..]))
4003
        }
4004
      }
4005
      impl<'de> Deserialize<'de> for StructField {
4006
        #[inline]
4007
        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
4008
        where
4009
          D: Deserializer<'de>,
4010
        {
4011
          deserializer.deserialize_identifier(StructFieldVisitor)
4012
        }
4013
      }
4014
    };
4015
  }
4016
4017
  impl<'de> Deserialize<'de> for Instruction {
4018
    #[inline]
4019
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
4020
    where
4021
      D: Deserializer<'de>,
4022
    {
4023
      if is_human_readable(deserializer.is_human_readable()) {
4024
        #[allow(non_camel_case_types)]
4025
        #[derive(Copy, Clone)]
4026
        #[allow(dead_code)]
4027
        enum StructField {
4028
          next_rip,
4029
          mem_displ,
4030
          flags1,
4031
          immediate,
4032
          code,
4033
          mem_base_reg,
4034
          mem_index_reg,
4035
          regs,
4036
          op_kinds,
4037
          scale,
4038
          displ_size,
4039
          len,
4040
          pad,
4041
        }
4042
        const _: () = assert!(StructField::pad as usize + 1 == NUM_FIELDS_READABLE);
4043
        const FIELDS: [&str; NUM_FIELDS_READABLE] = [
4044
          "next_rip",
4045
          "mem_displ",
4046
          "flags1",
4047
          "immediate",
4048
          "code",
4049
          "mem_base_reg",
4050
          "mem_index_reg",
4051
          "regs",
4052
          "op_kinds",
4053
          "scale",
4054
          "displ_size",
4055
          "len",
4056
          "pad",
4057
        ];
4058
        impl StructField {
4059
          #[inline]
4060
          fn values() -> impl Iterator<Item = StructField> + DoubleEndedIterator + ExactSizeIterator + FusedIterator {
4061
            // SAFETY: all values 0-max are valid enum values
4062
            (0..NUM_FIELDS_READABLE).map(|x| unsafe { mem::transmute::<u8, StructField>(x as u8) })
4063
          }
4064
        }
4065
        impl TryFrom<usize> for StructField {
4066
          type Error = &'static str;
4067
          #[inline]
4068
          fn try_from(value: usize) -> Result<Self, Self::Error> {
4069
            if value < NUM_FIELDS_READABLE {
4070
              // SAFETY: all values 0-max are valid enum values
4071
              Ok(unsafe { mem::transmute(value as u8) })
4072
            } else {
4073
              Err("Invalid struct field")
4074
            }
4075
          }
4076
        }
4077
4078
        mk_struct_field_visitor!();
4079
4080
        struct Visitor<'de> {
4081
          marker: PhantomData<Instruction>,
4082
          lifetime: PhantomData<&'de ()>,
4083
        }
4084
        impl<'de> de::Visitor<'de> for Visitor<'de> {
4085
          type Value = Instruction;
4086
          #[inline]
4087
          fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
4088
            formatter.write_str("struct Instruction")
4089
          }
4090
          #[allow(clippy::missing_inline_in_public_items)]
4091
          #[allow(clippy::mixed_read_write_in_expression)]
4092
          fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
4093
          where
4094
            A: de::SeqAccess<'de>,
4095
          {
4096
            let mut fields = 0;
4097
            macro_rules! next_element {
4098
              ($field_name:ident : $field_ty:ty) => {{
4099
                fields += 1;
4100
                match seq.next_element::<$field_ty>()? {
4101
                  Some(value) => value,
4102
                  None => return Err(de::Error::invalid_length(fields, &"struct Instruction with all its fields")),
4103
                }
4104
              }};
4105
            }
4106
            let instruction = Instruction {
4107
              next_rip: next_element!(next_rip: u64),
4108
              mem_displ: next_element!(mem_displ: u64),
4109
              flags1: next_element!(flags1: u32),
4110
              immediate: next_element!(immediate: u32),
4111
              code: next_element!(code: Code),
4112
              mem_base_reg: next_element!(mem_base_reg: Register),
4113
              mem_index_reg: next_element!(mem_index_reg: Register),
4114
              regs: next_element!(regs: [Register; 4]),
4115
              op_kinds: next_element!(op_kinds: [OpKind; 4]),
4116
              scale: next_element!(scale: InstrScale),
4117
              displ_size: next_element!(displ_size: u8),
4118
              len: next_element!(len: u8),
4119
              pad: next_element!(pad: u8),
4120
            };
4121
            debug_assert_eq!(fields, NUM_FIELDS_READABLE);
4122
            Ok(instruction)
4123
          }
4124
          #[allow(clippy::missing_inline_in_public_items)]
4125
          #[allow(clippy::mixed_read_write_in_expression)]
4126
          fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
4127
          where
4128
            A: de::MapAccess<'de>,
4129
          {
4130
            let mut next_rip: Option<u64> = None;
4131
            let mut mem_displ: Option<u64> = None;
4132
            let mut flags1: Option<u32> = None;
4133
            let mut immediate: Option<u32> = None;
4134
            let mut code: Option<Code> = None;
4135
            let mut mem_base_reg: Option<Register> = None;
4136
            let mut mem_index_reg: Option<Register> = None;
4137
            let mut regs: Option<[Register; 4]> = None;
4138
            let mut op_kinds: Option<[OpKind; 4]> = None;
4139
            let mut scale: Option<InstrScale> = None;
4140
            let mut displ_size: Option<u8> = None;
4141
            let mut len: Option<u8> = None;
4142
            let mut pad: Option<u8> = None;
4143
            while let Some(field) = map.next_key::<StructField>()? {
4144
              macro_rules! unpack {
4145
                ($field:ident : $field_ty:ty) => {{
4146
                  if $field.is_some() {
4147
                    return Err(<A::Error as de::Error>::duplicate_field(stringify!($field)));
4148
                  }
4149
                  $field = Some(map.next_value::<$field_ty>()?);
4150
                }};
4151
              }
4152
              match field {
4153
                StructField::next_rip => unpack!(next_rip: u64),
4154
                StructField::mem_displ => unpack!(mem_displ: u64),
4155
                StructField::flags1 => unpack!(flags1: u32),
4156
                StructField::immediate => unpack!(immediate: u32),
4157
                StructField::code => unpack!(code: Code),
4158
                StructField::mem_base_reg => unpack!(mem_base_reg: Register),
4159
                StructField::mem_index_reg => unpack!(mem_index_reg: Register),
4160
                StructField::regs => unpack!(regs: [Register; 4]),
4161
                StructField::op_kinds => unpack!(op_kinds: [OpKind; 4]),
4162
                StructField::scale => unpack!(scale: InstrScale),
4163
                StructField::displ_size => unpack!(displ_size: u8),
4164
                StructField::len => unpack!(len: u8),
4165
                StructField::pad => unpack!(pad: u8),
4166
              }
4167
            }
4168
            let mut fields = 0;
4169
            macro_rules! unpack_field {
4170
              ($field:ident) => {{
4171
                fields += 1;
4172
                match $field {
4173
                  Some(value) => value,
4174
                  None => return Err(<A::Error as de::Error>::missing_field(stringify!($field))),
4175
                }
4176
              }};
4177
            }
4178
            let instruction = Instruction {
4179
              next_rip: unpack_field!(next_rip),
4180
              mem_displ: unpack_field!(mem_displ),
4181
              flags1: unpack_field!(flags1),
4182
              immediate: unpack_field!(immediate),
4183
              code: unpack_field!(code),
4184
              mem_base_reg: unpack_field!(mem_base_reg),
4185
              mem_index_reg: unpack_field!(mem_index_reg),
4186
              regs: unpack_field!(regs),
4187
              op_kinds: unpack_field!(op_kinds),
4188
              scale: unpack_field!(scale),
4189
              displ_size: unpack_field!(displ_size),
4190
              len: unpack_field!(len),
4191
              pad: unpack_field!(pad),
4192
            };
4193
            debug_assert_eq!(fields, NUM_FIELDS_READABLE);
4194
            Ok(instruction)
4195
          }
4196
        }
4197
        deserializer.deserialize_struct("Instruction", &FIELDS[..], Visitor { marker: PhantomData::<Instruction>, lifetime: PhantomData })
4198
      } else {
4199
        #[allow(non_camel_case_types)]
4200
        #[derive(Copy, Clone)]
4201
        #[allow(dead_code)]
4202
        enum StructField {
4203
          next_rip,
4204
          mem_displ,
4205
          flags1,
4206
          immediate,
4207
          code,
4208
          mem_base_reg,
4209
          mem_index_reg,
4210
          regs0,
4211
          regs1,
4212
          regs2,
4213
          regs3,
4214
          op_kinds0,
4215
          op_kinds1,
4216
          op_kinds2,
4217
          op_kinds3,
4218
          scale,
4219
          displ_size,
4220
          len,
4221
          pad,
4222
        }
4223
        const _: () = assert!(StructField::pad as usize + 1 == NUM_FIELDS_BINARY);
4224
        const FIELDS: [&str; NUM_FIELDS_BINARY] = [
4225
          "next_rip",
4226
          "mem_displ",
4227
          "flags1",
4228
          "immediate",
4229
          "code",
4230
          "mem_base_reg",
4231
          "mem_index_reg",
4232
          "regs0",
4233
          "regs1",
4234
          "regs2",
4235
          "regs3",
4236
          "op_kinds0",
4237
          "op_kinds1",
4238
          "op_kinds2",
4239
          "op_kinds3",
4240
          "scale",
4241
          "displ_size",
4242
          "len",
4243
          "pad",
4244
        ];
4245
        impl StructField {
4246
          #[inline]
4247
          fn values() -> impl Iterator<Item = StructField> + DoubleEndedIterator + ExactSizeIterator + FusedIterator {
4248
            // SAFETY: all values 0-max are valid enum values
4249
            (0..NUM_FIELDS_BINARY).map(|x| unsafe { mem::transmute::<u8, StructField>(x as u8) })
4250
          }
4251
        }
4252
        impl TryFrom<usize> for StructField {
4253
          type Error = &'static str;
4254
          #[inline]
4255
          fn try_from(value: usize) -> Result<Self, Self::Error> {
4256
            if value < NUM_FIELDS_BINARY {
4257
              // SAFETY: all values 0-max are valid enum values
4258
              Ok(unsafe { mem::transmute(value as u8) })
4259
            } else {
4260
              Err("Invalid struct field")
4261
            }
4262
          }
4263
        }
4264
4265
        mk_struct_field_visitor!();
4266
4267
        struct Visitor<'de> {
4268
          marker: PhantomData<Instruction>,
4269
          lifetime: PhantomData<&'de ()>,
4270
        }
4271
        impl<'de> de::Visitor<'de> for Visitor<'de> {
4272
          type Value = Instruction;
4273
          #[inline]
4274
          fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
4275
            formatter.write_str("struct Instruction")
4276
          }
4277
          #[allow(clippy::missing_inline_in_public_items)]
4278
          #[allow(clippy::mixed_read_write_in_expression)]
4279
          fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
4280
          where
4281
            A: de::SeqAccess<'de>,
4282
          {
4283
            let mut fields = 0;
4284
            macro_rules! next_element {
4285
              ($field_name:ident : $field_ty:ty) => {{
4286
                fields += 1;
4287
                match seq.next_element::<$field_ty>()? {
4288
                  Some(value) => value,
4289
                  None => return Err(de::Error::invalid_length(fields, &"struct Instruction with all its fields")),
4290
                }
4291
              }};
4292
              ($field_name:ident : $field_ty:ty : $underlying_ty:ty) => {{
4293
                fields += 1;
4294
                let value = match seq.next_element::<$underlying_ty>()? {
4295
                  Some(value) => value,
4296
                  None => return Err(de::Error::invalid_length(fields, &"struct Instruction with all its fields")),
4297
                };
4298
                if let Ok(enum_value) = <$field_ty as TryFrom<usize>>::try_from(value as usize) {
4299
                  enum_value
4300
                } else {
4301
                  return Err(<A::Error as de::Error>::invalid_value(
4302
                    de::Unexpected::Unsigned(value.into()),
4303
                    &"an enum variant in range",
4304
                  ));
4305
                }
4306
              }};
4307
            }
4308
            let instruction = Instruction {
4309
              next_rip: next_element!(next_rip: u64),
4310
              mem_displ: next_element!(mem_displ: u64),
4311
              flags1: next_element!(flags1: u32),
4312
              immediate: next_element!(immediate: u32),
4313
              code: next_element!(code: Code: CodeUnderlyingType),
4314
              mem_base_reg: next_element!(mem_base_reg: Register: RegisterUnderlyingType),
4315
              mem_index_reg: next_element!(mem_index_reg: Register: RegisterUnderlyingType),
4316
              regs: [
4317
                next_element!(regs0: Register: RegisterUnderlyingType),
4318
                next_element!(regs1: Register: RegisterUnderlyingType),
4319
                next_element!(regs2: Register: RegisterUnderlyingType),
4320
                next_element!(regs3: Register: RegisterUnderlyingType),
4321
              ],
4322
              op_kinds: [
4323
                next_element!(op_kinds0: OpKind: OpKindUnderlyingType),
4324
                next_element!(op_kinds1: OpKind: OpKindUnderlyingType),
4325
                next_element!(op_kinds2: OpKind: OpKindUnderlyingType),
4326
                next_element!(op_kinds3: OpKind: OpKindUnderlyingType),
4327
              ],
4328
              scale: next_element!(scale: InstrScale: InstrScaleUnderlyingType),
4329
              displ_size: next_element!(displ_size: u8),
4330
              len: next_element!(len: u8),
4331
              pad: next_element!(pad: u8),
4332
            };
4333
            debug_assert_eq!(fields, NUM_FIELDS_BINARY);
4334
            Ok(instruction)
4335
          }
4336
          #[allow(clippy::missing_inline_in_public_items)]
4337
          #[allow(clippy::mixed_read_write_in_expression)]
4338
          fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
4339
          where
4340
            A: de::MapAccess<'de>,
4341
          {
4342
            let mut next_rip: Option<u64> = None;
4343
            let mut mem_displ: Option<u64> = None;
4344
            let mut flags1: Option<u32> = None;
4345
            let mut immediate: Option<u32> = None;
4346
            let mut code: Option<Code> = None;
4347
            let mut mem_base_reg: Option<Register> = None;
4348
            let mut mem_index_reg: Option<Register> = None;
4349
            let mut regs0: Option<Register> = None;
4350
            let mut regs1: Option<Register> = None;
4351
            let mut regs2: Option<Register> = None;
4352
            let mut regs3: Option<Register> = None;
4353
            let mut op_kinds0: Option<OpKind> = None;
4354
            let mut op_kinds1: Option<OpKind> = None;
4355
            let mut op_kinds2: Option<OpKind> = None;
4356
            let mut op_kinds3: Option<OpKind> = None;
4357
            let mut scale: Option<InstrScale> = None;
4358
            let mut displ_size: Option<u8> = None;
4359
            let mut len: Option<u8> = None;
4360
            let mut pad: Option<u8> = None;
4361
            while let Some(field) = map.next_key::<StructField>()? {
4362
              macro_rules! unpack {
4363
                ($field:ident : $field_ty:ty) => {{
4364
                  if $field.is_some() {
4365
                    return Err(<A::Error as de::Error>::duplicate_field(stringify!($field)));
4366
                  }
4367
                  $field = Some(map.next_value::<$field_ty>()?);
4368
                }};
4369
                ($field:ident : $field_ty:ty : $underlying_ty:ty) => {{
4370
                  if $field.is_some() {
4371
                    return Err(<A::Error as de::Error>::duplicate_field(stringify!($field)));
4372
                  }
4373
                  let value = map.next_value::<$underlying_ty>()?;
4374
                  if let Ok(enum_value) = <$field_ty as TryFrom<usize>>::try_from(value as usize) {
4375
                    $field = Some(enum_value);
4376
                  } else {
4377
                    return Err(<A::Error as de::Error>::invalid_value(
4378
                      de::Unexpected::Unsigned(value.into()),
4379
                      &"an enum variant in range",
4380
                    ));
4381
                  }
4382
                }};
4383
              }
4384
              match field {
4385
                StructField::next_rip => unpack!(next_rip: u64),
4386
                StructField::mem_displ => unpack!(mem_displ: u64),
4387
                StructField::flags1 => unpack!(flags1: u32),
4388
                StructField::immediate => unpack!(immediate: u32),
4389
                StructField::code => unpack!(code: Code: CodeUnderlyingType),
4390
                StructField::mem_base_reg => unpack!(mem_base_reg: Register: RegisterUnderlyingType),
4391
                StructField::mem_index_reg => unpack!(mem_index_reg: Register: RegisterUnderlyingType),
4392
                StructField::regs0 => unpack!(regs0: Register: RegisterUnderlyingType),
4393
                StructField::regs1 => unpack!(regs1: Register: RegisterUnderlyingType),
4394
                StructField::regs2 => unpack!(regs2: Register: RegisterUnderlyingType),
4395
                StructField::regs3 => unpack!(regs3: Register: RegisterUnderlyingType),
4396
                StructField::op_kinds0 => unpack!(op_kinds0: OpKind: OpKindUnderlyingType),
4397
                StructField::op_kinds1 => unpack!(op_kinds1: OpKind: OpKindUnderlyingType),
4398
                StructField::op_kinds2 => unpack!(op_kinds2: OpKind: OpKindUnderlyingType),
4399
                StructField::op_kinds3 => unpack!(op_kinds3: OpKind: OpKindUnderlyingType),
4400
                StructField::scale => unpack!(scale: InstrScale: InstrScaleUnderlyingType),
4401
                StructField::displ_size => unpack!(displ_size: u8),
4402
                StructField::len => unpack!(len: u8),
4403
                StructField::pad => unpack!(pad: u8),
4404
              }
4405
            }
4406
            let mut fields = 0;
4407
            macro_rules! unpack_field {
4408
              ($field:ident) => {{
4409
                fields += 1;
4410
                match $field {
4411
                  Some(value) => value,
4412
                  None => return Err(<A::Error as de::Error>::missing_field(stringify!($field))),
4413
                }
4414
              }};
4415
            }
4416
            let instruction = Instruction {
4417
              next_rip: unpack_field!(next_rip),
4418
              mem_displ: unpack_field!(mem_displ),
4419
              flags1: unpack_field!(flags1),
4420
              immediate: unpack_field!(immediate),
4421
              code: unpack_field!(code),
4422
              mem_base_reg: unpack_field!(mem_base_reg),
4423
              mem_index_reg: unpack_field!(mem_index_reg),
4424
              regs: [unpack_field!(regs0), unpack_field!(regs1), unpack_field!(regs2), unpack_field!(regs3)],
4425
              op_kinds: [unpack_field!(op_kinds0), unpack_field!(op_kinds1), unpack_field!(op_kinds2), unpack_field!(op_kinds3)],
4426
              scale: unpack_field!(scale),
4427
              displ_size: unpack_field!(displ_size),
4428
              len: unpack_field!(len),
4429
              pad: unpack_field!(pad),
4430
            };
4431
            debug_assert_eq!(fields, NUM_FIELDS_BINARY);
4432
            Ok(instruction)
4433
          }
4434
        }
4435
        deserializer.deserialize_struct("Instruction", &FIELDS[..], Visitor { marker: PhantomData::<Instruction>, lifetime: PhantomData })
4436
      }
4437
    }
4438
  }
4439
};