Path: blob/main/cranelift/assembler-x64/src/custom.rs
3068 views
pub mod encode {1use crate::{CodeSink, inst};23/// `NOP`4pub fn nop_1b(_: &inst::nop_1b, buf: &mut impl CodeSink) {5buf.put1(0x90);6}78/// `66 NOP`9pub fn nop_2b(_: &inst::nop_2b, buf: &mut impl CodeSink) {10buf.put1(0x66);11buf.put1(0x90);12}1314/// `NOP DWORD ptr [EAX]`15pub fn nop_3b(_: &inst::nop_3b, buf: &mut impl CodeSink) {16buf.put1(0x0F);17buf.put1(0x1F);18buf.put1(0x00);19}2021/// `NOP DWORD ptr [EAX + 00H]`22pub fn nop_4b(_: &inst::nop_4b, buf: &mut impl CodeSink) {23buf.put1(0x0F);24buf.put1(0x1F);25buf.put1(0x40);26buf.put1(0x00);27}2829/// `NOP DWORD ptr [EAX + EAX*1 + 00H]`30pub fn nop_5b(_: &inst::nop_5b, buf: &mut impl CodeSink) {31buf.put1(0x0F);32buf.put1(0x1F);33buf.put1(0x44);34buf.put2(0x00_00);35}3637/// `66 NOP DWORD ptr [EAX + EAX*1 + 00H]`38pub fn nop_6b(_: &inst::nop_6b, buf: &mut impl CodeSink) {39buf.put1(0x66);40buf.put1(0x0F);41buf.put1(0x1F);42buf.put1(0x44);43buf.put2(0x00_00);44}4546/// `NOP DWORD ptr [EAX + 00000000H]`47pub fn nop_7b(_: &inst::nop_7b, buf: &mut impl CodeSink) {48buf.put1(0x0F);49buf.put1(0x1F);50buf.put1(0x80);51buf.put4(0x00_00_00_00);52}5354/// `NOP DWORD ptr [EAX + EAX*1 + 00000000H]`55pub fn nop_8b(_: &inst::nop_8b, buf: &mut impl CodeSink) {56buf.put1(0x0F);57buf.put1(0x1F);58buf.put1(0x84);59buf.put1(0x00);60buf.put4(0x00_00_00_00);61}6263/// `66 NOP DWORD ptr [EAX + EAX*1 + 00000000H]`64pub fn nop_9b(_: &inst::nop_9b, buf: &mut impl CodeSink) {65buf.put1(0x66);66buf.put1(0x0F);67buf.put1(0x1F);68buf.put1(0x84);69buf.put1(0x00);70buf.put4(0x00_00_00_00);71}72}7374pub mod mnemonic {75use crate::inst;76use crate::{Registers, XmmMem};77use alloc::borrow::Cow;7879macro_rules! lock {80($name:tt => $mnemonic:expr) => {81pub fn $name<R: Registers>(_: &inst::$name<R>) -> Cow<'static, str> {82Cow::Borrowed(concat!("lock ", $mnemonic))83}84};85}8687lock!(lock_addb_mi => "addb");88lock!(lock_addw_mi => "addw");89lock!(lock_addl_mi => "addl");90lock!(lock_addq_mi_sxl => "addq");91lock!(lock_addl_mi_sxb => "addl");92lock!(lock_addq_mi_sxb => "addq");93lock!(lock_addb_mr => "addb");94lock!(lock_addw_mr => "addw");95lock!(lock_addl_mr => "addl");96lock!(lock_addq_mr => "addq");9798lock!(lock_adcb_mi => "adcb");99lock!(lock_adcw_mi => "adcw");100lock!(lock_adcl_mi => "adcl");101lock!(lock_adcq_mi_sxl => "adcq");102lock!(lock_adcl_mi_sxb => "adcl");103lock!(lock_adcq_mi_sxb => "adcq");104lock!(lock_adcb_mr => "adcb");105lock!(lock_adcw_mr => "adcw");106lock!(lock_adcl_mr => "adcl");107lock!(lock_adcq_mr => "adcq");108109lock!(lock_subb_mi => "subb");110lock!(lock_subw_mi => "subw");111lock!(lock_subl_mi => "subl");112lock!(lock_subq_mi_sxl => "subq");113lock!(lock_subl_mi_sxb => "subl");114lock!(lock_subq_mi_sxb => "subq");115lock!(lock_subb_mr => "subb");116lock!(lock_subw_mr => "subw");117lock!(lock_subl_mr => "subl");118lock!(lock_subq_mr => "subq");119120lock!(lock_sbbb_mi => "sbbb");121lock!(lock_sbbw_mi => "sbbw");122lock!(lock_sbbl_mi => "sbbl");123lock!(lock_sbbq_mi_sxl => "sbbq");124lock!(lock_sbbl_mi_sxb => "sbbl");125lock!(lock_sbbq_mi_sxb => "sbbq");126lock!(lock_sbbb_mr => "sbbb");127lock!(lock_sbbw_mr => "sbbw");128lock!(lock_sbbl_mr => "sbbl");129lock!(lock_sbbq_mr => "sbbq");130131lock!(lock_andb_mi => "andb");132lock!(lock_andw_mi => "andw");133lock!(lock_andl_mi => "andl");134lock!(lock_andq_mi_sxl => "andq");135lock!(lock_andl_mi_sxb => "andl");136lock!(lock_andq_mi_sxb => "andq");137lock!(lock_andb_mr => "andb");138lock!(lock_andw_mr => "andw");139lock!(lock_andl_mr => "andl");140lock!(lock_andq_mr => "andq");141142lock!(lock_orb_mi => "orb");143lock!(lock_orw_mi => "orw");144lock!(lock_orl_mi => "orl");145lock!(lock_orq_mi_sxl => "orq");146lock!(lock_orl_mi_sxb => "orl");147lock!(lock_orq_mi_sxb => "orq");148lock!(lock_orb_mr => "orb");149lock!(lock_orw_mr => "orw");150lock!(lock_orl_mr => "orl");151lock!(lock_orq_mr => "orq");152153lock!(lock_xorb_mi => "xorb");154lock!(lock_xorw_mi => "xorw");155lock!(lock_xorl_mi => "xorl");156lock!(lock_xorq_mi_sxl => "xorq");157lock!(lock_xorl_mi_sxb => "xorl");158lock!(lock_xorq_mi_sxb => "xorq");159lock!(lock_xorb_mr => "xorb");160lock!(lock_xorw_mr => "xorw");161lock!(lock_xorl_mr => "xorl");162lock!(lock_xorq_mr => "xorq");163164lock!(lock_xaddb_mr => "xaddb");165lock!(lock_xaddw_mr => "xaddw");166lock!(lock_xaddl_mr => "xaddl");167lock!(lock_xaddq_mr => "xaddq");168169lock!(lock_cmpxchgb_mr => "cmpxchgb");170lock!(lock_cmpxchgw_mr => "cmpxchgw");171lock!(lock_cmpxchgl_mr => "cmpxchgl");172lock!(lock_cmpxchgq_mr => "cmpxchgq");173lock!(lock_cmpxchg16b_m => "cmpxchg16b");174175pub fn vcvtpd2ps_a<R: Registers>(inst: &inst::vcvtpd2ps_a<R>) -> Cow<'static, str> {176match inst.xmm_m128 {177XmmMem::Xmm(_) => "vcvtpd2ps".into(),178XmmMem::Mem(_) => "vcvtpd2psx".into(),179}180}181182pub fn vcvttpd2dq_a<R: Registers>(inst: &inst::vcvttpd2dq_a<R>) -> Cow<'static, str> {183match inst.xmm_m128 {184XmmMem::Xmm(_) => "vcvttpd2dq".into(),185XmmMem::Mem(_) => "vcvttpd2dqx".into(),186}187}188}189190pub mod display {191use crate::inst;192use crate::{Amode, Gpr, GprMem, Registers, Size};193use alloc::string::ToString;194use core::fmt;195196pub fn callq_d(f: &mut fmt::Formatter, inst: &inst::callq_d) -> fmt::Result {197let inst::callq_d { imm32 } = inst;198display_displacement(f, "callq", i64::from(imm32.value()) + 5)199}200201pub fn callq_m<R: Registers>(f: &mut fmt::Formatter, inst: &inst::callq_m<R>) -> fmt::Result {202let inst::callq_m { rm64 } = inst;203let op = rm64.to_string(Size::Quadword);204write!(f, "callq *{op}")205}206207/// Return the predicate string used for the immediate of a `cmp*`208/// instruction.209fn pred_as_str(imm: u8) -> &'static str {210match imm {2110 => "eq",2121 => "lt",2132 => "le",2143 => "unord",2154 => "neq",2165 => "nlt",2176 => "nle",2187 => "ord",219_ => panic!("not a valid predicate for `cmp*`"),220}221}222223pub fn cmpss_a<R: Registers>(f: &mut fmt::Formatter, inst: &inst::cmpss_a<R>) -> fmt::Result {224let xmm1 = inst.xmm1.to_string();225let xmm_m32 = inst.xmm_m32.to_string();226let pred = inst.imm8.value();227if pred > 7 {228let imm8 = inst.imm8.to_string();229write!(f, "cmpss {imm8}, {xmm_m32}, {xmm1}")230} else {231write!(f, "cmp{}ss {xmm_m32}, {xmm1}", pred_as_str(pred))232}233}234235pub fn cmpsd_a<R: Registers>(f: &mut fmt::Formatter, inst: &inst::cmpsd_a<R>) -> fmt::Result {236let xmm1 = inst.xmm1.to_string();237let xmm_m64 = inst.xmm_m64.to_string();238let pred = inst.imm8.value();239if pred > 7 {240let imm8 = inst.imm8.to_string();241write!(f, "cmpsd {imm8}, {xmm_m64}, {xmm1}")242} else {243write!(f, "cmp{}sd {xmm_m64}, {xmm1}", pred_as_str(pred))244}245}246247pub fn cmpps_a<R: Registers>(f: &mut fmt::Formatter, inst: &inst::cmpps_a<R>) -> fmt::Result {248let xmm1 = inst.xmm1.to_string();249let xmm_m128 = inst.xmm_m128.to_string();250let pred = inst.imm8.value();251if pred > 7 {252let imm8 = inst.imm8.to_string();253write!(f, "cmpps {imm8}, {xmm_m128}, {xmm1}")254} else {255write!(f, "cmp{}ps {xmm_m128}, {xmm1}", pred_as_str(pred))256}257}258259pub fn cmppd_a<R: Registers>(f: &mut fmt::Formatter, inst: &inst::cmppd_a<R>) -> fmt::Result {260let xmm1 = inst.xmm1.to_string();261let xmm_m128 = inst.xmm_m128.to_string();262let pred = inst.imm8.value();263if pred > 7 {264let imm8 = inst.imm8.to_string();265write!(f, "cmppd {imm8}, {xmm_m128}, {xmm1}")266} else {267write!(f, "cmp{}pd {xmm_m128}, {xmm1}", pred_as_str(pred))268}269}270271/// Return the predicate string used for the immediate of a `vcmp*`272/// instruction; this is a more complex version of `pred_as_str`.273fn vex_pred_as_str(imm: u8) -> &'static str {274match imm {2750x0 => "eq",2760x1 => "lt",2770x2 => "le",2780x3 => "unord",2790x4 => "neq",2800x5 => "nlt",2810x6 => "nle",2820x7 => "ord",2830x8 => "eq_uq",2840x9 => "nge",2850xa => "ngt",2860xb => "false",2870xc => "neq_oq",2880xd => "ge",2890xe => "gt",2900xf => "true",2910x10 => "eq_os",2920x11 => "lt_oq",2930x12 => "le_oq",2940x13 => "unord_s",2950x14 => "neq_us",2960x15 => "nlt_uq",2970x16 => "nle_uq",2980x17 => "ord_s",2990x18 => "eq_us",3000x19 => "nge_uq",3010x1a => "ngt_uq",3020x1b => "false_os",3030x1c => "neq_os",3040x1d => "ge_oq",3050x1e => "gt_oq",3060x1f => "true_us",307_ => panic!("not a valid predicate for `cmp*`"),308}309}310311pub fn vcmpss_b<R: Registers>(f: &mut fmt::Formatter, inst: &inst::vcmpss_b<R>) -> fmt::Result {312let xmm1 = inst.xmm1.to_string();313let xmm2 = inst.xmm2.to_string();314let xmm_m32 = inst.xmm_m32.to_string();315let pred = inst.imm8.value();316if pred > 0x1f {317let imm8 = inst.imm8.to_string();318write!(f, "vcmpss {imm8}, {xmm_m32}, {xmm2}, {xmm1}")319} else {320write!(321f,322"vcmp{}ss {xmm_m32}, {xmm2}, {xmm1}",323vex_pred_as_str(pred)324)325}326}327328pub fn vcmpsd_b<R: Registers>(f: &mut fmt::Formatter, inst: &inst::vcmpsd_b<R>) -> fmt::Result {329let xmm1 = inst.xmm1.to_string();330let xmm2 = inst.xmm2.to_string();331let xmm_m64 = inst.xmm_m64.to_string();332let pred = inst.imm8.value();333if pred > 0x1f {334let imm8 = inst.imm8.to_string();335write!(f, "vcmpsd {imm8}, {xmm_m64}, {xmm2}, {xmm1}")336} else {337write!(338f,339"vcmp{}sd {xmm_m64}, {xmm2}, {xmm1}",340vex_pred_as_str(pred)341)342}343}344345pub fn vcmpps_b<R: Registers>(f: &mut fmt::Formatter, inst: &inst::vcmpps_b<R>) -> fmt::Result {346let xmm1 = inst.xmm1.to_string();347let xmm2 = inst.xmm2.to_string();348let xmm_m128 = inst.xmm_m128.to_string();349let pred = inst.imm8.value();350if pred > 0x1f {351let imm8 = inst.imm8.to_string();352write!(f, "vcmpps {imm8}, {xmm_m128}, {xmm2}, {xmm1}")353} else {354write!(355f,356"vcmp{}ps {xmm_m128}, {xmm2}, {xmm1}",357vex_pred_as_str(pred)358)359}360}361362pub fn vcmppd_b<R: Registers>(f: &mut fmt::Formatter, inst: &inst::vcmppd_b<R>) -> fmt::Result {363let xmm1 = inst.xmm1.to_string();364let xmm2 = inst.xmm2.to_string();365let xmm_m128 = inst.xmm_m128.to_string();366let pred = inst.imm8.value();367if pred > 0x1f {368let imm8 = inst.imm8.to_string();369write!(f, "vcmppd {imm8}, {xmm_m128}, {xmm2}, {xmm1}")370} else {371write!(372f,373"vcmp{}pd {xmm_m128}, {xmm2}, {xmm1}",374vex_pred_as_str(pred)375)376}377}378379pub fn nop_1b(f: &mut fmt::Formatter, _: &inst::nop_1b) -> fmt::Result {380write!(f, "nop")381}382383pub fn nop_2b(f: &mut fmt::Formatter, _: &inst::nop_2b) -> fmt::Result {384write!(f, "nop")385}386387pub fn nop_3b(f: &mut fmt::Formatter, _: &inst::nop_3b) -> fmt::Result {388write!(f, "nopl (%rax)")389}390391pub fn nop_4b(f: &mut fmt::Formatter, _: &inst::nop_4b) -> fmt::Result {392write!(f, "nopl (%rax)")393}394395pub fn nop_5b(f: &mut fmt::Formatter, _: &inst::nop_5b) -> fmt::Result {396write!(f, "nopl (%rax, %rax)")397}398399pub fn nop_6b(f: &mut fmt::Formatter, _: &inst::nop_6b) -> fmt::Result {400write!(f, "nopw (%rax, %rax)")401}402403pub fn nop_7b(f: &mut fmt::Formatter, _: &inst::nop_7b) -> fmt::Result {404write!(f, "nopl (%rax)")405}406407pub fn nop_8b(f: &mut fmt::Formatter, _: &inst::nop_8b) -> fmt::Result {408write!(f, "nopl (%rax, %rax)")409}410411pub fn nop_9b(f: &mut fmt::Formatter, _: &inst::nop_9b) -> fmt::Result {412write!(f, "nopw (%rax, %rax)")413}414415pub fn xchgb_rm<R: Registers>(416f: &mut fmt::Formatter<'_>,417inst: &inst::xchgb_rm<R>,418) -> fmt::Result {419let inst::xchgb_rm { r8, m8 } = inst;420xchg_rm::<R>(f, r8, m8, Size::Byte)421}422423pub fn xchgw_rm<R: Registers>(424f: &mut fmt::Formatter<'_>,425inst: &inst::xchgw_rm<R>,426) -> fmt::Result {427let inst::xchgw_rm { r16, m16 } = inst;428xchg_rm::<R>(f, r16, m16, Size::Word)429}430431pub fn xchgl_rm<R: Registers>(432f: &mut fmt::Formatter<'_>,433inst: &inst::xchgl_rm<R>,434) -> fmt::Result {435let inst::xchgl_rm { r32, m32 } = inst;436xchg_rm::<R>(f, r32, m32, Size::Doubleword)437}438439pub fn xchgq_rm<R: Registers>(440f: &mut fmt::Formatter<'_>,441inst: &inst::xchgq_rm<R>,442) -> fmt::Result {443let inst::xchgq_rm { r64, m64 } = inst;444xchg_rm::<R>(f, r64, m64, Size::Quadword)445}446447/// Swap the order of printing (register first) to match Capstone.448fn xchg_rm<R: Registers>(449f: &mut fmt::Formatter<'_>,450reg: &Gpr<R::ReadWriteGpr>,451mem: &Amode<R::ReadGpr>,452size: Size,453) -> fmt::Result {454let reg = reg.to_string(size);455let mem = mem.to_string();456let suffix = match size {457Size::Byte => "b",458Size::Word => "w",459Size::Doubleword => "l",460Size::Quadword => "q",461};462write!(f, "xchg{suffix} {reg}, {mem}")463}464465pub fn sarb_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::sarb_m1<R>) -> fmt::Result {466let inst::sarb_m1 { rm8 } = inst;467shift_m1::<R>(f, "sarb", rm8, Size::Byte)468}469470pub fn sarw_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::sarw_m1<R>) -> fmt::Result {471let inst::sarw_m1 { rm16 } = inst;472shift_m1::<R>(f, "sarw", rm16, Size::Word)473}474475pub fn sarl_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::sarl_m1<R>) -> fmt::Result {476let inst::sarl_m1 { rm32 } = inst;477shift_m1::<R>(f, "sarl", rm32, Size::Doubleword)478}479480pub fn sarq_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::sarq_m1<R>) -> fmt::Result {481let inst::sarq_m1 { rm64 } = inst;482shift_m1::<R>(f, "sarq", rm64, Size::Quadword)483}484485pub fn shlb_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::shlb_m1<R>) -> fmt::Result {486let inst::shlb_m1 { rm8 } = inst;487shift_m1::<R>(f, "shlb", rm8, Size::Byte)488}489490pub fn shlw_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::shlw_m1<R>) -> fmt::Result {491let inst::shlw_m1 { rm16 } = inst;492shift_m1::<R>(f, "shlw", rm16, Size::Word)493}494495pub fn shll_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::shll_m1<R>) -> fmt::Result {496let inst::shll_m1 { rm32 } = inst;497shift_m1::<R>(f, "shll", rm32, Size::Doubleword)498}499500pub fn shlq_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::shlq_m1<R>) -> fmt::Result {501let inst::shlq_m1 { rm64 } = inst;502shift_m1::<R>(f, "shlq", rm64, Size::Quadword)503}504505pub fn shrb_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::shrb_m1<R>) -> fmt::Result {506let inst::shrb_m1 { rm8 } = inst;507shift_m1::<R>(f, "shrb", rm8, Size::Byte)508}509510pub fn shrw_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::shrw_m1<R>) -> fmt::Result {511let inst::shrw_m1 { rm16 } = inst;512shift_m1::<R>(f, "shrw", rm16, Size::Word)513}514515pub fn shrl_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::shrl_m1<R>) -> fmt::Result {516let inst::shrl_m1 { rm32 } = inst;517shift_m1::<R>(f, "shrl", rm32, Size::Doubleword)518}519520pub fn shrq_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::shrq_m1<R>) -> fmt::Result {521let inst::shrq_m1 { rm64 } = inst;522shift_m1::<R>(f, "shrq", rm64, Size::Quadword)523}524525pub fn rorb_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::rorb_m1<R>) -> fmt::Result {526let inst::rorb_m1 { rm8 } = inst;527shift_m1::<R>(f, "rorb", rm8, Size::Byte)528}529530pub fn rorw_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::rorw_m1<R>) -> fmt::Result {531let inst::rorw_m1 { rm16 } = inst;532shift_m1::<R>(f, "rorw", rm16, Size::Word)533}534535pub fn rorl_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::rorl_m1<R>) -> fmt::Result {536let inst::rorl_m1 { rm32 } = inst;537shift_m1::<R>(f, "rorl", rm32, Size::Doubleword)538}539540pub fn rorq_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::rorq_m1<R>) -> fmt::Result {541let inst::rorq_m1 { rm64 } = inst;542shift_m1::<R>(f, "rorq", rm64, Size::Quadword)543}544545pub fn rolb_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::rolb_m1<R>) -> fmt::Result {546let inst::rolb_m1 { rm8 } = inst;547shift_m1::<R>(f, "rolb", rm8, Size::Byte)548}549550pub fn rolw_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::rolw_m1<R>) -> fmt::Result {551let inst::rolw_m1 { rm16 } = inst;552shift_m1::<R>(f, "rolw", rm16, Size::Word)553}554555pub fn roll_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::roll_m1<R>) -> fmt::Result {556let inst::roll_m1 { rm32 } = inst;557shift_m1::<R>(f, "roll", rm32, Size::Doubleword)558}559560pub fn rolq_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::rolq_m1<R>) -> fmt::Result {561let inst::rolq_m1 { rm64 } = inst;562shift_m1::<R>(f, "rolq", rm64, Size::Quadword)563}564565fn shift_m1<R: Registers>(566f: &mut fmt::Formatter<'_>,567mnemonic: &str,568rm: &GprMem<R::ReadWriteGpr, R::ReadGpr>,569size: Size,570) -> fmt::Result {571let reg = rm.to_string(size);572match rm {573GprMem::Gpr(_) => write!(f, "{mnemonic} $1, {reg}"),574GprMem::Mem(_) => write!(f, "{mnemonic} {reg}"),575}576}577578pub fn jmpq_m<R: Registers>(f: &mut fmt::Formatter<'_>, jmp: &inst::jmpq_m<R>) -> fmt::Result {579let inst::jmpq_m { rm64 } = jmp;580let rm64 = rm64.to_string(Size::Quadword);581write!(f, "jmpq *{rm64}")582}583584pub fn jmp_d8(f: &mut fmt::Formatter<'_>, jmp: &inst::jmp_d8) -> fmt::Result {585let inst::jmp_d8 { imm8 } = jmp;586display_displacement(f, "jmp", i64::from(imm8.value()) + 2)587}588589pub fn jmp_d32(f: &mut fmt::Formatter<'_>, jmp: &inst::jmp_d32) -> fmt::Result {590let inst::jmp_d32 { imm32 } = jmp;591display_displacement(f, "jmp", i64::from(imm32.value()) + 5)592}593594macro_rules! jcc {595($($mnemonic:tt = $j8:ident / $j32:ident;)*) => ($(596pub fn $j8(f: &mut fmt::Formatter<'_>, jmp: &inst::$j8) -> fmt::Result {597let inst::$j8 { imm8 } = jmp;598display_displacement(f, $mnemonic, i64::from(imm8.value()) + 2)599}600601pub fn $j32(f: &mut fmt::Formatter<'_>, jmp: &inst::$j32) -> fmt::Result {602let inst::$j32 { imm32 } = jmp;603display_displacement(f, $mnemonic, i64::from(imm32.value()) + 6)604}605)*)606}607608jcc! {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}626627fn display_displacement(628f: &mut fmt::Formatter<'_>,629mnemonic: &str,630displacement: i64,631) -> fmt::Result {632if displacement >= 0 && displacement < 10 {633write!(f, "{mnemonic} {displacement}")634} else {635write!(f, "{mnemonic} {displacement:#x}")636}637}638}639640pub mod visit {641use crate::inst::*;642use crate::{Amode, Fixed, Gpr, GprMem, RegisterVisitor, Registers, gpr};643644pub fn mulxl_rvm<R: Registers>(mulx: &mut mulxl_rvm<R>, visitor: &mut impl RegisterVisitor<R>) {645visit_mulx(646&mut mulx.r32a,647&mut mulx.r32b,648&mut mulx.rm32,649&mut mulx.edx,650visitor,651)652}653654pub fn mulxq_rvm<R: Registers>(mulx: &mut mulxq_rvm<R>, visitor: &mut impl RegisterVisitor<R>) {655visit_mulx(656&mut mulx.r64a,657&mut mulx.r64b,658&mut mulx.rm64,659&mut mulx.rdx,660visitor,661)662}663664/// Both mulxl and mulxq have custom register allocator behavior where if the665/// two writable registers are the same then only one is flagged as writable.666/// That represents how when they're both the same only one register is written,667/// not both.668fn visit_mulx<R: Registers>(669ra: &mut Gpr<R::WriteGpr>,670rb: &mut Gpr<R::WriteGpr>,671src1: &mut GprMem<R::ReadGpr, R::ReadGpr>,672src2: &mut Fixed<R::ReadGpr, { gpr::enc::RDX }>,673visitor: &mut impl RegisterVisitor<R>,674) {675if ra == rb {676visitor.write_gpr(ra.as_mut());677*rb = *ra;678} else {679visitor.write_gpr(ra.as_mut());680visitor.write_gpr(rb.as_mut());681}682visitor.read_gpr_mem(src1);683let enc = src2.expected_enc();684visitor.fixed_read_gpr(&mut src2.0, enc);685}686687pub fn lock_xaddb_mr<R: Registers>(688lock_xadd: &mut lock_xaddb_mr<R>,689visitor: &mut impl RegisterVisitor<R>,690) {691let lock_xaddb_mr { r8, m8 } = lock_xadd;692lock_xadd_mr(r8, m8, visitor)693}694695pub fn lock_xaddw_mr<R: Registers>(696lock_xadd: &mut lock_xaddw_mr<R>,697visitor: &mut impl RegisterVisitor<R>,698) {699let lock_xaddw_mr { r16, m16 } = lock_xadd;700lock_xadd_mr(r16, m16, visitor)701}702703pub fn lock_xaddl_mr<R: Registers>(704lock_xadd: &mut lock_xaddl_mr<R>,705visitor: &mut impl RegisterVisitor<R>,706) {707let lock_xaddl_mr { r32, m32 } = lock_xadd;708lock_xadd_mr(r32, m32, visitor)709}710711pub fn lock_xaddq_mr<R: Registers>(712lock_xadd: &mut lock_xaddq_mr<R>,713visitor: &mut impl RegisterVisitor<R>,714) {715let lock_xaddq_mr { r64, m64 } = lock_xadd;716lock_xadd_mr(r64, m64, visitor)717}718719/// Intel says the memory operand comes first, but regalloc requires the720/// register operand comes first, so the custom visit implementation here721/// resolves that.722fn lock_xadd_mr<R: Registers>(723reg: &mut Gpr<R::ReadWriteGpr>,724mem: &mut Amode<R::ReadGpr>,725visitor: &mut impl RegisterVisitor<R>,726) {727visitor.read_write_gpr(reg.as_mut());728visitor.read_amode(mem);729}730}731732733