mirror of
https://github.com/Zenithsiz/dcb.git
synced 2026-02-09 03:40:23 +00:00
Added pseudo::jmp.
Refactored `basic::{jmp, cond}`'s target calculation.
This commit is contained in:
@@ -135,7 +135,7 @@ impl FuncTable {
|
||||
kind: basic::jmp::imm::Kind::Jump,
|
||||
..
|
||||
},
|
||||
))) => Some(inst.address(pos)),
|
||||
))) => Some(inst.target(pos)),
|
||||
// Conditional jumps
|
||||
Inst::Basic(basic::Inst::Cond(basic::cond::Inst { offset, .. })) => Some(pos + offset.sign_extended::<i32>()),
|
||||
_ => None,
|
||||
@@ -152,7 +152,7 @@ impl FuncTable {
|
||||
kind: basic::jmp::imm::Kind::JumpLink,
|
||||
..
|
||||
},
|
||||
))) => Some(inst.address(pos)),
|
||||
))) => Some(inst.target(pos)),
|
||||
// `dw`
|
||||
Inst::Directive(Directive::Dw(address)) => Some(Pos(address)),
|
||||
_ => None,
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
//! Condition branches
|
||||
|
||||
// Imports
|
||||
use crate::exe::inst::{
|
||||
basic::{Decodable, Encodable},
|
||||
InstFmt, Register,
|
||||
use crate::{
|
||||
exe::inst::{
|
||||
basic::{Decodable, Encodable},
|
||||
InstFmt, Register,
|
||||
},
|
||||
Pos,
|
||||
};
|
||||
use int_conv::{SignExtended, Signed, Truncated, ZeroExtended};
|
||||
use std::fmt;
|
||||
@@ -82,6 +85,20 @@ pub struct Inst {
|
||||
pub kind: Kind,
|
||||
}
|
||||
|
||||
impl Inst {
|
||||
/// Returns the target for this instruction
|
||||
#[must_use]
|
||||
pub fn target(self, pos: Pos) -> Pos {
|
||||
Self::target_of(self.offset, pos)
|
||||
}
|
||||
|
||||
/// Returns the target using an offset
|
||||
#[must_use]
|
||||
pub fn target_of(offset: i16, pos: Pos) -> Pos {
|
||||
pos + 4 * offset.sign_extended::<i32>()
|
||||
}
|
||||
}
|
||||
|
||||
impl Decodable for Inst {
|
||||
type Raw = Raw;
|
||||
|
||||
@@ -135,19 +152,19 @@ impl InstFmt for Inst {
|
||||
self.kind.mnemonic()
|
||||
}
|
||||
|
||||
fn fmt(&self, pos: crate::Pos, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let Self { arg, offset, kind } = self;
|
||||
fn fmt(&self, pos: Pos, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let Self { kind, arg, .. } = self;
|
||||
let mnemonic = kind.mnemonic();
|
||||
let address = pos + 4 * offset.sign_extended::<i32>();
|
||||
let target = self.target(pos);
|
||||
|
||||
match kind {
|
||||
Kind::Equal(reg) | Kind::NotEqual(reg) => write!(f, "{mnemonic} {arg}, {reg}, {address}"),
|
||||
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}, {address}"),
|
||||
Kind::GreaterOrEqualZeroLink => write!(f, "{mnemonic} {arg}, {target}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,18 +43,24 @@ pub struct Raw {
|
||||
/// Jmp register instructions
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
pub struct Inst {
|
||||
/// Target
|
||||
pub target: u32,
|
||||
/// Immediate
|
||||
pub imm: u32,
|
||||
|
||||
/// Kind
|
||||
pub kind: Kind,
|
||||
}
|
||||
|
||||
impl Inst {
|
||||
/// Returns the address of this instruction
|
||||
/// Returns the target of this instruction
|
||||
#[must_use]
|
||||
pub fn address(self, pos: Pos) -> Pos {
|
||||
(pos & 0xf0000000) + self.target * 4
|
||||
pub fn target(self, pos: Pos) -> Pos {
|
||||
Self::target_of(self.imm, pos)
|
||||
}
|
||||
|
||||
/// Returns the target using an immediate
|
||||
#[must_use]
|
||||
pub fn target_of(imm: u32, pos: Pos) -> Pos {
|
||||
(pos & 0xf0000000) + imm * 4
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +74,7 @@ impl Decodable for Inst {
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
Some(Self { target: raw.i, kind })
|
||||
Some(Self { imm: raw.i, kind })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +84,7 @@ impl Encodable for Inst {
|
||||
Kind::Jump => 0,
|
||||
Kind::JumpLink => 1,
|
||||
};
|
||||
let i = self.target;
|
||||
let i = self.imm;
|
||||
|
||||
Raw { p, i }
|
||||
}
|
||||
@@ -91,8 +97,8 @@ impl InstFmt for Inst {
|
||||
|
||||
fn fmt(&self, pos: Pos, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
let mnemonic = self.kind.mnemonic();
|
||||
let address = self.address(pos);
|
||||
let target = self.target(pos);
|
||||
|
||||
write!(f, "{mnemonic} {address}")
|
||||
write!(f, "{mnemonic} {target}")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
|
||||
// Modules
|
||||
pub mod alu_assign;
|
||||
pub mod jmp;
|
||||
pub mod load_imm;
|
||||
//pub mod jmp;
|
||||
//pub mod load;
|
||||
pub mod move_reg;
|
||||
pub mod nop;
|
||||
@@ -31,19 +31,17 @@ pub enum Inst {
|
||||
|
||||
/// Move register
|
||||
MoveReg(move_reg::Inst),
|
||||
|
||||
/// Jump
|
||||
Jmp(jmp::Inst),
|
||||
/*
|
||||
/// Load
|
||||
Load(LoadPseudoInst),
|
||||
|
||||
/// Store
|
||||
Store(StorePseudoInst),
|
||||
|
||||
|
||||
|
||||
/// Load immediate
|
||||
LoadImm(LoadImmInst),
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
/// Subtract immediate
|
||||
/// Alias for `addi $rt, $rs, -imm`
|
||||
@@ -74,6 +72,7 @@ impl Decodable for Inst {
|
||||
load_imm ::Inst::decode(insts.clone()).map(Self::LoadImm )
|
||||
.or_else( || alu_assign::Inst::decode(insts.clone()).map(Self::AluAssign))
|
||||
.or_else( || nop ::Inst::decode(insts.clone()).map(Self::Nop ))
|
||||
.or_else( || jmp ::Inst::decode(insts.clone()).map(Self::Jmp ))
|
||||
.or_else(move || move_reg ::Inst::decode( insts ).map(Self::MoveReg ))
|
||||
}
|
||||
}
|
||||
@@ -85,6 +84,7 @@ impl InstSize for Inst {
|
||||
Self::LoadImm(inst) => inst.size(),
|
||||
Self::Nop(inst) => inst.size(),
|
||||
Self::MoveReg(inst) => inst.size(),
|
||||
Self::Jmp(inst) => inst.size(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -96,6 +96,7 @@ impl InstFmt for Inst {
|
||||
Self::LoadImm(inst) => inst.mnemonic(),
|
||||
Self::Nop(inst) => inst.mnemonic(),
|
||||
Self::MoveReg(inst) => inst.mnemonic(),
|
||||
Self::Jmp(inst) => inst.mnemonic(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,6 +106,7 @@ 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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,62 +1,98 @@
|
||||
//! Jump pseudo instructions
|
||||
|
||||
// Imports
|
||||
use crate::exe::inst::{
|
||||
basic::{
|
||||
cond::CondKind,
|
||||
special::{jmp::JmpKind, JmpInst},
|
||||
CondInst, InstIter, SpecialInst,
|
||||
},
|
||||
BasicInst, Pos, Register,
|
||||
};
|
||||
use crate::exe::inst::{basic, InstFmt, InstSize, Register};
|
||||
|
||||
use super::Decodable;
|
||||
|
||||
/// Jump / Branch instructions
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
#[derive(derive_more::Display)]
|
||||
pub enum JmpPseudoInst {
|
||||
pub enum Inst {
|
||||
/// Jump and link with return address
|
||||
/// Alias for `jalr $ra, $dst`
|
||||
#[display(fmt = "jalr {target}")]
|
||||
JalrRa { target: Register },
|
||||
/// Alias for `jalr $target, $ra`
|
||||
JalrRa {
|
||||
/// Target for the jump
|
||||
target: Register,
|
||||
},
|
||||
|
||||
/// Branch if equal to zero
|
||||
/// Alias for `beq $arg, $zr, offset`
|
||||
#[display(fmt = "beqz {arg}, {offset:#x}")]
|
||||
Beqz { arg: Register, offset: Pos },
|
||||
Beqz {
|
||||
/// Argument to compare
|
||||
arg: Register,
|
||||
|
||||
/// Jump offset
|
||||
offset: i16,
|
||||
},
|
||||
|
||||
/// Branch if different from zero
|
||||
/// Alias for `bne $arg, $zr, offset`
|
||||
#[display(fmt = "bnez {arg}, {offset:#x}")]
|
||||
Bnez { arg: Register, offset: Pos },
|
||||
Bnez {
|
||||
/// Argument to compare
|
||||
arg: Register,
|
||||
|
||||
/// Jump offset
|
||||
offset: i16,
|
||||
},
|
||||
|
||||
/// Jump relative
|
||||
/// Alias for `beq $zr, $zr, offset`
|
||||
#[display(fmt = "b {offset:#x}")]
|
||||
B { offset: Pos },
|
||||
B {
|
||||
/// Jump offset
|
||||
offset: i16,
|
||||
},
|
||||
}
|
||||
|
||||
impl JmpPseudoInst {
|
||||
/// Decodes this pseudo instruction
|
||||
#[must_use]
|
||||
pub fn decode(iter: InstIter<'_, impl Iterator<Item = u32> + Clone>) -> Option<Self> {
|
||||
let peeker = iter.peeker();
|
||||
let inst = match peeker.next()?? {
|
||||
BasicInst::Cond(CondInst { arg, offset, kind }) => match kind {
|
||||
CondKind::Equal(Register::Zr) => match arg == Register::Zr {
|
||||
true => Self::B { offset },
|
||||
false => Self::Beqz { arg, offset },
|
||||
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 },
|
||||
},
|
||||
CondKind::NotEqual(Register::Zr) => Self::Bnez { arg, offset },
|
||||
_ => return None,
|
||||
},
|
||||
BasicInst::Special(SpecialInst::Jmp(JmpInst { target, kind })) => match kind {
|
||||
JmpKind::Link(Register::At) => Self::JalrRa { target },
|
||||
// `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,
|
||||
};
|
||||
|
||||
peeker.apply();
|
||||
Some(inst)
|
||||
}
|
||||
}
|
||||
|
||||
impl InstSize for Inst {
|
||||
fn size(&self) -> usize {
|
||||
4
|
||||
}
|
||||
}
|
||||
|
||||
impl InstFmt for Inst {
|
||||
fn mnemonic(&self) -> &'static str {
|
||||
match self {
|
||||
Self::JalrRa { .. } => "jalr",
|
||||
Self::Beqz { .. } => "beqz",
|
||||
Self::Bnez { .. } => "bnez",
|
||||
Self::B { .. } => "b",
|
||||
}
|
||||
}
|
||||
|
||||
fn fmt(&self, pos: crate::Pos, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
let mnemonic = self.mnemonic();
|
||||
|
||||
match *self {
|
||||
Self::JalrRa { target } => write!(f, "{mnemonic} {target}"),
|
||||
Self::Beqz { arg, offset } | Self::Bnez { arg, offset } => write!(f, "{mnemonic} {arg}, {}", basic::cond::Inst::target_of(offset, pos)),
|
||||
Self::B { offset } => write!(f, "{mnemonic} {}", basic::cond::Inst::target_of(offset, pos)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user