mirror of
https://github.com/Zenithsiz/dcb.git
synced 2026-02-08 11:28:44 +00:00
SimpleInstruction is now defined using bitmatch instead of a macro.
This commit is contained in:
parent
2d931f10cb
commit
eb51f448ce
@ -65,6 +65,8 @@
|
||||
#![allow(clippy::large_digit_groups)]
|
||||
// We don't put the final `else` if it's empty
|
||||
#![allow(clippy::else_if_without_else)]
|
||||
// We're usually fine with missing future variants
|
||||
#![allow(clippy::wildcard_enum_match_arm)]
|
||||
|
||||
// Modules
|
||||
mod cli;
|
||||
@ -150,9 +152,9 @@ fn main() -> Result<(), anyhow::Error> {
|
||||
// Get all function jumps
|
||||
let funcs_pos: HashMap<Pos, usize> = instructions
|
||||
.iter()
|
||||
.filter_map(|(_, instruction)| match instruction {
|
||||
Instruction::Simple(SimpleInstruction::Jal { target }) |
|
||||
Instruction::Directive(Directive::Dw(target) | Directive::DwRepeated { value: target, .. }) => Some(Pos(*target)),
|
||||
.filter_map(|(_, instruction)| match *instruction {
|
||||
Instruction::Simple(SimpleInstruction::Jal { target }) => Some(target),
|
||||
Instruction::Directive(Directive::Dw(target) | Directive::DwRepeated { value: target, .. }) => Some(Pos(target)),
|
||||
_ => None,
|
||||
})
|
||||
.filter(|target| (Instruction::CODE_START..Instruction::CODE_END).contains(target) && offsets.contains(target))
|
||||
@ -163,7 +165,7 @@ fn main() -> Result<(), anyhow::Error> {
|
||||
// Get all local jumps
|
||||
let locals_pos: HashMap<Pos, usize> = instructions
|
||||
.iter()
|
||||
.filter_map(|(_, instruction)| match instruction {
|
||||
.filter_map(|(_, instruction)| match *instruction {
|
||||
Instruction::Simple(
|
||||
SimpleInstruction::J { target } |
|
||||
SimpleInstruction::Beq { target, .. } |
|
||||
@ -177,7 +179,7 @@ fn main() -> Result<(), anyhow::Error> {
|
||||
) |
|
||||
Instruction::Pseudo(
|
||||
PseudoInstruction::Beqz { target, .. } | PseudoInstruction::Bnez { target, .. } | PseudoInstruction::B { target },
|
||||
) => Some(Pos(*target)),
|
||||
) => Some(target),
|
||||
_ => None,
|
||||
})
|
||||
.filter(|target| (Instruction::CODE_START..Instruction::CODE_END).contains(target) && offsets.contains(target))
|
||||
@ -270,10 +272,10 @@ fn main() -> Result<(), anyhow::Error> {
|
||||
SimpleInstruction::Bgezal { target, .. },
|
||||
) => {
|
||||
print!(" #");
|
||||
if let Some(func_idx) = funcs_pos.get(Pos::ref_cast(target)) {
|
||||
if let Some(func_idx) = funcs_pos.get(target) {
|
||||
print!(" func_{func_idx}");
|
||||
}
|
||||
if let Some(local_idx) = locals_pos.get(Pos::ref_cast(target)) {
|
||||
if let Some(local_idx) = locals_pos.get(target) {
|
||||
print!(" .{local_idx}");
|
||||
}
|
||||
},
|
||||
|
||||
@ -18,6 +18,7 @@ ascii = { version = "1.0", features = ["serde"] }
|
||||
arrayref = "0.3"
|
||||
int-conv = "0.1"
|
||||
indoc = "1.0"
|
||||
bitmatch = "0.1"
|
||||
|
||||
# Serde
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
|
||||
@ -53,7 +53,6 @@ impl FromRawIter for Directive {
|
||||
let raw = iter.next()?;
|
||||
|
||||
// Try to get an ascii string from the raw and check for nulls
|
||||
#[allow(clippy::wildcard_enum_match_arm)] // Option won't get more variants
|
||||
match AsciiString::from_ascii(raw.repr.to_ne_bytes()).map(check_nulls) {
|
||||
// If we got a string with at least 1 non-null, but
|
||||
// at least 1 null and uniformly null, return just it
|
||||
|
||||
@ -223,24 +223,23 @@ pub enum PseudoInstruction {
|
||||
/// Branch if equal to zero
|
||||
/// Alias for `beq $rx, $zr, target`
|
||||
#[display(fmt = "beqz {rx}, {target:#x}")]
|
||||
Beqz { rx: Register, target: u32 },
|
||||
Beqz { rx: Register, target: Pos },
|
||||
|
||||
/// Branch if different from zero
|
||||
/// Alias for `bne $rx, $zr, target`
|
||||
#[display(fmt = "bnez {rx}, {target:#x}")]
|
||||
Bnez { rx: Register, target: u32 },
|
||||
Bnez { rx: Register, target: Pos },
|
||||
|
||||
/// Jump relative
|
||||
/// Alias for `beq $zr, $zr, target`
|
||||
#[display(fmt = "b {target:#x}")]
|
||||
B { target: u32 },
|
||||
B { target: Pos },
|
||||
// TODO: Push / Pop
|
||||
}
|
||||
|
||||
impl FromRawIter for PseudoInstruction {
|
||||
type Decoded = Option<(Pos, Self)>;
|
||||
|
||||
#[allow(clippy::wildcard_enum_match_arm)] // New entries won't affect this function, it can only act on entries it knows.
|
||||
#[allow(clippy::similar_names)] // With register names, this happens too much
|
||||
#[allow(clippy::too_many_lines, clippy::clippy::cognitive_complexity)] // We can't separate this into several functions, it's just 1 big match
|
||||
fn decode<I: Iterator<Item = Raw> + Clone>(iter: &mut I) -> Self::Decoded {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,65 +0,0 @@
|
||||
//! Raw instruction representation
|
||||
|
||||
// Imports
|
||||
use super::Raw;
|
||||
use int_conv::Truncate;
|
||||
|
||||
/// An instruction's raw representation, including
|
||||
/// it's current address.
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
#[allow(clippy::missing_docs_in_private_items)]
|
||||
pub struct RawRepr {
|
||||
pub op: u8,
|
||||
pub rs: u8,
|
||||
pub rt: u8,
|
||||
pub rd: u8,
|
||||
pub imm5: u8,
|
||||
pub op2: u8,
|
||||
pub imm16: u16,
|
||||
pub imm25: u32,
|
||||
pub imm26: u32,
|
||||
|
||||
/// Syscall / Break immediate
|
||||
pub sys_imm: u32,
|
||||
|
||||
/// Co-processor opcode
|
||||
pub co_op: u8,
|
||||
|
||||
/// Co-processor number
|
||||
pub co_n: u8,
|
||||
|
||||
/// Co-processor highest `rs` bit.
|
||||
pub co_rs0: u8,
|
||||
|
||||
/// Co-processor lowest `rs` bits.
|
||||
pub co_rs1: u8,
|
||||
|
||||
/// Position of the instruction
|
||||
pub pos: u32,
|
||||
}
|
||||
|
||||
#[allow(clippy::inconsistent_digit_grouping)] // We're grouping 6-5-5-5-5-6 as per docs.
|
||||
impl RawRepr {
|
||||
/// Creates a new split instruction
|
||||
#[must_use]
|
||||
#[rustfmt::skip]
|
||||
pub fn new(Raw {repr, pos}: Raw) -> Self {
|
||||
Self {
|
||||
op : ((repr & 0b111111_00000_00000_00000_00000_000000) >> 26).truncate(),
|
||||
rs : ((repr & 0b000000_11111_00000_00000_00000_000000) >> 21).truncate(),
|
||||
rt : ((repr & 0b000000_00000_11111_00000_00000_000000) >> 16).truncate(),
|
||||
rd : ((repr & 0b000000_00000_00000_11111_00000_000000) >> 11).truncate(),
|
||||
imm5 : ((repr & 0b000000_00000_00000_00000_11111_000000) >> 6 ).truncate(),
|
||||
op2 : ((repr & 0b000000_00000_00000_00000_00000_111111) >> 0 ).truncate(),
|
||||
imm16 : ((repr & 0b000000_00000_00000_11111_11111_111111) >> 0 ).truncate(),
|
||||
imm25 : ((repr & 0b000000_01111_11111_11111_11111_111111) >> 0 ),
|
||||
imm26 : ((repr & 0b000000_11111_11111_11111_11111_111111) >> 0 ),
|
||||
sys_imm: ((repr & 0b000000_11111_11111_11111_11111_000000) >> 0 ),
|
||||
co_op : ((repr & 0b111100_00000_00000_00000_00000_000000) >> 28).truncate(),
|
||||
co_rs0 : ((repr & 0b000000_10000_00000_00000_00000_000000) >> 25).truncate(),
|
||||
co_rs1 : ((repr & 0b000000_01111_00000_00000_00000_000000) >> 21).truncate(),
|
||||
co_n : ((repr & 0b000011_00000_00000_00000_00000_000000) >> 26).truncate(),
|
||||
pos: pos.0,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2,6 +2,7 @@
|
||||
// TODO: More implementations for `Pos`
|
||||
|
||||
// Imports
|
||||
use int_conv::Signed;
|
||||
use std::{fmt, ops};
|
||||
|
||||
/// An instruction position
|
||||
@ -26,6 +27,30 @@ impl ops::Sub<u32> for Pos {
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Add<u32> for Pos {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: u32) -> Self::Output {
|
||||
Self(self.0 + rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::Add<i32> for Pos {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: i32) -> Self::Output {
|
||||
Self((self.0.as_signed() + rhs).as_unsigned())
|
||||
}
|
||||
}
|
||||
|
||||
impl ops::BitAnd<u32> for Pos {
|
||||
type Output = Self;
|
||||
|
||||
fn bitand(self, rhs: u32) -> Self::Output {
|
||||
Self(self.0 & rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> ops::Sub<T> for &'_ Pos
|
||||
where
|
||||
Pos: ops::Sub<T, Output = Pos>,
|
||||
@ -36,3 +61,14 @@ where
|
||||
<Pos as ops::Sub<T>>::sub(Pos(self.0), rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> ops::Add<T> for &'_ Pos
|
||||
where
|
||||
Pos: ops::Add<T, Output = Pos>,
|
||||
{
|
||||
type Output = Pos;
|
||||
|
||||
fn add(self, rhs: T) -> Self::Output {
|
||||
<Pos as ops::Add<T>>::add(Pos(self.0), rhs)
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,6 +102,8 @@
|
||||
#![allow(clippy::panic_in_result_fn)]
|
||||
// A `match Option / Result / Bool` can sometimes look cleaner than a `if let / else`
|
||||
#![allow(clippy::single_match_else, clippy::match_bool)]
|
||||
// We're usually fine with missing future variants
|
||||
#![allow(clippy::wildcard_enum_match_arm)]
|
||||
|
||||
|
||||
// Modules
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user