summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/score/score.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/score/score.cpp')
-rw-r--r--src/devices/cpu/score/score.cpp199
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);