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 = 0b000000,
18 Load = 0b000001,
19 LoadImm = 0b10010000,
20 Loadf = 0b000010,
21 LoadIR1 = 0b1000001,
22 LoadIR2 = 0b1000010,
23 MovAccIR1 = 0b011111,
24 MovAccIR2 = 0b100000,
25 StoreIR1 = 0b000011,
26 StoreIR1Imm = 0b10010001,
27 StoreIR2 = 0b100011,
28 StoreIR2Imm = 0b11110010,
29 Storef = 0b000100,
30 MovIR1Acc = 0b100001,
31 MovIR2Acc = 0b100010,
32 MovIR2IR1 = 0b111111,
33 MovIR1IR2 = 0b1000000,
34 MovImm = 0b10000000,
35 Push = 0b000101,
36 Pop = 0b000111,
37 Pushf = 0b000110,
38 Popf = 0b001000,
39 PushIR1 = 0b111101,
40 PopIR1 = 0b001001,
41 PushIR2 = 0b100100,
42 PopIR2 = 0b100101,
43 AddAddr = 0b001010,
44 AddIR1 = 0b100110,
45 AddIR2 = 0b100111,
46 SubAddr = 0b001011,
47 SubIR1 = 0b101000,
48 SubIR2 = 0b101001,
49 MulAddr = 0b001110,
50 MulIR1 = 0b101010,
51 MulIR2 = 0b101011,
52 DivAddr = 0b001111,
53 DivIR1 = 0b101100,
54 DivIR2 = 0b101101,
55 Inc = 0b001100,
56 IncIR1 = 0b101110,
57 IncIR2 = 0b101111,
58 Dec = 0b001101,
59 DecIR1 = 0b110000,
60 DecIR2 = 0b110001,
61 AndAddr = 0b010000,
62 AndIR1 = 0b110010,
63 AndIR2 = 0b110011,
64 OrAddr = 0b010001,
65 OrIR1 = 0b110100,
66 OrIR2 = 0b110101,
67 XorAddr = 0b010010,
68 XorIR1 = 0b110110,
69 XorIR2 = 0b110111,
70 NotAddr = 0b010011,
71 NotIR1 = 0b111000,
72 NotIR2 = 0b111110,
73 Lsh = 0b10000001,
74 Rsh = 0b10000010,
75 CallAddr = 0b10000100,
76 Call = 0b010100,
77 Ret = 0b010101,
78 CmpAddr = 0b010110,
79 CmpImm = 0b10000101,
80 CmpIR1 = 0b111001,
81 CmpIR2 = 0b111010,
82 TestImm = 0b10000110,
83 TestAddr = 0b10001111,
84 TestIR1 = 0b111011,
85 TestIR2 = 0b111100,
86 JmpAddr = 0b10000111,
87 Jmp = 0b010111,
88 JeAddr = 0b10001000,
89 Je = 0b011000,
90 JneAddr = 0b10001001,
91 Jne = 0b011001,
92 JgAddr = 0b10001010,
93 Jg = 0b011010,
94 JgeAddr = 0b10001011,
95 Jge = 0b011011,
96 JlAddr = 0b10001100,
97 Jl = 0b011100,
98 JleAddr = 0b10001101,
99 Jle = 0b011101,
100 In = 0b10001110,
101 Out = 0b10011000,
102}
103
104macro_rules! with_immediate {
105 ($processor:ident, $op:expr) => {{
106 let immediate = $processor.load_immediate();
107 $op(immediate);
108 ProcessorContinue::KeepRunning
109 }};
110}
111
112macro_rules! arithmetic_imm {
113 ($processor:ident, $op:expr) => {{
114 let immediate = $processor.load_immediate();
115 let acc = $processor.registers.acc;
116 let result = $op(&mut $processor.registers.fr, acc, immediate);
117 $processor.registers.acc = result;
118 ProcessorContinue::KeepRunning
119 }};
120}
121
122macro_rules! arithmetic_addr {
123 ($processor:ident, $op:expr) => {{
124 let address = $processor.load_immediate();
125 let value = $processor.two_byte_memory().read(address);
126 let acc = $processor.registers.acc;
127 let result = $op(&mut $processor.registers.fr, acc, value);
128 $processor.registers.acc = result;
129 ProcessorContinue::KeepRunning
130 }};
131}
132
133macro_rules! arithmetic_ir1 {
134 ($processor:ident, $op:expr) => {{
135 let address = $processor.registers.ir1;
136 let value = $processor.two_byte_memory().read(address);
137 let acc = $processor.registers.acc;
138 let result = $op(&mut $processor.registers.fr, acc, value);
139 $processor.registers.acc = result;
140 ProcessorContinue::KeepRunning
141 }};
142}
143
144macro_rules! arithmetic_ir2 {
145 ($processor:ident, $op:expr) => {{
146 let address = $processor.registers.ir2;
147 let value = $processor.two_byte_memory().read(address);
148 let acc = $processor.registers.acc;
149 let result = $op(&mut $processor.registers.fr, acc, value);
150 $processor.registers.acc = result;
151 ProcessorContinue::KeepRunning
152 }};
153}
154
155macro_rules! arithmetic_acc {
156 ($processor:ident, $op:expr) => {{
157 let acc = $processor.registers.acc;
158 let result = $op(&mut $processor.registers.fr, acc);
159 $processor.registers.acc = result;
160 ProcessorContinue::KeepRunning
161 }};
162}
163
164macro_rules! arithmetic_ir1_single_operand {
165 ($processor:ident, $op:expr) => {{
166 let previous = $processor.registers.ir1;
167 let result = $op(&mut $processor.registers.fr, previous);
168 $processor.registers.ir1 = result;
169 ProcessorContinue::KeepRunning
170 }};
171}
172
173macro_rules! arithmetic_ir2_single_operand {
174 ($processor:ident, $op:expr) => {{
175 let previous = $processor.registers.ir2;
176 let result = $op(&mut $processor.registers.fr, previous);
177 $processor.registers.ir2 = result;
178 ProcessorContinue::KeepRunning
179 }};
180}
181
182macro_rules! arithmetic_acc_addr_into_acc {
183 ($processor:ident, $op:expr) => {{
184 let address = $processor.registers.acc;
185 let value = $processor.two_byte_memory().read(address);
186 let result = $op(&mut $processor.registers.fr, value);
187 $processor.registers.acc = result;
188 ProcessorContinue::KeepRunning
189 }};
190}
191
192macro_rules! arithmetic_ir1_into_acc {
193 ($processor:ident, $op:expr) => {{
194 let address = $processor.registers.ir1;
195 let value = $processor.two_byte_memory().read(address);
196 let result = $op(&mut $processor.registers.fr, value);
197 $processor.registers.acc = result;
198 ProcessorContinue::KeepRunning
199 }};
200}
201
202macro_rules! arithmetic_ir2_into_acc {
203 ($processor:ident, $op:expr) => {{
204 let address = $processor.registers.ir2;
205 let value = $processor.two_byte_memory().read(address);
206 let result = $op(&mut $processor.registers.fr, value);
207 $processor.registers.acc = result;
208 ProcessorContinue::KeepRunning
209 }};
210}
211
212implement_flag_register!(AccProcessorFlagRegister(u8));
213
214pub struct AccRegisters {
215 pub pc: u16,
216 pub fr: AccProcessorFlagRegister,
217 pub sp: u16,
218 pub ir1: u16,
219 pub ir2: u16,
220 pub acc: u16,
221}
222
223pub struct AccProcessor {
224 pub memory: Memory<u8>,
225 pub registers: AccRegisters,
226}
227
228impl AccProcessor {
229 pub fn new() -> AccProcessor {
230 AccProcessor {
231 memory: Memory::new(0, 65536),
232 registers: AccRegisters {
233 pc: 0,
234 fr: AccProcessorFlagRegister::new(),
235 sp: 1024,
236 ir1: 0,
237 ir2: 0,
238 acc: 0,
239 },
240 }
241 }
242
243 two_byte_stack!(memory_stack[sp: u16] -> u8, based on memory, growing downward);
244 two_byte_memory!(two_byte_memory: memory[u16] -> 2 * u8);
245
246 fn load_immediate(&mut self) -> u16 {
247 let immediate = self.next() as u16;
248 immediate << 8 | self.next() as u16
249 }
250}
251
252impl Processor<u8, u16, u16, u16> for AccProcessor {
253 fn next(&mut self) -> u8 {
254 let instruction = self.memory[self.registers.pc as usize];
255 self.registers.pc = self.registers.pc.wrapping_add(1);
256 instruction
257 }
258
259 fn at_pc_plus(&self, offset: u16) -> u8 {
260 self.memory[self.registers.pc.wrapping_add(offset) as usize]
261 }
262
263 fn pc(&self) -> u16 {
264 self.registers.pc
265 }
266
267 fn peek_stack(&mut self, n: u8) -> u16 {
268 self.memory_stack().peek_down_by(n * 2)
269 }
270
271 fn run_command<T, U>(&mut self, output: T, input: U) -> ProcessorContinue
272 where
273 T: Fn(u16, u16),
274 U: Fn(u16) -> u16,
275 {
276 let next_instruction = self.next();
277 let next_instruction_as_enum = match Opcode::from_u8(next_instruction.into()) {
278 Some(opcode) => opcode,
279 None => {
280 return ProcessorContinue::Error;
281 }
282 };
283 match next_instruction_as_enum {
284 Opcode::Halt => ProcessorContinue::Halt,
285 Opcode::Load => {
286 let address = self.registers.acc;
287 self.registers.acc = self.two_byte_memory().read(address);
288 ProcessorContinue::KeepRunning
289 }
290 Opcode::LoadImm => with_immediate!(self, |immediate| {
291 self.registers.acc = immediate;
292 }),
293 Opcode::Loadf => {
294 let value: u8 = self.registers.fr.into();
295 self.registers.acc = value as u16;
296 ProcessorContinue::KeepRunning
297 }
298 Opcode::LoadIR1 => {
299 let address = self.registers.ir1;
300 self.registers.acc = self.two_byte_memory().read(address);
301 ProcessorContinue::KeepRunning
302 }
303 Opcode::LoadIR2 => {
304 let address = self.registers.ir2;
305 self.registers.acc = self.two_byte_memory().read(address);
306 ProcessorContinue::KeepRunning
307 }
308 Opcode::MovAccIR1 => {
309 self.registers.acc = self.registers.ir1;
310 ProcessorContinue::KeepRunning
311 }
312 Opcode::MovAccIR2 => {
313 self.registers.acc = self.registers.ir2;
314 ProcessorContinue::KeepRunning
315 }
316 Opcode::StoreIR1 => {
317 let address = self.registers.ir1;
318 let value = self.registers.acc;
319 self.two_byte_memory().write(address, value);
320 ProcessorContinue::KeepRunning
321 }
322 Opcode::StoreIR1Imm => with_immediate!(self, |immediate| {
323 let address = self.registers.ir1;
324 self.two_byte_memory().write(address, immediate);
325 }),
326 Opcode::StoreIR2 => {
327 let address = self.registers.ir2;
328 let value = self.registers.acc;
329 self.two_byte_memory().write(address, value);
330 ProcessorContinue::KeepRunning
331 }
332 Opcode::StoreIR2Imm => with_immediate!(self, |immediate| {
333 let address = self.registers.ir2;
334 self.two_byte_memory().write(address, immediate);
335 }),
336 Opcode::Storef => {
337 let value = (self.registers.acc & 0xFF) as u8;
338 self.registers.fr.0 = value;
339 ProcessorContinue::KeepRunning
340 }
341 Opcode::MovIR1Acc => {
342 self.registers.ir1 = self.registers.acc;
343 ProcessorContinue::KeepRunning
344 }
345 Opcode::MovIR2Acc => {
346 self.registers.ir2 = self.registers.acc;
347 ProcessorContinue::KeepRunning
348 }
349 Opcode::MovIR2IR1 => {
350 self.registers.ir2 = self.registers.ir1;
351 ProcessorContinue::KeepRunning
352 }
353 Opcode::MovIR1IR2 => {
354 self.registers.ir1 = self.registers.ir2;
355 ProcessorContinue::KeepRunning
356 }
357 Opcode::MovImm => with_immediate!(self, |immediate| {
358 self.registers.acc = immediate;
359 }),
360 Opcode::Push => {
361 let value = self.registers.acc;
362 self.memory_stack().push(value);
363 ProcessorContinue::KeepRunning
364 }
365 Opcode::Pop => {
366 let value = self.memory_stack().pop();
367 self.registers.acc = value;
368 ProcessorContinue::KeepRunning
369 }
370 Opcode::Pushf => {
371 let value = self.registers.fr.0 as u16;
372 self.memory_stack().push(value);
373 ProcessorContinue::KeepRunning
374 }
375 Opcode::Popf => {
376 let value = self.memory_stack().pop();
377 self.registers.fr.0 = value as u8;
378 ProcessorContinue::KeepRunning
379 }
380 Opcode::PushIR1 => {
381 let value = self.registers.ir1;
382 self.memory_stack().push(value);
383 ProcessorContinue::KeepRunning
384 }
385 Opcode::PopIR1 => {
386 let value = self.memory_stack().pop();
387 self.registers.ir1 = value;
388 ProcessorContinue::KeepRunning
389 }
390 Opcode::PushIR2 => {
391 let value = self.registers.ir2;
392 self.memory_stack().push(value);
393 ProcessorContinue::KeepRunning
394 }
395 Opcode::PopIR2 => {
396 let value = self.memory_stack().pop();
397 self.registers.ir2 = value;
398 ProcessorContinue::KeepRunning
399 }
400 Opcode::AddAddr => arithmetic_addr!(self, arithmetic::add),
401 Opcode::AddIR1 => arithmetic_ir1!(self, arithmetic::add),
402 Opcode::AddIR2 => arithmetic_ir2!(self, arithmetic::add),
403 Opcode::SubAddr => arithmetic_addr!(self, arithmetic::sub),
404 Opcode::SubIR1 => arithmetic_ir1!(self, arithmetic::sub),
405 Opcode::SubIR2 => arithmetic_ir2!(self, arithmetic::sub),
406 Opcode::MulAddr => arithmetic_addr!(self, arithmetic::mul),
407 Opcode::MulIR1 => arithmetic_ir1!(self, arithmetic::mul),
408 Opcode::MulIR2 => arithmetic_ir2!(self, arithmetic::mul),
409 Opcode::DivAddr => arithmetic_addr!(self, arithmetic::div),
410 Opcode::DivIR1 => arithmetic_ir1!(self, arithmetic::div),
411 Opcode::DivIR2 => arithmetic_ir2!(self, arithmetic::div),
412 Opcode::Inc => arithmetic_acc!(self, arithmetic::inc),
413 Opcode::IncIR1 => arithmetic_ir1_single_operand!(self, arithmetic::inc),
414 Opcode::IncIR2 => arithmetic_ir2_single_operand!(self, arithmetic::inc),
415 Opcode::Dec => arithmetic_acc!(self, arithmetic::dec),
416 Opcode::DecIR1 => arithmetic_ir1_single_operand!(self, arithmetic::dec),
417 Opcode::DecIR2 => arithmetic_ir2_single_operand!(self, arithmetic::dec),
418 Opcode::AndAddr => arithmetic_addr!(self, arithmetic::and),
419 Opcode::AndIR1 => arithmetic_ir1!(self, arithmetic::and),
420 Opcode::AndIR2 => arithmetic_ir2!(self, arithmetic::and),
421 Opcode::OrAddr => arithmetic_addr!(self, arithmetic::or),
422 Opcode::OrIR1 => arithmetic_ir1!(self, arithmetic::or),
423 Opcode::OrIR2 => arithmetic_ir2!(self, arithmetic::or),
424 Opcode::XorAddr => arithmetic_addr!(self, arithmetic::xor),
425 Opcode::XorIR1 => arithmetic_ir1!(self, arithmetic::xor),
426 Opcode::XorIR2 => arithmetic_ir2!(self, arithmetic::xor),
427 Opcode::NotAddr => arithmetic_acc_addr_into_acc!(self, arithmetic::not),
428 Opcode::NotIR1 => arithmetic_ir1_into_acc!(self, arithmetic::not),
429 Opcode::NotIR2 => arithmetic_ir2_into_acc!(self, arithmetic::not),
430 Opcode::Lsh => arithmetic_imm!(self, arithmetic::shl),
431 Opcode::Rsh => arithmetic_imm!(self, arithmetic::shr),
432 Opcode::CallAddr => with_immediate!(self, |address| {
433 let return_address = self.registers.pc;
434 self.memory_stack().push(return_address);
435 self.registers.pc = address;
436 ProcessorContinue::KeepRunning
437 }),
438 Opcode::Call => {
439 let return_address = self.registers.pc;
440 self.memory_stack().push(return_address);
441 self.registers.pc = self.registers.acc;
442 ProcessorContinue::KeepRunning
443 }
444 Opcode::Ret => {
445 let return_address = self.memory_stack().pop();
446 self.registers.pc = return_address;
447 ProcessorContinue::KeepRunning
448 }
449 Opcode::CmpAddr => arithmetic_addr!(self, arithmetic::cmp),
450 Opcode::CmpImm => arithmetic_imm!(self, arithmetic::cmp),
451 Opcode::CmpIR1 => arithmetic_ir1!(self, arithmetic::cmp),
452 Opcode::CmpIR2 => arithmetic_ir2!(self, arithmetic::cmp),
453 Opcode::TestImm => arithmetic_imm!(self, arithmetic::test),
454 Opcode::TestAddr => arithmetic_addr!(self, arithmetic::test),
455 Opcode::TestIR1 => arithmetic_ir1!(self, arithmetic::test),
456 Opcode::TestIR2 => arithmetic_ir2!(self, arithmetic::test),
457 Opcode::JmpAddr => with_immediate!(self, |address| {
458 self.registers.pc = address;
459 }),
460 Opcode::Jmp => {
461 self.registers.pc = self.registers.acc;
462 ProcessorContinue::KeepRunning
463 }
464 Opcode::JeAddr => with_immediate!(self, |address| {
465 if self.registers.fr.get(ProcessorFlags::ZF) {
466 self.registers.pc = address;
467 }
468 }),
469 Opcode::Je => {
470 if self.registers.fr.get(ProcessorFlags::ZF) {
471 self.registers.pc = self.registers.acc;
472 }
473 ProcessorContinue::KeepRunning
474 }
475 Opcode::JneAddr => with_immediate!(self, |address| {
476 if !self.registers.fr.get(ProcessorFlags::ZF) {
477 self.registers.pc = address;
478 }
479 }),
480 Opcode::Jne => {
481 if !self.registers.fr.get(ProcessorFlags::ZF) {
482 self.registers.pc = self.registers.acc;
483 }
484 ProcessorContinue::KeepRunning
485 }
486 Opcode::JgAddr => with_immediate!(self, |address| {
487 if !self.registers.fr.get(ProcessorFlags::ZF)
488 && (self.registers.fr.get(ProcessorFlags::SF)
489 == self.registers.fr.get(ProcessorFlags::OF))
490 {
491 self.registers.pc = address;
492 }
493 }),
494 Opcode::Jg => {
495 if !self.registers.fr.get(ProcessorFlags::ZF)
496 && (self.registers.fr.get(ProcessorFlags::SF)
497 == self.registers.fr.get(ProcessorFlags::OF))
498 {
499 self.registers.pc = self.registers.acc;
500 }
501 ProcessorContinue::KeepRunning
502 }
503 Opcode::JgeAddr => with_immediate!(self, |address| {
504 if !self.registers.fr.get(ProcessorFlags::CF) {
505 self.registers.pc = address;
506 }
507 }),
508 Opcode::Jge => {
509 if !self.registers.fr.get(ProcessorFlags::CF) {
510 self.registers.pc = self.registers.acc;
511 }
512 ProcessorContinue::KeepRunning
513 }
514 Opcode::JlAddr => with_immediate!(self, |address| {
515 if self.registers.fr.get(ProcessorFlags::SF)
516 != self.registers.fr.get(ProcessorFlags::OF)
517 {
518 self.registers.pc = address;
519 }
520 }),
521 Opcode::Jl => {
522 if self.registers.fr.get(ProcessorFlags::SF)
523 != self.registers.fr.get(ProcessorFlags::OF)
524 {
525 self.registers.pc = self.registers.acc;
526 }
527 ProcessorContinue::KeepRunning
528 }
529 Opcode::JleAddr => with_immediate!(self, |address| {
530 if self.registers.fr.get(ProcessorFlags::ZF)
531 || self.registers.fr.get(ProcessorFlags::CF)
532 {
533 self.registers.pc = address;
534 }
535 }),
536 Opcode::Jle => {
537 if self.registers.fr.get(ProcessorFlags::ZF)
538 || self.registers.fr.get(ProcessorFlags::CF)
539 {
540 self.registers.pc = self.registers.acc;
541 }
542 ProcessorContinue::KeepRunning
543 }
544 Opcode::In => with_immediate!(self, |port| {
545 self.registers.acc = input(port);
546 }),
547 Opcode::Out => with_immediate!(self, |port| {
548 output(port, self.registers.acc);
549 }),
550 }
551 }
552
553 fn load_executable(&mut self, executable: &Executable) -> Result<(), String> {
554 if !matches!(executable.architecture(), Architecture::Accumulator) {
555 return Err("Executable is not accumulator architecture".to_string());
556 }
557 for segment in executable.segments() {
558 let array = tightly_packed_array::TightlyPackedArray::new(segment.data.clone(), 8);
559 for i in 0..segment.address_space_size {
560 self.memory[(segment.address_space_start + i) as usize] = array.at(i as usize);
561 }
562 }
563 self.registers.pc = executable.entry_point() as u16;
564 Ok(())
565 }
566}