use write instead of format

Decreases fuzz time from 183s to 72s.
This commit is contained in:
Richard Patel 2021-08-14 01:10:52 +02:00
parent 7d2b8c16ca
commit a94ee22d14
2 changed files with 231 additions and 153 deletions

View File

@ -88,8 +88,11 @@ impl Fuzzer {
let counter = Arc::clone(&self.counter);
let range = self.range.clone();
std::thread::spawn(move || {
let mut buf = String::with_capacity(1024);
for x in range.clone() {
black_box(Ins::disasm(x).to_string());
let ins = Ins::disasm(x);
ins.write_string(&mut buf).unwrap();
black_box(&buf);
if x % (1 << 19) == 0 {
counter.store(x, Ordering::Relaxed);
}

View File

@ -1,3 +1,4 @@
use std::fmt::Write;
use std::ops::Range;
use num_traits::AsPrimitive;
@ -1309,7 +1310,7 @@ impl Ins {
ins
}
fn to_string_form_reg123(&self) -> String {
fn write_string_form_reg123(&self, out: &mut String) -> std::fmt::Result {
let name = match self.op {
Opcode::Eciwx => "eciwx",
Opcode::Ecowx => "ecowx",
@ -1337,10 +1338,10 @@ impl Ins {
Opcode::Stwux => "stwux",
_ => disasm_unreachable!(self.code),
};
format!("{} r{}, r{}, r{}", name, self.d(), self.a(), self.b())
write!(out, "{} r{}, r{}, r{}", name, self.d(), self.a(), self.b())
}
fn to_string_form_reg123_rc(&self) -> String {
fn write_string_form_reg123_rc(&self, out: &mut String) -> std::fmt::Result {
let name_suffix = if self.rc() { "." } else { "" };
let name = match self.op {
Opcode::And => "and",
@ -1350,7 +1351,8 @@ impl Ins {
Opcode::Xor => "xor",
_ => disasm_unreachable!(self.code),
};
format!(
write!(
out,
"{}{} r{}, r{}, r{}",
name,
name_suffix,
@ -1360,7 +1362,7 @@ impl Ins {
)
}
fn to_string_form_reg123_oe_rc(&self) -> String {
fn write_string_form_reg123_oe_rc(&self, out: &mut String) -> std::fmt::Result {
let name_suffix = match (self.oe(), self.rc()) {
(false, false) => "",
(false, true) => ".",
@ -1379,7 +1381,8 @@ impl Ins {
Opcode::Subfe => "subfe",
_ => disasm_unreachable!(self.code),
};
format!(
write!(
out,
"{}{} r{}, r{}, r{}",
name,
name_suffix,
@ -1389,8 +1392,8 @@ impl Ins {
)
}
fn to_string_noargs(&self) -> String {
match self.op {
fn write_string_noargs(&self, out: &mut String) -> std::fmt::Result {
*out = match self.op {
Opcode::Eieio => "eieio",
Opcode::Isync => "isync",
Opcode::Rfi => "rfi",
@ -1398,11 +1401,11 @@ impl Ins {
Opcode::Sync => "sync",
Opcode::Tlbsync => "tlbsync",
_ => disasm_unreachable!(self.code),
}
.to_owned()
}.to_owned();
Ok(())
}
fn to_string_form_reg12_simm(&self) -> String {
fn write_string_form_reg12_simm(&self, out: &mut String) -> std::fmt::Result {
let name = match self.op {
Opcode::Addi => "addi",
Opcode::Addic => "addic",
@ -1412,10 +1415,17 @@ impl Ins {
Opcode::Subfic => "subfic",
_ => disasm_unreachable!(self.code),
};
format!("{} r{}, r{}, {}", name, self.d(), self.a(), self.simm())
write!(
out,
"{} r{}, r{}, {}",
name,
self.d(),
self.a(),
self.simm()
)
}
fn to_string_form_reg12_uimm(&self) -> String {
fn write_string_form_reg12_uimm(&self, out: &mut String) -> std::fmt::Result {
let name = match self.op {
Opcode::Andi_ => "andi.",
Opcode::Andis_ => "andis.",
@ -1425,10 +1435,17 @@ impl Ins {
Opcode::Xoris => "xoris",
_ => disasm_unreachable!(self.code),
};
format!("{} r{}, r{}, {}", name, self.d(), self.a(), self.uimm())
write!(
out,
"{} r{}, r{}, {}",
name,
self.d(),
self.a(),
self.uimm()
)
}
fn to_string_form_reg12_offset(&self) -> String {
fn write_string_form_reg12_offset(&self, out: &mut String) -> std::fmt::Result {
let name = match self.op {
Opcode::Lha => "lha",
Opcode::Lhau => "lhau",
@ -1448,10 +1465,17 @@ impl Ins {
Opcode::Stwu => "stwu",
_ => disasm_unreachable!(self.code),
};
format!("{} r{}, {}(r{})", name, self.d(), self.simm(), self.a())
write!(
out,
"{} r{}, {}(r{})",
name,
self.d(),
self.simm(),
self.a()
)
}
fn to_string_form_fr1_reg2_offset(&self) -> String {
fn write_string_form_fr1_reg2_offset(&self, out: &mut String) -> std::fmt::Result {
let name = match self.op {
Opcode::Lfd => "lfd",
Opcode::Lfdu => "lfdu",
@ -1463,10 +1487,17 @@ impl Ins {
Opcode::Stfsu => "stfsu",
_ => disasm_unreachable!(self.code),
};
format!("{} fr{}, {}(r{})", name, self.d(), self.simm(), self.a())
write!(
out,
"{} fr{}, {}(r{})",
name,
self.d(),
self.simm(),
self.a()
)
}
fn to_string_form_fr1_reg23(&self) -> String {
fn write_string_form_fr1_reg23(&self, out: &mut String) -> std::fmt::Result {
let name = match self.op {
Opcode::Lfdux => "lfdux",
Opcode::Lfdx => "lfdx",
@ -1479,23 +1510,24 @@ impl Ins {
Opcode::Stfsx => "stfsx",
_ => disasm_unreachable!(self.code),
};
format!("{} fr{}, r{}, r{}", name, self.d(), self.a(), self.b())
write!(out, "{} fr{}, r{}, r{}", name, self.d(), self.a(), self.b())
}
fn to_string_mtfsf(&self) -> String {
fn write_string_mtfsf(&self, out: &mut String) -> std::fmt::Result {
let name = match self.op {
Opcode::Mtfsf => "mtfsf",
_ => disasm_unreachable!(self.code),
};
format!("{} {}, fr{}", name, self.fm(), self.b())
write!(out, "{} {}, fr{}", name, self.fm(), self.b())
}
fn to_string_mtfsfi(&self) -> String {
fn write_string_mtfsfi(&self, out: &mut String) -> std::fmt::Result {
let name = match self.op {
Opcode::Mtfsfi => "mtfsfi",
_ => disasm_unreachable!(self.code),
};
format!(
write!(
out,
"{} crf{}, {}",
name,
self.crf_d(),
@ -1503,7 +1535,7 @@ impl Ins {
)
}
fn to_string_form_reg1(&self) -> String {
fn write_string_form_reg1(&self, out: &mut String) -> std::fmt::Result {
let name = match self.op {
Opcode::Mfcr => "mfcr",
Opcode::Mfmsr => "mfmsr",
@ -1511,10 +1543,10 @@ impl Ins {
Opcode::Tlbie => "tblie",
_ => disasm_unreachable!(self.code),
};
format!("{} r{}", name, self.d())
write!(out, "{} r{}", name, self.d())
}
fn to_string_form_reg12_oe_rc(&self) -> String {
fn write_string_form_reg12_oe_rc(&self, out: &mut String) -> std::fmt::Result {
let name_suffix = match (self.oe(), self.rc()) {
(false, false) => "",
(false, true) => ".",
@ -1529,19 +1561,19 @@ impl Ins {
Opcode::Subfze => "subfze",
_ => disasm_unreachable!(self.code),
};
format!("{}{} r{}, r{}", name, name_suffix, self.d(), self.a())
write!(out, "{}{} r{}, r{}", name, name_suffix, self.d(), self.a())
}
fn to_string_form_reg13(&self) -> String {
fn write_string_form_reg13(&self, out: &mut String) -> std::fmt::Result {
let name = match self.op {
Opcode::Mfsrin => "mfsrin",
Opcode::Mtsrin => "mtsrin",
_ => disasm_unreachable!(self.code),
};
format!("{} r{}, r{}", name, self.d(), self.b())
write!(out, "{} r{}, r{}", name, self.d(), self.b())
}
fn to_string_form_reg21_rc(&self) -> String {
fn write_string_form_reg21_rc(&self, out: &mut String) -> std::fmt::Result {
let name_suffix = if self.rc() { "." } else { "" };
let name = match self.op {
Opcode::Cntlzw => "cntlzw",
@ -1549,10 +1581,10 @@ impl Ins {
Opcode::Extsh => "extsh",
_ => disasm_unreachable!(self.code),
};
format!("{}{} r{}, r{}", name, name_suffix, self.a(), self.s())
write!(out, "{}{} r{}, r{}", name, name_suffix, self.a(), self.s())
}
fn to_string_form_fr1(&self) -> String {
fn write_string_form_fr1(&self, out: &mut String) -> std::fmt::Result {
let name = match self.op {
Opcode::Mffs => match self.rc() {
false => "mffs",
@ -1560,10 +1592,10 @@ impl Ins {
},
_ => disasm_unreachable!(self.code),
};
format!("{} fr{}", name, self.d())
write!(out, "{} fr{}", name, self.d())
}
fn to_string_form_fr13(&self) -> String {
fn write_string_form_fr13(&self, out: &mut String) -> std::fmt::Result {
let name_suffix = if self.rc() { "." } else { "" };
let name = match self.op {
Opcode::Fabs => "fabs",
@ -1583,10 +1615,17 @@ impl Ins {
Opcode::PsSum1 => "ps_sum1",
_ => disasm_unreachable!(self.code),
};
format!("{}{} fr{}, fr{}", name, name_suffix, self.d(), self.b())
write!(
out,
"{}{} fr{}, fr{}",
name,
name_suffix,
self.d(),
self.b()
)
}
fn to_string_form_fr123(&self) -> String {
fn write_string_form_fr123(&self, out: &mut String) -> std::fmt::Result {
let name_suffix = if self.rc() { "." } else { "" };
let name = match self.op {
Opcode::Fadd => "fadd",
@ -1604,7 +1643,8 @@ impl Ins {
Opcode::PsSub => "ps_sub",
_ => disasm_unreachable!(self.code),
};
format!(
write!(
out,
"{}{} fr{}, fr{}, fr{}",
name,
name_suffix,
@ -1614,7 +1654,7 @@ impl Ins {
)
}
fn to_string_form_fr1243(&self) -> String {
fn write_string_form_fr1243(&self, out: &mut String) -> std::fmt::Result {
let name_suffix = if self.rc() { "." } else { "" };
let name = match self.op {
Opcode::Fmadd => "fmadd",
@ -1637,7 +1677,8 @@ impl Ins {
Opcode::PsSum1 => "ps_sum1",
_ => disasm_unreachable!(self.code),
};
format!(
write!(
out,
"{}{} fr{}, fr{}, fr{}, fr{}",
name,
name_suffix,
@ -1648,7 +1689,7 @@ impl Ins {
)
}
fn to_string_form_fr124(&self) -> String {
fn write_string_form_fr124(&self, out: &mut String) -> std::fmt::Result {
let name_suffix = if self.rc() { "." } else { "" };
let name = match self.op {
Opcode::Fmul => "fmul",
@ -1658,7 +1699,8 @@ impl Ins {
Opcode::PsMuls1 => "ps_muls1",
_ => disasm_unreachable!(self.code),
};
format!(
write!(
out,
"{}{} fr{}, fr{}, fr{}",
name,
name_suffix,
@ -1668,7 +1710,7 @@ impl Ins {
)
}
fn to_string_form_condreg1_fr23(&self) -> String {
fn write_string_form_condreg1_fr23(&self, out: &mut String) -> std::fmt::Result {
let name = match self.op {
Opcode::Fcmpo => "fcmpo",
Opcode::Fcmpu => "fcmpu",
@ -1678,7 +1720,8 @@ impl Ins {
Opcode::PsCmpu1 => "ps_cmpu1",
_ => disasm_unreachable!(self.code),
};
format!(
write!(
out,
"{} crf{}, fr{}, fr{}",
name,
self.crf_d(),
@ -1687,14 +1730,15 @@ impl Ins {
)
}
fn to_string_form_condreg1_fr13_rc(&self) -> String {
fn write_string_form_condreg1_fr13_rc(&self, out: &mut String) -> std::fmt::Result {
let name_suffix = if self.rc() { "." } else { "" };
let name = match self.op {
Opcode::Fctiw => "fctiw",
Opcode::Fctiwz => "fctiwz",
_ => disasm_unreachable!(self.code),
};
format!(
write!(
out,
"{}{} crf{}, fr{}, fr{}",
name,
name_suffix,
@ -1704,7 +1748,7 @@ impl Ins {
)
}
fn to_string_b(&self) -> String {
fn write_string_b(&self, out: &mut String) -> std::fmt::Result {
let name = match (self.aa(), self.lk()) {
(false, false) => "b",
(false, true) => "bl",
@ -1712,10 +1756,10 @@ impl Ins {
(true, true) => "bla",
};
// TODO absolute address
format!("{} 0x{:x}", name, self.li())
write!(out, "{} 0x{:x}", name, self.li())
}
fn to_string_bc(&self) -> String {
fn write_string_bc(&self, out: &mut String) -> std::fmt::Result {
let name = match (self.aa(), self.lk()) {
(false, false) => "bc",
(false, true) => "bcl",
@ -1723,7 +1767,8 @@ impl Ins {
(true, true) => "bcla",
};
// TODO absolute address
format!(
write!(
out,
"{} 0x{:x}, 0x{:x}, 0x{:x}",
name,
self.bo(),
@ -1732,7 +1777,7 @@ impl Ins {
)
}
fn to_string_branch_cond_to_reg(&self) -> String {
fn write_string_branch_cond_to_reg(&self, out: &mut String) -> std::fmt::Result {
let name = match self.op {
Opcode::Bcctr => match self.lk() {
false => "bcctr",
@ -1744,16 +1789,17 @@ impl Ins {
},
_ => disasm_unreachable!(self.code),
};
format!("{} 0x{:x}, 0x{:x}", name, self.bo(), self.bi())
write!(out, "{} 0x{:x}, 0x{:x}", name, self.bo(), self.bi())
}
fn to_string_cmp(&self) -> String {
fn write_string_cmp(&self, out: &mut String) -> std::fmt::Result {
let name = match self.op {
Opcode::Cmp => "cmp",
Opcode::Cmpl => "cmpl",
_ => disasm_unreachable!(self.code),
};
format!(
write!(
out,
"{} crf{}, {}, r{}, r{}",
name,
self.crf_d(),
@ -1763,9 +1809,10 @@ impl Ins {
)
}
fn to_string_cmp_simm(&self) -> String {
fn write_string_cmp_simm(&self, out: &mut String) -> std::fmt::Result {
let name = "cmpi";
format!(
write!(
out,
"{} crf{}, {}, r{}, {}",
name,
self.crf_d(),
@ -1775,9 +1822,10 @@ impl Ins {
)
}
fn to_string_cmp_uimm(&self) -> String {
fn write_string_cmp_uimm(&self, out: &mut String) -> std::fmt::Result {
let name = "cmpli";
format!(
write!(
out,
"{} crf{}, {}, r{}, {}",
name,
self.crf_d(),
@ -1787,7 +1835,7 @@ impl Ins {
)
}
fn to_string_form_condreg1(&self) -> String {
fn write_string_form_condreg1(&self, out: &mut String) -> std::fmt::Result {
let name = match self.op {
Opcode::Mcrxr => "mcrxr",
Opcode::Mtfsb0 => match self.rc() {
@ -1800,19 +1848,19 @@ impl Ins {
},
_ => disasm_unreachable!(self.code),
};
format!("{} crf{}", name, self.crf_d())
write!(out, "{} crf{}", name, self.crf_d())
}
fn to_string_form_condreg12(&self) -> String {
fn write_string_form_condreg12(&self, out: &mut String) -> std::fmt::Result {
let name = match self.op {
Opcode::Mcrf => "mcrf",
Opcode::Mcrfs => "mcrfs",
_ => disasm_unreachable!(self.code),
};
format!("{} crf{}, crf{}", name, self.crf_d(), self.crf_s())
write!(out, "{} crf{}, crf{}", name, self.crf_d(), self.crf_s())
}
fn to_string_form_condreg123(&self) -> String {
fn write_string_form_condreg123(&self, out: &mut String) -> std::fmt::Result {
let name = match self.op {
Opcode::Crand => "crand",
Opcode::Crandc => "crandc",
@ -1824,7 +1872,8 @@ impl Ins {
Opcode::Crxor => "crxor",
_ => disasm_unreachable!(self.code),
};
format!(
write!(
out,
"{} crb{}, crb{}, crb{}",
name,
self.crb_d(),
@ -1833,7 +1882,7 @@ impl Ins {
)
}
fn to_string_form_reg23(&self) -> String {
fn write_string_form_reg23(&self, out: &mut String) -> std::fmt::Result {
let name = match self.op {
Opcode::Dcbf => "dcbf",
Opcode::Dcbi => "dcbi",
@ -1845,10 +1894,10 @@ impl Ins {
Opcode::Icbi => "icbi",
_ => disasm_unreachable!(self.code),
};
format!("{} r{}, r{}", name, self.a(), self.b())
write!(out, "{} r{}, r{}", name, self.a(), self.b())
}
fn to_string_form_reg213(&self) -> String {
fn write_string_form_reg213(&self, out: &mut String) -> std::fmt::Result {
let name_suffix = if self.rc() { "." } else { "" };
let name = match self.op {
Opcode::Eqv => "eqv",
@ -1861,7 +1910,8 @@ impl Ins {
Opcode::Srw => "srw",
_ => disasm_unreachable!(self.code),
};
format!(
write!(
out,
"{}{} r{}, r{}, r{}",
name,
name_suffix,
@ -1871,14 +1921,15 @@ impl Ins {
)
}
fn to_string_rlw_imm(&self) -> String {
fn write_string_rlw_imm(&self, out: &mut String) -> std::fmt::Result {
let name_prefix = if self.rc() { "." } else { "" };
let name = match self.op {
Opcode::Rlwimi => "rlwimi",
Opcode::Rlwinm => "rlwinm",
_ => disasm_unreachable!(self.code),
};
format!(
write!(
out,
"{}{} r{}, r{}, {}, {}, {}",
name,
name_prefix,
@ -1890,10 +1941,11 @@ impl Ins {
)
}
fn to_string_rlw_reg(&self) -> String {
fn write_string_rlw_reg(&self, out: &mut String) -> std::fmt::Result {
assert_eq!(self.op, Opcode::Rlwnm);
let name_prefix = if self.rc() { "." } else { "" };
format!(
write!(
out,
"rlwnm{} r{}, r{}, r{}, {}, {}",
name_prefix,
self.a(),
@ -1904,54 +1956,77 @@ impl Ins {
)
}
fn to_string_form_reg12_nb(&self) -> String {
fn write_string_form_reg12_nb(&self, out: &mut String) -> std::fmt::Result {
let name = match self.op {
Opcode::Lswi => "lswi",
Opcode::Stswi => "stswi",
_ => disasm_unreachable!(self.code),
};
format!("{} r{}, r{}, {}", name, self.d(), self.a(), self.b())
write!(out, "{} r{}, r{}, {}", name, self.d(), self.a(), self.b())
}
fn to_string_form_reg1_spr(&self) -> String {
fn write_string_form_reg1_spr(&self, out: &mut String) -> std::fmt::Result {
let name = match self.op {
Opcode::Mfspr => "mfspr",
Opcode::Mftb => "mftb",
_ => disasm_unreachable!(self.code),
};
format!("{} r{}, {}", name, self.d(), self.spr())
write!(out, "{} r{}, {}", name, self.d(), self.spr())
}
fn to_string_form_spr_reg1(&self) -> String {
fn write_string_form_spr_reg1(&self, out: &mut String) -> std::fmt::Result {
let name = match self.op {
Opcode::Mtspr => "mtspr",
_ => disasm_unreachable!(self.code),
};
format!("{} {}, r{}", name, self.spr(), self.s())
write!(out, "{} {}, r{}", name, self.spr(), self.s())
}
fn to_string_form_reg1_sr(&self) -> String {
fn write_string_form_reg1_sr(&self, out: &mut String) -> std::fmt::Result {
let name = match self.op {
Opcode::Mfsr => "mfsr",
_ => disasm_unreachable!(self.code),
};
format!("{} r{}, {}", name, self.d(), self.sr())
write!(out, "{} r{}, {}", name, self.d(), self.sr())
}
fn to_string_form_sr_reg1(&self) -> String {
fn write_string_form_sr_reg1(&self, out: &mut String) -> std::fmt::Result {
let name = match self.op {
Opcode::Mtsr => "mtsr",
_ => disasm_unreachable!(self.code),
};
format!("{} {}, r{}", name, self.sr(), self.s())
write!(out, "{} {}, r{}", name, self.sr(), self.s())
}
fn to_string_mtcrf(&self) -> String {
fn write_string_mtcrf(&self, out: &mut String) -> std::fmt::Result {
assert_eq!(self.op, Opcode::Mtcrf);
format!("mtcrf {} r{}", self.crm(), self.s())
write!(out, "mtcrf {} r{}", self.crm(), self.s())
}
fn to_string_psq(&self) -> String {
fn write_string_srawi(&self, out: &mut String) -> std::fmt::Result {
assert_eq!(self.op, Opcode::Srawi);
let name_suffix = if self.rc() { "." } else { "" };
write!(
out,
"srawi{} r{}, r{}, {}",
name_suffix,
self.s(),
self.a(),
self.sh()
)
}
fn write_string_tw(&self, out: &mut String) -> std::fmt::Result {
assert_eq!(self.op, Opcode::Tw);
write!(out, "tw {}, r{}, r{}", self.to(), self.a(), self.b())
}
fn write_string_twi(&self, out: &mut String) -> std::fmt::Result {
assert_eq!(self.op, Opcode::Twi);
write!(out, "twi {}, r{}, {}", self.to(), self.a(), self.simm())
}
fn write_string_psq(&self, out: &mut String) -> std::fmt::Result {
let name = match self.op {
Opcode::PsqL => "psq_l",
Opcode::PsqLu => "psq_lu",
@ -1959,7 +2034,8 @@ impl Ins {
Opcode::PsqStu => "psq_stu",
_ => disasm_unreachable!(self.code),
};
format!(
write!(
out,
"{} fr{}, {}(r{}), {}, {}",
name,
self.d(),
@ -1970,7 +2046,7 @@ impl Ins {
)
}
fn to_string_psq_x(&self) -> String {
fn write_string_psq_x(&self, out: &mut String) -> std::fmt::Result {
let name = match self.op {
Opcode::PsqLx => "psq_lx",
Opcode::PsqLux => "psq_lux",
@ -1978,7 +2054,8 @@ impl Ins {
Opcode::PsqStux => "psq_stux",
_ => disasm_unreachable!(self.code),
};
format!(
write!(
out,
"{} fr{}, r{}, r{}, {}, {}",
name,
self.d(),
@ -1988,12 +2065,10 @@ impl Ins {
self.ps_l()
)
}
}
impl ToString for Ins {
fn to_string(&self) -> String {
pub fn write_string(&self, out: &mut String) -> std::fmt::Result {
match self.op {
Opcode::Illegal => "<illegal>".to_string(),
Opcode::Illegal => write!(out, "<illegal>"),
// Standalone instructions
Opcode::Eieio
@ -2001,17 +2076,17 @@ impl ToString for Ins {
| Opcode::Rfi
| Opcode::Sc
| Opcode::Sync
| Opcode::Tlbsync => self.to_string_noargs(),
| Opcode::Tlbsync => self.write_string_noargs(out),
// General purpose register only
Opcode::Mfcr | Opcode::Mfmsr | Opcode::Mtmsr | Opcode::Tlbie => {
self.to_string_form_reg1()
self.write_string_form_reg1(out)
}
Opcode::Addme | Opcode::Addze | Opcode::Neg | Opcode::Subfme | Opcode::Subfze => {
self.to_string_form_reg12_oe_rc()
self.write_string_form_reg12_oe_rc(out)
}
Opcode::Mfsrin | Opcode::Mtsrin => self.to_string_form_reg13(),
Opcode::Cntlzw | Opcode::Extsb | Opcode::Extsh => self.to_string_form_reg21_rc(),
Opcode::Mfsrin | Opcode::Mtsrin => self.write_string_form_reg13(out),
Opcode::Cntlzw | Opcode::Extsb | Opcode::Extsh => self.write_string_form_reg21_rc(out),
Opcode::Dcbf
| Opcode::Dcbi
| Opcode::Dcbst
@ -2019,7 +2094,7 @@ impl ToString for Ins {
| Opcode::Dcbtst
| Opcode::Dcbz
| Opcode::DcbzL
| Opcode::Icbi => self.to_string_form_reg23(),
| Opcode::Icbi => self.write_string_form_reg23(out),
Opcode::Eciwx
| Opcode::Ecowx
| Opcode::Lhaux
@ -2043,9 +2118,9 @@ impl ToString for Ins {
| Opcode::Stwbrx
| Opcode::Stwcx_
| Opcode::Stwx
| Opcode::Stwux => self.to_string_form_reg123(),
| Opcode::Stwux => self.write_string_form_reg123(out),
Opcode::And | Opcode::Andc | Opcode::Mulhw | Opcode::Mulhwu | Opcode::Xor => {
self.to_string_form_reg123_rc()
self.write_string_form_reg123_rc(out)
}
Opcode::Add
| Opcode::Addc
@ -2055,7 +2130,7 @@ impl ToString for Ins {
| Opcode::Mullw
| Opcode::Subf
| Opcode::Subfc
| Opcode::Subfe => self.to_string_form_reg123_oe_rc(),
| Opcode::Subfe => self.write_string_form_reg123_oe_rc(out),
Opcode::Eqv
| Opcode::Nand
| Opcode::Nor
@ -2063,11 +2138,11 @@ impl ToString for Ins {
| Opcode::Orc
| Opcode::Slw
| Opcode::Sraw
| Opcode::Srw => self.to_string_form_reg213(),
| Opcode::Srw => self.write_string_form_reg213(out),
// General purpose shifts
Opcode::Rlwimi | Opcode::Rlwinm => self.to_string_rlw_imm(),
Opcode::Rlwnm => self.to_string_rlw_reg(),
Opcode::Rlwimi | Opcode::Rlwinm => self.write_string_rlw_imm(out),
Opcode::Rlwnm => self.write_string_rlw_reg(out),
// General purpose register misc
Opcode::Addi
@ -2075,13 +2150,13 @@ impl ToString for Ins {
| Opcode::Addic_
| Opcode::Addis
| Opcode::Mulli
| Opcode::Subfic => self.to_string_form_reg12_simm(),
| Opcode::Subfic => self.write_string_form_reg12_simm(out),
Opcode::Andi_
| Opcode::Andis_
| Opcode::Ori
| Opcode::Oris
| Opcode::Xori
| Opcode::Xoris => self.to_string_form_reg12_uimm(),
| Opcode::Xoris => self.write_string_form_reg12_uimm(out),
Opcode::Lbz
| Opcode::Lbzu
| Opcode::Lha
@ -2097,42 +2172,29 @@ impl ToString for Ins {
| Opcode::Sthu
| Opcode::Stmw
| Opcode::Stw
| Opcode::Stwu => self.to_string_form_reg12_offset(),
Opcode::Lswi | Opcode::Stswi => self.to_string_form_reg12_nb(),
Opcode::Mfspr | Opcode::Mftb => self.to_string_form_reg1_spr(),
Opcode::Mtspr => self.to_string_form_spr_reg1(),
Opcode::Mfsr => self.to_string_form_reg1_sr(),
Opcode::Mtsr => self.to_string_form_sr_reg1(),
Opcode::Mtcrf => self.to_string_mtcrf(),
Opcode::Srawi => {
let name_suffix = if self.rc() { "." } else { "" };
format!(
"srawi{} r{}, r{}, {}",
name_suffix,
self.s(),
self.a(),
self.sh()
)
}
Opcode::Tw => {
format!("tw {}, r{}, r{}", self.to(), self.a(), self.b())
}
Opcode::Twi => {
format!("twi {}, r{}, {}", self.to(), self.a(), self.simm())
}
| Opcode::Stwu => self.write_string_form_reg12_offset(out),
Opcode::Lswi | Opcode::Stswi => self.write_string_form_reg12_nb(out),
Opcode::Mfspr | Opcode::Mftb => self.write_string_form_reg1_spr(out),
Opcode::Mtspr => self.write_string_form_spr_reg1(out),
Opcode::Mfsr => self.write_string_form_reg1_sr(out),
Opcode::Mtsr => self.write_string_form_sr_reg1(out),
Opcode::Mtcrf => self.write_string_mtcrf(out),
Opcode::Srawi => self.write_string_srawi(out),
Opcode::Tw => self.write_string_tw(out),
Opcode::Twi => self.write_string_twi(out),
// Branch instructions
Opcode::B => self.to_string_b(),
Opcode::Bc => self.to_string_bc(),
Opcode::Bcctr | Opcode::Bclr => self.to_string_branch_cond_to_reg(),
Opcode::B => self.write_string_b(out),
Opcode::Bc => self.write_string_bc(out),
Opcode::Bcctr | Opcode::Bclr => self.write_string_branch_cond_to_reg(out),
// Compare instructions
Opcode::Cmp | Opcode::Cmpl => self.to_string_cmp(),
Opcode::Cmpi => self.to_string_cmp_simm(),
Opcode::Cmpli => self.to_string_cmp_uimm(),
Opcode::Cmp | Opcode::Cmpl => self.write_string_cmp(out),
Opcode::Cmpi => self.write_string_cmp_simm(out),
Opcode::Cmpli => self.write_string_cmp_uimm(out),
// Floating point register only instructions
Opcode::Mffs => self.to_string_form_fr1(),
Opcode::Mffs => self.write_string_form_fr1(out),
Opcode::Fabs
| Opcode::Fmr
| Opcode::Fnabs
@ -2145,7 +2207,7 @@ impl ToString for Ins {
| Opcode::PsNabs
| Opcode::PsNeg
| Opcode::PsRes
| Opcode::PsRsqrte => self.to_string_form_fr13(),
| Opcode::PsRsqrte => self.write_string_form_fr13(out),
Opcode::Fadd
| Opcode::Fadds
| Opcode::Fdiv
@ -2158,9 +2220,9 @@ impl ToString for Ins {
| Opcode::PsMerge01
| Opcode::PsMerge10
| Opcode::PsMerge11
| Opcode::PsSub => self.to_string_form_fr123(),
| Opcode::PsSub => self.write_string_form_fr123(out),
Opcode::Fmul | Opcode::Fmuls | Opcode::PsMul | Opcode::PsMuls0 | Opcode::PsMuls1 => {
self.to_string_form_fr124()
self.write_string_form_fr124(out)
}
Opcode::Fmadd
| Opcode::Fmadds
@ -2179,16 +2241,16 @@ impl ToString for Ins {
| Opcode::PsNmsub
| Opcode::PsSel
| Opcode::PsSum0
| Opcode::PsSum1 => self.to_string_form_fr1243(),
| Opcode::PsSum1 => self.write_string_form_fr1243(out),
// Floating point register misc instructions
Opcode::Fctiw | Opcode::Fctiwz => self.to_string_form_condreg1_fr13_rc(),
Opcode::Fctiw | Opcode::Fctiwz => self.write_string_form_condreg1_fr13_rc(out),
Opcode::Fcmpo
| Opcode::Fcmpu
| Opcode::PsCmpo0
| Opcode::PsCmpo1
| Opcode::PsCmpu0
| Opcode::PsCmpu1 => self.to_string_form_condreg1_fr23(),
| Opcode::PsCmpu1 => self.write_string_form_condreg1_fr23(out),
Opcode::Lfd
| Opcode::Lfdu
| Opcode::Lfs
@ -2196,7 +2258,7 @@ impl ToString for Ins {
| Opcode::Stfd
| Opcode::Stfdu
| Opcode::Stfs
| Opcode::Stfsu => self.to_string_form_fr1_reg2_offset(),
| Opcode::Stfsu => self.write_string_form_fr1_reg2_offset(out),
Opcode::Lfdux
| Opcode::Lfdx
| Opcode::Lfsux
@ -2205,12 +2267,12 @@ impl ToString for Ins {
| Opcode::Stfdx
| Opcode::Stfiwx
| Opcode::Stfsux
| Opcode::Stfsx => self.to_string_form_fr1_reg23(),
Opcode::Mtfsf => self.to_string_mtfsf(),
| Opcode::Stfsx => self.write_string_form_fr1_reg23(out),
Opcode::Mtfsf => self.write_string_mtfsf(out),
// Condition register only
Opcode::Mcrxr | Opcode::Mtfsb0 | Opcode::Mtfsb1 => self.to_string_form_condreg1(),
Opcode::Mcrf | Opcode::Mcrfs => self.to_string_form_condreg12(),
Opcode::Mcrxr | Opcode::Mtfsb0 | Opcode::Mtfsb1 => self.write_string_form_condreg1(out),
Opcode::Mcrf | Opcode::Mcrfs => self.write_string_form_condreg12(out),
Opcode::Crand
| Opcode::Crandc
| Opcode::Creqv
@ -2218,20 +2280,30 @@ impl ToString for Ins {
| Opcode::Crnor
| Opcode::Cror
| Opcode::Crorc
| Opcode::Crxor => self.to_string_form_condreg123(),
| Opcode::Crxor => self.write_string_form_condreg123(out),
// Condition register misc
Opcode::Mtfsfi => self.to_string_mtfsfi(),
Opcode::Mtfsfi => self.write_string_mtfsfi(out),
// Paired-single instructions
Opcode::PsqL | Opcode::PsqLu | Opcode::PsqSt | Opcode::PsqStu => self.to_string_psq(),
Opcode::PsqL | Opcode::PsqLu | Opcode::PsqSt | Opcode::PsqStu => {
self.write_string_psq(out)
}
Opcode::PsqLx | Opcode::PsqLux | Opcode::PsqStx | Opcode::PsqStux => {
self.to_string_psq_x()
self.write_string_psq_x(out)
}
}
}
}
impl ToString for Ins {
fn to_string(&self) -> String {
let mut s = String::new();
self.write_string(&mut s).unwrap();
s
}
}
#[cfg(test)]
mod tests {
use super::*;
@ -2290,7 +2362,10 @@ mod tests {
fn test_to_string() {
assert_eq!(Ins::disasm(0x4c000000).to_string(), "mcrf crf0, crf0");
assert_eq!(Ins::disasm(0x7c000278).to_string(), "xor r0, r0, r0");
assert_eq!(Ins::disasm(0x10000014).to_string(), "ps_sum0 fr0, fr0, fr0, fr0");
assert_eq!(
Ins::disasm(0x10000014).to_string(),
"ps_sum0 fr0, fr0, fr0, fr0"
);
assert_eq!(Ins::disasm(0x10000032).to_string(), "ps_mul fr0, fr0, fr0");
assert_eq!(Ins::disasm(0x7c00052a).to_string(), "");
}