Nugget
Bare-metal libraries and examples for the original PlayStation
Loading...
Searching...
No Matches
cop0dbg.h
Go to the documentation of this file.
1/*
2
3MIT License
4
5Copyright (c) 2026 PCSX-Redux authors
6
7Permission is hereby granted, free of charge, to any person obtaining a copy
8of this software and associated documentation files (the "Software"), to deal
9in the Software without restriction, including without limitation the rights
10to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11copies of the Software, and to permit persons to whom the Software is
12furnished to do so, subject to the following conditions:
13
14The above copyright notice and this permission notice shall be included in all
15copies or substantial portions of the Software.
16
17THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23SOFTWARE.
24
25*/
26
27#pragma once
28
29#include <stdint.h>
30
31/* cop0 accessors for the debug monitor. The LR33300/LR33310 R3000A exposes a
32 hardware-breakpoint unit through cop0 debug registers (BPC/BDA/DCIC/BPCM/
33 BDAM); psx-spx (cpuspecifications.md) documents the layout used here. Only
34 the registers the monitor needs are wrapped. */
35
36/* -- read-only exception state -- */
37static inline uint32_t readBadVaddr(void) {
38 uint32_t v;
39 __asm__ volatile("mfc0 %0, $8\nnop\n" : "=r"(v));
40 return v;
41}
42
43static inline uint32_t readCause(void) {
44 uint32_t v;
45 __asm__ volatile("mfc0 %0, $13\nnop\n" : "=r"(v));
46 return v;
47}
48
49static inline uint32_t readEPC(void) {
50 uint32_t v;
51 __asm__ volatile("mfc0 %0, $14\nnop\n" : "=r"(v));
52 return v;
53}
54
55/* -- hardware breakpoint unit -- */
56/* BPC cop0r3 : program-counter breakpoint address
57 BDA cop0r5 : data-access breakpoint address
58 DCIC cop0r7 : debug control / cause
59 BDAM cop0r9 : data-access breakpoint address mask
60 BPCM cop0r11 : program-counter breakpoint address mask */
61
62static inline void writeBPC(uint32_t v) { __asm__ volatile("mtc0 %0, $3\nnop\n" : : "r"(v)); }
63static inline void writeBDA(uint32_t v) { __asm__ volatile("mtc0 %0, $5\nnop\n" : : "r"(v)); }
64static inline void writeBPCM(uint32_t v) { __asm__ volatile("mtc0 %0, $11\nnop\n" : : "r"(v)); }
65static inline void writeBDAM(uint32_t v) { __asm__ volatile("mtc0 %0, $9\nnop\n" : : "r"(v)); }
66
67static inline uint32_t readDCIC(void) {
68 uint32_t v;
69 __asm__ volatile("mfc0 %0, $7\nnop\n" : "=r"(v));
70 return v;
71}
72static inline void writeDCIC(uint32_t v) { __asm__ volatile("mtc0 %0, $7\nnop\n" : : "r"(v)); }
73
74/* DCIC bit fields (psx-spx cpuspecifications.md). Without TR a match only sets
75 the status bits (0..4) instead of trapping to the cop0-break vector. */
76#define DCIC_DA (1u << 2) /* status: the break was a BDA data break */
77#define DCIC_DE (1u << 23) /* master debug enable */
78#define DCIC_PCE (1u << 24) /* program counter breakpoint enable */
79#define DCIC_DAE (1u << 25) /* data address breakpoint enable */
80#define DCIC_DR (1u << 26) /* break on data read */
81#define DCIC_DW (1u << 27) /* break on data write */
82#define DCIC_KD (1u << 29) /* enable in kernel mode */
83#define DCIC_UD (1u << 30) /* enable in user mode */
84#define DCIC_TR (1u << 31) /* trap enable (raise the exception) */
85
86/* Cause register ExcCode field (bits 6:2). */
87#define CAUSE_EXCCODE(cause) (((cause) >> 2) & 0x1f)
88#define EXCCODE_INT 0x00 /* interrupt */
89#define EXCCODE_ADEL 0x04 /* address error, load */
90#define EXCCODE_ADES 0x05 /* address error, store */
91#define EXCCODE_IBE 0x06 /* bus error, instruction fetch */
92#define EXCCODE_DBE 0x07 /* bus error, data */
93#define EXCCODE_SYS 0x08 /* syscall */
94#define EXCCODE_BP 0x09 /* breakpoint (break instruction) */
95#define EXCCODE_RI 0x0a /* reserved instruction */
96#define EXCCODE_CPU 0x0b /* coprocessor unusable */
97#define EXCCODE_OVF 0x0c /* arithmetic overflow */
__asm__(" .section .text.monitorSlotEntry, \"ax\", @progbits\n" " .align 2\n" " .global monitorSlotEntry\n" " .type monitorSlotEntry, @function\n" " .set push\n" " .set noreorder\n" " .set noat\n" "monitorSlotEntry:\n" " mfc0 $v0, $13\n" " nop\n" " andi $v0, $v0, 0x7c\n" " beqz $v0, 1f\n" " srl $v0, $v0, 2\n" " li $v1, " MON_STR(MON_SLOT_EXCMASK) "\n" " srlv $v1, $v1, $v0\n" " andi $v1, $v1, 1\n" " bnez $v1, 2f\n" " nop\n" " jr $ra\n" " nop\n" "1:\n" MON_SLOT_RX_TEST " jr $ra\n" " nop\n" "2:\n" " sw $a0, 0x10($k0)\n" " sw $a1, 0x14($k0)\n" " sw $a2, 0x18($k0)\n" " sw $a3, 0x1c($k0)\n" " mfc0 $a0, $12\n" " nop\n" " sw $a0, 0x8c($k0)\n" " mfc0 $a1, $13\n" " nop\n" " sw $a1, 0x90($k0)\n" " sw $k1, 0x6c($k0)\n" " sw $s0, 0x40($k0)\n" " sw $s1, 0x44($k0)\n" " sw $s2, 0x48($k0)\n" " sw $s3, 0x4c($k0)\n" " sw $s4, 0x50($k0)\n" " sw $s5, 0x54($k0)\n" " sw $s6, 0x58($k0)\n" " sw $s7, 0x5c($k0)\n" " sw $t0, 0x20($k0)\n" " sw $t1, 0x24($k0)\n" " sw $t2, 0x28($k0)\n" " sw $t3, 0x2c($k0)\n" " sw $t4, 0x30($k0)\n" " sw $t5, 0x34($k0)\n" " sw $t6, 0x38($k0)\n" " sw $t7, 0x3c($k0)\n" " sw $t8, 0x60($k0)\n" " sw $t9, 0x64($k0)\n" " sw $gp, 0x70($k0)\n" " sw $sp, 0x74($k0)\n" " sw $fp, 0x78($k0)\n" " mfhi $a0\n" " nop\n" " sw $a0, 0x84($k0)\n" " mflo $a0\n" " nop\n" " sw $a0, 0x88($k0)\n" " move $s0, $ra\n" " la $sp, monitorSlotStack + " MON_STR(MONITOR_SLOT_STACK_WORDS) " * 4 - 16\n" " jal monitorSlotDispatch\n" " nop\n" " lw $k0, 0x108($zero)\n" " move $ra, $s0\n" " lw $k0, 0($k0)\n" " nop\n" " addiu $k0, $k0, 8\n" " lw $a0, 0x84($k0)\n" " lw $a1, 0x88($k0)\n" " mthi $a0\n" " mtlo $a1\n" " lw $a0, 0x10($k0)\n" " lw $a1, 0x14($k0)\n" " lw $a2, 0x18($k0)\n" " lw $a3, 0x1c($k0)\n" " lw $t0, 0x20($k0)\n" " lw $t1, 0x24($k0)\n" " lw $t2, 0x28($k0)\n" " lw $t3, 0x2c($k0)\n" " lw $t4, 0x30($k0)\n" " lw $t5, 0x34($k0)\n" " lw $t6, 0x38($k0)\n" " lw $t7, 0x3c($k0)\n" " lw $t8, 0x60($k0)\n" " lw $t9, 0x64($k0)\n" " lw $s0, 0x40($k0)\n" " lw $sp, 0x74($k0)\n" " jr $ra\n" " nop\n" " .set pop\n" " .size monitorSlotEntry, . - monitorSlotEntry\n" " .previous\n")
void uint32_t(classId, spec)