diff --git a/disasm/src/formatter.rs b/disasm/src/formatter.rs index 3e2ca3c..d1322c5 100644 --- a/disasm/src/formatter.rs +++ b/disasm/src/formatter.rs @@ -7,7 +7,7 @@ pub struct FormattedIns(pub Ins); impl Display for FormattedIns { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { let simple = self.0.clone().simplified(); - write!(f, "{}{}", simple.mnemonic, simple.ins.suffix())?; + write!(f, "{}{}", simple.mnemonic, simple.suffix)?; let mut writing_offset = false; for (i, arg) in simple.args.iter().enumerate() { if i == 0 { diff --git a/disasm/src/generated.rs b/disasm/src/generated.rs index 5becd08..c24c5be 100644 --- a/disasm/src/generated.rs +++ b/disasm/src/generated.rs @@ -1132,7 +1132,7 @@ pub enum Field { offset(Offset), ps_offset(Offset), BO(OpaqueU), - BI(OpaqueU), + BI(CRBit), BH(OpaqueU), BD(BranchDest), LI(BranchDest), @@ -1165,6 +1165,8 @@ pub enum Field { tbr(OpaqueU), mtfsf_FM(OpaqueU), mtfsf_IMM(OpaqueU), + spr_SPRG(OpaqueU), + spr_BAT(OpaqueU), TO(OpaqueU), L(OpaqueU), xer, @@ -1179,7 +1181,7 @@ impl Field { Field::offset(x) => Some(Argument::Offset(*x)), Field::ps_offset(x) => Some(Argument::Offset(*x)), Field::BO(x) => Some(Argument::OpaqueU(*x)), - Field::BI(x) => Some(Argument::OpaqueU(*x)), + Field::BI(x) => Some(Argument::CRBit(*x)), Field::BH(x) => Some(Argument::OpaqueU(*x)), Field::BD(x) => Some(Argument::BranchDest(*x)), Field::LI(x) => Some(Argument::BranchDest(*x)), @@ -1212,6 +1214,8 @@ impl Field { Field::tbr(x) => Some(Argument::OpaqueU(*x)), Field::mtfsf_FM(x) => Some(Argument::OpaqueU(*x)), Field::mtfsf_IMM(x) => Some(Argument::OpaqueU(*x)), + Field::spr_SPRG(x) => Some(Argument::OpaqueU(*x)), + Field::spr_BAT(x) => Some(Argument::OpaqueU(*x)), Field::TO(x) => Some(Argument::OpaqueU(*x)), Field::L(x) => Some(Argument::OpaqueU(*x)), _ => None, @@ -1257,6 +1261,8 @@ impl Field { Field::tbr(_) => "tbr", Field::mtfsf_FM(_) => "mtfsf_FM", Field::mtfsf_IMM(_) => "mtfsf_IMM", + Field::spr_SPRG(_) => "spr_SPRG", + Field::spr_BAT(_) => "spr_BAT", Field::TO(_) => "TO", Field::L(_) => "L", Field::xer => "xer", @@ -1345,7 +1351,7 @@ impl Ins { ))], Opcode::Bc => vec![ Field::BO(OpaqueU(((self.code >> 21u8) & 0x1f) as _)), - Field::BI(OpaqueU(((self.code >> 16u8) & 0x1f) as _)), + Field::BI(CRBit(((self.code >> 16u8) & 0x1f) as _)), Field::BD(BranchDest( ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) as i32) << 2u8) as _, @@ -1353,12 +1359,12 @@ impl Ins { ], Opcode::Bcctr => vec![ Field::BO(OpaqueU(((self.code >> 21u8) & 0x1f) as _)), - Field::BI(OpaqueU(((self.code >> 16u8) & 0x1f) as _)), + Field::BI(CRBit(((self.code >> 16u8) & 0x1f) as _)), Field::BH(OpaqueU(((self.code >> 11u8) & 0x3) as _)), ], Opcode::Bclr => vec![ Field::BO(OpaqueU(((self.code >> 21u8) & 0x1f) as _)), - Field::BI(OpaqueU(((self.code >> 16u8) & 0x1f) as _)), + Field::BI(CRBit(((self.code >> 16u8) & 0x1f) as _)), Field::BH(OpaqueU(((self.code >> 11u8) & 0x3) as _)), ], Opcode::Cmp => vec![ @@ -4219,6 +4225,20 @@ impl Ins { if self.bit(30usize) { s.push('a'); } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) as i32) + << 2u8) + >= 0 + { + s.push('+'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) as i32) + << 2u8) + < 0 + { + s.push('-'); + } s } Opcode::Bcctr => { @@ -4226,6 +4246,9 @@ impl Ins { if self.bit(31usize) { s.push('l'); } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } s } Opcode::Bclr => { @@ -4233,6 +4256,9 @@ impl Ins { if self.bit(31usize) { s.push('l'); } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } s } Opcode::Cmp => String::new(), @@ -4823,6 +4849,7 @@ impl Ins { if ((self.code >> 16u8) & 0x1f) == 0 { return SimplifiedIns { mnemonic: "li", + suffix: String::new(), args: vec![ Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _)), Argument::Simm(Simm( @@ -4838,6 +4865,7 @@ impl Ins { if ((self.code >> 16u8) & 0x1f) == 0 { return SimplifiedIns { mnemonic: "lis", + suffix: String::new(), args: vec![ Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _)), Argument::Uimm(Uimm((self.code & 0xffff) as _)), @@ -4847,19 +4875,40 @@ impl Ins { } } Opcode::Bc => { - if ((self.code >> 21u8) & 0x1f) == 20 && ((self.code >> 16u8) & 0x1f) == 0 { - return SimplifiedIns { - mnemonic: "b", - args: vec![], - ins: self, - }; - } - if ((self.code >> 21u8) & 0x1f) == 12 - && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00 - && ((self.code >> 18u8) & 0x7) == 0 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 12 && ((self.code >> 16u8) & 0x1f) == 0 { return SimplifiedIns { mnemonic: "blt", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if self.bit(30usize) { + s.push('a'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + >= 0 + { + s.push('+'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + < 0 + { + s.push('-'); + } + s + } + }, args: vec![Argument::BranchDest(BranchDest( ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) as i32) @@ -4868,10 +4917,41 @@ impl Ins { ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 12 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 12 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 0 { return SimplifiedIns { mnemonic: "blt", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if self.bit(30usize) { + s.push('a'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + >= 0 + { + s.push('+'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + < 0 + { + s.push('-'); + } + s + } + }, args: vec![ Argument::CRField(CRField(((self.code >> 18u8) & 0x7) as _)), Argument::BranchDest(BranchDest( @@ -4883,12 +4963,40 @@ impl Ins { ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 4 - && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b01 - && ((self.code >> 18u8) & 0x7) == 0 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 4 && ((self.code >> 16u8) & 0x1f) == 1 { return SimplifiedIns { mnemonic: "ble", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if self.bit(30usize) { + s.push('a'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + >= 0 + { + s.push('+'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + < 0 + { + s.push('-'); + } + s + } + }, args: vec![Argument::BranchDest(BranchDest( ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) as i32) @@ -4897,10 +5005,41 @@ impl Ins { ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 4 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b01 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 4 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 1 { return SimplifiedIns { mnemonic: "ble", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if self.bit(30usize) { + s.push('a'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + >= 0 + { + s.push('+'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + < 0 + { + s.push('-'); + } + s + } + }, args: vec![ Argument::CRField(CRField(((self.code >> 18u8) & 0x7) as _)), Argument::BranchDest(BranchDest( @@ -4912,12 +5051,40 @@ impl Ins { ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 12 - && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b10 - && ((self.code >> 18u8) & 0x7) == 0 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 12 && ((self.code >> 16u8) & 0x1f) == 2 { return SimplifiedIns { mnemonic: "beq", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if self.bit(30usize) { + s.push('a'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + >= 0 + { + s.push('+'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + < 0 + { + s.push('-'); + } + s + } + }, args: vec![Argument::BranchDest(BranchDest( ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) as i32) @@ -4926,10 +5093,41 @@ impl Ins { ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 12 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b10 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 12 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 2 { return SimplifiedIns { mnemonic: "beq", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if self.bit(30usize) { + s.push('a'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + >= 0 + { + s.push('+'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + < 0 + { + s.push('-'); + } + s + } + }, args: vec![ Argument::CRField(CRField(((self.code >> 18u8) & 0x7) as _)), Argument::BranchDest(BranchDest( @@ -4941,12 +5139,40 @@ impl Ins { ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 4 - && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00 - && ((self.code >> 18u8) & 0x7) == 0 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 4 && ((self.code >> 16u8) & 0x1f) == 0 { return SimplifiedIns { mnemonic: "bge", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if self.bit(30usize) { + s.push('a'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + >= 0 + { + s.push('+'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + < 0 + { + s.push('-'); + } + s + } + }, args: vec![Argument::BranchDest(BranchDest( ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) as i32) @@ -4955,10 +5181,41 @@ impl Ins { ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 4 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 4 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 0 { return SimplifiedIns { mnemonic: "bge", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if self.bit(30usize) { + s.push('a'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + >= 0 + { + s.push('+'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + < 0 + { + s.push('-'); + } + s + } + }, args: vec![ Argument::CRField(CRField(((self.code >> 18u8) & 0x7) as _)), Argument::BranchDest(BranchDest( @@ -4970,12 +5227,40 @@ impl Ins { ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 12 - && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b01 - && ((self.code >> 18u8) & 0x7) == 0 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 12 && ((self.code >> 16u8) & 0x1f) == 1 { return SimplifiedIns { mnemonic: "bgt", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if self.bit(30usize) { + s.push('a'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + >= 0 + { + s.push('+'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + < 0 + { + s.push('-'); + } + s + } + }, args: vec![Argument::BranchDest(BranchDest( ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) as i32) @@ -4984,10 +5269,41 @@ impl Ins { ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 12 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b01 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 12 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 1 { return SimplifiedIns { mnemonic: "bgt", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if self.bit(30usize) { + s.push('a'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + >= 0 + { + s.push('+'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + < 0 + { + s.push('-'); + } + s + } + }, args: vec![ Argument::CRField(CRField(((self.code >> 18u8) & 0x7) as _)), Argument::BranchDest(BranchDest( @@ -4999,12 +5315,40 @@ impl Ins { ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 4 - && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b10 - && ((self.code >> 18u8) & 0x7) == 0 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 4 && ((self.code >> 16u8) & 0x1f) == 2 { return SimplifiedIns { mnemonic: "bne", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if self.bit(30usize) { + s.push('a'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + >= 0 + { + s.push('+'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + < 0 + { + s.push('-'); + } + s + } + }, args: vec![Argument::BranchDest(BranchDest( ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) as i32) @@ -5013,10 +5357,41 @@ impl Ins { ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 4 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b10 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 4 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 2 { return SimplifiedIns { mnemonic: "bne", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if self.bit(30usize) { + s.push('a'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + >= 0 + { + s.push('+'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + < 0 + { + s.push('-'); + } + s + } + }, args: vec![ Argument::CRField(CRField(((self.code >> 18u8) & 0x7) as _)), Argument::BranchDest(BranchDest( @@ -5028,12 +5403,40 @@ impl Ins { ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 12 - && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b11 - && ((self.code >> 18u8) & 0x7) == 0 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 12 && ((self.code >> 16u8) & 0x1f) == 3 { return SimplifiedIns { mnemonic: "bso", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if self.bit(30usize) { + s.push('a'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + >= 0 + { + s.push('+'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + < 0 + { + s.push('-'); + } + s + } + }, args: vec![Argument::BranchDest(BranchDest( ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) as i32) @@ -5042,10 +5445,41 @@ impl Ins { ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 12 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b11 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 12 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 3 { return SimplifiedIns { mnemonic: "bso", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if self.bit(30usize) { + s.push('a'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + >= 0 + { + s.push('+'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + < 0 + { + s.push('-'); + } + s + } + }, args: vec![ Argument::CRField(CRField(((self.code >> 18u8) & 0x7) as _)), Argument::BranchDest(BranchDest( @@ -5057,12 +5491,40 @@ impl Ins { ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 4 - && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b11 - && ((self.code >> 18u8) & 0x7) == 0 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 4 && ((self.code >> 16u8) & 0x1f) == 3 { return SimplifiedIns { mnemonic: "bns", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if self.bit(30usize) { + s.push('a'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + >= 0 + { + s.push('+'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + < 0 + { + s.push('-'); + } + s + } + }, args: vec![Argument::BranchDest(BranchDest( ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) as i32) @@ -5071,10 +5533,41 @@ impl Ins { ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 4 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b11 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 4 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 3 { return SimplifiedIns { mnemonic: "bns", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if self.bit(30usize) { + s.push('a'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + >= 0 + { + s.push('+'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + < 0 + { + s.push('-'); + } + s + } + }, args: vec![ Argument::CRField(CRField(((self.code >> 18u8) & 0x7) as _)), Argument::BranchDest(BranchDest( @@ -5086,9 +5579,40 @@ impl Ins { ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 16 && ((self.code >> 16u8) & 0x1f) == 0 { + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 16 && ((self.code >> 16u8) & 0x1f) == 0 + { return SimplifiedIns { mnemonic: "bdnz", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if self.bit(30usize) { + s.push('a'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + >= 0 + { + s.push('+'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + < 0 + { + s.push('-'); + } + s + } + }, args: vec![Argument::BranchDest(BranchDest( ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) as i32) @@ -5097,9 +5621,128 @@ impl Ins { ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 18 && ((self.code >> 16u8) & 0x1f) == 0 { + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 8 { + return SimplifiedIns { + mnemonic: "bdnzt", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if self.bit(30usize) { + s.push('a'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + >= 0 + { + s.push('+'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + < 0 + { + s.push('-'); + } + s + } + }, + args: vec![ + Argument::CRBit(CRBit(((self.code >> 16u8) & 0x1f) as _)), + Argument::BranchDest(BranchDest( + ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) + as i32) + << 2u8) as _, + )), + ], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 0 { + return SimplifiedIns { + mnemonic: "bdnzf", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if self.bit(30usize) { + s.push('a'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + >= 0 + { + s.push('+'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + < 0 + { + s.push('-'); + } + s + } + }, + args: vec![ + Argument::CRBit(CRBit(((self.code >> 16u8) & 0x1f) as _)), + Argument::BranchDest(BranchDest( + ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) + as i32) + << 2u8) as _, + )), + ], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 18 && ((self.code >> 16u8) & 0x1f) == 0 + { return SimplifiedIns { mnemonic: "bdz", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if self.bit(30usize) { + s.push('a'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + >= 0 + { + s.push('+'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + < 0 + { + s.push('-'); + } + s + } + }, args: vec![Argument::BranchDest(BranchDest( ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) as i32) @@ -5108,155 +5751,436 @@ impl Ins { ins: self, }; } + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 10 { + return SimplifiedIns { + mnemonic: "bdzt", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if self.bit(30usize) { + s.push('a'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + >= 0 + { + s.push('+'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + < 0 + { + s.push('-'); + } + s + } + }, + args: vec![ + Argument::CRBit(CRBit(((self.code >> 16u8) & 0x1f) as _)), + Argument::BranchDest(BranchDest( + ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) + as i32) + << 2u8) as _, + )), + ], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 2 { + return SimplifiedIns { + mnemonic: "bdzf", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if self.bit(30usize) { + s.push('a'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + >= 0 + { + s.push('+'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000) + .wrapping_sub(0x2000)) + as i32) + << 2u8) + < 0 + { + s.push('-'); + } + s + } + }, + args: vec![ + Argument::CRBit(CRBit(((self.code >> 16u8) & 0x1f) as _)), + Argument::BranchDest(BranchDest( + ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) + as i32) + << 2u8) as _, + )), + ], + ins: self, + }; + } } Opcode::Bcctr => { if ((self.code >> 21u8) & 0x1f) == 20 && ((self.code >> 16u8) & 0x1f) == 0 { return SimplifiedIns { mnemonic: "bctr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + s + } + }, args: vec![], ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 12 - && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00 - && ((self.code >> 18u8) & 0x7) == 0 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 12 && ((self.code >> 16u8) & 0x1f) == 0 { return SimplifiedIns { mnemonic: "bltctr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, args: vec![], ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 12 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 12 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 0 { return SimplifiedIns { mnemonic: "bltctr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, args: vec![Argument::CRField(CRField(((self.code >> 18u8) & 0x7) as _))], ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 4 - && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b01 - && ((self.code >> 18u8) & 0x7) == 0 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 4 && ((self.code >> 16u8) & 0x1f) == 1 { return SimplifiedIns { mnemonic: "blectr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, args: vec![], ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 4 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b01 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 4 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 1 { return SimplifiedIns { mnemonic: "blectr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, args: vec![Argument::CRField(CRField(((self.code >> 18u8) & 0x7) as _))], ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 12 - && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b10 - && ((self.code >> 18u8) & 0x7) == 0 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 12 && ((self.code >> 16u8) & 0x1f) == 2 { return SimplifiedIns { mnemonic: "beqctr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, args: vec![], ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 12 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b10 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 12 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 2 { return SimplifiedIns { mnemonic: "beqctr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, args: vec![Argument::CRField(CRField(((self.code >> 18u8) & 0x7) as _))], ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 4 - && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00 - && ((self.code >> 18u8) & 0x7) == 0 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 4 && ((self.code >> 16u8) & 0x1f) == 0 { return SimplifiedIns { mnemonic: "bgectr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, args: vec![], ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 4 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 4 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 0 { return SimplifiedIns { mnemonic: "bgectr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, args: vec![Argument::CRField(CRField(((self.code >> 18u8) & 0x7) as _))], ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 12 - && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b01 - && ((self.code >> 18u8) & 0x7) == 0 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 12 && ((self.code >> 16u8) & 0x1f) == 1 { return SimplifiedIns { mnemonic: "bgtctr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, args: vec![], ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 12 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b01 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 12 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 1 { return SimplifiedIns { mnemonic: "bgtctr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, args: vec![Argument::CRField(CRField(((self.code >> 18u8) & 0x7) as _))], ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 4 - && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b10 - && ((self.code >> 18u8) & 0x7) == 0 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 4 && ((self.code >> 16u8) & 0x1f) == 2 { return SimplifiedIns { mnemonic: "bnectr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, args: vec![], ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 4 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b10 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 4 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 2 { return SimplifiedIns { mnemonic: "bnectr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, args: vec![Argument::CRField(CRField(((self.code >> 18u8) & 0x7) as _))], ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 12 - && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b11 - && ((self.code >> 18u8) & 0x7) == 0 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 12 && ((self.code >> 16u8) & 0x1f) == 3 { return SimplifiedIns { mnemonic: "bsoctr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, args: vec![], ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 12 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b11 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 12 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 3 { return SimplifiedIns { mnemonic: "bsoctr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, args: vec![Argument::CRField(CRField(((self.code >> 18u8) & 0x7) as _))], ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 4 - && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b11 - && ((self.code >> 18u8) & 0x7) == 0 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 4 && ((self.code >> 16u8) & 0x1f) == 3 { return SimplifiedIns { mnemonic: "bnsctr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, args: vec![], ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 4 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b11 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 4 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 3 { return SimplifiedIns { mnemonic: "bnsctr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, args: vec![Argument::CRField(CRField(((self.code >> 18u8) & 0x7) as _))], ins: self, }; @@ -5266,159 +6190,469 @@ impl Ins { if ((self.code >> 21u8) & 0x1f) == 20 && ((self.code >> 16u8) & 0x1f) == 0 { return SimplifiedIns { mnemonic: "blr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + s + } + }, args: vec![], ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 12 - && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00 - && ((self.code >> 18u8) & 0x7) == 0 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 12 && ((self.code >> 16u8) & 0x1f) == 0 { return SimplifiedIns { mnemonic: "bltlr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, args: vec![], ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 12 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 12 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 0 { return SimplifiedIns { mnemonic: "bltlr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, args: vec![Argument::CRField(CRField(((self.code >> 18u8) & 0x7) as _))], ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 4 - && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b01 - && ((self.code >> 18u8) & 0x7) == 0 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 4 && ((self.code >> 16u8) & 0x1f) == 1 { return SimplifiedIns { mnemonic: "blelr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, args: vec![], ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 4 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b01 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 4 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 1 { return SimplifiedIns { mnemonic: "blelr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, args: vec![Argument::CRField(CRField(((self.code >> 18u8) & 0x7) as _))], ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 12 - && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b10 - && ((self.code >> 18u8) & 0x7) == 0 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 12 && ((self.code >> 16u8) & 0x1f) == 2 { return SimplifiedIns { mnemonic: "beqlr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, args: vec![], ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 12 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b10 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 12 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 2 { return SimplifiedIns { mnemonic: "beqlr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, args: vec![Argument::CRField(CRField(((self.code >> 18u8) & 0x7) as _))], ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 4 - && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00 - && ((self.code >> 18u8) & 0x7) == 0 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 4 && ((self.code >> 16u8) & 0x1f) == 0 { return SimplifiedIns { mnemonic: "bgelr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, args: vec![], ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 4 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 4 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 0 { return SimplifiedIns { mnemonic: "bgelr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, args: vec![Argument::CRField(CRField(((self.code >> 18u8) & 0x7) as _))], ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 12 - && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b01 - && ((self.code >> 18u8) & 0x7) == 0 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 12 && ((self.code >> 16u8) & 0x1f) == 1 { return SimplifiedIns { mnemonic: "bgtlr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, args: vec![], ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 12 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b01 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 12 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 1 { return SimplifiedIns { mnemonic: "bgtlr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, args: vec![Argument::CRField(CRField(((self.code >> 18u8) & 0x7) as _))], ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 4 - && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b10 - && ((self.code >> 18u8) & 0x7) == 0 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 4 && ((self.code >> 16u8) & 0x1f) == 2 { return SimplifiedIns { mnemonic: "bnelr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, args: vec![], ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 4 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b10 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 4 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 2 { return SimplifiedIns { mnemonic: "bnelr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, args: vec![Argument::CRField(CRField(((self.code >> 18u8) & 0x7) as _))], ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 12 - && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b11 - && ((self.code >> 18u8) & 0x7) == 0 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 12 && ((self.code >> 16u8) & 0x1f) == 3 { return SimplifiedIns { mnemonic: "bsolr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, args: vec![], ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 12 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b11 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 12 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 3 { return SimplifiedIns { mnemonic: "bsolr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, args: vec![Argument::CRField(CRField(((self.code >> 18u8) & 0x7) as _))], ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 4 - && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b11 - && ((self.code >> 18u8) & 0x7) == 0 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 4 && ((self.code >> 16u8) & 0x1f) == 3 { return SimplifiedIns { mnemonic: "bnslr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, args: vec![], ins: self, }; } - if ((self.code >> 21u8) & 0x1f) == 4 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b11 + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 4 + && ((self.code >> 16u8) & 0x1f) & 0b11 == 3 { return SimplifiedIns { mnemonic: "bnslr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, args: vec![Argument::CRField(CRField(((self.code >> 18u8) & 0x7) as _))], ins: self, }; } + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 16 && ((self.code >> 16u8) & 0x1f) == 0 + { + return SimplifiedIns { + mnemonic: "bdnzlr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, + args: vec![], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 8 { + return SimplifiedIns { + mnemonic: "bdnztlr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, + args: vec![Argument::CRBit(CRBit(((self.code >> 16u8) & 0x1f) as _))], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 0 { + return SimplifiedIns { + mnemonic: "bdnzflr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, + args: vec![Argument::CRBit(CRBit(((self.code >> 16u8) & 0x1f) as _))], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 18 && ((self.code >> 16u8) & 0x1f) == 0 + { + return SimplifiedIns { + mnemonic: "bdzlr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, + args: vec![], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 10 { + return SimplifiedIns { + mnemonic: "bdztlr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, + args: vec![Argument::CRBit(CRBit(((self.code >> 16u8) & 0x1f) as _))], + ins: self, + }; + } + if ((self.code >> 21u8) & 0x1f) & 0b11110 == 0 { + return SimplifiedIns { + mnemonic: "bdzflr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('l'); + } + if ((self.code >> 21u8) & 0x1f) & 1 == 1 { + s.push('+'); + } + s + } + }, + args: vec![Argument::CRBit(CRBit(((self.code >> 16u8) & 0x1f) as _))], + ins: self, + }; + } } Opcode::Cmp => { if ((self.code >> 23u8) & 0x7) == 0 && ((self.code >> 21u8) & 0x1) == 0 { return SimplifiedIns { mnemonic: "cmpw", + suffix: String::new(), args: vec![ Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), Argument::GPR(GPR(((self.code >> 11u8) & 0x1f) as _)), @@ -5429,6 +6663,7 @@ impl Ins { if ((self.code >> 21u8) & 0x1) == 0 { return SimplifiedIns { mnemonic: "cmpw", + suffix: String::new(), args: vec![ Argument::CRField(CRField(((self.code >> 23u8) & 0x7) as _)), Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), @@ -5440,6 +6675,7 @@ impl Ins { if ((self.code >> 23u8) & 0x7) == 0 && ((self.code >> 21u8) & 0x1) == 1 { return SimplifiedIns { mnemonic: "cmpd", + suffix: String::new(), args: vec![ Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), Argument::GPR(GPR(((self.code >> 11u8) & 0x1f) as _)), @@ -5450,6 +6686,7 @@ impl Ins { if ((self.code >> 21u8) & 0x1) == 1 { return SimplifiedIns { mnemonic: "cmpd", + suffix: String::new(), args: vec![ Argument::CRField(CRField(((self.code >> 23u8) & 0x7) as _)), Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), @@ -5463,6 +6700,7 @@ impl Ins { if ((self.code >> 23u8) & 0x7) == 0 && ((self.code >> 21u8) & 0x1) == 0 { return SimplifiedIns { mnemonic: "cmpwi", + suffix: String::new(), args: vec![ Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), Argument::Simm(Simm( @@ -5476,6 +6714,7 @@ impl Ins { if ((self.code >> 21u8) & 0x1) == 0 { return SimplifiedIns { mnemonic: "cmpwi", + suffix: String::new(), args: vec![ Argument::CRField(CRField(((self.code >> 23u8) & 0x7) as _)), Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), @@ -5490,6 +6729,7 @@ impl Ins { if ((self.code >> 23u8) & 0x7) == 0 && ((self.code >> 21u8) & 0x1) == 1 { return SimplifiedIns { mnemonic: "cmpdi", + suffix: String::new(), args: vec![ Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), Argument::Simm(Simm( @@ -5503,6 +6743,7 @@ impl Ins { if ((self.code >> 21u8) & 0x1) == 1 { return SimplifiedIns { mnemonic: "cmpdi", + suffix: String::new(), args: vec![ Argument::CRField(CRField(((self.code >> 23u8) & 0x7) as _)), Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), @@ -5519,6 +6760,7 @@ impl Ins { if ((self.code >> 23u8) & 0x7) == 0 && ((self.code >> 21u8) & 0x1) == 0 { return SimplifiedIns { mnemonic: "cmplw", + suffix: String::new(), args: vec![ Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), Argument::GPR(GPR(((self.code >> 11u8) & 0x1f) as _)), @@ -5529,6 +6771,7 @@ impl Ins { if ((self.code >> 21u8) & 0x1) == 0 { return SimplifiedIns { mnemonic: "cmplw", + suffix: String::new(), args: vec![ Argument::CRField(CRField(((self.code >> 23u8) & 0x7) as _)), Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), @@ -5540,6 +6783,7 @@ impl Ins { if ((self.code >> 23u8) & 0x7) == 0 && ((self.code >> 21u8) & 0x1) == 1 { return SimplifiedIns { mnemonic: "cmpld", + suffix: String::new(), args: vec![ Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), Argument::GPR(GPR(((self.code >> 11u8) & 0x1f) as _)), @@ -5550,6 +6794,7 @@ impl Ins { if ((self.code >> 21u8) & 0x1) == 1 { return SimplifiedIns { mnemonic: "cmpld", + suffix: String::new(), args: vec![ Argument::CRField(CRField(((self.code >> 23u8) & 0x7) as _)), Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), @@ -5563,6 +6808,7 @@ impl Ins { if ((self.code >> 23u8) & 0x7) == 0 && ((self.code >> 21u8) & 0x1) == 0 { return SimplifiedIns { mnemonic: "cmplwi", + suffix: String::new(), args: vec![ Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), Argument::Uimm(Uimm((self.code & 0xffff) as _)), @@ -5573,6 +6819,7 @@ impl Ins { if ((self.code >> 21u8) & 0x1) == 0 { return SimplifiedIns { mnemonic: "cmplwi", + suffix: String::new(), args: vec![ Argument::CRField(CRField(((self.code >> 23u8) & 0x7) as _)), Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), @@ -5584,6 +6831,7 @@ impl Ins { if ((self.code >> 23u8) & 0x7) == 0 && ((self.code >> 21u8) & 0x1) == 1 { return SimplifiedIns { mnemonic: "cmpldi", + suffix: String::new(), args: vec![ Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), Argument::Uimm(Uimm((self.code & 0xffff) as _)), @@ -5594,6 +6842,7 @@ impl Ins { if ((self.code >> 21u8) & 0x1) == 1 { return SimplifiedIns { mnemonic: "cmpldi", + suffix: String::new(), args: vec![ Argument::CRField(CRField(((self.code >> 23u8) & 0x7) as _)), Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), @@ -5609,6 +6858,7 @@ impl Ins { { return SimplifiedIns { mnemonic: "crset", + suffix: String::new(), args: vec![Argument::CRBit(CRBit(((self.code >> 21u8) & 0x1f) as _))], ins: self, }; @@ -5618,10 +6868,10 @@ impl Ins { if ((self.code >> 16u8) & 0x1f) == ((self.code >> 11u8) & 0x1f) { return SimplifiedIns { mnemonic: "crnot", + suffix: String::new(), args: vec![ Argument::CRBit(CRBit(((self.code >> 21u8) & 0x1f) as _)), Argument::CRBit(CRBit(((self.code >> 16u8) & 0x1f) as _)), - Argument::CRBit(CRBit(((self.code >> 11u8) & 0x1f) as _)), ], ins: self, }; @@ -5631,10 +6881,10 @@ impl Ins { if ((self.code >> 16u8) & 0x1f) == ((self.code >> 11u8) & 0x1f) { return SimplifiedIns { mnemonic: "crmove", + suffix: String::new(), args: vec![ Argument::CRBit(CRBit(((self.code >> 21u8) & 0x1f) as _)), Argument::CRBit(CRBit(((self.code >> 16u8) & 0x1f) as _)), - Argument::CRBit(CRBit(((self.code >> 11u8) & 0x1f) as _)), ], ins: self, }; @@ -5646,6 +6896,7 @@ impl Ins { { return SimplifiedIns { mnemonic: "crclr", + suffix: String::new(), args: vec![Argument::CRBit(CRBit(((self.code >> 21u8) & 0x1f) as _))], ins: self, }; @@ -5659,6 +6910,7 @@ impl Ins { { return SimplifiedIns { mnemonic: "mfxer", + suffix: String::new(), args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], ins: self, }; @@ -5670,6 +6922,7 @@ impl Ins { { return SimplifiedIns { mnemonic: "mflr", + suffix: String::new(), args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], ins: self, }; @@ -5681,6 +6934,7 @@ impl Ins { { return SimplifiedIns { mnemonic: "mfctr", + suffix: String::new(), args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], ins: self, }; @@ -5692,6 +6946,7 @@ impl Ins { { return SimplifiedIns { mnemonic: "mfdsisr", + suffix: String::new(), args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], ins: self, }; @@ -5699,11 +6954,152 @@ impl Ins { if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) as u32 - == 397 + == 19 + { + return SimplifiedIns { + mnemonic: "mfdar", + suffix: String::new(), + args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], + ins: self, + }; + } + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + == 22 + { + return SimplifiedIns { + mnemonic: "mfdec", + suffix: String::new(), + args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], + ins: self, + }; + } + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + == 25 + { + return SimplifiedIns { + mnemonic: "mfsdr1", + suffix: String::new(), + args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], + ins: self, + }; + } + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + == 26 + { + return SimplifiedIns { + mnemonic: "mfsrr0", + suffix: String::new(), + args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], + ins: self, + }; + } + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + == 27 + { + return SimplifiedIns { + mnemonic: "mfsrr1", + suffix: String::new(), + args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], + ins: self, + }; + } + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + & 0b1111111100 + == 272 + { + return SimplifiedIns { + mnemonic: "mfsprg", + suffix: String::new(), + args: vec![ + Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _)), + Argument::OpaqueU(OpaqueU(((self.code >> 16u8) & 0x3) as _)), + ], + ins: self, + }; + } + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + == 282 + { + return SimplifiedIns { + mnemonic: "mfear", + suffix: String::new(), + args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], + ins: self, + }; + } + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + & 0b1111111001 + == 528 + { + return SimplifiedIns { + mnemonic: "mfibatu", + suffix: String::new(), + args: vec![ + Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _)), + Argument::OpaqueU(OpaqueU(((self.code >> 17u8) & 0x3) as _)), + ], + ins: self, + }; + } + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + & 0b1111111001 + == 529 + { + return SimplifiedIns { + mnemonic: "mfibatl", + suffix: String::new(), + args: vec![ + Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _)), + Argument::OpaqueU(OpaqueU(((self.code >> 17u8) & 0x3) as _)), + ], + ins: self, + }; + } + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + & 0b1111111001 + == 536 { return SimplifiedIns { mnemonic: "mfdbatu", - args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], + suffix: String::new(), + args: vec![ + Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _)), + Argument::OpaqueU(OpaqueU(((self.code >> 17u8) & 0x3) as _)), + ], + ins: self, + }; + } + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + & 0b1111111001 + == 537 + { + return SimplifiedIns { + mnemonic: "mfdbatl", + suffix: String::new(), + args: vec![ + Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _)), + Argument::OpaqueU(OpaqueU(((self.code >> 17u8) & 0x3) as _)), + ], ins: self, }; } @@ -5716,6 +7112,7 @@ impl Ins { { return SimplifiedIns { mnemonic: "mtxer", + suffix: String::new(), args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], ins: self, }; @@ -5727,6 +7124,7 @@ impl Ins { { return SimplifiedIns { mnemonic: "mtlr", + suffix: String::new(), args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], ins: self, }; @@ -5738,6 +7136,7 @@ impl Ins { { return SimplifiedIns { mnemonic: "mtctr", + suffix: String::new(), args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], ins: self, }; @@ -5749,6 +7148,7 @@ impl Ins { { return SimplifiedIns { mnemonic: "mtdsisr", + suffix: String::new(), args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], ins: self, }; @@ -5756,11 +7156,176 @@ impl Ins { if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) as u32 - == 397 + == 19 + { + return SimplifiedIns { + mnemonic: "mtdar", + suffix: String::new(), + args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], + ins: self, + }; + } + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + == 22 + { + return SimplifiedIns { + mnemonic: "mtdec", + suffix: String::new(), + args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], + ins: self, + }; + } + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + == 25 + { + return SimplifiedIns { + mnemonic: "mtsdr1", + suffix: String::new(), + args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], + ins: self, + }; + } + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + == 26 + { + return SimplifiedIns { + mnemonic: "mtsrr0", + suffix: String::new(), + args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], + ins: self, + }; + } + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + == 27 + { + return SimplifiedIns { + mnemonic: "mtsrr1", + suffix: String::new(), + args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], + ins: self, + }; + } + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + & 0b1111111100 + == 272 + { + return SimplifiedIns { + mnemonic: "mtsprg", + suffix: String::new(), + args: vec![ + Argument::OpaqueU(OpaqueU(((self.code >> 16u8) & 0x3) as _)), + Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _)), + ], + ins: self, + }; + } + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + == 282 + { + return SimplifiedIns { + mnemonic: "mtear", + suffix: String::new(), + args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], + ins: self, + }; + } + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + == 284 + { + return SimplifiedIns { + mnemonic: "mttbl", + suffix: String::new(), + args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], + ins: self, + }; + } + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + == 285 + { + return SimplifiedIns { + mnemonic: "mttbu", + suffix: String::new(), + args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], + ins: self, + }; + } + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + & 0b1111111001 + == 528 + { + return SimplifiedIns { + mnemonic: "mtibatu", + suffix: String::new(), + args: vec![ + Argument::OpaqueU(OpaqueU(((self.code >> 17u8) & 0x3) as _)), + Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _)), + ], + ins: self, + }; + } + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + & 0b1111111001 + == 529 + { + return SimplifiedIns { + mnemonic: "mtibatl", + suffix: String::new(), + args: vec![ + Argument::OpaqueU(OpaqueU(((self.code >> 17u8) & 0x3) as _)), + Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _)), + ], + ins: self, + }; + } + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + & 0b1111111001 + == 536 { return SimplifiedIns { mnemonic: "mtdbatu", - args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], + suffix: String::new(), + args: vec![ + Argument::OpaqueU(OpaqueU(((self.code >> 17u8) & 0x3) as _)), + Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _)), + ], + ins: self, + }; + } + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + & 0b1111111001 + == 537 + { + return SimplifiedIns { + mnemonic: "mtdbatl", + suffix: String::new(), + args: vec![ + Argument::OpaqueU(OpaqueU(((self.code >> 17u8) & 0x3) as _)), + Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _)), + ], ins: self, }; } @@ -5769,6 +7334,15 @@ impl Ins { if ((self.code >> 21u8) & 0x1f) == ((self.code >> 11u8) & 0x1f) { return SimplifiedIns { mnemonic: "mr", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + }, args: vec![ Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _)), @@ -5784,15 +7358,48 @@ impl Ins { { return SimplifiedIns { mnemonic: "nop", + suffix: String::new(), args: vec![], ins: self, }; } } Opcode::Rlwinm => { + if ((self.code >> 11u8) & 0x1f) == 0 + && ((self.code >> 6u8) & 0x1f) == 0 + && ((self.code >> 1u8) & 0x1f) < 32 + { + return SimplifiedIns { + mnemonic: "clrrwi", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + }, + args: vec![ + Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), + Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _)), + Argument::OpaqueU(OpaqueU((31 - ((self.code >> 1u8) & 0x1f)) as _)), + ], + ins: self, + }; + } if ((self.code >> 11u8) & 0x1f) == 0 && ((self.code >> 1u8) & 0x1f) == 31 { return SimplifiedIns { mnemonic: "clrlwi", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + }, args: vec![ Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _)), @@ -5801,9 +7408,21 @@ impl Ins { ins: self, }; } - if ((self.code >> 6u8) & 0x1f) == 0 && ((self.code >> 1u8) & 0x1f) == 31 { + if ((self.code >> 6u8) & 0x1f) == 0 + && ((self.code >> 1u8) & 0x1f) == 31 + && ((self.code >> 11u8) & 0x1f) <= 16 + { return SimplifiedIns { mnemonic: "rotlwi", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + }, args: vec![ Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _)), @@ -5812,11 +7431,43 @@ impl Ins { ins: self, }; } + if ((self.code >> 6u8) & 0x1f) == 0 + && ((self.code >> 1u8) & 0x1f) == 31 + && ((self.code >> 11u8) & 0x1f) > 16 + { + return SimplifiedIns { + mnemonic: "rotrwi", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + }, + args: vec![ + Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), + Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _)), + Argument::OpaqueU(OpaqueU((32 - ((self.code >> 11u8) & 0x1f)) as _)), + ], + ins: self, + }; + } if ((self.code >> 6u8) & 0x1f) == 0 && 31 - ((self.code >> 11u8) & 0x1f) == ((self.code >> 1u8) & 0x1f) { return SimplifiedIns { mnemonic: "slwi", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + }, args: vec![ Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _)), @@ -5830,6 +7481,15 @@ impl Ins { { return SimplifiedIns { mnemonic: "srwi", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + }, args: vec![ Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _)), @@ -5838,11 +7498,106 @@ impl Ins { ins: self, }; } + if ((self.code >> 11u8) & 0x1f) < 32 + && ((self.code >> 1u8) & 0x1f) == 31 - ((self.code >> 11u8) & 0x1f) + { + return SimplifiedIns { + mnemonic: "clrlslwi", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + }, + args: vec![ + Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), + Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _)), + Argument::OpaqueU(OpaqueU( + (((self.code >> 6u8) & 0x1f) + ((self.code >> 11u8) & 0x1f)) as _, + )), + Argument::OpaqueU(OpaqueU(((self.code >> 11u8) & 0x1f) as _)), + ], + ins: self, + }; + } + if ((self.code >> 6u8) & 0x1f) == 0 { + return SimplifiedIns { + mnemonic: "extlwi", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + }, + args: vec![ + Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), + Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _)), + Argument::OpaqueU(OpaqueU((((self.code >> 1u8) & 0x1f) + 1) as _)), + Argument::OpaqueU(OpaqueU(((self.code >> 11u8) & 0x1f) as _)), + ], + ins: self, + }; + } + if ((self.code >> 1u8) & 0x1f) == 31 + && ((self.code >> 11u8) & 0x1f) >= 32 - ((self.code >> 6u8) & 0x1f) + { + return SimplifiedIns { + mnemonic: "extrwi", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + }, + args: vec![ + Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), + Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _)), + Argument::OpaqueU(OpaqueU((32 - ((self.code >> 6u8) & 0x1f)) as _)), + Argument::OpaqueU(OpaqueU( + (((self.code >> 11u8) & 0x1f) - (32 - ((self.code >> 6u8) & 0x1f))) + as _, + )), + ], + ins: self, + }; + } + } + Opcode::Rlwnm => { + if ((self.code >> 6u8) & 0x1f) == 0 && ((self.code >> 1u8) & 0x1f) == 31 { + return SimplifiedIns { + mnemonic: "rotlw", + suffix: { + { + let mut s = String::with_capacity(4); + if self.bit(31usize) { + s.push('.'); + } + s + } + }, + args: vec![ + Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), + Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _)), + Argument::GPR(GPR(((self.code >> 11u8) & 0x1f) as _)), + ], + ins: self, + }; + } } Opcode::Twi => { if ((self.code >> 21u8) & 0x1f) == 8 { return SimplifiedIns { mnemonic: "twgti", + suffix: String::new(), args: vec![ Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), Argument::Simm(Simm( @@ -5856,6 +7611,7 @@ impl Ins { if ((self.code >> 21u8) & 0x1f) == 6 { return SimplifiedIns { mnemonic: "twllei", + suffix: String::new(), args: vec![ Argument::GPR(GPR(((self.code >> 16u8) & 0x1f) as _)), Argument::Simm(Simm( @@ -6029,6 +7785,14 @@ impl Ins { ((self.code >> 12u8) & 0xf) as _ } #[inline(always)] + pub fn field_spr_SPRG(&self) -> usize { + ((self.code >> 16u8) & 0x3) as _ + } + #[inline(always)] + pub fn field_spr_BAT(&self) -> usize { + ((self.code >> 17u8) & 0x3) as _ + } + #[inline(always)] pub fn field_TO(&self) -> usize { ((self.code >> 21u8) & 0x1f) as _ } @@ -6052,4 +7816,19 @@ impl Ins { pub fn field_AA(&self) -> bool { self.bit(30usize) } + #[inline(always)] + pub fn field_BP(&self) -> bool { + ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) as i32) << 2u8) + >= 0 + } + #[inline(always)] + pub fn field_BNP(&self) -> bool { + ((self.code >> 21u8) & 0x1f) & 1 == 1 + && ((((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000)) as i32) << 2u8) < 0 + } + #[inline(always)] + pub fn field_BP_ND(&self) -> bool { + ((self.code >> 21u8) & 0x1f) & 1 == 1 + } } diff --git a/disasm/src/lib.rs b/disasm/src/lib.rs index 1fd538b..f47b868 100644 --- a/disasm/src/lib.rs +++ b/disasm/src/lib.rs @@ -104,11 +104,97 @@ field_arg!(FPR, u8, "f{}"); // Segment register. field_arg!(SR, u8); // Special-purpose register. -field_arg!(SPR, u16); +field_arg_no_display!(SPR, u16); +impl Display for SPR { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.write_str(match self.0 { + 1 => "XER", + 8 => "LR", + 9 => "CTR", + 18 => "DSISR", + 19 => "DAR", + 22 => "DEC", + 25 => "SDR1", + 26 => "SRR0", + 27 => "SRR1", + 272 => "SPRG0", + 273 => "SPRG1", + 274 => "SPRG2", + 275 => "SPRG3", + 282 => "EAR", + 287 => "PVR", + 528 => "IBAT0U", + 529 => "IBAT0L", + 530 => "IBAT1U", + 531 => "IBAT1L", + 532 => "IBAT2U", + 533 => "IBAT2L", + 534 => "IBAT3U", + 535 => "IBAT3L", + 536 => "DBAT0U", + 537 => "DBAT0L", + 538 => "DBAT1U", + 539 => "DBAT1L", + 540 => "DBAT2U", + 541 => "DBAT2L", + 542 => "DBAT3U", + 543 => "DBAT3L", + 912 => "GQR0", + 913 => "GQR1", + 914 => "GQR2", + 915 => "GQR3", + 916 => "GQR4", + 917 => "GQR5", + 918 => "GQR6", + 919 => "GQR7", + 920 => "HID2", + 921 => "WPAR", + 922 => "DMA_U", + 923 => "DMA_L", + 936 => "UMMCR0", + 937 => "UPMC1", + 938 => "UPMC2", + 939 => "USIA", + 940 => "UMMCR1", + 941 => "UPMC3", + 942 => "UPMC4", + 943 => "USDA", + 952 => "MMCR0", + 953 => "PMC1", + 954 => "PMC2", + 955 => "SIA", + 956 => "MMCR1", + 957 => "PMC3", + 958 => "PMC4", + 959 => "SDA", + 1008 => "HID0", + 1009 => "HID1", + 1010 => "IABR", + 1013 => "DABR", + 1017 => "L2CR", + 1019 => "ICTC", + 1020 => "THRM1", + 1021 => "THRM2", + 1022 => "THRM3", + _ => return write!(f, "{}", self.0), + }) + } +} // Condition register field. field_arg!(CRField, u8, "cr{}"); // Condition register bit (index + condition case). -field_arg!(CRBit, u8, "{}"); +field_arg_no_display!(CRBit, u8); +impl Display for CRBit { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + let cr = self.0 >> 2; + let cc = self.0 & 3; + if cr != 0 { + write!(f, "4*{}+", CRField(cr))?; + } + const CR_NAMES: [&str; 4] = ["lt", "gt", "eq", "so"]; + f.write_str(CR_NAMES[cc as usize]) + } +} // Paired-single graphics quantization register field_arg!(GQR, u8, "qr{}"); // Unsigned immediate. @@ -129,8 +215,6 @@ impl Display for Bit { // Unsigned opaque argument. field_arg!(OpaqueU, u32); -const SPR_LR: usize = 16; - #[derive(Debug, Clone)] pub enum Argument { GPR(GPR), @@ -287,12 +371,10 @@ impl Ins { self.branch_offset().and_then(|offset| { if self.field_AA() { Some(offset as u32) + } else if offset < 0 { + self.addr.checked_sub((-offset) as u32) } else { - if offset < 0 { - self.addr.checked_sub((-offset) as u32) - } else { - self.addr.checked_add(offset as u32) - } + self.addr.checked_add(offset as u32) } }) } @@ -333,12 +415,13 @@ impl Ins { pub struct SimplifiedIns { pub ins: Ins, pub mnemonic: &'static str, + pub suffix: String, pub args: Vec, } impl Display for SimplifiedIns { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - write!(f, "{}{} ", self.mnemonic, self.ins.suffix())?; + write!(f, "{}{} ", self.mnemonic, self.suffix)?; let mut writing_offset = false; for (i, argument) in self.args.iter().enumerate() { write!(f, "{}", argument)?; @@ -363,6 +446,7 @@ impl SimplifiedIns { pub(crate) fn basic_form(ins: Ins) -> Self { Self { mnemonic: ins.op.mnemonic(), + suffix: ins.suffix(), args: ins .fields() .iter() diff --git a/disasm/tests/test_disasm.rs b/disasm/tests/test_disasm.rs index 210cd81..783f623 100644 --- a/disasm/tests/test_disasm.rs +++ b/disasm/tests/test_disasm.rs @@ -95,6 +95,7 @@ fn test_ins_b() { assert_asm!(0x4BE03C99, "bl -0x1fc368"); assert_asm!(0x4BDC1A59, "bl -0x23e5a8"); assert_asm!(0x48000063, "bla 0x60"); + assert_asm!(0x48000002, "ba 0x0"); } #[test] @@ -121,18 +122,29 @@ fn test_ins_bc() { assert_asm!(0x418502E4, "bgt cr1, 0x2e4"); assert_asm!(0x419A0138, "beq cr6, 0x138"); assert_asm!(0x419C0008, "blt cr7, 0x8"); + assert_asm!(0x4240FFF0, "bdz -0x10"); assert_asm!(0x4200F560, "bdnz -0xaa0"); + assert_asm!(0x40010014, "bdnzf gt, 0x14"); + assert_asm!(0x40410035, "bdzfl gt, 0x34"); + assert_asm!(0x41430023, "bdztla so, 0x20"); + assert_asm!(0x4108FFE3, "bdnztla 4*cr2+lt, -0x20"); + assert_asm!(0x40A20008, "bne+ 0x8"); } #[test] fn test_ins_bcctr() { assert_asm!(0x4E800420, "bctr"); assert_asm!(0x4E800421, "bctrl"); + assert_asm!(0x4D820420, "beqctr"); + assert_asm!(0x4D8D0421, "bgtctrl cr3"); + assert_asm!(0x4DA20420, "beqctr+"); + assert_asm!(0x4DB90421, "bgtctrl+ cr6"); } #[test] fn test_ins_bclr() { assert_asm!(0x4C800020, "bgelr"); + assert_asm!(0x4CA00020, "bgelr+"); assert_asm!(0x4C810020, "blelr"); assert_asm!(0x4C820020, "bnelr"); assert_asm!(0x4C9E0020, "bnelr cr7"); @@ -142,6 +154,8 @@ fn test_ins_bclr() { assert_asm!(0x4D860020, "beqlr cr1"); assert_asm!(0x4E800020, "blr"); assert_asm!(0x4E800021, "blrl"); + assert_asm!(0x4D000020, "bdnztlr lt"); + assert_asm!(0x4C1F0021, "bdnzflrl 4*cr7+so"); } #[test] @@ -149,11 +163,10 @@ fn test_ins_cmp() { assert_asm!(0x7C030000, "cmpw r3, r0"); } -/* #[test] fn test_ins_cmpi() { assert_asm!(0x2C050D00, "cmpwi r5, 0xd00"); - assert_asm!(0x2F1F0000, "cmpwi cr6, r31, 0"); + assert_asm!(0x2F1F0000, "cmpwi cr6, r31, 0x0"); } #[test] @@ -166,16 +179,52 @@ fn test_ins_cmpli() { assert_asm!(0x2803FFF3, "cmplwi r3, 0xfff3"); assert_asm!(0x2884F8F0, "cmplwi cr1, r4, 0xf8f0"); } -*/ #[test] fn test_ins_cntlzw() { assert_asm!(0x7C030034, "cntlzw r3, r0"); } +#[test] +fn test_ins_crand() { + assert_asm!(0x4C853202, "crand 4*cr1+lt, 4*cr1+gt, 4*cr1+eq"); +} + +#[test] +fn test_ins_crandc() { + assert_asm!(0x4C642902, "crandc so, 4*cr1+lt, 4*cr1+gt"); +} + +#[test] +fn test_ins_creqv() { + assert_asm!(0x4CE00A42, "creqv 4*cr1+so, lt, gt"); +} + +#[test] +fn test_ins_crnand() { + assert_asm!(0x4C2219C2, "crnand gt, eq, so"); +} + #[test] fn test_ins_cror() { - assert_asm!(0x4C411382, "cror 2, 1, 2"); + assert_asm!(0x4C411382, "cror eq, gt, eq"); + assert_asm!(0x4CA63B82, "cror 4*cr1+gt, 4*cr1+eq, 4*cr1+so"); +} + +#[test] +fn test_ins_crorc() { + assert_asm!(0x4C432342, "crorc eq, so, 4*cr1+lt"); +} + +#[test] +fn test_ins_crnor() { + assert_asm!(0x4C011042, "crnor lt, gt, eq"); + assert_asm!(0x4CA63042, "crnot 4*cr1+gt, 4*cr1+eq"); +} + +#[test] +fn test_ins_crxor() { + assert_asm!(0x4CC70182, "crxor 4*cr1+eq, 4*cr1+so, lt"); } #[test] @@ -498,7 +547,10 @@ fn test_ins_mfmsr() { #[test] fn test_ins_mfspr() { - assert_asm!(0x7E1A02A6, "mfspr r16, 26"); + assert_asm!(0x7E1A02A6, "mfsrr0 r16"); + assert_asm!(0x7C70FAA6, "mfspr r3, HID0"); + assert_asm!(0x7C7482A6, "mfibatu r3, 2"); + assert_asm!(0x7C7782A6, "mfibatl r3, 3"); } #[test] @@ -516,14 +568,14 @@ fn test_ins_mtcrf() { assert_asm!(0x7C6FF120, "mtcrf 255, r3"); } -/* #[test] -fn test_ins_mtfsb0() {} - */ +fn test_ins_mtfsb0() { + assert_asm!(0xFFA0008C, "mtfsb0 4*cr7+gt") +} #[test] fn test_ins_mtfsb1() { - assert_asm!(0xFFA0004C, "mtfsb1 29"); + assert_asm!(0xFFA0004C, "mtfsb1 4*cr7+gt"); } #[test] @@ -539,7 +591,16 @@ fn test_ins_mtmsr() { #[test] fn test_ins_mtspr() { - assert_asm!(0x7E75FBA6, "mtspr 1013, r19"); + assert_asm!(0x7E75FBA6, "mtspr DABR, r19"); + assert_asm!(0x7C70FBA6, "mtspr HID0, r3"); + assert_asm!(0x7C7603A6, "mtdec r3"); + assert_asm!(0x7C7043A6, "mtsprg 0, r3"); + assert_asm!(0x7C7143A6, "mtsprg 1, r3"); + assert_asm!(0x7C7343A6, "mtsprg 3, r3"); + assert_asm!(0x7C7083A6, "mtibatu 0, r3"); + assert_asm!(0x7C7483A6, "mtibatu 2, r3"); + assert_asm!(0x7C7783A6, "mtibatl 3, r3"); + assert_asm!(0x7C7D83A6, "mtdbatl 2, r3"); } #[test] @@ -624,7 +685,7 @@ fn test_ins_psq_lx() { rA(GPR(0)), rB(GPR(0)), ps_WX(OpaqueU(0)), - ps_IX(GQR(0)) + ps_IX(GQR(0)), ] ); assert_eq!(ins.defs(), vec![frD(FPR(0))]); @@ -792,12 +853,24 @@ fn test_ins_rlwinm() { // mnemonics assert_asm!(0x57E5103A, "slwi r5, r31, 2"); + assert_asm!(0x54832026, "extlwi r3, r4, 20, 4"); + assert_asm!(0x5483AB3E, "extrwi r3, r4, 20, 1"); + assert_asm!(0x540027BE, "extrwi r0, r0, 2, 2"); + assert_asm!(0x54839B3E, "rlwinm r3, r4, 19, 12, 31"); + assert_asm!(0x5483203E, "rotlwi r3, r4, 4"); + assert_asm!(0x5483E03E, "rotrwi r3, r4, 4"); + assert_asm!(0x5464043E, "clrlwi r4, r3, 16"); + assert_asm!(0x54830036, "clrrwi r3, r4, 4"); + assert_asm!(0x54640FBC, "clrlslwi r4, r3, 31, 1"); + assert_asm!(0x54092DB4, "clrlslwi r9, r0, 27, 5"); + assert_asm!(0x54096226, "clrlslwi r9, r0, 20, 12"); } #[test] fn test_ins_rlwnm() { assert_asm!(0x5D6A67FE, "rlwnm r10, r11, r12, 31, 31"); assert_asm!(0x5FC52EFE, "rlwnm r5, r30, r5, 27, 31"); + assert_asm!(0x5FC5283F, "rotlw. r5, r30, r5"); } #[test] diff --git a/dol/src/lib.rs b/dol/src/lib.rs index 94059b2..a544ae8 100644 --- a/dol/src/lib.rs +++ b/dol/src/lib.rs @@ -205,12 +205,9 @@ impl From<&DolHeaderData> for DolHeader { impl DolHeader { pub fn section_at(&self, addr: u32) -> Option<&DolSection> { - for section in &self.sections { - if (section.target..(section.target + section.size)).contains(&addr) { - return Some(section); - } - } - None + self.sections.iter() + .find(|§ion| (section.target..(section.target + section.size)) + .contains(&addr)) } } diff --git a/genisa/src/main.rs b/genisa/src/main.rs index c15abde..92fa847 100644 --- a/genisa/src/main.rs +++ b/genisa/src/main.rs @@ -6,7 +6,7 @@ use std::process::{Command, Stdio}; use std::str::FromStr; use itertools::Itertools; -use proc_macro2::{Ident, Literal, Span, TokenStream, TokenTree}; +use proc_macro2::{Group, Ident, Literal, Span, TokenStream, TokenTree}; use quote::quote; use serde::{Deserialize, Deserializer}; use syn::{LitChar, LitInt, LitStr}; @@ -74,8 +74,8 @@ pub(crate) struct BitRange(Range); impl<'de> Deserialize<'de> for BitRange { fn deserialize(deserializer: D) -> std::result::Result - where - D: Deserializer<'de>, + where + D: Deserializer<'de>, { let range_str: String = Deserialize::deserialize(deserializer)?; if let Some((start_str, stop_str)) = range_str.split_once("..") { @@ -232,7 +232,8 @@ impl Opcode { pub(crate) struct Mnemonic { name: String, opcode: String, - modifiers: Vec, + // Overrides modifier list from opcode + modifiers: Option>, args: Vec, condition: String, } @@ -243,23 +244,31 @@ pub(crate) struct Modifier { name: String, suffix: char, bit: u8, + condition: String, } impl Modifier { - fn express_value_self(&self) -> TokenStream { - let modifier_bit = self.bit as usize; - quote!(self.bit(#modifier_bit)) + fn express_value_self(&self, field_by_name: &HashMap) -> Result { + if self.condition.is_empty() { + let modifier_bit = self.bit as usize; + Ok(quote!(self.bit(#modifier_bit))) + } else { + compile_mnemonic_condition( + field_by_name, + &self.condition, + ) + } } - fn construct_accessor(&self) -> TokenStream { + fn construct_accessor(&self, field_by_name: &HashMap) -> Result { let field_variant = to_rust_ident("field_", &self.name); - let value = self.express_value_self(); - quote! { + let value = self.express_value_self(field_by_name)?; + Ok(quote! { #[inline(always)] pub fn #field_variant(&self) -> bool { #value } - } + }) } } @@ -482,7 +491,7 @@ impl Isa { }); // Generate modifiers. - let suffix = express_suffix(&modifier_by_name, opcode)?; + let suffix = express_suffix(&modifier_by_name, &field_by_name, &opcode.modifiers)?; suffix_match_arms.push(quote! { Opcode::#ident => #suffix, }); @@ -556,21 +565,29 @@ impl Isa { )?); // Emit branch. let mnemonic_lit = LitStr::new(&mnemonic.name, Span::call_site()); + // Emit suffix. + let modifiers = mnemonic.modifiers.as_ref().unwrap_or(&opcode.modifiers); + let suffix = express_suffix(&modifier_by_name, &field_by_name, modifiers)?; // Extract arguments. let mut args = Vec::new(); for arg in &mnemonic.args { + let (field_name, expression) = arg.split_once('=').unwrap_or((arg, arg)); let field = field_by_name - .get(arg) + .get(field_name) .unwrap_or_else(|| panic!("field not found: {}", arg)); let variant = Ident::new(field.arg.as_ref().unwrap(), Span::call_site()); - let value = field.express_value_self(); - args.push(quote!(Argument::#variant(#variant(#value as _)),)); + let value = compile_mnemonic_condition( + &field_by_name, + expression, + )?; + args.push(quote!(Argument::#variant(#variant((#value) as _)),)); } let args = token_stream!(args); simplified_conditions.push(quote! { { return SimplifiedIns { mnemonic: #mnemonic_lit, + suffix: #suffix, args: vec![#args], ins: self, }; @@ -592,11 +609,10 @@ impl Isa { let simplified_ins_match_arms = token_stream!(simplified_ins_match_arms); let field_accessors = TokenStream::from_iter(self.fields.iter().map(|field| field.construct_accessor())); - let modifier_accessors = TokenStream::from_iter( - self.modifiers - .iter() - .map(|modifier| modifier.construct_accessor()), - ); + let modifiers: Vec = self.modifiers + .iter() + .map(|modifier| modifier.construct_accessor(&field_by_name)).try_collect()?; + let modifier_accessors = TokenStream::from_iter(modifiers); // Generate final fields function. let ins_impl = quote! { #[allow(clippy::all, unused_mut)] @@ -701,31 +717,41 @@ fn compile_mnemonic_condition( code: &str, ) -> Result { let src_stream = TokenStream::from_str(code)?; - let token_iter = src_stream.into_iter().flat_map(|token| { - if let TokenTree::Ident(ref ident) = token { - if let Some(field) = field_by_name.get(&ident.to_string()) { - return field.express_value_self(); + fn map_ident(field_by_name: &HashMap, token: TokenTree) -> TokenStream { + match token { + TokenTree::Ident(ref ident) => { + if let Some(field) = field_by_name.get(&ident.to_string()) { + return field.express_value_self(); + } } + TokenTree::Group(ref group) => { + let iter = group.stream().into_iter().flat_map(|token| map_ident(field_by_name, token)); + let stream = TokenStream::from_iter(iter); + return TokenStream::from(TokenTree::Group(Group::new(group.delimiter(), stream))); + } + _ => {} } token.into() - }); + } + let token_iter = src_stream.into_iter().flat_map(|token| map_ident(field_by_name, token)); Ok(TokenStream::from_iter(token_iter)) } fn express_suffix( modifier_by_name: &HashMap, - opcode: &Opcode, + field_by_name: &HashMap, + modifiers: &[String], ) -> Result { - Ok(if opcode.modifiers.is_empty() { + Ok(if modifiers.is_empty() { quote!(String::new()) } else { let mut chars = Vec::new(); - for mod_name in &opcode.modifiers { + for mod_name in modifiers { let modifier: &Modifier = modifier_by_name .get(mod_name) .ok_or_else(|| Error::from(format!("undefined modifier {}", mod_name)))?; let lit_char = LitChar::new(modifier.suffix, Span::call_site()); - let modifier_bit = modifier.express_value_self(); + let modifier_bit = modifier.express_value_self(field_by_name)?; chars.push(quote! { if #modifier_bit { s.push(#lit_char); diff --git a/isa.yaml b/isa.yaml index c39f470..93715ca 100644 --- a/isa.yaml +++ b/isa.yaml @@ -20,7 +20,7 @@ fields: arg: OpaqueU bits: 6..11 - name: BI - arg: OpaqueU + arg: CRBit bits: 11..16 - name: BH arg: OpaqueU @@ -141,6 +141,14 @@ fields: arg: OpaqueU desc: Immediate for mtfsfi bits: 16..20 + - name: spr_SPRG + arg: OpaqueU + desc: SPRG index for m[tf]sprg + bits: 14..16 + - name: spr_BAT + arg: OpaqueU + desc: IBAT/DBAT index for m[tf][id]bat[ul] + bits: 13..15 - name: TO arg: OpaqueU desc: Bitset for tw and twi @@ -167,6 +175,18 @@ modifiers: - name: AA suffix: a bit: 30 + # Predict branch to be taken + - name: BP + suffix: + + condition: BO & 1 == 1 && BD >= 0 + # Predict branch not to be taken (fall through) + - name: BNP + suffix: '-' + condition: BO & 1 == 1 && BD < 0 + # Predict branch to be taken (implicit dest for LR/CTR) + - name: BP_ND + suffix: + + condition: BO & 1 == 1 opcodes: - name: add @@ -294,14 +314,14 @@ opcodes: desc: Branch Conditional bitmask: 0xfc000000 pattern: 0x40000000 - modifiers: [ LK, AA ] + modifiers: [ LK, AA, BP, BNP ] args: [ BO, BI, BD ] - name: bcctr desc: Branch Conditional to Count Register bitmask: 0xfc007ffe pattern: 0x4c000420 - modifiers: [ LK ] + modifiers: [ LK, BP_ND ] args: [ BO, BI, BH ] uses: [ ctr ] @@ -309,7 +329,7 @@ opcodes: desc: Branch Conditional to Link Register bitmask: 0xfc007ffe pattern: 0x4c000020 - modifiers: [ LK ] + modifiers: [ LK, BP_ND ] args: [ BO, BI, BH ] uses: [ lr ] @@ -1966,6 +1986,18 @@ mnemonics: condition: rA == 0 && rS == 0 && uimm == 0 # Rotates/Shifts + - name: rotlw + opcode: rlwnm + args: [ rA, rS, rB ] + condition: MB == 0 && ME == 31 + + # TODO rlwimi: inslwi/insrwi + + # Rotates/Shifts Immediate + - name: clrrwi + opcode: rlwinm + args: [ rA, rS, ME=31-ME ] + condition: SH == 0 && MB == 0 && ME < 32 - name: clrlwi opcode: rlwinm args: [ rA, rS, MB ] @@ -1973,7 +2005,11 @@ mnemonics: - name: rotlwi opcode: rlwinm args: [ rA, rS, SH ] - condition: MB == 0 && ME == 31 + condition: MB == 0 && ME == 31 && SH <= 16 + - name: rotrwi + opcode: rlwinm + args: [ rA, rS, SH=32-SH ] + condition: MB == 0 && ME == 31 && SH > 16 - name: slwi opcode: rlwinm args: [ rA, rS, SH ] @@ -1982,6 +2018,18 @@ mnemonics: opcode: rlwinm args: [ rA, rS, MB ] condition: ME == 31 && 32 - MB == SH + - name: clrlslwi + opcode: rlwinm + args: [ rA, rS, MB=MB+SH, SH ] + condition: SH < 32 && ME == 31 - SH + - name: extlwi + opcode: rlwinm + args: [ rA, rS, ME=ME+1, SH ] + condition: MB == 0 + - name: extrwi + opcode: rlwinm + args: [ rA, rS, MB=32-MB, SH=SH-(32-MB) ] + condition: ME == 31 && SH >= 32 - MB # Compares Word - name: cmpwi @@ -2062,11 +2110,11 @@ mnemonics: condition: crbD == crbA && crbD == crbB - name: crmove opcode: cror - args: [ crbD, crbA, crbB ] + args: [ crbD, crbA ] condition: crbA == crbB - name: crnot opcode: crnor - args: [ crbD, crbA, crbB ] + args: [ crbD, crbA ] condition: crbA == crbB # Misc @@ -2099,10 +2147,58 @@ mnemonics: opcode: mtspr args: [ rS ] condition: spr == 18 - - name: mtdbatu + - name: mtdar opcode: mtspr args: [ rS ] - condition: spr == 397 + condition: spr == 19 + - name: mtdec + opcode: mtspr + args: [ rS ] + condition: spr == 22 + - name: mtsdr1 + opcode: mtspr + args: [ rS ] + condition: spr == 25 + - name: mtsrr0 + opcode: mtspr + args: [ rS ] + condition: spr == 26 + - name: mtsrr1 + opcode: mtspr + args: [ rS ] + condition: spr == 27 + - name: mtsprg + opcode: mtspr + args: [ spr_SPRG, rS ] + condition: spr & 0b1111111100 == 272 + - name: mtear + opcode: mtspr + args: [ rS ] + condition: spr == 282 + - name: mttbl + opcode: mtspr + args: [ rS ] + condition: spr == 284 + - name: mttbu + opcode: mtspr + args: [ rS ] + condition: spr == 285 + - name: mtibatu + opcode: mtspr + args: [ spr_BAT, rS ] + condition: spr & 0b1111111001 == 528 + - name: mtibatl + opcode: mtspr + args: [ spr_BAT, rS ] + condition: spr & 0b1111111001 == 529 + - name: mtdbatu + opcode: mtspr + args: [ spr_BAT, rS ] + condition: spr & 0b1111111001 == 536 + - name: mtdbatl + opcode: mtspr + args: [ spr_BAT, rS ] + condition: spr & 0b1111111001 == 537 # Move from special-purpose register - name: mfxer @@ -2121,117 +2217,155 @@ mnemonics: opcode: mfspr args: [ rD ] condition: spr == 18 - - name: mfdbatu + - name: mfdar opcode: mfspr args: [ rD ] - condition: spr == 397 + condition: spr == 19 + - name: mfdec + opcode: mfspr + args: [ rD ] + condition: spr == 22 + - name: mfsdr1 + opcode: mfspr + args: [ rD ] + condition: spr == 25 + - name: mfsrr0 + opcode: mfspr + args: [ rD ] + condition: spr == 26 + - name: mfsrr1 + opcode: mfspr + args: [ rD ] + condition: spr == 27 + - name: mfsprg + opcode: mfspr + args: [ rD, spr_SPRG ] + condition: spr & 0b1111111100 == 272 + - name: mfear + opcode: mfspr + args: [ rD ] + condition: spr == 282 + - name: mfibatu + opcode: mfspr + args: [ rD, spr_BAT ] + condition: spr & 0b1111111001 == 528 + - name: mfibatl + opcode: mfspr + args: [ rD, spr_BAT ] + condition: spr & 0b1111111001 == 529 + - name: mfdbatu + opcode: mfspr + args: [ rD, spr_BAT ] + condition: spr & 0b1111111001 == 536 + - name: mfdbatl + opcode: mfspr + args: [ rD, spr_BAT ] + condition: spr & 0b1111111001 == 537 # Branch Conditional - # bc branch always - - name: b - opcode: bc - modifiers: [ LK, AA ] - condition: BO == 20 && BI == 0 # bc branch if negative - name: blt opcode: bc - modifiers: [ LK, AA ] args: [ BD ] - condition: BO == 12 && BI & 0b11 == 0b00 && crfS == 0 + condition: BO & 0b11110 == 12 && BI == 0 - name: blt opcode: bc - modifiers: [ LK, AA ] args: [ crfS, BD ] - condition: BO == 12 && BI & 0b11 == 0b00 + condition: BO & 0b11110 == 12 && BI & 0b11 == 0 # bc branch if not positive - name: ble opcode: bc - modifiers: [ LK, AA ] args: [ BD ] - condition: BO == 4 && BI & 0b11 == 0b01 && crfS == 0 + condition: BO & 0b11110 == 4 && BI == 1 - name: ble opcode: bc - modifiers: [ LK, AA ] args: [ crfS, BD ] - condition: BO == 4 && BI & 0b11 == 0b01 + condition: BO & 0b11110 == 4 && BI & 0b11 == 1 # bc branch if zero - name: beq opcode: bc - modifiers: [ LK, AA ] args: [ BD ] - condition: BO == 12 && BI & 0b11 == 0b10 && crfS == 0 + condition: BO & 0b11110 == 12 && BI == 2 - name: beq opcode: bc - modifiers: [ LK, AA ] args: [ crfS, BD ] - condition: BO == 12 && BI & 0b11 == 0b10 + condition: BO & 0b11110 == 12 && BI & 0b11 == 2 # bc branch if not negative - name: bge opcode: bc - modifiers: [ LK, AA ] args: [ BD ] - condition: BO == 4 && BI & 0b11 == 0b00 && crfS == 0 + condition: BO & 0b11110 == 4 && BI == 0 - name: bge opcode: bc - modifiers: [ LK, AA ] args: [ crfS, BD ] - condition: BO == 4 && BI & 0b11 == 0b00 + condition: BO & 0b11110 == 4 && BI & 0b11 == 0 # bc branch if positive - name: bgt opcode: bc - modifiers: [ LK, AA ] args: [ BD ] - condition: BO == 12 && BI & 0b11 == 0b01 && crfS == 0 + condition: BO & 0b11110 == 12 && BI == 1 - name: bgt opcode: bc - modifiers: [ LK, AA ] args: [ crfS, BD ] - condition: BO == 12 && BI & 0b11 == 0b01 + condition: BO & 0b11110 == 12 && BI & 0b11 == 1 # bc branch if not zero - name: bne opcode: bc - modifiers: [ LK, AA ] args: [ BD ] - condition: BO == 4 && BI & 0b11 == 0b10 && crfS == 0 + condition: BO & 0b11110 == 4 && BI == 2 - name: bne opcode: bc - modifiers: [ LK, AA ] args: [ crfS, BD ] - condition: BO == 4 && BI & 0b11 == 0b10 + condition: BO & 0b11110 == 4 && BI & 0b11 == 2 # bc branch if summary overflow - name: bso opcode: bc - modifiers: [ LK, AA ] args: [ BD ] - condition: BO == 12 && BI & 0b11 == 0b11 && crfS == 0 + condition: BO & 0b11110 == 12 && BI == 3 - name: bso opcode: bc - modifiers: [ LK, AA ] args: [ crfS, BD ] - condition: BO == 12 && BI & 0b11 == 0b11 + condition: BO & 0b11110 == 12 && BI & 0b11 == 3 # bc branch if not summary overflow - name: bns opcode: bc - modifiers: [ LK, AA ] args: [ BD ] - condition: BO == 4 && BI & 0b11 == 0b11 && crfS == 0 + condition: BO & 0b11110 == 4 && BI == 3 - name: bns opcode: bc - modifiers: [ LK, AA ] args: [ crfS, BD ] - condition: BO == 4 && BI & 0b11 == 0b11 + condition: BO & 0b11110 == 4 && BI & 0b11 == 3 + # bc decrement CTR, branch if CTR non-zero - name: bdnz opcode: bc - modifiers: [ LK, AA ] args: [ BD ] - condition: BO == 16 && BI == 0 + condition: BO & 0b11110 == 16 && BI == 0 + # bc decrement CTR, branch if CTR non-zero AND condition true + - name: bdnzt + opcode: bc + args: [ BI, BD ] + condition: BO & 0b11110 == 8 + # bc decrement CTR, branch if CTR non-zero AND condition false + - name: bdnzf + opcode: bc + args: [ BI, BD ] + condition: BO & 0b11110 == 0 + # bc decrement CTR, branch if CTR zero - name: bdz opcode: bc - modifiers: [ LK, AA ] args: [ BD ] - condition: BO == 18 && BI == 0 - # TODO support conditional bd... + condition: BO & 0b11110 == 18 && BI == 0 + # bc decrement CTR, branch if CTR zero AND condition true + - name: bdzt + opcode: bc + args: [ BI, BD ] + condition: BO & 0b11110 == 10 + # bc decrement CTR, branch if CTR zero AND condition false + - name: bdzf + opcode: bc + args: [ BI, BD ] + condition: BO & 0b11110 == 2 # Branch Conditional to Count Register # bcctr branch always @@ -2242,86 +2376,69 @@ mnemonics: # bcctr branch if negative - name: bltctr opcode: bcctr - modifiers: [ LK ] - condition: BO == 12 && BI & 0b11 == 0b00 && crfS == 0 + condition: BO & 0b11110 == 12 && BI == 0 - name: bltctr opcode: bcctr - modifiers: [ LK ] args: [ crfS ] - condition: BO == 12 && BI & 0b11 == 0b00 + condition: BO & 0b11110 == 12 && BI & 0b11 == 0 # bcctr branch if not positive - name: blectr opcode: bcctr - modifiers: [ LK ] - condition: BO == 4 && BI & 0b11 == 0b01 && crfS == 0 + condition: BO & 0b11110 == 4 && BI == 1 - name: blectr opcode: bcctr - modifiers: [ LK ] args: [ crfS ] - condition: BO == 4 && BI & 0b11 == 0b01 + condition: BO & 0b11110 == 4 && BI & 0b11 == 1 # bcctr branch if zero - name: beqctr opcode: bcctr - modifiers: [ LK ] - condition: BO == 12 && BI & 0b11 == 0b10 && crfS == 0 + condition: BO & 0b11110 == 12 && BI == 2 - name: beqctr opcode: bcctr - modifiers: [ LK ] args: [ crfS ] - condition: BO == 12 && BI & 0b11 == 0b10 + condition: BO & 0b11110 == 12 && BI & 0b11 == 2 # bcctr branch if not negative - name: bgectr opcode: bcctr - modifiers: [ LK ] - condition: BO == 4 && BI & 0b11 == 0b00 && crfS == 0 + condition: BO & 0b11110 == 4 && BI == 0 - name: bgectr opcode: bcctr - modifiers: [ LK ] args: [ crfS ] - condition: BO == 4 && BI & 0b11 == 0b00 + condition: BO & 0b11110 == 4 && BI & 0b11 == 0 # bcctr branch if positive - name: bgtctr opcode: bcctr - modifiers: [ LK ] - condition: BO == 12 && BI & 0b11 == 0b01 && crfS == 0 + condition: BO & 0b11110 == 12 && BI == 1 - name: bgtctr opcode: bcctr - modifiers: [ LK ] args: [ crfS ] - condition: BO == 12 && BI & 0b11 == 0b01 + condition: BO & 0b11110 == 12 && BI & 0b11 == 1 # bcctr branch if not zero - name: bnectr opcode: bcctr - modifiers: [ LK ] - condition: BO == 4 && BI & 0b11 == 0b10 && crfS == 0 + condition: BO & 0b11110 == 4 && BI == 2 - name: bnectr opcode: bcctr - modifiers: [ LK ] args: [ crfS ] - condition: BO == 4 && BI & 0b11 == 0b10 + condition: BO & 0b11110 == 4 && BI & 0b11 == 2 # bcctr branch if summary overflow - name: bsoctr opcode: bcctr - modifiers: [ LK ] - condition: BO == 12 && BI & 0b11 == 0b11 && crfS == 0 + condition: BO & 0b11110 == 12 && BI == 3 - name: bsoctr opcode: bcctr - modifiers: [ LK ] args: [ crfS ] - condition: BO == 12 && BI & 0b11 == 0b11 + condition: BO & 0b11110 == 12 && BI & 0b11 == 3 # bcctr branch if not summary overflow - name: bnsctr opcode: bcctr - modifiers: [ LK ] - condition: BO == 4 && BI & 0b11 == 0b11 && crfS == 0 + condition: BO & 0b11110 == 4 && BI == 3 - name: bnsctr opcode: bcctr - modifiers: [ LK ] args: [ crfS ] - condition: BO == 4 && BI & 0b11 == 0b11 + condition: BO & 0b11110 == 4 && BI & 0b11 == 3 # Branch Conditional to Link Register - # bclr branch always - name: blr opcode: bclr @@ -2330,80 +2447,92 @@ mnemonics: # bclr branch if negative - name: bltlr opcode: bclr - modifiers: [ LK ] - condition: BO == 12 && BI & 0b11 == 0b00 && crfS == 0 + condition: BO & 0b11110 == 12 && BI == 0 - name: bltlr opcode: bclr - modifiers: [ LK ] args: [ crfS ] - condition: BO == 12 && BI & 0b11 == 0b00 + condition: BO & 0b11110 == 12 && BI & 0b11 == 0 # bclr branch if not positive - name: blelr opcode: bclr - modifiers: [ LK ] - condition: BO == 4 && BI & 0b11 == 0b01 && crfS == 0 + condition: BO & 0b11110 == 4 && BI == 1 - name: blelr opcode: bclr - modifiers: [ LK ] args: [ crfS ] - condition: BO == 4 && BI & 0b11 == 0b01 + condition: BO & 0b11110 == 4 && BI & 0b11 == 1 # bclr branch if zero - name: beqlr opcode: bclr - modifiers: [ LK ] - condition: BO == 12 && BI & 0b11 == 0b10 && crfS == 0 + condition: BO & 0b11110 == 12 && BI == 2 - name: beqlr opcode: bclr - modifiers: [ LK ] args: [ crfS ] - condition: BO == 12 && BI & 0b11 == 0b10 + condition: BO & 0b11110 == 12 && BI & 0b11 == 2 # bclr branch if not negative - name: bgelr opcode: bclr - modifiers: [ LK ] - condition: BO == 4 && BI & 0b11 == 0b00 && crfS == 0 + condition: BO & 0b11110 == 4 && BI == 0 - name: bgelr opcode: bclr - modifiers: [ LK ] args: [ crfS ] - condition: BO == 4 && BI & 0b11 == 0b00 + condition: BO & 0b11110 == 4 && BI & 0b11 == 0 # bclr branch if positive - name: bgtlr opcode: bclr - modifiers: [ LK ] - condition: BO == 12 && BI & 0b11 == 0b01 && crfS == 0 + condition: BO & 0b11110 == 12 && BI == 1 - name: bgtlr opcode: bclr - modifiers: [ LK ] args: [ crfS ] - condition: BO == 12 && BI & 0b11 == 0b01 + condition: BO & 0b11110 == 12 && BI & 0b11 == 1 # bclr branch if not zero - name: bnelr opcode: bclr - modifiers: [ LK ] - condition: BO == 4 && BI & 0b11 == 0b10 && crfS == 0 + condition: BO & 0b11110 == 4 && BI == 2 - name: bnelr opcode: bclr - modifiers: [ LK ] args: [ crfS ] - condition: BO == 4 && BI & 0b11 == 0b10 + condition: BO & 0b11110 == 4 && BI & 0b11 == 2 # bclr branch if summary overflow - name: bsolr opcode: bclr - modifiers: [ LK ] - condition: BO == 12 && BI & 0b11 == 0b11 && crfS == 0 + condition: BO & 0b11110 == 12 && BI == 3 - name: bsolr opcode: bclr - modifiers: [ LK ] args: [ crfS ] - condition: BO == 12 && BI & 0b11 == 0b11 + condition: BO & 0b11110 == 12 && BI & 0b11 == 3 # bclr branch if not summary overflow - name: bnslr opcode: bclr - modifiers: [ LK ] - condition: BO == 4 && BI & 0b11 == 0b11 && crfS == 0 + condition: BO & 0b11110 == 4 && BI == 3 - name: bnslr opcode: bclr - modifiers: [ LK ] args: [ crfS ] - condition: BO == 4 && BI & 0b11 == 0b11 + condition: BO & 0b11110 == 4 && BI & 0b11 == 3 + # bclr decrement CTR, branch if CTR non-zero + - name: bdnzlr + opcode: bclr + condition: BO & 0b11110 == 16 && BI == 0 + # bclr decrement CTR, branch if CTR non-zero AND condition true + - name: bdnztlr + opcode: bclr + args: [ BI ] + condition: BO & 0b11110 == 8 + # bclr decrement CTR, branch if CTR non-zero AND condition false + - name: bdnzflr + opcode: bclr + args: [ BI ] + condition: BO & 0b11110 == 0 + # bclr decrement CTR, branch if CTR zero + - name: bdzlr + opcode: bclr + condition: BO & 0b11110 == 18 && BI == 0 + # bclr decrement CTR, branch if CTR zero AND condition true + - name: bdztlr + opcode: bclr + args: [ BI ] + condition: BO & 0b11110 == 10 + # bclr decrement CTR, branch if CTR zero AND condition false + - name: bdzflr + opcode: bclr + args: [ BI ] + condition: BO & 0b11110 == 0