Skip to content

Commit 61c23fa

Browse files
committed
Rework pipelining implementation
The shell is finally booting!
1 parent a034f22 commit 61c23fa

11 files changed

Lines changed: 128 additions & 115 deletions

File tree

psx/cpu.c

Lines changed: 77 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
213219
const char* g_mips_cop0_register_names[] = {
214220
"cop0_r0",
215221
"cop0_r1",
@@ -288,28 +294,13 @@ void cpu_a_kcall_hook(psx_cpu_t*);
288294
void cpu_b_kcall_hook(psx_cpu_t*);
289295

290296
void 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-
313304
void 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

364370
int 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

374374
void 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

409403
void 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

415407
void 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

426418
void 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

499488
void 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

511500
void 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

527516
void 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

543532
void 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

558547
void 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

1008997
void 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

10221011
void 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

psx/cpu.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,13 @@ typedef void (*psx_cpu_kcall_hook_t)(psx_cpu_t*);
6666

6767
struct psx_cpu_t {
6868
uint32_t r[32];
69-
uint32_t buf[2];
70-
uint32_t pc;
69+
uint32_t opcode;
70+
uint32_t pc, next_pc, saved_pc;
7171
uint32_t hi, lo;
7272
uint32_t load_d, load_v;
7373
uint32_t last_cycles;
7474
uint32_t total_cycles;
75-
int branch, delay_slot;
75+
int branch, delay_slot, branch_taken;
7676

7777
uint32_t cop0_r[16];
7878

0 commit comments

Comments
 (0)