closure_ffi_iced_x86/code_asm/
mem.rs1use crate::code_asm::op_state::{CodeAsmOpState, MemoryOperandSize};
5use crate::code_asm::{AsmRegister16, AsmRegister32, AsmRegister64, AsmRegisterXmm, AsmRegisterYmm, AsmRegisterZmm, CodeLabel};
6use crate::{MemoryOperand, Register};
7use core::ops::{Add, Mul, Sub};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq)]
30pub struct AsmMemoryOperand {
31 base: Register,
32 index: Register,
33 scale: u8,
34 displ: i64,
35 state: CodeAsmOpState,
36}
37
38impl AsmMemoryOperand {
39 #[must_use]
42 #[inline]
43 #[rustfmt::skip]
44 pub(crate) fn ptr(mut self) -> Self {
45 self.state.ptr(MemoryOperandSize::None);
46 self
47 }
48
49 #[must_use]
50 #[inline]
51 #[rustfmt::skip]
52 pub(crate) fn byte_ptr(mut self) -> Self {
53 self.state.ptr(MemoryOperandSize::Byte);
54 self
55 }
56
57 #[must_use]
58 #[inline]
59 #[rustfmt::skip]
60 pub(crate) fn word_ptr(mut self) -> Self {
61 self.state.ptr(MemoryOperandSize::Word);
62 self
63 }
64
65 #[must_use]
66 #[inline]
67 #[rustfmt::skip]
68 pub(crate) fn dword_ptr(mut self) -> Self {
69 self.state.ptr(MemoryOperandSize::Dword);
70 self
71 }
72
73 #[must_use]
74 #[inline]
75 #[rustfmt::skip]
76 pub(crate) fn qword_ptr(mut self) -> Self {
77 self.state.ptr(MemoryOperandSize::Qword);
78 self
79 }
80
81 #[must_use]
82 #[inline]
83 #[rustfmt::skip]
84 pub(crate) fn mmword_ptr(mut self) -> Self {
85 self.state.ptr(MemoryOperandSize::Qword);
86 self
87 }
88
89 #[must_use]
90 #[inline]
91 #[rustfmt::skip]
92 pub(crate) fn tbyte_ptr(mut self) -> Self {
93 self.state.ptr(MemoryOperandSize::Tbyte);
94 self
95 }
96
97 #[must_use]
98 #[inline]
99 #[rustfmt::skip]
100 pub(crate) fn tword_ptr(mut self) -> Self {
101 self.state.ptr(MemoryOperandSize::Tbyte);
102 self
103 }
104
105 #[must_use]
106 #[inline]
107 #[rustfmt::skip]
108 pub(crate) fn fword_ptr(mut self) -> Self {
109 self.state.ptr(MemoryOperandSize::Fword);
110 self
111 }
112
113 #[must_use]
114 #[inline]
115 #[rustfmt::skip]
116 pub(crate) fn oword_ptr(mut self) -> Self {
117 self.state.ptr(MemoryOperandSize::Xword);
118 self
119 }
120
121 #[must_use]
122 #[inline]
123 #[rustfmt::skip]
124 pub(crate) fn xmmword_ptr(mut self) -> Self {
125 self.state.ptr(MemoryOperandSize::Xword);
126 self
127 }
128
129 #[must_use]
130 #[inline]
131 #[rustfmt::skip]
132 pub(crate) fn ymmword_ptr(mut self) -> Self {
133 self.state.ptr(MemoryOperandSize::Yword);
134 self
135 }
136
137 #[must_use]
138 #[inline]
139 #[rustfmt::skip]
140 pub(crate) fn zmmword_ptr(mut self) -> Self {
141 self.state.ptr(MemoryOperandSize::Zword);
142 self
143 }
144
145 #[must_use]
146 #[inline]
147 #[rustfmt::skip]
148 pub(crate) fn bcst(mut self) -> Self {
149 self.state.bcst(MemoryOperandSize::None);
150 self
151 }
152
153 #[must_use]
154 #[inline]
155 #[rustfmt::skip]
156 pub(crate) fn word_bcst(mut self) -> Self {
157 self.state.bcst(MemoryOperandSize::Word);
158 self
159 }
160
161 #[must_use]
162 #[inline]
163 #[rustfmt::skip]
164 pub(crate) fn dword_bcst(mut self) -> Self {
165 self.state.bcst(MemoryOperandSize::Dword);
166 self
167 }
168
169 #[must_use]
170 #[inline]
171 #[rustfmt::skip]
172 pub(crate) fn qword_bcst(mut self) -> Self {
173 self.state.bcst(MemoryOperandSize::Qword);
174 self
175 }
176 #[must_use]
180 #[inline]
181 pub fn es(mut self) -> Self {
182 self.state.set_es();
183 self
184 }
185
186 #[must_use]
188 #[inline]
189 pub fn cs(mut self) -> Self {
190 self.state.set_cs();
191 self
192 }
193
194 #[must_use]
196 #[inline]
197 pub fn ss(mut self) -> Self {
198 self.state.set_ss();
199 self
200 }
201
202 #[must_use]
204 #[inline]
205 pub fn ds(mut self) -> Self {
206 self.state.set_ds();
207 self
208 }
209
210 #[must_use]
212 #[inline]
213 pub fn fs(mut self) -> Self {
214 self.state.set_fs();
215 self
216 }
217
218 #[must_use]
220 #[inline]
221 pub fn gs(mut self) -> Self {
222 self.state.set_gs();
223 self
224 }
225
226 #[must_use]
228 #[inline]
229 pub fn k1(mut self) -> Self {
230 self.state.set_k1();
231 self
232 }
233
234 #[must_use]
236 #[inline]
237 pub fn k2(mut self) -> Self {
238 self.state.set_k2();
239 self
240 }
241
242 #[must_use]
244 #[inline]
245 pub fn k3(mut self) -> Self {
246 self.state.set_k3();
247 self
248 }
249
250 #[must_use]
252 #[inline]
253 pub fn k4(mut self) -> Self {
254 self.state.set_k4();
255 self
256 }
257
258 #[must_use]
260 #[inline]
261 pub fn k5(mut self) -> Self {
262 self.state.set_k5();
263 self
264 }
265
266 #[must_use]
268 #[inline]
269 pub fn k6(mut self) -> Self {
270 self.state.set_k6();
271 self
272 }
273
274 #[must_use]
276 #[inline]
277 pub fn k7(mut self) -> Self {
278 self.state.set_k7();
279 self
280 }
281
282 #[must_use]
283 #[inline]
284 pub(crate) fn is_displacement_only(&self) -> bool {
285 self.base == Register::None && self.index == Register::None
286 }
287
288 #[must_use]
289 #[inline]
290 pub(crate) fn to_memory_operand(self, bitness: u32) -> MemoryOperand {
291 MemoryOperand {
292 segment_prefix: self.state.segment(),
293 base: self.base,
294 index: self.index,
295 scale: self.scale as u32,
296 displacement: self.displ,
297 displ_size: if self.is_displacement_only() { bitness / 8 } else { (self.displ != 0) as u32 },
298 is_broadcast: self.is_broadcast(),
299 }
300 }
301
302 #[must_use]
303 #[inline]
304 pub(crate) fn is_broadcast(&self) -> bool {
305 self.state.is_broadcast()
306 }
307
308 #[must_use]
309 #[inline]
310 pub(crate) fn size(&self) -> MemoryOperandSize {
311 self.state.size()
312 }
313
314 #[must_use]
315 #[inline]
316 pub(crate) fn index(&self) -> Register {
317 self.index
318 }
319
320 #[must_use]
321 #[inline]
322 pub(crate) fn state(&self) -> CodeAsmOpState {
323 self.state
324 }
325}
326
327impl<R: Into<Register>> From<R> for AsmMemoryOperand {
328 #[inline]
329 fn from(other: R) -> Self {
330 AsmMemoryOperand { base: other.into(), index: Register::None, scale: 1, displ: 0, state: CodeAsmOpState::new() }
331 }
332}
333
334macro_rules! displ_to_mem_op {
335 ($($displ_ty:ty)+) => {
336 $(
337 impl From<$displ_ty> for AsmMemoryOperand {
338 #[inline]
339 #[allow(trivial_numeric_casts)]
340 fn from(other: $displ_ty) -> Self {
341 AsmMemoryOperand {
342 base: Register::None,
343 index: Register::None,
344 scale: 1,
345 displ: other as i64,
346 state: CodeAsmOpState::new(),
347 }
348 }
349 }
350 )+
351 };
352}
353displ_to_mem_op!(i8 i16 i32 i64 isize u8 u16 u32 u64 usize);
354
355macro_rules! reg_plus_displ {
356 ($reg_ty:ty, $($displ_ty:ty)+) => {
357 $(
358 impl Add<$displ_ty> for $reg_ty {
359 type Output = AsmMemoryOperand;
360 #[inline]
361 #[allow(trivial_numeric_casts)]
362 fn add(self, rhs: $displ_ty) -> Self::Output {
363 AsmMemoryOperand {
364 base: self.into(),
365 index: Register::None,
366 scale: 1,
367 displ: rhs as i64,
368 state: CodeAsmOpState::new(),
369 }
370 }
371 }
372 impl Add<$reg_ty> for $displ_ty {
373 type Output = AsmMemoryOperand;
374 #[inline]
375 #[allow(trivial_numeric_casts)]
376 fn add(self, rhs: $reg_ty) -> Self::Output {
377 AsmMemoryOperand {
378 base: rhs.into(),
379 index: Register::None,
380 scale: 1,
381 displ: self as i64,
382 state: CodeAsmOpState::new(),
383 }
384 }
385 }
386 impl Sub<$displ_ty> for $reg_ty {
387 type Output = AsmMemoryOperand;
388 #[inline]
389 #[allow(trivial_numeric_casts)]
390 fn sub(self, rhs: $displ_ty) -> Self::Output {
391 AsmMemoryOperand {
392 base: self.into(),
393 index: Register::None,
394 scale: 1,
395 displ: (rhs as i64).wrapping_neg(),
396 state: CodeAsmOpState::new(),
397 }
398 }
399 }
400 )+
401 };
402}
403reg_plus_displ!(AsmRegister16, i8 i16 i32 i64 isize u8 u16 u32 u64 usize);
404reg_plus_displ!(AsmRegister32, i8 i16 i32 i64 isize u8 u16 u32 u64 usize);
405reg_plus_displ!(AsmRegister64, i8 i16 i32 i64 isize u8 u16 u32 u64 usize);
406
407macro_rules! reg_mul_scale {
408 ($reg_ty:ty, $($scale_ty:ty)+) => {
409 $(
410 impl Mul<$scale_ty> for $reg_ty {
411 type Output = AsmMemoryOperand;
412 #[inline]
413 #[allow(trivial_numeric_casts)]
414 fn mul(self, rhs: $scale_ty) -> Self::Output {
415 AsmMemoryOperand {
416 base: Register::None,
417 index: self.into(),
418 scale: rhs as u8,
419 displ: 0,
420 state: CodeAsmOpState::new(),
421 }
422 }
423 }
424 impl Mul<$reg_ty> for $scale_ty {
425 type Output = AsmMemoryOperand;
426 #[inline]
427 #[allow(trivial_numeric_casts)]
428 fn mul(self, rhs: $reg_ty) -> Self::Output {
429 AsmMemoryOperand {
430 base: Register::None,
431 index: rhs.into(),
432 scale: self as u8,
433 displ: 0,
434 state: CodeAsmOpState::new(),
435 }
436 }
437 }
438 )+
439 };
440}
441reg_mul_scale!(AsmRegister32, i8 i16 i32 i64 isize u8 u16 u32 u64 usize);
442reg_mul_scale!(AsmRegister64, i8 i16 i32 i64 isize u8 u16 u32 u64 usize);
443reg_mul_scale!(AsmRegisterXmm, i8 i16 i32 i64 isize u8 u16 u32 u64 usize);
444reg_mul_scale!(AsmRegisterYmm, i8 i16 i32 i64 isize u8 u16 u32 u64 usize);
445reg_mul_scale!(AsmRegisterZmm, i8 i16 i32 i64 isize u8 u16 u32 u64 usize);
446
447macro_rules! reg_plus_reg {
448 ($left_ty:ty, $($right_ty:ty)+) => {
449 $(
450 impl Add<$right_ty> for $left_ty {
451 type Output = AsmMemoryOperand;
452 #[inline]
453 fn add(self, rhs: $right_ty) -> Self::Output {
454 AsmMemoryOperand { base: self.into(), index: rhs.into(), scale: 1, displ: 0, state: CodeAsmOpState::new() }
455 }
456 }
457 )+
458 };
459}
460reg_plus_reg!(AsmRegister16, AsmRegister16);
461reg_plus_reg!(AsmRegister32, AsmRegister32 AsmRegisterXmm AsmRegisterYmm AsmRegisterZmm);
462reg_plus_reg!(AsmRegister64, AsmRegister64 AsmRegisterXmm AsmRegisterYmm AsmRegisterZmm);
463
464macro_rules! indexreg_plus_reg {
466 ($($left_ty:ty)+, $right_ty:ty) => {
467 $(
468 impl Add<$right_ty> for $left_ty {
469 type Output = AsmMemoryOperand;
470 #[inline]
471 fn add(self, rhs: $right_ty) -> Self::Output {
472 AsmMemoryOperand { base: rhs.into(), index: self.into(), scale: 1, displ: 0, state: CodeAsmOpState::new() }
473 }
474 }
475 )+
476 };
477}
478indexreg_plus_reg!(AsmRegisterXmm AsmRegisterYmm AsmRegisterZmm, AsmRegister32);
479indexreg_plus_reg!(AsmRegisterXmm AsmRegisterYmm AsmRegisterZmm, AsmRegister64);
480
481macro_rules! reg_plus_mem {
482 ($($reg_ty:ty)+) => {
483 $(
484 impl Add<AsmMemoryOperand> for $reg_ty {
485 type Output = AsmMemoryOperand;
486 #[inline]
487 fn add(self, mut rhs: AsmMemoryOperand) -> Self::Output {
488 debug_assert_eq!(rhs.base, Register::None);
489 rhs.base = self.into();
490 rhs
491 }
492 }
493
494 impl Add<$reg_ty> for AsmMemoryOperand {
495 type Output = AsmMemoryOperand;
496 #[inline]
497 fn add(mut self, rhs: $reg_ty) -> Self::Output {
498 debug_assert_eq!(self.base, Register::None);
499 self.base = rhs.into();
500 self
501 }
502 }
503 )+
504 };
505}
506reg_plus_mem!(AsmRegister16 AsmRegister32 AsmRegister64);
507
508macro_rules! mem_plus_displ {
509 ($($displ_ty:ty)+) => {
510 $(
511 impl Add<$displ_ty> for AsmMemoryOperand {
512 type Output = AsmMemoryOperand;
513 #[inline]
514 #[allow(trivial_numeric_casts)]
515 fn add(mut self, rhs: $displ_ty) -> Self::Output {
516 self.displ = self.displ.wrapping_add(rhs as i64);
517 self
518 }
519 }
520 impl Add<AsmMemoryOperand> for $displ_ty {
521 type Output = AsmMemoryOperand;
522 #[inline]
523 #[allow(trivial_numeric_casts)]
524 fn add(self, mut rhs: AsmMemoryOperand) -> Self::Output {
525 rhs.displ = rhs.displ.wrapping_add(self as i64);
526 rhs
527 }
528 }
529 impl Sub<$displ_ty> for AsmMemoryOperand {
530 type Output = AsmMemoryOperand;
531 #[inline]
532 #[allow(trivial_numeric_casts)]
533 fn sub(mut self, rhs: $displ_ty) -> Self::Output {
534 self.displ = self.displ.wrapping_sub(rhs as i64);
535 self
536 }
537 }
538 )+
539 };
540}
541mem_plus_displ!(i8 i16 i32 i64 isize u8 u16 u32 u64 usize);
542
543impl Add<AsmMemoryOperand> for AsmMemoryOperand {
544 type Output = AsmMemoryOperand;
545 #[inline]
546 fn add(mut self, rhs: AsmMemoryOperand) -> Self::Output {
547 if self.base == Register::None {
548 self.base = rhs.base;
549 } else {
550 debug_assert_eq!(rhs.base, Register::None);
551 }
552 if self.index == Register::None {
553 self.index = rhs.index;
554 self.scale = rhs.scale;
555 } else {
556 debug_assert_eq!(rhs.index, Register::None);
557 }
558 self.displ = self.displ.wrapping_add(rhs.displ);
559 self
561 }
562}
563
564impl From<CodeLabel> for AsmMemoryOperand {
565 #[inline]
566 fn from(other: CodeLabel) -> Self {
567 AsmMemoryOperand { base: Register::RIP, index: Register::None, scale: 1, displ: other.id as i64, state: CodeAsmOpState::new() }
568 }
569}
570
571#[must_use]
585#[inline]
586#[rustfmt::skip]
587pub fn ptr<M: Into<AsmMemoryOperand>>(mem: M) -> AsmMemoryOperand {
588 mem.into().ptr()
589}
590
591#[must_use]
603#[inline]
604#[rustfmt::skip]
605pub fn byte_ptr<M: Into<AsmMemoryOperand>>(mem: M) -> AsmMemoryOperand {
606 mem.into().byte_ptr()
607}
608
609#[must_use]
621#[inline]
622#[rustfmt::skip]
623pub fn word_ptr<M: Into<AsmMemoryOperand>>(mem: M) -> AsmMemoryOperand {
624 mem.into().word_ptr()
625}
626
627#[must_use]
639#[inline]
640#[rustfmt::skip]
641pub fn dword_ptr<M: Into<AsmMemoryOperand>>(mem: M) -> AsmMemoryOperand {
642 mem.into().dword_ptr()
643}
644
645#[must_use]
657#[inline]
658#[rustfmt::skip]
659pub fn qword_ptr<M: Into<AsmMemoryOperand>>(mem: M) -> AsmMemoryOperand {
660 mem.into().qword_ptr()
661}
662
663#[must_use]
675#[inline]
676#[rustfmt::skip]
677pub fn mmword_ptr<M: Into<AsmMemoryOperand>>(mem: M) -> AsmMemoryOperand {
678 mem.into().mmword_ptr()
679}
680
681#[must_use]
693#[inline]
694#[rustfmt::skip]
695pub fn tbyte_ptr<M: Into<AsmMemoryOperand>>(mem: M) -> AsmMemoryOperand {
696 mem.into().tbyte_ptr()
697}
698
699#[must_use]
711#[inline]
712#[rustfmt::skip]
713pub fn tword_ptr<M: Into<AsmMemoryOperand>>(mem: M) -> AsmMemoryOperand {
714 mem.into().tword_ptr()
715}
716
717#[must_use]
729#[inline]
730#[rustfmt::skip]
731pub fn fword_ptr<M: Into<AsmMemoryOperand>>(mem: M) -> AsmMemoryOperand {
732 mem.into().fword_ptr()
733}
734
735#[must_use]
747#[inline]
748#[rustfmt::skip]
749pub fn oword_ptr<M: Into<AsmMemoryOperand>>(mem: M) -> AsmMemoryOperand {
750 mem.into().oword_ptr()
751}
752
753#[must_use]
765#[inline]
766#[rustfmt::skip]
767pub fn xmmword_ptr<M: Into<AsmMemoryOperand>>(mem: M) -> AsmMemoryOperand {
768 mem.into().xmmword_ptr()
769}
770
771#[must_use]
783#[inline]
784#[rustfmt::skip]
785pub fn ymmword_ptr<M: Into<AsmMemoryOperand>>(mem: M) -> AsmMemoryOperand {
786 mem.into().ymmword_ptr()
787}
788
789#[must_use]
801#[inline]
802#[rustfmt::skip]
803pub fn zmmword_ptr<M: Into<AsmMemoryOperand>>(mem: M) -> AsmMemoryOperand {
804 mem.into().zmmword_ptr()
805}
806
807#[must_use]
819#[inline]
820#[rustfmt::skip]
821pub fn bcst<M: Into<AsmMemoryOperand>>(mem: M) -> AsmMemoryOperand {
822 mem.into().bcst()
823}
824
825#[must_use]
837#[inline]
838#[rustfmt::skip]
839pub fn word_bcst<M: Into<AsmMemoryOperand>>(mem: M) -> AsmMemoryOperand {
840 mem.into().word_bcst()
841}
842
843#[must_use]
855#[inline]
856#[rustfmt::skip]
857pub fn dword_bcst<M: Into<AsmMemoryOperand>>(mem: M) -> AsmMemoryOperand {
858 mem.into().dword_bcst()
859}
860
861#[must_use]
873#[inline]
874#[rustfmt::skip]
875pub fn qword_bcst<M: Into<AsmMemoryOperand>>(mem: M) -> AsmMemoryOperand {
876 mem.into().qword_bcst()
877}
878