From dbb4595fccce473f3ca0a8908086d6809ec303c2 Mon Sep 17 00:00:00 2001 From: Sandro Ronco Date: Sat, 7 Sep 2013 21:33:27 +0000 Subject: [PATCH] (MESS) Added preliminary S+core CPU emulation. [Sandro Ronco] (MESS) New NOT WORKING system ----------------------- - Mattel HyperScan [Sandro Ronco] --- .gitattributes | 5 + src/emu/cpu/cpu.mak | 19 + src/emu/cpu/score/score.c | 1346 ++++++++++++++++++++++++++++++++++ src/emu/cpu/score/score.h | 148 ++++ src/emu/cpu/score/scoredsm.c | 292 ++++++++ src/emu/cpu/score/scorem.h | 144 ++++ src/mess/drivers/hyperscan.c | 645 ++++++++++++++++ src/mess/mess.lst | 1 + src/mess/mess.mak | 2 + 9 files changed, 2602 insertions(+) create mode 100644 src/emu/cpu/score/score.c create mode 100644 src/emu/cpu/score/score.h create mode 100644 src/emu/cpu/score/scoredsm.c create mode 100644 src/emu/cpu/score/scorem.h create mode 100644 src/mess/drivers/hyperscan.c diff --git a/.gitattributes b/.gitattributes index aebec76f9a2..34e73b57f5f 100644 --- a/.gitattributes +++ b/.gitattributes @@ -794,6 +794,10 @@ src/emu/cpu/sc61860/sctable.c svneol=native#text/plain src/emu/cpu/scmp/scmp.c svneol=native#text/plain src/emu/cpu/scmp/scmp.h svneol=native#text/plain src/emu/cpu/scmp/scmpdasm.c svneol=native#text/plain +src/emu/cpu/score/score.c svneol=native#text/plain +src/emu/cpu/score/score.h svneol=native#text/plain +src/emu/cpu/score/scoredsm.c svneol=native#text/plain +src/emu/cpu/score/scorem.h svneol=native#text/plain src/emu/cpu/scudsp/scudspdasm.c svneol=native#text/plain src/emu/cpu/se3208/se3208.c svneol=native#text/plain src/emu/cpu/se3208/se3208.h svneol=native#text/plain @@ -6317,6 +6321,7 @@ src/mess/drivers/hpz80unk.c svneol=native#text/plain src/mess/drivers/ht68k.c svneol=native#text/plain src/mess/drivers/huebler.c svneol=native#text/plain src/mess/drivers/hx20.c svneol=native#text/plain +src/mess/drivers/hyperscan.c svneol=native#text/plain src/mess/drivers/ibm6580.c svneol=native#text/plain src/mess/drivers/ibmpc.c svneol=native#text/plain src/mess/drivers/ie15.c svneol=native#text/plain diff --git a/src/emu/cpu/cpu.mak b/src/emu/cpu/cpu.mak index 1bd5e7f7d69..7bfbe9cdf91 100644 --- a/src/emu/cpu/cpu.mak +++ b/src/emu/cpu/cpu.mak @@ -2247,3 +2247,22 @@ endif $(CPUOBJ)/scudsp/scudspdasm.o: CPUOBJS += $(CPUOBJ)/scudsp/scudspdasm.c + +#------------------------------------------------- +# Sunplus Technology S+core +#@src/emu/cpu/score/score.h,CPUS += SCORE +#------------------------------------------------- + +ifneq ($(filter SCORE,$(CPUS)),) +OBJDIRS += $(CPUOBJ)/score +CPUOBJS += $(CPUOBJ)/score/score.o +DASMOBJS += $(CPUOBJ)/score/scoredsm.o +endif + +$(CPUOBJ)/score/score.o: $(CPUSRC)/score/score.c \ + $(CPUSRC)/score/score.h \ + $(CPUSRC)/score/scorem.h + +$(CPUOBJ)/score/scoredsm.o: $(CPUSRC)/score/scoredsm.c \ + $(CPUSRC)/score/scorem.h + diff --git a/src/emu/cpu/score/score.c b/src/emu/cpu/score/score.c new file mode 100644 index 00000000000..22f6eafe532 --- /dev/null +++ b/src/emu/cpu/score/score.c @@ -0,0 +1,1346 @@ +/****************************************************************************** + + Sunplus Technology S+core + by Sandro Ronco + +******************************************************************************/ + +#include "emu.h" +#include "debugger.h" +#include "score.h" + + +//************************************************************************** +// CONSTANTS +//************************************************************************** + +const device_type SCORE7 = &device_creator; + + +//************************************************************************** +// MACROS +//************************************************************************** + +#include "scorem.h" + + +//************************************************************************** +// Opcodes Tables +//************************************************************************** + +const score7_cpu_device::op_handler score7_cpu_device::s_opcode32_table[4*8] = +{ + &score7_cpu_device::op_specialform, &score7_cpu_device::op_iform1, &score7_cpu_device::op_jump , &score7_cpu_device::op_rixform1, &score7_cpu_device::op_branch, &score7_cpu_device::op_iform2, &score7_cpu_device::op_crform, &score7_cpu_device::op_rixform2, + &score7_cpu_device::op_addri , &score7_cpu_device::op_undef , &score7_cpu_device::op_undef, &score7_cpu_device::op_undef , &score7_cpu_device::op_andri , &score7_cpu_device::op_orri , &score7_cpu_device::op_undef , &score7_cpu_device::op_undef , + &score7_cpu_device::op_lw , &score7_cpu_device::op_lh , &score7_cpu_device::op_lhu , &score7_cpu_device::op_lb , &score7_cpu_device::op_sw , &score7_cpu_device::op_sh , &score7_cpu_device::op_lbu , &score7_cpu_device::op_sb , + &score7_cpu_device::op_cache , &score7_cpu_device::op_undef , &score7_cpu_device::op_undef, &score7_cpu_device::op_undef , &score7_cpu_device::op_cenew , &score7_cpu_device::op_undef , &score7_cpu_device::op_undef , &score7_cpu_device::op_undef +}; + +const score7_cpu_device::op_handler score7_cpu_device::s_opcode16_table[8] = +{ + &score7_cpu_device::op_rform1, &score7_cpu_device::op_undef, &score7_cpu_device::op_rform2, &score7_cpu_device::op_jform, &score7_cpu_device::op_branch16, &score7_cpu_device::op_ldiu, &score7_cpu_device::op_iform1a, &score7_cpu_device::op_iform1b +}; + + +//************************************************************************** +// LIVE DEVICE +//************************************************************************** + +//------------------------------------------------- +// score7_cpu_device - constructor +//------------------------------------------------- + +score7_cpu_device::score7_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) + : cpu_device(mconfig, SCORE7, "S+core 7", tag, owner, clock, "score7", __FILE__), + m_program_config("program", ENDIANNESS_LITTLE, 32, 32, 0), + m_pc(0), + m_ppc(0) +{ +} + +//------------------------------------------------- +// device_start - start up the device +//------------------------------------------------- + +void score7_cpu_device::device_start() +{ + // find address spaces + m_program = &space(AS_PROGRAM); + m_direct = &m_program->direct(); + + // set our instruction counter + m_icountptr = &m_icount; + + // register state for debugger + state_add(SCORE_PC , "PC" , m_pc).callimport().callexport().formatstr("%08X"); + + astring tmp_string; + + for(int i=0; i<0x20; i++) + state_add(SCORE_GPR + i, tmp_string.format("r%d", i).cstr(), m_gpr[i]).callimport().callexport().formatstr("%08X"); + + for(int i=0; i<0x20; i++) + state_add(SCORE_CR + i, tmp_string.format("cr%d", i).cstr(), m_cr[i]).callimport().callexport().formatstr("%08X"); + + for(int i=0; i<3; i++) + state_add(SCORE_SR + i, tmp_string.format("sr%d", i).cstr(), m_sr[i]).callimport().callexport().formatstr("%08X"); + + state_add(SCORE_CEH, "ceh", REG_CEH).callimport().callexport().formatstr("%08X"); + state_add(SCORE_CEL, "cel", REG_CEL).callimport().callexport().formatstr("%08X"); + + state_add(STATE_GENPC, "curpc", m_pc).callimport().callexport().formatstr("%08X").noshow(); + state_add(STATE_GENPCBASE, "curpcbase", m_ppc).callimport().callexport().formatstr("%8X").noshow(); + state_add(STATE_GENFLAGS, "GENFLAGS", m_ppc).formatstr("%5s").noshow(); + + // save state + save_item(NAME(m_pc)); + save_item(NAME(m_ppc)); + save_item(NAME(m_op)); + save_item(NAME(m_gpr)); + save_item(NAME(m_cr)); + save_item(NAME(m_sr)); + save_item(NAME(m_ce)); + save_item(NAME(m_pending_interrupt)); +} + + +//------------------------------------------------- +// device_reset - reset up the device +//------------------------------------------------- + +void score7_cpu_device::device_reset() +{ + // GPR are undefined at reset + memset(m_gpr,0, sizeof(m_gpr)); + 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)); + + REG_EXCPVEC = m_pc = 0x9f000000; +} + + +//------------------------------------------------- +// state_string_export - export state as a string +// for the debugger +//------------------------------------------------- + +void score7_cpu_device::state_string_export(const device_state_entry &entry, astring &string) +{ + switch (entry.index()) + { + case STATE_GENFLAGS: + string.printf("%s%s%s%s%s", + REG_CR & FLAG_V ? "V" : ".", + REG_CR & FLAG_C ? "C" : ".", + REG_CR & FLAG_Z ? "Z" : ".", + REG_CR & FLAG_N ? "N" : ".", + REG_CR & FLAG_T ? "T" : "." + ); + break; + } +} + + +//------------------------------------------------- +// memory_space_config - return the configuration +// of the specified address space, or NULL if +// the space doesn't exist +//------------------------------------------------- + +const address_space_config * score7_cpu_device::memory_space_config(address_spacenum spacenum) const +{ + return (spacenum == AS_PROGRAM) ? &m_program_config: NULL; +} + + +//------------------------------------------------- +// execute - execute for the provided number of +// cycles +//------------------------------------------------- + +void score7_cpu_device::execute_run() +{ + do + { + debugger_instruction_hook(this, m_pc); + + m_ppc = m_pc; + + check_irq(); + + UINT32 op = fetch(); + + switch(((op>>30) & 2) | ((op>>15) & 1)) + { + case 0: // 16-bit + 16-bit instruction + m_op = ((m_pc & 0x02) ? (op >> 16) : op) & 0x7fff; + m_pc += 2; + (this->*s_opcode16_table[(m_op >> 12) & 0x07])(); + break; + case 1: // undefined parity bit + m_pc += 4; + gen_exception(EXCEPTION_P_EL); + break; + case 2: // parallel conditional execution + m_op = (GET_T ? op: (op >> 16)) & 0x7fff; + m_pc += 4; + (this->*s_opcode16_table[(m_op >> 12) & 0x07])(); + break; + case 3: // 32-bit instruction + m_op = (op & 0x7fff) | ((op >> 1) & 0x3fff8000); + m_pc += 4; + (this->*s_opcode32_table[(m_op >> 25) & 0x01f])(); + break; + } + + m_icount -= 3; // FIXME: if available use correct cycles per instructions + } + while (m_icount > 0); +} + + +//------------------------------------------------- +// execute_set_input +//------------------------------------------------- + +void score7_cpu_device::execute_set_input(int inputnum, int state) +{ + switch (inputnum) + { + 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; + } +} + +//************************************************************************** +// HELPERS +//************************************************************************** + + +bool score7_cpu_device::check_condition_branch(UINT8 bc) +{ + if ((bc & 0x0f) == 14) // CNT>0, CNT-- + { + if (REG_CNT > 0) + { + REG_CNT--; + return true; + } + return false; + } + else + return check_condition(bc); +} + +bool score7_cpu_device::check_condition(UINT8 bc) +{ + switch(bc & 0x0f) + { + case 0: return GET_C; // carry set + case 1: return !GET_C; // carry clear + case 2: return GET_C && !GET_Z; // C & ~Z + case 3: return !GET_C || GET_Z; // ~C | Z + case 4: return GET_Z; // Z + case 5: return !GET_Z; // ~Z + case 6: return !GET_Z && (GET_N == GET_V); // (Z = 0) & (N = V) + case 7: return GET_Z || (GET_N != GET_V); // (Z = 1) | (N != V) + case 8: return (GET_N == GET_V); // N = V + case 9: return (GET_N != GET_V); // N != V + case 10: return GET_N; // N + case 11: return !GET_N; // ~N + case 12: return GET_V; // overflow V + case 13: return !GET_V; // no overflow ~V + case 14: return REG_CNT > 0; // CNT>0 + case 15: return true; // always + } + + return false; +} + +INT32 score7_cpu_device::sign_extend(UINT32 data, UINT8 len) +{ + data &= (1 << len) - 1; + UINT32 sign = 1 << (len - 1); + return (data ^ sign) - sign; +} + +UINT32 score7_cpu_device::fetch() +{ + return m_direct->read_decrypted_dword(m_pc & ~3); +} + +UINT8 score7_cpu_device::read_byte(offs_t offset) +{ + return m_program->read_byte(offset); +} + +UINT16 score7_cpu_device::read_word(offs_t offset) +{ + return m_program->read_word(offset & ~1); +} + +UINT32 score7_cpu_device::read_dword(offs_t offset) +{ + return m_program->read_dword(offset & ~3); +} + +void score7_cpu_device::write_byte(offs_t offset, UINT8 data) +{ + m_program->write_byte(offset, data); +} + +void score7_cpu_device::write_word(offs_t offset, UINT16 data) +{ + m_program->write_word(offset & ~1, data); +} + +void score7_cpu_device::write_dword(offs_t offset, UINT32 data) +{ + m_program->write_dword(offset & ~3, data); +} + +void score7_cpu_device::check_irq() +{ + if(REG_PSR & 0x01) + { + for (int i=63; i>0; i--) + { + if (m_pending_interrupt[i]) + { + m_pending_interrupt[i] = false; + debugger_interrupt_hook(this, i); + gen_exception(EXCEPTION_INTERRUPT, i); + return; + } + } + } +} + +void score7_cpu_device::gen_exception(int cause, UINT32 param) +{ + debugger_exception_hook(this, cause); + + REG_ECR = (REG_ECR & ~0x0000001f) | (cause & 0x1f); // set exception cause + REG_PSR = (REG_PSR & ~0x0000000f) | ((REG_PSR << 2) & 0x0c); // push status bits + REG_CR = (REG_CR & ~0x000003ff) | ((REG_CR << 5) & 0x3e0); // push flag bits + REG_EPC = m_ppc & 0xfffffffe; // set return address + + switch(cause) + { + case EXCEPTION_P_EL: + REG_EMA = REG_EPC; + // intentional fallthrough + case EXCEPTION_NMI: + case EXCEPTION_CEE: + case EXCEPTION_SYSCALL: + case EXCEPTION_TRAP: + case EXCEPTION_RI: + m_pc = (REG_EXCPVEC & 0xffff0000) + 0x200; + break; + + case EXCEPTION_SWI: + case EXCEPTION_INTERRUPT: + REG_ECR = (REG_ECR & ~0x00fc0000) | ((param & 0x3f) << 18); // set irq source + m_pc = (REG_EXCPVEC & 0xffff0000) + 0x200 + (param << (REG_EXCPVEC & 1 ? 4 : 2)); + break; + + case EXCEPTION_ADEL_INSTRUCTION: + case EXCEPTION_BUSEL_INSTRUCTION: + case EXCEPTION_CCU: + case EXCEPTION_ADEL_DATA: + case EXCEPTION_ADES_DATA: + case EXCEPTION_CPE: + case EXCEPTION_BUSEL_DATA: + fatalerror("unhandled exception: %d 0x%08x (PC=0x%08x)\n", cause, param, m_ppc); + break; + } +} + + +//************************************************************************** +// 32-bit opcodes +//************************************************************************** + +void score7_cpu_device::op_specialform() +{ + UINT8 ra = GET_S_RA(m_op); + UINT8 rb = GET_S_RB(m_op); + UINT8 rd = GET_S_RD(m_op); + UINT8 cu = GET_S_CU(m_op); + UINT32 r; + + switch(GET_S_FUNC6(m_op)) + { + case 0x00: // nop + break; + case 0x01: // syscall + gen_exception(EXCEPTION_SYSCALL); + break; + case 0x02: // trap + if (check_condition(rb)) + gen_exception(EXCEPTION_TRAP); + break; + case 0x03: // sdbbp + unemulated_op("sdbbp"); + break; + case 0x04: // br + if (check_condition_branch(rb)) + { + if (GET_S_LK(m_op)) + REG_LNK = m_pc; + + m_pc = m_gpr[ra]; + } + break; + case 0x05: // pflush + unemulated_op("pflush"); + break; + case 0x08: // add + r = m_gpr[ra] + m_gpr[rb]; + if (cu) + { + CHECK_Z(r); + CHECK_N(r); + CHECK_V_ADD(m_gpr[ra], m_gpr[rb], r); + CHECK_C_ADD(m_gpr[ra], m_gpr[rb]); + } + m_gpr[rd] = r; + break; + case 0x09: // addc + r = m_gpr[ra] + m_gpr[rb] + GET_C; + if (cu) + { + CHECK_Z(r); + CHECK_N(r); + CHECK_V_ADD(m_gpr[ra] + GET_C, m_gpr[rb], r); + CHECK_C_ADD(m_gpr[ra] + GET_C, m_gpr[rb]); + } + m_gpr[rd] = r; + break; + case 0x0a: // sub + r = m_gpr[ra] - m_gpr[rb]; + if (cu) + { + CHECK_Z(r); + CHECK_N(r); + CHECK_V_SUB(m_gpr[ra], m_gpr[rb], r); + CHECK_C_SUB(m_gpr[ra], m_gpr[rb]); + } + m_gpr[rd] = r; + break; + case 0x0b: // subc + r = m_gpr[ra] - m_gpr[rb] - (GET_C ^ 1); + if (cu) + { + CHECK_Z(r); + CHECK_N(r); + CHECK_V_SUB(m_gpr[ra] - (GET_C ^ 1), m_gpr[rb], r); + CHECK_C_SUB(m_gpr[ra] - (GET_C ^ 1), m_gpr[rb]); + } + m_gpr[rd] = r; + break; + case 0x0c: // cmp + if (cu) + { + r = m_gpr[ra] - m_gpr[rb]; + CHECK_Z(r); + CHECK_N(r); + CHECK_V_SUB(m_gpr[ra], m_gpr[rb], r); + CHECK_C_SUB(m_gpr[ra], m_gpr[rb]); + switch(rd & 0x03) + { + case 0: SET_T(GET_Z); break; + case 1: SET_T(GET_N); break; + } + } + break; + case 0x0d: // cmpz + if (cu) + { + r = m_gpr[ra] - 0; + CHECK_Z(r); + CHECK_N(r); + CHECK_V_SUB(m_gpr[ra], 0, r); + CHECK_C_SUB(m_gpr[ra], 0); + switch(rd & 0x03) + { + case 0: SET_T(GET_Z); break; + case 1: SET_T(GET_N); break; + } + } + break; + case 0x0f: // neg + r = 0 - m_gpr[rb]; + if (cu) + { + CHECK_Z(r); + CHECK_N(r); + CHECK_V_SUB(0, m_gpr[rb], r); + CHECK_C_SUB(0, m_gpr[rb]); + } + m_gpr[rd] = r; + break; + case 0x10: // and + m_gpr[rd] = m_gpr[ra] & m_gpr[rb]; + if (cu) + { + CHECK_Z(m_gpr[rd]); + CHECK_N(m_gpr[rd]); + } + break; + case 0x11: // or + m_gpr[rd] = m_gpr[ra] | m_gpr[rb]; + if (cu) + { + CHECK_Z(m_gpr[rd]); + CHECK_N(m_gpr[rd]); + } + break; + case 0x12: // not + r = ~m_gpr[ra]; + if (cu) + { + CHECK_Z(r); + CHECK_N(r); + } + m_gpr[rd] = r; + break; + case 0x13: // xor + m_gpr[rd] = m_gpr[ra] ^ m_gpr[rb]; + if (cu) + { + CHECK_Z(m_gpr[rd]); + CHECK_N(m_gpr[rd]); + } + break; + case 0x14: // bitclr + m_gpr[rd] = m_gpr[ra] & ~(1 << rb); + if (cu) + { + CHECK_Z(m_gpr[rd]); + CHECK_N(m_gpr[rd]); + } + break; + case 0x15: // bitset + m_gpr[rd] = m_gpr[ra] | (1 << rb); + if (cu) + { + CHECK_Z(m_gpr[rd]); + CHECK_N(m_gpr[rd]); + } + break; + case 0x16: // bittst + if (cu) + { + r = m_gpr[ra] & (1 << rb); + CHECK_N(m_gpr[ra]); + CHECK_Z(r); + } + break; + case 0x17: // bittgl + m_gpr[rd] = m_gpr[ra] ^ (1 << rb); + if (cu) + { + CHECK_Z(m_gpr[rd]); + CHECK_N(m_gpr[rd]); + } + break; + case 0x18: // sll + m_gpr[rd] = m_gpr[ra] << (m_gpr[rb] & 0x1f); + if (cu) + { + CHECK_Z(m_gpr[rd]); + CHECK_N(m_gpr[rd]); + SET_C(BIT(m_gpr[ra], 32 - (m_gpr[rb] & 0x1f))); + } + break; + case 0x1a: // srl + m_gpr[rd] = m_gpr[ra] >> (m_gpr[rb] & 0x1f); + if (cu) + { + CHECK_Z(m_gpr[rd]); + CHECK_N(m_gpr[rd]); + SET_C(BIT(m_gpr[ra], (m_gpr[rb] & 0x1f) - 1)); + } + break; + case 0x1b: // sra + m_gpr[rd] = sign_extend(m_gpr[ra] >> (m_gpr[rb] & 0x1f), 32 - (m_gpr[rb] & 0x1f)); + if (cu) + { + CHECK_Z(m_gpr[rd]); + CHECK_N(m_gpr[rd]); + SET_C(BIT(m_gpr[ra], (m_gpr[rb] & 0x1f) - 1)); + } + break; + case 0x1c: // ror + unemulated_op("ror"); + break; + case 0x1d: // rorc + unemulated_op("rorc"); + break; + case 0x1e: // rol + unemulated_op("rol"); + break; + case 0x1f: // rolc + unemulated_op("rolc"); + break; + case 0x20: // mul + { + INT64 a = (INT32)m_gpr[ra]; + INT64 b = (INT32)m_gpr[rb]; + UINT64 d = a * b; + REG_CEL = d & 0xffffffff; + REG_CEH = (d >> 32) & 0xffffffff; + break; + } + case 0x21: // mulu + { + UINT64 a = (UINT32)m_gpr[ra]; + UINT64 b = (UINT32)m_gpr[rb]; + UINT64 d = a * b; + REG_CEL = d & 0xffffffff; + REG_CEH = (d >> 32) & 0xffffffff; + break; + } + case 0x22: // div + if (m_gpr[rb]) + { + INT32 a = (INT32)m_gpr[ra]; + INT32 b = (INT32)m_gpr[rb]; + REG_CEL = a / b; + REG_CEH = a % b; + } + else + { + gen_exception(EXCEPTION_CEE); // divide by zero exception + } + break; + case 0x23: // divu + if (m_gpr[rb]) + { + UINT32 a = (UINT32)m_gpr[ra]; + UINT32 b = (UINT32)m_gpr[rb]; + REG_CEL = a / b; + REG_CEH = a % b; + } + else + { + gen_exception(EXCEPTION_CEE); // divide by zero exception + } + break; + case 0x24: // mfce + switch(rb & 3) + { + case 1: m_gpr[rd] = REG_CEL; break; + case 2: m_gpr[rd] = REG_CEH; break; + case 3: m_gpr[rd] = REG_CEH; m_gpr[ra] = REG_CEL; break; + } + break; + case 0x25: // mtce + switch(rb & 3) + { + case 1: REG_CEL = m_gpr[rd]; break; + case 2: REG_CEH = m_gpr[rd]; break; + case 3: REG_CEH = m_gpr[rd]; REG_CEL = m_gpr[ra]; break; + } + break; + case 0x28: // mfsr + if (rb < 3) + m_gpr[rd] = m_sr[rb]; + break; + case 0x29: // mtsr + if (rb < 3) + m_sr[rb] = m_gpr[ra]; + break; + case 0x2a: // t + SET_T(check_condition(rb)); + break; + case 0x2b: // mv + if ((rb & 0x0f) != 14 && check_condition(rb)) + m_gpr[rd] = m_gpr[ra]; + break; + case 0x2c: // extsb + case 0x2d: // extsh + m_gpr[rd] = sign_extend(m_gpr[ra], (GET_S_FUNC6(m_op) & 1) ? 16 : 8); + if (cu) + { + CHECK_N(m_gpr[rd]); + CHECK_Z(m_gpr[rd]); // undefined + } + break; + case 0x2e: // extzb + case 0x2f: // extzh + m_gpr[rd] = m_gpr[ra] & ((GET_S_FUNC6(m_op) & 1) ? 0xffff : 0x00ff); + if (cu) + { + CHECK_N(m_gpr[rd]); + CHECK_Z(m_gpr[rd]); // undefined + } + break; + case 0x30: // lcb + unemulated_op("lcb"); + break; + case 0x31: // lcw + unemulated_op("lcw"); + break; + case 0x33: // lce + unemulated_op("lce"); + break; + case 0x34: // scb + unemulated_op("scb"); + break; + case 0x35: // scw + unemulated_op("scw"); + break; + case 0x37: // sce + unemulated_op("sce"); + break; + case 0x38: // slli + m_gpr[rd] = m_gpr[ra] << rb; + if (cu) + { + CHECK_Z(m_gpr[rd]); + CHECK_N(m_gpr[rd]); + SET_C(BIT(m_gpr[ra], 32 - rb)); + } + break; + case 0x3a: // srli + m_gpr[rd] = m_gpr[ra] >> rb; + if (cu) + { + CHECK_Z(m_gpr[rd]); + CHECK_N(m_gpr[rd]); + SET_C(BIT(m_gpr[ra], rb - 1)); + } + break; + case 0x3b: // srai + m_gpr[rd] = sign_extend(m_gpr[ra] >> rb, 32 - rb); + if (cu) + { + CHECK_Z(m_gpr[rd]); + CHECK_N(m_gpr[rd]); + SET_C(BIT(m_gpr[ra], rb - 1)); + } + break; + case 0x3c: // rori + unemulated_op("rori"); + break; + case 0x3d: // roric + unemulated_op("roric"); + break; + case 0x3e: // roli + unemulated_op("roli"); + break; + case 0x3f: // rolic + unemulated_op("rolic"); + break; + default: + op_undef(); + } +} + +void score7_cpu_device::op_iform1() +{ + UINT8 rd = GET_I_RD(m_op); + UINT32 imm16 = GET_I_IMM16(m_op); + INT32 simm16 = sign_extend(imm16, 16); + UINT8 cu = GET_I_CU(m_op); + UINT32 r; + + switch(GET_I_FUNC3(m_op)) + { + case 0: // addi + r = m_gpr[rd] + simm16; + if (cu) + { + CHECK_Z(r); + CHECK_N(r); + CHECK_V_ADD(m_gpr[rd], (UINT32)simm16, r); + CHECK_C_ADD(m_gpr[rd], (UINT32)simm16); + } + m_gpr[rd] = r; + break; + case 2: // cmpi + if (cu) + { + r = m_gpr[rd] - simm16; + CHECK_Z(r); + CHECK_N(r); + CHECK_V_SUB(m_gpr[rd], (UINT32)simm16, r); + CHECK_C_SUB(m_gpr[rd], (UINT32)simm16); + } + break; + case 4: // andi + m_gpr[rd] = m_gpr[rd] & imm16; + if (cu) + { + CHECK_Z(m_gpr[rd]); + CHECK_N(m_gpr[rd]); + } + break; + case 5: // ori + m_gpr[rd] = m_gpr[rd] | imm16; + if (cu) + { + CHECK_Z(m_gpr[rd]); + CHECK_N(m_gpr[rd]); + } + break; + case 6: // ldi + m_gpr[rd] = simm16; + break; + default: + op_undef(); + } +} + +void score7_cpu_device::op_jump() +{ + if(GET_J_LK(m_op)) + REG_LNK = m_pc; + + m_pc = (m_ppc & 0xfe000000) | (GET_J_DISP24(m_op) << 1); +} + +void score7_cpu_device::op_rixform1() +{ + UINT8 ra = GET_RIX_RA(m_op); + UINT8 rd = GET_RIX_RD(m_op); + + // pre-increment + m_gpr[ra] += sign_extend(GET_RIX_IMM12(m_op), 12); + + switch(GET_RIX_FUNC3(m_op)) + { + case 0: // lw + m_gpr[rd] = read_dword(m_gpr[ra]); + break; + case 1: // lh + m_gpr[rd] = sign_extend(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); + break; + case 4: // sw + write_dword(m_gpr[ra], m_gpr[rd]); + break; + case 5: // sh + write_word(m_gpr[ra], m_gpr[rd] & 0xffff); + break; + case 6: // lbu + m_gpr[rd] = read_byte(m_gpr[ra]); + break; + case 7: // sb + write_byte(m_gpr[ra], m_gpr[rd] & 0xff); + break; + } +} + +void score7_cpu_device::op_branch() +{ + if (check_condition_branch(GET_BC_BC(m_op))) + { + INT32 disp = sign_extend(GET_BC_DISP19(m_op), 19) << 1; + if (GET_BC_LK(m_op)) + REG_LNK = m_pc; + + m_pc = m_ppc + disp; + } +} + +void score7_cpu_device::op_iform2() +{ + UINT8 rd = GET_I_RD(m_op); + UINT32 imm16 = GET_I_IMM16(m_op) << 16; + INT32 simm16 = (INT32)imm16; + UINT8 cu = GET_I_CU(m_op); + UINT32 r; + + switch(GET_I_FUNC3(m_op)) + { + case 0: // addis + r = m_gpr[rd] + simm16; + if (cu) + { + CHECK_Z(r); + CHECK_N(r); + CHECK_V_ADD(m_gpr[rd], imm16, r); + CHECK_C_ADD(m_gpr[rd], imm16); + } + m_gpr[rd] = r; + break; + case 2: // cmpis + if (cu) + { + r = m_gpr[rd] - simm16; + CHECK_Z(r); + CHECK_N(r); + CHECK_V_SUB(m_gpr[rd], imm16, r); + CHECK_C_SUB(m_gpr[rd], imm16); + } + break; + case 4: // andis + m_gpr[rd] = m_gpr[rd] & imm16; + if (cu) + { + CHECK_Z(m_gpr[rd]); + CHECK_N(m_gpr[rd]); + } + break; + case 5: // oris + m_gpr[rd] = m_gpr[rd] | imm16; + if (cu) + { + CHECK_Z(m_gpr[rd]); + CHECK_N(m_gpr[rd]); + } + break; + case 6: // ldis + m_gpr[rd] = imm16; + break; + default: + op_undef(); + } + +} + +void score7_cpu_device::op_crform() +{ + if ((REG_PSR & 0x08) && !(REG_PSR & 0x10000000)) + return; + + UINT8 cr = GET_CR_CR(m_op); + UINT8 rd = GET_CR_RD(m_op); + + switch(GET_CR_OP(m_op)) + { + case 0x00: // mtcr + m_cr[cr] = m_gpr[rd]; + break; + case 0x01: // mfcr + m_gpr[rd] = m_cr[cr]; + break; + case 0x84: // rte + REG_PSR = (REG_PSR & ~ 0x03) | ((REG_PSR >> 2) & 0x03); + REG_CR = (REG_CR & ~0x1f) | ((REG_CR >> 5) & 0x1f); + m_pc = REG_EPC; + break; + default: + if ((GET_CR_OP(m_op) & 0xc0) == 0) + fatalerror("%s: unemulated Coprocessor 0x%x (PC=0x%08x)\n", tag(), GET_CR_OP(m_op) & 0x07, m_ppc); + else + op_undef(); + } +} + +void score7_cpu_device::op_rixform2() +{ + UINT8 ra = GET_RIX_RA(m_op); + UINT8 rd = GET_RIX_RD(m_op); + + switch(GET_RIX_FUNC3(m_op)) + { + case 0: // lw + m_gpr[rd] = read_dword(m_gpr[ra]); + break; + case 1: // lh + m_gpr[rd] = sign_extend(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); + break; + case 4: // sw + write_dword(m_gpr[ra], m_gpr[rd]); + break; + case 5: // sh + write_word(m_gpr[ra], m_gpr[rd] & 0xffff); + break; + case 6: // lbu + m_gpr[rd] = read_byte(m_gpr[ra]); + break; + case 7: // sb + write_byte(m_gpr[ra], m_gpr[rd] & 0xff); + break; + } + + // post-increment + m_gpr[ra] += sign_extend(GET_RIX_IMM12(m_op), 12); +} + +void score7_cpu_device::op_addri() +{ + UINT8 ra = GET_RI_RA(m_op); + UINT8 rd = GET_RI_RD(m_op); + INT32 simm14 = sign_extend(GET_RI_IMM14(m_op), 14); + UINT8 cu = GET_RI_CU(m_op); + + UINT32 r = m_gpr[ra] + simm14; + if (cu) + { + CHECK_Z(r); + CHECK_N(r); + CHECK_V_ADD(m_gpr[ra], (UINT32)simm14, r); + CHECK_C_ADD(m_gpr[ra], (UINT32)simm14); + } + m_gpr[rd] = r; +} + +void score7_cpu_device::op_andri() +{ + UINT8 ra = GET_RI_RA(m_op); + UINT8 rd = GET_RI_RD(m_op); + UINT32 imm14 = GET_RI_IMM14(m_op); + + m_gpr[rd] = m_gpr[ra] & imm14; + + if (GET_RI_CU(m_op)) + { + CHECK_Z(m_gpr[rd]); + CHECK_N(m_gpr[rd]); + } +} + +void score7_cpu_device::op_orri() +{ + UINT8 ra = GET_RI_RA(m_op); + UINT8 rd = GET_RI_RD(m_op); + UINT32 imm14 = GET_RI_IMM14(m_op); + + m_gpr[rd] = m_gpr[ra] | imm14; + + if (GET_RI_CU(m_op)) + { + CHECK_Z(m_gpr[rd]); + CHECK_N(m_gpr[rd]); + } +} + +void score7_cpu_device::op_lw() +{ + UINT8 rd = GET_LS_RD(m_op); + UINT8 ra = GET_LS_RA(m_op); + INT32 simm15 = sign_extend(GET_LS_IMM15(m_op), 15); + + m_gpr[rd] = read_dword(m_gpr[ra] + simm15); +} + +void score7_cpu_device::op_lh() +{ + UINT8 rd = GET_LS_RD(m_op); + UINT8 ra = GET_LS_RA(m_op); + INT32 simm15 = sign_extend(GET_LS_IMM15(m_op), 15); + + m_gpr[rd] = sign_extend(read_word(m_gpr[ra] + simm15), 16); +} + +void score7_cpu_device::op_lhu() +{ + UINT8 rd = GET_LS_RD(m_op); + UINT8 ra = GET_LS_RA(m_op); + INT32 simm15 = sign_extend(GET_LS_IMM15(m_op), 15); + + m_gpr[rd] = read_word(m_gpr[ra] + simm15); +} + +void score7_cpu_device::op_lb() +{ + UINT8 rd = GET_LS_RD(m_op); + UINT8 ra = GET_LS_RA(m_op); + INT32 simm15 = sign_extend(GET_LS_IMM15(m_op), 15); + + m_gpr[rd] = sign_extend(read_byte(m_gpr[ra] + simm15), 8); +} + +void score7_cpu_device::op_sw() +{ + UINT8 rd = GET_LS_RD(m_op); + UINT8 ra = GET_LS_RA(m_op); + INT32 simm15 = sign_extend(GET_LS_IMM15(m_op), 15); + + write_dword(m_gpr[ra] + simm15, m_gpr[rd]); +} + +void score7_cpu_device::op_sh() +{ + UINT8 rd = GET_LS_RD(m_op); + UINT8 ra = GET_LS_RA(m_op); + INT32 simm15 = sign_extend(GET_LS_IMM15(m_op), 15); + + write_word(m_gpr[ra] + simm15, m_gpr[rd] & 0xffff); +} + +void score7_cpu_device::op_lbu() +{ + UINT8 rd = GET_LS_RD(m_op); + UINT8 ra = GET_LS_RA(m_op); + INT32 simm15 = sign_extend(GET_LS_IMM15(m_op), 15); + + m_gpr[rd] = read_byte(m_gpr[ra] + simm15); +} + +void score7_cpu_device::op_sb() +{ + UINT8 rd = GET_LS_RD(m_op); + UINT8 ra = GET_LS_RA(m_op); + INT32 simm15 = sign_extend(GET_LS_IMM15(m_op), 15); + + write_byte(m_gpr[ra] + simm15, m_gpr[rd] & 0xff); +} + +void score7_cpu_device::op_cache() +{ + //unemulated_op("CACHE"); +} + +void score7_cpu_device::op_cenew() +{ + unemulated_op("CENew"); +} + + +//************************************************************************** +// 16-bit opcodes +//************************************************************************** + +void score7_cpu_device::op_rform1() +{ + UINT8 rd = GET_R_RD(m_op); + UINT8 ra = GET_R_RA(m_op); + + switch(GET_R_FUNC4(m_op)) + { + case 0x00: // nop! + break; + case 0x01: // mlfh! + m_gpr[rd] = m_gpr[0x10 + ra]; + break; + case 0x02: // mhfl! + m_gpr[0x10 + rd] = m_gpr[ra]; + break; + case 0x03: // mv! + m_gpr[rd] = m_gpr[ra]; + break; + case 0x04: // br! + if (check_condition_branch(rd)) + m_pc = m_gpr[ra]; + break; + case 0x05: // t! + SET_T(check_condition(rd)); + break; + case 0x0c: // brl! + if (check_condition_branch(rd)) + { + REG_LNK = m_pc; + m_pc = m_gpr[ra]; + } + break; + default: + op_undef(); + } +} + +void score7_cpu_device::op_rform2() +{ + UINT8 rd = GET_R_RD(m_op); + UINT8 ra = GET_R_RA(m_op); + UINT32 r; + + switch(GET_R_FUNC4(m_op)) + { + case 0x00: // add! + r = m_gpr[rd] + m_gpr[ra]; + CHECK_Z(r); + CHECK_N(r); + CHECK_V_ADD(m_gpr[rd], m_gpr[ra], r); + CHECK_C_ADD(m_gpr[rd], m_gpr[ra]); + m_gpr[rd] = r; + break; + case 0x01: // sub! + r = m_gpr[rd] - m_gpr[ra]; + CHECK_Z(r); + CHECK_N(r); + CHECK_V_SUB(m_gpr[rd], m_gpr[ra], r); + CHECK_C_SUB(m_gpr[rd], m_gpr[ra]); + 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]); + CHECK_C_SUB(0, m_gpr[ra]); + break; + case 0x03: // cmp! + r = m_gpr[rd] - m_gpr[ra]; + CHECK_Z(r); + CHECK_N(r); + CHECK_V_SUB(m_gpr[rd], m_gpr[ra], r); + CHECK_C_SUB(m_gpr[rd], m_gpr[ra]); + break; + case 0x04: // and! + m_gpr[rd] &= m_gpr[ra]; + CHECK_Z(m_gpr[rd]); + CHECK_N(m_gpr[rd]); + break; + case 0x05: // or! + m_gpr[rd] |= m_gpr[ra]; + CHECK_Z(m_gpr[rd]); + CHECK_N(m_gpr[rd]); + break; + case 0x06: // not! + m_gpr[rd] = ~m_gpr[ra]; + CHECK_Z(m_gpr[rd]); + CHECK_N(m_gpr[rd]); + break; + case 0x07: // xor! + m_gpr[rd] ^= m_gpr[ra]; + CHECK_Z(m_gpr[rd]); + CHECK_N(m_gpr[rd]); + break; + case 0x08: // lw! + m_gpr[rd] = read_dword(m_gpr[ra]); + break; + case 0x09: // lh! + m_gpr[rd] = sign_extend(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)]); + m_gpr[GET_P_RAG(m_op)] += 0x04; + break; + case 0x0b: // lbu! + m_gpr[rd] = read_byte(m_gpr[ra]); + break; + case 0x0c: // sw! + write_dword(m_gpr[ra], m_gpr[rd]); + break; + case 0x0d: // sh! + write_word(m_gpr[ra], m_gpr[rd] & 0xffff); + break; + case 0x0e: // push + m_gpr[GET_P_RAG(m_op)] -= 0x04; + write_dword(m_gpr[GET_P_RAG(m_op)], m_gpr[GET_P_RDG(m_op)]); + break; + case 0x0f: // sb! + write_byte(m_gpr[ra], m_gpr[rd] & 0xff); + break; + } +} + +void score7_cpu_device::op_jform() +{ + if(GET_J_LK(m_op)) + REG_LNK = m_pc; + + m_pc = (m_ppc & 0xfffff000) | (GET_J_DISP11(m_op) << 1); +} + +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); +} + +void score7_cpu_device::op_ldiu() +{ + m_gpr[GET_I2_RD(m_op)] = GET_I2_IMM8(m_op); +} + +void score7_cpu_device::op_iform1a() +{ + UINT8 rd = GET_I16_RD(m_op); + UINT8 imm5 = GET_I16_IMM5(m_op); + + switch(GET_I16_FUNC3(m_op)) + { + case 0x00: // addei! + unemulated_op("addei!"); + break; + case 0x01: // slli! + m_gpr[rd] <<= imm5; + CHECK_Z(m_gpr[rd]); + CHECK_N(m_gpr[rd]); + break; + case 0x02: // sdbbp! + unemulated_op("sdbbp!"); + break; + case 0x03: // srli! + m_gpr[rd] >>= imm5; + CHECK_Z(m_gpr[rd]); + CHECK_N(m_gpr[rd]); + break; + case 0x04: // bitclr! + m_gpr[rd] &= ~(1 << imm5); + CHECK_Z(m_gpr[rd]); + CHECK_N(m_gpr[rd]); + break; + case 0x05: // bitset! + m_gpr[rd] |= (1 << imm5); + CHECK_Z(m_gpr[rd]); + CHECK_N(m_gpr[rd]); + break; + case 0x06: // bittst! + CHECK_N(m_gpr[rd]); + CHECK_Z(m_gpr[rd] & (1 << imm5)); + break; + default: + op_undef(); + } +} + +void score7_cpu_device::op_iform1b() +{ + UINT8 rd = GET_I16_RD(m_op); + UINT16 imm5 = GET_I16_IMM5(m_op); + + switch(GET_I16_FUNC3(m_op)) + { + case 0x00: // lwp! + 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); + break; + case 0x03: // lbup! + m_gpr[rd] = read_byte(REG_BP + imm5); + break; + case 0x04: // swp! + write_dword(REG_BP + (imm5<<2), m_gpr[rd]); + break; + case 0x05: // shp! + write_word(REG_BP + (imm5<<1), m_gpr[rd] & 0xffff); + break; + case 0x07: // sbp! + write_byte(REG_BP + imm5, m_gpr[rd] & 0xff); + break; + default: + op_undef(); + } +} + +void score7_cpu_device::op_undef() +{ + logerror("%s: undefined instruction 0x%x (PC=0x%08x)\n", tag(), m_op, m_ppc); + gen_exception(EXCEPTION_RI); +} + +void score7_cpu_device::unemulated_op(const char * op) +{ + fatalerror("%s: unemulated %s (PC=0x%08x)\n", tag(), op, m_ppc); +} diff --git a/src/emu/cpu/score/score.h b/src/emu/cpu/score/score.h new file mode 100644 index 00000000000..8def8d3ae28 --- /dev/null +++ b/src/emu/cpu/score/score.h @@ -0,0 +1,148 @@ +/********************************************************************** + + Sunplus Technology S+core + +**********************************************************************/ + +#pragma once + +#ifndef __SCORE_H__ +#define __SCORE_H__ + + +//************************************************************************** +// DEFINITION +//************************************************************************** + +enum +{ + SCORE_PC = 1, + SCORE_CEH, + SCORE_CEL, + SCORE_GPR, + SCORE_CR = SCORE_GPR + 0x20, + SCORE_SR = SCORE_CR + 0x20, +}; + + +// ======================> score7_cpu_device + +class score7_cpu_device : public cpu_device +{ +public: + // construction/destruction + score7_cpu_device(const machine_config &mconfig, const char *_tag, device_t *_owner, UINT32 _clock); +protected: + // device-level overrides + virtual void device_start(); + virtual void device_reset(); + + // device_execute_interface overrides + virtual UINT32 execute_min_cycles() const { return 1; } + virtual UINT32 execute_max_cycles() const { return 1; } + virtual UINT32 execute_input_lines() const { return 64; } + virtual void execute_run(); + virtual void execute_set_input(int inputnum, int state); + + // device_state_interface overrides + void state_string_export(const device_state_entry &entry, astring &string); + + // device_memory_interface overrides + virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const; + + // device_disasm_interface overrides + virtual UINT32 disasm_min_opcode_bytes() const { return 2; } + virtual UINT32 disasm_max_opcode_bytes() const { return 4; } + virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options); + +private: + // helpers + bool check_condition_branch(UINT8 bc); + bool check_condition(UINT8 bc); + INT32 sign_extend(UINT32 data, UINT8 len); + UINT32 fetch(); + UINT8 read_byte(offs_t offset); + UINT16 read_word(offs_t offset); + UINT32 read_dword(offs_t offset); + void write_byte(offs_t offset, UINT8 data); + void write_word(offs_t offset, UINT16 data); + void write_dword(offs_t offset, UINT32 data); + void check_irq(); + void gen_exception(int cause, UINT32 param = 0); + + offs_t disasm(char *buffer, offs_t pc, UINT32 opcode); + char *disasm32(char *buffer, offs_t pc, UINT32 opcode); + char *disasm16(char *buffer, offs_t pc, UINT16 opcode); + void unemulated_op(const char * op); + + // 32-bit opcodes + void op_specialform(); + void op_iform1(); + void op_jump(); + void op_rixform1(); + void op_branch(); + void op_iform2(); + void op_crform(); + void op_rixform2(); + void op_addri(); + void op_andri(); + void op_orri(); + void op_lw(); + void op_lh(); + void op_lhu(); + void op_lb(); + void op_sw(); + void op_sh(); + void op_lbu(); + void op_sb(); + void op_cache(); + void op_cenew(); + void op_undef(); + + // 16-bit opcodes + void op_rform1(); + void op_rform2(); + void op_jform(); + void op_branch16(); + void op_ldiu(); + void op_iform1a(); + void op_iform1b(); + +private: + address_space_config m_program_config; + address_space * m_program; + direct_read_data * m_direct; + + // internal state + int m_icount; + UINT32 m_pc; + UINT32 m_ppc; + UINT32 m_op; + UINT32 m_gpr[0x20]; + UINT32 m_cr[0x20]; + UINT32 m_sr[3]; + UINT32 m_ce[2]; + bool m_pending_interrupt[64]; + + // opcodes tables + typedef void (score7_cpu_device::*op_handler)(); + static const op_handler s_opcode32_table[4*8]; + static const op_handler s_opcode16_table[8]; + + // mnemonics + static const char *const m_cond[16]; + static const char *const m_tcs[4]; + static const char *const m_rix1_op[8]; + static const char *const m_rix2_op[8]; + static const char *const m_r2_op[16]; + static const char *const m_i1_op[8]; + static const char *const m_i2_op[8]; + static const char *const m_ls_op[8]; + static const char *const m_i1a_op[8]; + static const char *const m_i1b_op[8]; + static const char *const m_cr_op[2]; +}; + +extern const device_type SCORE7; + +#endif /* __SCORE_H__ */ diff --git a/src/emu/cpu/score/scoredsm.c b/src/emu/cpu/score/scoredsm.c new file mode 100644 index 00000000000..f4998d657a0 --- /dev/null +++ b/src/emu/cpu/score/scoredsm.c @@ -0,0 +1,292 @@ +/****************************************************************************** + + Sunplus Technology S+core disassembler + +******************************************************************************/ + +#include "emu.h" +#include "score.h" +#include "scorem.h" + +const char *const score7_cpu_device::m_cond[16] = { "cs", "cc", "gtu", "leu", "eq", "ne", "gt", "le", "ge", "lt", "mi", "pl", "vs", "vc", "cnz", "" }; +const char *const score7_cpu_device::m_tcs[4] = { "teq", "tmi", "", ""}; +const char *const score7_cpu_device::m_rix1_op[8] = { "lw" ,"lh" ,"lhu" ,"lb" ,"sw" ,"sh" ,"lbu" ,"sb" }; +const char *const score7_cpu_device::m_rix2_op[8] = { "lw", "lh", "lhu", "lb", "sw", "sh", "lbu", "sb" }; +const char *const score7_cpu_device::m_r2_op[16] = { "add", "sub", "neg", "cmp", "and", "or", "not", "xor", "lw", "lh", "pop", "lbu", "sw", "sh", "push", "sb" }; +const char *const score7_cpu_device::m_i1_op[8] = { "addi", "", "cmpi", "", "andi", "ori", "ldi", "" }; +const char *const score7_cpu_device::m_i2_op[8] = { "addis", "", "cmpis", "", "andis", "oris", "ldis", "" }; +const char *const score7_cpu_device::m_ls_op[8] = { "lw", "lh", "lhu", "lb", "sw", "sh", "lbu", "sb" }; +const char *const score7_cpu_device::m_i1a_op[8] = { "addei", "slli", "sdbbp", "srli", "bitclr", "bitset", "bittst", "" }; +const char *const score7_cpu_device::m_i1b_op[8] = { "lwp", "lhp", "", "lbup", "swp", "shp", "", "sbp" }; +const char *const score7_cpu_device::m_cr_op[2] = { "mtcr", "mfcr" }; + + +char *score7_cpu_device::disasm32(char *buffer, offs_t pc, UINT32 opcode) +{ + switch((opcode >> 25) & 0x1f) + { + case 0x00: // Special-form + { + UINT8 ra = GET_S_RA(opcode); + UINT8 rb = GET_S_RB(opcode); + UINT8 rd = GET_S_RD(opcode); + const char *cu = GET_S_CU(opcode) ? ".c": ""; + const char *lk = GET_S_LK(opcode) ? "l": ""; + + switch(GET_S_FUNC6(opcode)) + { + case 0x00: buffer += sprintf(buffer, "nop"); break; + case 0x01: buffer += sprintf(buffer, "syscall 0x%04x", (rd<<10) | (ra << 5) | rb); break; + case 0x02: buffer += sprintf(buffer, "trap%s 0x%02x", m_cond[rb & 0x0f], ra); break; + case 0x03: buffer += sprintf(buffer, "sdbbp 0x%02x", ra); break; + case 0x04: buffer += sprintf(buffer, "br%s%s r%d", m_cond[rb & 0x0f], lk, ra); break; + case 0x05: buffer += sprintf(buffer, "pflush"); break; + case 0x08: buffer += sprintf(buffer, "add%s r%d, r%d, r%d", cu, rd, ra, rb); break; + case 0x09: buffer += sprintf(buffer, "addc%s r%d, r%d, r%d", cu, rd, ra, rb); break; + case 0x0a: buffer += sprintf(buffer, "sub%s r%d, r%d, r%d", cu, rd, ra, rb); break; + case 0x0b: buffer += sprintf(buffer, "subc%s r%d, r%d, r%d", cu, rd, ra, rb); break; + case 0x0c: buffer += sprintf(buffer, "cmp%s%s r%d, r%d", m_tcs[rd & 3], cu, ra, rb); break; + case 0x0d: buffer += sprintf(buffer, "cmpz%s%s r%d, r%d", m_tcs[rd & 3], cu, ra, rb); break; + case 0x0f: buffer += sprintf(buffer, "neg%s r%d, r%d", cu, rd, rb); break; + case 0x10: buffer += sprintf(buffer, "and%s r%d, r%d, r%d", cu, rd, ra, rb); break; + case 0x11: buffer += sprintf(buffer, "or%s r%d, r%d, r%d", cu, rd, ra, rb); break; + case 0x12: buffer += sprintf(buffer, "not%s r%d, r%d", cu, rd, ra); break; + case 0x13: buffer += sprintf(buffer, "xor%s r%d, r%d, r%d", cu, rd, ra, rb); break; + case 0x14: buffer += sprintf(buffer, "bitclr%s r%d, %d", cu, ra, rb); break; + case 0x15: buffer += sprintf(buffer, "bitset%s r%d, %d", cu, ra, rb); break; + case 0x16: buffer += sprintf(buffer, "bittst%s r%d, %d", cu, ra, rb); break; + case 0x17: buffer += sprintf(buffer, "bittgl%s r%d, %d", cu, ra, rb); break; + case 0x18: buffer += sprintf(buffer, "sll%s r%d, r%d, r%d", cu, rd, ra, rb); break; + case 0x1a: buffer += sprintf(buffer, "srl%s r%d, r%d, r%d", cu, rd, ra, rb); break; + case 0x1b: buffer += sprintf(buffer, "sra%s r%d, r%d, r%d", cu, rd, ra, rb); break; + case 0x1c: buffer += sprintf(buffer, "ror%s r%d, r%d, r%d", cu, rd, ra, rb); break; + case 0x1d: buffer += sprintf(buffer, "rorc%s r%d, r%d, r%d", cu, rd, ra, rb); break; + case 0x1e: buffer += sprintf(buffer, "rol%s r%d, r%d, r%d", cu, rd, ra, rb); break; + case 0x1f: buffer += sprintf(buffer, "rolc%s r%d, r%d, r%d", cu, rd, ra, rb); break; + case 0x20: buffer += sprintf(buffer, "mul r%d, r%d", ra, rb); break; + case 0x21: buffer += sprintf(buffer, "mulu r%d, r%d", ra, rb); break; + case 0x22: buffer += sprintf(buffer, "div r%d, r%d", ra, rb); break; + case 0x23: buffer += sprintf(buffer, "divu r%d, r%d", ra, rb); break; + case 0x24: + buffer += sprintf(buffer, "mfce%s%s r%d", rb & 2 ? "h" : "", rb & 1 ? "l" : "", rd); + if ((rb & 3) == 3) buffer += sprintf(buffer, ", r%d", ra); + break; + case 0x25: + buffer += sprintf(buffer, "mtce%s%s r%d", rb & 2 ? "h" : "", rb & 1 ? "l" : "", rd); + if ((rb & 3) == 3) buffer += sprintf(buffer, ", r%d", ra); + break; + case 0x28: buffer += sprintf(buffer, "mfsr sr%d, r%d", rb, ra); break; + case 0x29: buffer += sprintf(buffer, "mtsr r%d, sr%d", ra, rb); break; + case 0x2a: buffer += sprintf(buffer, "t%s r%d", m_cond[rb & 0x0f], rb); break; + case 0x2b: buffer += sprintf(buffer, "mv%s r%d, r%d", m_cond[rb & 0x0f], rd, ra); break; + case 0x2c: buffer += sprintf(buffer, "extsb%s r%d, r%d", cu, rd, ra); break; + case 0x2d: buffer += sprintf(buffer, "extsh%s r%d, r%d", cu, rd, ra); break; + case 0x2e: buffer += sprintf(buffer, "extzb%s r%d, r%d", cu, rd, ra); break; + case 0x2f: buffer += sprintf(buffer, "extzh%s r%d, r%d", cu, rd, ra); break; + case 0x30: buffer += sprintf(buffer, "lcb [r%d]+", ra); break; + case 0x31: buffer += sprintf(buffer, "lcw r%d, [r%d]+", rd, ra); break; + case 0x33: buffer += sprintf(buffer, "lce r%d, [r%d]+", rd, ra); break; + case 0x34: buffer += sprintf(buffer, "scb r%d, [r%d]+", rd, ra); break; + case 0x35: buffer += sprintf(buffer, "scw r%d, [r%d]+", rd, ra); break; + case 0x37: buffer += sprintf(buffer, "sce [r%d]+", ra); break; + case 0x38: buffer += sprintf(buffer, "slli r%d, r%d, %d", rd, ra, rb); break; + case 0x3a: buffer += sprintf(buffer, "srli r%d, r%d, %d", rd, ra, rb); break; + case 0x3b: buffer += sprintf(buffer, "srai r%d, r%d, %d", rd, ra, rb); break; + case 0x3c: buffer += sprintf(buffer, "rori%s r%d, r%d, %d", cu, rd, ra, rb); break; + case 0x3d: buffer += sprintf(buffer, "roric%s r%d, r%d, %d", cu, rd, ra, rb); break; + case 0x3e: buffer += sprintf(buffer, "roli%s r%d, r%d, %d", cu, rd, ra, rb); break; + case 0x3f: buffer += sprintf(buffer, "rolic%s r%d, r%d, %d", cu, rd, ra, rb); break; + default: buffer += sprintf(buffer, "", GET_S_FUNC6(opcode)); + } + break; + } + case 0x01: // I-form-1 + switch(GET_I_FUNC3(opcode)) + { + case 0x00: + buffer += sprintf(buffer, "%s%s r%d, %d", m_i1_op[GET_I_FUNC3(opcode)], GET_I_CU(opcode) ? ".c": "", GET_I_RD(opcode), sign_extend(GET_I_IMM16(opcode), 16)); + break; + case 0x02: case 0x04: case 0x05: case 0x06: + buffer += sprintf(buffer, "%s%s r%d, 0x%04x", m_i1_op[GET_I_FUNC3(opcode)], GET_I_CU(opcode) ? ".c": "", GET_I_RD(opcode), GET_I_IMM16(opcode)); + break; + default: + buffer += sprintf(buffer, "", GET_I_FUNC3(opcode)); + } + break; + case 0x02: + buffer += sprintf(buffer, "j%s 0x%08x", GET_J_LK(opcode) ? "l": "", (pc & 0xfc000000) | (GET_J_DISP24(opcode) << 1)); + break; + case 0x03: // RIX-form-1 + buffer += sprintf(buffer, "%s r%d, [R%d, %d]+", m_rix1_op[GET_RIX_FUNC3(opcode)], GET_RIX_RD(opcode), GET_RIX_RA(opcode), sign_extend(GET_RIX_IMM12(opcode), 12)); + break; + case 0x04: + buffer += sprintf(buffer, "b%s%s 0x%08x", m_cond[GET_BC_BC(opcode) & 0x0f], GET_BC_LK(opcode) ? "l": "", pc + (sign_extend(GET_BC_DISP19(opcode), 19) << 1)); + break; + case 0x05: // I-form-2 + switch(GET_I_FUNC3(opcode)) + { + case 0x00: case 0x02: + case 0x04: case 0x05: case 0x06: + buffer += sprintf(buffer, "%s%s r%d, 0x%04x", m_i2_op[GET_I_FUNC3(opcode)], GET_I_CU(opcode) ? ".c": "", GET_I_RD(opcode), GET_I_IMM16(opcode)); + break; + default: + buffer += sprintf(buffer, "", GET_I_FUNC3(opcode)); + } + break; + case 0x06: // CR-form + switch(GET_CR_OP(opcode)) + { + case 0x00: case 0x01: + buffer += sprintf(buffer, "%s r%d, cr%d", m_cr_op[GET_CR_OP(opcode)], GET_CR_RD(opcode), GET_CR_CR(opcode)); + break; + case 0x84: + buffer += sprintf(buffer, "rte"); + break; + default: + if ((GET_CR_OP(opcode) & 0xc0) == 0) + buffer += sprintf(buffer, "", GET_CR_OP(opcode) & 0x07); + else + buffer += sprintf(buffer, "", GET_S_FUNC6(opcode)); + } + break; + case 0x07: // RIX-form-2 + buffer += sprintf(buffer, "%s r%d, [R%d]+, %d", m_rix2_op[GET_RIX_FUNC3(opcode)], GET_RIX_RD(opcode), GET_RIX_RA(opcode), sign_extend(GET_RIX_IMM12(opcode), 12)); + break; + case 0x08: + buffer += sprintf(buffer, "addri%s r%d, r%d, %d", GET_RI_CU(opcode) ? ".c": "", GET_RI_RD(opcode), GET_RI_RA(opcode), sign_extend(GET_RI_IMM14(opcode), 14)); + break; + case 0x0c: + buffer += sprintf(buffer, "andri%s r%d, r%d, 0x%04x", GET_RI_CU(opcode) ? ".c": "", GET_RI_RD(opcode), GET_RI_RA(opcode), GET_RI_IMM14(opcode)); + break; + case 0x0d: + buffer += sprintf(buffer, "orri%s r%d, r%d, 0x%04x", GET_RI_CU(opcode) ? ".c": "", GET_RI_RD(opcode), GET_RI_RA(opcode), GET_RI_IMM14(opcode)); + break; + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x14: case 0x15: case 0x16: case 0x17: + buffer += sprintf(buffer, "%s r%d, [r%d, %d]", m_ls_op[(opcode >> 25) & 0x07], GET_LS_RD(opcode), GET_LS_RA(opcode), sign_extend(GET_LS_IMM15(opcode), 15)); + break; + case 0x18: + buffer += sprintf(buffer, "cache 0x%02x, [r%d, %d]", GET_LS_RD(opcode), GET_LS_RA(opcode), sign_extend(GET_LS_IMM15(opcode), 15)); + break; + case 0x1c: + sprintf(buffer,"", opcode); + break; + default: + buffer += sprintf(buffer, "", opcode); + } + + return buffer; +} + +char *score7_cpu_device::disasm16(char *buffer, offs_t pc, UINT16 opcode) +{ + switch((opcode >> 12) & 0x07) + { + case 0x00: // R-form-1 + { + UINT8 rd = GET_R_RD(opcode); + UINT8 ra = GET_R_RA(opcode); + + switch(GET_R_FUNC4(opcode)) + { + case 0x00: buffer += sprintf(buffer, "nop!"); break; + case 0x01: buffer += sprintf(buffer, "mlfh! r%d, r%d", rd, 0x10 + ra); break; + case 0x02: buffer += sprintf(buffer, "mhfl! r%d, r%d", 0x10 + rd, ra); break; + case 0x03: buffer += sprintf(buffer, "mv! r%d, r%d", rd, ra); break; + case 0x04: buffer += sprintf(buffer, "br%s! r%d", m_cond[rd & 0x0f], ra); break; + case 0x05: buffer += sprintf(buffer, "t%s!", m_cond[rd & 0x0f]); break; + case 0x08: buffer += sprintf(buffer, "sll! r%d, r%d", rd, ra); break; + case 0x09: buffer += sprintf(buffer, "addc! r%d, r%d", rd, ra); break; + case 0x0a: buffer += sprintf(buffer, "srl! r%d, r%d", rd, ra); break; + case 0x0b: buffer += sprintf(buffer, "sra! r%d, r%d", rd, ra); break; + case 0x0c: buffer += sprintf(buffer, "br%sl! r%d", m_cond[rd & 0x0f], ra); break; + default: buffer += sprintf(buffer, "", GET_R_FUNC4(opcode)); + } + break; + } + case 0x02: // R-form-2 + switch(GET_R_FUNC4(opcode)) + { + case 0: case 1: case 2: case 3: + case 4: case 5: case 6: case 7: + buffer += sprintf(buffer, "%s! r%d, r%d", m_r2_op[GET_R_FUNC4(opcode)], GET_R_RD(opcode), GET_R_RA(opcode)); + break; + case 0x0a: case 0x0e: + buffer += sprintf(buffer, "%s! r%d, [r%d]", m_r2_op[GET_R_FUNC4(opcode)], GET_P_RDG(opcode), GET_P_RAG(opcode)); + break; + default: + buffer += sprintf(buffer, "%s! r%d, [r%d]", m_r2_op[GET_R_FUNC4(opcode)], GET_R_RD(opcode), GET_R_RA(opcode)); + } + break; + case 0x03: + buffer += sprintf(buffer, "j%s! 0x%08x", GET_J_LK(opcode) ? "l": "", (pc & 0xfffff000) | (GET_J_DISP11(opcode) << 1)); + break; + case 0x04: + buffer += sprintf(buffer, "b%s! 0x%08x", m_cond[GET_BX_EC(opcode) & 0x0f], pc + sign_extend(GET_BX_DISP8(opcode) << 1, 9)); + break; + case 0x05: + buffer += sprintf(buffer, "ldiu! r%d, 0x%02x", GET_I2_RD(opcode), GET_I2_IMM8(opcode)); + break; + case 0x06: // I-form-1a + if (GET_I16_FUNC3(opcode) != 7) + buffer += sprintf(buffer, "%s! r%d, %d", m_i1a_op[GET_I16_FUNC3(opcode)], GET_I16_RD(opcode), GET_I16_IMM5(opcode)); + else + buffer += sprintf(buffer, "", GET_I16_FUNC3(opcode)); + break; + case 0x07: // I-form-1b + switch(GET_I16_FUNC3(opcode)) + { + case 0: case 4: + buffer += sprintf(buffer, "%s! r%d, %d", m_i1b_op[GET_I16_FUNC3(opcode)], GET_I16_RD(opcode), GET_I16_IMM5(opcode)<<2); + break; + case 1: case 5: + buffer += sprintf(buffer, "%s! r%d, %d", m_i1b_op[GET_I16_FUNC3(opcode)], GET_I16_RD(opcode), GET_I16_IMM5(opcode)<<1); + break; + case 3: case 7: + buffer += sprintf(buffer, "%s! r%d, %d", m_i1b_op[GET_I16_FUNC3(opcode)], GET_I16_RD(opcode), GET_I16_IMM5(opcode)); + break; + default: + buffer += sprintf(buffer, "", GET_I16_FUNC3(opcode)); + } + break; + } + + return buffer; +} + +offs_t score7_cpu_device::disasm(char *buffer, offs_t pc, UINT32 opcode) +{ + UINT8 p = (pc & 0x02) ? 0 : (((opcode>>30) & 2) | ((opcode>>15) & 1)); + + switch(p) + { + case 0: // 16-bit + 16-bit instruction + buffer = disasm16(buffer, pc, opcode & 0x7fff); + break; + case 1: // undefined + buffer += sprintf(buffer,"", opcode); + break; + case 2: // parallel conditional execution + buffer = disasm16(buffer, pc, opcode & 0x7fff); + buffer += sprintf(buffer, " ||"); + break; + case 3: // 32-bit instruction + buffer = disasm32(buffer, pc, (opcode & 0x7fff) | ((opcode >> 1) & 0x3fff8000)); + break; + } + + return (p & 0x01) ? 4 : 2; +} + + +//------------------------------------------------- +// disasm_disassemble - call the disassembly +// helper function +//------------------------------------------------- + +offs_t score7_cpu_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) +{ + UINT32 opcode = oprom[0] | (oprom[1] << 8) | (oprom[2] << 16) | (oprom[3] << 24); + + return disasm(buffer, pc, opcode); +} diff --git a/src/emu/cpu/score/scorem.h b/src/emu/cpu/score/scorem.h new file mode 100644 index 00000000000..161d991a44c --- /dev/null +++ b/src/emu/cpu/score/scorem.h @@ -0,0 +1,144 @@ + +// Special-form +#define GET_S_FUNC6(op) ((op >> 1) & 0x3f) +#define GET_S_RB(op) ((op >> 10) & 0x1f) +#define GET_S_RA(op) ((op >> 15) & 0x1f) +#define GET_S_RD(op) ((op >> 20) & 0x1f) +#define GET_S_CU(op) (op & 0x01) +#define GET_S_LK(op) (op & 0x01) + +// I-form +#define GET_I_FUNC3(op) ((op >> 17) & 0x07) +#define GET_I_IMM16(op) ((op >> 1) & 0xffff) +#define GET_I_RD(op) ((op >> 20) & 0x1f) +#define GET_I_CU(op) (op & 0x01) + +// RI-form +#define GET_RI_IMM14(op) ((op >> 1) & 0x3fff) +#define GET_RI_RA(op) ((op >> 15) & 0x1f) +#define GET_RI_RD(op) ((op >> 20) & 0x1f) +#define GET_RI_CU(op) (op & 0x01) + +// J-form +#define GET_J_DISP24(op) ((op >> 1) & 0x00ffffff) +#define GET_J_DISP11(op) ((op >> 1) & 0x000007ff) +#define GET_J_LK(op) (op & 0x01) + +// BC-form +#define GET_BC_DISP19(op) (((op >> 6) & 0x07fe00) | ((op >> 1) & 0x0001ff)) +#define GET_BC_BC(op) ((op >> 10) & 0x1f) +#define GET_BC_LK(op) (op & 0x01) + +// RIX-form +#define GET_RIX_FUNC3(op) (op & 0x07) +#define GET_RIX_IMM12(op) ((op >> 3) & 0x0fff) +#define GET_RIX_RA(op) ((op >> 15) & 0x1f) +#define GET_RIX_RD(op) ((op >> 20) & 0x1f) + +// R-form +#define GET_R_FUNC4(op) (op & 0x0f) +#define GET_R_RA(op) ((op >> 4) & 0x0f) +#define GET_R_RD(op) ((op >> 8) & 0x0f) + +// BX-form +#define GET_BX_DISP8(op) (op & 0xff) +#define GET_BX_EC(op) ((op >> 8) & 0x0f) + +// LS-form +#define GET_LS_RD(op) ((op >> 20) & 0x1f) +#define GET_LS_RA(op) ((op >> 15) & 0x1f) +#define GET_LS_IMM15(op) (op & 0x7fff) + +// I2-form +#define GET_I2_RD(op) ((op >> 8) & 0x0f) +#define GET_I2_IMM8(op) (op & 0xff) + +// I-form +#define GET_I16_FUNC3(op) (op & 0x07) +#define GET_I16_RD(op) ((op >> 8) & 0x0f) +#define GET_I16_IMM5(op) ((op >> 3) & 0x1f) + +// CR-form +#define GET_CR_OP(op) (op & 0xff) +#define GET_CR_IMM10(op) ((op >> 5) & 0x3ff) +#define GET_CR_CR(op) ((op >> 15) & 0x1f) +#define GET_CR_RD(op) ((op >> 20) & 0x1f) + +// PUSH/POP-form +#define GET_P_RAG(op) ((op >> 4) & 0x07) +#define GET_P_RDG(op) (((op >> 8) & 0x0f) | ((op >> 3) & 0x10)) + + +// flags +#define FLAG_V 0x01 +#define FLAG_C 0x02 +#define FLAG_Z 0x04 +#define FLAG_N 0x08 +#define FLAG_T 0x10 + +#define GET_V ((REG_CR & FLAG_V)>>0) +#define GET_C ((REG_CR & FLAG_C)>>1) +#define GET_Z ((REG_CR & FLAG_Z)>>2) +#define GET_N ((REG_CR & FLAG_N)>>3) +#define GET_T ((REG_CR & FLAG_T)>>4) + +#define SET_V(f) if (f) REG_CR |= FLAG_V; else REG_CR &= ~FLAG_V; +#define SET_C(f) if (f) REG_CR |= FLAG_C; else REG_CR &= ~FLAG_C; +#define SET_Z(f) if (f) REG_CR |= FLAG_Z; else REG_CR &= ~FLAG_Z; +#define SET_N(f) if (f) REG_CR |= FLAG_N; else REG_CR &= ~FLAG_N; +#define SET_T(f) if (f) REG_CR |= FLAG_T; else REG_CR &= ~FLAG_T; + +#define CHECK_Z(r) SET_Z((r)==0) +#define CHECK_N(r) SET_N((INT32)(r) < 0) +#define CHECK_C_ADD(a,b) SET_C((a) > (0xffffffffu - (b))) +#define CHECK_C_SUB(a,b) SET_C((a) >= (b)) +#define CHECK_V_ADD(a,b,d) SET_V((INT32)(((a) ^ (d)) & ((b) ^ (d))) < 0) +#define CHECK_V_SUB(a,b,d) SET_V((INT32)(((a) ^ (b)) & ((a) ^ (d))) < 0) + + +// registers +#define REG_BP m_gpr[2] +#define REG_LNK m_gpr[3] +#define REG_PSR m_cr[0] +#define REG_CR m_cr[1] +#define REG_ECR m_cr[2] +#define REG_EXCPVEC m_cr[3] +#define REG_CCR m_cr[4] +#define REG_EPC m_cr[5] +#define REG_EMA m_cr[6] +#define REG_TLBLOCK m_cr[7] +#define REG_TLBPT m_cr[8] +#define REG_PEADDR m_cr[9] +#define REG_TLBRPT m_cr[10] +#define REG_PEVN m_cr[11] +#define REG_PECTX m_cr[12] +#define REG_LIMPFN m_cr[15] +#define REG_LDMPFN m_cr[16] +#define REG_PREV m_cr[18] +#define REG_DREG m_cr[29] +#define REG_DEPC m_cr[30] +#define REG_DSAVE m_cr[31] +#define REG_CNT m_sr[0] +#define REG_LCR m_sr[1] +#define REG_SCR m_sr[2] +#define REG_CEH m_ce[0] +#define REG_CEL m_ce[1] + + +// exceptions causes +#define EXCEPTION_RESET 0 +#define EXCEPTION_NMI 1 +#define EXCEPTION_ADEL_INSTRUCTION 2 +#define EXCEPTION_BUSEL_INSTRUCTION 5 +#define EXCEPTION_P_EL 6 +#define EXCEPTION_SYSCALL 7 +#define EXCEPTION_CCU 8 +#define EXCEPTION_RI 9 +#define EXCEPTION_TRAP 10 +#define EXCEPTION_ADEL_DATA 11 +#define EXCEPTION_ADES_DATA 12 +#define EXCEPTION_CEE 16 +#define EXCEPTION_CPE 17 +#define EXCEPTION_BUSEL_DATA 18 +#define EXCEPTION_SWI 19 +#define EXCEPTION_INTERRUPT 20 diff --git a/src/mess/drivers/hyperscan.c b/src/mess/drivers/hyperscan.c new file mode 100644 index 00000000000..fe2a3412114 --- /dev/null +++ b/src/mess/drivers/hyperscan.c @@ -0,0 +1,645 @@ +/*************************************************************************** + + Mattel HyperScan + + 08/17/2013 Skeleton driver by Sandro Ronco + + SPG290 Interrupt: + + Vector Source + 63 SPU FIQ + 62 SPU Beatirq + 61 SPU Envirq + 60 CD servo + 59 ADC gain overflow / ADC recorder / FIFO overflow + 58 General purpose ADC + 57 Timer base + 56 Timer + 55 TV vblanking start + 54 LCD vblanking start + 53 PPU vblanking start + 52 TV + 51 Sensor frame end + 50 Sensor coordinate hit + 49 Sensor motion frame end + 48 Sensor capture done + sensor debug IRQ + 47 TV coordinate hit + 46 PPU coordinate hit + 45 USB host+device + 44 SIO + 43 SPI + 42 Uart (IrDA) + 41 NAND + 40 SD + 39 I2C master + 38 I2S slave + 37 APBDMA CH1 + 36 APBDMA CH2 + 35 LDM_DMA + 34 BLN_DMA + 33 APBDMA CH3 + 32 APBDMA CH4 + 31 Alarm + HMS + 30 MP4 + 29 C3 (ECC module) + 28 GPIO + 27 Bufctl (for debug) + TV/PPU vblanking end (for debug) + 26 RESERVED1 + 25 RESERVED2 + 24 RESERVED3 + +****************************************************************************/ + +#include "emu.h" +#include "cpu/score/score.h" + + +#define LOG_SPG290_REGISTER_ACCESS (1) + + + +class hyperscan_state : public driver_device +{ +public: + hyperscan_state(const machine_config &mconfig, device_type type, const char *tag) + : driver_device(mconfig, type, tag), + m_maincpu(*this, "maincpu") + { } + + required_device m_maincpu; + + virtual void machine_start(); + virtual void machine_reset(); + virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); + + UINT32 spg290_screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect); + DECLARE_READ32_MEMBER(spg290_regs_r); + DECLARE_WRITE32_MEMBER(spg290_regs_w); + void spg290_timers_update(); + void spg290_vblank_irq(screen_device &screen, bool state); + inline UINT32 spg290_read_mem(UINT32 offset); + inline void spg290_write_mem(UINT32 offset, UINT32 data); + void spg290_argb1555(bitmap_rgb32 &bitmap, const rectangle &cliprect, UINT16 posy, UINT16 posx, UINT16 argb); + void spg290_rgb565(bitmap_rgb32 &bitmap, const rectangle &cliprect, UINT16 posy, UINT16 posx, UINT16 rgb, UINT32 transrgb); + void spg290_blit_sprite(bitmap_rgb32 &bitmap, const rectangle &cliprect, UINT32 control, UINT32 attribute, UINT32 *palettes, UINT32 buf_start); + void spg290_blit_bitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect, UINT32 control, UINT32 attribute, int posy, int posx, UINT32 nptr, UINT32 buf_start, UINT32 transrgb); + void spg290_blit_character(bitmap_rgb32 &bitmap, const rectangle &cliprect, UINT32 control, UINT32 attribute, int posy, int posx, UINT32 nptr, UINT32 buf_start, UINT32 transrgb); + +private: + static const device_timer_id TIMER_SPG290 = 0; + static const device_timer_id TIMER_I2C = 1; + + struct spg290_miu + { + UINT32 status; + }; + + struct spg290_ppu + { + UINT32 control; + UINT32 irq_control; + UINT32 irq_status; + UINT32 sprite_max; + UINT32 sprite_buf_start; + UINT32 frame_buff[3]; + UINT32 palettes[0x200]; + UINT32 tx_hoffset[0x200]; + UINT32 tx_hcomp[0x200]; + UINT32 transrgb; + + struct ppu_spite + { + UINT32 control; + UINT32 attribute; + } sprites[0x200]; + + struct ppu_tx + { + UINT32 control; + UINT32 attribute; + UINT32 posx; + UINT32 posy; + UINT32 nptr; + UINT32 buf_start[3]; + } txs[3]; + }; + + struct spg290_timer + { + UINT32 control; + UINT32 control2; + UINT16 preload; + UINT16 counter; + }; + + struct spg290_i2c + { + UINT32 config; + UINT32 irq_control; + UINT32 clock; + UINT8 count; + UINT32 id; + UINT32 port_addr; + UINT32 wdata; + UINT32 rdata; + }; + + spg290_miu m_miu; + spg290_ppu m_ppu; + spg290_timer m_timers[6]; + spg290_i2c m_i2c; + emu_timer * m_update_timer; + emu_timer * m_i2c_timer; +}; + + + +#if LOG_SPG290_REGISTER_ACCESS +static void log_spg290_regs(UINT8 module, UINT16 reg, UINT32 mem_mask, bool write, UINT32 data=0) +{ + static const char *const modules_name[] = + { + "CSI", "PPU", "JPG", "TV", "LCD", "SPU", "CD", "MIU", "APBDMA", "BUFCTL","IRQCTL", "GPUBUF", "LDMDMA", + "BLNDMA", "TPGBUF", "AHBDEC", "GPIO", "SPI", "SIO", "I2C", "I2S", "UART", "TIMERS/RTC", "WDOG", "SD", + "FLASH", "ADC", "USB device", "USB host", "Reserved", "Reserved", "Reserved", "SFTCFG", "CKG", "MP4", + "MIU2", "ECC" + }; + + if (module < 0x25) + logerror("SPG: %-10s", modules_name[module]); + else + logerror("SPG: mod 0x%02x ", module); + + if (!write) + logerror(" R 0x%04x", reg); + else + logerror(" W 0x%04x = 0x%08x", reg, data); + + if (mem_mask != 0xffffffffu) + logerror(" (0x%08x)\n", mem_mask); + else + logerror("\n"); +} +#endif + + +READ32_MEMBER(hyperscan_state::spg290_regs_r) +{ + UINT32 addr = offset << 2; + UINT32 data = 0; + + if (addr == 0x010000) // PPU Control + { + data = m_ppu.control; + } + else if (addr == 0x010084) // PPU IRQ Status + { + data = m_ppu.irq_status; + } + if (addr == 0x07006c) // MIU Status + { + data = m_miu.status; + } + else if ((addr & 0xff0fff) == 0x160000) // Timer X Status + { + int idx = (offset>>10) & 0x0f; + data = m_timers[idx].control; + } + else if(addr == 0x130024) // I2C interrupt + { + data = m_i2c.irq_control; + } + else if(addr == 0x130034) // I2C write data + { + data = m_i2c.wdata; + } + else if(addr == 0x130038) // I2C data data + { + data = m_i2c.rdata; + } + +#if LOG_SPG290_REGISTER_ACCESS + //else + { + if (!space.debugger_access()) + log_spg290_regs((offset >> 14) & 0xff, (offset<<2) & 0xffff, mem_mask, false); + } +#endif + + return data; +} + +WRITE32_MEMBER(hyperscan_state::spg290_regs_w) +{ + UINT32 addr = offset << 2; + + if (addr == 0x010000) // PPU Control + { + COMBINE_DATA(&m_ppu.control); + } + else if (addr == 0x010008) // PPU Max Sprites + { + COMBINE_DATA(&m_ppu.sprite_max); + } + else if (addr == 0x010010) // PPU Max Sprites + { + COMBINE_DATA(&m_ppu.transrgb); + } + else if (addr == 0x0100d0) // Sprites buffer start + { + COMBINE_DATA(&m_ppu.sprite_buf_start); + } + else if (addr == 0x010020 || addr == 0x01003c || addr == 0x010058) // Text Layers x pos + { + int idx = (((offset>>3) & 3) | ((offset>>4) & 1)) - 1; + COMBINE_DATA(&m_ppu.txs[idx].posx); + } + else if (addr == 0x010024 || addr == 0x010040 || addr == 0x01005c) // Text Layers y pos + { + int idx = (((offset>>3) & 3) | ((offset>>4) & 1)) - 1; + COMBINE_DATA(&m_ppu.txs[idx].posy); + } + else if (addr == 0x010028 || addr == 0x010044 || addr == 0x010060) // Text Layers attribute + { + int idx = ((offset>>3) & 3) - 1; + COMBINE_DATA(&m_ppu.txs[idx].attribute); + } + else if (addr == 0x01002c || addr == 0x010048 || addr == 0x010064) // Text Layers control + { + int idx = ((offset>>3) & 3) - 1; + COMBINE_DATA(&m_ppu.txs[idx].control); + } + else if (addr == 0x010030 || addr == 0x01004c || addr == 0x010068) // Text Layers number ptr + { + int idx = ((offset>>3) & 3) - 1; + COMBINE_DATA(&m_ppu.txs[idx].nptr); + } + else if (addr == 0x010080) // PPU IRQ Control + { + COMBINE_DATA(&m_ppu.irq_control); + } + else if (addr == 0x010084) // PPU IRQ ack + { + if (ACCESSING_BITS_0_7) + m_ppu.irq_status &= ~data; + } + else if (addr >= 0x0100a0 && addr <= 0x0100a8) // Tx1 buffer start + { + COMBINE_DATA(&m_ppu.txs[0].buf_start[offset & 3]); + } + else if (addr >= 0x0100ac && addr <= 0x0100b4) // Tx2 buffer start + { + COMBINE_DATA(&m_ppu.txs[1].buf_start[(offset+1) & 3]); + } + else if (addr >= 0x0100b8 && addr <= 0x0100c0) // Tx3 buffer starts + { + COMBINE_DATA(&m_ppu.txs[2].buf_start[(offset+2) & 3]); + } + else if ((addr & 0xfff000) == 0x011000) // Palettes + { + COMBINE_DATA(&m_ppu.palettes[offset & 0x01ff]); + } + else if ((addr & 0xfff000) == 0x012000) // Tx horizontal offset + { + COMBINE_DATA(&m_ppu.tx_hoffset[offset & 0x01ff]); + } + else if ((addr & 0xfff000) == 0x013000) // Tx horizontal compression + { + COMBINE_DATA(&m_ppu.tx_hcomp[offset & 0x01ff]); + } + else if ((addr & 0xfff000) == 0x014000) // Sprite Control Registers + { + int idx = (offset>>1) & 0x1ff; + if (offset & 1) + COMBINE_DATA(&m_ppu.sprites[idx].attribute); + else + COMBINE_DATA(&m_ppu.sprites[idx].control); + } + else if (addr == 0x07005c) // MIU Status + { + COMBINE_DATA(&m_miu.status); + } + else if ((addr & 0xff0fff) == 0x160000) // Timer X Control 1 + { + int idx = (offset>>10) & 0x07; + COMBINE_DATA(&m_timers[idx].control); + + if (ACCESSING_BITS_24_31) + m_timers[idx].control &= ~(data & 0x04000000); // Timers IRQ ack + } + else if ((addr & 0xff0fff) == 0x160004) // Timer X Control 2 + { + int idx = (offset>>10) & 0x07; + COMBINE_DATA(&m_timers[idx].control2); + } + else if ((addr & 0xff0fff) == 0x160008) // Timer X Preload + { + int idx = (offset>>10) & 0x07; + COMBINE_DATA(&m_timers[idx].preload); + } + else if (addr == 0x2100e4) // Timer Source Clock Selection + { + UINT32 timers_clk = XTAL_27MHz / ((data & 0xff) + 1); + m_update_timer->adjust(attotime::from_hz(timers_clk), 0, attotime::from_hz(timers_clk)); + } + else if(addr == 0x130020) // I2C configuration + { + COMBINE_DATA(&m_i2c.config); + } + else if(addr == 0x130024) // I2C interrupt + { + COMBINE_DATA(&m_i2c.irq_control); + + if (ACCESSING_BITS_0_7) + m_i2c.irq_control &= ~(data & 0x00000001); // I2C IRQ ack + } + else if(addr == 0x130028) // I2C clock setting + { + COMBINE_DATA(&m_i2c.clock); + UINT32 i2c_clk = XTAL_27MHz / ((m_i2c.clock & 0x3ff) + 1); + m_i2c_timer->adjust(attotime::from_hz(i2c_clk), 0, attotime::from_hz(i2c_clk)); + } + else if(addr == 0x13002c) // I2C ID + { + COMBINE_DATA(&m_i2c.id); + } + else if(addr == 0x130030) // I2C port address + { + COMBINE_DATA(&m_i2c.port_addr); + } + else if(addr == 0x130034) // I2C write data + { + COMBINE_DATA(&m_i2c.wdata); + } + else if(addr == 0x130038) // I2C data data + { + COMBINE_DATA(&m_i2c.rdata); + } + else if(addr == 0x150000) // UART data + { + if (ACCESSING_BITS_0_7) + printf("%c", data & 0xff); + } + +#if LOG_SPG290_REGISTER_ACCESS + //else + { + if (!space.debugger_access()) + log_spg290_regs((offset >> 14) & 0xff, (offset<<2) & 0xffff, mem_mask, true, data); + } +#endif +} + +inline UINT32 hyperscan_state::spg290_read_mem(UINT32 offset) +{ + return m_maincpu->space(0).read_dword(offset); +} + +inline void hyperscan_state::spg290_write_mem(UINT32 offset, UINT32 data) +{ + return m_maincpu->space(0).write_dword(offset, data); +} + +void hyperscan_state::spg290_argb1555(bitmap_rgb32 &bitmap, const rectangle &cliprect, UINT16 posy, UINT16 posx, UINT16 argb) +{ + if (!(argb & 0x8000) && cliprect.contains(posx, posy)) + { + rgb_t color = MAKE_RGB(pal5bit(argb >> 10), pal5bit(argb >> 5), pal5bit(argb >> 0)); + bitmap.pix32(posy, posx) = color; + } +} + +void hyperscan_state::spg290_rgb565(bitmap_rgb32 &bitmap, const rectangle &cliprect, UINT16 posy, UINT16 posx, UINT16 rgb, UINT32 transrgb) +{ + if ((!(transrgb & 0x10000) || (transrgb & 0xffff) != rgb) && cliprect.contains(posx, posy)) + { + rgb_t color = MAKE_RGB(pal5bit(rgb >> 11), pal6bit(rgb >> 5), pal5bit(rgb >> 0)); + bitmap.pix32(posy, posx) = color; + } +} + +void hyperscan_state::spg290_blit_sprite(bitmap_rgb32 &bitmap, const rectangle &cliprect, UINT32 control, UINT32 attribute, UINT32 *palettes, UINT32 buf_start) +{ + UINT32 sprite_base = buf_start + ((control & 0xffff) << 8); + UINT16 sprite_x = (control >> 16) & 0x3ff; + UINT16 sprite_y = (attribute >> 16) & 0x3ff; + UINT8 sprite_hsize = 8 << ((attribute >> 4) & 0x03); + UINT8 sprite_vsize = 8 << ((attribute >> 6) & 0x03); + UINT8 bit_pixel = ((attribute & 3) + 1) << 1; + UINT8 pixel_word = 32 / bit_pixel; + UINT8 word_line = sprite_hsize / pixel_word; + UINT8 sprite_flip = (attribute >> 2) & 0x03; + + for (int y=0; y < sprite_vsize; y++) + for (int x=0; x < word_line; x++) + { + UINT32 data = spg290_read_mem(sprite_base + (y * pixel_word + x) * 4); + + for (int b=0; b < pixel_word; b++) + { + UINT16 pen = ((data >> (b * bit_pixel)) & ((1 << bit_pixel) - 1)); + UINT16 posx; + if (sprite_flip & 0x01) + posx = sprite_x + (sprite_hsize - (x * word_line + b)); + else + posx = sprite_x + x * (word_line) + b; + + UINT16 posy; + if (sprite_flip & 0x02) + posy = sprite_y + (sprite_vsize - y); + else + posy = sprite_y + y; + + spg290_argb1555(bitmap, cliprect, posy, posx, palettes[pen]); + } + } +} + +void hyperscan_state::spg290_blit_bitmap(bitmap_rgb32 &bitmap, const rectangle &cliprect, UINT32 control, UINT32 attribute, int posy, int posx, UINT32 nptr, UINT32 buf_start, UINT32 transrgb) +{ + for (int y=0; y<512; y++) + { + int line = (control & 0x04) ? 0 : y; + UINT32 tx_start = spg290_read_mem(nptr + (posy + line) * 4); + + for (int x=0; x < 1024>>1; x++) + { + UINT32 data = spg290_read_mem(buf_start + (tx_start + posx) * 2 + x * 4); + + for (int b=0; b < 2; b++) + { + UINT16 posx = x * 2 + b; + UINT16 posy = y; + UINT16 pix = (data >> (b*16)) & 0xffff; + + if (control & 0x0080) + spg290_argb1555(bitmap, cliprect, posy, posx, pix); + if (control & 0x1000) + spg290_rgb565(bitmap, cliprect, posy, posx, pix, transrgb); + } + } + } +} + +void hyperscan_state::spg290_blit_character(bitmap_rgb32 &bitmap, const rectangle &cliprect, UINT32 control, UINT32 attribute, int posy, int posx, UINT32 nptr, UINT32 buf_start, UINT32 transrgb) +{ + // TODO +} + + +UINT32 hyperscan_state::spg290_screen_update(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect) +{ + if (m_ppu.control & 0x1000) + { + for (int depth=0; depth<4; depth++) + { + // draw the bitmap/text layers + for (int l=0; l<3; l++) + if ((m_ppu.txs[l].control & 0x08) && ((m_ppu.txs[l].attribute >> 13) & 3) == depth) + { + if (m_ppu.txs[l].control & 0x01) + spg290_blit_bitmap(bitmap, cliprect, m_ppu.txs[l].control, m_ppu.txs[l].attribute, m_ppu.txs[l].posy & 0x1ff, m_ppu.txs[l].posx & 0x1ff, m_ppu.txs[l].nptr, m_ppu.txs[l].buf_start[0], m_ppu.transrgb); + else + spg290_blit_character(bitmap, cliprect, m_ppu.txs[l].control, m_ppu.txs[l].attribute, m_ppu.txs[l].posy & 0x1ff, m_ppu.txs[l].posx & 0x1ff, m_ppu.txs[l].nptr, m_ppu.txs[l].buf_start[0], m_ppu.transrgb); + } + + // draw the sprites + for (int i=0; i<=(m_ppu.sprite_max & 0x1ff); i++) + { + if (((m_ppu.sprites[i].attribute >> 13) & 3) == depth) + spg290_blit_sprite(bitmap, cliprect, m_ppu.sprites[i].control, m_ppu.sprites[i].attribute, m_ppu.palettes, m_ppu.sprite_buf_start); + } + } + } + else + { + bitmap.fill(RGB_BLACK, cliprect); + } + + return 0; +} + +void hyperscan_state::spg290_timers_update() +{ + for(int i=0; i<6; i++) + if (m_timers[i].control & 0x80000000) + { + if (((m_timers[i].control2 >> 30) & 0x03) == 0x00) + { + if (m_timers[i].counter == 0xffff) + { + m_timers[i].counter = m_timers[i].preload; + if (m_timers[i].control & 0x08000000) + { + m_timers[i].control |= 0x04000000; + m_maincpu->set_input_line_and_vector(0, HOLD_LINE, 56); + } + } + else + m_timers[i].counter++; + } + else + { + // TODO: capture, comparison and PWM mode + + } + } +} + +void hyperscan_state::spg290_vblank_irq(screen_device &screen, bool state) +{ + if (state && m_ppu.irq_control & 0x01) // VBlanking Start IRQ + { + m_ppu.irq_status |= 0x01; + m_maincpu->set_input_line_and_vector(0, HOLD_LINE, 53); + } + else if (!state && m_ppu.irq_control & 0x02) // VBlanking End IRQ + { + m_ppu.irq_status |= 0x02; + m_maincpu->set_input_line_and_vector(0, HOLD_LINE, 53); + } +} + + +void hyperscan_state::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) +{ + switch (id) + { + case TIMER_SPG290: + spg290_timers_update(); + break; + case TIMER_I2C: + if ((m_i2c.config & 0x40) && (m_i2c.config & 0x01)) + { + // TODO: replace with real I2C emulation + m_i2c.rdata = 0; + + m_maincpu->set_input_line_and_vector(0, HOLD_LINE, 39); + } + break; + } +} + +static ADDRESS_MAP_START(spg290_mem, AS_PROGRAM, 32, hyperscan_state) + ADDRESS_MAP_GLOBAL_MASK(0x1fffffff) + AM_RANGE(0x00000000, 0x00ffffff) AM_RAM AM_MIRROR(0x07000000) + AM_RANGE(0x08000000, 0x09ffffff) AM_READWRITE(spg290_regs_r, spg290_regs_w) + AM_RANGE(0x0a000000, 0x0a003fff) AM_RAM // internal SRAM + AM_RANGE(0x0b000000, 0x0b007fff) AM_ROM AM_REGION("spg290", 0) // internal ROM + AM_RANGE(0x1e000000, 0x1e0fffff) AM_ROM AM_REGION("bios", 0) AM_MIRROR(0x0e000000) + AM_RANGE(0x1f000000, 0x1f0fffff) AM_ROM AM_REGION("bios", 0) AM_MIRROR(0x0e000000) +ADDRESS_MAP_END + +/* Input ports */ +static INPUT_PORTS_START( hyperscan ) +INPUT_PORTS_END + + +void hyperscan_state::machine_start() +{ + m_update_timer = timer_alloc(TIMER_SPG290); + m_i2c_timer = timer_alloc(TIMER_I2C); +} + +void hyperscan_state::machine_reset() +{ + memset(&m_ppu, 0, sizeof(spg290_ppu)); + memset(&m_miu, 0, sizeof(spg290_miu)); + memset(&m_i2c, 0, sizeof(m_i2c)); + m_i2c_timer->adjust(attotime::never, 0, attotime::never); + + // disable JTAG + m_maincpu->set_state_int(SCORE_CR + 29, 0x20000000); +} + + +static MACHINE_CONFIG_START( hyperscan, hyperscan_state ) + /* basic machine hardware */ + MCFG_CPU_ADD("maincpu", SCORE7, XTAL_27MHz * 4) // 108MHz S+core 7 + MCFG_CPU_PROGRAM_MAP(spg290_mem) + + /* video hardware */ + MCFG_SCREEN_ADD("screen", RASTER) + MCFG_SCREEN_REFRESH_RATE(50) + MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500)) /* not accurate */ + MCFG_SCREEN_UPDATE_DRIVER(hyperscan_state, spg290_screen_update) + MCFG_SCREEN_SIZE(640, 480) + MCFG_SCREEN_VISIBLE_AREA(0, 640-1, 0, 480-1) + MCFG_SCREEN_VBLANK_DRIVER(hyperscan_state, spg290_vblank_irq) +MACHINE_CONFIG_END + + +/* ROM definition */ +ROM_START( hs ) + ROM_REGION( 0x100000, "bios", ROMREGION_32BIT | ROMREGION_LE ) + ROM_LOAD32_DWORD("hyperscan.bin", 0x000000, 0x100000, CRC(ce346a14) SHA1(560cb747e7193e6781d4b8b0bd4d7b45d3d28690)) + + ROM_REGION( 0x008000, "spg290", ROMREGION_32BIT | ROMREGION_LE ) + ROM_LOAD32_DWORD("spg290.bin", 0x000000, 0x008000, NO_DUMP) // 256Kbit SPG290 internal ROM +ROM_END + + +/* Driver */ + +/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS */ +COMP( 2006, hs, 0, 0, hyperscan , hyperscan , driver_device, 0, "Mattel", "HyperScan", GAME_NOT_WORKING | GAME_NO_SOUND) diff --git a/src/mess/mess.lst b/src/mess/mess.lst index 9ee798971aa..a44ef486501 100644 --- a/src/mess/mess.lst +++ b/src/mess/mess.lst @@ -1421,6 +1421,7 @@ intvecs // 1983 - Mattel Intellivision ECS aquarius // 1983 Aquarius // aquariu2 // 1984 Aquarius II juicebox +hs // Exidy, Inc. sorcerer // Sorcerer diff --git a/src/mess/mess.mak b/src/mess/mess.mak index 3b958dfada9..3f40d90775b 100644 --- a/src/mess/mess.mak +++ b/src/mess/mess.mak @@ -125,6 +125,7 @@ CPUS += PPS4 CPUS += UPD7725 CPUS += HD61700 CPUS += LC8670 +CPUS += SCORE CPUS += ES5510 CPUS += SCUDSP CPUS += IE15 @@ -1581,6 +1582,7 @@ $(MESSOBJ)/mattel.a: \ $(MESS_VIDEO)/aquarius.o \ $(MESS_DRIVERS)/juicebox.o \ $(MESS_MACHINE)/s3c44b0.o \ + $(MESS_DRIVERS)/hyperscan.o \ $(MESSOBJ)/matsushi.a: \ $(MESS_DRIVERS)/jr100.o \