1pub mod encode {
2 use crate::{CodeSink, inst};
3
4 pub fn nop_1b(_: &inst::nop_1b, buf: &mut impl CodeSink) {
6 buf.put1(0x90);
7 }
8
9 pub fn nop_2b(_: &inst::nop_2b, buf: &mut impl CodeSink) {
11 buf.put1(0x66);
12 buf.put1(0x90);
13 }
14
15 pub fn nop_3b(_: &inst::nop_3b, buf: &mut impl CodeSink) {
17 buf.put1(0x0F);
18 buf.put1(0x1F);
19 buf.put1(0x00);
20 }
21
22 pub fn nop_4b(_: &inst::nop_4b, buf: &mut impl CodeSink) {
24 buf.put1(0x0F);
25 buf.put1(0x1F);
26 buf.put1(0x40);
27 buf.put1(0x00);
28 }
29
30 pub fn nop_5b(_: &inst::nop_5b, buf: &mut impl CodeSink) {
32 buf.put1(0x0F);
33 buf.put1(0x1F);
34 buf.put1(0x44);
35 buf.put2(0x00_00);
36 }
37
38 pub fn nop_6b(_: &inst::nop_6b, buf: &mut impl CodeSink) {
40 buf.put1(0x66);
41 buf.put1(0x0F);
42 buf.put1(0x1F);
43 buf.put1(0x44);
44 buf.put2(0x00_00);
45 }
46
47 pub fn nop_7b(_: &inst::nop_7b, buf: &mut impl CodeSink) {
49 buf.put1(0x0F);
50 buf.put1(0x1F);
51 buf.put1(0x80);
52 buf.put4(0x00_00_00_00);
53 }
54
55 pub fn nop_8b(_: &inst::nop_8b, buf: &mut impl CodeSink) {
57 buf.put1(0x0F);
58 buf.put1(0x1F);
59 buf.put1(0x84);
60 buf.put1(0x00);
61 buf.put4(0x00_00_00_00);
62 }
63
64 pub fn nop_9b(_: &inst::nop_9b, buf: &mut impl CodeSink) {
66 buf.put1(0x66);
67 buf.put1(0x0F);
68 buf.put1(0x1F);
69 buf.put1(0x84);
70 buf.put1(0x00);
71 buf.put4(0x00_00_00_00);
72 }
73}
74
75pub mod mnemonic {
76 use crate::inst;
77 use crate::{Registers, XmmMem};
78 use std::borrow::Cow;
79
80 macro_rules! lock {
81 ($name:tt => $mnemonic:expr) => {
82 pub fn $name<R: Registers>(_: &inst::$name<R>) -> Cow<'static, str> {
83 Cow::Borrowed(concat!("lock ", $mnemonic))
84 }
85 };
86 }
87
88 lock!(lock_addb_mi => "addb");
89 lock!(lock_addw_mi => "addw");
90 lock!(lock_addl_mi => "addl");
91 lock!(lock_addq_mi_sxl => "addq");
92 lock!(lock_addl_mi_sxb => "addl");
93 lock!(lock_addq_mi_sxb => "addq");
94 lock!(lock_addb_mr => "addb");
95 lock!(lock_addw_mr => "addw");
96 lock!(lock_addl_mr => "addl");
97 lock!(lock_addq_mr => "addq");
98
99 lock!(lock_adcb_mi => "adcb");
100 lock!(lock_adcw_mi => "adcw");
101 lock!(lock_adcl_mi => "adcl");
102 lock!(lock_adcq_mi_sxl => "adcq");
103 lock!(lock_adcl_mi_sxb => "adcl");
104 lock!(lock_adcq_mi_sxb => "adcq");
105 lock!(lock_adcb_mr => "adcb");
106 lock!(lock_adcw_mr => "adcw");
107 lock!(lock_adcl_mr => "adcl");
108 lock!(lock_adcq_mr => "adcq");
109
110 lock!(lock_subb_mi => "subb");
111 lock!(lock_subw_mi => "subw");
112 lock!(lock_subl_mi => "subl");
113 lock!(lock_subq_mi_sxl => "subq");
114 lock!(lock_subl_mi_sxb => "subl");
115 lock!(lock_subq_mi_sxb => "subq");
116 lock!(lock_subb_mr => "subb");
117 lock!(lock_subw_mr => "subw");
118 lock!(lock_subl_mr => "subl");
119 lock!(lock_subq_mr => "subq");
120
121 lock!(lock_sbbb_mi => "sbbb");
122 lock!(lock_sbbw_mi => "sbbw");
123 lock!(lock_sbbl_mi => "sbbl");
124 lock!(lock_sbbq_mi_sxl => "sbbq");
125 lock!(lock_sbbl_mi_sxb => "sbbl");
126 lock!(lock_sbbq_mi_sxb => "sbbq");
127 lock!(lock_sbbb_mr => "sbbb");
128 lock!(lock_sbbw_mr => "sbbw");
129 lock!(lock_sbbl_mr => "sbbl");
130 lock!(lock_sbbq_mr => "sbbq");
131
132 lock!(lock_andb_mi => "andb");
133 lock!(lock_andw_mi => "andw");
134 lock!(lock_andl_mi => "andl");
135 lock!(lock_andq_mi_sxl => "andq");
136 lock!(lock_andl_mi_sxb => "andl");
137 lock!(lock_andq_mi_sxb => "andq");
138 lock!(lock_andb_mr => "andb");
139 lock!(lock_andw_mr => "andw");
140 lock!(lock_andl_mr => "andl");
141 lock!(lock_andq_mr => "andq");
142
143 lock!(lock_orb_mi => "orb");
144 lock!(lock_orw_mi => "orw");
145 lock!(lock_orl_mi => "orl");
146 lock!(lock_orq_mi_sxl => "orq");
147 lock!(lock_orl_mi_sxb => "orl");
148 lock!(lock_orq_mi_sxb => "orq");
149 lock!(lock_orb_mr => "orb");
150 lock!(lock_orw_mr => "orw");
151 lock!(lock_orl_mr => "orl");
152 lock!(lock_orq_mr => "orq");
153
154 lock!(lock_xorb_mi => "xorb");
155 lock!(lock_xorw_mi => "xorw");
156 lock!(lock_xorl_mi => "xorl");
157 lock!(lock_xorq_mi_sxl => "xorq");
158 lock!(lock_xorl_mi_sxb => "xorl");
159 lock!(lock_xorq_mi_sxb => "xorq");
160 lock!(lock_xorb_mr => "xorb");
161 lock!(lock_xorw_mr => "xorw");
162 lock!(lock_xorl_mr => "xorl");
163 lock!(lock_xorq_mr => "xorq");
164
165 lock!(lock_xaddb_mr => "xaddb");
166 lock!(lock_xaddw_mr => "xaddw");
167 lock!(lock_xaddl_mr => "xaddl");
168 lock!(lock_xaddq_mr => "xaddq");
169
170 lock!(lock_cmpxchgb_mr => "cmpxchgb");
171 lock!(lock_cmpxchgw_mr => "cmpxchgw");
172 lock!(lock_cmpxchgl_mr => "cmpxchgl");
173 lock!(lock_cmpxchgq_mr => "cmpxchgq");
174 lock!(lock_cmpxchg16b_m => "cmpxchg16b");
175
176 pub fn vcvtpd2ps_a<R: Registers>(inst: &inst::vcvtpd2ps_a<R>) -> Cow<'static, str> {
177 match inst.xmm_m128 {
178 XmmMem::Xmm(_) => "vcvtpd2ps".into(),
179 XmmMem::Mem(_) => "vcvtpd2psx".into(),
180 }
181 }
182
183 pub fn vcvttpd2dq_a<R: Registers>(inst: &inst::vcvttpd2dq_a<R>) -> Cow<'static, str> {
184 match inst.xmm_m128 {
185 XmmMem::Xmm(_) => "vcvttpd2dq".into(),
186 XmmMem::Mem(_) => "vcvttpd2dqx".into(),
187 }
188 }
189}
190
191pub mod display {
192 use crate::inst;
193 use crate::{Amode, Gpr, GprMem, Registers, Size};
194 use std::fmt;
195
196 pub fn callq_d(f: &mut fmt::Formatter, inst: &inst::callq_d) -> fmt::Result {
197 let inst::callq_d { imm32 } = inst;
198 display_displacement(f, "callq", i64::from(imm32.value()) + 5)
199 }
200
201 pub fn callq_m<R: Registers>(f: &mut fmt::Formatter, inst: &inst::callq_m<R>) -> fmt::Result {
202 let inst::callq_m { rm64 } = inst;
203 let op = rm64.to_string(Size::Quadword);
204 write!(f, "callq *{op}")
205 }
206
207 fn pred_as_str(imm: u8) -> &'static str {
210 match imm {
211 0 => "eq",
212 1 => "lt",
213 2 => "le",
214 3 => "unord",
215 4 => "neq",
216 5 => "nlt",
217 6 => "nle",
218 7 => "ord",
219 _ => panic!("not a valid predicate for `cmp*`"),
220 }
221 }
222
223 pub fn cmpss_a<R: Registers>(f: &mut fmt::Formatter, inst: &inst::cmpss_a<R>) -> fmt::Result {
224 let xmm1 = inst.xmm1.to_string();
225 let xmm_m32 = inst.xmm_m32.to_string();
226 let pred = inst.imm8.value();
227 if pred > 7 {
228 let imm8 = inst.imm8.to_string();
229 write!(f, "cmpss {imm8}, {xmm_m32}, {xmm1}")
230 } else {
231 write!(f, "cmp{}ss {xmm_m32}, {xmm1}", pred_as_str(pred))
232 }
233 }
234
235 pub fn cmpsd_a<R: Registers>(f: &mut fmt::Formatter, inst: &inst::cmpsd_a<R>) -> fmt::Result {
236 let xmm1 = inst.xmm1.to_string();
237 let xmm_m64 = inst.xmm_m64.to_string();
238 let pred = inst.imm8.value();
239 if pred > 7 {
240 let imm8 = inst.imm8.to_string();
241 write!(f, "cmpsd {imm8}, {xmm_m64}, {xmm1}")
242 } else {
243 write!(f, "cmp{}sd {xmm_m64}, {xmm1}", pred_as_str(pred))
244 }
245 }
246
247 pub fn cmpps_a<R: Registers>(f: &mut fmt::Formatter, inst: &inst::cmpps_a<R>) -> fmt::Result {
248 let xmm1 = inst.xmm1.to_string();
249 let xmm_m128 = inst.xmm_m128.to_string();
250 let pred = inst.imm8.value();
251 if pred > 7 {
252 let imm8 = inst.imm8.to_string();
253 write!(f, "cmpps {imm8}, {xmm_m128}, {xmm1}")
254 } else {
255 write!(f, "cmp{}ps {xmm_m128}, {xmm1}", pred_as_str(pred))
256 }
257 }
258
259 pub fn cmppd_a<R: Registers>(f: &mut fmt::Formatter, inst: &inst::cmppd_a<R>) -> fmt::Result {
260 let xmm1 = inst.xmm1.to_string();
261 let xmm_m128 = inst.xmm_m128.to_string();
262 let pred = inst.imm8.value();
263 if pred > 7 {
264 let imm8 = inst.imm8.to_string();
265 write!(f, "cmppd {imm8}, {xmm_m128}, {xmm1}")
266 } else {
267 write!(f, "cmp{}pd {xmm_m128}, {xmm1}", pred_as_str(pred))
268 }
269 }
270
271 fn vex_pred_as_str(imm: u8) -> &'static str {
274 match imm {
275 0x0 => "eq",
276 0x1 => "lt",
277 0x2 => "le",
278 0x3 => "unord",
279 0x4 => "neq",
280 0x5 => "nlt",
281 0x6 => "nle",
282 0x7 => "ord",
283 0x8 => "eq_uq",
284 0x9 => "nge",
285 0xa => "ngt",
286 0xb => "false",
287 0xc => "neq_oq",
288 0xd => "ge",
289 0xe => "gt",
290 0xf => "true",
291 0x10 => "eq_os",
292 0x11 => "lt_oq",
293 0x12 => "le_oq",
294 0x13 => "unord_s",
295 0x14 => "neq_us",
296 0x15 => "nlt_uq",
297 0x16 => "nle_uq",
298 0x17 => "ord_s",
299 0x18 => "eq_us",
300 0x19 => "nge_uq",
301 0x1a => "ngt_uq",
302 0x1b => "false_os",
303 0x1c => "neq_os",
304 0x1d => "ge_oq",
305 0x1e => "gt_oq",
306 0x1f => "true_us",
307 _ => panic!("not a valid predicate for `cmp*`"),
308 }
309 }
310
311 pub fn vcmpss_b<R: Registers>(f: &mut fmt::Formatter, inst: &inst::vcmpss_b<R>) -> fmt::Result {
312 let xmm1 = inst.xmm1.to_string();
313 let xmm2 = inst.xmm2.to_string();
314 let xmm_m32 = inst.xmm_m32.to_string();
315 let pred = inst.imm8.value();
316 if pred > 0x1f {
317 let imm8 = inst.imm8.to_string();
318 write!(f, "vcmpss {imm8}, {xmm_m32}, {xmm2}, {xmm1}")
319 } else {
320 write!(
321 f,
322 "vcmp{}ss {xmm_m32}, {xmm2}, {xmm1}",
323 vex_pred_as_str(pred)
324 )
325 }
326 }
327
328 pub fn vcmpsd_b<R: Registers>(f: &mut fmt::Formatter, inst: &inst::vcmpsd_b<R>) -> fmt::Result {
329 let xmm1 = inst.xmm1.to_string();
330 let xmm2 = inst.xmm2.to_string();
331 let xmm_m64 = inst.xmm_m64.to_string();
332 let pred = inst.imm8.value();
333 if pred > 0x1f {
334 let imm8 = inst.imm8.to_string();
335 write!(f, "vcmpsd {imm8}, {xmm_m64}, {xmm2}, {xmm1}")
336 } else {
337 write!(
338 f,
339 "vcmp{}sd {xmm_m64}, {xmm2}, {xmm1}",
340 vex_pred_as_str(pred)
341 )
342 }
343 }
344
345 pub fn vcmpps_b<R: Registers>(f: &mut fmt::Formatter, inst: &inst::vcmpps_b<R>) -> fmt::Result {
346 let xmm1 = inst.xmm1.to_string();
347 let xmm2 = inst.xmm2.to_string();
348 let xmm_m128 = inst.xmm_m128.to_string();
349 let pred = inst.imm8.value();
350 if pred > 0x1f {
351 let imm8 = inst.imm8.to_string();
352 write!(f, "vcmpps {imm8}, {xmm_m128}, {xmm2}, {xmm1}")
353 } else {
354 write!(
355 f,
356 "vcmp{}ps {xmm_m128}, {xmm2}, {xmm1}",
357 vex_pred_as_str(pred)
358 )
359 }
360 }
361
362 pub fn vcmppd_b<R: Registers>(f: &mut fmt::Formatter, inst: &inst::vcmppd_b<R>) -> fmt::Result {
363 let xmm1 = inst.xmm1.to_string();
364 let xmm2 = inst.xmm2.to_string();
365 let xmm_m128 = inst.xmm_m128.to_string();
366 let pred = inst.imm8.value();
367 if pred > 0x1f {
368 let imm8 = inst.imm8.to_string();
369 write!(f, "vcmppd {imm8}, {xmm_m128}, {xmm2}, {xmm1}")
370 } else {
371 write!(
372 f,
373 "vcmp{}pd {xmm_m128}, {xmm2}, {xmm1}",
374 vex_pred_as_str(pred)
375 )
376 }
377 }
378
379 pub fn nop_1b(f: &mut fmt::Formatter, _: &inst::nop_1b) -> fmt::Result {
380 write!(f, "nop")
381 }
382
383 pub fn nop_2b(f: &mut fmt::Formatter, _: &inst::nop_2b) -> fmt::Result {
384 write!(f, "nop")
385 }
386
387 pub fn nop_3b(f: &mut fmt::Formatter, _: &inst::nop_3b) -> fmt::Result {
388 write!(f, "nopl (%rax)")
389 }
390
391 pub fn nop_4b(f: &mut fmt::Formatter, _: &inst::nop_4b) -> fmt::Result {
392 write!(f, "nopl (%rax)")
393 }
394
395 pub fn nop_5b(f: &mut fmt::Formatter, _: &inst::nop_5b) -> fmt::Result {
396 write!(f, "nopl (%rax, %rax)")
397 }
398
399 pub fn nop_6b(f: &mut fmt::Formatter, _: &inst::nop_6b) -> fmt::Result {
400 write!(f, "nopw (%rax, %rax)")
401 }
402
403 pub fn nop_7b(f: &mut fmt::Formatter, _: &inst::nop_7b) -> fmt::Result {
404 write!(f, "nopl (%rax)")
405 }
406
407 pub fn nop_8b(f: &mut fmt::Formatter, _: &inst::nop_8b) -> fmt::Result {
408 write!(f, "nopl (%rax, %rax)")
409 }
410
411 pub fn nop_9b(f: &mut fmt::Formatter, _: &inst::nop_9b) -> fmt::Result {
412 write!(f, "nopw (%rax, %rax)")
413 }
414
415 pub fn xchgb_rm<R: Registers>(
416 f: &mut fmt::Formatter<'_>,
417 inst: &inst::xchgb_rm<R>,
418 ) -> fmt::Result {
419 let inst::xchgb_rm { r8, m8 } = inst;
420 xchg_rm::<R>(f, r8, m8, Size::Byte)
421 }
422
423 pub fn xchgw_rm<R: Registers>(
424 f: &mut fmt::Formatter<'_>,
425 inst: &inst::xchgw_rm<R>,
426 ) -> fmt::Result {
427 let inst::xchgw_rm { r16, m16 } = inst;
428 xchg_rm::<R>(f, r16, m16, Size::Word)
429 }
430
431 pub fn xchgl_rm<R: Registers>(
432 f: &mut fmt::Formatter<'_>,
433 inst: &inst::xchgl_rm<R>,
434 ) -> fmt::Result {
435 let inst::xchgl_rm { r32, m32 } = inst;
436 xchg_rm::<R>(f, r32, m32, Size::Doubleword)
437 }
438
439 pub fn xchgq_rm<R: Registers>(
440 f: &mut fmt::Formatter<'_>,
441 inst: &inst::xchgq_rm<R>,
442 ) -> fmt::Result {
443 let inst::xchgq_rm { r64, m64 } = inst;
444 xchg_rm::<R>(f, r64, m64, Size::Quadword)
445 }
446
447 fn xchg_rm<R: Registers>(
449 f: &mut fmt::Formatter<'_>,
450 reg: &Gpr<R::ReadWriteGpr>,
451 mem: &Amode<R::ReadGpr>,
452 size: Size,
453 ) -> fmt::Result {
454 let reg = reg.to_string(size);
455 let mem = mem.to_string();
456 let suffix = match size {
457 Size::Byte => "b",
458 Size::Word => "w",
459 Size::Doubleword => "l",
460 Size::Quadword => "q",
461 };
462 write!(f, "xchg{suffix} {reg}, {mem}")
463 }
464
465 pub fn sarb_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::sarb_m1<R>) -> fmt::Result {
466 let inst::sarb_m1 { rm8 } = inst;
467 shift_m1::<R>(f, "sarb", rm8, Size::Byte)
468 }
469
470 pub fn sarw_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::sarw_m1<R>) -> fmt::Result {
471 let inst::sarw_m1 { rm16 } = inst;
472 shift_m1::<R>(f, "sarw", rm16, Size::Word)
473 }
474
475 pub fn sarl_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::sarl_m1<R>) -> fmt::Result {
476 let inst::sarl_m1 { rm32 } = inst;
477 shift_m1::<R>(f, "sarl", rm32, Size::Doubleword)
478 }
479
480 pub fn sarq_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::sarq_m1<R>) -> fmt::Result {
481 let inst::sarq_m1 { rm64 } = inst;
482 shift_m1::<R>(f, "sarq", rm64, Size::Quadword)
483 }
484
485 pub fn shlb_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::shlb_m1<R>) -> fmt::Result {
486 let inst::shlb_m1 { rm8 } = inst;
487 shift_m1::<R>(f, "shlb", rm8, Size::Byte)
488 }
489
490 pub fn shlw_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::shlw_m1<R>) -> fmt::Result {
491 let inst::shlw_m1 { rm16 } = inst;
492 shift_m1::<R>(f, "shlw", rm16, Size::Word)
493 }
494
495 pub fn shll_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::shll_m1<R>) -> fmt::Result {
496 let inst::shll_m1 { rm32 } = inst;
497 shift_m1::<R>(f, "shll", rm32, Size::Doubleword)
498 }
499
500 pub fn shlq_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::shlq_m1<R>) -> fmt::Result {
501 let inst::shlq_m1 { rm64 } = inst;
502 shift_m1::<R>(f, "shlq", rm64, Size::Quadword)
503 }
504
505 pub fn shrb_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::shrb_m1<R>) -> fmt::Result {
506 let inst::shrb_m1 { rm8 } = inst;
507 shift_m1::<R>(f, "shrb", rm8, Size::Byte)
508 }
509
510 pub fn shrw_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::shrw_m1<R>) -> fmt::Result {
511 let inst::shrw_m1 { rm16 } = inst;
512 shift_m1::<R>(f, "shrw", rm16, Size::Word)
513 }
514
515 pub fn shrl_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::shrl_m1<R>) -> fmt::Result {
516 let inst::shrl_m1 { rm32 } = inst;
517 shift_m1::<R>(f, "shrl", rm32, Size::Doubleword)
518 }
519
520 pub fn shrq_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::shrq_m1<R>) -> fmt::Result {
521 let inst::shrq_m1 { rm64 } = inst;
522 shift_m1::<R>(f, "shrq", rm64, Size::Quadword)
523 }
524
525 pub fn rorb_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::rorb_m1<R>) -> fmt::Result {
526 let inst::rorb_m1 { rm8 } = inst;
527 shift_m1::<R>(f, "rorb", rm8, Size::Byte)
528 }
529
530 pub fn rorw_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::rorw_m1<R>) -> fmt::Result {
531 let inst::rorw_m1 { rm16 } = inst;
532 shift_m1::<R>(f, "rorw", rm16, Size::Word)
533 }
534
535 pub fn rorl_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::rorl_m1<R>) -> fmt::Result {
536 let inst::rorl_m1 { rm32 } = inst;
537 shift_m1::<R>(f, "rorl", rm32, Size::Doubleword)
538 }
539
540 pub fn rorq_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::rorq_m1<R>) -> fmt::Result {
541 let inst::rorq_m1 { rm64 } = inst;
542 shift_m1::<R>(f, "rorq", rm64, Size::Quadword)
543 }
544
545 pub fn rolb_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::rolb_m1<R>) -> fmt::Result {
546 let inst::rolb_m1 { rm8 } = inst;
547 shift_m1::<R>(f, "rolb", rm8, Size::Byte)
548 }
549
550 pub fn rolw_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::rolw_m1<R>) -> fmt::Result {
551 let inst::rolw_m1 { rm16 } = inst;
552 shift_m1::<R>(f, "rolw", rm16, Size::Word)
553 }
554
555 pub fn roll_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::roll_m1<R>) -> fmt::Result {
556 let inst::roll_m1 { rm32 } = inst;
557 shift_m1::<R>(f, "roll", rm32, Size::Doubleword)
558 }
559
560 pub fn rolq_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::rolq_m1<R>) -> fmt::Result {
561 let inst::rolq_m1 { rm64 } = inst;
562 shift_m1::<R>(f, "rolq", rm64, Size::Quadword)
563 }
564
565 fn shift_m1<R: Registers>(
566 f: &mut fmt::Formatter<'_>,
567 mnemonic: &str,
568 rm: &GprMem<R::ReadWriteGpr, R::ReadGpr>,
569 size: Size,
570 ) -> fmt::Result {
571 let reg = rm.to_string(size);
572 match rm {
573 GprMem::Gpr(_) => write!(f, "{mnemonic} $1, {reg}"),
574 GprMem::Mem(_) => write!(f, "{mnemonic} {reg}"),
575 }
576 }
577
578 pub fn jmpq_m<R: Registers>(f: &mut fmt::Formatter<'_>, jmp: &inst::jmpq_m<R>) -> fmt::Result {
579 let inst::jmpq_m { rm64 } = jmp;
580 let rm64 = rm64.to_string(Size::Quadword);
581 write!(f, "jmpq *{rm64}")
582 }
583
584 pub fn jmp_d8(f: &mut fmt::Formatter<'_>, jmp: &inst::jmp_d8) -> fmt::Result {
585 let inst::jmp_d8 { imm8 } = jmp;
586 display_displacement(f, "jmp", i64::from(imm8.value()) + 2)
587 }
588
589 pub fn jmp_d32(f: &mut fmt::Formatter<'_>, jmp: &inst::jmp_d32) -> fmt::Result {
590 let inst::jmp_d32 { imm32 } = jmp;
591 display_displacement(f, "jmp", i64::from(imm32.value()) + 5)
592 }
593
594 macro_rules! jcc {
595 ($($mnemonic:tt = $j8:ident / $j32:ident;)*) => ($(
596 pub fn $j8(f: &mut fmt::Formatter<'_>, jmp: &inst::$j8) -> fmt::Result {
597 let inst::$j8 { imm8 } = jmp;
598 display_displacement(f, $mnemonic, i64::from(imm8.value()) + 2)
599 }
600
601 pub fn $j32(f: &mut fmt::Formatter<'_>, jmp: &inst::$j32) -> fmt::Result {
602 let inst::$j32 { imm32 } = jmp;
603 display_displacement(f, $mnemonic, i64::from(imm32.value()) + 6)
604 }
605 )*)
606 }
607
608 jcc! {
609 "ja" = ja_d8 / ja_d32;
610 "jae" = jae_d8 / jae_d32;
611 "jb" = jb_d8 / jb_d32;
612 "jbe" = jbe_d8 / jbe_d32;
613 "je" = je_d8 / je_d32;
614 "jg" = jg_d8 / jg_d32;
615 "jge" = jge_d8 / jge_d32;
616 "jl" = jl_d8 / jl_d32;
617 "jle" = jle_d8 / jle_d32;
618 "jne" = jne_d8 / jne_d32;
619 "jno" = jno_d8 / jno_d32;
620 "jnp" = jnp_d8 / jnp_d32;
621 "jns" = jns_d8 / jns_d32;
622 "jo" = jo_d8 / jo_d32;
623 "jp" = jp_d8 / jp_d32;
624 "js" = js_d8 / js_d32;
625 }
626
627 fn display_displacement(
628 f: &mut fmt::Formatter<'_>,
629 mnemonic: &str,
630 displacement: i64,
631 ) -> fmt::Result {
632 if displacement >= 0 && displacement < 10 {
633 write!(f, "{mnemonic} {displacement}")
634 } else {
635 write!(f, "{mnemonic} {displacement:#x}")
636 }
637 }
638}
639
640pub mod visit {
641 use crate::inst::*;
642 use crate::{Amode, Fixed, Gpr, GprMem, RegisterVisitor, Registers, gpr};
643
644 pub fn mulxl_rvm<R: Registers>(mulx: &mut mulxl_rvm<R>, visitor: &mut impl RegisterVisitor<R>) {
645 visit_mulx(
646 &mut mulx.r32a,
647 &mut mulx.r32b,
648 &mut mulx.rm32,
649 &mut mulx.edx,
650 visitor,
651 )
652 }
653
654 pub fn mulxq_rvm<R: Registers>(mulx: &mut mulxq_rvm<R>, visitor: &mut impl RegisterVisitor<R>) {
655 visit_mulx(
656 &mut mulx.r64a,
657 &mut mulx.r64b,
658 &mut mulx.rm64,
659 &mut mulx.rdx,
660 visitor,
661 )
662 }
663
664 fn visit_mulx<R: Registers>(
669 ra: &mut Gpr<R::WriteGpr>,
670 rb: &mut Gpr<R::WriteGpr>,
671 src1: &mut GprMem<R::ReadGpr, R::ReadGpr>,
672 src2: &mut Fixed<R::ReadGpr, { gpr::enc::RDX }>,
673 visitor: &mut impl RegisterVisitor<R>,
674 ) {
675 if ra == rb {
676 visitor.write_gpr(ra.as_mut());
677 *rb = *ra;
678 } else {
679 visitor.write_gpr(ra.as_mut());
680 visitor.write_gpr(rb.as_mut());
681 }
682 visitor.read_gpr_mem(src1);
683 let enc = src2.expected_enc();
684 visitor.fixed_read_gpr(&mut src2.0, enc);
685 }
686
687 pub fn lock_xaddb_mr<R: Registers>(
688 lock_xadd: &mut lock_xaddb_mr<R>,
689 visitor: &mut impl RegisterVisitor<R>,
690 ) {
691 let lock_xaddb_mr { r8, m8 } = lock_xadd;
692 lock_xadd_mr(r8, m8, visitor)
693 }
694
695 pub fn lock_xaddw_mr<R: Registers>(
696 lock_xadd: &mut lock_xaddw_mr<R>,
697 visitor: &mut impl RegisterVisitor<R>,
698 ) {
699 let lock_xaddw_mr { r16, m16 } = lock_xadd;
700 lock_xadd_mr(r16, m16, visitor)
701 }
702
703 pub fn lock_xaddl_mr<R: Registers>(
704 lock_xadd: &mut lock_xaddl_mr<R>,
705 visitor: &mut impl RegisterVisitor<R>,
706 ) {
707 let lock_xaddl_mr { r32, m32 } = lock_xadd;
708 lock_xadd_mr(r32, m32, visitor)
709 }
710
711 pub fn lock_xaddq_mr<R: Registers>(
712 lock_xadd: &mut lock_xaddq_mr<R>,
713 visitor: &mut impl RegisterVisitor<R>,
714 ) {
715 let lock_xaddq_mr { r64, m64 } = lock_xadd;
716 lock_xadd_mr(r64, m64, visitor)
717 }
718
719 fn lock_xadd_mr<R: Registers>(
723 reg: &mut Gpr<R::ReadWriteGpr>,
724 mem: &mut Amode<R::ReadGpr>,
725 visitor: &mut impl RegisterVisitor<R>,
726 ) {
727 visitor.read_write_gpr(reg.as_mut());
728 visitor.read_amode(mem);
729 }
730}