diff options
Diffstat (limited to 'src/emu/cpu/rsp/rspdrc.c')
-rw-r--r-- | src/emu/cpu/rsp/rspdrc.c | 443 |
1 files changed, 333 insertions, 110 deletions
diff --git a/src/emu/cpu/rsp/rspdrc.c b/src/emu/cpu/rsp/rspdrc.c index e2f5e9bb805..24154b985fc 100644 --- a/src/emu/cpu/rsp/rspdrc.c +++ b/src/emu/cpu/rsp/rspdrc.c @@ -4686,7 +4686,7 @@ inline void rsp_device::ccfunc_rsp_vaddc_scalar() INT32 s2 = (UINT32)(UINT16)w2; INT32 r = s1 + s2; - vres[i] = (INT16)r; + vres[i] = (INT16)(r); SET_ACCUM_L((INT16)r, i); if (r & 0xffff0000) @@ -4754,7 +4754,6 @@ inline void rsp_device::ccfunc_rsp_vsubc_scalar() { int op = m_rsp_state->arg0; - CLEAR_ZERO_FLAGS(); CLEAR_CARRY_FLAGS(); @@ -4789,6 +4788,67 @@ static void cfunc_rsp_vsubc_scalar(void *param) } #endif +// VADDB +// +// 31 25 24 20 15 10 5 0 +// ------------------------------------------------------ +// | 010010 | 1 | EEEE | SSSSS | TTTTT | DDDDD | 010110 | +// ------------------------------------------------------ +// +// Adds two vector registers bytewise with rounding +inline void rsp_device::ccfunc_rsp_vaddb_scalar() +{ + const int op = m_rsp_state->arg0; + const int round = (EL == 0) ? 0 : (1 << (EL - 1)); + + INT16 vres[8]; + for (int i = 0; i < 8; i++) + { + UINT16 w1, w2; + SCALAR_GET_VS1(w1, i); + SCALAR_GET_VS2(w2, i); + + UINT8 hb1 = w1 >> 8; + UINT8 lb1 = w1 & 0xff; + UINT8 hb2 = w2 >> 8; + UINT8 lb2 = w2 & 0xff; + + UINT16 hs = hb1 + hb2 + round; + UINT16 ls = lb1 + lb2 + round; + + SET_ACCUM_L((hs << 8) | ls, i); + + hs >>= EL; + if (hs > 255) + { + hs = 255; + } + else if (hs < 0) + { + hs = 0; + } + + ls >>= EL; + if (ls > 255) + { + ls = 255; + } + else if (ls < 0) + { + ls = 0; + } + + vres[i] = 0; // VD writeback disabled on production hardware + // vres[i] = (hs << 8) | ls; + } + WRITEBACK_RESULT(); +} + +static void cfunc_rsp_vaddb_scalar(void *param) +{ + ((rsp_device *)param)->ccfunc_rsp_vaddb_scalar(); +} + #if USE_SIMD // VSAW // @@ -6318,13 +6378,15 @@ inline void rsp_device::ccfunc_rsp_vrcpl_simd() UINT16 urec; SIMD_EXTRACT16(m_xv[VS2REG], urec, EL); - INT32 rec = (urec | m_reciprocal_high); - + INT32 rec = (INT16)urec; INT32 datainput = rec; - if (rec < 0) + if (m_dp_allowed) { - if (m_dp_allowed) + rec = (rec & 0x0000ffff) | m_reciprocal_high; + datainput = rec; + + if (rec < 0) { if (rec < -32768) { @@ -6335,12 +6397,13 @@ inline void rsp_device::ccfunc_rsp_vrcpl_simd() datainput = -datainput; } } - else - { - datainput = -datainput; - } } + else if (datainput < 0) + { + datainput = -datainput; + shifter = 0x10; + } if (datainput) { @@ -6353,25 +6416,12 @@ inline void rsp_device::ccfunc_rsp_vrcpl_simd() } } } - else - { - if (m_dp_allowed) - { - shifter = 0; - } - else - { - shifter = 0x10; - } - } INT32 address = ((datainput << shifter) & 0x7fc00000) >> 22; INT32 fetchval = rsp_divtable[address]; INT32 temp = (0x40000000 | (fetchval << 14)) >> ((~shifter) & 0x1f); - if (rec < 0) - { - temp = ~temp; - } + temp ^= rec >> 31; + if (!rec) { temp = 0x7fffffff; @@ -6408,12 +6458,15 @@ inline void rsp_device::ccfunc_rsp_vrcpl_scalar() int op = m_rsp_state->arg0; INT32 shifter = 0; - INT32 rec = ((UINT16)(VREG_S(VS2REG, EL & 7)) | m_reciprocal_high); + INT32 rec = (INT16)VREG_S(VS2REG, EL & 7); INT32 datainput = rec; - if (rec < 0) + if (m_dp_allowed) { - if (m_dp_allowed) + rec = (rec & 0x0000ffff) | m_reciprocal_high; + datainput = rec; + + if (rec < 0) { if (rec < -32768) { @@ -6424,12 +6477,13 @@ inline void rsp_device::ccfunc_rsp_vrcpl_scalar() datainput = -datainput; } } - else - { - datainput = -datainput; - } } + else if (datainput < 0) + { + datainput = -datainput; + shifter = 0x10; + } if (datainput) { @@ -6442,25 +6496,11 @@ inline void rsp_device::ccfunc_rsp_vrcpl_scalar() } } } - else - { - if (m_dp_allowed) - { - shifter = 0; - } - else - { - shifter = 0x10; - } - } - INT32 address = ((datainput << shifter) & 0x7fc00000) >> 22; - INT32 fetchval = rsp_divtable[address]; + UINT32 address = (datainput << shifter) >> 22; + INT32 fetchval = rsp_divtable[address & 0x1ff]; INT32 temp = (0x40000000 | (fetchval << 14)) >> ((~shifter) & 0x1f); - if (rec < 0) - { - temp = ~temp; - } + temp ^= rec >> 31; if (!rec) { temp = 0x7fffffff; @@ -6592,6 +6632,136 @@ static void cfunc_rsp_vmov_scalar(void *param) } #endif +// VRSQ +// +// 31 25 24 20 15 10 5 0 +// ------------------------------------------------------ +// | 010010 | 1 | EEEE | SSSSS | ?FFFF | DDDDD | 110100 | +// ------------------------------------------------------ +// +// Calculates reciprocal square-root + +inline void rsp_device::ccfunc_rsp_vrsq_scalar() +{ + int op = m_rsp_state->arg0; + + INT32 shifter = 0; + INT32 rec = (INT16)VREG_S(VS2REG, EL & 7); + INT32 datainput = (rec < 0) ? (-rec) : (rec); + + if (rec < 0) + { + if (rec < -32768) + { + datainput = ~datainput; + } + else + { + datainput = -datainput; + } + } + + if (datainput) + { + for (int i = 0; i < 32; i++) + { + if (datainput & (1 << ((~i) & 0x1f))) + { + shifter = i; + break; + } + } + } + else + { + shifter = 0; + } + + INT32 address = ((datainput << shifter) & 0x7fc00000) >> 22; + address = ((address | 0x200) & 0x3fe) | (shifter & 1); + + INT32 fetchval = rsp_divtable[address]; + INT32 temp = (0x40000000 | (fetchval << 14)) >> (((~shifter) & 0x1f) >> 1); + if (rec < 0) + { + temp = ~temp; + } + if (!rec) + { + temp = 0x7fffffff; + } + else if (rec == 0xffff8000) + { + temp = 0xffff0000; + } + rec = temp; + + if (rec < 0) + { + if (m_dp_allowed) + { + if (rec < -32768) + { + datainput = ~datainput; + } + else + { + datainput = -datainput; + } + } + else + { + datainput = -datainput; + } + } + + if (datainput) + { + for (int i = 0; i < 32; i++) + { + if (datainput & (1 << ((~i) & 0x1f))) + { + shifter = i; + break; + } + } + } + else + { + shifter = 0; + } + + address = ((datainput << shifter) & 0x7fc00000) >> 22; + address = ((address | 0x200) & 0x3fe) | (shifter & 1); + + fetchval = rsp_divtable[address]; + temp = (0x40000000 | (fetchval << 14)) >> (((~shifter) & 0x1f) >> 1); + if (rec < 0) + { + temp = ~temp; + } + if (!rec) + { + temp = 0x7fff; + } + else if (rec == 0xffff8000) + { + temp = 0x0000; + } + rec = temp; + + W_VREG_S(VDREG, VS1REG & 7) = (UINT16)rec; + for (int i = 0; i < 8; i++) + { + SET_ACCUM_L(VREG_S(VS2REG, VEC_EL_2(EL, i)), i); + } +} + +static void cfunc_rsp_vrsq_scalar(void *param) +{ + ((rsp_device *)param)->ccfunc_rsp_vrsq_scalar(); +} + #if USE_SIMD // VRSQL // @@ -6615,12 +6785,15 @@ inline void rsp_device::ccfunc_rsp_vrsql_simd() INT32 shifter = 0; UINT16 val; SIMD_EXTRACT16(m_xv[VS2REG], val, EL); - INT32 rec = m_reciprocal_high | val; + INT32 rec = (INT16)val; INT32 datainput = rec; - if (rec < 0) + if (m_dp_allowed) { - if (m_dp_allowed) + rec = (rec & 0x0000ffff) | m_reciprocal_high; + datainput = rec; + + if (rec < 0) { if (rec < -32768) { @@ -6631,10 +6804,12 @@ inline void rsp_device::ccfunc_rsp_vrsql_simd() datainput = -datainput; } } - else - { - datainput = -datainput; - } + } + else if (datainput < 0) + { + datainput = -datainput; + + shifter = 0x10; } if (datainput) @@ -6648,27 +6823,14 @@ inline void rsp_device::ccfunc_rsp_vrsql_simd() } } } - else - { - if (m_dp_allowed) - { - shifter = 0; - } - else - { - shifter = 0x10; - } - } INT32 address = ((datainput << shifter) & 0x7fc00000) >> 22; address = ((address | 0x200) & 0x3fe) | (shifter & 1); INT32 fetchval = rsp_divtable[address]; INT32 temp = (0x40000000 | (fetchval << 14)) >> (((~shifter) & 0x1f) >> 1); - if (rec < 0) - { - temp = ~temp; - } + temp ^= rec >> 31; + if (!rec) { temp = 0x7fffffff; @@ -6699,12 +6861,15 @@ inline void rsp_device::ccfunc_rsp_vrsql_scalar() int op = m_rsp_state->arg0; INT32 shifter = 0; - INT32 rec = m_reciprocal_high | (UINT16)VREG_S(VS2REG, EL & 7); + INT32 rec = (INT16)VREG_S(VS2REG, EL & 7); INT32 datainput = rec; - if (rec < 0) + if (m_dp_allowed) { - if (m_dp_allowed) + rec = (rec & 0x0000ffff) | m_reciprocal_high; + datainput = rec; + + if (rec < 0) { if (rec < -32768) { @@ -6715,10 +6880,12 @@ inline void rsp_device::ccfunc_rsp_vrsql_scalar() datainput = -datainput; } } - else - { - datainput = -datainput; - } + } + else if (datainput < 0) + { + datainput = -datainput; + + shifter = 0x10; } if (datainput) @@ -6732,27 +6899,14 @@ inline void rsp_device::ccfunc_rsp_vrsql_scalar() } } } - else - { - if (m_dp_allowed) - { - shifter = 0; - } - else - { - shifter = 0x10; - } - } INT32 address = ((datainput << shifter) & 0x7fc00000) >> 22; address = ((address | 0x200) & 0x3fe) | (shifter & 1); INT32 fetchval = rsp_divtable[address]; INT32 temp = (0x40000000 | (fetchval << 14)) >> (((~shifter) & 0x1f) >> 1); - if (rec < 0) - { - temp = ~temp; - } + temp ^= rec >> 31; + if (!rec) { temp = 0x7fffffff; @@ -7361,6 +7515,30 @@ void rsp_device::generate_sequence_instruction(drcuml_block *block, compiler_sta } /*------------------------------------------------------------------ + generate_branch +------------------------------------------------------------------*/ + +void rsp_device::generate_branch(drcuml_block *block, compiler_state *compiler, const opcode_desc *desc) +{ + compiler_state compiler_temp = *compiler; + + /* update the cycles and jump through the hash table to the target */ + if (desc->targetpc != BRANCH_TARGET_DYNAMIC) + { + generate_update_cycles(block, &compiler_temp, desc->targetpc, TRUE); // <subtract cycles> + if (desc->flags & OPFLAG_INTRABLOCK_BRANCH) + UML_JMP(block, desc->targetpc | 0x80000000); // jmp desc->targetpc + else + UML_HASHJMP(block, 0, desc->targetpc, *m_nocode); // hashjmp <mode>,desc->targetpc,nocode + } + else + { + generate_update_cycles(block, &compiler_temp, mem(&m_rsp_state->jmpdest), TRUE); // <subtract cycles> + UML_HASHJMP(block, 0, mem(&m_rsp_state->jmpdest), *m_nocode); // hashjmp <mode>,<rsreg>,nocode + } +} + +/*------------------------------------------------------------------ generate_delay_slot_and_branch ------------------------------------------------------------------*/ @@ -7386,23 +7564,7 @@ void rsp_device::generate_delay_slot_and_branch(drcuml_block *block, compiler_st assert(desc->delay.first() != NULL); generate_sequence_instruction(block, &compiler_temp, desc->delay.first()); // <next instruction> - /* update the cycles and jump through the hash table to the target */ - if (desc->targetpc != BRANCH_TARGET_DYNAMIC) - { - generate_update_cycles(block, &compiler_temp, desc->targetpc, TRUE); // <subtract cycles> - if (desc->flags & OPFLAG_INTRABLOCK_BRANCH) - UML_JMP(block, desc->targetpc | 0x80000000); // jmp desc->targetpc - else - UML_HASHJMP(block, 0, desc->targetpc, *m_nocode); - // hashjmp <mode>,desc->targetpc,nocode - } - else - { - generate_update_cycles(block, &compiler_temp, mem(&m_rsp_state->jmpdest), TRUE); - // <subtract cycles> - UML_HASHJMP(block, 0, mem(&m_rsp_state->jmpdest), *m_nocode); - // hashjmp <mode>,<rsreg>,nocode - } + generate_branch(block, compiler, desc); /* update the label */ compiler->labelnum = compiler_temp.labelnum; @@ -7618,6 +7780,26 @@ int rsp_device::generate_vector_opcode(drcuml_block *block, compiler_state *comp #endif return TRUE; + case 0x16: /* VADDB */ + UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_CALLC(block, cfunc_rsp_vaddb_scalar, this); + return TRUE; + + case 0x17: /* VSUBB (reserved, functionally identical to VADDB) */ + UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_CALLC(block, cfunc_rsp_vaddb_scalar, this); + return TRUE; + + case 0x18: /* VACCB (reserved, functionally identical to VADDB) */ + UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_CALLC(block, cfunc_rsp_vaddb_scalar, this); + return TRUE; + + case 0x19: /* VSUCB (reserved, functionally identical to VADDB) */ + UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_CALLC(block, cfunc_rsp_vaddb_scalar, this); + return TRUE; + case 0x1d: /* VSAW */ UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_rsp_vsaw_simd, this); @@ -7827,6 +8009,11 @@ int rsp_device::generate_vector_opcode(drcuml_block *block, compiler_state *comp #endif return TRUE; + case 0x34: /* VRSQ */ + UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_CALLC_block, cfunc_rsp_vrsq_scalar, this); + return TRUE; + case 0x35: /* VRSQL */ UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_rsp_vrsql_simd, this); @@ -7849,6 +8036,10 @@ int rsp_device::generate_vector_opcode(drcuml_block *block, compiler_state *comp #endif return TRUE; + case 0x37: /* VNOP */ + case 0x3F: /* VNULL */ + return TRUE; + default: UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_unimplemented_opcode, this); @@ -7954,6 +8145,26 @@ int rsp_device::generate_vector_opcode(drcuml_block *block, compiler_state *comp UML_CALLC(block, cfunc_rsp_vsubc_scalar, this); return TRUE; + case 0x16: /* VADDB */ + UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_CALLC(block, cfunc_rsp_vaddb_scalar, this); + return TRUE; + + case 0x17: /* VSUBB (reserved, functionally identical to VADDB) */ + UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_CALLC(block, cfunc_rsp_vaddb_scalar, this); + return TRUE; + + case 0x18: /* VACCB (reserved, functionally identical to VADDB) */ + UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_CALLC(block, cfunc_rsp_vaddb_scalar, this); + return TRUE; + + case 0x19: /* VSUCB (reserved, functionally identical to VADDB) */ + UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_CALLC(block, cfunc_rsp_vaddb_scalar, this); + return TRUE; + case 0x1d: /* VSAW */ UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_rsp_vsaw_scalar, this); @@ -8049,6 +8260,11 @@ int rsp_device::generate_vector_opcode(drcuml_block *block, compiler_state *comp UML_CALLC(block, cfunc_rsp_vmov_scalar, this); return TRUE; + case 0x34: /* VRSQ */ + UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l + UML_CALLC(block, cfunc_rsp_vrsq_scalar, this); + return TRUE; + case 0x35: /* VRSQL */ UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_rsp_vrsql_scalar, this); @@ -8059,6 +8275,10 @@ int rsp_device::generate_vector_opcode(drcuml_block *block, compiler_state *comp UML_CALLC(block, cfunc_rsp_vrsqh_scalar, this); return TRUE; + case 0x37: /* VNOP */ + case 0x3F: /* VNULL */ + return TRUE; + default: UML_MOV(block, mem(&m_rsp_state->arg0), desc->opptr.l[0]); // mov [arg0],desc->opptr.l UML_CALLC(block, cfunc_unimplemented_opcode, this); @@ -8421,6 +8641,9 @@ int rsp_device::generate_special(drcuml_block *block, compiler_state *compiler, UML_MOV(block, mem(&m_rsp_state->arg0), 3); // mov [arg0],3 UML_CALLC(block, cfunc_sp_set_status_cb, this); // callc cfunc_sp_set_status_cb UML_MOV(block, mem(&m_rsp_state->icount), 0); // mov icount, #0 + UML_MOV(block, mem(&m_rsp_state->jmpdest), desc->targetpc); + + generate_branch(block, compiler, desc); UML_EXIT(block, EXECUTE_OUT_OF_CYCLES); return TRUE; |