mirror of
https://github.com/n64dev/cen64.git
synced 2024-06-23 14:33:13 -04:00
Fix a slew of bugs in the pipeline.
This commit is contained in:
parent
cbb4c4ea07
commit
3bb8d496b4
|
@ -85,6 +85,7 @@ struct vr4300 {
|
|||
struct vr4300_pipeline pipeline;
|
||||
|
||||
struct bus_controller *bus;
|
||||
unsigned long long cycles;
|
||||
unsigned signals;
|
||||
};
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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--;
|
||||
|
|
Loading…
Reference in a new issue