From a80372c1b68bb87c0934c25725c5a3de0b52ebed Mon Sep 17 00:00:00 2001 From: Richard Patel Date: Mon, 11 Apr 2022 00:08:39 +0200 Subject: [PATCH] disasm: branch helpers, fix split fields --- disasm/src/generated.rs | 103 +++++++++++++++++++++++++++++++++------- disasm/src/lib.rs | 34 +++++++++++-- genisa/src/main.rs | 4 ++ isa.yaml | 5 ++ 4 files changed, 126 insertions(+), 20 deletions(-) diff --git a/disasm/src/generated.rs b/disasm/src/generated.rs index c1a3e61..86cbc1c 100644 --- a/disasm/src/generated.rs +++ b/disasm/src/generated.rs @@ -1808,7 +1808,11 @@ impl Ins { Opcode::Mfmsr => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], Opcode::Mfspr => vec![ Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), - Field::spr(SPR(((self.code >> 11u8) & 0x3ff) as _)), + Field::spr(SPR( + (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 as _, + )), ], Opcode::Mfsr => vec![ Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), @@ -1820,7 +1824,11 @@ impl Ins { ], Opcode::Mftb => vec![ Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), - Field::tbr(OpaqueU(((self.code >> 11u8) & 0x3ff) as _)), + Field::tbr(OpaqueU( + (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 as _, + )), ], Opcode::Mtcrf => vec![ Field::crm(OpaqueU(((self.code >> 12u8) & 0xff) as _)), @@ -1838,7 +1846,11 @@ impl Ins { ], Opcode::Mtmsr => vec![Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _))], Opcode::Mtspr => vec![ - Field::spr(SPR(((self.code >> 11u8) & 0x3ff) as _)), + Field::spr(SPR( + (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 as _, + )), Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)), ], Opcode::Mtsr => vec![ @@ -4971,6 +4983,13 @@ 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 @@ -5637,42 +5656,66 @@ impl Ins { } } Opcode::Mfspr => { - if ((self.code >> 11u8) & 0x3ff) == 1 { + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + == 1 + { return SimplifiedIns { mnemonic: "mfxer", args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], ins: self, }; } - if ((self.code >> 11u8) & 0x3ff) == 8 { + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + == 8 + { return SimplifiedIns { mnemonic: "mflr", args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], ins: self, }; } - if ((self.code >> 11u8) & 0x3ff) == 9 { + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + == 9 + { return SimplifiedIns { mnemonic: "mfctr", args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], ins: self, }; } - if ((self.code >> 11u8) & 0x3ff) == 18 { + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + == 18 + { return SimplifiedIns { mnemonic: "mfdsisr", args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], ins: self, }; } - if ((self.code >> 11u8) & 0x3ff) == 397 { + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + == 397 + { return SimplifiedIns { mnemonic: "mfdbatu", args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], ins: self, }; } - if ((self.code >> 11u8) & 0x3ff) == 571 { + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + == 571 + { return SimplifiedIns { mnemonic: "mftdu", args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], @@ -5681,42 +5724,66 @@ impl Ins { } } Opcode::Mtspr => { - if ((self.code >> 11u8) & 0x3ff) == 1 { + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + == 1 + { return SimplifiedIns { mnemonic: "mtxer", args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], ins: self, }; } - if ((self.code >> 11u8) & 0x3ff) == 8 { + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + == 8 + { return SimplifiedIns { mnemonic: "mtlr", args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], ins: self, }; } - if ((self.code >> 11u8) & 0x3ff) == 9 { + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + == 9 + { return SimplifiedIns { mnemonic: "mtctr", args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], ins: self, }; } - if ((self.code >> 11u8) & 0x3ff) == 18 { + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + == 18 + { return SimplifiedIns { mnemonic: "mtdsisr", args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], ins: self, }; } - if ((self.code >> 11u8) & 0x3ff) == 397 { + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + == 397 + { return SimplifiedIns { mnemonic: "mtdbatu", args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], ins: self, }; } - if ((self.code >> 11u8) & 0x3ff) == 571 { + if (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) + as u32 + == 571 + { return SimplifiedIns { mnemonic: "mttdu", args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], @@ -5901,7 +5968,8 @@ impl Ins { } #[inline(always)] pub fn field_spr(&self) -> usize { - ((self.code >> 11u8) & 0x3ff) as _ + (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) as u32 as _ } #[inline(always)] pub fn field_frS(&self) -> usize { @@ -5961,7 +6029,8 @@ impl Ins { } #[inline(always)] pub fn field_tbr(&self) -> usize { - ((self.code >> 11u8) & 0x3ff) as _ + (((((self.code >> 11u8) & 0x3ff) & 0b11111_00000u32) >> 5u32) + | ((((self.code >> 11u8) & 0x3ff) & 0b00000_11111u32) << 5u32)) as u32 as _ } #[inline(always)] pub fn field_mtfsf_FM(&self) -> usize { diff --git a/disasm/src/lib.rs b/disasm/src/lib.rs index 6803399..5ba3526 100644 --- a/disasm/src/lib.rs +++ b/disasm/src/lib.rs @@ -129,6 +129,8 @@ impl Display for Bit { // Unsigned opaque argument. field_arg!(OpaqueU, u32); +const SPR_LR: usize = 16; + #[derive(Debug, Clone)] pub enum Argument { GPR(GPR), @@ -166,9 +168,9 @@ impl Display for Argument { } } -impl Into for Argument { - fn into(self) -> i64 { - match self { +impl From for i64 { + fn from(arg: Argument) -> Self { + match arg { Argument::GPR(x) => x.0 as i64, Argument::FPR(x) => x.0 as i64, Argument::SR(x) => x.0 as i64, @@ -288,6 +290,32 @@ impl Ins { } }) } + + pub fn is_branch(&self) -> bool { + match self.op { + Opcode::B | Opcode::Bc | Opcode::Bcctr | Opcode::Bclr => true, + _ => false, + } + } + + pub fn is_unconditional_branch(&self) -> bool { + match self.op { + Opcode::B => true, + Opcode::Bc | Opcode::Bcctr | Opcode::Bclr => { + self.field_BO() == 20 && self.field_BI() == 0 + } + _ => false, + } + } + + pub fn is_conditional_branch(&self) -> bool { + self.is_branch() && !self.is_unconditional_branch() + } + + pub fn is_blr(&self) -> bool { + // self.op == Opcode::Bclr && self.is_unconditional_branch() && !self.field_LK() + self.code == 0x4e800020 + } } /// A simplified PowerPC 750CL instruction. diff --git a/genisa/src/main.rs b/genisa/src/main.rs index 978f230..aaf807f 100644 --- a/genisa/src/main.rs +++ b/genisa/src/main.rs @@ -128,6 +128,10 @@ impl Field { val = quote!((#val & #mask)); } + if self.split { + val = quote!((((#val & 0b11111_00000u32) >> 5u32) | ((#val & 0b00000_11111u32) << 5u32)) as u32); + } + // https://graphics.stanford.edu/~seander/bithacks.html#VariableSignExtend if self.signed { let mask2 = 1u32 << (self.bits.0.len() - 1); diff --git a/isa.yaml b/isa.yaml index 58d884b..b5680d5 100644 --- a/isa.yaml +++ b/isa.yaml @@ -2112,6 +2112,11 @@ mnemonics: condition: spr == 571 # Branch Conditional + # bc branch always + - name: b + opcode: bc + modifiers: [ AA, LK ] + condition: BO == 20 && BI == 0 # bc branch if negative - name: blt opcode: bc