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