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}