Skip to content

Commit 5f59a41

Browse files
Make LC3 a Trait (#1)
* Move definitions to their own file * Make LC3 machines into a trait Define an `LC3` trait with all necessary interface methods. Move the existing `LC3` into `CoreLC3`. This allows for some alternative backends to hook into `Instruction` logic, e.g. an implementation only tracking nonzero memory to save space or an implementation layering for rollback. Also added `thiserror` as a crate to make error definitions easier. * Apply clippy lints
1 parent 5c7f6b1 commit 5f59a41

File tree

7 files changed

+902
-619
lines changed

7 files changed

+902
-619
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,5 @@ name = "lc3sim"
1414
path = "src/cli.rs"
1515

1616
[dependencies]
17+
thiserror = "2"
1718

src/defs.rs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
use thiserror::Error;
2+
3+
pub type LC3Word = u16;
4+
pub type SignedLC3Word = i16;
5+
pub type LC3MemAddr = u16;
6+
7+
pub const ADDR_SPACE_SIZE: usize = 2_usize.pow(16_u32); //size of the memory address space
8+
pub const TRAP_VEC_TBL: LC3Word = 0x0000; //first address of the trap vector table
9+
pub const IR_VEC_TBL: LC3Word = 0x0100; //first address of the interrupt vector table
10+
pub const OS_SUPER_STACK: LC3Word = 0x0200; //first address of the operating and supervisor
11+
//stack space
12+
pub const USER_SPACE: LC3Word = 0x3000; //first address of the user code space
13+
pub const DEV_REG_ADDR: LC3Word = 0xFE00; //first address of the device register address
14+
//space
15+
16+
pub const NUM_REGS: usize = 8_usize; //number of registers in the LC3 spec
17+
18+
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
19+
pub enum RegAddr {
20+
Zero,
21+
One,
22+
Two,
23+
Three,
24+
Four,
25+
Five,
26+
Six,
27+
Seven,
28+
}
29+
30+
impl RegAddr {
31+
/// `const` optimized u8 conversion.
32+
///
33+
/// Panics when u8 is out of range.
34+
pub const fn panic_from_u8(value: u8) -> Self {
35+
match value {
36+
0 => RegAddr::Zero,
37+
1 => RegAddr::One,
38+
2 => RegAddr::Two,
39+
3 => RegAddr::Three,
40+
4 => RegAddr::Four,
41+
5 => RegAddr::Five,
42+
6 => RegAddr::Six,
43+
7 => RegAddr::Seven,
44+
_ => panic!("Argument outside of [0, 7] (the valid LC-3 registers"),
45+
}
46+
}
47+
}
48+
49+
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Error)]
50+
#[error("{0} is not in [0, 7] (the valid LC-3 registers)")]
51+
pub struct InvalidRegAddr(u8);
52+
53+
impl TryFrom<u8> for RegAddr {
54+
type Error = InvalidRegAddr;
55+
fn try_from(value: u8) -> Result<Self, Self::Error> {
56+
match value {
57+
0 => Ok(RegAddr::Zero),
58+
1 => Ok(RegAddr::One),
59+
2 => Ok(RegAddr::Two),
60+
3 => Ok(RegAddr::Three),
61+
4 => Ok(RegAddr::Four),
62+
5 => Ok(RegAddr::Five),
63+
6 => Ok(RegAddr::Six),
64+
7 => Ok(RegAddr::Seven),
65+
x => Err(InvalidRegAddr(x)),
66+
}
67+
}
68+
}
69+
70+
impl From<RegAddr> for u8 {
71+
fn from(value: RegAddr) -> Self {
72+
match value {
73+
RegAddr::Zero => 0,
74+
RegAddr::One => 1,
75+
RegAddr::Two => 2,
76+
RegAddr::Three => 3,
77+
RegAddr::Four => 4,
78+
RegAddr::Five => 5,
79+
RegAddr::Six => 6,
80+
RegAddr::Seven => 7,
81+
}
82+
}
83+
}
84+
85+
impl From<RegAddr> for usize {
86+
fn from(value: RegAddr) -> Self {
87+
u8::from(value) as usize
88+
}
89+
}

0 commit comments

Comments
 (0)