logo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// SPDX-License-Identifier: MIT
// Copyright (C) 2018-present iced project and contributors

/// Contains the offsets of the displacement and immediate. Call [`Decoder::get_constant_offsets()`] or
/// [`Encoder::get_constant_offsets()`] to get the offsets of the constants after the instruction has been
/// decoded/encoded.
///
/// [`Decoder::get_constant_offsets()`]: struct.Decoder.html#method.get_constant_offsets
/// [`Encoder::get_constant_offsets()`]: struct.Encoder.html#method.get_constant_offsets
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Hash)]
#[allow(dead_code)]
pub struct ConstantOffsets {
	pub(crate) displacement_offset: u8,
	pub(crate) displacement_size: u8,
	pub(crate) immediate_offset: u8,
	pub(crate) immediate_size: u8,
	pub(crate) immediate_offset2: u8,
	pub(crate) immediate_size2: u8,
	pad1: u8,
	pad2: u8,
}

impl ConstantOffsets {
	/// The offset of the displacement, if any
	#[must_use]
	#[inline]
	pub fn displacement_offset(&self) -> usize {
		self.displacement_offset as usize
	}

	/// Size in bytes of the displacement, or 0 if there's no displacement
	#[must_use]
	#[inline]
	pub fn displacement_size(&self) -> usize {
		self.displacement_size as usize
	}

	/// The offset of the first immediate, if any.
	///
	/// This field can be invalid even if the operand has an immediate if it's an immediate that isn't part
	/// of the instruction stream, eg. `SHL AL,1`.
	#[must_use]
	#[inline]
	pub fn immediate_offset(&self) -> usize {
		self.immediate_offset as usize
	}

	/// Size in bytes of the first immediate, or 0 if there's no immediate
	#[must_use]
	#[inline]
	pub fn immediate_size(&self) -> usize {
		self.immediate_size as usize
	}

	/// The offset of the second immediate, if any.
	#[must_use]
	#[inline]
	pub fn immediate_offset2(&self) -> usize {
		self.immediate_offset2 as usize
	}

	/// Size in bytes of the second immediate, or 0 if there's no second immediate
	#[must_use]
	#[inline]
	pub fn immediate_size2(&self) -> usize {
		self.immediate_size2 as usize
	}

	/// `true` if [`displacement_offset()`] and [`displacement_size()`] are valid
	///
	/// [`displacement_offset()`]: #method.displacement_offset
	/// [`displacement_size()`]: #method.displacement_size
	#[must_use]
	#[inline]
	pub fn has_displacement(&self) -> bool {
		self.displacement_size != 0
	}

	/// `true` if [`immediate_offset()`] and [`immediate_size()`] are valid
	///
	/// [`immediate_offset()`]: #method.immediate_offset
	/// [`immediate_size()`]: #method.immediate_size
	#[must_use]
	#[inline]
	pub fn has_immediate(&self) -> bool {
		self.immediate_size != 0
	}

	/// `true` if [`immediate_offset2()`] and [`immediate_size2()`] are valid
	///
	/// [`immediate_offset2()`]: #method.immediate_offset2
	/// [`immediate_size2()`]: #method.immediate_size2
	#[must_use]
	#[inline]
	pub fn has_immediate2(&self) -> bool {
		self.immediate_size2 != 0
	}
}