1use monistode_binutils::{Architecture, Executable};
2
3use crate::tightly_packed_array;
4
5use super::{
6 arithmetic,
7 common::{Processor, ProcessorContinue},
8 flag_register::{implement_flag_register, FlagRegister, ProcessorFlags},
9 memory::{two_byte_memory, Memory, TwoByteMemory},
10 stack::{two_byte_stack, Stack, TwoByteStack},
11};
12use num_derive::FromPrimitive;
13use num_traits::FromPrimitive;
14
15#[derive(Debug, FromPrimitive)]
16enum Opcode {
17 Halt = 0b00000,
18 Load = 0b000001,
19 Store = 0b000010,
20 MovRegImm = 0b000110,
21 MovRegReg = 0b000101,
22 Push = 0b101000,
23 Pop = 0b101001,
24 Add = 0b000011,
25 Addc = 0b100100,
26 Sub = 0b000100,
27 Mul = 0b001010,
28 Div = 0b001011,
29 And = 0b001100,
30 Or = 0b001101,
31 Xor = 0b001110,
32 Not = 0b001111,
33 Lsh = 0b010000,
34 Rsh = 0b010001,
35 CallAddr = 0b010010,
36 CallRegAddr = 0b010011,
37 Ret = 0b010100,
38 CmpRegReg = 0b010101,
39 CmpRegImm = 0b010110,
40 TestRegReg = 0b010111,
41 TestRegImm = 0b011000,
42 JmpAddr = 0b011001,
43 JmpReg = 0b011010,
44 Je = 0b001000,
45 Jne = 0b011011,
46 Jg = 0b011100,
47 Jge = 0b011101,
48 Jl = 0b011110,
49 Jle = 0b011111,
50 In = 0b100000,
51 OutImmImm = 0b100001,
52 OutImmReg = 0b100010,
53 Nop = 0b100011,
54}
55
56macro_rules! with_registers {
57 ($processor:ident, $args_head:ident, $op:expr) => {{
58 let next_byte = $processor.next();
59 let register_3 = (next_byte >> 1) & 0b111;
61 let register_2 = (next_byte >> 4) & 0b111;
62 let register_1 = (next_byte >> 7) & 0b1 | $args_head << 1;
63 $op(register_1, register_2, register_3)
64 }};
65}
66
67macro_rules! with_immediate {
68 ($processor: ident, $args_head:ident, $op:expr) => {{
69 let mut immediate = ($args_head as u16) << 14;
70 immediate = immediate | ($processor.next() as u16) << 6;
71 immediate = immediate | ($processor.next() as u16) >> 2;
72 $op(immediate)
73 }};
74}
75
76macro_rules! with_two_immediates {
77 ($processor: ident, $args_head:ident, $op:expr) => {{
78 let mut immediate_1 = ($args_head as u16) << 14;
79 immediate_1 = immediate_1 | ($processor.next() as u16) << 6;
80 let intersecting_byte = $processor.next();
81 immediate_1 = immediate_1 | (intersecting_byte as u16) >> 2;
82 let mut immediate_2 = (intersecting_byte as u16) << 14;
83 immediate_2 = immediate_2 | ($processor.next() as u16) << 6;
84 immediate_2 = immediate_2 | ($processor.next() as u16) >> 2;
85 $op(immediate_1, immediate_2)
86 }};
87}
88
89macro_rules! with_immediate_and_register {
90 ($processor: ident, $args_head:ident, $op:expr) => {{
91 let mut immediate = ($args_head as u16) << 14;
92 immediate = immediate | ($processor.next() as u16) << 6;
93 let intersecting_byte = $processor.next();
94 immediate = immediate | (intersecting_byte as u16) >> 2;
95 let mut register = (intersecting_byte << 1) & 0b110;
96 register = register | ($processor.next() >> 7) & 0b1;
97 $op(immediate, register)
98 }};
99}
100
101macro_rules! with_reg_and_immediate {
102 ($processor: ident, $args_head:ident, $op:expr) => {{
103 with_registers!(
104 $processor,
105 $args_head,
106 |register_1, register_2, register_3| {
107 let mut immediate = ($processor.next() as u16) << 8;
108 immediate = immediate | ($processor.next() as u16);
109 $op(register_1, register_2, register_3, immediate)
110 }
111 )
112 }};
113}
114
115macro_rules! unary_arithmetic {
116 ($processor:ident, $args_head:ident, $op:expr) => {{
117 with_registers!($processor, $args_head, |register_1, register_2, _| {
118 let Some(value_2) = $processor.get_register_value(register_2) else {
119 return ProcessorContinue::Error;
120 };
121 let result = $op(&mut $processor.registers.fr, value_2);
122 $processor.output_into_register(register_1, result)
123 })
124 }};
125}
126
127macro_rules! arithmetic {
128 ($processor:ident, $args_head:ident, $op:expr) => {{
129 with_registers!(
130 $processor,
131 $args_head,
132 |register_1, register_2, register_3| {
133 let Some(value_2) = $processor.get_register_value(register_2) else {
134 return ProcessorContinue::Error;
135 };
136 let Some(value_3) = $processor.get_register_value(register_3) else {
137 return ProcessorContinue::Error;
138 };
139 let result = $op(&mut $processor.registers.fr, value_2, value_3);
140 $processor.output_into_register(register_1, result)
141 }
142 )
143 }};
144}
145
146implement_flag_register!(RiscProcessorFlagRegister(u8));
147
148pub struct RiscRegisters {
149 pub pc: u16,
150 pub fr: RiscProcessorFlagRegister,
151 pub r: [u16; 4],
152 pub sp: u16,
153}
154
155pub struct RiscProcessor {
156 pub memory: Memory<u8>,
157 pub registers: RiscRegisters,
158}
159
160impl RiscProcessor {
161 pub fn new() -> RiscProcessor {
162 RiscProcessor {
163 memory: Memory::new(0, 65536),
164 registers: RiscRegisters {
165 pc: 0,
166 fr: RiscProcessorFlagRegister::new(),
167 r: [0; 4],
168 sp: 1024,
169 },
170 }
171 }
172
173 two_byte_stack!(memory_stack[sp: u16] -> u8, based on memory, growing downward);
174 two_byte_memory!(two_byte_memory: memory[u16] -> 2 * u8);
175
176 fn get_register_value(&self, register_id: u8) -> Option<u16> {
177 self.registers
178 .r
179 .get(register_id as usize)
180 .copied()
181 .or(match register_id {
182 4 => Some(self.registers.sp),
183 _ => None,
184 })
185 }
186
187 fn set_register_value(&mut self, register_id: u8, value: u16) -> bool {
188 match register_id {
189 0..=3 => {
190 self.registers.r[register_id as usize] = value;
191 true
192 }
193 4 => {
194 self.registers.sp = value;
195 true
196 }
197 _ => false,
198 }
199 }
200
201 fn output_into_register(&mut self, register_id: u8, value: u16) -> ProcessorContinue {
202 if self.set_register_value(register_id, value) {
203 ProcessorContinue::KeepRunning
204 } else {
205 ProcessorContinue::Error
206 }
207 }
208}
209
210impl Processor<u8, u16, u16, u16> for RiscProcessor {
211 fn next(&mut self) -> u8 {
212 let instruction = self.memory[self.registers.pc as usize];
213 self.registers.pc = self.registers.pc.wrapping_add(1);
214 instruction
215 }
216 fn at_pc_plus(&self, offset: u16) -> u8 {
217 self.memory[self.registers.pc.wrapping_add(offset) as usize]
218 }
219 fn pc(&self) -> u16 {
220 self.registers.pc
221 }
222
223 fn peek_stack(&mut self, n: u8) -> u16 {
224 self.memory_stack().peek_down_by(n * 2)
225 }
226
227 fn run_command<T, U>(&mut self, output: T, input: U) -> ProcessorContinue
228 where
229 T: Fn(u16, u16),
230 U: Fn(u16) -> u16,
231 {
232 let next_byte = self.next();
233 let next_instruction = next_byte >> 2;
234 let next_instruction_as_enum = match Opcode::from_u8(next_instruction.into()) {
235 Some(opcode) => opcode,
236 None => {
237 return ProcessorContinue::Error;
238 }
239 };
240
241 let args_head = next_byte & 0b11;
242
243 match next_instruction_as_enum {
244 Opcode::Halt => ProcessorContinue::Halt,
245 Opcode::Load => with_registers!(self, args_head, |register_1, register_2, _| {
246 let Some(address) = self.get_register_value(register_2) else {
247 return ProcessorContinue::Error;
248 };
249 let value = self.two_byte_memory().read(address);
250 self.output_into_register(register_1, value)
251 }),
252 Opcode::Store => with_registers!(self, args_head, |register_1, register_2, _| {
253 let Some(address) = self.get_register_value(register_1) else {
254 return ProcessorContinue::Error;
255 };
256 let Some(value) = self.get_register_value(register_2) else {
257 return ProcessorContinue::Error;
258 };
259 self.two_byte_memory().write(address, value);
260 ProcessorContinue::KeepRunning
261 }),
262 Opcode::MovRegImm => {
263 with_reg_and_immediate!(self, args_head, |register_1, _, _, immediate| {
264 self.output_into_register(register_1, immediate)
265 })
266 }
267 Opcode::MovRegReg => with_registers!(self, args_head, |register_1, register_2, _| {
268 let Some(value) = self.get_register_value(register_2) else {
269 return ProcessorContinue::Error;
270 };
271 self.output_into_register(register_1, value)
272 }),
273 Opcode::Push => with_registers!(self, args_head, |register_1, _, _| {
274 let Some(value) = self.get_register_value(register_1) else {
275 return ProcessorContinue::Error;
276 };
277 self.memory_stack().push(value);
278 ProcessorContinue::KeepRunning
279 }),
280 Opcode::Pop => with_registers!(self, args_head, |register_1, _, _| {
281 let value = self.memory_stack().pop();
282 self.output_into_register(register_1, value)
283 }),
284 Opcode::Add => arithmetic!(self, args_head, arithmetic::add),
285 Opcode::Addc => arithmetic!(self, args_head, arithmetic::addc),
286 Opcode::Sub => arithmetic!(self, args_head, arithmetic::sub),
287 Opcode::Mul => arithmetic!(self, args_head, arithmetic::mul),
288 Opcode::Div => arithmetic!(self, args_head, arithmetic::div),
289 Opcode::And => arithmetic!(self, args_head, arithmetic::and),
290 Opcode::Or => arithmetic!(self, args_head, arithmetic::or),
291 Opcode::Xor => arithmetic!(self, args_head, arithmetic::xor),
292 Opcode::Not => unary_arithmetic!(self, args_head, arithmetic::not),
293 Opcode::Lsh => arithmetic!(self, args_head, arithmetic::shl),
294 Opcode::Rsh => arithmetic!(self, args_head, arithmetic::shr),
295 Opcode::CallAddr => with_immediate!(self, args_head, |immediate| {
296 let return_address = self.registers.pc;
297 self.memory_stack().push(return_address);
298 self.registers.pc = immediate;
299 ProcessorContinue::KeepRunning
300 }),
301 Opcode::CallRegAddr => with_registers!(self, args_head, |register_1, _, _| {
302 let Some(address) = self.get_register_value(register_1) else {
303 return ProcessorContinue::Error;
304 };
305 let return_address = self.registers.pc;
306 self.memory_stack().push(return_address);
307 self.registers.pc = address;
308 ProcessorContinue::KeepRunning
309 }),
310 Opcode::Ret => {
311 let return_address = self.memory_stack().pop();
312 self.registers.pc = return_address;
313 ProcessorContinue::KeepRunning
314 }
315 Opcode::CmpRegReg => with_registers!(self, args_head, |register_1, register_2, _| {
316 let Some(value_1) = self.get_register_value(register_1) else {
317 return ProcessorContinue::Error;
318 };
319 let Some(value_2) = self.get_register_value(register_2) else {
320 return ProcessorContinue::Error;
321 };
322 arithmetic::cmp(&mut self.registers.fr, value_1, value_2);
323 ProcessorContinue::KeepRunning
324 }),
325 Opcode::CmpRegImm => {
326 with_reg_and_immediate!(self, args_head, |register_1, _, _, immediate| {
327 let Some(value) = self.get_register_value(register_1) else {
328 return ProcessorContinue::Error;
329 };
330 arithmetic::cmp(&mut self.registers.fr, value, immediate);
331 ProcessorContinue::KeepRunning
332 })
333 }
334 Opcode::TestRegReg => with_registers!(self, args_head, |register_1, register_2, _| {
335 let Some(value_1) = self.get_register_value(register_1) else {
336 return ProcessorContinue::Error;
337 };
338 let Some(value_2) = self.get_register_value(register_2) else {
339 return ProcessorContinue::Error;
340 };
341 arithmetic::test(&mut self.registers.fr, value_1, value_2);
342 ProcessorContinue::KeepRunning
343 }),
344 Opcode::TestRegImm => {
345 with_reg_and_immediate!(self, args_head, |register_1, _, _, immediate| {
346 let Some(value) = self.get_register_value(register_1) else {
347 return ProcessorContinue::Error;
348 };
349 arithmetic::test(&mut self.registers.fr, value, immediate);
350 ProcessorContinue::KeepRunning
351 })
352 }
353 Opcode::JmpAddr => with_immediate!(self, args_head, |immediate| {
354 self.registers.pc = immediate;
355 ProcessorContinue::KeepRunning
356 }),
357 Opcode::JmpReg => with_registers!(self, args_head, |register_1, _, _| {
358 let Some(address) = self.get_register_value(register_1) else {
359 return ProcessorContinue::Error;
360 };
361 self.registers.pc = address;
362 ProcessorContinue::KeepRunning
363 }),
364 Opcode::Je => with_immediate!(self, args_head, |immediate| {
365 if self.registers.fr.get(ProcessorFlags::ZF) {
366 self.registers.pc = immediate;
367 }
368 ProcessorContinue::KeepRunning
369 }),
370 Opcode::Jne => with_immediate!(self, args_head, |immediate| {
371 if !self.registers.fr.get(ProcessorFlags::ZF) {
372 self.registers.pc = immediate;
373 }
374 ProcessorContinue::KeepRunning
375 }),
376 Opcode::Jg => with_immediate!(self, args_head, |address| {
377 if !self.registers.fr.get(ProcessorFlags::ZF)
378 && (self.registers.fr.get(ProcessorFlags::SF)
379 == self.registers.fr.get(ProcessorFlags::OF))
380 {
381 self.registers.pc = address;
382 }
383 ProcessorContinue::KeepRunning
384 }),
385 Opcode::Jge => with_immediate!(self, args_head, |address| {
386 if !self.registers.fr.get(ProcessorFlags::CF) {
387 self.registers.pc = address;
388 }
389 ProcessorContinue::KeepRunning
390 }),
391 Opcode::Jl => with_immediate!(self, args_head, |address| {
392 if self.registers.fr.get(ProcessorFlags::SF)
393 != self.registers.fr.get(ProcessorFlags::OF)
394 {
395 self.registers.pc = address;
396 }
397 ProcessorContinue::KeepRunning
398 }),
399 Opcode::Jle => with_immediate!(self, args_head, |address| {
400 if self.registers.fr.get(ProcessorFlags::ZF)
401 || self.registers.fr.get(ProcessorFlags::CF)
402 {
403 self.registers.pc = address;
404 }
405 ProcessorContinue::KeepRunning
406 }),
407 Opcode::In => {
408 with_reg_and_immediate!(self, args_head, |register_1, _, _, immediate| self
409 .output_into_register(register_1, input(immediate)))
410 }
411 Opcode::OutImmImm => with_two_immediates!(self, args_head, |port, data| {
412 output(port, data);
413 ProcessorContinue::KeepRunning
414 }),
415 Opcode::OutImmReg => with_immediate_and_register!(self, args_head, |port, register| {
416 let Some(data) = self.get_register_value(register) else {
417 return ProcessorContinue::Error;
418 };
419 output(port, data);
420 ProcessorContinue::KeepRunning
421 }),
422 Opcode::Nop => ProcessorContinue::KeepRunning,
423 }
424 }
425
426 fn load_executable(&mut self, executable: &Executable) -> Result<(), String> {
427 if !matches!(executable.architecture(), Architecture::Risc) {
428 return Err("Executable is not risc architecture".to_string());
429 }
430 for segment in executable.segments() {
431 let array = tightly_packed_array::TightlyPackedArray::new(segment.data.clone(), 8);
432 for i in 0..segment.address_space_size {
433 self.memory[(segment.address_space_start + i) as usize] = array.at(i as usize);
434 }
435 }
436 self.registers.pc = executable.entry_point() as u16;
437 Ok(())
438 }
439}