diff --git a/dcb-exe/src/exe/inst/basic/cond.rs b/dcb-exe/src/exe/inst/basic/cond.rs index 2b8f71f..1e883e0 100644 --- a/dcb-exe/src/exe/inst/basic/cond.rs +++ b/dcb-exe/src/exe/inst/basic/cond.rs @@ -55,23 +55,6 @@ pub enum Kind { GreaterOrEqualZeroLink, } -impl Kind { - /// Returns this instruction kind's mnemonic - #[must_use] - pub const fn mnemonic(self) -> &'static str { - match self { - Self::Equal(_) => "beq", - Self::NotEqual(_) => "bne", - Self::LessOrEqualZero => "blez", - Self::GreaterThanZero => "bgtz", - Self::LessThanZero => "bltz", - Self::GreaterOrEqualZero => "bgez", - Self::LessThanZeroLink => "bltzal", - Self::GreaterOrEqualZeroLink => "bgezal", - } - } -} - /// Condition instructions #[derive(PartialEq, Eq, Clone, Copy, Debug)] pub struct Inst { @@ -158,15 +141,24 @@ impl Inst { pub fn fmt_target<'a>(self, target: impl fmt::Display + 'a) -> impl fmt::Display + 'a { dcb_util::DisplayWrapper::new(move |f| { let Self { kind, arg, .. } = self; - let mnemonic = kind.mnemonic(); + + // `beq $zr, $zr, offset` => `b offset` + // `beq $zr, $arg, offset` => `beqz $arg, offset` + // `beq $zr, $arg, offset` => `bnez $arg, offset` match kind { - Kind::Equal(reg) | Kind::NotEqual(reg) => write!(f, "{mnemonic} {arg}, {reg}, {target}"), - Kind::LessOrEqualZero | - Kind::GreaterThanZero | - Kind::LessThanZero | - Kind::GreaterOrEqualZero | - Kind::LessThanZeroLink | - Kind::GreaterOrEqualZeroLink => write!(f, "{mnemonic} {arg}, {target}"), + Kind::Equal(Register::Zr) => match arg { + Register::Zr => write!(f, "b {target}"), + arg => write!(f, "beqz {arg}, {target}"), + }, + Kind::Equal(reg) => write!(f, "beq {arg}, {reg}, {target}"), + Kind::NotEqual(Register::Zr) => write!(f, "bnez {arg}, {target}"), + Kind::NotEqual(reg) => write!(f, "bne {arg}, {reg}, {target}"), + Kind::LessOrEqualZero => write!(f, "blez {arg}, {target}"), + Kind::GreaterThanZero => write!(f, "bgtz {arg}, {target}"), + Kind::LessThanZero => write!(f, "bltz {arg}, {target}"), + Kind::GreaterOrEqualZero => write!(f, "bgez {arg}, {target}"), + Kind::LessThanZeroLink => write!(f, "bltzal {arg}, {target}"), + Kind::GreaterOrEqualZeroLink => write!(f, "bgezal {arg}, {target}"), } }) } diff --git a/dcb-exe/src/exe/inst/basic/jmp/reg.rs b/dcb-exe/src/exe/inst/basic/jmp/reg.rs index f4c074a..2711346 100644 --- a/dcb-exe/src/exe/inst/basic/jmp/reg.rs +++ b/dcb-exe/src/exe/inst/basic/jmp/reg.rs @@ -84,7 +84,11 @@ impl InstFmt for Inst { match kind { Kind::Jump => write!(f, "{mnemonic} {target}"), - Kind::JumpLink(reg) => write!(f, "{mnemonic} {target}, {reg}"), + Kind::JumpLink(reg) => match reg { + // If using `$ra`, don't output it. + Register::Ra => write!(f, "{mnemonic} {target}"), + reg => write!(f, "{mnemonic} {target}, {reg}"), + }, } } } diff --git a/dcb-exe/src/exe/inst/pseudo.rs b/dcb-exe/src/exe/inst/pseudo.rs index 98ba054..85fb65b 100644 --- a/dcb-exe/src/exe/inst/pseudo.rs +++ b/dcb-exe/src/exe/inst/pseudo.rs @@ -6,7 +6,6 @@ // Modules pub mod alu_assign; -pub mod jmp; pub mod load; pub mod load_imm; pub mod move_reg; @@ -36,9 +35,6 @@ pub enum Inst { /// Move register MoveReg(move_reg::Inst), - /// Jump - Jmp(jmp::Inst), - /// Load Load(load::Inst), @@ -53,7 +49,6 @@ impl Decodable for Inst { .or_else( || nop ::Inst::decode(insts.clone()).map(Self::Nop )) // Note: Nop must come before `shift_assign` .or_else( || alu_assign ::Inst::decode(insts.clone()).map(Self::AluAssign )) .or_else( || shift_assign::Inst::decode(insts.clone()).map(Self::ShiftAssign)) - .or_else( || jmp ::Inst::decode(insts.clone()).map(Self::Jmp )) .or_else( || load ::Inst::decode(insts.clone()).map(Self::Load )) .or_else( || store ::Inst::decode(insts.clone()).map(Self::Store )) .or_else(move || move_reg ::Inst::decode( insts ).map(Self::MoveReg )) @@ -68,7 +63,6 @@ impl InstSize for Inst { Self::LoadImm(inst) => inst.size(), Self::Nop(inst) => inst.size(), Self::MoveReg(inst) => inst.size(), - Self::Jmp(inst) => inst.size(), Self::Load(inst) => inst.size(), Self::Store(inst) => inst.size(), } @@ -83,7 +77,6 @@ impl InstFmt for Inst { Self::LoadImm(inst) => inst.fmt(pos, f), Self::Nop(inst) => inst.fmt(pos, f), Self::MoveReg(inst) => inst.fmt(pos, f), - Self::Jmp(inst) => inst.fmt(pos, f), Self::Load(inst) => inst.fmt(pos, f), Self::Store(inst) => inst.fmt(pos, f), } diff --git a/dcb-exe/src/exe/inst/pseudo/jmp.rs b/dcb-exe/src/exe/inst/pseudo/jmp.rs deleted file mode 100644 index db0198e..0000000 --- a/dcb-exe/src/exe/inst/pseudo/jmp.rs +++ /dev/null @@ -1,88 +0,0 @@ -//! Jump pseudo instructions - -// Imports -use crate::exe::inst::{basic, InstFmt, InstSize, Register}; - -use super::Decodable; - -/// Jump / Branch instructions -#[derive(PartialEq, Eq, Clone, Copy, Debug)] -pub enum Inst { - /// Jump and link with return address - /// Alias for `jalr $target, $ra` - JalrRa { - /// Target for the jump - target: Register, - }, - - /// Branch if equal to zero - /// Alias for `beq $arg, $zr, offset` - Beqz { - /// Argument to compare - arg: Register, - - /// Jump offset - offset: i16, - }, - - /// Branch if different from zero - /// Alias for `bne $arg, $zr, offset` - Bnez { - /// Argument to compare - arg: Register, - - /// Jump offset - offset: i16, - }, - - /// Jump relative - /// Alias for `beq $zr, $zr, offset` - B { - /// Jump offset - offset: i16, - }, -} - -impl Decodable for Inst { - fn decode(mut insts: impl Iterator + Clone) -> Option { - let inst = match insts.next()? { - basic::Inst::Cond(basic::cond::Inst { arg, offset, kind }) => match kind { - basic::cond::Kind::Equal(Register::Zr) => match arg { - // `beq $zr, $zr, offset` - Register::Zr => Self::B { offset }, - // `beq $zr, $arg, offset` - _ => Self::Beqz { arg, offset }, - }, - // `bnq $zr, $arg, offset` - basic::cond::Kind::NotEqual(Register::Zr) => Self::Bnez { arg, offset }, - _ => return None, - }, - // `jalr $ra, $target` - basic::Inst::Jmp(basic::jmp::Inst::Reg(basic::jmp::reg::Inst { - target, - kind: basic::jmp::reg::Kind::JumpLink(Register::Ra), - })) => Self::JalrRa { target }, - - _ => return None, - }; - - Some(inst) - } -} - -impl InstSize for Inst { - fn size(&self) -> usize { - 4 - } -} - -impl InstFmt for Inst { - fn fmt(&self, pos: crate::Pos, f: &mut std::fmt::Formatter) -> std::fmt::Result { - match *self { - Self::JalrRa { target } => write!(f, "jalr {target}"), - Self::Beqz { arg, offset } => write!(f, "beqz {arg}, {}", basic::cond::Inst::target_of(offset, pos)), - Self::Bnez { arg, offset } => write!(f, "bnez {arg}, {}", basic::cond::Inst::target_of(offset, pos)), - Self::B { offset } => write!(f, "b {}", basic::cond::Inst::target_of(offset, pos)), - } - } -} diff --git a/dcb-tools/src/decompiler/main.rs b/dcb-tools/src/decompiler/main.rs index 546fba4..ed7397f 100644 --- a/dcb-tools/src/decompiler/main.rs +++ b/dcb-tools/src/decompiler/main.rs @@ -165,7 +165,6 @@ fn main() -> Result<(), anyhow::Error> { Inst::Basic (basic ::Inst::Load (inst)) => print!("{}", inst.fmt_value(pos)), Inst::Basic (basic ::Inst::Store (inst)) => print!("{}", inst.fmt_value(pos)), Inst::Pseudo(pseudo::Inst::LoadImm(inst)) => print!("{}", inst.fmt_value(pos)), - Inst::Pseudo(pseudo::Inst::Jmp (inst)) => print!("{}", inst.fmt_value(pos)), Inst::Pseudo(pseudo::Inst::Load (inst)) => print!("{}", inst.fmt_value(pos)), Inst::Pseudo(pseudo::Inst::Store (inst)) => print!("{}", inst.fmt_value(pos)), inst => print!("{}", inst.fmt_value(pos)),