VR4300: Add support for MF{HI,LO], MULT{,U} instructions.

This commit is contained in:
Tyler Stachecki 2014-04-18 15:05:57 -04:00
parent b3e5d94811
commit 91f0b758fa
4 changed files with 50 additions and 6 deletions

View file

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

View file

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

View file

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

View file

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