@@ -84,15 +84,15 @@ uint32_t g_psx_cpu_cop0_write_mask_table[] = {
8484 0x00000000 // cop0r15 - PRID - Processor ID (R)
8585};
8686
87- #define OP ((cpu->buf[1] >> 26) & 0x3f)
88- #define S ((cpu->buf[1] >> 21) & 0x1f)
89- #define T ((cpu->buf[1] >> 16) & 0x1f)
90- #define D ((cpu->buf[1] >> 11) & 0x1f)
91- #define IMM5 ((cpu->buf[1] >> 6) & 0x1f)
92- #define CMT ((cpu->buf[1] >> 6) & 0xfffff)
93- #define SOP (cpu->buf[1] & 0x3f)
94- #define IMM26 (cpu->buf[1] & 0x3ffffff)
95- #define IMM16 (cpu->buf[1] & 0xffff)
87+ #define OP ((cpu->opcode >> 26) & 0x3f)
88+ #define S ((cpu->opcode >> 21) & 0x1f)
89+ #define T ((cpu->opcode >> 16) & 0x1f)
90+ #define D ((cpu->opcode >> 11) & 0x1f)
91+ #define IMM5 ((cpu->opcode >> 6) & 0x1f)
92+ #define CMT ((cpu->opcode >> 6) & 0xfffff)
93+ #define SOP (cpu->opcode & 0x3f)
94+ #define IMM26 (cpu->opcode & 0x3ffffff)
95+ #define IMM16 (cpu->opcode & 0xffff)
9696#define IMM16S ((int32_t)((int16_t)IMM16))
9797
9898#define R_R0 (cpu->r[0])
@@ -128,7 +128,7 @@ uint32_t g_psx_cpu_cop0_write_mask_table[] = {
128128#define R_FP (cpu->r[30])
129129#define R_RA (cpu->r[31])
130130
131- // #define CPU_TRACE
131+ #define CPU_TRACE
132132
133133#ifdef CPU_TRACE
134134#define TRACE_M (m ) \
@@ -210,6 +210,12 @@ uint32_t g_psx_cpu_cop0_write_mask_table[] = {
210210#define SE8 (v ) ((int32_t)((int8_t)v))
211211#define SE16 (v ) ((int32_t)((int16_t)v))
212212
213+ #define BRANCH (offset ) \
214+ cpu->next_pc = cpu->next_pc + (offset); \
215+ cpu->next_pc = cpu->next_pc - 4; \
216+ cpu->branch = 1; \
217+ cpu->branch_taken = 1;
218+
213219const char * g_mips_cop0_register_names [] = {
214220 "cop0_r0" ,
215221 "cop0_r1" ,
@@ -288,28 +294,13 @@ void cpu_a_kcall_hook(psx_cpu_t*);
288294void cpu_b_kcall_hook (psx_cpu_t * );
289295
290296void psx_cpu_fetch (psx_cpu_t * cpu ) {
291- cpu -> buf [0 ] = psx_bus_read32 (cpu -> bus , cpu -> pc );
292- cpu -> pc += 4 ;
297+ // cpu->buf[0] = psx_bus_read32(cpu->bus, cpu->pc);
298+ // cpu->pc += 4;
293299
294300 // Discard fetch cycles
295301 psx_bus_get_access_cycles (cpu -> bus );
296302}
297303
298- void psx_cpu_init (psx_cpu_t * cpu , psx_bus_t * bus ) {
299- memset (cpu , 0 , sizeof (psx_cpu_t ));
300-
301- psx_cpu_set_a_kcall_hook (cpu , cpu_a_kcall_hook );
302- psx_cpu_set_b_kcall_hook (cpu , cpu_b_kcall_hook );
303-
304- cpu -> bus = bus ;
305- cpu -> pc = 0xbfc00000 ;
306-
307- cpu -> cop0_r [COP0_SR ] = 0x10900000 ;
308- cpu -> cop0_r [COP0_PRID ] = 0x00000002 ;
309-
310- psx_cpu_fetch (cpu );
311- }
312-
313304void psx_cpu_destroy (psx_cpu_t * cpu ) {
314305 free (cpu );
315306}
@@ -330,28 +321,43 @@ void psx_cpu_load_state(psx_cpu_t* cpu, FILE* file) {
330321 fread ((char * )cpu , sizeof (* cpu ) - sizeof (psx_bus_t * ), 1 , file );
331322}
332323
333- void psx_cpu_cycle (psx_cpu_t * cpu ) {
334- if ((cpu -> pc & 0x3fffffff ) == 0x000000a4 )
335- if (cpu -> a_function_hook ) cpu -> a_function_hook (cpu );
324+ void psx_cpu_init (psx_cpu_t * cpu , psx_bus_t * bus ) {
325+ memset (cpu , 0 , sizeof (psx_cpu_t ));
326+
327+ psx_cpu_set_a_kcall_hook (cpu , cpu_a_kcall_hook );
328+ psx_cpu_set_b_kcall_hook (cpu , cpu_b_kcall_hook );
336329
330+ cpu -> bus = bus ;
331+ cpu -> pc = 0xbfc00000 ;
332+ cpu -> next_pc = cpu -> pc + 4 ;
333+
334+ cpu -> cop0_r [COP0_SR ] = 0x10900000 ;
335+ cpu -> cop0_r [COP0_PRID ] = 0x00000002 ;
336+ }
337+
338+ void psx_cpu_cycle (psx_cpu_t * cpu ) {
337339 if ((cpu -> pc & 0x3fffffff ) == 0x000000b4 )
338- if (cpu -> a_function_hook ) cpu -> b_function_hook (cpu );
340+ if (cpu -> b_function_hook ) cpu -> b_function_hook (cpu );
339341
340- cpu -> buf [1 ] = cpu -> buf [0 ];
342+ cpu -> saved_pc = cpu -> pc ;
343+ cpu -> delay_slot = cpu -> branch ;
344+ cpu -> branch = 0 ;
345+ cpu -> branch_taken = 0 ;
341346
342- if (cpu -> pc & 0x3 ) {
347+ if (cpu -> saved_pc & 3 ) {
343348 psx_cpu_exception (cpu , CAUSE_ADEL );
344-
345- return ;
346349 }
347350
348- if (psx_cpu_check_irq (cpu ))
349- return ;
351+ cpu -> opcode = psx_bus_read32 (cpu -> bus , cpu -> pc );
350352
351- psx_cpu_fetch (cpu );
353+ cpu -> pc = cpu -> next_pc ;
354+ cpu -> next_pc += 4 ;
352355
353- cpu -> delay_slot = cpu -> branch ;
354- cpu -> branch = 0 ;
356+ if (psx_cpu_check_irq (cpu )) {
357+ psx_cpu_exception (cpu , CAUSE_INT );
358+
359+ return ;
360+ }
355361
356362 g_psx_cpu_primary_table [OP ](cpu );
357363
@@ -362,33 +368,25 @@ void psx_cpu_cycle(psx_cpu_t* cpu) {
362368}
363369
364370int psx_cpu_check_irq (psx_cpu_t * cpu ) {
365- if ((cpu -> cop0_r [COP0_SR ] & SR_IEC ) && (cpu -> cop0_r [COP0_SR ] & cpu -> cop0_r [COP0_CAUSE ] & 0x00000700 )) {
366- psx_cpu_exception (cpu , CAUSE_INT );
367-
368- return 1 ;
369- }
370-
371- return 0 ;
371+ return (cpu -> cop0_r [COP0_SR ] & SR_IEC ) && (cpu -> cop0_r [COP0_SR ] & cpu -> cop0_r [COP0_CAUSE ] & 0x00000700 );
372372}
373373
374374void psx_cpu_exception (psx_cpu_t * cpu , uint32_t cause ) {
375+ cpu -> cop0_r [COP0_CAUSE ] &= 0x0000ff00 ;
376+
375377 // Set excode and clear 3 LSBs
376378 cpu -> cop0_r [COP0_CAUSE ] &= 0xffffff80 ;
377379 cpu -> cop0_r [COP0_CAUSE ] |= cause ;
378380
379- if (cause == CAUSE_INT ) {
380- cpu -> cop0_r [COP0_EPC ] = cpu -> pc - 4 ;
381- } else {
382- cpu -> cop0_r [COP0_EPC ] = cpu -> pc - 8 ;
383- }
381+ cpu -> cop0_r [COP0_EPC ] = cpu -> saved_pc ;
384382
385- // If we're in a delay slot, set delay slot bit
386- // on CAUSE
387383 if (cpu -> delay_slot ) {
388384 cpu -> cop0_r [COP0_EPC ] -= 4 ;
389385 cpu -> cop0_r [COP0_CAUSE ] |= 0x80000000 ;
390- } else {
391- cpu -> cop0_r [COP0_CAUSE ] &= 0x7fffffff ;
386+ }
387+
388+ if ((cause == CAUSE_INT ) && (cpu -> cop0_r [COP0_EPC ] & 0xfe000000 ) == 0x4a000000 ) {
389+ cpu -> cop0_r [COP0_EPC ] += 4 ;
392390 }
393391
394392 // Do exception stack push
@@ -399,21 +397,15 @@ void psx_cpu_exception(psx_cpu_t* cpu, uint32_t cause) {
399397
400398 // Set PC to the vector selected on BEV
401399 cpu -> pc = (cpu -> cop0_r [COP0_SR ] & SR_BEV ) ? 0xbfc00180 : 0x80000080 ;
402-
403- // Simulate pipeline flush
404- psx_cpu_fetch (cpu );
405-
406- cpu -> buf [1 ] = cpu -> buf [0 ];
400+ cpu -> next_pc = cpu -> pc + 4 ;
407401}
408402
409403void psx_cpu_irq (psx_cpu_t * cpu , uint32_t irq ) {
410- // Set interrupt pending field
411- cpu -> cop0_r [COP0_CAUSE ] &= ~SR_IM2 ;
412404 cpu -> cop0_r [COP0_CAUSE ] |= irq ? SR_IM2 : 0 ;
413405}
414406
415407void psx_cpu_i_invalid (psx_cpu_t * cpu ) {
416- log_fatal ("%08x: Illegal instruction %08x" , cpu -> pc - 8 , cpu -> buf [ 1 ] );
408+ log_fatal ("%08x: Illegal instruction %08x" , cpu -> pc - 8 , cpu -> opcode );
417409
418410 psx_cpu_exception (cpu , CAUSE_RI );
419411}
@@ -425,6 +417,7 @@ void psx_cpu_i_special(psx_cpu_t* cpu) {
425417
426418void psx_cpu_i_bxx (psx_cpu_t * cpu ) {
427419 cpu -> branch = 1 ;
420+ cpu -> branch_taken = 0 ;
428421
429422 g_psx_cpu_bxx_table [T ](cpu );
430423}
@@ -438,8 +431,7 @@ void psx_cpu_i_bltz(psx_cpu_t* cpu) {
438431 DO_PENDING_LOAD ;
439432
440433 if ((int32_t )s < (int32_t )0 ) {
441- cpu -> pc -= 4 ;
442- cpu -> pc += (IMM16S << 2 );
434+ BRANCH (IMM16S << 2 );
443435 }
444436}
445437
@@ -451,8 +443,7 @@ void psx_cpu_i_bgez(psx_cpu_t* cpu) {
451443 DO_PENDING_LOAD ;
452444
453445 if ((int32_t )s >= (int32_t )0 ) {
454- cpu -> pc -= 4 ;
455- cpu -> pc += (IMM16S << 2 );
446+ BRANCH (IMM16S << 2 );
456447 }
457448}
458449
@@ -463,11 +454,10 @@ void psx_cpu_i_bltzal(psx_cpu_t* cpu) {
463454
464455 DO_PENDING_LOAD ;
465456
466- R_RA = cpu -> pc ;
457+ R_RA = cpu -> next_pc ;
467458
468459 if ((int32_t )s < (int32_t )0 ) {
469- cpu -> pc -= 4 ;
470- cpu -> pc += (IMM16S << 2 );
460+ BRANCH (IMM16S << 2 );
471461 }
472462}
473463
@@ -478,11 +468,10 @@ void psx_cpu_i_bgezal(psx_cpu_t* cpu) {
478468
479469 DO_PENDING_LOAD ;
480470
481- R_RA = cpu -> pc ;
471+ R_RA = cpu -> next_pc ;
482472
483473 if ((int32_t )s >= (int32_t )0 ) {
484- cpu -> pc -= 4 ;
485- cpu -> pc += (IMM16S << 2 );
474+ BRANCH (IMM16S << 2 );
486475 }
487476}
488477
@@ -493,7 +482,7 @@ void psx_cpu_i_j(psx_cpu_t* cpu) {
493482
494483 DO_PENDING_LOAD ;
495484
496- cpu -> pc = (cpu -> pc & 0xf0000000 ) | (IMM26 << 2 );
485+ cpu -> next_pc = (cpu -> next_pc & 0xf0000000 ) | (IMM26 << 2 );
497486}
498487
499488void psx_cpu_i_jal (psx_cpu_t * cpu ) {
@@ -503,13 +492,14 @@ void psx_cpu_i_jal(psx_cpu_t* cpu) {
503492
504493 DO_PENDING_LOAD ;
505494
506- cpu -> r [ 31 ] = cpu -> pc ;
495+ R_RA = cpu -> next_pc ;
507496
508- cpu -> pc = (cpu -> pc & 0xf0000000 ) | (IMM26 << 2 );
497+ cpu -> next_pc = (cpu -> next_pc & 0xf0000000 ) | (IMM26 << 2 );
509498}
510499
511500void psx_cpu_i_beq (psx_cpu_t * cpu ) {
512501 cpu -> branch = 1 ;
502+ cpu -> branch_taken = 0 ;
513503
514504 TRACE_B ("beq" );
515505
@@ -519,13 +509,13 @@ void psx_cpu_i_beq(psx_cpu_t* cpu) {
519509 DO_PENDING_LOAD ;
520510
521511 if (s == t ) {
522- cpu -> pc -= 4 ;
523- cpu -> pc += (IMM16S << 2 );
512+ BRANCH (IMM16S << 2 );
524513 }
525514}
526515
527516void psx_cpu_i_bne (psx_cpu_t * cpu ) {
528517 cpu -> branch = 1 ;
518+ cpu -> branch_taken = 0 ;
529519
530520 TRACE_B ("bne" );
531521
@@ -535,13 +525,13 @@ void psx_cpu_i_bne(psx_cpu_t* cpu) {
535525 DO_PENDING_LOAD ;
536526
537527 if (s != t ) {
538- cpu -> pc -= 4 ;
539- cpu -> pc += (IMM16S << 2 );
528+ BRANCH (IMM16S << 2 );
540529 }
541530}
542531
543532void psx_cpu_i_blez (psx_cpu_t * cpu ) {
544533 cpu -> branch = 1 ;
534+ cpu -> branch_taken = 0 ;
545535
546536 TRACE_B ("blez" );
547537
@@ -550,13 +540,13 @@ void psx_cpu_i_blez(psx_cpu_t* cpu) {
550540 DO_PENDING_LOAD ;
551541
552542 if ((int32_t )s <= (int32_t )0 ) {
553- cpu -> pc -= 4 ;
554- cpu -> pc += (IMM16S << 2 );
543+ BRANCH (IMM16S << 2 );
555544 }
556545}
557546
558547void psx_cpu_i_bgtz (psx_cpu_t * cpu ) {
559548 cpu -> branch = 1 ;
549+ cpu -> branch_taken = 0 ;
560550
561551 TRACE_B ("bgtz" );
562552
@@ -565,8 +555,7 @@ void psx_cpu_i_bgtz(psx_cpu_t* cpu) {
565555 DO_PENDING_LOAD ;
566556
567557 if ((int32_t )s > (int32_t )0 ) {
568- cpu -> pc -= 4 ;
569- cpu -> pc += (IMM16S << 2 );
558+ BRANCH (IMM16S << 2 );
570559 }
571560}
572561
@@ -1002,7 +991,7 @@ void psx_cpu_i_jr(psx_cpu_t* cpu) {
1002991
1003992 DO_PENDING_LOAD ;
1004993
1005- cpu -> pc = s ;
994+ cpu -> next_pc = s ;
1006995}
1007996
1008997void psx_cpu_i_jalr (psx_cpu_t * cpu ) {
@@ -1014,15 +1003,13 @@ void psx_cpu_i_jalr(psx_cpu_t* cpu) {
10141003
10151004 DO_PENDING_LOAD ;
10161005
1017- cpu -> r [D ] = cpu -> pc ;
1006+ cpu -> r [D ] = cpu -> next_pc ;
10181007
1019- cpu -> pc = s ;
1008+ cpu -> next_pc = s ;
10201009}
10211010
10221011void psx_cpu_i_syscall (psx_cpu_t * cpu ) {
10231012 TRACE_I20 ("syscall" );
1024-
1025- //log_info("SYS(%02xh): %s()", cpu->r[4], g_psx_cpu_syscall_function_symbol_table[cpu->r[4]]);
10261013
10271014 DO_PENDING_LOAD ;
10281015
0 commit comments