1#![allow(dead_code)]
2
3use std::str::FromStr;
4
5use crate::Register;
6
7#[derive(Debug, PartialEq, Clone, Copy)]
8pub enum Instruction {
9 AddInstruction(AddInstruction),
10 AndInstruction(AndInstruction),
11 Br(Condition, PCOffset9),
12 Jmp(Register),
13 Jsr(PCOffset11),
14 Jsrr(Register),
15 Ldb(Register, Register, PCOffset6),
16 Ldi(Register, Register, PCOffset6),
17 Ldr(Register, Register, PCOffset6),
18 Lea(Register, PCOffset9),
19 Not(Register, Register),
20 Ret,
21 Rti,
22 Shf(Register, Register, Bit, Bit, Immediate4),
23 Stb(Register, Register, PCOffset6),
24 Sti(Register, Register, PCOffset6),
25 Str(Register, Register, PCOffset6),
26 Trap(TrapVect8),
27}
28
29impl From<&Instruction> for [u8; 2] {
30 fn from(value: &Instruction) -> Self {
31 let mut bytes = [0; 2];
32
33 match value {
34 Instruction::AddInstruction(AddInstruction::AddReg(r1, r2, r3)) => {
35 bytes[0] |= 0b00010000;
36 bytes[0] |= (r1.to_index() as u8) << 1;
37 bytes[0] |= (r2.to_index() as u8) >> 2;
38
39 bytes[1] |= (r2.to_index() as u8) << 6;
40 bytes[1] |= (r3.to_index() as u8) << 0;
41 }
42 Instruction::AddInstruction(AddInstruction::AddImm(r1, r2, imm5)) => {
43 bytes[0] |= 0b00010000;
44 bytes[0] |= (r1.to_index() as u8) << 1;
45 bytes[0] |= (r2.to_index() as u8) >> 2;
46
47 bytes[1] |= (r2.to_index() as u8) << 6;
48 bytes[1] |= 0b00100000;
49 bytes[1] |= imm5.0 & 0b00011111;
50 }
51 other => todo!("wah: {:?}", other),
52 }
53
54 bytes
55 }
56}
57
58#[derive(Debug, PartialEq, Clone, Copy)]
59pub enum AddInstruction {
60 AddReg(Register, Register, Register),
61 AddImm(Register, Register, Immediate5),
62}
63
64#[derive(Debug, PartialEq, Clone, Copy)]
65pub enum AndInstruction {
66 AndReg(Register, Register, Register),
67 AndImm(Register, Register, Immediate5),
68}
69
70#[derive(Debug, PartialEq, Clone, Copy)]
71pub struct Immediate5(pub(crate) u8);
72
73impl Immediate5 {
74 pub fn new(imm5: u8) -> eyre::Result<Self> {
75 assert!(imm5 < 32);
76 if imm5 >= 32 {
77 return Err(eyre::eyre!("value `{}` too large, must be < 32", imm5));
78 }
79
80 Ok(Immediate5(imm5))
81 }
82
83 pub fn value(&self) -> u8 {
84 self.0
85 }
86}
87
88impl FromStr for Immediate5 {
89 type Err = eyre::Report;
90
91 fn from_str(s: &str) -> Result<Self, Self::Err> {
92 Self::new(s.parse()?)
94 }
95}
96
97impl Immediate5 {
98 pub fn to_value(&self) -> u16 {
99 self.0 as u16
100 }
101}
102
103#[derive(Debug, PartialEq, Clone, Copy)]
104pub struct Immediate4(pub(crate) u8);
105
106impl Immediate4 {
107 pub fn new(val: u8) -> eyre::Result<Self> {
108 if val >= 16 {
109 return Err(eyre::eyre!("value `{}` too large, must be < 16", val));
110 }
111
112 Ok(Immediate4(val))
113 }
114}
115
116#[derive(Debug, Default, PartialEq, Clone, Copy)]
117pub struct Condition {
118 n: bool,
119 z: bool,
120 p: bool,
121}
122
123#[derive(Debug, PartialEq, Clone, Copy)]
124pub struct PCOffset9(u16);
125#[derive(Debug, PartialEq, Clone, Copy)]
126pub struct PCOffset11(u16);
127#[derive(Debug, PartialEq, Clone, Copy)]
128pub struct PCOffset6(u8);
129
130#[derive(Debug, PartialEq, Clone, Copy)]
131pub struct Bit(bool);
132
133#[derive(Debug, PartialEq, Clone, Copy)]
134pub struct TrapVect8(u8);