iced_x86/
instruction.rs

1// SPDX-License-Identifier: MIT
2// Copyright (C) 2018-present iced project and contributors
3
4use crate::iced_constants::IcedConstants;
5use crate::iced_error::IcedError;
6#[cfg(feature = "instr_info")]
7use crate::info::enums::*;
8use crate::instruction_internal;
9use crate::*;
10#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm", feature = "fast_fmt", feature = "serde"))]
11use core::fmt;
12use core::hash::{Hash, Hasher};
13use core::iter::{ExactSizeIterator, FusedIterator};
14use core::{mem, slice};
15
16// GENERATOR-BEGIN: InstrFlags1
17// ⚠️This was generated by GENERATOR!🦹‍♂️
18pub(crate) struct InstrFlags1;
19#[allow(dead_code)]
20impl 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!🦹‍♂️
43pub(crate) struct MvexInstrFlags;
44#[allow(dead_code)]
45impl 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)]
57pub 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)]
74pub(crate) const INSTRUCTION_TOTAL_SIZE: usize = 40;
75
76#[allow(clippy::len_without_is_empty)]
77impl Instruction {
78	/// Creates an empty `Instruction` (all fields are cleared). See also the `with_*()` constructor methods.
79	#[must_use]
80	#[inline]
81	pub fn new() -> Self {
82		Instruction::default()
83	}
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	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			let a: *const u8 = self as *const Self as *const u8;
94			let b: *const u8 = other as *const Self as *const u8;
95			let sa = slice::from_raw_parts(a, mem::size_of::<Self>());
96			let sb = slice::from_raw_parts(b, mem::size_of::<Self>());
97			sa == sb
98		}
99	}
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	pub const fn ip16(&self) -> u16 {
107		(self.next_rip as u16).wrapping_sub(self.len() as u16)
108	}
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	pub fn set_ip16(&mut self, new_value: u16) {
119		self.next_rip = (new_value as u64).wrapping_add(self.len() as u64);
120	}
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	pub const fn ip32(&self) -> u32 {
128		(self.next_rip as u32).wrapping_sub(self.len() as u32)
129	}
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	pub fn set_ip32(&mut self, new_value: u32) {
140		self.next_rip = (new_value as u64).wrapping_add(self.len() as u64);
141	}
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	pub const fn ip(&self) -> u64 {
149		self.next_rip.wrapping_sub(self.len() as u64)
150	}
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	pub fn set_ip(&mut self, new_value: u64) {
161		self.next_rip = new_value.wrapping_add(self.len() as u64);
162	}
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	pub const fn next_ip16(&self) -> u16 {
170		self.next_rip as u16
171	}
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	pub fn set_next_ip16(&mut self, new_value: u16) {
182		self.next_rip = new_value as u64;
183	}
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	pub const fn next_ip32(&self) -> u32 {
191		self.next_rip as u32
192	}
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	pub fn set_next_ip32(&mut self, new_value: u32) {
203		self.next_rip = new_value as u64;
204	}
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	pub const fn next_ip(&self) -> u64 {
212		self.next_rip
213	}
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	pub fn set_next_ip(&mut self, new_value: u64) {
224		self.next_rip = new_value;
225	}
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	pub fn code_size(&self) -> CodeSize {
232		unsafe { mem::transmute(((self.flags1 >> InstrFlags1::CODE_SIZE_SHIFT) & InstrFlags1::CODE_SIZE_MASK) as CodeSizeUnderlyingType) }
233	}
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	pub fn set_code_size(&mut self, new_value: CodeSize) {
243		self.flags1 = (self.flags1 & !(InstrFlags1::CODE_SIZE_MASK << InstrFlags1::CODE_SIZE_SHIFT))
244			| (((new_value as u32) & InstrFlags1::CODE_SIZE_MASK) << InstrFlags1::CODE_SIZE_SHIFT);
245	}
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	pub fn is_invalid(&self) -> bool {
254		self.code == Code::INVALID
255	}
256
257	/// Gets the instruction code, see also [`mnemonic()`]
258	///
259	/// [`mnemonic()`]: #method.mnemonic
260	#[must_use]
261	#[inline]
262	pub const fn code(&self) -> Code {
263		self.code
264	}
265
266	/// Sets the instruction code
267	///
268	/// # Arguments
269	///
270	/// * `new_value`: new value
271	#[inline]
272	pub fn set_code(&mut self, new_value: Code) {
273		self.code = new_value
274	}
275
276	/// Gets the mnemonic, see also [`code()`]
277	///
278	/// [`code()`]: #method.code
279	#[must_use]
280	#[inline]
281	pub fn mnemonic(&self) -> Mnemonic {
282		self.code().mnemonic()
283	}
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	pub fn op_count(&self) -> u32 {
302		instruction_op_counts::OP_COUNT[self.code() as usize] as u32
303	}
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	pub const fn len(&self) -> usize {
310		self.len as usize
311	}
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	pub fn set_len(&mut self, new_value: usize) {
321		self.len = new_value as u8
322	}
323
324	#[inline]
325	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		if self.op0_kind() != OpKind::Memory {
329			false
330		} else if self.has_lock_prefix() {
331			self.code() != Code::Cmpxchg16b_m128
332		} else {
333			self.mnemonic() == Mnemonic::Xchg
334		}
335	}
336
337	#[inline]
338	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		if self.op0_kind() != OpKind::Memory {
342			false
343		} else if self.has_lock_prefix() {
344			self.code() != Code::Cmpxchg16b_m128
345		} else {
346			matches!(
347				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	}
360
361	/// `true` if the instruction has the `XACQUIRE` prefix (`F2`)
362	#[must_use]
363	#[inline]
364	pub fn has_xacquire_prefix(&self) -> bool {
365		(self.flags1 & InstrFlags1::REPNE_PREFIX) != 0 && self.is_xacquire_instr()
366	}
367
368	/// `true` if the instruction has the `XACQUIRE` prefix (`F2`)
369	///
370	/// # Arguments
371	///
372	/// * `new_value`: new value
373	#[inline]
374	pub fn set_has_xacquire_prefix(&mut self, new_value: bool) {
375		if new_value {
376			self.flags1 |= InstrFlags1::REPNE_PREFIX;
377		} else {
378			self.flags1 &= !InstrFlags1::REPNE_PREFIX;
379		}
380	}
381
382	/// `true` if the instruction has the `XRELEASE` prefix (`F3`)
383	#[must_use]
384	#[inline]
385	pub fn has_xrelease_prefix(&self) -> bool {
386		(self.flags1 & InstrFlags1::REPE_PREFIX) != 0 && self.is_xrelease_instr()
387	}
388
389	/// `true` if the instruction has the `XRELEASE` prefix (`F3`)
390	///
391	/// # Arguments
392	///
393	/// * `new_value`: new value
394	#[inline]
395	pub fn set_has_xrelease_prefix(&mut self, new_value: bool) {
396		if new_value {
397			self.flags1 |= InstrFlags1::REPE_PREFIX;
398		} else {
399			self.flags1 &= !InstrFlags1::REPE_PREFIX;
400		}
401	}
402
403	/// `true` if the instruction has the `REPE` or `REP` prefix (`F3`)
404	#[must_use]
405	#[inline]
406	pub const fn has_rep_prefix(&self) -> bool {
407		(self.flags1 & InstrFlags1::REPE_PREFIX) != 0
408	}
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	pub fn set_has_rep_prefix(&mut self, new_value: bool) {
417		if new_value {
418			self.flags1 |= InstrFlags1::REPE_PREFIX;
419		} else {
420			self.flags1 &= !InstrFlags1::REPE_PREFIX;
421		}
422	}
423
424	/// `true` if the instruction has the `REPE` or `REP` prefix (`F3`)
425	#[must_use]
426	#[inline]
427	pub const fn has_repe_prefix(&self) -> bool {
428		(self.flags1 & InstrFlags1::REPE_PREFIX) != 0
429	}
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	pub fn set_has_repe_prefix(&mut self, new_value: bool) {
438		if new_value {
439			self.flags1 |= InstrFlags1::REPE_PREFIX;
440		} else {
441			self.flags1 &= !InstrFlags1::REPE_PREFIX;
442		}
443	}
444
445	/// `true` if the instruction has the `REPNE` prefix (`F2`)
446	#[must_use]
447	#[inline]
448	pub const fn has_repne_prefix(&self) -> bool {
449		(self.flags1 & InstrFlags1::REPNE_PREFIX) != 0
450	}
451
452	/// `true` if the instruction has the `REPNE` prefix (`F2`)
453	///
454	/// # Arguments
455	///
456	/// * `new_value`: new value
457	#[inline]
458	pub fn set_has_repne_prefix(&mut self, new_value: bool) {
459		if new_value {
460			self.flags1 |= InstrFlags1::REPNE_PREFIX;
461		} else {
462			self.flags1 &= !InstrFlags1::REPNE_PREFIX;
463		}
464	}
465
466	/// `true` if the instruction has the `LOCK` prefix (`F0`)
467	#[must_use]
468	#[inline]
469	pub const fn has_lock_prefix(&self) -> bool {
470		(self.flags1 & InstrFlags1::LOCK_PREFIX) != 0
471	}
472
473	/// `true` if the instruction has the `LOCK` prefix (`F0`)
474	///
475	/// # Arguments
476	///
477	/// * `new_value`: new value
478	#[inline]
479	pub fn set_has_lock_prefix(&mut self, new_value: bool) {
480		if new_value {
481			self.flags1 |= InstrFlags1::LOCK_PREFIX;
482		} else {
483			self.flags1 &= !InstrFlags1::LOCK_PREFIX;
484		}
485	}
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	pub const fn op0_kind(&self) -> OpKind {
494		self.op_kinds[0]
495	}
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	pub fn set_op0_kind(&mut self, new_value: OpKind) {
507		self.op_kinds[0] = new_value
508	}
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	pub const fn op1_kind(&self) -> OpKind {
517		self.op_kinds[1]
518	}
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	pub fn set_op1_kind(&mut self, new_value: OpKind) {
530		self.op_kinds[1] = new_value
531	}
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	pub const fn op2_kind(&self) -> OpKind {
540		self.op_kinds[2]
541	}
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	pub fn set_op2_kind(&mut self, new_value: OpKind) {
553		self.op_kinds[2] = new_value
554	}
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	pub const fn op3_kind(&self) -> OpKind {
563		self.op_kinds[3]
564	}
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	pub fn set_op3_kind(&mut self, new_value: OpKind) {
576		self.op_kinds[3] = new_value
577	}
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	pub const fn op4_kind(&self) -> OpKind {
587		OpKind::Immediate8
588	}
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	pub fn set_op4_kind(&mut self, new_value: OpKind) {
601		debug_assert_eq!(new_value, OpKind::Immediate8);
602	}
603
604	#[allow(clippy::unused_self)]
605	#[inline]
606	#[doc(hidden)]
607	pub fn try_set_op4_kind(&mut self, new_value: OpKind) -> Result<(), IcedError> {
608		if new_value != OpKind::Immediate8 {
609			Err(IcedError::new("Invalid opkind"))
610		} else {
611			Ok(())
612		}
613	}
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	pub fn op_kinds(&self) -> impl Iterator<Item = OpKind> + ExactSizeIterator + FusedIterator {
635		OpKindIterator::new(self)
636	}
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	pub fn op_kind(&self, operand: u32) -> OpKind {
666		const _: () = assert!(IcedConstants::MAX_OP_COUNT == 5);
667		if let Some(&op_kind) = self.op_kinds.get(operand as usize) {
668			op_kind
669		} else if operand == 4 {
670			self.op4_kind()
671		} else {
672			debug_assert!(false, "Invalid operand: {}", operand);
673			OpKind::default()
674		}
675	}
676
677	#[doc(hidden)]
678	#[inline]
679	pub fn try_op_kind(&self, operand: u32) -> Result<OpKind, IcedError> {
680		const _: () = assert!(IcedConstants::MAX_OP_COUNT == 5);
681		if let Some(&op_kind) = self.op_kinds.get(operand as usize) {
682			Ok(op_kind)
683		} else if operand == 4 {
684			Ok(self.op4_kind())
685		} else {
686			Err(IcedError::new("Invalid operand"))
687		}
688	}
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	pub fn set_op_kind(&mut self, operand: u32, op_kind: OpKind) {
698		const _: () = assert!(IcedConstants::MAX_OP_COUNT == 5);
699		if let Some(field) = self.op_kinds.get_mut(operand as usize) {
700			*field = op_kind;
701		} else if operand == 4 {
702			self.set_op4_kind(op_kind)
703		} else {
704			debug_assert!(false, "Invalid operand: {}", operand);
705		}
706	}
707
708	#[doc(hidden)]
709	#[inline]
710	pub fn try_set_op_kind(&mut self, operand: u32, op_kind: OpKind) -> Result<(), IcedError> {
711		const _: () = assert!(IcedConstants::MAX_OP_COUNT == 5);
712		if let Some(field) = self.op_kinds.get_mut(operand as usize) {
713			*field = op_kind;
714			Ok(())
715		} else if operand == 4 {
716			self.try_set_op4_kind(op_kind)
717		} else {
718			Err(IcedError::new("Invalid operand"))
719		}
720	}
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	pub const fn has_segment_prefix(&self) -> bool {
728		((self.flags1 >> InstrFlags1::SEGMENT_PREFIX_SHIFT) & InstrFlags1::SEGMENT_PREFIX_MASK).wrapping_sub(1) < 6
729	}
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	pub fn segment_prefix(&self) -> Register {
745		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		if index < 6 {
752			// SAFETY: ES+index is a valid enum variant, see above const assert!()'s
753			unsafe { mem::transmute((Register::ES as u32 + index) as RegisterUnderlyingType) }
754		} else {
755			Register::None
756		}
757	}
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	pub fn set_segment_prefix(&mut self, new_value: Register) {
776		debug_assert!(new_value == Register::None || (Register::ES <= new_value && new_value <= Register::GS));
777		let enc_value =
778			if new_value == Register::None { 0 } else { (((new_value as u32) - (Register::ES as u32)) + 1) & InstrFlags1::SEGMENT_PREFIX_MASK };
779		self.flags1 = (self.flags1 & !(InstrFlags1::SEGMENT_PREFIX_MASK << InstrFlags1::SEGMENT_PREFIX_SHIFT))
780			| (enc_value << InstrFlags1::SEGMENT_PREFIX_SHIFT);
781	}
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	pub fn memory_segment(&self) -> Register {
794		let seg_reg = self.segment_prefix();
795		if seg_reg != Register::None {
796			return seg_reg;
797		}
798		match self.memory_base() {
799			Register::BP | Register::EBP | Register::ESP | Register::RBP | Register::RSP => Register::SS,
800			_ => Register::DS,
801		}
802	}
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	pub const fn memory_displ_size(&self) -> u32 {
814		let size = self.displ_size as u32;
815		if size <= 2 {
816			size
817		} else if size == 3 {
818			4
819		} else {
820			8
821		}
822	}
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	pub fn set_memory_displ_size(&mut self, new_value: u32) {
837		self.displ_size = match new_value {
838			0 => 0,
839			1 => 1,
840			2 => 2,
841			4 => 3,
842			_ => 4,
843		};
844	}
845
846	/// `true` if the data is broadcast (EVEX instructions only)
847	#[must_use]
848	#[inline]
849	pub const fn is_broadcast(&self) -> bool {
850		(self.flags1 & InstrFlags1::BROADCAST) != 0
851	}
852
853	/// Sets the is broadcast flag (EVEX instructions only)
854	///
855	/// # Arguments
856	///
857	/// * `new_value`: New value
858	#[inline]
859	pub fn set_is_broadcast(&mut self, new_value: bool) {
860		if new_value {
861			self.flags1 |= InstrFlags1::BROADCAST;
862		} else {
863			self.flags1 &= !InstrFlags1::BROADCAST;
864		}
865	}
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	pub fn memory_size(&self) -> MemorySize {
934		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		if !self.is_broadcast() {
951			instruction_memory_sizes::SIZES_NORMAL[code as usize]
952		} else {
953			instruction_memory_sizes::SIZES_BCST[code as usize]
954		}
955	}
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	pub const fn memory_index_scale(&self) -> u32 {
963		1 << (self.scale as u8)
964	}
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	pub fn set_memory_index_scale(&mut self, new_value: u32) {
975		match new_value {
976			1 => self.scale = InstrScale::Scale1,
977			2 => self.scale = InstrScale::Scale2,
978			4 => self.scale = InstrScale::Scale4,
979			_ => {
980				debug_assert_eq!(new_value, 8);
981				self.scale = InstrScale::Scale8;
982			}
983		}
984	}
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	pub const fn memory_displacement32(&self) -> u32 {
994		self.mem_displ as u32
995	}
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	pub fn set_memory_displacement32(&mut self, new_value: u32) {
1008		self.mem_displ = new_value as u64;
1009	}
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	pub const fn memory_displacement64(&self) -> u64 {
1019		self.mem_displ
1020	}
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	pub fn set_memory_displacement64(&mut self, new_value: u64) {
1033		self.mem_displ = new_value;
1034	}
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	pub fn try_immediate(&self, operand: u32) -> Result<u64, IcedError> {
1051		Ok(match self.try_op_kind(operand)? {
1052			OpKind::Immediate8 => self.immediate8() as u64,
1053			OpKind::Immediate8_2nd => self.immediate8_2nd() as u64,
1054			OpKind::Immediate16 => self.immediate16() as u64,
1055			OpKind::Immediate32 => self.immediate32() as u64,
1056			OpKind::Immediate64 => self.immediate64(),
1057			OpKind::Immediate8to16 => self.immediate8to16() as u64,
1058			OpKind::Immediate8to32 => self.immediate8to32() as u64,
1059			OpKind::Immediate8to64 => self.immediate8to64() as u64,
1060			OpKind::Immediate32to64 => self.immediate32to64() as u64,
1061			_ => return Err(IcedError::new("Not an immediate operand")),
1062		})
1063	}
1064
1065	/// Gets an operand's immediate value
1066	///
1067	/// # Arguments
1068	///
1069	/// * `operand`: Operand number, 0-4
1070	#[must_use]
1071	#[inline]
1072	pub fn immediate(&self, operand: u32) -> u64 {
1073		match self.try_immediate(operand) {
1074			Ok(value) => value,
1075			Err(_) => {
1076				debug_assert!(false, "Invalid operand: {}", operand);
1077				0
1078			}
1079		}
1080	}
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	pub fn set_immediate_i32(&mut self, operand: u32, new_value: i32) {
1090		match self.try_set_immediate_i32(operand, new_value) {
1091			Ok(()) => {}
1092			Err(_) => debug_assert!(false, "Invalid operand: {}", operand),
1093		}
1094	}
1095
1096	#[inline]
1097	#[doc(hidden)]
1098	pub fn try_set_immediate_i32(&mut self, operand: u32, new_value: i32) -> Result<(), IcedError> {
1099		self.try_set_immediate_u64(operand, new_value as u64)
1100	}
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	pub fn set_immediate_u32(&mut self, operand: u32, new_value: u32) {
1110		match self.try_set_immediate_u32(operand, new_value) {
1111			Ok(()) => {}
1112			Err(_) => debug_assert!(false, "Invalid operand: {}", operand),
1113		}
1114	}
1115
1116	#[inline]
1117	#[doc(hidden)]
1118	pub fn try_set_immediate_u32(&mut self, operand: u32, new_value: u32) -> Result<(), IcedError> {
1119		self.try_set_immediate_u64(operand, new_value as u64)
1120	}
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	pub fn set_immediate_i64(&mut self, operand: u32, new_value: i64) {
1130		match self.try_set_immediate_i64(operand, new_value) {
1131			Ok(()) => {}
1132			Err(_) => debug_assert!(false, "Invalid operand: {}", operand),
1133		}
1134	}
1135
1136	#[inline]
1137	#[doc(hidden)]
1138	pub fn try_set_immediate_i64(&mut self, operand: u32, new_value: i64) -> Result<(), IcedError> {
1139		self.try_set_immediate_u64(operand, new_value as u64)
1140	}
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	pub fn set_immediate_u64(&mut self, operand: u32, new_value: u64) {
1150		match self.try_set_immediate_u64(operand, new_value) {
1151			Ok(()) => {}
1152			Err(_) => debug_assert!(false, "Invalid operand: {}", operand),
1153		}
1154	}
1155
1156	#[allow(clippy::missing_inline_in_public_items)]
1157	#[doc(hidden)]
1158	pub fn try_set_immediate_u64(&mut self, operand: u32, new_value: u64) -> Result<(), IcedError> {
1159		match self.try_op_kind(operand)? {
1160			OpKind::Immediate8 => self.set_immediate8(new_value as u8),
1161			OpKind::Immediate8to16 => self.set_immediate8to16(new_value as i16),
1162			OpKind::Immediate8to32 => self.set_immediate8to32(new_value as i32),
1163			OpKind::Immediate8to64 => self.set_immediate8to64(new_value as i64),
1164			OpKind::Immediate8_2nd => self.set_immediate8_2nd(new_value as u8),
1165			OpKind::Immediate16 => self.set_immediate16(new_value as u16),
1166			OpKind::Immediate32to64 => self.set_immediate32to64(new_value as i64),
1167			OpKind::Immediate32 => self.set_immediate32(new_value as u32),
1168			OpKind::Immediate64 => self.set_immediate64(new_value),
1169			_ => return Err(IcedError::new("Not an immediate operand")),
1170		}
1171		Ok(())
1172	}
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	pub const fn immediate8(&self) -> u8 {
1180		self.immediate as u8
1181	}
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	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		{
1198			self.immediate = new_value as u32;
1199		}
1200	}
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	pub const fn immediate8_2nd(&self) -> u8 {
1208		self.mem_displ as u8
1209	}
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	pub fn set_immediate8_2nd(&mut self, new_value: u8) {
1220		self.mem_displ = new_value as u64;
1221	}
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	pub const fn immediate16(&self) -> u16 {
1229		self.immediate as u16
1230	}
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	pub fn set_immediate16(&mut self, new_value: u16) {
1241		self.immediate = new_value as u32;
1242	}
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	pub const fn immediate32(&self) -> u32 {
1250		self.immediate
1251	}
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	pub fn set_immediate32(&mut self, new_value: u32) {
1262		self.immediate = new_value;
1263	}
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	pub const fn immediate64(&self) -> u64 {
1271		(self.mem_displ << 32) | (self.immediate as u64)
1272	}
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	pub fn set_immediate64(&mut self, new_value: u64) {
1283		self.immediate = new_value as u32;
1284		self.mem_displ = new_value >> 32;
1285	}
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	pub const fn immediate8to16(&self) -> i16 {
1293		self.immediate as i8 as i16
1294	}
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	pub fn set_immediate8to16(&mut self, new_value: i16) {
1305		self.immediate = new_value as i8 as u32;
1306	}
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	pub const fn immediate8to32(&self) -> i32 {
1314		self.immediate as i8 as i32
1315	}
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	pub fn set_immediate8to32(&mut self, new_value: i32) {
1326		self.immediate = new_value as i8 as u32;
1327	}
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	pub const fn immediate8to64(&self) -> i64 {
1335		self.immediate as i8 as i64
1336	}
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	pub fn set_immediate8to64(&mut self, new_value: i64) {
1347		self.immediate = new_value as i8 as u32;
1348	}
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	pub const fn immediate32to64(&self) -> i64 {
1356		self.immediate as i32 as i64
1357	}
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	pub fn set_immediate32to64(&mut self, new_value: i64) {
1368		self.immediate = new_value as u32;
1369	}
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	pub const fn near_branch16(&self) -> u16 {
1377		self.mem_displ as u16
1378	}
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	pub fn set_near_branch16(&mut self, new_value: u16) {
1389		self.mem_displ = new_value as u64;
1390	}
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	pub const fn near_branch32(&self) -> u32 {
1398		self.mem_displ as u32
1399	}
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	pub fn set_near_branch32(&mut self, new_value: u32) {
1410		self.mem_displ = new_value as u64;
1411	}
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	pub const fn near_branch64(&self) -> u64 {
1419		self.mem_displ
1420	}
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	pub fn set_near_branch64(&mut self, new_value: u64) {
1431		self.mem_displ = new_value
1432	}
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	pub fn near_branch_target(&self) -> u64 {
1445		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		match op_kind {
1454			OpKind::NearBranch16 => self.near_branch16() as u64,
1455			OpKind::NearBranch32 => self.near_branch32() as u64,
1456			OpKind::NearBranch64 => self.near_branch64(),
1457			_ => 0,
1458		}
1459	}
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	pub const fn far_branch16(&self) -> u16 {
1467		self.immediate as u16
1468	}
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	pub fn set_far_branch16(&mut self, new_value: u16) {
1479		self.immediate = new_value as u32;
1480	}
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	pub const fn far_branch32(&self) -> u32 {
1488		self.immediate
1489	}
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	pub fn set_far_branch32(&mut self, new_value: u32) {
1500		self.immediate = new_value;
1501	}
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	pub const fn far_branch_selector(&self) -> u16 {
1510		self.mem_displ as u16
1511	}
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	pub fn set_far_branch_selector(&mut self, new_value: u16) {
1523		self.mem_displ = new_value as u64;
1524	}
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	pub const fn memory_base(&self) -> Register {
1533		self.mem_base_reg
1534	}
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	pub fn set_memory_base(&mut self, new_value: Register) {
1546		self.mem_base_reg = new_value;
1547	}
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	pub const fn memory_index(&self) -> Register {
1556		self.mem_index_reg
1557	}
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	pub fn set_memory_index(&mut self, new_value: Register) {
1569		self.mem_index_reg = new_value;
1570	}
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	pub const fn op0_register(&self) -> Register {
1582		self.regs[0]
1583	}
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	pub fn set_op0_register(&mut self, new_value: Register) {
1598		self.regs[0] = new_value;
1599	}
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	pub const fn op1_register(&self) -> Register {
1611		self.regs[1]
1612	}
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	pub fn set_op1_register(&mut self, new_value: Register) {
1627		self.regs[1] = new_value;
1628	}
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	pub const fn op2_register(&self) -> Register {
1640		self.regs[2]
1641	}
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	pub fn set_op2_register(&mut self, new_value: Register) {
1656		self.regs[2] = new_value;
1657	}
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	pub const fn op3_register(&self) -> Register {
1669		self.regs[3]
1670	}
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	pub fn set_op3_register(&mut self, new_value: Register) {
1685		self.regs[3] = new_value;
1686	}
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	pub const fn op4_register(&self) -> Register {
1699		Register::None
1700	}
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	pub fn set_op4_register(&mut self, new_value: Register) {
1716		debug_assert_eq!(new_value, Register::None);
1717	}
1718
1719	#[allow(clippy::unused_self)]
1720	#[inline]
1721	#[doc(hidden)]
1722	pub fn try_set_op4_register(&mut self, new_value: Register) -> Result<(), IcedError> {
1723		if new_value != Register::None {
1724			Err(IcedError::new("Invalid register"))
1725		} else {
1726			Ok(())
1727		}
1728	}
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	pub fn op_register(&self, operand: u32) -> Register {
1756		const _: () = assert!(IcedConstants::MAX_OP_COUNT == 5);
1757		if let Some(&reg) = self.regs.get(operand as usize) {
1758			reg
1759		} else if operand == 4 {
1760			self.op4_register()
1761		} else {
1762			debug_assert!(false, "Invalid operand: {}", operand);
1763			Register::default()
1764		}
1765	}
1766
1767	#[inline]
1768	#[doc(hidden)]
1769	pub fn try_op_register(&self, operand: u32) -> Result<Register, IcedError> {
1770		const _: () = assert!(IcedConstants::MAX_OP_COUNT == 5);
1771		if let Some(&reg) = self.regs.get(operand as usize) {
1772			Ok(reg)
1773		} else if operand == 4 {
1774			Ok(self.op4_register())
1775		} else {
1776			Err(IcedError::new("Invalid operand"))
1777		}
1778	}
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	pub fn set_op_register(&mut self, operand: u32, new_value: Register) {
1790		const _: () = assert!(IcedConstants::MAX_OP_COUNT == 5);
1791		match operand {
1792			0 => self.set_op0_register(new_value),
1793			1 => self.set_op1_register(new_value),
1794			2 => self.set_op2_register(new_value),
1795			3 => self.set_op3_register(new_value),
1796			4 => self.set_op4_register(new_value),
1797			_ => debug_assert!(false, "Invalid operand: {}", operand),
1798		}
1799	}
1800
1801	#[inline]
1802	#[doc(hidden)]
1803	pub fn try_set_op_register(&mut self, operand: u32, new_value: Register) -> Result<(), IcedError> {
1804		const _: () = assert!(IcedConstants::MAX_OP_COUNT == 5);
1805		match operand {
1806			0 => self.set_op0_register(new_value),
1807			1 => self.set_op1_register(new_value),
1808			2 => self.set_op2_register(new_value),
1809			3 => self.set_op3_register(new_value),
1810			4 => return self.try_set_op4_register(new_value),
1811			_ => return Err(IcedError::new("Invalid operand")),
1812		}
1813		Ok(())
1814	}
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	pub fn op_mask(&self) -> Register {
1824		let r = (self.flags1 >> InstrFlags1::OP_MASK_SHIFT) & InstrFlags1::OP_MASK_MASK;
1825		if r == 0 {
1826			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			unsafe { mem::transmute((r + Register::K0 as u32) as RegisterUnderlyingType) }
1838		}
1839	}
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	pub fn set_op_mask(&mut self, new_value: Register) {
1852		debug_assert!(new_value == Register::None || (Register::K1 <= new_value && new_value <= Register::K7));
1853		let r = if new_value == Register::None { 0 } else { (new_value as u32 - Register::K0 as u32) & InstrFlags1::OP_MASK_MASK };
1854		self.flags1 = (self.flags1 & !(InstrFlags1::OP_MASK_MASK << InstrFlags1::OP_MASK_SHIFT)) | (r << InstrFlags1::OP_MASK_SHIFT);
1855	}
1856
1857	/// Checks if there's an opmask register ([`op_mask()`])
1858	///
1859	/// [`op_mask()`]: #method.op_mask
1860	#[must_use]
1861	#[inline]
1862	pub const fn has_op_mask(&self) -> bool {
1863		(self.flags1 & (InstrFlags1::OP_MASK_MASK << InstrFlags1::OP_MASK_SHIFT)) != 0
1864	}
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	pub const fn zeroing_masking(&self) -> bool {
1871		(self.flags1 & InstrFlags1::ZEROING_MASKING) != 0
1872	}
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	pub fn set_zeroing_masking(&mut self, new_value: bool) {
1882		if new_value {
1883			self.flags1 |= InstrFlags1::ZEROING_MASKING;
1884		} else {
1885			self.flags1 &= !InstrFlags1::ZEROING_MASKING;
1886		}
1887	}
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	pub const fn merging_masking(&self) -> bool {
1894		(self.flags1 & InstrFlags1::ZEROING_MASKING) == 0
1895	}
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	pub fn set_merging_masking(&mut self, new_value: bool) {
1905		if new_value {
1906			self.flags1 &= !InstrFlags1::ZEROING_MASKING;
1907		} else {
1908			self.flags1 |= InstrFlags1::ZEROING_MASKING;
1909		}
1910	}
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	pub fn rounding_control(&self) -> RoundingControl {
1920		unsafe {
1921			mem::transmute(
1922				((self.flags1 >> InstrFlags1::ROUNDING_CONTROL_SHIFT) & InstrFlags1::ROUNDING_CONTROL_MASK) as RoundingControlUnderlyingType,
1923			)
1924		}
1925	}
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	pub fn set_rounding_control(&mut self, new_value: RoundingControl) {
1938		self.flags1 = (self.flags1 & !(InstrFlags1::ROUNDING_CONTROL_MASK << InstrFlags1::ROUNDING_CONTROL_SHIFT))
1939			| ((new_value as u32) << InstrFlags1::ROUNDING_CONTROL_SHIFT);
1940	}
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	pub const fn declare_data_len(&self) -> usize {
1953		(((self.flags1 >> InstrFlags1::DATA_LENGTH_SHIFT) & InstrFlags1::DATA_LENGTH_MASK) + 1) as usize
1954	}
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	pub fn set_declare_data_len(&mut self, new_value: usize) {
1970		debug_assert!(1 <= new_value && new_value <= 0x10);
1971		self.flags1 = (self.flags1 & !(InstrFlags1::DATA_LENGTH_MASK << InstrFlags1::DATA_LENGTH_SHIFT))
1972			| ((((new_value as u32) - 1) & InstrFlags1::DATA_LENGTH_MASK) << InstrFlags1::DATA_LENGTH_SHIFT);
1973	}
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	pub fn set_declare_byte_value_i8(&mut self, index: usize, new_value: i8) {
1988		match self.try_set_declare_byte_value_i8(index, new_value) {
1989			Ok(()) => {}
1990			Err(_) => debug_assert!(false, "Invalid index: {}", index),
1991		}
1992	}
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	pub fn try_set_declare_byte_value_i8(&mut self, index: usize, new_value: i8) -> Result<(), IcedError> {
2011		self.try_set_declare_byte_value(index, new_value as u8)
2012	}
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	pub fn set_declare_byte_value(&mut self, index: usize, new_value: u8) {
2027		match self.try_set_declare_byte_value(index, new_value) {
2028			Ok(()) => {}
2029			Err(_) => debug_assert!(false, "Invalid index: {}", index),
2030		}
2031	}
2032
2033	#[allow(clippy::missing_inline_in_public_items)]
2034	#[doc(hidden)]
2035	pub fn try_set_declare_byte_value(&mut self, index: usize, new_value: u8) -> Result<(), IcedError> {
2036		match index {
2037			0 => self.regs[0] = Register::from_u8(new_value),
2038			1 => self.regs[1] = Register::from_u8(new_value),
2039			2 => self.regs[2] = Register::from_u8(new_value),
2040			3 => self.regs[3] = Register::from_u8(new_value),
2041			4 => self.immediate = (self.immediate & 0xFFFF_FF00) | new_value as u32,
2042			5 => self.immediate = (self.immediate & 0xFFFF_00FF) | ((new_value as u32) << 8),
2043			6 => self.immediate = (self.immediate & 0xFF00_FFFF) | ((new_value as u32) << 16),
2044			7 => self.immediate = (self.immediate & 0x00FF_FFFF) | ((new_value as u32) << 24),
2045			8 => self.mem_displ = (self.mem_displ & 0xFFFF_FFFF_FFFF_FF00) | new_value as u64,
2046			9 => self.mem_displ = (self.mem_displ & 0xFFFF_FFFF_FFFF_00FF) | ((new_value as u64) << 8),
2047			10 => self.mem_displ = (self.mem_displ & 0xFFFF_FFFF_FF00_FFFF) | ((new_value as u64) << 16),
2048			11 => self.mem_displ = (self.mem_displ & 0xFFFF_FFFF_00FF_FFFF) | ((new_value as u64) << 24),
2049			12 => self.mem_displ = (self.mem_displ & 0xFFFF_FF00_FFFF_FFFF) | ((new_value as u64) << 32),
2050			13 => self.mem_displ = (self.mem_displ & 0xFFFF_00FF_FFFF_FFFF) | ((new_value as u64) << 40),
2051			14 => self.mem_displ = (self.mem_displ & 0xFF00_FFFF_FFFF_FFFF) | ((new_value as u64) << 48),
2052			15 => self.mem_displ = (self.mem_displ & 0x00FF_FFFF_FFFF_FFFF) | ((new_value as u64) << 56),
2053			_ => return Err(IcedError::new("Invalid index")),
2054		}
2055		Ok(())
2056	}
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	pub fn get_declare_byte_value(&self, index: usize) -> u8 {
2071		match self.try_get_declare_byte_value(index) {
2072			Ok(value) => value,
2073			Err(_) => {
2074				debug_assert!(false, "Invalid index: {}", index);
2075				0
2076			}
2077		}
2078	}
2079
2080	#[allow(clippy::missing_inline_in_public_items)]
2081	#[doc(hidden)]
2082	pub const fn try_get_declare_byte_value(&self, index: usize) -> Result<u8, IcedError> {
2083		Ok(match index {
2084			0 => self.regs[0] as u8,
2085			1 => self.regs[1] as u8,
2086			2 => self.regs[2] as u8,
2087			3 => self.regs[3] as u8,
2088			4 => self.immediate as u8,
2089			5 => (self.immediate >> 8) as u8,
2090			6 => (self.immediate >> 16) as u8,
2091			7 => (self.immediate >> 24) as u8,
2092			8 => self.mem_displ as u8,
2093			9 => ((self.mem_displ as u32) >> 8) as u8,
2094			10 => ((self.mem_displ as u32) >> 16) as u8,
2095			11 => ((self.mem_displ as u32) >> 24) as u8,
2096			12 => (self.mem_displ >> 32) as u8,
2097			13 => (self.mem_displ >> 40) as u8,
2098			14 => (self.mem_displ >> 48) as u8,
2099			15 => (self.mem_displ >> 56) as u8,
2100			_ => return Err(IcedError::new("Invalid index")),
2101		})
2102	}
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	pub fn set_declare_word_value_i16(&mut self, index: usize, new_value: i16) {
2117		match self.try_set_declare_word_value_i16(index, new_value) {
2118			Ok(()) => {}
2119			Err(_) => debug_assert!(false, "Invalid index: {}", index),
2120		}
2121	}
2122
2123	#[inline]
2124	#[doc(hidden)]
2125	pub fn try_set_declare_word_value_i16(&mut self, index: usize, new_value: i16) -> Result<(), IcedError> {
2126		self.try_set_declare_word_value(index, new_value as u16)
2127	}
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	pub fn set_declare_word_value(&mut self, index: usize, new_value: u16) {
2142		match self.try_set_declare_word_value(index, new_value) {
2143			Ok(()) => {}
2144			Err(_) => debug_assert!(false, "Invalid index: {}", index),
2145		}
2146	}
2147
2148	#[allow(clippy::missing_inline_in_public_items)]
2149	#[doc(hidden)]
2150	pub fn try_set_declare_word_value(&mut self, index: usize, new_value: u16) -> Result<(), IcedError> {
2151		match index {
2152			0 => {
2153				self.regs[0] = Register::from_u8(new_value as u8);
2154				self.regs[1] = Register::from_u8((new_value >> 8) as u8);
2155			}
2156			1 => {
2157				self.regs[2] = Register::from_u8(new_value as u8);
2158				self.regs[3] = Register::from_u8((new_value >> 8) as u8);
2159			}
2160			2 => self.immediate = (self.immediate & 0xFFFF_0000) | new_value as u32,
2161			3 => self.immediate = self.immediate as u16 as u32 | (new_value as u32) << 16,
2162			4 => self.mem_displ = (self.mem_displ & 0xFFFF_FFFF_FFFF_0000) | new_value as u64,
2163			5 => self.mem_displ = (self.mem_displ & 0xFFFF_FFFF_0000_FFFF) | ((new_value as u64) << 16),
2164			6 => self.mem_displ = (self.mem_displ & 0xFFFF_0000_FFFF_FFFF) | ((new_value as u64) << 32),
2165			7 => self.mem_displ = (self.mem_displ & 0x0000_FFFF_FFFF_FFFF) | ((new_value as u64) << 48),
2166			_ => return Err(IcedError::new("Invalid index")),
2167		}
2168		Ok(())
2169	}
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	pub fn get_declare_word_value(&self, index: usize) -> u16 {
2184		match self.try_get_declare_word_value(index) {
2185			Ok(value) => value,
2186			Err(_) => {
2187				debug_assert!(false, "Invalid index: {}", index);
2188				0
2189			}
2190		}
2191	}
2192
2193	#[allow(clippy::missing_inline_in_public_items)]
2194	#[doc(hidden)]
2195	pub const fn try_get_declare_word_value(&self, index: usize) -> Result<u16, IcedError> {
2196		Ok(match index {
2197			0 => self.regs[0] as u16 | ((self.regs[1] as u16) << 8),
2198			1 => self.regs[2] as u16 | ((self.regs[3] as u16) << 8),
2199			2 => self.immediate as u16,
2200			3 => (self.immediate >> 16) as u16,
2201			4 => self.mem_displ as u16,
2202			5 => ((self.mem_displ as u32) >> 16) as u16,
2203			6 => (self.mem_displ >> 32) as u16,
2204			7 => (self.mem_displ >> 48) as u16,
2205			_ => return Err(IcedError::new("Invalid index")),
2206		})
2207	}
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	pub fn set_declare_dword_value_i32(&mut self, index: usize, new_value: i32) {
2222		match self.try_set_declare_dword_value_i32(index, new_value) {
2223			Ok(()) => {}
2224			Err(_) => debug_assert!(false, "Invalid index: {}", index),
2225		}
2226	}
2227
2228	#[inline]
2229	#[doc(hidden)]
2230	pub fn try_set_declare_dword_value_i32(&mut self, index: usize, new_value: i32) -> Result<(), IcedError> {
2231		self.try_set_declare_dword_value(index, new_value as u32)
2232	}
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	pub fn set_declare_dword_value(&mut self, index: usize, new_value: u32) {
2247		match self.try_set_declare_dword_value(index, new_value) {
2248			Ok(()) => {}
2249			Err(_) => debug_assert!(false, "Invalid index: {}", index),
2250		}
2251	}
2252
2253	#[allow(clippy::missing_inline_in_public_items)]
2254	#[doc(hidden)]
2255	pub fn try_set_declare_dword_value(&mut self, index: usize, new_value: u32) -> Result<(), IcedError> {
2256		match index {
2257			0 => {
2258				self.regs[0] = Register::from_u8(new_value as u8);
2259				self.regs[1] = Register::from_u8((new_value >> 8) as u8);
2260				self.regs[2] = Register::from_u8((new_value >> 16) as u8);
2261				self.regs[3] = Register::from_u8((new_value >> 24) as u8);
2262			}
2263			1 => self.immediate = new_value,
2264			2 => self.mem_displ = (self.mem_displ & 0xFFFF_FFFF_0000_0000) | new_value as u64,
2265			3 => self.mem_displ = (self.mem_displ & 0x0000_0000_FFFF_FFFF) | (new_value as u64) << 32,
2266			_ => return Err(IcedError::new("Invalid index")),
2267		}
2268		Ok(())
2269	}
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	pub fn get_declare_dword_value(&self, index: usize) -> u32 {
2284		match self.try_get_declare_dword_value(index) {
2285			Ok(value) => value,
2286			Err(_) => {
2287				debug_assert!(false, "Invalid index: {}", index);
2288				0
2289			}
2290		}
2291	}
2292
2293	#[allow(clippy::missing_inline_in_public_items)]
2294	#[doc(hidden)]
2295	pub const fn try_get_declare_dword_value(&self, index: usize) -> Result<u32, IcedError> {
2296		Ok(match index {
2297			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			1 => self.immediate,
2299			2 => self.mem_displ as u32,
2300			3 => (self.mem_displ >> 32) as u32,
2301			_ => return Err(IcedError::new("Invalid index")),
2302		})
2303	}
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	pub fn set_declare_qword_value_i64(&mut self, index: usize, new_value: i64) {
2318		match self.try_set_declare_qword_value_i64(index, new_value) {
2319			Ok(()) => {}
2320			Err(_) => debug_assert!(false, "Invalid index: {}", index),
2321		}
2322	}
2323
2324	#[inline]
2325	#[doc(hidden)]
2326	pub fn try_set_declare_qword_value_i64(&mut self, index: usize, new_value: i64) -> Result<(), IcedError> {
2327		self.try_set_declare_qword_value(index, new_value as u64)
2328	}
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	pub fn set_declare_qword_value(&mut self, index: usize, new_value: u64) {
2343		match self.try_set_declare_qword_value(index, new_value) {
2344			Ok(()) => {}
2345			Err(_) => debug_assert!(false, "Invalid index: {}", index),
2346		}
2347	}
2348
2349	#[allow(clippy::missing_inline_in_public_items)]
2350	#[doc(hidden)]
2351	pub fn try_set_declare_qword_value(&mut self, index: usize, new_value: u64) -> Result<(), IcedError> {
2352		match index {
2353			0 => {
2354				self.regs[0] = Register::from_u8(new_value as u8);
2355				self.regs[1] = Register::from_u8((new_value >> 8) as u8);
2356				self.regs[2] = Register::from_u8((new_value >> 16) as u8);
2357				self.regs[3] = Register::from_u8((new_value >> 24) as u8);
2358				self.immediate = (new_value >> 32) as u32;
2359			}
2360			1 => self.mem_displ = new_value,
2361			_ => return Err(IcedError::new("Invalid index")),
2362		}
2363		Ok(())
2364	}
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	pub fn get_declare_qword_value(&self, index: usize) -> u64 {
2379		match self.try_get_declare_qword_value(index) {
2380			Ok(value) => value,
2381			Err(_) => {
2382				debug_assert!(false, "Invalid index: {}", index);
2383				0
2384			}
2385		}
2386	}
2387
2388	#[allow(clippy::missing_inline_in_public_items)]
2389	#[doc(hidden)]
2390	pub const fn try_get_declare_qword_value(&self, index: usize) -> Result<u64, IcedError> {
2391		Ok(match index {
2392			0 => {
2393				self.regs[0] as u64
2394					| ((self.regs[1] as u64) << 8)
2395					| ((self.regs[2] as u64) << 16)
2396					| ((self.regs[3] as u64) << 24)
2397					| ((self.immediate as u64) << 32)
2398			}
2399			1 => self.mem_displ,
2400			_ => return Err(IcedError::new("Invalid index")),
2401		})
2402	}
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	pub const fn is_vsib(&self) -> bool {
2411		self.vsib().is_some()
2412	}
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	pub const fn is_vsib32(&self) -> bool {
2420		if let Some(is_vsib64) = self.vsib() {
2421			!is_vsib64
2422		} else {
2423			false
2424		}
2425	}
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	pub const fn is_vsib64(&self) -> bool {
2433		if let Some(is_vsib64) = self.vsib() {
2434			is_vsib64
2435		} else {
2436			false
2437		}
2438	}
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	pub const fn vsib(&self) -> Option<bool> {
2451		#[cfg_attr(feature = "cargo-fmt", rustfmt::skip)]
2452		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			=> 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			=> Some(true),
2560			// GENERATOR-END: Vsib64
2561
2562			_ => None,
2563		}
2564	}
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	pub const fn suppress_all_exceptions(&self) -> bool {
2574		(self.flags1 & InstrFlags1::SUPPRESS_ALL_EXCEPTIONS) != 0
2575	}
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	pub fn set_suppress_all_exceptions(&mut self, new_value: bool) {
2588		if new_value {
2589			self.flags1 |= InstrFlags1::SUPPRESS_ALL_EXCEPTIONS;
2590		} else {
2591			self.flags1 &= !InstrFlags1::SUPPRESS_ALL_EXCEPTIONS;
2592		}
2593	}
2594
2595	/// Checks if the memory operand is `RIP`/`EIP` relative
2596	#[must_use]
2597	#[inline]
2598	pub fn is_ip_rel_memory_operand(&self) -> bool {
2599		let base_reg = self.memory_base();
2600		base_reg == Register::RIP || base_reg == Register::EIP
2601	}
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	pub fn ip_rel_memory_address(&self) -> u64 {
2612		if self.memory_base() == Register::RIP {
2613			self.memory_displacement64()
2614		} else {
2615			self.memory_displacement32() as u64
2616		}
2617	}
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	pub fn virtual_address<F>(&self, operand: u32, element_index: usize, get_register_value: F) -> Option<u64>
2658	where
2659		F: FnMut(Register, usize, usize) -> Option<u64>,
2660	{
2661		self.try_virtual_address(operand, element_index, get_register_value)
2662	}
2663
2664	#[must_use]
2665	#[allow(clippy::missing_inline_in_public_items)]
2666	#[doc(hidden)]
2667	pub fn try_virtual_address<F>(&self, operand: u32, element_index: usize, mut get_register_value: F) -> Option<u64>
2668	where
2669		F: FnMut(Register, usize, usize) -> Option<u64>,
2670	{
2671		let op_kind = self.op_kind(operand);
2672		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			| OpKind::Immediate32to64 => 0,
2688
2689			OpKind::MemorySegSI => {
2690				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				get_register_value(self.memory_segment(), 0, 0)?.wrapping_add(get_register_value(Register::ESI, 0, 0)? as u32 as u64)
2694			}
2695			OpKind::MemorySegRSI => get_register_value(self.memory_segment(), 0, 0)?.wrapping_add(get_register_value(Register::RSI, 0, 0)?),
2696			OpKind::MemorySegDI => {
2697				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				get_register_value(self.memory_segment(), 0, 0)?.wrapping_add(get_register_value(Register::EDI, 0, 0)? as u32 as u64)
2701			}
2702			OpKind::MemorySegRDI => get_register_value(self.memory_segment(), 0, 0)?.wrapping_add(get_register_value(Register::RDI, 0, 0)?),
2703			OpKind::MemoryESDI => get_register_value(Register::ES, 0, 0)?.wrapping_add(get_register_value(Register::DI, 0, 0)? as u16 as u64),
2704			OpKind::MemoryESEDI => get_register_value(Register::ES, 0, 0)?.wrapping_add(get_register_value(Register::EDI, 0, 0)? as u32 as u64),
2705			OpKind::MemoryESRDI => get_register_value(Register::ES, 0, 0)?.wrapping_add(get_register_value(Register::RDI, 0, 0)?),
2706			OpKind::Memory => {
2707				let base_reg = self.memory_base();
2708				let index_reg = self.memory_index();
2709				let addr_size = instruction_internal::get_address_size_in_bytes(base_reg, index_reg, self.memory_displ_size(), self.code_size());
2710				let mut offset = self.memory_displacement64();
2711				let offset_mask = match addr_size {
2712					8 => u64::MAX,
2713					4 => u32::MAX as u64,
2714					_ => {
2715						debug_assert_eq!(addr_size, 2);
2716						u16::MAX as u64
2717					}
2718				};
2719				match base_reg {
2720					Register::None | Register::EIP | Register::RIP => {}
2721					_ => offset = offset.wrapping_add(get_register_value(base_reg, 0, 0)?),
2722				}
2723				let code = self.code();
2724				if index_reg != Register::None && !code.ignores_index() && !code.is_tile_stride_index() {
2725					if let Some(is_vsib64) = self.vsib() {
2726						if is_vsib64 {
2727							offset = offset.wrapping_add(
2728								get_register_value(index_reg, element_index, 8)? << instruction_internal::internal_get_memory_index_scale(self),
2729							);
2730						} else {
2731							offset = offset.wrapping_add(
2732								(get_register_value(index_reg, element_index, 4)? as i32 as u64)
2733									<< instruction_internal::internal_get_memory_index_scale(self),
2734							);
2735						}
2736					} else {
2737						offset =
2738							offset.wrapping_add(get_register_value(index_reg, 0, 0)? << instruction_internal::internal_get_memory_index_scale(self));
2739					}
2740				}
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				offset &= offset_mask;
2755				if !code.ignores_segment() {
2756					get_register_value(self.memory_segment(), 0, 0)?.wrapping_add(offset)
2757				} else {
2758					offset
2759				}
2760			}
2761		})
2762	}
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)]
2768pub struct FpuStackIncrementInfo {
2769	increment: i32,
2770	conditional: bool,
2771	writes_top: bool,
2772}
2773
2774#[cfg(feature = "instr_info")]
2775impl FpuStackIncrementInfo {
2776	/// Constructor
2777	#[must_use]
2778	#[inline]
2779	pub const fn new(increment: i32, conditional: bool, writes_top: bool) -> Self {
2780		Self { increment, conditional, writes_top }
2781	}
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	pub const fn increment(&self) -> i32 {
2794		self.increment
2795	}
2796
2797	/// `true` if it's a conditional push/pop (eg. `FPTAN` or `FSINCOS`)
2798	#[must_use]
2799	#[inline]
2800	pub const fn conditional(&self) -> bool {
2801		self.conditional
2802	}
2803
2804	/// `true` if `TOP` is written (it's a conditional/unconditional push/pop, `FNSAVE`, `FLDENV`, etc)
2805	#[must_use]
2806	#[inline]
2807	pub const fn writes_top(&self) -> bool {
2808		self.writes_top
2809	}
2810}
2811
2812#[cfg(feature = "instr_info")]
2813impl 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	pub fn stack_pointer_increment(&self) -> i32 {
2833		#[cfg_attr(feature = "cargo-fmt", rustfmt::skip)]
2834		#[allow(clippy::match_single_binding)]
2835		match self.code() {
2836			// GENERATOR-BEGIN: StackPointerIncrementTable
2837			// ⚠️This was generated by GENERATOR!🦹‍♂️
2838			Code::Pushad => -32,
2839			Code::Pushaw
2840			| 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			| 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			| 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			| 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			| 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			| 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			| Code::Popq_GS => 8,
2907			Code::Popaw
2908			| Code::Retfq => 16,
2909			Code::Uiret => 24,
2910			Code::Popad => 32,
2911			Code::Iretq => 40,
2912			Code::Eretu
2913			| Code::Erets => 48,
2914			Code::Enterw_imm16_imm8 => -(2 + (self.immediate8_2nd() as i32 & 0x1F) * 2 + self.immediate16() as i32),
2915			Code::Enterd_imm16_imm8 => -(4 + (self.immediate8_2nd() as i32 & 0x1F) * 4 + self.immediate16() as i32),
2916			Code::Enterq_imm16_imm8 => -(8 + (self.immediate8_2nd() as i32 & 0x1F) * 8 + self.immediate16() as i32),
2917			Code::Iretw => if self.code_size() == CodeSize::Code64 { 2 * 5 } else { 2 * 3 },
2918			Code::Iretd => if self.code_size() == CodeSize::Code64 { 4 * 5 } else { 4 * 3 },
2919			Code::Retnw_imm16 => 2 + self.immediate16() as i32,
2920			Code::Retnd_imm16
2921			| Code::Retfw_imm16 => 4 + self.immediate16() as i32,
2922			Code::Retnq_imm16
2923			| Code::Retfd_imm16 => 8 + self.immediate16() as i32,
2924			Code::Retfq_imm16 => 16 + self.immediate16() as i32,
2925			// GENERATOR-END: StackPointerIncrementTable
2926			_ => 0,
2927		}
2928	}
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	pub fn fpu_stack_increment_info(&self) -> FpuStackIncrementInfo {
2952		#[cfg_attr(feature = "cargo-fmt", rustfmt::skip)]
2953		#[allow(clippy::match_single_binding)]
2954		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			=> FpuStackIncrementInfo { increment: -1, conditional: false, writes_top: true },
2975			Code::Fptan
2976			| Code::Fsincos
2977			=> 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			=> 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			=> FpuStackIncrementInfo { increment: 1, conditional: false, writes_top: true },
3026			Code::Fucompp
3027			| Code::Fcompp
3028			=> FpuStackIncrementInfo { increment: 2, conditional: false, writes_top: true },
3029			// GENERATOR-END: FpuStackIncrementInfoTable
3030			_ => FpuStackIncrementInfo::default(),
3031		}
3032	}
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	pub fn encoding(&self) -> EncodingKind {
3051		self.code().encoding()
3052	}
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	pub fn cpuid_features(&self) -> &'static [CpuidFeature] {
3082		self.code().cpuid_features()
3083	}
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	pub fn flow_control(&self) -> FlowControl {
3113		self.code().flow_control()
3114	}
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	pub fn is_privileged(&self) -> bool {
3120		self.code().is_privileged()
3121	}
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	pub fn is_stack_instruction(&self) -> bool {
3150		self.code().is_stack_instruction()
3151	}
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	pub fn is_save_restore_instruction(&self) -> bool {
3157		self.code().is_save_restore_instruction()
3158	}
3159
3160	/// `true` if it's a "string" instruction, such as `MOVS`, `LODS`, `SCAS`, etc.
3161	#[must_use]
3162	#[inline]
3163	pub const fn is_string_instruction(&self) -> bool {
3164		self.code().is_string_instruction()
3165	}
3166
3167	#[must_use]
3168	fn rflags_info(&self) -> RflagsInfo {
3169		let flags1 = crate::info::info_table::TABLE[self.code() as usize].0;
3170		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		let result = unsafe { mem::transmute(((flags1 >> InfoFlags1::RFLAGS_INFO_SHIFT) & InfoFlags1::RFLAGS_INFO_MASK) as u8) };
3177		let e = implied_access.wrapping_sub(ImpliedAccess::Shift_Ib_MASK1FMOD9 as u32);
3178		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				let m = if e == 0 { 9 } else { 17 };
3184				match (self.immediate8() & 0x1F) % m {
3185					0 => return RflagsInfo::None,
3186					1 => return RflagsInfo::R_c_W_co,
3187					_ => {}
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				let mask = if e == 2 { 0x1F } else { 0x3F };
3194				match self.immediate8() & mask {
3195					0 => return RflagsInfo::None,
3196					1 => {
3197						if result == RflagsInfo::W_c_U_o {
3198							return RflagsInfo::W_co;
3199						} else if result == RflagsInfo::R_c_W_c_U_o {
3200							return RflagsInfo::R_c_W_co;
3201						} else {
3202							debug_assert_eq!(result, RflagsInfo::W_cpsz_U_ao);
3203							return RflagsInfo::W_copsz_U_a;
3204						}
3205					}
3206					_ => {}
3207				}
3208			}
3209			4 => {
3210				const _: () = assert!(ImpliedAccess::Clear_rflags as u32 - ImpliedAccess::Shift_Ib_MASK1FMOD9 as u32 == 4);
3211				if self.op0_register() == self.op1_register() && self.op0_kind() == OpKind::Register && self.op1_kind() == OpKind::Register {
3212					if self.mnemonic() == Mnemonic::Xor {
3213						return RflagsInfo::C_cos_S_pz_U_a;
3214					} else {
3215						return RflagsInfo::C_acos_S_pz;
3216					}
3217				}
3218			}
3219			_ => {}
3220		}
3221		result
3222	}
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	pub fn rflags_read(&self) -> u32 {
3261		crate::info::rflags_table::FLAGS_READ[self.rflags_info() as usize] as u32
3262	}
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	pub fn rflags_written(&self) -> u32 {
3301		crate::info::rflags_table::FLAGS_WRITTEN[self.rflags_info() as usize] as u32
3302	}
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	pub fn rflags_cleared(&self) -> u32 {
3341		crate::info::rflags_table::FLAGS_CLEARED[self.rflags_info() as usize] as u32
3342	}
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	pub fn rflags_set(&self) -> u32 {
3381		crate::info::rflags_table::FLAGS_SET[self.rflags_info() as usize] as u32
3382	}
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	pub fn rflags_undefined(&self) -> u32 {
3421		crate::info::rflags_table::FLAGS_UNDEFINED[self.rflags_info() as usize] as u32
3422	}
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	pub fn rflags_modified(&self) -> u32 {
3459		crate::info::rflags_table::FLAGS_MODIFIED[self.rflags_info() as usize] as u32
3460	}
3461
3462	/// Checks if it's a `Jcc SHORT` or `Jcc NEAR` instruction
3463	#[must_use]
3464	#[inline]
3465	pub const fn is_jcc_short_or_near(&self) -> bool {
3466		self.code().is_jcc_short_or_near()
3467	}
3468
3469	/// Checks if it's a `Jcc NEAR` instruction
3470	#[must_use]
3471	#[inline]
3472	pub const fn is_jcc_near(&self) -> bool {
3473		self.code().is_jcc_near()
3474	}
3475
3476	/// Checks if it's a `Jcc SHORT` instruction
3477	#[must_use]
3478	#[inline]
3479	pub const fn is_jcc_short(&self) -> bool {
3480		self.code().is_jcc_short()
3481	}
3482
3483	/// Checks if it's a `JMP SHORT` instruction
3484	#[must_use]
3485	#[inline]
3486	pub const fn is_jmp_short(&self) -> bool {
3487		self.code().is_jmp_short()
3488	}
3489
3490	/// Checks if it's a `JMP NEAR` instruction
3491	#[must_use]
3492	#[inline]
3493	pub const fn is_jmp_near(&self) -> bool {
3494		self.code().is_jmp_near()
3495	}
3496
3497	/// Checks if it's a `JMP SHORT` or a `JMP NEAR` instruction
3498	#[must_use]
3499	#[inline]
3500	pub const fn is_jmp_short_or_near(&self) -> bool {
3501		self.code().is_jmp_short_or_near()
3502	}
3503
3504	/// Checks if it's a `JMP FAR` instruction
3505	#[must_use]
3506	#[inline]
3507	pub const fn is_jmp_far(&self) -> bool {
3508		self.code().is_jmp_far()
3509	}
3510
3511	/// Checks if it's a `CALL NEAR` instruction
3512	#[must_use]
3513	#[inline]
3514	pub const fn is_call_near(&self) -> bool {
3515		self.code().is_call_near()
3516	}
3517
3518	/// Checks if it's a `CALL FAR` instruction
3519	#[must_use]
3520	#[inline]
3521	pub const fn is_call_far(&self) -> bool {
3522		self.code().is_call_far()
3523	}
3524
3525	/// Checks if it's a `JMP NEAR reg/[mem]` instruction
3526	#[must_use]
3527	#[inline]
3528	pub const fn is_jmp_near_indirect(&self) -> bool {
3529		self.code().is_jmp_near_indirect()
3530	}
3531
3532	/// Checks if it's a `JMP FAR [mem]` instruction
3533	#[must_use]
3534	#[inline]
3535	pub const fn is_jmp_far_indirect(&self) -> bool {
3536		self.code().is_jmp_far_indirect()
3537	}
3538
3539	/// Checks if it's a `CALL NEAR reg/[mem]` instruction
3540	#[must_use]
3541	#[inline]
3542	pub const fn is_call_near_indirect(&self) -> bool {
3543		self.code().is_call_near_indirect()
3544	}
3545
3546	/// Checks if it's a `CALL FAR [mem]` instruction
3547	#[must_use]
3548	#[inline]
3549	pub const fn is_call_far_indirect(&self) -> bool {
3550		self.code().is_call_far_indirect()
3551	}
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	pub const fn is_jcx_short(&self) -> bool {
3581		self.code().is_jcx_short()
3582	}
3583
3584	/// Checks if it's a `LOOPcc SHORT` instruction
3585	#[must_use]
3586	#[inline]
3587	pub const fn is_loopcc(&self) -> bool {
3588		self.code().is_loopcc()
3589	}
3590
3591	/// Checks if it's a `LOOP SHORT` instruction
3592	#[must_use]
3593	#[inline]
3594	pub const fn is_loop(&self) -> bool {
3595		self.code().is_loop()
3596	}
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	pub fn negate_condition_code(&mut self) {
3619		self.set_code(self.code().negate_condition_code())
3620	}
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	pub fn as_short_branch(&mut self) {
3642		self.set_code(self.code().as_short_branch())
3643	}
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	pub fn as_near_branch(&mut self) {
3665		self.set_code(self.code().as_near_branch())
3666	}
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	pub fn condition_code(&self) -> ConditionCode {
3703		self.code().condition_code()
3704	}
3705}
3706
3707#[cfg(all(feature = "encoder", feature = "op_code_info"))]
3708impl Instruction {
3709	/// Gets the [`OpCodeInfo`]
3710	///
3711	/// [`OpCodeInfo`]: struct.OpCodeInfo.html
3712	#[must_use]
3713	#[inline]
3714	pub fn op_code(&self) -> &'static OpCodeInfo {
3715		self.code().op_code()
3716	}
3717}
3718
3719impl Eq for Instruction {}
3720
3721impl PartialEq<Instruction> for Instruction {
3722	#[must_use]
3723	#[allow(clippy::missing_inline_in_public_items)]
3724	fn eq(&self, other: &Self) -> bool {
3725		self.mem_displ == other.mem_displ
3726			&& ((self.flags1 ^ other.flags1) & !InstrFlags1::EQUALS_IGNORE_MASK) == 0
3727			&& self.immediate == other.immediate
3728			&& self.code == other.code
3729			&& self.mem_base_reg == other.mem_base_reg
3730			&& self.mem_index_reg == other.mem_index_reg
3731			&& self.regs == other.regs
3732			&& self.op_kinds == other.op_kinds
3733			&& self.scale == other.scale
3734			&& self.displ_size == other.displ_size
3735			&& self.pad == other.pad
3736	}
3737}
3738
3739impl Hash for Instruction {
3740	#[allow(clippy::missing_inline_in_public_items)]
3741	fn hash<H: Hasher>(&self, state: &mut H) {
3742		self.mem_displ.hash(state);
3743		(self.flags1 & !InstrFlags1::EQUALS_IGNORE_MASK).hash(state);
3744		self.immediate.hash(state);
3745		self.code.hash(state);
3746		self.mem_base_reg.hash(state);
3747		self.mem_index_reg.hash(state);
3748		self.regs.hash(state);
3749		self.op_kinds.hash(state);
3750		self.scale.hash(state);
3751		self.displ_size.hash(state);
3752		self.pad.hash(state);
3753	}
3754}
3755
3756#[cfg(any(feature = "gas", feature = "intel", feature = "masm", feature = "nasm"))]
3757struct 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"))]
3762impl<'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"))]
3768impl 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"))]
3777impl 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
3812struct OpKindIterator {
3813	count: u8,
3814	index: u8,
3815	op_kinds: [OpKind; IcedConstants::MAX_OP_COUNT],
3816}
3817
3818impl OpKindIterator {
3819	fn new(instruction: &Instruction) -> Self {
3820		// `index`/`count` are `u8`
3821		const _: () = assert!(IcedConstants::MAX_OP_COUNT <= core::u8::MAX as usize);
3822		OpKindIterator {
3823			count: instruction.op_count() as u8,
3824			index: 0,
3825			op_kinds: [instruction.op0_kind(), instruction.op1_kind(), instruction.op2_kind(), instruction.op3_kind(), instruction.op4_kind()],
3826		}
3827	}
3828}
3829
3830impl Iterator for OpKindIterator {
3831	type Item = OpKind;
3832
3833	#[inline]
3834	fn next(&mut self) -> Option<Self::Item> {
3835		let index = self.index;
3836		if index < self.count {
3837			self.index = index + 1;
3838			Some(self.op_kinds[index as usize])
3839		} else {
3840			None
3841		}
3842	}
3843
3844	#[inline]
3845	fn size_hint(&self) -> (usize, Option<usize>) {
3846		let len = self.count as usize - self.index as usize;
3847		(len, Some(len))
3848	}
3849}
3850
3851impl ExactSizeIterator for OpKindIterator {}
3852impl 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")]
3858const _: () = {
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};