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"))]
21impl 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
73pub 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,
104
105 #[cfg(feature = "debugger")]
106 #[cfg_attr(docsrs, doc(cfg(feature = "debugger")))]
107 InstructionBreakpoint(u32),
109
110 #[cfg(feature = "debugger")]
111 #[cfg_attr(docsrs, doc(cfg(feature = "debugger")))]
112 WriteBreakpoint { addr: u32, bits: u8 },
115
116 #[cfg(feature = "debugger")]
117 #[cfg_attr(docsrs, doc(cfg(feature = "debugger")))]
118 ReadBreakpoint { addr: u32, bits: u8 },
121
122 #[cfg(feature = "debugger")]
123 #[cfg_attr(docsrs, doc(cfg(feature = "debugger")))]
124 Step,
126
127 #[cfg(feature = "debugger")]
128 #[cfg_attr(docsrs, doc(cfg(feature = "debugger")))]
129 StepOver,
133
134 #[cfg(feature = "debugger")]
135 #[cfg_attr(docsrs, doc(cfg(feature = "debugger")))]
136 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 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 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 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 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 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 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 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 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 let target_pc = match cause {
327 Exception::Interrupt => {
328 if bd {
329 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 let new_cause = (self.cop0.read_cause() & !0x400) | ((pending_interrupts as u32) << 10);
348 self.cop0.write_cause(new_cause);
349
350 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 }
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 let rs = self.regs.read_general(instruction.rs_raw);
467 let computed_addr = rs.wrapping_add(Self::sign_extend_16(instruction.imm16()));
468
469 let start = computed_addr & !3;
471 let end = computed_addr;
472 let offset = computed_addr & 3;
473 let mut result = 0;
474
475 for part_addr in (start..=end).rev() {
477 result <<= 8;
478 result |= self.bus_read_u8(bus, part_addr) as u32;
479 }
480 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 for part_addr in (start..=end).rev() {
501 result <<= 8;
502 result |= self.bus_read_u8(bus, part_addr) as u32;
503 }
504 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 let start = computed_addr & !3;
535 let end = computed_addr;
536 let offset = computed_addr & 3;
537
538 let shift = (3 - offset) * 8;
540 rt >>= shift;
541
542 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 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 if rt == 0 {
702 self.regs.hi = rs as u32;
703 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 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 self.regs.write_ra(self.regs.pc + 4);
787 }
788 Opcode::Bgezal => {
789 self.execute_branch(instruction, false, |rs, _| rs >= 0);
790 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 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::Rfe => {
846 let mut sr = self.cop0.read_sr();
847 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}