1 // license:BSD-3-Clause
2 // copyright-holders:smf
3 /*
4 * PlayStation CPU emulator
5 *
6 * Copyright 2003-2017 smf
7 *
8 * Known chip id's
9 * CXD8530AQ
10 * CXD8530BQ
11 * CXD8530CQ
12 * CXD8661R
13 * CXD8606BQ
14 * CXD8606CQ
15 *
16 * The PlayStation CPU is based on the LSI CoreWare CW33300 library, this was available packaged as an LSI LR33300.
17 *
18 * Differences from the LR33300:
19 *
20 * There is only 1k of data cache ram ( the LR33300 has 2k )
21 *
22 * There is no data cache tag ram, so the data cache ram can only be used as a fast area
23 * of ram ( which is a standard LR33300 feature ).
24 *
25 * If COP0 is disabled in user mode you get a coprocessor unusable exception, while
26 * the LR33300 is documented to generate a reserved instruction exception.
27 *
28 * MDEC is based on the LSI Jpeg CoreWare library (CW702?).
29 *
30 * Known limitations of the emulation:
31 *
32 * Program counter, read data & write data break points are emulated, trace break points are not.
33 *
34 * Load/Store timings are based on load scheduling turned off & no write cache. This affects when
35 * bus error exceptions occur and also when the read & write handlers are called. A scheduled
36 * load will complete if a load breakpoint fires, but an unscheduled load will not.
37 *
38 * Reading from the data and instruction cache at the same time causes a bus conflict that
39 * corrupts the data in a reliable but strange way, which is not emulated.
40 *
41 * Values written to COP1 & COP3 can be read back by the next instruction, which is not emulated.
42 * Because of loadscheduling the value loaded with LWC1/LWC3 can be read by more than the next
43 * instruction.
44 *
45 * SWC0 writes stale data from a previous operation, this is only partially emulated as the timing
46 * is complicated. Left over instruction fetches are currently emulated as they are the most
47 * 'interesting' and have no impact on the rest of the emulation.
48 *
49 * MTC0 timing is not emulated, switching to user mode while in kernel space continues
50 * execution for another two instructions before taking an exception. Using RFE to do the same
51 * thing causes the exception straight away, unless the RFE is the first instruction that follows
52 * an MTC0 instruction.
53 *
54 * The PRId register should be 1 on some revisions of the CPU ( there might be other values too ).
55 *
56 * Moving to the HI/LO register after a multiply or divide, but before reading the results will
57 * always abort the operation as if you did it immediately. In reality it should complete on it's
58 * own, and aborting before it completes would result in returning the working results.
59 *
60 * Running code in cached address space does not use or update the instruction cache.
61 *
62 * Wait states are not emulated.
63 *
64 * Bus errors caused by instruction burst fetches are not supported.
65 *
66 */
67
68 #include "emu.h"
69 #include "psx.h"
70 #include "mdec.h"
71 #include "rcnt.h"
72 #include "sound/spu.h"
73 #include "debugger.h"
74
75 #include "psxdefs.h"
76
77 #define LOG_BIOSCALL ( 0 )
78
79 #define EXC_INT ( 0 )
80 #define EXC_ADEL ( 4 )
81 #define EXC_ADES ( 5 )
82 #define EXC_IBE ( 6 )
83 #define EXC_DBE ( 7 )
84 #define EXC_SYS ( 8 )
85 #define EXC_BP ( 9 )
86 #define EXC_RI ( 10 )
87 #define EXC_CPU ( 11 )
88 #define EXC_OVF ( 12 )
89
90 #define CP0_INDEX ( 0 )
91 #define CP0_RANDOM ( 1 )
92 #define CP0_ENTRYLO ( 2 )
93 #define CP0_CONTEXT ( 4 )
94 #define CP0_ENTRYHI ( 10 )
95
96 #define CP0_BPC ( 3 )
97 #define CP0_BDA ( 5 )
98 #define CP0_TAR ( 6 )
99 #define CP0_DCIC ( 7 )
100 #define CP0_BADA ( 8 )
101 #define CP0_BDAM ( 9 )
102 #define CP0_BPCM ( 11 )
103 #define CP0_SR ( 12 )
104 #define CP0_CAUSE ( 13 )
105 #define CP0_EPC ( 14 )
106 #define CP0_PRID ( 15 )
107
108 #define DCIC_DB ( 1L << 0 )
109 #define DCIC_PC ( 1L << 1 )
110 #define DCIC_DA ( 1L << 2 )
111 #define DCIC_R ( 1L << 3 )
112 #define DCIC_W ( 1L << 4 )
113 #define DCIC_T ( 1L << 5 ) // not emulated
114 // unknown ( 1L << 12 )
115 // unknown ( 1L << 13 )
116 // unknown ( 1L << 14 )
117 // unknown ( 1L << 15 )
118 #define DCIC_DE ( 1L << 23 )
119 #define DCIC_PCE ( 1L << 24 )
120 #define DCIC_DAE ( 1L << 25 )
121 #define DCIC_DR ( 1L << 26 )
122 #define DCIC_DW ( 1L << 27 )
123 #define DCIC_TE ( 1L << 28 ) // not emulated
124 #define DCIC_KD ( 1L << 29 )
125 #define DCIC_UD ( 1L << 30 )
126 #define DCIC_TR ( 1L << 31 )
127
128 #define SR_IEC ( 1L << 0 )
129 #define SR_KUC ( 1L << 1 )
130 #define SR_ISC ( 1L << 16 )
131 #define SR_SWC ( 1L << 17 )
132 #define SR_BEV ( 1L << 22 )
133 #define SR_CU0 ( 1L << 28 )
134 #define SR_CU1 ( 1L << 29 )
135 #define SR_CU2 ( 1L << 30 )
136 #define SR_CU3 ( 1L << 31 )
137
138 #define CAUSE_EXC ( 31L << 2 )
139 #define CAUSE_IP ( 255L << 8 )
140 // software interrupts
141 #define CAUSE_IP0 ( 1L << 8 )
142 #define CAUSE_IP1 ( 1L << 9 )
143 // hardware interrupts
144 #define CAUSE_IP2 ( 1L << 10 )
145 #define CAUSE_IP3 ( 1L << 11 )
146 #define CAUSE_IP4 ( 1L << 12 )
147 #define CAUSE_IP5 ( 1L << 13 )
148 #define CAUSE_IP6 ( 1L << 14 )
149 #define CAUSE_IP7 ( 1L << 15 )
150 #define CAUSE_CE ( 3L << 28 )
151 #define CAUSE_BT ( 1L << 30 )
152 #define CAUSE_BD ( 1L << 31 )
153
154 #define BIU_LOCK ( 0x00000001 )
155 #define BIU_INV ( 0x00000002 )
156 #define BIU_TAG ( 0x00000004 )
157 #define BIU_RAM ( 0x00000008 )
158 #define BIU_DS ( 0x00000080 )
159 #define BIU_IS1 ( 0x00000800 )
160
161 #define TAG_MATCH_MASK ( 0 - ( ICACHE_ENTRIES * 4 ) )
162 #define TAG_MATCH ( 0x10 )
163 #define TAG_VALID ( 0x0f )
164
165 #define MULTIPLIER_OPERATION_IDLE ( 0 )
166 #define MULTIPLIER_OPERATION_MULT ( 1 )
167 #define MULTIPLIER_OPERATION_MULTU ( 2 )
168 #define MULTIPLIER_OPERATION_DIV ( 3 )
169 #define MULTIPLIER_OPERATION_DIVU ( 4 )
170
171 static const char *const delayn[] =
172 {
173 "", "at", "v0", "v1", "a0", "a1", "a2", "a3",
174 "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
175 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
176 "t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra",
177 "pc", "!pc"
178 };
179
180 // device type definition
181 DEFINE_DEVICE_TYPE(CXD8530AQ, cxd8530aq_device, "cxd8530aq", "Sony CXD8530AQ")
182 DEFINE_DEVICE_TYPE(CXD8530BQ, cxd8530bq_device, "cxd8530bq", "Sony CXD8530BQ")
183 DEFINE_DEVICE_TYPE(CXD8530CQ, cxd8530cq_device, "cxd8530cq", "Sony CXD8530CQ")
184 DEFINE_DEVICE_TYPE(CXD8661R, cxd8661r_device, "cxd8661r", "Sony CXD8661R")
185 DEFINE_DEVICE_TYPE(CXD8606BQ, cxd8606bq_device, "cxd8606bq", "Sony CXD8606BQ")
186 DEFINE_DEVICE_TYPE(CXD8606CQ, cxd8606cq_device, "cxd8606cq", "Sony CXD8606CQ")
187
188 static const uint32_t mtc0_writemask[]=
189 {
190 0x00000000, /* !INDEX */
191 0x00000000, /* !RANDOM */
192 0x00000000, /* !ENTRYLO */
193 0xffffffff, /* BPC */
194 0x00000000, /* !CONTEXT */
195 0xffffffff, /* BDA */
196 0x00000000, /* TAR */
197 0xff80f03f, /* DCIC */
198 0x00000000, /* BADA */
199 0xffffffff, /* BDAM */
200 0x00000000, /* !ENTRYHI */
201 0xffffffff, /* BPCM */
202 0xf04fff3f, /* SR */
203 0x00000300, /* CAUSE */
204 0x00000000, /* EPC */
205 0x00000000 /* PRID */
206 };
207
berr_r()208 uint32_t psxcpu_device::berr_r()
209 {
210 if( !machine().side_effects_disabled() )
211 m_berr = 1;
212 return 0;
213 }
214
berr_w(uint32_t data)215 void psxcpu_device::berr_w(uint32_t data)
216 {
217 if( !machine().side_effects_disabled() )
218 m_berr = 1;
219 }
220
exp_base_r()221 uint32_t psxcpu_device::exp_base_r()
222 {
223 return m_exp_base;
224 }
225
exp_base_w(offs_t offset,uint32_t data,uint32_t mem_mask)226 void psxcpu_device::exp_base_w(offs_t offset, uint32_t data, uint32_t mem_mask)
227 {
228 COMBINE_DATA( &m_exp_base ); // TODO: check byte writes
229
230 m_exp_base = 0x1f000000 | ( m_exp_base & 0xffffff );
231 }
232
exp_base()233 uint32_t psxcpu_device::exp_base()
234 {
235 return m_exp_base;
236 }
237
exp_config_r()238 uint32_t psxcpu_device::exp_config_r()
239 {
240 return m_exp_config;
241 }
242
exp_config_w(offs_t offset,uint32_t data,uint32_t mem_mask)243 void psxcpu_device::exp_config_w(offs_t offset, uint32_t data, uint32_t mem_mask)
244 {
245 COMBINE_DATA( &m_exp_config ); // TODO: check byte writes
246
247 m_exp_config &= 0xaf1fffff;
248 }
249
ram_config_r()250 uint32_t psxcpu_device::ram_config_r()
251 {
252 return m_ram_config;
253 }
254
ram_config_w(offs_t offset,uint32_t data,uint32_t mem_mask)255 void psxcpu_device::ram_config_w(offs_t offset, uint32_t data, uint32_t mem_mask)
256 {
257 uint32_t old = m_ram_config;
258
259 COMBINE_DATA( &m_ram_config ); // TODO: check byte writes
260
261 if( ( ( m_ram_config ^ old ) & 0xff00 ) != 0 )
262 {
263 update_ram_config();
264 }
265 }
266
rom_config_r()267 uint32_t psxcpu_device::rom_config_r()
268 {
269 return m_rom_config;
270 }
271
rom_config_w(offs_t offset,uint32_t data,uint32_t mem_mask)272 void psxcpu_device::rom_config_w(offs_t offset, uint32_t data, uint32_t mem_mask)
273 {
274 uint32_t old = m_rom_config;
275
276 COMBINE_DATA( &m_rom_config ); // TODO: check byte writes
277
278 if( ( ( m_rom_config ^ old ) & 0x001f0000 ) != 0 )
279 {
280 update_rom_config();
281 }
282 }
283
com_delay_r(offs_t offset,uint32_t mem_mask)284 uint32_t psxcpu_device::com_delay_r(offs_t offset, uint32_t mem_mask)
285 {
286 //verboselog( p_psx, 1, "psx_com_delay_r( %08x )\n", mem_mask );
287 return m_com_delay;
288 }
289
com_delay_w(offs_t offset,uint32_t data,uint32_t mem_mask)290 void psxcpu_device::com_delay_w(offs_t offset, uint32_t data, uint32_t mem_mask)
291 {
292 COMBINE_DATA( &m_com_delay ); // TODO: check byte writes
293 //verboselog( p_psx, 1, "psx_com_delay_w( %08x %08x )\n", data, mem_mask );
294 }
295
biu_r()296 uint32_t psxcpu_device::biu_r()
297 {
298 return m_biu;
299 }
300
biu_w(offs_t offset,uint32_t data,uint32_t mem_mask)301 void psxcpu_device::biu_w(offs_t offset, uint32_t data, uint32_t mem_mask)
302 {
303 uint32_t old = m_biu;
304
305 COMBINE_DATA( &m_biu ); // TODO: check byte writes
306
307 if( ( old & ( BIU_RAM | BIU_DS ) ) != ( m_biu & ( BIU_RAM | BIU_DS ) ) )
308 {
309 update_scratchpad();
310 }
311 }
312
stop()313 void psxcpu_device::stop()
314 {
315 machine().debug_break();
316 debugger_instruction_hook( m_pc );
317 }
318
cache_readword(uint32_t offset)319 uint32_t psxcpu_device::cache_readword( uint32_t offset )
320 {
321 uint32_t data = 0;
322
323 if( ( m_biu & BIU_TAG ) != 0 )
324 {
325 if( ( m_biu & BIU_IS1 ) != 0 )
326 {
327 uint32_t tag = m_icacheTag[ ( offset / 16 ) % ( ICACHE_ENTRIES / 4 ) ];
328 data |= tag & TAG_VALID;
329
330 if( ( ( tag ^ offset ) & TAG_MATCH_MASK ) == 0 )
331 {
332 data |= TAG_MATCH;
333 }
334 }
335 }
336 else if( ( m_biu & ( BIU_LOCK | BIU_INV ) ) != 0 )
337 {
338 }
339 else
340 {
341 if( ( m_biu & BIU_IS1 ) == BIU_IS1 )
342 {
343 data |= m_icache[ ( offset / 4 ) % ICACHE_ENTRIES ];
344 }
345
346 if( ( m_biu & BIU_DS ) == BIU_DS )
347 {
348 data |= m_dcache[ ( offset / 4 ) % DCACHE_ENTRIES ];
349 }
350 }
351
352 return data;
353 }
354
cache_writeword(uint32_t offset,uint32_t data)355 void psxcpu_device::cache_writeword( uint32_t offset, uint32_t data )
356 {
357 if( ( m_biu & BIU_TAG ) != 0 )
358 {
359 if( ( m_biu & BIU_IS1 ) != 0 )
360 {
361 m_icacheTag[ ( offset / 16 ) % ( ICACHE_ENTRIES / 4 ) ] = ( data & TAG_VALID ) | ( offset & TAG_MATCH_MASK );
362 }
363 }
364 else if( ( m_biu & ( BIU_LOCK | BIU_INV ) ) != 0 )
365 {
366 if( ( m_biu & BIU_IS1 ) != 0 )
367 {
368 m_icacheTag[ ( offset / 16 ) % ( ICACHE_ENTRIES / 4 ) ] = ( offset & TAG_MATCH_MASK );
369 }
370 }
371 else
372 {
373 if( ( m_biu & BIU_IS1 ) != 0 )
374 {
375 m_icache[ ( offset / 4 ) % ICACHE_ENTRIES ] = data;
376 }
377
378 if( ( m_biu & BIU_DS ) != 0 )
379 {
380 m_dcache[ ( offset / 4 ) % DCACHE_ENTRIES ] = data;
381 }
382 }
383 }
384
readbyte(uint32_t address)385 uint8_t psxcpu_device::readbyte( uint32_t address )
386 {
387 if( m_bus_attached )
388 {
389 return m_data.read_byte( address );
390 }
391
392 return cache_readword( address ) >> ( ( address & 3 ) * 8 );
393 }
394
readhalf(uint32_t address)395 uint16_t psxcpu_device::readhalf( uint32_t address )
396 {
397 if( m_bus_attached )
398 {
399 return m_data.read_word( address );
400 }
401
402 return cache_readword( address ) >> ( ( address & 2 ) * 8 );
403 }
404
readword(uint32_t address)405 uint32_t psxcpu_device::readword( uint32_t address )
406 {
407 if( m_bus_attached )
408 {
409 return m_data.read_dword( address );
410 }
411
412 return cache_readword( address );
413 }
414
readword_masked(uint32_t address,uint32_t mask)415 uint32_t psxcpu_device::readword_masked( uint32_t address, uint32_t mask )
416 {
417 if( m_bus_attached )
418 {
419 return m_data.read_dword( address, mask );
420 }
421
422 return cache_readword( address );
423 }
424
writeword(uint32_t address,uint32_t data)425 void psxcpu_device::writeword( uint32_t address, uint32_t data )
426 {
427 if( m_bus_attached )
428 {
429 m_data.write_dword( address, data );
430 }
431 else
432 {
433 cache_writeword( address, data );
434 }
435 }
436
writeword_masked(uint32_t address,uint32_t data,uint32_t mask)437 void psxcpu_device::writeword_masked( uint32_t address, uint32_t data, uint32_t mask )
438 {
439 if( m_bus_attached )
440 {
441 m_data.write_dword( address, data, mask );
442 }
443 else
444 {
445 cache_writeword( address, data );
446 }
447 }
448
449
450 static const struct
451 {
452 int address;
453 int operation;
454 const char *prototype;
455 } bioscalls[] =
456 {
457 { 0xa0, 0x00, "int open(const char *name, int mode)" },
458 { 0xa0, 0x01, "int lseek(int fd, int offset, int whence)" },
459 { 0xa0, 0x02, "int read(int fd, void *buf, int nbytes)" },
460 { 0xa0, 0x03, "int write(int fd, void *buf, int nbytes)" },
461 { 0xa0, 0x04, "int close(int fd)" },
462 { 0xa0, 0x05, "int ioctl(int fd, int cmd, int arg)" },
463 { 0xa0, 0x06, "void exit(int code)" },
464 { 0xa0, 0x07, "sys_a0_07()" },
465 { 0xa0, 0x08, "char getc(int fd)" },
466 { 0xa0, 0x09, "void putc(char c, int fd)" },
467 { 0xa0, 0x0a, "todigit()" },
468 { 0xa0, 0x0b, "double atof(const char *s)" },
469 { 0xa0, 0x0c, "long strtoul(const char *s, char **ptr, int base)" },
470 { 0xa0, 0x0d, "unsigned long strtol(const char *s, char **ptr, int base)" },
471 { 0xa0, 0x0e, "int abs(int val)" },
472 { 0xa0, 0x0f, "long labs(long lval)" },
473 { 0xa0, 0x10, "long atoi(const char *s)" },
474 { 0xa0, 0x11, "int atol(const char *s)" },
475 { 0xa0, 0x12, "atob()" },
476 { 0xa0, 0x13, "int setjmp(jmp_buf *ctx)" },
477 { 0xa0, 0x14, "void longjmp(jmp_buf *ctx, int value)" },
478 { 0xa0, 0x15, "char *strcat(char *dst, const char *src)" },
479 { 0xa0, 0x16, "char *strncat(char *dst, const char *src, size_t n)" },
480 { 0xa0, 0x17, "int strcmp(const char *dst, const char *src)" },
481 { 0xa0, 0x18, "int strncmp(const char *dst, const char *src, size_t n)" },
482 { 0xa0, 0x19, "char *strcpy(char *dst, const char *src)" },
483 { 0xa0, 0x1a, "char *strncpy(char *dst, const char *src, size_t n)" },
484 { 0xa0, 0x1b, "size_t strlen(const char *s)" },
485 { 0xa0, 0x1c, "int index(const char *s, int c)" },
486 { 0xa0, 0x1d, "int rindex(const char *s, int c)" },
487 { 0xa0, 0x1e, "char *strchr(const char *s, int c)" },
488 { 0xa0, 0x1f, "char *strrchr(const char *s, int c)" },
489 { 0xa0, 0x20, "char *strpbrk(const char *dst, const char *src)" },
490 { 0xa0, 0x21, "size_t strspn(const char *s, const char *set)" },
491 { 0xa0, 0x22, "size_t strcspn(const char *s, const char *set)" },
492 { 0xa0, 0x23, "char *strtok(char *s, const char *set)" },
493 { 0xa0, 0x24, "char *strstr(const char *s, const char *set)" },
494 { 0xa0, 0x25, "int toupper(int c)" },
495 { 0xa0, 0x26, "int tolower(int c)" },
496 { 0xa0, 0x27, "void bcopy(const void *src, void *dst, size_t len)" },
497 { 0xa0, 0x28, "void bzero(void *ptr, size_t len)" },
498 { 0xa0, 0x29, "int bcmp(const void *ptr1, const void *ptr2, int len)" },
499 { 0xa0, 0x2a, "void *memcpy(void *dst, const void *src, size_t n)" },
500 { 0xa0, 0x2b, "void *memset(void *dst, char c, size_t n)" },
501 { 0xa0, 0x2c, "void *memmove(void *dst, const void *src, size_t n)" },
502 { 0xa0, 0x2d, "int memcmp(const void *dst, const void *src, size_t n)" },
503 { 0xa0, 0x2e, "void *memchr(const void *s, int c, size_t n)" },
504 { 0xa0, 0x2f, "int rand()" },
505 { 0xa0, 0x30, "void srand(unsigned int seed)" },
506 { 0xa0, 0x31, "void qsort(void *base, int nel, int width, int (*cmp)(void *, void *))" },
507 { 0xa0, 0x32, "double strtod(const char *s, char **endptr)" },
508 { 0xa0, 0x33, "void *malloc(int size)" },
509 { 0xa0, 0x34, "void free(void *buf)" },
510 { 0xa0, 0x35, "void *lsearch(void *key, void *base, int belp, int width, int (*cmp)(void *, void *))" },
511 { 0xa0, 0x36, "void *bsearch(void *key, void *base, int nel, int size, int (*cmp)(void *, void *))" },
512 { 0xa0, 0x37, "void *calloc(int size, int n)" },
513 { 0xa0, 0x38, "void *realloc(void *buf, int n)" },
514 { 0xa0, 0x39, "InitHeap(void *block, int size)" },
515 { 0xa0, 0x3a, "void _exit(int code)" },
516 { 0xa0, 0x3b, "char getchar(void)" },
517 { 0xa0, 0x3c, "void putchar(char c)" },
518 { 0xa0, 0x3d, "char *gets(char *s)" },
519 { 0xa0, 0x3e, "void puts(const char *s)" },
520 { 0xa0, 0x3f, "int printf(const char *fmt, ...)" },
521 { 0xa0, 0x40, "sys_a0_40()" },
522 { 0xa0, 0x41, "int LoadTest(const char *name, struct EXEC *header)" },
523 { 0xa0, 0x42, "int Load(const char *name, struct EXEC *header)" },
524 { 0xa0, 0x43, "int Exec(struct EXEC *header, int argc, char **argv)" },
525 { 0xa0, 0x44, "void FlushCache()" },
526 { 0xa0, 0x45, "void InstallInterruptHandler()" },
527 { 0xa0, 0x46, "GPU_dw(int x, int y, int w, int h, long *data)" },
528 { 0xa0, 0x47, "mem2vram(int x, int y, int w, int h, long *data)" },
529 { 0xa0, 0x48, "SendGPU(int status)" },
530 { 0xa0, 0x49, "GPU_cw(long cw)" },
531 { 0xa0, 0x4a, "GPU_cwb(long *pkt, int len)" },
532 { 0xa0, 0x4b, "SendPackets(void *ptr)" },
533 { 0xa0, 0x4c, "sys_a0_4c()" },
534 { 0xa0, 0x4d, "int GetGPUStatus()" },
535 { 0xa0, 0x4e, "GPU_sync()" },
536 { 0xa0, 0x4f, "sys_a0_4f()" },
537 { 0xa0, 0x50, "sys_a0_50()" },
538 { 0xa0, 0x51, "int LoadExec(const char *name, int, int)" },
539 { 0xa0, 0x52, "GetSysSp()" },
540 { 0xa0, 0x53, "sys_a0_53()" },
541 { 0xa0, 0x54, "_96_init()" },
542 { 0xa0, 0x55, "_bu_init()" },
543 { 0xa0, 0x56, "_96_remove()" },
544 { 0xa0, 0x57, "sys_a0_57()" },
545 { 0xa0, 0x58, "sys_a0_58()" },
546 { 0xa0, 0x59, "sys_a0_59()" },
547 { 0xa0, 0x5a, "sys_a0_5a()" },
548 { 0xa0, 0x5b, "dev_tty_init()" },
549 { 0xa0, 0x5c, "dev_tty_open()" },
550 { 0xa0, 0x5d, "dev_tty_5d()" },
551 { 0xa0, 0x5e, "dev_tty_ioctl()" },
552 { 0xa0, 0x5f, "dev_cd_open()" },
553 { 0xa0, 0x60, "dev_cd_read()" },
554 { 0xa0, 0x61, "dev_cd_close()" },
555 { 0xa0, 0x62, "dev_cd_firstfile()" },
556 { 0xa0, 0x63, "dev_cd_nextfile()" },
557 { 0xa0, 0x64, "dev_cd_chdir()" },
558 { 0xa0, 0x65, "dev_card_open()" },
559 { 0xa0, 0x66, "dev_card_read()" },
560 { 0xa0, 0x67, "dev_card_write()" },
561 { 0xa0, 0x68, "dev_card_close()" },
562 { 0xa0, 0x69, "dev_card_firstfile()" },
563 { 0xa0, 0x6a, "dev_card_nextfile()" },
564 { 0xa0, 0x6b, "dev_card_erase()" },
565 { 0xa0, 0x6c, "dev_card_undelete()" },
566 { 0xa0, 0x6d, "dev_card_format()" },
567 { 0xa0, 0x6e, "dev_card_rename()" },
568 { 0xa0, 0x6f, "dev_card_6f()" },
569 { 0xa0, 0x70, "_bu_init()" },
570 { 0xa0, 0x71, "_96_init()" },
571 { 0xa0, 0x72, "_96_remove()" },
572 { 0xa0, 0x73, "sys_a0_73()" },
573 { 0xa0, 0x74, "sys_a0_74()" },
574 { 0xa0, 0x75, "sys_a0_75()" },
575 { 0xa0, 0x76, "sys_a0_76()" },
576 { 0xa0, 0x77, "sys_a0_77()" },
577 { 0xa0, 0x78, "_96_CdSeekL()" },
578 { 0xa0, 0x79, "sys_a0_79()" },
579 { 0xa0, 0x7a, "sys_a0_7a()" },
580 { 0xa0, 0x7b, "sys_a0_7b()" },
581 { 0xa0, 0x7c, "_96_CdGetStatus()" },
582 { 0xa0, 0x7d, "sys_a0_7d()" },
583 { 0xa0, 0x7e, "_96_CdRead()" },
584 { 0xa0, 0x7f, "sys_a0_7f()" },
585 { 0xa0, 0x80, "sys_a0_80()" },
586 { 0xa0, 0x81, "sys_a0_81()" },
587 { 0xa0, 0x82, "sys_a0_82()" },
588 { 0xa0, 0x83, "sys_a0_83()" },
589 { 0xa0, 0x84, "sys_a0_84()" },
590 { 0xa0, 0x85, "_96_CdStop()" },
591 { 0xa0, 0x84, "sys_a0_84()" },
592 { 0xa0, 0x85, "sys_a0_85()" },
593 { 0xa0, 0x86, "sys_a0_86()" },
594 { 0xa0, 0x87, "sys_a0_87()" },
595 { 0xa0, 0x88, "sys_a0_88()" },
596 { 0xa0, 0x89, "sys_a0_89()" },
597 { 0xa0, 0x8a, "sys_a0_8a()" },
598 { 0xa0, 0x8b, "sys_a0_8b()" },
599 { 0xa0, 0x8c, "sys_a0_8c()" },
600 { 0xa0, 0x8d, "sys_a0_8d()" },
601 { 0xa0, 0x8e, "sys_a0_8e()" },
602 { 0xa0, 0x8f, "sys_a0_8f()" },
603 { 0xa0, 0x90, "sys_a0_90()" },
604 { 0xa0, 0x91, "sys_a0_91()" },
605 { 0xa0, 0x92, "sys_a0_92()" },
606 { 0xa0, 0x93, "sys_a0_93()" },
607 { 0xa0, 0x94, "sys_a0_94()" },
608 { 0xa0, 0x95, "sys_a0_95()" },
609 { 0xa0, 0x96, "AddCDROMDevice()" },
610 { 0xa0, 0x97, "AddMemCardDevice()" },
611 { 0xa0, 0x98, "DisableKernelIORedirection()" },
612 { 0xa0, 0x99, "EnableKernelIORedirection()" },
613 { 0xa0, 0x9a, "sys_a0_9a()" },
614 { 0xa0, 0x9b, "sys_a0_9b()" },
615 { 0xa0, 0x9c, "void SetConf(int Event, int TCB, int Stack)" },
616 { 0xa0, 0x9d, "void GetConf(int *Event, int *TCB, int *Stack)" },
617 { 0xa0, 0x9e, "sys_a0_9e()" },
618 { 0xa0, 0x9f, "void SetMem(int size)" },
619 { 0xa0, 0xa0, "_boot()" },
620 { 0xa0, 0xa1, "SystemError()" },
621 { 0xa0, 0xa2, "EnqueueCdIntr()" },
622 { 0xa0, 0xa3, "DequeueCdIntr()" },
623 { 0xa0, 0xa4, "sys_a0_a4()" },
624 { 0xa0, 0xa5, "ReadSector(int count, int sector, void *buffer)" },
625 { 0xa0, 0xa6, "get_cd_status()" },
626 { 0xa0, 0xa7, "bufs_cb_0()" },
627 { 0xa0, 0xa8, "bufs_cb_1()" },
628 { 0xa0, 0xa9, "bufs_cb_2()" },
629 { 0xa0, 0xaa, "bufs_cb_3()" },
630 { 0xa0, 0xab, "_card_info()" },
631 { 0xa0, 0xac, "_card_load()" },
632 { 0xa0, 0xad, "_card_auto()" },
633 { 0xa0, 0xae, "bufs_cb_4()" },
634 { 0xa0, 0xaf, "sys_a0_af()" },
635 { 0xa0, 0xb0, "sys_a0_b0()" },
636 { 0xa0, 0xb1, "sys_a0_b1()" },
637 { 0xa0, 0xb2, "do_a_long_jmp()" },
638 { 0xa0, 0xb3, "sys_a0_b3()" },
639 { 0xa0, 0xb4, "GetKernelInfo(int sub_function)" },
640 { 0xb0, 0x00, "SysMalloc()" },
641 { 0xb0, 0x01, "sys_b0_01()" },
642 { 0xb0, 0x02, "sys_b0_02()" },
643 { 0xb0, 0x03, "sys_b0_03()" },
644 { 0xb0, 0x04, "sys_b0_04()" },
645 { 0xb0, 0x05, "sys_b0_05()" },
646 { 0xb0, 0x06, "sys_b0_06()" },
647 { 0xb0, 0x07, "void DeliverEvent(u_long class, u_long event)" },
648 { 0xb0, 0x08, "long OpenEvent(u_long class, long spec, long mode, long (*func)())" },
649 { 0xb0, 0x09, "long CloseEvent(long event)" },
650 { 0xb0, 0x0a, "long WaitEvent(long event)" },
651 { 0xb0, 0x0b, "long TestEvent(long event)" },
652 { 0xb0, 0x0c, "long EnableEvent(long event)" },
653 { 0xb0, 0x0d, "long DisableEvent(long event)" },
654 { 0xb0, 0x0e, "OpenTh()" },
655 { 0xb0, 0x0f, "CloseTh()" },
656 { 0xb0, 0x10, "ChangeTh()" },
657 { 0xb0, 0x11, "sys_b0_11()" },
658 { 0xb0, 0x12, "int InitPAD(char *buf1, int len1, char *buf2, int len2)" },
659 { 0xb0, 0x13, "int StartPAD(void)" },
660 { 0xb0, 0x14, "int StopPAD(void)" },
661 { 0xb0, 0x15, "PAD_init(u_long nazo, u_long *pad_buf)" },
662 { 0xb0, 0x16, "u_long PAD_dr()" },
663 { 0xb0, 0x17, "void ReturnFromException(void)" },
664 { 0xb0, 0x18, "ResetEntryInt()" },
665 { 0xb0, 0x19, "HookEntryInt()" },
666 { 0xb0, 0x1a, "sys_b0_1a()" },
667 { 0xb0, 0x1b, "sys_b0_1b()" },
668 { 0xb0, 0x1c, "sys_b0_1c()" },
669 { 0xb0, 0x1d, "sys_b0_1d()" },
670 { 0xb0, 0x1e, "sys_b0_1e()" },
671 { 0xb0, 0x1f, "sys_b0_1f()" },
672 { 0xb0, 0x20, "UnDeliverEvent(int class, int event)" },
673 { 0xb0, 0x21, "sys_b0_21()" },
674 { 0xb0, 0x22, "sys_b0_22()" },
675 { 0xb0, 0x23, "sys_b0_23()" },
676 { 0xb0, 0x24, "sys_b0_24()" },
677 { 0xb0, 0x25, "sys_b0_25()" },
678 { 0xb0, 0x26, "sys_b0_26()" },
679 { 0xb0, 0x27, "sys_b0_27()" },
680 { 0xb0, 0x28, "sys_b0_28()" },
681 { 0xb0, 0x29, "sys_b0_29()" },
682 { 0xb0, 0x2a, "sys_b0_2a()" },
683 { 0xb0, 0x2b, "sys_b0_2b()" },
684 { 0xb0, 0x2c, "sys_b0_2c()" },
685 { 0xb0, 0x2d, "sys_b0_2d()" },
686 { 0xb0, 0x2e, "sys_b0_2e()" },
687 { 0xb0, 0x2f, "sys_b0_2f()" },
688 { 0xb0, 0x2f, "sys_b0_30()" },
689 { 0xb0, 0x31, "sys_b0_31()" },
690 { 0xb0, 0x32, "int open(const char *name, int access)" },
691 { 0xb0, 0x33, "int lseek(int fd, long pos, int seektype)" },
692 { 0xb0, 0x34, "int read(int fd, void *buf, int nbytes)" },
693 { 0xb0, 0x35, "int write(int fd, void *buf, int nbytes)" },
694 { 0xb0, 0x36, "close(int fd)" },
695 { 0xb0, 0x37, "int ioctl(int fd, int cmd, int arg)" },
696 { 0xb0, 0x38, "exit(int exitcode)" },
697 { 0xb0, 0x39, "sys_b0_39()" },
698 { 0xb0, 0x3a, "char getc(int fd)" },
699 { 0xb0, 0x3b, "putc(int fd, char ch)" },
700 { 0xb0, 0x3c, "char getchar(void)" },
701 { 0xb0, 0x3d, "putchar(char ch)" },
702 { 0xb0, 0x3e, "char *gets(char *s)" },
703 { 0xb0, 0x3f, "puts(const char *s)" },
704 { 0xb0, 0x40, "int cd(const char *path)" },
705 { 0xb0, 0x41, "int format(const char *fs)" },
706 { 0xb0, 0x42, "struct DIRENTRY* firstfile(const char *name, struct DIRENTRY *dir)" },
707 { 0xb0, 0x43, "struct DIRENTRY* nextfile(struct DIRENTRY *dir)" },
708 { 0xb0, 0x44, "int rename(const char *oldname, const char *newname)" },
709 { 0xb0, 0x45, "int delete(const char *name)" },
710 { 0xb0, 0x46, "undelete()" },
711 { 0xb0, 0x47, "AddDevice()" },
712 { 0xb0, 0x48, "RemoveDevice()" },
713 { 0xb0, 0x49, "PrintInstalledDevices()" },
714 { 0xb0, 0x4a, "InitCARD()" },
715 { 0xb0, 0x4b, "StartCARD()" },
716 { 0xb0, 0x4c, "StopCARD()" },
717 { 0xb0, 0x4d, "sys_b0_4d()" },
718 { 0xb0, 0x4e, "_card_write()" },
719 { 0xb0, 0x4f, "_card_read()" },
720 { 0xb0, 0x50, "_new_card()" },
721 { 0xb0, 0x51, "void *Krom2RawAdd(int code)" },
722 { 0xb0, 0x52, "sys_b0_52()" },
723 { 0xb0, 0x53, "sys_b0_53()" },
724 { 0xb0, 0x54, "long _get_errno(void)" },
725 { 0xb0, 0x55, "long _get_error(long fd)" },
726 { 0xb0, 0x56, "GetC0Table()" },
727 { 0xb0, 0x57, "GetB0Table()" },
728 { 0xb0, 0x58, "_card_chan()" },
729 { 0xb0, 0x59, "sys_b0_59()" },
730 { 0xb0, 0x5a, "sys_b0_5a()" },
731 { 0xb0, 0x5b, "ChangeClearPAD(int, int)" },
732 { 0xb0, 0x5c, "_card_status()" },
733 { 0xb0, 0x5d, "_card_wait()" },
734 { 0xc0, 0x00, "InitRCnt()" },
735 { 0xc0, 0x01, "InitException()" },
736 { 0xc0, 0x02, "SysEnqIntRP(int index, long *queue)" },
737 { 0xc0, 0x03, "SysDeqIntRP(int index, long *queue)" },
738 { 0xc0, 0x04, "int get_free_EvCB_slot(void)" },
739 { 0xc0, 0x05, "get_free_TCB_slot()" },
740 { 0xc0, 0x06, "ExceptionHandler()" },
741 { 0xc0, 0x07, "InstallExceptionHandlers()" },
742 { 0xc0, 0x08, "SysInitMemory()" },
743 { 0xc0, 0x09, "SysInitKMem()" },
744 { 0xc0, 0x0a, "ChangeClearRCnt()" },
745 { 0xc0, 0x0b, "SystemError()" },
746 { 0xc0, 0x0c, "InitDefInt()" },
747 { 0xc0, 0x0d, "sys_c0_0d()" },
748 { 0xc0, 0x0e, "sys_c0_0e()" },
749 { 0xc0, 0x0f, "sys_c0_0f()" },
750 { 0xc0, 0x10, "sys_c0_10()" },
751 { 0xc0, 0x11, "sys_c0_11()" },
752 { 0xc0, 0x12, "InstallDevices()" },
753 { 0xc0, 0x13, "FlushStdInOutPut()" },
754 { 0xc0, 0x14, "sys_c0_14()" },
755 { 0xc0, 0x15, "_cdevinput()" },
756 { 0xc0, 0x16, "_cdevscan()" },
757 { 0xc0, 0x17, "char _circgetc(struct device_buf *circ)" },
758 { 0xc0, 0x18, "_circputc(char c, struct device_buf *circ)" },
759 { 0xc0, 0x19, "ioabort(const char *str)" },
760 { 0xc0, 0x1a, "sys_c0_1a()" },
761 { 0xc0, 0x1b, "KernelRedirect(int flag)" },
762 { 0xc0, 0x1c, "PatchA0Table()" },
763 { 0x00, 0x00, nullptr }
764 };
765
log_bioscall_parameter(int parm)766 uint32_t psxcpu_device::log_bioscall_parameter( int parm )
767 {
768 if( parm < 4 )
769 {
770 return m_r[ 4 + parm ];
771 }
772
773 return readword( m_r[ 29 ] + ( parm * 4 ) );
774 }
775
log_bioscall_string(int parm)776 const char *psxcpu_device::log_bioscall_string( int parm )
777 {
778 int pos;
779 uint32_t address;
780 static char string[ 1024 ];
781
782 address = log_bioscall_parameter( parm );
783 if( address == 0 )
784 {
785 return "NULL";
786 }
787
788 pos = 0;
789 string[ pos++ ] = '\"';
790
791 for( ;; )
792 {
793 uint8_t c = readbyte( address );
794 if( c == 0 )
795 {
796 break;
797 }
798 else if( c == '\t' )
799 {
800 string[ pos++ ] = '\\';
801 string[ pos++ ] = 't';
802 }
803 else if( c == '\r' )
804 {
805 string[ pos++ ] = '\\';
806 string[ pos++ ] = 'r';
807 }
808 else if( c == '\n' )
809 {
810 string[ pos++ ] = '\\';
811 string[ pos++ ] = 'n';
812 }
813 else if( c < 32 || c > 127 )
814 {
815 string[ pos++ ] = '\\';
816 string[ pos++ ] = ( ( c / 64 ) % 8 ) + '0';
817 string[ pos++ ] = ( ( c / 8 ) % 8 ) + '0';
818 string[ pos++ ] = ( ( c / 1 ) % 8 ) + '0';
819 }
820 else
821 {
822 string[ pos++ ] = c;
823 }
824 address++;
825 }
826
827 string[ pos++ ] = '\"';
828 string[ pos++ ] = 0;
829
830 return string;
831 }
832
log_bioscall_hex(int parm)833 const char *psxcpu_device::log_bioscall_hex( int parm )
834 {
835 static char string[ 1024 ];
836
837 sprintf( string, "0x%08x", log_bioscall_parameter( parm ) );
838
839 return string;
840 }
841
log_bioscall_char(int parm)842 const char *psxcpu_device::log_bioscall_char( int parm )
843 {
844 int c;
845 static char string[ 1024 ];
846
847 c = log_bioscall_parameter( parm );
848 if( c < 32 || c > 127 )
849 {
850 sprintf( string, "0x%02x", c );
851 }
852 else
853 {
854 sprintf( string, "'%c'", c );
855 }
856
857 return string;
858 }
859
log_bioscall()860 void psxcpu_device::log_bioscall()
861 {
862 int address = m_pc - 0x04;
863 if( address == 0xa0 ||
864 address == 0xb0 ||
865 address == 0xc0 )
866 {
867 char buf[ 1024 ];
868 int operation = m_r[ 9 ] & 0xff;
869 int bioscall = 0;
870
871 if( ( address == 0xa0 && operation == 0x3c ) ||
872 ( address == 0xb0 && operation == 0x3d ) )
873 {
874 putchar( log_bioscall_parameter( 0 ) );
875 }
876
877 if( ( address == 0xa0 && operation == 0x03 ) ||
878 ( address == 0xb0 && operation == 0x35 ) )
879 {
880 int fd = log_bioscall_parameter( 0 );
881 int buffer = log_bioscall_parameter( 1 );
882 int nbytes = log_bioscall_parameter( 2 );
883
884 if( fd == 1 )
885 {
886 while( nbytes > 0 )
887 {
888 uint8_t c = readbyte( buffer );
889 putchar( c );
890 nbytes--;
891 buffer++;
892 }
893 }
894 }
895
896 while( bioscalls[ bioscall ].prototype != nullptr &&
897 ( bioscalls[ bioscall ].address != address ||
898 bioscalls[ bioscall ].operation != operation ) )
899 {
900 bioscall++;
901 }
902
903 if( bioscalls[ bioscall ].prototype != nullptr )
904 {
905 const char *prototype = bioscalls[ bioscall ].prototype;
906 const char *parmstart = nullptr;
907 int parm = 0;
908 int parmlen = -1;
909 int brackets = 0;
910 int pos = 0;
911
912 while( *( prototype ) != 0 )
913 {
914 int ch = *( prototype );
915
916 switch( ch )
917 {
918 case '(':
919 brackets++;
920 prototype++;
921 if( brackets == 1 )
922 {
923 buf[ pos++ ] = ch;
924 parmstart = prototype;
925 }
926 break;
927
928 case ')':
929 if( brackets == 1 )
930 {
931 parmlen = prototype - parmstart;
932 }
933 prototype++;
934 brackets--;
935 break;
936
937 case ',':
938 if( brackets == 1 )
939 {
940 parmlen = prototype - parmstart;
941 }
942 prototype++;
943 break;
944
945 default:
946 if( brackets == 0 )
947 {
948 buf[ pos++ ] = ch;
949 }
950 prototype++;
951 break;
952 }
953
954 if( parmlen >= 0 )
955 {
956 while( parmlen > 0 && parmstart[ 0 ] == ' ' )
957 {
958 parmstart++;
959 parmlen--;
960 }
961 while( parmlen > 0 && parmstart[ parmlen - 1 ] == ' ' )
962 {
963 parmlen--;
964 }
965
966 if( parmlen == 0 ||
967 ( parmlen == 4 && memcmp( parmstart, "void", 4 ) == 0 ) )
968 {
969 parm = -1;
970 }
971 else if( parmlen == 3 && memcmp( parmstart, "...", 3 ) == 0 )
972 {
973 if( parm > 0 )
974 {
975 uint32_t format = log_bioscall_parameter( parm - 1 );
976 const char *parmstr = nullptr;
977 int percent = 0;
978
979 for( ;; )
980 {
981 uint8_t c = readbyte( format );
982 if( c == 0 )
983 {
984 break;
985 }
986 if( percent == 0 )
987 {
988 if( c == '%' )
989 {
990 percent = 1;
991 }
992 }
993 else
994 {
995 if( c == '%' )
996 {
997 percent = 0;
998 }
999 else if( c == '*' )
1000 {
1001 parmstr = log_bioscall_hex( parm );
1002 }
1003 else if( c == 's' )
1004 {
1005 parmstr = log_bioscall_string( parm );
1006 percent = 0;
1007 }
1008 else if( c == 'c' )
1009 {
1010 parmstr = log_bioscall_char( parm );
1011 percent = 0;
1012 }
1013 else if( c != '-' && c != '.' && c != 'l' && ( c < '0' || c > '9' ) )
1014 {
1015 parmstr = log_bioscall_hex( parm );
1016 percent = 0;
1017 }
1018 }
1019
1020 if( parmstr != nullptr )
1021 {
1022 if( parm > 0 )
1023 {
1024 buf[ pos++ ] = ',';
1025 }
1026 buf[ pos++ ] = ' ';
1027
1028 strcpy( &buf[ pos ], parmstr );
1029 pos += strlen( parmstr );
1030 parmstr = nullptr;
1031
1032 parm++;
1033 }
1034 format++;
1035 }
1036 }
1037 }
1038 else if( parmlen > 0 )
1039 {
1040 const char *parmstr;
1041
1042 int typelen = parmlen;
1043 while( typelen > 0 && parmstart[ typelen - 1 ] != ' ' && parmstart[ typelen - 1 ] != '*' )
1044 {
1045 typelen--;
1046 }
1047
1048 if( typelen == 5 && memcmp( parmstart, "char ", 5 ) == 0 )
1049 {
1050 parmstr = log_bioscall_char( parm );
1051 }
1052 else if( typelen == 12 && memcmp( parmstart, "const char *", 12 ) == 0 )
1053 {
1054 parmstr = log_bioscall_string( parm );
1055 }
1056 else
1057 {
1058 parmstr = log_bioscall_hex( parm );
1059 }
1060
1061 if( parm > 0 )
1062 {
1063 buf[ pos++ ] = ',';
1064 }
1065 buf[ pos++ ] = ' ';
1066
1067 strcpy( &buf[ pos ], parmstr );
1068 pos += strlen( parmstr );
1069 }
1070
1071 parmlen = -1;
1072 parm++;
1073
1074 if( ch == ',' )
1075 {
1076 parmstart = prototype;
1077 }
1078 else
1079 {
1080 if( parm > 0 )
1081 {
1082 buf[ pos++ ] = ' ';
1083 }
1084 buf[ pos++ ] = ch;
1085 }
1086 }
1087 }
1088 buf[ pos ] = 0;
1089 }
1090 else
1091 {
1092 sprintf( buf, "unknown_%02x_%02x", address, operation );
1093 }
1094 logerror( "%08x: bioscall %s\n", (unsigned int)m_r[ 31 ] - 8, buf );
1095 }
1096 }
1097
log_syscall()1098 void psxcpu_device::log_syscall()
1099 {
1100 char buf[ 1024 ];
1101 int operation = m_r[ 4 ];
1102
1103 switch( operation )
1104 {
1105 case 0:
1106 strcpy( buf, "void Exception()" );
1107 break;
1108
1109 case 1:
1110 strcpy( buf, "void EnterCriticalSection()" );
1111 break;
1112
1113 case 2:
1114 strcpy( buf, "void ExitCriticalSection()" );
1115 break;
1116
1117 default:
1118 sprintf( buf, "unknown_%02x", operation );
1119 break;
1120 }
1121 logerror( "%08x: syscall %s\n", (unsigned int)m_r[ 31 ] - 8, buf );
1122 }
1123
update_memory_handlers()1124 void psxcpu_device::update_memory_handlers()
1125 {
1126 if( ( m_cp0r[ CP0_SR ] & SR_ISC ) != 0 )
1127 {
1128 m_bus_attached = 0;
1129 }
1130 else
1131 {
1132 m_bus_attached = 1;
1133 }
1134 }
1135
funct_mthi()1136 void psxcpu_device::funct_mthi()
1137 {
1138 m_multiplier_operation = MULTIPLIER_OPERATION_IDLE;
1139 m_hi = m_r[ INS_RS( m_op ) ];
1140 }
1141
funct_mtlo()1142 void psxcpu_device::funct_mtlo()
1143 {
1144 m_multiplier_operation = MULTIPLIER_OPERATION_IDLE;
1145 m_lo = m_r[ INS_RS( m_op ) ];
1146 }
1147
funct_mult()1148 void psxcpu_device::funct_mult()
1149 {
1150 m_multiplier_operation = MULTIPLIER_OPERATION_MULT;
1151 m_multiplier_operand1 = m_r[ INS_RS( m_op ) ];
1152 m_multiplier_operand2 = m_r[ INS_RT( m_op ) ];
1153 m_lo = m_multiplier_operand1;
1154 }
1155
funct_multu()1156 void psxcpu_device::funct_multu()
1157 {
1158 m_multiplier_operation = MULTIPLIER_OPERATION_MULTU;
1159 m_multiplier_operand1 = m_r[ INS_RS( m_op ) ];
1160 m_multiplier_operand2 = m_r[ INS_RT( m_op ) ];
1161 m_lo = m_multiplier_operand1;
1162 }
1163
funct_div()1164 void psxcpu_device::funct_div()
1165 {
1166 m_multiplier_operation = MULTIPLIER_OPERATION_DIV;
1167 m_multiplier_operand1 = m_r[ INS_RS( m_op ) ];
1168 m_multiplier_operand2 = m_r[ INS_RT( m_op ) ];
1169 m_lo = m_multiplier_operand1;
1170 m_hi = 0;
1171 }
1172
funct_divu()1173 void psxcpu_device::funct_divu()
1174 {
1175 m_multiplier_operation = MULTIPLIER_OPERATION_DIVU;
1176 m_multiplier_operand1 = m_r[ INS_RS( m_op ) ];
1177 m_multiplier_operand2 = m_r[ INS_RT( m_op ) ];
1178 m_lo = m_multiplier_operand1;
1179 m_hi = 0;
1180 }
1181
multiplier_update()1182 void psxcpu_device::multiplier_update()
1183 {
1184 switch( m_multiplier_operation )
1185 {
1186 case MULTIPLIER_OPERATION_MULT:
1187 {
1188 int64_t result = mul_32x32( (int32_t)m_multiplier_operand1, (int32_t)m_multiplier_operand2 );
1189 m_lo = extract_64lo( result );
1190 m_hi = extract_64hi( result );
1191 }
1192 break;
1193
1194 case MULTIPLIER_OPERATION_MULTU:
1195 {
1196 uint64_t result = mulu_32x32( m_multiplier_operand1, m_multiplier_operand2 );
1197 m_lo = extract_64lo( result );
1198 m_hi = extract_64hi( result );
1199 }
1200 break;
1201
1202 case MULTIPLIER_OPERATION_DIV:
1203 if( m_multiplier_operand1 == 0x80000000 && m_multiplier_operand2 == 0xffffffff)
1204 {
1205 m_hi = 0x00000000;
1206 m_lo = 0x80000000;
1207 }
1208 else if( m_multiplier_operand2 == 0 )
1209 {
1210 if( (int32_t)m_multiplier_operand1 < 0 )
1211 {
1212 m_lo = 1;
1213 }
1214 else
1215 {
1216 m_lo = 0xffffffff;
1217 }
1218
1219 m_hi = m_multiplier_operand1;
1220 }
1221 else
1222 {
1223 m_lo = (int32_t)m_multiplier_operand1 / (int32_t)m_multiplier_operand2;
1224 m_hi = (int32_t)m_multiplier_operand1 % (int32_t)m_multiplier_operand2;
1225 }
1226 break;
1227
1228 case MULTIPLIER_OPERATION_DIVU:
1229 if( m_multiplier_operand2 == 0 )
1230 {
1231 m_lo = 0xffffffff;
1232 m_hi = m_multiplier_operand1;
1233 }
1234 else
1235 {
1236 m_lo = m_multiplier_operand1 / m_multiplier_operand2;
1237 m_hi = m_multiplier_operand1 % m_multiplier_operand2;
1238 }
1239 break;
1240 }
1241
1242 m_multiplier_operation = MULTIPLIER_OPERATION_IDLE;
1243 }
1244
get_hi()1245 uint32_t psxcpu_device::get_hi()
1246 {
1247 if( m_multiplier_operation != MULTIPLIER_OPERATION_IDLE )
1248 {
1249 multiplier_update();
1250 }
1251
1252 return m_hi;
1253 }
1254
get_lo()1255 uint32_t psxcpu_device::get_lo()
1256 {
1257 if( m_multiplier_operation != MULTIPLIER_OPERATION_IDLE )
1258 {
1259 multiplier_update();
1260 }
1261
1262 return m_lo;
1263 }
1264
execute_unstoppable_instructions(int executeCop2)1265 int psxcpu_device::execute_unstoppable_instructions( int executeCop2 )
1266 {
1267 switch( INS_OP( m_op ) )
1268 {
1269 case OP_SPECIAL:
1270 switch( INS_FUNCT( m_op ) )
1271 {
1272 case FUNCT_MTHI:
1273 funct_mthi();
1274 break;
1275
1276 case FUNCT_MTLO:
1277 funct_mtlo();
1278 break;
1279
1280 case FUNCT_MULT:
1281 funct_mult();
1282 break;
1283
1284 case FUNCT_MULTU:
1285 funct_multu();
1286 break;
1287
1288 case FUNCT_DIV:
1289 funct_div();
1290 break;
1291
1292 case FUNCT_DIVU:
1293 funct_divu();
1294 break;
1295 }
1296 break;
1297
1298 case OP_COP2:
1299 if( executeCop2 )
1300 {
1301 switch( INS_CO( m_op ) )
1302 {
1303 case 1:
1304 if( ( m_cp0r[ CP0_SR ] & SR_CU2 ) == 0 )
1305 {
1306 return 0;
1307 }
1308
1309 if( !m_gte.docop2( m_pc, INS_COFUN( m_op ) ) )
1310 {
1311 stop();
1312 }
1313 break;
1314 }
1315 }
1316 }
1317
1318 return 1;
1319 }
1320
update_address_masks()1321 void psxcpu_device::update_address_masks()
1322 {
1323 if( ( m_cp0r[ CP0_SR ] & SR_KUC ) != 0 )
1324 {
1325 m_bad_byte_address_mask = 0x80000000;
1326 m_bad_half_address_mask = 0x80000001;
1327 m_bad_word_address_mask = 0x80000003;
1328 }
1329 else
1330 {
1331 m_bad_byte_address_mask = 0;
1332 m_bad_half_address_mask = 1;
1333 m_bad_word_address_mask = 3;
1334 }
1335 }
1336
update_scratchpad()1337 void psxcpu_device::update_scratchpad()
1338 {
1339 if( ( m_biu & BIU_RAM ) == 0 )
1340 {
1341 m_program->install_readwrite_handler( 0x1f800000, 0x1f8003ff, read32smo_delegate(*this, FUNC(psxcpu_device::berr_r)), write32smo_delegate(*this, FUNC(psxcpu_device::berr_w)) );
1342 }
1343 else if( ( m_biu & BIU_DS ) == 0 )
1344 {
1345 m_program->install_read_handler( 0x1f800000, 0x1f8003ff, read32smo_delegate(*this, FUNC(psxcpu_device::berr_r)) );
1346 m_program->nop_write( 0x1f800000, 0x1f8003ff );
1347 }
1348 else
1349 {
1350 m_program->install_ram( 0x1f800000, 0x1f8003ff, m_dcache );
1351 }
1352 }
1353
update_ram_config()1354 void psxcpu_device::update_ram_config()
1355 {
1356 /// TODO: find out what these values really control and confirm they are the same on each cpu type.
1357
1358 int window_size = 0;
1359 switch( ( m_ram_config >> 8 ) & 0xf )
1360 {
1361 case 0x8: // konami gv
1362 window_size = 0x0200000;
1363 break;
1364
1365 case 0xc: // zn1/konami gq/namco system 11/twinkle/system 573
1366 window_size = 0x0400000;
1367 break;
1368
1369 case 0x3: // zn2
1370 case 0xb: // console/primal rage 2
1371 window_size = 0x0800000;
1372 break;
1373
1374 case 0xf: // namco system 10/namco system 12
1375 window_size = 0x1000000;
1376 break;
1377 }
1378
1379 uint32_t ram_size = m_ram->size();
1380 uint8_t *pointer = m_ram->pointer();
1381
1382 if( ram_size > window_size )
1383 {
1384 ram_size = window_size;
1385 }
1386
1387 if( ram_size > 0 )
1388 {
1389 int start = 0;
1390 while( start < window_size )
1391 {
1392 m_program->install_ram( start + 0x00000000, start + 0x00000000 + ram_size - 1, pointer );
1393 m_program->install_ram( start + 0x80000000, start + 0x80000000 + ram_size - 1, pointer );
1394 m_program->install_ram( start + 0xa0000000, start + 0xa0000000 + ram_size - 1, pointer );
1395
1396 start += ram_size;
1397 }
1398 }
1399
1400 m_program->install_readwrite_handler( 0x00000000 + window_size, 0x1effffff, read32smo_delegate(*this, FUNC(psxcpu_device::berr_r)), write32smo_delegate(*this, FUNC(psxcpu_device::berr_w)) );
1401 m_program->install_readwrite_handler( 0x80000000 + window_size, 0x9effffff, read32smo_delegate(*this, FUNC(psxcpu_device::berr_r)), write32smo_delegate(*this, FUNC(psxcpu_device::berr_w)) );
1402 m_program->install_readwrite_handler( 0xa0000000 + window_size, 0xbeffffff, read32smo_delegate(*this, FUNC(psxcpu_device::berr_r)), write32smo_delegate(*this, FUNC(psxcpu_device::berr_w)) );
1403 }
1404
update_rom_config()1405 void psxcpu_device::update_rom_config()
1406 {
1407 int window_size = 1 << ( ( m_rom_config >> 16 ) & 0x1f );
1408 int max_window_size = 0x400000;
1409 if( window_size > max_window_size )
1410 {
1411 window_size = max_window_size;
1412 }
1413
1414 uint32_t rom_size = m_rom->bytes();
1415 uint8_t *pointer = m_rom->base();
1416
1417 if( rom_size > window_size )
1418 {
1419 rom_size = window_size;
1420 }
1421
1422 if( rom_size > 0 )
1423 {
1424 int start = 0;
1425 while( start < window_size )
1426 {
1427 m_program->install_rom( start + 0x1fc00000, start + 0x1fc00000 + rom_size - 1, pointer );
1428 m_program->install_rom( start + 0x9fc00000, start + 0x9fc00000 + rom_size - 1, pointer );
1429 m_program->install_rom( start + 0xbfc00000, start + 0xbfc00000 + rom_size - 1, pointer );
1430
1431 start += rom_size;
1432 }
1433 }
1434
1435 if( window_size < max_window_size && !m_disable_rom_berr)
1436 {
1437 m_program->install_readwrite_handler( 0x1fc00000 + window_size, 0x1fffffff, read32smo_delegate(*this, FUNC(psxcpu_device::berr_r)), write32smo_delegate(*this, FUNC(psxcpu_device::berr_w)) );
1438 m_program->install_readwrite_handler( 0x9fc00000 + window_size, 0x9fffffff, read32smo_delegate(*this, FUNC(psxcpu_device::berr_r)), write32smo_delegate(*this, FUNC(psxcpu_device::berr_w)) );
1439 m_program->install_readwrite_handler( 0xbfc00000 + window_size, 0xbfffffff, read32smo_delegate(*this, FUNC(psxcpu_device::berr_r)), write32smo_delegate(*this, FUNC(psxcpu_device::berr_w)) );
1440 }
1441 }
1442
update_cop0(int reg)1443 void psxcpu_device::update_cop0(int reg)
1444 {
1445 if (reg == CP0_SR)
1446 {
1447 update_memory_handlers();
1448 update_address_masks();
1449 }
1450
1451 if ((reg == CP0_SR || reg == CP0_CAUSE) &&
1452 (m_cp0r[CP0_SR] & SR_IEC) != 0)
1453 {
1454 uint32_t ip = m_cp0r[CP0_SR] & m_cp0r[CP0_CAUSE] & CAUSE_IP;
1455 if (ip != 0)
1456 {
1457 if (ip & CAUSE_IP0) debugger_exception_hook(EXC_INT);
1458 if (ip & CAUSE_IP1) debugger_exception_hook(EXC_INT);
1459 //if (ip & CAUSE_IP2) debugger_interrupt_hook(PSXCPU_IRQ0);
1460 //if (ip & CAUSE_IP3) debugger_interrupt_hook(PSXCPU_IRQ1);
1461 //if (ip & CAUSE_IP4) debugger_interrupt_hook(PSXCPU_IRQ2);
1462 //if (ip & CAUSE_IP5) debugger_interrupt_hook(PSXCPU_IRQ3);
1463 //if (ip & CAUSE_IP6) debugger_interrupt_hook(PSXCPU_IRQ4);
1464 //if (ip & CAUSE_IP7) debugger_interrupt_hook(PSXCPU_IRQ5);
1465 m_op = m_instruction.read_dword(m_pc);
1466 execute_unstoppable_instructions(1);
1467 exception(EXC_INT);
1468 }
1469 }
1470 }
1471
commit_delayed_load()1472 void psxcpu_device::commit_delayed_load()
1473 {
1474 if( m_delayr != 0 )
1475 {
1476 m_r[ m_delayr ] = m_delayv;
1477 m_delayr = 0;
1478 m_delayv = 0;
1479 }
1480 }
1481
set_pc(unsigned pc)1482 void psxcpu_device::set_pc( unsigned pc )
1483 {
1484 m_pc = pc;
1485 }
1486
fetch_next_op()1487 void psxcpu_device::fetch_next_op()
1488 {
1489 if( m_delayr == PSXCPU_DELAYR_PC )
1490 {
1491 uint32_t safepc = m_delayv & ~m_bad_word_address_mask;
1492
1493 m_op = m_instruction.read_dword( safepc );
1494 }
1495 else
1496 {
1497 m_op = m_instruction.read_dword( m_pc + 4 );
1498 }
1499 }
1500
advance_pc()1501 void psxcpu_device::advance_pc()
1502 {
1503 if( m_delayr == PSXCPU_DELAYR_PC )
1504 {
1505 m_pc = m_delayv;
1506 m_delayr = 0;
1507 m_delayv = 0;
1508 }
1509 else if( m_delayr == PSXCPU_DELAYR_NOTPC )
1510 {
1511 m_delayr = 0;
1512 m_delayv = 0;
1513 m_pc += 4;
1514 }
1515 else
1516 {
1517 commit_delayed_load();
1518 m_pc += 4;
1519 }
1520 }
1521
load(uint32_t reg,uint32_t value)1522 void psxcpu_device::load( uint32_t reg, uint32_t value )
1523 {
1524 advance_pc();
1525
1526 if( reg != 0 )
1527 {
1528 m_r[ reg ] = value;
1529 }
1530 }
1531
delayed_load(uint32_t reg,uint32_t value)1532 void psxcpu_device::delayed_load( uint32_t reg, uint32_t value )
1533 {
1534 if( m_delayr == reg )
1535 {
1536 m_delayr = 0;
1537 m_delayv = 0;
1538 }
1539
1540 advance_pc();
1541
1542 m_delayr = reg;
1543 m_delayv = value;
1544 }
1545
branch(uint32_t address)1546 void psxcpu_device::branch( uint32_t address )
1547 {
1548 advance_pc();
1549
1550 m_delayr = PSXCPU_DELAYR_PC;
1551 m_delayv = address;
1552 }
1553
conditional_branch(int takeBranch)1554 void psxcpu_device::conditional_branch( int takeBranch )
1555 {
1556 advance_pc();
1557
1558 if( takeBranch )
1559 {
1560 m_delayr = PSXCPU_DELAYR_PC;
1561 m_delayv = m_pc + ( PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) ) << 2 );
1562 }
1563 else
1564 {
1565 m_delayr = PSXCPU_DELAYR_NOTPC;
1566 m_delayv = 0;
1567 }
1568 }
1569
unconditional_branch()1570 void psxcpu_device::unconditional_branch()
1571 {
1572 advance_pc();
1573
1574 m_delayr = PSXCPU_DELAYR_PC;
1575 m_delayv = ( m_pc & 0xf0000000 ) + ( INS_TARGET( m_op ) << 2 );
1576 }
1577
common_exception(int exception,uint32_t romOffset,uint32_t ramOffset)1578 void psxcpu_device::common_exception( int exception, uint32_t romOffset, uint32_t ramOffset )
1579 {
1580 int cause = ( exception << 2 ) | ( ( ( m_op >> 26 ) & 3 ) << 28 );
1581
1582 if( m_delayr == PSXCPU_DELAYR_PC )
1583 {
1584 cause |= CAUSE_BT;
1585 m_cp0r[ CP0_TAR ] = m_delayv;
1586 }
1587 else if( m_delayr == PSXCPU_DELAYR_NOTPC )
1588 {
1589 m_cp0r[ CP0_TAR ] = m_pc + 4;
1590 }
1591 else
1592 {
1593 commit_delayed_load();
1594 }
1595
1596 if( m_delayr == PSXCPU_DELAYR_PC || m_delayr == PSXCPU_DELAYR_NOTPC )
1597 {
1598 cause |= CAUSE_BD;
1599 m_cp0r[ CP0_EPC ] = m_pc - 4;
1600 }
1601 else
1602 {
1603 m_cp0r[ CP0_EPC ] = m_pc;
1604 }
1605
1606 if (exception != EXC_INT)
1607 {
1608 if (LOG_BIOSCALL)
1609 logerror("%08x: Exception %d\n", m_pc, exception);
1610
1611 debugger_exception_hook(exception);
1612 }
1613
1614 m_delayr = 0;
1615 m_delayv = 0;
1616 m_berr = 0;
1617
1618 if( m_cp0r[ CP0_SR ] & SR_BEV )
1619 {
1620 set_pc( romOffset );
1621 }
1622 else
1623 {
1624 set_pc( ramOffset );
1625 }
1626
1627 m_cp0r[ CP0_SR ] = ( m_cp0r[ CP0_SR ] & ~0x3f ) | ( ( m_cp0r[ CP0_SR ] << 2 ) & 0x3f );
1628 m_cp0r[ CP0_CAUSE ] = ( m_cp0r[ CP0_CAUSE ] & ~( CAUSE_EXC | CAUSE_BD | CAUSE_BT | CAUSE_CE ) ) | cause;
1629 update_cop0( CP0_SR );
1630 }
1631
exception(int exception)1632 void psxcpu_device::exception( int exception )
1633 {
1634 common_exception( exception, 0xbfc00180, 0x80000080 );
1635 }
1636
breakpoint_exception()1637 void psxcpu_device::breakpoint_exception()
1638 {
1639 fetch_next_op();
1640 execute_unstoppable_instructions( 1 );
1641 common_exception( EXC_BP, 0xbfc00140, 0x80000040 );
1642 }
1643
fetch_bus_error_exception()1644 void psxcpu_device::fetch_bus_error_exception()
1645 {
1646 common_exception( EXC_IBE, 0xbfc00180, 0x80000080 );
1647 }
1648
load_bus_error_exception()1649 void psxcpu_device::load_bus_error_exception()
1650 {
1651 fetch_next_op();
1652 execute_unstoppable_instructions( 0 );
1653 common_exception( EXC_DBE, 0xbfc00180, 0x80000080 );
1654 }
1655
store_bus_error_exception()1656 void psxcpu_device::store_bus_error_exception()
1657 {
1658 fetch_next_op();
1659
1660 if( execute_unstoppable_instructions( 1 ) )
1661 {
1662 advance_pc();
1663
1664 if( ( m_pc & m_bad_word_address_mask ) != 0 )
1665 {
1666 load_bad_address( m_pc );
1667 return;
1668 }
1669
1670 fetch_next_op();
1671 execute_unstoppable_instructions( 0 );
1672 }
1673
1674 common_exception( EXC_DBE, 0xbfc00180, 0x80000080 );
1675 }
1676
load_bad_address(uint32_t address)1677 void psxcpu_device::load_bad_address( uint32_t address )
1678 {
1679 m_cp0r[ CP0_BADA ] = address;
1680 exception( EXC_ADEL );
1681 }
1682
store_bad_address(uint32_t address)1683 void psxcpu_device::store_bad_address( uint32_t address )
1684 {
1685 m_cp0r[ CP0_BADA ] = address;
1686 exception( EXC_ADES );
1687 }
1688
data_address_breakpoint(int dcic_rw,int dcic_status,uint32_t address)1689 int psxcpu_device::data_address_breakpoint( int dcic_rw, int dcic_status, uint32_t address )
1690 {
1691 if( address < 0x1f000000 || address > 0x1fffffff )
1692 {
1693 if( ( m_cp0r[ CP0_DCIC ] & DCIC_DE ) != 0 &&
1694 ( m_cp0r[ CP0_DCIC ] & dcic_rw ) == dcic_rw &&
1695 ( ( ( m_cp0r[ CP0_DCIC ] & DCIC_KD ) != 0 && ( m_pc & 0x80000000 ) != 0 ) ||
1696 ( ( m_cp0r[ CP0_DCIC ] & DCIC_UD ) != 0 && ( m_pc & 0x80000000 ) == 0 ) ) )
1697 {
1698 if( ( address & m_cp0r[ CP0_BDAM ] ) == ( m_cp0r[ CP0_BDA ] & m_cp0r[ CP0_BDAM ] ) )
1699 {
1700 m_cp0r[ CP0_DCIC ] |= dcic_status;
1701
1702 if( ( m_cp0r[ CP0_DCIC ] & DCIC_TR ) != 0 )
1703 {
1704 return 1;
1705 }
1706 }
1707 }
1708 }
1709
1710 return 0;
1711 }
1712
program_counter_breakpoint()1713 int psxcpu_device::program_counter_breakpoint()
1714 {
1715 if( ( m_cp0r[ CP0_DCIC ] & DCIC_DE ) != 0 &&
1716 ( m_cp0r[ CP0_DCIC ] & DCIC_PCE ) != 0 &&
1717 ( ( ( m_cp0r[ CP0_DCIC ] & DCIC_KD ) != 0 && ( m_pc & 0x80000000 ) != 0 ) ||
1718 ( ( m_cp0r[ CP0_DCIC ] & DCIC_UD ) != 0 && ( m_pc & 0x80000000 ) == 0 ) ) )
1719 {
1720 if( ( m_pc & m_cp0r[ CP0_BPCM ] ) == ( m_cp0r[ CP0_BPC ] & m_cp0r[ CP0_BPCM ] ) )
1721 {
1722 m_cp0r[ CP0_DCIC ] |= DCIC_PC | DCIC_DB;
1723
1724 if( ( m_cp0r[ CP0_DCIC ] & DCIC_TR ) != 0 )
1725 {
1726 return 1;
1727 }
1728 }
1729 }
1730
1731 return 0;
1732 }
1733
load_data_address_breakpoint(uint32_t address)1734 int psxcpu_device::load_data_address_breakpoint( uint32_t address )
1735 {
1736 return data_address_breakpoint( DCIC_DR | DCIC_DAE, DCIC_DB | DCIC_DA | DCIC_R, address );
1737 }
1738
store_data_address_breakpoint(uint32_t address)1739 int psxcpu_device::store_data_address_breakpoint( uint32_t address )
1740 {
1741 return data_address_breakpoint( DCIC_DW | DCIC_DAE, DCIC_DB | DCIC_DA | DCIC_W, address );
1742 }
1743
1744 // On-board RAM and peripherals
psxcpu_internal_map(address_map & map)1745 void psxcpu_device::psxcpu_internal_map(address_map &map)
1746 {
1747 map(0x1f800000, 0x1f8003ff).noprw(); /* scratchpad */
1748 map(0x1f800400, 0x1f800fff).rw(FUNC(psxcpu_device::berr_r), FUNC(psxcpu_device::berr_w));
1749 map(0x1f801000, 0x1f801003).rw(FUNC(psxcpu_device::exp_base_r), FUNC(psxcpu_device::exp_base_w));
1750 map(0x1f801004, 0x1f801007).ram();
1751 map(0x1f801008, 0x1f80100b).rw(FUNC(psxcpu_device::exp_config_r), FUNC(psxcpu_device::exp_config_w));
1752 map(0x1f80100c, 0x1f80100f).ram();
1753 map(0x1f801010, 0x1f801013).rw(FUNC(psxcpu_device::rom_config_r), FUNC(psxcpu_device::rom_config_w));
1754 map(0x1f801014, 0x1f80101f).ram();
1755 /* 1f801014 spu delay */
1756 /* 1f801018 dv delay */
1757 map(0x1f801020, 0x1f801023).rw(FUNC(psxcpu_device::com_delay_r), FUNC(psxcpu_device::com_delay_w));
1758 map(0x1f801024, 0x1f80102f).ram();
1759 map(0x1f801040, 0x1f80104f).rw("sio0", FUNC(psxsio_device::read), FUNC(psxsio_device::write));
1760 map(0x1f801050, 0x1f80105f).rw("sio1", FUNC(psxsio_device::read), FUNC(psxsio_device::write));
1761 map(0x1f801060, 0x1f801063).rw(FUNC(psxcpu_device::ram_config_r), FUNC(psxcpu_device::ram_config_w));
1762 map(0x1f801064, 0x1f80106f).ram();
1763 map(0x1f801070, 0x1f801077).rw("irq", FUNC(psxirq_device::read), FUNC(psxirq_device::write));
1764 map(0x1f801080, 0x1f8010ff).rw("dma", FUNC(psxdma_device::read), FUNC(psxdma_device::write));
1765 map(0x1f801100, 0x1f80112f).rw("rcnt", FUNC(psxrcnt_device::read), FUNC(psxrcnt_device::write));
1766 map(0x1f801800, 0x1f801803).rw(FUNC(psxcpu_device::cd_r), FUNC(psxcpu_device::cd_w));
1767 map(0x1f801810, 0x1f801817).rw(FUNC(psxcpu_device::gpu_r), FUNC(psxcpu_device::gpu_w));
1768 map(0x1f801820, 0x1f801827).rw("mdec", FUNC(psxmdec_device::read), FUNC(psxmdec_device::write));
1769 map(0x1f801c00, 0x1f801dff).rw(FUNC(psxcpu_device::spu_r), FUNC(psxcpu_device::spu_w));
1770 map(0x1f802020, 0x1f802033).ram(); /* ?? */
1771 /* 1f802030 int 2000 */
1772 /* 1f802040 dip switches */
1773 map(0x1f802040, 0x1f802043).nopw();
1774 map(0x20000000, 0x7fffffff).rw(FUNC(psxcpu_device::berr_r), FUNC(psxcpu_device::berr_w));
1775 map(0xc0000000, 0xfffdffff).rw(FUNC(psxcpu_device::berr_r), FUNC(psxcpu_device::berr_w));
1776 map(0xfffe0130, 0xfffe0133).rw(FUNC(psxcpu_device::biu_r), FUNC(psxcpu_device::biu_w));
1777 }
1778
1779
1780 //**************************************************************************
1781 // DEVICE INTERFACE
1782 //**************************************************************************
1783
1784 //-------------------------------------------------
1785 // psxcpu_device - constructor
1786 //-------------------------------------------------
1787
psxcpu_device(const machine_config & mconfig,device_type type,const char * tag,device_t * owner,uint32_t clock)1788 psxcpu_device::psxcpu_device( const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock ) :
1789 cpu_device( mconfig, type, tag, owner, clock ),
1790 m_program_config( "program", ENDIANNESS_LITTLE, 32, 32, 0, address_map_constructor(FUNC(psxcpu_device::psxcpu_internal_map), this)),
1791 m_gpu_read_handler( *this ),
1792 m_gpu_write_handler( *this ),
1793 m_spu_read_handler( *this ),
1794 m_spu_write_handler( *this ),
1795 m_cd_read_handler( *this ),
1796 m_cd_write_handler( *this ),
1797 m_ram( *this, "ram" )
1798 {
1799 m_disable_rom_berr = false;
1800 }
1801
cxd8530aq_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1802 cxd8530aq_device::cxd8530aq_device( const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock )
1803 : psxcpu_device( mconfig, CXD8530AQ, tag, owner, clock)
1804 {
1805 }
1806
cxd8530bq_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1807 cxd8530bq_device::cxd8530bq_device( const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock )
1808 : psxcpu_device( mconfig, CXD8530BQ, tag, owner, clock)
1809 {
1810 }
1811
cxd8530cq_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1812 cxd8530cq_device::cxd8530cq_device( const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock )
1813 : psxcpu_device( mconfig, CXD8530CQ, tag, owner, clock)
1814 {
1815 }
1816
cxd8661r_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1817 cxd8661r_device::cxd8661r_device( const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock )
1818 : psxcpu_device( mconfig, CXD8661R, tag, owner, clock)
1819 {
1820 }
1821
cxd8606bq_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1822 cxd8606bq_device::cxd8606bq_device( const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock )
1823 : psxcpu_device( mconfig, CXD8606BQ, tag, owner, clock)
1824 {
1825 }
1826
cxd8606cq_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)1827 cxd8606cq_device::cxd8606cq_device( const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock )
1828 : psxcpu_device( mconfig, CXD8606CQ, tag, owner, clock)
1829 {
1830 }
1831
1832 //-------------------------------------------------
1833 // device_start - start up the device
1834 //-------------------------------------------------
1835
device_start()1836 void psxcpu_device::device_start()
1837 {
1838 // get our address spaces
1839 m_program = &space( AS_PROGRAM );
1840 m_program->cache(m_instruction);
1841 m_program->specific(m_data);
1842
1843 save_item( NAME( m_op ) );
1844 save_item( NAME( m_pc ) );
1845 save_item( NAME( m_delayv ) );
1846 save_item( NAME( m_delayr ) );
1847 save_item( NAME( m_hi ) );
1848 save_item( NAME( m_lo ) );
1849 save_item( NAME( m_biu ) );
1850 save_item( NAME( m_r ) );
1851 save_item( NAME( m_cp0r ) );
1852 save_item( NAME( m_gte.m_cp2cr ) );
1853 save_item( NAME( m_gte.m_cp2dr ) );
1854 save_item( NAME( m_icacheTag ) );
1855 save_item( NAME( m_icache ) );
1856 save_item( NAME( m_dcache ) );
1857 save_item( NAME( m_multiplier_operation ) );
1858 save_item( NAME( m_multiplier_operand1 ) );
1859 save_item( NAME( m_multiplier_operand2 ) );
1860 save_item( NAME( m_exp_base ) );
1861 save_item( NAME( m_exp_config ) );
1862 save_item( NAME( m_ram_config ) );
1863 save_item( NAME( m_rom_config ) );
1864
1865 state_add( STATE_GENPC, "GENPC", m_pc ).noshow();
1866 state_add( STATE_GENPCBASE, "CURPC", m_pc ).noshow();
1867 state_add( PSXCPU_PC, "pc", m_pc );
1868 state_add( PSXCPU_DELAYR, "delayr", m_delayr ).formatstr("%8s");
1869 state_add( PSXCPU_DELAYV, "delayv", m_delayv );
1870 state_add( PSXCPU_HI, "hi", m_hi );
1871 state_add( PSXCPU_LO, "lo", m_lo );
1872 state_add( PSXCPU_BIU, "biu", m_biu );
1873 state_add( PSXCPU_R0, "zero", m_r[ 0 ] );
1874 state_add( PSXCPU_R1, "at", m_r[ 1 ] );
1875 state_add( PSXCPU_R2, "v0", m_r[ 2 ] );
1876 state_add( PSXCPU_R3, "v1", m_r[ 3 ] );
1877 state_add( PSXCPU_R4, "a0", m_r[ 4 ] );
1878 state_add( PSXCPU_R5, "a1", m_r[ 5 ] );
1879 state_add( PSXCPU_R6, "a2", m_r[ 6 ] );
1880 state_add( PSXCPU_R7, "a3", m_r[ 7 ] );
1881 state_add( PSXCPU_R8, "t0", m_r[ 8 ] );
1882 state_add( PSXCPU_R9, "t1", m_r[ 9 ] );
1883 state_add( PSXCPU_R10, "t2", m_r[ 10 ] );
1884 state_add( PSXCPU_R11, "t3", m_r[ 11 ] );
1885 state_add( PSXCPU_R12, "t4", m_r[ 12 ] );
1886 state_add( PSXCPU_R13, "t5", m_r[ 13 ] );
1887 state_add( PSXCPU_R14, "t6", m_r[ 14 ] );
1888 state_add( PSXCPU_R15, "t7", m_r[ 15 ] );
1889 state_add( PSXCPU_R16, "s0", m_r[ 16 ] );
1890 state_add( PSXCPU_R17, "s1", m_r[ 17 ] );
1891 state_add( PSXCPU_R18, "s2", m_r[ 18 ] );
1892 state_add( PSXCPU_R19, "s3", m_r[ 19 ] );
1893 state_add( PSXCPU_R20, "s4", m_r[ 20 ] );
1894 state_add( PSXCPU_R21, "s5", m_r[ 21 ] );
1895 state_add( PSXCPU_R22, "s6", m_r[ 22 ] );
1896 state_add( PSXCPU_R23, "s7", m_r[ 23 ] );
1897 state_add( PSXCPU_R24, "t8", m_r[ 24 ] );
1898 state_add( PSXCPU_R25, "t9", m_r[ 25 ] );
1899 state_add( PSXCPU_R26, "k0", m_r[ 26 ] );
1900 state_add( PSXCPU_R27, "k1", m_r[ 27 ] );
1901 state_add( PSXCPU_R28, "gp", m_r[ 28 ] );
1902 state_add( PSXCPU_R29, "sp", m_r[ 29 ] );
1903 state_add( PSXCPU_R30, "fp", m_r[ 30 ] );
1904 state_add( PSXCPU_R31, "ra", m_r[ 31 ] );
1905 state_add( PSXCPU_CP0R0, "!Index", m_cp0r[ 0 ] );
1906 state_add( PSXCPU_CP0R1, "!Random", m_cp0r[ 1 ] );
1907 state_add( PSXCPU_CP0R2, "!EntryLo", m_cp0r[ 2 ] );
1908 state_add( PSXCPU_CP0R3, "BPC", m_cp0r[ 3 ] );
1909 state_add( PSXCPU_CP0R4, "!Context", m_cp0r[ 4 ] );
1910 state_add( PSXCPU_CP0R5, "BDA", m_cp0r[ 5 ] );
1911 state_add( PSXCPU_CP0R6, "TAR", m_cp0r[ 6 ] );
1912 state_add( PSXCPU_CP0R7, "DCIC", m_cp0r[ 7 ] );
1913 state_add( PSXCPU_CP0R8, "BadA", m_cp0r[ 8 ] );
1914 state_add( PSXCPU_CP0R9, "BDAM", m_cp0r[ 9 ] );
1915 state_add( PSXCPU_CP0R10, "!EntryHi", m_cp0r[ 10 ] );
1916 state_add( PSXCPU_CP0R11, "BPCM", m_cp0r[ 11 ] );
1917 state_add( PSXCPU_CP0R12, "SR", m_cp0r[ 12 ] ).callimport();
1918 state_add( PSXCPU_CP0R13, "Cause", m_cp0r[ 13 ] ).callimport();
1919 state_add( PSXCPU_CP0R14, "EPC", m_cp0r[ 14 ] );
1920 state_add( PSXCPU_CP0R15, "PRId", m_cp0r[ 15 ] );
1921 state_add( PSXCPU_CP2DR0, "vxy0", m_gte.m_cp2dr[ 0 ].d );
1922 state_add( PSXCPU_CP2DR1, "vz0", m_gte.m_cp2dr[ 1 ].d );
1923 state_add( PSXCPU_CP2DR2, "vxy1", m_gte.m_cp2dr[ 2 ].d );
1924 state_add( PSXCPU_CP2DR3, "vz1", m_gte.m_cp2dr[ 3 ].d );
1925 state_add( PSXCPU_CP2DR4, "vxy2", m_gte.m_cp2dr[ 4 ].d );
1926 state_add( PSXCPU_CP2DR5, "vz2", m_gte.m_cp2dr[ 5 ].d );
1927 state_add( PSXCPU_CP2DR6, "rgb", m_gte.m_cp2dr[ 6 ].d );
1928 state_add( PSXCPU_CP2DR7, "otz", m_gte.m_cp2dr[ 7 ].d );
1929 state_add( PSXCPU_CP2DR8, "ir0", m_gte.m_cp2dr[ 8 ].d );
1930 state_add( PSXCPU_CP2DR9, "ir1", m_gte.m_cp2dr[ 9 ].d );
1931 state_add( PSXCPU_CP2DR10, "ir2", m_gte.m_cp2dr[ 10 ].d );
1932 state_add( PSXCPU_CP2DR11, "ir3", m_gte.m_cp2dr[ 11 ].d );
1933 state_add( PSXCPU_CP2DR12, "sxy0", m_gte.m_cp2dr[ 12 ].d );
1934 state_add( PSXCPU_CP2DR13, "sxy1", m_gte.m_cp2dr[ 13 ].d );
1935 state_add( PSXCPU_CP2DR14, "sxy2", m_gte.m_cp2dr[ 14 ].d );
1936 state_add( PSXCPU_CP2DR15, "sxyp", m_gte.m_cp2dr[ 15 ].d );
1937 state_add( PSXCPU_CP2DR16, "sz0", m_gte.m_cp2dr[ 16 ].d );
1938 state_add( PSXCPU_CP2DR17, "sz1", m_gte.m_cp2dr[ 17 ].d );
1939 state_add( PSXCPU_CP2DR18, "sz2", m_gte.m_cp2dr[ 18 ].d );
1940 state_add( PSXCPU_CP2DR19, "sz3", m_gte.m_cp2dr[ 19 ].d );
1941 state_add( PSXCPU_CP2DR20, "rgb0", m_gte.m_cp2dr[ 20 ].d );
1942 state_add( PSXCPU_CP2DR21, "rgb1", m_gte.m_cp2dr[ 21 ].d );
1943 state_add( PSXCPU_CP2DR22, "rgb2", m_gte.m_cp2dr[ 22 ].d );
1944 state_add( PSXCPU_CP2DR23, "res1", m_gte.m_cp2dr[ 23 ].d );
1945 state_add( PSXCPU_CP2DR24, "mac0", m_gte.m_cp2dr[ 24 ].d );
1946 state_add( PSXCPU_CP2DR25, "mac1", m_gte.m_cp2dr[ 25 ].d );
1947 state_add( PSXCPU_CP2DR26, "mac2", m_gte.m_cp2dr[ 26 ].d );
1948 state_add( PSXCPU_CP2DR27, "mac3", m_gte.m_cp2dr[ 27 ].d );
1949 state_add( PSXCPU_CP2DR28, "irgb", m_gte.m_cp2dr[ 28 ].d );
1950 state_add( PSXCPU_CP2DR29, "orgb", m_gte.m_cp2dr[ 29 ].d );
1951 state_add( PSXCPU_CP2DR30, "lzcs", m_gte.m_cp2dr[ 30 ].d );
1952 state_add( PSXCPU_CP2DR31, "lzcr", m_gte.m_cp2dr[ 31 ].d );
1953 state_add( PSXCPU_CP2CR0, "r11r12", m_gte.m_cp2cr[ 0 ].d );
1954 state_add( PSXCPU_CP2CR1, "r13r21", m_gte.m_cp2cr[ 1 ].d );
1955 state_add( PSXCPU_CP2CR2, "r22r23", m_gte.m_cp2cr[ 2 ].d );
1956 state_add( PSXCPU_CP2CR3, "r31r32", m_gte.m_cp2cr[ 3 ].d );
1957 state_add( PSXCPU_CP2CR4, "r33", m_gte.m_cp2cr[ 4 ].d );
1958 state_add( PSXCPU_CP2CR5, "trx", m_gte.m_cp2cr[ 5 ].d );
1959 state_add( PSXCPU_CP2CR6, "try", m_gte.m_cp2cr[ 6 ].d );
1960 state_add( PSXCPU_CP2CR7, "trz", m_gte.m_cp2cr[ 7 ].d );
1961 state_add( PSXCPU_CP2CR8, "l11l12", m_gte.m_cp2cr[ 8 ].d );
1962 state_add( PSXCPU_CP2CR9, "l13l21", m_gte.m_cp2cr[ 9 ].d );
1963 state_add( PSXCPU_CP2CR10, "l22l23", m_gte.m_cp2cr[ 10 ].d );
1964 state_add( PSXCPU_CP2CR11, "l31l32", m_gte.m_cp2cr[ 11 ].d );
1965 state_add( PSXCPU_CP2CR12, "l33", m_gte.m_cp2cr[ 12 ].d );
1966 state_add( PSXCPU_CP2CR13, "rbk", m_gte.m_cp2cr[ 13 ].d );
1967 state_add( PSXCPU_CP2CR14, "gbk", m_gte.m_cp2cr[ 14 ].d );
1968 state_add( PSXCPU_CP2CR15, "bbk", m_gte.m_cp2cr[ 15 ].d );
1969 state_add( PSXCPU_CP2CR16, "lr1lr2", m_gte.m_cp2cr[ 16 ].d );
1970 state_add( PSXCPU_CP2CR17, "lr31g1", m_gte.m_cp2cr[ 17 ].d );
1971 state_add( PSXCPU_CP2CR18, "lg2lg3", m_gte.m_cp2cr[ 18 ].d );
1972 state_add( PSXCPU_CP2CR19, "lb1lb2", m_gte.m_cp2cr[ 19 ].d );
1973 state_add( PSXCPU_CP2CR20, "lb3", m_gte.m_cp2cr[ 20 ].d );
1974 state_add( PSXCPU_CP2CR21, "rfc", m_gte.m_cp2cr[ 21 ].d );
1975 state_add( PSXCPU_CP2CR22, "gfc", m_gte.m_cp2cr[ 22 ].d );
1976 state_add( PSXCPU_CP2CR23, "bfc", m_gte.m_cp2cr[ 23 ].d );
1977 state_add( PSXCPU_CP2CR24, "ofx", m_gte.m_cp2cr[ 24 ].d );
1978 state_add( PSXCPU_CP2CR25, "ofy", m_gte.m_cp2cr[ 25 ].d );
1979 state_add( PSXCPU_CP2CR26, "h", m_gte.m_cp2cr[ 26 ].d );
1980 state_add( PSXCPU_CP2CR27, "dqa", m_gte.m_cp2cr[ 27 ].d );
1981 state_add( PSXCPU_CP2CR28, "dqb", m_gte.m_cp2cr[ 28 ].d );
1982 state_add( PSXCPU_CP2CR29, "zsf3", m_gte.m_cp2cr[ 29 ].d );
1983 state_add( PSXCPU_CP2CR30, "zsf4", m_gte.m_cp2cr[ 30 ].d );
1984 state_add( PSXCPU_CP2CR31, "flag", m_gte.m_cp2cr[ 31 ].d );
1985
1986 // set our instruction counter
1987 set_icountptr(m_icount);
1988
1989 m_gpu_read_handler.resolve_safe( 0 );
1990 m_gpu_write_handler.resolve_safe();
1991 m_spu_read_handler.resolve_safe( 0 );
1992 m_spu_write_handler.resolve_safe();
1993 m_cd_read_handler.resolve_safe( 0 );
1994 m_cd_write_handler.resolve_safe();
1995
1996 m_rom = memregion( "rom" );
1997 }
1998
1999
2000 //-------------------------------------------------
2001 // device_reset - reset the device
2002 //-------------------------------------------------
2003
device_reset()2004 void psxcpu_device::device_reset()
2005 {
2006 m_ram_config = 0x800;
2007 update_ram_config();
2008
2009 m_rom_config = 0x00130000;
2010 update_rom_config();
2011
2012 /// TODO: get dma to access ram through the memory map?
2013 psxdma_device *psxdma = subdevice<psxdma_device>( "dma" );
2014 psxdma->m_ram = (uint32_t *)m_ram->pointer();
2015 psxdma->m_ramsize = m_ram->size();
2016
2017 m_delayr = 0;
2018 m_delayv = 0;
2019 m_berr = 0;
2020 m_biu = 0;
2021
2022 m_multiplier_operation = MULTIPLIER_OPERATION_IDLE;
2023
2024 m_r[ 0 ] = 0;
2025
2026 m_cp0r[ CP0_SR ] = SR_BEV;
2027 m_cp0r[ CP0_CAUSE ] = 0x00000000;
2028 m_cp0r[ CP0_PRID ] = 0x00000002;
2029 m_cp0r[ CP0_DCIC ] = 0x00000000;
2030 m_cp0r[ CP0_BPCM ] = 0xffffffff;
2031 m_cp0r[ CP0_BDAM ] = 0xffffffff;
2032
2033 update_memory_handlers();
2034 update_address_masks();
2035 update_scratchpad();
2036
2037 set_pc( 0xbfc00000 );
2038 }
2039
2040
2041 //-------------------------------------------------
2042 // device_post_load - device-specific post-load
2043 //-------------------------------------------------
2044
device_post_load()2045 void psxcpu_device::device_post_load()
2046 {
2047 update_memory_handlers();
2048 update_address_masks();
2049 update_scratchpad();
2050 update_ram_config();
2051 update_rom_config();
2052 }
2053
2054
2055 //-------------------------------------------------
2056 // state_import - import state into the device,
2057 // after it has been set
2058 //-------------------------------------------------
2059
state_import(const device_state_entry & entry)2060 void psxcpu_device::state_import( const device_state_entry &entry )
2061 {
2062 switch( entry.index() )
2063 {
2064 case PSXCPU_CP0R12: // SR
2065 case PSXCPU_CP0R13: // CAUSE
2066 update_cop0( entry.index() - PSXCPU_CP0R0 );
2067 break;
2068 }
2069 }
2070
2071
2072 //-------------------------------------------------
2073 // state_string_export - export state as a string
2074 // for the debugger
2075 //-------------------------------------------------
2076
state_string_export(const device_state_entry & entry,std::string & str) const2077 void psxcpu_device::state_string_export( const device_state_entry &entry, std::string &str ) const
2078 {
2079 switch( entry.index() )
2080 {
2081 case PSXCPU_DELAYR:
2082 if( m_delayr <= PSXCPU_DELAYR_NOTPC )
2083 {
2084 str = string_format("%02x %-3s", m_delayr, delayn[m_delayr]);
2085 }
2086 else
2087 {
2088 str = string_format("%02x ---", m_delayr);
2089 }
2090 break;
2091 }
2092 }
2093
2094
2095 //-------------------------------------------------
2096 // disassemble - call the disassembly
2097 // helper function
2098 //-------------------------------------------------
2099
create_disassembler()2100 std::unique_ptr<util::disasm_interface> psxcpu_device::create_disassembler()
2101 {
2102 return std::make_unique<psxcpu_disassembler>(static_cast<psxcpu_disassembler::config *>(this));
2103 }
2104
2105
get_register_from_pipeline(int reg)2106 uint32_t psxcpu_device::get_register_from_pipeline( int reg )
2107 {
2108 if( m_delayr == reg )
2109 {
2110 return m_delayv;
2111 }
2112
2113 return m_r[ reg ];
2114 }
2115
cop0_usable()2116 int psxcpu_device::cop0_usable()
2117 {
2118 if( ( m_cp0r[ CP0_SR ] & SR_KUC ) != 0 && ( m_cp0r[ CP0_SR ] & SR_CU0 ) == 0 )
2119 {
2120 exception( EXC_CPU );
2121
2122 return 0;
2123 }
2124
2125 return 1;
2126 }
2127
lwc(int cop,int sr_cu)2128 void psxcpu_device::lwc( int cop, int sr_cu )
2129 {
2130 uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
2131 int breakpoint = load_data_address_breakpoint( address );
2132
2133 if( ( m_cp0r[ CP0_SR ] & sr_cu ) == 0 )
2134 {
2135 exception( EXC_CPU );
2136 }
2137 else if( ( address & m_bad_word_address_mask ) != 0 )
2138 {
2139 load_bad_address( address );
2140 }
2141 else if( breakpoint )
2142 {
2143 breakpoint_exception();
2144 }
2145 else
2146 {
2147 uint32_t data = readword( address );
2148
2149 if( m_berr )
2150 {
2151 load_bus_error_exception();
2152 }
2153 else
2154 {
2155 int reg = INS_RT( m_op );
2156
2157 advance_pc();
2158
2159 switch( cop )
2160 {
2161 case 0:
2162 /* lwc0 doesn't update any cop0 registers */
2163 break;
2164
2165 case 1:
2166 setcp1dr( reg, data );
2167 break;
2168
2169 case 2:
2170 m_gte.setcp2dr( m_pc, reg, data );
2171 break;
2172
2173 case 3:
2174 setcp3dr( reg, data );
2175 break;
2176 }
2177 }
2178 }
2179 }
2180
swc(int cop,int sr_cu)2181 void psxcpu_device::swc( int cop, int sr_cu )
2182 {
2183 uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
2184 int breakpoint = store_data_address_breakpoint( address );
2185
2186 if( ( m_cp0r[ CP0_SR ] & sr_cu ) == 0 )
2187 {
2188 exception( EXC_CPU );
2189 }
2190 else if( ( address & m_bad_word_address_mask ) != 0 )
2191 {
2192 store_bad_address( address );
2193 }
2194 else
2195 {
2196 uint32_t data = 0;
2197
2198 switch( cop )
2199 {
2200 case 0:
2201 {
2202 int address;
2203
2204 if( m_delayr == PSXCPU_DELAYR_PC )
2205 {
2206 switch( m_delayv & 0x0c )
2207 {
2208 case 0x0c:
2209 address = m_delayv;
2210 break;
2211
2212 default:
2213 address = m_delayv + 4;
2214 break;
2215 }
2216 }
2217 else
2218 {
2219 switch( m_pc & 0x0c )
2220 {
2221 case 0x0:
2222 case 0xc:
2223 address = m_pc + 0x08;
2224 break;
2225
2226 default:
2227 address = m_pc | 0x0c;
2228 break;
2229 }
2230 }
2231
2232 data = m_program->read_dword( address );
2233 }
2234 break;
2235
2236 case 1:
2237 data = getcp1dr( INS_RT( m_op ) );
2238 break;
2239
2240 case 2:
2241 data = m_gte.getcp2dr( m_pc, INS_RT( m_op ) );
2242 break;
2243
2244 case 3:
2245 data = getcp3dr( INS_RT( m_op ) );
2246 break;
2247 }
2248
2249 writeword( address, data );
2250
2251 if( breakpoint )
2252 {
2253 breakpoint_exception();
2254 }
2255 else if( m_berr )
2256 {
2257 store_bus_error_exception();
2258 }
2259 else
2260 {
2261 advance_pc();
2262 }
2263 }
2264 }
2265
bc(int cop,int sr_cu,int condition)2266 void psxcpu_device::bc( int cop, int sr_cu, int condition )
2267 {
2268 if( ( m_cp0r[ CP0_SR ] & sr_cu ) == 0 )
2269 {
2270 exception( EXC_CPU );
2271 }
2272 else
2273 {
2274 conditional_branch( !condition );
2275 }
2276 }
2277
2278
2279
2280 /***************************************************************************
2281 CORE EXECUTION LOOP
2282 ***************************************************************************/
2283
2284
execute_set_input(int inputnum,int state)2285 void psxcpu_device::execute_set_input( int inputnum, int state )
2286 {
2287 uint32_t ip;
2288
2289 switch( inputnum )
2290 {
2291 case PSXCPU_IRQ0:
2292 ip = CAUSE_IP2;
2293 break;
2294
2295 case PSXCPU_IRQ1:
2296 ip = CAUSE_IP3;
2297 break;
2298
2299 case PSXCPU_IRQ2:
2300 ip = CAUSE_IP4;
2301 break;
2302
2303 case PSXCPU_IRQ3:
2304 ip = CAUSE_IP5;
2305 break;
2306
2307 case PSXCPU_IRQ4:
2308 ip = CAUSE_IP6;
2309 break;
2310
2311 case PSXCPU_IRQ5:
2312 ip = CAUSE_IP7;
2313 break;
2314
2315 default:
2316 return;
2317 }
2318
2319 switch( state )
2320 {
2321 case CLEAR_LINE:
2322 m_cp0r[ CP0_CAUSE ] &= ~ip;
2323 break;
2324
2325 case ASSERT_LINE:
2326 m_cp0r[ CP0_CAUSE ] |= ip;
2327 break;
2328 }
2329
2330 update_cop0( CP0_CAUSE );
2331 }
2332
2333
execute_run()2334 void psxcpu_device::execute_run()
2335 {
2336 do
2337 {
2338 if( LOG_BIOSCALL ) log_bioscall();
2339 debugger_instruction_hook( m_pc );
2340
2341 int breakpoint = program_counter_breakpoint();
2342
2343 if( ( m_pc & m_bad_word_address_mask ) != 0 )
2344 {
2345 load_bad_address( m_pc );
2346 }
2347 else if( breakpoint )
2348 {
2349 breakpoint_exception();
2350 }
2351 else
2352 {
2353 m_op = m_instruction.read_dword(m_pc);
2354
2355 if( m_berr )
2356 {
2357 fetch_bus_error_exception();
2358 }
2359 else
2360 {
2361 switch( INS_OP( m_op ) )
2362 {
2363 case OP_SPECIAL:
2364 switch( INS_FUNCT( m_op ) )
2365 {
2366 case FUNCT_SLL:
2367 load( INS_RD( m_op ), m_r[ INS_RT( m_op ) ] << INS_SHAMT( m_op ) );
2368 break;
2369
2370 case FUNCT_SRL:
2371 load( INS_RD( m_op ), m_r[ INS_RT( m_op ) ] >> INS_SHAMT( m_op ) );
2372 break;
2373
2374 case FUNCT_SRA:
2375 load( INS_RD( m_op ), (int32_t)m_r[ INS_RT( m_op ) ] >> INS_SHAMT( m_op ) );
2376 break;
2377
2378 case FUNCT_SLLV:
2379 load( INS_RD( m_op ), m_r[ INS_RT( m_op ) ] << ( m_r[ INS_RS( m_op ) ] & 31 ) );
2380 break;
2381
2382 case FUNCT_SRLV:
2383 load( INS_RD( m_op ), m_r[ INS_RT( m_op ) ] >> ( m_r[ INS_RS( m_op ) ] & 31 ) );
2384 break;
2385
2386 case FUNCT_SRAV:
2387 load( INS_RD( m_op ), (int32_t)m_r[ INS_RT( m_op ) ] >> ( m_r[ INS_RS( m_op ) ] & 31 ) );
2388 break;
2389
2390 case FUNCT_JR:
2391 branch( m_r[ INS_RS( m_op ) ] );
2392 break;
2393
2394 case FUNCT_JALR:
2395 branch( m_r[ INS_RS( m_op ) ] );
2396 if( INS_RD( m_op ) != 0 )
2397 {
2398 m_r[ INS_RD( m_op ) ] = m_pc + 4;
2399 }
2400 break;
2401
2402 case FUNCT_SYSCALL:
2403 if( LOG_BIOSCALL ) log_syscall();
2404 exception( EXC_SYS );
2405 break;
2406
2407 case FUNCT_BREAK:
2408 exception( EXC_BP );
2409 break;
2410
2411 case FUNCT_MFHI:
2412 load( INS_RD( m_op ), get_hi() );
2413 break;
2414
2415 case FUNCT_MTHI:
2416 funct_mthi();
2417 advance_pc();
2418 break;
2419
2420 case FUNCT_MFLO:
2421 load( INS_RD( m_op ), get_lo() );
2422 break;
2423
2424 case FUNCT_MTLO:
2425 funct_mtlo();
2426 advance_pc();
2427 break;
2428
2429 case FUNCT_MULT:
2430 funct_mult();
2431 advance_pc();
2432 break;
2433
2434 case FUNCT_MULTU:
2435 funct_multu();
2436 advance_pc();
2437 break;
2438
2439 case FUNCT_DIV:
2440 funct_div();
2441 advance_pc();
2442 break;
2443
2444 case FUNCT_DIVU:
2445 funct_divu();
2446 advance_pc();
2447 break;
2448
2449 case FUNCT_ADD:
2450 {
2451 uint32_t result = m_r[ INS_RS( m_op ) ] + m_r[ INS_RT( m_op ) ];
2452 if( (int32_t)( ~( m_r[ INS_RS( m_op ) ] ^ m_r[ INS_RT( m_op ) ] ) & ( m_r[ INS_RS( m_op ) ] ^ result ) ) < 0 )
2453 {
2454 exception( EXC_OVF );
2455 }
2456 else
2457 {
2458 load( INS_RD( m_op ), result );
2459 }
2460 }
2461 break;
2462
2463 case FUNCT_ADDU:
2464 load( INS_RD( m_op ), m_r[ INS_RS( m_op ) ] + m_r[ INS_RT( m_op ) ] );
2465 break;
2466
2467 case FUNCT_SUB:
2468 {
2469 uint32_t result = m_r[ INS_RS( m_op ) ] - m_r[ INS_RT( m_op ) ];
2470 if( (int32_t)( ( m_r[ INS_RS( m_op ) ] ^ m_r[ INS_RT( m_op ) ] ) & ( m_r[ INS_RS( m_op ) ] ^ result ) ) < 0 )
2471 {
2472 exception( EXC_OVF );
2473 }
2474 else
2475 {
2476 load( INS_RD( m_op ), result );
2477 }
2478 }
2479 break;
2480
2481 case FUNCT_SUBU:
2482 load( INS_RD( m_op ), m_r[ INS_RS( m_op ) ] - m_r[ INS_RT( m_op ) ] );
2483 break;
2484
2485 case FUNCT_AND:
2486 load( INS_RD( m_op ), m_r[ INS_RS( m_op ) ] & m_r[ INS_RT( m_op ) ] );
2487 break;
2488
2489 case FUNCT_OR:
2490 load( INS_RD( m_op ), m_r[ INS_RS( m_op ) ] | m_r[ INS_RT( m_op ) ] );
2491 break;
2492
2493 case FUNCT_XOR:
2494 load( INS_RD( m_op ), m_r[ INS_RS( m_op ) ] ^ m_r[ INS_RT( m_op ) ] );
2495 break;
2496
2497 case FUNCT_NOR:
2498 load( INS_RD( m_op ), ~( m_r[ INS_RS( m_op ) ] | m_r[ INS_RT( m_op ) ] ) );
2499 break;
2500
2501 case FUNCT_SLT:
2502 load( INS_RD( m_op ), (int32_t)m_r[ INS_RS( m_op ) ] < (int32_t)m_r[ INS_RT( m_op ) ] );
2503 break;
2504
2505 case FUNCT_SLTU:
2506 load( INS_RD( m_op ), m_r[ INS_RS( m_op ) ] < m_r[ INS_RT( m_op ) ] );
2507 break;
2508
2509 default:
2510 exception( EXC_RI );
2511 break;
2512 }
2513 break;
2514
2515 case OP_REGIMM:
2516 switch( INS_RT_REGIMM( m_op ) )
2517 {
2518 case RT_BLTZ:
2519 conditional_branch( (int32_t)m_r[ INS_RS( m_op ) ] < 0 );
2520
2521 if( INS_RT( m_op ) == RT_BLTZAL )
2522 {
2523 m_r[ 31 ] = m_pc + 4;
2524 }
2525 break;
2526
2527 case RT_BGEZ:
2528 conditional_branch( (int32_t)m_r[ INS_RS( m_op ) ] >= 0 );
2529
2530 if( INS_RT( m_op ) == RT_BGEZAL )
2531 {
2532 m_r[ 31 ] = m_pc + 4;
2533 }
2534 break;
2535 }
2536 break;
2537
2538 case OP_J:
2539 unconditional_branch();
2540 break;
2541
2542 case OP_JAL:
2543 unconditional_branch();
2544 m_r[ 31 ] = m_pc + 4;
2545 break;
2546
2547 case OP_BEQ:
2548 conditional_branch( m_r[ INS_RS( m_op ) ] == m_r[ INS_RT( m_op ) ] );
2549 break;
2550
2551 case OP_BNE:
2552 conditional_branch( m_r[ INS_RS( m_op ) ] != m_r[ INS_RT( m_op ) ] );
2553 break;
2554
2555 case OP_BLEZ:
2556 conditional_branch( (int32_t)m_r[ INS_RS( m_op ) ] < 0 || m_r[ INS_RS( m_op ) ] == m_r[ INS_RT( m_op ) ] );
2557 break;
2558
2559 case OP_BGTZ:
2560 conditional_branch( (int32_t)m_r[ INS_RS( m_op ) ] >= 0 && m_r[ INS_RS( m_op ) ] != m_r[ INS_RT( m_op ) ] );
2561 break;
2562
2563 case OP_ADDI:
2564 {
2565 uint32_t immediate = PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
2566 uint32_t result = m_r[ INS_RS( m_op ) ] + immediate;
2567 if( (int32_t)( ~( m_r[ INS_RS( m_op ) ] ^ immediate ) & ( m_r[ INS_RS( m_op ) ] ^ result ) ) < 0 )
2568 {
2569 exception( EXC_OVF );
2570 }
2571 else
2572 {
2573 load( INS_RT( m_op ), result );
2574 }
2575 }
2576 break;
2577
2578 case OP_ADDIU:
2579 load( INS_RT( m_op ), m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) ) );
2580 break;
2581
2582 case OP_SLTI:
2583 load( INS_RT( m_op ), (int32_t)m_r[ INS_RS( m_op ) ] < PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) ) );
2584 break;
2585
2586 case OP_SLTIU:
2587 load( INS_RT( m_op ), m_r[ INS_RS( m_op ) ] < (uint32_t)PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) ) );
2588 break;
2589
2590 case OP_ANDI:
2591 load( INS_RT( m_op ), m_r[ INS_RS( m_op ) ] & INS_IMMEDIATE( m_op ) );
2592 break;
2593
2594 case OP_ORI:
2595 load( INS_RT( m_op ), m_r[ INS_RS( m_op ) ] | INS_IMMEDIATE( m_op ) );
2596 break;
2597
2598 case OP_XORI:
2599 load( INS_RT( m_op ), m_r[ INS_RS( m_op ) ] ^ INS_IMMEDIATE( m_op ) );
2600 break;
2601
2602 case OP_LUI:
2603 load( INS_RT( m_op ), INS_IMMEDIATE( m_op ) << 16 );
2604 break;
2605
2606 case OP_COP0:
2607 switch( INS_RS( m_op ) )
2608 {
2609 case RS_MFC:
2610 {
2611 int reg = INS_RD( m_op );
2612
2613 if( reg == CP0_INDEX ||
2614 reg == CP0_RANDOM ||
2615 reg == CP0_ENTRYLO ||
2616 reg == CP0_CONTEXT ||
2617 reg == CP0_ENTRYHI )
2618 {
2619 exception( EXC_RI );
2620 }
2621 else if( reg < 16 )
2622 {
2623 if( cop0_usable() )
2624 {
2625 delayed_load( INS_RT( m_op ), m_cp0r[ reg ] );
2626 }
2627 }
2628 else
2629 {
2630 advance_pc();
2631 }
2632 }
2633 break;
2634
2635 case RS_CFC:
2636 exception( EXC_RI );
2637 break;
2638
2639 case RS_MTC:
2640 {
2641 int reg = INS_RD( m_op );
2642
2643 if( reg == CP0_INDEX ||
2644 reg == CP0_RANDOM ||
2645 reg == CP0_ENTRYLO ||
2646 reg == CP0_CONTEXT ||
2647 reg == CP0_ENTRYHI )
2648 {
2649 exception( EXC_RI );
2650 }
2651 else if( reg < 16 )
2652 {
2653 if( cop0_usable() )
2654 {
2655 uint32_t data = ( m_cp0r[ reg ] & ~mtc0_writemask[ reg ] ) |
2656 ( m_r[ INS_RT( m_op ) ] & mtc0_writemask[ reg ] );
2657 advance_pc();
2658
2659 m_cp0r[ reg ] = data;
2660 update_cop0( reg );
2661 }
2662 }
2663 else
2664 {
2665 advance_pc();
2666 }
2667 }
2668 break;
2669
2670 case RS_CTC:
2671 exception( EXC_RI );
2672 break;
2673
2674 case RS_BC:
2675 case RS_BC_ALT:
2676 switch( INS_BC( m_op ) )
2677 {
2678 case BC_BCF:
2679 bc( 0, SR_CU0, 0 );
2680 break;
2681
2682 case BC_BCT:
2683 bc( 0, SR_CU0, 1 );
2684 break;
2685 }
2686 break;
2687
2688 default:
2689 switch( INS_CO( m_op ) )
2690 {
2691 case 1:
2692 switch( INS_CF( m_op ) )
2693 {
2694 case CF_TLBR:
2695 case CF_TLBWI:
2696 case CF_TLBWR:
2697 case CF_TLBP:
2698 exception( EXC_RI );
2699 break;
2700
2701 case CF_RFE:
2702 if( cop0_usable() )
2703 {
2704 advance_pc();
2705 m_cp0r[ CP0_SR ] = ( m_cp0r[ CP0_SR ] & ~0xf ) | ( ( m_cp0r[ CP0_SR ] >> 2 ) & 0xf );
2706 update_cop0( CP0_SR );
2707 }
2708 break;
2709
2710 default:
2711 advance_pc();
2712 break;
2713 }
2714 break;
2715
2716 default:
2717 advance_pc();
2718 break;
2719 }
2720 break;
2721 }
2722 break;
2723
2724 case OP_COP1:
2725 if( ( m_cp0r[ CP0_SR ] & SR_CU1 ) == 0 )
2726 {
2727 exception( EXC_CPU );
2728 }
2729 else
2730 {
2731 switch( INS_RS( m_op ) )
2732 {
2733 case RS_MFC:
2734 delayed_load( INS_RT( m_op ), getcp1dr( INS_RD( m_op ) ) );
2735 break;
2736
2737 case RS_CFC:
2738 delayed_load( INS_RT( m_op ), getcp1cr( INS_RD( m_op ) ) );
2739 break;
2740
2741 case RS_MTC:
2742 setcp1dr( INS_RD( m_op ), m_r[ INS_RT( m_op ) ] );
2743 advance_pc();
2744 break;
2745
2746 case RS_CTC:
2747 setcp1cr( INS_RD( m_op ), m_r[ INS_RT( m_op ) ] );
2748 advance_pc();
2749 break;
2750
2751 case RS_BC:
2752 case RS_BC_ALT:
2753 switch( INS_BC( m_op ) )
2754 {
2755 case BC_BCF:
2756 bc( 1, SR_CU1, 0 );
2757 break;
2758
2759 case BC_BCT:
2760 bc( 1, SR_CU1, 1 );
2761 break;
2762 }
2763 break;
2764
2765 default:
2766 advance_pc();
2767 break;
2768 }
2769 }
2770 break;
2771
2772 case OP_COP2:
2773 if( ( m_cp0r[ CP0_SR ] & SR_CU2 ) == 0 )
2774 {
2775 exception( EXC_CPU );
2776 }
2777 else
2778 {
2779 switch( INS_RS( m_op ) )
2780 {
2781 case RS_MFC:
2782 delayed_load( INS_RT( m_op ), m_gte.getcp2dr( m_pc, INS_RD( m_op ) ) );
2783 break;
2784
2785 case RS_CFC:
2786 delayed_load( INS_RT( m_op ), m_gte.getcp2cr( m_pc, INS_RD( m_op ) ) );
2787 break;
2788
2789 case RS_MTC:
2790 m_gte.setcp2dr( m_pc, INS_RD( m_op ), m_r[ INS_RT( m_op ) ] );
2791 advance_pc();
2792 break;
2793
2794 case RS_CTC:
2795 m_gte.setcp2cr( m_pc, INS_RD( m_op ), m_r[ INS_RT( m_op ) ] );
2796 advance_pc();
2797 break;
2798
2799 case RS_BC:
2800 case RS_BC_ALT:
2801 switch( INS_BC( m_op ) )
2802 {
2803 case BC_BCF:
2804 bc( 2, SR_CU2, 0 );
2805 break;
2806
2807 case BC_BCT:
2808 bc( 2, SR_CU2, 1 );
2809 break;
2810 }
2811 break;
2812
2813 default:
2814 switch( INS_CO( m_op ) )
2815 {
2816 case 1:
2817 if( !m_gte.docop2( m_pc, INS_COFUN( m_op ) ) )
2818 {
2819 stop();
2820 }
2821
2822 advance_pc();
2823 break;
2824
2825 default:
2826 advance_pc();
2827 break;
2828 }
2829 break;
2830 }
2831 }
2832 break;
2833
2834 case OP_COP3:
2835 if( ( m_cp0r[ CP0_SR ] & SR_CU3 ) == 0 )
2836 {
2837 exception( EXC_CPU );
2838 }
2839 else
2840 {
2841 switch( INS_RS( m_op ) )
2842 {
2843 case RS_MFC:
2844 delayed_load( INS_RT( m_op ), getcp3dr( INS_RD( m_op ) ) );
2845 break;
2846
2847 case RS_CFC:
2848 delayed_load( INS_RT( m_op ), getcp3cr( INS_RD( m_op ) ) );
2849 break;
2850
2851 case RS_MTC:
2852 setcp3dr( INS_RD( m_op ), m_r[ INS_RT( m_op ) ] );
2853 advance_pc();
2854 break;
2855
2856 case RS_CTC:
2857 setcp3cr( INS_RD( m_op ), m_r[ INS_RT( m_op ) ] );
2858 advance_pc();
2859 break;
2860
2861 case RS_BC:
2862 case RS_BC_ALT:
2863 switch( INS_BC( m_op ) )
2864 {
2865 case BC_BCF:
2866 bc( 3, SR_CU3, 0 );
2867 break;
2868
2869 case BC_BCT:
2870 bc( 3, SR_CU3, 1 );
2871 break;
2872 }
2873 break;
2874
2875 default:
2876 advance_pc();
2877 break;
2878 }
2879 }
2880 break;
2881
2882 case OP_LB:
2883 {
2884 uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
2885 int breakpoint = load_data_address_breakpoint( address );
2886
2887 if( ( address & m_bad_byte_address_mask ) != 0 )
2888 {
2889 load_bad_address( address );
2890 }
2891 else if( breakpoint )
2892 {
2893 breakpoint_exception();
2894 }
2895 else
2896 {
2897 uint32_t data = PSXCPU_BYTE_EXTEND( readbyte( address ) );
2898
2899 if( m_berr )
2900 {
2901 load_bus_error_exception();
2902 }
2903 else
2904 {
2905 delayed_load( INS_RT( m_op ), data );
2906 }
2907 }
2908 }
2909 break;
2910
2911 case OP_LH:
2912 {
2913 uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
2914 int breakpoint = load_data_address_breakpoint( address );
2915
2916 if( ( address & m_bad_half_address_mask ) != 0 )
2917 {
2918 load_bad_address( address );
2919 }
2920 else if( breakpoint )
2921 {
2922 breakpoint_exception();
2923 }
2924 else
2925 {
2926 uint32_t data = PSXCPU_WORD_EXTEND( readhalf( address ) );
2927
2928 if( m_berr )
2929 {
2930 load_bus_error_exception();
2931 }
2932 else
2933 {
2934 delayed_load( INS_RT( m_op ), data );
2935 }
2936 }
2937 }
2938 break;
2939
2940 case OP_LWL:
2941 {
2942 uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
2943 int load_type = address & 3;
2944 int breakpoint;
2945
2946 address &= ~3;
2947 breakpoint = load_data_address_breakpoint( address );
2948
2949 if( ( address & m_bad_byte_address_mask ) != 0 )
2950 {
2951 load_bad_address( address );
2952 }
2953 else if( breakpoint )
2954 {
2955 breakpoint_exception();
2956 }
2957 else
2958 {
2959 uint32_t data = get_register_from_pipeline( INS_RT( m_op ) );
2960
2961 switch( load_type )
2962 {
2963 case 0:
2964 data = ( data & 0x00ffffff ) | ( readword_masked( address, 0x000000ff ) << 24 );
2965 break;
2966
2967 case 1:
2968 data = ( data & 0x0000ffff ) | ( readword_masked( address, 0x0000ffff ) << 16 );
2969 break;
2970
2971 case 2:
2972 data = ( data & 0x000000ff ) | ( readword_masked( address, 0x00ffffff ) << 8 );
2973 break;
2974
2975 case 3:
2976 data = readword( address );
2977 break;
2978 }
2979
2980 if( m_berr )
2981 {
2982 load_bus_error_exception();
2983 }
2984 else
2985 {
2986 delayed_load( INS_RT( m_op ), data );
2987 }
2988 }
2989 }
2990 break;
2991
2992 case OP_LW:
2993 {
2994 uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
2995 int breakpoint = load_data_address_breakpoint( address );
2996
2997 if( ( address & m_bad_word_address_mask ) != 0 )
2998 {
2999 load_bad_address( address );
3000 }
3001 else if( breakpoint )
3002 {
3003 breakpoint_exception();
3004 }
3005 else
3006 {
3007 uint32_t data = readword( address );
3008
3009 if( m_berr )
3010 {
3011 load_bus_error_exception();
3012 }
3013 else
3014 {
3015 delayed_load( INS_RT( m_op ), data );
3016 }
3017 }
3018 }
3019 break;
3020
3021 case OP_LBU:
3022 {
3023 uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
3024 int breakpoint = load_data_address_breakpoint( address );
3025
3026 if( ( address & m_bad_byte_address_mask ) != 0 )
3027 {
3028 load_bad_address( address );
3029 }
3030 else if( breakpoint )
3031 {
3032 breakpoint_exception();
3033 }
3034 else
3035 {
3036 uint32_t data = readbyte( address );
3037
3038 if( m_berr )
3039 {
3040 load_bus_error_exception();
3041 }
3042 else
3043 {
3044 delayed_load( INS_RT( m_op ), data );
3045 }
3046 }
3047 }
3048 break;
3049
3050 case OP_LHU:
3051 {
3052 uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
3053 int breakpoint = load_data_address_breakpoint( address );
3054
3055 if( ( address & m_bad_half_address_mask ) != 0 )
3056 {
3057 load_bad_address( address );
3058 }
3059 else if( breakpoint )
3060 {
3061 breakpoint_exception();
3062 }
3063 else
3064 {
3065 uint32_t data = readhalf( address );
3066
3067 if( m_berr )
3068 {
3069 load_bus_error_exception();
3070 }
3071 else
3072 {
3073 delayed_load( INS_RT( m_op ), data );
3074 }
3075 }
3076 }
3077 break;
3078
3079 case OP_LWR:
3080 {
3081 uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
3082 int breakpoint = load_data_address_breakpoint( address );
3083
3084 if( ( address & m_bad_byte_address_mask ) != 0 )
3085 {
3086 load_bad_address( address );
3087 }
3088 else if( breakpoint )
3089 {
3090 breakpoint_exception();
3091 }
3092 else
3093 {
3094 uint32_t data = get_register_from_pipeline( INS_RT( m_op ) );
3095
3096 switch( address & 3 )
3097 {
3098 case 0:
3099 data = readword( address );
3100 break;
3101
3102 case 1:
3103 data = ( data & 0xff000000 ) | ( readword_masked( address, 0xffffff00 ) >> 8 );
3104 break;
3105
3106 case 2:
3107 data = ( data & 0xffff0000 ) | ( readword_masked( address, 0xffff0000 ) >> 16 );
3108 break;
3109
3110 case 3:
3111 data = ( data & 0xffffff00 ) | ( readword_masked( address, 0xff000000 ) >> 24 );
3112 break;
3113 }
3114
3115 if( m_berr )
3116 {
3117 load_bus_error_exception();
3118 }
3119 else
3120 {
3121 delayed_load( INS_RT( m_op ), data );
3122 }
3123 }
3124 }
3125 break;
3126
3127 case OP_SB:
3128 {
3129 uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
3130 int breakpoint = store_data_address_breakpoint( address );
3131
3132 if( ( address & m_bad_byte_address_mask ) != 0 )
3133 {
3134 store_bad_address( address );
3135 }
3136 else
3137 {
3138 int shift = 8 * ( address & 3 );
3139 writeword_masked( address, m_r[ INS_RT( m_op ) ] << shift, 0xff << shift );
3140
3141 if( breakpoint )
3142 {
3143 breakpoint_exception();
3144 }
3145 else if( m_berr )
3146 {
3147 store_bus_error_exception();
3148 }
3149 else
3150 {
3151 advance_pc();
3152 }
3153 }
3154 }
3155 break;
3156
3157 case OP_SH:
3158 {
3159 uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
3160 int breakpoint = store_data_address_breakpoint( address );
3161
3162 if( ( address & m_bad_half_address_mask ) != 0 )
3163 {
3164 store_bad_address( address );
3165 }
3166 else
3167 {
3168 int shift = 8 * ( address & 2 );
3169 writeword_masked( address, m_r[ INS_RT( m_op ) ] << shift, 0xffff << shift );
3170
3171 if( breakpoint )
3172 {
3173 breakpoint_exception();
3174 }
3175 else if( m_berr )
3176 {
3177 store_bus_error_exception();
3178 }
3179 else
3180 {
3181 advance_pc();
3182 }
3183 }
3184 }
3185 break;
3186
3187 case OP_SWL:
3188 {
3189 uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
3190 int save_type = address & 3;
3191 int breakpoint;
3192
3193 address &= ~3;
3194 breakpoint = store_data_address_breakpoint( address );
3195
3196 if( ( address & m_bad_byte_address_mask ) != 0 )
3197 {
3198 store_bad_address( address );
3199 }
3200 else
3201 {
3202 switch( save_type )
3203 {
3204 case 0:
3205 writeword_masked( address, m_r[ INS_RT( m_op ) ] >> 24, 0x000000ff );
3206 break;
3207
3208 case 1:
3209 writeword_masked( address, m_r[ INS_RT( m_op ) ] >> 16, 0x0000ffff );
3210 break;
3211
3212 case 2:
3213 writeword_masked( address, m_r[ INS_RT( m_op ) ] >> 8, 0x00ffffff );
3214 break;
3215
3216 case 3:
3217 writeword( address, m_r[ INS_RT( m_op ) ] );
3218 break;
3219 }
3220
3221 if( breakpoint )
3222 {
3223 breakpoint_exception();
3224 }
3225 else if( m_berr )
3226 {
3227 store_bus_error_exception();
3228 }
3229 else
3230 {
3231 advance_pc();
3232 }
3233 }
3234 }
3235 break;
3236
3237 case OP_SW:
3238 {
3239 uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
3240 int breakpoint = store_data_address_breakpoint( address );
3241
3242 if( ( address & m_bad_word_address_mask ) != 0 )
3243 {
3244 store_bad_address( address );
3245 }
3246 else
3247 {
3248 writeword( address, m_r[ INS_RT( m_op ) ] );
3249
3250 if( breakpoint )
3251 {
3252 breakpoint_exception();
3253 }
3254 else if( m_berr )
3255 {
3256 store_bus_error_exception();
3257 }
3258 else
3259 {
3260 advance_pc();
3261 }
3262 }
3263 }
3264 break;
3265
3266 case OP_SWR:
3267 {
3268 uint32_t address = m_r[ INS_RS( m_op ) ] + PSXCPU_WORD_EXTEND( INS_IMMEDIATE( m_op ) );
3269 int breakpoint = store_data_address_breakpoint( address );
3270
3271 if( ( address & m_bad_byte_address_mask ) != 0 )
3272 {
3273 store_bad_address( address );
3274 }
3275 else
3276 {
3277 switch( address & 3 )
3278 {
3279 case 0:
3280 writeword( address, m_r[ INS_RT( m_op ) ] );
3281 break;
3282
3283 case 1:
3284 writeword_masked( address, m_r[ INS_RT( m_op ) ] << 8, 0xffffff00 );
3285 break;
3286
3287 case 2:
3288 writeword_masked( address, m_r[ INS_RT( m_op ) ] << 16, 0xffff0000 );
3289 break;
3290
3291 case 3:
3292 writeword_masked( address, m_r[ INS_RT( m_op ) ] << 24, 0xff000000 );
3293 break;
3294 }
3295
3296 if( breakpoint )
3297 {
3298 breakpoint_exception();
3299 }
3300 else if( m_berr )
3301 {
3302 store_bus_error_exception();
3303 }
3304 else
3305 {
3306 advance_pc();
3307 }
3308 }
3309 }
3310 break;
3311
3312 case OP_LWC0:
3313 lwc( 0, SR_CU0 );
3314 break;
3315
3316 case OP_LWC1:
3317 lwc( 1, SR_CU1 );
3318 break;
3319
3320 case OP_LWC2:
3321 lwc( 2, SR_CU2 );
3322 break;
3323
3324 case OP_LWC3:
3325 lwc( 3, SR_CU3 );
3326 break;
3327
3328 case OP_SWC0:
3329 swc( 0, SR_CU0 );
3330 break;
3331
3332 case OP_SWC1:
3333 swc( 1, SR_CU1 );
3334 break;
3335
3336 case OP_SWC2:
3337 swc( 2, SR_CU2 );
3338 break;
3339
3340 case OP_SWC3:
3341 swc( 3, SR_CU3 );
3342 break;
3343
3344 default:
3345 logerror( "%08x: unknown opcode %08x\n", m_pc, m_op );
3346 stop();
3347 exception( EXC_RI );
3348 break;
3349 }
3350 }
3351 }
3352
3353 m_icount--;
3354 } while( m_icount > 0 );
3355 }
3356
getcp1dr(int reg)3357 uint32_t psxcpu_device::getcp1dr( int reg )
3358 {
3359 /* if a mtc/ctc precedes then this will get the value moved (which cop1 register is irrelevant). */
3360 /* if a mfc/cfc follows then it will get the same value as this one. */
3361 return m_program->read_dword( m_pc + 4 );
3362 }
3363
setcp1dr(int reg,uint32_t value)3364 void psxcpu_device::setcp1dr( int reg, uint32_t value )
3365 {
3366 }
3367
getcp1cr(int reg)3368 uint32_t psxcpu_device::getcp1cr( int reg )
3369 {
3370 /* if a mtc/ctc precedes then this will get the value moved (which cop1 register is irrelevant). */
3371 /* if a mfc/cfc follows then it will get the same value as this one. */
3372 return m_program->read_dword( m_pc + 4 );
3373 }
3374
setcp1cr(int reg,uint32_t value)3375 void psxcpu_device::setcp1cr( int reg, uint32_t value )
3376 {
3377 }
3378
3379
getcp3dr(int reg)3380 uint32_t psxcpu_device::getcp3dr( int reg )
3381 {
3382 /* if you have mtc/ctc with an mfc/cfc directly afterwards then you get the value that was moved. */
3383 /* if you have an lwc with an mfc/cfc somewhere after it then you get the value that is loaded */
3384 /* otherwise you get the next opcode. which register you transfer to or from is irrelevant. */
3385 return m_program->read_dword( m_pc + 4 );
3386 }
3387
setcp3dr(int reg,uint32_t value)3388 void psxcpu_device::setcp3dr( int reg, uint32_t value )
3389 {
3390 }
3391
getcp3cr(int reg)3392 uint32_t psxcpu_device::getcp3cr( int reg )
3393 {
3394 /* if you have mtc/ctc with an mfc/cfc directly afterwards then you get the value that was moved. */
3395 /* if you have an lwc with an mfc/cfc somewhere after it then you get the value that is loaded */
3396 /* otherwise you get the next opcode. which register you transfer to or from is irrelevant. */
3397 return m_program->read_dword( m_pc + 4 );
3398 }
3399
setcp3cr(int reg,uint32_t value)3400 void psxcpu_device::setcp3cr( int reg, uint32_t value )
3401 {
3402 }
3403
gpu_r(offs_t offset,uint32_t mem_mask)3404 uint32_t psxcpu_device::gpu_r(offs_t offset, uint32_t mem_mask)
3405 {
3406 return m_gpu_read_handler( offset, mem_mask );
3407 }
3408
gpu_w(offs_t offset,uint32_t data,uint32_t mem_mask)3409 void psxcpu_device::gpu_w(offs_t offset, uint32_t data, uint32_t mem_mask)
3410 {
3411 m_gpu_write_handler( offset, data, mem_mask );
3412 }
3413
spu_r(offs_t offset,uint16_t mem_mask)3414 uint16_t psxcpu_device::spu_r(offs_t offset, uint16_t mem_mask)
3415 {
3416 return m_spu_read_handler( offset, mem_mask );
3417 }
3418
spu_w(offs_t offset,uint16_t data,uint16_t mem_mask)3419 void psxcpu_device::spu_w(offs_t offset, uint16_t data, uint16_t mem_mask)
3420 {
3421 m_spu_write_handler( offset, data, mem_mask );
3422 }
3423
cd_r(offs_t offset,uint8_t mem_mask)3424 uint8_t psxcpu_device::cd_r(offs_t offset, uint8_t mem_mask)
3425 {
3426 return m_cd_read_handler( offset, mem_mask );
3427 }
3428
cd_w(offs_t offset,uint8_t data,uint8_t mem_mask)3429 void psxcpu_device::cd_w(offs_t offset, uint8_t data, uint8_t mem_mask)
3430 {
3431 m_cd_write_handler( offset, data, mem_mask );
3432 }
3433
set_disable_rom_berr(bool mode)3434 void psxcpu_device::set_disable_rom_berr(bool mode)
3435 {
3436 m_disable_rom_berr = mode;
3437 }
3438
memory_space_config() const3439 device_memory_interface::space_config_vector psxcpu_device::memory_space_config() const
3440 {
3441 return space_config_vector {
3442 std::make_pair(AS_PROGRAM, &m_program_config),
3443 };
3444 }
3445
3446 //-------------------------------------------------
3447 // device_add_mconfig - add device configuration
3448 //-------------------------------------------------
3449
device_add_mconfig(machine_config & config)3450 void psxcpu_device::device_add_mconfig(machine_config &config)
3451 {
3452 auto &irq(PSX_IRQ(config, "irq", 0));
3453 irq.irq().set_inputline(DEVICE_SELF, PSXCPU_IRQ0);
3454
3455 auto &dma(PSX_DMA(config, "dma", 0));
3456 dma.irq().set("irq", FUNC(psxirq_device::intin3));
3457
3458 auto &mdec(PSX_MDEC(config, "mdec", 0));
3459 dma.install_write_handler(0, psxdma_device::write_delegate(&psxmdec_device::dma_write, &mdec));
3460 dma.install_read_handler(1, psxdma_device::write_delegate(&psxmdec_device::dma_read, &mdec));
3461
3462 auto &rcnt(PSX_RCNT(config, "rcnt", 0));
3463 rcnt.irq0().set("irq", FUNC(psxirq_device::intin4));
3464 rcnt.irq1().set("irq", FUNC(psxirq_device::intin5));
3465 rcnt.irq2().set("irq", FUNC(psxirq_device::intin6));
3466
3467 auto &sio0(PSX_SIO0(config, "sio0", DERIVED_CLOCK(1, 2)));
3468 sio0.irq_handler().set("irq", FUNC(psxirq_device::intin7));
3469
3470 auto &sio1(PSX_SIO1(config, "sio1", DERIVED_CLOCK(1, 2)));
3471 sio1.irq_handler().set("irq", FUNC(psxirq_device::intin8));
3472
3473 RAM(config, "ram").set_default_value(0x00);
3474 }
3475