assembler: enhance error handling and tokenization logic
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
use crate::{instructions::encode::Encode, prelude::*};
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
|
||||
pub enum Interrupt {
|
||||
Software(u8),
|
||||
Breakpoint,
|
||||
#[default]
|
||||
HardFault,
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
//! Various types of arguments that instructions can take, alongside encoding and decoding logic.
|
||||
//! Various types of arguments that instructions can take, alongside encoding and decoding
|
||||
//! logic.
|
||||
|
||||
use crate::{
|
||||
instructions::{RegisterParseError, encode::Encode},
|
||||
@@ -35,18 +36,20 @@ impl std::fmt::Display for ArgsDecodeError {
|
||||
|
||||
impl std::error::Error for ArgsDecodeError {}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||
/// Used by instructions with 2 registers and an immediate argument.
|
||||
pub struct ITypeArgs {
|
||||
pub immediate: u16,
|
||||
pub r1: Register,
|
||||
/// May not actually be used by some instructions taking an immediate e.g. LUI. This is solved by making the constructor take Options.
|
||||
/// May not actually be used by some instructions taking an immediate e.g. LUI. This
|
||||
/// is solved by making the constructor take Options.
|
||||
pub r2: Register,
|
||||
}
|
||||
|
||||
impl ITypeArgs {
|
||||
#[must_use]
|
||||
/// Creates a new [`ITypeArgs`]. If r1 or r2 is unset, they will be replaced with [`Register::NoReg`].
|
||||
/// Creates a new [`ITypeArgs`]. If r1 or r2 is unset, they will be replaced with
|
||||
/// [`Register::NoReg`].
|
||||
pub fn new(immediate: u16, r1: Option<Register>, r2: Option<Register>) -> Self {
|
||||
let r1 = r1.unwrap_or_default();
|
||||
let r2 = r2.unwrap_or_default();
|
||||
@@ -56,8 +59,8 @@ impl ITypeArgs {
|
||||
}
|
||||
|
||||
impl Encode for ITypeArgs {
|
||||
/// Encodes an I-type instruction from its fields. These must have some unused high-order
|
||||
/// bits set to 0 else the bit shifting logic gets fucked.
|
||||
/// Encodes an I-type instruction from its fields. These must have some unused
|
||||
/// high-order bits set to 0 else the bit shifting logic gets fucked.
|
||||
fn encode(self, opcode: u8) -> u32 {
|
||||
let opcode = u32::from(opcode);
|
||||
let r1 = self.r1 as u32;
|
||||
@@ -84,7 +87,7 @@ impl TryFrom<u32> for ITypeArgs {
|
||||
}
|
||||
|
||||
/// Used by instructions not using immediates (besides 5 bit shift values).
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||
pub struct RTypeArgs {
|
||||
pub sr1: Register,
|
||||
pub sr2: Register,
|
||||
@@ -95,7 +98,8 @@ pub struct RTypeArgs {
|
||||
|
||||
impl RTypeArgs {
|
||||
#[must_use]
|
||||
/// Creates a new [`RTypeArgs`]. If any registers are unset, they will be replaced with [`Register::NoReg`]. If `shamt` is unset, it will be set to 0.
|
||||
/// Creates a new [`RTypeArgs`]. If any registers are unset, they will be replaced
|
||||
/// with [`Register::NoReg`]. If `shamt` is unset, it will be set to 0.
|
||||
pub fn new(
|
||||
sr1: Option<Register>,
|
||||
sr2: Option<Register>,
|
||||
@@ -122,7 +126,8 @@ impl Encode for RTypeArgs {
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// - `shamt`: The amount to shift value (used only in shift instructions, otherwise 0).
|
||||
/// - `shamt`: The amount to shift value (used only in shift instructions, otherwise
|
||||
/// 0).
|
||||
fn encode(self, opcode: u8) -> u32 {
|
||||
let opcode = u32::from(opcode);
|
||||
let sr1 = self.sr1 as u32;
|
||||
|
||||
Reference in New Issue
Block a user