Removed pseudo::jmp and made basic::{cond, jmp::reg} write the pseudo instrutions.

This commit is contained in:
2021-01-12 01:30:30 +00:00
parent 220d0068a6
commit 27fc4e4a5a
5 changed files with 22 additions and 122 deletions

View File

@@ -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}"),
}
})
}

View File

@@ -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}"),
},
}
}
}

View File

@@ -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),
}

View File

@@ -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<Item = basic::Inst> + Clone) -> Option<Self> {
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)),
}
}
}

View File

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