disasm: branch helpers, fix split fields
This commit is contained in:
parent
5c4a3d01e5
commit
a80372c1b6
|
@ -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 {
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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);
|
||||||
|
|
5
isa.yaml
5
isa.yaml
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue