1use monistode_binutils::Executable;
2
3use super::{
4 arithmetic,
5 common::{Processor, ProcessorContinue},
6 flag_register::{implement_flag_register, FlagRegister, ProcessorFlags},
7 memory::{two_byte_memory, Memory, TwoByteMemory},
8 stack::{two_byte_stack, Stack, TwoByteStack},
9};
10use num_derive::FromPrimitive;
11use num_traits::FromPrimitive;
12
13#[derive(Debug, FromPrimitive)]
14enum Opcode {
15 Halt = 0b00000000,
16 MovRegImm = 0b10000000,
17 MovRegReg = 0b01100000,
18 MovRegRegAdr = 0b01100001,
19 MovRegRegAdrOff = 0b10100000,
20 MovRegAdrReg = 0b01100010,
21 MovRegAdrImm = 0b10000001,
22 MovRegAdrOffReg = 0b10100001,
23 MovRegAdrOffImm = 0b11000000,
24 PushReg = 0b00000001,
25 PushImm = 0b01000000,
26 PopReg = 0b00000010,
27 EnterImm = 0b01000001,
28 Leave = 00100000,
29 AddRegRegAdr = 0b01100011,
30 AddRegReg = 0b01100100,
31 AddRegRegAdrOff = 0b10100010,
32 AddRegAdrReg = 0b01100101,
33 SubRegRegAdr = 0b01100110,
34 SubRegReg = 0b01100111,
35 SubRegRegAdrOff = 0b10100011,
36 SubRegAdrReg = 0b01101000,
37 IncReg = 0b00011111,
38 IncRegAdr = 0b00000100,
39 IncRegAdrOff = 0b100000010,
40 DecReg = 0b00000101,
41 DecRegAdr = 0b00000110,
42 DecRegAdrOff = 0b10000011,
43 MulRegReg = 0b01101001,
44 MulRegRegAdr = 0b01101010,
45 MulRegAdrReg = 0b01101011,
46 MulRegImm = 0b10000100,
47 MulRegRegAdrOff = 0b10100100,
48 DivRegReg = 0b01101100,
49 DivRegRegAdr = 0b01101101,
50 DivRegAdrReg = 0b01101110,
51 DivRegImm = 0b10000101,
52 DivRegRegAdrOff = 0b10100101,
53 AndRegReg = 0b01101111,
54 AndRegRegAdr = 0b01110000,
55 OrRegReg = 0b01110001,
56 OrRegRegAdr = 0b01110010,
57 XorRegReg = 0b01110011,
58 XorRegRegAdr = 0b01110100,
59 NotReg = 0b00000111,
60 NotRegAdr = 0b00001000,
61 LshRegImm = 0b10000110,
62 LshRegAdrImm = 0b10000111,
63 LshRegAdrOffImm = 0b11000001,
64 RshRegImm = 0b10001000,
65 RshRegAdrImm = 0b10001001,
66 RshRegAdrOffImm = 0b11000010,
67 CallImm = 0b01000010,
68 CallReg = 0b00001001,
69 CallRegOff = 145,
70 Ret = 0b00100001,
71 CmpRegReg = 0b01110101,
72 CmpRegImm = 0b10001011,
73 CmpRegRegAdr = 146,
74 CmpRegRegAdrOff = 0b10100110,
75 TestRegReg = 0b01110111,
76 TestRegRegAdr = 0b01111000,
77 TestRegRegAdrOff = 0b10100111,
78 JmpImm = 0b01000011,
79 JmpReg = 0b00001010,
80 JmpRegOff = 0b10001100,
81 JeImm = 0b01000100,
82 JneImm = 0b01000101,
83 JgImm = 0b01000110,
84 JgeImm = 0b01000111,
85 JlImm = 0b01001000,
86 JleImm = 0b01001001,
87 InRegPort = 0b10001101,
88 InRegAdrPort = 0b10001110,
89 InRegAdrOffPort = 0b11000011,
90 OutPortImm = 0b11001111,
91 OutPortReg = 0b10001111,
92 OutPortRegAdr = 0b10010000,
93 OutPortRegAdrOff = 0b11000100,
94 Nop = 0b00100010,
101}
102
103macro_rules! with_register_value {
104 ($processor:ident, $op:expr) => {{
105 let register_value = match $processor.load_register() {
106 Some(value) => value,
107 None => return ProcessorContinue::Error,
108 };
109 $op(register_value);
110 ProcessorContinue::KeepRunning
111 }};
112}
113
114macro_rules! with_register_id_and_register_value {
115 ($processor:ident, $op:expr) => {{
116 let (register_id, address_register_id) = $processor.load_two_register_ids();
117 let value = match $processor.get_register_value(address_register_id) {
118 Some(value) => value,
119 None => return ProcessorContinue::Error,
120 };
121 $op(register_id, value)
122 }};
123}
124
125macro_rules! with_two_register_values {
126 ($processor:ident, $op:expr) => {{
127 let (register_id1, register_id2) = $processor.load_two_register_ids();
128 let value1 = match $processor.get_register_value(register_id1) {
129 Some(value) => value,
130 None => return ProcessorContinue::Error,
131 };
132 let value2 = match $processor.get_register_value(register_id2) {
133 Some(value) => value,
134 None => return ProcessorContinue::Error,
135 };
136 $op(value1, value2)
137 }};
138}
139
140macro_rules! with_register_id_and_register_address {
141 ($processor:ident, $op:expr) => {{
142 let (register_id, address_register_id) = $processor.load_two_register_ids();
143 let value = match $processor.get_register_value(address_register_id) {
144 Some(value) => $processor.two_byte_memory().read(value),
145 None => return ProcessorContinue::Error,
146 };
147 $op(register_id, value)
148 }};
149}
150
151macro_rules! with_register_address {
152 ($processor:ident, $op:expr) => {{
153 let value = $processor.load_register_address();
154 match value {
155 Some(value) => {
156 $op(value);
157 ProcessorContinue::KeepRunning
158 }
159 None => ProcessorContinue::Error,
160 }
161 }};
162}
163
164macro_rules! with_register_id_and_register_address_offset {
165 ($processor:ident, $op:expr) => {{
166 let (register_id, address_register_id) = $processor.load_two_register_ids();
167 let address_register_value = match $processor.get_register_value(address_register_id) {
168 Some(value) => value,
169 None => return ProcessorContinue::Error,
170 };
171 with_immediate_raw!($processor, |immediate| {
172 let value = $processor
173 .two_byte_memory()
174 .read(address_register_value.wrapping_add(immediate));
175 $op(register_id, value)
176 })
177 }};
178}
179
180macro_rules! with_register_address_offset {
181 ($processor:ident, $op:expr) => {{
182 let value = $processor.load_register_address_offset();
183 $op(value);
184 ProcessorContinue::KeepRunning
185 }};
186}
187
188macro_rules! with_register_address_offset_as_address {
189 ($processor:ident, $op:expr) => {{
190 let register_value = match $processor.load_register() {
191 Some(value) => value,
192 None => return ProcessorContinue::Error,
193 };
194 with_immediate!($processor, |immediate| {
195 $op(register_value.wrapping_add(immediate));
196 })
197 }};
198}
199
200macro_rules! with_register_id {
201 ($processor:ident, $op:expr) => {{
202 let register_id = $processor.next();
203 $op(register_id);
204 ProcessorContinue::KeepRunning
205 }};
206}
207
208macro_rules! with_immediate_raw {
209 ($processor:ident, $op:expr) => {{
210 let immediate = $processor.load_immediate();
211 $op(immediate)
212 }};
213}
214
215macro_rules! with_immediate {
216 ($processor:ident, $op:expr) => {{
217 let immediate = $processor.load_immediate();
218 $op(immediate);
219 ProcessorContinue::KeepRunning
220 }};
221}
222
223macro_rules! save_to_register {
224 ($processor:ident, $op:expr) => {{
225 let register_id = $processor.next();
226 let value = $op();
227 match $processor.save_register(register_id, value) {
228 Ok(_) => ProcessorContinue::KeepRunning,
229 Err(_) => ProcessorContinue::Error,
230 }
231 }};
232}
233
234macro_rules! save_to_register_address {
235 ($processor:ident, $op:expr) => {{
236 let address = match $processor.load_register() {
237 Some(value) => value,
238 None => return ProcessorContinue::Error,
239 };
240 let value = $op();
241 $processor.two_byte_memory().write(address, value);
242 ProcessorContinue::KeepRunning
243 }};
244}
245
246macro_rules! save_to_register_address_offset {
247 ($processor:ident, $op:expr) => {{
248 let address = match $processor.load_register() {
249 Some(value) => value,
250 None => return ProcessorContinue::Error,
251 };
252 let offset = $processor.load_immediate();
253 let value = $op();
254 $processor
255 .two_byte_memory()
256 .write(address.wrapping_add(offset), value);
257 ProcessorContinue::KeepRunning
258 }};
259}
260
261macro_rules! save_optional_to_register_address_offset {
262 ($processor:ident, $op:expr) => {{
263 let address = match $processor.load_register() {
264 Some(value) => value,
265 None => return ProcessorContinue::Error,
266 };
267 let offset = $processor.load_immediate();
268 let value = match $op() {
269 Some(value) => value,
270 None => return ProcessorContinue::Error,
271 };
272 $processor
273 .two_byte_memory()
274 .write(address.wrapping_add(offset), value);
275 ProcessorContinue::KeepRunning
276 }};
277}
278
279macro_rules! push_result {
280 ($processor:ident, $op:expr) => {{
281 let value = $op();
282 $processor.memory_stack().push(value);
283 ProcessorContinue::KeepRunning
284 }};
285}
286
287macro_rules! push_optional_result {
288 ($processor:ident, $op:expr) => {{
289 let value = match $op() {
290 Some(value) => value,
291 None => return ProcessorContinue::Error,
292 };
293 $processor.memory_stack().push(value);
294 ProcessorContinue::KeepRunning
295 }};
296}
297
298implement_flag_register!(CiscProcessorFlagRegister(u8));
299
300macro_rules! arithmetic_reg_reg_addr {
301 ($processor: ident, $op: expr) => {{
302 with_register_id_and_register_address!($processor, |register_id, b| {
303 let a = match $processor.get_register_value(register_id) {
304 Some(value) => value,
305 None => return ProcessorContinue::Error,
306 };
307 let result = $op(&mut $processor.registers.fr, a, b);
308 match $processor.save_register(register_id, result) {
309 Ok(_) => ProcessorContinue::KeepRunning,
310 Err(_) => ProcessorContinue::Error,
311 }
312 })
313 }};
314}
315
316macro_rules! arithmetic_reg_addr_reg {
317 ($processor: ident, $op: expr) => {{
318 with_two_register_values!($processor, |address, b| {
319 let a = $processor.two_byte_memory().read(address);
320 let result = $op(&mut $processor.registers.fr, a, b);
321 $processor.two_byte_memory().write(address, result);
322 ProcessorContinue::KeepRunning
323 })
324 }};
325}
326
327macro_rules! arithmetic_reg_reg {
328 ($processor: ident, $op: expr) => {{
329 with_register_id_and_register_value!($processor, |register_id, b| {
330 let a = match $processor.get_register_value(register_id) {
331 Some(value) => value,
332 None => return ProcessorContinue::Error,
333 };
334 let result = $op(&mut $processor.registers.fr, a, b);
335 match $processor.save_register(register_id, result) {
336 Ok(_) => ProcessorContinue::KeepRunning,
337 Err(_) => ProcessorContinue::Error,
338 }
339 })
340 }};
341}
342
343macro_rules! arithmetic_reg_reg_addr_off {
344 ($processor: ident, $op: expr) => {{
345 with_register_id_and_register_address_offset!($processor, |register_id, b| {
346 let a = match $processor.get_register_value(register_id) {
347 Some(value) => value,
348 None => return ProcessorContinue::Error,
349 };
350 let result = $op(&mut $processor.registers.fr, a, b);
351 match $processor.save_register(register_id, result) {
352 Ok(_) => ProcessorContinue::KeepRunning,
353 Err(_) => ProcessorContinue::Error,
354 }
355 })
356 }};
357}
358
359macro_rules! arithmetic_reg_imm {
360 ($processor: ident, $op: expr) => {{
361 with_register_id!($processor, |register_id| {
362 with_immediate!($processor, |b| {
363 let a = match $processor.get_register_value(register_id) {
364 Some(value) => value,
365 None => return ProcessorContinue::Error,
366 };
367 let result = $op(&mut $processor.registers.fr, a, b);
368 match $processor.save_register(register_id, result) {
369 Ok(_) => ProcessorContinue::KeepRunning,
370 Err(_) => ProcessorContinue::Error,
371 }
372 })
373 })
374 }};
375}
376
377macro_rules! arithmetic_reg_addr_imm {
378 ($processor: ident, $op: expr) => {{
379 with_register_value!($processor, |address| {
380 with_immediate!($processor, |b| {
381 let a = $processor.two_byte_memory().read(address);
382 let result = $op(&mut $processor.registers.fr, a, b);
383 $processor.two_byte_memory().write(address, result);
384 ProcessorContinue::KeepRunning
385 })
386 })
387 }};
388}
389
390macro_rules! arithmetic_reg_addr_offset_imm {
391 ($processor: ident, $op: expr) => {{
392 with_register_address_offset_as_address!($processor, |address| {
393 with_immediate!($processor, |b| {
394 let a = $processor.two_byte_memory().read(address);
395 let result = $op(&mut $processor.registers.fr, a, b);
396 $processor.two_byte_memory().write(address, result);
397 ProcessorContinue::KeepRunning
398 })
399 })
400 }};
401}
402
403macro_rules! arithmetic_reg {
404 ($processor: ident, $op: expr) => {{
405 with_register_id!($processor, |register_id| {
406 let a = match $processor.get_register_value(register_id) {
407 Some(value) => value,
408 None => return ProcessorContinue::Error,
409 };
410 let result = $op(&mut $processor.registers.fr, a);
411 match $processor.save_register(register_id, result) {
412 Ok(_) => ProcessorContinue::KeepRunning,
413 Err(_) => ProcessorContinue::Error,
414 }
415 })
416 }};
417}
418
419macro_rules! arithmetic_reg_addr {
420 ($processor: ident, $op: expr) => {{
421 with_register_value!($processor, |address| {
422 let a = $processor.two_byte_memory().read(address);
423 let result = $op(&mut $processor.registers.fr, a);
424 $processor.two_byte_memory().write(address, result);
425 ProcessorContinue::KeepRunning
426 })
427 }};
428}
429
430macro_rules! arithmetic_reg_addr_offset {
431 ($processor: ident, $op: expr) => {{
432 with_register_address_offset_as_address!($processor, |address| {
433 let a = $processor.two_byte_memory().read(address);
434 let result = $op(&mut $processor.registers.fr, a);
435 $processor.two_byte_memory().write(address, result);
436 ProcessorContinue::KeepRunning
437 })
438 }};
439}
440
441pub struct CiscRegisters {
442 pub pc: u16,
443 pub fr: CiscProcessorFlagRegister,
444 pub r: [u16; 4],
445 pub bp: u16,
446 pub sp: u16,
447}
448
449pub struct CiscProcessor {
450 pub memory: Memory<u8>,
451 pub registers: CiscRegisters,
452}
453
454impl CiscProcessor {
455 pub fn new() -> CiscProcessor {
456 CiscProcessor {
457 memory: Memory::new(0, 65536),
458 registers: CiscRegisters {
459 pc: 0,
460 fr: CiscProcessorFlagRegister::new(),
461 r: [0; 4],
462 bp: 0,
463 sp: 1024,
464 },
465 }
466 }
467
468 two_byte_stack!(memory_stack[sp: u16] -> u8, based on memory, growing downward);
469 two_byte_memory!(two_byte_memory: memory[u16] -> 2 * u8);
470
471 fn load_immediate(&mut self) -> u16 {
472 let immediate = self.next() as u16;
473 immediate << 8 | self.next() as u16
474 }
475
476 fn load_register(&mut self) -> Option<u16> {
477 let register = self.next();
478 self.registers
479 .r
480 .get(register as usize)
481 .copied()
482 .or(match register {
483 4 => Some(self.registers.bp),
484 5 => Some(self.registers.sp),
485 _ => None,
486 })
487 }
488
489 fn load_two_register_ids(&mut self) -> (u8, u8) {
490 let registers = self.next();
491 return (registers >> 4, registers & 0b00001111);
492 }
493
494 fn get_register_value(&self, register_id: u8) -> Option<u16> {
495 self.registers
496 .r
497 .get(register_id as usize)
498 .copied()
499 .or(match register_id {
500 4 => Some(self.registers.bp),
501 5 => Some(self.registers.sp),
502 _ => None,
503 })
504 }
505
506 fn load_register_address(&mut self) -> Option<u16> {
507 let register = self.next();
508 let address = self
509 .registers
510 .r
511 .get(register as usize)
512 .copied()
513 .or(match register {
514 4 => Some(self.registers.bp),
515 5 => Some(self.registers.sp),
516 _ => None,
517 });
518 address.map(|address| self.two_byte_memory().read(address))
519 }
520
521 fn load_register_address_offset(&mut self) -> Option<u16> {
522 let register = self.next();
523 let offset = self.load_immediate();
524 let address = self
525 .registers
526 .r
527 .get(register as usize)
528 .copied()
529 .or(match register {
530 4 => Some(self.registers.bp),
531 5 => Some(self.registers.sp),
532 _ => None,
533 });
534 address.map(|address| self.two_byte_memory().read(address.wrapping_add(offset)))
535 }
536
537 fn save_register(&mut self, register_id: u8, value: u16) -> Result<(), ()> {
538 if register_id > 5 {
539 return Err(());
540 }
541 if register_id == 4 {
542 self.registers.bp = value;
543 return Ok(());
544 }
545 if register_id == 5 {
546 self.registers.sp = value;
547 return Ok(());
548 }
549 self.registers.r[register_id as usize] = value;
550 Ok(())
551 }
552}
553
554impl Processor<u8, u16, u16, u16> for CiscProcessor {
555 fn next(&mut self) -> u8 {
556 let instruction = self.memory[self.registers.pc as usize];
557 self.registers.pc = self.registers.pc.wrapping_add(1);
558 instruction
559 }
560
561 fn at_pc_plus(&self, offset: u16) -> u8 {
562 self.memory[self.registers.pc.wrapping_add(offset) as usize]
563 }
564
565 fn pc(&self) -> u16 {
566 self.registers.pc
567 }
568
569 fn peek_stack(&mut self, n: u8) -> u16 {
570 self.memory_stack().peek_down_by(n * 2)
571 }
572
573 fn run_command<T, U>(&mut self, output: T, input: U) -> ProcessorContinue
574 where
575 T: Fn(u16, u16),
576 U: Fn(u16) -> u16,
577 {
578 let next_instruction = self.next();
579 let next_instruction_as_enum = match Opcode::from_u8(next_instruction.into()) {
580 Some(opcode) => opcode,
581 None => {
582 return ProcessorContinue::Error;
583 }
584 };
585 match next_instruction_as_enum {
586 Opcode::Halt => ProcessorContinue::Halt,
587 Opcode::MovRegImm => save_to_register!(self, || self.load_immediate()),
588 Opcode::MovRegReg => {
589 with_register_id_and_register_value!(self, |destination, value| {
590 match self.save_register(destination, value) {
591 Ok(_) => ProcessorContinue::KeepRunning,
592 Err(_) => ProcessorContinue::Error,
593 }
594 })
595 }
596 Opcode::MovRegRegAdr => {
597 with_register_id_and_register_address!(self, |destination, value| {
598 match self.save_register(destination, value) {
599 Ok(_) => ProcessorContinue::KeepRunning,
600 Err(_) => ProcessorContinue::Error,
601 }
602 })
603 }
604 Opcode::MovRegRegAdrOff => {
605 with_register_id_and_register_address_offset!(self, |destination, value| {
606 match self.save_register(destination, value) {
607 Ok(_) => ProcessorContinue::KeepRunning,
608 Err(_) => ProcessorContinue::Error,
609 }
610 })
611 }
612 Opcode::MovRegAdrReg => {
613 let (destination, source) = self.load_two_register_ids();
614 let value = match self.get_register_value(source) {
615 Some(value) => value,
616 None => return ProcessorContinue::Error,
617 };
618 match self.save_register(destination, value) {
619 Ok(_) => ProcessorContinue::KeepRunning,
620 Err(_) => ProcessorContinue::Error,
621 }
622 }
623 Opcode::MovRegAdrImm => save_to_register_address!(self, || self.load_immediate()),
624 Opcode::MovRegAdrOffReg => {
625 save_optional_to_register_address_offset!(self, || self.load_register())
626 }
627 Opcode::MovRegAdrOffImm => {
628 save_to_register_address_offset!(self, || self.load_immediate())
629 }
630 Opcode::PushReg => push_optional_result!(self, || self.load_register()),
631 Opcode::PushImm => push_result!(self, || self.load_immediate()),
632 Opcode::PopReg => save_to_register!(self, || self.memory_stack().pop()),
633 Opcode::EnterImm => {
634 let offset = self.load_immediate();
635 let bp = self.registers.bp;
636 self.memory_stack().push(bp);
637 self.registers.bp = self.registers.sp;
638 self.registers.sp = self.registers.sp.wrapping_sub(offset);
639 ProcessorContinue::KeepRunning
640 }
641 Opcode::Leave => {
642 let bp = self.memory_stack().pop();
643 self.registers.sp = self.registers.bp;
644 self.registers.bp = bp;
645 ProcessorContinue::KeepRunning
646 }
647
648 Opcode::AddRegRegAdr => arithmetic_reg_reg_addr!(self, arithmetic::add),
650 Opcode::AddRegReg => arithmetic_reg_reg!(self, arithmetic::add),
651 Opcode::AddRegRegAdrOff => arithmetic_reg_reg_addr_off!(self, arithmetic::add),
652 Opcode::AddRegAdrReg => arithmetic_reg_addr_reg!(self, arithmetic::add),
653
654 Opcode::SubRegRegAdr => arithmetic_reg_reg_addr!(self, arithmetic::sub),
655 Opcode::SubRegReg => arithmetic_reg_reg!(self, arithmetic::sub),
656 Opcode::SubRegRegAdrOff => arithmetic_reg_reg_addr_off!(self, arithmetic::sub),
657 Opcode::SubRegAdrReg => arithmetic_reg_addr_reg!(self, arithmetic::sub),
658
659 Opcode::IncReg => arithmetic_reg!(self, arithmetic::inc),
660 Opcode::IncRegAdr => arithmetic_reg_addr!(self, arithmetic::inc),
661 Opcode::IncRegAdrOff => arithmetic_reg_addr_offset!(self, arithmetic::inc),
662 Opcode::DecReg => arithmetic_reg!(self, arithmetic::dec),
663 Opcode::DecRegAdr => arithmetic_reg_addr!(self, arithmetic::dec),
664 Opcode::DecRegAdrOff => arithmetic_reg_addr_offset!(self, arithmetic::dec),
665
666 Opcode::MulRegRegAdr => arithmetic_reg_reg_addr!(self, arithmetic::mul),
667 Opcode::MulRegReg => arithmetic_reg_reg!(self, arithmetic::mul),
668 Opcode::MulRegRegAdrOff => arithmetic_reg_reg_addr_off!(self, arithmetic::mul),
669 Opcode::MulRegImm => arithmetic_reg_imm!(self, arithmetic::mul),
670 Opcode::MulRegAdrReg => arithmetic_reg_addr_reg!(self, arithmetic::mul),
671
672 Opcode::DivRegRegAdr => arithmetic_reg_reg_addr!(self, arithmetic::div),
673 Opcode::DivRegReg => arithmetic_reg_reg!(self, arithmetic::div),
674 Opcode::DivRegRegAdrOff => arithmetic_reg_reg_addr_off!(self, arithmetic::div),
675 Opcode::DivRegImm => arithmetic_reg_imm!(self, arithmetic::div),
676 Opcode::DivRegAdrReg => arithmetic_reg_addr_reg!(self, arithmetic::div),
677
678 Opcode::AndRegReg => arithmetic_reg_reg!(self, arithmetic::and),
679 Opcode::AndRegRegAdr => arithmetic_reg_reg_addr!(self, arithmetic::and),
680 Opcode::OrRegReg => arithmetic_reg_reg!(self, arithmetic::or),
681 Opcode::OrRegRegAdr => arithmetic_reg_reg_addr!(self, arithmetic::or),
682 Opcode::XorRegReg => arithmetic_reg_reg!(self, arithmetic::xor),
683 Opcode::XorRegRegAdr => arithmetic_reg_reg_addr!(self, arithmetic::xor),
684 Opcode::NotReg => arithmetic_reg!(self, arithmetic::not),
685 Opcode::NotRegAdr => arithmetic_reg_addr!(self, arithmetic::not),
686
687 Opcode::LshRegImm => arithmetic_reg_imm!(self, arithmetic::shl),
688 Opcode::LshRegAdrImm => arithmetic_reg_addr_imm!(self, arithmetic::shl),
689 Opcode::LshRegAdrOffImm => arithmetic_reg_addr_offset_imm!(self, arithmetic::shl),
690
691 Opcode::RshRegImm => arithmetic_reg_imm!(self, arithmetic::shr),
692 Opcode::RshRegAdrImm => arithmetic_reg_addr_imm!(self, arithmetic::shr),
693 Opcode::RshRegAdrOffImm => arithmetic_reg_addr_offset_imm!(self, arithmetic::shr),
694
695 Opcode::CallImm => with_immediate!(self, |immediate| {
697 let pc = self.registers.pc;
698 self.memory_stack().push(pc);
699 self.registers.pc = immediate;
700 }),
701 Opcode::CallReg => with_register_value!(self, |value| {
702 let pc = self.registers.pc;
703 self.memory_stack().push(pc);
704 self.registers.pc = value;
705 }),
706 Opcode::CallRegOff => with_register_address_offset_as_address!(self, |address| {
707 let pc = self.registers.pc;
708 self.memory_stack().push(pc);
709 self.registers.pc = address;
710 }),
711 Opcode::Ret => {
712 let pc = self.memory_stack().pop();
713 self.registers.pc = pc;
714 ProcessorContinue::KeepRunning
715 }
716
717 Opcode::CmpRegReg => arithmetic_reg_reg!(self, arithmetic::cmp),
719 Opcode::CmpRegImm => arithmetic_reg_imm!(self, arithmetic::cmp),
720 Opcode::CmpRegRegAdr => arithmetic_reg_reg_addr!(self, arithmetic::cmp),
721 Opcode::CmpRegRegAdrOff => arithmetic_reg_reg_addr_off!(self, arithmetic::cmp),
722 Opcode::TestRegReg => arithmetic_reg_reg!(self, arithmetic::test),
723 Opcode::TestRegRegAdr => arithmetic_reg_reg_addr!(self, arithmetic::test),
724 Opcode::TestRegRegAdrOff => arithmetic_reg_reg_addr_off!(self, arithmetic::test),
725 Opcode::JmpImm => with_immediate!(self, |immediate| self.registers.pc = immediate),
727 Opcode::JmpReg => with_register_value!(self, |value| self.registers.pc = value),
728 Opcode::JmpRegOff => {
729 with_register_address_offset_as_address!(self, |address| self.registers.pc =
730 address)
731 }
732 Opcode::JeImm => with_immediate!(self, |immediate| {
733 if self.registers.fr.get(ProcessorFlags::ZF) {
734 self.registers.pc = immediate;
735 }
736 }),
737 Opcode::JneImm => with_immediate!(self, |immediate| {
738 if !self.registers.fr.get(ProcessorFlags::ZF) {
739 self.registers.pc = immediate;
740 }
741 }),
742 Opcode::JgImm => with_immediate!(self, |immediate| {
743 if !self.registers.fr.get(ProcessorFlags::ZF)
744 && (self.registers.fr.get(ProcessorFlags::SF)
745 == self.registers.fr.get(ProcessorFlags::OF))
746 {
747 self.registers.pc = immediate;
748 }
749 }),
750 Opcode::JgeImm => with_immediate!(self, |immediate| {
751 if !self.registers.fr.get(ProcessorFlags::CF) {
752 self.registers.pc = immediate;
753 }
754 }),
755 Opcode::JlImm => with_immediate!(self, |immediate| {
756 if self.registers.fr.get(ProcessorFlags::SF)
757 != self.registers.fr.get(ProcessorFlags::OF)
758 {
759 self.registers.pc = immediate;
760 }
761 }),
762 Opcode::JleImm => with_immediate!(self, |immediate| {
763 if self.registers.fr.get(ProcessorFlags::ZF)
764 || self.registers.fr.get(ProcessorFlags::CF)
765 {
766 self.registers.pc = immediate;
767 }
768 }),
769
770 Opcode::InRegPort => {
771 save_to_register!(self, || with_immediate_raw!(self, input))
772 }
773 Opcode::InRegAdrPort => {
774 save_to_register_address!(self, || with_immediate_raw!(self, input))
775 }
776 Opcode::InRegAdrOffPort => {
777 save_to_register_address_offset!(self, || with_immediate_raw!(self, input))
778 }
779 Opcode::OutPortImm => {
780 with_immediate!(self, |port| with_register_value!(self, |immediate| {
781 output(port, immediate)
782 }))
783 }
784 Opcode::OutPortReg => {
785 with_immediate!(self, |port| with_register_value!(self, |value| output(
786 port, value
787 )))
788 }
789 Opcode::OutPortRegAdr => {
790 with_immediate!(self, |port| with_register_address!(self, |address| output(
791 port, address
792 )))
793 }
794 Opcode::OutPortRegAdrOff => {
795 with_immediate_raw!(self, |port| with_register_address_offset!(self, |value| {
796 match value {
797 Some(value) => {
798 output(port, value);
799 ProcessorContinue::KeepRunning
800 }
801 None => ProcessorContinue::Error,
802 }
803 }))
804 }
805 Opcode::Nop => ProcessorContinue::KeepRunning,
806 }
807 }
808
809 fn load_executable(&mut self, executable: &Executable) -> Result<(), String> {
810 unimplemented!()
811 }
812}