mirror of
https://github.com/Zenithsiz/dcb.git
synced 2026-02-04 08:23:13 +00:00
Added InstDisplay for better instruction formatting.
This commit is contained in:
parent
3c7bed14e6
commit
d0bd0d22b3
@ -15,7 +15,7 @@ pub mod target;
|
||||
// Exports
|
||||
pub use directive::Directive;
|
||||
pub use error::DecodeError;
|
||||
pub use fmt::{InstFmt, InstTargetFmt};
|
||||
pub use fmt::{DisplayCtx, InstDisplay, InstFmt, InstFmtArg, InstTargetFmt};
|
||||
pub use iter::ParseIter;
|
||||
pub use parse::{Parsable, ParseCtx, ParseError};
|
||||
pub use reg::Register;
|
||||
|
||||
@ -17,8 +17,12 @@ pub mod store;
|
||||
pub mod sys;
|
||||
|
||||
// Imports
|
||||
use super::{parse::LineArg, InstSize, ParseCtx, ParseError, Register};
|
||||
use super::{
|
||||
parse::{LineArg, Parsable},
|
||||
DisplayCtx, InstDisplay, InstFmtArg, InstSize, ParseCtx, ParseError, Register,
|
||||
};
|
||||
use crate::inst::InstFmt;
|
||||
use std::fmt;
|
||||
|
||||
/// All basic instructions
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
@ -55,7 +59,6 @@ pub enum Inst {
|
||||
Co(co::Inst),
|
||||
}
|
||||
|
||||
|
||||
impl Decode for Inst {
|
||||
#[rustfmt::skip]
|
||||
fn decode(raw: u32) -> Option<Self> {
|
||||
@ -73,7 +76,6 @@ impl Decode for Inst {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Encode error
|
||||
#[derive(PartialEq, Clone, Debug, thiserror::Error)]
|
||||
pub enum EncodeError {
|
||||
@ -106,7 +108,7 @@ impl TryEncode for Inst {
|
||||
}
|
||||
}
|
||||
|
||||
impl super::parse::Parsable for Inst {
|
||||
impl Parsable for Inst {
|
||||
fn parse<Ctx: ?Sized + ParseCtx>(mnemonic: &str, args: &[LineArg], ctx: &Ctx) -> Result<Self, ParseError> {
|
||||
#[rustfmt::skip]
|
||||
let parsers: &[&dyn Fn() -> Result<Self, ParseError>] = &[
|
||||
@ -136,6 +138,45 @@ impl super::parse::Parsable for Inst {
|
||||
}
|
||||
}
|
||||
|
||||
impl InstDisplay for Inst {
|
||||
type Args = impl Iterator<Item = InstFmtArg>;
|
||||
type Mnemonic = impl fmt::Display;
|
||||
|
||||
#[auto_enums::auto_enum(Display)]
|
||||
#[rustfmt::skip]
|
||||
fn mnemonic<Ctx: DisplayCtx>(&self, ctx: &Ctx) -> Self::Mnemonic {
|
||||
match self {
|
||||
Inst::Alu (inst) => inst.mnemonic(ctx),
|
||||
Inst::Cond (inst) => inst.mnemonic(ctx),
|
||||
Inst::Jmp (inst) => inst.mnemonic(ctx),
|
||||
Inst::Load (inst) => inst.mnemonic(ctx),
|
||||
Inst::Lui (inst) => inst.mnemonic(ctx),
|
||||
Inst::Mult (inst) => inst.mnemonic(ctx),
|
||||
Inst::Shift(inst) => inst.mnemonic(ctx),
|
||||
Inst::Store(inst) => inst.mnemonic(ctx),
|
||||
Inst::Sys (inst) => inst.mnemonic(ctx),
|
||||
Inst::Co (inst) => inst.mnemonic(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
#[auto_enums::auto_enum(Iterator)]
|
||||
#[rustfmt::skip]
|
||||
fn args<Ctx: DisplayCtx>(&self, ctx: &Ctx) -> Self::Args {
|
||||
match self {
|
||||
Inst::Alu (inst) => inst.args(ctx),
|
||||
Inst::Cond (inst) => inst.args(ctx),
|
||||
Inst::Jmp (inst) => inst.args(ctx),
|
||||
Inst::Load (inst) => inst.args(ctx),
|
||||
Inst::Lui (inst) => inst.args(ctx),
|
||||
Inst::Mult (inst) => inst.args(ctx),
|
||||
Inst::Shift(inst) => inst.args(ctx),
|
||||
Inst::Store(inst) => inst.args(ctx),
|
||||
Inst::Sys (inst) => inst.args(ctx),
|
||||
Inst::Co (inst) => inst.args(ctx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ModifiesReg for Inst {
|
||||
#[rustfmt::skip]
|
||||
fn modifies_reg(&self, reg: Register) -> bool {
|
||||
|
||||
@ -9,7 +9,7 @@ use super::ModifiesReg;
|
||||
use crate::inst::{
|
||||
basic::{Decode, Encode},
|
||||
parse::LineArg,
|
||||
InstFmt, Parsable, ParseCtx, ParseError,
|
||||
DisplayCtx, InstDisplay, InstFmt, InstFmtArg, Parsable, ParseCtx, ParseError,
|
||||
};
|
||||
|
||||
/// Alu register instructions
|
||||
@ -49,6 +49,28 @@ impl Parsable for Inst {
|
||||
}
|
||||
}
|
||||
|
||||
impl InstDisplay for Inst {
|
||||
type Mnemonic = &'static str;
|
||||
|
||||
type Args = impl Iterator<Item = InstFmtArg>;
|
||||
|
||||
fn mnemonic<Ctx: DisplayCtx>(&self, ctx: &Ctx) -> Self::Mnemonic {
|
||||
match self {
|
||||
Inst::Imm(inst) => inst.mnemonic(ctx),
|
||||
Inst::Reg(inst) => inst.mnemonic(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
#[auto_enums::auto_enum(Iterator)]
|
||||
fn args<Ctx: DisplayCtx>(&self, ctx: &Ctx) -> Self::Args {
|
||||
match self {
|
||||
Inst::Imm(inst) => inst.args(ctx).into_iter(),
|
||||
Inst::Reg(inst) => inst.args(ctx).into_iter(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl InstFmt for Inst {
|
||||
fn fmt(&self, pos: crate::Pos, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
|
||||
@ -4,11 +4,11 @@
|
||||
use crate::inst::{
|
||||
basic::{Decode, Encode, ModifiesReg},
|
||||
parse::LineArg,
|
||||
InstFmt, Parsable, ParseCtx, ParseError, Register,
|
||||
DisplayCtx, InstDisplay, InstFmt, InstFmtArg, Parsable, ParseCtx, ParseError, Register,
|
||||
};
|
||||
use dcb_util::SignedHex;
|
||||
use int_conv::{Signed, Truncated, ZeroExtended};
|
||||
use std::{convert::TryInto, fmt};
|
||||
use std::{array, convert::TryInto, fmt};
|
||||
|
||||
/// Instruction kind
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
@ -50,9 +50,18 @@ impl Kind {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the value of this kind as a `i64`
|
||||
#[must_use]
|
||||
pub fn value(self) -> i64 {
|
||||
match self {
|
||||
Kind::Add(value) | Kind::AddUnsigned(value) | Kind::SetLessThan(value) => i64::from(value),
|
||||
Kind::SetLessThanUnsigned(value) | Kind::And(value) | Kind::Or(value) | Kind::Xor(value) => i64::from(value),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a displayable with the value of this kind
|
||||
#[must_use]
|
||||
pub fn value_fmt(self) -> impl fmt::Display {
|
||||
fn value_fmt(self) -> impl fmt::Display {
|
||||
dcb_util::DisplayWrapper::new(move |f| match self {
|
||||
// Signed
|
||||
Self::Add(rhs) | Self::AddUnsigned(rhs) | Self::SetLessThan(rhs) => write!(f, "{:#}", SignedHex(rhs)),
|
||||
@ -152,6 +161,29 @@ impl Parsable for Inst {
|
||||
}
|
||||
}
|
||||
|
||||
impl InstDisplay for Inst {
|
||||
type Mnemonic = &'static str;
|
||||
|
||||
type Args = impl IntoIterator<Item = InstFmtArg>;
|
||||
|
||||
fn mnemonic<Ctx: DisplayCtx>(&self, _ctx: &Ctx) -> Self::Mnemonic {
|
||||
self.kind.mnemonic()
|
||||
}
|
||||
|
||||
#[auto_enums::auto_enum(Iterator)]
|
||||
fn args<Ctx: DisplayCtx>(&self, _ctx: &Ctx) -> Self::Args {
|
||||
let &Self { dst, lhs, kind } = self;
|
||||
let value = kind.value();
|
||||
|
||||
// If we're not `slti[u]` and if `$dst` and `$lhs` are the same,
|
||||
// only return one of them
|
||||
match !matches!(kind, Kind::SetLessThan(_) | Kind::SetLessThanUnsigned(_)) && dst == lhs {
|
||||
true => array::IntoIter::new([InstFmtArg::Register(dst), InstFmtArg::literal(value)]),
|
||||
false => array::IntoIter::new([InstFmtArg::Register(dst), InstFmtArg::Register(lhs), InstFmtArg::literal(value)]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl InstFmt for Inst {
|
||||
fn fmt(&self, _pos: crate::Pos, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
let Self { dst, lhs, kind } = self;
|
||||
|
||||
@ -4,8 +4,9 @@
|
||||
use crate::inst::{
|
||||
basic::{Decode, Encode, ModifiesReg},
|
||||
parse::LineArg,
|
||||
InstFmt, Parsable, ParseCtx, ParseError, Register,
|
||||
DisplayCtx, InstDisplay, InstFmt, InstFmtArg, Parsable, ParseCtx, ParseError, Register,
|
||||
};
|
||||
use std::array;
|
||||
|
||||
/// Alu register instruction kind
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
@ -160,6 +161,28 @@ impl Parsable for Inst {
|
||||
}
|
||||
}
|
||||
|
||||
impl InstDisplay for Inst {
|
||||
type Mnemonic = &'static str;
|
||||
|
||||
type Args = impl IntoIterator<Item = InstFmtArg>;
|
||||
|
||||
fn mnemonic<Ctx: DisplayCtx>(&self, _ctx: &Ctx) -> Self::Mnemonic {
|
||||
self.kind.mnemonic()
|
||||
}
|
||||
|
||||
#[auto_enums::auto_enum(Iterator)]
|
||||
fn args<Ctx: DisplayCtx>(&self, _ctx: &Ctx) -> Self::Args {
|
||||
let &Self { dst, lhs, rhs, kind } = self;
|
||||
|
||||
// If we're not `slt[u]` and if `$dst` and `$lhs` are the same,
|
||||
// only return one of them
|
||||
match !matches!(kind, Kind::SetLessThan | Kind::SetLessThanUnsigned) && dst == lhs {
|
||||
true => array::IntoIter::new([InstFmtArg::Register(dst), InstFmtArg::Register(rhs)]),
|
||||
false => array::IntoIter::new([InstFmtArg::Register(dst), InstFmtArg::Register(lhs), InstFmtArg::Register(rhs)]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl InstFmt for Inst {
|
||||
fn fmt(&self, _pos: crate::Pos, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
|
||||
@ -5,11 +5,11 @@ use super::ModifiesReg;
|
||||
use crate::inst::{
|
||||
basic::{Decode, Encode},
|
||||
parse::LineArg,
|
||||
InstFmt, Parsable, ParseCtx, ParseError, Register,
|
||||
DisplayCtx, InstDisplay, InstFmt, InstFmtArg, Parsable, ParseCtx, ParseError, Register,
|
||||
};
|
||||
use dcb_util::SignedHex;
|
||||
use int_conv::{Signed, Truncated, ZeroExtended};
|
||||
use std::convert::TryInto;
|
||||
use std::{array, convert::TryInto, fmt};
|
||||
|
||||
/// Co-processor register kind
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
@ -238,9 +238,52 @@ impl Parsable for Inst {
|
||||
}
|
||||
}
|
||||
|
||||
impl InstDisplay for Inst {
|
||||
type Args = impl Iterator<Item = InstFmtArg>;
|
||||
type Mnemonic = impl fmt::Display;
|
||||
|
||||
fn mnemonic<Ctx: DisplayCtx>(&self, _ctx: &Ctx) -> Self::Mnemonic {
|
||||
/// Wrapper necessary for `impl Trait` to work without using `Ctx`.
|
||||
fn wrapper(n: u32, kind: Kind) -> impl fmt::Display {
|
||||
dcb_util::DisplayWrapper::new(move |f| match kind {
|
||||
Kind::CopN { .. } => write!(f, "cop{n}"),
|
||||
Kind::MoveFrom { kind, .. } => match kind {
|
||||
RegisterKind::Control => write!(f, "cfc{n}"),
|
||||
RegisterKind::Data => write!(f, "mfc{n}"),
|
||||
},
|
||||
Kind::MoveTo { kind, .. } => match kind {
|
||||
RegisterKind::Data => write!(f, "mtc{n}"),
|
||||
RegisterKind::Control => write!(f, "ctc{n}"),
|
||||
},
|
||||
Kind::Branch { on, .. } => match on {
|
||||
true => write!(f, "bc{n}f"),
|
||||
false => write!(f, "bc{n}t"),
|
||||
},
|
||||
Kind::Load { .. } => write!(f, "lwc{n}"),
|
||||
Kind::Store { .. } => write!(f, "swc{n}"),
|
||||
})
|
||||
}
|
||||
|
||||
wrapper(self.n, self.kind)
|
||||
}
|
||||
|
||||
#[auto_enums::auto_enum(Iterator)]
|
||||
fn args<Ctx: DisplayCtx>(&self, _ctx: &Ctx) -> Self::Args {
|
||||
let &Self { kind, .. } = self;
|
||||
match kind {
|
||||
Kind::CopN { imm } => array::IntoIter::new([InstFmtArg::literal(imm)]),
|
||||
Kind::MoveFrom { dst, src, .. } => array::IntoIter::new([InstFmtArg::Register(dst), InstFmtArg::literal(src)]),
|
||||
Kind::MoveTo { dst, src, .. } => array::IntoIter::new([InstFmtArg::Register(src), InstFmtArg::literal(dst)]),
|
||||
Kind::Branch { offset, .. } => array::IntoIter::new([InstFmtArg::literal(offset)]),
|
||||
Kind::Load { dst, src, offset } => array::IntoIter::new([InstFmtArg::literal(dst), InstFmtArg::register_offset(src, offset)]),
|
||||
Kind::Store { dst, src, offset } => array::IntoIter::new([InstFmtArg::literal(dst), InstFmtArg::register_offset(src, offset)]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl InstFmt for Inst {
|
||||
#[rustfmt::skip]
|
||||
fn fmt(&self, _pos: crate::Pos, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
fn fmt(&self, _pos: crate::Pos, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
let Self { n, kind } = self;
|
||||
match kind {
|
||||
Kind::CopN { imm } => write!(f, "cop{n} {imm:#x}"),
|
||||
|
||||
@ -6,12 +6,12 @@ use crate::{
|
||||
inst::{
|
||||
basic::{Decode, Encode},
|
||||
parse::LineArg,
|
||||
InstTarget, InstTargetFmt, Parsable, ParseCtx, ParseError, Register,
|
||||
DisplayCtx, InstDisplay, InstFmtArg, InstTarget, InstTargetFmt, Parsable, ParseCtx, ParseError, Register,
|
||||
},
|
||||
Pos,
|
||||
};
|
||||
use int_conv::{SignExtended, Signed, Truncated, ZeroExtended};
|
||||
use std::{convert::TryInto, fmt};
|
||||
use std::{array, convert::TryInto, fmt};
|
||||
|
||||
/// Instruction kind
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
@ -186,6 +186,59 @@ impl Parsable for Inst {
|
||||
}
|
||||
}
|
||||
|
||||
/// Variants:
|
||||
/// `beq $zr, $zr, offset` => `b offset`
|
||||
/// `beq $arg, $zr, offset` => `beqz $arg, offset`
|
||||
/// `bne $arg, $zr, offset` => `bnez $arg, offset`
|
||||
impl InstDisplay for Inst {
|
||||
type Mnemonic = &'static str;
|
||||
|
||||
type Args = impl Iterator<Item = InstFmtArg>;
|
||||
|
||||
fn mnemonic<Ctx: DisplayCtx>(&self, _ctx: &Ctx) -> Self::Mnemonic {
|
||||
match self.kind {
|
||||
Kind::Equal(Register::Zr) => match self.arg {
|
||||
Register::Zr => "b",
|
||||
_ => "beqz",
|
||||
},
|
||||
Kind::Equal(_) => "beq",
|
||||
Kind::NotEqual(Register::Zr) => "bnez",
|
||||
Kind::NotEqual(_) => "bne",
|
||||
Kind::LessOrEqualZero => "blez",
|
||||
Kind::GreaterThanZero => "bgtz",
|
||||
Kind::LessThanZero => "bltz",
|
||||
Kind::GreaterOrEqualZero => "bgez",
|
||||
Kind::LessThanZeroLink => "bltzal",
|
||||
Kind::GreaterOrEqualZeroLink => "bgezal",
|
||||
}
|
||||
}
|
||||
|
||||
#[auto_enums::auto_enum(Iterator)]
|
||||
#[rustfmt::skip]
|
||||
fn args<Ctx: DisplayCtx>(&self, ctx: &Ctx) -> Self::Args {
|
||||
use InstFmtArg::Register as register;
|
||||
let &Self { arg, offset, kind } = self;
|
||||
let target = Self::target_of(offset, ctx.cur_pos());
|
||||
|
||||
match (arg, kind) {
|
||||
(Register::Zr, Kind::Equal (Register::Zr)) => array::IntoIter::new([ InstFmtArg::Target(target)]),
|
||||
(_ , Kind::Equal (Register::Zr)) => array::IntoIter::new([register(arg), InstFmtArg::Target(target)]),
|
||||
(_ , Kind::Equal (reg) ) => array::IntoIter::new([register(arg), register(reg), InstFmtArg::Target(target)]),
|
||||
(_ , Kind::NotEqual(Register::Zr)) => array::IntoIter::new([register(arg), InstFmtArg::Target(target)]),
|
||||
(_ , Kind::NotEqual(reg) ) => array::IntoIter::new([register(arg), register(reg), InstFmtArg::Target(target)]),
|
||||
(
|
||||
_,
|
||||
Kind::LessOrEqualZero |
|
||||
Kind::GreaterThanZero |
|
||||
Kind::LessThanZero |
|
||||
Kind::GreaterOrEqualZero |
|
||||
Kind::LessThanZeroLink |
|
||||
Kind::GreaterOrEqualZeroLink,
|
||||
) => array::IntoIter::new([register(arg), InstFmtArg::Target(target)]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl InstTarget for Inst {
|
||||
fn target(&self, pos: Pos) -> Pos {
|
||||
Self::target_of(self.offset, pos)
|
||||
|
||||
@ -9,7 +9,7 @@ use super::ModifiesReg;
|
||||
use crate::inst::{
|
||||
basic::{Decode, Encode},
|
||||
parse::LineArg,
|
||||
InstFmt, Parsable, ParseCtx, ParseError, Register,
|
||||
DisplayCtx, InstDisplay, InstFmt, InstFmtArg, Parsable, ParseCtx, ParseError, Register,
|
||||
};
|
||||
|
||||
/// Jmp register instructions
|
||||
@ -49,6 +49,28 @@ impl Parsable for Inst {
|
||||
}
|
||||
}
|
||||
|
||||
impl InstDisplay for Inst {
|
||||
type Mnemonic = &'static str;
|
||||
|
||||
type Args = impl Iterator<Item = InstFmtArg>;
|
||||
|
||||
fn mnemonic<Ctx: DisplayCtx>(&self, ctx: &Ctx) -> Self::Mnemonic {
|
||||
match self {
|
||||
Inst::Imm(inst) => inst.mnemonic(ctx),
|
||||
Inst::Reg(inst) => inst.mnemonic(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
#[auto_enums::auto_enum(Iterator)]
|
||||
fn args<Ctx: DisplayCtx>(&self, ctx: &Ctx) -> Self::Args {
|
||||
match self {
|
||||
Inst::Imm(inst) => inst.args(ctx),
|
||||
Inst::Reg(inst) => inst.args(ctx).into_iter(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl InstFmt for Inst {
|
||||
fn fmt(&self, pos: crate::Pos, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
|
||||
@ -5,10 +5,11 @@ use crate::{
|
||||
inst::{
|
||||
basic::{Decode, Encode, ModifiesReg},
|
||||
parse::LineArg,
|
||||
InstTarget, InstTargetFmt, Parsable, ParseCtx, ParseError, Register,
|
||||
DisplayCtx, InstDisplay, InstFmtArg, InstTarget, InstTargetFmt, Parsable, ParseCtx, ParseError, Register,
|
||||
},
|
||||
Pos,
|
||||
};
|
||||
use std::array;
|
||||
|
||||
/// Jmp immediate instruction kind
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
@ -109,6 +110,20 @@ impl Parsable for Inst {
|
||||
}
|
||||
}
|
||||
|
||||
impl InstDisplay for Inst {
|
||||
type Args = array::IntoIter<InstFmtArg, 1>;
|
||||
type Mnemonic = &'static str;
|
||||
|
||||
fn mnemonic<Ctx: DisplayCtx>(&self, _ctx: &Ctx) -> Self::Mnemonic {
|
||||
self.kind.mnemonic()
|
||||
}
|
||||
|
||||
fn args<Ctx: DisplayCtx>(&self, ctx: &Ctx) -> Self::Args {
|
||||
array::IntoIter::new([InstFmtArg::Target(Self::target_of(self.imm, ctx.cur_pos()))])
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl InstTarget for Inst {
|
||||
fn target(&self, pos: Pos) -> Pos {
|
||||
Self::target_of(self.imm, pos)
|
||||
|
||||
@ -4,8 +4,9 @@
|
||||
use crate::inst::{
|
||||
basic::{Decode, Encode, ModifiesReg},
|
||||
parse::LineArg,
|
||||
InstFmt, Parsable, ParseCtx, ParseError, Register,
|
||||
DisplayCtx, InstDisplay, InstFmt, InstFmtArg, Parsable, ParseCtx, ParseError, Register,
|
||||
};
|
||||
use std::array;
|
||||
|
||||
/// Jmp register instruction kind
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
@ -92,6 +93,27 @@ impl Parsable for Inst {
|
||||
}
|
||||
}
|
||||
|
||||
impl InstDisplay for Inst {
|
||||
type Mnemonic = &'static str;
|
||||
|
||||
type Args = impl IntoIterator<Item = InstFmtArg>;
|
||||
|
||||
fn mnemonic<Ctx: DisplayCtx>(&self, _ctx: &Ctx) -> Self::Mnemonic {
|
||||
self.kind.mnemonic()
|
||||
}
|
||||
|
||||
#[auto_enums::auto_enum(Iterator)]
|
||||
fn args<Ctx: DisplayCtx>(&self, _ctx: &Ctx) -> Self::Args {
|
||||
let &Self { target, kind } = self;
|
||||
|
||||
match kind {
|
||||
// If linking with `$ra`, don't output it
|
||||
Kind::Jump | Kind::JumpLink(Register::Ra) => array::IntoIter::new([InstFmtArg::Register(target)]),
|
||||
Kind::JumpLink(reg) => array::IntoIter::new([InstFmtArg::Register(target), InstFmtArg::Register(reg)]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl InstFmt for Inst {
|
||||
fn fmt(&self, _pos: crate::Pos, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
|
||||
@ -5,11 +5,11 @@ use super::ModifiesReg;
|
||||
use crate::inst::{
|
||||
basic::{Decode, Encode},
|
||||
parse::LineArg,
|
||||
InstFmt, Parsable, ParseCtx, ParseError, Register,
|
||||
DisplayCtx, InstDisplay, InstFmt, InstFmtArg, Parsable, ParseCtx, ParseError, Register,
|
||||
};
|
||||
use dcb_util::SignedHex;
|
||||
use int_conv::{Signed, Truncated, ZeroExtended};
|
||||
use std::convert::TryInto;
|
||||
use std::{array, convert::TryInto};
|
||||
|
||||
/// Instruction kind
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
@ -140,6 +140,21 @@ impl Parsable for Inst {
|
||||
}
|
||||
}
|
||||
|
||||
impl InstDisplay for Inst {
|
||||
type Args = array::IntoIter<InstFmtArg, 2>;
|
||||
type Mnemonic = &'static str;
|
||||
|
||||
fn mnemonic<Ctx: DisplayCtx>(&self, _ctx: &Ctx) -> Self::Mnemonic {
|
||||
self.kind.mnemonic()
|
||||
}
|
||||
|
||||
fn args<Ctx: DisplayCtx>(&self, _ctx: &Ctx) -> Self::Args {
|
||||
let &Self { value, addr, offset, .. } = self;
|
||||
|
||||
array::IntoIter::new([InstFmtArg::Register(value), InstFmtArg::register_offset(addr, offset)])
|
||||
}
|
||||
}
|
||||
|
||||
impl InstFmt for Inst {
|
||||
fn fmt(&self, _pos: crate::Pos, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
let Self { addr, value, offset, kind } = self;
|
||||
|
||||
@ -5,10 +5,10 @@ use super::ModifiesReg;
|
||||
use crate::inst::{
|
||||
basic::{Decode, Encode},
|
||||
parse::LineArg,
|
||||
InstFmt, Parsable, ParseCtx, ParseError, Register,
|
||||
DisplayCtx, InstDisplay, InstFmt, InstFmtArg, Parsable, ParseCtx, ParseError, Register,
|
||||
};
|
||||
use int_conv::{Truncated, ZeroExtended};
|
||||
use std::convert::TryInto;
|
||||
use std::{array, convert::TryInto};
|
||||
|
||||
/// Load instructions
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
@ -62,6 +62,21 @@ impl Parsable for Inst {
|
||||
}
|
||||
}
|
||||
|
||||
impl InstDisplay for Inst {
|
||||
type Args = array::IntoIter<InstFmtArg, 2>;
|
||||
type Mnemonic = &'static str;
|
||||
|
||||
fn mnemonic<Ctx: DisplayCtx>(&self, _ctx: &Ctx) -> Self::Mnemonic {
|
||||
"lui"
|
||||
}
|
||||
|
||||
fn args<Ctx: DisplayCtx>(&self, _ctx: &Ctx) -> Self::Args {
|
||||
let &Self { dst, value } = self;
|
||||
|
||||
array::IntoIter::new([InstFmtArg::Register(dst), InstFmtArg::literal(value)])
|
||||
}
|
||||
}
|
||||
|
||||
impl InstFmt for Inst {
|
||||
fn fmt(&self, _pos: crate::Pos, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
let Self { dst, value } = self;
|
||||
|
||||
@ -5,8 +5,9 @@ use super::ModifiesReg;
|
||||
use crate::inst::{
|
||||
basic::{Decode, Encode},
|
||||
parse::LineArg,
|
||||
InstFmt, Parsable, ParseCtx, ParseError, Register,
|
||||
DisplayCtx, InstDisplay, InstFmt, InstFmtArg, Parsable, ParseCtx, ParseError, Register,
|
||||
};
|
||||
use std::array;
|
||||
|
||||
/// Operation kind
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
@ -205,9 +206,27 @@ impl Parsable for Inst {
|
||||
}
|
||||
}
|
||||
|
||||
impl InstDisplay for Inst {
|
||||
type Mnemonic = &'static str;
|
||||
|
||||
type Args = impl Iterator<Item = InstFmtArg>;
|
||||
|
||||
fn mnemonic<Ctx: DisplayCtx>(&self, _ctx: &Ctx) -> Self::Mnemonic {
|
||||
Self::mnemonic(*self)
|
||||
}
|
||||
|
||||
#[auto_enums::auto_enum(Iterator)]
|
||||
fn args<Ctx: DisplayCtx>(&self, _ctx: &Ctx) -> Self::Args {
|
||||
match *self {
|
||||
Self::Mult { lhs, rhs, .. } => array::IntoIter::new([InstFmtArg::Register(lhs), InstFmtArg::Register(rhs)]),
|
||||
Self::MoveFrom { dst: arg, .. } | Self::MoveTo { src: arg, .. } => array::IntoIter::new([InstFmtArg::Register(arg)]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl InstFmt for Inst {
|
||||
fn fmt(&self, _pos: crate::Pos, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
let mnemonic = self.mnemonic();
|
||||
let mnemonic = Self::mnemonic(*self);
|
||||
match self {
|
||||
Self::Mult { lhs, rhs, .. } => write!(f, "{mnemonic} {lhs}, {rhs}"),
|
||||
Self::MoveFrom { dst: arg, .. } | Self::MoveTo { src: arg, .. } => write!(f, "{mnemonic} {arg}"),
|
||||
|
||||
@ -8,7 +8,7 @@ pub mod reg;
|
||||
use crate::inst::{
|
||||
basic::{Decode, Encode, ModifiesReg, TryEncode},
|
||||
parse::LineArg,
|
||||
InstFmt, Parsable, ParseCtx, ParseError, Register,
|
||||
DisplayCtx, InstDisplay, InstFmt, InstFmtArg, Parsable, ParseCtx, ParseError, Register,
|
||||
};
|
||||
|
||||
/// Alu register instructions
|
||||
@ -58,6 +58,27 @@ impl Parsable for Inst {
|
||||
}
|
||||
}
|
||||
|
||||
impl InstDisplay for Inst {
|
||||
type Mnemonic = &'static str;
|
||||
|
||||
type Args = impl Iterator<Item = InstFmtArg>;
|
||||
|
||||
fn mnemonic<Ctx: DisplayCtx>(&self, ctx: &Ctx) -> Self::Mnemonic {
|
||||
match self {
|
||||
Inst::Imm(inst) => inst.mnemonic(ctx),
|
||||
Inst::Reg(inst) => inst.mnemonic(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
#[auto_enums::auto_enum(Iterator)]
|
||||
fn args<Ctx: DisplayCtx>(&self, ctx: &Ctx) -> Self::Args {
|
||||
match self {
|
||||
Inst::Imm(inst) => inst.args(ctx).into_iter(),
|
||||
Inst::Reg(inst) => inst.args(ctx).into_iter(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl InstFmt for Inst {
|
||||
fn fmt(&self, pos: crate::Pos, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
match self {
|
||||
|
||||
@ -4,10 +4,10 @@
|
||||
use crate::inst::{
|
||||
basic::{Decode, ModifiesReg, TryEncode},
|
||||
parse::LineArg,
|
||||
InstFmt, Parsable, ParseCtx, ParseError, Register,
|
||||
DisplayCtx, InstDisplay, InstFmt, InstFmtArg, Parsable, ParseCtx, ParseError, Register,
|
||||
};
|
||||
use int_conv::{Truncated, ZeroExtended};
|
||||
use std::convert::TryInto;
|
||||
use std::{array, convert::TryInto};
|
||||
|
||||
/// Shift immediate instruction kind
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
@ -128,6 +128,27 @@ impl Parsable for Inst {
|
||||
}
|
||||
}
|
||||
|
||||
impl InstDisplay for Inst {
|
||||
type Mnemonic = &'static str;
|
||||
|
||||
type Args = impl IntoIterator<Item = InstFmtArg>;
|
||||
|
||||
fn mnemonic<Ctx: DisplayCtx>(&self, _ctx: &Ctx) -> Self::Mnemonic {
|
||||
self.kind.mnemonic()
|
||||
}
|
||||
|
||||
#[auto_enums::auto_enum(Iterator)]
|
||||
fn args<Ctx: DisplayCtx>(&self, _ctx: &Ctx) -> Self::Args {
|
||||
let &Self { dst, lhs, rhs, .. } = self;
|
||||
|
||||
// If `$dst` and `$lhs` are the same, only print one of them
|
||||
match dst == lhs {
|
||||
true => array::IntoIter::new([InstFmtArg::Register(dst), InstFmtArg::literal(rhs)]),
|
||||
false => array::IntoIter::new([InstFmtArg::Register(dst), InstFmtArg::Register(lhs), InstFmtArg::literal(rhs)]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl InstFmt for Inst {
|
||||
fn fmt(&self, _pos: crate::Pos, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
let Self { dst, lhs, rhs, kind } = self;
|
||||
|
||||
@ -4,8 +4,9 @@
|
||||
use crate::inst::{
|
||||
basic::{Decode, Encode, ModifiesReg},
|
||||
parse::LineArg,
|
||||
InstFmt, Parsable, ParseCtx, ParseError, Register,
|
||||
DisplayCtx, InstDisplay, InstFmt, InstFmtArg, Parsable, ParseCtx, ParseError, Register,
|
||||
};
|
||||
use std::array;
|
||||
|
||||
/// Shift register instruction kind
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
@ -108,6 +109,27 @@ impl Parsable for Inst {
|
||||
}
|
||||
}
|
||||
|
||||
impl InstDisplay for Inst {
|
||||
type Mnemonic = &'static str;
|
||||
|
||||
type Args = impl IntoIterator<Item = InstFmtArg>;
|
||||
|
||||
fn mnemonic<Ctx: DisplayCtx>(&self, _ctx: &Ctx) -> Self::Mnemonic {
|
||||
self.kind.mnemonic()
|
||||
}
|
||||
|
||||
#[auto_enums::auto_enum(Iterator)]
|
||||
fn args<Ctx: DisplayCtx>(&self, _ctx: &Ctx) -> Self::Args {
|
||||
let &Self { dst, lhs, rhs, .. } = self;
|
||||
|
||||
// If `$dst` and `$lhs` are the same, only print one of them
|
||||
match dst == lhs {
|
||||
true => array::IntoIter::new([InstFmtArg::Register(dst), InstFmtArg::Register(rhs)]),
|
||||
false => array::IntoIter::new([InstFmtArg::Register(dst), InstFmtArg::Register(lhs), InstFmtArg::Register(rhs)]),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl InstFmt for Inst {
|
||||
fn fmt(&self, _pos: crate::Pos, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
let Self { dst, lhs, rhs, kind } = self;
|
||||
|
||||
@ -5,11 +5,11 @@ use super::ModifiesReg;
|
||||
use crate::inst::{
|
||||
basic::{Decode, Encode},
|
||||
parse::LineArg,
|
||||
InstFmt, Parsable, ParseCtx, ParseError, Register,
|
||||
DisplayCtx, InstDisplay, InstFmt, InstFmtArg, Parsable, ParseCtx, ParseError, Register,
|
||||
};
|
||||
use dcb_util::SignedHex;
|
||||
use int_conv::{Signed, Truncated, ZeroExtended};
|
||||
use std::convert::TryInto;
|
||||
use std::{array, convert::TryInto};
|
||||
|
||||
/// Store instruction kind
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
@ -127,6 +127,21 @@ impl Parsable for Inst {
|
||||
}
|
||||
}
|
||||
|
||||
impl InstDisplay for Inst {
|
||||
type Args = array::IntoIter<InstFmtArg, 2>;
|
||||
type Mnemonic = &'static str;
|
||||
|
||||
fn mnemonic<Ctx: DisplayCtx>(&self, _ctx: &Ctx) -> Self::Mnemonic {
|
||||
self.kind.mnemonic()
|
||||
}
|
||||
|
||||
fn args<Ctx: DisplayCtx>(&self, _ctx: &Ctx) -> Self::Args {
|
||||
let &Self { value, addr, offset, .. } = self;
|
||||
|
||||
array::IntoIter::new([InstFmtArg::Register(value), InstFmtArg::register_offset(addr, offset)])
|
||||
}
|
||||
}
|
||||
|
||||
impl InstFmt for Inst {
|
||||
fn fmt(&self, _pos: crate::Pos, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
let Self { addr, value, offset, kind } = self;
|
||||
|
||||
@ -5,9 +5,9 @@ use super::ModifiesReg;
|
||||
use crate::inst::{
|
||||
basic::{Decode, TryEncode},
|
||||
parse::LineArg,
|
||||
InstFmt, Parsable, ParseCtx, ParseError, Register,
|
||||
DisplayCtx, InstDisplay, InstFmt, InstFmtArg, Parsable, ParseCtx, ParseError, Register,
|
||||
};
|
||||
use std::convert::TryInto;
|
||||
use std::{array, convert::TryInto};
|
||||
|
||||
/// Sys instruction func
|
||||
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
|
||||
@ -86,7 +86,6 @@ impl TryEncode for Inst {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl Parsable for Inst {
|
||||
fn parse<Ctx: ?Sized + ParseCtx>(mnemonic: &str, args: &[LineArg], _ctx: &Ctx) -> Result<Self, ParseError> {
|
||||
let kind = match mnemonic {
|
||||
@ -104,6 +103,18 @@ impl Parsable for Inst {
|
||||
}
|
||||
}
|
||||
|
||||
impl InstDisplay for Inst {
|
||||
type Args = array::IntoIter<InstFmtArg, 1>;
|
||||
type Mnemonic = &'static str;
|
||||
|
||||
fn mnemonic<Ctx: DisplayCtx>(&self, _ctx: &Ctx) -> Self::Mnemonic {
|
||||
self.kind.mnemonic()
|
||||
}
|
||||
|
||||
fn args<Ctx: DisplayCtx>(&self, _ctx: &Ctx) -> Self::Args {
|
||||
array::IntoIter::new([InstFmtArg::literal(self.comment)])
|
||||
}
|
||||
}
|
||||
|
||||
impl InstFmt for Inst {
|
||||
fn fmt(&self, _pos: crate::Pos, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
|
||||
@ -4,9 +4,70 @@
|
||||
|
||||
// Imports
|
||||
use super::InstTarget;
|
||||
use crate::Pos;
|
||||
use crate::{inst::Register, Pos};
|
||||
use std::fmt;
|
||||
|
||||
/// Instruction display
|
||||
pub trait InstDisplay {
|
||||
/// Mnemonic type
|
||||
type Mnemonic: fmt::Display;
|
||||
|
||||
/// Args type
|
||||
type Args: IntoIterator<Item = InstFmtArg>;
|
||||
|
||||
/// Returns this instruction's mnemonic
|
||||
fn mnemonic<Ctx: DisplayCtx>(&self, ctx: &Ctx) -> Self::Mnemonic;
|
||||
|
||||
/// Returns all arguments of this instruction
|
||||
fn args<Ctx: DisplayCtx>(&self, ctx: &Ctx) -> Self::Args;
|
||||
}
|
||||
|
||||
/// Display context
|
||||
pub trait DisplayCtx {
|
||||
/// Current position
|
||||
fn cur_pos(&self) -> Pos;
|
||||
}
|
||||
|
||||
/// An formattable argument
|
||||
#[derive(PartialEq, Clone, Debug)]
|
||||
pub enum InstFmtArg {
|
||||
/// Register
|
||||
Register(Register),
|
||||
|
||||
/// Register offset
|
||||
RegisterOffset {
|
||||
/// The register
|
||||
register: Register,
|
||||
|
||||
/// The offset
|
||||
offset: i64,
|
||||
},
|
||||
|
||||
/// Literal
|
||||
Literal(i64),
|
||||
|
||||
/// Target
|
||||
Target(Pos),
|
||||
}
|
||||
|
||||
impl InstFmtArg {
|
||||
/// Creates a `Literal` variant
|
||||
#[must_use]
|
||||
pub fn literal(value: impl Into<i64>) -> Self {
|
||||
Self::Literal(value.into())
|
||||
}
|
||||
|
||||
/// Creates a `RegisterOffset` variant
|
||||
#[must_use]
|
||||
pub fn register_offset(register: Register, offset: impl Into<i64>) -> Self {
|
||||
Self::RegisterOffset {
|
||||
register,
|
||||
offset: offset.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// A formattable instruction
|
||||
///
|
||||
/// This trait defines formatting for all instruction, which may require the
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user