mirror of
https://github.com/holub/mame
synced 2025-04-24 09:20:02 +03:00
Added Signetics 8X300 microcontroller core, updated Wicat driver to use
it. [Barry Rodewald]
This commit is contained in:
parent
b867663d4c
commit
fa26a13b8a
3
.gitattributes
vendored
3
.gitattributes
vendored
@ -919,6 +919,9 @@ src/emu/clifront.c svneol=native#text/plain
|
||||
src/emu/clifront.h svneol=native#text/plain
|
||||
src/emu/config.c svneol=native#text/plain
|
||||
src/emu/config.h svneol=native#text/plain
|
||||
src/emu/cpu/8x300/8x300.c svneol=native#text/plain
|
||||
src/emu/cpu/8x300/8x300.h svneol=native#text/plain
|
||||
src/emu/cpu/8x300/8x300dasm.c svneol=native#text/plain
|
||||
src/emu/cpu/adsp2100/2100dasm.c svneol=native#text/plain
|
||||
src/emu/cpu/adsp2100/2100ops.c svneol=native#text/plain
|
||||
src/emu/cpu/adsp2100/adsp2100.c svneol=native#text/plain
|
||||
|
553
src/emu/cpu/8x300/8x300.c
Normal file
553
src/emu/cpu/8x300/8x300.c
Normal file
@ -0,0 +1,553 @@
|
||||
/*
|
||||
* 8x300.c
|
||||
*
|
||||
* Implementation of the Scientific Micro Systems SMS300 / Signetics 8X300 CPU
|
||||
* Created on: 18/12/2013
|
||||
*
|
||||
* Written by Barry Rodewald
|
||||
*/
|
||||
|
||||
#include "debugger.h"
|
||||
#include "8x300.h"
|
||||
|
||||
#define FETCHOP(a) (m_direct->read_decrypted_word(a))
|
||||
#define CYCLES(x) do { m_icount -= (x); } while (0)
|
||||
#define READPORT(a) (m_io->read_byte(a))
|
||||
#define WRITEPORT(a,v) (m_io->write_byte((a), (v)))
|
||||
|
||||
#define SRC ((opcode & 0x1f00) >> 8)
|
||||
#define DST (opcode & 0x001f)
|
||||
#define ROTLEN ((opcode & 0x00e0) >> 5)
|
||||
#define IMM8 (opcode & 0x00ff)
|
||||
#define IMM5 (opcode & 0x001f)
|
||||
#define ADDR (opcode & 0x1fff)
|
||||
#define OP ((opcode & 0xe000) >> 13)
|
||||
#define SRC_IS_RIGHT_BANK (opcode & 0x0800)
|
||||
#define DST_IS_RIGHT_BANK (opcode & 0x0008)
|
||||
#define SRC_LSB ((opcode & 0x0700) >> 8)
|
||||
#define DST_LSB (opcode & 0x0007)
|
||||
#define SET_PC(x) do { m_PC = (x); m_AR = m_PC; m_genPC = m_PC << 1; } while (0)
|
||||
// for XEC intruction, which sets the AR, but not PC, so that after the instruction at the relative address is done, execution
|
||||
// returns back to next instruction after XEC, unless a JMP or successful NZT is there.
|
||||
#define SET_AR(x) do { m_AR = (x); m_genPC = m_AR << 1; m_PC--;} while (0)
|
||||
#define SRC_LATCH do { if(SRC_IS_RIGHT_BANK) m_right_IV = READPORT(m_IVR+0x100); else m_left_IV = READPORT(m_IVL); } while (0)
|
||||
#define DST_LATCH do { if(DST_IS_RIGHT_BANK) m_right_IV = READPORT(m_IVR+0x100); else m_left_IV = READPORT(m_IVL); } while (0)
|
||||
#define SET_OVF do { if(result & 0xff00) m_OVF = 1; else m_OVF = 0; } while (0)
|
||||
|
||||
const device_type N8X300 = &device_creator<n8x300_cpu_device>;
|
||||
|
||||
|
||||
n8x300_cpu_device::n8x300_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: cpu_device(mconfig, N8X300, "Signetics 8X300", tag, owner, clock, "8x300", __FILE__)
|
||||
, m_program_config("program", ENDIANNESS_BIG, 16, 14, 0)
|
||||
, m_io_config("io", ENDIANNESS_BIG, 8, 9, 0)
|
||||
{
|
||||
}
|
||||
|
||||
void n8x300_cpu_device::set_reg(UINT8 reg, UINT8 val)
|
||||
{
|
||||
switch(reg)
|
||||
{
|
||||
case 0x00: m_AUX = val; break;
|
||||
case 0x01: m_R1 = val; break;
|
||||
case 0x02: m_R2 = val; break;
|
||||
case 0x03: m_R3 = val; break;
|
||||
case 0x04: m_R4 = val; break;
|
||||
case 0x05: m_R5 = val; break;
|
||||
case 0x06: m_R6 = val; break;
|
||||
case 0x07: m_IVL = val; break;
|
||||
// OVF is read-only
|
||||
case 0x09: m_R11 = val; break;
|
||||
case 0x0f: m_IVR = val; break;
|
||||
default: logerror("8X300: Invalid register %02x written to.\n",reg); break;
|
||||
}
|
||||
}
|
||||
|
||||
UINT8 n8x300_cpu_device::get_reg(UINT8 reg)
|
||||
{
|
||||
switch(reg)
|
||||
{
|
||||
case 0x00: return m_AUX;
|
||||
case 0x01: return m_R1;
|
||||
case 0x02: return m_R2;
|
||||
case 0x03: return m_R3;
|
||||
case 0x04: return m_R4;
|
||||
case 0x05: return m_R5;
|
||||
case 0x06: return m_R6;
|
||||
// IVL is write-only
|
||||
case 0x08: return m_OVF;
|
||||
case 0x09: return m_R11;
|
||||
// IVR is write-only
|
||||
default: logerror("8X300: Invalid register %02x read.\n",reg); return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void n8x300_cpu_device::device_start()
|
||||
{
|
||||
m_program = &space(AS_PROGRAM);
|
||||
m_direct = &m_program->direct();
|
||||
m_io = &space(AS_IO);
|
||||
|
||||
save_item(NAME(m_PC));
|
||||
save_item(NAME(m_AR));
|
||||
save_item(NAME(m_IR));
|
||||
save_item(NAME(m_R1));
|
||||
save_item(NAME(m_R2));
|
||||
save_item(NAME(m_R3));
|
||||
save_item(NAME(m_R4));
|
||||
save_item(NAME(m_R5));
|
||||
save_item(NAME(m_R6));
|
||||
save_item(NAME(m_R11));
|
||||
save_item(NAME(m_AUX));
|
||||
save_item(NAME(m_IVL));
|
||||
save_item(NAME(m_IVR));
|
||||
save_item(NAME(m_OVF));
|
||||
save_item(NAME(m_left_IV));
|
||||
save_item(NAME(m_right_IV));
|
||||
|
||||
// Register state for debugger
|
||||
state_add( _8X300_PC, "PC", m_PC).mask(0x1fff).formatstr("%04X");
|
||||
state_add( _8X300_AR, "AR", m_AR).mask(0x1fff).formatstr("%04X");
|
||||
state_add( _8X300_IR, "IR", m_IR).mask(0xffff).formatstr("%04X");
|
||||
state_add( _8X300_AUX, "AUX", m_AUX).mask(0xff).formatstr("%02X");
|
||||
state_add( _8X300_R1, "R1", m_R1).mask(0xff).formatstr("%02X");
|
||||
state_add( _8X300_R2, "R2", m_R2).mask(0xff).formatstr("%02X");
|
||||
state_add( _8X300_R3, "R3", m_R3).mask(0xff).formatstr("%02X");
|
||||
state_add( _8X300_R4, "R4", m_R4).mask(0xff).formatstr("%02X");
|
||||
state_add( _8X300_R5, "R5", m_R5).mask(0xff).formatstr("%02X");
|
||||
state_add( _8X300_R6, "R6", m_R6).mask(0xff).formatstr("%02X");
|
||||
state_add( _8X300_R11, "R11", m_R11).mask(0xff).formatstr("%02X");
|
||||
state_add( _8X300_OVF, "OVF", m_OVF).mask(0x01).formatstr("%01X");
|
||||
state_add( _8X300_IVL, "IVL", m_IVL).mask(0xff).formatstr("%02X");
|
||||
state_add( _8X300_IVR, "IVR", m_IVR).mask(0xff).formatstr("%02X");
|
||||
state_add(STATE_GENPC, "curpc", m_genPC).noshow();
|
||||
|
||||
m_icountptr = &m_icount;
|
||||
|
||||
// reset registers here, since they are unchanged when /RESET goes low.
|
||||
m_R1 = 0;
|
||||
m_R2 = 0;
|
||||
m_R3 = 0;
|
||||
m_R4 = 0;
|
||||
m_R5 = 0;
|
||||
m_R6 = 0;
|
||||
m_R11 = 0;
|
||||
m_IVL = 0;
|
||||
m_IVR = 0;
|
||||
m_AUX = 0;
|
||||
}
|
||||
|
||||
void n8x300_cpu_device::state_string_export(const device_state_entry &entry, astring &string)
|
||||
{
|
||||
switch (entry.index())
|
||||
{
|
||||
// case STATE_GENFLAGS:
|
||||
// string.printf("%c%c%c%c%c%c",
|
||||
// break;
|
||||
}
|
||||
}
|
||||
|
||||
void n8x300_cpu_device::device_reset()
|
||||
{
|
||||
/* zero registers */
|
||||
m_PC = 0;
|
||||
m_AR = 0;
|
||||
m_IR = 0;
|
||||
}
|
||||
|
||||
void n8x300_cpu_device::execute_run()
|
||||
{
|
||||
do
|
||||
{
|
||||
UINT16 opcode;
|
||||
UINT8 src = 0;
|
||||
UINT8 dst;
|
||||
UINT8 rotlen; // rotate amount or I/O field length
|
||||
UINT8 mask;
|
||||
UINT16 result;
|
||||
|
||||
/* fetch the opcode */
|
||||
debugger_instruction_hook(this, m_genPC);
|
||||
opcode = FETCHOP(m_genPC);
|
||||
m_PC++;
|
||||
m_PC &= 0x1fff;
|
||||
m_AR = m_PC;
|
||||
m_IR = opcode;
|
||||
m_genPC = m_PC << 1;
|
||||
|
||||
switch (OP)
|
||||
{
|
||||
case 0x00: // MOVE
|
||||
rotlen = ROTLEN;
|
||||
if(is_rot(opcode)) // MOVE reg,reg
|
||||
{
|
||||
src = get_reg(SRC);
|
||||
dst = rotate(src,rotlen);
|
||||
set_reg(DST,dst);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(rotlen == 0)
|
||||
rotlen = 8; // 0 = 8-bit I/O field length
|
||||
if(is_src_reg(opcode) && !(is_dst_reg(opcode)))
|
||||
{ // MOVE reg,IV
|
||||
DST_LATCH;
|
||||
mask = ((1 << rotlen)-1);
|
||||
src = (get_reg(SRC)) << (7-DST_LSB);
|
||||
mask <<= (7-DST_LSB);
|
||||
if(DST_IS_RIGHT_BANK)
|
||||
{
|
||||
dst = (m_right_IV & ~mask) | (src & mask);
|
||||
m_right_IV = dst;
|
||||
WRITEPORT(m_IVR+0x100,m_right_IV);
|
||||
}
|
||||
else
|
||||
{
|
||||
dst = (m_left_IV & ~mask) | (src & mask);
|
||||
m_left_IV = dst;
|
||||
WRITEPORT(m_IVL,m_left_IV);
|
||||
}
|
||||
}
|
||||
else if(!(is_src_reg(opcode)) && is_dst_reg(opcode))
|
||||
{ // MOVE IV,reg
|
||||
SRC_LATCH;
|
||||
if(SRC_IS_RIGHT_BANK)
|
||||
src = rotate(m_right_IV,7-SRC_LSB);
|
||||
else
|
||||
src = rotate(m_left_IV,7-SRC_LSB);
|
||||
mask = ((1 << rotlen)-1);
|
||||
dst = src & mask;
|
||||
set_reg(DST,dst);
|
||||
}
|
||||
else if(!(is_src_reg(opcode)) && !(is_dst_reg(opcode)))
|
||||
{ // MOVE IV,IV
|
||||
SRC_LATCH;
|
||||
if(SRC_IS_RIGHT_BANK)
|
||||
src = rotate(m_right_IV,7-SRC_LSB);
|
||||
else
|
||||
src = rotate(m_left_IV,7-SRC_LSB);
|
||||
mask = ((1 << rotlen)-1);
|
||||
dst = src & mask;
|
||||
dst <<= (7-DST_LSB);
|
||||
mask <<= (7-DST_LSB);
|
||||
if(SRC_IS_RIGHT_BANK) // untouched source IV bits are preserved and sent to destination IV
|
||||
{
|
||||
dst = (m_right_IV & ~mask) | (dst & mask);
|
||||
m_right_IV = dst;
|
||||
WRITEPORT(m_IVR+0x100,m_right_IV);
|
||||
}
|
||||
else
|
||||
{
|
||||
dst = (m_left_IV & ~mask) | (dst & mask);
|
||||
m_left_IV = dst;
|
||||
WRITEPORT(m_IVL,m_left_IV);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x01: // ADD
|
||||
rotlen = ROTLEN;
|
||||
if(is_rot(opcode))
|
||||
{ // ADD reg,reg
|
||||
src = rotate(get_reg(SRC),rotlen);
|
||||
result = src + m_AUX;
|
||||
set_reg(DST,result & 0xff);
|
||||
SET_OVF;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(rotlen == 0)
|
||||
rotlen = 8; // 0 = 8-bit I/O field length
|
||||
if(is_src_reg(opcode) && !(is_dst_reg(opcode)))
|
||||
{ // ADD reg,IV
|
||||
DST_LATCH;
|
||||
result = get_reg(SRC) + m_AUX;
|
||||
mask = ((1 << rotlen)-1);
|
||||
dst = (result & 0xff) << DST_LSB;
|
||||
mask <<= DST_LSB;
|
||||
SET_OVF;
|
||||
if(DST_IS_RIGHT_BANK)
|
||||
{
|
||||
dst = (m_right_IV & ~mask) | (dst & mask);
|
||||
m_right_IV = dst;
|
||||
WRITEPORT(m_IVR+0x100,m_right_IV);
|
||||
}
|
||||
else
|
||||
{
|
||||
dst = (m_left_IV & ~mask) | (dst & mask);
|
||||
m_left_IV = dst;
|
||||
WRITEPORT(m_IVL,m_left_IV);
|
||||
}
|
||||
}
|
||||
else if(!(is_src_reg(opcode)) && is_dst_reg(opcode))
|
||||
{ // ADD IV,reg
|
||||
SRC_LATCH;
|
||||
mask = ((1 << rotlen)-1);
|
||||
if(SRC_IS_RIGHT_BANK)
|
||||
src = rotate(m_right_IV,7-SRC_LSB) & mask;
|
||||
else
|
||||
src = rotate(m_left_IV,7-SRC_LSB) & mask;
|
||||
result = src + m_AUX;
|
||||
SET_OVF;
|
||||
set_reg(DST,result & 0xff);
|
||||
}
|
||||
else if(!(is_src_reg(opcode)) && !(is_dst_reg(opcode)))
|
||||
{ // ADD IV,IV
|
||||
SRC_LATCH;
|
||||
DST_LATCH;
|
||||
mask = ((1 << rotlen)-1);
|
||||
if(SRC_IS_RIGHT_BANK)
|
||||
src = rotate(m_right_IV,7-SRC_LSB) & mask;
|
||||
else
|
||||
src = rotate(m_left_IV,7-SRC_LSB) & mask;
|
||||
result = src + m_AUX;
|
||||
SET_OVF;
|
||||
dst = (result << (7-DST_LSB)) & 0xff;
|
||||
mask <<= (7-DST_LSB);
|
||||
if(SRC_IS_RIGHT_BANK) // unused destination IV data is not preserved, is merged with input IV data
|
||||
{
|
||||
dst = (m_right_IV & ~mask) | (dst & mask);
|
||||
m_right_IV = dst;
|
||||
WRITEPORT(m_IVR+0x100,m_right_IV);
|
||||
}
|
||||
else
|
||||
{
|
||||
dst = (m_left_IV & ~mask) | (dst & mask);
|
||||
m_left_IV = dst;
|
||||
WRITEPORT(m_IVL,m_left_IV);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x02: // AND
|
||||
rotlen = ROTLEN;
|
||||
if(is_rot(opcode))
|
||||
{ // AND reg,reg
|
||||
src = rotate(get_reg(SRC),rotlen);
|
||||
dst = src & m_AUX;
|
||||
set_reg(DST,dst);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(rotlen == 0)
|
||||
rotlen = 8; // 0 = 8-bit I/O field length
|
||||
if(is_src_reg(opcode) && !(is_dst_reg(opcode)))
|
||||
{ // AND reg,IV
|
||||
DST_LATCH;
|
||||
src = get_reg(SRC) & m_AUX;
|
||||
mask = ((1 << rotlen)-1);
|
||||
src <<= (7-DST_LSB);
|
||||
mask <<= (7-DST_LSB);
|
||||
if(DST_IS_RIGHT_BANK)
|
||||
{
|
||||
dst = (m_right_IV & ~mask) | (src & mask);
|
||||
m_right_IV = dst;
|
||||
WRITEPORT(m_IVR+0x100,m_right_IV);
|
||||
}
|
||||
else
|
||||
{
|
||||
dst = (m_left_IV & ~mask) | (src & mask);
|
||||
m_left_IV = dst;
|
||||
WRITEPORT(m_IVL,m_left_IV);
|
||||
}
|
||||
}
|
||||
else if(!(is_src_reg(opcode)) && is_dst_reg(opcode))
|
||||
{ // AND IV,reg
|
||||
SRC_LATCH;
|
||||
mask = ((1 << rotlen)-1);
|
||||
if(SRC_IS_RIGHT_BANK)
|
||||
src = rotate(m_right_IV,7-SRC_LSB) & mask;
|
||||
else
|
||||
src = rotate(m_left_IV,7-SRC_LSB) & mask;
|
||||
src &= mask;
|
||||
dst = src & m_AUX;
|
||||
set_reg(DST,dst);
|
||||
}
|
||||
else if(!(is_src_reg(opcode)) && !(is_dst_reg(opcode)))
|
||||
{ // AND IV,IV
|
||||
SRC_LATCH;
|
||||
DST_LATCH;
|
||||
mask = ((1 << rotlen)-1);
|
||||
if(SRC_IS_RIGHT_BANK)
|
||||
src = rotate(m_right_IV,7-SRC_LSB) & mask;
|
||||
else
|
||||
src = rotate(m_left_IV,7-SRC_LSB) & mask;
|
||||
src &= mask;
|
||||
dst = src & m_AUX;
|
||||
dst <<= (7-DST_LSB);
|
||||
mask <<= (7-DST_LSB);
|
||||
if(SRC_IS_RIGHT_BANK)
|
||||
{
|
||||
dst = (m_right_IV & ~mask) | (src & mask);
|
||||
m_right_IV = dst;
|
||||
WRITEPORT(m_IVR+0x100,m_right_IV);
|
||||
}
|
||||
else
|
||||
{
|
||||
dst = (m_left_IV & ~mask) | (src & mask);
|
||||
m_left_IV = dst;
|
||||
WRITEPORT(m_IVL,m_left_IV);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x03: // XOR
|
||||
rotlen = ROTLEN;
|
||||
if(is_rot(opcode))
|
||||
{ // AND reg,reg
|
||||
src = rotate(get_reg(SRC),rotlen);
|
||||
dst = src ^ m_AUX;
|
||||
set_reg(DST,dst);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(rotlen == 0)
|
||||
rotlen = 8; // 0 = 8-bit I/O field length
|
||||
if(is_src_reg(opcode) && !(is_dst_reg(opcode)))
|
||||
{ // AND reg,IV
|
||||
DST_LATCH;
|
||||
src = get_reg(SRC) ^ m_AUX;
|
||||
mask = ((1 << rotlen)-1);
|
||||
src <<= (7-DST_LSB);
|
||||
mask <<= (7-DST_LSB);
|
||||
if(DST_IS_RIGHT_BANK)
|
||||
{
|
||||
dst = (m_right_IV & ~mask) | (src & mask);
|
||||
m_right_IV = dst;
|
||||
WRITEPORT(m_IVR+0x100,m_right_IV);
|
||||
}
|
||||
else
|
||||
{
|
||||
dst = (m_left_IV & ~mask) | (src & mask);
|
||||
m_left_IV = dst;
|
||||
WRITEPORT(m_IVL,m_left_IV);
|
||||
}
|
||||
}
|
||||
else if(!(is_src_reg(opcode)) && is_dst_reg(opcode))
|
||||
{ // AND IV,reg
|
||||
SRC_LATCH;
|
||||
mask = ((1 << rotlen)-1);
|
||||
if(SRC_IS_RIGHT_BANK)
|
||||
src = rotate(m_right_IV,7-SRC_LSB) & mask;
|
||||
else
|
||||
src = rotate(m_left_IV,7-SRC_LSB) & mask;
|
||||
src &= mask;
|
||||
dst = src ^ m_AUX;
|
||||
set_reg(DST,dst);
|
||||
}
|
||||
else if(!(is_src_reg(opcode)) && !(is_dst_reg(opcode)))
|
||||
{ // AND IV,IV
|
||||
SRC_LATCH;
|
||||
DST_LATCH;
|
||||
mask = ((1 << rotlen)-1);
|
||||
if(SRC_IS_RIGHT_BANK)
|
||||
src = rotate(m_right_IV,7-SRC_LSB) & mask;
|
||||
else
|
||||
src = rotate(m_left_IV,7-SRC_LSB) & mask;
|
||||
src &= mask;
|
||||
dst = src ^ m_AUX;
|
||||
dst <<= (7-DST_LSB);
|
||||
mask <<= (7-DST_LSB);
|
||||
if(SRC_IS_RIGHT_BANK)
|
||||
{
|
||||
dst = (m_right_IV & ~mask) | (src & mask);
|
||||
m_right_IV = dst;
|
||||
WRITEPORT(m_IVR+0x100,m_right_IV);
|
||||
}
|
||||
else
|
||||
{
|
||||
dst = (m_left_IV & ~mask) | (src & mask);
|
||||
m_left_IV = dst;
|
||||
WRITEPORT(m_IVL,m_left_IV);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x04: // XEC (Execute)
|
||||
if(is_src_reg(opcode))
|
||||
{
|
||||
src = get_reg(SRC);
|
||||
src += IMM8;
|
||||
SET_AR((m_AR & 0x1f00) | src);
|
||||
}
|
||||
else
|
||||
{
|
||||
SRC_LATCH;
|
||||
rotlen = ROTLEN;
|
||||
if(rotlen == 0)
|
||||
rotlen = 8; // 0 = 8-bit I/O field length
|
||||
mask = ((1 << rotlen)-1);
|
||||
if(SRC_IS_RIGHT_BANK)
|
||||
src = rotate(m_right_IV,7-SRC_LSB);
|
||||
else
|
||||
src = rotate(m_left_IV,7-SRC_LSB);
|
||||
src &= mask;
|
||||
src += IMM5;
|
||||
SET_AR((m_AR & 0x1fe0) | (src & 0x1f));
|
||||
}
|
||||
break;
|
||||
case 0x05: // NZT (Non-zero transfer)
|
||||
if(is_src_reg(opcode))
|
||||
{
|
||||
src = get_reg(SRC);
|
||||
if(src != 0)
|
||||
SET_PC((m_PC & 0x1f00) | IMM8);
|
||||
}
|
||||
else
|
||||
{
|
||||
SRC_LATCH;
|
||||
rotlen = ROTLEN;
|
||||
if(rotlen == 0)
|
||||
rotlen = 8; // 0 = 8-bit I/O field length
|
||||
mask = ((1 << rotlen)-1);
|
||||
if(SRC_IS_RIGHT_BANK)
|
||||
src = rotate(m_right_IV,7-SRC_LSB);
|
||||
else
|
||||
src = rotate(m_left_IV,7-SRC_LSB);
|
||||
rotate(src,SRC_LSB);
|
||||
src &= mask;
|
||||
if(src != 0)
|
||||
SET_PC((m_PC & 0x1fe0) | IMM5);
|
||||
}
|
||||
break;
|
||||
case 0x06: // XMIT (Transmit)
|
||||
// the source is actually the destination for this instruction
|
||||
if(is_src_reg(opcode))
|
||||
set_reg(SRC,IMM8);
|
||||
else
|
||||
{
|
||||
SRC_LATCH;
|
||||
rotlen = ROTLEN;
|
||||
if(rotlen == 0)
|
||||
rotlen = 8; // 0 = 8-bit I/O field length
|
||||
mask = ((1 << rotlen)-1);
|
||||
dst = IMM5;
|
||||
mask <<= (7-SRC_LSB);
|
||||
dst <<= (7-SRC_LSB);
|
||||
if(SRC_IS_RIGHT_BANK)
|
||||
{
|
||||
m_right_IV = (m_right_IV & ~mask) | (dst & mask);
|
||||
WRITEPORT(m_IVR+0x100,m_right_IV);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_left_IV = (m_left_IV & ~mask) | (dst & mask);
|
||||
WRITEPORT(m_IVL,m_left_IV);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x07: // JMP
|
||||
SET_PC(ADDR);
|
||||
break;
|
||||
}
|
||||
CYCLES(1); // all instructions take 1 cycle (250ns)
|
||||
} while (m_icount > 0);
|
||||
}
|
||||
|
||||
offs_t n8x300_cpu_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
|
||||
{
|
||||
extern CPU_DISASSEMBLE( n8x300 );
|
||||
return CPU_DISASSEMBLE_NAME(n8x300)(this, buffer, pc, oprom, opram, options);
|
||||
}
|
||||
|
134
src/emu/cpu/8x300/8x300.h
Normal file
134
src/emu/cpu/8x300/8x300.h
Normal file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* 8x300.h
|
||||
*
|
||||
* Implementation of the Scientific Micro Systems SMS300 / Signetics 8X300 Microcontroller
|
||||
* Created on: 18/12/2013
|
||||
*/
|
||||
|
||||
#ifndef _8X300_H_
|
||||
#define _8X300_H_
|
||||
|
||||
// Register enumeration
|
||||
enum
|
||||
{
|
||||
_8X300_PC = 1,
|
||||
_8X300_AR,
|
||||
_8X300_IR,
|
||||
_8X300_AUX,
|
||||
_8X300_R1,
|
||||
_8X300_R2,
|
||||
_8X300_R3,
|
||||
_8X300_R4,
|
||||
_8X300_R5,
|
||||
_8X300_R6,
|
||||
_8X300_IVL,
|
||||
_8X300_OVF,
|
||||
_8X300_R11,
|
||||
_8X300_UNUSED12,
|
||||
_8X300_UNUSED13,
|
||||
_8X300_UNUSED14,
|
||||
_8X300_UNUSED15,
|
||||
_8X300_UNUSED16,
|
||||
_8X300_IVR,
|
||||
_8X300_LIV,
|
||||
_8X300_RIV,
|
||||
_8X300_GENPC
|
||||
};
|
||||
|
||||
class n8x300_cpu_device : public cpu_device
|
||||
{
|
||||
public:
|
||||
// construction/destruction
|
||||
n8x300_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 0; }
|
||||
virtual void execute_run();
|
||||
|
||||
// device_memory_interface overrides
|
||||
virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const
|
||||
{
|
||||
switch (spacenum)
|
||||
{
|
||||
case AS_PROGRAM: return &m_program_config;
|
||||
case AS_IO: return &m_io_config;
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// device_state_interface overrides
|
||||
void state_string_export(const device_state_entry &entry, astring &string);
|
||||
|
||||
// device_disasm_interface overrides
|
||||
virtual UINT32 disasm_min_opcode_bytes() const { return 2; }
|
||||
virtual UINT32 disasm_max_opcode_bytes() const { return 2; }
|
||||
virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
|
||||
|
||||
address_space_config m_program_config;
|
||||
address_space_config m_io_config;
|
||||
|
||||
int m_icount;
|
||||
|
||||
address_space *m_program;
|
||||
direct_read_data *m_direct;
|
||||
address_space *m_io;
|
||||
|
||||
UINT16 m_PC; // Program Counter
|
||||
UINT16 m_AR; // Address Register
|
||||
UINT16 m_IR; // Instruction Register
|
||||
UINT8 m_AUX; // Auxiliary Register (second operand for AND, ADD, XOR)
|
||||
UINT8 m_R1;
|
||||
UINT8 m_R2;
|
||||
UINT8 m_R3;
|
||||
UINT8 m_R4;
|
||||
UINT8 m_R5;
|
||||
UINT8 m_R6;
|
||||
UINT8 m_R11;
|
||||
UINT8 m_IVL; // Interface vector (I/O) left bank (write-only)
|
||||
UINT8 m_IVR; // Interface vector (I/O) right bank (write-only)
|
||||
UINT8 m_OVF; // Overflow register (read-only)
|
||||
UINT16 m_genPC;
|
||||
|
||||
UINT8 m_left_IV; // IV bank contents, these are latched when IVL or IVR are set
|
||||
UINT8 m_right_IV;
|
||||
|
||||
private:
|
||||
inline bool is_rot(UINT16 opcode)
|
||||
{
|
||||
if((opcode & 0x1000) || (opcode & 0x0010))
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
inline bool is_src_reg(UINT16 opcode)
|
||||
{
|
||||
if((opcode & 0x1000))
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
inline bool is_dst_reg(UINT16 opcode)
|
||||
{
|
||||
if((opcode & 0x0010))
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
inline UINT8 rotate(UINT8 s, UINT8 n) // right rotate
|
||||
{
|
||||
return ((s & ((UINT8)0xff << n)) >> n) | ((s & ((UINT8)0xff >> (8-n))) << (8-n));
|
||||
}
|
||||
void set_reg(UINT8 reg,UINT8 val);
|
||||
UINT8 get_reg(UINT8 reg);
|
||||
};
|
||||
|
||||
extern const device_type N8X300;
|
||||
|
||||
#endif /* 8X300_H_ */
|
149
src/emu/cpu/8x300/8x300dasm.c
Normal file
149
src/emu/cpu/8x300/8x300dasm.c
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* 8x300dasm.c
|
||||
* Implementation of the Scientific Micro Systems SMS300 / Signetics 8X300 Microcontroller
|
||||
*
|
||||
* Created on: 18/12/2013
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
#include "8x300.h"
|
||||
|
||||
#define SRC ((opcode & 0x1f00) >> 8)
|
||||
#define DST (opcode & 0x001f)
|
||||
#define ROTLEN ((opcode & 0x00e0) >> 5)
|
||||
#define IMM8 (opcode & 0x00ff)
|
||||
#define IMM5 (opcode & 0x001f)
|
||||
|
||||
static const char *reg_names[32] =
|
||||
{
|
||||
"AUX", "R1", "R2", "R3", "R4", "R5", "R6", "IVL", "OVF", "R11",
|
||||
"Unused12", "Unused13", "Unused14", "Unused15", "Unused16", "IVR",
|
||||
"LIV0", "LIV1", "LIV2", "LIV3", "LIV4", "LIV5", "LIV6", "LIV7",
|
||||
"RIV0", "RIV1", "RIV2", "RIV3", "RIV4", "RIV5", "RIV6", "RIV7"
|
||||
};
|
||||
|
||||
// determines if right rotate or I/O field length is to be used
|
||||
INLINE bool is_rot(UINT16 opcode)
|
||||
{
|
||||
if((opcode & 0x1000) || (opcode & 0x0010))
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
INLINE bool is_src_rot(UINT16 opcode)
|
||||
{
|
||||
if((opcode & 0x1000))
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
CPU_DISASSEMBLE( n8x300 )
|
||||
{
|
||||
char tmp[16];
|
||||
unsigned startpc = pc;
|
||||
UINT16 opcode = (oprom[pc - startpc] << 8) | oprom[pc+1 - startpc];
|
||||
UINT8 inst = opcode >> 13;
|
||||
pc+=2;
|
||||
|
||||
// determine instruction
|
||||
switch (inst)
|
||||
{
|
||||
case 0x00:
|
||||
sprintf(buffer,"MOVE ");
|
||||
strcat(buffer,reg_names[SRC]);
|
||||
if(is_rot(opcode))
|
||||
sprintf(tmp,"(%i),",ROTLEN);
|
||||
else
|
||||
sprintf(tmp,",%i,",ROTLEN);
|
||||
strcat(buffer,tmp);
|
||||
strcat(buffer,reg_names[DST]);
|
||||
break;
|
||||
case 0x01:
|
||||
sprintf(buffer,"ADD ");
|
||||
strcat(buffer,reg_names[SRC]);
|
||||
if(is_rot(opcode))
|
||||
sprintf(tmp,"(%i),",ROTLEN);
|
||||
else
|
||||
sprintf(tmp,",%i,",ROTLEN);
|
||||
strcat(buffer,tmp);
|
||||
strcat(buffer,reg_names[DST]);
|
||||
break;
|
||||
case 0x02:
|
||||
sprintf(buffer,"AND ");
|
||||
strcat(buffer,reg_names[SRC]);
|
||||
if(is_rot(opcode))
|
||||
sprintf(tmp,"(%i),",ROTLEN);
|
||||
else
|
||||
sprintf(tmp,",%i,",ROTLEN);
|
||||
strcat(buffer,tmp);
|
||||
strcat(buffer,reg_names[DST]);
|
||||
break;
|
||||
case 0x03:
|
||||
sprintf(buffer,"XOR ");
|
||||
strcat(buffer,reg_names[SRC]);
|
||||
if(is_rot(opcode))
|
||||
sprintf(tmp,"(%i),",ROTLEN);
|
||||
else
|
||||
sprintf(tmp,",%i,",ROTLEN);
|
||||
strcat(buffer,tmp);
|
||||
strcat(buffer,reg_names[DST]);
|
||||
break;
|
||||
case 0x04:
|
||||
sprintf(buffer,"XEC ");
|
||||
strcat(buffer,reg_names[SRC]);
|
||||
if(is_src_rot(opcode))
|
||||
{
|
||||
sprintf(tmp,",%02XH",IMM8);
|
||||
strcat(buffer,tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(tmp,",%i",ROTLEN);
|
||||
strcat(buffer,tmp);
|
||||
sprintf(tmp,",%02XH",IMM5);
|
||||
strcat(buffer,tmp);
|
||||
}
|
||||
break;
|
||||
case 0x05:
|
||||
sprintf(buffer,"NZT ");
|
||||
strcat(buffer,reg_names[SRC]);
|
||||
if(is_src_rot(opcode))
|
||||
{
|
||||
sprintf(tmp,",%02XH",IMM8);
|
||||
strcat(buffer,tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(tmp,",%i",ROTLEN);
|
||||
strcat(buffer,tmp);
|
||||
sprintf(tmp,",%02XH",IMM5);
|
||||
strcat(buffer,tmp);
|
||||
}
|
||||
break;
|
||||
case 0x06:
|
||||
sprintf(buffer,"XMIT ");
|
||||
if(is_src_rot(opcode))
|
||||
{
|
||||
sprintf(tmp,"%02XH,",IMM8);
|
||||
strcat(buffer,tmp);
|
||||
strcat(buffer,reg_names[SRC]);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(tmp,"%02XH,",IMM5);
|
||||
strcat(buffer,tmp);
|
||||
strcat(buffer,reg_names[SRC]);
|
||||
sprintf(tmp,",%i",ROTLEN);
|
||||
strcat(buffer,tmp);
|
||||
}
|
||||
break;
|
||||
case 0x07:
|
||||
sprintf(buffer,"JMP %04XH",opcode & 0x1fff);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return (pc - startpc);
|
||||
}
|
@ -66,6 +66,20 @@ $(DRCOBJ): $(DRCDEPS)
|
||||
|
||||
|
||||
|
||||
#-------------------------------------------------
|
||||
# Signetics 8X300 / Scientific Micro Systems SMS300
|
||||
#@src/emu/cpu/8x300/8x300.h,CPUS += 8X300
|
||||
#-------------------------------------------------
|
||||
|
||||
ifneq ($(filter 8X300,$(CPUS)),)
|
||||
OBJDIRS += $(CPUOBJ)/8x300
|
||||
CPUOBJS += $(CPUOBJ)/8x300/8x300.o
|
||||
DASMOBJS += $(CPUOBJ)/8x300/8x300dasm.o
|
||||
endif
|
||||
|
||||
$(CPUOBJ)/8x300/8x300.o: $(CPUSRC)/8x300/8x300.c \
|
||||
$(CPUSRC)/8x300/8x300.h
|
||||
|
||||
#-------------------------------------------------
|
||||
# Acorn ARM series
|
||||
#
|
||||
|
@ -11,6 +11,7 @@ Wicat - various systems.
|
||||
#include "emu.h"
|
||||
#include "cpu/m68000/m68000.h"
|
||||
#include "cpu/z8000/z8000.h"
|
||||
#include "cpu/8x300/8x300.h"
|
||||
#include "machine/serial.h"
|
||||
#include "machine/6522via.h"
|
||||
#include "machine/mm58274c.h"
|
||||
@ -19,6 +20,7 @@ Wicat - various systems.
|
||||
#include "video/i8275x.h"
|
||||
#include "machine/am9517a.h"
|
||||
#include "machine/x2212.h"
|
||||
#include "machine/wd17xx.h"
|
||||
#include "wicat.lh"
|
||||
|
||||
class wicat_state : public driver_device
|
||||
@ -159,6 +161,16 @@ static ADDRESS_MAP_START(wicat_video_io, AS_IO, 8, wicat_state)
|
||||
AM_RANGE(0x9000,0x9fff) AM_ROM AM_REGION("g2char",0x0000)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
static ADDRESS_MAP_START(wicat_flop_mem, AS_PROGRAM, 16, wicat_state)
|
||||
AM_RANGE(0x0000, 0x17ff) AM_ROM AM_REGION("wd3", 0x0000)
|
||||
AM_RANGE(0x1800, 0x1fff) AM_NOP
|
||||
ADDRESS_MAP_END
|
||||
|
||||
static ADDRESS_MAP_START(wicat_flop_io, AS_IO, 8, wicat_state)
|
||||
AM_RANGE(0x0000, 0x00ff) AM_RAM // left bank
|
||||
AM_RANGE(0x0100, 0x01ff) AM_RAM // right bank -- one of these probably is RAM...
|
||||
ADDRESS_MAP_END
|
||||
|
||||
|
||||
/* Input ports */
|
||||
static INPUT_PORTS_START( wicat )
|
||||
@ -673,8 +685,8 @@ static MACHINE_CONFIG_START( wicat, wicat_state )
|
||||
MCFG_X2212_ADD("videosram") // XD2210
|
||||
|
||||
MCFG_SCREEN_ADD("screen",RASTER)
|
||||
MCFG_SCREEN_SIZE(400,300)
|
||||
MCFG_SCREEN_VISIBLE_AREA(0,400-1,0,300-1)
|
||||
MCFG_SCREEN_SIZE(720,300)
|
||||
MCFG_SCREEN_VISIBLE_AREA(0,720-1,0,300-1)
|
||||
MCFG_SCREEN_REFRESH_RATE(60)
|
||||
MCFG_SCREEN_UPDATE_DEVICE("video",i8275x_device,screen_update)
|
||||
|
||||
@ -684,6 +696,12 @@ static MACHINE_CONFIG_START( wicat, wicat_state )
|
||||
|
||||
MCFG_DEFAULT_LAYOUT(layout_wicat)
|
||||
|
||||
/* Winchester Floppy Controller */
|
||||
MCFG_CPU_ADD("floppycpu",N8X300,XTAL_8MHz)
|
||||
MCFG_CPU_PROGRAM_MAP(wicat_flop_mem)
|
||||
MCFG_CPU_IO_MAP(wicat_flop_io)
|
||||
// MCFG_FD1795_ADD("fdc")
|
||||
|
||||
MACHINE_CONFIG_END
|
||||
|
||||
/* ROM definition */
|
||||
@ -750,14 +768,14 @@ ROM_START( wicat )
|
||||
ROM_LOAD ("apl.chr", 0x00800, 0x0800, CRC(8c6d698e) SHA1(147dd9296fe2efc6140fa148a6edf673c33f9371) )
|
||||
|
||||
// Winchester Floppy Controller (Signetics N8X300I + FD1795)
|
||||
ROM_REGION(0x1800, "wd3", 0)
|
||||
ROM_LOAD ("wd3.u95", 0x00000, 0x0800, CRC(80bb0617) SHA1(ac0f3194fcbef77532571baa3fec78b3010528bf) )
|
||||
ROM_LOAD ("wd3.u96", 0x00800, 0x0800, CRC(52736e61) SHA1(71c7c9170c733c483393969cb1cb3798b3eb980c) )
|
||||
ROM_LOAD ("wd3.u97", 0x01000, 0x0800, CRC(a66619ec) SHA1(5d091ac7c88f2f45b4a05e78bfc7a16c206b31ff) )
|
||||
ROM_REGION16_BE(0x1800, "wd3", 0)
|
||||
ROM_LOAD16_BYTE("wd3.u96", 0x00000, 0x0800, CRC(52736e61) SHA1(71c7c9170c733c483393969cb1cb3798b3eb980c) )
|
||||
ROM_LOAD16_BYTE("wd3.u97", 0x00001, 0x0800, CRC(a66619ec) SHA1(5d091ac7c88f2f45b4a05e78bfc7a16c206b31ff) )
|
||||
ROM_LOAD ("wd3.u95", 0x01000, 0x0800, CRC(80bb0617) SHA1(ac0f3194fcbef77532571baa3fec78b3010528bf) )
|
||||
ROM_END
|
||||
|
||||
|
||||
/* Driver */
|
||||
|
||||
/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */
|
||||
COMP( 198?, wicat, 0, 0, wicat, wicat, driver_device, 0, "Millennium Systems", "Wicat", GAME_NOT_WORKING | GAME_NO_SOUND_HW )
|
||||
COMP( 1982, wicat, 0, 0, wicat, wicat, driver_device, 0, "Millennium Systems", "Wicat System 150", GAME_NOT_WORKING | GAME_NO_SOUND_HW )
|
||||
|
@ -129,6 +129,7 @@ CPUS += SCORE
|
||||
CPUS += ES5510
|
||||
CPUS += SCUDSP
|
||||
CPUS += IE15
|
||||
CPUS += 8X300
|
||||
|
||||
#-------------------------------------------------
|
||||
# specify available sound cores; some of these are
|
||||
|
Loading…
Reference in New Issue
Block a user