1use std::{collections::BTreeMap, ops::Range};
2
3use crate::{Bytecode, CpuStats, ExecutionError, RunMode};
4use num_traits::FromPrimitive;
5
6const L1_LATENCY: usize = 3;
7const L2_LATENCY: usize = 11;
8const L3_LATENCY: usize = 50;
9const MEMORY_LATENCY: usize = 125;
10const AVERAGE_STORE_LATENCY: usize = 1;
11
12const LINE_SIZE: u32 = 64;
13const L1_SETS: usize = 64;
14const L1_WAYS: usize = 4;
15const L2_SETS: usize = 256;
16const L2_WAYS: usize = 8;
17const L3_SETS: usize = 1024;
18const L3_WAYS: usize = 16;
19
20const REGISTER_WIDTH: u32 = 32; const SHIFT_BITS: u32 = REGISTER_WIDTH.trailing_zeros();
25
26const SHIFT_MASK: u32 = (1 << SHIFT_BITS) - 1;
28
29#[derive(Debug, Default, Clone)]
30struct CacheLine {
31 valid: bool,
32 tag: u32,
33}
34
35#[derive(Debug)]
36struct Cache {
37 sets: Vec<Vec<CacheLine>>,
38 sets_mask: u32,
39 line_offset_bits: u32,
40 tag_shift: u32,
41 latency: usize,
42}
43
44impl Cache {
45 fn new(num_sets: usize, ways: usize, line_size: u32, latency: usize) -> Self {
46 let line_offset_bits = line_size.trailing_zeros();
47 let set_count = num_sets as u32;
48 let set_index_bits = set_count.trailing_zeros();
49
50 let sets = vec![vec![CacheLine::default(); ways]; num_sets];
51
52 Self {
53 sets,
54 sets_mask: set_count - 1,
55 line_offset_bits,
56 tag_shift: line_offset_bits + set_index_bits,
57 latency,
58 }
59 }
60
61 fn access(&mut self, address: u32, tag: u32) -> Option<usize> {
62 let set_index = ((address >> self.line_offset_bits) & self.sets_mask) as usize;
63 let set = &mut self.sets[set_index];
64
65 if let Some(pos) = set.iter().position(|line| line.valid && line.tag == tag) {
66 let line = set.remove(pos);
68 set.insert(0, line);
69 return Some(self.latency);
70 }
71
72 None
73 }
74
75 fn insert_line(&mut self, address: u32, tag: u32) {
76 let set_index = ((address >> self.line_offset_bits) & self.sets_mask) as usize;
77 let set = &mut self.sets[set_index];
78
79 let mut evict_line = set.pop().unwrap();
81 evict_line.valid = true;
82 evict_line.tag = tag;
83
84 set.insert(0, evict_line);
86 }
87
88 fn line_tag(&self, address: u32) -> u32 {
89 address >> self.tag_shift
90 }
91}
92
93#[derive(Debug, PartialEq, Eq)]
94enum MemoryAccessDirection {
95 LoadData,
96 LoadInstruction,
97 Prefetch,
98 Store,
99}
100
101#[derive(Debug, Default, Clone, Copy)]
102pub struct Flags {
103 pub zero: bool,
104 pub carry: bool,
105 pub sign: bool,
106 pub overflow: bool,
107}
108
109pub trait HostIO: std::fmt::Debug {
110 fn syscall(&mut self, code: u32, cpu: &mut NativeCpu<Self>) -> Result<usize, ExecutionError>
111 where
112 Self: Sized;
113}
114
115#[derive(Debug)]
116pub struct NullHostIO;
117
118impl HostIO for NullHostIO {
119 fn syscall(
120 &mut self,
121 _code: u32,
122 _cpu: &mut NativeCpu<NullHostIO>,
123 ) -> Result<usize, ExecutionError> {
124 Ok(1250)
126 }
127}
128
129#[derive(Debug)]
130pub struct NativeCpu<IO: HostIO> {
131 memory: Vec<u32>,
132 registers: Vec<u32>,
133 instruction_pointer: u32,
134 stack_pointer: u32,
135 stats: CpuStats,
136 flags: Flags,
137 l1i: Cache,
138 l1d: Cache,
139 l2: Cache,
140 l3: Cache,
141
142 protected_memory: Range<u32>,
143
144 last_load_addresses: Vec<u32>,
145 stable_stride: Option<i32>,
146 pub host_io: Option<IO>,
147 halted: bool,
148 verbose: bool,
149 print_memory_access: bool,
150 addresses_as_integers: bool,
151}
152
153impl<IO: HostIO> NativeCpu<IO> {
154 pub fn set_addresses_as_integers(&mut self, addresses_as_integers: bool) {
155 self.addresses_as_integers = addresses_as_integers;
156 }
157
158 pub fn print_state(&self) {
159 println!();
160 println!("========== VM STATE ===========");
161 println!();
162 println!("IP: {}", self.instruction_pointer);
163 println!("SP: {}", self.stack_pointer);
164 println!("Flags: {:#?}", self.flags);
165 println!(
166 "Registers: {:#?}",
167 self.registers
168 .iter()
169 .enumerate()
170 .collect::<BTreeMap<_, _>>()
171 );
172 println!(
173 "Memory: {:#?}",
174 self.memory.iter().enumerate().collect::<BTreeMap<_, _>>()
175 );
176 }
177
178 pub fn set_halted(&mut self, halted: bool) {
179 self.halted = halted;
180 }
181
182 #[allow(unused)]
183 pub fn get_halted(&self) -> bool {
184 self.halted
185 }
186
187 pub fn set_print_memory_access(&mut self, print_memory_access: bool) {
188 self.print_memory_access = print_memory_access;
189 }
190
191 pub fn set_verbose(&mut self, verbose: bool) {
192 self.verbose = verbose;
193 }
194
195 pub fn set_entrypoint(&mut self, entrypoint: u32) {
196 self.instruction_pointer = entrypoint;
197 }
198
199 pub fn protect(&mut self, range: Range<u32>) {
200 self.protected_memory = range;
201 }
202
203 pub fn load_protected_memory(&mut self, address: u32, memory: &[u32]) {
204 let len = self.memory.len().min(memory.len());
205 self.memory[address as usize..address as usize + len].copy_from_slice(&memory[..len]);
206 self.protect(address..address + memory.len() as u32);
207 }
208
209 pub fn load_memory(&mut self, address: u32, memory: &[u32]) {
210 let len = self.memory.len().min(memory.len());
211 self.memory[address as usize..address as usize + len].copy_from_slice(&memory[..len]);
212 }
213
214 pub fn execute(&mut self, run_mode: RunMode) -> Result<CpuStats, ExecutionError> {
215 match run_mode {
216 RunMode::Run => self.run(-1),
217 RunMode::RunFor(cycles) => self.run(cycles),
218 _ => Err(ExecutionError::NotImplemented),
219 }
220 }
221
222 pub fn get_registers(&self) -> &[u32] {
223 &self.registers
224 }
225
226 pub fn get_mut_registers(&mut self) -> &mut [u32] {
227 &mut self.registers
228 }
229
230 pub fn get_memory(&self) -> &[u32] {
231 &self.memory
232 }
233
234 pub fn new(memory_size: u32, registers: u8, host_io: IO) -> Self {
235 Self {
236 memory: vec![0; memory_size as usize],
237 registers: vec![0; registers as usize],
238 instruction_pointer: 0,
239 stack_pointer: memory_size - 1,
240 verbose: false,
241 stats: CpuStats::default(),
242 flags: Flags::default(),
243 l1i: Cache::new(L1_SETS, L1_WAYS, LINE_SIZE, L1_LATENCY),
244 l1d: Cache::new(L1_SETS, L1_WAYS, LINE_SIZE, L1_LATENCY),
245 l2: Cache::new(L2_SETS, L2_WAYS, LINE_SIZE, L2_LATENCY),
246 l3: Cache::new(L3_SETS, L3_WAYS, LINE_SIZE, L3_LATENCY),
247
248 protected_memory: 0..0,
249
250 last_load_addresses: Vec::new(),
251 stable_stride: None,
252 host_io: Some(host_io),
253 halted: false,
254 print_memory_access: false,
255 addresses_as_integers: false,
256 }
257 }
258
259 fn shift_left(&self, value: u32, count: u32) -> (u32, bool) {
261 let shift = count & SHIFT_MASK;
262 if shift == 0 {
263 return (value, false);
264 }
265 let carry_out = ((value >> (32 - shift)) & 1) == 1;
267 let result = value.wrapping_shl(shift);
268 (result, carry_out)
269 }
270
271 fn shift_right(&self, value: u32, count: u32) -> (u32, bool) {
273 let shift = count & 31;
274 if shift == 0 {
275 return (value, false);
276 }
277 let carry_out = ((value >> (shift - 1)) & 1) == 1;
279 let result = value.wrapping_shr(shift);
280 (result, carry_out)
281 }
282
283 fn update_flags_shl(&mut self, original: u32, result: u32, carry_out: bool, shift_count: u32) {
287 self.flags.zero = result == 0;
288 self.flags.sign = (result as i32) < 0;
289 self.flags.carry = carry_out;
290
291 if shift_count == 1 {
293 let msb_original = (original >> 31) & 1;
294 let msb_result = (result >> 31) & 1;
295 self.flags.overflow = msb_original != msb_result;
296 } else {
297 self.flags.overflow = false;
298 }
299 }
300
301 fn update_flags_shr(&mut self, result: u32, carry_out: bool) {
304 self.flags.zero = result == 0;
305 self.flags.sign = (result as i32) < 0;
306 self.flags.carry = carry_out;
307 self.flags.overflow = false;
308 }
309
310 fn access(&mut self, address: u32, direction: MemoryAccessDirection) -> usize {
311 self.stats.memory_access_count += 1;
312 let l1_cache = if direction == MemoryAccessDirection::LoadInstruction {
313 &mut self.l1i
314 } else {
315 &mut self.l1d
316 };
317 let tag_l1 = l1_cache.line_tag(address);
318
319 if let Some(l1_lat) = l1_cache.access(address, tag_l1) {
321 if self.print_memory_access && direction != MemoryAccessDirection::Prefetch {
322 println!(" (L1 HIT)");
323 }
324
325 if direction == MemoryAccessDirection::LoadInstruction {
326 self.stats.cache_hits.l1i += 1;
327 } else {
328 self.stats.cache_hits.l1d += 1;
329 }
330 return match direction {
332 MemoryAccessDirection::LoadData
333 | MemoryAccessDirection::LoadInstruction
334 | MemoryAccessDirection::Prefetch => l1_lat,
335 MemoryAccessDirection::Store => AVERAGE_STORE_LATENCY,
336 };
337 }
338
339 let tag_l2 = self.l2.line_tag(address);
340
341 if let Some(l2_lat) = self.l2.access(address, tag_l2) {
343 if self.print_memory_access && direction != MemoryAccessDirection::Prefetch {
344 println!(" (L2 HIT)");
345 }
346 self.stats.cache_hits.l2 += 1;
347 l1_cache.insert_line(address, tag_l1);
349
350 return match direction {
351 MemoryAccessDirection::LoadData
352 | MemoryAccessDirection::LoadInstruction
353 | MemoryAccessDirection::Prefetch => l2_lat,
354 MemoryAccessDirection::Store => AVERAGE_STORE_LATENCY,
355 };
356 }
357
358 let tag_l3 = self.l3.line_tag(address);
359
360 if let Some(l3_lat) = self.l3.access(address, tag_l3) {
362 if self.print_memory_access && direction != MemoryAccessDirection::Prefetch {
363 println!(" (L3 HIT)");
364 }
365 self.stats.cache_hits.l3 += 1;
366 self.l2.insert_line(address, tag_l2);
368 l1_cache.insert_line(address, tag_l1);
369
370 return match direction {
371 MemoryAccessDirection::LoadData
372 | MemoryAccessDirection::LoadInstruction
373 | MemoryAccessDirection::Prefetch => l3_lat,
374 MemoryAccessDirection::Store => AVERAGE_STORE_LATENCY,
375 };
376 }
377
378 if self.print_memory_access && direction != MemoryAccessDirection::Prefetch {
379 println!(" (CACHE MISS)");
380 }
381
382 self.l3.insert_line(address, tag_l3);
385 self.l2.insert_line(address, tag_l2);
386 l1_cache.insert_line(address, tag_l1);
387
388 match direction {
389 MemoryAccessDirection::LoadData
390 | MemoryAccessDirection::LoadInstruction
391 | MemoryAccessDirection::Prefetch => MEMORY_LATENCY,
392 MemoryAccessDirection::Store => AVERAGE_STORE_LATENCY,
393 }
394 }
395
396 fn detect_stride(&mut self) {
397 if self.last_load_addresses.len() < 4 {
400 self.stable_stride = None;
401 return;
402 }
403
404 let len = self.last_load_addresses.len();
406 let a1 = self.last_load_addresses[len - 4];
407 let a2 = self.last_load_addresses[len - 3];
408 let a3 = self.last_load_addresses[len - 2];
409 let a4 = self.last_load_addresses[len - 1];
410
411 let d1 = a2 as i32 - a1 as i32;
412 let d2 = a3 as i32 - a2 as i32;
413 let d3 = a4 as i32 - a3 as i32;
414
415 if d1 == d2 && d2 == d3 {
417 self.stable_stride = Some(d1);
419 } else {
420 self.stable_stride = None;
421 }
422 }
423
424 fn prefetch_instructions(&mut self, current_address: u32) {
425 let words_per_line = (LINE_SIZE / 4) as i32;
426
427 for i in 0..10 {
428 let next_line_address = ((current_address as i32) + (words_per_line * i)) as u32;
429
430 _ = self.access(next_line_address, MemoryAccessDirection::Prefetch);
432 }
433 }
434
435 fn prefetch_lines(&mut self, current_address: u32) {
436 let stride = match self.stable_stride {
438 Some(s) => s,
439 None => return,
440 };
441
442 if stride == 0 {
443 return; }
445
446 if stride > 0 {
449 let words_per_line = (LINE_SIZE / 4) as i32;
450
451 let next_line_address = ((current_address as i32) + stride) as u32;
452 let second_line_address = ((current_address as i32) + stride + words_per_line) as u32;
453
454 _ = self.access(next_line_address, MemoryAccessDirection::Prefetch);
457 _ = self.access(second_line_address, MemoryAccessDirection::Prefetch);
458 }
459 }
460
461 fn update_load_history(&mut self, address: u32) {
462 self.last_load_addresses.push(address);
463 if self.last_load_addresses.len() > 16 {
464 self.last_load_addresses.remove(0);
465 }
466 self.detect_stride();
467 }
468
469 fn read_instruction(&mut self, address: u32) -> Result<Bytecode, ExecutionError> {
470 self.valid_address(address)?;
471 if self.print_memory_access {
472 if self.addresses_as_integers {
473 print!("READ INSTR @{}", address);
474 } else {
475 print!("READ INSTR @{:#02x}", address);
476 }
477 }
478 let cost = self.access(address, MemoryAccessDirection::LoadInstruction);
479 self.stats.cycles += cost;
480
481 self.prefetch_instructions(address);
482
483 let value = self.memory[address as usize];
484
485 match Bytecode::from_u32(value) {
486 Some(instr) => {
487 self.instruction_pointer += 1;
488 Ok(instr)
489 }
490 None => Err(ExecutionError::InvalidOpcode(
491 value,
492 self.instruction_pointer,
493 )),
494 }
495 }
496
497 fn read_operand(&mut self, address: u32) -> Result<u32, ExecutionError> {
498 let result = self.read_memory(address)?;
499 self.instruction_pointer += 1;
500 Ok(result)
501 }
502
503 fn read_memory(&mut self, address: u32) -> Result<u32, ExecutionError> {
504 self.valid_address(address)?;
505 if self.print_memory_access {
506 if self.addresses_as_integers {
507 print!("READ @{}", address);
508 } else {
509 print!("READ @{:#02x}", address);
510 }
511 }
512 let cost = self.access(address, MemoryAccessDirection::LoadData);
513 self.stats.cycles += cost;
514
515 self.update_load_history(address);
516
517 self.prefetch_lines(address);
518
519 Ok(self.memory[address as usize])
520 }
521
522 fn write_memory(&mut self, address: u32, value: u32) -> Result<(), ExecutionError> {
523 self.valid_address(address)?;
524 if self.protected_memory.contains(&address) {
525 return Err(ExecutionError::WriteProtectedMemory(address));
526 }
527 if self.print_memory_access {
528 if self.addresses_as_integers {
529 print!("WRITE @{}, {}", address, value);
530 } else {
531 print!("WRITE @{:#02x}, {}", address, value);
532 }
533 }
534 let cost = self.access(address, MemoryAccessDirection::Store);
535 self.stats.cycles += cost;
536 self.memory[address as usize] = value;
537 Ok(())
538 }
539
540 fn update_flags_and(&mut self, a: u32, b: u32, result: u32) {
548 self.flags.zero = result == 0;
549 self.flags.sign = (result as i32) < 0;
550 self.flags.carry = false;
551 self.flags.overflow = false;
552
553 if self.verbose {
554 println!(
555 "FLAGS (AND): a=0x{:08X}, b=0x{:08X}, result=0x{:08X}, zero={}, sign={}, carry={}, overflow={}",
556 a, b, result, self.flags.zero, self.flags.sign, self.flags.carry, self.flags.overflow
557 );
558 }
559 }
560
561 fn update_flags_or(&mut self, a: u32, b: u32, result: u32) {
569 self.flags.zero = result == 0;
570 self.flags.sign = (result as i32) < 0;
571 self.flags.carry = false;
572 self.flags.overflow = false;
573
574 if self.verbose {
575 println!(
576 "FLAGS (OR): a=0x{:08X}, b=0x{:08X}, result=0x{:08X}, zero={}, sign={}, carry={}, overflow={}",
577 a, b, result, self.flags.zero, self.flags.sign, self.flags.carry, self.flags.overflow
578 );
579 }
580 }
581
582 fn update_flags_xor(&mut self, a: u32, b: u32, result: u32) {
590 self.flags.zero = result == 0;
591 self.flags.sign = (result as i32) < 0;
592 self.flags.carry = false;
593 self.flags.overflow = false;
594
595 if self.verbose {
596 println!(
597 "FLAGS (XOR): a=0x{:08X}, b=0x{:08X}, result=0x{:08X}, zero={}, sign={}, carry={}, overflow={}",
598 a, b, result, self.flags.zero, self.flags.sign, self.flags.carry, self.flags.overflow
599 );
600 }
601 }
602
603 fn update_flags_not(&mut self, a: u32, result: u32) {
611 self.flags.zero = result == 0;
612 self.flags.sign = (result as i32) < 0;
613 self.flags.carry = false;
614 self.flags.overflow = false;
615
616 if self.verbose {
617 println!(
618 "FLAGS (NOT): a=0x{:08X}, result=0x{:08X}, zero={}, sign={}, carry={}, overflow={}",
619 a, result, self.flags.zero, self.flags.sign, self.flags.carry, self.flags.overflow
620 );
621 }
622 }
623
624 fn update_flags_mul(&mut self, _a: u32, _b: u32, result: u64) {
625 let low_result = result as u32;
627
628 self.flags.zero = low_result == 0;
630
631 self.flags.sign = (low_result as i32) < 0;
633
634 let high_result = (result >> 32) as u32;
637 let overflow_occurred = high_result != 0;
638 self.flags.carry = overflow_occurred;
639 self.flags.overflow = overflow_occurred;
640 }
641
642 fn update_flags_div(&mut self, _a: u32, _b: u32, result: u32) {
643 self.flags.carry = false;
644 self.flags.overflow = false;
645
646 self.flags.zero = result == 0;
648
649 self.flags.sign = (result as i32) < 0;
651 }
652
653 fn should_jump(&self, instr: Bytecode) -> bool {
654 let f = &self.flags;
655 match instr {
656 Bytecode::Je => f.zero,
658 Bytecode::Jne => !f.zero,
659 Bytecode::Jg => !f.zero && (f.sign == f.overflow),
660 Bytecode::Jge => f.sign == f.overflow,
661 Bytecode::Jl => f.sign != f.overflow,
662 Bytecode::Jle => f.zero || (f.sign != f.overflow),
663
664 Bytecode::Ja => !f.carry && !f.zero,
666 Bytecode::Jae => !f.carry,
667 Bytecode::Jb => f.carry,
668 Bytecode::Jbe => f.carry || f.zero,
669
670 Bytecode::Jc => f.carry,
672 Bytecode::Jnc => !f.carry,
673 Bytecode::Jo => f.overflow,
674 Bytecode::Jno => !f.overflow,
675 Bytecode::Js => f.sign,
676 Bytecode::Jns => !f.sign,
677
678 Bytecode::Jxcz => {
680 let cx = self.registers.get(1).copied().unwrap_or(0);
681 cx == 0
682 }
683
684 _ => false,
686 }
687 }
688
689 fn update_flags_add(&mut self, a: u32, b: u32, result: u32) {
690 self.flags.zero = result == 0;
692
693 self.flags.sign = (result as i32) < 0;
695
696 let (_, c) = a.overflowing_add(b);
698 self.flags.carry = c;
699
700 let a_sign = (a as i32) < 0;
703 let b_sign = (b as i32) < 0;
704 let r_sign = (result as i32) < 0;
705 self.flags.overflow = (a_sign == b_sign) && (a_sign != r_sign);
706 }
707
708 fn update_flags_sub(&mut self, a: u32, b: u32, result: u32) {
709 self.flags.zero = result == 0;
711
712 self.flags.sign = (result as i32) < 0;
714
715 self.flags.carry = b > a;
718
719 let a_sign = (a as i32) < 0;
722 let b_sign = (b as i32) < 0;
723 let r_sign = (result as i32) < 0;
724
725 self.flags.overflow = (a_sign != b_sign) && (r_sign != a_sign);
726 }
727
728 fn read_byte(&mut self, address: u32) -> Result<u8, ExecutionError> {
729 self.valid_address(address)?;
730 let cost = self.access(address, MemoryAccessDirection::LoadData);
731 self.stats.cycles += cost;
732
733 let byte_index = (address as usize) * 4;
734 if byte_index + 1 > self.memory.len() * 4 {
735 return Err(ExecutionError::InvalidMemoryLocation(address));
736 }
737
738 let mem_as_bytes = unsafe {
739 std::slice::from_raw_parts(self.memory.as_ptr() as *const u8, self.memory.len() * 4)
740 };
741 Ok(mem_as_bytes[byte_index])
742 }
743
744 fn write_byte(&mut self, address: u32, value: u8) -> Result<(), ExecutionError> {
745 self.valid_address(address)?;
746 let cost = self.access(address, MemoryAccessDirection::Store);
747 self.stats.cycles += cost;
748
749 let byte_index = (address as usize) * 4;
750 if byte_index + 1 > self.memory.len() * 4 {
751 return Err(ExecutionError::InvalidMemoryLocation(address));
752 }
753
754 let mem_as_bytes = unsafe {
755 std::slice::from_raw_parts_mut(
756 self.memory.as_mut_ptr() as *mut u8,
757 self.memory.len() * 4,
758 )
759 };
760 mem_as_bytes[byte_index] = value;
761 Ok(())
762 }
763
764 fn update_flags_float(&mut self, a: f32, b: f32) {
765 self.flags.zero = (a == b) && a.is_finite() && b.is_finite();
767
768 self.flags.sign = a < b;
770
771 self.flags.overflow = !(a.is_finite() && b.is_finite());
773
774 self.flags.carry = false;
776 }
777
778 fn write_register(&mut self, reg: u32, value: u32) {
779 if reg != 0 {
780 self.registers[reg as usize] = value;
781 }
782 }
783
784 fn read_register(&self, reg: u32) -> u32 {
785 if reg != 0 {
786 self.registers[reg as usize]
787 } else {
788 0
789 }
790 }
791
792 fn run(&mut self, cycles: isize) -> Result<CpuStats, ExecutionError> {
793 if self.halted {
794 return Ok(self.stats);
795 }
796
797 let mut executed = 0;
798
799 while (cycles < 0 || executed < cycles)
800 && (self.instruction_pointer as usize) < self.memory.len()
801 {
802 let opcode = self.read_instruction(self.instruction_pointer)?;
803
804 match opcode {
805 Bytecode::Nop => {
806 if self.verbose {
807 println!("NOP");
808 }
809 }
810 Bytecode::LoadValue => {
811 let reg = self.read_operand(self.instruction_pointer)?;
812 let imm = self.read_operand(self.instruction_pointer)?;
813
814 if self.verbose {
815 println!("LOAD R{}, {}", reg, imm);
816 }
817
818 self.write_register(reg, imm);
819 }
820 Bytecode::LoadFromRegMemory => {
821 let reg1 = self.read_operand(self.instruction_pointer)?;
822 let reg2 = self.read_operand(self.instruction_pointer)?;
823
824 let addr = self.read_register(reg2);
825
826 if self.verbose {
827 if self.addresses_as_integers {
828 println!("LOADREG R{}, R{}(@{})", reg1, reg2, addr);
829 } else {
830 println!("LOADREG R{}, R{}(@{:#02x})", reg1, reg2, addr);
831 }
832 }
833
834 let value = self.read_memory(addr)?;
835 self.write_register(reg1, value);
836 }
837 Bytecode::LoadMemory => {
838 let reg = self.read_operand(self.instruction_pointer)?;
839 let addr = self.read_operand(self.instruction_pointer)?;
840
841 if self.verbose {
842 if self.addresses_as_integers {
843 println!("LOAD R{}, @{}", reg, addr);
844 } else {
845 println!("LOAD R{}, @{:#02x}", reg, addr);
846 }
847 }
848
849 let value = self.read_memory(addr)?;
850 self.write_register(reg, value);
851 }
852 Bytecode::LoadReg => {
853 let reg1 = self.read_operand(self.instruction_pointer)?;
854 let reg2 = self.read_operand(self.instruction_pointer)?;
855
856 if self.verbose {
857 println!("LOAD R{}, R{}", reg1, reg2);
858 }
859
860 self.write_register(reg1, self.read_register(reg2));
861 }
862 Bytecode::Store => {
863 let addr = self.read_operand(self.instruction_pointer)?;
864 let reg = self.read_operand(self.instruction_pointer)?;
865
866 if self.verbose {
867 if self.addresses_as_integers {
868 println!("STORE @{}, R{}", addr, reg);
869 } else {
870 println!("STORE @{:#02x}, R{}", addr, reg);
871 }
872 }
873
874 self.write_memory(addr, self.read_register(reg))?;
875 }
876 Bytecode::StoreAtReg => {
877 let reg1 = self.read_operand(self.instruction_pointer)?;
878 let reg2 = self.read_operand(self.instruction_pointer)?;
879
880 let addr = self.read_register(reg1);
881
882 if self.verbose {
883 if self.addresses_as_integers {
884 println!("STOREREG R{}(@{}), R{}", reg1, addr, reg2);
885 } else {
886 println!("STOREREG R{}(@{:#02x}), R{}", reg1, addr, reg2);
887 }
888 }
889
890 self.write_memory(addr, self.read_register(reg2))?;
891 }
892 Bytecode::StoreValue => {
893 let addr = self.read_operand(self.instruction_pointer)?;
894 let imm = self.read_operand(self.instruction_pointer)?;
895
896 if self.verbose {
897 if self.addresses_as_integers {
898 println!("STORE @{}, {}", addr, imm);
899 } else {
900 println!("STORE @{:#02x}, {}", addr, imm);
901 }
902 }
903
904 self.write_memory(addr, imm)?;
905 }
906 Bytecode::StoreValueAtReg => {
907 let reg = self.read_operand(self.instruction_pointer)?;
908 let imm = self.read_operand(self.instruction_pointer)?;
909
910 let addr = self.read_register(reg);
911
912 if self.verbose {
913 if self.addresses_as_integers {
914 println!("STOREREG R{}(@{}), {}", reg, addr, imm);
915 } else {
916 println!("STOREREG R{}(@{:#02x}), {}", reg, addr, imm);
917 }
918 }
919
920 self.write_memory(addr, imm)?;
921 }
922 Bytecode::PushValue => {
923 let imm = self.read_operand(self.instruction_pointer)?;
924
925 if self.verbose {
926 println!("PUSH {}", imm);
927 }
928
929 self.push_stack(imm)?;
930 }
931 Bytecode::PushReg => {
932 let reg = self.read_operand(self.instruction_pointer)?;
933
934 if self.verbose {
935 println!("PUSH R{}", reg);
936 }
937
938 let val = self.read_register(reg);
939
940 self.push_stack(val)?;
941 }
942 Bytecode::Pop => {
943 let reg = self.read_operand(self.instruction_pointer)?;
944
945 if self.verbose {
946 println!("POP R{}", reg);
947 }
948
949 let value = self.pop_stack()?;
950 self.write_register(reg, value);
951 }
952 Bytecode::And => {
953 let reg1 = self.read_operand(self.instruction_pointer)?;
954 let reg2 = self.read_operand(self.instruction_pointer)?;
955
956 let a = self.read_register(reg1);
957 let b = self.read_register(reg2);
958 let result = a & b;
959
960 if self.verbose {
961 println!("AND R{}({}), R{}({}) => {}", reg1, a, reg2, b, result);
962 }
963
964 self.write_register(reg1, result);
965 self.update_flags_and(a, b, result);
966 }
967 Bytecode::AndValue => {
968 let reg = self.read_operand(self.instruction_pointer)?;
969 let imm = self.read_operand(self.instruction_pointer)?;
970
971 let a = self.read_register(reg);
972 let b = imm;
973 let result = a & b;
974
975 if self.verbose {
976 println!("AND R{}({}), {} => {}", reg, a, b, result);
977 }
978
979 self.write_register(reg, result);
980 self.update_flags_and(a, b, result);
981 }
982 Bytecode::Or => {
983 let reg1 = self.read_operand(self.instruction_pointer)?;
984 let reg2 = self.read_operand(self.instruction_pointer)?;
985
986 let a = self.read_register(reg1);
987 let b = self.read_register(reg2);
988 let result = a | b;
989
990 if self.verbose {
991 println!("OR R{}({}), R{}({}) => {}", reg1, a, reg2, b, result);
992 }
993
994 self.write_register(reg1, result);
995 self.update_flags_or(a, b, result);
996 }
997 Bytecode::OrValue => {
998 let reg = self.read_operand(self.instruction_pointer)?;
999 let imm = self.read_operand(self.instruction_pointer)?;
1000
1001 let a = self.read_register(reg);
1002 let b = imm;
1003 let result = a | b;
1004
1005 if self.verbose {
1006 println!("OR R{}({}), {} => {}", reg, a, b, result);
1007 }
1008
1009 self.write_register(reg, result);
1010 self.update_flags_or(a, b, result);
1011 }
1012 Bytecode::Xor => {
1013 let reg1 = self.read_operand(self.instruction_pointer)?;
1014 let reg2 = self.read_operand(self.instruction_pointer)?;
1015
1016 let a = self.read_register(reg1);
1017 let b = self.read_register(reg2);
1018 let result = a ^ b;
1019
1020 if self.verbose {
1021 println!("XOR R{}({}), R{}({}) => {}", reg1, a, reg2, b, result);
1022 }
1023
1024 self.write_register(reg1, result);
1025 self.update_flags_xor(a, b, result);
1026 }
1027 Bytecode::XorValue => {
1028 let reg = self.read_operand(self.instruction_pointer)?;
1029 let imm = self.read_operand(self.instruction_pointer)?;
1030
1031 let a = self.read_register(reg);
1032 let b = imm;
1033 let result = a ^ b;
1034
1035 if self.verbose {
1036 println!("XOR R{}({}), {} => {}", reg, a, b, result);
1037 }
1038
1039 self.write_register(reg, result);
1040 self.update_flags_xor(a, b, result);
1041 }
1042 Bytecode::Not => {
1043 let reg = self.read_operand(self.instruction_pointer)?;
1044
1045 let a = self.read_register(reg);
1046 let result = !a;
1047
1048 if self.verbose {
1049 println!("NOT R{}({}) => {}", reg, a, result);
1050 }
1051
1052 self.write_register(reg, result);
1053 self.update_flags_not(a, result);
1054 }
1055 Bytecode::ShiftLeft => {
1056 let reg1 = self.read_operand(self.instruction_pointer)?;
1058 let reg2 = self.read_operand(self.instruction_pointer)?;
1059
1060 let original = self.read_register(reg1);
1061 let shift_count = self.read_register(reg2) & SHIFT_MASK;
1062
1063 let (result, carry_out) = self.shift_left(original, shift_count);
1064 self.write_register(reg1, result);
1065
1066 self.update_flags_shl(original, result, carry_out, shift_count);
1068
1069 if self.verbose {
1070 println!(
1071 "SHL R{}({:#x}), R{}({}) => {:#x}, CF={}",
1072 reg1, original, reg2, shift_count, result, carry_out
1073 );
1074 }
1075 }
1076 Bytecode::ShiftLeftValue => {
1077 let reg1 = self.read_operand(self.instruction_pointer)?;
1079 let imm = self.read_operand(self.instruction_pointer)?; let original = self.read_register(reg1);
1082 let shift_count = imm & SHIFT_MASK;
1083
1084 let (result, carry_out) = self.shift_left(original, shift_count);
1085 self.write_register(reg1, result);
1086
1087 self.update_flags_shl(original, result, carry_out, shift_count);
1089
1090 if self.verbose {
1091 println!(
1092 "SHL R{}({:#x}), #{} => {:#x}, CF={}",
1093 reg1, original, shift_count, result, carry_out
1094 );
1095 }
1096 }
1097 Bytecode::ShiftRight => {
1098 let reg1 = self.read_operand(self.instruction_pointer)?;
1100 let reg2 = self.read_operand(self.instruction_pointer)?;
1101
1102 let original = self.read_register(reg1);
1103 let shift_count = self.read_register(reg2) & SHIFT_MASK;
1104
1105 let (result, carry_out) = self.shift_right(original, shift_count);
1106 self.write_register(reg1, result);
1107
1108 self.update_flags_shr(result, carry_out);
1110
1111 if self.verbose {
1112 println!(
1113 "SHR R{}({:#x}), R{}({}) => {:#x}, CF={}",
1114 reg1, original, reg2, shift_count, result, carry_out
1115 );
1116 }
1117 }
1118 Bytecode::ShiftRightValue => {
1119 let reg1 = self.read_operand(self.instruction_pointer)?;
1121 let imm = self.read_operand(self.instruction_pointer)?; let original = self.read_register(reg1);
1124 let shift_count = imm & SHIFT_MASK;
1125
1126 let (result, carry_out) = self.shift_right(original, shift_count);
1127 self.write_register(reg1, result);
1128
1129 self.update_flags_shr(result, carry_out);
1131
1132 if self.verbose {
1133 println!(
1134 "SHR R{}({:#x}), #{} => {:#x}, CF={}",
1135 reg1, original, shift_count, result, carry_out
1136 );
1137 }
1138 }
1139 Bytecode::Add => {
1140 let reg1 = self.read_operand(self.instruction_pointer)?;
1141 let reg2 = self.read_operand(self.instruction_pointer)?;
1142
1143 let a = self.read_register(reg1);
1144 let b = self.read_register(reg2);
1145 let result = a.wrapping_add(b);
1146
1147 if self.verbose {
1148 println!("ADD R{}({}), R{}({}) => {}", reg1, a, reg2, b, result);
1149 }
1150
1151 self.write_register(reg1, result);
1152 self.update_flags_add(a, b, result);
1153 }
1154 Bytecode::AddValue => {
1155 let reg = self.read_operand(self.instruction_pointer)?;
1156 let imm = self.read_operand(self.instruction_pointer)?;
1157
1158 let a = self.read_register(reg);
1159 let b = imm;
1160 let result = a.wrapping_add(b);
1161
1162 if self.verbose {
1163 println!("ADD R{}({}), {} => {}", reg, a, b, result);
1164 }
1165
1166 self.write_register(reg, result);
1167 self.update_flags_add(a, b, result);
1168 }
1169 Bytecode::FAdd => {
1170 let reg1 = self.read_operand(self.instruction_pointer)?;
1171 let reg2 = self.read_operand(self.instruction_pointer)?;
1172
1173 let a = f32::from_bits(self.read_register(reg1));
1174 let b = f32::from_bits(self.read_register(reg2));
1175 let result = a + b;
1176
1177 if self.verbose {
1178 println!("FADD R{}({}), R{}({}) => {}", reg1, a, reg2, b, result);
1179 }
1180
1181 self.write_register(reg1, result.to_bits());
1182 self.update_flags_float(a, b);
1183 }
1184 Bytecode::FAddValue => {
1185 let reg = self.read_operand(self.instruction_pointer)?;
1186 let imm = self.read_operand(self.instruction_pointer)?;
1187
1188 let a = f32::from_bits(self.read_register(reg));
1189 let b = f32::from_bits(imm);
1190 let result = a + b;
1191
1192 if self.verbose {
1193 println!("FADD R{}({}), {} => {}", reg, a, b, result);
1194 }
1195
1196 self.write_register(reg, result.to_bits());
1197 self.update_flags_float(a, b);
1198 }
1199 Bytecode::Sub => {
1200 let reg1 = self.read_operand(self.instruction_pointer)?;
1201 let reg2 = self.read_operand(self.instruction_pointer)?;
1202
1203 let a = self.read_register(reg1);
1204 let b = self.read_register(reg2);
1205 let result = a.wrapping_sub(b);
1206
1207 if self.verbose {
1208 println!("SUB R{}({}), R{}({}) => {}", reg1, a, reg2, b, result);
1209 }
1210
1211 self.write_register(reg1, result);
1212 self.update_flags_sub(a, b, result);
1213 }
1214 Bytecode::SubValue => {
1215 let reg = self.read_operand(self.instruction_pointer)?;
1216 let imm = self.read_operand(self.instruction_pointer)?;
1217
1218 let a = self.read_register(reg);
1219 let b = imm;
1220 let result = a.wrapping_sub(b);
1221
1222 if self.verbose {
1223 println!("SUB R{}({}), {} => {}", reg, a, b, result);
1224 }
1225
1226 self.write_register(reg, result);
1227 self.update_flags_sub(a, b, result);
1228 }
1229 Bytecode::FSub => {
1230 let reg1 = self.read_operand(self.instruction_pointer)?;
1231 let reg2 = self.read_operand(self.instruction_pointer)?;
1232
1233 let a = f32::from_bits(self.read_register(reg1));
1234 let b = f32::from_bits(self.read_register(reg2));
1235 let result = a - b;
1236
1237 if self.verbose {
1238 println!("FSUB R{}({}), R{}({}) => {}", reg1, a, reg2, b, result);
1239 }
1240
1241 self.write_register(reg1, result.to_bits());
1242 self.update_flags_float(a, b);
1243 }
1244 Bytecode::FSubValue => {
1245 let reg = self.read_operand(self.instruction_pointer)?;
1246 let imm = self.read_operand(self.instruction_pointer)?;
1247
1248 let a = f32::from_bits(self.read_register(reg));
1249 let b = f32::from_bits(imm);
1250 let result = a - b;
1251
1252 if self.verbose {
1253 println!("FSUB R{}({}), {} => {}", reg, a, b, result);
1254 }
1255
1256 self.write_register(reg, result.to_bits());
1257 self.update_flags_float(a, b);
1258 }
1259 Bytecode::Mul => {
1260 let reg1 = self.read_operand(self.instruction_pointer)?;
1261 let reg2 = self.read_operand(self.instruction_pointer)?;
1262
1263 let a = self.read_register(reg1);
1264 let b = self.read_register(reg2);
1265
1266 let wide_result = (a as u64).wrapping_mul(b as u64);
1267 let result = wide_result as u32;
1268
1269 if self.verbose {
1270 println!("MUL R{}({}), R{}({}) => {}", reg1, a, reg2, b, result);
1271 }
1272
1273 self.write_register(reg1, result);
1274 self.update_flags_mul(a, b, wide_result);
1275 }
1276 Bytecode::MulValue => {
1277 let reg = self.read_operand(self.instruction_pointer)?;
1278 let imm = self.read_operand(self.instruction_pointer)?;
1279
1280 let a = self.read_register(reg);
1281 let b = imm;
1282
1283 let wide_result = (a as u64).wrapping_mul(b as u64);
1284 let result = wide_result as u32;
1285
1286 if self.verbose {
1287 println!("MUL R{}({}), {} => {}", reg, a, b, result);
1288 }
1289
1290 self.write_register(reg, result);
1291 self.update_flags_mul(a, b, wide_result);
1292 }
1293 Bytecode::FMul => {
1294 let reg1 = self.read_operand(self.instruction_pointer)?;
1295 let reg2 = self.read_operand(self.instruction_pointer)?;
1296
1297 let a = f32::from_bits(self.read_register(reg1));
1298 let b = f32::from_bits(self.read_register(reg2));
1299 let result = a * b;
1300
1301 if self.verbose {
1302 println!("FMUL R{}({}), R{}({}) => {}", reg1, a, reg2, b, result);
1303 }
1304
1305 self.write_register(reg1, result.to_bits());
1306 self.update_flags_float(a, b);
1307 }
1308 Bytecode::FMulValue => {
1309 let reg = self.read_operand(self.instruction_pointer)?;
1310 let imm = self.read_operand(self.instruction_pointer)?;
1311
1312 let a = f32::from_bits(self.read_register(reg));
1313 let b = f32::from_bits(imm);
1314 let result = a * b;
1315
1316 if self.verbose {
1317 println!("FMUL R{}({}), {} => {}", reg, a, b, result);
1318 }
1319
1320 self.write_register(reg, result.to_bits());
1321 self.update_flags_float(a, b);
1322 }
1323 Bytecode::Div => {
1324 let reg1 = self.read_operand(self.instruction_pointer)?;
1325 let reg2 = self.read_operand(self.instruction_pointer)?;
1326
1327 let a = self.read_register(reg1);
1328 let b = self.read_register(reg2);
1329
1330 if b == 0 {
1331 return Err(ExecutionError::DivisionByZero);
1332 }
1333
1334 let result = a.wrapping_div(b);
1335
1336 if self.verbose {
1337 println!("DIV R{}({}), R{}({}) => {}", reg1, a, reg2, b, result);
1338 }
1339
1340 self.write_register(reg1, result);
1341 self.update_flags_div(a, b, result);
1342 }
1343 Bytecode::DivValue => {
1344 let reg = self.read_operand(self.instruction_pointer)?;
1345 let imm = self.read_operand(self.instruction_pointer)?;
1346
1347 let a = self.read_register(reg);
1348 let b = imm;
1349
1350 if b == 0 {
1351 return Err(ExecutionError::DivisionByZero);
1352 }
1353
1354 let result = a.wrapping_div(b);
1355
1356 if self.verbose {
1357 println!("DIV R{}({}), {} => {}", reg, a, b, result);
1358 }
1359
1360 self.write_register(reg, result);
1361 self.update_flags_div(a, b, result);
1362 }
1363 Bytecode::FDiv => {
1364 let reg1 = self.read_operand(self.instruction_pointer)?;
1365 let reg2 = self.read_operand(self.instruction_pointer)?;
1366
1367 let a = f32::from_bits(self.read_register(reg1));
1368 let b = f32::from_bits(self.read_register(reg2));
1369
1370 if b == 0.0 {
1371 return Err(ExecutionError::DivisionByZero);
1372 }
1373
1374 let result = a / b;
1375
1376 if self.verbose {
1377 println!("FDIV R{}({}), R{}({}) => {}", reg1, a, reg2, b, result);
1378 }
1379
1380 self.write_register(reg1, result.to_bits());
1381 self.update_flags_float(a, b);
1382 }
1383 Bytecode::FDivValue => {
1384 let reg = self.read_operand(self.instruction_pointer)?;
1385 let imm = self.read_operand(self.instruction_pointer)?;
1386
1387 let a = f32::from_bits(self.read_register(reg));
1388 let b = f32::from_bits(imm);
1389
1390 if b == 0.0 {
1391 return Err(ExecutionError::DivisionByZero);
1392 }
1393
1394 let result = a / b;
1395
1396 if self.verbose {
1397 println!("FDIV R{}({}), {} => {}", reg, a, b, result);
1398 }
1399
1400 self.write_register(reg, result.to_bits());
1401 self.update_flags_float(a, b);
1402 }
1403 Bytecode::LoadByte => {
1404 let reg = self.read_operand(self.instruction_pointer)?;
1405 let addr = self.read_operand(self.instruction_pointer)?;
1406
1407 let byte = self.read_byte(addr)?;
1408 self.write_register(reg, byte as u32);
1409 }
1410
1411 Bytecode::StoreByte => {
1412 let addr = self.read_operand(self.instruction_pointer)?;
1413 let reg = self.read_operand(self.instruction_pointer)?;
1414
1415 let value = (self.read_register(reg) & 0xFF) as u8;
1416 self.write_byte(addr, value)?;
1417 }
1418 Bytecode::Cmp => {
1419 let reg1 = self.read_operand(self.instruction_pointer)?;
1420 let reg2 = self.read_operand(self.instruction_pointer)?;
1421
1422 let a = self.read_register(reg1);
1423 let b = self.read_register(reg2);
1424
1425 let result = a.wrapping_sub(b);
1426
1427 if self.verbose {
1428 println!(
1429 "CMP R{}({}), R{}({}) => (flags updated for {} - {})",
1430 reg1, a, reg2, b, a, b
1431 );
1432 }
1433
1434 self.update_flags_sub(a, b, result);
1435 }
1436
1437 Bytecode::CmpValue => {
1438 let reg = self.read_operand(self.instruction_pointer)?;
1439 let imm = self.read_operand(self.instruction_pointer)?;
1440
1441 let a = self.read_register(reg);
1442 let b = imm;
1443
1444 let result = a.wrapping_sub(b);
1445
1446 if self.verbose {
1447 println!(
1448 "CMP R{}({}), {} => (flags updated for {} - {})",
1449 reg, a, b, a, b
1450 );
1451 }
1452
1453 self.update_flags_sub(a, b, result);
1454 }
1455 Bytecode::FCmp => {
1456 let reg1 = self.read_operand(self.instruction_pointer)?;
1457 let reg2 = self.read_operand(self.instruction_pointer)?;
1458
1459 let a = f32::from_bits(self.read_register(reg1));
1460 let b = f32::from_bits(self.read_register(reg2));
1461
1462 if self.verbose {
1463 println!(
1464 "FCMP R{}({}), R{}({}) => (flags updated for {} - {})",
1465 reg1, a, reg2, b, a, b
1466 );
1467 }
1468
1469 self.update_flags_float(a, b);
1470 }
1471 Bytecode::FCmpValue => {
1472 let reg = self.read_operand(self.instruction_pointer)?;
1473 let imm = self.read_operand(self.instruction_pointer)?;
1474
1475 let a = f32::from_bits(self.read_register(reg));
1476 let b = f32::from_bits(imm);
1477
1478 if self.verbose {
1479 println!(
1480 "FCMP R{}({}), {} => (flags updated for {} - {})",
1481 reg, a, b, a, b
1482 );
1483 }
1484
1485 self.update_flags_float(a, b);
1486 }
1487 Bytecode::Jmp => {
1488 let imm = self.read_operand(self.instruction_pointer)?;
1489
1490 if self.verbose {
1491 println!("JMP {}", imm);
1492 }
1493 self.instruction_pointer = imm;
1494 }
1495 Bytecode::Je
1496 | Bytecode::Jne
1497 | Bytecode::Jg
1498 | Bytecode::Jge
1499 | Bytecode::Jl
1500 | Bytecode::Jle
1501 | Bytecode::Ja
1502 | Bytecode::Jae
1503 | Bytecode::Jb
1504 | Bytecode::Jbe
1505 | Bytecode::Jc
1506 | Bytecode::Jnc
1507 | Bytecode::Jo
1508 | Bytecode::Jno
1509 | Bytecode::Js
1510 | Bytecode::Jns
1511 | Bytecode::Jxcz => {
1512 let imm = self.read_operand(self.instruction_pointer)?;
1513
1514 if self.should_jump(opcode) {
1515 if self.verbose {
1516 println!("CONDITIONAL JUMP ({opcode}) to {imm}");
1517 }
1518 self.instruction_pointer = imm;
1519 } else if self.verbose {
1520 println!("CONDITIONAL JUMP ({opcode}) not taken");
1521 }
1522 }
1523 Bytecode::Call => {
1524 let target = self.read_operand(self.instruction_pointer)?;
1525
1526 if self.verbose {
1527 if self.addresses_as_integers {
1528 println!("CALL @{target}");
1529 } else {
1530 println!("CALL @{target:#02x}");
1531 }
1532 }
1533
1534 self.push_stack(self.instruction_pointer)?;
1535
1536 self.instruction_pointer = target;
1537 }
1538 Bytecode::Ret => {
1539 let return_address = self.pop_stack()?;
1540
1541 if self.verbose {
1542 if self.addresses_as_integers {
1543 println!("RET to @{return_address}");
1544 } else {
1545 println!("RET to @{return_address:#02x}");
1546 }
1547 }
1548
1549 self.instruction_pointer = return_address;
1550 }
1551 Bytecode::Syscall => {
1552 let code = self.read_register(1);
1553 if self.verbose {
1554 println!("SYSCALL code={}", code);
1555 }
1556
1557 if let Some(mut host_io) = self.host_io.take() {
1558 let return_value = host_io.syscall(code, self)?;
1559 self.stats.cycles += return_value;
1560 self.host_io.replace(host_io);
1561 } else {
1562 return Err(ExecutionError::NoHostIO);
1563 }
1564 }
1565 Bytecode::Inspect => {
1566 let addr = self.read_operand(self.instruction_pointer)?;
1567
1568 if self.addresses_as_integers {
1569 println!("INSPECT @{} = {}", addr, self.read_memory(addr)?);
1570 } else {
1571 println!("INSPECT @{:#02x} = {}", addr, self.read_memory(addr)?);
1572 }
1573 }
1574 Bytecode::Halt => {
1575 self.set_halted(true);
1576 if self.verbose {
1577 println!("HALT");
1578 }
1579 break;
1580 }
1581 }
1582
1583 self.stats.cycles += Self::update_cycles(opcode);
1584
1585 executed += 1;
1586 }
1587 Ok(self.stats)
1588 }
1589
1590 fn update_cycles(opcode: Bytecode) -> usize {
1591 match opcode {
1592 Bytecode::Nop
1593 | Bytecode::LoadFromRegMemory
1594 | Bytecode::StoreAtReg
1595 | Bytecode::StoreValueAtReg
1596 | Bytecode::LoadValue
1597 | Bytecode::LoadMemory
1598 | Bytecode::LoadReg
1599 | Bytecode::Store
1600 | Bytecode::StoreValue
1601 | Bytecode::PushValue
1602 | Bytecode::PushReg
1603 | Bytecode::Pop
1604 | Bytecode::And
1605 | Bytecode::AndValue
1606 | Bytecode::Or
1607 | Bytecode::OrValue
1608 | Bytecode::Xor
1609 | Bytecode::XorValue
1610 | Bytecode::Not
1611 | Bytecode::ShiftLeft
1612 | Bytecode::ShiftLeftValue
1613 | Bytecode::ShiftRight
1614 | Bytecode::ShiftRightValue
1615 | Bytecode::Add
1616 | Bytecode::AddValue
1617 | Bytecode::Sub
1618 | Bytecode::SubValue
1619 | Bytecode::Cmp
1620 | Bytecode::CmpValue
1621 | Bytecode::Jmp => 1,
1622 Bytecode::LoadByte
1623 | Bytecode::StoreByte
1624 | Bytecode::FCmp
1625 | Bytecode::FCmpValue
1626 | Bytecode::Je
1627 | Bytecode::Jne
1628 | Bytecode::Jg
1629 | Bytecode::Jge
1630 | Bytecode::Jl
1631 | Bytecode::Jle
1632 | Bytecode::Ja
1633 | Bytecode::Jae
1634 | Bytecode::Jb
1635 | Bytecode::Jbe
1636 | Bytecode::Jc
1637 | Bytecode::Jnc
1638 | Bytecode::Jo
1639 | Bytecode::Jno
1640 | Bytecode::Js
1641 | Bytecode::Jns
1642 | Bytecode::Jxcz
1643 | Bytecode::FSub
1644 | Bytecode::FSubValue
1645 | Bytecode::FAdd
1646 | Bytecode::FAddValue => 2,
1647 Bytecode::Mul | Bytecode::MulValue | Bytecode::FMul | Bytecode::FMulValue => 4,
1648 Bytecode::Ret => 5,
1649 Bytecode::Call => 25,
1650 Bytecode::Div | Bytecode::DivValue | Bytecode::FDiv | Bytecode::FDivValue => 27,
1651 Bytecode::Syscall | Bytecode::Inspect | Bytecode::Halt => 0,
1652 }
1653 }
1654
1655 fn valid_address(&self, address: u32) -> Result<(), ExecutionError> {
1656 if (address as usize) < self.memory.len() {
1657 Ok(())
1658 } else {
1659 Err(ExecutionError::InvalidMemoryLocation(address))
1660 }
1661 }
1662
1663 fn push_stack(&mut self, value: u32) -> Result<(), ExecutionError> {
1664 if self.stack_pointer == 0 {
1665 return Err(ExecutionError::StackOverflow);
1666 }
1667
1668 self.write_memory(self.stack_pointer, value)?;
1669 self.stack_pointer -= 1;
1670 Ok(())
1671 }
1672
1673 fn pop_stack(&mut self) -> Result<u32, ExecutionError> {
1674 if self.stack_pointer as usize >= self.memory.len() - 1 {
1675 return Err(ExecutionError::StackUnderflow);
1676 }
1677
1678 self.stack_pointer += 1;
1679 self.read_memory(self.stack_pointer)
1680 }
1681}
1682
1683#[cfg(test)]
1684mod tests {
1685 use super::*;
1686
1687 fn run_program(program: &[u32], memory_size: u32, registers: u8) -> NativeCpu<NullHostIO> {
1688 let mut cpu = NativeCpu::new(memory_size, registers, NullHostIO);
1689 cpu.load_protected_memory(0, program);
1690 cpu.execute(RunMode::Run).unwrap();
1691 cpu
1692 }
1693
1694 #[test]
1695 fn test_nop() {
1696 let program = &[Bytecode::Nop as u32, Bytecode::Halt as u32];
1697
1698 let cpu = run_program(program, 128, 4);
1699 assert_eq!(cpu.instruction_pointer, 2);
1700 }
1701
1702 #[test]
1703 fn test_load_value() {
1704 let program = &[
1705 Bytecode::LoadValue as u32,
1706 1, 42, Bytecode::Halt as u32,
1709 ];
1710
1711 let cpu = run_program(program, 128, 4);
1712 assert_eq!(cpu.get_registers()[1], 42);
1713 }
1714
1715 #[test]
1716 fn test_add() {
1717 let program = &[
1718 Bytecode::LoadValue as u32,
1719 1,
1720 5, Bytecode::LoadValue as u32,
1722 2,
1723 10, Bytecode::Add as u32,
1725 1,
1726 2, Bytecode::Halt as u32,
1728 ];
1729
1730 let cpu = run_program(program, 128, 4);
1731 assert_eq!(cpu.get_registers()[1], 15);
1732 assert!(!cpu.flags.zero);
1733 }
1734
1735 #[test]
1736 fn test_sub() {
1737 let program = &[
1738 Bytecode::LoadValue as u32,
1739 1,
1740 10, Bytecode::LoadValue as u32,
1742 2,
1743 5, Bytecode::Sub as u32,
1745 1,
1746 2, Bytecode::Halt as u32,
1748 ];
1749
1750 let cpu = run_program(program, 128, 4);
1751 assert_eq!(cpu.get_registers()[1], 5);
1752 assert!(!cpu.flags.zero);
1753 assert!(!cpu.flags.sign);
1754 }
1755
1756 #[test]
1757 fn test_mul() {
1758 let program = &[
1759 Bytecode::LoadValue as u32,
1760 1,
1761 6, Bytecode::LoadValue as u32,
1763 2,
1764 7, Bytecode::Mul as u32,
1766 1,
1767 2, Bytecode::Halt as u32,
1769 ];
1770
1771 let cpu = run_program(program, 128, 4);
1772 assert_eq!(cpu.get_registers()[1], 42);
1773 }
1774
1775 #[test]
1776 fn test_div() {
1777 let program = &[
1778 Bytecode::LoadValue as u32,
1779 1,
1780 42,
1781 Bytecode::LoadValue as u32,
1782 2,
1783 6,
1784 Bytecode::Div as u32,
1785 1,
1786 2, Bytecode::Halt as u32,
1788 ];
1789
1790 let cpu = run_program(program, 128, 4);
1791 assert_eq!(cpu.get_registers()[1], 7);
1792 }
1793
1794 #[test]
1795 fn test_write_r0() {
1796 let program = &[Bytecode::LoadValue as u32, 0, 42, Bytecode::Halt as u32];
1797
1798 let cpu = run_program(program, 128, 4);
1799 assert_eq!(cpu.get_registers()[0], 0);
1800 }
1801
1802 #[test]
1803 fn test_cmp_je() {
1804 let program = &[
1805 Bytecode::LoadValue as u32,
1806 1,
1807 5,
1808 Bytecode::LoadValue as u32,
1809 2,
1810 5,
1811 Bytecode::Cmp as u32,
1812 1,
1813 2,
1814 Bytecode::Je as u32,
1815 15,
1816 Bytecode::LoadValue as u32,
1817 3,
1818 100, Bytecode::Halt as u32,
1820 Bytecode::LoadValue as u32,
1822 3,
1823 999,
1824 Bytecode::Halt as u32,
1825 ];
1826
1827 let cpu = run_program(program, 128, 4);
1828 assert_eq!(cpu.get_registers()[3], 999);
1829 }
1830
1831 #[test]
1832 fn test_stack_operations() {
1833 let program = &[
1834 Bytecode::PushValue as u32,
1835 42, Bytecode::Pop as u32,
1837 1, Bytecode::PushValue as u32,
1839 10, Bytecode::PushValue as u32,
1841 20, Bytecode::Pop as u32,
1843 2, Bytecode::Pop as u32,
1845 3, Bytecode::Halt as u32,
1847 ];
1848
1849 let cpu = run_program(program, 128, 4);
1850 let registers = cpu.get_registers();
1851 assert_eq!(registers[1], 42);
1852 assert_eq!(registers[2], 20);
1853 assert_eq!(registers[3], 10);
1854 }
1855
1856 #[test]
1857 fn test_store_load_memory() {
1858 let program = &[
1859 Bytecode::LoadValue as u32,
1860 1,
1861 123, Bytecode::Store as u32,
1863 50,
1864 1, Bytecode::LoadMemory as u32,
1866 2,
1867 50, Bytecode::Halt as u32,
1869 ];
1870
1871 let cpu = run_program(program, 128, 4);
1872 let registers = cpu.get_registers();
1873 assert_eq!(registers[2], 123);
1874 assert_eq!(cpu.get_memory()[50], 123);
1875 }
1876
1877 #[derive(Debug)]
1878 struct TestHostIO {
1879 pub calls: Vec<(u32, u32, u32)>,
1880 }
1881
1882 impl HostIO for TestHostIO {
1883 fn syscall(
1884 &mut self,
1885 code: u32,
1886 cpu: &mut NativeCpu<Self>,
1887 ) -> Result<usize, ExecutionError> {
1888 let arg1 = cpu.registers.get(2).copied().unwrap_or(0);
1889 let arg2 = cpu.registers.get(3).copied().unwrap_or(0);
1890 self.calls.push((code, arg1, arg2));
1891 Ok(0)
1892 }
1893 }
1894
1895 fn run_program_with_host<IO: HostIO>(
1896 program: &[u32],
1897 memory_size: u32,
1898 registers: u8,
1899 host_io: IO,
1900 ) -> NativeCpu<IO> {
1901 let mut cpu = NativeCpu::new(memory_size, registers, host_io);
1902 cpu.load_protected_memory(0, program);
1903 cpu.execute(RunMode::Run).unwrap();
1904 cpu
1905 }
1906
1907 #[test]
1908 fn test_syscall() {
1909 let program = &[
1910 Bytecode::LoadValue as u32,
1911 1,
1912 1, Bytecode::LoadValue as u32,
1914 2,
1915 123, Bytecode::LoadValue as u32,
1917 3,
1918 456, Bytecode::Syscall as u32,
1920 Bytecode::Halt as u32,
1921 ];
1922
1923 let cpu = run_program_with_host(program, 128, 8, TestHostIO { calls: vec![] });
1924
1925 assert_eq!(cpu.host_io.as_ref().unwrap().calls.len(), 1);
1926 assert_eq!(cpu.host_io.as_ref().unwrap().calls[0], (1, 123, 456));
1927 }
1928
1929 #[test]
1930 fn test_load_store_byte() {
1931 let program = &[
1932 Bytecode::LoadValue as u32,
1933 1,
1934 42, Bytecode::StoreByte as u32,
1936 10,
1937 1, Bytecode::LoadByte as u32,
1939 2,
1940 10, Bytecode::Halt as u32,
1942 ];
1943
1944 let cpu = run_program(program, 1024, 8);
1945
1946 assert_eq!(cpu.get_registers()[2], 42);
1947 }
1948
1949 #[test]
1950 fn test_load_float() {
1951 let f_val = 1.5f32.to_bits();
1952 let program = &[Bytecode::LoadValue as u32, 1, f_val, Bytecode::Halt as u32];
1953
1954 let cpu = run_program(program, 128, 8);
1955 let result_bits = cpu.get_registers()[1];
1956 let result_float = f32::from_bits(result_bits);
1957
1958 assert!((result_float - 1.5).abs() < 1e-7);
1959 }
1960
1961 #[test]
1962 fn test_fadd() {
1963 let f1 = 1.5f32.to_bits();
1964 let f2 = 2.5f32.to_bits();
1965 let program = &[
1966 Bytecode::LoadValue as u32,
1967 1,
1968 f1, Bytecode::LoadValue as u32,
1970 2,
1971 f2, Bytecode::FAdd as u32,
1973 1,
1974 2, Bytecode::Halt as u32,
1976 ];
1977
1978 let cpu = run_program(program, 128, 8);
1979 let result_float = f32::from_bits(cpu.get_registers()[1]);
1980
1981 assert!((result_float - 4.0).abs() < 1e-7);
1982 }
1983
1984 #[test]
1985 fn test_fsub() {
1986 let f5 = 5.0f32.to_bits();
1987 let f3 = 3.0f32.to_bits();
1988 let program = &[
1989 Bytecode::LoadValue as u32,
1990 1,
1991 f5,
1992 Bytecode::LoadValue as u32,
1993 2,
1994 f3,
1995 Bytecode::FSub as u32,
1996 1,
1997 2,
1998 Bytecode::Halt as u32,
1999 ];
2000
2001 let cpu = run_program(program, 128, 8);
2002 let result = f32::from_bits(cpu.get_registers()[1]);
2003
2004 assert!((result - 2.0).abs() < 1e-7);
2005 }
2006
2007 #[test]
2008 fn test_fmul() {
2009 let f2 = 2.0f32.to_bits();
2010 let f3_5 = 3.5f32.to_bits();
2011 let program = &[
2012 Bytecode::LoadValue as u32,
2013 1,
2014 f2,
2015 Bytecode::LoadValue as u32,
2016 2,
2017 f3_5,
2018 Bytecode::FMul as u32,
2019 1,
2020 2,
2021 Bytecode::Halt as u32,
2022 ];
2023
2024 let cpu = run_program(program, 128, 8);
2025 let result = f32::from_bits(cpu.get_registers()[1]);
2026
2027 assert!((result - 7.0).abs() < 1e-7);
2028 }
2029
2030 #[test]
2031 fn test_fdiv() {
2032 let f10 = 10.0f32.to_bits();
2033 let f2 = 2.0f32.to_bits();
2034 let program = &[
2035 Bytecode::LoadValue as u32,
2036 1,
2037 f10,
2038 Bytecode::LoadValue as u32,
2039 2,
2040 f2,
2041 Bytecode::FDiv as u32,
2042 1,
2043 2,
2044 Bytecode::Halt as u32,
2045 ];
2046
2047 let cpu = run_program(program, 128, 8);
2048 let result = f32::from_bits(cpu.get_registers()[1]);
2049
2050 assert!((result - 5.0).abs() < 1e-7);
2051 }
2052
2053 #[test]
2054 fn test_shift_left_register() {
2055 let program = &[
2070 Bytecode::LoadValue as u32,
2071 1,
2072 0x80000001, Bytecode::LoadValue as u32,
2074 2,
2075 1, Bytecode::ShiftLeft as u32,
2077 1,
2078 2, Bytecode::Halt as u32,
2080 ];
2081
2082 let cpu = run_program(program, 128, 4);
2083 let registers = cpu.get_registers();
2084
2085 assert_eq!(
2087 registers[1], 0x00000002,
2088 "R1 should have been shifted left by 1"
2089 );
2090
2091 assert!(!cpu.flags.zero, "0x2 is not zero");
2093 assert!(!cpu.flags.sign, "0x2 has no sign bit set");
2094 assert!(cpu.flags.carry, "Should carry out the top bit 1");
2095 assert!(
2096 cpu.flags.overflow,
2097 "Shifting MSB out with shift=1 => overflow set"
2098 );
2099 }
2100
2101 #[test]
2102 fn test_shift_left_value() {
2103 let program = &[
2114 Bytecode::LoadValue as u32,
2115 1,
2116 0x00000001,
2117 Bytecode::ShiftLeftValue as u32,
2118 1,
2119 4,
2120 Bytecode::Halt as u32,
2121 ];
2122
2123 let cpu = run_program(program, 128, 4);
2124 let registers = cpu.get_registers();
2125
2126 assert_eq!(registers[1], 0x10, "R1 = 1 << 4 should be 0x10");
2127
2128 assert!(!cpu.flags.zero);
2130 assert!(!cpu.flags.sign);
2131 assert!(!cpu.flags.carry, "No high bit was lost shifting 0x1 by 4");
2132 assert!(!cpu.flags.overflow);
2134 }
2135
2136 #[test]
2137 fn test_shift_right_register() {
2138 let program = &[
2150 Bytecode::LoadValue as u32,
2151 1,
2152 0x000000FF,
2153 Bytecode::LoadValue as u32,
2154 2,
2155 4,
2156 Bytecode::ShiftRight as u32,
2157 1,
2158 2,
2159 Bytecode::Halt as u32,
2160 ];
2161
2162 let cpu = run_program(program, 128, 4);
2163 let registers = cpu.get_registers();
2164
2165 assert_eq!(registers[1], 0x0000000F);
2166
2167 assert!(!cpu.flags.zero);
2169 assert!(!cpu.flags.sign);
2170 assert!(cpu.flags.carry, "The last bit shifted out was 1");
2171 assert!(!cpu.flags.overflow);
2172 }
2173
2174 #[test]
2175 fn test_shift_right_value_zero_flag() {
2176 let program = &[
2192 Bytecode::LoadValue as u32,
2193 1,
2194 0x1,
2195 Bytecode::ShiftRightValue as u32,
2197 1,
2198 1,
2199 Bytecode::ShiftRightValue as u32,
2201 1,
2202 1,
2203 Bytecode::Halt as u32,
2204 ];
2205
2206 let cpu = run_program(program, 128, 4);
2207 let registers = cpu.get_registers();
2208
2209 assert_eq!(registers[1], 0x0, "Final shift result is 0");
2210 assert!(cpu.flags.zero, "Result is zero");
2211 assert!(!cpu.flags.sign, "0 not negative");
2212 assert!(!cpu.flags.carry, "Second shift from 0 => carry=0");
2213 assert!(!cpu.flags.overflow);
2214 }
2215}