Path: blob/main/cranelift/assembler-x64/src/custom.rs
1692 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 std::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 std::fmt;194195pub fn callq_d(f: &mut fmt::Formatter, inst: &inst::callq_d) -> fmt::Result {196let inst::callq_d { imm32 } = inst;197display_displacement(f, "callq", i64::from(imm32.value()) + 5)198}199200pub fn callq_m<R: Registers>(f: &mut fmt::Formatter, inst: &inst::callq_m<R>) -> fmt::Result {201let inst::callq_m { rm64 } = inst;202let op = rm64.to_string(Size::Quadword);203write!(f, "callq *{op}")204}205206/// Return the predicate string used for the immediate of a `cmp*`207/// instruction.208fn pred_as_str(imm: u8) -> &'static str {209match imm {2100 => "eq",2111 => "lt",2122 => "le",2133 => "unord",2144 => "neq",2155 => "nlt",2166 => "nle",2177 => "ord",218_ => panic!("not a valid predicate for `cmp*`"),219}220}221222pub fn cmpss_a<R: Registers>(f: &mut fmt::Formatter, inst: &inst::cmpss_a<R>) -> fmt::Result {223let xmm1 = inst.xmm1.to_string();224let xmm_m32 = inst.xmm_m32.to_string();225let pred = inst.imm8.value();226if pred > 7 {227let imm8 = inst.imm8.to_string();228write!(f, "cmpss {imm8}, {xmm_m32}, {xmm1}")229} else {230write!(f, "cmp{}ss {xmm_m32}, {xmm1}", pred_as_str(pred))231}232}233234pub fn cmpsd_a<R: Registers>(f: &mut fmt::Formatter, inst: &inst::cmpsd_a<R>) -> fmt::Result {235let xmm1 = inst.xmm1.to_string();236let xmm_m64 = inst.xmm_m64.to_string();237let pred = inst.imm8.value();238if pred > 7 {239let imm8 = inst.imm8.to_string();240write!(f, "cmpsd {imm8}, {xmm_m64}, {xmm1}")241} else {242write!(f, "cmp{}sd {xmm_m64}, {xmm1}", pred_as_str(pred))243}244}245246pub fn cmpps_a<R: Registers>(f: &mut fmt::Formatter, inst: &inst::cmpps_a<R>) -> fmt::Result {247let xmm1 = inst.xmm1.to_string();248let xmm_m128 = inst.xmm_m128.to_string();249let pred = inst.imm8.value();250if pred > 7 {251let imm8 = inst.imm8.to_string();252write!(f, "cmpps {imm8}, {xmm_m128}, {xmm1}")253} else {254write!(f, "cmp{}ps {xmm_m128}, {xmm1}", pred_as_str(pred))255}256}257258pub fn cmppd_a<R: Registers>(f: &mut fmt::Formatter, inst: &inst::cmppd_a<R>) -> fmt::Result {259let xmm1 = inst.xmm1.to_string();260let xmm_m128 = inst.xmm_m128.to_string();261let pred = inst.imm8.value();262if pred > 7 {263let imm8 = inst.imm8.to_string();264write!(f, "cmppd {imm8}, {xmm_m128}, {xmm1}")265} else {266write!(f, "cmp{}pd {xmm_m128}, {xmm1}", pred_as_str(pred))267}268}269270/// Return the predicate string used for the immediate of a `vcmp*`271/// instruction; this is a more complex version of `pred_as_str`.272fn vex_pred_as_str(imm: u8) -> &'static str {273match imm {2740x0 => "eq",2750x1 => "lt",2760x2 => "le",2770x3 => "unord",2780x4 => "neq",2790x5 => "nlt",2800x6 => "nle",2810x7 => "ord",2820x8 => "eq_uq",2830x9 => "nge",2840xa => "ngt",2850xb => "false",2860xc => "neq_oq",2870xd => "ge",2880xe => "gt",2890xf => "true",2900x10 => "eq_os",2910x11 => "lt_oq",2920x12 => "le_oq",2930x13 => "unord_s",2940x14 => "neq_us",2950x15 => "nlt_uq",2960x16 => "nle_uq",2970x17 => "ord_s",2980x18 => "eq_us",2990x19 => "nge_uq",3000x1a => "ngt_uq",3010x1b => "false_os",3020x1c => "neq_os",3030x1d => "ge_oq",3040x1e => "gt_oq",3050x1f => "true_us",306_ => panic!("not a valid predicate for `cmp*`"),307}308}309310pub fn vcmpss_b<R: Registers>(f: &mut fmt::Formatter, inst: &inst::vcmpss_b<R>) -> fmt::Result {311let xmm1 = inst.xmm1.to_string();312let xmm2 = inst.xmm2.to_string();313let xmm_m32 = inst.xmm_m32.to_string();314let pred = inst.imm8.value();315if pred > 0x1f {316let imm8 = inst.imm8.to_string();317write!(f, "vcmpss {imm8}, {xmm_m32}, {xmm2}, {xmm1}")318} else {319write!(320f,321"vcmp{}ss {xmm_m32}, {xmm2}, {xmm1}",322vex_pred_as_str(pred)323)324}325}326327pub fn vcmpsd_b<R: Registers>(f: &mut fmt::Formatter, inst: &inst::vcmpsd_b<R>) -> fmt::Result {328let xmm1 = inst.xmm1.to_string();329let xmm2 = inst.xmm2.to_string();330let xmm_m64 = inst.xmm_m64.to_string();331let pred = inst.imm8.value();332if pred > 0x1f {333let imm8 = inst.imm8.to_string();334write!(f, "vcmpsd {imm8}, {xmm_m64}, {xmm2}, {xmm1}")335} else {336write!(337f,338"vcmp{}sd {xmm_m64}, {xmm2}, {xmm1}",339vex_pred_as_str(pred)340)341}342}343344pub fn vcmpps_b<R: Registers>(f: &mut fmt::Formatter, inst: &inst::vcmpps_b<R>) -> fmt::Result {345let xmm1 = inst.xmm1.to_string();346let xmm2 = inst.xmm2.to_string();347let xmm_m128 = inst.xmm_m128.to_string();348let pred = inst.imm8.value();349if pred > 0x1f {350let imm8 = inst.imm8.to_string();351write!(f, "vcmpps {imm8}, {xmm_m128}, {xmm2}, {xmm1}")352} else {353write!(354f,355"vcmp{}ps {xmm_m128}, {xmm2}, {xmm1}",356vex_pred_as_str(pred)357)358}359}360361pub fn vcmppd_b<R: Registers>(f: &mut fmt::Formatter, inst: &inst::vcmppd_b<R>) -> fmt::Result {362let xmm1 = inst.xmm1.to_string();363let xmm2 = inst.xmm2.to_string();364let xmm_m128 = inst.xmm_m128.to_string();365let pred = inst.imm8.value();366if pred > 0x1f {367let imm8 = inst.imm8.to_string();368write!(f, "vcmppd {imm8}, {xmm_m128}, {xmm2}, {xmm1}")369} else {370write!(371f,372"vcmp{}pd {xmm_m128}, {xmm2}, {xmm1}",373vex_pred_as_str(pred)374)375}376}377378pub fn nop_1b(f: &mut fmt::Formatter, _: &inst::nop_1b) -> fmt::Result {379write!(f, "nop")380}381382pub fn nop_2b(f: &mut fmt::Formatter, _: &inst::nop_2b) -> fmt::Result {383write!(f, "nop")384}385386pub fn nop_3b(f: &mut fmt::Formatter, _: &inst::nop_3b) -> fmt::Result {387write!(f, "nopl (%rax)")388}389390pub fn nop_4b(f: &mut fmt::Formatter, _: &inst::nop_4b) -> fmt::Result {391write!(f, "nopl (%rax)")392}393394pub fn nop_5b(f: &mut fmt::Formatter, _: &inst::nop_5b) -> fmt::Result {395write!(f, "nopl (%rax, %rax)")396}397398pub fn nop_6b(f: &mut fmt::Formatter, _: &inst::nop_6b) -> fmt::Result {399write!(f, "nopw (%rax, %rax)")400}401402pub fn nop_7b(f: &mut fmt::Formatter, _: &inst::nop_7b) -> fmt::Result {403write!(f, "nopl (%rax)")404}405406pub fn nop_8b(f: &mut fmt::Formatter, _: &inst::nop_8b) -> fmt::Result {407write!(f, "nopl (%rax, %rax)")408}409410pub fn nop_9b(f: &mut fmt::Formatter, _: &inst::nop_9b) -> fmt::Result {411write!(f, "nopw (%rax, %rax)")412}413414pub fn xchgb_rm<R: Registers>(415f: &mut fmt::Formatter<'_>,416inst: &inst::xchgb_rm<R>,417) -> fmt::Result {418let inst::xchgb_rm { r8, m8 } = inst;419xchg_rm::<R>(f, r8, m8, Size::Byte)420}421422pub fn xchgw_rm<R: Registers>(423f: &mut fmt::Formatter<'_>,424inst: &inst::xchgw_rm<R>,425) -> fmt::Result {426let inst::xchgw_rm { r16, m16 } = inst;427xchg_rm::<R>(f, r16, m16, Size::Word)428}429430pub fn xchgl_rm<R: Registers>(431f: &mut fmt::Formatter<'_>,432inst: &inst::xchgl_rm<R>,433) -> fmt::Result {434let inst::xchgl_rm { r32, m32 } = inst;435xchg_rm::<R>(f, r32, m32, Size::Doubleword)436}437438pub fn xchgq_rm<R: Registers>(439f: &mut fmt::Formatter<'_>,440inst: &inst::xchgq_rm<R>,441) -> fmt::Result {442let inst::xchgq_rm { r64, m64 } = inst;443xchg_rm::<R>(f, r64, m64, Size::Quadword)444}445446/// Swap the order of printing (register first) to match Capstone.447fn xchg_rm<R: Registers>(448f: &mut fmt::Formatter<'_>,449reg: &Gpr<R::ReadWriteGpr>,450mem: &Amode<R::ReadGpr>,451size: Size,452) -> fmt::Result {453let reg = reg.to_string(size);454let mem = mem.to_string();455let suffix = match size {456Size::Byte => "b",457Size::Word => "w",458Size::Doubleword => "l",459Size::Quadword => "q",460};461write!(f, "xchg{suffix} {reg}, {mem}")462}463464pub fn sarb_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::sarb_m1<R>) -> fmt::Result {465let inst::sarb_m1 { rm8 } = inst;466shift_m1::<R>(f, "sarb", rm8, Size::Byte)467}468469pub fn sarw_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::sarw_m1<R>) -> fmt::Result {470let inst::sarw_m1 { rm16 } = inst;471shift_m1::<R>(f, "sarw", rm16, Size::Word)472}473474pub fn sarl_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::sarl_m1<R>) -> fmt::Result {475let inst::sarl_m1 { rm32 } = inst;476shift_m1::<R>(f, "sarl", rm32, Size::Doubleword)477}478479pub fn sarq_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::sarq_m1<R>) -> fmt::Result {480let inst::sarq_m1 { rm64 } = inst;481shift_m1::<R>(f, "sarq", rm64, Size::Quadword)482}483484pub fn shlb_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::shlb_m1<R>) -> fmt::Result {485let inst::shlb_m1 { rm8 } = inst;486shift_m1::<R>(f, "shlb", rm8, Size::Byte)487}488489pub fn shlw_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::shlw_m1<R>) -> fmt::Result {490let inst::shlw_m1 { rm16 } = inst;491shift_m1::<R>(f, "shlw", rm16, Size::Word)492}493494pub fn shll_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::shll_m1<R>) -> fmt::Result {495let inst::shll_m1 { rm32 } = inst;496shift_m1::<R>(f, "shll", rm32, Size::Doubleword)497}498499pub fn shlq_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::shlq_m1<R>) -> fmt::Result {500let inst::shlq_m1 { rm64 } = inst;501shift_m1::<R>(f, "shlq", rm64, Size::Quadword)502}503504pub fn shrb_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::shrb_m1<R>) -> fmt::Result {505let inst::shrb_m1 { rm8 } = inst;506shift_m1::<R>(f, "shrb", rm8, Size::Byte)507}508509pub fn shrw_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::shrw_m1<R>) -> fmt::Result {510let inst::shrw_m1 { rm16 } = inst;511shift_m1::<R>(f, "shrw", rm16, Size::Word)512}513514pub fn shrl_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::shrl_m1<R>) -> fmt::Result {515let inst::shrl_m1 { rm32 } = inst;516shift_m1::<R>(f, "shrl", rm32, Size::Doubleword)517}518519pub fn shrq_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::shrq_m1<R>) -> fmt::Result {520let inst::shrq_m1 { rm64 } = inst;521shift_m1::<R>(f, "shrq", rm64, Size::Quadword)522}523524pub fn rorb_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::rorb_m1<R>) -> fmt::Result {525let inst::rorb_m1 { rm8 } = inst;526shift_m1::<R>(f, "rorb", rm8, Size::Byte)527}528529pub fn rorw_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::rorw_m1<R>) -> fmt::Result {530let inst::rorw_m1 { rm16 } = inst;531shift_m1::<R>(f, "rorw", rm16, Size::Word)532}533534pub fn rorl_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::rorl_m1<R>) -> fmt::Result {535let inst::rorl_m1 { rm32 } = inst;536shift_m1::<R>(f, "rorl", rm32, Size::Doubleword)537}538539pub fn rorq_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::rorq_m1<R>) -> fmt::Result {540let inst::rorq_m1 { rm64 } = inst;541shift_m1::<R>(f, "rorq", rm64, Size::Quadword)542}543544pub fn rolb_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::rolb_m1<R>) -> fmt::Result {545let inst::rolb_m1 { rm8 } = inst;546shift_m1::<R>(f, "rolb", rm8, Size::Byte)547}548549pub fn rolw_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::rolw_m1<R>) -> fmt::Result {550let inst::rolw_m1 { rm16 } = inst;551shift_m1::<R>(f, "rolw", rm16, Size::Word)552}553554pub fn roll_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::roll_m1<R>) -> fmt::Result {555let inst::roll_m1 { rm32 } = inst;556shift_m1::<R>(f, "roll", rm32, Size::Doubleword)557}558559pub fn rolq_m1<R: Registers>(f: &mut fmt::Formatter, inst: &inst::rolq_m1<R>) -> fmt::Result {560let inst::rolq_m1 { rm64 } = inst;561shift_m1::<R>(f, "rolq", rm64, Size::Quadword)562}563564fn shift_m1<R: Registers>(565f: &mut fmt::Formatter<'_>,566mnemonic: &str,567rm: &GprMem<R::ReadWriteGpr, R::ReadGpr>,568size: Size,569) -> fmt::Result {570let reg = rm.to_string(size);571match rm {572GprMem::Gpr(_) => write!(f, "{mnemonic} $1, {reg}"),573GprMem::Mem(_) => write!(f, "{mnemonic} {reg}"),574}575}576577pub fn jmpq_m<R: Registers>(f: &mut fmt::Formatter<'_>, jmp: &inst::jmpq_m<R>) -> fmt::Result {578let inst::jmpq_m { rm64 } = jmp;579let rm64 = rm64.to_string(Size::Quadword);580write!(f, "jmpq *{rm64}")581}582583pub fn jmp_d8(f: &mut fmt::Formatter<'_>, jmp: &inst::jmp_d8) -> fmt::Result {584let inst::jmp_d8 { imm8 } = jmp;585display_displacement(f, "jmp", i64::from(imm8.value()) + 2)586}587588pub fn jmp_d32(f: &mut fmt::Formatter<'_>, jmp: &inst::jmp_d32) -> fmt::Result {589let inst::jmp_d32 { imm32 } = jmp;590display_displacement(f, "jmp", i64::from(imm32.value()) + 5)591}592593macro_rules! jcc {594($($mnemonic:tt = $j8:ident / $j32:ident;)*) => ($(595pub fn $j8(f: &mut fmt::Formatter<'_>, jmp: &inst::$j8) -> fmt::Result {596let inst::$j8 { imm8 } = jmp;597display_displacement(f, $mnemonic, i64::from(imm8.value()) + 2)598}599600pub fn $j32(f: &mut fmt::Formatter<'_>, jmp: &inst::$j32) -> fmt::Result {601let inst::$j32 { imm32 } = jmp;602display_displacement(f, $mnemonic, i64::from(imm32.value()) + 6)603}604)*)605}606607jcc! {608"ja" = ja_d8 / ja_d32;609"jae" = jae_d8 / jae_d32;610"jb" = jb_d8 / jb_d32;611"jbe" = jbe_d8 / jbe_d32;612"je" = je_d8 / je_d32;613"jg" = jg_d8 / jg_d32;614"jge" = jge_d8 / jge_d32;615"jl" = jl_d8 / jl_d32;616"jle" = jle_d8 / jle_d32;617"jne" = jne_d8 / jne_d32;618"jno" = jno_d8 / jno_d32;619"jnp" = jnp_d8 / jnp_d32;620"jns" = jns_d8 / jns_d32;621"jo" = jo_d8 / jo_d32;622"jp" = jp_d8 / jp_d32;623"js" = js_d8 / js_d32;624}625626fn display_displacement(627f: &mut fmt::Formatter<'_>,628mnemonic: &str,629displacement: i64,630) -> fmt::Result {631if displacement >= 0 && displacement < 10 {632write!(f, "{mnemonic} {displacement}")633} else {634write!(f, "{mnemonic} {displacement:#x}")635}636}637}638639pub mod visit {640use crate::inst::*;641use crate::{Amode, Fixed, Gpr, GprMem, RegisterVisitor, Registers, gpr};642643pub fn mulxl_rvm<R: Registers>(mulx: &mut mulxl_rvm<R>, visitor: &mut impl RegisterVisitor<R>) {644visit_mulx(645&mut mulx.r32a,646&mut mulx.r32b,647&mut mulx.rm32,648&mut mulx.edx,649visitor,650)651}652653pub fn mulxq_rvm<R: Registers>(mulx: &mut mulxq_rvm<R>, visitor: &mut impl RegisterVisitor<R>) {654visit_mulx(655&mut mulx.r64a,656&mut mulx.r64b,657&mut mulx.rm64,658&mut mulx.rdx,659visitor,660)661}662663/// Both mulxl and mulxq have custom register allocator behavior where if the664/// two writable registers are the same then only one is flagged as writable.665/// That represents how when they're both the same only one register is written,666/// not both.667fn visit_mulx<R: Registers>(668ra: &mut Gpr<R::WriteGpr>,669rb: &mut Gpr<R::WriteGpr>,670src1: &mut GprMem<R::ReadGpr, R::ReadGpr>,671src2: &mut Fixed<R::ReadGpr, { gpr::enc::RDX }>,672visitor: &mut impl RegisterVisitor<R>,673) {674if ra == rb {675visitor.write_gpr(ra.as_mut());676*rb = *ra;677} else {678visitor.write_gpr(ra.as_mut());679visitor.write_gpr(rb.as_mut());680}681visitor.read_gpr_mem(src1);682let enc = src2.expected_enc();683visitor.fixed_read_gpr(&mut src2.0, enc);684}685686pub fn lock_xaddb_mr<R: Registers>(687lock_xadd: &mut lock_xaddb_mr<R>,688visitor: &mut impl RegisterVisitor<R>,689) {690let lock_xaddb_mr { r8, m8 } = lock_xadd;691lock_xadd_mr(r8, m8, visitor)692}693694pub fn lock_xaddw_mr<R: Registers>(695lock_xadd: &mut lock_xaddw_mr<R>,696visitor: &mut impl RegisterVisitor<R>,697) {698let lock_xaddw_mr { r16, m16 } = lock_xadd;699lock_xadd_mr(r16, m16, visitor)700}701702pub fn lock_xaddl_mr<R: Registers>(703lock_xadd: &mut lock_xaddl_mr<R>,704visitor: &mut impl RegisterVisitor<R>,705) {706let lock_xaddl_mr { r32, m32 } = lock_xadd;707lock_xadd_mr(r32, m32, visitor)708}709710pub fn lock_xaddq_mr<R: Registers>(711lock_xadd: &mut lock_xaddq_mr<R>,712visitor: &mut impl RegisterVisitor<R>,713) {714let lock_xaddq_mr { r64, m64 } = lock_xadd;715lock_xadd_mr(r64, m64, visitor)716}717718/// Intel says the memory operand comes first, but regalloc requires the719/// register operand comes first, so the custom visit implementation here720/// resolves that.721fn lock_xadd_mr<R: Registers>(722reg: &mut Gpr<R::ReadWriteGpr>,723mem: &mut Amode<R::ReadGpr>,724visitor: &mut impl RegisterVisitor<R>,725) {726visitor.read_write_gpr(reg.as_mut());727visitor.read_amode(mem);728}729}730731732