Skip to main content

hecate_common/
native.rs

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; // Example: 8, 16, 32, or 64, etc.
21
22// Calculate how many bits we need to mask off for shifting
23// e.g. 32.trailing_zeros() = 5; 64.trailing_zeros() = 6
24const SHIFT_BITS: u32 = REGISTER_WIDTH.trailing_zeros();
25
26// Then your mask is (1 << SHIFT_BITS) - 1
27const 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            // Hit. Move line to front for LRU policy
67            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        // Evict LRU (end of vector)
80        let mut evict_line = set.pop().unwrap();
81        evict_line.valid = true;
82        evict_line.tag = tag;
83
84        // Insert as MRU
85        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        // Default: do nothing
125        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    /// Perform a logical left shift by `count` bits, returning (new_value, carry_bit).
260    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        // The carry bit is the leftmost bit that gets shifted out:
266        let carry_out = ((value >> (32 - shift)) & 1) == 1;
267        let result = value.wrapping_shl(shift);
268        (result, carry_out)
269    }
270
271    /// Perform a logical right shift by `count` bits, returning (new_value, carry_bit).
272    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        // The carry bit is the rightmost bit that gets shifted out:
278        let carry_out = ((value >> (shift - 1)) & 1) == 1;
279        let result = value.wrapping_shr(shift);
280        (result, carry_out)
281    }
282
283    /// Update flags after a logical left shift.
284    /// If shift_count == 1, we follow x86-like semantics: Overflow is set if MSB changed.
285    /// Otherwise, we clear overflow.
286    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        // Overflow: if shifting by 1, check if the sign bit changed
292        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    /// Update flags after a logical right shift.
302    /// Typically, there's no concept of overflow for logical right shift, so we set OF=0.
303    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        // Check L1
320        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            // L1 hit
331            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        // L1 miss, check L2
342        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            // L2 hit: bring line to L1
348            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        // L2 miss, check L3
361        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            // L3 hit: bring line into L2 and L1
367            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        // Miss in all caches, fetch from memory
383        // Insert line into L3, L2, L1
384        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        // We want to detect a stable stride from recent load addresses
398        // Let's say we need at least 4 load addresses to guess a pattern.
399        if self.last_load_addresses.len() < 4 {
400            self.stable_stride = None;
401            return;
402        }
403
404        // Consider last 4 addresses to detect a pattern
405        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        // Check if strides are consistent
416        if d1 == d2 && d2 == d3 {
417            // We have a stable stride
418            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            // We ignore the cost here, as this is normally done by the hardware in the background
431            _ = self.access(next_line_address, MemoryAccessDirection::Prefetch);
432        }
433    }
434
435    fn prefetch_lines(&mut self, current_address: u32) {
436        // If no stable stride, no prefetch
437        let stride = match self.stable_stride {
438            Some(s) => s,
439            None => return,
440        };
441
442        if stride == 0 {
443            return; // no stride to prefetch
444        }
445
446        // Ensure stride moves forward. If stride is negative, we could still prefetch backwards,
447        // but we'll just handle positive stride for simplicity.
448        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            // Prefetch both lines. Treat them as loads.
455            // We ignore the cost here, as this is normally done by the hardware in the background
456            _ = 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    /// Update flags after an AND operation.
541    ///
542    /// Typical behavior:
543    /// - ZERO = (result == 0)
544    /// - SIGN = (result's most significant bit set)
545    /// - CARRY = false
546    /// - OVERFLOW = false
547    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    /// Update flags after an OR operation.
562    ///
563    /// Typical behavior:
564    /// - ZERO = (result == 0)
565    /// - SIGN = (result's most significant bit set)
566    /// - CARRY = false
567    /// - OVERFLOW = false
568    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    /// Update flags after an XOR operation.
583    ///
584    /// Typical behavior:
585    /// - ZERO = (result == 0)
586    /// - SIGN = (result's most significant bit set)
587    /// - CARRY = false
588    /// - OVERFLOW = false
589    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    /// Update flags after a NOT operation.
604    ///
605    /// Typical behavior:
606    /// - ZERO = (result == 0)
607    /// - SIGN = (result's most significant bit set)
608    /// - CARRY = false
609    /// - OVERFLOW = false
610    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        // The final value is the lower 32 bits
626        let low_result = result as u32;
627
628        // Zero flag
629        self.flags.zero = low_result == 0;
630
631        // Sign flag (check MSB of low_result)
632        self.flags.sign = (low_result as i32) < 0;
633
634        // Carry and Overflow:
635        // If the upper 32 bits of result are not zero, it means the multiplication overflowed the 32-bit range.
636        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        // Zero flag: set if result is zero
647        self.flags.zero = result == 0;
648
649        // Sign flag
650        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            // Signed conditions
657            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            // Unsigned conditions
665            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            // Other flag conditions
671            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            // Special conditions
679            Bytecode::Jxcz => {
680                let cx = self.registers.get(1).copied().unwrap_or(0);
681                cx == 0
682            }
683
684            // For all other instructions that are not conditional jumps:
685            _ => false,
686        }
687    }
688
689    fn update_flags_add(&mut self, a: u32, b: u32, result: u32) {
690        // Zero flag
691        self.flags.zero = result == 0;
692
693        // Sign flag (check MSB of result)
694        self.flags.sign = (result as i32) < 0;
695
696        // Carry flag: if unsigned addition overflows
697        let (_, c) = a.overflowing_add(b);
698        self.flags.carry = c;
699
700        // Overflow flag: check signed overflow
701        // Signed overflow occurs if (a and b have same sign) and (result differs in sign)
702        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        // Zero flag
710        self.flags.zero = result == 0;
711
712        // Sign flag
713        self.flags.sign = (result as i32) < 0;
714
715        // Carry flag for subtraction: set if there's a borrow.
716        // A borrow occurs if b > a in an unsigned sense.
717        self.flags.carry = b > a;
718
719        // Overflow flag: For subtraction, overflow occurs if the sign of a and b differ
720        // and the sign of the result differs from a.
721        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        // Zero flag: a == b (but beware NaNs: if either is NaN, a == b is false)
766        self.flags.zero = (a == b) && a.is_finite() && b.is_finite();
767
768        // Sign flag: a < b
769        self.flags.sign = a < b;
770
771        // Overflow flag: Set if a or b is not finite (NaN or Infinity)
772        self.flags.overflow = !(a.is_finite() && b.is_finite());
773
774        // Carry flag: Clear it (no meaning in floats)
775        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                    // shift R<reg1> by R<reg2> (logical left)
1057                    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                    // update flags
1067                    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                    // shift R<reg> by immediate (logical left)
1078                    let reg1 = self.read_operand(self.instruction_pointer)?;
1079                    let imm = self.read_operand(self.instruction_pointer)?; // shift amount
1080
1081                    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                    // update flags
1088                    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                    // shift R<reg1> by R<reg2> (logical right)
1099                    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                    // update flags
1109                    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                    // shift R<reg> by immediate (logical right)
1120                    let reg1 = self.read_operand(self.instruction_pointer)?;
1121                    let imm = self.read_operand(self.instruction_pointer)?; // shift amount
1122
1123                    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                    // update flags
1130                    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,  // R1
1707            42, // value
1708            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, // R1 = 5
1721            Bytecode::LoadValue as u32,
1722            2,
1723            10, // R2 = 10
1724            Bytecode::Add as u32,
1725            1,
1726            2, // R1 = R1 + R2
1727            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, // R1 = 10
1741            Bytecode::LoadValue as u32,
1742            2,
1743            5, // R2 = 5
1744            Bytecode::Sub as u32,
1745            1,
1746            2, // R1 = R1 - R2 (10-5 =5)
1747            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, // R1 = 6
1762            Bytecode::LoadValue as u32,
1763            2,
1764            7, // R2 = 7
1765            Bytecode::Mul as u32,
1766            1,
1767            2, // R1 = R1 * R2 (6*7=42)
1768            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, // R1 = R1 / R2 = 42/6 =7
1787            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, // If not equal, R3=100
1819            Bytecode::Halt as u32,
1820            // Jump target (index 15):
1821            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, // Push 42 on stack
1836            Bytecode::Pop as u32,
1837            1, // Pop into R1 => R1=42
1838            Bytecode::PushValue as u32,
1839            10, // push 10
1840            Bytecode::PushValue as u32,
1841            20, // push 20
1842            Bytecode::Pop as u32,
1843            2, // pop into R2 => R2=20
1844            Bytecode::Pop as u32,
1845            3, // pop into R3 => R3=10
1846            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, // R1=123
1862            Bytecode::Store as u32,
1863            50,
1864            1, // memory[50]=R1=123
1865            Bytecode::LoadMemory as u32,
1866            2,
1867            50, // R2=memory[50] = 123
1868            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, // R1=1 (syscall code)
1913            Bytecode::LoadValue as u32,
1914            2,
1915            123, // R2=123
1916            Bytecode::LoadValue as u32,
1917            3,
1918            456, // R3=456
1919            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, // R1=42
1935            Bytecode::StoreByte as u32,
1936            10,
1937            1, // memory[10*4]=42
1938            Bytecode::LoadByte as u32,
1939            2,
1940            10, // R2 = memory[10*4]
1941            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, // R1=1.5
1969            Bytecode::LoadValue as u32,
1970            2,
1971            f2, // R2=2.5
1972            Bytecode::FAdd as u32,
1973            1,
1974            2, // R1=R1+R2 =4.0
1975            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        // Program flow:
2056        // 1) Load R1 with 0x80000001  (has MSB set and LSB set)
2057        // 2) Load R2 with 1          (shift amount in register)
2058        // 3) ShiftLeft R1, R2       (R1 <<= R2)
2059        // 4) Halt
2060        //
2061        // Expected:
2062        //   - R1 becomes 0x00000002
2063        //   - carry flag set to true (the MSB "fell off")
2064        //   - sign flag = false (since 0x00000002 is positive)
2065        //   - zero flag = false
2066        //   - overflow flag = true, because shifting by 1 changed the MSB
2067        //     (x86-like semantics if shift == 1)
2068
2069        let program = &[
2070            Bytecode::LoadValue as u32,
2071            1,
2072            0x80000001, // R1 = 0x80000001
2073            Bytecode::LoadValue as u32,
2074            2,
2075            1, // R2 = 1
2076            Bytecode::ShiftLeft as u32,
2077            1,
2078            2, // SHL R1, R1
2079            Bytecode::Halt as u32,
2080        ];
2081
2082        let cpu = run_program(program, 128, 4);
2083        let registers = cpu.get_registers();
2084
2085        // Check R1 result
2086        assert_eq!(
2087            registers[1], 0x00000002,
2088            "R1 should have been shifted left by 1"
2089        );
2090
2091        // Check flags
2092        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        // Program flow:
2104        // 1) Load R1 with 0x00000001
2105        // 2) ShiftLeftValue R1, 4  => R1 <<= 4
2106        // 3) Halt
2107        //
2108        // Expected:
2109        //   - R1 = 0x00000010
2110        //   - carry = false, no high bits fell off
2111        //   - sign = false, zero = false, overflow = false (shift=4 won't set OF on x86-like semantics)
2112
2113        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        // Check flags
2129        assert!(!cpu.flags.zero);
2130        assert!(!cpu.flags.sign);
2131        assert!(!cpu.flags.carry, "No high bit was lost shifting 0x1 by 4");
2132        // shift=4 => overflow=0 in our design
2133        assert!(!cpu.flags.overflow);
2134    }
2135
2136    #[test]
2137    fn test_shift_right_register() {
2138        // Program flow:
2139        // 1) Load R1 with 0x000000FF
2140        // 2) Load R2 with 4
2141        // 3) ShiftRight R1, R2 => R1 >>= 4 (logical right)
2142        // 4) Halt
2143        //
2144        // Expected:
2145        //   - R1 = 0x0000000F
2146        //   - carry = bit that was shifted out (lowest 4 bits were 1111, so carry = 1 after final shift)
2147        //   - zero = false, sign = false, overflow = false (typical logical right)
2148
2149        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        // Check flags
2168        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        // Program flow:
2177        // 1) Load R1 with 0x00000001
2178        // 2) ShiftRightValue R1, 1 => R1 >>= 1
2179        // 3) ShiftRightValue R1, 1 => R1 >>= 1 again
2180        //    after two shifts, R1 = 0x00000000 => zero flag set
2181        // 4) Halt
2182        //
2183        // Expected:
2184        //   - final R1 = 0
2185        //   - zero = true
2186        //   - carry = ?  (the bit shifted out each time)
2187        //        first shift => carry=1 (LSB=1)
2188        //        second shift => carry=0 (LSB=0 from 0x00000000)
2189        //   - We'll just check final carry from the second shift (should be false)
2190
2191        let program = &[
2192            Bytecode::LoadValue as u32,
2193            1,
2194            0x1,
2195            // SHIFT RIGHT R1 by #1 => 0x1 -> 0x0 (carry=1)
2196            Bytecode::ShiftRightValue as u32,
2197            1,
2198            1,
2199            // SHIFT RIGHT R1 by #1 => 0x0 -> 0x0 (carry=0)
2200            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}