Implement DCB-type stalls.

This commit is contained in:
Tyler Stachecki 2015-07-05 08:07:19 -04:00
parent a53d9a6d88
commit 98d3ae952c
5 changed files with 63 additions and 36 deletions

View file

@ -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,

View file

@ -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;

View file

@ -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))

View file

@ -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.

View file

@ -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 {