Fix a slew of bugs in the pipeline.

This commit is contained in:
Tyler Stachecki 2014-04-20 12:07:33 -04:00
parent cbb4c4ea07
commit 3bb8d496b4
5 changed files with 33 additions and 17 deletions

View file

@ -85,6 +85,7 @@ struct vr4300 {
struct vr4300_pipeline pipeline;
struct bus_controller *bus;
unsigned long long cycles;
unsigned signals;
};

View file

@ -87,13 +87,16 @@ void VR4300_IADE(unused(struct vr4300 *vr4300)) {
// INTR: Interrupt exception.
void VR4300_INTR(unused(struct vr4300 *vr4300)) {
struct vr4300_pipeline *pipeline = &vr4300->pipeline;
struct vr4300_latch *common = &pipeline->exdc_latch.common;
struct vr4300_latch *common = &pipeline->dcwb_latch.common;
bool in_bd_slot = common->cause_data >> 31;
uint32_t status = vr4300->regs[VR4300_CP0_REGISTER_STATUS];
uint32_t cause = vr4300->regs[VR4300_CP0_REGISTER_CAUSE];
uint64_t epc = vr4300->regs[VR4300_CP0_REGISTER_EPC];
// Kill our output.
common->fault = ~0;
// Record branch delay slot?
if (!(status & 0x2)) {
if (in_bd_slot) {

View file

@ -10,10 +10,9 @@
#ifndef VR4300_FAULT_LIST
#define VR4300_FAULT_LIST \
X(NONE) X(KILLED) X(CP0I) X(RST) X(NMI) X(OVFL) X(TRAP) X(FPE) \
X(DADE) X(DTLB) X(WAT) X(INTR) X(DCM) X(DCB) X(COP) X(DBE) X(SYSC) \
X(BRPT) X(CPU) X(RSVD) X(LDI) X(MCI) X(IADE) X(ITM) X(ICB) X(UNC) \
X(IBE)
X(NONE) X(CP0I) X(RST) X(NMI) X(OVFL) X(TRAP) X(FPE) X(DADE) \
X(DTLB) X(WAT) X(INTR) X(DCM) X(DCB) X(COP) X(DBE) X(SYSC) X(BRPT) \
X(CPU) X(RSVD) X(LDI) X(MCI) X(IADE) X(ITM) X(ICB) X(UNC) X(IBE)
#endif
VR4300_FAULT_LIST

View file

@ -201,6 +201,7 @@ void VR4300_BEQ_BEQL_BNE_BNEL(struct vr4300 *vr4300, uint64_t rs, uint64_t rt) {
bool cmp = rs == rt;
if (cmp == is_ne) {
icrf_latch->common.fault |= ~mask;
rfex_latch->iw_mask = mask;
return;
}
@ -227,6 +228,7 @@ void VR4300_BGEZ_BGEZL_BLTZ_BLTZL(
bool cmp = (int64_t) rs < 0;
if (cmp == is_ge) {
icrf_latch->common.fault |= ~mask;
rfex_latch->iw_mask = mask;
return;
}
@ -257,6 +259,7 @@ void VR4300_BGEZAL_BGEZALL_BLTZAL_BLTZALL(
exdc_latch->dest = VR4300_REGISTER_RA;
if (cmp == is_ge) {
icrf_latch->common.fault |= ~mask;
rfex_latch->iw_mask = mask;
return;
}
@ -283,6 +286,7 @@ void VR4300_BGTZ_BGTZL_BLEZ_BLEZL(
bool cmp = (int64_t) rs <= 0;
if (cmp == is_gt) {
icrf_latch->common.fault |= ~mask;
rfex_latch->iw_mask = mask;
return;
}
@ -419,6 +423,7 @@ void VR4300_DSRA32(struct vr4300 *vr4300, uint64_t unused(rs), uint64_t rt) {
void VR4300_ERET(struct vr4300 *vr4300, uint64_t unused(rs), uint64_t rt) {
struct vr4300_icrf_latch *icrf_latch = &vr4300->pipeline.icrf_latch;
struct vr4300_rfex_latch *rfex_latch = &vr4300->pipeline.rfex_latch;
struct vr4300_exdc_latch *exdc_latch = &vr4300->pipeline.exdc_latch;
int32_t status = vr4300->regs[VR4300_CP0_REGISTER_STATUS];
if (status & 0x4) {
@ -433,10 +438,10 @@ void VR4300_ERET(struct vr4300 *vr4300, uint64_t unused(rs), uint64_t rt) {
// Until we delay CP0 writes, we have to kill ourselves
// to prevent squashing this instruction the next cycle.
rfex_latch->common.fault = VR4300_FAULT_KILLED;
exdc_latch->common.fault = ~0;
// TODO/FIXME: Look into safely doing this!
vr4300->regs[VR4300_CP0_REGISTER_STATUS] = status;
icrf_latch->common.fault = ~0;
rfex_latch->iw_mask = 0;
// vr4300->llbit = 0;
}
@ -812,11 +817,12 @@ void VR4300_STORE(struct vr4300 *vr4300, uint64_t rs, uint64_t rt) {
uint32_t iw = rfex_latch->iw;
unsigned request_size = (iw >> 26 & 0x3) + 1;
unsigned shiftamt = (4 - request_size + (iw & 0x3)) << 3;
unsigned lshiftamt = (4 - request_size) << 3;
unsigned rshiftamt = (iw & 0x3) << 3;
exdc_latch->request.address = rs + (int16_t) iw;
exdc_latch->request.data = rt << shiftamt;
exdc_latch->request.dqm = ~0U << shiftamt;
exdc_latch->request.address = (rs + (int16_t) iw) & ~0x3ULL;
exdc_latch->request.data = (rt << lshiftamt) >> rshiftamt;
exdc_latch->request.dqm = (~0U << lshiftamt) >> rshiftamt;
exdc_latch->request.type = VR4300_BUS_REQUEST_WRITE;
exdc_latch->request.size = request_size;
}

View file

@ -38,8 +38,8 @@ static inline int vr4300_ic_stage(struct vr4300 *vr4300) {
rfex_latch->iw_mask = ~0U;
// Latch common pipeline values.
icrf_latch->common.fault = VR4300_FAULT_NONE;
icrf_latch->common.pc = pc;
//icrf_latch->common.fault = ...;
// If decoding of prior instruction indicates this is a BD slot...
icrf_latch->common.cause_data = (opcode->flags & OPCODE_INFO_BRANCH)
@ -58,8 +58,6 @@ static inline int vr4300_ic_stage(struct vr4300 *vr4300) {
icrf_latch->segment = segment;
}
// We didn't have an IADE, so reset the status vector.
icrf_latch->common.fault = VR4300_FAULT_NONE;
icrf_latch->pc += 4;
return 0;
}
@ -152,9 +150,14 @@ static inline int vr4300_dc_stage(struct vr4300 *vr4300) {
return 1;
}
// Check if we should raise an interrupt exception.
if (unlikely(cause & status & 0xFF00) && (status & 0x1)
&& !(status & 0x6) && dcwb_latch->common.fault == 0) {
// In both in DC and WB, we have to make sure that
// don't make the actions of squashed insns visible.
if (exdc_latch->common.fault != VR4300_FAULT_NONE)
return 0;
// Check if we should raise an interrupt.
if (unlikely(cause & status & 0xFF00) &&
(status & 0x1) && !(status & 0x6)) {
VR4300_INTR(vr4300);
return 1;
}
@ -410,6 +413,10 @@ static const pipeline_function pipeline_function_lut[6] = {
void vr4300_cycle(struct vr4300 *vr4300) {
struct vr4300_pipeline *pipeline = &vr4300->pipeline;
// Increment counters.
vr4300->regs[VR4300_CP0_REGISTER_COUNT] += vr4300->cycles & 1;
vr4300->cycles++;
// We're stalling for something...
if (pipeline->cycles_to_stall > 0) {
pipeline->cycles_to_stall--;