fix bcctr and bclr

This commit is contained in:
Richard Patel 2022-04-07 04:44:38 +02:00
parent 16f955947e
commit 99c7f252f8
3 changed files with 433 additions and 183 deletions

View File

@ -500,10 +500,10 @@ impl Opcode {
if code & 0xfc000000 == 0x40000000 {
return Opcode::Bc;
}
if code & 0xfc00ffff == 0x4c000210 {
if code & 0xfc007ffe == 0x4c000420 {
return Opcode::Bcctr;
}
if code & 0xfc00fffe == 0x4c000020 {
if code & 0xfc007ffe == 0x4c000020 {
return Opcode::Bclr;
}
if code & 0xfc4007ff == 0x7c000000 {
@ -5022,7 +5022,22 @@ impl Ins {
}
}
Opcode::Bcctr => {
if ((self.code >> 21u8) & 0x1f) == 12 {
if ((self.code >> 21u8) & 0x1f) == 20 && ((self.code >> 16u8) & 0x1f) == 0 {
return SimplifiedIns {
mnemonic: "bctr",
modifiers: {
let mut m = Modifiers::default();
m.lk = self.bit(31);
m
},
args: vec![],
ins: self,
};
}
if ((self.code >> 21u8) & 0x1f) == 12
&& ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00
&& ((self.code >> 18u8) & 0x7) == 0
{
return SimplifiedIns {
mnemonic: "bltctr",
modifiers: {
@ -5030,17 +5045,27 @@ impl Ins {
m.lk = self.bit(31);
m
},
args: vec![
Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _)),
Argument::BranchDest(BranchDest(
(((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000))
<< 2u8) as _,
)),
],
args: vec![],
ins: self,
};
}
if ((self.code >> 21u8) & 0x1f) == 4 {
if ((self.code >> 21u8) & 0x1f) == 12 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00
{
return SimplifiedIns {
mnemonic: "bltctr",
modifiers: {
let mut m = Modifiers::default();
m.lk = self.bit(31);
m
},
args: vec![Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _))],
ins: self,
};
}
if ((self.code >> 21u8) & 0x1f) == 4
&& ((self.code >> 16u8) & 0x1f) & 0b11 == 0b01
&& ((self.code >> 18u8) & 0x7) == 0
{
return SimplifiedIns {
mnemonic: "blectr",
modifiers: {
@ -5048,17 +5073,27 @@ impl Ins {
m.lk = self.bit(31);
m
},
args: vec![
Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _)),
Argument::BranchDest(BranchDest(
(((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000))
<< 2u8) as _,
)),
],
args: vec![],
ins: self,
};
}
if ((self.code >> 21u8) & 0x1f) == 12 {
if ((self.code >> 21u8) & 0x1f) == 4 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b01
{
return SimplifiedIns {
mnemonic: "blectr",
modifiers: {
let mut m = Modifiers::default();
m.lk = self.bit(31);
m
},
args: vec![Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _))],
ins: self,
};
}
if ((self.code >> 21u8) & 0x1f) == 12
&& ((self.code >> 16u8) & 0x1f) & 0b11 == 0b10
&& ((self.code >> 18u8) & 0x7) == 0
{
return SimplifiedIns {
mnemonic: "beqctr",
modifiers: {
@ -5066,17 +5101,27 @@ impl Ins {
m.lk = self.bit(31);
m
},
args: vec![
Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _)),
Argument::BranchDest(BranchDest(
(((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000))
<< 2u8) as _,
)),
],
args: vec![],
ins: self,
};
}
if ((self.code >> 21u8) & 0x1f) == 4 {
if ((self.code >> 21u8) & 0x1f) == 12 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b10
{
return SimplifiedIns {
mnemonic: "beqctr",
modifiers: {
let mut m = Modifiers::default();
m.lk = self.bit(31);
m
},
args: vec![Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _))],
ins: self,
};
}
if ((self.code >> 21u8) & 0x1f) == 4
&& ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00
&& ((self.code >> 18u8) & 0x7) == 0
{
return SimplifiedIns {
mnemonic: "bgectr",
modifiers: {
@ -5084,17 +5129,27 @@ impl Ins {
m.lk = self.bit(31);
m
},
args: vec![
Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _)),
Argument::BranchDest(BranchDest(
(((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000))
<< 2u8) as _,
)),
],
args: vec![],
ins: self,
};
}
if ((self.code >> 21u8) & 0x1f) == 12 {
if ((self.code >> 21u8) & 0x1f) == 4 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00
{
return SimplifiedIns {
mnemonic: "bgectr",
modifiers: {
let mut m = Modifiers::default();
m.lk = self.bit(31);
m
},
args: vec![Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _))],
ins: self,
};
}
if ((self.code >> 21u8) & 0x1f) == 12
&& ((self.code >> 16u8) & 0x1f) & 0b11 == 0b01
&& ((self.code >> 18u8) & 0x7) == 0
{
return SimplifiedIns {
mnemonic: "bgtctr",
modifiers: {
@ -5102,17 +5157,27 @@ impl Ins {
m.lk = self.bit(31);
m
},
args: vec![
Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _)),
Argument::BranchDest(BranchDest(
(((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000))
<< 2u8) as _,
)),
],
args: vec![],
ins: self,
};
}
if ((self.code >> 21u8) & 0x1f) == 4 {
if ((self.code >> 21u8) & 0x1f) == 12 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b01
{
return SimplifiedIns {
mnemonic: "bgtctr",
modifiers: {
let mut m = Modifiers::default();
m.lk = self.bit(31);
m
},
args: vec![Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _))],
ins: self,
};
}
if ((self.code >> 21u8) & 0x1f) == 4
&& ((self.code >> 16u8) & 0x1f) & 0b11 == 0b10
&& ((self.code >> 18u8) & 0x7) == 0
{
return SimplifiedIns {
mnemonic: "bnectr",
modifiers: {
@ -5120,17 +5185,27 @@ impl Ins {
m.lk = self.bit(31);
m
},
args: vec![
Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _)),
Argument::BranchDest(BranchDest(
(((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000))
<< 2u8) as _,
)),
],
args: vec![],
ins: self,
};
}
if ((self.code >> 21u8) & 0x1f) == 12 {
if ((self.code >> 21u8) & 0x1f) == 4 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b10
{
return SimplifiedIns {
mnemonic: "bnectr",
modifiers: {
let mut m = Modifiers::default();
m.lk = self.bit(31);
m
},
args: vec![Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _))],
ins: self,
};
}
if ((self.code >> 21u8) & 0x1f) == 12
&& ((self.code >> 16u8) & 0x1f) & 0b11 == 0b11
&& ((self.code >> 18u8) & 0x7) == 0
{
return SimplifiedIns {
mnemonic: "bsoctr",
modifiers: {
@ -5138,17 +5213,27 @@ impl Ins {
m.lk = self.bit(31);
m
},
args: vec![
Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _)),
Argument::BranchDest(BranchDest(
(((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000))
<< 2u8) as _,
)),
],
args: vec![],
ins: self,
};
}
if ((self.code >> 21u8) & 0x1f) == 4 {
if ((self.code >> 21u8) & 0x1f) == 12 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b11
{
return SimplifiedIns {
mnemonic: "bsoctr",
modifiers: {
let mut m = Modifiers::default();
m.lk = self.bit(31);
m
},
args: vec![Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _))],
ins: self,
};
}
if ((self.code >> 21u8) & 0x1f) == 4
&& ((self.code >> 16u8) & 0x1f) & 0b11 == 0b11
&& ((self.code >> 18u8) & 0x7) == 0
{
return SimplifiedIns {
mnemonic: "bnsctr",
modifiers: {
@ -5156,13 +5241,20 @@ impl Ins {
m.lk = self.bit(31);
m
},
args: vec![
Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _)),
Argument::BranchDest(BranchDest(
(((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000))
<< 2u8) as _,
)),
],
args: vec![],
ins: self,
};
}
if ((self.code >> 21u8) & 0x1f) == 4 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b11
{
return SimplifiedIns {
mnemonic: "bnsctr",
modifiers: {
let mut m = Modifiers::default();
m.lk = self.bit(31);
m
},
args: vec![Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _))],
ins: self,
};
}
@ -5171,12 +5263,19 @@ impl Ins {
if ((self.code >> 21u8) & 0x1f) == 20 && ((self.code >> 16u8) & 0x1f) == 0 {
return SimplifiedIns {
mnemonic: "blr",
modifiers: Modifiers::default(),
modifiers: {
let mut m = Modifiers::default();
m.lk = self.bit(31);
m
},
args: vec![],
ins: self,
};
}
if ((self.code >> 21u8) & 0x1f) == 12 {
if ((self.code >> 21u8) & 0x1f) == 12
&& ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00
&& ((self.code >> 18u8) & 0x7) == 0
{
return SimplifiedIns {
mnemonic: "bltlr",
modifiers: {
@ -5184,17 +5283,27 @@ impl Ins {
m.lk = self.bit(31);
m
},
args: vec![
Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _)),
Argument::BranchDest(BranchDest(
(((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000))
<< 2u8) as _,
)),
],
args: vec![],
ins: self,
};
}
if ((self.code >> 21u8) & 0x1f) == 4 {
if ((self.code >> 21u8) & 0x1f) == 12 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00
{
return SimplifiedIns {
mnemonic: "bltlr",
modifiers: {
let mut m = Modifiers::default();
m.lk = self.bit(31);
m
},
args: vec![Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _))],
ins: self,
};
}
if ((self.code >> 21u8) & 0x1f) == 4
&& ((self.code >> 16u8) & 0x1f) & 0b11 == 0b01
&& ((self.code >> 18u8) & 0x7) == 0
{
return SimplifiedIns {
mnemonic: "blelr",
modifiers: {
@ -5202,17 +5311,27 @@ impl Ins {
m.lk = self.bit(31);
m
},
args: vec![
Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _)),
Argument::BranchDest(BranchDest(
(((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000))
<< 2u8) as _,
)),
],
args: vec![],
ins: self,
};
}
if ((self.code >> 21u8) & 0x1f) == 12 {
if ((self.code >> 21u8) & 0x1f) == 4 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b01
{
return SimplifiedIns {
mnemonic: "blelr",
modifiers: {
let mut m = Modifiers::default();
m.lk = self.bit(31);
m
},
args: vec![Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _))],
ins: self,
};
}
if ((self.code >> 21u8) & 0x1f) == 12
&& ((self.code >> 16u8) & 0x1f) & 0b11 == 0b10
&& ((self.code >> 18u8) & 0x7) == 0
{
return SimplifiedIns {
mnemonic: "beqlr",
modifiers: {
@ -5220,17 +5339,27 @@ impl Ins {
m.lk = self.bit(31);
m
},
args: vec![
Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _)),
Argument::BranchDest(BranchDest(
(((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000))
<< 2u8) as _,
)),
],
args: vec![],
ins: self,
};
}
if ((self.code >> 21u8) & 0x1f) == 4 {
if ((self.code >> 21u8) & 0x1f) == 12 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b10
{
return SimplifiedIns {
mnemonic: "beqlr",
modifiers: {
let mut m = Modifiers::default();
m.lk = self.bit(31);
m
},
args: vec![Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _))],
ins: self,
};
}
if ((self.code >> 21u8) & 0x1f) == 4
&& ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00
&& ((self.code >> 18u8) & 0x7) == 0
{
return SimplifiedIns {
mnemonic: "bgelr",
modifiers: {
@ -5238,17 +5367,27 @@ impl Ins {
m.lk = self.bit(31);
m
},
args: vec![
Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _)),
Argument::BranchDest(BranchDest(
(((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000))
<< 2u8) as _,
)),
],
args: vec![],
ins: self,
};
}
if ((self.code >> 21u8) & 0x1f) == 12 {
if ((self.code >> 21u8) & 0x1f) == 4 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00
{
return SimplifiedIns {
mnemonic: "bgelr",
modifiers: {
let mut m = Modifiers::default();
m.lk = self.bit(31);
m
},
args: vec![Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _))],
ins: self,
};
}
if ((self.code >> 21u8) & 0x1f) == 12
&& ((self.code >> 16u8) & 0x1f) & 0b11 == 0b01
&& ((self.code >> 18u8) & 0x7) == 0
{
return SimplifiedIns {
mnemonic: "bgtlr",
modifiers: {
@ -5256,17 +5395,27 @@ impl Ins {
m.lk = self.bit(31);
m
},
args: vec![
Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _)),
Argument::BranchDest(BranchDest(
(((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000))
<< 2u8) as _,
)),
],
args: vec![],
ins: self,
};
}
if ((self.code >> 21u8) & 0x1f) == 4 {
if ((self.code >> 21u8) & 0x1f) == 12 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b01
{
return SimplifiedIns {
mnemonic: "bgtlr",
modifiers: {
let mut m = Modifiers::default();
m.lk = self.bit(31);
m
},
args: vec![Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _))],
ins: self,
};
}
if ((self.code >> 21u8) & 0x1f) == 4
&& ((self.code >> 16u8) & 0x1f) & 0b11 == 0b10
&& ((self.code >> 18u8) & 0x7) == 0
{
return SimplifiedIns {
mnemonic: "bnelr",
modifiers: {
@ -5274,17 +5423,27 @@ impl Ins {
m.lk = self.bit(31);
m
},
args: vec![
Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _)),
Argument::BranchDest(BranchDest(
(((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000))
<< 2u8) as _,
)),
],
args: vec![],
ins: self,
};
}
if ((self.code >> 21u8) & 0x1f) == 12 {
if ((self.code >> 21u8) & 0x1f) == 4 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b10
{
return SimplifiedIns {
mnemonic: "bnelr",
modifiers: {
let mut m = Modifiers::default();
m.lk = self.bit(31);
m
},
args: vec![Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _))],
ins: self,
};
}
if ((self.code >> 21u8) & 0x1f) == 12
&& ((self.code >> 16u8) & 0x1f) & 0b11 == 0b11
&& ((self.code >> 18u8) & 0x7) == 0
{
return SimplifiedIns {
mnemonic: "bsolr",
modifiers: {
@ -5292,17 +5451,27 @@ impl Ins {
m.lk = self.bit(31);
m
},
args: vec![
Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _)),
Argument::BranchDest(BranchDest(
(((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000))
<< 2u8) as _,
)),
],
args: vec![],
ins: self,
};
}
if ((self.code >> 21u8) & 0x1f) == 4 {
if ((self.code >> 21u8) & 0x1f) == 12 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b11
{
return SimplifiedIns {
mnemonic: "bsolr",
modifiers: {
let mut m = Modifiers::default();
m.lk = self.bit(31);
m
},
args: vec![Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _))],
ins: self,
};
}
if ((self.code >> 21u8) & 0x1f) == 4
&& ((self.code >> 16u8) & 0x1f) & 0b11 == 0b11
&& ((self.code >> 18u8) & 0x7) == 0
{
return SimplifiedIns {
mnemonic: "bnslr",
modifiers: {
@ -5310,13 +5479,20 @@ impl Ins {
m.lk = self.bit(31);
m
},
args: vec![
Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _)),
Argument::BranchDest(BranchDest(
(((((self.code >> 2u8) & 0x3fff) ^ 0x2000).wrapping_sub(0x2000))
<< 2u8) as _,
)),
],
args: vec![],
ins: self,
};
}
if ((self.code >> 21u8) & 0x1f) == 4 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b11
{
return SimplifiedIns {
mnemonic: "bnslr",
modifiers: {
let mut m = Modifiers::default();
m.lk = self.bit(31);
m
},
args: vec![Argument::CRBit(CRBit(((self.code >> 18u8) & 0x7) as _))],
ins: self,
};
}

