28
28
#include " core/psxemulator.h"
29
29
#include " core/psxmem.h"
30
30
#include " core/r3000a.h"
31
+ #include " supportpsx/memory.h"
31
32
32
33
enum {
33
34
MAP_EXEC = 1 ,
@@ -40,80 +41,134 @@ enum {
40
41
MAP_EXEC_JAL = 128 ,
41
42
};
42
43
44
+ PCSX::Debug::Debug () : m_listener(g_system->m_eventBus) {
45
+ m_listener.listen <PCSX::Events::ExecutionFlow::Reset>([this ](auto &) {
46
+ m_checkKernel = false ;
47
+ clearMaps ();
48
+ });
49
+ }
50
+
43
51
uint32_t PCSX::Debug::normalizeAddress (uint32_t address) {
44
- uint32_t base = (address >> 20 ) & 0xffc ;
45
- uint32_t real = address & 0x7fffff ;
52
+ PSXAddress addr (address);
46
53
const bool ramExpansion = PCSX::g_emulator->settings .get <PCSX::Emulator::Setting8MB>();
47
- if (!ramExpansion && ((base == 0x000 ) || (base == 0x800 ) || (base == 0xa00 ) )) {
48
- return address & ~0x00600000 ;
54
+ if (!ramExpansion && (addr. type == PSXAddress::Type::RAM )) {
55
+ addr. physical &= ~0x00600000 ;
49
56
}
50
- return address;
57
+ return addr.toVirtual ().value_or (0xffffffff );
58
+ }
59
+
60
+ bool PCSX::Debug::isInKernel (uint32_t address, bool biosIsKernel) {
61
+ PSXAddress addr (address);
62
+ const bool ramExpansion = PCSX::g_emulator->settings .get <PCSX::Emulator::Setting8MB>();
63
+ if (addr.type == PSXAddress::Type::ROM) return biosIsKernel;
64
+ if (addr.type != PSXAddress::Type::RAM) return false ;
65
+ if (!ramExpansion) addr.physical &= ~0x00600000 ;
66
+ return addr.physical < 0x10000 ;
51
67
}
52
68
53
69
void PCSX::Debug::markMap (uint32_t address, int mask) {
54
- address = normalizeAddress (address);
55
- uint32_t base = (address >> 20 ) & 0xffc ;
56
- uint32_t real = address & 0x7fffff ;
57
- uint32_t shortReal = address & 0x3fffff ;
58
- if (((base == 0x000 ) || (base == 0x800 ) || (base == 0xa00 )) && (real < sizeof (m_mainMemoryMap))) {
59
- m_mainMemoryMap[real] |= mask;
60
- } else if ((base == 0x1f8 ) && (real < sizeof (m_scratchPadMap))) {
61
- m_scratchPadMap[real] |= mask;
62
- } else if ((base == 0xbfc ) && (shortReal < sizeof (m_biosMemoryMap))) {
63
- m_biosMemoryMap[shortReal] |= mask;
70
+ PSXAddress addr (normalizeAddress (address));
71
+
72
+ switch (addr.type ) {
73
+ case PSXAddress::Type::RAM:
74
+ if (addr.physical < sizeof (m_mainMemoryMap)) {
75
+ m_mainMemoryMap[addr.physical ] |= mask;
76
+ }
77
+ break ;
78
+ case PSXAddress::Type::ScratchPad:
79
+ if (addr.physical < sizeof (m_scratchPadMap)) {
80
+ m_scratchPadMap[addr.physical ] |= mask;
81
+ }
82
+ break ;
83
+ case PSXAddress::Type::ROM:
84
+ if (addr.physical < sizeof (m_biosMemoryMap)) {
85
+ m_biosMemoryMap[addr.physical ] |= mask;
86
+ }
87
+ break ;
64
88
}
65
89
}
66
90
67
91
bool PCSX::Debug::isMapMarked (uint32_t address, int mask) {
68
- address = normalizeAddress (address);
69
- uint32_t base = (address >> 20 ) & 0xffc ;
70
- uint32_t real = address & 0x7fffff ;
71
- uint32_t shortReal = address & 0x3fffff ;
72
- if (((base == 0x000 ) || (base == 0x800 ) || (base == 0xa00 )) && (real < sizeof (m_mainMemoryMap))) {
73
- return m_mainMemoryMap[real] & mask;
74
- } else if ((base == 0x1f8 ) && (real < sizeof (m_scratchPadMap))) {
75
- return m_scratchPadMap[real] & mask;
76
- } else if ((base == 0xbfc ) && (shortReal < sizeof (m_biosMemoryMap))) {
77
- return m_biosMemoryMap[shortReal] & mask;
92
+ PSXAddress addr (normalizeAddress (address));
93
+
94
+ switch (addr.type ) {
95
+ case PSXAddress::Type::RAM:
96
+ if (addr.physical < sizeof (m_mainMemoryMap)) {
97
+ return m_mainMemoryMap[addr.physical ] & mask;
98
+ }
99
+ break ;
100
+ case PSXAddress::Type::ScratchPad:
101
+ if (addr.physical < sizeof (m_scratchPadMap)) {
102
+ return m_scratchPadMap[addr.physical ] & mask;
103
+ }
104
+ break ;
105
+ case PSXAddress::Type::ROM:
106
+ if (addr.physical < sizeof (m_biosMemoryMap)) {
107
+ return m_biosMemoryMap[addr.physical ] & mask;
108
+ }
109
+ break ;
78
110
}
79
111
return false ;
80
112
}
81
113
82
114
void PCSX::Debug::process (uint32_t oldPC, uint32_t newPC, uint32_t oldCode, uint32_t newCode, bool linked) {
115
+ const auto & regs = g_emulator->m_cpu ->m_regs ;
83
116
const uint32_t basic = newCode >> 26 ;
84
117
const bool isAnyLoadOrStore = (basic >= 0x20 ) && (basic < 0x3b );
85
- const auto & regs = g_emulator->m_cpu ->m_regs ;
118
+ const bool isJAL = basic == 3 ;
119
+ const bool isJR = (basic == 0 ) && ((newCode & 0x3f ) == 8 );
120
+ const bool isJALR = (basic == 0 ) && ((newCode & 0x3f ) == 9 );
121
+ const bool isLB = basic == 0x20 ;
122
+ const bool isLH = basic == 0x21 ;
123
+ const bool isLWL = basic == 0x22 ;
124
+ const bool isLW = basic == 0x23 ;
125
+ const bool isLBU = basic == 0x24 ;
126
+ const bool isLHU = basic == 0x25 ;
127
+ const bool isLWR = basic == 0x26 ;
128
+ const bool isSB = basic == 0x28 ;
129
+ const bool isSH = basic == 0x29 ;
130
+ const bool isSWL = basic == 0x2a ;
131
+ const bool isSW = basic == 0x2b ;
132
+ const bool isSWR = basic == 0x2e ;
133
+ const bool isLWC2 = basic == 0x32 ;
134
+ const bool isSWC2 = basic == 0x3a ;
135
+ const bool isLoad = isLB || isLBU || isLH || isLHU || isLW || isLWL || isLWR || isLWC2;
136
+ const bool isStore = isSB || isSH || isSW || isSWL || isSWR || isSWC2;
137
+ const bool wasInKernel = isInKernel (oldPC);
138
+ const bool isInKernelNow = isInKernel (newPC);
139
+ const uint32_t target = (newCode & 0x03ffffff ) * 4 + (newPC & 0xf0000000 );
140
+ const bool isTargetInKernel = isInKernel (target);
141
+ const uint32_t rd = (newCode >> 11 ) & 0x1f ;
142
+ uint32_t offset = regs.GPR .r [(newCode >> 21 ) & 0x1f ] + int16_t (newCode);
143
+ const bool offsetIsInKernel = isInKernel (offset, false );
144
+ const bool isJRToRA = isJR && (rd == 31 );
145
+ const uint32_t oldPCBase = normalizeAddress (oldPC) & ~0xe0000000 ;
146
+ const uint32_t newPCBase = normalizeAddress (newPC) & ~0xe0000000 ;
147
+ const uint32_t targetBase = normalizeAddress (target) & ~0xe0000000 ;
86
148
87
149
checkBP (newPC, BreakpointType::Exec, 4 );
88
150
if (m_breakmp_e && !isMapMarked (newPC, MAP_EXEC)) {
89
151
triggerBP (nullptr , newPC, 4 , _ (" Execution map" ));
90
152
}
91
153
if (m_mapping_e) {
92
- const bool isJAL = basic == 3 ;
93
- const bool isJALR = (basic == 0 ) && ((newCode & 0x3F ) == 9 );
94
- const uint32_t target = (newCode & 0x03ffffff ) * 4 + (newPC & 0xf0000000 );
95
- const uint32_t rd = (newCode >> 11 ) & 0x1f ;
96
154
markMap (newPC, MAP_EXEC);
97
155
if (isJAL) markMap (target, MAP_EXEC_JAL);
98
156
if (isJALR) markMap (regs.GPR .r [rd], MAP_EXEC_JAL);
99
157
}
100
158
159
+ // Are we jumping from a non-kernel address to a kernel address which:
160
+ // - is not a jr to $ra (aka a return from a callback)
161
+ // - is not a jump to 0xa0 / 0xb0 / 0xc0 (aka the syscall gates)
162
+ // - is not going to the break or exception handler
163
+ if ((isJR || isJALR) && !wasInKernel && isTargetInKernel && !isJRToRA && (targetBase != 0x40 ) &&
164
+ (targetBase != 0x80 ) && (targetBase != 0xa0 ) && (targetBase != 0xb0 ) && (targetBase != 0xc0 )) {
165
+ if (m_checkKernel) {
166
+ g_system->printf (_ (" Kernel checker: Jump from 0x%08x to 0x%08x\n " ), oldPC, targetBase);
167
+ g_system->pause ();
168
+ }
169
+ }
170
+
101
171
if (isAnyLoadOrStore) {
102
- const bool isLB = basic == 0x20 ;
103
- const bool isLH = basic == 0x21 ;
104
- const bool isLWL = basic == 0x22 ;
105
- const bool isLW = (basic == 0x23 ) || (basic == 0x32 );
106
- const bool isLBU = basic == 0x24 ;
107
- const bool isLHU = basic == 0x25 ;
108
- const bool isLWR = basic == 0x26 ;
109
- const bool isSB = basic == 0x28 ;
110
- const bool isSH = basic == 0x29 ;
111
- const bool isSWL = basic == 0x2a ;
112
- const bool isSW = (basic == 0x2b ) || (basic == 0x3a );
113
- const bool isSWR = basic == 0x2e ;
114
- const bool isLWC2 = basic == 0x32 ;
115
- const bool isSWC2 = basic == 0x3a ;
116
- uint32_t offset = regs.GPR .r [(newCode >> 21 ) & 0x1f ] + int16_t (newCode);
117
172
if (isLWL || isLWR || isSWR || isSWL) offset &= ~3 ;
118
173
if (isLB || isLBU) {
119
174
checkBP (offset, BreakpointType::Read, 1 );
@@ -157,6 +212,19 @@ void PCSX::Debug::process(uint32_t oldPC, uint32_t newPC, uint32_t oldCode, uint
157
212
}
158
213
if (m_mapping_w32) markMap (offset, MAP_W32);
159
214
}
215
+ // Are we accessing a kernel address from a non-kernel address, while not in IRQ?
216
+ if (!g_emulator->m_cpu ->m_inISR && offsetIsInKernel && !wasInKernel) {
217
+ if (m_checkKernel) {
218
+ if (isLoad) {
219
+ g_system->printf (_ (" Kernel checker: Reading %08x from %08x\n " ), offset, oldPC);
220
+ g_system->pause ();
221
+ } else {
222
+ g_system->printf (_ (" Kernel checker: Writing to %08x from %08x\n " ), offset, oldPC);
223
+ g_system->pause ();
224
+ }
225
+ g_system->pause ();
226
+ }
227
+ }
160
228
}
161
229
162
230
if (m_step == STEP_NONE) return ;
0 commit comments