diff options
Diffstat (limited to 'src/devices/cpu/score/score.cpp')
-rw-r--r-- | src/devices/cpu/score/score.cpp | 199 |
1 files changed, 111 insertions, 88 deletions
diff --git a/src/devices/cpu/score/score.cpp b/src/devices/cpu/score/score.cpp index bf5b434cb06..14565f23488 100644 --- a/src/devices/cpu/score/score.cpp +++ b/src/devices/cpu/score/score.cpp @@ -5,10 +5,15 @@ Sunplus Technology S+core by Sandro Ronco + TODO: + - unemulated opcodes + - irq priority + - instruction cycles + - cache + ******************************************************************************/ #include "emu.h" -#include "debugger.h" #include "score.h" #include "scoredsm.h" @@ -72,8 +77,8 @@ score7_cpu_device::score7_cpu_device(const machine_config &mconfig, const char * void score7_cpu_device::device_start() { // find address spaces - m_program = &space(AS_PROGRAM); - m_cache = m_program->cache<2, 0, ENDIANNESS_LITTLE>(); + space(AS_PROGRAM).cache(m_cache); + space(AS_PROGRAM).specific(m_program); // set our instruction counter set_icountptr(m_icount); @@ -120,7 +125,7 @@ void score7_cpu_device::device_reset() memset(m_cr, 0, sizeof(m_cr)); memset(m_sr, 0, sizeof(m_sr)); memset(m_ce, 0, sizeof(m_ce)); - memset(m_pending_interrupt, 0, sizeof(m_pending_interrupt)); + m_pending_interrupt = 0; REG_EXCPVEC = m_pc = 0x9f000000; } @@ -174,7 +179,8 @@ void score7_cpu_device::execute_run() m_ppc = m_pc; debugger_instruction_hook(m_pc); - check_irq(); + if (m_pending_interrupt) + check_irq(); uint32_t op = fetch(); @@ -201,7 +207,7 @@ void score7_cpu_device::execute_run() break; } - m_icount -= 3; // FIXME: if available use correct cycles per instructions + m_icount -= 6; // FIXME: if available use correct cycles per instructions } while (m_icount > 0); } @@ -213,19 +219,10 @@ void score7_cpu_device::execute_run() void score7_cpu_device::execute_set_input(int inputnum, int state) { - switch (inputnum) + if (state) { - case 0: - if(state) - { - int vector = standard_irq_callback(0); - if (vector > 0 && vector < 64) - { - if((REG_PSR & 0x01) && state) - m_pending_interrupt[vector] = true; - } - } - break; + if (inputnum > 0 && inputnum < 64) + m_pending_interrupt |= 1ULL << inputnum; } } @@ -274,46 +271,39 @@ bool score7_cpu_device::check_condition(uint8_t bc) return false; } -int32_t score7_cpu_device::sign_extend(uint32_t data, uint8_t len) -{ - data &= (1 << len) - 1; - uint32_t sign = 1 << (len - 1); - return (data ^ sign) - sign; -} - uint32_t score7_cpu_device::fetch() { - return m_cache->read_dword(m_pc & ~3); + return m_cache.read_dword(m_pc & ~3); } uint8_t score7_cpu_device::read_byte(offs_t offset) { - return m_program->read_byte(offset); + return m_program.read_byte(offset); } uint16_t score7_cpu_device::read_word(offs_t offset) { - return m_program->read_word(offset & ~1); + return m_program.read_word(offset & ~1); } uint32_t score7_cpu_device::read_dword(offs_t offset) { - return m_program->read_dword(offset & ~3); + return m_program.read_dword(offset & ~3); } void score7_cpu_device::write_byte(offs_t offset, uint8_t data) { - m_program->write_byte(offset, data); + m_program.write_byte(offset, data); } void score7_cpu_device::write_word(offs_t offset, uint16_t data) { - m_program->write_word(offset & ~1, data); + m_program.write_word(offset & ~1, data); } void score7_cpu_device::write_dword(offs_t offset, uint32_t data) { - m_program->write_dword(offset & ~3, data); + m_program.write_dword(offset & ~3, data); } void score7_cpu_device::check_irq() @@ -322,10 +312,10 @@ void score7_cpu_device::check_irq() { for (int i=63; i>0; i--) { - if (m_pending_interrupt[i]) + if (m_pending_interrupt & (1ULL << i)) { - m_pending_interrupt[i] = false; - standard_irq_callback(i); + m_pending_interrupt &= ~(1ULL << i); + standard_irq_callback(i, m_pc); gen_exception(EXCEPTION_INTERRUPT, i); return; } @@ -346,7 +336,7 @@ void score7_cpu_device::gen_exception(int cause, uint32_t param) { case EXCEPTION_P_EL: REG_EMA = REG_EPC; - // intentional fallthrough + [[fallthrough]]; case EXCEPTION_NMI: case EXCEPTION_CEE: case EXCEPTION_SYSCALL: @@ -562,31 +552,34 @@ void score7_cpu_device::op_specialform() } break; case 0x18: // sll - m_gpr[rd] = m_gpr[ra] << (m_gpr[rb] & 0x1f); + r = m_gpr[ra] << (m_gpr[rb] & 0x1f); if (cu) { - CHECK_Z(m_gpr[rd]); - CHECK_N(m_gpr[rd]); + CHECK_Z(r); + CHECK_N(r); SET_C(BIT(m_gpr[ra], 32 - (m_gpr[rb] & 0x1f))); } + m_gpr[rd] = r; break; case 0x1a: // srl - m_gpr[rd] = m_gpr[ra] >> (m_gpr[rb] & 0x1f); + r = m_gpr[ra] >> (m_gpr[rb] & 0x1f); if (cu) { - CHECK_Z(m_gpr[rd]); - CHECK_N(m_gpr[rd]); + CHECK_Z(r); + CHECK_N(r); SET_C(BIT(m_gpr[ra], (m_gpr[rb] & 0x1f) - 1)); } + m_gpr[rd] = r; break; case 0x1b: // sra - m_gpr[rd] = sign_extend(m_gpr[ra] >> (m_gpr[rb] & 0x1f), 32 - (m_gpr[rb] & 0x1f)); + r = util::sext(m_gpr[ra] >> (m_gpr[rb] & 0x1f), 32 - (m_gpr[rb] & 0x1f)); if (cu) { - CHECK_Z(m_gpr[rd]); - CHECK_N(m_gpr[rd]); + CHECK_Z(r); + CHECK_N(r); SET_C(BIT(m_gpr[ra], (m_gpr[rb] & 0x1f) - 1)); } + m_gpr[rd] = r; break; case 0x1c: // ror unemulated_op("ror"); @@ -602,18 +595,14 @@ void score7_cpu_device::op_specialform() break; case 0x20: // mul { - int64_t a = (int32_t)m_gpr[ra]; - int64_t b = (int32_t)m_gpr[rb]; - uint64_t d = a * b; + uint64_t d = mul_32x32(m_gpr[ra], m_gpr[rb]); REG_CEL = d & 0xffffffff; REG_CEH = (d >> 32) & 0xffffffff; break; } case 0x21: // mulu { - uint64_t a = (uint32_t)m_gpr[ra]; - uint64_t b = (uint32_t)m_gpr[rb]; - uint64_t d = a * b; + uint64_t d = mulu_32x32(m_gpr[ra], m_gpr[rb]); REG_CEL = d & 0xffffffff; REG_CEH = (d >> 32) & 0xffffffff; break; @@ -663,10 +652,14 @@ void score7_cpu_device::op_specialform() case 0x28: // mfsr if (rb < 3) m_gpr[rd] = m_sr[rb]; + else + logerror("%s: mfsr accessing sr%d (PC=0x%08x)\n", tag(), rb, m_ppc); break; case 0x29: // mtsr if (rb < 3) m_sr[rb] = m_gpr[ra]; + else + logerror("%s: mtsr accessing sr%d (PC=0x%08x)\n", tag(), rb, m_ppc); break; case 0x2a: // t SET_T(check_condition(rb)); @@ -677,7 +670,7 @@ void score7_cpu_device::op_specialform() break; case 0x2c: // extsb case 0x2d: // extsh - m_gpr[rd] = sign_extend(m_gpr[ra], (GET_S_FUNC6(m_op) & 1) ? 16 : 8); + m_gpr[rd] = util::sext(m_gpr[ra], (GET_S_FUNC6(m_op) & 1) ? 16 : 8); if (cu) { CHECK_N(m_gpr[rd]); @@ -712,31 +705,34 @@ void score7_cpu_device::op_specialform() unemulated_op("sce"); break; case 0x38: // slli - m_gpr[rd] = m_gpr[ra] << rb; + r = m_gpr[ra] << rb; if (cu) { - CHECK_Z(m_gpr[rd]); - CHECK_N(m_gpr[rd]); + CHECK_Z(r); + CHECK_N(r); SET_C(BIT(m_gpr[ra], 32 - rb)); } + m_gpr[rd] = r; break; case 0x3a: // srli - m_gpr[rd] = m_gpr[ra] >> rb; + r = m_gpr[ra] >> rb; if (cu) { - CHECK_Z(m_gpr[rd]); - CHECK_N(m_gpr[rd]); + CHECK_Z(r); + CHECK_N(r); SET_C(BIT(m_gpr[ra], rb - 1)); } + m_gpr[rd] = r; break; case 0x3b: // srai - m_gpr[rd] = sign_extend(m_gpr[ra] >> rb, 32 - rb); + r = util::sext(m_gpr[ra] >> rb, 32 - rb); if (cu) { - CHECK_Z(m_gpr[rd]); - CHECK_N(m_gpr[rd]); + CHECK_Z(r); + CHECK_N(r); SET_C(BIT(m_gpr[ra], rb - 1)); } + m_gpr[rd] = r; break; case 0x3c: // rori unemulated_op("rori"); @@ -759,7 +755,7 @@ void score7_cpu_device::op_iform1() { uint8_t rd = GET_I_RD(m_op); uint32_t imm16 = GET_I_IMM16(m_op); - int32_t simm16 = sign_extend(imm16, 16); + int32_t simm16 = util::sext(imm16, 16); uint8_t cu = GET_I_CU(m_op); uint32_t r; @@ -824,7 +820,7 @@ void score7_cpu_device::op_rixform1() uint8_t rd = GET_RIX_RD(m_op); // pre-increment - m_gpr[ra] += sign_extend(GET_RIX_IMM12(m_op), 12); + m_gpr[ra] += util::sext(GET_RIX_IMM12(m_op), 12); switch(GET_RIX_FUNC3(m_op)) { @@ -832,13 +828,13 @@ void score7_cpu_device::op_rixform1() m_gpr[rd] = read_dword(m_gpr[ra]); break; case 1: // lh - m_gpr[rd] = sign_extend(read_word(m_gpr[ra]), 16); + m_gpr[rd] = util::sext(read_word(m_gpr[ra]), 16); break; case 2: // lhu m_gpr[rd] = read_word(m_gpr[ra]); break; case 3: // lb - m_gpr[rd] = sign_extend(read_byte(m_gpr[ra]), 8); + m_gpr[rd] = util::sext(read_byte(m_gpr[ra]), 8); break; case 4: // sw write_dword(m_gpr[ra], m_gpr[rd]); @@ -859,7 +855,7 @@ void score7_cpu_device::op_branch() { if (check_condition_branch(GET_BC_BC(m_op))) { - int32_t disp = sign_extend(GET_BC_DISP19(m_op), 19) << 1; + int32_t disp = util::sext(GET_BC_DISP19(m_op), 19) << 1; if (GET_BC_LK(m_op)) REG_LNK = m_pc; @@ -963,13 +959,13 @@ void score7_cpu_device::op_rixform2() m_gpr[rd] = read_dword(m_gpr[ra]); break; case 1: // lh - m_gpr[rd] = sign_extend(read_word(m_gpr[ra]), 16); + m_gpr[rd] = util::sext(read_word(m_gpr[ra]), 16); break; case 2: // lhu m_gpr[rd] = read_word(m_gpr[ra]); break; case 3: // lb - m_gpr[rd] = sign_extend(read_byte(m_gpr[ra]), 8); + m_gpr[rd] = util::sext(read_byte(m_gpr[ra]), 8); break; case 4: // sw write_dword(m_gpr[ra], m_gpr[rd]); @@ -986,14 +982,14 @@ void score7_cpu_device::op_rixform2() } // post-increment - m_gpr[ra] += sign_extend(GET_RIX_IMM12(m_op), 12); + m_gpr[ra] += util::sext(GET_RIX_IMM12(m_op), 12); } void score7_cpu_device::op_addri() { uint8_t ra = GET_RI_RA(m_op); uint8_t rd = GET_RI_RD(m_op); - int32_t simm14 = sign_extend(GET_RI_IMM14(m_op), 14); + int32_t simm14 = util::sext(GET_RI_IMM14(m_op), 14); uint8_t cu = GET_RI_CU(m_op); uint32_t r = m_gpr[ra] + simm14; @@ -1041,7 +1037,7 @@ void score7_cpu_device::op_lw() { uint8_t rd = GET_LS_RD(m_op); uint8_t ra = GET_LS_RA(m_op); - int32_t simm15 = sign_extend(GET_LS_IMM15(m_op), 15); + int32_t simm15 = util::sext(GET_LS_IMM15(m_op), 15); m_gpr[rd] = read_dword(m_gpr[ra] + simm15); } @@ -1050,16 +1046,16 @@ void score7_cpu_device::op_lh() { uint8_t rd = GET_LS_RD(m_op); uint8_t ra = GET_LS_RA(m_op); - int32_t simm15 = sign_extend(GET_LS_IMM15(m_op), 15); + int32_t simm15 = util::sext(GET_LS_IMM15(m_op), 15); - m_gpr[rd] = sign_extend(read_word(m_gpr[ra] + simm15), 16); + m_gpr[rd] = util::sext(read_word(m_gpr[ra] + simm15), 16); } void score7_cpu_device::op_lhu() { uint8_t rd = GET_LS_RD(m_op); uint8_t ra = GET_LS_RA(m_op); - int32_t simm15 = sign_extend(GET_LS_IMM15(m_op), 15); + int32_t simm15 = util::sext(GET_LS_IMM15(m_op), 15); m_gpr[rd] = read_word(m_gpr[ra] + simm15); } @@ -1068,16 +1064,16 @@ void score7_cpu_device::op_lb() { uint8_t rd = GET_LS_RD(m_op); uint8_t ra = GET_LS_RA(m_op); - int32_t simm15 = sign_extend(GET_LS_IMM15(m_op), 15); + int32_t simm15 = util::sext(GET_LS_IMM15(m_op), 15); - m_gpr[rd] = sign_extend(read_byte(m_gpr[ra] + simm15), 8); + m_gpr[rd] = util::sext(read_byte(m_gpr[ra] + simm15), 8); } void score7_cpu_device::op_sw() { uint8_t rd = GET_LS_RD(m_op); uint8_t ra = GET_LS_RA(m_op); - int32_t simm15 = sign_extend(GET_LS_IMM15(m_op), 15); + int32_t simm15 = util::sext(GET_LS_IMM15(m_op), 15); write_dword(m_gpr[ra] + simm15, m_gpr[rd]); } @@ -1086,7 +1082,7 @@ void score7_cpu_device::op_sh() { uint8_t rd = GET_LS_RD(m_op); uint8_t ra = GET_LS_RA(m_op); - int32_t simm15 = sign_extend(GET_LS_IMM15(m_op), 15); + int32_t simm15 = util::sext(GET_LS_IMM15(m_op), 15); write_word(m_gpr[ra] + simm15, m_gpr[rd] & 0xffff); } @@ -1095,7 +1091,7 @@ void score7_cpu_device::op_lbu() { uint8_t rd = GET_LS_RD(m_op); uint8_t ra = GET_LS_RA(m_op); - int32_t simm15 = sign_extend(GET_LS_IMM15(m_op), 15); + int32_t simm15 = util::sext(GET_LS_IMM15(m_op), 15); m_gpr[rd] = read_byte(m_gpr[ra] + simm15); } @@ -1104,7 +1100,7 @@ void score7_cpu_device::op_sb() { uint8_t rd = GET_LS_RD(m_op); uint8_t ra = GET_LS_RA(m_op); - int32_t simm15 = sign_extend(GET_LS_IMM15(m_op), 15); + int32_t simm15 = util::sext(GET_LS_IMM15(m_op), 15); write_byte(m_gpr[ra] + simm15, m_gpr[rd] & 0xff); } @@ -1149,6 +1145,18 @@ void score7_cpu_device::op_rform1() case 0x05: // t! SET_T(check_condition(rd)); break; + case 0x08: // sll! + m_gpr[rd] = m_gpr[rd] << (m_gpr[ra] & 0x1f); + break; + case 0x09: // addc! + m_gpr[rd] = m_gpr[rd] + m_gpr[ra] + GET_C; + break; + case 0x0a: // srl! + m_gpr[rd] = m_gpr[rd] >> (m_gpr[ra] & 0x1f); + break; + case 0x0b: // sra! + m_gpr[rd] = util::sext(m_gpr[rd] >> (m_gpr[ra] & 0x1f), 32 - (m_gpr[ra] & 0x1f)); + break; case 0x0c: // brl! if (check_condition_branch(rd)) { @@ -1186,11 +1194,12 @@ void score7_cpu_device::op_rform2() m_gpr[rd] = r; break; case 0x02: // neg! - m_gpr[rd] = 0 - m_gpr[ra]; - CHECK_Z(m_gpr[rd]); - CHECK_N(m_gpr[rd]); - CHECK_V_SUB(0, m_gpr[ra], m_gpr[rd]); + r = 0 - m_gpr[ra]; + CHECK_Z(r); + CHECK_N(r); + CHECK_V_SUB(0, m_gpr[ra], r); CHECK_C_SUB(0, m_gpr[ra]); + m_gpr[rd] = r; break; case 0x03: // cmp! r = m_gpr[rd] - m_gpr[ra]; @@ -1223,7 +1232,7 @@ void score7_cpu_device::op_rform2() m_gpr[rd] = read_dword(m_gpr[ra]); break; case 0x09: // lh! - m_gpr[rd] = sign_extend(read_word(m_gpr[ra]), 16); + m_gpr[rd] = util::sext(read_word(m_gpr[ra]), 16); break; case 0x0a: // pop! m_gpr[GET_P_RDG(m_op)] = read_dword(m_gpr[GET_P_RAG(m_op)]); @@ -1259,7 +1268,7 @@ void score7_cpu_device::op_jform() void score7_cpu_device::op_branch16() { if(check_condition_branch(GET_BX_EC(m_op))) - m_pc = m_ppc + (sign_extend(GET_BX_DISP8(m_op), 8) << 1); + m_pc = m_ppc + (util::sext(GET_BX_DISP8(m_op), 8) << 1); } void score7_cpu_device::op_ldiu() @@ -1275,9 +1284,17 @@ void score7_cpu_device::op_iform1a() switch(GET_I16_FUNC3(m_op)) { case 0x00: // addei! - unemulated_op("addei!"); + if (imm5 & 0x10) + m_gpr[rd] -= 1 << (imm5 & 0xf); + else + m_gpr[rd] += 1 << (imm5 & 0xf); + + // according to the datasheet, the flags are undefined after this instruction, but xmen expects the Z flag to be valid. + CHECK_Z(m_gpr[rd]); + CHECK_N(m_gpr[rd]); break; case 0x01: // slli! + SET_C(BIT(m_gpr[rd], 32 - imm5)); m_gpr[rd] <<= imm5; CHECK_Z(m_gpr[rd]); CHECK_N(m_gpr[rd]); @@ -1286,6 +1303,7 @@ void score7_cpu_device::op_iform1a() unemulated_op("sdbbp!"); break; case 0x03: // srli! + SET_C(BIT(m_gpr[rd], imm5 - 1)); m_gpr[rd] >>= imm5; CHECK_Z(m_gpr[rd]); CHECK_N(m_gpr[rd]); @@ -1304,6 +1322,11 @@ void score7_cpu_device::op_iform1a() CHECK_N(m_gpr[rd]); CHECK_Z(m_gpr[rd] & (1 << imm5)); break; + case 0x07: // bittgl! + m_gpr[rd] ^= (1 << imm5); + CHECK_Z(m_gpr[rd]); + CHECK_N(m_gpr[rd]); + break; default: op_undef(); } @@ -1320,7 +1343,7 @@ void score7_cpu_device::op_iform1b() m_gpr[rd] = read_dword(REG_BP + (imm5<<2)); break; case 0x01: // lhp! - m_gpr[rd] = sign_extend(read_word(REG_BP + (imm5<<1)), 16); + m_gpr[rd] = util::sext(read_word(REG_BP + (imm5<<1)), 16); break; case 0x03: // lbup! m_gpr[rd] = read_byte(REG_BP + imm5); |