View File

@ -108,7 +108,6 @@ fn test_ins_bc() {
assert_asm!(0x408600D8, "bne cr1, 0xd8");
assert_asm!(0x4086FECC, "bne cr1, -0x134");
assert_asm!(0x409C000C, "bge cr7, 0xc");
// assert_asm!(0x40A10010, "ble+ 0x10");
assert_asm!(0x4180000C, "blt 0xc");
assert_asm!(0x4180F9C0, "blt -0x640");
assert_asm!(0x4181021C, "bgt 0x21c");
@ -124,15 +123,12 @@ fn test_ins_bc() {
assert_asm!(0x4200F560, "bdnz -0xaa0");
}
/*
#[test]
fn test_ins_bcctr() {
assert_asm!(0x4E800420, "bctr");
assert_asm!(0x4E800421, "bctrl");
}
*/
/*
#[test]
fn test_ins_bclr() {
assert_asm!(0x4C800020, "bgelr");
@ -146,7 +142,6 @@ fn test_ins_bclr() {
assert_asm!(0x4E800020, "blr");
assert_asm!(0x4E800021, "blrl");
}
*/
#[test]
fn test_ins_cmp() {

173
isa.yaml
View File

@ -279,15 +279,15 @@ opcodes:
- name: bcctr
desc: Branch Conditional to Count Register
bitmask: 0xfc00ffff
pattern: 0x4c000210
bitmask: 0xfc007ffe
pattern: 0x4c000420
modifiers: [ LK ]
args: [ BO, BI ]
uses: [ ctr ]
- name: bclr
desc: Branch Conditional to Link Register
bitmask: 0xfc00fffe
bitmask: 0xfc007ffe
pattern: 0x4c000020
modifiers: [ LK ]
args: [ BO, BI ]
@ -2033,10 +2033,6 @@ mnemonics:
- name: twui
args: [ rA, simm ]
condition: TO == 31
# Branches
- name: blr
opcode: bclr
condition: BO == 20 && BI == 0
# Move to special-purpose register
- name: mtxer
@ -2091,7 +2087,6 @@ mnemonics:
condition: spr == 571
# Branch Conditional
# bc branch if negative
- name: blt
opcode: bc
@ -2103,7 +2098,6 @@ mnemonics:
modifiers: [ AA, LK ]
args: [ crfS, BD ]
condition: BO == 12 && BI & 0b11 == 0b00
# bc branch if not positive
- name: ble
opcode: bc
@ -2115,7 +2109,6 @@ mnemonics:
modifiers: [ AA, LK ]
args: [ crfS, BD ]
condition: BO == 4 && BI & 0b11 == 0b01
# bc branch if zero
- name: beq
opcode: bc
@ -2127,7 +2120,6 @@ mnemonics:
modifiers: [ AA, LK ]
args: [ crfS, BD ]
condition: BO == 12 && BI & 0b11 == 0b10
# bc branch if not negative
- name: bge
opcode: bc
@ -2139,7 +2131,6 @@ mnemonics:
modifiers: [ AA, LK ]
args: [ crfS, BD ]
condition: BO == 4 && BI & 0b11 == 0b00
# bc branch if positive
- name: bgt
opcode: bc
@ -2151,7 +2142,6 @@ mnemonics:
modifiers: [ AA, LK ]
args: [ crfS, BD ]
condition: BO == 12 && BI & 0b11 == 0b01
# bc branch if not zero
- name: bne
opcode: bc
@ -2163,7 +2153,6 @@ mnemonics:
modifiers: [ AA, LK ]
args: [ crfS, BD ]
condition: BO == 4 && BI & 0b11 == 0b10
# bc branch if summary overflow
- name: bso
opcode: bc
@ -2175,7 +2164,6 @@ mnemonics:
modifiers: [ AA, LK ]
args: [ crfS, BD ]
condition: BO == 12 && BI & 0b11 == 0b11
# bc branch if not summary overflow
- name: bns
opcode: bc
@ -2201,85 +2189,176 @@ mnemonics:
# TODO support conditional bd...
# Branch Conditional to Count Register
# bcctr branch always
- name: bctr
opcode: bcctr
modifiers: [ LK ]
condition: BO == 20 && BI == 0
# bcctr branch if negative
- name: bltctr
opcode: bcctr
modifiers: [ LK ]
args: [ crfS, BD ]
condition: BO == 12
condition: BO == 12 && BI & 0b11 == 0b00 && crfS == 0
- name: bltctr
opcode: bcctr
modifiers: [ LK ]
args: [ crfS ]
condition: BO == 12 && BI & 0b11 == 0b00
# bcctr branch if not positive
- name: blectr
opcode: bcctr
modifiers: [ LK ]
args: [ crfS, BD ]
condition: BO == 4
condition: BO == 4 && BI & 0b11 == 0b01 && crfS == 0
- name: blectr
opcode: bcctr
modifiers: [ LK ]
args: [ crfS ]
condition: BO == 4 && BI & 0b11 == 0b01
# bcctr branch if zero
- name: beqctr
opcode: bcctr
modifiers: [ LK ]
args: [ crfS, BD ]
condition: BO == 12
condition: BO == 12 && BI & 0b11 == 0b10 && crfS == 0
- name: beqctr
opcode: bcctr
modifiers: [ LK ]
args: [ crfS ]
condition: BO == 12 && BI & 0b11 == 0b10
# bcctr branch if not negative
- name: bgectr
opcode: bcctr
modifiers: [ LK ]
args: [ crfS, BD ]
condition: BO == 4
condition: BO == 4 && BI & 0b11 == 0b00 && crfS == 0
- name: bgectr
opcode: bcctr
modifiers: [ LK ]
args: [ crfS ]
condition: BO == 4 && BI & 0b11 == 0b00
# bcctr branch if positive
- name: bgtctr
opcode: bcctr
modifiers: [ LK ]
args: [ crfS, BD ]
condition: BO == 12
condition: BO == 12 && BI & 0b11 == 0b01 && crfS == 0
- name: bgtctr
opcode: bcctr
modifiers: [ LK ]
args: [ crfS ]
condition: BO == 12 && BI & 0b11 == 0b01
# bcctr branch if not zero
- name: bnectr
opcode: bcctr
modifiers: [ LK ]
args: [ crfS, BD ]
condition: BO == 4
condition: BO == 4 && BI & 0b11 == 0b10 && crfS == 0
- name: bnectr
opcode: bcctr
modifiers: [ LK ]
args: [ crfS ]
condition: BO == 4 && BI & 0b11 == 0b10
# bcctr branch if summary overflow
- name: bsoctr
opcode: bcctr
modifiers: [ LK ]
args: [ crfS, BD ]
condition: BO == 12
condition: BO == 12 && BI & 0b11 == 0b11 && crfS == 0
- name: bsoctr
opcode: bcctr
modifiers: [ LK ]
args: [ crfS ]
condition: BO == 12 && BI & 0b11 == 0b11
# bcctr branch if not summary overflow
- name: bnsctr
opcode: bcctr
modifiers: [ LK ]
args: [ crfS, BD ]
condition: BO == 4
condition: BO == 4 && BI & 0b11 == 0b11 && crfS == 0
- name: bnsctr
opcode: bcctr
modifiers: [ LK ]
args: [ crfS ]
condition: BO == 4 && BI & 0b11 == 0b11
# Branch Conditional to Link Register
# bclr branch always
- name: blr
opcode: bclr
modifiers: [ LK ]
condition: BO == 20 && BI == 0
# bclr branch if negative
- name: bltlr
opcode: bclr
modifiers: [ LK ]
args: [ crfS, BD ]
condition: BO == 12
condition: BO == 12 && BI & 0b11 == 0b00 && crfS == 0
- name: bltlr
opcode: bclr
modifiers: [ LK ]
args: [ crfS ]
condition: BO == 12 && BI & 0b11 == 0b00
# bclr branch if not positive
- name: blelr
opcode: bclr
modifiers: [ LK ]
args: [ crfS, BD ]
condition: BO == 4
condition: BO == 4 && BI & 0b11 == 0b01 && crfS == 0
- name: blelr
opcode: bclr
modifiers: [ LK ]
args: [ crfS ]
condition: BO == 4 && BI & 0b11 == 0b01
# bclr branch if zero
- name: beqlr
opcode: bclr
modifiers: [ LK ]
args: [ crfS, BD ]
condition: BO == 12
condition: BO == 12 && BI & 0b11 == 0b10 && crfS == 0
- name: beqlr
opcode: bclr
modifiers: [ LK ]
args: [ crfS ]
condition: BO == 12 && BI & 0b11 == 0b10
# bclr branch if not negative
- name: bgelr
opcode: bclr
modifiers: [ LK ]
args: [ crfS, BD ]
condition: BO == 4
condition: BO == 4 && BI & 0b11 == 0b00 && crfS == 0
- name: bgelr
opcode: bclr
modifiers: [ LK ]
args: [ crfS ]
condition: BO == 4 && BI & 0b11 == 0b00
# bclr branch if positive
- name: bgtlr
opcode: bclr
modifiers: [ LK ]
args: [ crfS, BD ]
condition: BO == 12
condition: BO == 12 && BI & 0b11 == 0b01 && crfS == 0
- name: bgtlr
opcode: bclr
modifiers: [ LK ]
args: [ crfS ]
condition: BO == 12 && BI & 0b11 == 0b01
# bclr branch if not zero
- name: bnelr
opcode: bclr
modifiers: [ LK ]
args: [ crfS, BD ]
condition: BO == 4
condition: BO == 4 && BI & 0b11 == 0b10 && crfS == 0
- name: bnelr
opcode: bclr
modifiers: [ LK ]
args: [ crfS ]
condition: BO == 4 && BI & 0b11 == 0b10
# bclr branch if summary overflow
- name: bsolr
opcode: bclr
modifiers: [ LK ]
args: [ crfS, BD ]
condition: BO == 12
condition: BO == 12 && BI & 0b11 == 0b11 && crfS == 0
- name: bsolr
opcode: bclr
modifiers: [ LK ]
args: [ crfS ]
condition: BO == 12 && BI & 0b11 == 0b11
# bclr branch if not summary overflow
- name: bnslr
opcode: bclr
modifiers: [ LK ]
args: [ crfS, BD ]
condition: BO == 4
condition: BO == 4 && BI & 0b11 == 0b11 && crfS == 0
- name: bnslr
opcode: bclr
modifiers: [ LK ]
args: [ crfS ]
condition: BO == 4 && BI & 0b11 == 0b11