Implement all print instructions
This commit is contained in:
parent
a08ef23ab6
commit
ae8503b217
537
src/main.rs
537
src/main.rs
|
@ -319,6 +319,7 @@ impl Ins {
|
||||||
ins_bit!(lk, 31);
|
ins_bit!(lk, 31);
|
||||||
ins_bit!(l, 10);
|
ins_bit!(l, 10);
|
||||||
ins_bit!(oe, 21);
|
ins_bit!(oe, 21);
|
||||||
|
ins_bit!(w, 16);
|
||||||
|
|
||||||
// Registers
|
// Registers
|
||||||
ins_field!(s, u8, 6..11);
|
ins_field!(s, u8, 6..11);
|
||||||
|
@ -341,8 +342,15 @@ impl Ins {
|
||||||
ins_field!(uimm, u16, 16..32);
|
ins_field!(uimm, u16, 16..32);
|
||||||
ins_field!(bo, u8, 6..11);
|
ins_field!(bo, u8, 6..11);
|
||||||
ins_field!(bi, u8, 11..16);
|
ins_field!(bi, u8, 11..16);
|
||||||
|
ins_field!(sh, u8, 16..21);
|
||||||
|
ins_field!(mb, u8, 21..26);
|
||||||
|
ins_field!(me, u8, 26..31);
|
||||||
//ins_field!(bd, u16, 16..30);
|
//ins_field!(bd, u16, 16..30);
|
||||||
ins_field!(li, u32, 6..30);
|
ins_field!(li, u32, 6..30);
|
||||||
|
ins_field!(to, u8, 6..11);
|
||||||
|
// Paired-single fields.
|
||||||
|
ins_field!(ps_l, u8, 17..20);
|
||||||
|
ins_field!(ps_d, u16, 20..32);
|
||||||
|
|
||||||
fn disasm(x: u32) -> Self {
|
fn disasm(x: u32) -> Self {
|
||||||
let family = bits(x, 0..6);
|
let family = bits(x, 0..6);
|
||||||
|
@ -1371,6 +1379,38 @@ impl Ins {
|
||||||
(true, false) => "mullwuo",
|
(true, false) => "mullwuo",
|
||||||
(true, true) => "mullwuo.",
|
(true, true) => "mullwuo.",
|
||||||
},
|
},
|
||||||
|
Opcode::Stbux => "stbux",
|
||||||
|
Opcode::Stbx => "stbx",
|
||||||
|
Opcode::Sthux => "sthux",
|
||||||
|
Opcode::Sthx => "sthx",
|
||||||
|
Opcode::Sthbrx => "sthbrx",
|
||||||
|
Opcode::Stswi => "stswx",
|
||||||
|
Opcode::Stwbrx => "stwbrx",
|
||||||
|
Opcode::Stwcx_ => "stwcx.",
|
||||||
|
Opcode::Stwx => "stwx",
|
||||||
|
Opcode::Stwux => "stwux",
|
||||||
|
Opcode::Subf => match (self.oe(), self.rc()) {
|
||||||
|
(false, false) => "subfu",
|
||||||
|
(false, true) => "subfu.",
|
||||||
|
(true, false) => "subfo",
|
||||||
|
(true, true) => "subfo.",
|
||||||
|
},
|
||||||
|
Opcode::Subfc => match (self.oe(), self.rc()) {
|
||||||
|
(false, false) => "subfcu",
|
||||||
|
(false, true) => "subfcu.",
|
||||||
|
(true, false) => "subfco",
|
||||||
|
(true, true) => "subfco.",
|
||||||
|
},
|
||||||
|
Opcode::Subfe => match (self.oe(), self.rc()) {
|
||||||
|
(false, false) => "subfeu",
|
||||||
|
(false, true) => "subfeu.",
|
||||||
|
(true, false) => "subfeo",
|
||||||
|
(true, true) => "subfeo.",
|
||||||
|
},
|
||||||
|
Opcode::Xor => match self.rc() {
|
||||||
|
false => "xor",
|
||||||
|
true => "xor.",
|
||||||
|
},
|
||||||
_ => disasm_unreachable!(self.code),
|
_ => disasm_unreachable!(self.code),
|
||||||
};
|
};
|
||||||
format!("{} r{}, r{}, r{}", name, self.d(), self.a(), self.b())
|
format!("{} r{}, r{}, r{}", name, self.d(), self.a(), self.b())
|
||||||
|
@ -1380,6 +1420,10 @@ impl Ins {
|
||||||
match self.op {
|
match self.op {
|
||||||
Opcode::Eieio => "eieio",
|
Opcode::Eieio => "eieio",
|
||||||
Opcode::Isync => "isync",
|
Opcode::Isync => "isync",
|
||||||
|
Opcode::Rfi => "rfi",
|
||||||
|
Opcode::Sc => "sc",
|
||||||
|
Opcode::Sync => "sync",
|
||||||
|
Opcode::Tlbsync => "tlbsync",
|
||||||
_ => disasm_unreachable!(self.code),
|
_ => disasm_unreachable!(self.code),
|
||||||
}
|
}
|
||||||
.to_owned()
|
.to_owned()
|
||||||
|
@ -1392,6 +1436,7 @@ impl Ins {
|
||||||
Opcode::Addic_ => "addic.",
|
Opcode::Addic_ => "addic.",
|
||||||
Opcode::Addis => "addis",
|
Opcode::Addis => "addis",
|
||||||
Opcode::Mulli => "mulli",
|
Opcode::Mulli => "mulli",
|
||||||
|
Opcode::Subfic => "subfic",
|
||||||
_ => disasm_unreachable!(self.code),
|
_ => disasm_unreachable!(self.code),
|
||||||
};
|
};
|
||||||
format!("{} r{}, r{}, {}", name, self.d(), self.a(), self.simm())
|
format!("{} r{}, r{}, {}", name, self.d(), self.a(), self.simm())
|
||||||
|
@ -1403,6 +1448,8 @@ impl Ins {
|
||||||
Opcode::Andis_ => "andis.",
|
Opcode::Andis_ => "andis.",
|
||||||
Opcode::Ori => "ori",
|
Opcode::Ori => "ori",
|
||||||
Opcode::Oris => "oris",
|
Opcode::Oris => "oris",
|
||||||
|
Opcode::Xori => "xori",
|
||||||
|
Opcode::Xoris => "xoris",
|
||||||
_ => disasm_unreachable!(self.code),
|
_ => disasm_unreachable!(self.code),
|
||||||
};
|
};
|
||||||
format!("{} r{}, r{}, {}", name, self.d(), self.a(), self.uimm())
|
format!("{} r{}, r{}, {}", name, self.d(), self.a(), self.uimm())
|
||||||
|
@ -1419,6 +1466,13 @@ impl Ins {
|
||||||
Opcode::Lmw => "lmw",
|
Opcode::Lmw => "lmw",
|
||||||
Opcode::Lwz => "lwz",
|
Opcode::Lwz => "lwz",
|
||||||
Opcode::Lwzu => "lwzu",
|
Opcode::Lwzu => "lwzu",
|
||||||
|
Opcode::Stb => "stb",
|
||||||
|
Opcode::Stbu => "stbu",
|
||||||
|
Opcode::Sth => "sth",
|
||||||
|
Opcode::Sthu => "sthu",
|
||||||
|
Opcode::Stmw => "stmw",
|
||||||
|
Opcode::Stw => "stw",
|
||||||
|
Opcode::Stwu => "stwu",
|
||||||
_ => disasm_unreachable!(self.code),
|
_ => disasm_unreachable!(self.code),
|
||||||
};
|
};
|
||||||
format!("{} r{}, {}(r{})", name, self.d(), self.simm(), self.a())
|
format!("{} r{}, {}(r{})", name, self.d(), self.simm(), self.a())
|
||||||
|
@ -1430,6 +1484,10 @@ impl Ins {
|
||||||
Opcode::Lfdu => "lfdu",
|
Opcode::Lfdu => "lfdu",
|
||||||
Opcode::Lfs => "lfs",
|
Opcode::Lfs => "lfs",
|
||||||
Opcode::Lfsu => "lfsu",
|
Opcode::Lfsu => "lfsu",
|
||||||
|
Opcode::Stfd => "stfd",
|
||||||
|
Opcode::Stfdu => "stfdu",
|
||||||
|
Opcode::Stfs => "stfs",
|
||||||
|
Opcode::Stfsu => "stfsu",
|
||||||
_ => disasm_unreachable!(self.code),
|
_ => disasm_unreachable!(self.code),
|
||||||
};
|
};
|
||||||
format!("{} fr{}, {}(r{})", name, self.d(), self.simm(), self.a())
|
format!("{} fr{}, {}(r{})", name, self.d(), self.simm(), self.a())
|
||||||
|
@ -1441,6 +1499,11 @@ impl Ins {
|
||||||
Opcode::Lfdx => "lfdx",
|
Opcode::Lfdx => "lfdx",
|
||||||
Opcode::Lfsux => "lfsux",
|
Opcode::Lfsux => "lfsux",
|
||||||
Opcode::Lfsx => "lfsx",
|
Opcode::Lfsx => "lfsx",
|
||||||
|
Opcode::Stfdux => "stfdux",
|
||||||
|
Opcode::Stfdx => "stfdx",
|
||||||
|
Opcode::Stfiwx => "stfiwx",
|
||||||
|
Opcode::Stfsux => "stfsux",
|
||||||
|
Opcode::Stfsx => "stfsx",
|
||||||
_ => disasm_unreachable!(self.code),
|
_ => disasm_unreachable!(self.code),
|
||||||
};
|
};
|
||||||
format!("{} fr{}, r{}, r{}", name, self.d(), self.a(), self.b())
|
format!("{} fr{}, r{}, r{}", name, self.d(), self.a(), self.b())
|
||||||
|
@ -1472,6 +1535,7 @@ impl Ins {
|
||||||
Opcode::Mfcr => "mfcr",
|
Opcode::Mfcr => "mfcr",
|
||||||
Opcode::Mfmsr => "mfmsr",
|
Opcode::Mfmsr => "mfmsr",
|
||||||
Opcode::Mtmsr => "mtmsr",
|
Opcode::Mtmsr => "mtmsr",
|
||||||
|
Opcode::Tlbie => "tblie",
|
||||||
_ => disasm_unreachable!(self.code),
|
_ => disasm_unreachable!(self.code),
|
||||||
};
|
};
|
||||||
format!("{} r{}", name, self.d())
|
format!("{} r{}", name, self.d())
|
||||||
|
@ -1497,6 +1561,18 @@ impl Ins {
|
||||||
(true, false) => "nego",
|
(true, false) => "nego",
|
||||||
(true, true) => "nego.",
|
(true, true) => "nego.",
|
||||||
},
|
},
|
||||||
|
Opcode::Subfme => match (self.oe(), self.rc()) {
|
||||||
|
(false, false) => "subfme",
|
||||||
|
(false, true) => "subfme.",
|
||||||
|
(true, false) => "subfmeo",
|
||||||
|
(true, true) => "subfmeo.",
|
||||||
|
},
|
||||||
|
Opcode::Subfze => match (self.oe(), self.rc()) {
|
||||||
|
(false, false) => "subfze",
|
||||||
|
(false, true) => "subfze.",
|
||||||
|
(true, false) => "subfzeo",
|
||||||
|
(true, true) => "subfzeo.",
|
||||||
|
},
|
||||||
_ => disasm_unreachable!(self.code),
|
_ => disasm_unreachable!(self.code),
|
||||||
};
|
};
|
||||||
format!("{} r{}, r{}", name, self.d(), self.a())
|
format!("{} r{}, r{}", name, self.d(), self.a())
|
||||||
|
@ -1542,114 +1618,81 @@ impl Ins {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_string_form_fr13(&self) -> String {
|
fn to_string_form_fr13(&self) -> String {
|
||||||
|
let name_suffix = if self.rc() { "." } else { "" };
|
||||||
let name = match self.op {
|
let name = match self.op {
|
||||||
Opcode::Fabs => match self.rc() {
|
Opcode::Fabs => "fabs",
|
||||||
false => "fabs",
|
Opcode::Fnabs => "fnabs",
|
||||||
true => "fabs.",
|
Opcode::Fmr => "fmr",
|
||||||
},
|
Opcode::Fneg => "fneg",
|
||||||
Opcode::Fnabs => match self.rc() {
|
Opcode::Fres => "fres",
|
||||||
false => "fnabs",
|
Opcode::Frsp => "frsp",
|
||||||
true => "fnabs.",
|
Opcode::Frsqrte => "frsqrte",
|
||||||
},
|
Opcode::PsAbs => "ps_abs",
|
||||||
Opcode::Fmr => match self.rc() {
|
Opcode::PsMr => "ps_mr",
|
||||||
false => "fmr",
|
Opcode::PsNabs => "ps_nabs",
|
||||||
true => "fmr.",
|
Opcode::PsNeg => "ps_neg",
|
||||||
},
|
Opcode::PsRes => "ps_res",
|
||||||
Opcode::Fneg => match self.rc() {
|
Opcode::PsRsqrte => "ps_rsqrte",
|
||||||
false => "fneg",
|
Opcode::PsSum0 => "ps_sum0",
|
||||||
true => "fneg.",
|
Opcode::PsSum1 => "ps_sum1",
|
||||||
},
|
|
||||||
Opcode::Fres => match self.rc() {
|
|
||||||
false => "fres",
|
|
||||||
true => "fres.",
|
|
||||||
},
|
|
||||||
Opcode::Frsp => match self.rc() {
|
|
||||||
false => "frsp",
|
|
||||||
true => "frsp.",
|
|
||||||
},
|
|
||||||
Opcode::Frsqrte => match self.rc() {
|
|
||||||
false => "frsqrte",
|
|
||||||
true => "frsqrte.",
|
|
||||||
},
|
|
||||||
_ => disasm_unreachable!(self.code),
|
_ => disasm_unreachable!(self.code),
|
||||||
};
|
};
|
||||||
format!("{} fr{}, fr{}", name, self.d(), self.b())
|
format!("{}{} fr{}, fr{}", name, name_suffix, self.d(), self.b())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_string_form_fr123(&self) -> String {
|
fn to_string_form_fr123(&self) -> String {
|
||||||
|
let name_suffix = if self.rc() { "." } else { "" };
|
||||||
let name = match self.op {
|
let name = match self.op {
|
||||||
Opcode::Fadd => match self.rc() {
|
Opcode::Fadd => "fadd",
|
||||||
false => "fadd",
|
Opcode::Fadds => "fadds",
|
||||||
true => "fadd.",
|
Opcode::Fdiv => "fdiv",
|
||||||
},
|
Opcode::Fdivs => "fdivs",
|
||||||
Opcode::Fadds => match self.rc() {
|
Opcode::Fsub => "fsub",
|
||||||
false => "fadds",
|
Opcode::Fsubs => "fsubs",
|
||||||
true => "fadds.",
|
Opcode::PsAdd => "ps_add",
|
||||||
},
|
Opcode::PsDiv => "ps_div",
|
||||||
Opcode::Fdiv => match self.rc() {
|
Opcode::PsMerge00 => "ps_merge00",
|
||||||
false => "fdiv",
|
Opcode::PsMerge01 => "ps_merge01",
|
||||||
true => "fdiv.",
|
Opcode::PsMerge10 => "ps_merge10",
|
||||||
},
|
Opcode::PsMerge11 => "ps_merge11",
|
||||||
Opcode::Fdivs => match self.rc() {
|
Opcode::PsSub => "ps_sub",
|
||||||
false => "fdivs",
|
|
||||||
true => "fdivs.",
|
|
||||||
},
|
|
||||||
Opcode::Fsub => match self.rc() {
|
|
||||||
false => "fsub",
|
|
||||||
true => "fsub.",
|
|
||||||
},
|
|
||||||
Opcode::Fsubs => match self.rc() {
|
|
||||||
false => "fsubs",
|
|
||||||
true => "fsubs.",
|
|
||||||
},
|
|
||||||
_ => disasm_unreachable!(self.code),
|
|
||||||
};
|
|
||||||
format!("{} fr{}, fr{}, fr{}", name, self.d(), self.a(), self.b())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_string_form_fr1243(&self) -> String {
|
|
||||||
let name = match self.op {
|
|
||||||
Opcode::Fmadd => match self.rc() {
|
|
||||||
false => "fmadd",
|
|
||||||
true => "fmadd.",
|
|
||||||
},
|
|
||||||
Opcode::Fmadds => match self.rc() {
|
|
||||||
false => "fmadds",
|
|
||||||
true => "fmadds.",
|
|
||||||
},
|
|
||||||
Opcode::Fmsub => match self.rc() {
|
|
||||||
false => "fmsub",
|
|
||||||
true => "fmsub.",
|
|
||||||
},
|
|
||||||
Opcode::Fmsubs => match self.rc() {
|
|
||||||
false => "fmsubs",
|
|
||||||
true => "fmsubs.",
|
|
||||||
},
|
|
||||||
Opcode::Fnmadd => match self.rc() {
|
|
||||||
false => "fnmadd",
|
|
||||||
true => "fnmadd.",
|
|
||||||
},
|
|
||||||
Opcode::Fnmadds => match self.rc() {
|
|
||||||
false => "fnmadds",
|
|
||||||
true => "fnmadds.",
|
|
||||||
},
|
|
||||||
Opcode::Fnmsub => match self.rc() {
|
|
||||||
false => "fnmsub",
|
|
||||||
true => "fnmsub.",
|
|
||||||
},
|
|
||||||
Opcode::Fnmsubs => match self.rc() {
|
|
||||||
false => "fnmsubs",
|
|
||||||
true => "fnmsubs.",
|
|
||||||
},
|
|
||||||
Opcode::Fsel => match self.rc() {
|
|
||||||
false => "fsel",
|
|
||||||
true => "fsel.",
|
|
||||||
},
|
|
||||||
_ => disasm_unreachable!(self.code),
|
_ => disasm_unreachable!(self.code),
|
||||||
};
|
};
|
||||||
format!(
|
format!(
|
||||||
"{} fr{}, fr{}, fr{}, fr{}",
|
"{}{} fr{}, fr{}, fr{}",
|
||||||
name,
|
name,
|
||||||
|
name_suffix,
|
||||||
|
self.d(),
|
||||||
|
self.a(),
|
||||||
|
self.b()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_string_form_fr1243(&self) -> String {
|
||||||
|
let name_suffix = if self.rc() { "." } else { "" };
|
||||||
|
let name = match self.op {
|
||||||
|
Opcode::Fmadd => "fmadd",
|
||||||
|
Opcode::Fmadds => "fmadds",
|
||||||
|
Opcode::Fmsub => "fmsub",
|
||||||
|
Opcode::Fmsubs => "fmsubs",
|
||||||
|
Opcode::Fnmadd => "fnmadd",
|
||||||
|
Opcode::Fnmadds => "fnmadds",
|
||||||
|
Opcode::Fnmsub => "fnmsub",
|
||||||
|
Opcode::Fnmsubs => "fnmsubs",
|
||||||
|
Opcode::Fsel => "fsel",
|
||||||
|
Opcode::PsMadd => "ps_madd",
|
||||||
|
Opcode::PsMadds0 => "ps_madds0",
|
||||||
|
Opcode::PsMadds1 => "ps_madds1",
|
||||||
|
Opcode::PsMsub => "ps_msub",
|
||||||
|
Opcode::PsNmadd => "ps_nmadd",
|
||||||
|
Opcode::PsNmsub => "ps_nmsub",
|
||||||
|
Opcode::PsSel => "ps_sel",
|
||||||
|
_ => disasm_unreachable!(self.code),
|
||||||
|
};
|
||||||
|
format!(
|
||||||
|
"{}{} fr{}, fr{}, fr{}, fr{}",
|
||||||
|
name,
|
||||||
|
name_suffix,
|
||||||
self.d(),
|
self.d(),
|
||||||
self.a(),
|
self.a(),
|
||||||
self.c(),
|
self.c(),
|
||||||
|
@ -1658,24 +1701,33 @@ impl Ins {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_string_form_fr124(&self) -> String {
|
fn to_string_form_fr124(&self) -> String {
|
||||||
|
let name_suffix = if self.rc() { "." } else { "" };
|
||||||
let name = match self.op {
|
let name = match self.op {
|
||||||
Opcode::Fmul => match self.rc() {
|
Opcode::Fmul => "fmul",
|
||||||
false => "fmul",
|
Opcode::Fmuls => "fmuls",
|
||||||
true => "fmul.",
|
Opcode::PsMadd => "ps_madd",
|
||||||
},
|
Opcode::PsMuls0 => "ps_muls0",
|
||||||
Opcode::Fmuls => match self.rc() {
|
Opcode::PsMuls1 => "ps_muls1",
|
||||||
false => "fmuls",
|
|
||||||
true => "fmuls.",
|
|
||||||
},
|
|
||||||
_ => disasm_unreachable!(self.code),
|
_ => disasm_unreachable!(self.code),
|
||||||
};
|
};
|
||||||
format!("{} fr{}, fr{}, fr{}", name, self.d(), self.a(), self.c())
|
format!(
|
||||||
|
"{}{} fr{}, fr{}, fr{}",
|
||||||
|
name,
|
||||||
|
name_suffix,
|
||||||
|
self.d(),
|
||||||
|
self.a(),
|
||||||
|
self.c()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_string_form_condreg1_fr23(&self) -> String {
|
fn to_string_form_condreg1_fr23(&self) -> String {
|
||||||
let name = match self.op {
|
let name = match self.op {
|
||||||
Opcode::Fcmpo => "fcmpo",
|
Opcode::Fcmpo => "fcmpo",
|
||||||
Opcode::Fcmpu => "fcmpu",
|
Opcode::Fcmpu => "fcmpu",
|
||||||
|
Opcode::PsCmpo0 => "ps_cmpo0",
|
||||||
|
Opcode::PsCmpo1 => "ps_cmpo1",
|
||||||
|
Opcode::PsCmpu0 => "ps_cmpu0",
|
||||||
|
Opcode::PsCmpu1 => "ps_cmpu1",
|
||||||
_ => disasm_unreachable!(self.code),
|
_ => disasm_unreachable!(self.code),
|
||||||
};
|
};
|
||||||
format!(
|
format!(
|
||||||
|
@ -1853,35 +1905,65 @@ impl Ins {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_string_form_reg213(&self) -> String {
|
fn to_string_form_reg213(&self) -> String {
|
||||||
|
let name_suffix = if self.rc() { "." } else { "" };
|
||||||
let name = match self.op {
|
let name = match self.op {
|
||||||
Opcode::Eqv => match self.rc() {
|
Opcode::Eqv => "eqv",
|
||||||
false => "eqv",
|
Opcode::Nand => "nand",
|
||||||
true => "eqv.",
|
Opcode::Nor => "nor",
|
||||||
},
|
Opcode::Or => "or",
|
||||||
Opcode::Nand => match self.rc() {
|
Opcode::Orc => "orc",
|
||||||
false => "nand",
|
Opcode::Slw => "slw",
|
||||||
true => "nand.",
|
Opcode::Sraw => "sraw",
|
||||||
},
|
Opcode::Srw => "srw",
|
||||||
Opcode::Nor => match self.rc() {
|
|
||||||
false => "nor",
|
|
||||||
true => "nor.",
|
|
||||||
},
|
|
||||||
Opcode::Or => match self.rc() {
|
|
||||||
false => "or",
|
|
||||||
true => "or.",
|
|
||||||
},
|
|
||||||
Opcode::Orc => match self.rc() {
|
|
||||||
false => "orc",
|
|
||||||
true => "orc.",
|
|
||||||
},
|
|
||||||
_ => disasm_unreachable!(self.code),
|
_ => disasm_unreachable!(self.code),
|
||||||
};
|
};
|
||||||
format!("{} r{}, r{}, r{}", name, self.a(), self.s(), self.b())
|
format!(
|
||||||
|
"{}{} r{}, r{}, r{}",
|
||||||
|
name,
|
||||||
|
name_suffix,
|
||||||
|
self.a(),
|
||||||
|
self.s(),
|
||||||
|
self.b()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_string_rlw_imm(&self) -> String {
|
||||||
|
let name_prefix = if self.rc() { "." } else { "" };
|
||||||
|
let name = match self.op {
|
||||||
|
Opcode::Rlwimi => "rlwimi",
|
||||||
|
Opcode::Rlwinm => "rlwinm",
|
||||||
|
_ => disasm_unreachable!(self.code),
|
||||||
|
};
|
||||||
|
format!(
|
||||||
|
"{}{} r{}, r{}, {}, {}, {}",
|
||||||
|
name,
|
||||||
|
name_prefix,
|
||||||
|
self.a(),
|
||||||
|
self.s(),
|
||||||
|
self.sh(),
|
||||||
|
self.mb(),
|
||||||
|
self.me()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_string_rlw_reg(&self) -> String {
|
||||||
|
assert_eq!(self.op, Opcode::Rlwnm);
|
||||||
|
let name_prefix = if self.rc() { "." } else { "" };
|
||||||
|
format!(
|
||||||
|
"rlwnm{} r{}, r{}, r{}, {}, {}",
|
||||||
|
name_prefix,
|
||||||
|
self.a(),
|
||||||
|
self.s(),
|
||||||
|
self.b(),
|
||||||
|
self.mb(),
|
||||||
|
self.me()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_string_form_reg12_nb(&self) -> String {
|
fn to_string_form_reg12_nb(&self) -> String {
|
||||||
let name = match self.op {
|
let name = match self.op {
|
||||||
Opcode::Lswi => "lswi",
|
Opcode::Lswi => "lswi",
|
||||||
|
Opcode::Stswi => "stswi",
|
||||||
_ => disasm_unreachable!(self.code),
|
_ => disasm_unreachable!(self.code),
|
||||||
};
|
};
|
||||||
format!("{} r{}, r{}, {}", name, self.d(), self.a(), self.b())
|
format!("{} r{}, r{}, {}", name, self.d(), self.a(), self.b())
|
||||||
|
@ -1924,6 +2006,44 @@ impl Ins {
|
||||||
assert_eq!(self.op, Opcode::Mtcrf);
|
assert_eq!(self.op, Opcode::Mtcrf);
|
||||||
format!("mtcrf {} r{}", self.crm(), self.s())
|
format!("mtcrf {} r{}", self.crm(), self.s())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn to_string_psq(&self) -> String {
|
||||||
|
let name = match self.op {
|
||||||
|
Opcode::PsqL => "psq_l",
|
||||||
|
Opcode::PsqLu => "psq_lu",
|
||||||
|
Opcode::PsqSt => "psq_st",
|
||||||
|
Opcode::PsqStu => "psq_stu",
|
||||||
|
_ => disasm_unreachable!(self.code),
|
||||||
|
};
|
||||||
|
format!(
|
||||||
|
"{} fr{}, {}(r{}), {}, {}",
|
||||||
|
name,
|
||||||
|
self.d(),
|
||||||
|
self.ps_d(),
|
||||||
|
self.a(),
|
||||||
|
self.w(),
|
||||||
|
self.ps_l()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn to_string_psq_x(&self) -> String {
|
||||||
|
let name = match self.op {
|
||||||
|
Opcode::PsqLx => "psq_lx",
|
||||||
|
Opcode::PsqLux => "psq_lux",
|
||||||
|
Opcode::PsqStx => "psq_stx",
|
||||||
|
Opcode::PsqStux => "psq_stux",
|
||||||
|
_ => disasm_unreachable!(self.code),
|
||||||
|
};
|
||||||
|
format!(
|
||||||
|
"{} fr{}, r{}, r{}, {}, {}",
|
||||||
|
name,
|
||||||
|
self.d(),
|
||||||
|
self.a(),
|
||||||
|
self.b(),
|
||||||
|
self.w(),
|
||||||
|
self.ps_l()
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToString for Ins {
|
impl ToString for Ins {
|
||||||
|
@ -1932,11 +2052,20 @@ impl ToString for Ins {
|
||||||
Opcode::Illegal => "<illegal>".to_string(),
|
Opcode::Illegal => "<illegal>".to_string(),
|
||||||
|
|
||||||
// Standalone instructions
|
// Standalone instructions
|
||||||
Opcode::Eieio | Opcode::Isync => self.to_string_noargs(),
|
Opcode::Eieio
|
||||||
|
| Opcode::Isync
|
||||||
|
| Opcode::Rfi
|
||||||
|
| Opcode::Sc
|
||||||
|
| Opcode::Sync
|
||||||
|
| Opcode::Tlbsync => self.to_string_noargs(),
|
||||||
|
|
||||||
// General purpose register only
|
// General purpose register only
|
||||||
Opcode::Mfcr | Opcode::Mfmsr | Opcode::Mtmsr => self.to_string_form_reg1(),
|
Opcode::Mfcr | Opcode::Mfmsr | Opcode::Mtmsr | Opcode::Tlbie => {
|
||||||
Opcode::Addme | Opcode::Addze | Opcode::Neg => self.to_string_form_reg12(),
|
self.to_string_form_reg1()
|
||||||
|
}
|
||||||
|
Opcode::Addme | Opcode::Addze | Opcode::Neg | Opcode::Subfme | Opcode::Subfze => {
|
||||||
|
self.to_string_form_reg12()
|
||||||
|
}
|
||||||
Opcode::Mfsrin | Opcode::Mtsrin => self.to_string_form_reg13(),
|
Opcode::Mfsrin | Opcode::Mtsrin => self.to_string_form_reg13(),
|
||||||
Opcode::Cntlzw | Opcode::Extsb | Opcode::Extsh => self.to_string_form_reg21(),
|
Opcode::Cntlzw | Opcode::Extsb | Opcode::Extsh => self.to_string_form_reg21(),
|
||||||
Opcode::Dcbf
|
Opcode::Dcbf
|
||||||
|
@ -1970,18 +2099,47 @@ impl ToString for Ins {
|
||||||
| Opcode::Lwzx
|
| Opcode::Lwzx
|
||||||
| Opcode::Mulhw
|
| Opcode::Mulhw
|
||||||
| Opcode::Mulhwu
|
| Opcode::Mulhwu
|
||||||
| Opcode::Mullw => self.to_string_form_reg123(),
|
| Opcode::Mullw
|
||||||
Opcode::Eqv | Opcode::Nand | Opcode::Nor | Opcode::Or | Opcode::Orc => {
|
| Opcode::Stbx
|
||||||
self.to_string_form_reg213()
|
| Opcode::Stbux
|
||||||
}
|
| Opcode::Sthbrx
|
||||||
|
| Opcode::Sthx
|
||||||
|
| Opcode::Sthux
|
||||||
|
| Opcode::Stswx
|
||||||
|
| Opcode::Stwbrx
|
||||||
|
| Opcode::Stwcx_
|
||||||
|
| Opcode::Stwx
|
||||||
|
| Opcode::Stwux
|
||||||
|
| Opcode::Subf
|
||||||
|
| Opcode::Subfc
|
||||||
|
| Opcode::Subfe
|
||||||
|
| Opcode::Xor => self.to_string_form_reg123(),
|
||||||
|
Opcode::Eqv
|
||||||
|
| Opcode::Nand
|
||||||
|
| Opcode::Nor
|
||||||
|
| Opcode::Or
|
||||||
|
| Opcode::Orc
|
||||||
|
| Opcode::Slw
|
||||||
|
| Opcode::Sraw
|
||||||
|
| Opcode::Srw => self.to_string_form_reg213(),
|
||||||
|
|
||||||
|
// General purpose shifts
|
||||||
|
Opcode::Rlwimi | Opcode::Rlwinm => self.to_string_rlw_imm(),
|
||||||
|
Opcode::Rlwnm => self.to_string_rlw_reg(),
|
||||||
|
|
||||||
// General purpose register misc
|
// General purpose register misc
|
||||||
Opcode::Addi | Opcode::Addic | Opcode::Addic_ | Opcode::Addis | Opcode::Mulli => {
|
Opcode::Addi
|
||||||
self.to_string_form_reg12_simm()
|
| Opcode::Addic
|
||||||
}
|
| Opcode::Addic_
|
||||||
Opcode::Andi_ | Opcode::Andis_ | Opcode::Ori | Opcode::Oris => {
|
| Opcode::Addis
|
||||||
self.to_string_form_reg12_uimm()
|
| Opcode::Mulli
|
||||||
}
|
| Opcode::Subfic => self.to_string_form_reg12_simm(),
|
||||||
|
Opcode::Andi_
|
||||||
|
| Opcode::Andis_
|
||||||
|
| Opcode::Ori
|
||||||
|
| Opcode::Oris
|
||||||
|
| Opcode::Xori
|
||||||
|
| Opcode::Xoris => self.to_string_form_reg12_uimm(),
|
||||||
Opcode::Lbz
|
Opcode::Lbz
|
||||||
| Opcode::Lbzu
|
| Opcode::Lbzu
|
||||||
| Opcode::Lha
|
| Opcode::Lha
|
||||||
|
@ -1990,13 +2148,36 @@ impl ToString for Ins {
|
||||||
| Opcode::Lhzu
|
| Opcode::Lhzu
|
||||||
| Opcode::Lmw
|
| Opcode::Lmw
|
||||||
| Opcode::Lwz
|
| Opcode::Lwz
|
||||||
| Opcode::Lwzu => self.to_string_form_reg12_offset(),
|
| Opcode::Lwzu
|
||||||
Opcode::Lswi => self.to_string_form_reg12_nb(),
|
| Opcode::Stb
|
||||||
|
| Opcode::Stbu
|
||||||
|
| Opcode::Sth
|
||||||
|
| 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::Mfspr | Opcode::Mftb => self.to_string_form_reg1_spr(),
|
||||||
Opcode::Mtspr => self.to_string_form_spr_reg1(),
|
Opcode::Mtspr => self.to_string_form_spr_reg1(),
|
||||||
Opcode::Mfsr => self.to_string_form_reg1_sr(),
|
Opcode::Mfsr => self.to_string_form_reg1_sr(),
|
||||||
Opcode::Mtsr => self.to_string_form_sr_reg1(),
|
Opcode::Mtsr => self.to_string_form_sr_reg1(),
|
||||||
Opcode::Mtcrf => self.to_string_mtcrf(),
|
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())
|
||||||
|
}
|
||||||
|
|
||||||
// Branch instructions
|
// Branch instructions
|
||||||
Opcode::B => self.to_string_b(),
|
Opcode::B => self.to_string_b(),
|
||||||
|
@ -2016,14 +2197,29 @@ impl ToString for Ins {
|
||||||
| Opcode::Fneg
|
| Opcode::Fneg
|
||||||
| Opcode::Fres
|
| Opcode::Fres
|
||||||
| Opcode::Frsp
|
| Opcode::Frsp
|
||||||
| Opcode::Frsqrte => self.to_string_form_fr13(),
|
| Opcode::Frsqrte
|
||||||
|
| Opcode::PsAbs
|
||||||
|
| Opcode::PsMr
|
||||||
|
| Opcode::PsNabs
|
||||||
|
| Opcode::PsNeg
|
||||||
|
| Opcode::PsRes
|
||||||
|
| Opcode::PsRsqrte => self.to_string_form_fr13(),
|
||||||
Opcode::Fadd
|
Opcode::Fadd
|
||||||
| Opcode::Fadds
|
| Opcode::Fadds
|
||||||
| Opcode::Fdiv
|
| Opcode::Fdiv
|
||||||
| Opcode::Fdivs
|
| Opcode::Fdivs
|
||||||
| Opcode::Fsub
|
| Opcode::Fsub
|
||||||
| Opcode::Fsubs => self.to_string_form_fr123(),
|
| Opcode::Fsubs
|
||||||
Opcode::Fmul | Opcode::Fmuls => self.to_string_form_fr124(),
|
| Opcode::PsAdd
|
||||||
|
| Opcode::PsDiv
|
||||||
|
| Opcode::PsMerge00
|
||||||
|
| Opcode::PsMerge01
|
||||||
|
| Opcode::PsMerge10
|
||||||
|
| Opcode::PsMerge11
|
||||||
|
| Opcode::PsSub => self.to_string_form_fr123(),
|
||||||
|
Opcode::Fmul | Opcode::Fmuls | Opcode::PsMul | Opcode::PsMuls0 | Opcode::PsMuls1 => {
|
||||||
|
self.to_string_form_fr124()
|
||||||
|
}
|
||||||
Opcode::Fmadd
|
Opcode::Fmadd
|
||||||
| Opcode::Fmadds
|
| Opcode::Fmadds
|
||||||
| Opcode::Fmsub
|
| Opcode::Fmsub
|
||||||
|
@ -2032,17 +2228,42 @@ impl ToString for Ins {
|
||||||
| Opcode::Fnmadds
|
| Opcode::Fnmadds
|
||||||
| Opcode::Fnmsub
|
| Opcode::Fnmsub
|
||||||
| Opcode::Fnmsubs
|
| Opcode::Fnmsubs
|
||||||
| Opcode::Fsel => self.to_string_form_fr1243(),
|
| Opcode::Fsel
|
||||||
|
| Opcode::PsMadd
|
||||||
|
| Opcode::PsMadds0
|
||||||
|
| Opcode::PsMadds1
|
||||||
|
| Opcode::PsMsub
|
||||||
|
| Opcode::PsNmadd
|
||||||
|
| Opcode::PsNmsub
|
||||||
|
| Opcode::PsSel
|
||||||
|
| Opcode::PsSum0
|
||||||
|
| Opcode::PsSum1 => self.to_string_form_fr1243(),
|
||||||
|
|
||||||
// Floating point register misc instructions
|
// Floating point register misc instructions
|
||||||
Opcode::Fctiw | Opcode::Fctiwz => self.to_string_form_condreg1_fr13(),
|
Opcode::Fctiw | Opcode::Fctiwz => self.to_string_form_condreg1_fr13(),
|
||||||
Opcode::Fcmpo | Opcode::Fcmpu => self.to_string_form_condreg1_fr23(),
|
Opcode::Fcmpo
|
||||||
Opcode::Lfd | Opcode::Lfdu | Opcode::Lfs | Opcode::Lfsu => {
|
| Opcode::Fcmpu
|
||||||
self.to_string_form_fr1_reg2_offset()
|
| Opcode::PsCmpo0
|
||||||
}
|
| Opcode::PsCmpo1
|
||||||
Opcode::Lfdux | Opcode::Lfdx | Opcode::Lfsux | Opcode::Lfsx => {
|
| Opcode::PsCmpu0
|
||||||
self.to_string_form_fr1_reg23()
|
| Opcode::PsCmpu1 => self.to_string_form_condreg1_fr23(),
|
||||||
}
|
Opcode::Lfd
|
||||||
|
| Opcode::Lfdu
|
||||||
|
| Opcode::Lfs
|
||||||
|
| Opcode::Lfsu
|
||||||
|
| Opcode::Stfd
|
||||||
|
| Opcode::Stfdu
|
||||||
|
| Opcode::Stfs
|
||||||
|
| Opcode::Stfsu => self.to_string_form_fr1_reg2_offset(),
|
||||||
|
Opcode::Lfdux
|
||||||
|
| Opcode::Lfdx
|
||||||
|
| Opcode::Lfsux
|
||||||
|
| Opcode::Lfsx
|
||||||
|
| Opcode::Stfdux
|
||||||
|
| Opcode::Stfdx
|
||||||
|
| Opcode::Stfiwx
|
||||||
|
| Opcode::Stfsux
|
||||||
|
| Opcode::Stfsx => self.to_string_form_fr1_reg23(),
|
||||||
Opcode::Mtfsf => self.to_string_mtfsf(),
|
Opcode::Mtfsf => self.to_string_mtfsf(),
|
||||||
|
|
||||||
// Condition register only
|
// Condition register only
|
||||||
|
@ -2060,7 +2281,11 @@ impl ToString for Ins {
|
||||||
// Condition register misc
|
// Condition register misc
|
||||||
Opcode::Mtfsfi => self.to_string_mtfsfi(),
|
Opcode::Mtfsfi => self.to_string_mtfsfi(),
|
||||||
|
|
||||||
_ => todo!("can't format instruction 0x{:x}", self.code),
|
// Paired-single instructions
|
||||||
|
Opcode::PsqL | Opcode::PsqLu | Opcode::PsqSt | Opcode::PsqStu => self.to_string_psq(),
|
||||||
|
Opcode::PsqLx | Opcode::PsqLux | Opcode::PsqStx | Opcode::PsqStux => {
|
||||||
|
self.to_string_psq_x()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2140,6 +2365,10 @@ mod tests {
|
||||||
Ins::disasm(0b000100_00001_00000_00000_0000000111_1).op,
|
Ins::disasm(0b000100_00001_00000_00000_0000000111_1).op,
|
||||||
Opcode::Illegal
|
Opcode::Illegal
|
||||||
);
|
);
|
||||||
|
assert_eq!(
|
||||||
|
Ins::disasm(0b1111100000000000000001001111000).op,
|
||||||
|
Opcode::Illegal,
|
||||||
|
);
|
||||||
// TODO more tests
|
// TODO more tests
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue