mirror of
https://github.com/n64dev/cen64.git
synced 2024-06-20 21:17:58 -04:00
Implement DCB-type stalls.
This commit is contained in:
parent
a53d9a6d88
commit
98d3ae952c
|
@ -29,6 +29,8 @@
|
|||
#define OPCODE_INFO_NEEDFS ((1U << 3) | (1U << 0))
|
||||
#define OPCODE_INFO_NEEDRT (1U << 4)
|
||||
#define OPCODE_INFO_NEEDFT ((1U << 4) | (1U << 1))
|
||||
#define OPCODE_INFO_LOAD (1U << 5)
|
||||
#define OPCODE_INFO_STORE (1U << 6)
|
||||
|
||||
enum vr4300_fmt {
|
||||
VR4300_FMT_S = 16,
|
||||
|
|
|
@ -220,6 +220,12 @@ void VR4300_DADE(struct vr4300 *vr4300) {
|
|||
|
||||
// DCB: Data cache busy interlock.
|
||||
void VR4300_DCB(struct vr4300 *vr4300) {
|
||||
vr4300->pipeline.dcwb_latch.last_op_was_cache_store = false;
|
||||
vr4300_common_interlocks(vr4300, 0, 1);
|
||||
}
|
||||
|
||||
// DCM: Data cache busy interlock.
|
||||
void VR4300_DCM(struct vr4300 *vr4300) {
|
||||
struct vr4300_dcwb_latch *dcwb_latch = &vr4300->pipeline.dcwb_latch;
|
||||
struct vr4300_exdc_latch *exdc_latch = &vr4300->pipeline.exdc_latch;
|
||||
struct vr4300_bus_request *request = &exdc_latch->request;
|
||||
|
@ -303,11 +309,6 @@ void VR4300_DCB(struct vr4300 *vr4300) {
|
|||
vr4300_dcache_fill(&vr4300->dcache, vaddr, paddr, data);
|
||||
}
|
||||
|
||||
// DCM: Data cache miss interlock.
|
||||
void VR4300_DCM(struct vr4300 *vr4300) {
|
||||
vr4300_common_interlocks(vr4300, 0, 6);
|
||||
}
|
||||
|
||||
// DTLB: Data TLB exception.
|
||||
void VR4300_DTLB(struct vr4300 *vr4300, unsigned miss, unsigned inv, unsigned mod) {
|
||||
struct vr4300_exdc_latch *exdc_latch = &vr4300->pipeline.exdc_latch;
|
||||
|
|
|
@ -78,20 +78,20 @@
|
|||
#define DSUBU VR4300_BUILD_OP(DSUBU, DADDU_DSUBU, INFO2(NEEDRS, NEEDRT))
|
||||
#define JALR VR4300_BUILD_OP(JALR, JALR_JR, INFO2(BRANCH, NEEDRS))
|
||||
#define JR VR4300_BUILD_OP(JR, JALR_JR, INFO2(BRANCH, NEEDRS))
|
||||
#define LB VR4300_BUILD_OP(LB, LOAD_STORE, INFO1(NEEDRS))
|
||||
#define LBU VR4300_BUILD_OP(LBU, LOAD_STORE, INFO1(NEEDRS))
|
||||
#define LD VR4300_BUILD_OP(LD, LD_SD, INFO1(NEEDRS))
|
||||
#define LDL VR4300_BUILD_OP(LDL, LDL_LDR, INFO2(NEEDRS, NEEDRT))
|
||||
#define LDR VR4300_BUILD_OP(LDR, LDL_LDR, INFO2(NEEDRS, NEEDRT))
|
||||
#define LH VR4300_BUILD_OP(LH, LOAD_STORE, INFO1(NEEDRS))
|
||||
#define LHU VR4300_BUILD_OP(LHU, LOAD_STORE, INFO1(NEEDRS))
|
||||
#define LB VR4300_BUILD_OP(LB, LOAD_STORE, INFO2(NEEDRS, LOAD))
|
||||
#define LBU VR4300_BUILD_OP(LBU, LOAD_STORE, INFO2(NEEDRS, LOAD))
|
||||
#define LD VR4300_BUILD_OP(LD, LD_SD, INFO2(NEEDRS, LOAD))
|
||||
#define LDL VR4300_BUILD_OP(LDL, LDL_LDR, INFO3(NEEDRS, NEEDRT, LOAD))
|
||||
#define LDR VR4300_BUILD_OP(LDR, LDL_LDR, INFO3(NEEDRS, NEEDRT, LOAD))
|
||||
#define LH VR4300_BUILD_OP(LH, LOAD_STORE, INFO2(NEEDRS, LOAD))
|
||||
#define LHU VR4300_BUILD_OP(LHU, LOAD_STORE, INFO2(NEEDRS, LOAD))
|
||||
#define LL VR4300_BUILD_OP(LL, INVALID, INFO1(NONE))
|
||||
#define LLD VR4300_BUILD_OP(LLD, INVALID, INFO1(NONE))
|
||||
#define LUI VR4300_BUILD_OP(LUI, ADDIU_LUI_SUBIU, INFO1(NONE))
|
||||
#define LW VR4300_BUILD_OP(LW, LOAD_STORE, INFO1(NEEDRS))
|
||||
#define LWL VR4300_BUILD_OP(LWL, LWL_LWR, INFO2(NEEDRS, NEEDRT))
|
||||
#define LWR VR4300_BUILD_OP(LWR, LWL_LWR, INFO2(NEEDRS, NEEDRT))
|
||||
#define LWU VR4300_BUILD_OP(LWU, LOAD_STORE, INFO1(NEEDRS))
|
||||
#define LW VR4300_BUILD_OP(LW, LOAD_STORE, INFO2(NEEDRS, LOAD))
|
||||
#define LWL VR4300_BUILD_OP(LWL, LWL_LWR, INFO3(NEEDRS, NEEDRT, LOAD))
|
||||
#define LWR VR4300_BUILD_OP(LWR, LWL_LWR, INFO3(NEEDRS, NEEDRT, LOAD))
|
||||
#define LWU VR4300_BUILD_OP(LWU, LOAD_STORE, INFO2(NEEDRS, LOAD))
|
||||
#define MFHI VR4300_BUILD_OP(MFHI, MFHI_MFLO, INFO1(NONE))
|
||||
#define MFLO VR4300_BUILD_OP(MFLO, MFHI_MFLO, INFO1(NONE))
|
||||
#define MTHI VR4300_BUILD_OP(MTHI, MTHI_MTLO, INFO1(NEEDRS))
|
||||
|
@ -101,13 +101,13 @@
|
|||
#define NOR VR4300_BUILD_OP(NOR, NOR, INFO2(NEEDRS, NEEDRT))
|
||||
#define OR VR4300_BUILD_OP(OR, AND_OR_XOR, INFO2(NEEDRS, NEEDRT))
|
||||
#define ORI VR4300_BUILD_OP(ORI, ANDI_ORI_XORI, INFO1(NEEDRS))
|
||||
#define SB VR4300_BUILD_OP(SB, LOAD_STORE, INFO2(NEEDRS, NEEDRT))
|
||||
#define SB VR4300_BUILD_OP(SB, LOAD_STORE, INFO3(NEEDRS, NEEDRT, STORE))
|
||||
#define SC VR4300_BUILD_OP(SC, INVALID, INFO1(NONE))
|
||||
#define SCD VR4300_BUILD_OP(SCD, INVALID, INFO1(NONE))
|
||||
#define SD VR4300_BUILD_OP(SD, LD_SD, INFO2(NEEDRS, NEEDRT))
|
||||
#define SDL VR4300_BUILD_OP(SDL, SDL_SDR, INFO2(NEEDRS, NEEDRT))
|
||||
#define SDR VR4300_BUILD_OP(SDR, SDL_SDR, INFO2(NEEDRS, NEEDRT))
|
||||
#define SH VR4300_BUILD_OP(SH, LOAD_STORE, INFO2(NEEDRS, NEEDRT))
|
||||
#define SD VR4300_BUILD_OP(SD, LD_SD, INFO3(NEEDRS, NEEDRT, STORE))
|
||||
#define SDL VR4300_BUILD_OP(SDL, SDL_SDR, INFO3(NEEDRS, NEEDRT, STORE))
|
||||
#define SDR VR4300_BUILD_OP(SDR, SDL_SDR, INFO3(NEEDRS, NEEDRT, STORE))
|
||||
#define SH VR4300_BUILD_OP(SH, LOAD_STORE, INFO3(NEEDRS, NEEDRT, STORE))
|
||||
#define SLL VR4300_BUILD_OP(SLL, SLL_SLLV, INFO1(NEEDRT))
|
||||
#define SLLV VR4300_BUILD_OP(SLLV, SLL_SLLV, INFO2(NEEDRS, NEEDRT))
|
||||
#define SLT VR4300_BUILD_OP(SLT, SLT, INFO2(NEEDRS, NEEDRT))
|
||||
|
@ -120,9 +120,9 @@
|
|||
#define SRLV VR4300_BUILD_OP(SRLV, SRLV, INFO2(NEEDRS, NEEDRT))
|
||||
#define SUB VR4300_BUILD_OP(SUB, ADD_SUB, INFO2(NEEDRS, NEEDRT))
|
||||
#define SUBU VR4300_BUILD_OP(SUBU, ADDU_SUBU, INFO1(NEEDRS))
|
||||
#define SW VR4300_BUILD_OP(SW, LOAD_STORE, INFO2(NEEDRS, NEEDRT))
|
||||
#define SWL VR4300_BUILD_OP(SWL, SWL_SWR, INFO2(NEEDRS, NEEDRT))
|
||||
#define SWR VR4300_BUILD_OP(SWR, SWL_SWR, INFO2(NEEDRS, NEEDRT))
|
||||
#define SW VR4300_BUILD_OP(SW, LOAD_STORE, INFO3(NEEDRS, NEEDRT, STORE))
|
||||
#define SWL VR4300_BUILD_OP(SWL, SWL_SWR, INFO3(NEEDRS, NEEDRT, STORE))
|
||||
#define SWR VR4300_BUILD_OP(SWR, SWL_SWR, INFO3(NEEDRS, NEEDRT, STORE))
|
||||
#define SYNC VR4300_BUILD_OP(SYNC, SLL_SLLV, INFO1(NONE))
|
||||
#define SYSCALL VR4300_BUILD_OP(SYSCALL, INVALID, INFO1(NONE))
|
||||
#define TEQ VR4300_BUILD_OP(TEQ, INVALID, INFO1(NONE))
|
||||
|
@ -145,12 +145,12 @@
|
|||
#define CTC0 VR4300_BUILD_OP(CTC0, INVALID, INFO1(NONE))
|
||||
#define DMFC0 VR4300_BUILD_OP(DMFC0, DMFC0, INFO1(NONE))
|
||||
#define DMTC0 VR4300_BUILD_OP(DMTC0, DMTC0, INFO1(NEEDRT))
|
||||
#define LDC0 VR4300_BUILD_OP(LDC0, INVALID, INFO1(NONE))
|
||||
#define LWC0 VR4300_BUILD_OP(LWC0, INVALID, INFO1(NONE))
|
||||
#define LDC0 VR4300_BUILD_OP(LDC0, INVALID, INFO1(LOAD))
|
||||
#define LWC0 VR4300_BUILD_OP(LWC0, INVALID, INFO1(LOAD))
|
||||
#define MFC0 VR4300_BUILD_OP(MFC0, MFC0, INFO1(NONE))
|
||||
#define MTC0 VR4300_BUILD_OP(MTC0, MTC0, INFO1(NEEDRT))
|
||||
#define SDC0 VR4300_BUILD_OP(SDC0, INVALID, INFO1(NONE))
|
||||
#define SWC0 VR4300_BUILD_OP(SWC0, INVALID, INFO1(NONE))
|
||||
#define SDC0 VR4300_BUILD_OP(SDC0, INVALID, INFO1(STORE))
|
||||
#define SWC0 VR4300_BUILD_OP(SWC0, INVALID, INFO1(STORE))
|
||||
|
||||
#define CACHE VR4300_BUILD_OP(CACHE, CACHE, INFO1(NEEDRS))
|
||||
#define ERET VR4300_BUILD_OP(ERET, ERET, INFO1(NONE))
|
||||
|
@ -164,12 +164,12 @@
|
|||
#define CTC1 VR4300_BUILD_OP(CTC1, CTC1, INFO2(FPU, NONE))
|
||||
#define DMFC1 VR4300_BUILD_OP(DMFC1, DMFC1, INFO2(FPU, NEEDFS))
|
||||
#define DMTC1 VR4300_BUILD_OP(DMTC1, DMTC1, INFO2(FPU, NEEDRT))
|
||||
#define LDC1 VR4300_BUILD_OP(LDC1, LDC1, INFO2(FPU, NEEDRS))
|
||||
#define LWC1 VR4300_BUILD_OP(LWC1, LWC1, INFO3(FPU, NEEDRS, NEEDFT))
|
||||
#define LDC1 VR4300_BUILD_OP(LDC1, LDC1, INFO3(FPU, NEEDRS, LOAD))
|
||||
#define LWC1 VR4300_BUILD_OP(LWC1, LWC1, INFO4(FPU, NEEDRS, NEEDFT, LOAD))
|
||||
#define MFC1 VR4300_BUILD_OP(MFC1, MFC1, INFO2(FPU, NEEDFS))
|
||||
#define MTC1 VR4300_BUILD_OP(MTC1, MTC1, INFO3(FPU, NEEDFS, NEEDRT))
|
||||
#define SDC1 VR4300_BUILD_OP(SDC1, SDC1, INFO3(FPU, NEEDRS, NEEDFT))
|
||||
#define SWC1 VR4300_BUILD_OP(SWC1, SWC1, INFO3(FPU, NEEDRS, NEEDFT))
|
||||
#define SDC1 VR4300_BUILD_OP(SDC1, SDC1, INFO4(FPU, NEEDRS, NEEDFT, STORE))
|
||||
#define SWC1 VR4300_BUILD_OP(SWC1, SWC1, INFO4(FPU, NEEDRS, NEEDFT, STORE))
|
||||
|
||||
#define CP1_ABS VR4300_BUILD_OP(CP1_ABS, CP1_ABS, INFO3(FPU, FPU, NEEDFS))
|
||||
#define CP1_ADD VR4300_BUILD_OP(CP1_ADD, CP1_ADD, INFO3(FPU, NEEDFS, NEEDFT))
|
||||
|
|
|
@ -279,7 +279,7 @@ static int vr4300_dc_stage(struct vr4300 *vr4300) {
|
|||
}
|
||||
}
|
||||
|
||||
// If not cached or we miss in the DC, it's an DCB.
|
||||
// If not cached or we miss in the DC, it's an DCM.
|
||||
if (likely(exdc_latch->request.type < VR4300_BUS_REQUEST_CACHE)) {
|
||||
uint64_t dword, rtemp, wtemp, wdqm;
|
||||
unsigned shiftamt, rshiftamt, lshiftamt;
|
||||
|
@ -287,10 +287,33 @@ static int vr4300_dc_stage(struct vr4300 *vr4300) {
|
|||
|
||||
line = vr4300_dcache_probe(&vr4300->dcache, vaddr, paddr);
|
||||
|
||||
if (!(line && cached)) {
|
||||
if (cached) {
|
||||
bool last_cache_was_store = dcwb_latch->last_op_was_cache_store;
|
||||
dcwb_latch->last_op_was_cache_store = (exdc_latch->request.type ==
|
||||
VR4300_BUS_REQUEST_WRITE);
|
||||
|
||||
if (!line) {
|
||||
request->paddr = paddr;
|
||||
exdc_latch->cached = cached;
|
||||
|
||||
// Miss: stall for one cycle, then move to the DCM phase.
|
||||
vr4300->pipeline.cycles_to_stall = 0;
|
||||
vr4300->regs[PIPELINE_CYCLE_TYPE] = 6;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Cached store-to-cached operation will result in a DCB.
|
||||
if (last_cache_was_store) {
|
||||
VR4300_DCB(vr4300);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
dcwb_latch->last_op_was_cache_store = false;
|
||||
|
||||
request->paddr = paddr;
|
||||
exdc_latch->cached = cached;
|
||||
|
||||
VR4300_DCM(vr4300);
|
||||
return 1;
|
||||
}
|
||||
|
@ -460,7 +483,7 @@ cen64_align(static const pipeline_function
|
|||
vr4300_cycle_slow_ic,
|
||||
|
||||
vr4300_cycle_busywait,
|
||||
VR4300_DCB,
|
||||
VR4300_DCM,
|
||||
};
|
||||
|
||||
// Advances the processor pipeline by one pclock.
|
||||
|
|
|
@ -80,6 +80,7 @@ struct vr4300_dcwb_latch {
|
|||
struct vr4300_latch common;
|
||||
int64_t result;
|
||||
uint32_t dest;
|
||||
bool last_op_was_cache_store;
|
||||
};
|
||||
|
||||
struct vr4300_pipeline {
|
||||
|
|
Loading…
Reference in a new issue