1use std::fmt::Write as _;
10use std::ops::Range;
11
12use crate::sim::SimErr;
13
14use super::{CondCode, IOffset, ImmOrReg, Reg, TrapVect8};
15
16const OP_BR: u16 = 0b0000;
17const OP_ADD: u16 = 0b0001;
18const OP_LD: u16 = 0b0010;
19const OP_ST: u16 = 0b0011;
20const OP_JSR: u16 = 0b0100;
21const OP_AND: u16 = 0b0101;
22const OP_LDR: u16 = 0b0110;
23const OP_STR: u16 = 0b0111;
24const OP_RTI: u16 = 0b1000;
25const OP_NOT: u16 = 0b1001;
26const OP_LDI: u16 = 0b1010;
27const OP_STI: u16 = 0b1011;
28const OP_JMP: u16 = 0b1100;
29const OP_LEA: u16 = 0b1110;
30const OP_TRAP: u16 = 0b1111;
31
32#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
42pub enum SimInstr {
43 #[allow(missing_docs)]
44 BR(CondCode, IOffset<9>),
45 #[allow(missing_docs)]
46 ADD(Reg, Reg, ImmOrReg<5>),
47 #[allow(missing_docs)]
48 LD(Reg, IOffset<9>),
49 #[allow(missing_docs)]
50 ST(Reg, IOffset<9>),
51 #[allow(missing_docs)]
52 JSR(ImmOrReg<11>),
53 #[allow(missing_docs)]
54 AND(Reg, Reg, ImmOrReg<5>),
55 #[allow(missing_docs)]
56 LDR(Reg, Reg, IOffset<6>),
57 #[allow(missing_docs)]
58 STR(Reg, Reg, IOffset<6>),
59 #[allow(missing_docs)]
60 RTI,
61 #[allow(missing_docs)]
62 NOT(Reg, Reg),
63 #[allow(missing_docs)]
64 LDI(Reg, IOffset<9>),
65 #[allow(missing_docs)]
66 STI(Reg, IOffset<9>),
67 #[allow(missing_docs)]
68 JMP(Reg),
69 #[allow(missing_docs)]
71 LEA(Reg, IOffset<9>),
72 #[allow(missing_docs)]
73 TRAP(TrapVect8),
74}
75impl std::fmt::Display for SimInstr {
76 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
77 match self {
78 Self::BR(cc, off) => {
79 if cc != &0 {
80 write!(f, "BR")?;
81 if cc & 0b100 != 0 { f.write_char('n')?; };
82 if cc & 0b010 != 0 { f.write_char('z')?; };
83 if cc & 0b001 != 0 { f.write_char('p')?; };
84 } else {
85 write!(f, "NOP")?;
86 }
87
88 write!(f, " {off}")
89 },
90 Self::ADD(dr, sr1, sr2) => write!(f, "ADD {dr}, {sr1}, {sr2}"),
91 Self::LD(dr, off) => write!(f, "LD {dr}, {off}"),
92 Self::ST(sr, off) => write!(f, "ST {sr}, {off}"),
93 Self::JSR(off) => match off {
94 ImmOrReg::Imm(imm) => write!(f, "JSR {imm}"),
95 ImmOrReg::Reg(reg) => write!(f, "JSRR {reg}"),
96 },
97 Self::AND(dr, sr1, sr2) => write!(f, "AND {dr}, {sr1}, {sr2}"),
98 Self::LDR(dr, br, off) => write!(f, "LDR {dr}, {br}, {off}"),
99 Self::STR(sr, br, off) => write!(f, "STR {sr}, {br}, {off}"),
100 Self::RTI => f.write_str("RTI"),
101 Self::NOT(dr, sr) => write!(f, "NOT {dr}, {sr}"),
102 Self::LDI(dr, off) => write!(f, "LDI {dr}, {off}"),
103 Self::STI(sr, off) => write!(f, "STI {sr}, {off}"),
104 Self::JMP(br) => write!(f, "JMP {br}"),
105 Self::LEA(dr, off) => write!(f, "LEA {dr}, {off}"),
106 Self::TRAP(vect) => write!(f, "TRAP {vect:02X}")
107 }
108 }
109}
110
111impl SimInstr {
112 pub fn opcode(&self) -> u16 {
114 match self {
115 SimInstr::BR(_, _) => OP_BR,
116 SimInstr::ADD(_, _, _) => OP_ADD,
117 SimInstr::LD(_, _) => OP_LD,
118 SimInstr::ST(_, _) => OP_ST,
119 SimInstr::JSR(_) => OP_JSR,
120 SimInstr::AND(_, _, _) => OP_AND,
121 SimInstr::LDR(_, _, _) => OP_LDR,
122 SimInstr::STR(_, _, _) => OP_STR,
123 SimInstr::RTI => OP_RTI,
124 SimInstr::NOT(_, _) => OP_NOT,
125 SimInstr::LDI(_, _) => OP_LDI,
126 SimInstr::STI(_, _) => OP_STI,
127 SimInstr::JMP(_) => OP_JMP,
128 SimInstr::LEA(_, _) => OP_LEA,
130 SimInstr::TRAP(_) => OP_TRAP,
131 }
132 }
133
134 pub fn encode(&self) -> u16 {
136 match self {
137 SimInstr::BR(cc, off) => join_bits([
138 (self.opcode(), 12..16),
139 (*cc as u16, 9..12),
140 (off.get() as u16, 0..9)
141 ]),
142 SimInstr::ADD(dr, sr1, ImmOrReg::Imm(i2)) => join_bits([ (self.opcode(), 12..16),
144 (dr.reg_no() as u16, 9..12),
145 (sr1.reg_no() as u16, 6..9),
146 (0b1, 5..6),
147 (i2.get() as u16, 0..5)
148 ]),
149 SimInstr::ADD(dr, sr1, ImmOrReg::Reg(r2)) => join_bits([ (self.opcode(), 12..16),
151 (dr.reg_no() as u16, 9..12),
152 (sr1.reg_no() as u16, 6..9),
153 (0b000, 3..6),
154 (r2.reg_no() as u16, 0..3)
155 ]),
156 SimInstr::LD(dr, off) => join_bits([
157 (self.opcode(), 12..16),
158 (dr.reg_no() as u16, 9..12),
159 (off.get() as u16, 0..9)
160 ]),
161 SimInstr::ST(sr, off) => join_bits([
162 (self.opcode(), 12..16),
163 (sr.reg_no() as u16, 9..12),
164 (off.get() as u16, 0..9)
165 ]),
166 SimInstr::JSR(ImmOrReg::Imm(off)) => join_bits([ (self.opcode(), 12..16),
168 (0b1, 11..12),
169 (off.get() as u16, 0..11)
170 ]),
171 SimInstr::JSR(ImmOrReg::Reg(br)) => join_bits([ (self.opcode(), 12..16),
173 (0b000, 9..12),
174 (br.reg_no() as u16, 6..9),
175 (0b000_000, 0..6)
176 ]),
177 SimInstr::AND(dr, sr1, ImmOrReg::Imm(i2)) => join_bits([ (self.opcode(), 12..16),
179 (dr.reg_no() as u16, 9..12),
180 (sr1.reg_no() as u16, 6..9),
181 (0b1, 5..6),
182 (i2.get() as u16, 0..5)
183 ]),
184 SimInstr::AND(dr, sr1, ImmOrReg::Reg(r2)) => join_bits([ (self.opcode(), 12..16),
186 (dr.reg_no() as u16, 9..12),
187 (sr1.reg_no() as u16, 6..9),
188 (0b000, 3..6),
189 (r2.reg_no() as u16, 0..3)
190 ]),
191 SimInstr::LDR(dr, br, off) => join_bits([
192 (self.opcode(), 12..16),
193 (dr.reg_no() as u16, 9..12),
194 (br.reg_no() as u16, 6..9),
195 (off.get() as u16, 0..6)
196 ]),
197 SimInstr::STR(dr, br, off) => join_bits([
198 (self.opcode(), 12..16),
199 (dr.reg_no() as u16, 9..12),
200 (br.reg_no() as u16, 6..9),
201 (off.get() as u16, 0..6)
202 ]),
203 SimInstr::RTI => join_bits([
204 (self.opcode(), 12..16),
205 (0b0000_0000_0000, 0..12)
206 ]),
207 SimInstr::NOT(dr, sr) => join_bits([
208 (self.opcode(), 12..16),
209 (dr.reg_no() as u16, 9..12),
210 (sr.reg_no() as u16, 6..9),
211 (0b111_111, 0..6)
212 ]),
213 SimInstr::LDI(dr, off) => join_bits([
214 (self.opcode(), 12..16),
215 (dr.reg_no() as u16, 9..12),
216 (off.get() as u16, 0..9)
217 ]),
218 SimInstr::STI(sr, off) => join_bits([
219 (self.opcode(), 12..16),
220 (sr.reg_no() as u16, 9..12),
221 (off.get() as u16, 0..9)
222 ]),
223 SimInstr::JMP(br) => join_bits([
224 (self.opcode(), 12..16),
225 (0b000, 9..12),
226 (br.reg_no() as u16, 6..9),
227 (0b000_000, 0..6)
228 ]),
229 SimInstr::LEA(dr, off) => join_bits([
230 (self.opcode(), 12..16),
231 (dr.reg_no() as u16, 9..12),
232 (off.get() as u16, 0..9)
233 ]),
234 SimInstr::TRAP(vect) => join_bits([
235 (self.opcode(), 12..16),
236 (0b0000, 8..12),
237 (vect.get(), 0..8)
238 ]),
239 }
240 }
241
242 pub fn decode(word: u16) -> Result<Self, SimErr> {
245 let opcode = word.slice(12..16);
248
249 match opcode {
250 OP_BR => {
251 let cc = word.slice(9..12) as u8;
252 let off = word.slice(0..9).interpret();
253 Ok(Self::BR(cc, off))
254 },
255 OP_ADD => {
256 let dr = word.slice(9..12).interpret();
257 let sr1 = word.slice(6..9).interpret();
258 let sr2 = match word.slice(5..6) != 0 {
259 false => {
260 word.slice(3..5).assert_equals(0b00)?;
261 ImmOrReg::Reg(word.slice(0..3).interpret())
262 },
263 true => ImmOrReg::Imm(word.slice(0..5).interpret()),
264 };
265 Ok(Self::ADD(dr, sr1, sr2))
266 },
267 OP_LD => {
268 let dr = word.slice(9..12).interpret();
269 let off = word.slice(0..9).interpret();
270 Ok(Self::LD(dr, off))
271 }
272 OP_ST => {
273 let sr = word.slice(9..12).interpret();
274 let off = word.slice(0..9).interpret();
275 Ok(Self::ST(sr, off))
276 },
277 OP_JSR => {
278 let val = match word.slice(11..12) != 0 {
279 true => ImmOrReg::Imm(word.slice(0..11).interpret()),
280 false => {
281 word.slice(9..11).assert_equals(0b00)?;
282 word.slice(0..6).assert_equals(0b000_000)?;
283 ImmOrReg::Reg(word.slice(6..9).interpret())
284 },
285 };
286 Ok(Self::JSR(val))
287 },
288 OP_AND => {
289 let dr = word.slice(9..12).interpret();
290 let sr1 = word.slice(6..9).interpret();
291 let sr2 = match word.slice(5..6) != 0 {
292 false => {
293 word.slice(3..5).assert_equals(0b00)?;
294 ImmOrReg::Reg(word.slice(0..3).interpret())
295 },
296 true => ImmOrReg::Imm(word.slice(0..5).interpret()),
297 };
298 Ok(Self::AND(dr, sr1, sr2))
299 },
300 OP_LDR => {
301 let dr = word.slice(9..12).interpret();
302 let br = word.slice(6..9).interpret();
303 let off = word.slice(0..6).interpret();
304 Ok(Self::LDR(dr, br, off))
305 },
306 OP_STR => {
307 let sr = word.slice(9..12).interpret();
308 let br = word.slice(6..9).interpret();
309 let off = word.slice(0..6).interpret();
310 Ok(Self::STR(sr, br, off))
311 },
312 OP_RTI => {
313 word.slice(0..12).assert_equals(0b0000_0000_0000)?;
314 Ok(Self::RTI)
315 },
316 OP_NOT => {
317 let dr = word.slice(9..12).interpret();
318 let sr = word.slice(6..9).interpret();
319 word.slice(0..6).assert_equals(0b111_111)?;
320 Ok(Self::NOT(dr, sr))
321 },
322 OP_LDI => {
323 let dr = word.slice(9..12).interpret();
324 let off = word.slice(0..9).interpret();
325 Ok(Self::LDI(dr, off))
326 },
327 OP_STI => {
328 let sr = word.slice(9..12).interpret();
329 let off = word.slice(0..9).interpret();
330 Ok(Self::STI(sr, off))
331 },
332 OP_JMP => {
333 word.slice(9..11).assert_equals(0b00)?;
334 let reg = word.slice(6..9).interpret();
335 word.slice(0..6).assert_equals(0b000_000)?;
336 Ok(Self::JMP(reg))
337 },
338 OP_LEA => {
339 let dr = word.slice(9..12).interpret();
340 let off = word.slice(0..9).interpret();
341 Ok(Self::LEA(dr, off))
342 },
343 OP_TRAP => {
344 word.slice(8..12).assert_equals(0b0000)?;
345 let vect = word.slice(0..8).interpret();
346 Ok(Self::TRAP(vect))
347 },
348 _ => Err(SimErr::IllegalOpcode)
349 }
350 }
351}
352
353fn join_bits<const N: usize>(bits: [(u16, Range<usize>); N]) -> u16 {
356 bits.into_iter()
357 .map(|(val, Range { start, end })| {
358 let len = end - start;
359 let mask = (1 << len) - 1;
360 (val & mask) << start
361 })
362 .fold(0, std::ops::BitOr::bitor)
363}
364
365trait FromBits: Sized {
366 fn from_bits(bits: u16) -> Self;
368}
369trait DecodeUtils: Sized + Eq {
370 fn interpret<T: FromBits>(self) -> T;
372
373 fn assert_equals(self, bits: Self) -> Result<(), SimErr> {
375 match self == bits {
376 true => Ok(()),
377 false => Err(SimErr::InvalidInstrFormat),
378 }
379 }
380
381 fn slice(self, range: Range<usize>) -> Self;
384}
385impl DecodeUtils for u16 {
386 fn interpret<T: FromBits>(self) -> T {
387 T::from_bits(self)
388 }
389
390 fn slice(self, range: Range<usize>) -> Self {
391 let len = range.end - range.start;
392 (self >> range.start) & ((1 << len) - 1)
393 }
394}
395
396impl FromBits for Reg {
397 fn from_bits(bits: u16) -> Self {
398 Reg::try_from(bits as u8).unwrap()
399 }
400}
401impl<const N: u32> FromBits for IOffset<N> {
402 fn from_bits(bits: u16) -> Self {
403 Self::new_trunc(bits as i16)
404 }
405}
406impl<const N: u32> FromBits for crate::ast::Offset<u16, N> {
407 fn from_bits(bits: u16) -> Self {
408 Self::new_trunc(bits)
409 }
410}