disasm: branch helpers, fix split fields

This commit is contained in:
Richard Patel 2022-04-11 00:08:39 +02:00
parent 5c4a3d01e5
commit a80372c1b6
4 changed files with 126 additions and 20 deletions

View File

@ -1808,7 +1808,11 @@ impl Ins {
Opcode::Mfmsr => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))], Opcode::Mfmsr => vec![Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _))],
Opcode::Mfspr => vec![ Opcode::Mfspr => vec![
Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), 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![ Opcode::Mfsr => vec![
Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)),
@ -1820,7 +1824,11 @@ impl Ins {
], ],
Opcode::Mftb => vec![ Opcode::Mftb => vec![
Field::rD(GPR(((self.code >> 21u8) & 0x1f) as _)), 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![ Opcode::Mtcrf => vec![
Field::crm(OpaqueU(((self.code >> 12u8) & 0xff) as _)), 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::Mtmsr => vec![Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _))],
Opcode::Mtspr => vec![ 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 _)), Field::rS(GPR(((self.code >> 21u8) & 0x1f) as _)),
], ],
Opcode::Mtsr => vec![ Opcode::Mtsr => vec![
@ -4971,6 +4983,13 @@ impl Ins {
} }
} }
Opcode::Bc => { 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 if ((self.code >> 21u8) & 0x1f) == 12
&& ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00 && ((self.code >> 16u8) & 0x1f) & 0b11 == 0b00
&& ((self.code >> 18u8) & 0x7) == 0 && ((self.code >> 18u8) & 0x7) == 0
@ -5637,42 +5656,66 @@ impl Ins {
} }
} }
Opcode::Mfspr => { 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 { return SimplifiedIns {
mnemonic: "mfxer", mnemonic: "mfxer",
args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))],
ins: self, 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 { return SimplifiedIns {
mnemonic: "mflr", mnemonic: "mflr",
args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))],
ins: self, 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 { return SimplifiedIns {
mnemonic: "mfctr", mnemonic: "mfctr",
args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))],
ins: self, 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 { return SimplifiedIns {
mnemonic: "mfdsisr", mnemonic: "mfdsisr",
args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))],
ins: self, 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 { return SimplifiedIns {
mnemonic: "mfdbatu", mnemonic: "mfdbatu",
args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))],
ins: self, 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 { return SimplifiedIns {
mnemonic: "mftdu", mnemonic: "mftdu",
args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))],
@ -5681,42 +5724,66 @@ impl Ins {
} }
} }
Opcode::Mtspr => { 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 { return SimplifiedIns {
mnemonic: "mtxer", mnemonic: "mtxer",
args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))],
ins: self, 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 { return SimplifiedIns {
mnemonic: "mtlr", mnemonic: "mtlr",
args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))],
ins: self, 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 { return SimplifiedIns {
mnemonic: "mtctr", mnemonic: "mtctr",
args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))],
ins: self, 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 { return SimplifiedIns {
mnemonic: "mtdsisr", mnemonic: "mtdsisr",
args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))],
ins: self, 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 { return SimplifiedIns {
mnemonic: "mtdbatu", mnemonic: "mtdbatu",
args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))],
ins: self, 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 { return SimplifiedIns {
mnemonic: "mttdu", mnemonic: "mttdu",
args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))], args: vec![Argument::GPR(GPR(((self.code >> 21u8) & 0x1f) as _))],
@ -5901,7 +5968,8 @@ impl Ins {
} }
#[inline(always)] #[inline(always)]
pub fn field_spr(&self) -> usize { 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)] #[inline(always)]
pub fn field_frS(&self) -> usize { pub fn field_frS(&self) -> usize {
@ -5961,7 +6029,8 @@ impl Ins {
} }
#[inline(always)] #[inline(always)]
pub fn field_tbr(&self) -> usize { 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)] #[inline(always)]
pub fn field_mtfsf_FM(&self) -> usize { pub fn field_mtfsf_FM(&self) -> usize {

View File

@ -129,6 +129,8 @@ impl Display for Bit {
// Unsigned opaque argument. // Unsigned opaque argument.
field_arg!(OpaqueU, u32); field_arg!(OpaqueU, u32);
const SPR_LR: usize = 16;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum Argument { pub enum Argument {
GPR(GPR), GPR(GPR),
@ -166,9 +168,9 @@ impl Display for Argument {
} }
} }
impl Into<i64> for Argument { impl From<Argument> for i64 {
fn into(self) -> i64 { fn from(arg: Argument) -> Self {
match self { match arg {
Argument::GPR(x) => x.0 as i64, Argument::GPR(x) => x.0 as i64,
Argument::FPR(x) => x.0 as i64, Argument::FPR(x) => x.0 as i64,
Argument::SR(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. /// A simplified PowerPC 750CL instruction.

View File

@ -128,6 +128,10 @@ impl Field {
val = quote!((#val & #mask)); 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 // https://graphics.stanford.edu/~seander/bithacks.html#VariableSignExtend
if self.signed { if self.signed {
let mask2 = 1u32 << (self.bits.0.len() - 1); let mask2 = 1u32 << (self.bits.0.len() - 1);

View File

@ -2112,6 +2112,11 @@ mnemonics:
condition: spr == 571 condition: spr == 571
# Branch Conditional # Branch Conditional
# bc branch always
- name: b
opcode: bc
modifiers: [ AA, LK ]
condition: BO == 20 && BI == 0
# bc branch if negative # bc branch if negative
- name: blt - name: blt
opcode: bc opcode: bc