Implement all print instructions

This commit is contained in:
Richard Patel 2021-08-13 22:25:43 +02:00
parent a08ef23ab6
commit ae8503b217
1 changed files with 383 additions and 154 deletions

View File

@ -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
} }