trapezoid_core/
cpu.rs

1#[cfg(feature = "debugger")]
2mod debugger;
3mod instruction;
4mod instructions_table;
5mod register;
6
7use crate::coprocessor::{Gte, SystemControlCoprocessor};
8pub use crate::memory::BusLine;
9
10pub use instruction::{Instruction, Opcode};
11pub use register::{RegisterType, Registers};
12
13#[cfg(feature = "debugger")]
14#[cfg_attr(docsrs, doc(cfg(feature = "debugger")))]
15pub use self::debugger::Debugger;
16
17#[cfg(not(feature = "debugger"))]
18struct Debugger;
19
20#[cfg(not(feature = "debugger"))]
21// dummy implementation when the debugger is disabled
22impl Debugger {
23    #[inline]
24    pub fn new() -> Self {
25        Self
26    }
27
28    #[inline]
29    pub fn paused(&self) -> bool {
30        false
31    }
32
33    #[inline]
34    pub fn last_state(&self) -> CpuState {
35        CpuState::Normal
36    }
37
38    #[inline]
39    pub fn clear_state(&mut self) {}
40
41    #[inline]
42    pub fn handle_pending_processing<P: CpuBusProvider>(
43        &mut self,
44        _bus: &mut P,
45        _regs: &Registers,
46        _jumping: bool,
47    ) {
48    }
49
50    pub fn trace_exception(&mut self, _addr: u32) {}
51
52    #[inline]
53    pub fn trace_instruction(
54        &mut self,
55        _regs: &Registers,
56        _jumping: bool,
57        _instruction: &Instruction,
58    ) -> bool {
59        false
60    }
61
62    pub fn trace_write(&mut self, _addr: u32, _bits: u8) {}
63
64    pub fn trace_read(&mut self, _addr: u32, _bits: u8) {}
65
66    pub fn call_stack(&self) -> &[u32] {
67        &[]
68    }
69}
70
71const SHELL_LOCATION: u32 = 0x80030000;
72
73/// A specific Bus that is connected to the CPU directly, where it can send Interrupt messages
74/// to it and also request DMA access.
75///
76/// The trait only tells if the device is requesting for DMA,
77/// then the implementer should handle the DMA operation as needed.
78///
79/// It's done like that so that the CPU just need to know when it should be interrupted and allow
80/// the other components to run the DMA, here, the CPU doesn't run the DMA itself.
81pub trait CpuBusProvider: BusLine {
82    fn pending_interrupts(&self) -> bool;
83    fn should_run_dma(&self) -> bool;
84}
85
86#[derive(Debug, Clone, Copy)]
87enum Exception {
88    Interrupt = 0x00,
89    AddressErrorLoad = 0x04,
90    AddressErrorStore = 0x05,
91    _BusErrorInstructionFetch = 0x06,
92    _BusErrorDataLoadStore = 0x07,
93    Syscall = 0x08,
94    Breakpoint = 0x09,
95    ReservedInstruction = 0x0A,
96    _CoprocessorUnusable = 0x0B,
97    ArithmeticOverflow = 0x0C,
98}
99
100#[derive(Debug, PartialEq, Eq, Clone, Copy)]
101pub enum CpuState {
102    /// Normal execution, no breakpoints
103    Normal,
104
105    #[cfg(feature = "debugger")]
106    #[cfg_attr(docsrs, doc(cfg(feature = "debugger")))]
107    /// Paused on an execution breakpoint, the pause happen BEFORE execution
108    InstructionBreakpoint(u32),
109
110    #[cfg(feature = "debugger")]
111    #[cfg_attr(docsrs, doc(cfg(feature = "debugger")))]
112    /// Paused on a write breakpoint, together with the value that was written
113    /// the pause happen AFTER the operation
114    WriteBreakpoint { addr: u32, bits: u8 },
115
116    #[cfg(feature = "debugger")]
117    #[cfg_attr(docsrs, doc(cfg(feature = "debugger")))]
118    /// Paused on a read breakpoint
119    /// the pause happen AFTER the operation
120    ReadBreakpoint { addr: u32, bits: u8 },
121
122    #[cfg(feature = "debugger")]
123    #[cfg_attr(docsrs, doc(cfg(feature = "debugger")))]
124    /// Paused after a single instruction was executed
125    Step,
126
127    #[cfg(feature = "debugger")]
128    #[cfg_attr(docsrs, doc(cfg(feature = "debugger")))]
129    /// Paused after a single instruction was executed, if the instruction is `Jal` or `Jalr`
130    /// which is used for function calls, the pause will happen after the function returns,
131    /// i.e. step over the function
132    StepOver,
133
134    #[cfg(feature = "debugger")]
135    #[cfg_attr(docsrs, doc(cfg(feature = "debugger")))]
136    /// Continue execution until the CPU exit the current function
137    StepOut,
138}
139
140pub struct Cpu {
141    regs: Registers,
142    cop0: SystemControlCoprocessor,
143    cop2: Gte,
144
145    jump_dest_next: Option<u32>,
146
147    elapsed_cycles: u32,
148
149    shell_reached_before: bool,
150    shell_reached_now: bool,
151    current_instr_pc: u32,
152
153    debugger: Debugger,
154}
155
156impl Cpu {
157    pub fn new() -> Self {
158        Self {
159            // reset value
160            regs: Registers::new(),
161            cop0: SystemControlCoprocessor::default(),
162            cop2: Gte::default(),
163            jump_dest_next: None,
164
165            elapsed_cycles: 0,
166            shell_reached_before: false,
167            shell_reached_now: false,
168            current_instr_pc: 0,
169
170            debugger: Debugger::new(),
171        }
172    }
173
174    pub fn reset(&mut self) {
175        self.regs = Registers::new();
176        self.cop0 = SystemControlCoprocessor::default();
177        self.cop2 = Gte::default();
178        self.jump_dest_next = None;
179        self.elapsed_cycles = 0;
180        self.shell_reached_before = false;
181        self.current_instr_pc = 0;
182    }
183
184    pub fn registers(&self) -> &Registers {
185        &self.regs
186    }
187
188    pub fn registers_mut(&mut self) -> &mut Registers {
189        &mut self.regs
190    }
191
192    #[cfg(feature = "debugger")]
193    #[cfg_attr(docsrs, doc(cfg(feature = "debugger")))]
194    pub fn debugger(&mut self) -> &mut Debugger {
195        &mut self.debugger
196    }
197
198    // Attempt to run `instructions` number of instructions
199    // it can return early depending on number of reasons, such as:
200    // - `debugger` reached a breakpoint
201    // - `bus` requested a DMA operation
202    // - shell location is reached
203    pub fn clock<P: CpuBusProvider>(&mut self, bus: &mut P, instructions: u32) -> (u32, CpuState) {
204        self.shell_reached_now = false;
205        let mut state = CpuState::Normal;
206
207        // we only need to run this only once before any instruction, as this
208        // is used to process any pending debugger commands
209        self.debugger
210            .handle_pending_processing(bus, &self.regs, self.jump_dest_next.is_some());
211
212        let pending_interrupts = bus.pending_interrupts();
213        self.check_and_execute_interrupt(pending_interrupts);
214
215        for _ in 0..instructions {
216            // notify the UI when the shell location is reached
217            if !self.shell_reached_before && self.regs.pc == SHELL_LOCATION {
218                self.shell_reached_before = true;
219                self.shell_reached_now = true;
220                log::info!("shell location reached");
221                break;
222            }
223
224            if let Some(instruction) = self.bus_read_u32(bus, self.regs.pc) {
225                let instruction = Instruction::from_u32(instruction, self.regs.pc);
226
227                self.current_instr_pc = self.regs.pc;
228
229                log::trace!(
230                    "{:08X}: {}{}",
231                    self.regs.pc,
232                    if self.jump_dest_next.is_some() {
233                        "_"
234                    } else {
235                        ""
236                    },
237                    instruction
238                );
239
240                // breakpoint hit
241                if self.debugger.trace_instruction(
242                    &self.regs,
243                    self.jump_dest_next.is_some(),
244                    &instruction,
245                ) {
246                    break;
247                }
248
249                self.regs.pc += 4;
250                if let Some(jump_dest) = self.jump_dest_next.take() {
251                    log::trace!("pc jump {:08X}", jump_dest);
252                    self.regs.pc = jump_dest;
253                }
254
255                self.execute_instruction(&instruction, bus);
256                self.regs.handle_delayed_load();
257
258                if self.debugger.paused() {
259                    break;
260                }
261
262                // exit so that we can run dma
263                // Delaying the DMA can cause problems,
264                // since if the DMA's SyncMode is `0`, it should run between
265                // CPU cycles. This means that the following execution flow doesn't have
266                // race conditions, becuase the DMA will run in between these two
267                // CPU executions:
268                // - CPU: Setup and start DMA channel 6 (SyncMode=0)
269                // - CPU: Setup and start DMA channel 6 (SyncMode=0)
270                //
271                // Thus, if we delayed the execution of DMA even for
272                // just a small amount, it would cause problems.
273                //
274                // TODO: maybe we should optimize this a bit more, so that we
275                //       won't need to check on every CPU instruction
276                if bus.should_run_dma() {
277                    break;
278                }
279            }
280        }
281
282        if self.debugger.paused() {
283            state = self.debugger.last_state();
284            self.debugger.clear_state();
285        }
286
287        (std::mem::take(&mut self.elapsed_cycles), state)
288    }
289
290    pub fn is_shell_reached(&self) -> bool {
291        self.shell_reached_now
292    }
293}
294
295impl Cpu {
296    fn execute_exception(&mut self, cause: Exception) {
297        log::info!(
298            "executing exception: {:?}, cause code: {:02X}",
299            cause,
300            cause as u8
301        );
302
303        let cause_code = cause as u8;
304
305        let old_cause = self.cop0.read_cause();
306        // remove the next jump
307        let bd = self.jump_dest_next.take().is_some();
308        let new_cause =
309            (old_cause & 0x7FFFFF00) | ((bd as u32) << 31) | ((cause_code & 0x1F) as u32) << 2;
310        self.cop0.write_cause(new_cause);
311
312        // move the current exception enable to the next position
313        let mut sr = self.cop0.read_sr();
314        let first_two_bits = sr & 3;
315        let second_two_bits = (sr >> 2) & 3;
316        sr &= !0b111111;
317        sr |= first_two_bits << 2;
318        sr |= second_two_bits << 4;
319        self.cop0.write_sr(sr);
320
321        let bev = (sr >> 22) & 1 == 1;
322
323        let jmp_vector = if bev { 0xBFC00180 } else { 0x80000080 };
324
325        // TODO: check the written value to EPC
326        let target_pc = match cause {
327            Exception::Interrupt => {
328                if bd {
329                    // execute branch again
330                    self.regs.pc - 4
331                } else {
332                    self.regs.pc
333                }
334            }
335            _ => self.regs.pc - 4,
336        };
337
338        self.cop0.write_epc(target_pc);
339        self.regs.pc = jmp_vector;
340        self.regs.flush_delayed_load();
341        self.debugger.trace_exception(target_pc);
342    }
343
344    fn check_and_execute_interrupt(&mut self, pending_interrupts: bool) {
345        let sr = self.cop0.read_sr();
346        // cause.10 is not a latch, so it should be updated continually
347        let new_cause = (self.cop0.read_cause() & !0x400) | ((pending_interrupts as u32) << 10);
348        self.cop0.write_cause(new_cause);
349
350        // cause.10 is set and sr.10 and sr.0 are set, then execute the interrupt
351        if pending_interrupts && (sr & 0x401 == 0x401) {
352            self.execute_exception(Exception::Interrupt);
353        }
354    }
355
356    fn sign_extend_16(data: u16) -> u32 {
357        data as i16 as i32 as u32
358    }
359
360    fn sign_extend_8(data: u8) -> u32 {
361        data as i8 as i32 as u32
362    }
363
364    #[inline]
365    fn execute_alu_reg<F>(&mut self, instruction: &Instruction, handler: F)
366    where
367        F: FnOnce(u32, u32) -> (u32, bool),
368    {
369        let rs = self.regs.read_general(instruction.rs_raw);
370        let rt = self.regs.read_general(instruction.rt_raw);
371
372        let (result, overflow) = handler(rs, rt);
373        if overflow {
374            self.execute_exception(Exception::ArithmeticOverflow);
375        } else {
376            self.regs.write_general(instruction.rd_raw, result);
377        }
378    }
379
380    #[inline]
381    fn execute_alu_imm<F>(&mut self, instruction: &Instruction, handler: F)
382    where
383        F: FnOnce(u32, &Instruction) -> u32,
384    {
385        let rs = self.regs.read_general(instruction.rs_raw);
386        let result = handler(rs, instruction);
387        self.regs.write_general(instruction.rt_raw, result);
388    }
389
390    #[inline]
391    fn execute_branch<F>(&mut self, instruction: &Instruction, have_rt: bool, handler: F)
392    where
393        F: FnOnce(i32, i32) -> bool,
394    {
395        let rs = self.regs.read_general(instruction.rs_raw) as i32;
396        let rt = if have_rt {
397            self.regs.read_general(instruction.rt_raw) as i32
398        } else {
399            0
400        };
401        let signed_imm16 = Self::sign_extend_16(instruction.imm16()).wrapping_mul(4);
402
403        let should_jump = handler(rs, rt);
404        if should_jump {
405            self.jump_dest_next = Some(self.regs.pc.wrapping_add(signed_imm16));
406        }
407    }
408
409    #[inline]
410    fn execute_load<F>(&mut self, instruction: &Instruction, mut handler: F)
411    where
412        F: FnMut(&mut Self, u32) -> Option<u32>,
413    {
414        let rs = self.regs.read_general(instruction.rs_raw);
415        let computed_addr = rs.wrapping_add(Self::sign_extend_16(instruction.imm16()));
416
417        if let Some(data) = handler(self, computed_addr) {
418            self.regs.write_delayed(instruction.rt_raw, data);
419        }
420    }
421
422    #[inline]
423    fn execute_store<F>(&mut self, instruction: &Instruction, mut handler: F)
424    where
425        F: FnMut(&mut Self, u32, u32),
426    {
427        let rs = self.regs.read_general(instruction.rs_raw);
428        let rt = self.regs.read_general(instruction.rt_raw);
429        let computed_addr = rs.wrapping_add(Self::sign_extend_16(instruction.imm16()));
430
431        handler(self, computed_addr, rt);
432    }
433
434    fn execute_instruction<P: CpuBusProvider>(&mut self, instruction: &Instruction, bus: &mut P) {
435        match instruction.opcode {
436            Opcode::Nop => {
437                // nothing
438            }
439            Opcode::Lb => {
440                self.execute_load(instruction, |s, computed_addr| {
441                    Some(Self::sign_extend_8(s.bus_read_u8(bus, computed_addr)))
442                });
443            }
444            Opcode::Lbu => {
445                self.execute_load(instruction, |s, computed_addr| {
446                    Some(s.bus_read_u8(bus, computed_addr) as u32)
447                });
448            }
449            Opcode::Lh => {
450                self.execute_load(instruction, |s, computed_addr| {
451                    Some(Self::sign_extend_16(s.bus_read_u16(bus, computed_addr)?))
452                });
453            }
454            Opcode::Lhu => {
455                self.execute_load(instruction, |s, computed_addr| {
456                    Some(s.bus_read_u16(bus, computed_addr)? as u32)
457                });
458            }
459            Opcode::Lw => {
460                self.execute_load(instruction, |s, computed_addr| {
461                    s.bus_read_u32(bus, computed_addr)
462                });
463            }
464            Opcode::Lwl => {
465                // TODO: test these unaligned addressing instructions
466                let rs = self.regs.read_general(instruction.rs_raw);
467                let computed_addr = rs.wrapping_add(Self::sign_extend_16(instruction.imm16()));
468
469                // round to the nearest floor of four
470                let start = computed_addr & !3;
471                let end = computed_addr;
472                let offset = computed_addr & 3;
473                let mut result = 0;
474
475                // read the data in little endian
476                for part_addr in (start..=end).rev() {
477                    result <<= 8;
478                    result |= self.bus_read_u8(bus, part_addr) as u32;
479                }
480                // move it to the upper part
481                let shift = (3 - offset) * 8;
482                result <<= shift;
483
484                let mask = !((0xFFFFFFFF >> shift) << shift);
485                let original_rt = self.regs.read_general_latest(instruction.rt_raw);
486                let result = (original_rt & mask) | result;
487
488                self.regs.write_delayed(instruction.rt_raw, result);
489            }
490            Opcode::Lwr => {
491                let rs = self.regs.read_general(instruction.rs_raw);
492                let computed_addr = rs.wrapping_add(Self::sign_extend_16(instruction.imm16()));
493
494                let start = computed_addr;
495                let end = computed_addr | 3;
496                let offset = computed_addr & 3;
497                let mut result = 0;
498
499                // read the data in little endian
500                for part_addr in (start..=end).rev() {
501                    result <<= 8;
502                    result |= self.bus_read_u8(bus, part_addr) as u32;
503                }
504                // move it to the upper part
505                let shift = offset * 8;
506
507                let mask = !(0xFFFFFFFF >> shift);
508                let original_rt = self.regs.read_general_latest(instruction.rt_raw);
509                let result = (original_rt & mask) | result;
510
511                self.regs.write_delayed(instruction.rt_raw, result);
512            }
513            Opcode::Sb => {
514                self.execute_store(instruction, |s, computed_addr, data| {
515                    s.bus_write_u8(bus, computed_addr, data as u8)
516                });
517            }
518            Opcode::Sh => {
519                self.execute_store(instruction, |s, computed_addr, data| {
520                    s.bus_write_u16(bus, computed_addr, data as u16)
521                });
522            }
523            Opcode::Sw => {
524                self.execute_store(instruction, |s, computed_addr, data| {
525                    s.bus_write_u32(bus, computed_addr, data)
526                });
527            }
528            Opcode::Swl => {
529                let rs = self.regs.read_general(instruction.rs_raw);
530                let mut rt = self.regs.read_general(instruction.rt_raw);
531                let computed_addr = rs.wrapping_add(Self::sign_extend_16(instruction.imm16()));
532
533                // round to the nearest floor of four
534                let start = computed_addr & !3;
535                let end = computed_addr;
536                let offset = computed_addr & 3;
537
538                // move it from the upper part
539                let shift = (3 - offset) * 8;
540                rt >>= shift;
541
542                // write the data in little endian
543                for part_addr in start..=end {
544                    self.bus_write_u8(bus, part_addr, rt as u8);
545                    rt >>= 8;
546                }
547            }
548            Opcode::Swr => {
549                let rs = self.regs.read_general(instruction.rs_raw);
550                let mut rt = self.regs.read_general(instruction.rt_raw);
551                let computed_addr = rs.wrapping_add(Self::sign_extend_16(instruction.imm16()));
552
553                let start = computed_addr;
554                let end = computed_addr | 3;
555
556                // write the data in little endian
557                for part_addr in start..=end {
558                    self.bus_write_u8(bus, part_addr, rt as u8);
559                    rt >>= 8;
560                }
561            }
562            Opcode::Slt => {
563                let rs = self.regs.read_general(instruction.rs_raw) as i32;
564                let rt = self.regs.read_general(instruction.rt_raw) as i32;
565
566                self.regs
567                    .write_general(instruction.rd_raw, (rs < rt) as u32);
568            }
569            Opcode::Sltu => {
570                let rs = self.regs.read_general(instruction.rs_raw);
571                let rt = self.regs.read_general(instruction.rt_raw);
572
573                self.regs
574                    .write_general(instruction.rd_raw, (rs < rt) as u32);
575            }
576            Opcode::Slti => {
577                let rs = self.regs.read_general(instruction.rs_raw) as i32;
578                let imm = instruction.imm16() as i16 as i32;
579
580                self.regs
581                    .write_general(instruction.rt_raw, (rs < imm) as u32);
582            }
583            Opcode::Sltiu => {
584                let rs = self.regs.read_general(instruction.rs_raw);
585                let imm = Self::sign_extend_16(instruction.imm16());
586
587                self.regs
588                    .write_general(instruction.rt_raw, (rs < imm) as u32);
589            }
590            Opcode::Addu => {
591                self.execute_alu_reg(instruction, |rs, rt| (rs.wrapping_add(rt), false));
592            }
593            Opcode::Add => {
594                self.execute_alu_reg(instruction, |rs, rt| {
595                    let (value, overflow) = (rs as i32).overflowing_add(rt as i32);
596                    (value as u32, overflow)
597                });
598            }
599            Opcode::Subu => {
600                self.execute_alu_reg(instruction, |rs, rt| (rs.wrapping_sub(rt), false));
601            }
602            Opcode::Sub => {
603                self.execute_alu_reg(instruction, |rs, rt| {
604                    let (value, overflow) = (rs as i32).overflowing_sub(rt as i32);
605                    (value as u32, overflow)
606                });
607            }
608            Opcode::Addiu => {
609                self.execute_alu_imm(instruction, |rs, instr| {
610                    rs.wrapping_add(Self::sign_extend_16(instr.imm16()))
611                });
612            }
613            Opcode::Addi => {
614                let rs = self.regs.read_general(instruction.rs_raw);
615                let (result, overflow) =
616                    (rs as i32).overflowing_add(Self::sign_extend_16(instruction.imm16()) as i32);
617
618                if overflow {
619                    self.execute_exception(Exception::ArithmeticOverflow);
620                } else {
621                    self.regs.write_general(instruction.rt_raw, result as u32);
622                }
623            }
624            Opcode::And => {
625                self.execute_alu_reg(instruction, |rs, rt| (rs & rt, false));
626            }
627            Opcode::Or => {
628                self.execute_alu_reg(instruction, |rs, rt| (rs | rt, false));
629            }
630            Opcode::Xor => {
631                self.execute_alu_reg(instruction, |rs, rt| (rs ^ rt, false));
632            }
633            Opcode::Nor => {
634                self.execute_alu_reg(instruction, |rs, rt| (!(rs | rt), false));
635            }
636            Opcode::Andi => {
637                self.execute_alu_imm(instruction, |rs, instr| rs & (instr.imm16() as u32));
638            }
639            Opcode::Ori => {
640                self.execute_alu_imm(instruction, |rs, instr| rs | (instr.imm16() as u32));
641            }
642            Opcode::Xori => {
643                self.execute_alu_imm(instruction, |rs, instr| rs ^ (instr.imm16() as u32));
644            }
645            Opcode::Sllv => {
646                self.execute_alu_reg(instruction, |rs, rt| (rt << (rs & 0x1F), false));
647            }
648            Opcode::Srlv => {
649                self.execute_alu_reg(instruction, |rs, rt| (rt >> (rs & 0x1F), false));
650            }
651            Opcode::Srav => {
652                self.execute_alu_reg(instruction, |rs, rt| {
653                    (((rt as i32) >> (rs & 0x1F)) as u32, false)
654                });
655            }
656            Opcode::Sll => {
657                let rt = self.regs.read_general(instruction.rt_raw);
658                let result = rt << instruction.imm5();
659                self.regs.write_general(instruction.rd_raw, result);
660            }
661            Opcode::Srl => {
662                let rt = self.regs.read_general(instruction.rt_raw);
663                let result = rt >> instruction.imm5();
664                self.regs.write_general(instruction.rd_raw, result);
665            }
666            Opcode::Sra => {
667                let rt = self.regs.read_general(instruction.rt_raw);
668                let result = ((rt as i32) >> instruction.imm5()) as u32;
669                self.regs.write_general(instruction.rd_raw, result);
670            }
671            Opcode::Lui => {
672                let result = (instruction.imm16() as u32) << 16;
673                self.regs.write_general(instruction.rt_raw, result);
674            }
675            Opcode::Mult => {
676                self.elapsed_cycles += 5;
677                let rs = self.regs.read_general(instruction.rs_raw) as i32 as i64;
678                let rt = self.regs.read_general(instruction.rt_raw) as i32 as i64;
679
680                let result = (rs * rt) as u64;
681
682                self.regs.hi = (result >> 32) as u32;
683                self.regs.lo = result as u32;
684            }
685            Opcode::Multu => {
686                self.elapsed_cycles += 5;
687                let rs = self.regs.read_general(instruction.rs_raw) as u64;
688                let rt = self.regs.read_general(instruction.rt_raw) as u64;
689
690                let result = rs * rt;
691
692                self.regs.hi = (result >> 32) as u32;
693                self.regs.lo = result as u32;
694            }
695            Opcode::Div => {
696                self.elapsed_cycles += 10;
697                let rs = self.regs.read_general(instruction.rs_raw) as i32 as i64;
698                let rt = self.regs.read_general(instruction.rt_raw) as i32 as i64;
699
700                // division by zero (overflow)
701                if rt == 0 {
702                    self.regs.hi = rs as u32;
703                    // -1 or 1
704                    self.regs.lo = if rs >= 0 { 0xFFFFFFFF } else { 1 };
705                } else {
706                    let div = (rs / rt) as u32;
707                    let remainder = (rs % rt) as u32;
708
709                    self.regs.hi = remainder;
710                    self.regs.lo = div;
711                }
712            }
713            Opcode::Divu => {
714                self.elapsed_cycles += 10;
715                let rs = self.regs.read_general(instruction.rs_raw) as u64;
716                let rt = self.regs.read_general(instruction.rt_raw) as u64;
717
718                // division by zero
719                if rt == 0 {
720                    self.regs.hi = rs as u32;
721                    self.regs.lo = 0xFFFFFFFF;
722                } else {
723                    let div = (rs / rt) as u32;
724                    let remainder = (rs % rt) as u32;
725
726                    self.regs.hi = remainder;
727                    self.regs.lo = div;
728                }
729            }
730            Opcode::Mfhi => {
731                self.regs.write_general(instruction.rd_raw, self.regs.hi);
732            }
733            Opcode::Mthi => {
734                self.regs.hi = self.regs.read_general(instruction.rs_raw);
735            }
736            Opcode::Mflo => {
737                self.regs.write_general(instruction.rd_raw, self.regs.lo);
738            }
739            Opcode::Mtlo => {
740                self.regs.lo = self.regs.read_general(instruction.rs_raw);
741            }
742            Opcode::J => {
743                let base = self.regs.pc & 0xF0000000;
744                let offset = instruction.imm26() * 4;
745
746                self.jump_dest_next = Some(base + offset);
747            }
748            Opcode::Jal => {
749                let base = self.regs.pc & 0xF0000000;
750                let offset = instruction.imm26() * 4;
751
752                self.jump_dest_next = Some(base + offset);
753
754                self.regs.write_ra(self.regs.pc + 4);
755            }
756            Opcode::Jr => {
757                self.jump_dest_next = Some(self.regs.read_general(instruction.rs_raw));
758            }
759            Opcode::Jalr => {
760                self.jump_dest_next = Some(self.regs.read_general(instruction.rs_raw));
761
762                self.regs
763                    .write_general(instruction.rd_raw, self.regs.pc + 4);
764            }
765            Opcode::Beq => {
766                self.execute_branch(instruction, true, |rs, rt| rs == rt);
767            }
768            Opcode::Bne => {
769                self.execute_branch(instruction, true, |rs, rt| rs != rt);
770            }
771            Opcode::Bgtz => {
772                self.execute_branch(instruction, false, |rs, _| rs > 0);
773            }
774            Opcode::Blez => {
775                self.execute_branch(instruction, false, |rs, _| rs <= 0);
776            }
777            Opcode::Bltz => {
778                self.execute_branch(instruction, false, |rs, _| rs < 0);
779            }
780            Opcode::Bgez => {
781                self.execute_branch(instruction, false, |rs, _| rs >= 0);
782            }
783            Opcode::Bltzal => {
784                self.execute_branch(instruction, false, |rs, _| rs < 0);
785                // modify ra either way
786                self.regs.write_ra(self.regs.pc + 4);
787            }
788            Opcode::Bgezal => {
789                self.execute_branch(instruction, false, |rs, _| rs >= 0);
790                // modify ra either way
791                self.regs.write_ra(self.regs.pc + 4);
792            }
793            Opcode::Bcondz => unreachable!("bcondz should be converted"),
794            Opcode::Syscall => {
795                self.execute_exception(Exception::Syscall);
796            }
797            Opcode::Break => {
798                self.execute_exception(Exception::Breakpoint);
799            }
800            Opcode::Cop(n) => {
801                // the only cop0 command RFE is handled as its own opcode
802                // so we only handle cop2 commands
803                assert!(n == 2);
804
805                self.cop2.execute_command(instruction.imm25());
806            }
807            Opcode::Mfc(n) => {
808                let result = match n {
809                    0 => self.cop0.read_data(instruction.rd_raw),
810                    2 => self.cop2.read_data(instruction.rd_raw),
811                    _ => unreachable!(),
812                };
813
814                self.regs.write_general(instruction.rt_raw, result);
815            }
816            Opcode::Cfc(n) => {
817                let result = match n {
818                    0 => self.cop0.read_ctrl(instruction.rd_raw),
819                    2 => self.cop2.read_ctrl(instruction.rd_raw),
820                    _ => unreachable!(),
821                };
822
823                self.regs.write_general(instruction.rt_raw, result);
824            }
825            Opcode::Mtc(n) => {
826                let rt = self.regs.read_general(instruction.rt_raw);
827
828                match n {
829                    0 => self.cop0.write_data(instruction.rd_raw, rt),
830                    2 => self.cop2.write_data(instruction.rd_raw, rt),
831                    _ => unreachable!(),
832                }
833            }
834            Opcode::Ctc(n) => {
835                let rt = self.regs.read_general(instruction.rt_raw);
836
837                match n {
838                    0 => self.cop0.write_ctrl(instruction.rd_raw, rt),
839                    2 => self.cop2.write_ctrl(instruction.rd_raw, rt),
840                    _ => unreachable!(),
841                }
842            }
843            //Opcode::Bcf(_) => {}
844            //Opcode::Bct(_) => {}
845            Opcode::Rfe => {
846                let mut sr = self.cop0.read_sr();
847                // clear first two bits
848                let second_two_bits = (sr >> 2) & 3;
849                let third_two_bits = (sr >> 4) & 3;
850                sr &= !0b1111;
851                sr |= second_two_bits;
852                sr |= third_two_bits << 2;
853
854                self.cop0.write_sr(sr);
855            }
856            Opcode::Lwc(n) => {
857                let rs = self.regs.read_general(instruction.rs_raw);
858                let computed_addr = rs.wrapping_add(Self::sign_extend_16(instruction.imm16()));
859
860                if let Some(data) = self.bus_read_u32(bus, computed_addr) {
861                    match n {
862                        0 => self.cop0.write_data(instruction.rt_raw, data),
863                        2 => self.cop2.write_data(instruction.rt_raw, data),
864                        _ => unreachable!(),
865                    }
866                }
867            }
868            Opcode::Swc(n) => {
869                let result = match n {
870                    0 => self.cop0.read_data(instruction.rt_raw),
871                    2 => self.cop2.read_data(instruction.rt_raw),
872                    _ => unreachable!(),
873                };
874
875                self.execute_store(instruction, |s, computed_addr, _| {
876                    s.bus_write_u32(bus, computed_addr, result);
877                });
878            }
879            Opcode::Invalid => {
880                self.execute_exception(Exception::ReservedInstruction);
881            }
882            Opcode::SecondaryOpcode => unreachable!(),
883            _ => todo!("unimplemented_instruction {:?}", instruction.opcode),
884        }
885    }
886}
887
888impl Cpu {
889    fn print_call_stack(&self) {
890        let call_stack = self.debugger.call_stack();
891
892        if call_stack.is_empty() {
893            log::error!("call stack is empty");
894        } else {
895            log::error!("call stack:");
896            for (i, pc) in call_stack.iter().enumerate() {
897                log::error!("  {:02}: {:08X}", i, pc);
898            }
899        }
900    }
901
902    fn bus_read_u32<P: BusLine>(&mut self, bus: &mut P, addr: u32) -> Option<u32> {
903        self.elapsed_cycles += 2;
904
905        if addr % 4 != 0 {
906            log::error!(
907                "AddressErrorLoad(u32): {:08X} at {:08X}",
908                addr,
909                self.current_instr_pc
910            );
911            self.execute_exception(Exception::AddressErrorLoad);
912            self.cop0.write_bad_vaddr(addr);
913
914            return None;
915        }
916
917        self.debugger.trace_read(addr, 32);
918        match addr {
919            0x00000000..=0x00001000 if self.cop0.is_cache_isolated() => Some(0),
920            _ => {
921                let r = bus.read_u32(addr);
922                match r {
923                    Ok(value) => Some(value),
924                    Err(err) => {
925                        log::error!(
926                            "bus_read_u32: {:08X} at {:08X}: {}",
927                            addr,
928                            self.current_instr_pc,
929                            err
930                        );
931                        self.print_call_stack();
932                        None
933                    }
934                }
935            }
936        }
937    }
938
939    fn bus_write_u32<P: BusLine>(&mut self, bus: &mut P, addr: u32, data: u32) {
940        self.elapsed_cycles += 1;
941
942        if addr % 4 != 0 {
943            log::error!(
944                "AddressErrorStore(u32): {:08X} at {:08X}",
945                addr,
946                self.current_instr_pc
947            );
948            self.execute_exception(Exception::AddressErrorStore);
949            self.cop0.write_bad_vaddr(addr);
950        } else {
951            self.debugger.trace_write(addr, 32);
952            match addr {
953                0x00000000..=0x00001000 if self.cop0.is_cache_isolated() => {}
954                _ => {
955                    let r = bus.write_u32(addr, data);
956                    if let Err(err) = r {
957                        log::error!(
958                            "bus_write_u32: {:08X} at {:08X}: {}",
959                            addr,
960                            self.current_instr_pc,
961                            err
962                        );
963                        self.print_call_stack();
964                    }
965                }
966            }
967        }
968    }
969
970    fn bus_read_u16<P: BusLine>(&mut self, bus: &mut P, addr: u32) -> Option<u16> {
971        self.elapsed_cycles += 1;
972        if addr % 2 != 0 {
973            log::error!(
974                "AddressErrorLoad(u16): {:08X} at {:08X}",
975                addr,
976                self.current_instr_pc
977            );
978            self.execute_exception(Exception::AddressErrorLoad);
979            self.cop0.write_bad_vaddr(addr);
980
981            return None;
982        }
983
984        self.debugger.trace_read(addr, 16);
985        match addr {
986            0x00000000..=0x00001000 if self.cop0.is_cache_isolated() => Some(0),
987            _ => {
988                let r = bus.read_u16(addr);
989                match r {
990                    Ok(value) => Some(value),
991                    Err(err) => {
992                        log::error!(
993                            "bus_read_u16: {:08X} at {:08X}: {}",
994                            addr,
995                            self.current_instr_pc,
996                            err
997                        );
998                        self.print_call_stack();
999                        None
1000                    }
1001                }
1002            }
1003        }
1004    }
1005
1006    fn bus_write_u16<P: BusLine>(&mut self, bus: &mut P, addr: u32, data: u16) {
1007        self.elapsed_cycles += 1;
1008        if addr % 2 != 0 {
1009            log::error!(
1010                "AddressErrorStore(u16): {:08X} at {:08X}",
1011                addr,
1012                self.current_instr_pc
1013            );
1014            self.execute_exception(Exception::AddressErrorStore);
1015            self.cop0.write_bad_vaddr(addr);
1016        } else {
1017            self.debugger.trace_write(addr, 16);
1018            match addr {
1019                0x00000000..=0x00001000 if self.cop0.is_cache_isolated() => {}
1020                _ => {
1021                    let r = bus.write_u16(addr, data);
1022                    if let Err(err) = r {
1023                        log::error!(
1024                            "bus_write_u16: {:08X} at {:08X}: {}",
1025                            addr,
1026                            self.current_instr_pc,
1027                            err
1028                        );
1029                        self.print_call_stack();
1030                    }
1031                }
1032            }
1033        }
1034    }
1035
1036    fn bus_read_u8<P: BusLine>(&mut self, bus: &mut P, addr: u32) -> u8 {
1037        self.elapsed_cycles += 1;
1038        self.debugger.trace_read(addr, 8);
1039        match addr {
1040            0x00000000..=0x00001000 if self.cop0.is_cache_isolated() => 0,
1041            _ => {
1042                let r = bus.read_u8(addr);
1043                match r {
1044                    Ok(value) => value,
1045                    Err(err) => {
1046                        log::error!(
1047                            "bus_read_u8: {:08X} at {:08X}: {}",
1048                            addr,
1049                            self.current_instr_pc,
1050                            err
1051                        );
1052                        self.print_call_stack();
1053                        0
1054                    }
1055                }
1056            }
1057        }
1058    }
1059
1060    fn bus_write_u8<P: BusLine>(&mut self, bus: &mut P, addr: u32, data: u8) {
1061        self.elapsed_cycles += 1;
1062        self.debugger.trace_write(addr, 8);
1063        match addr {
1064            0x00000000..=0x00001000 if self.cop0.is_cache_isolated() => {}
1065            _ => {
1066                let r = bus.write_u8(addr, data);
1067                if let Err(err) = r {
1068                    log::error!(
1069                        "bus_write_u8: {:08X} at {:08X}: {}",
1070                        addr,
1071                        self.current_instr_pc,
1072                        err
1073                    );
1074                    self.print_call_stack();
1075                }
1076            }
1077        }
1078    }
1079}