mirror of
https://github.com/n64dev/cen64.git
synced 2024-06-22 22:12:45 -04:00
VR4300: Add support for MF{HI,LO], MULT{,U} instructions.
This commit is contained in:
parent
b3e5d94811
commit
91f0b758fa
|
@ -62,7 +62,7 @@ enum vr4300_register {
|
|||
VR4300_REGISTER_CP1_30, VR4300_REGISTER_CP1_31,
|
||||
|
||||
// Miscellanious registers.
|
||||
VR4300_REGISTER_LO, VR4300_REGISTER_HI,
|
||||
VR4300_REGISTER_HI, VR4300_REGISTER_LO,
|
||||
NUM_VR4300_REGISTERS
|
||||
};
|
||||
|
||||
|
|
|
@ -33,6 +33,11 @@ cen64_align(static const uint32_t vr4300_branch_lut[2], 8) = {
|
|||
~0U, 0U
|
||||
};
|
||||
|
||||
// Mask to selectively sign-extend compute values.
|
||||
cen64_align(static const uint64_t vr4300_mult_sex_mask[2], 16) = {
|
||||
~0ULL, ~0ULL >> 32
|
||||
};
|
||||
|
||||
// Mask to selectively sign-extend loaded values.
|
||||
cen64_align(static const uint64_t vr4300_load_sex_mask[2], 16) = {
|
||||
~0ULL, 0ULL
|
||||
|
@ -80,7 +85,8 @@ void VR4300_ADDI_SUBI(struct vr4300 *vr4300, uint64_t rs, uint64_t rt) {
|
|||
rt = (rt ^ mask) - mask;
|
||||
rt = rs + rt;
|
||||
|
||||
assert(((rt >> 31) == (rt >> 32)) && "Overflow exception.");
|
||||
// TODO/FIXME: Uncomment this later...
|
||||
//assert(((rt >> 31) == (rt >> 32)) && "Overflow exception.");
|
||||
|
||||
exdc_latch->result = (int32_t) rt;
|
||||
exdc_latch->dest = dest;
|
||||
|
@ -344,6 +350,43 @@ void VR4300_LOAD(struct vr4300 *vr4300, uint64_t rs, uint64_t unused(rt)) {
|
|||
exdc_latch->dest = dest;
|
||||
}
|
||||
|
||||
//
|
||||
// MFHI
|
||||
// MFLO
|
||||
//
|
||||
void VR4300_MFHI_MFLO(struct vr4300 *vr4300, uint64_t rs, uint64_t rt) {
|
||||
struct vr4300_rfex_latch *rfex_latch = &vr4300->pipeline.rfex_latch;
|
||||
struct vr4300_exdc_latch *exdc_latch = &vr4300->pipeline.exdc_latch;
|
||||
|
||||
uint32_t iw = rfex_latch->iw;
|
||||
unsigned dest = GET_RD(iw);
|
||||
bool is_mflo = iw >> 1 & 0x1;
|
||||
|
||||
// TODO: Read these here, or...? Registers are probably tied into EX logic...
|
||||
exdc_latch->result = vr4300->regs[VR4300_REGISTER_HI + is_mflo];
|
||||
exdc_latch->dest = dest;
|
||||
}
|
||||
|
||||
//
|
||||
// MULT
|
||||
// MULTU
|
||||
//
|
||||
void VR4300_MULT_MULTU(struct vr4300 *vr4300, uint64_t rs, uint64_t rt) {
|
||||
struct vr4300_rfex_latch *rfex_latch = &vr4300->pipeline.rfex_latch;
|
||||
|
||||
uint32_t iw = rfex_latch->iw;
|
||||
bool is_multu = iw & 0x1;
|
||||
|
||||
uint64_t sex_mask = vr4300_mult_sex_mask[is_multu];
|
||||
uint64_t rs_sex = (int32_t) rs & sex_mask;
|
||||
uint64_t rt_sex = (int32_t) rt & sex_mask;
|
||||
uint64_t result = rs_sex * rt_sex;
|
||||
|
||||
// TODO: Delay the output a few cycles.
|
||||
vr4300->regs[VR4300_REGISTER_LO] = (int32_t) result;
|
||||
vr4300->regs[VR4300_REGISTER_HI] = (int32_t) (result >> 32);
|
||||
}
|
||||
|
||||
//
|
||||
// LUI
|
||||
//
|
||||
|
|
|
@ -138,15 +138,15 @@ extern const char *vr4300_opcode_mnemonics[NUM_VR4300_OPCODES];
|
|||
#define MFC0 VR4300_BUILD_OP(MFC0, INV, INFO1(NONE))
|
||||
#define MFC1 VR4300_BUILD_OP(MFC1, INV, INFO1(NONE))
|
||||
#define MFC2 VR4300_BUILD_OP(MFC2, INV, INFO1(NONE))
|
||||
#define MFHI VR4300_BUILD_OP(MFHI, INV, INFO1(NONE))
|
||||
#define MFLO VR4300_BUILD_OP(MFLO, INV, INFO1(NONE))
|
||||
#define MFHI VR4300_BUILD_OP(MFHI, MFHI_MFLO, INFO1(NONE))
|
||||
#define MFLO VR4300_BUILD_OP(MFLO, MFHI_MFLO, INFO1(NONE))
|
||||
#define MTC0 VR4300_BUILD_OP(MTC0, MTCx, INFO1(NEEDRT))
|
||||
#define MTC1 VR4300_BUILD_OP(MTC1, INV, INFO1(NONE))
|
||||
#define MTC2 VR4300_BUILD_OP(MTC2, INV, INFO1(NONE))
|
||||
#define MTHI VR4300_BUILD_OP(MTHI, INV, INFO1(NONE))
|
||||
#define MTLO VR4300_BUILD_OP(MTLO, INV, INFO1(NONE))
|
||||
#define MULT VR4300_BUILD_OP(MULT, INV, INFO1(NONE))
|
||||
#define MULTU VR4300_BUILD_OP(MULTU, INV, INFO1(NONE))
|
||||
#define MULT VR4300_BUILD_OP(MULT, MULT_MULTU, INFO2(NEEDRS, NEEDRT))
|
||||
#define MULTU VR4300_BUILD_OP(MULTU, MULT_MULTU, INFO2(NEEDRS, NEEDRT))
|
||||
#define NOR VR4300_BUILD_OP(NOR, INV, INFO1(NONE))
|
||||
#define OR VR4300_BUILD_OP(OR, AND_OR_XOR, INFO2(NEEDRS, NEEDRT))
|
||||
#define ORI VR4300_BUILD_OP(ORI, ANDI_ORI_XORI, INFO1(NEEDRS))
|
||||
|
|
|
@ -114,6 +114,7 @@ static inline int vr4300_ex_stage (struct vr4300 *vr4300) {
|
|||
vr4300_opcode_mnemonics[rfex_latch->opcode.id]);
|
||||
#endif
|
||||
|
||||
exdc_latch->dest = VR4300_REGISTER_R0;
|
||||
exdc_latch->request.type = VR4300_BUS_REQUEST_NONE;
|
||||
vr4300_function_table[rfex_latch->opcode.id](vr4300, rs_reg, rt_reg);
|
||||
return 0;
|
||||
|
|
Loading…
Reference in a new issue