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::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 {

View File

@ -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<i64> for Argument {
fn into(self) -> i64 {
match self {
impl From<Argument> 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.

View File

@ -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);

View File

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