iced_x86/encoder/
mem_op.rs

1// SPDX-License-Identifier: MIT
2// Copyright (C) 2018-present iced project and contributors
3
4use crate::*;
5
6/// Memory operand passed to one of [`Instruction`]'s `with_*()` constructor methods
7///
8/// [`Instruction`]: struct.Instruction.html
9#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Hash)]
10pub struct MemoryOperand {
11	/// Segment override or [`Register::None`]
12	///
13	/// [`Register::None`]: enum.Register.html#variant.None
14	pub segment_prefix: Register,
15
16	/// Base register or [`Register::None`]
17	///
18	/// [`Register::None`]: enum.Register.html#variant.None
19	pub base: Register,
20
21	/// Index register or [`Register::None`]
22	///
23	/// [`Register::None`]: enum.Register.html#variant.None
24	pub index: Register,
25
26	/// Index register scale (1, 2, 4, or 8)
27	pub scale: u32,
28
29	/// Memory displacement
30	pub displacement: i64,
31
32	/// 0 (no displ), 1 (16/32/64-bit, but use 2/4/8 if it doesn't fit in a `i8`), 2 (16-bit), 4 (32-bit) or 8 (64-bit)
33	pub displ_size: u32,
34
35	/// `true` if it's broadcast memory (EVEX instructions)
36	pub is_broadcast: bool,
37}
38
39impl MemoryOperand {
40	/// Constructor
41	///
42	/// # Arguments
43	///
44	/// * `base`: Base register or [`Register::None`]
45	/// * `index`: Index register or [`Register::None`]
46	/// * `scale`: Index register scale (1, 2, 4, or 8)
47	/// * `displacement`: Memory displacement
48	/// * `displ_size`: 0 (no displ), 1 (16/32/64-bit, but use 2/4/8 if it doesn't fit in a `i8`), 2 (16-bit), 4 (32-bit) or 8 (64-bit)
49	/// * `is_broadcast`: `true` if it's broadcast memory (EVEX instructions)
50	/// * `segment_prefix`: Segment override or [`Register::None`]
51	///
52	/// [`Register::None`]: enum.Register.html#variant.None
53	#[must_use]
54	#[inline]
55	pub const fn new(
56		base: Register, index: Register, scale: u32, displacement: i64, displ_size: u32, is_broadcast: bool, segment_prefix: Register,
57	) -> Self {
58		Self { segment_prefix, base, index, scale, displacement, displ_size, is_broadcast }
59	}
60
61	/// Constructor
62	///
63	/// # Arguments
64	///
65	/// * `base`: Base register or [`Register::None`]
66	/// * `index`: Index register or [`Register::None`]
67	/// * `scale`: Index register scale (1, 2, 4, or 8)
68	/// * `is_broadcast`: `true` if it's broadcast memory (EVEX instructions)
69	/// * `segment_prefix`: Segment override or [`Register::None`]
70	///
71	/// [`Register::None`]: enum.Register.html#variant.None
72	#[must_use]
73	#[inline]
74	pub const fn with_base_index_scale_bcst_seg(base: Register, index: Register, scale: u32, is_broadcast: bool, segment_prefix: Register) -> Self {
75		Self { segment_prefix, base, index, scale, displacement: 0, displ_size: 0, is_broadcast }
76	}
77
78	/// Constructor
79	///
80	/// # Arguments
81	///
82	/// * `base`: Base register or [`Register::None`]
83	/// * `displacement`: Memory displacement
84	/// * `displ_size`: 0 (no displ), 1 (16/32/64-bit, but use 2/4/8 if it doesn't fit in a `i8`), 2 (16-bit), 4 (32-bit) or 8 (64-bit)
85	/// * `is_broadcast`: `true` if it's broadcast memory (EVEX instructions)
86	/// * `segment_prefix`: Segment override or [`Register::None`]
87	///
88	/// [`Register::None`]: enum.Register.html#variant.None
89	#[must_use]
90	#[inline]
91	pub const fn with_base_displ_size_bcst_seg(
92		base: Register, displacement: i64, displ_size: u32, is_broadcast: bool, segment_prefix: Register,
93	) -> Self {
94		Self { segment_prefix, base, index: Register::None, scale: 1, displacement, displ_size, is_broadcast }
95	}
96
97	/// Constructor
98	///
99	/// # Arguments
100	///
101	/// * `index`: Index register or [`Register::None`]
102	/// * `scale`: Index register scale (1, 2, 4, or 8)
103	/// * `displacement`: Memory displacement
104	/// * `displ_size`: 0 (no displ), 1 (16/32/64-bit, but use 2/4/8 if it doesn't fit in a `i8`), 2 (16-bit), 4 (32-bit) or 8 (64-bit)
105	/// * `is_broadcast`: `true` if it's broadcast memory (EVEX instructions)
106	/// * `segment_prefix`: Segment override or [`Register::None`]
107	///
108	/// [`Register::None`]: enum.Register.html#variant.None
109	#[must_use]
110	#[inline]
111	pub const fn with_index_scale_displ_size_bcst_seg(
112		index: Register, scale: u32, displacement: i64, displ_size: u32, is_broadcast: bool, segment_prefix: Register,
113	) -> Self {
114		Self { segment_prefix, base: Register::None, index, scale, displacement, displ_size, is_broadcast }
115	}
116
117	/// Constructor
118	///
119	/// # Arguments
120	///
121	/// * `base`: Base register or [`Register::None`]
122	/// * `displacement`: Memory displacement
123	/// * `is_broadcast`: `true` if it's broadcast memory (EVEX instructions)
124	/// * `segment_prefix`: Segment override or [`Register::None`]
125	///
126	/// [`Register::None`]: enum.Register.html#variant.None
127	#[must_use]
128	#[inline]
129	pub const fn with_base_displ_bcst_seg(base: Register, displacement: i64, is_broadcast: bool, segment_prefix: Register) -> Self {
130		Self { segment_prefix, base, index: Register::None, scale: 1, displacement, displ_size: 1, is_broadcast }
131	}
132
133	/// Constructor
134	///
135	/// # Arguments
136	///
137	/// * `base`: Base register or [`Register::None`]
138	/// * `index`: Index register or [`Register::None`]
139	/// * `scale`: Index register scale (1, 2, 4, or 8)
140	/// * `displacement`: Memory displacement
141	/// * `displ_size`: 0 (no displ), 1 (16/32/64-bit, but use 2/4/8 if it doesn't fit in a `i8`), 2 (16-bit), 4 (32-bit) or 8 (64-bit)
142	///
143	/// [`Register::None`]: enum.Register.html#variant.None
144	#[must_use]
145	#[inline]
146	pub const fn with_base_index_scale_displ_size(base: Register, index: Register, scale: u32, displacement: i64, displ_size: u32) -> Self {
147		Self { segment_prefix: Register::None, base, index, scale, displacement, displ_size, is_broadcast: false }
148	}
149
150	/// Constructor
151	///
152	/// # Arguments
153	///
154	/// * `base`: Base register or [`Register::None`]
155	/// * `index`: Index register or [`Register::None`]
156	/// * `scale`: Index register scale (1, 2, 4, or 8)
157	///
158	/// [`Register::None`]: enum.Register.html#variant.None
159	#[must_use]
160	#[inline]
161	pub const fn with_base_index_scale(base: Register, index: Register, scale: u32) -> Self {
162		Self { segment_prefix: Register::None, base, index, scale, displacement: 0, displ_size: 0, is_broadcast: false }
163	}
164
165	/// Constructor
166	///
167	/// # Arguments
168	///
169	/// * `base`: Base register or [`Register::None`]
170	/// * `index`: Index register or [`Register::None`]
171	///
172	/// [`Register::None`]: enum.Register.html#variant.None
173	#[must_use]
174	#[inline]
175	pub const fn with_base_index(base: Register, index: Register) -> Self {
176		Self { segment_prefix: Register::None, base, index, scale: 1, displacement: 0, displ_size: 0, is_broadcast: false }
177	}
178
179	/// Constructor
180	///
181	/// # Arguments
182	///
183	/// * `base`: Base register or [`Register::None`]
184	/// * `displacement`: Memory displacement
185	/// * `displ_size`: 0 (no displ), 1 (16/32/64-bit, but use 2/4/8 if it doesn't fit in a `i8`), 2 (16-bit), 4 (32-bit) or 8 (64-bit)
186	///
187	/// [`Register::None`]: enum.Register.html#variant.None
188	#[must_use]
189	#[inline]
190	pub const fn with_base_displ_size(base: Register, displacement: i64, displ_size: u32) -> Self {
191		Self { segment_prefix: Register::None, base, index: Register::None, scale: 1, displacement, displ_size, is_broadcast: false }
192	}
193
194	/// Constructor
195	///
196	/// # Arguments
197	///
198	/// * `index`: Index register or [`Register::None`]
199	/// * `scale`: Index register scale (1, 2, 4, or 8)
200	/// * `displacement`: Memory displacement
201	/// * `displ_size`: 0 (no displ), 1 (16/32/64-bit, but use 2/4/8 if it doesn't fit in a `i8`), 2 (16-bit), 4 (32-bit) or 8 (64-bit)
202	///
203	/// [`Register::None`]: enum.Register.html#variant.None
204	#[must_use]
205	#[inline]
206	pub const fn with_index_scale_displ_size(index: Register, scale: u32, displacement: i64, displ_size: u32) -> Self {
207		Self { segment_prefix: Register::None, base: Register::None, index, scale, displacement, displ_size, is_broadcast: false }
208	}
209
210	/// Constructor
211	///
212	/// # Arguments
213	///
214	/// * `base`: Base register or [`Register::None`]
215	/// * `displacement`: Memory displacement
216	///
217	/// [`Register::None`]: enum.Register.html#variant.None
218	#[must_use]
219	#[inline]
220	pub const fn with_base_displ(base: Register, displacement: i64) -> Self {
221		Self { segment_prefix: Register::None, base, index: Register::None, scale: 1, displacement, displ_size: 1, is_broadcast: false }
222	}
223
224	/// Constructor
225	///
226	/// # Arguments
227	///
228	/// * `base`: Base register or [`Register::None`]
229	///
230	/// [`Register::None`]: enum.Register.html#variant.None
231	#[must_use]
232	#[inline]
233	pub const fn with_base(base: Register) -> Self {
234		Self { segment_prefix: Register::None, base, index: Register::None, scale: 1, displacement: 0, displ_size: 0, is_broadcast: false }
235	}
236
237	/// Constructor
238	///
239	/// # Arguments
240	///
241	/// * `displacement`: Memory displacement
242	/// * `displ_size`: 2 (16-bit), 4 (32-bit) or 8 (64-bit)
243	///
244	/// [`Register::None`]: enum.Register.html#variant.None
245	#[must_use]
246	#[inline]
247	pub const fn with_displ(displacement: u64, displ_size: u32) -> Self {
248		Self {
249			segment_prefix: Register::None,
250			base: Register::None,
251			index: Register::None,
252			scale: 1,
253			displacement: displacement as i64,
254			displ_size,
255			is_broadcast: false,
256		}
257	}
258}