summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu')
-rw-r--r--src/devices/cpu/8x300/8x300.cpp330
-rw-r--r--src/devices/cpu/8x300/8x300.h47
-rw-r--r--src/devices/cpu/8x300/8x300dasm.cpp8
-rw-r--r--src/devices/cpu/alpha/alpha.cpp995
-rw-r--r--src/devices/cpu/alpha/alpha.h284
-rw-r--r--src/devices/cpu/alpha/alphad.cpp1245
-rw-r--r--src/devices/cpu/alpha/alphad.h40
-rw-r--r--src/devices/cpu/alpha/common.h19
-rw-r--r--src/devices/cpu/alto2/a2ether.cpp10
-rw-r--r--src/devices/cpu/amis2000/amis2000.h3
-rw-r--r--src/devices/cpu/amis2000/amis2000op.cpp11
-rw-r--r--src/devices/cpu/arm7/lpc210x.cpp7
-rw-r--r--src/devices/cpu/cosmac/cosmac.cpp2
-rw-r--r--src/devices/cpu/dspp/dspp.h18
-rw-r--r--src/devices/cpu/dspp/dsppdrc.cpp334
-rw-r--r--src/devices/cpu/e132xs/e132xs.h2
-rw-r--r--src/devices/cpu/f8/f8.cpp692
-rw-r--r--src/devices/cpu/f8/f8.h3
-rw-r--r--src/devices/cpu/g65816/g65816.cpp7
-rw-r--r--src/devices/cpu/g65816/g65816.h7
-rw-r--r--src/devices/cpu/g65816/g65816ds.cpp2
-rw-r--r--src/devices/cpu/g65816/g65816op.h3
-rw-r--r--src/devices/cpu/h8/h83003.cpp3
-rw-r--r--src/devices/cpu/hmcs40/hmcs40.cpp1
-rw-r--r--src/devices/cpu/hpc/hpc.cpp144
-rw-r--r--src/devices/cpu/hpc/hpc.h88
-rw-r--r--src/devices/cpu/hpc/hpcdasm.cpp764
-rw-r--r--src/devices/cpu/hpc/hpcdasm.h58
-rw-r--r--src/devices/cpu/hphybrid/hphybrid.cpp45
-rw-r--r--src/devices/cpu/hphybrid/hphybrid.h28
-rw-r--r--src/devices/cpu/i386/cache.h258
-rw-r--r--src/devices/cpu/i386/cpuidmsrs.hxx94
-rw-r--r--src/devices/cpu/i386/i386.cpp236
-rw-r--r--src/devices/cpu/i386/i386.h52
-rw-r--r--src/devices/cpu/i386/i386priv.h32
-rw-r--r--src/devices/cpu/i386/i486ops.hxx8
-rw-r--r--src/devices/cpu/i386/pentops.hxx13
-rw-r--r--src/devices/cpu/i8089/i8089.cpp2
-rw-r--r--src/devices/cpu/i8089/i8089_channel.cpp7
-rw-r--r--src/devices/cpu/i86/i186.cpp29
-rw-r--r--src/devices/cpu/i86/i186.h12
-rw-r--r--src/devices/cpu/i86/i86.cpp2
-rw-r--r--src/devices/cpu/m6502/dxavix2000.lst2
-rw-r--r--src/devices/cpu/m6502/oxavix.lst8
-rw-r--r--src/devices/cpu/m6502/oxavix2000.lst13
-rw-r--r--src/devices/cpu/m6502/xavix.h4
-rw-r--r--src/devices/cpu/m6502/xavix2000.cpp101
-rw-r--r--src/devices/cpu/m6502/xavix2000.h11
-rw-r--r--src/devices/cpu/m68000/m68000.h19
-rw-r--r--src/devices/cpu/m68000/m68k_in.cpp1
-rw-r--r--src/devices/cpu/m68000/m68kcpu.cpp21
-rw-r--r--src/devices/cpu/m68000/m68kmmu.h2
-rw-r--r--src/devices/cpu/m6809/6x09dasm.cpp22
-rw-r--r--src/devices/cpu/m6809/6x09dasm.h6
-rw-r--r--src/devices/cpu/mcs51/mcs51.cpp12
-rw-r--r--src/devices/cpu/mcs51/mcs51.h4
-rw-r--r--src/devices/cpu/mips/mips1.cpp2118
-rw-r--r--src/devices/cpu/mips/mips1.h208
-rw-r--r--src/devices/cpu/mips/mips3.cpp74
-rw-r--r--src/devices/cpu/mips/mips3.h3
-rw-r--r--src/devices/cpu/mips/mips3com.cpp7
-rw-r--r--src/devices/cpu/mips/mips3drc.cpp59
-rw-r--r--src/devices/cpu/mips/mips3fe.cpp4
-rw-r--r--src/devices/cpu/mips/r4000.cpp3067
-rw-r--r--src/devices/cpu/mips/r4000.h463
-rw-r--r--src/devices/cpu/nec/v5x.cpp8
-rw-r--r--src/devices/cpu/ns32000/ns32000.cpp160
-rw-r--r--src/devices/cpu/ns32000/ns32000.h149
-rw-r--r--src/devices/cpu/ns32000/ns32000dasm.cpp835
-rw-r--r--src/devices/cpu/ns32000/ns32000dasm.h117
-rw-r--r--src/devices/cpu/pic16c5x/pic16c5x.cpp4
-rw-r--r--src/devices/cpu/sh/sh2.cpp2
-rw-r--r--src/devices/cpu/sm510/sm510base.cpp4
-rw-r--r--src/devices/cpu/tms1000/tms0270.cpp7
-rw-r--r--src/devices/cpu/tms1000/tms0270.h9
-rw-r--r--src/devices/cpu/tms1000/tms1000c.cpp18
-rw-r--r--src/devices/cpu/tms1000/tms1000c.h1
-rw-r--r--src/devices/cpu/tms1000/tms1k_base.cpp19
-rw-r--r--src/devices/cpu/tms1000/tms1k_base.h18
-rw-r--r--src/devices/cpu/tms34010/tms34010.cpp91
-rw-r--r--src/devices/cpu/tms34010/tms34010.h26
-rw-r--r--src/devices/cpu/tms9900/tms9900.cpp87
-rw-r--r--src/devices/cpu/tms9900/tms9995.cpp108
-rw-r--r--src/devices/cpu/tms9900/tms9995.h2
-rw-r--r--src/devices/cpu/unsp/unsp.cpp840
-rw-r--r--src/devices/cpu/unsp/unsp.h181
-rw-r--r--src/devices/cpu/unsp/unspdefs.h22
-rw-r--r--src/devices/cpu/unsp/unspdrc.cpp1316
-rw-r--r--src/devices/cpu/unsp/unspfe.cpp357
-rw-r--r--src/devices/cpu/unsp/unspfe.h27
-rw-r--r--src/devices/cpu/z8/z8.cpp542
-rw-r--r--src/devices/cpu/z8/z8.h56
-rw-r--r--src/devices/cpu/z8/z8dasm.cpp5
-rw-r--r--src/devices/cpu/z80/kl5c80a12.cpp5
94 files changed, 2416 insertions, 14774 deletions
diff --git a/src/devices/cpu/8x300/8x300.cpp b/src/devices/cpu/8x300/8x300.cpp
index a8a9b9dcdad..130df2dd7e3 100644
--- a/src/devices/cpu/8x300/8x300.cpp
+++ b/src/devices/cpu/8x300/8x300.cpp
@@ -34,29 +34,17 @@
// 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_increment_pc = false; } while (0)
-#define SRC_LATCH do { if(SRC_IS_RIGHT_BANK) m_IV_latch = READPORT(m_IVR+0x100); else m_IV_latch = READPORT(m_IVL); } while (0)
-#define DST_LATCH do { if(DST_IS_RIGHT_BANK) m_IV_latch = READPORT(m_IVR+0x100); else m_IV_latch = READPORT(m_IVL); } 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)
DEFINE_DEVICE_TYPE(N8X300, n8x300_cpu_device, "8x300", "Signetics 8X300")
-DEFINE_DEVICE_TYPE(N8X305, n8x305_cpu_device, "8x305", "Signetics 8X305")
-n8x300_cpu_device::n8x300_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
- : cpu_device(mconfig, type, tag, owner, clock)
- , m_program_config("program", ENDIANNESS_BIG, 16, 13, -1)
- , m_io_config("io", ENDIANNESS_BIG, 8, 9, 0)
- , m_sc_callback(*this)
-{
-}
-
n8x300_cpu_device::n8x300_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : n8x300_cpu_device(mconfig, N8X300, tag, owner, clock)
-{
-}
-
-n8x305_cpu_device::n8x305_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : n8x300_cpu_device(mconfig, N8X305, tag, owner, clock)
+ : cpu_device(mconfig, N8X300, tag, owner, clock)
+ , m_program_config("program", ENDIANNESS_BIG, 16, 14, 0)
+ , m_io_config("io", ENDIANNESS_BIG, 8, 9, 0)
{
}
@@ -68,21 +56,9 @@ device_memory_interface::space_config_vector n8x300_cpu_device::memory_space_con
};
}
-void n8x300_cpu_device::xmit_lb(uint8_t dst, uint8_t mask)
+void n8x300_cpu_device::set_reg(uint8_t reg, uint8_t val)
{
- m_IV_latch = (m_IV_latch & ~mask) | (dst & mask);
- WRITEPORT(m_IVL, m_IV_latch);
-}
-
-void n8x300_cpu_device::xmit_rb(uint8_t dst, uint8_t mask)
-{
- m_IV_latch = (m_IV_latch & ~mask) | (dst & mask);
- WRITEPORT(m_IVR + 0x100, m_IV_latch);
-}
-
-void n8x300_cpu_device::set_reg(uint8_t reg, uint8_t val, bool xmit)
-{
- switch (reg)
+ switch(reg)
{
case 0x00: m_AUX = val; break;
case 0x01: m_R1 = val; break;
@@ -91,30 +67,17 @@ void n8x300_cpu_device::set_reg(uint8_t reg, uint8_t val, bool xmit)
case 0x04: m_R4 = val; break;
case 0x05: m_R5 = val; break;
case 0x06: m_R6 = val; break;
- case 0x07: m_IVL = val; m_sc_callback(0, val); break;
+ case 0x07: m_IVL = val; break;
// OVF is read-only
case 0x09: m_R11 = val; break;
- case 0x0f: m_IVR = val; m_sc_callback(1, val); break;
+ case 0x0f: m_IVR = val; break;
default: logerror("8X300: Invalid register %02x written to.\n",reg); break;
}
}
-void n8x305_cpu_device::set_reg(uint8_t reg, uint8_t val, bool xmit)
-{
- switch (reg)
- {
- case 0x0a: if (xmit) xmit_lb(val, 0xff); else m_R12 = val; break;
- case 0x0b: if (xmit) xmit_rb(val, 0xff); else m_R13 = val; break;
- case 0x0c: m_R14 = val; break;
- case 0x0d: m_R15 = val; break;
- case 0x0e: m_R16 = val; break;
- default: n8x300_cpu_device::set_reg(reg, val, xmit); break;
- }
-}
-
uint8_t n8x300_cpu_device::get_reg(uint8_t reg)
{
- switch (reg)
+ switch(reg)
{
case 0x00: return m_AUX;
case 0x01: return m_R1;
@@ -123,38 +86,18 @@ uint8_t n8x300_cpu_device::get_reg(uint8_t reg)
case 0x04: return m_R4;
case 0x05: return m_R5;
case 0x06: return m_R6;
-// IVL is write-only on the 8X300
+// IVL is write-only
case 0x08: return m_OVF;
case 0x09: return m_R11;
-// IVR is write-only on the 8X300
+// IVR is write-only
default: logerror("8X300: Invalid register %02x read.\n",reg); return 0;
}
}
-uint8_t n8x305_cpu_device::get_reg(uint8_t reg)
-{
- switch (reg)
- {
- case 0x07: return m_IVL;
- case 0x0a: return m_R12;
- case 0x0b: return m_R13;
- case 0x0c: return m_R14;
- case 0x0d: return m_R15;
- case 0x0e: return m_R16;
- case 0x0f: return m_IVR;
- default: return n8x300_cpu_device::get_reg(reg);
- }
-}
-
-void n8x300_cpu_device::device_resolve_objects()
-{
- m_sc_callback.resolve_safe();
-}
-
void n8x300_cpu_device::device_start()
{
m_program = &space(AS_PROGRAM);
- m_cache = m_program->cache<1, -1, ENDIANNESS_BIG>();
+ m_cache = m_program->cache<1, 0, ENDIANNESS_BIG>();
m_io = &space(AS_IO);
save_item(NAME(m_PC));
@@ -167,19 +110,12 @@ void n8x300_cpu_device::device_start()
save_item(NAME(m_R5));
save_item(NAME(m_R6));
save_item(NAME(m_R11));
- if (type() == N8X305)
- {
- save_item(NAME(m_R12));
- save_item(NAME(m_R13));
- save_item(NAME(m_R14));
- save_item(NAME(m_R15));
- save_item(NAME(m_R16));
- }
save_item(NAME(m_AUX));
save_item(NAME(m_IVL));
save_item(NAME(m_IVR));
save_item(NAME(m_OVF));
- save_item(NAME(m_IV_latch));
+ save_item(NAME(m_left_IV));
+ save_item(NAME(m_right_IV));
save_item(NAME(m_genPC));
save_item(NAME(m_increment_pc));
@@ -191,14 +127,6 @@ void n8x300_cpu_device::device_start()
m_R5 = 0;
m_R6 = 0;
m_R11 = 0;
- if (type() == N8X305)
- {
- m_R12 = 0;
- m_R13 = 0;
- m_R14 = 0;
- m_R15 = 0;
- m_R16 = 0;
- }
m_IVL = 0;
m_IVR = 0;
m_AUX = 0;
@@ -218,19 +146,11 @@ void n8x300_cpu_device::device_start()
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");
- if (type() == N8X305)
- {
- state_add( _8X300_R12, "R12", m_R12).mask(0xff).formatstr("%02X");
- state_add( _8X300_R13, "R13", m_R13).mask(0xff).formatstr("%02X");
- state_add( _8X300_R14, "R14", m_R14).mask(0xff).formatstr("%02X");
- state_add( _8X300_R15, "R15", m_R15).mask(0xff).formatstr("%02X");
- state_add( _8X300_R16, "R16", m_R16).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, "GENPC", m_genPC).mask(0x1fff).callimport().noshow();
- state_add(STATE_GENPCBASE, "CURPC", m_genPC).mask(0x1fff).callimport().noshow();
+ state_add(STATE_GENPC, "GENPC", m_genPC).mask(0x3ffe).callimport().noshow();
+ state_add(STATE_GENPCBASE, "CURPC", m_genPC).mask(0x3ffe).callimport().noshow();
set_icountptr(m_icount);
}
@@ -246,12 +166,12 @@ void n8x300_cpu_device::state_import(const device_state_entry &entry)
{
case _8X300_PC:
m_AR = m_PC;
- m_genPC = m_AR;
+ m_genPC = m_AR << 1;
m_increment_pc = true;
break;
case _8X300_AR:
- m_genPC = m_AR;
+ m_genPC = m_AR << 1;
m_increment_pc = false;
break;
@@ -282,9 +202,10 @@ void n8x300_cpu_device::execute_run()
uint8_t dst;
uint8_t rotlen; // rotate amount or I/O field length
uint8_t mask;
+ uint16_t result;
/* fetch the opcode */
- m_genPC = m_AR;
+ m_genPC = m_AR << 1;
debugger_instruction_hook(m_genPC);
opcode = FETCHOP(m_genPC);
@@ -309,7 +230,7 @@ void n8x300_cpu_device::execute_run()
{
src = get_reg(SRC);
dst = rotate(src,rotlen);
- set_reg(DST,dst,false);
+ set_reg(DST,dst);
}
else
{
@@ -322,42 +243,62 @@ void n8x300_cpu_device::execute_run()
src = (get_reg(SRC)) << (7-DST_LSB);
mask <<= (7-DST_LSB);
if(DST_IS_RIGHT_BANK)
- xmit_rb(src, mask);
+ {
+ dst = (m_right_IV & ~mask) | (src & mask);
+ m_right_IV = dst;
+ WRITEPORT(m_IVR+0x100,m_right_IV);
+ }
else
- xmit_lb(src, mask);
+ {
+ 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;
- src = rotate(m_IV_latch,7-SRC_LSB);
+ 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,false);
+ set_reg(DST,dst);
}
else if(!(is_src_reg(opcode)) && !(is_dst_reg(opcode)))
{ // MOVE IV,IV
SRC_LATCH;
- src = rotate(m_IV_latch,7-SRC_LSB);
+ 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(DST_IS_RIGHT_BANK) // untouched source IV bits are preserved and sent to destination IV
- xmit_rb(dst, mask);
+ 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
- xmit_lb(dst, mask);
+ {
+ dst = (m_left_IV & ~mask) | (dst & mask);
+ m_left_IV = dst;
+ WRITEPORT(m_IVL,m_left_IV);
+ }
}
}
break;
case 0x01: // ADD
- {
- uint16_t result;
rotlen = ROTLEN;
if(is_rot(opcode))
{ // ADD reg,reg
src = rotate(get_reg(SRC),rotlen);
result = src + m_AUX;
- set_reg(DST,result & 0xff,false);
+ set_reg(DST,result & 0xff);
SET_OVF;
}
else
@@ -373,43 +314,65 @@ void n8x300_cpu_device::execute_run()
mask <<= DST_LSB;
SET_OVF;
if(DST_IS_RIGHT_BANK)
- xmit_rb(dst, mask);
+ {
+ dst = (m_right_IV & ~mask) | (dst & mask);
+ m_right_IV = dst;
+ WRITEPORT(m_IVR+0x100,m_right_IV);
+ }
else
- xmit_lb(dst, mask);
+ {
+ 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);
- src = rotate(m_IV_latch,7-SRC_LSB) & mask;
+ 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,false);
+ 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);
- src = rotate(m_IV_latch,7-SRC_LSB) & mask;
+ 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(DST_IS_RIGHT_BANK) // unused destination IV data is not preserved, is merged with input IV data
- xmit_rb(dst, mask);
+ 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
- xmit_lb(dst, mask);
+ {
+ 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,false);
+ set_reg(DST,dst);
}
else
{
@@ -418,36 +381,60 @@ void n8x300_cpu_device::execute_run()
if(is_src_reg(opcode) && !(is_dst_reg(opcode)))
{ // AND reg,IV
DST_LATCH;
- src = get_reg(SRC);
- dst = src & m_AUX;
+ src = get_reg(SRC) & m_AUX;
mask = ((1 << rotlen)-1);
- dst <<= (7-DST_LSB);
+ src <<= (7-DST_LSB);
mask <<= (7-DST_LSB);
if(DST_IS_RIGHT_BANK)
- xmit_rb(dst, mask);
+ {
+ dst = (m_right_IV & ~mask) | (src & mask);
+ m_right_IV = dst;
+ WRITEPORT(m_IVR+0x100,m_right_IV);
+ }
else
- xmit_lb(dst, mask);
+ {
+ 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);
- src = rotate(m_IV_latch,7-SRC_LSB) & mask;
+ 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,false);
+ 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);
- src = rotate(m_IV_latch,7-SRC_LSB) & mask;
+ 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(DST_IS_RIGHT_BANK)
- xmit_rb(dst, mask);
+ if(SRC_IS_RIGHT_BANK)
+ {
+ dst = (m_right_IV & ~mask) | (src & mask);
+ m_right_IV = dst;
+ WRITEPORT(m_IVR+0x100,m_right_IV);
+ }
else
- xmit_lb(dst, mask);
+ {
+ dst = (m_left_IV & ~mask) | (src & mask);
+ m_left_IV = dst;
+ WRITEPORT(m_IVL,m_left_IV);
+ }
}
}
break;
@@ -457,45 +444,69 @@ void n8x300_cpu_device::execute_run()
{ // AND reg,reg
src = rotate(get_reg(SRC),rotlen);
dst = src ^ m_AUX;
- set_reg(DST,dst,false);
+ 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)))
- { // XOR reg,IV
+ { // AND reg,IV
DST_LATCH;
- src = get_reg(SRC);
- dst = src ^ m_AUX;
+ src = get_reg(SRC) ^ m_AUX;
mask = ((1 << rotlen)-1);
- dst <<= (7-DST_LSB);
+ src <<= (7-DST_LSB);
mask <<= (7-DST_LSB);
if(DST_IS_RIGHT_BANK)
- xmit_rb(dst, mask);
+ {
+ dst = (m_right_IV & ~mask) | (src & mask);
+ m_right_IV = dst;
+ WRITEPORT(m_IVR+0x100,m_right_IV);
+ }
else
- xmit_lb(dst, mask);
+ {
+ 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))
- { // XOR IV,reg
+ { // AND IV,reg
SRC_LATCH;
mask = ((1 << rotlen)-1);
- src = rotate(m_IV_latch,7-SRC_LSB) & mask;
+ 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,false);
+ set_reg(DST,dst);
}
else if(!(is_src_reg(opcode)) && !(is_dst_reg(opcode)))
- { // XOR IV,IV
+ { // AND IV,IV
SRC_LATCH;
+ DST_LATCH;
mask = ((1 << rotlen)-1);
- src = rotate(m_IV_latch,7-SRC_LSB) & mask;
+ 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(DST_IS_RIGHT_BANK)
- xmit_rb(dst, mask);
+ if(SRC_IS_RIGHT_BANK)
+ {
+ dst = (m_right_IV & ~mask) | (src & mask);
+ m_right_IV = dst;
+ WRITEPORT(m_IVR+0x100,m_right_IV);
+ }
else
- xmit_lb(dst, mask);
+ {
+ dst = (m_left_IV & ~mask) | (src & mask);
+ m_left_IV = dst;
+ WRITEPORT(m_IVL,m_left_IV);
+ }
}
}
break;
@@ -513,7 +524,10 @@ void n8x300_cpu_device::execute_run()
if(rotlen == 0)
rotlen = 8; // 0 = 8-bit I/O field length
mask = ((1 << rotlen)-1);
- src = rotate(m_IV_latch,7-SRC_LSB);
+ 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));
@@ -533,7 +547,11 @@ void n8x300_cpu_device::execute_run()
if(rotlen == 0)
rotlen = 8; // 0 = 8-bit I/O field length
mask = ((1 << rotlen)-1);
- src = rotate(m_IV_latch,7-SRC_LSB);
+ 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);
@@ -542,7 +560,7 @@ void n8x300_cpu_device::execute_run()
case 0x06: // XMIT (Transmit)
// the source is actually the destination for this instruction
if(is_src_reg(opcode))
- set_reg(SRC,IMM8,true);
+ set_reg(SRC,IMM8);
else
{
SRC_LATCH;
@@ -554,9 +572,15 @@ void n8x300_cpu_device::execute_run()
mask <<= (7-SRC_LSB);
dst <<= (7-SRC_LSB);
if(SRC_IS_RIGHT_BANK)
- xmit_rb(dst, mask);
+ {
+ m_right_IV = (m_right_IV & ~mask) | (dst & mask);
+ WRITEPORT(m_IVR+0x100,m_right_IV);
+ }
else
- xmit_lb(dst, mask);
+ {
+ m_left_IV = (m_left_IV & ~mask) | (dst & mask);
+ WRITEPORT(m_IVL,m_left_IV);
+ }
}
break;
case 0x07: // JMP
diff --git a/src/devices/cpu/8x300/8x300.h b/src/devices/cpu/8x300/8x300.h
index 155079d225a..e3e3d68e7f6 100644
--- a/src/devices/cpu/8x300/8x300.h
+++ b/src/devices/cpu/8x300/8x300.h
@@ -28,11 +28,11 @@ enum
_8X300_IVL,
_8X300_OVF,
_8X300_R11,
- _8X300_R12,
- _8X300_R13,
- _8X300_R14,
- _8X300_R15,
- _8X300_R16,
+ _8X300_UNUSED12,
+ _8X300_UNUSED13,
+ _8X300_UNUSED14,
+ _8X300_UNUSED15,
+ _8X300_UNUSED16,
_8X300_IVR,
_8X300_LIV,
_8X300_RIV,
@@ -45,13 +45,8 @@ public:
// construction/destruction
n8x300_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- auto sc_callback() { return m_sc_callback.bind(); }
-
protected:
- n8x300_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
// device-level overrides
- virtual void device_resolve_objects() override;
virtual void device_start() override;
virtual void device_reset() override;
@@ -70,12 +65,6 @@ protected:
// device_disasm_interface overrides
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
- virtual void set_reg(uint8_t reg, uint8_t val, bool xmit);
- virtual uint8_t get_reg(uint8_t reg);
-
- void xmit_lb(uint8_t dst, uint8_t mask);
- void xmit_rb(uint8_t dst, uint8_t mask);
-
address_space_config m_program_config;
address_space_config m_io_config;
@@ -83,11 +72,9 @@ protected:
bool m_increment_pc;
address_space *m_program;
- memory_access_cache<1, -1, ENDIANNESS_BIG> *m_cache;
+ memory_access_cache<1, 0, ENDIANNESS_BIG> *m_cache;
address_space *m_io;
- devcb_write8 m_sc_callback; // Select Command (address latch)
-
uint16_t m_PC; // Program Counter
uint16_t m_AR; // Address Register
uint16_t m_IR; // Instruction Register
@@ -99,17 +86,13 @@ protected:
uint8_t m_R5;
uint8_t m_R6;
uint8_t m_R11;
- uint8_t m_R12;
- uint8_t m_R13;
- uint8_t m_R14;
- uint8_t m_R15;
- uint8_t m_R16;
uint8_t m_IVL; // Interface vector (I/O) left bank (write-only)
uint8_t m_IVR; // Interface vector (I/O) right bank (write-only)
uint8_t m_OVF; // Overflow register (read-only)
uint16_t m_genPC;
- uint8_t m_IV_latch; // IV bank contents, these are latched when IVL or IVR are set
+ uint8_t m_left_IV; // IV bank contents, these are latched when IVL or IVR are set
+ uint8_t m_right_IV;
private:
inline bool is_rot(uint16_t opcode)
@@ -137,20 +120,10 @@ private:
{
return ((s & ((uint8_t)0xff << n)) >> n) | ((s & ((uint8_t)0xff >> (8-n))) << (8-n));
}
-};
-
-class n8x305_cpu_device : public n8x300_cpu_device
-{
-public:
- // construction/destruction
- n8x305_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- virtual void set_reg(uint8_t reg, uint8_t val, bool xmit) override;
- virtual uint8_t get_reg(uint8_t reg) override;
+ void set_reg(uint8_t reg,uint8_t val);
+ uint8_t get_reg(uint8_t reg);
};
DECLARE_DEVICE_TYPE(N8X300, n8x300_cpu_device)
-DECLARE_DEVICE_TYPE(N8X305, n8x305_cpu_device)
#endif // MAME_CPU_8X300_8X300_H
diff --git a/src/devices/cpu/8x300/8x300dasm.cpp b/src/devices/cpu/8x300/8x300dasm.cpp
index 3f03ed19cfd..db231195f04 100644
--- a/src/devices/cpu/8x300/8x300dasm.cpp
+++ b/src/devices/cpu/8x300/8x300dasm.cpp
@@ -19,7 +19,7 @@
const char *const n8x300_disassembler::reg_names[32] =
{
"AUX", "R1", "R2", "R3", "R4", "R5", "R6", "IVL", "OVF", "R11",
- "R12", "R13", "R14", "R15", "R16", "IVR",
+ "Unused12", "Unused13", "Unused14", "Unused15", "Unused16", "IVR",
"LIV0", "LIV1", "LIV2", "LIV3", "LIV4", "LIV5", "LIV6", "LIV7",
"RIV0", "RIV1", "RIV2", "RIV3", "RIV4", "RIV5", "RIV6", "RIV7"
};
@@ -43,7 +43,7 @@ bool n8x300_disassembler::is_src_rot(uint16_t opcode)
u32 n8x300_disassembler::opcode_alignment() const
{
- return 1;
+ return 2;
}
offs_t n8x300_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params)
@@ -51,7 +51,7 @@ offs_t n8x300_disassembler::disassemble(std::ostream &stream, offs_t pc, const d
unsigned startpc = pc;
uint16_t opcode = opcodes.r16(pc);
uint8_t inst = opcode >> 13;
- pc+=1;
+ pc+=2;
// determine instruction
switch (inst)
@@ -127,7 +127,7 @@ offs_t n8x300_disassembler::disassemble(std::ostream &stream, offs_t pc, const d
}
break;
case 0x07:
- util::stream_format(stream, "JMP %04XH", (opcode & 0x1fff));
+ util::stream_format(stream, "JMP %04XH", (opcode & 0x1fff) << 1);
break;
}
diff --git a/src/devices/cpu/alpha/alpha.cpp b/src/devices/cpu/alpha/alpha.cpp
deleted file mode 100644
index 9ebfc6dd09e..00000000000
--- a/src/devices/cpu/alpha/alpha.cpp
+++ /dev/null
@@ -1,995 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Patrick Mackinlay
-
-/*
- * An implementation of the Digital Alpha CPU family.
- *
- * Sources:
- *
- * http://bitsavers.org/pdf/dec/alpha/21064-aa-RISC%20Microprocessor%20Preliminary%20Data%20Sheet-apr92.pdf
- * http://bitsavers.org/pdf/dec/alpha/Sites_AlphaAXPArchitectureReferenceManual_2ed_1995.pdf
- * https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=blob_plain;f=opcodes/alpha-opc.c;hb=HEAD
- * http://ftp.twaren.net/NetBSD/misc/dec-docs/
- *
- * TODO
- * - interrupts and exceptions
- * - address translation
- * - ibox/abox registers
- * - floating point instructions
- * - primary caches
- * - later cpu implementations
- * - instruction set extensions
- * - big-endian mode
- */
-
-#include "emu.h"
-#include "alpha.h"
-#include "common.h"
-
-#include "debugger.h"
-
-#include "softfloat3/source/include/softfloat.h"
-
-#define LOG_GENERAL (1U << 0)
-#define LOG_EXCEPTION (1U << 1)
-#define LOG_SYSCALLS (1U << 2)
-
-//#define VERBOSE (LOG_GENERAL | LOG_EXCEPTION)
-
-#include "logmacro.h"
-
-DEFINE_DEVICE_TYPE(DEC_21064, dec_21064_device, "21064", "DEC Alpha 21064")
-
-dec_21064_device::dec_21064_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : alpha_ev4_device(mconfig, DEC_21064, tag, owner, clock)
-{
-}
-
-alpha_ev4_device::alpha_ev4_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
- : alpha_device(mconfig, type, tag, owner, clock)
-{
-}
-
-alpha_device::alpha_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock)
- : cpu_device(mconfig, type, tag, owner, clock)
- , m_dasm_type(alpha_disassembler::dasm_type::TYPE_UNKNOWN)
- , m_as_config
- {
- address_space_config("0", ENDIANNESS_LITTLE, 64, 32, 0),
- address_space_config("1", ENDIANNESS_LITTLE, 64, 32, 0),
- address_space_config("2", ENDIANNESS_LITTLE, 64, 32, 0),
- address_space_config("3", ENDIANNESS_LITTLE, 64, 32, 0)
- }
- , m_srom_oe_cb(*this)
- , m_srom_data_cb(*this)
- , m_icount(0)
-{
-}
-
-void alpha_device::device_start()
-{
- set_icountptr(m_icount);
-
- save_item(NAME(m_pc));
- save_item(NAME(m_r));
- save_item(NAME(m_f));
-
- save_item(NAME(m_pal_mode));
-
- state_add(STATE_GENPC, "GENPC", m_pc).noshow();
- state_add(STATE_GENPCBASE, "CURPC", m_pc).noshow();
-
- state_add(64, "PC", m_pc);
-
- // integer registers
- for (unsigned i = 0; i < 32; i++)
- state_add(i, util::string_format("R%d", i).c_str(), m_r[i]);
-
- // floating point registers
- for (unsigned i = 0; i < 32; i++)
- state_add(i + 32, util::string_format("F%d", i).c_str(), m_f[i]);
-
- m_srom_oe_cb.resolve_safe();
- m_srom_data_cb.resolve_safe(0);
-}
-
-void alpha_device::device_reset()
-{
- m_pc = 0;
- m_pal_mode = true;
-}
-
-void alpha_device::execute_run()
-{
- while (m_icount > 0)
- {
- debugger_instruction_hook(m_pc);
-
- fetch(m_pc,
- [this](u32 const op)
- {
- // update the program counter
- m_pc += 4;
-
- // execute an instruction
- cpu_execute(op);
-
- // reset always-zero registers
- m_r[31] = 0;
- m_f[31] = 0;
- });
-
- m_icount--;
- }
-}
-
-void alpha_device::execute_set_input(int inputnum, int state)
-{
-}
-
-device_memory_interface::space_config_vector alpha_device::memory_space_config() const
-{
- /*
- * EV4 devices have a 34-bit physical address space. This is mapped using
- * the top two bits to select one of four memory spaces with the other 32
- * bits giving the offset within each space. This approach works out quite
- * well for the jensen hardware, which uses the first space for memory, and
- * the others for a variety of I/O memory mapping.
- *
- * Note: space numbers are multiplied by two to avoid the special handling
- * applied to the decrypted opcode space (number 3).
- */
- return space_config_vector {
- std::make_pair(0, &m_as_config[0]),
- std::make_pair(2, &m_as_config[1]),
- std::make_pair(4, &m_as_config[2]),
- std::make_pair(6, &m_as_config[3])
- };
-}
-
-bool alpha_device::memory_translate(int spacenum, int intention, offs_t &address)
-{
- u64 placeholder = s64(s32(address));
-
- if (cpu_translate(placeholder, intention))
- {
- address = placeholder;
-
- return true;
- }
-
- return false;
-}
-
-std::unique_ptr<util::disasm_interface> alpha_device::create_disassembler()
-{
- return std::make_unique<alpha_disassembler>(m_dasm_type);
-}
-
-void alpha_device::cpu_execute(u32 const op)
-{
- switch ((op >> 26) & 0x3f)
- {
- case 0x08: m_r[Ra(op)] = m_r[Rb(op)] + Disp_M(op); break; // lda
- case 0x09: m_r[Ra(op)] = m_r[Rb(op)] + (Disp_M(op) << 16); break; // ldah
- case 0x0b: load<u64>((m_r[Rb(op)] + Disp_M(op)) & ~7, [this, op](u64 data) { m_r[Ra(op)] = data; }); break; // ldq_u
- case 0x0f: store<u64>((m_r[Rb(op)] + Disp_M(op)) & ~7, m_r[Ra(op)]); break; // stq_u
-
- case 0x10: // INTA* (integer arithmetic)
- switch ((op >> 5) & 0xff)
- {
- // register variants
- case 0x00: m_r[Rc(op)] = s64(s32(m_r[Ra(op)]) + s32(m_r[Rb(op)])); break; // addl
- case 0x02: m_r[Rc(op)] = s64(s32(m_r[Ra(op)] << 2) + s32(m_r[Rb(op)])); break; // s4addl
- case 0x09: m_r[Rc(op)] = s64(s32(m_r[Ra(op)]) - s32(m_r[Rb(op)])); break; // subl
- case 0x0b: m_r[Rc(op)] = s64(s32(m_r[Ra(op)] << 2) - s32(m_r[Rb(op)])); break; // s4subl
- case 0x0f: // cmpbge
- {
- u8 temp = 0;
- for (unsigned i = 0; i < 8; i++)
- if (u8(m_r[Ra(op)] >> (i * 8)) >= u8(m_r[Rb(op)] >> (i * 8)))
- temp |= (1U << i);
-
- m_r[Rc(op)] = u64(temp);
- }
- break;
- case 0x12: m_r[Rc(op)] = s64(s32(m_r[Ra(op)] << 3) + s32(m_r[Rb(op)])); break; // s8addl
- case 0x1b: m_r[Rc(op)] = s64(s32(m_r[Ra(op)] << 3) - s32(m_r[Rb(op)])); break; // s8subl
- case 0x1d: m_r[Rc(op)] = m_r[Ra(op)] < m_r[Rb(op)]; break; // cmpult
- case 0x20: m_r[Rc(op)] = m_r[Ra(op)] + m_r[Rb(op)]; break; // addq
- case 0x22: m_r[Rc(op)] = (m_r[Ra(op)] << 2) + m_r[Rb(op)]; break; // s4addq
- case 0x29: m_r[Rc(op)] = m_r[Ra(op)] - m_r[Rb(op)]; break; // subq
- case 0x2b: m_r[Rc(op)] = (m_r[Ra(op)] << 2) - m_r[Rb(op)]; break; // s4subq
- case 0x2d: m_r[Rc(op)] = m_r[Ra(op)] == m_r[Rb(op)]; break; // cmpeq
- case 0x32: m_r[Rc(op)] = (m_r[Ra(op)] << 3) + m_r[Rb(op)]; break; // s8addq
- case 0x3b: m_r[Rc(op)] = (m_r[Ra(op)] << 3) - m_r[Rb(op)]; break; // s8subq
- case 0x3d: m_r[Rc(op)] = m_r[Ra(op)] <= m_r[Rb(op)]; break; // cmpule
- case 0x40: m_r[Rc(op)] = s64(s32(m_r[Ra(op)]) + s32(m_r[Rb(op)])); break; // addl/v
- case 0x49: m_r[Rc(op)] = s64(s32(m_r[Ra(op)]) - s32(m_r[Rb(op)])); break; // subl/v
- case 0x4d: m_r[Rc(op)] = s64(m_r[Ra(op)]) < s64(m_r[Rb(op)]); break; // cmplt
- case 0x60: m_r[Rc(op)] = m_r[Ra(op)] + m_r[Rb(op)]; break; // addq/v
- case 0x69: m_r[Rc(op)] = m_r[Ra(op)] - m_r[Rb(op)]; break; // subq/v
- case 0x6d: m_r[Rc(op)] = s64(m_r[Ra(op)]) <= s64(m_r[Rb(op)]); break; // cmple
-
- // immediate variants
- case 0x80: m_r[Rc(op)] = s64(s32(m_r[Ra(op)]) + s32(Im(op))); break; // addl
- case 0x82: m_r[Rc(op)] = s64(s32(m_r[Ra(op)] << 2) + s32(Im(op))); break; // s4addl
- case 0x89: m_r[Rc(op)] = s64(s32(m_r[Ra(op)]) - s32(Im(op))); break; // subl
- case 0x8b: m_r[Rc(op)] = s64(s32(m_r[Ra(op)] << 2) - s32(Im(op))); break; // s4subl
- case 0x8f: // cmpbge
- {
- u8 temp = 0;
- for (unsigned i = 0; i < 8; i++)
- if (u8(m_r[Ra(op)] >> (i * 8)) >= u8(Im(op)))
- temp |= (1U << i);
-
- m_r[Rc(op)] = u64(temp);
- }
- break;
- case 0x92: m_r[Rc(op)] = s64(s32(m_r[Ra(op)] << 3) + s32(Im(op))); break; // s4addl
- case 0x9b: m_r[Rc(op)] = s64(s32(m_r[Ra(op)] << 3) - s32(Im(op))); break; // s8subl
- case 0x9d: m_r[Rc(op)] = m_r[Ra(op)] < Im(op); break; // cmpult
- case 0xa0: m_r[Rc(op)] = m_r[Ra(op)] + Im(op); break; // addq
- case 0xa2: m_r[Rc(op)] = (m_r[Ra(op)] << 2) + Im(op); break; // s4addq
- case 0xa9: m_r[Rc(op)] = m_r[Ra(op)] - Im(op); break; // subq
- case 0xab: m_r[Rc(op)] = (m_r[Ra(op)] << 2) - Im(op); break; // s4subq
- case 0xad: m_r[Rc(op)] = m_r[Ra(op)] == Im(op); break; // cmpeq
- case 0xb2: m_r[Rc(op)] = (m_r[Ra(op)] << 3) + Im(op); break; // s8addq
- case 0xbb: m_r[Rc(op)] = (m_r[Ra(op)] << 3) - Im(op); break; // s8subq
- case 0xbd: m_r[Rc(op)] = m_r[Ra(op)] <= Im(op); break; // cmpule
- case 0xc0: m_r[Rc(op)] = s64(s32(m_r[Ra(op)]) + s32(Im(op))); break; // addl/v
- case 0xc9: m_r[Rc(op)] = s64(s32(m_r[Ra(op)]) - s32(Im(op))); break; // subl/v
- case 0xcd: m_r[Rc(op)] = s64(m_r[Ra(op)]) < s64(Im(op)); break; // cmplt
- case 0xe0: m_r[Rc(op)] = m_r[Ra(op)] + Im(op); break; // addq/v
- case 0xe9: m_r[Rc(op)] = m_r[Ra(op)] - Im(op); break; // subq/v
- case 0xed: m_r[Rc(op)] = s64(m_r[Ra(op)]) <= s64(Im(op)); break; // cmple
- }
- break;
- case 0x11: // INTL* (integer logical)
- switch ((op >> 5) & 0xff)
- {
- // register variants
- case 0x00: m_r[Rc(op)] = m_r[Ra(op)] & m_r[Rb(op)]; break; // and
- case 0x08: m_r[Rc(op)] = m_r[Ra(op)] & ~m_r[Rb(op)]; break; // bic
- case 0x14: // cmovlbs
- if (BIT(m_r[Ra(op)], 0))
- m_r[Rc(op)] = m_r[Rb(op)];
- break;
- case 0x16: // cmovlbc
- if (!BIT(m_r[Ra(op)], 0))
- m_r[Rc(op)] = m_r[Rb(op)];
- break;
- case 0x20: m_r[Rc(op)] = m_r[Ra(op)] | m_r[Rb(op)]; break; // bis
- case 0x24: // cmoveq
- if (m_r[Ra(op)] == 0)
- m_r[Rc(op)] = m_r[Rb(op)];
- break;
- case 0x26: // cmovne
- if (m_r[Ra(op)] != 0)
- m_r[Rc(op)] = m_r[Rb(op)];
- break;
- case 0x28: m_r[Rc(op)] = m_r[Ra(op)] | ~m_r[Rb(op)]; break; // ornot
- case 0x40: m_r[Rc(op)] = m_r[Ra(op)] ^ m_r[Rb(op)]; break; // xor
- case 0x44: // cmovlt
- if (s64(m_r[Ra(op)]) < 0)
- m_r[Rc(op)] = m_r[Rb(op)];
- break;
- case 0x46: // cmovge
- if (s64(m_r[Ra(op)]) >= 0)
- m_r[Rc(op)] = m_r[Rb(op)];
- break;
- case 0x48: m_r[Rc(op)] = m_r[Ra(op)] ^ ~m_r[Rb(op)]; break; // eqv
- case 0x61: m_r[Rc(op)] = m_r[Rb(op)]; break; // amask
- case 0x64: // cmovle
- if (s64(m_r[Ra(op)]) <= 0)
- m_r[Rc(op)] = m_r[Rb(op)];
- break;
- case 0x66: // cmovgt
- if (s64(m_r[Ra(op)]) > 0)
- m_r[Rc(op)] = m_r[Rb(op)];
- break;
-
- // immediate variants
- case 0x80: m_r[Rc(op)] = m_r[Ra(op)] & Im(op); break; // and
- case 0x88: m_r[Rc(op)] = m_r[Ra(op)] & ~Im(op); break; // bic
- case 0x94: // cmovlbs
- if (BIT(m_r[Ra(op)], 0))
- m_r[Rc(op)] = Im(op);
- break;
- case 0x96: // cmovlbc
- if (!BIT(m_r[Ra(op)], 0))
- m_r[Rc(op)] = Im(op);
- break;
- case 0xa0: m_r[Rc(op)] = m_r[Ra(op)] | Im(op); break; // bis
- case 0xa4: // cmoveq
- if (m_r[Ra(op)] == 0)
- m_r[Rc(op)] = Im(op);
- break;
- case 0xa6: // cmovne
- if (m_r[Ra(op)] != 0)
- m_r[Rc(op)] = Im(op);
- break;
- case 0xa8: m_r[Rc(op)] = m_r[Ra(op)] | ~Im(op); break; // ornot
- case 0xc0: m_r[Rc(op)] = m_r[Ra(op)] ^ Im(op); break; // xor
- case 0xc4: // cmovlt
- if (s64(m_r[Ra(op)]) < 0)
- m_r[Rc(op)] = Im(op);
- break;
- case 0xc6: // cmovge
- if (s64(m_r[Ra(op)]) >= 0)
- m_r[Rc(op)] = Im(op);
- break;
- case 0xc8: m_r[Rc(op)] = m_r[Ra(op)] ^ ~Im(op); break; // eqv
- case 0xe1: m_r[Rc(op)] = Im(op); break; // amask
- case 0xe4: // cmovle
- if (s64(m_r[Ra(op)]) <= 0)
- m_r[Rc(op)] = Im(op);
- break;
- case 0xe6: // cmovgt
- if (s64(m_r[Ra(op)]) > 0)
- m_r[Rc(op)] = Im(op);
- break;
- case 0xec: m_r[Rc(op)] = 0; break; // implver
- }
- break;
- case 0x12: // INTS* (integer shift)
- switch ((op >> 5) & 0xff)
- {
- // register variants
- case 0x02: m_r[Rc(op)] = m_r[Ra(op)] & zap_mask(u8(0x01) << (m_r[Rb(op)] & 7)); break; // mskbl
- case 0x06: m_r[Rc(op)] = (m_r[Ra(op)] >> ((m_r[Rb(op)] & 7) * 8)) & zap_mask(~u8(0x01)); break; // extbl
- case 0x0b: m_r[Rc(op)] = (m_r[Ra(op)] << ((m_r[Rb(op)] & 7) * 8)) & zap_mask(~(u8(0x01) << (m_r[Rb(op)] & 7))); break; // insbl
- case 0x12: m_r[Rc(op)] = m_r[Ra(op)] & zap_mask(u8(0x03) << (m_r[Rb(op)] & 7)); break; // mskwl
- case 0x16: m_r[Rc(op)] = (m_r[Ra(op)] >> ((m_r[Rb(op)] & 7) * 8)) & zap_mask(~u8(0x03)); break; // extwl
- case 0x1b: m_r[Rc(op)] = (m_r[Ra(op)] << ((m_r[Rb(op)] & 7) * 8)) & zap_mask(~(u8(0x03) << (m_r[Rb(op)] & 7))); break; // inswl
- case 0x22: m_r[Rc(op)] = m_r[Ra(op)] & zap_mask(u8(0x0f) << (m_r[Rb(op)] & 7)); break; // mskll
- case 0x26: m_r[Rc(op)] = (m_r[Ra(op)] >> ((m_r[Rb(op)] & 7) * 8)) & zap_mask(~u8(0x0f)); break; // extll
- case 0x2b: m_r[Rc(op)] = (m_r[Ra(op)] << ((m_r[Rb(op)] & 7) * 8)) & zap_mask(~(u8(0x0f) << (m_r[Rb(op)] & 7))); break; // insll
- case 0x30: m_r[Rc(op)] = m_r[Ra(op)] & zap_mask(m_r[Rb(op)]); break; // zap
- case 0x31: m_r[Rc(op)] = m_r[Ra(op)] & ~zap_mask(m_r[Rb(op)]); break; // zapnot
- case 0x32: m_r[Rc(op)] = m_r[Ra(op)] & zap_mask(u8(0xff) << (m_r[Rb(op)] & 7)); break; // mskql
- case 0x34: m_r[Rc(op)] = m_r[Ra(op)] >> (m_r[Rb(op)] & 63); break; // srl
- case 0x36: m_r[Rc(op)] = (m_r[Ra(op)] >> ((m_r[Rb(op)] & 7) * 8)) & zap_mask(u8(~u8(0xff))); break; // extql
- case 0x39: m_r[Rc(op)] = m_r[Ra(op)] << (m_r[Rb(op)] & 63); break; // sll
- case 0x3b: m_r[Rc(op)] = (m_r[Ra(op)] << ((m_r[Rb(op)] & 7) * 8)) & zap_mask(~(u8(0xff) << (m_r[Rb(op)] & 7))); break; // insql
- case 0x3c: m_r[Rc(op)] = s64(m_r[Ra(op)]) >> (m_r[Rb(op)] & 63); break; // sra
- case 0x52: m_r[Rc(op)] = m_r[Ra(op)] & zap_mask(u8(0x03) >> (8 - (m_r[Rb(op)] & 7))); break; // mskwh
- case 0x57: m_r[Rc(op)] = (m_r[Ra(op)] >> (64 - ((m_r[Rb(op)] & 7) * 8))) & zap_mask(~(u8(0x03) >> (8 - (m_r[Rb(op)] & 7)))); break; // inswh
- case 0x5a: m_r[Rc(op)] = (m_r[Ra(op)] << (64 - ((m_r[Rb(op)] & 7) * 8))) & zap_mask(~u8(0x03)); break; // extwh
- case 0x62: m_r[Rc(op)] = m_r[Ra(op)] & zap_mask(u8(0x0f) >> (8 - (m_r[Rb(op)] & 7))); break; // msklh
- case 0x67: m_r[Rc(op)] = (m_r[Ra(op)] >> (64 - ((m_r[Rb(op)] & 7) * 8))) & zap_mask(~(u8(0x0f) >> (8 - (m_r[Rb(op)] & 7)))); break; // inslh
- case 0x6a: m_r[Rc(op)] = (m_r[Ra(op)] << (64 - ((m_r[Rb(op)] & 7) * 8))) & zap_mask(~u8(0x0f)); break; // extlh
- case 0x72: m_r[Rc(op)] = m_r[Ra(op)] & zap_mask(u8(0xff) >> (8 - (m_r[Rb(op)] & 7))); break; // mskqh
- case 0x77: m_r[Rc(op)] = (m_r[Ra(op)] >> (64 - ((m_r[Rb(op)] & 7) * 8))) & zap_mask(~(u8(0xff) >> (8 - (m_r[Rb(op)] & 7)))); break; // insqh
- case 0x7a: m_r[Rc(op)] = (m_r[Ra(op)] << (64 - ((m_r[Rb(op)] & 7) * 8))) & zap_mask(u8(~u8(0xff))); break; // extqh
-
- // immediate variants
- case 0x82: m_r[Rc(op)] = m_r[Ra(op)] & zap_mask(u8(0x01) << (Im(op) & 7)); break; // mskbl
- case 0x86: m_r[Rc(op)] = (m_r[Ra(op)] >> ((Im(op) & 7) * 8)) & zap_mask(~u8(0x01)); break; // extbl
- case 0x8b: m_r[Rc(op)] = (m_r[Ra(op)] << ((Im(op) & 7) * 8)) & zap_mask(~(u8(0x01) << (Im(op) & 7))); break; // insbl
- case 0x92: m_r[Rc(op)] = m_r[Ra(op)] & zap_mask(u8(0x03) << (Im(op) & 7)); break; // mskwl
- case 0x96: m_r[Rc(op)] = (m_r[Ra(op)] >> ((Im(op) & 7) * 8)) & zap_mask(~u8(0x03)); break; // extwl
- case 0x9b: m_r[Rc(op)] = (m_r[Ra(op)] << ((Im(op) & 7) * 8)) & zap_mask(~(u8(0x03) << (Im(op) & 7))); break; // inswl
- case 0xa2: m_r[Rc(op)] = m_r[Ra(op)] & zap_mask(u8(0x0f) << (Im(op) & 7)); break; // mskll
- case 0xa6: m_r[Rc(op)] = (m_r[Ra(op)] >> ((Im(op) & 7) * 8)) & zap_mask(~u8(0x0f)); break; // extll
- case 0xab: m_r[Rc(op)] = (m_r[Ra(op)] << ((Im(op) & 7) * 8)) & zap_mask(~(u8(0x0f) << (Im(op) & 7))); break; // insll
- case 0xb0: m_r[Rc(op)] = m_r[Ra(op)] & zap_mask(Im(op)); break; // zap
- case 0xb1: m_r[Rc(op)] = m_r[Ra(op)] & ~zap_mask(Im(op)); break; // zapnot
- case 0xb2: m_r[Rc(op)] = m_r[Ra(op)] & zap_mask(u8(0xff) << (Im(op) & 7)); break; // mskql
- case 0xb4: m_r[Rc(op)] = m_r[Ra(op)] >> (Im(op) & 63); break; // srl
- case 0xb6: m_r[Rc(op)] = (m_r[Ra(op)] >> ((Im(op) & 7) * 8)) & zap_mask(u8(~u8(0xff))); break; // extql
- case 0xb9: m_r[Rc(op)] = m_r[Ra(op)] << (Im(op) & 63); break; // sll
- case 0xbb: m_r[Rc(op)] = (m_r[Ra(op)] << ((Im(op) & 7) * 8)) & zap_mask(~(u8(0xff) << (Im(op) & 7))); break; // insql
- case 0xbc: m_r[Rc(op)] = s64(m_r[Ra(op)]) >> (Im(op) & 63); break; // sra
- case 0xd2: m_r[Rc(op)] = m_r[Ra(op)] & zap_mask(u8(0x03) >> (8 - (Im(op) & 7))); break; // mskwh
- case 0xd7: m_r[Rc(op)] = (m_r[Ra(op)] >> (64 - ((Im(op) & 7) * 8))) & zap_mask(~(u8(0x03) >> (8 - (Im(op) & 7)))); break; // inswh
- case 0xda: m_r[Rc(op)] = (m_r[Ra(op)] << (64 - ((Im(op) & 7) * 8))) & zap_mask(~u8(0x03)); break; // extwh
- case 0xe2: m_r[Rc(op)] = m_r[Ra(op)] & zap_mask(u8(0x0f) >> (8 - (Im(op) & 7))); break; // msklh
- case 0xe7: m_r[Rc(op)] = (m_r[Ra(op)] >> (64 - ((Im(op) & 7) * 8))) & zap_mask(~(u8(0x0f) >> (8 - (Im(op) & 7)))); break; // inslh
- case 0xea: m_r[Rc(op)] = (m_r[Ra(op)] << (64 - ((Im(op) & 7) * 8))) & zap_mask(~u8(0x0f)); break; // extlh
- case 0xf2: m_r[Rc(op)] = m_r[Ra(op)] & zap_mask(u8(0xff) >> (8 - (Im(op) & 7))); break; // mskqh
- case 0xf7: m_r[Rc(op)] = (m_r[Ra(op)] >> (64 - ((Im(op) & 7) * 8))) & zap_mask(~(u8(0xff) >> (8 - (Im(op) & 7)))); break; // insqh
- case 0xfa: m_r[Rc(op)] = (m_r[Ra(op)] << (64 - ((Im(op) & 7) * 8))) & zap_mask(u8(~u8(0xff))); break; // extqh
- }
- break;
- case 0x13: // INTM* (integer multiply)
- switch ((op >> 5) & 0xff)
- {
- // register variants
- case 0x00: m_r[Rc(op)] = s64(s32(u32(m_r[Ra(op)]) * u32(m_r[Rb(op)]))); break; // mull
- case 0x20: m_r[Rc(op)] = m_r[Ra(op)] * m_r[Rb(op)]; break; // mulq
- case 0x30: mulu_64x64(m_r[Ra(op)], m_r[Rb(op)], &m_r[Rc(op)]); break; // umulh
- case 0x40: m_r[Rc(op)] = s64(s32(u32(m_r[Ra(op)]) * u32(m_r[Rb(op)]))); break; // mull/v
- case 0x60: m_r[Rc(op)] = m_r[Ra(op)] * m_r[Rb(op)]; break; // mulq/v
-
- // immediate variants
- case 0x80: m_r[Rc(op)] = s64(s32(u32(m_r[Ra(op)]) * u32(Im(op)))); break; // mull
- case 0xa0: m_r[Rc(op)] = m_r[Ra(op)] * Im(op); break; // mulq
- case 0xb0: mulu_64x64(m_r[Ra(op)], Im(op), &m_r[Rc(op)]); break; // umulh
- case 0xc0: m_r[Rc(op)] = s64(s32(u32(m_r[Ra(op)]) * u32(Im(op)))); break; // mull/v
- case 0xe0: m_r[Rc(op)] = m_r[Ra(op)] * Im(op); break; // mulq/v
- }
- break;
- //case 0x14: // ITFP* (integer to floating)
- //case 0x15: // FLTV* (vax floating)
- //case 0x16: // FLTI* (ieee floating)
- //case 0x17: // FLTL* (floating)
-
- case 0x18: // MISC* (miscellaneous)
- // TODO: all of these are effectively no-ops for now
- switch (u16(op))
- {
- case 0x0000: break; // trapb
- case 0x0400: break; // excb
- case 0x4000: break; // mb
- case 0x4400: break; // wmb
- case 0x8000: break; // fetch
- case 0xa000: break; // fetch_m
- case 0xc000: break; // rpcc
- case 0xe000: break; // rc
- case 0xe800: break; // ecb
- case 0xf000: break; // rs
- case 0xf800: break; // wh64
- }
- break;
-
- case 0x1a: // JSR*
- m_r[Ra(op)] = m_pc;
- m_pc = m_r[Rb(op)] & ~3;
- break;
-
- case 0x20: load<u32>(m_r[Rb(op)] + Disp_M(op), [this, op](u32 data) { m_f[Ra(op)] = u32_to_f_floating(data); }); break; // ldf
- case 0x21: load<u64>(m_r[Rb(op)] + Disp_M(op), [this, op](u64 data) { m_f[Ra(op)] = u64_to_g_floating(data); }); break; // ldg
- case 0x22: load<u32>(m_r[Rb(op)] + Disp_M(op), [this, op](u32 data) { m_f[Ra(op)] = f32_to_f64(float32_t{ data }).v; }); break; // lds
- case 0x23: load<u64>(m_r[Rb(op)] + Disp_M(op), [this, op](u64 data) { m_f[Ra(op)] = data; }); break; // ldt
- case 0x24: store<u32>(m_r[Rb(op)] + Disp_M(op), f_floating_to_u32(m_f[Ra(op)])); break; // stf
- case 0x25: store<u64>(m_r[Rb(op)] + Disp_M(op), u64_to_g_floating(m_f[Ra(op)])); break; // stg
- case 0x26: store<u32>(m_r[Rb(op)] + Disp_M(op), f64_to_f32(float64_t{ m_f[Ra(op)] }).v); break; // sts
- case 0x27: store<u64>(m_r[Rb(op)] + Disp_M(op), m_f[Ra(op)]); break; // stt
- case 0x28: load<u32>(m_r[Rb(op)] + Disp_M(op), [this, op](s32 data) { m_r[Ra(op)] = s64(data); }); break; // ldl
- case 0x29: load<u64>(m_r[Rb(op)] + Disp_M(op), [this, op](u64 data) { m_r[Ra(op)] = data; }); break; // ldq
- case 0x2a: // ldl_l
- load_l<u32>(m_r[Rb(op)] + Disp_M(op),
- [this, op](address_space &space, u64 address, s32 data)
- {
- if (m_lock_watch)
- m_lock_watch->remove();
-
- m_r[Ra(op)] = s64(data);
-
- space.install_write_tap(offs_t(address & ~15), offs_t(address | 15), "ldl_l",
- [this](offs_t offset, u64 &data, u64 mem_mask)
- {
- m_lock_watch->remove();
- m_lock_watch = nullptr;
- });
- });
- break;
- case 0x2b: // ldq_l
- load_l<u64>(m_r[Rb(op)] + Disp_M(op),
- [this, op](address_space &space, u64 address, u64 data)
- {
- if (m_lock_watch)
- m_lock_watch->remove();
-
- m_r[Ra(op)] = data;
-
- space.install_write_tap(offs_t(address & ~15), offs_t(address | 15), "ldq_l",
- [this](offs_t offset, u64 &data, u64 mem_mask)
- {
- m_lock_watch->remove();
- m_lock_watch = nullptr;
- });
- });
- break;
- case 0x2c: store<u32>(m_r[Rb(op)] + Disp_M(op), u32(m_r[Ra(op)])); break; // stl
- case 0x2d: store<u64>(m_r[Rb(op)] + Disp_M(op), m_r[Ra(op)]); break; // stq
- case 0x2e: // stl_c
- if (m_lock_watch)
- {
- store<u32>(m_r[Rb(op)] + Disp_M(op), u32(m_r[Ra(op)]));
- m_r[Ra(op)] = 1;
-
- m_lock_watch->remove();
- m_lock_watch = nullptr;
- }
- else
- m_r[Ra(op)] = 0;
- break;
- case 0x2f: // stq_c
- if (m_lock_watch)
- {
- store<u64>(m_r[Rb(op)] + Disp_M(op), m_r[Ra(op)]);
- m_r[Ra(op)] = 1;
-
- m_lock_watch->remove();
- m_lock_watch = nullptr;
- }
- else
- m_r[Ra(op)] = 0;
- break;
-
- // branch format
- case 0x30: // br
- m_r[Ra(op)] = m_pc;
- m_pc += Disp_B(op);
- break;
- case 0x31: // fbeq
- if (!(m_f[Ra(op)] & 0x7fffffff'ffffffffULL))
- m_pc += Disp_B(op);
- break;
- case 0x32: // fblt
- if (BIT(m_f[Ra(op)], 63) && (m_f[Ra(op)] & 0x7fffffff'ffffffffULL))
- m_pc += Disp_B(op);
- break;
- case 0x33: // fble
- if (BIT(m_f[Ra(op)], 63) || !(m_f[Ra(op)] & 0x7fffffff'ffffffffULL))
- m_pc += Disp_B(op);
- break;
- case 0x34: // bsr
- m_r[Ra(op)] = m_pc;
- m_pc += Disp_B(op);
- break;
- case 0x35: // fbne
- if (m_f[Ra(op)] & 0x7fffffff'ffffffffULL)
- m_pc += Disp_B(op);
- break;
- case 0x36: // fbge
- if (!BIT(m_f[Ra(op)], 63) || !(m_f[Ra(op)] & 0x7fffffff'ffffffffULL))
- m_pc += Disp_B(op);
- break;
- case 0x37: // fbgt
- if (!BIT(m_f[Ra(op)], 63) && (m_f[Ra(op)] & 0x7fffffff'ffffffffULL))
- m_pc += Disp_B(op);
- break;
- case 0x38: // blbc
- if (!BIT(m_r[Ra(op)], 0))
- m_pc += Disp_B(op);
- break;
- case 0x39: // beq
- if (m_r[Ra(op)] == 0)
- m_pc += Disp_B(op);
- break;
- case 0x3a: // blt
- if (s64(m_r[Ra(op)]) < 0)
- m_pc += Disp_B(op);
- break;
- case 0x3b: // ble
- if (s64(m_r[Ra(op)]) <= 0)
- m_pc += Disp_B(op);
- break;
- case 0x3c: // blbs
- if (BIT(m_r[Ra(op)], 0))
- m_pc += Disp_B(op);
- break;
- case 0x3d: // bne
- if (m_r[Ra(op)] != 0)
- m_pc += Disp_B(op);
- break;
- case 0x3e: // bge
- if (s64(m_r[Ra(op)]) >= 0)
- m_pc += Disp_B(op);
- break;
- case 0x3f: // bgt
- if (s64(m_r[Ra(op)]) > 0)
- m_pc += Disp_B(op);
- break;
- }
-}
-
-u64 alpha_device::zap_mask(u8 const zap_bits)
-{
- u64 mask = 0;
-
- for (unsigned i = 0; i < 8; i++)
- if (!BIT(zap_bits, i))
- mask |= (0xffULL << (i << 3));
-
- return mask;
-}
-
-// transform from f_floating memory to register format
-u64 alpha_device::u32_to_f_floating(u32 const data)
-{
- if (!BIT(data, 14) && (data & 0x00003f80UL))
- return
- (u64(data & 0x0000c000UL) << 48) |
- (u64(7) << 61) |
- (u64(data & 0x00003fffUL) << 45) |
- (u64(data & 0xffff0000UL) << 13);
- else
- return
- (u64(data & 0x0000c000UL) << 48) |
- (u64(data & 0x00003fffUL) << 45) |
- (u64(data & 0xffff0000UL) << 13);
-}
-
-// transform from f_floating register to memory format
-u32 alpha_device::f_floating_to_u32(u64 const data)
-{
- return
- (u32(data >> 48) & 0x0000c000UL) |
- (u32(data >> 45) & 0x00003fffUL) |
- (u32(data >> 13) & 0xffff0000UL);
-}
-
-// transform between g_floating register and memory format
-u64 alpha_device::u64_to_g_floating(u64 const data)
-{
- return
- ((data & 0x00000000'0000ffffULL) << 48) |
- ((data & 0x00000000'ffff0000ULL) << 16) |
- ((data & 0x0000ffff'00000000ULL) >> 16) |
- ((data & 0xffff0000'00000000ULL) >> 48);
-}
-
-bool alpha_ev4_device::cpu_translate(u64 &address, int intention)
-{
- // trim virtual address to 43 bits
- address &= 0x7ff'ffffffff;
-
- if (intention & TRANSLATE_FETCH)
- {
- // instruction superpage mapping
- if ((m_ibx[IBX_ICCSR] & IBX_ICCSR_R_MAP) && !(m_ibx[IBX_PS] & IBX_PS_R_CM) && (address >> 41) == 2)
- {
- address &= 0x3'ffffffff;
-
- return true;
- }
- }
- else
- {
- // data superpage 1 mapping
- if ((m_abx[ABX_ABOX_CTL] & ABX_ABOX_CTL_SPE_1) && !(m_ibx[IBX_PS] & IBX_PS_R_CM) && (address >> 30) == 0x1ffe)
- {
- address &= 0x3fffffff;
-
- return true;
- }
-
- // data superpage 2 mapping
- if ((m_abx[ABX_ABOX_CTL] & ABX_ABOX_CTL_SPE_2) && !(m_ibx[IBX_PS] & IBX_PS_R_CM) && (address >> 41) == 2)
- {
- address &= 0x3'ffffffff;
-
- return true;
- }
- }
-
- return true;
-}
-
-template <typename T, typename U> std::enable_if_t<std::is_convertible<U, std::function<void(T)>>::value, void> alpha_device::load(u64 address, U &&apply)
-{
- cpu_translate(address, TRANSLATE_READ);
-
- unsigned const s = (address >> 31) & 6;
-
- switch (sizeof(T))
- {
- case 1: apply(T(space(s).read_byte(address))); break;
- case 2: apply(T(space(s).read_word(address))); break;
- case 4: apply(T(space(s).read_dword(address))); break;
- case 8: apply(T(space(s).read_qword(address))); break;
- }
-}
-
-template <typename T, typename U> std::enable_if_t<std::is_convertible<U, std::function<void(address_space &, u64, T)>>::value, void> alpha_device::load_l(u64 address, U &&apply)
-{
- cpu_translate(address, TRANSLATE_READ);
-
- unsigned const s = (address >> 31) & 6;
-
- switch (sizeof(T))
- {
- case 4: apply(space(s), address, T(space(s).read_dword(address))); break;
- case 8: apply(space(s), address, T(space(s).read_qword(address))); break;
- }
-}
-
-template <typename T, typename U> std::enable_if_t<std::is_convertible<U, T>::value, void> alpha_device::store(u64 address, U data, T mem_mask)
-{
- cpu_translate(address, TRANSLATE_WRITE);
-
- unsigned const s = (address >> 31) & 6;
-
- switch (sizeof(T))
- {
- case 1: space(s).write_byte(address, T(data)); break;
- case 2: space(s).write_word(address, T(data), mem_mask); break;
- case 4: space(s).write_dword(address, T(data), mem_mask); break;
- case 8: space(s).write_qword(address, T(data), mem_mask); break;
- }
-}
-
-void alpha_device::fetch(u64 address, std::function<void(u32)> &&apply)
-{
- cpu_translate(address, TRANSLATE_FETCH);
-
- apply(icache_fetch(address));
-}
-
-u32 alpha_device::read_srom(unsigned const bits)
-{
- u32 data = 0;
-
- for (unsigned i = 0; i < bits; i++)
- if (m_srom_data_cb())
- data |= (1U << i);
-
- return data;
-}
-
-void alpha_ev4_device::device_start()
-{
- alpha_device::device_start();
-
- save_item(NAME(m_ibx));
- save_item(NAME(m_abx));
- save_item(NAME(m_pt));
-}
-
-void alpha_ev4_device::device_reset()
-{
- alpha_device::device_reset();
-
- m_ibx[IBX_ICCSR] = IBX_ICCSR_R_PC0 | IBX_ICCSR_R_PC1; // FIXME: ASN
- m_ibx[IBX_PAL_BASE] = 0;
-
- m_abx[ABX_ABOX_CTL] = 0;
- m_abx[ABX_BIU_CTL] = 0;
-}
-
-void alpha_ev4_device::cpu_execute(u32 const op)
-{
- switch (op >> 26)
- {
- case 0x00: // call_pal
- {
- u16 offset = CALL_PAL | ((op & 0x3f) << 6);
- if (op & 0x80)
- {
- // unprivileged
- if (op & CALL_PAL_MASK)
- offset = OPCDEC;
- else
- offset |= 0x1000;
- }
- else
- {
- // privileged
- if ((op & CALL_PAL_MASK) || (m_ibx[IBX_PS] & IBX_PS_R_CM))
- offset = OPCDEC;
- }
-
- m_ibx[IBX_EXC_ADDR] = m_pc;
- if (m_pal_mode)
- m_ibx[IBX_EXC_ADDR] |= 1;
-
- m_pal_mode = true;
- m_pc = m_ibx[IBX_PAL_BASE] | offset;
- }
- break;
-
- case 0x19: // hw_mfpr
- if (op & 0x20)
- m_r[Ra(op)] = ibx_get(Rc(op));
- if (op & 0x40)
- m_r[Ra(op)] = abx_get(Rc(op));
- if (op & 0x80)
- m_r[Ra(op)] = m_pt[Rc(op)];
- break;
-
- case 0x1d: // hw_mtpr
- if (op & 0x20)
- ibx_set(Rc(op), m_r[Ra(op)]);
- if (op & 0x40)
- abx_set(Rc(op), m_r[Ra(op)]);
- if (op & 0x80)
- m_pt[Rc(op)] = m_r[Ra(op)];
- break;
- case 0x1e: // hw_rei
- m_pc = m_ibx[IBX_EXC_ADDR] & ~3;
- m_pal_mode = BIT(m_ibx[IBX_EXC_ADDR], 0);
-
- if (m_lock_watch)
- {
- m_lock_watch->remove();
- m_lock_watch = nullptr;
- }
- break;
-
- default:
- alpha_device::cpu_execute(op);
- break;
- }
-}
-
-u64 alpha_ev4_device::ibx_get(u8 reg)
-{
- switch (ibx_reg(reg))
- {
- // PALmode only
- case IBX_ITB_PTE:
- case IBX_ITB_PTE_TEMP:
- if (m_pal_mode)
- return m_ibx[reg];
- else
- return 0;
-
- case IBX_ICCSR:
- case IBX_EXC_ADDR:
- case IBX_SL_RCV:
- case IBX_PS:
- case IBX_EXC_SUM:
- case IBX_PAL_BASE:
- case IBX_HIRR:
- case IBX_SIRR:
- case IBX_ASTRR:
- case IBX_HIER:
- case IBX_SIER:
- case IBX_ASTER:
- return m_ibx[reg];
-
- default:
- logerror("invalid mfpr/i register %d (%s)\n", reg, machine().describe_context());
- return 0;
- }
-}
-
-#define IBX_SET(Reg, Field) if (data & IBX_##Reg##_W_##Field) m_ibx[reg] |= IBX_##Reg##_R_##Field
-#define IBX_SHL(Reg, Field, Shift) m_ibx[reg] |= (data & IBX_##Reg##_W_##Field) << Shift
-#define IBX_SHR(Reg, Field, Shift) m_ibx[reg] |= (data & IBX_##Reg##_W_##Field) >> Shift
-
-void alpha_ev4_device::ibx_set(u8 reg, u64 data)
-{
- switch (ibx_reg(reg))
- {
- // PALmode only
- case IBX_TB_TAG:
- case IBX_ITB_PTE:
- case IBX_ITBZAP:
- case IBX_ITBASM:
- case IBX_ITBIS:
- if (m_pal_mode)
- {
- m_ibx[reg] = data;
- return;
- }
- break;
-
- case IBX_EXC_ADDR:
- case IBX_EXC_SUM:
- case IBX_SIRR:
- case IBX_ASTRR:
- case IBX_HIER:
- case IBX_SIER:
- case IBX_ASTER:
- case IBX_SL_CLR:
- case IBX_SL_XMIT:
- m_ibx[reg] = data;
- return;
-
- case IBX_ICCSR:
- m_ibx[reg] = data & IBX_ICCSR_R_PCE;
- IBX_SET(ICCSR, PC1);
- IBX_SET(ICCSR, PC0);
- IBX_SHL(ICCSR, PCMUX0, 1);
- IBX_SHR(ICCSR, GRP1, 19);
- IBX_SHR(ICCSR, ASN, 19);
- return;
-
- case IBX_PS:
- m_ibx[reg] = 0;
- IBX_SET(PS, CM0);
- IBX_SET(PS, CM1);
- return;
-
- case IBX_PAL_BASE:
- m_ibx[reg] = data & IBX_PAL_BASE_W;
- return;
-
- default:
- logerror("invalid mtpr/i register %d (%s)\n", reg, machine().describe_context());
- break;
- }
-}
-
-u64 alpha_ev4_device::abx_get(u8 reg)
-{
- switch (abx_reg(reg))
- {
- case ABX_DTB_PTE:
- case ABX_DTB_PTE_TEMP:
- case ABX_MM_CSR:
- case ABX_VA:
- case ABX_BIU_ADDR:
- case ABX_BIU_STAT:
- case ABX_DC_STAT:
- case ABX_FILL_ADDR:
- return m_abx[reg];
-
- default:
- logerror("invalid mfpr/a register %d (%s)\n", reg, machine().describe_context());
- return 0;
- }
-}
-
-void alpha_ev4_device::abx_set(u8 reg, u64 data)
-{
- switch (abx_reg(reg))
- {
- case ABX_TB_CTL:
- case ABX_DTB_PTE:
- case ABX_DTBZAP:
- case ABX_DTBASM:
- case ABX_DTBIS:
- case ABX_ABOX_CTL:
- case ABX_ALT_MODE:
- case ABX_CC:
- case ABX_CC_CTL:
- case ABX_BIU_CTL:
- case ABX_FILL_SYNDROME:
- case ABX_BC_TAG:
- case ABX_FLUSH_IC:
- case ABX_FLUSH_IC_ASM:
- m_abx[reg] = data;
- return;
-
- default:
- logerror("invalid mtpr/a register %d (%s)\n", reg, machine().describe_context());
- break;
- }
-}
-
-void dec_21064_device::device_reset()
-{
- alpha_ev4_device::device_reset();
-
- m_srom_oe_cb(0);
-
- // load icache from srom
- for (icache_block &block : m_icache)
- {
- block.lw[0] = read_srom(32);
- block.lw[2] = read_srom(32);
- block.lw[4] = read_srom(32);
- block.lw[6] = read_srom(32);
-
- block.tag = read_srom(21);
- block.aav = read_srom(8);
-
- block.lw[1] = read_srom(32);
- block.lw[3] = read_srom(32);
- block.lw[5] = read_srom(32);
- block.lw[7] = read_srom(32);
-
- block.bht = read_srom(8);
- }
-
- m_srom_oe_cb(1);
-}
-
-u32 dec_21064_device::icache_fetch(u64 const address)
-{
- icache_block &block = m_icache[(address >> 5) & 0xff];
-
- // check tag, valid, and asm or asn
- if ((block.tag != (address >> 13)) || !(block.aav & AAV_V) || (!(block.aav & AAV_ASM) && ((block.aav & AAV_ASN) != (((m_ibx[IBX_ICCSR] & IBX_ICCSR_R_ASN) >> 28)))))
- {
- // fetch a new block
- block.tag = address >> 13;
- block.aav = AAV_V | ((m_ibx[IBX_ICCSR] & IBX_ICCSR_R_ASN) >> 28); // TODO: set ASM depending on PTE
-
- // always set ASM if istream superpage mapping is enabled
- if (m_ibx[IBX_ICCSR] & IBX_ICCSR_R_MAP)
- block.aav |= AAV_ASM;
-
- address_space &s = space((address >> 31) & 6);
- for (unsigned i = 0; i < 8; i++)
- block.lw[i] = s.read_dword(address | (i << 2));
- }
-
- return block.lw[(address >> 2) & 7];
-}
diff --git a/src/devices/cpu/alpha/alpha.h b/src/devices/cpu/alpha/alpha.h
deleted file mode 100644
index ac1f5e60e2f..00000000000
--- a/src/devices/cpu/alpha/alpha.h
+++ /dev/null
@@ -1,284 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Patrick Mackinlay
-
-#ifndef MAME_CPU_ALPHA_ALPHA_H
-#define MAME_CPU_ALPHA_ALPHA_H
-
-#pragma once
-
-#include "alphad.h"
-
-class alpha_device : public cpu_device
-{
-public:
- void set_dasm_type(alpha_disassembler::dasm_type type) { m_dasm_type = type; }
-
- // input/output lines
- auto srom_oe_w() { return m_srom_oe_cb.bind(); }
- auto srom_data_r() { return m_srom_data_cb.bind(); }
-
-protected:
- alpha_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
-
- // device_t overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- // device_execute_interface overrides
- virtual u32 execute_min_cycles() const override { return 1; }
- virtual u32 execute_max_cycles() const override { return 1; }
- virtual void execute_run() override;
- virtual void execute_set_input(int inputnum, int state) override;
-
- // device_memory_interface overrides
- virtual space_config_vector memory_space_config() const override;
- virtual bool memory_translate(int spacenum, int intention, offs_t &address) override;
-
- // device_disasm_interface overrides
- virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
-
- virtual void cpu_execute(u32 const op);
- virtual bool cpu_translate(u64 &address, int intention) { return false; }
-
- // execution helpers
- static u64 zap_mask(u8 const zap_bits);
- static u64 u64_to_g_floating(u64 const data);
- static u64 u32_to_f_floating(u32 const data);
- static u32 f_floating_to_u32(u64 const data);
-
- // memory access helpers
- template <typename T, typename U> std::enable_if_t<std::is_convertible<U, std::function<void(T)>>::value, void> load(u64 address, U &&apply);
- template <typename T, typename U> std::enable_if_t<std::is_convertible<U, std::function<void(address_space &, u64, T)>>::value, void> load_l(u64 address, U &&apply);
- template <typename T, typename U> std::enable_if_t<std::is_convertible<U, T>::value, void> store(u64 address, U data, T mem_mask = ~T(0));
- void fetch(u64 address, std::function<void(u32)> &&apply);
-
- // cache helpers
- u32 read_srom(unsigned const bits);
- virtual u32 icache_fetch(u64 const address) = 0;
-
- // configuration
- alpha_disassembler::dasm_type m_dasm_type;
- address_space_config m_as_config[4];
- devcb_write_line m_srom_oe_cb;
- devcb_read_line m_srom_data_cb;
-
- // emulation state
- int m_icount;
-
- u64 m_pc;
- u64 m_r[32];
- u64 m_f[32];
-
- bool m_pal_mode;
- memory_passthrough_handler *m_lock_watch;
-};
-
-class alpha_ev4_device : public alpha_device
-{
-public:
- alpha_ev4_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
-
-protected:
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- // device_execute_interface overrides
- virtual u32 execute_input_lines() const override { return 6; }
-
- virtual void cpu_execute(u32 const op) override;
- virtual bool cpu_translate(u64 &address, int intention) override;
-
- enum ibx_reg : unsigned
- {
- IBX_TB_TAG = 0, // w, PALmode only
- IBX_ITB_PTE = 1, // r/w, PALmode only
- IBX_ICCSR = 2, // r/w
- IBX_ITB_PTE_TEMP = 3, // r, PALmode only
- IBX_EXC_ADDR = 4, // r/w
- IBX_SL_RCV = 5, // r
- IBX_ITBZAP = 6, // w, PALmode only
- IBX_ITBASM = 7, // w, PALmode only
- IBX_ITBIS = 8, // w, PALmode only
- IBX_PS = 9, // r/w
- IBX_EXC_SUM = 10, // r/w
- IBX_PAL_BASE = 11, // r/w
- IBX_HIRR = 12, // r
- IBX_SIRR = 13, // r/w
- IBX_ASTRR = 14, // r/w
- IBX_HIER = 16, // r/w
- IBX_SIER = 17, // r/w
- IBX_ASTER = 18, // r/w
- IBX_SL_CLR = 19, // w
- IBX_SL_XMIT = 22, // w
- };
-
- enum ibx_itb_pte_mask : u64
- {
- IBX_ITB_PTE_W_ASM = 0x00000000'00000010, // address space match
- IBX_ITB_PTE_W_KRE = 0x00000000'00000100, // kernel read-enable
- IBX_ITB_PTE_W_ERE = 0x00000000'00000200, // executive read-enable
- IBX_ITB_PTE_W_SRE = 0x00000000'00000400, // supervisor read-enable
- IBX_ITB_PTE_W_URE = 0x00000000'00000800, // user read-enable
- IBX_ITB_PTE_W_PFN = 0x001fffff'00000000, // page frame number
-
- IBX_ITB_PTE_R_KRE = 0x00000000'00000200, // kernel read-enable
- IBX_ITB_PTE_R_ERE = 0x00000000'00000400, // executive read-enable
- IBX_ITB_PTE_R_SRE = 0x00000000'00000800, // supervisor read-enable
- IBX_ITB_PTE_R_URE = 0x00000000'00001000, // user read-enable
- IBX_ITB_PTE_R_PFN = 0x00000003'ffffe000, // page frame number
- IBX_ITB_PTE_R_ASM = 0x00000004'00000000, // address space match
- };
- enum ibx_iccsr_mask : u64
- {
- IBX_ICCSR_W_PC1 = 0x00000000'00000001, // performance counter 1 interrupt enable
- IBX_ICCSR_W_PC0 = 0x00000000'00000008, // performance counter 0 interrupt enable
- IBX_ICCSR_W_PCMUX0 = 0x00000000'00000f00,
- IBX_ICCSR_W_PCMUX1 = 0x00000007'00000000,
- IBX_ICCSR_W_PIPE = 0x00000008'00000000, // pipeline enable
- IBX_ICCSR_W_BPE = 0x00000010'00000000,
- IBX_ICCSR_W_JSE = 0x00000020'00000000, // jsr stack enable
- IBX_ICCSR_W_BHE = 0x00000040'00000000,
- IBX_ICCSR_W_DI = 0x00000080'00000000, // dual issue enable
- IBX_ICCSR_W_HWE = 0x00000100'00000000, // hardware mode enable
- IBX_ICCSR_W_MAP = 0x00000200'00000000, // i-stream superpage enable
- IBX_ICCSR_W_FPE = 0x00000400'00000000, // floating-point enable
- IBX_ICCSR_W_PCE = 0x00003000'00000000, // performance counter enable
- IBX_ICCSR_W_ASN = 0x001f8000'00000000, // address space number
-
- IBX_ICCSR_R_PC0 = 0x00000000'00000002, // performance counter 0 interrupt enable
- IBX_ICCSR_R_PC1 = 0x00000000'00000004, // performance counter 1 interrupt enable
- IBX_ICCSR_R_PCMUX0 = 0x00000000'00001e00,
- IBX_ICCSR_R_PCMUX1 = 0x00000000'0000e000,
- IBX_ICCSR_R_PIPE = 0x00000000'00010000, // pipeline enable
- IBX_ICCSR_R_BPE = 0x00000000'00020000,
- IBX_ICCSR_R_JSE = 0x00000000'00040000, // jsr stack enable
- IBX_ICCSR_R_BHE = 0x00000000'00080000,
- IBX_ICCSR_R_DI = 0x00000000'00100000, // dual issue enable
- IBX_ICCSR_R_HWE = 0x00000000'00200000, // hardware mode enable
- IBX_ICCSR_R_MAP = 0x00000000'00400000, // i-stream superpage enable
- IBX_ICCSR_R_FPE = 0x00000000'00800000, // floating-point enable
- IBX_ICCSR_R_ASN = 0x00000003'f0000000, // address space number
- IBX_ICCSR_R_PCE = 0x00003000'00000000, // performance counter enable
-
- IBX_ICCSR_W_GRP1 = 0x000007ff'00000000,
- };
- enum ibx_ps_mask : u64
- {
- IBX_PS_R_CM0 = 0x00000000'00000001,
- IBX_PS_R_CM1 = 0x00000004'00000000,
- IBX_PS_R_CM = 0x00000004'00000001,
-
- IBX_PS_W_CM0 = 0x00000000'00000008,
- IBX_PS_W_CM1 = 0x00000000'00000010,
- };
- enum ibx_pal_base_mask : u64
- {
- IBX_PAL_BASE_W = 0x00000003'ffffc000,
- };
-
- enum abx_reg : unsigned
- {
- ABX_TB_CTL = 0, // w
- ABX_DTB_PTE = 2, // r/w
- ABX_DTB_PTE_TEMP = 3, // r
- ABX_MM_CSR = 4, // r
- ABX_VA = 5, // r
- ABX_DTBZAP = 6, // w
- ABX_DTBASM = 7, // w
- ABX_DTBIS = 8, // w
- ABX_BIU_ADDR = 9, // r
- ABX_BIU_STAT = 10, // r
- ABX_DC_STAT = 12, // r
- ABX_FILL_ADDR = 13, // r
- ABX_ABOX_CTL = 14, // w
- ABX_ALT_MODE = 15, // w
- ABX_CC = 16, // w
- ABX_CC_CTL = 17, // w
- ABX_BIU_CTL = 18, // w
- ABX_FILL_SYNDROME = 19, // w
- ABX_BC_TAG = 20, // w
- ABX_FLUSH_IC = 21, // w
- ABX_FLUSH_IC_ASM = 23, // w
- };
-
- enum abx_abox_ctl_mask : u64
- {
- ABX_ABOX_CTL_WB_DIS = 0x0001, // write buffer unload disable
- ABX_ABOX_CTL_MCHK_EN = 0x0002, // machine check enable
- ABX_ABOX_CTL_CRD_EN = 0x0004, // corrected read data interrupt enable
- ABX_ABOX_CTL_IC_SBUF_EN = 0x0008, // icache stream buffer enable
- ABX_ABOX_CTL_SPE_1 = 0x0010, // super page enable 1
- ABX_ABOX_CTL_SPE_2 = 0x0020, // super page enable 2
- ABX_ABOX_CTL_EMD_EN = 0x0040, // big-endian mode enable
- ABX_ABOX_CTL_STC_NORESULT = 0x0080, //
- ABX_ABOX_CTL_NCACHE_NDISTURB = 0x0100, //
- ABX_ABOX_CTL_DTB_RR = 0x0200, // dtb round-robin replacement
- ABX_ABOX_CTL_DC_ENA = 0x0400, // dcache enable
- ABX_ABOX_CTL_DC_FHIT = 0x0800, // dcache force hit
- ABX_ABOX_CTL_DC_16K = 0x1000, // select 16K dcache (21064A only)
- ABX_ABOX_CTL_F_TAG_ERR = 0x2000, // generate bad dcache tag parity (21064A only)
- ABX_ABOX_CTL_NOCHK_PAR = 0x4000, // disable cache parity checks (21064A only)
- ABX_ABOX_CTL_DOUBLE_INVAL = 0x8000, // (21064A only)
- };
-
- enum palcode_entry : u16
- {
- RESET = 0x0000,
- MCHK = 0x0020,
- ARITH = 0x0060,
- INTERRUPT = 0x00e0,
- D_FAULT = 0x01e0,
- ITB_MISS = 0x03e0,
- ITB_ACV = 0x07e0,
- DTB_MISS_NATIVE = 0x08e0,
- DTB_MISS_PAL = 0x09e0,
- UNALIGN = 0x11e0,
- OPCDEC = 0x13e0,
- FEN = 0x17e0,
- CALL_PAL = 0x2000,
- };
- static constexpr u32 CALL_PAL_MASK = 0x03ffff40;
-
- u64 ibx_get(u8 reg);
- void ibx_set(u8 reg, u64 data);
- u64 abx_get(u8 reg);
- void abx_set(u8 reg, u64 data);
-
- u64 m_ibx[32];
- u64 m_abx[32];
- u64 m_pt[32];
-};
-
-class dec_21064_device : public alpha_ev4_device
-{
-public:
- dec_21064_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-
-protected:
- virtual void device_reset() override;
-
- virtual u32 icache_fetch(u64 const address) override;
-
-private:
- struct icache_block
- {
- u32 lw[8]; // instruction longwords
- u32 tag; // cache tag
- u8 aav; // asn, asm and v fields
- u8 bht; // branch history table
- };
-
- enum aav_mask : u8
- {
- AAV_ASN = 0x3f, // address space number
- AAV_ASM = 0x40, // address space match
- AAV_V = 0x80, // valid
- };
-
- icache_block m_icache[256];
-};
-
-DECLARE_DEVICE_TYPE(DEC_21064, dec_21064_device)
-
-#endif // MAME_CPU_ALPHA_ALPHA_H
diff --git a/src/devices/cpu/alpha/alphad.cpp b/src/devices/cpu/alpha/alphad.cpp
deleted file mode 100644
index 4bd759e53c3..00000000000
--- a/src/devices/cpu/alpha/alphad.cpp
+++ /dev/null
@@ -1,1245 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Patrick Mackinlay
-
-/*
- * TODO
- * - enforce "should be zero" fields
- * - enforce "Ra must be R31"
- * - assembly and register naming preferences
- * - implementation-dependent instructions for EV5 and EV6
- */
-
-#include "emu.h"
-#include "alphad.h"
-#include "common.h"
-
- // instruction formats
-#define OPERATE_RRR(opcode, ra, rb, rc) util::stream_format(stream, "%-10s %s, %s, %s", opcode, R[ra], R[rb], R[rc])
-#define OPERATE_FFF(opcode, ra, rb, rc) util::stream_format(stream, "%-10s %s, %s, %s", opcode, F[ra], F[rb], F[rc])
-#define OPERATE_RIR(opcode, ra, im, rc) util::stream_format(stream, "%-10s %s, #%d, %s", opcode, R[ra], im, R[rc])
-#define OPERATE_RR(opcode, rb, rc) util::stream_format(stream, "%-10s %s, %s", opcode, R[rb], R[rc])
-#define OPERATE_FF(opcode, rb, rc) util::stream_format(stream, "%-10s %s, %s", opcode, F[rb], F[rc])
-#define OPERATE_RF(opcode, ra, rc) util::stream_format(stream, "%-10s %s, %s", opcode, R[ra], F[rc])
-#define OPERATE_FR(opcode, ra, rc) util::stream_format(stream, "%-10s %s, %s", opcode, F[ra], R[rc])
-#define OPERATE_IR(opcode, im, rc) util::stream_format(stream, "%-10s #%d, %s", opcode, im, R[rc])
-#define OPERATE_R(opcode, rc) util::stream_format(stream, "%-10s %s", opcode, R[rc])
-#define OPERATE_F(opcode, rc) util::stream_format(stream, "%-10s %s", opcode, F[rc])
-
-// TODO: verify syntax for multiple register formats
-#define OPERATE_RI(opcode, rb, rc) util::stream_format(stream, "%-10s %s, %s", opcode, R[rb], IBX[rc])
-#define OPERATE_RA(opcode, rb, rc) util::stream_format(stream, "%-10s %s, %s", opcode, R[rb], ABX[rc])
-#define OPERATE_RAI(opcode, rb, rc) util::stream_format(stream, "%-10s %s, %s:%s", opcode, R[rb], ABX[rc], IBX[rc])
-#define OPERATE_RP(opcode, rb, rc) util::stream_format(stream, "%-10s %s, %s", opcode, R[rb], PT[rc])
-#define OPERATE_RPI(opcode, rb, rc) util::stream_format(stream, "%-10s %s, %s:%s", opcode, R[rb], PT[rc], IBX[rc])
-#define OPERATE_RPA(opcode, rb, rc) util::stream_format(stream, "%-10s %s, %s:%s", opcode, R[rb], PT[rc], ABX[rc])
-#define OPERATE_RPAI(opcode, rb, rc) util::stream_format(stream, "%-10s %s, %s:%s:%s", opcode, R[rb], PT[rc], ABX[rc], IBX[rc])
-
-#define MEMORY_R(opcode, ra, disp, rb) util::stream_format(stream, "%-10s %s, %d(%s)", opcode, R[ra], disp, R[rb])
-#define MEMORY_F(opcode, ra, disp, rb) util::stream_format(stream, "%-10s %s, %d(%s)", opcode, F[ra], disp, R[rb])
-#define BRANCH_R(opcode, ra, offset) util::stream_format(stream, "%-10s %s, 0x%x", opcode, R[ra], pc + 4 + offset)
-#define BRANCH_F(opcode, ra, offset) util::stream_format(stream, "%-10s %s, 0x%x", opcode, F[ra], pc + 4 + offset)
-#define BRANCH(opcode, offset) util::stream_format(stream, "%-10s 0x%x", opcode, pc + 4 + offset)
-
-#define JUMP(opcode, ra, rb) util::stream_format(stream, "%-10s %s, (%s)", opcode, R[ra], R[rb])
-
-#define MISC(opcode) util::stream_format(stream, "%-10s", opcode)
-#define MISC_R(opcode, ra) util::stream_format(stream, "%-10s %s", opcode, R[ra])
-#define MISC_M(opcode, rb) util::stream_format(stream, "%-10s (%s)", opcode, R[rb])
-
-#define CALL_PAL(fnc) util::stream_format(stream, "%-10s %s", "call_pal", fnc)
-
-#define RESERVED(opcode) util::stream_format(stream, "%-10s", opcode)
-#define UNKNOWN(type) util::stream_format(stream, "unknown %s", type)
-
-// register names
-const char *const alpha_disassembler::R[] =
-{
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
- "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
- "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
-};
-
-const char *const alpha_disassembler::F[] =
-{
- "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
- "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
- "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
- "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31"
-};
-
-const char *const alpha_disassembler::PT[] =
-{
- "pt0", "pt1", "pt2", "pt3", "pt4", "pt5", "pt6", "pt7",
- "pt8", "pt9", "pt10", "pt11", "pt12", "pt13", "pt14", "pt15",
- "pt16", "pt17", "pt18", "pt19", "pt20", "pt21", "pt22", "pt23",
- "pt24", "pt25", "pt26", "pt27", "pt28", "pt29", "pt30", "pt31"
-};
-
-// NOTE: ABXn and IBXn are placeholders for undefined/unused registers
-const char *const alpha_disassembler::ABX[] =
-{
- "TB_CTL", "ABX1", "DTB_PTE", "DTB_PTE_TEMP", "MM_CSR", "VA", "DTBZAP", "DTBASM",
- "DTBIS", "BIU_ADDR", "BIU_STAT", "ABX12", "DC_STAT", "FILL_ADDR", "ABOX_CTL", "ALT_MODE",
- "CC", "CC_CTL", "BIU_CTL", "FILL_SYNDROME", "BC_TAG", "FLUSH_IC", "ABX22", "FLUSH_IC_ASM",
- "ABX24", "ABX25", "ABX26", "ABX27", "ABX28", "ABX29", "ABX30", "ABX31"
-};
-
-const char *const alpha_disassembler::IBX[] =
-{
- "TB_TAG", "ITB_PTE", "ICCSR", "ITB_PTE_TEMP", "EXC_ADDR", "SL_RCV", "ITBZAP", "ITBASM",
- "ITBIS", "PS", "EXC_SUM", "PAL_BASE", "HIRR", "SIRR", "ASTRR", "IBX15",
- "HIERR", "SIER", "ASTER", "SL_CLR", "IBX20", "IBX21", "SL_XMIT", "IBX23",
- "IBX24", "IBX25", "IBX26", "IBX27", "IBX28", "IBX29", "IBX30", "IBX31"
-};
-
-offs_t alpha_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params)
-{
- offs_t const bytes = 4;
- u32 flags = SUPPORTED;
-
- u32 const instruction = opcodes.r32(pc);
-
- switch (instruction >> 26)
- {
- // pal format
- case 0x00:
- switch (m_dasm_type)
- {
- case TYPE_UNKNOWN:
- switch (instruction & 0x03ffffff)
- {
- case 0x0000: CALL_PAL("halt"); break;
- case 0x0002: CALL_PAL("draina"); break;
- case 0x0086: CALL_PAL("imb"); break;
-
- default: UNKNOWN("call_pal"); break;
- }
- break;
-
- case TYPE_NT:
- switch (instruction & 0x03ffffff)
- {
- // Windows NT unprivileged PALcode
- case 0x0080: CALL_PAL("bpt"); break; // breakpoint trap
- case 0x0083: CALL_PAL("callsys"); break; // call system service
- case 0x0086: CALL_PAL("imb"); break; // instruction memory barrier
- case 0x00aa: CALL_PAL("gentrap"); break; // generate trap
- case 0x00ab: CALL_PAL("rdteb"); break; // read TEB internal processor register
- case 0x00ac: CALL_PAL("kbpt"); break; // kernel breakpoint trap
- case 0x00ad: CALL_PAL("callkd"); break; // call kernel debugger
-
- // Windows NT privileged PALcode
- case 0x0000: CALL_PAL("halt"); break; // trap to illegal instruction
- case 0x0001: CALL_PAL("restart"); break; // restart the processor
- case 0x0002: CALL_PAL("draina"); break; // drain aborts
- case 0x0003: CALL_PAL("reboot"); break; // transfer to console firmware
- case 0x0004: CALL_PAL("initpal"); break; // initialize the PALcode
- case 0x0005: CALL_PAL("wrentry"); break; // write system entry
- case 0x0006: CALL_PAL("swpirql"); break; // swap IRQL
- case 0x0007: CALL_PAL("rdirql"); break; // read current IRQL
- case 0x0008: CALL_PAL("di"); break; // disable interrupts
- case 0x0009: CALL_PAL("ei"); break; // enable interrupts
- case 0x000a: CALL_PAL("swppal"); break; // swap PALcode
- case 0x000c: CALL_PAL("ssir"); break; // set software interrupt request
- case 0x000d: CALL_PAL("csir"); break; // clear software interrupt request
- case 0x000e: CALL_PAL("rfe"); break; // return from exception
- case 0x000f: CALL_PAL("retsys"); break; // return from system service call
- case 0x0010: CALL_PAL("swpctx"); break; // swap privileged thread context
- case 0x0011: CALL_PAL("swpprocess"); break; // swap privileged process context
- case 0x0012: CALL_PAL("rdmces"); break; // read machine check error summary
- case 0x0013: CALL_PAL("wrmces"); break; // write machine check error summary
- case 0x0014: CALL_PAL("tbia"); break; // translation buffer invalidate all
- case 0x0015: CALL_PAL("tbis"); break; // translation buffer invalidate single
- case 0x0016: CALL_PAL("dtbis"); break; // data translation buffer invalidate single
- case 0x0017: CALL_PAL("tbisasn"); break; // translation buffer invalidate single ASN
- case 0x0018: CALL_PAL("rdksp"); break; // read initial kernel stack
- case 0x0019: CALL_PAL("swpksp"); break; // swap initial kernel stack
- case 0x001a: CALL_PAL("rdpsr"); break; // read processor status register
- case 0x001c: CALL_PAL("rdpcr"); break; // read PCR (processor control registers)
- case 0x001e: CALL_PAL("rdthread"); break; // read the current thread value
- case 0x0020: CALL_PAL("wrperfmon"); break; // write performance monitoring values
- case 0x0030: CALL_PAL("rdcounters"); break; // read PALcode event counters
- case 0x0031: CALL_PAL("rdstate"); break; // read internal processor state
-
- default: UNKNOWN("call_pal"); break;
- }
- break;
-
- case TYPE_UNIX:
- switch (instruction & 0x03ffffff)
- {
- // Digital UNIX unprivileged PALcode
- case 0x0080: CALL_PAL("bpt"); break; // breakpoint trap
- case 0x0081: CALL_PAL("bugchk"); break; // bugcheck
- case 0x0083: CALL_PAL("callsys"); break; // system call
- case 0x0086: CALL_PAL("imb"); break; // i-stream memory barrier
- case 0x0092: CALL_PAL("urti"); break; // return from user mode trap
- case 0x009e: CALL_PAL("rdunique"); break; // read unique value
- case 0x009f: CALL_PAL("wrunique"); break; // write unique value
- case 0x00aa: CALL_PAL("gentrap"); break; // generate software trap
- case 0x00ae: CALL_PAL("clrfen"); break; // clear floating-point enable
-
- // Digital UNIX privileged PALcode
- case 0x0000: CALL_PAL("halt"); break; // halt the processor
- case 0x0001: CALL_PAL("cflush"); break; // cache flush
- case 0x0002: CALL_PAL("draina"); break; // drain aborts
- case 0x0009: CALL_PAL("cserve"); break; // console service
- case 0x000a: CALL_PAL("swppal"); break; // swap PALcode image
- case 0x000d: CALL_PAL("wripir"); break; // write interprocessor interrupt request
- case 0x0010: CALL_PAL("rdmces"); break; // read machine check error summary register
- case 0x0011: CALL_PAL("wrmces"); break; // write machine check error summary register
- case 0x002b: CALL_PAL("wrfen"); break; // write floating-point enable
- case 0x002d: CALL_PAL("wrvptptr"); break; // write virtual page table pointer
- case 0x0030: CALL_PAL("swpctx"); break; // swap privileged context
- case 0x0031: CALL_PAL("wrval"); break; // write system value
- case 0x0032: CALL_PAL("rdval"); break; // read system value
- case 0x0033: CALL_PAL("tbi"); break; // translation buffer invalidate
- case 0x0034: CALL_PAL("wrent"); break; // write system entry address
- case 0x0035: CALL_PAL("swpipl"); break; // swap interrupt priority level
- case 0x0036: CALL_PAL("rdps"); break; // read processor status
- case 0x0037: CALL_PAL("wrkgp"); break; // write kernel global pointer
- case 0x0038: CALL_PAL("wrusp"); break; // write user stack pointer
- case 0x0039: CALL_PAL("wrperfmon"); break; // performance monitoring function
- case 0x003a: CALL_PAL("rdusp"); break; // read user stack pointer
- case 0x003c: CALL_PAL("whami"); break; // who am I
- case 0x003d: CALL_PAL("retsys"); break; // return from system call
- case 0x003e: CALL_PAL("wtint"); break; // wait for interrupt
- case 0x003f: CALL_PAL("rti"); break; // return from trap or interrupt
-
- default: UNKNOWN("call_pal"); break;
- }
- break;
-
- case TYPE_VMS:
- switch (instruction & 0x03ffffff)
- {
- // OpenVMS unprivileged PALcode
- case 0x0080: CALL_PAL("bpt"); break; // breakpoint
- case 0x0081: CALL_PAL("bugchk"); break; // bugcheck
- case 0x0082: CALL_PAL("chme"); break; // change mode to executive
- case 0x0083: CALL_PAL("chmk"); break; // change mode to kernel
- case 0x0084: CALL_PAL("chms"); break; // change mode to supervisor
- case 0x0085: CALL_PAL("chmu"); break; // change mode to user
- case 0x0086: CALL_PAL("imb"); break; // i-stream memory barrier
- case 0x0087: CALL_PAL("insqhil"); break; // insert into longword queue at head interlocked
- case 0x0088: CALL_PAL("insqtil"); break; // insert into longword queue at tail interlocked
- case 0x0089: CALL_PAL("insqhiq"); break; // insert into quadword queue at head interlocked
- case 0x008a: CALL_PAL("insqtiq"); break; // insert into quadword queue at tail interlocked
- case 0x008b: CALL_PAL("insquel"); break; // insert entry into longword queue
- case 0x008c: CALL_PAL("insqueq"); break; // insert entry into quadword queue
- case 0x008d: CALL_PAL("insquel/d"); break; // insert entry into longword queue deferred
- case 0x008e: CALL_PAL("insqueq/d"); break; // insert entry into quadword queue deferred
- case 0x008f: CALL_PAL("prober"); break; // probe for read access
- case 0x0090: CALL_PAL("probew"); break; // probe for write access
- case 0x0091: CALL_PAL("rd_ps"); break; // move processor status
- case 0x0092: CALL_PAL("rei"); break; // return from exception or interrupt
- case 0x0093: CALL_PAL("remqhil"); break; // remove from longword queue at head interlocked
- case 0x0094: CALL_PAL("remqtil"); break; // remove from longword queue at tail interlocked
- case 0x0095: CALL_PAL("remqhiq"); break; // remove from quadword queue at head interlocked
- case 0x0096: CALL_PAL("remqtiq"); break; // remove from quadword queue at tail interlocked
- case 0x0097: CALL_PAL("remquel"); break; // remove entry from longword queue
- case 0x0098: CALL_PAL("remqueq"); break; // remove entry from quadword queue
- case 0x0099: CALL_PAL("remquel/d"); break; // remove entry from longword queue deferred
- case 0x009a: CALL_PAL("remqueq/d"); break; // remove entry from quadword queue deferred
- case 0x009b: CALL_PAL("swasten"); break; // swap AST enable for current mode
- case 0x009c: CALL_PAL("wr_ps_sw"); break; // write processor status software field
- case 0x009d: CALL_PAL("rscc"); break; // read system cycle counter
- case 0x009e: CALL_PAL("read_unq"); break; // read unique context
- case 0x009f: CALL_PAL("write_unq"); break; // write unique context
- case 0x00a0: CALL_PAL("amovrr"); break; // atomic move from register to register
- case 0x00a1: CALL_PAL("amovrm"); break; // atomic move from register to memory
- case 0x00a2: CALL_PAL("insqhilr"); break; // insert into longword queue at head interlocked resident
- case 0x00a3: CALL_PAL("insqtilr"); break; // insert into longword queue at tail interlocked resident
- case 0x00a4: CALL_PAL("insqhiqr"); break; // insert into quadword queue at head interlocked resident
- case 0x00a5: CALL_PAL("insqtiqr"); break; // insert into quadword queue at tail interlocked resident
- case 0x00a6: CALL_PAL("remqhilr"); break; // remove from longword queue at head interlocked resident
- case 0x00a7: CALL_PAL("remqtilr"); break; // remove from longword queue at tail interlocked resident
- case 0x00a8: CALL_PAL("remqhiqr"); break; // remove from quadword queue at head interlocked resident
- case 0x00a9: CALL_PAL("remqtiqr"); break; // remove from quadword queue at tail interlocked resident
- case 0x00aa: CALL_PAL("gentrap"); break; // generate software trap
- case 0x00ae: CALL_PAL("clrfen"); break; // clear floating-point enable
-
- // OpenVMS privileged PALcode
- case 0x0000: CALL_PAL("halt"); break; // halt processor
- case 0x0001: CALL_PAL("cflush"); break; // cache flush
- case 0x0002: CALL_PAL("draina"); break; // drain aborts
- case 0x0003: CALL_PAL("ldqp"); break; // load quadword physical
- case 0x0004: CALL_PAL("stqp"); break; // store quadword physical
- case 0x0005: CALL_PAL("swpctx"); break; // swap privileged context
- case 0x0006: CALL_PAL("mfpr_asn"); break; // move from processor register ASN
- case 0x0009: CALL_PAL("cserve"); break; // console service
- case 0x000a: CALL_PAL("swppal"); break; // swap PALcode image
- case 0x000b: CALL_PAL("mfpr_fen"); break; // move from processor register FEN
- case 0x000c: CALL_PAL("mtpr_fen"); break; // move to processor register FEN
- case 0x000d: CALL_PAL("mtpr_ipir"); break; // move to processor register IPRI
- case 0x000e: CALL_PAL("mfpr_ipl"); break; // move from processor register IPL
- case 0x000f: CALL_PAL("mtpr_ipl"); break; // move to processor register IPL
- case 0x0010: CALL_PAL("mfpr_mces"); break; // move from processor register MCES
- case 0x0011: CALL_PAL("mtpr_mces"); break; // move to processor register MCES
- case 0x0012: CALL_PAL("mfpr_pcbb"); break; // move from processor register PCBB
- case 0x0013: CALL_PAL("mfpr_prbr"); break; // move from processor register PRBR
- case 0x0014: CALL_PAL("mtpr_prbr"); break; // move to processor register PRBR
- case 0x0015: CALL_PAL("mfpr_ptbr"); break; // move from processor register PTBR
- case 0x0016: CALL_PAL("mfpr_scbb"); break; // move from processor register SCBB
- case 0x0017: CALL_PAL("mtpr_scbb"); break; // move to processor register SCBB
- case 0x0018: CALL_PAL("mtpr_sirr"); break; // move to processor register SIRR
- case 0x0019: CALL_PAL("mfpr_sisr"); break; // move from processor register SISR
- case 0x001a: CALL_PAL("mfpr_tbchk"); break; // move from processor register TBCHK
- case 0x001b: CALL_PAL("mtpr_tbia"); break; // move to processor register TBIA
- case 0x001c: CALL_PAL("mtpr_tbiap"); break; // move to processor register TBIAP
- case 0x001d: CALL_PAL("mtpr_tbis"); break; // move to processor register TBIS
- case 0x001e: CALL_PAL("mfpr_esp"); break; // move from processor register ESP
- case 0x001f: CALL_PAL("mtpr_esp"); break; // move to processor register ESP
- case 0x0020: CALL_PAL("mfpr_ssp"); break; // move from processor register SSP
- case 0x0021: CALL_PAL("mtpr_ssp"); break; // move to processor register SSP
- case 0x0022: CALL_PAL("mfpr_usp"); break; // move from processor register USP
- case 0x0023: CALL_PAL("mtpr_usp"); break; // move to processor register USP
- case 0x0024: CALL_PAL("mtpr_tbisd"); break; // move to processor register TBISD
- case 0x0025: CALL_PAL("mtpr_tbisi"); break; // move to processor register TBISI
- case 0x0026: CALL_PAL("mtpr_asten"); break; // move to processor register ASTEN
- case 0x0027: CALL_PAL("mtpr_astsr"); break; // move to processor register ASTSR
- case 0x0029: CALL_PAL("mfpr_vptb"); break; // move from processor register VPTB
- case 0x002a: CALL_PAL("mtpr_vptb"); break; // move to processor register VPTB
- case 0x002b: CALL_PAL("mtpr_perfmon"); break; // move to processor register PERFMON
- case 0x002e: CALL_PAL("mtpr_datfx"); break; // move to processor register DATFX
- case 0x003e: CALL_PAL("wtint"); break; // wait for interrupt
- case 0x003f: CALL_PAL("mfpr_whami"); break; // move from processor register WHAMI
-
- default: UNKNOWN("call_pal"); break;
- }
- break;
- }
- break;
-
- // reserved opcodes
- case 0x01: RESERVED("opc01"); break; // OPC01
- case 0x02: RESERVED("opc02"); break; // OPC02
- case 0x03: RESERVED("opc03"); break; // OPC03
- case 0x04: RESERVED("opc04"); break; // OPC04
- case 0x05: RESERVED("opc05"); break; // OPC05
- case 0x06: RESERVED("opc06"); break; // OPC06
- case 0x07: RESERVED("opc07"); break; // OPC07
-
- // memory format
- case 0x08:
- if (Rb(instruction) == 31)
- OPERATE_IR("mov", Disp_M(instruction), Ra(instruction));
- else
- MEMORY_R("lda", Ra(instruction), Disp_M(instruction), Rb(instruction)); // LDA
- break;
- case 0x09: MEMORY_R("ldah", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // LDAH
- case 0x0a: MEMORY_R("ldbu", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // LDBU (BWX)
- case 0x0b:
- if (Ra(instruction) == 31 && Disp_M(instruction) == 0)
- MISC("unop");
- else
- MEMORY_R("ldq_u", Ra(instruction), Disp_M(instruction), Rb(instruction)); // LDQ_U
- break;
- case 0x0c: MEMORY_R("ldwu", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // LDWU (BWX)
- case 0x0d: MEMORY_R("stw", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // STW (BWX)
- case 0x0e: MEMORY_R("stb", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // STB (BWX)
- case 0x0f: MEMORY_R("stq_u", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // STQ_U
-
- // operate format
- case 0x10: // INTA* (integer arithmetic)
- switch ((instruction >> 5) & 0xff)
- {
- // register variants
- case 0x00:
- if (Ra(instruction) == 31)
- OPERATE_RR("sextl", Rb(instruction), Rc(instruction));
- else
- OPERATE_RRR("addl", Ra(instruction), Rb(instruction), Rc(instruction)); // ADDL
- break;
- case 0x02: OPERATE_RRR("s4addl", Ra(instruction), Rb(instruction), Rc(instruction)); break; // S4ADDL
- case 0x09:
- if (Ra(instruction) == 31)
- OPERATE_RR("negl", Rb(instruction), Rc(instruction));
- else
- OPERATE_RRR("subl", Ra(instruction), Rb(instruction), Rc(instruction)); // SUBL
- break;
- case 0x0b: OPERATE_RRR("s4subl", Ra(instruction), Rb(instruction), Rc(instruction)); break; // S4SUBL
- case 0x0f: OPERATE_RRR("cmpbge", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPBGE
- case 0x12: OPERATE_RRR("s8addl", Ra(instruction), Rb(instruction), Rc(instruction)); break; // S8ADDL
- case 0x1b: OPERATE_RRR("s8subl", Ra(instruction), Rb(instruction), Rc(instruction)); break; // S8SUBL
- case 0x1d: OPERATE_RRR("cmpult", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPULT
- case 0x20: OPERATE_RRR("addq", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDQ
- case 0x22: OPERATE_RRR("s4addq", Ra(instruction), Rb(instruction), Rc(instruction)); break; // S4ADDQ
- case 0x29:
- if (Ra(instruction) == 31)
- OPERATE_RR("negq", Rb(instruction), Rc(instruction));
- else
- OPERATE_RRR("subq", Ra(instruction), Rb(instruction), Rc(instruction)); // SUBQ
- break;
- case 0x2b: OPERATE_RRR("s4subq", Ra(instruction), Rb(instruction), Rc(instruction)); break; // S4SUBQ
- case 0x2d: OPERATE_RRR("cmpeq", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPEQ
- case 0x32: OPERATE_RRR("s8addq", Ra(instruction), Rb(instruction), Rc(instruction)); break; // S8ADDQ
- case 0x3b: OPERATE_RRR("s8subq", Ra(instruction), Rb(instruction), Rc(instruction)); break; // S8SUBQ
- case 0x3d: OPERATE_RRR("cmpule", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPULE
- case 0x40: OPERATE_RRR("addl/v", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDL/V
- case 0x49:
- if (Ra(instruction) == 31)
- OPERATE_RR("negl/v", Rb(instruction), Rc(instruction));
- else
- OPERATE_RRR("subl/v", Ra(instruction), Rb(instruction), Rc(instruction)); // SUBL/V
- break;
- case 0x4d: OPERATE_RRR("cmplt", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPLT
- case 0x60: OPERATE_RRR("addq/v", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDQ/V
- case 0x69:
- if (Ra(instruction) == 31)
- OPERATE_RR("negq/v", Rb(instruction), Rc(instruction));
- else
- OPERATE_RRR("subq/v", Ra(instruction), Rb(instruction), Rc(instruction)); // SUBQ/V
- break;
- case 0x6d: OPERATE_RRR("cmple", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPLE
-
- // immediate variants
- case 0x80:
- if (Ra(instruction) == 31)
- OPERATE_IR("sextl", Im(instruction), Rc(instruction));
- else
- OPERATE_RIR("addl", Ra(instruction), Im(instruction), Rc(instruction)); // ADDL
- break;
- case 0x82: OPERATE_RIR("s4addl", Ra(instruction), Im(instruction), Rc(instruction)); break; // S4ADDL
- case 0x89:
- if (Ra(instruction) == 31)
- OPERATE_IR("negl", Im(instruction), Rc(instruction));
- else
- OPERATE_RIR("subl", Ra(instruction), Im(instruction), Rc(instruction)); // SUBL
- break;
- case 0x8b: OPERATE_RIR("s4subl", Ra(instruction), Im(instruction), Rc(instruction)); break; // S4SUBL
- case 0x8f: OPERATE_RIR("cmpbge", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMPBGE
- case 0x92: OPERATE_RIR("s8addl", Ra(instruction), Im(instruction), Rc(instruction)); break; // S8ADDL
- case 0x9b: OPERATE_RIR("s8subl", Ra(instruction), Im(instruction), Rc(instruction)); break; // S8SUBL
- case 0x9d: OPERATE_RIR("cmpult", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMPULT
- case 0xa0: OPERATE_RIR("addq", Ra(instruction), Im(instruction), Rc(instruction)); break; // ADDQ
- case 0xa2: OPERATE_RIR("s4addq", Ra(instruction), Im(instruction), Rc(instruction)); break; // S4ADDQ
- case 0xa9:
- if (Ra(instruction) == 31)
- OPERATE_IR("negq", Im(instruction), Rc(instruction));
- else
- OPERATE_RIR("subq", Ra(instruction), Im(instruction), Rc(instruction)); // SUBQ
- break;
- case 0xab: OPERATE_RIR("s4subq", Ra(instruction), Im(instruction), Rc(instruction)); break; // S4SUBQ
- case 0xad: OPERATE_RIR("cmpeq", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMPEQ
- case 0xb2: OPERATE_RIR("s8addq", Ra(instruction), Im(instruction), Rc(instruction)); break; // S8ADDQ
- case 0xbb: OPERATE_RIR("s8subq", Ra(instruction), Im(instruction), Rc(instruction)); break; // S8SUBQ
- case 0xbd: OPERATE_RIR("cmpule", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMPULE
- case 0xc0: OPERATE_RIR("addl/v", Ra(instruction), Im(instruction), Rc(instruction)); break; // ADDL/V
- case 0xc9:
- if (Ra(instruction) == 31)
- OPERATE_IR("negl/v", Im(instruction), Rc(instruction));
- else
- OPERATE_RIR("subl/v", Ra(instruction), Im(instruction), Rc(instruction)); // SUBL/V
- break;
- case 0xcd: OPERATE_RIR("cmplt", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMPLT
- case 0xe0: OPERATE_RIR("addq/v", Ra(instruction), Im(instruction), Rc(instruction)); break; // ADDQ/V
- case 0xe9:
- if (Ra(instruction) == 31)
- OPERATE_IR("negq/v", Im(instruction), Rc(instruction));
- else
- OPERATE_RIR("subq/v", Ra(instruction), Im(instruction), Rc(instruction)); // SUBQ/V
- break;
- case 0xed: OPERATE_RIR("cmple", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMPLE
-
- default: UNKNOWN("inta*"); break;
- }
- break;
- case 0x11: // INTL* (integer logical)
- switch ((instruction >> 5) & 0xff)
- {
- // register variants
- case 0x00: OPERATE_RRR("and", Ra(instruction), Rb(instruction), Rc(instruction)); break; // AND
- case 0x08: OPERATE_RRR("bic", Ra(instruction), Rb(instruction), Rc(instruction)); break; // BIC
- case 0x14: OPERATE_RRR("cmovlbs", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMOVLBS
- case 0x16: OPERATE_RRR("cmovlbc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMOVLBC
- case 0x20:
- if (Ra(instruction) == 31 && Rb(instruction) == 31 && Rc(instruction) == 31)
- MISC("nop");
- else if (Ra(instruction) == 31 && Rb(instruction) == 31)
- OPERATE_R("clr", Rc(instruction));
- else if (Ra(instruction) == Rb(instruction))
- OPERATE_RR("mov", Rb(instruction), Rc(instruction));
- else
- OPERATE_RRR("bis", Ra(instruction), Rb(instruction), Rc(instruction)); // BIS
- break;
- case 0x24: OPERATE_RRR("cmoveq", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMOVEQ
- case 0x26: OPERATE_RRR("cmovne", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMOVNE
- case 0x28:
- if (Ra(instruction) == 31)
- OPERATE_RR("not", Rb(instruction), Rc(instruction));
- else
- OPERATE_RRR("ornot", Ra(instruction), Rb(instruction), Rc(instruction)); // ORNOT
- break;
- case 0x40: OPERATE_RRR("xor", Ra(instruction), Rb(instruction), Rc(instruction)); break; // XOR
- case 0x44: OPERATE_RRR("cmovlt", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMOVLT
- case 0x46: OPERATE_RRR("cmovge", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMOVGE
- case 0x48: OPERATE_RRR("eqv", Ra(instruction), Rb(instruction), Rc(instruction)); break; // EQV
- case 0x61: OPERATE_RR("amask", Rb(instruction), Rc(instruction)); break; // AMASK
- case 0x64: OPERATE_RRR("cmovle", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMOVLE
- case 0x66: OPERATE_RRR("cmovgt", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMOVGT
-
- // immediate variants
- case 0x80: OPERATE_RIR("and", Ra(instruction), Im(instruction), Rc(instruction)); break; // AND
- case 0x88: OPERATE_RIR("bic", Ra(instruction), Im(instruction), Rc(instruction)); break; // BIC
- case 0x94: OPERATE_RIR("cmovlbs", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMOVLBS
- case 0x96: OPERATE_RIR("cmovlbc", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMOVLBC
- case 0xa0:
- if (Ra(instruction) == 31)
- OPERATE_IR("mov", Im(instruction), Rc(instruction));
- else
- OPERATE_RIR("bis", Ra(instruction), Im(instruction), Rc(instruction)); // BIS
- break;
- case 0xa4: OPERATE_RIR("cmoveq", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMOVEQ
- case 0xa6: OPERATE_RIR("cmovne", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMOVNE
- case 0xa8:
- if (Ra(instruction) == 31)
- OPERATE_IR("not", Im(instruction), Rc(instruction));
- else
- OPERATE_RIR("ornot", Ra(instruction), Im(instruction), Rc(instruction)); // ORNOT
- break;
- case 0xc0: OPERATE_RIR("xor", Ra(instruction), Im(instruction), Rc(instruction)); break; // XOR
- case 0xc4: OPERATE_RIR("cmovlt", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMOVLT
- case 0xc6: OPERATE_RIR("cmovge", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMOVGE
- case 0xc8: OPERATE_RIR("eqv", Ra(instruction), Im(instruction), Rc(instruction)); break; // EQV
- case 0xe1: OPERATE_IR("amask", Im(instruction), Rc(instruction)); break; // AMASK
- case 0xe4: OPERATE_RIR("cmovle", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMOVLE
- case 0xe6: OPERATE_RIR("cmovgt", Ra(instruction), Im(instruction), Rc(instruction)); break; // CMOVGT
-
- // TODO: Rb must be literal #1?
- case 0xec: OPERATE_R("implver", Rc(instruction)); break; // IMPLVER
-
- default: UNKNOWN("intl*"); break;
- }
- break;
- case 0x12: // INTS* (integer shift)
- switch ((instruction >> 5) & 0xff)
- {
- // register variants
- case 0x02: OPERATE_RRR("mskbl", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MSKBL
- case 0x06: OPERATE_RRR("extbl", Ra(instruction), Rb(instruction), Rc(instruction)); break; // EXTBL
- case 0x0b: OPERATE_RRR("insbl", Ra(instruction), Rb(instruction), Rc(instruction)); break; // INSBL
- case 0x12: OPERATE_RRR("mskwl", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MSKWL
- case 0x16: OPERATE_RRR("extwl", Ra(instruction), Rb(instruction), Rc(instruction)); break; // EXTWL
- case 0x1b: OPERATE_RRR("inswl", Ra(instruction), Rb(instruction), Rc(instruction)); break; // INSWL
- case 0x22: OPERATE_RRR("mskll", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MSKLL
- case 0x26: OPERATE_RRR("extll", Ra(instruction), Rb(instruction), Rc(instruction)); break; // EXTLL
- case 0x2b: OPERATE_RRR("insll", Ra(instruction), Rb(instruction), Rc(instruction)); break; // INSLL
- case 0x30: OPERATE_RRR("zap", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ZAP
- case 0x31: OPERATE_RRR("zapnot", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ZAPNOT
- case 0x32: OPERATE_RRR("mskql", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MSKQL
- case 0x34: OPERATE_RRR("srl", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SRL
- case 0x36: OPERATE_RRR("extql", Ra(instruction), Rb(instruction), Rc(instruction)); break; // EXTQL
- case 0x39: OPERATE_RRR("sll", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SLL
- case 0x3b: OPERATE_RRR("insql", Ra(instruction), Rb(instruction), Rc(instruction)); break; // INSQL
- case 0x3c: OPERATE_RRR("sra", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SRA
- case 0x52: OPERATE_RRR("mskwh", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MSKWH
- case 0x57: OPERATE_RRR("inswh", Ra(instruction), Rb(instruction), Rc(instruction)); break; // INSWH
- case 0x5a: OPERATE_RRR("extwh", Ra(instruction), Rb(instruction), Rc(instruction)); break; // EXTWH
- case 0x62: OPERATE_RRR("msklh", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MSKLH
- case 0x67: OPERATE_RRR("inslh", Ra(instruction), Rb(instruction), Rc(instruction)); break; // INSLH
- case 0x6a: OPERATE_RRR("extlh", Ra(instruction), Rb(instruction), Rc(instruction)); break; // EXTLH
- case 0x72: OPERATE_RRR("mskqh", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MSKQH
- case 0x77: OPERATE_RRR("insqh", Ra(instruction), Rb(instruction), Rc(instruction)); break; // INSQH
- case 0x7a: OPERATE_RRR("extqh", Ra(instruction), Rb(instruction), Rc(instruction)); break; // EXTQH
-
- // immediate variants
- case 0x82: OPERATE_RIR("mskbl", Ra(instruction), Im(instruction), Rc(instruction)); break; // MSKBL
- case 0x86: OPERATE_RIR("extbl", Ra(instruction), Im(instruction), Rc(instruction)); break; // EXTBL
- case 0x8b: OPERATE_RIR("insbl", Ra(instruction), Im(instruction), Rc(instruction)); break; // INSBL
- case 0x92: OPERATE_RIR("mskwl", Ra(instruction), Im(instruction), Rc(instruction)); break; // MSKWL
- case 0x96: OPERATE_RIR("extwl", Ra(instruction), Im(instruction), Rc(instruction)); break; // EXTWL
- case 0x9b: OPERATE_RIR("inswl", Ra(instruction), Im(instruction), Rc(instruction)); break; // INSWL
- case 0xa2: OPERATE_RIR("mskll", Ra(instruction), Im(instruction), Rc(instruction)); break; // MSKLL
- case 0xa6: OPERATE_RIR("extll", Ra(instruction), Im(instruction), Rc(instruction)); break; // EXTLL
- case 0xab: OPERATE_RIR("insll", Ra(instruction), Im(instruction), Rc(instruction)); break; // INSLL
- case 0xb0: OPERATE_RIR("zap", Ra(instruction), Im(instruction), Rc(instruction)); break; // ZAP
- case 0xb1: OPERATE_RIR("zapnot", Ra(instruction), Im(instruction), Rc(instruction)); break; // ZAPNOT
- case 0xb2: OPERATE_RIR("mskql", Ra(instruction), Im(instruction), Rc(instruction)); break; // MSKQL
- case 0xb4: OPERATE_RIR("srl", Ra(instruction), Im(instruction), Rc(instruction)); break; // SRL
- case 0xb6: OPERATE_RIR("extql", Ra(instruction), Im(instruction), Rc(instruction)); break; // EXTQL
- case 0xb9: OPERATE_RIR("sll", Ra(instruction), Im(instruction), Rc(instruction)); break; // SLL
- case 0xbb: OPERATE_RIR("insql", Ra(instruction), Im(instruction), Rc(instruction)); break; // INSQL
- case 0xbc: OPERATE_RIR("sra", Ra(instruction), Im(instruction), Rc(instruction)); break; // SRA
- case 0xd2: OPERATE_RIR("mskwh", Ra(instruction), Im(instruction), Rc(instruction)); break; // MSKWH
- case 0xd7: OPERATE_RIR("inswh", Ra(instruction), Im(instruction), Rc(instruction)); break; // INSWH
- case 0xda: OPERATE_RIR("extwh", Ra(instruction), Im(instruction), Rc(instruction)); break; // EXTWH
- case 0xe2: OPERATE_RIR("msklh", Ra(instruction), Im(instruction), Rc(instruction)); break; // MSKLH
- case 0xe7: OPERATE_RIR("inslh", Ra(instruction), Im(instruction), Rc(instruction)); break; // INSLH
- case 0xea: OPERATE_RIR("extlh", Ra(instruction), Im(instruction), Rc(instruction)); break; // EXTLH
- case 0xf2: OPERATE_RIR("mskqh", Ra(instruction), Im(instruction), Rc(instruction)); break; // MSKQH
- case 0xf7: OPERATE_RIR("insqh", Ra(instruction), Im(instruction), Rc(instruction)); break; // INSQH
- case 0xfa: OPERATE_RIR("extqh", Ra(instruction), Im(instruction), Rc(instruction)); break; // EXTQH
-
- default: UNKNOWN("ints*"); break;
- }
- break;
- case 0x13: // INTM* (integer multiply)
- switch ((instruction >> 5) & 0xff)
- {
- // register variants
- case 0x00: OPERATE_RRR("mull", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULL
- case 0x20: OPERATE_RRR("mulq", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULQ
- case 0x30: OPERATE_RRR("umulh", Ra(instruction), Rb(instruction), Rc(instruction)); break; // UMULH
- case 0x40: OPERATE_RRR("mull/v", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULL/V
- case 0x60: OPERATE_RRR("mulq/v", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULQ/V
-
- // immediate variants
- case 0x80: OPERATE_RIR("mull", Ra(instruction), Im(instruction), Rc(instruction)); break; // MULL
- case 0xa0: OPERATE_RIR("mulq", Ra(instruction), Im(instruction), Rc(instruction)); break; // MULQ
- case 0xb0: OPERATE_RIR("umulh", Ra(instruction), Im(instruction), Rc(instruction)); break; // UMULH
- case 0xc0: OPERATE_RIR("mull/v", Ra(instruction), Im(instruction), Rc(instruction)); break; // MULL/V
- case 0xe0: OPERATE_RIR("mulq/v", Ra(instruction), Im(instruction), Rc(instruction)); break; // MULQ/V
-
- default: UNKNOWN("intm*"); break;
- }
- case 0x14: // ITFP* (integer to floating)
- switch ((instruction >> 5) & 0x7ff)
- {
- case 0x004: OPERATE_RF("itofs", Ra(instruction), Rc(instruction)); break; // ITOFS
- case 0x00a: OPERATE_FF("sqrtf/c", Rb(instruction), Rc(instruction)); break; // SQRTF/C
- case 0x00b: OPERATE_FF("sqrts/c", Rb(instruction), Rc(instruction)); break; // SQRTS/C
- case 0x014: OPERATE_RF("itoff", Ra(instruction), Rc(instruction)); break; // ITOFF
- case 0x024: OPERATE_RF("itoft", Ra(instruction), Rc(instruction)); break; // ITOFT
- case 0x02a: OPERATE_FF("sqrtg/c", Rb(instruction), Rc(instruction)); break; // SQRTG/C
- case 0x02b: OPERATE_FF("sqrtt/c", Rb(instruction), Rc(instruction)); break; // SQRTT/C
- case 0x04b: OPERATE_FF("sqrts/m", Rb(instruction), Rc(instruction)); break; // SQRTS/M
- case 0x06b: OPERATE_FF("sqrtt/m", Rb(instruction), Rc(instruction)); break; // SQRTT/M
- case 0x08a: OPERATE_FF("sqrtf", Rb(instruction), Rc(instruction)); break; // SQRTF
- case 0x08b: OPERATE_FF("sqrts", Rb(instruction), Rc(instruction)); break; // SQRTS
- case 0x0aa: OPERATE_FF("sqrtg", Rb(instruction), Rc(instruction)); break; // SQRTG
- case 0x0ab: OPERATE_FF("sqrtt", Rb(instruction), Rc(instruction)); break; // SQRTT
- case 0x0cb: OPERATE_FF("sqrts/d", Rb(instruction), Rc(instruction)); break; // SQRTS/D
- case 0x0eb: OPERATE_FF("sqrtt/d", Rb(instruction), Rc(instruction)); break; // SQRTT/D
- case 0x10a: OPERATE_FF("sqrtf/uc", Rb(instruction), Rc(instruction)); break; // SQRTF/UC
- case 0x10b: OPERATE_FF("sqrts/uc", Rb(instruction), Rc(instruction)); break; // SQRTS/UC
- case 0x12a: OPERATE_FF("sqrtg/uc", Rb(instruction), Rc(instruction)); break; // SQRTG/UC
- case 0x12b: OPERATE_FF("sqrtt/uc", Rb(instruction), Rc(instruction)); break; // SQRTT/UC
- case 0x14b: OPERATE_FF("sqrts/um", Rb(instruction), Rc(instruction)); break; // SQRTS/UM
- case 0x16b: OPERATE_FF("sqrtt/um", Rb(instruction), Rc(instruction)); break; // SQRTT/UM
- case 0x18a: OPERATE_FF("sqrtf/u", Rb(instruction), Rc(instruction)); break; // SQRTF/U
- case 0x1aa: OPERATE_FF("sqrtg/u", Rb(instruction), Rc(instruction)); break; // SQRTG/U
- case 0x1ab: OPERATE_FF("sqrtt/u", Rb(instruction), Rc(instruction)); break; // SQRTT/U
- case 0x1cb: OPERATE_FF("sqrts/ud", Rb(instruction), Rc(instruction)); break; // SQRTS/UD
- case 0x1eb: OPERATE_FF("sqrtt/ud", Rb(instruction), Rc(instruction)); break; // SQRTT/UD
- case 0x40a: OPERATE_FF("sqrtf/sc", Rb(instruction), Rc(instruction)); break; // SQRTF/SC
- case 0x42a: OPERATE_FF("sqrtg/sc", Rb(instruction), Rc(instruction)); break; // SQRTG/SC
- case 0x48a: OPERATE_FF("sqrtf/s", Rb(instruction), Rc(instruction)); break; // SQRTF/S
- case 0x4aa: OPERATE_FF("sqrtg/s", Rb(instruction), Rc(instruction)); break; // SQRTG/S
- case 0x50a: OPERATE_FF("sqrtf/suc", Rb(instruction), Rc(instruction)); break; // SQRTF/SUC
- case 0x50b: OPERATE_FF("sqrts/suc", Rb(instruction), Rc(instruction)); break; // SQRTS/SUC
- case 0x52a: OPERATE_FF("sqrtg/suc", Rb(instruction), Rc(instruction)); break; // SQRTG/SUC
- case 0x52b: OPERATE_FF("sqrtt/suc", Rb(instruction), Rc(instruction)); break; // SQRTT/SUC
- case 0x54b: OPERATE_FF("sqrts/sum", Rb(instruction), Rc(instruction)); break; // SQRTS/SUM
- case 0x56b: OPERATE_FF("sqrtt/sum", Rb(instruction), Rc(instruction)); break; // SQRTT/SUM
- case 0x58a: OPERATE_FF("sqrtf/su", Rb(instruction), Rc(instruction)); break; // SQRTF/SU
- case 0x58b: OPERATE_FF("sqrts/su", Rb(instruction), Rc(instruction)); break; // SQRTS/SU
- case 0x5aa: OPERATE_FF("sqrtg/su", Rb(instruction), Rc(instruction)); break; // SQRTG/SU
- case 0x5ab: OPERATE_FF("sqrtt/su", Rb(instruction), Rc(instruction)); break; // SQRTT/SU
- case 0x5cb: OPERATE_FF("sqrts/sud", Rb(instruction), Rc(instruction)); break; // SQRTS/SUD
- case 0x5eb: OPERATE_FF("sqrtt/sud", Rb(instruction), Rc(instruction)); break; // SQRTT/SUD
- case 0x70b: OPERATE_FF("sqrts/suic", Rb(instruction), Rc(instruction)); break; // SQRTS/SUIC
- case 0x72b: OPERATE_FF("sqrtt/suic", Rb(instruction), Rc(instruction)); break; // SQRTT/SUIC
- case 0x74b: OPERATE_FF("sqrts/suim", Rb(instruction), Rc(instruction)); break; // SQRTS/SUIM
- case 0x76b: OPERATE_FF("sqrtt/suim", Rb(instruction), Rc(instruction)); break; // SQRTT/SUIM
- case 0x78b: OPERATE_FF("sqrts/sui", Rb(instruction), Rc(instruction)); break; // SQRTS/SUI
- case 0x7ab: OPERATE_FF("sqrtt/sui", Rb(instruction), Rc(instruction)); break; // SQRTT/SUI
- case 0x7cb: OPERATE_FF("sqrts/suid", Rb(instruction), Rc(instruction)); break; // SQRTS/SUID
- case 0x7eb: OPERATE_FF("sqrtt/suid", Rb(instruction), Rc(instruction)); break; // SQRTT/SUID
-
- default: UNKNOWN("itfp*"); break;
- }
- break;
- case 0x15: // FLTV* (vax floating)
- switch ((instruction >> 5) & 0x7ff)
- {
- case 0x000: OPERATE_FFF("addf/c", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDF/C
- case 0x001: OPERATE_FFF("subf/c", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBF/C
- case 0x002: OPERATE_FFF("mulf/c", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULF/C
- case 0x003: OPERATE_FFF("divf/c", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVF/C
- case 0x01e: OPERATE_FF("cvtdg/c", Rb(instruction), Rc(instruction)); break; // CVTDG/C
- case 0x020: OPERATE_FFF("addg/c", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDG/C
- case 0x021: OPERATE_FFF("subg/c", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBG/C
- case 0x022: OPERATE_FFF("mulg/c", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULG/C
- case 0x023: OPERATE_FFF("divg/c", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVG/C
- case 0x02c: OPERATE_FF("cvtgf/c", Rb(instruction), Rc(instruction)); break; // CVTGF/C
- case 0x02d: OPERATE_FF("cvtgd/c", Rb(instruction), Rc(instruction)); break; // CVTGD/C
- case 0x02f: OPERATE_FF("cvtgq/c", Rb(instruction), Rc(instruction)); break; // CVTGQ/C
- case 0x03c: OPERATE_FF("cvtqf/c", Rb(instruction), Rc(instruction)); break; // CVTQF/C
- case 0x03e: OPERATE_FF("cvtqg/c", Rb(instruction), Rc(instruction)); break; // CVTQG/C
- case 0x080: OPERATE_FFF("addf", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDF
- case 0x081:
- if (Ra(instruction) == 31)
- OPERATE_FF("negf", Rb(instruction), Rc(instruction));
- else
- OPERATE_FFF("subf", Ra(instruction), Rb(instruction), Rc(instruction)); // SUBF
- break;
- case 0x082: OPERATE_FFF("mulf", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULF
- case 0x083: OPERATE_FFF("divf", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVF
- case 0x09e: OPERATE_FF("cvtdg", Rb(instruction), Rc(instruction)); break; // CVTDG
- case 0x0a0: OPERATE_FFF("addg", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDG
- case 0x0a1:
- if (Ra(instruction) == 31)
- OPERATE_FF("negg", Rb(instruction), Rc(instruction));
- else
- OPERATE_FFF("subg", Ra(instruction), Rb(instruction), Rc(instruction)); // SUBG
- break;
- case 0x0a2: OPERATE_FFF("mulg", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULG
- case 0x0a3: OPERATE_FFF("divg", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVG
- case 0x0a5: OPERATE_FFF("cmpgeq", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPGEQ
- case 0x0a6: OPERATE_FFF("cmpglt", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPGLT
- case 0x0a7: OPERATE_FFF("cmpgle", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPGLE
- case 0x0ac: OPERATE_FF("cvtgf", Rb(instruction), Rc(instruction)); break; // CVTGF
- case 0x0ad: OPERATE_FF("cvtgd", Rb(instruction), Rc(instruction)); break; // CVTGD
- case 0x0af: OPERATE_FF("cvtgq", Rb(instruction), Rc(instruction)); break; // CVTGQ
- case 0x0bc: OPERATE_FF("cvtqf", Rb(instruction), Rc(instruction)); break; // CVTQF
- case 0x0be: OPERATE_FF("cvtqg", Rb(instruction), Rc(instruction)); break; // CVTQG
- case 0x100: OPERATE_FFF("addf/uc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDF/UC
- case 0x101: OPERATE_FFF("subf/uc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBF/UC
- case 0x102: OPERATE_FFF("mulf/uc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULF/UC
- case 0x103: OPERATE_FFF("divf/uc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVF/UC
- case 0x11e: OPERATE_FF("cvtdg/uc", Rb(instruction), Rc(instruction)); break; // CVTDG/UC
- case 0x120: OPERATE_FFF("addg/uc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDG/UC
- case 0x121: OPERATE_FFF("subg/uc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBG/UC
- case 0x122: OPERATE_FFF("mulg/uc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULG/UC
- case 0x123: OPERATE_FFF("divg/uc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVG/UC
- case 0x12c: OPERATE_FF("cvtgf/uc", Rb(instruction), Rc(instruction)); break; // CVTGF/UC
- case 0x12d: OPERATE_FF("cvtgd/uc", Rb(instruction), Rc(instruction)); break; // CVTGD/UC
- case 0x12f: OPERATE_FF("cvtgq/vc", Rb(instruction), Rc(instruction)); break; // CVTGQ/VC
- case 0x180: OPERATE_FFF("addf/u", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDF/U
- case 0x181: OPERATE_FFF("subf/u", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBF/U
- case 0x182: OPERATE_FFF("mulf/u", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULF/U
- case 0x183: OPERATE_FFF("divf/u", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVF/U
- case 0x19e: OPERATE_FF("cvtdg/u", Rb(instruction), Rc(instruction)); break; // CVTDG/U
- case 0x1a0: OPERATE_FFF("addg/u", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDG/U
- case 0x1a1: OPERATE_FFF("subg/u", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBG/U
- case 0x1a2: OPERATE_FFF("mulg/u", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULG/U
- case 0x1a3: OPERATE_FFF("divg/u", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVG/U
- case 0x1ac: OPERATE_FF("cvtgf/u", Rb(instruction), Rc(instruction)); break; // CVTGF/U
- case 0x1ad: OPERATE_FF("cvtgd/u", Rb(instruction), Rc(instruction)); break; // CVTGD/U
- case 0x1af: OPERATE_FF("cvtgq/v", Rb(instruction), Rc(instruction)); break; // CVTGQ/V
- case 0x400: OPERATE_FFF("addf/sc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDF/SC
- case 0x401: OPERATE_FFF("subf/sc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBF/SC
- case 0x402: OPERATE_FFF("mulf/sc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULF/SC
- case 0x403: OPERATE_FFF("divf/sc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVF/SC
- case 0x41e: OPERATE_FF("cvtdg/sc", Rb(instruction), Rc(instruction)); break; // CVTDG/SC
- case 0x420: OPERATE_FFF("addg/sc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDG/SC
- case 0x421: OPERATE_FFF("subg/sc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBG/SC
- case 0x422: OPERATE_FFF("mulg/sc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULG/SC
- case 0x423: OPERATE_FFF("divg/sc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVG/SC
- case 0x42c: OPERATE_FF("cvtgf/sc", Rb(instruction), Rc(instruction)); break; // CVTGF/SC
- case 0x42d: OPERATE_FF("cvtgd/sc", Rb(instruction), Rc(instruction)); break; // CVTGD/SC
- case 0x42f: OPERATE_FF("cvtgq/sc", Rb(instruction), Rc(instruction)); break; // CVTGQ/SC
- case 0x480: OPERATE_FFF("addf/s", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDF/S
- case 0x481:
- if (Ra(instruction) == 31)
- OPERATE_FF("negf/s", Rb(instruction), Rc(instruction));
- else
- OPERATE_FFF("subf/s", Ra(instruction), Rb(instruction), Rc(instruction)); // SUBF/S
- break;
- case 0x482: OPERATE_FFF("mulf/s", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULF/S
- case 0x483: OPERATE_FFF("divf/s", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVF/S
- case 0x49e: OPERATE_FF("cvtdg/s", Rb(instruction), Rc(instruction)); break; // CVTDG/S
- case 0x4a0: OPERATE_FFF("addg/s", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDG/S
- case 0x4a1:
- if (Ra(instruction) == 31)
- OPERATE_FF("negg/s", Rb(instruction), Rc(instruction));
- else
- OPERATE_FFF("subg/s", Ra(instruction), Rb(instruction), Rc(instruction)); // SUBG/S
- break;
- case 0x4a2: OPERATE_FFF("mulg/s", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULG/S
- case 0x4a3: OPERATE_FFF("divg/s", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVG/S
- case 0x4a5: OPERATE_FFF("cmpgeq/s", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPGEQ/S
- case 0x4a6: OPERATE_FFF("cmpglt/s", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPGLT/S
- case 0x4a7: OPERATE_FFF("cmpgle/s", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPGLE/S
- case 0x4ac: OPERATE_FF("cvtgf/s", Rb(instruction), Rc(instruction)); break; // CVTGF/S
- case 0x4ad: OPERATE_FF("cvtgd/s", Rb(instruction), Rc(instruction)); break; // CVTGD/S
- case 0x4af: OPERATE_FF("cvtgq/s", Rb(instruction), Rc(instruction)); break; // CVTGQ/S
- case 0x500: OPERATE_FFF("addf/suc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDF/SUC
- case 0x501: OPERATE_FFF("subf/suc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBF/SUC
- case 0x502: OPERATE_FFF("mulf/suc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULF/SUC
- case 0x503: OPERATE_FFF("divf/suc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVF/SUC
- case 0x51e: OPERATE_FF("cvtdg/suc", Rb(instruction), Rc(instruction)); break; // CVTDG/SUC
- case 0x520: OPERATE_FFF("addg/suc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDG/SUC
- case 0x521: OPERATE_FFF("subg/suc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBG/SUC
- case 0x522: OPERATE_FFF("mulg/suc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULG/SUC
- case 0x523: OPERATE_FFF("divg/suc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVG/SUC
- case 0x52c: OPERATE_FF("cvtgf/suc", Rb(instruction), Rc(instruction)); break; // CVTGF/SUC
- case 0x52d: OPERATE_FF("cvtgd/suc", Rb(instruction), Rc(instruction)); break; // CVTGD/SUC
- case 0x52f: OPERATE_FF("cvtgq/svc", Rb(instruction), Rc(instruction)); break; // CVTGQ/SVC
- case 0x580: OPERATE_FFF("addf/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDF/SU
- case 0x581: OPERATE_FFF("subf/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBF/SU
- case 0x582: OPERATE_FFF("mulf/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULF/SU
- case 0x583: OPERATE_FFF("divf/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVF/SU
- case 0x59e: OPERATE_FF("cvtdg/su", Rb(instruction), Rc(instruction)); break; // CVTDG/SU
- case 0x5a0: OPERATE_FFF("addg/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDG/SU
- case 0x5a1: OPERATE_FFF("subg/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBG/SU
- case 0x5a2: OPERATE_FFF("mulg/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULG/SU
- case 0x5a3: OPERATE_FFF("divg/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVG/SU
- case 0x5ac: OPERATE_FF("cvtgf/su", Rb(instruction), Rc(instruction)); break; // CVTGF/SU
- case 0x5ad: OPERATE_FF("cvtgd/su", Rb(instruction), Rc(instruction)); break; // CVTGD/SU
- case 0x5af: OPERATE_FF("cvtgq/sv", Rb(instruction), Rc(instruction)); break; // CVTGQ/SV
-
- default: UNKNOWN("fltv*"); break;
- }
- break;
- case 0x16: // FLTI* (ieee floating)
- switch ((instruction >> 5) & 0x7ff)
- {
- case 0x000: OPERATE_FFF("adds/c", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS/C
- case 0x001: OPERATE_FFF("subs/c", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBS/C
- case 0x002: OPERATE_FFF("muls/c", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS/C
- case 0x003: OPERATE_FFF("divs/c", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS/C
- case 0x020: OPERATE_FFF("addt/c", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT/C
- case 0x021: OPERATE_FFF("subt/c", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBT/C
- case 0x022: OPERATE_FFF("mult/c", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT/C
- case 0x023: OPERATE_FFF("divt/c", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT/C
- case 0x02c: OPERATE_FF("cvttts/c", Rb(instruction), Rc(instruction)); break; // CVTTS/C
- case 0x02f: OPERATE_FF("cvttq/c", Rb(instruction), Rc(instruction)); break; // CVTTQ/C
- case 0x03c: OPERATE_FF("cvtqs/c", Rb(instruction), Rc(instruction)); break; // CVTQS/C
- case 0x03e: OPERATE_FF("cvtqt/c", Rb(instruction), Rc(instruction)); break; // CVTQT/C
- case 0x040: OPERATE_FFF("adds/m", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS/M
- case 0x041: OPERATE_FFF("subs/m", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBS/M
- case 0x042: OPERATE_FFF("muls/m", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS/M
- case 0x043: OPERATE_FFF("divs/m", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS/M
- case 0x060: OPERATE_FFF("addt/m", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT/M
- case 0x061: OPERATE_FFF("subt/m", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBT/M
- case 0x062: OPERATE_FFF("mult/m", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT/M
- case 0x063: OPERATE_FFF("divt/m", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT/M
- case 0x06c: OPERATE_FF("cvttts/m", Rb(instruction), Rc(instruction)); break; // CVTTS/M
- case 0x06f: OPERATE_FF("cvttq/m", Rb(instruction), Rc(instruction)); break; // CVTTQ/M
- case 0x07c: OPERATE_FF("cvtqs/m", Rb(instruction), Rc(instruction)); break; // CVTQS/M
- case 0x07e: OPERATE_FF("cvtqt/m", Rb(instruction), Rc(instruction)); break; // CVTQT/M
- case 0x080: OPERATE_FFF("adds", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS
- case 0x081:
- if (Ra(instruction) == 31)
- OPERATE_FF("negs", Rb(instruction), Rc(instruction));
- else
- OPERATE_FFF("subs", Ra(instruction), Rb(instruction), Rc(instruction)); // SUBS
- break;
- case 0x082: OPERATE_FFF("muls", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS
- case 0x083: OPERATE_FFF("divs", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS
- case 0x0a0: OPERATE_FFF("addt", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT
- case 0x0a1:
- if (Ra(instruction) == 31)
- OPERATE_FF("negt", Rb(instruction), Rc(instruction));
- else
- OPERATE_FFF("subt", Ra(instruction), Rb(instruction), Rc(instruction)); // SUBT
- break;
- case 0x0a2: OPERATE_FFF("mult", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT
- case 0x0a3: OPERATE_FFF("divt", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT
- case 0x0a4: OPERATE_FFF("cmptun", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPTUN
- case 0x0a5: OPERATE_FFF("cmpteq", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPTEQ
- case 0x0a6: OPERATE_FFF("cmptlt", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPTLT
- case 0x0a7: OPERATE_FFF("cmptle", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPTLE
- case 0x0ac: OPERATE_FF("cvttts", Rb(instruction), Rc(instruction)); break; // CVTTS
- case 0x0af: OPERATE_FF("cvttq", Rb(instruction), Rc(instruction)); break; // CVTTQ
- case 0x0bc: OPERATE_FF("cvtqs", Rb(instruction), Rc(instruction)); break; // CVTQS
- case 0x0be: OPERATE_FF("cvtqt", Rb(instruction), Rc(instruction)); break; // CVTQT
- case 0x0c0: OPERATE_FFF("adds/d", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS/D
- case 0x0c1: OPERATE_FFF("subs/d", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBS/D
- case 0x0c2: OPERATE_FFF("muls/d", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS/D
- case 0x0c3: OPERATE_FFF("divs/d", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS/D
- case 0x0e0: OPERATE_FFF("addt/d", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT/D
- case 0x0e1: OPERATE_FFF("subt/d", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBT/D
- case 0x0e2: OPERATE_FFF("mult/d", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT/D
- case 0x0e3: OPERATE_FFF("divt/d", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT/D
- case 0x0ec: OPERATE_FF("cvttts/d", Rb(instruction), Rc(instruction)); break; // CVTTS/D
- case 0x0ef: OPERATE_FF("cvttq/d", Rb(instruction), Rc(instruction)); break; // CVTTQ/D
- case 0x0fc: OPERATE_FF("cvtqs/d", Rb(instruction), Rc(instruction)); break; // CVTQS/D
- case 0x0fe: OPERATE_FF("cvtqt/d", Rb(instruction), Rc(instruction)); break; // CVTQT/D
- case 0x100: OPERATE_FFF("adds/uc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS/UC
- case 0x101: OPERATE_FFF("subs/uc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBS/UC
- case 0x102: OPERATE_FFF("muls/uc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS/UC
- case 0x103: OPERATE_FFF("divs/uc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS/UC
- case 0x120: OPERATE_FFF("addt/uc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT/UC
- case 0x121: OPERATE_FFF("subt/uc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBT/UC
- case 0x122: OPERATE_FFF("mult/uc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT/UC
- case 0x123: OPERATE_FFF("divt/uc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT/UC
- case 0x12c: OPERATE_FF("cvttts/uc", Rb(instruction), Rc(instruction)); break; // CVTTS/UC
- case 0x12f: OPERATE_FF("cvttq/vc", Rb(instruction), Rc(instruction)); break; // CVTTQ/VC
- case 0x140: OPERATE_FFF("adds/um", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS/UM
- case 0x141: OPERATE_FFF("subs/um", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBS/UM
- case 0x142: OPERATE_FFF("muls/um", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS/UM
- case 0x143: OPERATE_FFF("divs/um", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS/UM
- case 0x160: OPERATE_FFF("addt/um", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT/UM
- case 0x161: OPERATE_FFF("subt/um", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBT/UM
- case 0x162: OPERATE_FFF("mult/um", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT/UM
- case 0x163: OPERATE_FFF("divt/um", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT/UM
- case 0x16c: OPERATE_FF("cvttts/um", Rb(instruction), Rc(instruction)); break; // CVTTS/UM
- case 0x16f: OPERATE_FF("cvttq/vm", Rb(instruction), Rc(instruction)); break; // CVTTQ/VM
- case 0x180: OPERATE_FFF("adds/u", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS/U
- case 0x181: OPERATE_FFF("subs/u", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBS/U
- case 0x182: OPERATE_FFF("muls/u", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS/U
- case 0x183: OPERATE_FFF("divs/u", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS/U
- case 0x1a0: OPERATE_FFF("addt/u", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT/U
- case 0x1a1: OPERATE_FFF("subt/u", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBT/U
- case 0x1a2: OPERATE_FFF("mult/u", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT/U
- case 0x1a3: OPERATE_FFF("divt/u", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT/U
- case 0x1ac: OPERATE_FF("cvttts/u", Rb(instruction), Rc(instruction)); break; // CVTTS/U
- case 0x1af: OPERATE_FF("cvttq/v", Rb(instruction), Rc(instruction)); break; // CVTTQ/V
- case 0x1c0: OPERATE_FFF("adds/ud", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS/UD
- case 0x1c1: OPERATE_FFF("subs/ud", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBS/UD
- case 0x1c2: OPERATE_FFF("muls/ud", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS/UD
- case 0x1c3: OPERATE_FFF("divs/ud", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS/UD
- case 0x1e0: OPERATE_FFF("addt/ud", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT/UD
- case 0x1e1: OPERATE_FFF("subs/ud", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBT/UD
- case 0x1e2: OPERATE_FFF("mult/ud", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT/UD
- case 0x1e3: OPERATE_FFF("divt/ud", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT/UD
- case 0x1ec: OPERATE_FF("cvttts/ud", Rb(instruction), Rc(instruction)); break; // CVTTS/UD
- case 0x1ef: OPERATE_FF("cvttq/vd", Rb(instruction), Rc(instruction)); break; // CVTTQ/VD
- case 0x2ac: OPERATE_FF("cvtst", Rb(instruction), Rc(instruction)); break; // CVTST
- case 0x500: OPERATE_FFF("adds/suc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS/SUC
- case 0x501: OPERATE_FFF("subs/suc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBS/SUC
- case 0x502: OPERATE_FFF("muls/suc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS/SUC
- case 0x503: OPERATE_FFF("divs/suc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS/SUC
- case 0x520: OPERATE_FFF("addt/suc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT/SUC
- case 0x521: OPERATE_FFF("subt/suc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBT/SUC
- case 0x522: OPERATE_FFF("mult/suc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT/SUC
- case 0x523: OPERATE_FFF("divt/suc", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT/SUC
- case 0x52c: OPERATE_FF("cvttts/suc", Rb(instruction), Rc(instruction)); break; // CVTTS/SUC
- case 0x52f: OPERATE_FF("cvttq/svc", Rb(instruction), Rc(instruction)); break; // CVTTQ/SVC
- case 0x540: OPERATE_FFF("adds/sum", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS/SUM
- case 0x541: OPERATE_FFF("subs/sum", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBS/SUM
- case 0x542: OPERATE_FFF("muls/sum", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS/SUM
- case 0x543: OPERATE_FFF("divs/sum", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS/SUM
- case 0x560: OPERATE_FFF("addt/sum", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT/SUM
- case 0x561: OPERATE_FFF("subt/sum", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBT/SUM
- case 0x562: OPERATE_FFF("mult/sum", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT/SUM
- case 0x563: OPERATE_FFF("divt/sum", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT/SUM
- case 0x56c: OPERATE_FF("cvttts/sum", Rb(instruction), Rc(instruction)); break; // CVTTS/SUM
- case 0x56f: OPERATE_FF("cvttq/svm", Rb(instruction), Rc(instruction)); break; // CVTTQ/SVM
- case 0x580: OPERATE_FFF("adds/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS/SU
- case 0x581:
- if (Ra(instruction) == 31)
- OPERATE_FF("negs/su", Rb(instruction), Rc(instruction));
- else
- OPERATE_FFF("subs/su", Ra(instruction), Rb(instruction), Rc(instruction)); // SUBS/SU
- break;
- case 0x582: OPERATE_FFF("muls/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS/SU
- case 0x583: OPERATE_FFF("divs/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS/SU
- case 0x5a0: OPERATE_FFF("addt/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT/SU
- case 0x5a1:
- if (Ra(instruction) == 31)
- OPERATE_FF("negt/su", Rb(instruction), Rc(instruction));
- else
- OPERATE_FFF("subt/su", Ra(instruction), Rb(instruction), Rc(instruction)); // SUBT/SU
- break;
- case 0x5a2: OPERATE_FFF("mult/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT/SU
- case 0x5a3: OPERATE_FFF("divt/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT/SU
- case 0x5a4: OPERATE_FFF("cmptun/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPTUN/SU
- case 0x5a5: OPERATE_FFF("cmpteq/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPTEQ/SU
- case 0x5a6: OPERATE_FFF("cmptlt/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPTLT/SU
- case 0x5a7: OPERATE_FFF("cmptle/su", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CMPTLE/SU
- case 0x5ac: OPERATE_FF("cvttts/su", Rb(instruction), Rc(instruction)); break; // CVTTS/SU
- case 0x5af: OPERATE_FF("cvttq/sv", Rb(instruction), Rc(instruction)); break; // CVTTQ/SV
- case 0x5c0: OPERATE_FFF("adds/sud", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS/SUD
- case 0x5c1: OPERATE_FFF("subs/sud", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBS/SUD
- case 0x5c2: OPERATE_FFF("muls/sud", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS/SUD
- case 0x5c3: OPERATE_FFF("divs/sud", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS/SUD
- case 0x5e0: OPERATE_FFF("addt/sud", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT/SUD
- case 0x5e1: OPERATE_FFF("subt/sud", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBT/SUD
- case 0x5e2: OPERATE_FFF("mult/sud", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT/SUD
- case 0x5e3: OPERATE_FFF("divt/sud", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT/SUD
- case 0x5ec: OPERATE_FF("cvttts/sud", Rb(instruction), Rc(instruction)); break; // CVTTS/SUD
- case 0x5ef: OPERATE_FF("cvttq/svd", Rb(instruction), Rc(instruction)); break; // CVTTQ/SVD
- case 0x6ac: OPERATE_FF("cvtst/s", Rb(instruction), Rc(instruction)); break; // CVTST/S
- case 0x700: OPERATE_FFF("adds/suic", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS/SUIC
- case 0x701: OPERATE_FFF("subs/suic", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBS/SUIC
- case 0x702: OPERATE_FFF("muls/suic", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS/SUIC
- case 0x703: OPERATE_FFF("divs/suic", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS/SUIC
- case 0x720: OPERATE_FFF("addt/suic", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT/SUIC
- case 0x721: OPERATE_FFF("subt/suic", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBT/SUIC
- case 0x722: OPERATE_FFF("mult/suic", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT/SUIC
- case 0x723: OPERATE_FFF("divt/suic", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT/SUIC
- case 0x72c: OPERATE_FF("cvttts/suic", Rb(instruction), Rc(instruction)); break; // CVTTS/SUIC
- case 0x72f: OPERATE_FF("cvttq/svic", Rb(instruction), Rc(instruction)); break; // CVTTQ/SVIC
- case 0x73c: OPERATE_FF("cvtqs/suic", Rb(instruction), Rc(instruction)); break; // CVTQS/SUIC
- case 0x73e: OPERATE_FF("cvtqt/suic", Rb(instruction), Rc(instruction)); break; // CVTQT/SUIC
- case 0x740: OPERATE_FFF("adds/suim", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS/SUIM
- case 0x741: OPERATE_FFF("subs/suim", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBS/SUIM
- case 0x742: OPERATE_FFF("muls/suim", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS/SUIM
- case 0x743: OPERATE_FFF("divs/suim", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS/SUIM
- case 0x760: OPERATE_FFF("addt/suim", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT/SUIM
- case 0x761: OPERATE_FFF("subt/suim", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBT/SUIM
- case 0x762: OPERATE_FFF("mult/suim", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT/SUIM
- case 0x763: OPERATE_FFF("divt/suim", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT/SUIM
- case 0x76c: OPERATE_FF("cvttts/suim", Rb(instruction), Rc(instruction)); break; // CVTTS/SUIM
- case 0x76f: OPERATE_FF("cvttq/svim", Rb(instruction), Rc(instruction)); break; // CVTTQ/SVIM
- case 0x77c: OPERATE_FF("cvtqs/suim", Rb(instruction), Rc(instruction)); break; // CVTQS/SUIM
- case 0x77e: OPERATE_FF("cvtqt/suim", Rb(instruction), Rc(instruction)); break; // CVTQT/SUIM
- case 0x780: OPERATE_FFF("adds/sui", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS/SUI
- case 0x781:
- if (Ra(instruction) == 31)
- OPERATE_FF("negs/sui", Rb(instruction), Rc(instruction));
- else
- OPERATE_FFF("subs/sui", Ra(instruction), Rb(instruction), Rc(instruction)); // SUBS/SUI
- break;
- case 0x782: OPERATE_FFF("muls/sui", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS/SUI
- case 0x783: OPERATE_FFF("divs/sui", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS/SUI
- case 0x7a0: OPERATE_FFF("addt/sui", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT/SUI
- case 0x7a1:
- if (Ra(instruction) == 31)
- OPERATE_FF("negt/sui", Rb(instruction), Rc(instruction));
- else
- OPERATE_FFF("subt/sui", Ra(instruction), Rb(instruction), Rc(instruction)); // SUBT/SUI
- break;
- case 0x7a2: OPERATE_FFF("mult/sui", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT/SUI
- case 0x7a3: OPERATE_FFF("divt/sui", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT/SUI
- case 0x7ac: OPERATE_FF("cvttts/sui", Rb(instruction), Rc(instruction)); break; // CVTTS/SUI
- case 0x7af: OPERATE_FF("cvttq/svi", Rb(instruction), Rc(instruction)); break; // CVTTQ/SVI
- case 0x7bc: OPERATE_FF("cvtqs/sui", Rb(instruction), Rc(instruction)); break; // CVTQS/SUI
- case 0x7be: OPERATE_FF("cvtqt/sui", Rb(instruction), Rc(instruction)); break; // CVTQT/SUI
- case 0x7c0: OPERATE_FFF("adds/suid", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDS/SUID
- case 0x7c1: OPERATE_FFF("subs/suid", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBS/SUID
- case 0x7c2: OPERATE_FFF("muls/suid", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULS/SUID
- case 0x7c3: OPERATE_FFF("divs/suid", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVS/SUID
- case 0x7e0: OPERATE_FFF("addt/suid", Ra(instruction), Rb(instruction), Rc(instruction)); break; // ADDT/SUID
- case 0x7e1: OPERATE_FFF("subt/suid", Ra(instruction), Rb(instruction), Rc(instruction)); break; // SUBT/SUID
- case 0x7e2: OPERATE_FFF("mult/suid", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MULT/SUID
- case 0x7e3: OPERATE_FFF("divt/suid", Ra(instruction), Rb(instruction), Rc(instruction)); break; // DIVT/SUID
- case 0x7ec: OPERATE_FF("cvttts/suid", Rb(instruction), Rc(instruction)); break; // CVTTS/SUID
- case 0x7ef: OPERATE_FF("cvttq/svid", Rb(instruction), Rc(instruction)); break; // CVTTQ/SVID
- case 0x7fc: OPERATE_FF("cvtqs/suid", Rb(instruction), Rc(instruction)); break; // CVTQS/SUID
- case 0x7fe: OPERATE_FF("cvtqt/suid", Rb(instruction), Rc(instruction)); break; // CVTQT/SUID
-
- default: UNKNOWN("flti*"); break;
- }
- break;
- case 0x17: // FLTL* (floating)
- switch ((instruction >> 5) & 0x7ff)
- {
- case 0x010: OPERATE_FF("cvtlq", Rb(instruction), Rc(instruction)); break; // CVTLQ
- case 0x020:
- if (Ra(instruction) == 31 && Rb(instruction) == 31 && Rc(instruction) == 31)
- MISC("fnop");
- else if (Ra(instruction) == 31 && Rb(instruction) == 31)
- OPERATE_F("fclr", Rc(instruction));
- else if (Ra(instruction) == 31)
- OPERATE_FF("fabs", Rb(instruction), Rc(instruction));
- else if (Ra(instruction) == Rb(instruction))
- OPERATE_FF("fmov", Rb(instruction), Rc(instruction));
- else
- OPERATE_FFF("cpys", Ra(instruction), Rb(instruction), Rc(instruction)); // CPYS
- break;
- case 0x021:
- if (Ra(instruction) == Rb(instruction))
- OPERATE_FF("fneg", Rb(instruction), Rc(instruction));
- else
- OPERATE_FFF("cpysn", Ra(instruction), Rb(instruction), Rc(instruction)); // CPYSN
- break;
- case 0x022: OPERATE_FFF("cpyse", Ra(instruction), Rb(instruction), Rc(instruction)); break; // CPYSE
- case 0x024:
- if (Ra(instruction) == Rb(instruction) && Rb(instruction) == Rc(instruction))
- OPERATE_F("mt_fpcr", Rc(instruction));
- else
- OPERATE_FFF("mt_fpcr", Ra(instruction), Rb(instruction), Rc(instruction)); // MT_FPCR
- break;
- case 0x025:
- if (Ra(instruction) == Rb(instruction) && Rb(instruction) == Rc(instruction))
- OPERATE_F("mf_fpcr", Rc(instruction));
- else
- OPERATE_FFF("mf_fpcr", Ra(instruction), Rb(instruction), Rc(instruction)); // MF_FPCR
- break;
- case 0x02a: OPERATE_FFF("fcmoveq", Ra(instruction), Rb(instruction), Rc(instruction)); break; // FCMOVEQ
- case 0x02b: OPERATE_FFF("fcmovne", Ra(instruction), Rb(instruction), Rc(instruction)); break; // FCMOVNE
- case 0x02c: OPERATE_FFF("fcmovlt", Ra(instruction), Rb(instruction), Rc(instruction)); break; // FCMOVLT
- case 0x02d: OPERATE_FFF("fcmovge", Ra(instruction), Rb(instruction), Rc(instruction)); break; // FCMOVGE
- case 0x02e: OPERATE_FFF("fcmovle", Ra(instruction), Rb(instruction), Rc(instruction)); break; // FCMOVLE
- case 0x02f: OPERATE_FFF("fcmovgt", Ra(instruction), Rb(instruction), Rc(instruction)); break; // FCMOVGT
- case 0x030: OPERATE_FF("cvtql", Rb(instruction), Rc(instruction)); break; // CVTQL
- case 0x130: OPERATE_FF("cvtql/v", Rb(instruction), Rc(instruction)); break; // CVTQL/V
- case 0x530: OPERATE_FF("cvtql/sv", Rb(instruction), Rc(instruction)); break; // CVTQL/SV
-
- default: UNKNOWN("fltl*"); break;
- }
- break;
- case 0x18: // MISC* (miscellaneous)
- switch (u16(instruction))
- {
- case 0x0000: MISC("trapb"); break; // TRAPB
- case 0x0400: MISC("excb"); break; // EXCB
- case 0x4000: MISC("mb"); break; // MB
- case 0x4400: MISC("wmb"); break; // WMB
- case 0x8000: MISC_M("fetch", Rb(instruction)); break; // FETCH
- case 0xa000: MISC_M("fetch_m", Rb(instruction)); break; // FETCH_M
- case 0xc000: MISC_R("rpcc", Ra(instruction)); break; // RPCC
- case 0xe000: MISC_R("rc", Ra(instruction)); break; // RC
- case 0xe800: MISC_M("ecb", Rb(instruction)); break; // ECB
- case 0xf000: MISC_R("rs", Ra(instruction)); break; // RS
- case 0xf800: MISC_M("wh64", Rb(instruction)); break; // WH64
-
- default: UNKNOWN("misc*"); break;
- }
- break;
- case 0x19: // PAL19
- switch ((instruction >> 5) & 0x7)
- {
- case 0x0: MISC("nop"); break;
- case 0x1: OPERATE_RI("hw_mfpr/i", Rb(instruction), Rc(instruction)); break;
- case 0x2: OPERATE_RA("hw_mfpr/a", Rb(instruction), Rc(instruction)); break;
- case 0x3: OPERATE_RAI("hw_mfpr/ai", Rb(instruction), Rc(instruction)); break;
- case 0x4: OPERATE_RP("hw_mfpr/p", Rb(instruction), Rc(instruction)); break;
- case 0x5: OPERATE_RPI("hw_mfpr/pi", Rb(instruction), Rc(instruction)); break;
- case 0x6: OPERATE_RPA("hw_mfpr/pa", Rb(instruction), Rc(instruction)); break;
- case 0x7: OPERATE_RPAI("hw_mfpr/pai", Rb(instruction), Rc(instruction)); break;
- }
- break;
-
- case 0x1a: // JSR* (jump)
- switch ((instruction >> 14) & 3)
- {
- case 0: JUMP("jmp", Ra(instruction), Rb(instruction)); break; // JMP
- case 1: JUMP("jsr", Ra(instruction), Rb(instruction)); flags |= STEP_OVER; break; // JSR
- case 2: JUMP("ret", Ra(instruction), Rb(instruction)); flags |= STEP_OUT; break; // RET
- case 3: JUMP("jsr_c", Ra(instruction), Rb(instruction)); break; // JSR_COROUTINE
- }
- break;
- case 0x1b: // PAL1B
- switch ((instruction >> 12) & 0xf)
- {
- case 0x0: MEMORY_R("hw_ldl", Ra(instruction), Disp_P(instruction), Rb(instruction)); break;
- case 0x1: MEMORY_R("hw_ldq", Ra(instruction), Disp_P(instruction), Rb(instruction)); break;
- case 0x2: MEMORY_R("hw_ldl/r", Ra(instruction), Disp_P(instruction), Rb(instruction)); break;
- case 0x3: MEMORY_R("hw_ldq/r", Ra(instruction), Disp_P(instruction), Rb(instruction)); break;
- case 0x4: MEMORY_R("hw_ldl/a", Ra(instruction), Disp_P(instruction), Rb(instruction)); break;
- case 0x5: MEMORY_R("hw_ldq/a", Ra(instruction), Disp_P(instruction), Rb(instruction)); break;
- case 0x6: MEMORY_R("hw_ldl/ar", Ra(instruction), Disp_P(instruction), Rb(instruction)); break;
- case 0x7: MEMORY_R("hw_ldq/ar", Ra(instruction), Disp_P(instruction), Rb(instruction)); break;
- case 0x8: MEMORY_R("hw_ldl/p", Ra(instruction), Disp_P(instruction), Rb(instruction)); break;
- case 0x9: MEMORY_R("hw_ldq/p", Ra(instruction), Disp_P(instruction), Rb(instruction)); break;
- case 0xa: MEMORY_R("hw_ldl/pr", Ra(instruction), Disp_P(instruction), Rb(instruction)); break;
- case 0xb: MEMORY_R("hw_ldq/pr", Ra(instruction), Disp_P(instruction), Rb(instruction)); break;
- case 0xc: MEMORY_R("hw_ldl/pa", Ra(instruction), Disp_P(instruction), Rb(instruction)); break;
- case 0xd: MEMORY_R("hw_ldq/pa", Ra(instruction), Disp_P(instruction), Rb(instruction)); break;
- case 0xe: MEMORY_R("hw_ldl/par", Ra(instruction), Disp_P(instruction), Rb(instruction)); break;
- case 0xf: MEMORY_R("hw_ldq/par", Ra(instruction), Disp_P(instruction), Rb(instruction)); break;
- }
- break;
- case 0x1c: // FPTI* (floating to integer)
- switch ((instruction >> 5) & 0xff)
- {
- // register variants
- case 0x00: OPERATE_RR("sextb", Rb(instruction), Rc(instruction)); break; // SEXTB (BWX)
- case 0x01: OPERATE_RR("sextw", Rb(instruction), Rc(instruction)); break; // SEXTW (BWX)
- case 0x30: OPERATE_RR("ctpop", Rb(instruction), Rc(instruction)); break; // CTPOP (CIX)
- case 0x31: OPERATE_RRR("perr", Ra(instruction), Rb(instruction), Rc(instruction)); break; // PERR (MVI)
- case 0x32: OPERATE_RR("ctlz", Rb(instruction), Rc(instruction)); break; // CTLZ (CIX)
- case 0x33: OPERATE_RR("cttz", Rb(instruction), Rc(instruction)); break; // CTTZ (CIX)
- case 0x34: OPERATE_RR("unpkbw", Rb(instruction), Rc(instruction)); break; // UNPKBW (MVI)
- case 0x35: OPERATE_RR("unpkbl", Rb(instruction), Rc(instruction)); break; // UNPKBL (MVI)
- case 0x36: OPERATE_RR("pkwb", Rb(instruction), Rc(instruction)); break; // PKWB (MVI)
- case 0x37: OPERATE_RR("pklb", Rb(instruction), Rc(instruction)); break; // PKLB (MVI)
- case 0x38: OPERATE_RRR("minsb8", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MINSB8 (MVI)
- case 0x39: OPERATE_RRR("minsw4", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MINSW4 (MVI)
- case 0x3a: OPERATE_RRR("minub8", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MINUB8 (MVI)
- case 0x3b: OPERATE_RRR("minuw4", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MINUW4 (MVI)
- case 0x3c: OPERATE_RRR("maxub8", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MAXUB8 (MVI)
- case 0x3d: OPERATE_RRR("maxuw4", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MAXUW4 (MVI)
- case 0x3e: OPERATE_RRR("maxsb8", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MAXSB8 (MVI)
- case 0x3f: OPERATE_RRR("maxsw4", Ra(instruction), Rb(instruction), Rc(instruction)); break; // MAXSW4 (MVI)
- case 0x70: OPERATE_FR("ftoit", Ra(instruction), Rc(instruction)); break; // FTOIT (FIX)
- case 0x78: OPERATE_FR("ftois", Ra(instruction), Rc(instruction)); break; // FTOIS (FIX)
-
- // immediate variants
- case 0x80: OPERATE_IR("sextb", Im(instruction), Rc(instruction)); break; // SEXTB (BWX)
- case 0x81: OPERATE_IR("sextw", Im(instruction), Rc(instruction)); break; // SEXTW (BWX)
- case 0xb8: OPERATE_RIR("minsb8", Ra(instruction), Im(instruction), Rc(instruction)); break; // MINSB8 (MVI)
- case 0xb9: OPERATE_RIR("minsw4", Ra(instruction), Im(instruction), Rc(instruction)); break; // MINSW4 (MVI)
- case 0xba: OPERATE_RIR("minub8", Ra(instruction), Im(instruction), Rc(instruction)); break; // MINUB8 (MVI)
- case 0xbb: OPERATE_RIR("minuw4", Ra(instruction), Im(instruction), Rc(instruction)); break; // MINUW4 (MVI)
- case 0xbc: OPERATE_RIR("maxub8", Ra(instruction), Im(instruction), Rc(instruction)); break; // MAXUB8 (MVI)
- case 0xbd: OPERATE_RIR("maxuw4", Ra(instruction), Im(instruction), Rc(instruction)); break; // MAXUW4 (MVI)
- case 0xbe: OPERATE_RIR("maxsb8", Ra(instruction), Im(instruction), Rc(instruction)); break; // MAXSB8 (MVI)
- case 0xbf: OPERATE_RIR("maxsw4", Ra(instruction), Im(instruction), Rc(instruction)); break; // MAXSW4 (MVI)
-
- default: UNKNOWN("fpti*"); break;
- }
- break;
- case 0x1d: // PAL1D
- switch ((instruction >> 5) & 0x7)
- {
- case 0x0: MISC("nop"); break;
- case 0x1: OPERATE_RI("hw_mtpr/i", Rb(instruction), Rc(instruction)); break;
- case 0x2: OPERATE_RA("hw_mtpr/a", Rb(instruction), Rc(instruction)); break;
- case 0x3: OPERATE_RAI("hw_mtpr/ai", Rb(instruction), Rc(instruction)); break;
- case 0x4: OPERATE_RP("hw_mtpr/p", Rb(instruction), Rc(instruction)); break;
- case 0x5: OPERATE_RPI("hw_mtpr/pi", Rb(instruction), Rc(instruction)); break;
- case 0x6: OPERATE_RPA("hw_mtpr/pa", Rb(instruction), Rc(instruction)); break;
- case 0x7: OPERATE_RPAI("hw_mtpr/pai", Rb(instruction), Rc(instruction)); break;
- }
- break;
- case 0x1e: // PAL1E
- switch (instruction & 0x03ffffff)
- {
- case 0x03ff8000: MISC("hw_rei"); break;
-
- default: UNKNOWN("pal1e"); break;
- }
- break;
- case 0x1f: // PAL1F
- switch ((instruction >> 12) & 0xf)
- {
- case 0x0: MEMORY_R("hw_stl", Ra(instruction), Disp_P(instruction), Rb(instruction)); break;
- case 0x1: MEMORY_R("hw_stq", Ra(instruction), Disp_P(instruction), Rb(instruction)); break;
- case 0x2: MEMORY_R("hw_stl/r", Ra(instruction), Disp_P(instruction), Rb(instruction)); break;
- case 0x3: MEMORY_R("hw_stq/r", Ra(instruction), Disp_P(instruction), Rb(instruction)); break;
- case 0x4: MEMORY_R("hw_stl/a", Ra(instruction), Disp_P(instruction), Rb(instruction)); break;
- case 0x5: MEMORY_R("hw_stq/a", Ra(instruction), Disp_P(instruction), Rb(instruction)); break;
- case 0x6: MEMORY_R("hw_stl/ar", Ra(instruction), Disp_P(instruction), Rb(instruction)); break;
- case 0x7: MEMORY_R("hw_stq/ar", Ra(instruction), Disp_P(instruction), Rb(instruction)); break;
- case 0x8: MEMORY_R("hw_stl/p", Ra(instruction), Disp_P(instruction), Rb(instruction)); break;
- case 0x9: MEMORY_R("hw_stq/p", Ra(instruction), Disp_P(instruction), Rb(instruction)); break;
- case 0xa: MEMORY_R("hw_stl/pr", Ra(instruction), Disp_P(instruction), Rb(instruction)); break;
- case 0xb: MEMORY_R("hw_stq/pr", Ra(instruction), Disp_P(instruction), Rb(instruction)); break;
- case 0xc: MEMORY_R("hw_stl/pa", Ra(instruction), Disp_P(instruction), Rb(instruction)); break;
- case 0xd: MEMORY_R("hw_stq/pa", Ra(instruction), Disp_P(instruction), Rb(instruction)); break;
- case 0xe: MEMORY_R("hw_stl/par", Ra(instruction), Disp_P(instruction), Rb(instruction)); break;
- case 0xf: MEMORY_R("hw_stq/par", Ra(instruction), Disp_P(instruction), Rb(instruction)); break;
- }
- break;
- // memory format
- case 0x20: MEMORY_F("ldf", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // LDF
- case 0x21: MEMORY_F("ldg", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // LDG
- case 0x22: MEMORY_F("lds", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // LDS
- case 0x23: MEMORY_F("ldt", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // LDT
- case 0x24: MEMORY_F("stf", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // STF
- case 0x25: MEMORY_F("stg", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // STG
- case 0x26: MEMORY_F("sts", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // STS
- case 0x27: MEMORY_F("stt", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // STT
- case 0x28: MEMORY_R("ldl", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // LDL
- case 0x29: MEMORY_R("ldq", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // LDQ
- case 0x2a: MEMORY_R("ldl_l", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // LDL_L
- case 0x2b: MEMORY_R("ldq_l", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // LDQ_L
- case 0x2c: MEMORY_R("stl", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // STL
- case 0x2d: MEMORY_R("stq", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // STQ
- case 0x2e: MEMORY_R("stl_c", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // STL_C
- case 0x2f: MEMORY_R("stq_c", Ra(instruction), Disp_M(instruction), Rb(instruction)); break; // STQ_C
-
- // branch format
- case 0x30:
- if (Ra(instruction) == 31)
- BRANCH("br", Disp_B(instruction));
- else
- BRANCH_R("br", Ra(instruction), Disp_B(instruction)); // BR
- break;
- case 0x31: BRANCH_F("fbeq", Ra(instruction), Disp_B(instruction)); break; // FBEQ
- case 0x32: BRANCH_F("fblt", Ra(instruction), Disp_B(instruction)); break; // FBLT
- case 0x33: BRANCH_F("fble", Ra(instruction), Disp_B(instruction)); break; // FBLE
- case 0x34: BRANCH_R("bsr", Ra(instruction), Disp_B(instruction)); break; // BSR
- case 0x35: BRANCH_F("fbne", Ra(instruction), Disp_B(instruction)); break; // FBNE
- case 0x36: BRANCH_F("fbge", Ra(instruction), Disp_B(instruction)); break; // FBGE
- case 0x37: BRANCH_F("fbgt", Ra(instruction), Disp_B(instruction)); break; // FBGT
- case 0x38: BRANCH_R("blbc", Ra(instruction), Disp_B(instruction)); break; // BLBC
- case 0x39: BRANCH_R("beq", Ra(instruction), Disp_B(instruction)); break; // BEQ
- case 0x3a: BRANCH_R("blt", Ra(instruction), Disp_B(instruction)); break; // BLT
- case 0x3b: BRANCH_R("ble", Ra(instruction), Disp_B(instruction)); break; // BLE
- case 0x3c: BRANCH_R("blbs", Ra(instruction), Disp_B(instruction)); break; // BLBS
- case 0x3d: BRANCH_R("bne", Ra(instruction), Disp_B(instruction)); break; // BNE
- case 0x3e: BRANCH_R("bge", Ra(instruction), Disp_B(instruction)); break; // BGE
- case 0x3f: BRANCH_R("bgt", Ra(instruction), Disp_B(instruction)); break; // BGT
- }
-
- return bytes | flags;
-}
diff --git a/src/devices/cpu/alpha/alphad.h b/src/devices/cpu/alpha/alphad.h
deleted file mode 100644
index 3c3475e5730..00000000000
--- a/src/devices/cpu/alpha/alphad.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Patrick Mackinlay
-
-#ifndef MAME_CPU_ALPHA_ALPHAD_H
-#define MAME_CPU_ALPHA_ALPHAD_H
-
-#pragma once
-
-class alpha_disassembler : public util::disasm_interface
-{
-public:
- enum dasm_type : unsigned
- {
- TYPE_UNKNOWN = 0,
- TYPE_NT = 1,
- TYPE_UNIX = 2,
- TYPE_VMS = 3,
- };
-
- alpha_disassembler(alpha_disassembler::dasm_type type = TYPE_UNKNOWN)
- : m_dasm_type(type)
- {
- };
- virtual ~alpha_disassembler() = default;
-
- virtual u32 opcode_alignment() const override { return 4; };
- virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params) override;
-
-private:
- static char const *const R[];
- static char const *const F[];
-
- static char const *const PT[];
- static char const *const ABX[];
- static char const *const IBX[];
-
- dasm_type const m_dasm_type;
-};
-
-#endif // MAME_CPU_ALPHA_ALPHAD_H
diff --git a/src/devices/cpu/alpha/common.h b/src/devices/cpu/alpha/common.h
deleted file mode 100644
index 0c9668f304a..00000000000
--- a/src/devices/cpu/alpha/common.h
+++ /dev/null
@@ -1,19 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Patrick Mackinlay
-
-#ifndef MAME_CPU_ALPHA_COMMON_H
-#define MAME_CPU_ALPHA_COMMON_H
-
-#pragma once
-
-// instruction field extraction
-#define Ra(x) ((x >> 21) & 31) // 'a' register field
-#define Rb(x) ((x >> 16) & 31) // 'b' register field
-#define Rc(x) (x & 31) // 'c' register field
-#define Im(x) (u64(u8(x >> 13))) // literal immediate field
-
-#define Disp_M(x) (s64(s16(x))) // memory instruction 16-bit signed offset
-#define Disp_P(x) (s64(s16(x << 4)) >> 4) // hardware load/store 12-bit signed offset
-#define Disp_B(x) (s64(s32(x << 11)) >> 9) // branch instruction offset
-
-#endif // MAME_CPU_ALPHA_COMMON_H
diff --git a/src/devices/cpu/alto2/a2ether.cpp b/src/devices/cpu/alto2/a2ether.cpp
index 2c1a3d56a89..7af15ffbad0 100644
--- a/src/devices/cpu/alto2/a2ether.cpp
+++ b/src/devices/cpu/alto2/a2ether.cpp
@@ -522,7 +522,7 @@ void alto2_cpu_device::rx_breath_of_life(void* ptr, int32_t arg)
m_eth.rx_timer->adjust(attotime::from_seconds(m_eth.breath_of_life), 0);
} else {
// receive at a rate of 5.44us per word
- m_eth.rx_timer->adjust(attotime::from_nsec(5440), arg);
+ m_eth.rx_timer->adjust(attotime::from_usec(5.44), arg);
}
eth_wakeup();
}
@@ -557,10 +557,10 @@ void alto2_cpu_device::tx_packet(void* ptr, int32_t arg)
// the FIFO is empty now: clear the OBUSY and WLF flip flops
PUT_ETH_OBUSY(m_eth.status, 0);
PUT_ETH_WLF(m_eth.status, 0);
- m_eth.tx_timer->adjust(attotime::from_nsec(5440), -1);
+ m_eth.tx_timer->adjust(attotime::from_usec(5.44), -1);
} else {
// transmit the next word after 5.44us
- m_eth.tx_timer->adjust(attotime::from_nsec(5440), arg + 1);
+ m_eth.tx_timer->adjust(attotime::from_usec(5.44), arg + 1);
}
eth_wakeup();
}
@@ -722,7 +722,7 @@ void alto2_cpu_device::f2_late_eodfct()
uint8_t a49 = m_ether_a49[16 * m_eth.fifo_wr + m_eth.fifo_rd];
if (0 == BF(a49)) {
m_task_wakeup &= ~(1 << task_ether);
- m_eth.tx_timer->adjust(attotime::from_nsec(5440), 0);
+ m_eth.tx_timer->adjust(attotime::from_usec(5.44), 0);
}
}
@@ -774,7 +774,7 @@ void alto2_cpu_device::f2_late_eefct()
PUT_ETH_OBUSY(m_eth.status, 1);
PUT_ETH_OEOT(m_eth.status, 1);
// end transmitting the packet
- m_eth.tx_timer->adjust(attotime::from_nsec(5440), -1);
+ m_eth.tx_timer->adjust(attotime::from_usec(5.44), -1);
eth_wakeup();
}
diff --git a/src/devices/cpu/amis2000/amis2000.h b/src/devices/cpu/amis2000/amis2000.h
index 58665c7f6bc..2739461b44b 100644
--- a/src/devices/cpu/amis2000/amis2000.h
+++ b/src/devices/cpu/amis2000/amis2000.h
@@ -30,13 +30,12 @@ public:
// S2000 has a hardcoded 7seg table, that (unlike S2200) is officially
// uncustomizable, but wildfire proves to be an exception to that rule.
- void set_7seg_table(const u8 *ptr) { m_7seg_table = ptr; } // d0=A, d1=B, etc.
+ void set_7seg_table(const u8 *ptr) { m_7seg_table = ptr; }
void data_64x4(address_map &map);
void data_80x4(address_map &map);
void program_1_5k(address_map &map);
void program_1k(address_map &map);
-
protected:
// construction/destruction
amis2000_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u8 bu_bits, u8 callstack_bits, u8 callstack_depth, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data)
diff --git a/src/devices/cpu/amis2000/amis2000op.cpp b/src/devices/cpu/amis2000/amis2000op.cpp
index 92c2eaae3dc..e67ee6d153b 100644
--- a/src/devices/cpu/amis2000/amis2000op.cpp
+++ b/src/devices/cpu/amis2000/amis2000op.cpp
@@ -220,13 +220,11 @@ void amis2000_base_device::op_disn()
// DISN: set D-latch to ACC+carry via on-die segment decoder
static const u8 lut_segment_decoder[0x10] =
{
- 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, // 0-7
- 0x7f, 0x6f, 0x77, 0x7c, 0x39, 0x5e, 0x79, 0x71 // 8-F
+ // 0-F digits in bit order [DP]abcdefg
+ 0x7e, 0x30, 0x6d, 0x79, 0x33, 0x5b, 0x5f, 0x70, 0x7f, 0x7b, 0x77, 0x1f, 0x4e, 0x3d, 0x4f, 0x47
};
- const u8 *lut = (m_7seg_table != nullptr) ? m_7seg_table : lut_segment_decoder;
-
- // segments are in order [DP]abcdefg
- m_d = bitswap<7>(lut[m_acc],0,1,2,3,4,5,6) | (m_carry ? 0x80 : 0x00);
+ const u8 *ptr = (m_7seg_table != nullptr) ? m_7seg_table : lut_segment_decoder;
+ m_d = ptr[m_acc] | (m_carry ? 0x80 : 0x00);
d_latch_out(true);
}
@@ -502,6 +500,7 @@ void amis2000_base_device::op_rf2()
}
+
// AMI S2152 specific handlers
void amis2152_cpu_device::d2f_timer_clock()
diff --git a/src/devices/cpu/arm7/lpc210x.cpp b/src/devices/cpu/arm7/lpc210x.cpp
index d2964589e01..19f21ea7b00 100644
--- a/src/devices/cpu/arm7/lpc210x.cpp
+++ b/src/devices/cpu/arm7/lpc210x.cpp
@@ -2,7 +2,7 @@
// copyright-holders:David Haywood
/***************************************************************************
- NXP (Philips) LPC2103 series
+ NXP (Phillips) LPC2103 series
covering LPC2101, LPC2102, LPC2103*
*currently only LPC2103
@@ -276,6 +276,5 @@ void lpc210x_device::write_timer(address_space &space, int timer, int offset, ui
-void lpc210x_device::device_add_mconfig(machine_config &config)
-{
-}
+MACHINE_CONFIG_START(lpc210x_device::device_add_mconfig)
+MACHINE_CONFIG_END
diff --git a/src/devices/cpu/cosmac/cosmac.cpp b/src/devices/cpu/cosmac/cosmac.cpp
index e4155a514c7..0a7bd554d93 100644
--- a/src/devices/cpu/cosmac/cosmac.cpp
+++ b/src/devices/cpu/cosmac/cosmac.cpp
@@ -733,12 +733,10 @@ inline void cosmac_device::run_state()
case cosmac_state::STATE_2_DMA_IN:
dma_input();
- debug();
break;
case cosmac_state::STATE_2_DMA_OUT:
dma_output();
- debug();
break;
case cosmac_state::STATE_3_INT:
diff --git a/src/devices/cpu/dspp/dspp.h b/src/devices/cpu/dspp/dspp.h
index 302d141db13..9ebf08f6f6e 100644
--- a/src/devices/cpu/dspp/dspp.h
+++ b/src/devices/cpu/dspp/dspp.h
@@ -67,10 +67,10 @@ public:
DECLARE_READ16_MEMBER( noise_r );
void update_fifo_dma();
- void print_sums() { printf("%04x: %04x\n", (uint16_t)m_core->m_arg0, (uint16_t)m_core->m_arg1); }
- void print_branches() { printf("Branch: %d %d %d %d %d\n", m_core->m_arg0 ? 1 : 0, m_core->m_arg1 ? 1 : 0, m_core->m_arg2 ? 1 : 0, m_core->m_arg3 ? 1 : 0, m_core->m_arg4 ? 1 : 0); }
- void print_value() { printf("Value is %08x\n", m_core->m_arg0); }
- void print_addr() { printf("New value is %08x from %08x\n", m_core->m_arg0, m_core->m_arg1); }
+ void print_sums() { printf("%04x: %04x\n", (uint16_t)m_core->m_arg0, (uint16_t)m_core->m_arg1); }
+ void print_branches() { printf("Branch: %d %d %d %d %d\n", m_core->m_arg0 ? 1 : 0, m_core->m_arg1 ? 1 : 0, m_core->m_arg2 ? 1 : 0, m_core->m_arg3 ? 1 : 0, m_core->m_arg4 ? 1 : 0); }
+ void print_value() { printf("Value is %08x\n", m_core->m_arg0); }
+ void print_addr() { printf("New value is %08x from %08x\n", m_core->m_arg0, m_core->m_arg1); }
protected:
// device-level overrides
@@ -232,10 +232,10 @@ private:
const char *m_format;
uint32_t m_arg0;
- uint32_t m_arg1;
- uint32_t m_arg2;
- uint32_t m_arg3;
- uint32_t m_arg4;
+ uint32_t m_arg1;
+ uint32_t m_arg2;
+ uint32_t m_arg3;
+ uint32_t m_arg4;
struct
{
@@ -316,7 +316,7 @@ private:
uint32_t cycles; /* accumulated cycles */
uint8_t checkints; /* need to check interrupts before next instruction */
uint8_t checksoftints; /* need to check software interrupts before next instruction */
- uml::code_label abortlabel; /* label to abort execution of this block */
+ uml::code_label abortlabel; /* label to abort execution of this block */
uml::code_label labelnum; /* index for local labels */
};
diff --git a/src/devices/cpu/dspp/dsppdrc.cpp b/src/devices/cpu/dspp/dsppdrc.cpp
index 68b0c3cb741..aefa9b9999c 100644
--- a/src/devices/cpu/dspp/dsppdrc.cpp
+++ b/src/devices/cpu/dspp/dsppdrc.cpp
@@ -22,7 +22,7 @@ using namespace uml;
// map variables
#define MAPVAR_PC M0
-#define MAPVAR_CYCLES M1
+#define MAPVAR_CYCLES M1
// exit codes
#define EXECUTE_OUT_OF_CYCLES 0
@@ -244,12 +244,12 @@ void dspp_device::compile_block(offs_t pc)
if (seqhead->flags & OPFLAG_IS_BRANCH_TARGET)
UML_LABEL(block, seqhead->pc | 0x80000000); // label seqhead->pc
- compiler.abortlabel = compiler.labelnum++;
+ compiler.abortlabel = compiler.labelnum++;
/* iterate over instructions in the sequence and compile them */
for (curdesc = seqhead; curdesc != seqlast->next(); curdesc = curdesc->next())
generate_sequence_instruction(block, &compiler, curdesc);
- UML_LABEL(block, compiler.abortlabel);
+ UML_LABEL(block, compiler.abortlabel);
/* if we need to return to the start, do it */
if (seqlast->flags & OPFLAG_RETURN_TO_START)
@@ -293,11 +293,11 @@ void dspp_device::generate_checksum_block(drcuml_block &block, compiler_state *c
uint32_t sum = seqhead->opptr.w[0];
uint32_t addr = seqhead->physpc;
const void *base = m_codeptr(addr);
- UML_MOV(block, I0, 0);
+ UML_MOV(block, I0, 0);
UML_LOAD(block, I0, base, 0, SIZE_WORD, SCALE_x2); // load i0,base,0,word
- UML_CMP(block, I0, sum); // cmp i0,opptr[0]
- UML_EXHc(block, COND_NE, *m_nocode, seqhead->pc); // exne nocode,seqhead->pc
+ UML_CMP(block, I0, sum); // cmp i0,opptr[0]
+ UML_EXHc(block, COND_NE, *m_nocode, seqhead->pc); // exne nocode,seqhead->pc
}
}
@@ -307,7 +307,7 @@ void dspp_device::generate_checksum_block(drcuml_block &block, compiler_state *c
uint32_t sum = 0;
uint32_t addr = seqhead->physpc;
const void *base = m_codeptr(addr);
- UML_LOAD(block, I0, base, 0, SIZE_WORD, SCALE_x2); // load i0,base,0,dword
+ UML_LOAD(block, I0, base, 0, SIZE_WORD, SCALE_x2); // load i0,base,0,dword
sum += seqhead->opptr.w[0];
for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next())
if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP))
@@ -315,12 +315,12 @@ void dspp_device::generate_checksum_block(drcuml_block &block, compiler_state *c
addr = curdesc->physpc;
base = m_codeptr(addr);
assert(base != nullptr);
- UML_LOAD(block, I1, base, 0, SIZE_WORD, SCALE_x2); // load i1,base,dword
- UML_ADD(block, I0, I0, I1); // add i0,i0,i1
+ UML_LOAD(block, I1, base, 0, SIZE_WORD, SCALE_x2); // load i1,base,dword
+ UML_ADD(block, I0, I0, I1); // add i0,i0,i1
sum += curdesc->opptr.w[0];
}
- UML_CMP(block, I0, sum); // cmp i0,sum
- UML_EXHc(block, COND_NE, *m_nocode, epc(seqhead)); // exne nocode,seqhead->pc
+ UML_CMP(block, I0, sum); // cmp i0,sum
+ UML_EXHc(block, COND_NE, *m_nocode, epc(seqhead)); // exne nocode,seqhead->pc
}
}
@@ -373,12 +373,12 @@ void dspp_device::static_generate_nocode_handler()
/* generate a hash jump via the current mode and PC */
alloc_handle(m_drcuml.get(), &m_nocode, "nocode");
- UML_HANDLE(block, *m_nocode); // handle nocode
- UML_GETEXP(block, I0); // getexp i0
+ UML_HANDLE(block, *m_nocode); // handle nocode
+ UML_GETEXP(block, I0); // getexp i0
- UML_MOV(block, mem(&m_core->m_pc), I0); // mov [pc],i0
- //save_fast_iregs(block); // <save fastregs>
- UML_EXIT(block, EXECUTE_MISSING_CODE); // exit EXECUTE_MISSING_CODE
+ UML_MOV(block, mem(&m_core->m_pc), I0); // mov [pc],i0
+ //save_fast_iregs(block); // <save fastregs>
+ UML_EXIT(block, EXECUTE_MISSING_CODE); // exit EXECUTE_MISSING_CODE
block.end();
}
@@ -390,11 +390,11 @@ void dspp_device::static_generate_out_of_cycles()
/* generate a hash jump via the current mode and PC */
alloc_handle(m_drcuml.get(), &m_out_of_cycles, "out_of_cycles");
- UML_HANDLE(block, *m_out_of_cycles); // handle out_of_cycles
- UML_GETEXP(block, I0); // getexp i0
- UML_MOV(block, mem(&m_core->m_pc), I0); // mov <pc>,i0
- //save_fast_iregs(block); // <save fastregs>
- UML_EXIT(block, EXECUTE_OUT_OF_CYCLES); // exit EXECUTE_OUT_OF_CYCLES
+ UML_HANDLE(block, *m_out_of_cycles); // handle out_of_cycles
+ UML_GETEXP(block, I0); // getexp i0
+ UML_MOV(block, mem(&m_core->m_pc), I0); // mov <pc>,i0
+ //save_fast_iregs(block); // <save fastregs>
+ UML_EXIT(block, EXECUTE_OUT_OF_CYCLES); // exit EXECUTE_OUT_OF_CYCLES
block.end();
}
@@ -402,28 +402,28 @@ void dspp_device::static_generate_out_of_cycles()
void dspp_device::generate_sequence_instruction(drcuml_block &block, compiler_state *compiler, const opcode_desc *desc)
{
/* set the PC map variable */
- UML_MAPVAR(block, MAPVAR_PC, desc->pc); // mapvar PC,desc->pc
+ UML_MAPVAR(block, MAPVAR_PC, desc->pc); // mapvar PC,desc->pc
/* accumulate total cycles */
compiler->cycles += desc->cycles;
/* update the icount map variable */
- UML_MAPVAR(block, MAPVAR_CYCLES, compiler->cycles); // mapvar CYCLES,compiler->cycles
+ UML_MAPVAR(block, MAPVAR_CYCLES, compiler->cycles); // mapvar CYCLES,compiler->cycles
/* if we are debugging, call the debugger */
if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
{
- UML_MOV(block, mem(&m_core->m_pc), desc->pc); // mov [pc],desc->pc
- //save_fast_iregs(block); // <save fastregs>
- UML_DEBUG(block, desc->pc); // debug desc->pc
+ UML_MOV(block, mem(&m_core->m_pc), desc->pc); // mov [pc],desc->pc
+ //save_fast_iregs(block); // <save fastregs>
+ UML_DEBUG(block, desc->pc); // debug desc->pc
}
/* if we hit an unmapped address, fatal error */
if (desc->flags & OPFLAG_COMPILER_UNMAPPED)
{
- UML_MOV(block, mem(&m_core->m_pc), desc->pc); // mov [pc],desc->pc
- save_fast_iregs(block); // <save fastregs>
- UML_EXIT(block, EXECUTE_UNMAPPED_CODE); // exit EXECUTE_UNMAPPED_CODE
+ UML_MOV(block, mem(&m_core->m_pc), desc->pc); // mov [pc],desc->pc
+ save_fast_iregs(block); // <save fastregs>
+ UML_EXIT(block, EXECUTE_UNMAPPED_CODE); // exit EXECUTE_UNMAPPED_CODE
}
/* unless this is a virtual no-op, it's a regular instruction */
@@ -438,9 +438,9 @@ void dspp_device::generate_update_cycles(drcuml_block &block, compiler_state *co
/* account for cycles */
if (compiler->cycles > 0)
{
- UML_SUB(block, mem(&m_core->m_icount), mem(&m_core->m_icount), MAPVAR_CYCLES); // sub icount,icount,cycles
- UML_MAPVAR(block, MAPVAR_CYCLES, 0); // mapvar cycles,0
- UML_EXHc(block, COND_S, *m_out_of_cycles, param); // exh out_of_cycles,nextpc
+ UML_SUB(block, mem(&m_core->m_icount), mem(&m_core->m_icount), MAPVAR_CYCLES); // sub icount,icount,cycles
+ UML_MAPVAR(block, MAPVAR_CYCLES, 0); // mapvar cycles,0
+ UML_EXHc(block, COND_S, *m_out_of_cycles, param); // exh out_of_cycles,nextpc
}
compiler->cycles = 0;
}
@@ -458,8 +458,8 @@ void dspp_device::generate_opcode(drcuml_block &block, compiler_state *compiler,
code_label skip = compiler->labelnum++;
UML_TEST(block, mem(&m_core->m_dspx_control), DSPX_CONTROL_GWILLING);
UML_JMPc(block, COND_Z, compiler->abortlabel);
- //UML_TEST(block, mem(&m_core->m_flag_sleep), 1);
- //UML_JMPc(block, COND_NZ, compiler->abortlabel);
+ //UML_TEST(block, mem(&m_core->m_flag_sleep), 1);
+ //UML_JMPc(block, COND_NZ, compiler->abortlabel);
//UML_MOV(block, mem(&m_core->m_arg0), desc->physpc);
//UML_MOV(block, mem(&m_core->m_arg1), op);
@@ -522,7 +522,7 @@ void dspp_device::generate_super_special(drcuml_block &block, compiler_state *co
{
if (m_drcuml.get()->logging())
block.append_comment("BAC");
- UML_SHR(block, mem(&m_core->m_jmpdest), mem(&m_core->m_acc), 4); // m_core->m_pc = m_core->m_acc >> 4;
+ UML_SHR(block, mem(&m_core->m_jmpdest), mem(&m_core->m_acc), 4); // m_core->m_pc = m_core->m_acc >> 4;
generate_branch(block, compiler, desc);
break;
}
@@ -549,8 +549,8 @@ void dspp_device::generate_super_special(drcuml_block &block, compiler_state *co
// TODO: How does sleep work?
if (m_drcuml.get()->logging())
block.append_comment("SLEEP");
- UML_SUB(block, mem(&m_core->m_pc), mem(&m_core->m_pc), 1); // --m_core->m_pc;
- UML_MOV(block, mem(&m_core->m_flag_sleep), 1); // m_core->m_flag_sleep = 1;
+ UML_SUB(block, mem(&m_core->m_pc), mem(&m_core->m_pc), 1); // --m_core->m_pc;
+ UML_MOV(block, mem(&m_core->m_flag_sleep), 1); // m_core->m_flag_sleep = 1;
break;
}
@@ -609,7 +609,7 @@ void dspp_device::generate_special_opcode(drcuml_block &block, compiler_state *c
// Indirect
if (regdi & 0x0010)
{
- UML_CALLH(block, *m_dm_read16); // addr = read_data(addr);
+ UML_CALLH(block, *m_dm_read16); // addr = read_data(addr);
UML_MOV(block, I2, I0);
}
else
@@ -621,7 +621,7 @@ void dspp_device::generate_special_opcode(drcuml_block &block, compiler_state *c
generate_read_next_operand(block, compiler, desc);
UML_MOV(block, I0, I1);
UML_MOV(block, I1, I2);
- UML_CALLH(block, *m_dm_write16); // write_data(addr, read_next_operand());
+ UML_CALLH(block, *m_dm_write16); // write_data(addr, read_next_operand());
break;
}
case 5: // RBASE
@@ -639,7 +639,7 @@ void dspp_device::generate_special_opcode(drcuml_block &block, compiler_state *c
generate_read_next_operand(block, compiler, desc);
UML_MOV(block, I0, I1);
UML_MOV(block, I1, op & 0x3ff);
- UML_CALLH(block, *m_dm_write16); // write_data(op & 0x3ff, read_next_operand());
+ UML_CALLH(block, *m_dm_write16); // write_data(op & 0x3ff, read_next_operand());
break;
}
case 7: // MOVEI
@@ -648,12 +648,12 @@ void dspp_device::generate_special_opcode(drcuml_block &block, compiler_state *c
block.append_comment("MOVEI");
generate_parse_operands(block, compiler, desc, 1);
UML_MOV(block, I1, op & 0x3ff);
- UML_CALLH(block, *m_dm_read16); // uint32_t addr = read_data(op & 0x3ff);
+ UML_CALLH(block, *m_dm_read16); // uint32_t addr = read_data(op & 0x3ff);
UML_MOV(block, I2, I1);
generate_read_next_operand(block, compiler, desc);
UML_MOV(block, I0, I1);
UML_MOV(block, I1, I2);
- UML_CALLH(block, *m_dm_write16); // write_data(addr, read_next_operand());
+ UML_CALLH(block, *m_dm_write16); // write_data(addr, read_next_operand());
break;
}
@@ -669,23 +669,23 @@ void dspp_device::generate_branch(drcuml_block &block, compiler_state *compiler,
/* update the cycles and jump through the hash table to the target */
if (desc->targetpc != BRANCH_TARGET_DYNAMIC)
{
- generate_update_cycles(block, &compiler_temp, desc->targetpc); // <subtract cycles>
+ generate_update_cycles(block, &compiler_temp, desc->targetpc); // <subtract cycles>
if (desc->flags & OPFLAG_INTRABLOCK_BRANCH)
- UML_JMP(block, desc->targetpc | 0x80000000); // jmp desc->targetpc | 0x80000000
+ UML_JMP(block, desc->targetpc | 0x80000000); // jmp desc->targetpc | 0x80000000
else
- UML_HASHJMP(block, 0, desc->targetpc, *m_nocode); // hashjmp <mode>,desc->targetpc,nocode
+ UML_HASHJMP(block, 0, desc->targetpc, *m_nocode); // hashjmp <mode>,desc->targetpc,nocode
}
else
{
- generate_update_cycles(block, &compiler_temp, uml::mem(&m_core->m_jmpdest)); // <subtract cycles>
- UML_HASHJMP(block, 0, mem(&m_core->m_jmpdest), *m_nocode); // hashjmp <mode>,<rsreg>,nocode
+ generate_update_cycles(block, &compiler_temp, uml::mem(&m_core->m_jmpdest)); // <subtract cycles>
+ UML_HASHJMP(block, 0, mem(&m_core->m_jmpdest), *m_nocode); // hashjmp <mode>,<rsreg>,nocode
}
/* update the label */
compiler->labelnum = compiler_temp.labelnum;
/* reset the mapvar to the current cycles */
- UML_MAPVAR(block, MAPVAR_CYCLES, compiler->cycles); // mapvar CYCLES,compiler.cycles
+ UML_MAPVAR(block, MAPVAR_CYCLES, compiler->cycles); // mapvar CYCLES,compiler.cycles
}
void dspp_device::generate_branch_opcode(drcuml_block &block, compiler_state *compiler, const opcode_desc *desc)
@@ -718,10 +718,10 @@ void dspp_device::generate_branch_opcode(drcuml_block &block, compiler_state *co
UML_OR(block, I0, I0, mask0);
UML_OR(block, I1, I1, mask1);
- UML_AND(block, I0, I0, I1); // bool branch = (flag0 || mask0) && (flag1 || mask1);
+ UML_AND(block, I0, I0, I1); // bool branch = (flag0 || mask0) && (flag1 || mask1);
- if (mode == 2) // if (mode == 2)
- UML_SUB(block, I0, 1, I0); // branch = !branch;
+ if (mode == 2) // if (mode == 2)
+ UML_SUB(block, I0, 1, I0); // branch = !branch;
//UML_MOV(block, mem(&m_core->m_arg0), I0);
//UML_MOV(block, mem(&m_core->m_arg2), 1-mask0);
@@ -729,9 +729,9 @@ void dspp_device::generate_branch_opcode(drcuml_block &block, compiler_state *co
//UML_CALLC(block, cfunc_print_branches, this);
code_label skip = compiler->labelnum++;
- UML_TEST(block, I0, 1); // if (branch)
+ UML_TEST(block, I0, 1); // if (branch)
UML_JMPc(block, COND_Z, skip);
- UML_MOV(block, mem(&m_core->m_jmpdest), op & 0x3ff); // m_core->m_pc = op & 0x3ff;
+ UML_MOV(block, mem(&m_core->m_jmpdest), op & 0x3ff); // m_core->m_pc = op & 0x3ff;
generate_branch(block, compiler, desc);
UML_LABEL(block, skip);
}
@@ -745,19 +745,19 @@ void dspp_device::generate_complex_branch_opcode(drcuml_block &block, compiler_s
case 0: // BLT
if (m_drcuml.get()->logging())
block.append_comment("BLT");
- UML_XOR(block, I0, mem(&m_core->m_flag_neg), mem(&m_core->m_flag_over)); // branch = (n && !v) || (!n && v);
+ UML_XOR(block, I0, mem(&m_core->m_flag_neg), mem(&m_core->m_flag_over)); // branch = (n && !v) || (!n && v);
break;
case 1: // BLE
if (m_drcuml.get()->logging())
block.append_comment("BLE");
UML_XOR(block, I0, mem(&m_core->m_flag_neg), mem(&m_core->m_flag_over));
- UML_OR(block, I0, I0, mem(&m_core->m_flag_zero)); // branch = ((n && !v) || (!n && v)) || z;
+ UML_OR(block, I0, I0, mem(&m_core->m_flag_zero)); // branch = ((n && !v) || (!n && v)) || z;
break;
case 2: // BGE
if (m_drcuml.get()->logging())
block.append_comment("BGE");
UML_XOR(block, I0, mem(&m_core->m_flag_neg), mem(&m_core->m_flag_over));
- UML_SUB(block, I0, 1, I0); // branch = ((n && v) || (!n && !v));
+ UML_SUB(block, I0, 1, I0); // branch = ((n && v) || (!n && !v));
break;
case 3: // BGT
if (m_drcuml.get()->logging())
@@ -765,36 +765,36 @@ void dspp_device::generate_complex_branch_opcode(drcuml_block &block, compiler_s
UML_AND(block, I0, mem(&m_core->m_flag_neg), mem(&m_core->m_flag_over));
UML_SUB(block, I0, 1, I0);
UML_SUB(block, I1, 1, mem(&m_core->m_flag_zero));
- UML_AND(block, I0, I0, I1); // branch = ((n && v) || (!n && !v)) && !z;
+ UML_AND(block, I0, I0, I1); // branch = ((n && v) || (!n && !v)) && !z;
break;
case 4: // BHI
if (m_drcuml.get()->logging())
block.append_comment("BHI");
UML_SUB(block, I0, 1, mem(&m_core->m_flag_zero));
- UML_AND(block, I0, I0, mem(&m_core->m_flag_carry)); // branch = c && !z;
+ UML_AND(block, I0, I0, mem(&m_core->m_flag_carry)); // branch = c && !z;
break;
case 5: // BLS
if (m_drcuml.get()->logging())
block.append_comment("BLS");
UML_SUB(block, I0, 1, mem(&m_core->m_flag_carry));
- UML_OR(block, I0, I0, mem(&m_core->m_flag_zero)); // branch = !c || z;
+ UML_OR(block, I0, I0, mem(&m_core->m_flag_zero)); // branch = !c || z;
break;
case 6: // BXS
if (m_drcuml.get()->logging())
block.append_comment("BXS");
- UML_MOV(block, I0, mem(&m_core->m_flag_exact)); // branch = x;
+ UML_MOV(block, I0, mem(&m_core->m_flag_exact)); // branch = x;
break;
case 7: // BXC
if (m_drcuml.get()->logging())
block.append_comment("BXC");
- UML_SUB(block, I0, 1, mem(&m_core->m_flag_exact)); // branch = !x;
+ UML_SUB(block, I0, 1, mem(&m_core->m_flag_exact)); // branch = !x;
break;
}
code_label skip = compiler->labelnum++;
- UML_TEST(block, I0, 1); // if (branch)
+ UML_TEST(block, I0, 1); // if (branch)
UML_JMPc(block, COND_Z, skip);
- UML_MOV(block, mem(&m_core->m_jmpdest), op & 0x3ff); // m_core->m_pc = op & 0x3ff;
+ UML_MOV(block, mem(&m_core->m_jmpdest), op & 0x3ff); // m_core->m_pc = op & 0x3ff;
generate_branch(block, compiler, desc);
UML_LABEL(block, skip);
}
@@ -941,8 +941,8 @@ void dspp_device::generate_read_next_operand(drcuml_block &block, compiler_state
UML_LOAD(block, I0, (void *)&m_core->m_operands[0].value, mem(&m_core->m_opidx), SIZE_DWORD, SCALE_x8);
//if (op == 0x46a0)
//{
- // UML_MOV(block, mem(&m_core->m_arg0), I0);
- // UML_CALLC(block, cfunc_print_value, this);
+ // UML_MOV(block, mem(&m_core->m_arg0), I0);
+ // UML_CALLC(block, cfunc_print_value, this);
//}
UML_TEST(block, I0, 0x80000000U);
@@ -950,13 +950,13 @@ void dspp_device::generate_read_next_operand(drcuml_block &block, compiler_state
UML_LOAD(block, I1, (void *)&m_core->m_operands[0].addr, mem(&m_core->m_opidx), SIZE_DWORD, SCALE_x8);
//if (op == 0x46a0)
//{
- // UML_MOV(block, mem(&m_core->m_arg1), I1);
+ // UML_MOV(block, mem(&m_core->m_arg1), I1);
//}
UML_CALLH(block, *m_dm_read16);
//if (op == 0x46a0)
//{
- // UML_MOV(block, mem(&m_core->m_arg0), I0);
- // UML_CALLC(block, cfunc_print_addr, this);
+ // UML_MOV(block, mem(&m_core->m_arg0), I0);
+ // UML_CALLC(block, cfunc_print_addr, this);
//}
UML_LABEL(block, no_load);
@@ -1071,16 +1071,16 @@ void dspp_device::generate_arithmetic_opcode(drcuml_block &block, compiler_state
if (m_drcuml.get()->logging())
block.append_comment("_TRA");
UML_MOV(block, I0, I2); // alu_res = alu_a;
- UML_MOV(block, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = 0;
- UML_MOV(block, mem(&m_core->m_flag_carry), 0); // m_core->m_flag_carry = 0;
+ UML_MOV(block, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = 0;
+ UML_MOV(block, mem(&m_core->m_flag_carry), 0); // m_core->m_flag_carry = 0;
break;
case 1: // _NEG
if (m_drcuml.get()->logging())
block.append_comment("_NEG");
UML_SUB(block, I0, 0, I3); // alu_res = -alu_b;
- UML_MOV(block, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = 0;
- UML_MOV(block, mem(&m_core->m_flag_carry), 0); // m_core->m_flag_carry = 0;
+ UML_MOV(block, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = 0;
+ UML_MOV(block, mem(&m_core->m_flag_carry), 0); // m_core->m_flag_carry = 0;
break;
case 2: // _+
@@ -1092,175 +1092,175 @@ void dspp_device::generate_arithmetic_opcode(drcuml_block &block, compiler_state
UML_XOR(block, I3, I2, I3);
UML_TEST(block, I3, 0x80000);
- UML_JMPc(block, COND_NZ, skip_over); // if ((alu_a & 0x80000) == (alu_b & 0x80000) &&
+ UML_JMPc(block, COND_NZ, skip_over); // if ((alu_a & 0x80000) == (alu_b & 0x80000) &&
UML_XOR(block, I3, I2, I0);
- UML_TEST(block, I3, 0x80000); // (alu_a & 0x80000) != (alu_res & 0x80000))
- UML_MOVc(block, COND_NZ, mem(&m_core->m_flag_over), 1); // m_core->m_flag_over = 1;
+ UML_TEST(block, I3, 0x80000); // (alu_a & 0x80000) != (alu_res & 0x80000))
+ UML_MOVc(block, COND_NZ, mem(&m_core->m_flag_over), 1); // m_core->m_flag_over = 1;
UML_LABEL(block, skip_over);
- UML_TEST(block, I0, 0x00100000); // if (alu_res & 0x00100000)
- UML_MOVc(block, COND_NZ, mem(&m_core->m_flag_carry), 1); // m_core->m_flag_carry = 1;
+ UML_TEST(block, I0, 0x00100000); // if (alu_res & 0x00100000)
+ UML_MOVc(block, COND_NZ, mem(&m_core->m_flag_carry), 1); // m_core->m_flag_carry = 1;
// else
- UML_MOVc(block, COND_Z, mem(&m_core->m_flag_carry), 0); // m_core->m_flag_carry = 0;
+ UML_MOVc(block, COND_Z, mem(&m_core->m_flag_carry), 0); // m_core->m_flag_carry = 0;
break;
case 3: // _+C
if (m_drcuml.get()->logging())
block.append_comment("_+C");
UML_SHL(block, I3, mem(&m_core->m_flag_carry), 4);
- UML_ADD(block, I0, I2, I3); // alu_res = alu_a + (m_core->m_flag_carry << 4);
+ UML_ADD(block, I0, I2, I3); // alu_res = alu_a + (m_core->m_flag_carry << 4);
- UML_MOV(block, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = 0;
+ UML_MOV(block, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = 0;
- UML_TEST(block, I0, 0x00100000); // if (alu_res & 0x00100000)
- UML_MOVc(block, COND_NZ, mem(&m_core->m_flag_carry), 1); // m_core->m_flag_carry = 1;
+ UML_TEST(block, I0, 0x00100000); // if (alu_res & 0x00100000)
+ UML_MOVc(block, COND_NZ, mem(&m_core->m_flag_carry), 1); // m_core->m_flag_carry = 1;
// else
- UML_MOVc(block, COND_Z, mem(&m_core->m_flag_carry), 0); // m_core->m_flag_carry = 0;
+ UML_MOVc(block, COND_Z, mem(&m_core->m_flag_carry), 0); // m_core->m_flag_carry = 0;
break;
case 4: // _-
if (m_drcuml.get()->logging())
block.append_comment("_-");
- UML_SUB(block, I0, I2, I3); // alu_res = alu_a - alu_b;
+ UML_SUB(block, I0, I2, I3); // alu_res = alu_a - alu_b;
UML_MOV(block, mem(&m_core->m_flag_over), 0);
UML_XOR(block, I3, I3, 0xffffffffU);
UML_XOR(block, I3, I2, I3);
UML_TEST(block, I3, 0x80000);
- UML_JMPc(block, COND_NZ, skip_over); // if ((alu_a & 0x80000) == (~alu_b & 0x80000) &&
+ UML_JMPc(block, COND_NZ, skip_over); // if ((alu_a & 0x80000) == (~alu_b & 0x80000) &&
UML_XOR(block, I3, I2, I0);
- UML_TEST(block, I3, 0x80000); // (alu_a & 0x80000) != (alu_res & 0x80000))
- UML_MOVc(block, COND_NZ, mem(&m_core->m_flag_over), 1); // m_core->m_flag_over = 1;
+ UML_TEST(block, I3, 0x80000); // (alu_a & 0x80000) != (alu_res & 0x80000))
+ UML_MOVc(block, COND_NZ, mem(&m_core->m_flag_over), 1); // m_core->m_flag_over = 1;
UML_LABEL(block, skip_over);
- UML_TEST(block, I0, 0x00100000); // if (alu_res & 0x00100000)
- UML_MOVc(block, COND_NZ, mem(&m_core->m_flag_carry), 1); // m_core->m_flag_carry = 1;
+ UML_TEST(block, I0, 0x00100000); // if (alu_res & 0x00100000)
+ UML_MOVc(block, COND_NZ, mem(&m_core->m_flag_carry), 1); // m_core->m_flag_carry = 1;
// else
- UML_MOVc(block, COND_Z, mem(&m_core->m_flag_carry), 0); // m_core->m_flag_carry = 0;
+ UML_MOVc(block, COND_Z, mem(&m_core->m_flag_carry), 0); // m_core->m_flag_carry = 0;
break;
case 5: // _-B
if (m_drcuml.get()->logging())
block.append_comment("_-B");
UML_SHL(block, I3, mem(&m_core->m_flag_carry), 4);
- UML_SUB(block, I0, I2, I3); // alu_res = alu_a - (m_core->m_flag_carry << 4);
+ UML_SUB(block, I0, I2, I3); // alu_res = alu_a - (m_core->m_flag_carry << 4);
- UML_MOV(block, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = 0;
+ UML_MOV(block, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = 0;
- UML_TEST(block, I0, 0x00100000); // if (alu_res & 0x00100000)
- UML_MOVc(block, COND_NZ, mem(&m_core->m_flag_carry), 1); // m_core->m_flag_carry = 1;
+ UML_TEST(block, I0, 0x00100000); // if (alu_res & 0x00100000)
+ UML_MOVc(block, COND_NZ, mem(&m_core->m_flag_carry), 1); // m_core->m_flag_carry = 1;
// else
- UML_MOVc(block, COND_Z, mem(&m_core->m_flag_carry), 0); // m_core->m_flag_carry = 0;
+ UML_MOVc(block, COND_Z, mem(&m_core->m_flag_carry), 0); // m_core->m_flag_carry = 0;
break;
case 6: // _++
if (m_drcuml.get()->logging())
block.append_comment("_++");
- UML_ADD(block, I0, I2, 1); // alu_res = alu_a + 1;
+ UML_ADD(block, I0, I2, 1); // alu_res = alu_a + 1;
UML_XOR(block, I3, I2, 0x80000);
UML_AND(block, I3, I3, I0);
UML_TEST(block, I3, 0x80000);
UML_MOVc(block, COND_NZ, mem(&m_core->m_flag_over), 1);
- UML_MOVc(block, COND_Z, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = !(alu_a & 0x80000) && (alu_res & 0x80000);
+ UML_MOVc(block, COND_Z, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = !(alu_a & 0x80000) && (alu_res & 0x80000);
- UML_MOV(block, mem(&m_core->m_flag_carry), 0); // m_core->m_flag_carry = 0;
+ UML_MOV(block, mem(&m_core->m_flag_carry), 0); // m_core->m_flag_carry = 0;
break;
case 7: // _--
if (m_drcuml.get()->logging())
block.append_comment("_--");
- UML_SUB(block, I0, I2, 1); // alu_res = alu_a - 1;
+ UML_SUB(block, I0, I2, 1); // alu_res = alu_a - 1;
UML_XOR(block, I3, I0, 0x80000);
UML_AND(block, I3, I3, I2);
UML_TEST(block, I3, 0x80000);
UML_MOVc(block, COND_NZ, mem(&m_core->m_flag_over), 1);
- UML_MOVc(block, COND_Z, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = (alu_a & 0x80000) && !(alu_res & 0x80000);
+ UML_MOVc(block, COND_Z, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = (alu_a & 0x80000) && !(alu_res & 0x80000);
- UML_MOV(block, mem(&m_core->m_flag_carry), 0); // m_core->m_flag_carry = 0;
+ UML_MOV(block, mem(&m_core->m_flag_carry), 0); // m_core->m_flag_carry = 0;
break;
case 8: // _TRL
if (m_drcuml.get()->logging())
block.append_comment("_TRL");
- UML_MOV(block, I0, I2); // alu_res = alu_a;
- UML_MOV(block, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = 0;
- UML_MOV(block, mem(&m_core->m_flag_carry), 0); // m_core->m_flag_carry = 0;
+ UML_MOV(block, I0, I2); // alu_res = alu_a;
+ UML_MOV(block, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = 0;
+ UML_MOV(block, mem(&m_core->m_flag_carry), 0); // m_core->m_flag_carry = 0;
break;
case 9: // _NOT
if (m_drcuml.get()->logging())
block.append_comment("_NOT");
- UML_XOR(block, I0, I2, 0xffffffff); // alu_res = ~alu_a;
- UML_MOV(block, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = 0;
- UML_MOV(block, mem(&m_core->m_flag_carry), 0); // m_core->m_flag_carry = 0;
+ UML_XOR(block, I0, I2, 0xffffffff); // alu_res = ~alu_a;
+ UML_MOV(block, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = 0;
+ UML_MOV(block, mem(&m_core->m_flag_carry), 0); // m_core->m_flag_carry = 0;
break;
case 10: // _AND
if (m_drcuml.get()->logging())
block.append_comment("_AND");
- UML_AND(block, I0, I2, I3); // alu_res = alu_a & alu_b;
- UML_MOV(block, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = 0;
- UML_MOV(block, mem(&m_core->m_flag_carry), 0); // m_core->m_flag_carry = 0;
+ UML_AND(block, I0, I2, I3); // alu_res = alu_a & alu_b;
+ UML_MOV(block, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = 0;
+ UML_MOV(block, mem(&m_core->m_flag_carry), 0); // m_core->m_flag_carry = 0;
break;
case 11: // _NAND
if (m_drcuml.get()->logging())
block.append_comment("_NAND");
UML_AND(block, I0, I2, I3);
- UML_XOR(block, I0, I0, 0xffffffff); // alu_res = ~(alu_a & alu_b);
- UML_MOV(block, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = 0;
- UML_MOV(block, mem(&m_core->m_flag_carry), 0); // m_core->m_flag_carry = 0;
+ UML_XOR(block, I0, I0, 0xffffffff); // alu_res = ~(alu_a & alu_b);
+ UML_MOV(block, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = 0;
+ UML_MOV(block, mem(&m_core->m_flag_carry), 0); // m_core->m_flag_carry = 0;
break;
case 12: // _OR
if (m_drcuml.get()->logging())
block.append_comment("_OR");
- UML_OR(block, I0, I2, I3); // alu_res = alu_a | alu_b;
- UML_MOV(block, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = 0;
- UML_MOV(block, mem(&m_core->m_flag_carry), 0); // m_core->m_flag_carry = 0;
+ UML_OR(block, I0, I2, I3); // alu_res = alu_a | alu_b;
+ UML_MOV(block, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = 0;
+ UML_MOV(block, mem(&m_core->m_flag_carry), 0); // m_core->m_flag_carry = 0;
break;
case 13: // _NOR
if (m_drcuml.get()->logging())
block.append_comment("_NOR");
UML_OR(block, I0, I2, I3);
- UML_XOR(block, I0, I0, 0xffffffff); // alu_res = ~(alu_a | alu_b);
- UML_MOV(block, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = 0;
- UML_MOV(block, mem(&m_core->m_flag_carry), 0); // m_core->m_flag_carry = 0;
+ UML_XOR(block, I0, I0, 0xffffffff); // alu_res = ~(alu_a | alu_b);
+ UML_MOV(block, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = 0;
+ UML_MOV(block, mem(&m_core->m_flag_carry), 0); // m_core->m_flag_carry = 0;
break;
case 14: // _XOR
if (m_drcuml.get()->logging())
block.append_comment("_XOR");
- UML_XOR(block, I0, I2, I3); // alu_res = alu_a ^ alu_b;
- UML_MOV(block, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = 0;
- UML_MOV(block, mem(&m_core->m_flag_carry), 0); // m_core->m_flag_carry = 0;
+ UML_XOR(block, I0, I2, I3); // alu_res = alu_a ^ alu_b;
+ UML_MOV(block, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = 0;
+ UML_MOV(block, mem(&m_core->m_flag_carry), 0); // m_core->m_flag_carry = 0;
break;
case 15: // _XNOR
if (m_drcuml.get()->logging())
block.append_comment("_XNOR");
UML_XOR(block, I0, I2, I3);
- UML_XOR(block, I0, I0, 0xffffffff); // alu_res = ~(alu_a ^ alu_b);
- UML_MOV(block, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = 0;
- UML_MOV(block, mem(&m_core->m_flag_carry), 0); // m_core->m_flag_carry = 0;
+ UML_XOR(block, I0, I0, 0xffffffff); // alu_res = ~(alu_a ^ alu_b);
+ UML_MOV(block, mem(&m_core->m_flag_over), 0); // m_core->m_flag_over = 0;
+ UML_MOV(block, mem(&m_core->m_flag_carry), 0); // m_core->m_flag_carry = 0;
break;
}
UML_TEST(block, I0, 0x00080000);
UML_MOVc(block, COND_NZ, mem(&m_core->m_flag_neg), 1);
- UML_MOVc(block, COND_Z, mem(&m_core->m_flag_neg), 0); // m_core->m_flag_neg = (alu_res & 0x00080000) != 0;
+ UML_MOVc(block, COND_Z, mem(&m_core->m_flag_neg), 0); // m_core->m_flag_neg = (alu_res & 0x00080000) != 0;
UML_TEST(block, I0, 0x000ffff0);
UML_MOVc(block, COND_Z, mem(&m_core->m_flag_zero), 1);
- UML_MOVc(block, COND_NZ, mem(&m_core->m_flag_zero), 0); // m_core->m_flag_zero = (alu_res & 0x000ffff0) == 0;
+ UML_MOVc(block, COND_NZ, mem(&m_core->m_flag_zero), 0); // m_core->m_flag_zero = (alu_res & 0x000ffff0) == 0;
UML_TEST(block, I0, 0x0000000f);
UML_MOVc(block, COND_Z, mem(&m_core->m_flag_exact), 1);
- UML_MOVc(block, COND_NZ, mem(&m_core->m_flag_exact), 0); // m_core->m_flag_exact = (alu_res & 0x0000000f) == 0;
+ UML_MOVc(block, COND_NZ, mem(&m_core->m_flag_exact), 0); // m_core->m_flag_exact = (alu_res & 0x0000000f) == 0;
// ALU_RES = I3
UML_MOV(block, I3, I0);
@@ -1269,9 +1269,9 @@ void dspp_device::generate_arithmetic_opcode(drcuml_block &block, compiler_state
static const int32_t shifts[8] = { 0, 1, 2, 3, 4, 5, 8, 16 };
if (barrel_code == 8)
- generate_read_next_operand(block, compiler, desc); // I0 = barrel_code;
+ generate_read_next_operand(block, compiler, desc); // I0 = barrel_code;
else
- UML_MOV(block, I0, barrel_code); // I0 = barrel_code;
+ UML_MOV(block, I0, barrel_code); // I0 = barrel_code;
code_label left_shift = compiler->labelnum++;
code_label done_shift = compiler->labelnum++;
@@ -1279,57 +1279,57 @@ void dspp_device::generate_arithmetic_opcode(drcuml_block &block, compiler_state
code_label no_clip = compiler->labelnum++;
code_label no_writeback = compiler->labelnum++;
code_label done = compiler->labelnum++;
- UML_TEST(block, I0, 8); // if (barrel_code & 8)
- UML_JMPc(block, COND_Z, left_shift); // {
+ UML_TEST(block, I0, 8); // if (barrel_code & 8)
+ UML_JMPc(block, COND_Z, left_shift); // {
UML_XOR(block, I0, I0, 0xffffffffU);
UML_ADD(block, I0, I0, 1);
UML_AND(block, I0, I0, 7);
- UML_LOAD(block, I0, (void *)shifts, I0, SIZE_DWORD, SCALE_x8); // uint32_t shift = shifts[(~barrel_code + 1) & 7];
- if (alu_op < 8) // if (alu_op < 8)
- { // {
+ UML_LOAD(block, I0, (void *)shifts, I0, SIZE_DWORD, SCALE_x8); // uint32_t shift = shifts[(~barrel_code + 1) & 7];
+ if (alu_op < 8) // if (alu_op < 8)
+ { // {
UML_SHL(block, I3, I3, 12);
- UML_SAR(block, I3, I3, 12); // // Arithmetic
- UML_SAR(block, mem(&m_core->m_acc), I3, I0); // m_core->m_acc = sign_extend20(alu_res) >> shift;
- } // }
- else // else
- { // {
- UML_AND(block, I3, I3, 0x000fffff); // // Logical
- UML_SHR(block, mem(&m_core->m_acc), I3, I0); // m_core->m_acc = (alu_res & 0xfffff) >> shift;
- } // }
- UML_JMP(block, done_shift); // }
- UML_LABEL(block, left_shift); // else
+ UML_SAR(block, I3, I3, 12); // // Arithmetic
+ UML_SAR(block, mem(&m_core->m_acc), I3, I0); // m_core->m_acc = sign_extend20(alu_res) >> shift;
+ } // }
+ else // else
+ { // {
+ UML_AND(block, I3, I3, 0x000fffff); // // Logical
+ UML_SHR(block, mem(&m_core->m_acc), I3, I0); // m_core->m_acc = (alu_res & 0xfffff) >> shift;
+ } // }
+ UML_JMP(block, done_shift); // }
+ UML_LABEL(block, left_shift); // else
// {
- UML_LOAD(block, I0, (void *)shifts, I0, SIZE_DWORD, SCALE_x8); // uint32_t shift = shifts[barrel_code];
- UML_CMP(block, I0, 16); // if (shift != 16)
- UML_JMPc(block, COND_E, no_shift); // {
+ UML_LOAD(block, I0, (void *)shifts, I0, SIZE_DWORD, SCALE_x8); // uint32_t shift = shifts[barrel_code];
+ UML_CMP(block, I0, 16); // if (shift != 16)
+ UML_JMPc(block, COND_E, no_shift); // {
UML_SHL(block, I3, I3, 12);
UML_SAR(block, I3, I3, 12);
- UML_SHL(block, mem(&m_core->m_acc), I3, I0); // m_core->m_acc = sign_extend20(alu_res) << shift;
- UML_JMP(block, done_shift); // }
+ UML_SHL(block, mem(&m_core->m_acc), I3, I0); // m_core->m_acc = sign_extend20(alu_res) << shift;
+ UML_JMP(block, done_shift); // }
// else
- UML_LABEL(block, no_shift); // {
- UML_TEST(block, mem(&m_core->m_flag_over), 1); // // Clip and saturate
- UML_JMPc(block, COND_Z, no_clip); // if (m_core->m_flag_over)
+ UML_LABEL(block, no_shift); // {
+ UML_TEST(block, mem(&m_core->m_flag_over), 1); // // Clip and saturate
+ UML_JMPc(block, COND_Z, no_clip); // if (m_core->m_flag_over)
UML_TEST(block, mem(&m_core->m_flag_neg), 1);
- UML_MOVc(block, COND_NZ, mem(&m_core->m_acc), 0x7ffff); // m_core->m_acc = m_core->m_flag_neg ? 0x7ffff : 0xfff80000;
+ UML_MOVc(block, COND_NZ, mem(&m_core->m_acc), 0x7ffff); // m_core->m_acc = m_core->m_flag_neg ? 0x7ffff : 0xfff80000;
UML_MOVc(block, COND_Z, mem(&m_core->m_acc), 0xfff80000);
- UML_JMP(block, done_shift); // else
+ UML_JMP(block, done_shift); // else
UML_LABEL(block, no_clip);
- UML_SHL(block, I3, I3, 12); // sign_extend20(alu_res);
- UML_SAR(block, mem(&m_core->m_acc), I3, 12); // }
- UML_LABEL(block, done_shift); // }
+ UML_SHL(block, I3, I3, 12); // sign_extend20(alu_res);
+ UML_SAR(block, mem(&m_core->m_acc), I3, 12); // }
+ UML_LABEL(block, done_shift); // }
- UML_CMP(block, mem(&m_core->m_writeback), 0); // if (m_core->m_writeback >= 0)
- UML_JMPc(block, COND_L, no_writeback); // {
+ UML_CMP(block, mem(&m_core->m_writeback), 0); // if (m_core->m_writeback >= 0)
+ UML_JMPc(block, COND_L, no_writeback); // {
UML_SHR(block, I0, mem(&m_core->m_acc), 4);
UML_MOV(block, I1, mem(&m_core->m_writeback));
- UML_CALLH(block, *m_dm_write16); // write_data(m_core->m_writeback, m_core->m_acc >> 4);
- UML_MOV(block, mem(&m_core->m_writeback), 0xffffffffU); // m_core->m_writeback = -1;
- UML_JMP(block, done); // }
+ UML_CALLH(block, *m_dm_write16); // write_data(m_core->m_writeback, m_core->m_acc >> 4);
+ UML_MOV(block, mem(&m_core->m_writeback), 0xffffffffU); // m_core->m_writeback = -1;
+ UML_JMP(block, done); // }
UML_LABEL(block, no_writeback);
- UML_CMP(block, mem(&m_core->m_opidx), numops); // else if (m_core->m_opidx < numops)
- UML_JMPc(block, COND_GE, done); // {
- generate_write_next_operand(block, compiler); // write_next_operand(m_core->m_acc >> 4);
- UML_LABEL(block, done); // }
+ UML_CMP(block, mem(&m_core->m_opidx), numops); // else if (m_core->m_opidx < numops)
+ UML_JMPc(block, COND_GE, done); // {
+ generate_write_next_operand(block, compiler); // write_next_operand(m_core->m_acc >> 4);
+ UML_LABEL(block, done); // }
}
diff --git a/src/devices/cpu/e132xs/e132xs.h b/src/devices/cpu/e132xs/e132xs.h
index 335aeab8898..ff5e9cb9bdb 100644
--- a/src/devices/cpu/e132xs/e132xs.h
+++ b/src/devices/cpu/e132xs/e132xs.h
@@ -439,6 +439,8 @@ private:
uint32_t m_drcoptions;
uint8_t m_cache_dirty;
+ uml::parameter m_regmap[16];
+
uml::code_handle *m_entry;
uml::code_handle *m_nocode;
uml::code_handle *m_interrupt_checks;
diff --git a/src/devices/cpu/f8/f8.cpp b/src/devices/cpu/f8/f8.cpp
index ce09d9ca835..e0f86369a06 100644
--- a/src/devices/cpu/f8/f8.cpp
+++ b/src/devices/cpu/f8/f8.cpp
@@ -7,11 +7,6 @@
* This work is based on Frank Palazzolo's F8 emulation in a standalone
* Fairchild Channel F emulator and the 'Fairchild F3850 CPU' data sheets.
*
- * TODO:
- * - ROMC signals are supposed to be handled externally
- *
- *****************************************************************************
- *
* The 3850 CPU itself does not include the address bus, pointer registers
* or an interrupt controller. Those functions are provided by at least one
* of the following devices:
@@ -19,9 +14,7 @@
* - 3851 Program Storage Unit (PSU)
* - 3852 Dynamic Memory Interface (DMI)
* - 3853 Static Memory Interface (SMI)
- * - 3854 Direct Memory Access Controller (DMAC)
* - 3856 Program Storage Unit (PSU)
- * - 38T56 Program Storage Unit (PSU)
* - 3861 Peripheral Input/Output (PIO)
* - 3871 Peripheral Input/Output (PIO)
*
@@ -35,12 +28,6 @@
* devices responding to the same DC0 address and attempting to place their
* bytes on the data bus simultaneously!
*
- * Combined packages:
- * - 3859 = 3850 + 3851
- * - 3870 = 3850 + 38T56
- * - 3872 = 3870 + extra 2KB ROM
- * - 3873 = 3870 + extra 64 bytes executable RAM
- *
*****************************************************************************/
#include "emu.h"
@@ -50,11 +37,11 @@
/* status flags */
-static constexpr u8 S = 0x01; // sign
-static constexpr u8 C = 0x02; // carry
-static constexpr u8 Z = 0x04; // zero
-static constexpr u8 O = 0x08; // overflow
-static constexpr u8 I = 0x10; // interrupt control bit (ICB)
+static constexpr u8 S = 0x01;
+static constexpr u8 C = 0x02;
+static constexpr u8 Z = 0x04;
+static constexpr u8 O = 0x08;
+static constexpr u8 I = 0x10;
/* cycle (short/long) */
static constexpr int cS = 4;
@@ -64,11 +51,21 @@ static constexpr int cL = 6;
DEFINE_DEVICE_TYPE(F8, f8_cpu_device, "f8", "Fairchild F8")
-f8_cpu_device::f8_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
- cpu_device(mconfig, F8, tag, owner, clock),
- m_program_config("program", ENDIANNESS_BIG, 8, 16, 0),
- m_io_config("io", ENDIANNESS_BIG, 8, 8, 0)
-{ }
+f8_cpu_device::f8_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
+ : cpu_device(mconfig, F8, tag, owner, clock)
+ , m_program_config("program", ENDIANNESS_BIG, 8, 16, 0)
+ , m_io_config("io", ENDIANNESS_BIG, 8, 8, 0)
+ , m_pc0(0)
+ , m_pc1(0)
+ , m_dc0(0)
+ , m_dc1(0)
+ , m_a(0)
+ , m_w(0)
+ , m_is(0)
+ , m_debug_pc(0)
+{
+ memset(m_r, 0x00, sizeof(m_r));
+}
device_memory_interface::space_config_vector f8_cpu_device::memory_space_config() const
{
@@ -104,22 +101,6 @@ void f8_cpu_device::device_start()
m_cache = m_program->cache<0, 0, ENDIANNESS_BIG>();
m_iospace = &space(AS_IO);
- // zerofill
- m_debug_pc = 0;
- m_pc0 = 0;
- m_pc1 = 0;
- m_dc0 = 0;
- m_dc1 = 0;
- m_a = 0;
- m_w = 0;
- m_is = 0;
- m_dbus = 0;
- m_io = 0;
- m_irq_vector = 0;
- memset(m_r, 0, sizeof(m_r));
- m_irq_request = 0;
-
- // register for savestates
save_item(NAME(m_debug_pc));
save_item(NAME(m_pc0));
save_item(NAME(m_pc1));
@@ -134,7 +115,6 @@ void f8_cpu_device::device_start()
save_item(NAME(m_irq_request));
save_item(NAME(m_r));
- // register for debugger
state_add( F8_PC0, "PC0", m_pc0).formatstr("%04X");
state_add( F8_PC1, "PC1", m_pc1).formatstr("%04X");
state_add( F8_DC0, "DC0", m_dc0).formatstr("%04X");
@@ -216,18 +196,55 @@ void f8_cpu_device::device_start()
void f8_cpu_device::device_reset()
{
- // save PC0 to PC1 and reset PC0, and clear ICB
- ROMC_08();
- m_w &= ~I;
+ m_debug_pc = 0;
+ m_pc0 = 0;
+ m_pc1 = 0;
+ m_dc0 = 0;
+ m_dc1 = 0;
+ m_a = 0;
+ m_w = 0;
+ m_is = 0;
+ m_dbus = 0;
+ m_io = 0;
+ m_irq_vector = 0;
+ memset(m_r, 0, sizeof(m_r));
+ m_irq_request = 0;
+
+ m_w&=~I;
- // fetch the first opcode
+ /* save PC0 to PC1 and reset PC0 */
+ ROMC_08();
+ /* fetch the first opcode */
ROMC_00(cS);
+
+ /* initialize the timer shift register
+ * this is an 8 bit polynomial counter which can be loaded parallel
+ * with 0xff the outputs never change and thus the timer is disabled.
+ * with 0xfe the shifter starts cycling through 255 states until it
+ * reaches 0xfe again (and then issues an interrupt).
+ * the counter output values are not sequential, but go like this:
+ * 0xfe, 0xfd, 0xfb, 0xf7, 0xee, 0xdc ... etc. :-)
+ * We have to build a lookup table to tell how many cycles a write
+
+ */
+ u8 data = 0xfe; /* initial value */
+ for (int i = 0; i < 256; i++)
+ {
+ timer_shifter[i] = data;
+ if ( (((data >> 3) ^ (data >> 4)) ^ ((data >> 5) ^ (data >> 7))) & 1 )
+ {
+ data <<= 1;
+ }
+ else
+ {
+ data = (data << 1) | 1;
+ }
+ }
}
void f8_cpu_device::execute_set_input( int inptnum, int state )
{
- assert (inptnum == F8_INPUT_LINE_INT_REQ);
m_irq_request = state;
}
@@ -499,7 +516,7 @@ void f8_cpu_device::ROMC_10()
/*
* Inhibit any modification to the interrupt priority logic.
*/
- // TODO
+ m_w |= 0x20; /* ???? */
m_icount -= cL;
}
@@ -985,7 +1002,7 @@ void f8_cpu_device::f8_pop()
void f8_cpu_device::f8_lr_w_j()
{
ROMC_1C(cS);
- m_w = m_r[9] & 0x1f;
+ m_w = m_r[9];
}
/***************************************************
@@ -1314,9 +1331,9 @@ void f8_cpu_device::f8_bt(int e)
{
ROMC_1C(cS);
if (m_w & e)
- ROMC_01(); // take the relative branch
+ ROMC_01(); /* take the relative branch */
else
- ROMC_03(cS); // just read the argument on the data bus
+ ROMC_03(cS); /* just read the argument on the data bus */
}
/***************************************************
@@ -1395,7 +1412,7 @@ void f8_cpu_device::f8_cm()
void f8_cpu_device::f8_adc()
{
m_dbus = m_a;
- ROMC_0A(); // add data bus value to DC0
+ ROMC_0A(); /* add data bus value to DC0 */
}
/***************************************************
@@ -1405,9 +1422,9 @@ void f8_cpu_device::f8_adc()
void f8_cpu_device::f8_br7()
{
if ((m_is & 7) == 7)
- ROMC_03(cS); // just read the argument on the data bus
+ ROMC_03(cS); /* just read the argument on the data bus */
else
- ROMC_01(); // take the relative branch
+ ROMC_01(); /* take the relative branch */
}
/***************************************************
@@ -1418,9 +1435,9 @@ void f8_cpu_device::f8_bf(int t)
{
ROMC_1C(cS);
if (m_w & t)
- ROMC_03(cS); // just read the argument on the data bus
+ ROMC_03(cS); /* just read the argument on the data bus */
else
- ROMC_01(); // take the relative branch
+ ROMC_01(); /* take the relative branch */
}
/***************************************************
@@ -1652,10 +1669,7 @@ void f8_cpu_device::f8_ns_isar_d()
}
-/***************************************************
- * Execute cycles
- ***************************************************/
-
+/* Execute cycles - returns number of cycles actually run */
void f8_cpu_device::execute_run()
{
do
@@ -1665,307 +1679,305 @@ void f8_cpu_device::execute_run()
m_debug_pc = (m_pc0 - 1) & 0xffff;
debugger_instruction_hook(m_debug_pc);
- switch (op)
+ switch( op )
{
- case 0x00: f8_lr_a_ku(); break;
- case 0x01: f8_lr_a_kl(); break;
- case 0x02: f8_lr_a_qu(); break;
- case 0x03: f8_lr_a_ql(); break;
- case 0x04: f8_lr_ku_a(); break;
- case 0x05: f8_lr_kl_a(); break;
- case 0x06: f8_lr_qu_a(); break;
- case 0x07: f8_lr_ql_a(); break;
- case 0x08: f8_lr_k_p(); break;
- case 0x09: f8_lr_p_k(); break;
- case 0x0a: f8_lr_a_is(); break;
- case 0x0b: f8_lr_is_a(); break;
- case 0x0c: f8_pk(); break;
- case 0x0d: f8_lr_p0_q(); break;
- case 0x0e: f8_lr_q_dc(); break;
- case 0x0f: f8_lr_dc_q(); break;
-
- case 0x10: f8_lr_dc_h(); break;
- case 0x11: f8_lr_h_dc(); break;
- case 0x12: f8_sr_1(); break;
- case 0x13: f8_sl_1(); break;
- case 0x14: f8_sr_4(); break;
- case 0x15: f8_sl_4(); break;
- case 0x16: f8_lm(); break;
- case 0x17: f8_st(); break;
- case 0x18: f8_com(); break;
- case 0x19: f8_lnk(); break;
- case 0x1a: f8_di(); break;
- case 0x1b: f8_ei(); break;
- case 0x1c: f8_pop(); break;
- case 0x1d: f8_lr_w_j(); break;
- case 0x1e: f8_lr_j_w(); break;
- case 0x1f: f8_inc(); break;
-
- case 0x20: f8_li(); break;
- case 0x21: f8_ni(); break;
- case 0x22: f8_oi(); break;
- case 0x23: f8_xi(); break;
- case 0x24: f8_ai(); break;
- case 0x25: f8_ci(); break;
- case 0x26: f8_in(); break;
- case 0x27: f8_out(); break;
- case 0x28: f8_pi(); break;
- case 0x29: f8_jmp(); break;
- case 0x2a: f8_dci(); break;
- case 0x2b: f8_nop(); break;
- case 0x2c: f8_xdc(); break;
- case 0x2d: illegal(); break;
- case 0x2e: illegal(); break;
- case 0x2f: illegal(); break;
-
- case 0x30: f8_ds_r(0); break;
- case 0x31: f8_ds_r(1); break;
- case 0x32: f8_ds_r(2); break;
- case 0x33: f8_ds_r(3); break;
- case 0x34: f8_ds_r(4); break;
- case 0x35: f8_ds_r(5); break;
- case 0x36: f8_ds_r(6); break;
- case 0x37: f8_ds_r(7); break;
- case 0x38: f8_ds_r(8); break;
- case 0x39: f8_ds_r(9); break;
- case 0x3a: f8_ds_r(10); break;
- case 0x3b: f8_ds_r(11); break;
- case 0x3c: f8_ds_isar(); break;
- case 0x3d: f8_ds_isar_i(); break;
- case 0x3e: f8_ds_isar_d(); break;
- case 0x3f: illegal(); break;
-
- case 0x40: f8_lr_a_r(0); break;
- case 0x41: f8_lr_a_r(1); break;
- case 0x42: f8_lr_a_r(2); break;
- case 0x43: f8_lr_a_r(3); break;
- case 0x44: f8_lr_a_r(4); break;
- case 0x45: f8_lr_a_r(5); break;
- case 0x46: f8_lr_a_r(6); break;
- case 0x47: f8_lr_a_r(7); break;
- case 0x48: f8_lr_a_r(8); break;
- case 0x49: f8_lr_a_r(9); break;
- case 0x4a: f8_lr_a_r(10); break;
- case 0x4b: f8_lr_a_r(11); break;
- case 0x4c: f8_lr_a_isar(); break;
- case 0x4d: f8_lr_a_isar_i(); break;
- case 0x4e: f8_lr_a_isar_d(); break;
- case 0x4f: illegal(); break;
-
- case 0x50: f8_lr_r_a(0); break;
- case 0x51: f8_lr_r_a(1); break;
- case 0x52: f8_lr_r_a(2); break;
- case 0x53: f8_lr_r_a(3); break;
- case 0x54: f8_lr_r_a(4); break;
- case 0x55: f8_lr_r_a(5); break;
- case 0x56: f8_lr_r_a(6); break;
- case 0x57: f8_lr_r_a(7); break;
- case 0x58: f8_lr_r_a(8); break;
- case 0x59: f8_lr_r_a(9); break;
- case 0x5a: f8_lr_r_a(10); break;
- case 0x5b: f8_lr_r_a(11); break;
- case 0x5c: f8_lr_isar_a(); break;
- case 0x5d: f8_lr_isar_i_a(); break;
- case 0x5e: f8_lr_isar_d_a(); break;
- case 0x5f: illegal(); break;
-
- case 0x60: f8_lisu(0x00); break;
- case 0x61: f8_lisu(0x08); break;
- case 0x62: f8_lisu(0x10); break;
- case 0x63: f8_lisu(0x18); break;
- case 0x64: f8_lisu(0x20); break;
- case 0x65: f8_lisu(0x28); break;
- case 0x66: f8_lisu(0x30); break;
- case 0x67: f8_lisu(0x38); break;
- case 0x68: f8_lisl(0x00); break;
- case 0x69: f8_lisl(0x01); break;
- case 0x6a: f8_lisl(0x02); break;
- case 0x6b: f8_lisl(0x03); break;
- case 0x6c: f8_lisl(0x04); break;
- case 0x6d: f8_lisl(0x05); break;
- case 0x6e: f8_lisl(0x06); break;
- case 0x6f: f8_lisl(0x07); break;
-
- case 0x70: f8_lis(0x0); break;
- case 0x71: f8_lis(0x1); break;
- case 0x72: f8_lis(0x2); break;
- case 0x73: f8_lis(0x3); break;
- case 0x74: f8_lis(0x4); break;
- case 0x75: f8_lis(0x5); break;
- case 0x76: f8_lis(0x6); break;
- case 0x77: f8_lis(0x7); break;
- case 0x78: f8_lis(0x8); break;
- case 0x79: f8_lis(0x9); break;
- case 0x7a: f8_lis(0xa); break;
- case 0x7b: f8_lis(0xb); break;
- case 0x7c: f8_lis(0xc); break;
- case 0x7d: f8_lis(0xd); break;
- case 0x7e: f8_lis(0xe); break;
- case 0x7f: f8_lis(0xf); break;
-
- case 0x80: f8_bt(0); break;
- case 0x81: f8_bt(1); break;
- case 0x82: f8_bt(2); break;
- case 0x83: f8_bt(3); break;
- case 0x84: f8_bt(4); break;
- case 0x85: f8_bt(5); break;
- case 0x86: f8_bt(6); break;
- case 0x87: f8_bt(7); break;
- case 0x88: f8_am(); break;
- case 0x89: f8_amd(); break;
- case 0x8a: f8_nm(); break;
- case 0x8b: f8_om(); break;
- case 0x8c: f8_xm(); break;
- case 0x8d: f8_cm(); break;
- case 0x8e: f8_adc(); break;
- case 0x8f: f8_br7(); break;
-
- case 0x90: f8_bf(0x0); break;
- case 0x91: f8_bf(0x1); break;
- case 0x92: f8_bf(0x2); break;
- case 0x93: f8_bf(0x3); break;
- case 0x94: f8_bf(0x4); break;
- case 0x95: f8_bf(0x5); break;
- case 0x96: f8_bf(0x6); break;
- case 0x97: f8_bf(0x7); break;
- case 0x98: f8_bf(0x8); break;
- case 0x99: f8_bf(0x9); break;
- case 0x9a: f8_bf(0xa); break;
- case 0x9b: f8_bf(0xb); break;
- case 0x9c: f8_bf(0xc); break;
- case 0x9d: f8_bf(0xd); break;
- case 0x9e: f8_bf(0xe); break;
- case 0x9f: f8_bf(0xf); break;
-
- case 0xa0: f8_ins_0(0x0); break;
- case 0xa1: f8_ins_0(0x1); break;
- case 0xa2: illegal(); break;
- case 0xa3: illegal(); break;
- case 0xa4: f8_ins_1(0x4); break;
- case 0xa5: f8_ins_1(0x5); break;
- case 0xa6: f8_ins_1(0x6); break;
- case 0xa7: f8_ins_1(0x7); break;
- case 0xa8: f8_ins_1(0x8); break;
- case 0xa9: f8_ins_1(0x9); break;
- case 0xaa: f8_ins_1(0xa); break;
- case 0xab: f8_ins_1(0xb); break;
- case 0xac: f8_ins_1(0xc); break;
- case 0xad: f8_ins_1(0xd); break;
- case 0xae: f8_ins_1(0xe); break;
- case 0xaf: f8_ins_1(0xf); break;
-
- case 0xb0: f8_outs_0(0x0); break;
- case 0xb1: f8_outs_0(0x1); break;
- case 0xb2: illegal(); break;
- case 0xb3: illegal(); break;
- case 0xb4: f8_outs_1(0x4); break;
- case 0xb5: f8_outs_1(0x5); break;
- case 0xb6: f8_outs_1(0x6); break;
- case 0xb7: f8_outs_1(0x7); break;
- case 0xb8: f8_outs_1(0x8); break;
- case 0xb9: f8_outs_1(0x9); break;
- case 0xba: f8_outs_1(0xa); break;
- case 0xbb: f8_outs_1(0xb); break;
- case 0xbc: f8_outs_1(0xc); break;
- case 0xbd: f8_outs_1(0xd); break;
- case 0xbe: f8_outs_1(0xe); break;
- case 0xbf: f8_outs_1(0xf); break;
-
- case 0xc0: f8_as(0x0); break;
- case 0xc1: f8_as(0x1); break;
- case 0xc2: f8_as(0x2); break;
- case 0xc3: f8_as(0x3); break;
- case 0xc4: f8_as(0x4); break;
- case 0xc5: f8_as(0x5); break;
- case 0xc6: f8_as(0x6); break;
- case 0xc7: f8_as(0x7); break;
- case 0xc8: f8_as(0x8); break;
- case 0xc9: f8_as(0x9); break;
- case 0xca: f8_as(0xa); break;
- case 0xcb: f8_as(0xb); break;
- case 0xcc: f8_as_isar(); break;
- case 0xcd: f8_as_isar_i(); break;
- case 0xce: f8_as_isar_d(); break;
- case 0xcf: illegal(); break;
-
- case 0xd0: f8_asd(0x0); break;
- case 0xd1: f8_asd(0x1); break;
- case 0xd2: f8_asd(0x2); break;
- case 0xd3: f8_asd(0x3); break;
- case 0xd4: f8_asd(0x4); break;
- case 0xd5: f8_asd(0x5); break;
- case 0xd6: f8_asd(0x6); break;
- case 0xd7: f8_asd(0x7); break;
- case 0xd8: f8_asd(0x8); break;
- case 0xd9: f8_asd(0x9); break;
- case 0xda: f8_asd(0xa); break;
- case 0xdb: f8_asd(0xb); break;
- case 0xdc: f8_asd_isar(); break;
- case 0xdd: f8_asd_isar_i(); break;
- case 0xde: f8_asd_isar_d(); break;
- case 0xdf: illegal(); break;
-
- case 0xe0: f8_xs(0x0); break;
- case 0xe1: f8_xs(0x1); break;
- case 0xe2: f8_xs(0x2); break;
- case 0xe3: f8_xs(0x3); break;
- case 0xe4: f8_xs(0x4); break;
- case 0xe5: f8_xs(0x5); break;
- case 0xe6: f8_xs(0x6); break;
- case 0xe7: f8_xs(0x7); break;
- case 0xe8: f8_xs(0x8); break;
- case 0xe9: f8_xs(0x9); break;
- case 0xea: f8_xs(0xa); break;
- case 0xeb: f8_xs(0xb); break;
- case 0xec: f8_xs_isar(); break;
- case 0xed: f8_xs_isar_i(); break;
- case 0xee: f8_xs_isar_d(); break;
- case 0xef: illegal(); break;
-
- case 0xf0: f8_ns(0x0); break;
- case 0xf1: f8_ns(0x1); break;
- case 0xf2: f8_ns(0x2); break;
- case 0xf3: f8_ns(0x3); break;
- case 0xf4: f8_ns(0x4); break;
- case 0xf5: f8_ns(0x5); break;
- case 0xf6: f8_ns(0x6); break;
- case 0xf7: f8_ns(0x7); break;
- case 0xf8: f8_ns(0x8); break;
- case 0xf9: f8_ns(0x9); break;
- case 0xfa: f8_ns(0xa); break;
- case 0xfb: f8_ns(0xb); break;
- case 0xfc: f8_ns_isar(); break;
- case 0xfd: f8_ns_isar_i(); break;
- case 0xfe: f8_ns_isar_d(); break;
- case 0xff: illegal(); break;
+ /* opcode bitmask */
+ case 0x00: /* 0000 0000 */ f8_lr_a_ku(); break;
+ case 0x01: /* 0000 0001 */ f8_lr_a_kl(); break;
+ case 0x02: /* 0000 0010 */ f8_lr_a_qu(); break;
+ case 0x03: /* 0000 0011 */ f8_lr_a_ql(); break;
+ case 0x04: /* 0000 0100 */ f8_lr_ku_a(); break;
+ case 0x05: /* 0000 0101 */ f8_lr_kl_a(); break;
+ case 0x06: /* 0000 0110 */ f8_lr_qu_a(); break;
+ case 0x07: /* 0000 0111 */ f8_lr_ql_a(); break;
+ case 0x08: /* 0000 1000 */ f8_lr_k_p(); break;
+ case 0x09: /* 0000 1001 */ f8_lr_p_k(); break;
+ case 0x0a: /* 0000 1010 */ f8_lr_a_is(); break;
+ case 0x0b: /* 0000 1011 */ f8_lr_is_a(); break;
+ case 0x0c: /* 0000 1100 */ f8_pk(); break;
+ case 0x0d: /* 0000 1101 */ f8_lr_p0_q(); break;
+ case 0x0e: /* 0000 1110 */ f8_lr_q_dc(); break;
+ case 0x0f: /* 0000 1111 */ f8_lr_dc_q(); break;
+
+ case 0x10: /* 0001 0000 */ f8_lr_dc_h(); break;
+ case 0x11: /* 0001 0001 */ f8_lr_h_dc(); break;
+ case 0x12: /* 0001 0010 */ f8_sr_1(); break;
+ case 0x13: /* 0001 0011 */ f8_sl_1(); break;
+ case 0x14: /* 0001 0100 */ f8_sr_4(); break;
+ case 0x15: /* 0001 0101 */ f8_sl_4(); break;
+ case 0x16: /* 0001 0110 */ f8_lm(); break;
+ case 0x17: /* 0001 0111 */ f8_st(); break;
+ case 0x18: /* 0001 1000 */ f8_com(); break;
+ case 0x19: /* 0001 1001 */ f8_lnk(); break;
+ case 0x1a: /* 0001 1010 */ f8_di(); break;
+ case 0x1b: /* 0001 1011 */ f8_ei(); break;
+ case 0x1c: /* 0001 1100 */ f8_pop(); break;
+ case 0x1d: /* 0001 1101 */ f8_lr_w_j(); break;
+ case 0x1e: /* 0001 1110 */ f8_lr_j_w(); break;
+ case 0x1f: /* 0001 1111 */ f8_inc(); break;
+
+ case 0x20: /* 0010 0000 */ f8_li(); break;
+ case 0x21: /* 0010 0001 */ f8_ni(); break;
+ case 0x22: /* 0010 0010 */ f8_oi(); break;
+ case 0x23: /* 0010 0011 */ f8_xi(); break;
+ case 0x24: /* 0010 0100 */ f8_ai(); break;
+ case 0x25: /* 0010 0101 */ f8_ci(); break;
+ case 0x26: /* 0010 0110 */ f8_in(); break;
+ case 0x27: /* 0010 0111 */ f8_out(); break;
+ case 0x28: /* 0010 1000 */ f8_pi(); break;
+ case 0x29: /* 0010 1001 */ f8_jmp(); break;
+ case 0x2a: /* 0010 1010 */ f8_dci(); break;
+ case 0x2b: /* 0010 1011 */ f8_nop(); break;
+ case 0x2c: /* 0010 1100 */ f8_xdc(); break;
+ case 0x2d: /* 0010 1101 */ illegal(); break;
+ case 0x2e: /* 0010 1110 */ illegal(); break;
+ case 0x2f: /* 0010 1111 */ illegal(); break;
+
+ case 0x30: /* 0011 0000 */ f8_ds_r( 0); break;
+ case 0x31: /* 0011 0001 */ f8_ds_r( 1); break;
+ case 0x32: /* 0011 0010 */ f8_ds_r( 2); break;
+ case 0x33: /* 0011 0011 */ f8_ds_r( 3); break;
+ case 0x34: /* 0011 0100 */ f8_ds_r( 4); break;
+ case 0x35: /* 0011 0101 */ f8_ds_r( 5); break;
+ case 0x36: /* 0011 0110 */ f8_ds_r( 6); break;
+ case 0x37: /* 0011 0111 */ f8_ds_r( 7); break;
+ case 0x38: /* 0011 1000 */ f8_ds_r( 8); break;
+ case 0x39: /* 0011 1001 */ f8_ds_r( 9); break;
+ case 0x3a: /* 0011 1010 */ f8_ds_r(10); break;
+ case 0x3b: /* 0011 1011 */ f8_ds_r(11); break;
+ case 0x3c: /* 0011 1100 */ f8_ds_isar(); break;
+ case 0x3d: /* 0011 1101 */ f8_ds_isar_i(); break;
+ case 0x3e: /* 0011 1110 */ f8_ds_isar_d(); break;
+ case 0x3f: /* 0011 1111 */ illegal(); break;
+
+ case 0x40: /* 0100 0000 */ f8_lr_a_r( 0); break;
+ case 0x41: /* 0100 0001 */ f8_lr_a_r( 1); break;
+ case 0x42: /* 0100 0010 */ f8_lr_a_r( 2); break;
+ case 0x43: /* 0100 0011 */ f8_lr_a_r( 3); break;
+ case 0x44: /* 0100 0100 */ f8_lr_a_r( 4); break;
+ case 0x45: /* 0100 0101 */ f8_lr_a_r( 5); break;
+ case 0x46: /* 0100 0110 */ f8_lr_a_r( 6); break;
+ case 0x47: /* 0100 0111 */ f8_lr_a_r( 7); break;
+ case 0x48: /* 0100 1000 */ f8_lr_a_r( 8); break;
+ case 0x49: /* 0100 1001 */ f8_lr_a_r( 9); break;
+ case 0x4a: /* 0100 1010 */ f8_lr_a_r(10); break;
+ case 0x4b: /* 0100 1011 */ f8_lr_a_r(11); break;
+ case 0x4c: /* 0100 1100 */ f8_lr_a_isar(); break;
+ case 0x4d: /* 0100 1101 */ f8_lr_a_isar_i(); break;
+ case 0x4e: /* 0100 1110 */ f8_lr_a_isar_d(); break;
+ case 0x4f: /* 0100 1111 */ illegal(); break;
+
+ case 0x50: /* 0101 0000 */ f8_lr_r_a( 0); break;
+ case 0x51: /* 0101 0001 */ f8_lr_r_a( 1); break;
+ case 0x52: /* 0101 0010 */ f8_lr_r_a( 2); break;
+ case 0x53: /* 0101 0011 */ f8_lr_r_a( 3); break;
+ case 0x54: /* 0101 0100 */ f8_lr_r_a( 4); break;
+ case 0x55: /* 0101 0101 */ f8_lr_r_a( 5); break;
+ case 0x56: /* 0101 0110 */ f8_lr_r_a( 6); break;
+ case 0x57: /* 0101 0111 */ f8_lr_r_a( 7); break;
+ case 0x58: /* 0101 1000 */ f8_lr_r_a( 8); break;
+ case 0x59: /* 0101 1001 */ f8_lr_r_a( 9); break;
+ case 0x5a: /* 0101 1010 */ f8_lr_r_a(10); break;
+ case 0x5b: /* 0101 1011 */ f8_lr_r_a(11); break;
+ case 0x5c: /* 0101 1100 */ f8_lr_isar_a(); break;
+ case 0x5d: /* 0101 1101 */ f8_lr_isar_i_a(); break;
+ case 0x5e: /* 0101 1110 */ f8_lr_isar_d_a(); break;
+ case 0x5f: /* 0101 1111 */ illegal(); break;
+
+ case 0x60: /* 0110 0000 */ f8_lisu(0x00); break;
+ case 0x61: /* 0110 0001 */ f8_lisu(0x08); break;
+ case 0x62: /* 0110 0010 */ f8_lisu(0x10); break;
+ case 0x63: /* 0110 0011 */ f8_lisu(0x18); break;
+ case 0x64: /* 0110 0100 */ f8_lisu(0x20); break;
+ case 0x65: /* 0110 0101 */ f8_lisu(0x28); break;
+ case 0x66: /* 0110 0110 */ f8_lisu(0x30); break;
+ case 0x67: /* 0110 0111 */ f8_lisu(0x38); break;
+ case 0x68: /* 0110 1000 */ f8_lisl(0x00); break;
+ case 0x69: /* 0110 1001 */ f8_lisl(0x01); break;
+ case 0x6a: /* 0110 1010 */ f8_lisl(0x02); break;
+ case 0x6b: /* 0110 1011 */ f8_lisl(0x03); break;
+ case 0x6c: /* 0110 1100 */ f8_lisl(0x04); break;
+ case 0x6d: /* 0110 1101 */ f8_lisl(0x05); break;
+ case 0x6e: /* 0110 1110 */ f8_lisl(0x06); break;
+ case 0x6f: /* 0110 1111 */ f8_lisl(0x07); break;
+
+ case 0x70: /* 0111 0000 */ f8_lis(0x0); break;
+ case 0x71: /* 0111 0001 */ f8_lis(0x1); break;
+ case 0x72: /* 0111 0010 */ f8_lis(0x2); break;
+ case 0x73: /* 0111 0011 */ f8_lis(0x3); break;
+ case 0x74: /* 0111 0100 */ f8_lis(0x4); break;
+ case 0x75: /* 0111 0101 */ f8_lis(0x5); break;
+ case 0x76: /* 0111 0110 */ f8_lis(0x6); break;
+ case 0x77: /* 0111 0111 */ f8_lis(0x7); break;
+ case 0x78: /* 0111 1000 */ f8_lis(0x8); break;
+ case 0x79: /* 0111 1001 */ f8_lis(0x9); break;
+ case 0x7a: /* 0111 1010 */ f8_lis(0xa); break;
+ case 0x7b: /* 0111 1011 */ f8_lis(0xb); break;
+ case 0x7c: /* 0111 1100 */ f8_lis(0xc); break;
+ case 0x7d: /* 0111 1101 */ f8_lis(0xd); break;
+ case 0x7e: /* 0111 1110 */ f8_lis(0xe); break;
+ case 0x7f: /* 0111 1111 */ f8_lis(0xf); break;
+
+ case 0x80: /* 1000 0000 */ f8_bt(0); break;
+ case 0x81: /* 1000 0001 */ f8_bt(1); break;
+ case 0x82: /* 1000 0010 */ f8_bt(2); break;
+ case 0x83: /* 1000 0011 */ f8_bt(3); break;
+ case 0x84: /* 1000 0100 */ f8_bt(4); break;
+ case 0x85: /* 1000 0101 */ f8_bt(5); break;
+ case 0x86: /* 1000 0110 */ f8_bt(6); break;
+ case 0x87: /* 1000 0111 */ f8_bt(7); break;
+ case 0x88: /* 1000 1000 */ f8_am(); break;
+ case 0x89: /* 1000 1001 */ f8_amd(); break;
+ case 0x8a: /* 1000 1010 */ f8_nm(); break;
+ case 0x8b: /* 1000 1011 */ f8_om(); break;
+ case 0x8c: /* 1000 1100 */ f8_xm(); break;
+ case 0x8d: /* 1000 1101 */ f8_cm(); break;
+ case 0x8e: /* 1000 1110 */ f8_adc(); break;
+ case 0x8f: /* 1000 1111 */ f8_br7(); break;
+
+ case 0x90: /* 1001 0000 */ f8_bf(0x0); break;
+ case 0x91: /* 1001 0001 */ f8_bf(0x1); break;
+ case 0x92: /* 1001 0010 */ f8_bf(0x2); break;
+ case 0x93: /* 1001 0011 */ f8_bf(0x3); break;
+ case 0x94: /* 1001 0100 */ f8_bf(0x4); break;
+ case 0x95: /* 1001 0101 */ f8_bf(0x5); break;
+ case 0x96: /* 1001 0110 */ f8_bf(0x6); break;
+ case 0x97: /* 1001 0111 */ f8_bf(0x7); break;
+ case 0x98: /* 1001 1000 */ f8_bf(0x8); break;
+ case 0x99: /* 1001 1001 */ f8_bf(0x9); break;
+ case 0x9a: /* 1001 1010 */ f8_bf(0xa); break;
+ case 0x9b: /* 1001 1011 */ f8_bf(0xb); break;
+ case 0x9c: /* 1001 1100 */ f8_bf(0xc); break;
+ case 0x9d: /* 1001 1101 */ f8_bf(0xd); break;
+ case 0x9e: /* 1001 1110 */ f8_bf(0xe); break;
+ case 0x9f: /* 1001 1111 */ f8_bf(0xf); break;
+
+ case 0xa0: /* 1010 0000 */ f8_ins_0(0x0); break;
+ case 0xa1: /* 1010 0001 */ f8_ins_0(0x1); break;
+ case 0xa2: /* 1010 0010 */ illegal(); break;
+ case 0xa3: /* 1010 0011 */ illegal(); break;
+ case 0xa4: /* 1010 0100 */ f8_ins_1(0x4); break;
+ case 0xa5: /* 1010 0101 */ f8_ins_1(0x5); break;
+ case 0xa6: /* 1010 0110 */ f8_ins_1(0x6); break;
+ case 0xa7: /* 1010 0111 */ f8_ins_1(0x7); break;
+ case 0xa8: /* 1010 1000 */ f8_ins_1(0x8); break;
+ case 0xa9: /* 1010 1001 */ f8_ins_1(0x9); break;
+ case 0xaa: /* 1010 1010 */ f8_ins_1(0xa); break;
+ case 0xab: /* 1010 1011 */ f8_ins_1(0xb); break;
+ case 0xac: /* 1010 1100 */ f8_ins_1(0xc); break;
+ case 0xad: /* 1010 1101 */ f8_ins_1(0xd); break;
+ case 0xae: /* 1010 1110 */ f8_ins_1(0xe); break;
+ case 0xaf: /* 1010 1111 */ f8_ins_1(0xf); break;
+
+ case 0xb0: /* 1011 0000 */ f8_outs_0(0x0); break;
+ case 0xb1: /* 1011 0001 */ f8_outs_0(0x1); break;
+ case 0xb2: /* 1011 0010 */ illegal(); break;
+ case 0xb3: /* 1011 0011 */ illegal(); break;
+ case 0xb4: /* 1011 0100 */ f8_outs_1(0x4); break;
+ case 0xb5: /* 1011 0101 */ f8_outs_1(0x5); break;
+ case 0xb6: /* 1011 0110 */ f8_outs_1(0x6); break;
+ case 0xb7: /* 1011 0111 */ f8_outs_1(0x7); break;
+ case 0xb8: /* 1011 1000 */ f8_outs_1(0x8); break;
+ case 0xb9: /* 1011 1001 */ f8_outs_1(0x9); break;
+ case 0xba: /* 1011 1010 */ f8_outs_1(0xa); break;
+ case 0xbb: /* 1011 1011 */ f8_outs_1(0xb); break;
+ case 0xbc: /* 1011 1100 */ f8_outs_1(0xc); break;
+ case 0xbd: /* 1011 1101 */ f8_outs_1(0xd); break;
+ case 0xbe: /* 1011 1110 */ f8_outs_1(0xe); break;
+ case 0xbf: /* 1011 1111 */ f8_outs_1(0xf); break;
+
+ case 0xc0: /* 1100 0000 */ f8_as(0x0); break;
+ case 0xc1: /* 1100 0001 */ f8_as(0x1); break;
+ case 0xc2: /* 1100 0010 */ f8_as(0x2); break;
+ case 0xc3: /* 1100 0011 */ f8_as(0x3); break;
+ case 0xc4: /* 1100 0100 */ f8_as(0x4); break;
+ case 0xc5: /* 1100 0101 */ f8_as(0x5); break;
+ case 0xc6: /* 1100 0110 */ f8_as(0x6); break;
+ case 0xc7: /* 1100 0111 */ f8_as(0x7); break;
+ case 0xc8: /* 1100 1000 */ f8_as(0x8); break;
+ case 0xc9: /* 1100 1001 */ f8_as(0x9); break;
+ case 0xca: /* 1100 1010 */ f8_as(0xa); break;
+ case 0xcb: /* 1100 1011 */ f8_as(0xb); break;
+ case 0xcc: /* 1100 1100 */ f8_as_isar(); break;
+ case 0xcd: /* 1100 1101 */ f8_as_isar_i(); break;
+ case 0xce: /* 1100 1110 */ f8_as_isar_d(); break;
+ case 0xcf: /* 1100 1111 */ illegal(); break;
+
+ case 0xd0: /* 1101 0000 */ f8_asd(0x0); break;
+ case 0xd1: /* 1101 0001 */ f8_asd(0x1); break;
+ case 0xd2: /* 1101 0010 */ f8_asd(0x2); break;
+ case 0xd3: /* 1101 0011 */ f8_asd(0x3); break;
+ case 0xd4: /* 1101 0100 */ f8_asd(0x4); break;
+ case 0xd5: /* 1101 0101 */ f8_asd(0x5); break;
+ case 0xd6: /* 1101 0110 */ f8_asd(0x6); break;
+ case 0xd7: /* 1101 0111 */ f8_asd(0x7); break;
+ case 0xd8: /* 1101 1000 */ f8_asd(0x8); break;
+ case 0xd9: /* 1101 1001 */ f8_asd(0x9); break;
+ case 0xda: /* 1101 1010 */ f8_asd(0xa); break;
+ case 0xdb: /* 1101 1011 */ f8_asd(0xb); break;
+ case 0xdc: /* 1101 1100 */ f8_asd_isar(); break;
+ case 0xdd: /* 1101 1101 */ f8_asd_isar_i(); break;
+ case 0xde: /* 1101 1110 */ f8_asd_isar_d(); break;
+ case 0xdf: /* 1101 1111 */ illegal(); break;
+
+ case 0xe0: /* 1110 0000 */ f8_xs(0x0); break;
+ case 0xe1: /* 1110 0001 */ f8_xs(0x1); break;
+ case 0xe2: /* 1110 0010 */ f8_xs(0x2); break;
+ case 0xe3: /* 1110 0011 */ f8_xs(0x3); break;
+ case 0xe4: /* 1110 0100 */ f8_xs(0x4); break;
+ case 0xe5: /* 1110 0101 */ f8_xs(0x5); break;
+ case 0xe6: /* 1110 0110 */ f8_xs(0x6); break;
+ case 0xe7: /* 1110 0111 */ f8_xs(0x7); break;
+ case 0xe8: /* 1110 1000 */ f8_xs(0x8); break;
+ case 0xe9: /* 1110 1001 */ f8_xs(0x9); break;
+ case 0xea: /* 1110 1010 */ f8_xs(0xa); break;
+ case 0xeb: /* 1110 1011 */ f8_xs(0xb); break;
+ case 0xec: /* 1110 1100 */ f8_xs_isar(); break;
+ case 0xed: /* 1110 1101 */ f8_xs_isar_i(); break;
+ case 0xee: /* 1110 1110 */ f8_xs_isar_d(); break;
+ case 0xef: /* 1110 1111 */ illegal(); break;
+
+ case 0xf0: /* 1111 0000 */ f8_ns(0x0); break;
+ case 0xf1: /* 1111 0001 */ f8_ns(0x1); break;
+ case 0xf2: /* 1111 0010 */ f8_ns(0x2); break;
+ case 0xf3: /* 1111 0011 */ f8_ns(0x3); break;
+ case 0xf4: /* 1111 0100 */ f8_ns(0x4); break;
+ case 0xf5: /* 1111 0101 */ f8_ns(0x5); break;
+ case 0xf6: /* 1111 0110 */ f8_ns(0x6); break;
+ case 0xf7: /* 1111 0111 */ f8_ns(0x7); break;
+ case 0xf8: /* 1111 1000 */ f8_ns(0x8); break;
+ case 0xf9: /* 1111 1001 */ f8_ns(0x9); break;
+ case 0xfa: /* 1111 1010 */ f8_ns(0xa); break;
+ case 0xfb: /* 1111 1011 */ f8_ns(0xb); break;
+ case 0xfc: /* 1111 1100 */ f8_ns_isar(); break;
+ case 0xfd: /* 1111 1101 */ f8_ns_isar_i(); break;
+ case 0xfe: /* 1111 1110 */ f8_ns_isar_d(); break;
+ case 0xff: /* 1111 1111 */ illegal(); break;
}
- switch (op)
- {
- case 0x0c: case 0x1b: case 0x1c: case 0x1d:
+ switch (op) {
+ case 0x0d: case 0x1b: case 0x1c: case 0x1d:
case 0x27: case 0x28: case 0x29:
case 0xb4: case 0xb5: case 0xb6: case 0xb7:
case 0xb8: case 0xb9: case 0xba: case 0xbb:
case 0xbc: case 0xbd: case 0xbe: case 0xbf:
- // don't handle irq after privileged instruction
ROMC_00(cS);
break;
default:
- // 'freeze cycle' for handling interrupts
if (m_w&I && m_irq_request)
{
- ROMC_10();
ROMC_1C(cL);
ROMC_0F();
ROMC_13();
}
-
- // fetch next instruction (DS is long cycle)
- if ((op >= 0x30) && (op <= 0x3f))
+ if( ( op >= 0x30 ) && ( op <= 0x3f) ) /* DS is a long cycle inst */
+ {
ROMC_00(cL);
+ }
else
+ {
ROMC_00(cS);
-
+ }
break;
}
} while( m_icount > 0 );
diff --git a/src/devices/cpu/f8/f8.h b/src/devices/cpu/f8/f8.h
index 5185b938a05..cdd8f03b862 100644
--- a/src/devices/cpu/f8/f8.h
+++ b/src/devices/cpu/f8/f8.h
@@ -76,6 +76,9 @@ private:
u8 m_r[64]; /* scratchpad RAM */
int m_irq_request;
+ /* timer shifter polynomial values (will be used for timer interrupts) */
+ u8 timer_shifter[256];
+
u16 m_debug_pc; // only for the MAME debugger
inline void CLR_OZCS();
diff --git a/src/devices/cpu/g65816/g65816.cpp b/src/devices/cpu/g65816/g65816.cpp
index 93c93f96ed8..a65122b6153 100644
--- a/src/devices/cpu/g65816/g65816.cpp
+++ b/src/devices/cpu/g65816/g65816.cpp
@@ -17,10 +17,6 @@ All rights reserved.
/*
Changes:
- 1.02 (2019-02-02):
- R. Belmont
- - Corrected WDM to take 2 bytes and added callback
-
1.01 (2010-04-04):
Angelo Salese
- Added boundary checks for MVP and MVN in M mode.
@@ -119,7 +115,6 @@ g65816_device::g65816_device(const machine_config &mconfig, device_type type, co
, m_data_config("data", ENDIANNESS_LITTLE, 8, 24, 0, internal)
, m_opcode_config("opcodes", ENDIANNESS_LITTLE, 8, 24, 0, internal)
, m_vector_config("vectors", ENDIANNESS_LITTLE, 8, 5, 0)
- , m_wdm_w(*this)
, m_cpu_type(cpu_type)
{
}
@@ -865,8 +860,6 @@ void g65816_device::device_start()
m_program_cache = program_space.cache<0, 0, ENDIANNESS_LITTLE>();
m_opcode_cache = (has_space(AS_OPCODES) ? space(AS_OPCODES) : program_space).cache<0, 0, ENDIANNESS_LITTLE>();
- m_wdm_w.resolve_safe();
-
save_item(NAME(m_a));
save_item(NAME(m_b));
save_item(NAME(m_x));
diff --git a/src/devices/cpu/g65816/g65816.h b/src/devices/cpu/g65816/g65816.h
index 454dc7fd1b5..e53f9eb784b 100644
--- a/src/devices/cpu/g65816/g65816.h
+++ b/src/devices/cpu/g65816/g65816.h
@@ -56,8 +56,7 @@ public:
// construction/destruction
g65816_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- auto wdm_handler() { return m_wdm_w.bind(); }
-
+protected:
/* Registers - used by g65816_set_reg() and g65816_get_reg() */
enum
{
@@ -67,7 +66,6 @@ public:
_5A22_FASTROM
};
-protected:
g65816_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int cpu_type, address_map_constructor internal);
// device-level overrides
@@ -98,7 +96,6 @@ protected:
address_space_config m_data_config;
address_space_config m_opcode_config;
address_space_config m_vector_config;
- devcb_write8 m_wdm_w; /* WDM callback */
typedef void (g65816_device::*opcode_func) ();
typedef unsigned (g65816_device::*get_reg_func)(int regnum);
@@ -142,10 +139,8 @@ protected:
void g65816_set_pc(unsigned val);
unsigned g65816_get_sp();
void g65816_set_sp(unsigned val);
-public:
unsigned g65816_get_reg(int regnum);
void g65816_set_reg(int regnum, unsigned value);
-protected:
void g65816_restore_state();
unsigned g65816i_read_8_normal(unsigned address);
unsigned g65816i_read_8_immediate(unsigned address);
diff --git a/src/devices/cpu/g65816/g65816ds.cpp b/src/devices/cpu/g65816/g65816ds.cpp
index 355be140f99..0f40b42f5d6 100644
--- a/src/devices/cpu/g65816/g65816ds.cpp
+++ b/src/devices/cpu/g65816/g65816ds.cpp
@@ -101,7 +101,7 @@ const g65816_disassembler::opcode_struct g65816_disassembler::s_opcodes[256] =
{op::BIT, M, DX }, {op::AND, M, DX }, {op::ROL, M, DX }, {op::AND, M, DLIY},
{op::SEC, I, IMP }, {op::AND, M, AY }, {op::DEA, I, IMP }, {op::TSC, I, IMP },
{op::BIT, M, AX }, {op::AND, M, AX }, {op::ROL, M, AX }, {op::AND, M, ALX },
- {op::RTI, I, IMP }, {op::EOR, M, DXI }, {op::WDM, I, SIG }, {op::EOR, M, S },
+ {op::RTI, I, IMP }, {op::EOR, M, DXI }, {op::WDM, I, IMP }, {op::EOR, M, S },
{op::MVP, I, MVP }, {op::EOR, M, D }, {op::LSR, M, D }, {op::EOR, M, DLI },
{op::PHA, I, IMP }, {op::EOR, M, IMM }, {op::LSR, M, ACC }, {op::PHK, I, IMP },
{op::JMP, I, A }, {op::EOR, M, A }, {op::LSR, M, A }, {op::EOR, M, AL },
diff --git a/src/devices/cpu/g65816/g65816op.h b/src/devices/cpu/g65816/g65816op.h
index 727117c0f29..97b198e9385 100644
--- a/src/devices/cpu/g65816/g65816op.h
+++ b/src/devices/cpu/g65816/g65816op.h
@@ -1428,8 +1428,7 @@
#undef OP_WDM
#define OP_WDM() \
CLK(CLK_OP + CLK_IMPLIED); \
- SRC = OPER_8_IMM(); \
- m_wdm_w(SRC);
+ REGISTER_PC++
/* G65816 Exchange accum high and low bytes */
#undef OP_XBA
diff --git a/src/devices/cpu/h8/h83003.cpp b/src/devices/cpu/h8/h83003.cpp
index 7b7b468d7b5..4e3e59c15cf 100644
--- a/src/devices/cpu/h8/h83003.cpp
+++ b/src/devices/cpu/h8/h83003.cpp
@@ -136,9 +136,7 @@ void h83003_device::map(address_map &map)
map(0xffffd2, 0xffffd2).rw("port9", FUNC(h8_port_device::port_r), FUNC(h8_port_device::dr_w));
map(0xffffd3, 0xffffd3).rw("porta", FUNC(h8_port_device::port_r), FUNC(h8_port_device::dr_w));
map(0xffffd4, 0xffffd4).w("portb", FUNC(h8_port_device::ddr_w));
- map(0xffffd5, 0xffffd5).w("portc", FUNC(h8_port_device::ddr_w));
map(0xffffd6, 0xffffd6).rw("portb", FUNC(h8_port_device::port_r), FUNC(h8_port_device::dr_w));
- map(0xffffd7, 0xffffd7).rw("portc", FUNC(h8_port_device::port_r), FUNC(h8_port_device::dr_w));
map(0xffffda, 0xffffda).rw("port4", FUNC(h8_port_device::pcr_r), FUNC(h8_port_device::pcr_w));
map(0xffffe0, 0xffffe7).r("adc", FUNC(h8_adc_device::addr8_r));
@@ -169,7 +167,6 @@ void h83003_device::device_add_mconfig(machine_config &config)
H8_PORT(config, "port9", h8_device::PORT_9, 0x00, 0xc0);
H8_PORT(config, "porta", h8_device::PORT_A, 0x00, 0x00);
H8_PORT(config, "portb", h8_device::PORT_B, 0x00, 0x00);
- H8_PORT(config, "portc", h8_device::PORT_C, 0x00, 0x00);
H8_TIMER16(config, "timer16", 5, 0xe0);
H8H_TIMER16_CHANNEL(config, "timer16:0", 2, 2, "intc", 24);
H8H_TIMER16_CHANNEL(config, "timer16:1", 2, 2, "intc", 28);
diff --git a/src/devices/cpu/hmcs40/hmcs40.cpp b/src/devices/cpu/hmcs40/hmcs40.cpp
index 42e1ca45ef8..795ab3de985 100644
--- a/src/devices/cpu/hmcs40/hmcs40.cpp
+++ b/src/devices/cpu/hmcs40/hmcs40.cpp
@@ -466,7 +466,6 @@ void hmcs40_cpu_device::do_interrupt()
m_irt = 0;
standard_irq_callback(line);
- m_prev_pc = m_pc;
}
void hmcs40_cpu_device::execute_set_input(int line, int state)
diff --git a/src/devices/cpu/hpc/hpc.cpp b/src/devices/cpu/hpc/hpc.cpp
deleted file mode 100644
index 399ca9164af..00000000000
--- a/src/devices/cpu/hpc/hpc.cpp
+++ /dev/null
@@ -1,144 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:AJR
-/***************************************************************************
-
- National Semiconductor High-Performance microController (HPC)
-
- Currently this device is just a stub with no actual execution core.
-
-****************************************************************************
-
- HPC feature options by part number
-
- HPC16xxx Military temperature range (-55°C to +125°C)
- HPC26xxx Automotive temperature range (-40°C to +105°C)
- HPC36xxx Industrial temperature range (-40°C to +85°C)
- HPC46xxx Commercial temperature range (0°C to +75°C)
-
- HPCxx1xx 8-channel A/D converter
- HPCxx0xx No A/D converter
-
- HPCxxx6x 16k bytes of on-chip ROM
- HPCxxx8x 8k bytes of on-chip ROM
- HPCxxx0x No on-chip ROM
-
- HPCxxxx4 512 bytes of on-chip RAM
- HPCxxxx3 256 bytes of on-chip RAM
-
-***************************************************************************/
-
-#include "emu.h"
-#include "hpc.h"
-#include "hpcdasm.h"
-
-// device type definitions
-DEFINE_DEVICE_TYPE(HPC46003, hpc46003_device, "hpc46003", "HPC46003")
-DEFINE_DEVICE_TYPE(HPC46104, hpc46104_device, "hpc46104", "HPC46104")
-
-
-void hpc46003_device::internal_map(address_map &map)
-{
- map(0x0000, 0x00bf).ram();
- map(0x00c0, 0x00c0).rw(FUNC(hpc46003_device::psw_r), FUNC(hpc46003_device::psw_w));
- map(0x00c4, 0x00cf).ram().share("core_regs");
- // TODO: many other internal registers
- map(0x01c0, 0x01ff).ram();
-}
-
-void hpc46104_device::internal_map(address_map &map)
-{
- map(0x0000, 0x00bf).ram();
- map(0x00c0, 0x00c0).rw(FUNC(hpc46104_device::psw_r), FUNC(hpc46104_device::psw_w));
- map(0x00c4, 0x00cf).ram().share("core_regs");
- // TODO: many other internal registers
- map(0x01c0, 0x02ff).ram();
-}
-
-std::unique_ptr<util::disasm_interface> hpc46003_device::create_disassembler()
-{
- return std::make_unique<hpc16083_disassembler>();
-}
-
-std::unique_ptr<util::disasm_interface> hpc46104_device::create_disassembler()
-{
- return std::make_unique<hpc16164_disassembler>();
-}
-
-
-hpc_device::hpc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor map)
- : cpu_device(mconfig, type, tag, owner, clock)
- , m_program_config("program", ENDIANNESS_LITTLE, 16, 16, 0, map)
- , m_program(nullptr)
- , m_core_regs(*this, "core_regs")
- , m_psw(0)
- , m_icount(0)
-{
-}
-
-hpc46003_device::hpc46003_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : hpc_device(mconfig, HPC46003, tag, owner, clock, address_map_constructor(FUNC(hpc46003_device::internal_map), this))
-{
-}
-
-hpc46104_device::hpc46104_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : hpc_device(mconfig, HPC46104, tag, owner, clock, address_map_constructor(FUNC(hpc46104_device::internal_map), this))
-{
-}
-
-device_memory_interface::space_config_vector hpc_device::memory_space_config() const
-{
- return space_config_vector {
- std::make_pair(AS_PROGRAM, &m_program_config),
- };
-}
-
-
-void hpc_device::device_start()
-{
- m_program = &space(AS_PROGRAM);
-
- set_icountptr(m_icount);
-
- state_add(HPC_PSW, "PSW", m_psw);
- state_add(HPC_SP, "SP", m_core_regs[0]);
- state_add(HPC_PC, "PC", m_core_regs[1]);
- state_add(STATE_GENPC, "GENPC", m_core_regs[1]).callimport().noshow();
- state_add(STATE_GENPCBASE, "CURPC", m_core_regs[1]).callimport().noshow();
- state_add(HPC_A, "A", m_core_regs[2]);
- state_add(HPC_K, "K", m_core_regs[3]);
- state_add(HPC_B, "B", m_core_regs[4]);
- state_add(HPC_X, "X", m_core_regs[5]);
-
- save_item(NAME(m_psw));
-}
-
-void hpc_device::device_reset()
-{
- m_psw = 0x00;
- std::fill_n(&m_core_regs[0], 6, 0x0000);
-}
-
-
-u8 hpc_device::psw_r()
-{
- return m_psw;
-}
-
-void hpc_device::psw_w(u8 data)
-{
- m_psw = data;
-}
-
-
-void hpc_device::execute_run()
-{
- m_core_regs[1] = m_program->read_word(0xfffe);
- debugger_instruction_hook(m_core_regs[1]);
-
- m_icount = 0;
-}
-
-void hpc_device::execute_set_input(int inputnum, int state)
-{
- // TODO
-}
diff --git a/src/devices/cpu/hpc/hpc.h b/src/devices/cpu/hpc/hpc.h
deleted file mode 100644
index 5f73a0ee2e6..00000000000
--- a/src/devices/cpu/hpc/hpc.h
+++ /dev/null
@@ -1,88 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:AJR
-
-#ifndef MAME_CPU_HPC_HPC_H
-#define MAME_CPU_HPC_HPC_H
-
-#pragma once
-
-
-class hpc_device : public cpu_device
-{
-public:
- enum {
- HPC_PSW,
- HPC_SP,
- HPC_PC,
- HPC_A,
- HPC_K,
- HPC_B,
- HPC_X
- };
-
-protected:
- // construction/destruction
- hpc_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, address_map_constructor map);
-
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- // device_execute_interface overrides
- virtual void execute_run() override;
- virtual void execute_set_input(int inputnum, int state) override;
-
- // device_memory_interface overrides
- virtual space_config_vector memory_space_config() const override;
-
- // internal register access
- u8 psw_r();
- void psw_w(u8 data);
-
-private:
- // address space
- address_space_config m_program_config;
- address_space *m_program;
-
- // internal state
- required_shared_ptr<u16> m_core_regs;
- u8 m_psw;
-
- // execution sequencing
- s32 m_icount;
-};
-
-class hpc46003_device : public hpc_device
-{
-public:
- // construction/destruction
- hpc46003_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-
-protected:
- // device_disasm_interface overrides
- virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
-
-private:
- void internal_map(address_map &map);
-};
-
-class hpc46104_device : public hpc_device
-{
-public:
- // construction/destruction
- hpc46104_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-
-protected:
- // device_disasm_interface overrides
- virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
-
-private:
- void internal_map(address_map &map);
-};
-
-
-// device type declarations
-DECLARE_DEVICE_TYPE(HPC46003, hpc46003_device)
-DECLARE_DEVICE_TYPE(HPC46104, hpc46104_device)
-
-#endif // MAME_CPU_HPC_HPC_H
diff --git a/src/devices/cpu/hpc/hpcdasm.cpp b/src/devices/cpu/hpc/hpcdasm.cpp
deleted file mode 100644
index 86c575a826e..00000000000
--- a/src/devices/cpu/hpc/hpcdasm.cpp
+++ /dev/null
@@ -1,764 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:AJR
-/***************************************************************************
-
- National Semiconductor HPC disassembler
-
- Note that though all 16-bit fields in instructions have the MSB first,
- the HPC's memory organization is in fact little-endian. This is why r16
- is not used to read them.
-
-***************************************************************************/
-
-#include "util/disasmintf.h"
-#include "hpcdasm.h"
-
-#include "util/strformat.h"
-#include <ctype.h>
-
-using osd::u32;
-using util::BIT;
-using offs_t = u32;
-
-const char *const hpc16083_disassembler::s_regs[128] =
-{
- "psw", nullptr, "SP", "PC", "A", "K", "B", "X",
- "enir", "irpd", "ircd", "sio", "porti", nullptr, "halten", nullptr,
- "porta", "portb", nullptr, "upic", nullptr, nullptr, nullptr, nullptr,
- "dira", "dirb", "bfun", nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, "portd", nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- "enu", "enui", "rbuf", "tbuf", "enur", nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- "t4", "r4", "t5", "r5", "t6", "r6", "t7", "r7",
- "pwmode", "portp", nullptr, nullptr, nullptr, nullptr, "eicon", "eicr",
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- "i4cr", "i3cr", "i2cr", "r2", "t2", "r3", "t3", "divby",
- "tmmode", "t0con", "watchdog", nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
-};
-
-const char *const hpc16164_disassembler::s_regs[128] =
-{
- "psw", nullptr, "SP", "PC", "A", "K", "B", "X",
- "enir", "irpd", "ircd", "sio", "porti", nullptr, "halten", "romdump",
- "porta", "portb", nullptr, "upic", nullptr, nullptr, nullptr, nullptr,
- "dira", "dirb", "bfun", nullptr, nullptr, nullptr, nullptr, nullptr,
- "adcr1", "adcr2", "portd", "adcr3", nullptr, nullptr, nullptr, nullptr,
- "ad0", "ad1", "ad2", "ad3", "ad4", "ad5", "ad6", "ad7",
- "enu", "enui", "rbuf", "tbuf", "enur", nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- "t4", "r4", "t5", "r5", "t6", "r6", "t7", "r7",
- "pwmode", "portp", nullptr, nullptr, nullptr, nullptr, "eicon", "eicr",
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- "i4cr", "i3cr", "i2cr", "r2", "t2", "r3", "t3", "divby",
- "tmmode", "t0con", "watchdog", nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr
-};
-
-hpc_disassembler::hpc_disassembler(const char *const regs[])
- : util::disasm_interface()
- , m_regs(regs)
-{
-}
-
-u32 hpc_disassembler::opcode_alignment() const
-{
- return 1;
-}
-
-void hpc_disassembler::format_register(std::ostream &stream, u16 reg) const
-{
- if (reg >= 0x00c0 && reg < 0x01c0)
- {
- const char *name = m_regs[(reg - 0x00c0) >> 1];
- if (name != nullptr)
- {
- stream << name;
- if (BIT(reg, 0))
- stream << "+1";
- return;
- }
- }
-
- util::stream_format(stream, "0%X", reg);
-}
-
-void hpc_disassembler::format_immediate_byte(std::ostream &stream, u8 data) const
-{
- stream << "#";
- if (data >= 0x10)
- stream << "0";
- util::stream_format(stream, "%02X", data);
-}
-
-void hpc_disassembler::format_immediate_word(std::ostream &stream, u16 data) const
-{
- stream << "#";
- if (data >= 0x1000)
- stream << "0";
- util::stream_format(stream, "%04X", data);
-}
-
-void hpc_disassembler::disassemble_op(std::ostream &stream, const char *op, u16 reg, u16 src, bool imm, bool indir, bool idx, bool w) const
-{
- util::stream_format(stream, "%-8s", op);
- if (idx)
- stream << "A";
- else
- format_register(stream, reg);
- stream << ",";
- if (imm)
- {
- if (w)
- format_immediate_word(stream, src);
- else
- format_immediate_byte(stream, src);
- }
- else
- {
- if (idx)
- util::stream_format(stream, "0%X", u16(reg));
-
- if (indir)
- stream << "[";
- format_register(stream, src);
- if (indir)
- stream << "]";
-
- if (w)
- stream << ".w";
- else
- stream << ".b";
- }
-}
-
-void hpc_disassembler::disassemble_unary_op(std::ostream &stream, const char *op, u16 offset, u16 src, bool indir, bool idx, bool w) const
-{
- util::stream_format(stream, "%-8s", op);
- if (idx)
- util::stream_format(stream, "0%X", offset);
-
- if (indir)
- stream << "[";
- format_register(stream, src);
- if (indir)
- stream << "]";
-
- if (w)
- {
- if (src < 0x00c4 || src >= 0x00d0 || indir)
- stream << ".w";
- }
- else
- stream << ".b";
-}
-
-void hpc_disassembler::disassemble_bit_op(std::ostream &stream, const char *op, u8 bit, u16 offset, u16 src, bool indir, bool idx) const
-{
- if (src >= 0x00c0 && src < 0x01c0 && BIT(src, 0) && !indir && m_regs[(src - 0x00c0) >> 1] != nullptr)
- {
- src &= 0xfffe;
- bit += 8;
- }
-
- util::stream_format(stream, "%-8s%d,", op, bit);
-
- if (idx)
- util::stream_format(stream, "0%X", offset);
-
- if (indir)
- stream << "[";
- format_register(stream, src);
- if (indir)
- stream << "].b";
-}
-
-offs_t hpc_disassembler::disassemble(std::ostream &stream, offs_t pc, const hpc_disassembler::data_buffer &opcodes, const hpc_disassembler::data_buffer &params)
-{
- u8 opcode = opcodes.r8(pc);
- u16 reg = REGISTER_A;
- u16 src = REGISTER_B;
- bool imm = false;
- bool dmode = false;
- bool indir = true;
- bool idx = false;
- bool jmp = false;
- offs_t bytes = 1;
-
- switch (opcode)
- {
- case 0x20: case 0x21: case 0x22: case 0x23:
- case 0x24: case 0x25: case 0x26: case 0x27:
- case 0x28: case 0x29: case 0x2a: case 0x2b:
- case 0x2c: case 0x2d: case 0x2e: case 0x2f:
- jmp = true;
- src = 0xffd0 + (opcode & 0x0f) * 2;
- bytes = 1;
- break;
-
- case 0x30: case 0x31: case 0x32: case 0x33:
- jmp = true;
- src = pc + 2 + ((opcode & 0x03) << 8 | opcodes.r8(pc + 1));
- bytes = 2;
- break;
-
- case 0x34: case 0x35: case 0x36: case 0x37:
- jmp = true;
- src = pc - ((opcode & 0x03) << 8 | opcodes.r8(pc + 1));
- bytes = 2;
- break;
-
- case 0x38: case 0x39: case 0x3a:
- reg = REGISTER_X;
- break;
-
- case 0x3f:
- case 0x89: case 0x8a:
- case 0xa9: case 0xaa: case 0xaf:
- indir = false;
- src = opcodes.r8(pc + 1);
- bytes = 2;
- break;
-
- case 0x40: case 0x41: case 0x42: case 0x43:
- case 0x44: case 0x45: case 0x46: case 0x47:
- case 0x48: case 0x49: case 0x4a: case 0x4b:
- case 0x4c: case 0x4d: case 0x4e: case 0x4f:
- case 0x50: case 0x51: case 0x52: case 0x53:
- case 0x54: case 0x55: case 0x56: case 0x57:
- case 0x58: case 0x59: case 0x5a: case 0x5b:
- case 0x5c: case 0x5d: case 0x5e: case 0x5f:
- jmp = true;
- src = pc + 1 + (opcode & 0x1f);
- break;
-
- case 0x60: case 0x61: case 0x62: case 0x63:
- case 0x64: case 0x65: case 0x66: case 0x67:
- case 0x68: case 0x69: case 0x6a: case 0x6b:
- case 0x6c: case 0x6d: case 0x6e: case 0x6f:
- case 0x70: case 0x71: case 0x72: case 0x73:
- case 0x74: case 0x75: case 0x76: case 0x77:
- case 0x78: case 0x79: case 0x7a: case 0x7b:
- case 0x7c: case 0x7d: case 0x7e: case 0x7f:
- jmp = true;
- src = pc - (opcode & 0x1f);
- break;
-
- case 0x80: case 0x82:
- case 0xa0:
- dmode = true;
- indir = false;
- if (BIT(opcode, 1))
- imm = true;
-
- src = opcodes.r8(pc + 1);
- reg = opcodes.r8(pc + 2);
- opcode = opcodes.r8(pc + 3);
- bytes = 4;
- break;
-
- case 0x84: case 0x86:
- case 0xa4:
- dmode = true;
- indir = false;
- if (BIT(opcode, 1))
- imm = true;
-
- src = (opcodes.r8(pc + 1) << 8) | opcodes.r8(pc + 2);
- reg = opcodes.r8(pc + 3);
- opcode = opcodes.r8(pc + 4);
- bytes = 5;
- break;
-
- case 0x81: case 0x83:
- case 0xa1:
- dmode = true;
- indir = false;
- if (BIT(opcode, 1))
- imm = true;
-
- src = opcodes.r8(pc + 1);
- reg = (opcodes.r8(pc + 2) << 8) | opcodes.r8(pc + 3);
- opcode = opcodes.r8(pc + 4);
- bytes = 5;
- break;
-
- case 0xa2:
- idx = true;
- reg = opcodes.r8(pc + 1);
- src = opcodes.r8(pc + 2);
- opcode = opcodes.r8(pc + 3);
- bytes = 4;
- break;
-
- case 0x85: case 0x87:
- case 0xa5:
- dmode = true;
- indir = false;
- if (BIT(opcode, 1))
- imm = true;
-
- src = (opcodes.r8(pc + 1) << 8) | opcodes.r8(pc + 2);
- reg = (opcodes.r8(pc + 3) << 8) | opcodes.r8(pc + 4);
- opcode = opcodes.r8(pc + 5);
- bytes = 6;
- break;
-
- case 0xa6:
- idx = true;
- reg = (opcodes.r8(pc + 1) << 8) | opcodes.r8(pc + 2);
- src = opcodes.r8(pc + 3);
- opcode = opcodes.r8(pc + 4);
- bytes = 5;
- break;
-
- case 0x88: case 0x8b: case 0x8e:
- case 0xa8: case 0xab: case 0xae:
- indir = false;
- src = opcodes.r8(pc + 1);
- bytes = 2;
- break;
-
- case 0x8c:
- case 0xac:
- indir = false;
- src = opcodes.r8(pc + 1);
- reg = opcodes.r8(pc + 2);
- bytes = 3;
- break;
-
- case 0x8d:
- imm = true;
- src = opcodes.r8(pc + 1);
- reg = opcodes.r8(pc + 2);
- bytes = 3;
- break;
-
- case 0x8f:
- src = REGISTER_X;
- opcode = opcodes.r8(pc + 1);
- bytes = 2;
- break;
-
- case 0x90: case 0x91: case 0x92: case 0x93:
- imm = true;
- reg = 0x00c8 | ((opcode & 0x03) << 1);
- src = opcodes.r8(pc + 1);
- bytes = 2;
- break;
-
- case 0x98: case 0x99: case 0x9a: case 0x9b:
- case 0x9c: case 0x9d: case 0x9e: case 0x9f:
- imm = true;
- src = opcodes.r8(pc + 1);
- bytes = 2;
- break;
-
- case 0x94:
- jmp = true;
- src = pc + 2 + opcodes.r8(pc + 1);
- bytes = 2;
- break;
-
- case 0x95:
- jmp = true;
- src = pc - opcodes.r8(pc + 1);
- bytes = 2;
- break;
-
- case 0x96:
- indir = false;
- src = opcodes.r8(pc + 1);
- opcode = opcodes.r8(pc + 2);
- bytes = 3;
- break;
-
- case 0x97:
- indir = false;
- imm = true;
- src = opcodes.r8(pc + 1);
- reg = opcodes.r8(pc + 2);
- bytes = 3;
- break;
-
- case 0xa7:
- imm = true;
- src = (opcodes.r8(pc + 1) << 8) | opcodes.r8(pc + 2);
- reg = (opcodes.r8(pc + 3) << 8) | opcodes.r8(pc + 4);
- bytes = 5;
- break;
-
- case 0xad:
- src = opcodes.r8(pc + 1);
- opcode = opcodes.r8(pc + 2);
- bytes = 3;
- break;
-
- case 0xb0: case 0xb1: case 0xb2: case 0xb3:
- imm = true;
- reg = 0x00c8 | ((opcode & 0x03) << 1);
- src = (opcodes.r8(pc + 1) << 8) | opcodes.r8(pc + 2);
- bytes = 3;
- break;
-
- case 0xb8: case 0xb9: case 0xba: case 0xbb:
- case 0xbc: case 0xbd: case 0xbe: case 0xbf:
- imm = true;
- src = (opcodes.r8(pc + 1) << 8) | opcodes.r8(pc + 2);
- bytes = 3;
- break;
-
- case 0xb4: case 0xb5:
- jmp = true;
- src = pc + 3 + ((opcodes.r8(pc + 1) << 8) | opcodes.r8(pc + 2));
- bytes = 3;
- break;
-
- case 0xb6:
- indir = false;
- src = (opcodes.r8(pc + 1) << 8) | opcodes.r8(pc + 2);
- opcode = opcodes.r8(pc + 3);
- bytes = 4;
- break;
-
- case 0xb7:
- imm = true;
- src = (opcodes.r8(pc + 1) << 8) | opcodes.r8(pc + 2);
- reg = opcodes.r8(pc + 3);
- bytes = 4;
- break;
-
- case 0xd4: case 0xd5: case 0xd6:
- case 0xf4: case 0xf5: case 0xf6:
- src = REGISTER_X;
- break;
- }
-
- switch (opcode)
- {
- case 0x00:
- util::stream_format(stream, "%-8sA", "clr");
- break;
-
- case 0x01:
- util::stream_format(stream, "%-8sA", "comp");
- break;
-
- case 0x02:
- stream << "sc";
- break;
-
- case 0x03:
- stream << "rc";
- break;
-
- case 0x04:
- util::stream_format(stream, "%-8sA", "inc");
- break;
-
- case 0x05:
- util::stream_format(stream, "%-8sA", "dec");
- break;
-
- case 0x06:
- stream << "ifnc";
- break;
-
- case 0x07:
- stream << "ifc";
- break;
-
- case 0x08: case 0x09: case 0x0a: case 0x0b:
- case 0x0c: case 0x0d: case 0x0e: case 0x0f:
- disassemble_bit_op(stream, "sbit", opcode & 0x07, reg, src, indir, idx);
- break;
-
- case 0x10: case 0x11: case 0x12: case 0x13:
- case 0x14: case 0x15: case 0x16: case 0x17:
- disassemble_bit_op(stream, "ifbit", opcode & 0x07, reg, src, indir, idx);
- break;
-
- case 0x18: case 0x19: case 0x1a: case 0x1b:
- case 0x1c: case 0x1d: case 0x1e: case 0x1f:
- disassemble_bit_op(stream, "rbit", opcode & 0x07, reg, src, indir, idx);
- break;
-
- case 0x20: case 0x21: case 0x22: case 0x23:
- case 0x24: case 0x25: case 0x26: case 0x27:
- case 0x28: case 0x29: case 0x2a: case 0x2b:
- case 0x2c: case 0x2d: case 0x2e: case 0x2f:
- util::stream_format(stream, "%-8s", "jsrp");
- if (jmp)
- util::stream_format(stream, "[0%X]", src);
- else
- stream << "???";
- bytes |= STEP_OVER;
- break;
-
- case 0x30: case 0x31: case 0x32: case 0x33:
- case 0x34: case 0x35: case 0x36: case 0x37:
- util::stream_format(stream, "%-8s", "jsr");
- if (jmp)
- util::stream_format(stream, "0%X", src);
- else
- stream << "???";
- bytes |= STEP_OVER;
- break;
-
- case 0x38:
- disassemble_op(stream, "rbit", reg, src, imm, indir, idx, false);
- break;
-
- case 0x39:
- disassemble_op(stream, "sbit", reg, src, imm, indir, idx, false);
- break;
-
- case 0x3a:
- disassemble_op(stream, "ifbit", reg, src, imm, indir, idx, false);
- break;
-
- case 0x3b:
- util::stream_format(stream, "%-8sA", "swap");
- break;
-
- case 0x3c:
- stream << "ret";
- bytes |= STEP_OUT;
- break;
-
- case 0x3d:
- stream << "retsk";
- bytes |= STEP_OUT;
- break;
-
- case 0x3e:
- stream << "reti";
- bytes |= STEP_OUT;
- break;
-
- case 0x3f:
- util::stream_format(stream, "%-8s", "pop");
- format_register(stream, src);
- break;
-
- case 0x40:
- stream << "nop";
- break;
-
- case 0x41: case 0x42: case 0x43:
- case 0x44: case 0x45: case 0x46: case 0x47:
- case 0x48: case 0x49: case 0x4a: case 0x4b:
- case 0x4c: case 0x4d: case 0x4e: case 0x4f:
- case 0x50: case 0x51: case 0x52: case 0x53:
- case 0x54: case 0x55: case 0x56: case 0x57:
- case 0x58: case 0x59: case 0x5a: case 0x5b:
- case 0x5c: case 0x5d: case 0x5e: case 0x5f:
- case 0x60: case 0x61: case 0x62: case 0x63:
- case 0x64: case 0x65: case 0x66: case 0x67:
- case 0x68: case 0x69: case 0x6a: case 0x6b:
- case 0x6c: case 0x6d: case 0x6e: case 0x6f:
- case 0x70: case 0x71: case 0x72: case 0x73:
- case 0x74: case 0x75: case 0x76: case 0x77:
- case 0x78: case 0x79: case 0x7a: case 0x7b:
- case 0x7c: case 0x7d: case 0x7e: case 0x7f:
- util::stream_format(stream, "%-8s", "jp");
- if (jmp)
- util::stream_format(stream, "0%X", src);
- else
- stream << "???";
- break;
-
- case 0x88: case 0x8c:
- case 0x90: case 0x91: case 0x92: case 0x93:
- case 0x97:
- case 0xa8: case 0xac:
- case 0xb0: case 0xb1: case 0xb2: case 0xb3:
- case 0xb7:
- case 0xc4:
- case 0xd4:
- case 0xe4:
- case 0xf4:
- disassemble_op(stream, "ld", reg, src, imm, indir, idx, BIT(opcode, 5));
- break;
-
- case 0x89:
- case 0xa9:
- disassemble_unary_op(stream, "inc", reg, src, indir, idx, BIT(opcode, 5));
- break;
-
- case 0x8a:
- case 0xaa:
- disassemble_unary_op(stream, "decsz", reg, src, indir, idx, BIT(opcode, 5));
- bytes |= STEP_OVER | (1 << OVERINSTSHIFT);
- break;
-
- case 0x8b:
- case 0xab:
- case 0xc6:
- case 0xd6:
- case 0xe6:
- case 0xf6:
- disassemble_op(stream, dmode ? "ld" : "st", reg, src, imm, indir, idx, BIT(opcode, 5));
- break;
-
- case 0x8d:
- util::stream_format(stream, "%-8sBK,", "ld");
- format_immediate_byte(stream, src);
- stream << ",";
- format_immediate_byte(stream, reg);
- break;
-
- case 0x8e:
- case 0xae:
- case 0xc5:
- case 0xd5:
- case 0xe5:
- case 0xf5:
- disassemble_op(stream, "x", reg, src, imm, indir, idx, BIT(opcode, 5));
- break;
-
- case 0x94: case 0x95:
- util::stream_format(stream, "%-8s", "jp");
- if (jmp)
- util::stream_format(stream, "0%X", src);
- else
- stream << "???";
- break;
-
- case 0x98: case 0xb8: case 0xd8: case 0xf8:
- disassemble_op(stream, "add", reg, src, imm, indir, idx, BIT(opcode, 5));
- break;
-
- case 0x99: case 0xb9: case 0xd9: case 0xf9:
- disassemble_op(stream, "and", reg, src, imm, indir, idx, BIT(opcode, 5));
- break;
-
- case 0x9a: case 0xba: case 0xda: case 0xfa:
- disassemble_op(stream, "or", reg, src, imm, indir, idx, BIT(opcode, 5));
- break;
-
- case 0x9b: case 0xbb: case 0xdb: case 0xfb:
- disassemble_op(stream, "xor", reg, src, imm, indir, idx, BIT(opcode, 5));
- break;
-
- case 0x9c: case 0xbc: case 0xdc: case 0xfc:
- disassemble_op(stream, "ifeq", reg, src, imm, indir, idx, BIT(opcode, 5));
- break;
-
- case 0x9d: case 0xbd: case 0xdd: case 0xfd:
- disassemble_op(stream, "ifgt", reg, src, imm, indir, idx, BIT(opcode, 5));
- break;
-
- case 0x9e: case 0xbe: case 0xde: case 0xfe:
- disassemble_op(stream, "mult", reg, src, imm, indir, idx, BIT(opcode, 5));
- break;
-
- case 0x9f: case 0xbf: case 0xdf: case 0xff:
- disassemble_op(stream, "div", reg, src, imm, indir, idx, BIT(opcode, 5));
- break;
-
- case 0xa7:
- util::stream_format(stream, "%-8sBK,", "ld");
- format_immediate_word(stream, src);
- stream << ",";
- format_immediate_word(stream, reg);
- break;
-
- case 0xaf:
- util::stream_format(stream, "%-8s", "push");
- format_register(stream, src);
- break;
-
- case 0xb4:
- util::stream_format(stream, "%-8s", "jmpl");
- if (jmp)
- util::stream_format(stream, "0%X", src);
- else
- stream << "???";
- break;
-
- case 0xb5:
- util::stream_format(stream, "%-8s", "jsrl");
- if (jmp)
- util::stream_format(stream, "0%X", src);
- else
- stream << "???";
- bytes |= STEP_OVER;
- break;
-
- case 0xc0: case 0xc2:
- case 0xe0: case 0xe2:
- util::stream_format(stream, "%-8sA,[B%c].%c", "lds",
- BIT(opcode, 1) ? '-' : '+',
- BIT(opcode, 5) ? 'w' : 'b');
- bytes |= STEP_OVER | (1 << OVERINSTSHIFT);
- break;
-
- case 0xd0: case 0xd2:
- case 0xf0: case 0xf2:
- util::stream_format(stream, "%-8sA,[X%c].%c", "ld",
- BIT(opcode, 1) ? '-' : '+',
- BIT(opcode, 5) ? 'w' : 'b');
- break;
-
- case 0xc1: case 0xc3:
- case 0xe1: case 0xe3:
- util::stream_format(stream, "%-8sA,[B%c].%c", "xs",
- BIT(opcode, 1) ? '-' : '+',
- BIT(opcode, 5) ? 'w' : 'b');
- bytes |= STEP_OVER | (1 << OVERINSTSHIFT);
- break;
-
- case 0xd1: case 0xd3:
- case 0xf1: case 0xf3:
- util::stream_format(stream, "%-8sA,[X%c].%c", "x",
- BIT(opcode, 1) ? '-' : '+',
- BIT(opcode, 5) ? 'w' : 'b');
- break;
-
- case 0xc7: case 0xe7:
- util::stream_format(stream, "%-8sA", BIT(opcode, 5) ? "shl" : "shr");
- break;
-
- case 0xd7: case 0xf7:
- util::stream_format(stream, "%-8sA", BIT(opcode, 5) ? "rlc" : "rrc");
- break;
-
- case 0xc8: case 0xe8:
- disassemble_op(stream, "adc", reg, src, imm, indir, idx, BIT(opcode, 5));
- break;
-
- case 0xc9: case 0xe9:
- disassemble_op(stream, "dadc", reg, src, imm, indir, idx, BIT(opcode, 5));
- break;
-
- case 0xca: case 0xea:
- disassemble_op(stream, "dsubc", reg, src, imm, indir, idx, BIT(opcode, 5));
- break;
-
- case 0xcb: case 0xeb:
- disassemble_op(stream, "subc", reg, src, imm, indir, idx, BIT(opcode, 5));
- break;
-
- case 0xcc: case 0xec:
- stream << "jid";
- if (BIT(opcode, 5))
- stream << "w";
- break;
-
- case 0xcf: case 0xef:
- disassemble_op(stream, "divd", reg, src, imm, indir, idx, BIT(opcode, 5));
- break;
-
- default:
- stream << "???";
- break;
- }
-
- return bytes | SUPPORTED;
-}
diff --git a/src/devices/cpu/hpc/hpcdasm.h b/src/devices/cpu/hpc/hpcdasm.h
deleted file mode 100644
index ed57c6b1a35..00000000000
--- a/src/devices/cpu/hpc/hpcdasm.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:AJR
-
-#ifndef MAME_CPU_HPC_HPCDASM_H
-#define MAME_CPU_HPC_HPCDASM_H
-
-#pragma once
-
-class hpc_disassembler : public util::disasm_interface
-{
-protected:
- enum : u16
- {
- REGISTER_A = 0x00c8,
- REGISTER_K = 0x00ca,
- REGISTER_B = 0x00cc,
- REGISTER_X = 0x00ce
- };
-
- // construction/destruction
- hpc_disassembler(const char *const regs[]);
-
- // disassembler overrides
- virtual u32 opcode_alignment() const override;
- virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params) override;
-
-private:
- // internal helpers
- void format_register(std::ostream &stream, u16 reg) const;
- void format_immediate_byte(std::ostream &stream, u8 data) const;
- void format_immediate_word(std::ostream &stream, u16 data) const;
- void disassemble_op(std::ostream &stream, const char *op, u16 reg, u16 src, bool imm, bool indir, bool idx, bool w) const;
- void disassemble_unary_op(std::ostream &stream, const char *op, u16 offset, u16 src, bool indir, bool idx, bool w) const;
- void disassemble_bit_op(std::ostream &stream, const char *op, u8 bit, u16 offset, u16 src, bool indir, bool idx) const;
-
- // register names
- const char *const *m_regs;
-};
-
-class hpc16083_disassembler : public hpc_disassembler
-{
-public:
- hpc16083_disassembler() : hpc_disassembler(s_regs) { }
-
-private:
- static const char *const s_regs[128];
-};
-
-class hpc16164_disassembler : public hpc_disassembler
-{
-public:
- hpc16164_disassembler() : hpc_disassembler(s_regs) { }
-
-private:
- static const char *const s_regs[128];
-};
-
-#endif // MAME_CPU_HPC_HPCDASM_H
diff --git a/src/devices/cpu/hphybrid/hphybrid.cpp b/src/devices/cpu/hphybrid/hphybrid.cpp
index b9e7da6cc4e..246804ec468 100644
--- a/src/devices/cpu/hphybrid/hphybrid.cpp
+++ b/src/devices/cpu/hphybrid/hphybrid.cpp
@@ -175,8 +175,6 @@ uint8_t hp_hybrid_cpu_device::pa_r() const
hp_hybrid_cpu_device::hp_hybrid_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint8_t addrwidth)
: cpu_device(mconfig, type, tag, owner, clock)
, m_pa_changed_func(*this)
- , m_opcode_func(*this)
- , m_stm_func(*this)
, m_addr_mask((1U << addrwidth) - 1)
, m_relative_mode(true)
, m_r_cycles(DEF_MEM_R_CYCLES)
@@ -243,8 +241,6 @@ void hp_hybrid_cpu_device::device_start()
set_icountptr(m_icount);
m_pa_changed_func.resolve_safe();
- m_opcode_func.resolve_safe();
- m_stm_func.resolve();
}
void hp_hybrid_cpu_device::device_reset()
@@ -264,7 +260,6 @@ void hp_hybrid_cpu_device::device_reset()
m_dmapa = 0;
m_dmama = 0;
m_dmac = 0;
- m_curr_cycle = 0;
m_forced_bsc_25 = m_boot_mode;
m_last_pa = ~0;
@@ -317,7 +312,7 @@ uint16_t hp_hybrid_cpu_device::execute_one(uint16_t opcode)
}
// Indirect addressing in EXE instruction seems to use AEC case A instead of case C
// (because it's an opcode fetch)
- return fetch_at(add_mae(AEC_CASE_A , fetch_addr));
+ return RM(add_mae(AEC_CASE_A , fetch_addr));
} else {
uint16_t next_P;
if (!execute_one_bpc(opcode , next_P) &&
@@ -957,11 +952,6 @@ uint16_t hp_hybrid_cpu_device::RM(uint32_t addr)
// Any access to internal registers removes forcing of BSC 2x
m_forced_bsc_25 = false;
- if (m_stm_func) {
- m_stm_func(m_curr_cycle | CYCLE_RAL_MASK | CYCLE_RD_MASK);
- m_curr_cycle = 0;
- }
-
// Memory mapped BPC registers
uint16_t tmp;
switch (addr_wo_bsc) {
@@ -1026,10 +1016,6 @@ uint16_t hp_hybrid_cpu_device::RM(uint32_t addr)
return tmp;
} else {
m_icount -= m_r_cycles;
- if (m_stm_func) {
- m_stm_func(m_curr_cycle | CYCLE_RD_MASK);
- m_curr_cycle = 0;
- }
return m_cache->read_word(addr);
}
}
@@ -1079,11 +1065,6 @@ void hp_hybrid_cpu_device::WM(uint32_t addr , uint16_t v)
// Any access to internal registers removes forcing of BSC 2x
m_forced_bsc_25 = false;
- if (m_stm_func) {
- m_stm_func(m_curr_cycle | CYCLE_RAL_MASK | CYCLE_WR_MASK);
- m_curr_cycle = 0;
- }
-
// Memory mapped BPC registers
switch (addr_wo_bsc) {
case HP_REG_A_ADDR:
@@ -1149,10 +1130,6 @@ void hp_hybrid_cpu_device::WM(uint32_t addr , uint16_t v)
m_icount -= REGISTER_RW_CYCLES;
} else {
m_icount -= m_w_cycles;
- if (m_stm_func) {
- m_stm_func(m_curr_cycle | CYCLE_WR_MASK);
- m_curr_cycle = 0;
- }
m_program->write_word(addr , v);
}
}
@@ -1191,15 +1168,7 @@ bool hp_hybrid_cpu_device::write_emc_reg(uint16_t addr , uint16_t v)
uint16_t hp_hybrid_cpu_device::fetch()
{
m_genpc = add_mae(AEC_CASE_A , m_reg_P);
- return fetch_at(m_genpc);
-}
-
-uint16_t hp_hybrid_cpu_device::fetch_at(uint32_t addr)
-{
- m_curr_cycle |= CYCLE_IFETCH_MASK;
- uint16_t opcode = RM(addr);
- m_opcode_func(opcode);
- return opcode;
+ return RM(m_genpc);
}
uint16_t hp_hybrid_cpu_device::get_indirect_target(uint32_t addr)
@@ -1617,10 +1586,6 @@ bool hp_5061_3011_cpu_device::execute_no_bpc(uint16_t opcode , uint16_t& next_pc
// 16 bits units.
WM(tmp_addr >> 1 , tmp);
} else {
- if (m_stm_func) {
- m_stm_func(m_curr_cycle | CYCLE_WR_MASK);
- m_curr_cycle = 0;
- }
// Extend address, form byte address
uint16_t mask = BIT(tmp_addr , 0) ? 0x00ff : 0xff00;
tmp_addr = add_mae(AEC_CASE_C , tmp_addr >> 1);
@@ -1709,7 +1674,6 @@ void hp_5061_3011_cpu_device::handle_dma()
bool tc = BIT(--m_dmac , 15) != 0;
uint16_t tmp;
- m_curr_cycle |= CYCLE_DMA_MASK;
// Timing here assumes that DMA transfers are isolated and not done in bursts
if (BIT(m_flags , HPHYBRID_DMADIR_BIT)) {
// "Outward" DMA: memory -> peripheral
@@ -1991,10 +1955,6 @@ bool hp_09825_67907_cpu_device::execute_no_bpc(uint16_t opcode , uint16_t& next_
// 16 bits units.
WM(tmp_addr , tmp);
} else {
- if (m_stm_func) {
- m_stm_func(m_curr_cycle | CYCLE_WR_MASK);
- m_curr_cycle = 0;
- }
uint16_t mask = BIT(*ptr_reg , 15) ? 0xff00 : 0x00ff;
m_program->write_word(tmp_addr , tmp , mask);
m_icount -= m_w_cycles;
@@ -2077,7 +2037,6 @@ void hp_09825_67907_cpu_device::handle_dma()
uint16_t tmp;
// Timing here assumes that DMA transfers are isolated and not done in bursts
- m_curr_cycle |= CYCLE_DMA_MASK;
if (BIT(m_dmama , 15)) {
// "Outward" DMA: memory -> peripheral
tmp = RM(AEC_CASE_D , m_dmama);
diff --git a/src/devices/cpu/hphybrid/hphybrid.h b/src/devices/cpu/hphybrid/hphybrid.h
index 5059e114bb7..5d29f77b515 100644
--- a/src/devices/cpu/hphybrid/hphybrid.h
+++ b/src/devices/cpu/hphybrid/hphybrid.h
@@ -64,29 +64,6 @@ public:
void set_relative_mode(bool rela) { m_relative_mode = rela; }
void set_rw_cycles(unsigned read_cycles , unsigned write_cycles) { m_r_cycles = read_cycles; m_w_cycles = write_cycles; }
- // Possible combinations:
- // 00 No r/w cycle in progress
- // 01 Non-ifetch rd cycle
- // 05 Ifetch rd cycle
- // 09 DMA rd cycle
- // 02 Wr cycle
- // 0a DMA wr cycle
- //
- // CYCLE_RAL_MASK is set when access is into register space [0..1f]
- enum : uint8_t {
- CYCLE_RD_MASK = 0x01,
- CYCLE_WR_MASK = 0x02,
- CYCLE_IFETCH_MASK = 0x04,
- CYCLE_DMA_MASK = 0x08,
- CYCLE_RAL_MASK = 0x10
- };
-
- // Called at start of each memory access
- auto stm_cb() { return m_stm_func.bind(); }
-
- // Tap into fetched opcodes
- auto opcode_cb() { return m_opcode_func.bind(); }
-
protected:
hp_hybrid_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint8_t addrwidth);
@@ -146,7 +123,6 @@ protected:
void WIO(uint8_t pa , uint8_t ic , uint16_t v);
uint16_t fetch();
- uint16_t fetch_at(uint32_t addr);
virtual uint16_t get_indirect_target(uint32_t addr);
virtual void enter_isr();
virtual void handle_dma() = 0;
@@ -157,8 +133,6 @@ protected:
devcb_write8 m_pa_changed_func;
uint8_t m_last_pa;
- devcb_write16 m_opcode_func;
- devcb_write8 m_stm_func;
int m_icount;
uint32_t m_addr_mask;
@@ -185,8 +159,6 @@ protected:
uint16_t m_dmac; // DMA counter
uint16_t m_reg_I; // Instruction register
uint32_t m_genpc; // Full PC
- uint8_t m_curr_cycle; // Current cycle type
-
// EMC registers
uint16_t m_reg_ar2[ 4 ]; // AR2 register
uint16_t m_reg_se; // SE register (4 bits)
diff --git a/src/devices/cpu/i386/cache.h b/src/devices/cpu/i386/cache.h
deleted file mode 100644
index a04f2cacf2e..00000000000
--- a/src/devices/cpu/i386/cache.h
+++ /dev/null
@@ -1,258 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Samuele Zannoli
-
-#ifndef MAME_CPU_I386_CACHE_H
-#define MAME_CPU_I386_CACHE_H
-
-#pragma once
-
-/* To test it outside of Mame
-#include <cstdlib>
-
-typedef unsigned char u8;
-typedef unsigned int u32;
-*/
-
-enum {
- CacheLineBytes16 = 4,
- CacheLineBytes32 = 5,
- CacheLineBytes64 = 6,
- CacheLineBytes128 = 7,
- CacheLineBytes256 = 8,
-};
-
-enum {
- CacheDirectMapped = 0,
- Cache2Way = 1,
- Cache4Way = 2,
- Cache8Way = 3,
- Cache16Way = 4
-};
-
-enum {
- CacheRead = 0,
- CacheWrite = 1
-};
-
-template<int TagBits, int SetBits, int WayBits, int LineBits>
-class cpucache {
-public:
- // Constructor
- cpucache();
- // Reset the cache
- void reset();
- // Find the cacheline containing data at address
- template <int ReadWrite> u8* search(u32 address);
- // Allocate a cacheline for data at address
- template <int ReadWrite> bool allocate(u32 address, u8 **data);
- // Get the address where the cacheline data should be written back to
- u32 old();
- // Get the address of the first byte of the cacheline that contains data at address
- u32 base(u32 address);
- // Compose the cacheline parameters into an address
- u32 address(u32 tag, u32 set, u32 offset);
- // Get the data of the first cacheline marked as dirty
- u8* first_dirty(u32 &base, bool clean);
- // Get the data of the next cacheline marked as dirty
- u8* next_dirty(u32 &base, bool clean);
-
-private:
- static const int Ways = 1 << WayBits;
- static const int LineBytes = 1 << LineBits;
- static const int Sets = 1 << SetBits;
- static const u32 LineMask = (1 << LineBits) - 1;
- static const u32 SetMask = ((1 << SetBits) - 1) << LineBits;
- static const u32 WayMask = (1 << WayBits) - 1;
- static const int TagShift = LineBits + SetBits;
-
- struct cacheline {
- u8 data[LineBytes];
- bool allocated;
- bool dirty;
- u32 tag;
- u32 debug_address;
- };
-
- struct cacheset {
- cacheline lines[Ways];
- int nextway;
- };
-
- cacheset sets[Sets];
- u32 writeback_base;
- int last_set;
- int last_way;
-};
-
-template<int TagBits, int SetBits, int WayBits, int LineBits>
-cpucache<TagBits, SetBits, WayBits, LineBits>::cpucache()
-{
- reset();
-}
-
-template<int TagBits, int SetBits, int WayBits, int LineBits>
-void cpucache<TagBits, SetBits, WayBits, LineBits>::reset()
-{
- for (int s = 0; s < Sets; s++)
- for (int w = 0; w < Ways; w++)
- {
- sets[s].nextway = 0;
- sets[s].lines[w].allocated = false;
- sets[s].lines[w].dirty = false;
- sets[s].lines[w].debug_address = 0;
- }
- last_set = -1;
- last_way = -1;
-}
-
-template<int TagBits, int SetBits, int WayBits, int LineBits>
-template<int ReadWrite>
-u8* cpucache<TagBits, SetBits, WayBits, LineBits>::search(u32 address)
-{
- const int addresset = (address & SetMask) >> LineBits;
- const int addrestag = address >> TagShift;
-
- for (int w = 0; w < Ways; w++)
- if ((sets[addresset].lines[w].allocated) && (sets[addresset].lines[w].tag == addrestag))
- {
- if (ReadWrite != 0)
- sets[addresset].lines[w].dirty = true;
- return sets[addresset].lines[w].data;
- }
- return nullptr;
-}
-
-template<int TagBits, int SetBits, int WayBits, int LineBits>
-template<int ReadWrite>
-bool cpucache<TagBits, SetBits, WayBits, LineBits>::allocate(u32 address, u8 **data)
-{
- const int addresset = (address & SetMask) >> LineBits;
- const int addrestag = address >> TagShift;
- const int victimway = sets[addresset].nextway;
- bool old_allocated, old_dirty;
- bool ret;
-
- sets[addresset].nextway = (victimway + 1) & WayMask; // decide wich way will be allocated next
- old_allocated = sets[addresset].lines[victimway].allocated;
- old_dirty = sets[addresset].lines[victimway].dirty;
- writeback_base = (sets[addresset].lines[victimway].tag << TagShift) | (address & SetMask);
- sets[addresset].lines[victimway].tag = addrestag;
- sets[addresset].lines[victimway].allocated = true;
- if (ReadWrite == 0)
- sets[addresset].lines[victimway].dirty = false; // caller must write back the cacheline if told so
- else
- sets[addresset].lines[victimway].dirty = true; // line is allocated to write into it
- *data = sets[addresset].lines[victimway].data;
- sets[addresset].lines[victimway].debug_address = address;
- ret = old_allocated; // ret = old_allocated && old_dirty
- if (!old_dirty)
- ret = false;
- return ret; // true if caller must write back the cacheline
-}
-
-template<int TagBits, int SetBits, int WayBits, int LineBits>
-u32 cpucache<TagBits, SetBits, WayBits, LineBits>::old()
-{
- return writeback_base;
-}
-
-template<int TagBits, int SetBits, int WayBits, int LineBits>
-u32 cpucache<TagBits, SetBits, WayBits, LineBits>::base(u32 address)
-{
- return address & ~LineMask;
-}
-
-template<int TagBits, int SetBits, int WayBits, int LineBits>
-u32 cpucache<TagBits, SetBits, WayBits, LineBits>::address(u32 tag, u32 set, u32 offset)
-{
- return (tag << TagShift) | (set << LineBits) | offset;
-}
-
-template<int TagBits, int SetBits, int WayBits, int LineBits>
-u8* cpucache<TagBits, SetBits, WayBits, LineBits>::first_dirty(u32 &base, bool clean)
-{
- for (int s = 0; s < Sets; s++)
- for (int w = 0; w < Ways; w++)
- if (sets[s].lines[w].dirty == true)
- {
- if (clean)
- sets[s].lines[w].dirty = false;
- last_set = s;
- last_way = w;
- base = address(sets[s].lines[w].tag, s, 0);
- return sets[s].lines[w].data;
- }
- return nullptr;
-}
-
-template<int TagBits, int SetBits, int WayBits, int LineBits>
-u8* cpucache<TagBits, SetBits, WayBits, LineBits>::next_dirty(u32 &base, bool clean)
-{
- if (last_set < 0)
- return nullptr;
- while (true)
- {
- last_way++;
- if (last_way == Ways)
- {
- last_way = 0;
- last_set++;
- if (last_set == Sets)
- {
- last_set = -1;
- last_way = -1;
- return nullptr;
- }
- }
- if (sets[last_set].lines[last_way].dirty == true)
- {
- if (clean)
- sets[last_set].lines[last_way].dirty = false;
- base = address(sets[last_set].lines[last_way].tag, last_set, 0);
- return sets[last_set].lines[last_way].data;
- }
- }
-}
-
-#endif
-
-/* To test it outside of Mame
-const int memorysize = 256 * 1024;
-u8 memory[memorysize];
-
-void readline(u8 *data, u32 address)
-{
- for (int n = 0; n < 64; n++)
- data[n] = memory[address + n];
-}
-
-void writeline(u8 *data, u32 address)
-{
- for (int n = 0; n < 64; n++)
- memory[address + n] = data[n];
-}
-
-void cache_tester()
-{
- cpucache<18, 8, 6, 2> cache;
- bool r;
- u8 *data;
- int address;
- u8 value;
-
- for (int n = 0; n < memorysize; n++)
- memory[n] = 0xaa ^ n;
- address = std::rand() & (memorysize - 1);
- r = cache.search(address, &data);
- if (r == false)
- {
- r = cache.allocate(address, &data);
- if (r == true)
- writeline(data, cache.base(address));
- readline(data, cache.base(address));
- }
- value = data[address & 63];
- if (value != memory[address])
- printf("Error reading address %d\n\r", address);
-}
-*/
diff --git a/src/devices/cpu/i386/cpuidmsrs.hxx b/src/devices/cpu/i386/cpuidmsrs.hxx
index 842ff85b4b2..e7abcf27154 100644
--- a/src/devices/cpu/i386/cpuidmsrs.hxx
+++ b/src/devices/cpu/i386/cpuidmsrs.hxx
@@ -1,5 +1,3 @@
-// license:BSD-3-Clause
-// copyright-holders:Ville Linde, Barry Rodewald, Carl, Philip Bennett, Samuele Zannoli
uint64_t pentium_device::opcode_rdmsr(bool &valid_msr)
{
@@ -255,85 +253,49 @@ void athlonxp_device::opcode_cpuid()
uint64_t athlonxp_device::opcode_rdmsr(bool &valid_msr)
{
- uint64_t ret;
uint32_t offset = REG32(ECX);
- ret = 0;
switch (offset)
{
case 0x10: // TSC
break;
case 0x1b: // APIC_BASE
break;
- case 0xfe: // MTRRcap
- // 7-0 MTRRCapVCnt - Number of variable range MTRRs (8)
- // 8 MtrrCapFix - Fixed range MTRRs available (1)
- // 10 MtrrCapWc - Write combining memory type available (1)
- ret = 0x508;
- break;
case 0x17b: // MCG_CTL
break;
case 0x200: // MTRRphysBase0-7
- case 0x202:
- case 0x204:
- case 0x206:
- case 0x208:
- case 0x20a:
- case 0x20c:
- case 0x20e:
- // 7-0 Type - Memory type for this memory range
- // 39-12 PhyBase27-0 - Base address for this memory range
- /* Format of type field:
- Bits 2-0 specify the memory type with the following encoding
- 0 UC Uncacheable
- 1 WC Write Combining
- 4 WT Write Through
- 5 WP Write Protect
- 6 WB Write Back
- 7 UC Uncacheable used only in PAT register
- Bit 3 WrMem 1 write to memory 0 write to mmio, present only in fixed range MTRRs
- Bit 4 RdMem 1 read from memory 0 read from mmio, present only in fixed range MTRRs
- Other bits are unused
- */
- break;
case 0x201: // MTRRphysMask0-7
+ case 0x202:
case 0x203:
+ case 0x204:
case 0x205:
+ case 0x206:
case 0x207:
+ case 0x208:
case 0x209:
+ case 0x20a:
case 0x20b:
+ case 0x20c:
case 0x20d:
+ case 0x20e:
case 0x20f:
- // 11 Valid - Memory range active
- // 39-12 PhyMask27-0 - Address mask
break;
case 0x2ff: // MTRRdefType
- // 7-0 MtrrDefMemType - Default memory type
- // 10 MtrrDefTypeFixEn - Enable fixed range MTRRs
- // 11 MtrrDefTypeEn - Enable MTRRs
break;
case 0x250: // MTRRfix64K_00000
- // 8 bits for each 64k block starting at address 0
- ret = m_msr_mtrrfix[0];
break;
case 0x258: // MTRRfix16K_80000
- // 8 bits for each 16k block starting at address 0x80000
- ret = m_msr_mtrrfix[1];
break;
case 0x259: // MTRRfix16K_A0000
- // 8 bits for each 16k block starting at address 0xa0000
- ret = m_msr_mtrrfix[2];
- break;
- case 0x268: // MTRRfix4K_C0000
- case 0x269: // MTRRfix4K_C8000
- case 0x26a: // MTRRfix4K_D0000
- case 0x26b: // MTRRfix4K_D8000
- case 0x26c: // MTRRfix4K_E0000
- case 0x26d: // MTRRfix4K_E8000
- case 0x26e: // MTRRfix4K_F0000
- case 0x26f: // MTRRfix4K_F8000
- // 8 bits for each 4k block
- ret = m_msr_mtrrfix[3 + offset - 0x268];
+ break;
+ case 0x268: // MTRRfix4K_C0000-F8000
+ case 0x269:
+ case 0x26a:
+ case 0x26b:
+ case 0x26c:
+ case 0x26d:
+ case 0x26e:
+ case 0x26f:
break;
case 0x400: // MC0_CTL
break;
@@ -344,25 +306,15 @@ uint64_t athlonxp_device::opcode_rdmsr(bool &valid_msr)
case 0x40c: // MC3_CTL
break;
case 0xC0010010: // SYS_CFG
- // 20 MtrrVarDramEn - Enable top of memory address and I/O range registers
- // 19 MtrrFixDramModEn - Enable modification of RdDram and WrDram bits in fixed MTRRs
- // 18 MtrrFixDramEn - Enable RdDram and WrDram attributes in fixed MTRRs
break;
case 0xC0010015: // HWCR
break;
- case 0xC0010016: // IORRBase0-1
+ case 0xC0010016: // IORRBase
+ case 0xC0010017: // IORRMask
case 0xC0010018:
- // 39-12 Base27-0 - Base address for this memory range
- // 4 RdDram - Read from DRAM
- // 3 WrDram - Write to DRAM
- break;
- case 0xC0010017: // IORRMask0-1
case 0xC0010019:
- // 39-12 Mask27-0 - Address mask
- // 11 V - Register enabled
break;
case 0xC001001A: // TOP_MEM
- // 39-23 TOM16-0 - Top of Memory, accesses from this address onward are directed to mmio
break;
case 0xC001001D: // TOP_MEM2
break;
@@ -370,7 +322,7 @@ uint64_t athlonxp_device::opcode_rdmsr(bool &valid_msr)
break;
}
valid_msr = true;
- return ret;
+ return 0;
}
void athlonxp_device::opcode_wrmsr(uint64_t data, bool &valid_msr)
@@ -403,16 +355,10 @@ void athlonxp_device::opcode_wrmsr(uint64_t data, bool &valid_msr)
case 0x2ff: // MTRRdefType
break;
case 0x250: // MTRRfix64K_00000
- m_msr_mtrrfix[0] = data;
- parse_mtrrfix(data, 0, 64);
break;
case 0x258: // MTRRfix16K_80000
- m_msr_mtrrfix[1] = data;
- parse_mtrrfix(data, 0x80000, 16);
break;
case 0x259: // MTRRfix16K_A0000
- m_msr_mtrrfix[2] = data;
- parse_mtrrfix(data, 0xa0000, 16);
break;
case 0x268: // MTRRfix4K_C0000-F8000
case 0x269:
@@ -422,8 +368,6 @@ void athlonxp_device::opcode_wrmsr(uint64_t data, bool &valid_msr)
case 0x26d:
case 0x26e:
case 0x26f:
- m_msr_mtrrfix[3 + offset - 0x268] = data;
- parse_mtrrfix(data, 0xc0000 + (offset - 0x268) * 0x8000, 4);
break;
case 0x400: // MC0_CTL
break;
diff --git a/src/devices/cpu/i386/i386.cpp b/src/devices/cpu/i386/i386.cpp
index f372dba1239..a4408c69175 100644
--- a/src/devices/cpu/i386/i386.cpp
+++ b/src/devices/cpu/i386/i386.cpp
@@ -3367,10 +3367,15 @@ void i386_device::i386_common_init()
m_program = &space(AS_PROGRAM);
if(m_program->data_width() == 16) {
- // for the 386sx
- macache16 = m_program->cache<1, 0, ENDIANNESS_LITTLE>();
+ auto cache = m_program->cache<1, 0, ENDIANNESS_LITTLE>();
+ m_pr8 = [cache](offs_t address) -> u8 { return cache->read_byte(address); };
+ m_pr16 = [cache](offs_t address) -> u16 { return cache->read_word(address); };
+ m_pr32 = [cache](offs_t address) -> u32 { return cache->read_dword(address); };
} else {
- macache32 = m_program->cache<2, 0, ENDIANNESS_LITTLE>();
+ auto cache = m_program->cache<2, 0, ENDIANNESS_LITTLE>();
+ m_pr8 = [cache](offs_t address) -> u8 { return cache->read_byte(address); };
+ m_pr16 = [cache](offs_t address) -> u16 { return cache->read_word(address); };
+ m_pr32 = [cache](offs_t address) -> u32 { return cache->read_dword(address); };
}
m_io = &space(AS_IO);
@@ -4721,10 +4726,6 @@ void athlonxp_device::device_reset()
m_cpuid_id2 = ('D' << 24) | ('M' << 16) | ('A' << 8) | 'c'; // cAMD
memset(m_processor_name_string, 0, 48);
strcpy((char *)m_processor_name_string, "AMD Athlon(tm) Processor");
- for (int n = 0; n < 11; n++)
- m_msr_mtrrfix[n] = 0;
- for (int n = 0; n < (1024 / 4); n++)
- m_memory_ranges_1m[n] = 0; // change the 0 to 6 to test the cache just after reset
m_cpuid_max_input_value_eax = 0x01;
m_cpu_version = REG32(EDX);
@@ -4735,227 +4736,6 @@ void athlonxp_device::device_reset()
CHANGE_PC(m_eip);
}
-void athlonxp_device::parse_mtrrfix(u64 mtrr, offs_t base, int kblock)
-{
- int nb = kblock / 4;
- int range = (int)(base >> 12); // base must never be higher than 1 megabyte
-
- for (int n = 0; n < 8; n++)
- {
- uint8_t type = mtrr & 0xff;
-
- for (int b = 0; b < nb; b++)
- {
- m_memory_ranges_1m[range] = type;
- range++;
- }
- mtrr = mtrr >> 8;
- }
-}
-
-int athlonxp_device::check_cacheable(offs_t address)
-{
- offs_t block;
- int disabled;
-
- disabled = 0;
- if (m_cr[0] & (1 << 30))
- disabled = 128;
- if (address >= 0x100000)
- return disabled;
- block = address >> 12;
- return m_memory_ranges_1m[block] | disabled;
-}
-
-template <class dt, offs_t xorle>
-dt athlonxp_device::opcode_read_cache(offs_t address)
-{
- int mode = check_cacheable(address);
- bool nocache = false;
- u8 *data;
-
- if ((mode & 7) == 0)
- nocache = true;
- if (mode & 1)
- nocache = true;
- if (nocache == false)
- {
- int offset = (address & 63) ^ xorle;
- data = cache.search<CacheRead>(address);
- if (data)
- return *(dt *)(data + offset);
- if (!(mode & 128))
- {
- bool dirty = cache.allocate<CacheRead>(address, &data);
- address = cache.base(address);
- if (dirty)
- {
- offs_t old_address = cache.old();
-
- for (int w = 0; w < 64; w += 4)
- macache32->write_dword(old_address + w, *(u32 *)(data + w));
- }
- for (int r = 0; r < 64; r += 4)
- *(u32 *)(data + r) = macache32->read_dword(address + r);
- return *(dt *)(data + offset);
- }
- else
- {
- if (sizeof(dt) == 1)
- return macache32->read_byte(address);
- else if (sizeof(dt) == 2)
- return macache32->read_word(address);
- else
- return macache32->read_dword(address);
- }
- }
- else
- {
- if (sizeof(dt) == 1)
- return macache32->read_byte(address);
- else if (sizeof(dt) == 2)
- return macache32->read_word(address);
- else
- return macache32->read_dword(address);
- }
-}
-
-template <class dt, offs_t xorle>
-dt athlonxp_device::program_read_cache(offs_t address)
-{
- int mode = check_cacheable(address);
- bool nocache = false;
- u8 *data;
-
- if ((mode & 7) == 0)
- nocache = true;
- if (mode & 1)
- nocache = true;
- if (nocache == false)
- {
- int offset = (address & 63) ^ xorle;
- data = cache.search<CacheRead>(address);
- if (data)
- return *(dt *)(data + offset);
- if (!(mode & 128))
- {
- bool dirty = cache.allocate<CacheRead>(address, &data);
- address = cache.base(address);
- if (dirty)
- {
- offs_t old_address = cache.old();
-
- for (int w = 0; w < 64; w += 4)
- m_program->write_dword(old_address + w, *(u32 *)(data + w));
- }
- for (int r = 0; r < 64; r += 4)
- *(u32 *)(data + r) = m_program->read_dword(address + r);
- return *(dt *)(data + offset);
- }
- else
- {
- if (sizeof(dt) == 1)
- return m_program->read_byte(address);
- else if (sizeof(dt) == 2)
- return m_program->read_word(address);
- else
- return m_program->read_dword(address);
- }
- }
- else
- {
- if (sizeof(dt) == 1)
- return m_program->read_byte(address);
- else if (sizeof(dt) == 2)
- return m_program->read_word(address);
- else
- return m_program->read_dword(address);
- }
-}
-
-template <class dt, offs_t xorle>
-void athlonxp_device::program_write_cache(offs_t address, dt data)
-{
- int mode = check_cacheable(address);
- bool nocache = false;
- u8 *dataw;
-
- if ((mode & 7) == 0)
- nocache = true;
- if (mode & 1)
- nocache = true;
- if (nocache == false)
- {
- int offset = (address & 63) ^ xorle;
- dataw = cache.search<CacheWrite>(address);
- if (dataw)
- {
- *(dt *)(dataw + offset) = data;
- return;
- }
- if (!(mode & 128))
- {
- bool dirty = cache.allocate<CacheWrite>(address, &dataw);
- address = cache.base(address);
- if (dirty)
- {
- offs_t old_address = cache.old();
-
- for (int w = 0; w < 64; w += 4)
- m_program->write_dword(old_address + w, *(u32 *)(dataw + w));
- }
- for (int r = 0; r < 64; r += 4)
- *(u32 *)(dataw + r) = m_program->read_dword(address + r);
- *(dt *)(dataw + offset) = data;
- }
- else
- {
- if (sizeof(dt) == 1)
- m_program->write_byte(address, data);
- else if (sizeof(dt) == 2)
- m_program->write_word(address, data);
- else
- m_program->write_dword(address, data);
- }
- }
- else
- {
- if (sizeof(dt) == 1)
- m_program->write_byte(address, data);
- else if (sizeof(dt) == 2)
- m_program->write_word(address, data);
- else
- m_program->write_dword(address, data);
- }
-}
-
-void athlonxp_device::invalidate_cache(bool writeback)
-{
- u32 base;
- u8 *data;
-
- data = cache.first_dirty(base, true);
- while (data != nullptr)
- {
- if (writeback)
- for (int w = 0; w < 64; w += 4)
- m_program->write_dword(base + w, *(u32 *)(data + w));
- data = cache.next_dirty(base, true);
- }
- cache.reset();
-}
-
-void athlonxp_device::opcode_invd()
-{
- invalidate_cache(false);
-}
-
-void athlonxp_device::opcode_wbinvd()
-{
- invalidate_cache(true);
-}
-
-
/*****************************************************************************/
/* Intel Pentium 4 */
diff --git a/src/devices/cpu/i386/i386.h b/src/devices/cpu/i386/i386.h
index 90aab9f0667..e7a460488c0 100644
--- a/src/devices/cpu/i386/i386.h
+++ b/src/devices/cpu/i386/i386.h
@@ -16,7 +16,6 @@
#include "divtlb.h"
#include "i386dasm.h"
-#include "cache.h"
#define INPUT_LINE_A20 1
#define INPUT_LINE_SMI 2
@@ -72,24 +71,10 @@ protected:
virtual int get_mode() const override;
// routines for opcodes whose operation can vary between cpu models
- // default implementations usually just log an error message
+ // default implementations just log an error message
virtual void opcode_cpuid();
virtual uint64_t opcode_rdmsr(bool &valid_msr);
virtual void opcode_wrmsr(uint64_t data, bool &valid_msr);
- virtual void opcode_invd() {}
- virtual void opcode_wbinvd() {}
-
- // routine to access memory
- virtual u8 mem_pr8(offs_t address) { return macache32->read_byte(address); }
- virtual u16 mem_pr16(offs_t address) { return macache32->read_word(address); }
- virtual u32 mem_pr32(offs_t address) { return macache32->read_dword(address); }
-
- virtual u8 mem_prd8(offs_t address) { return m_program->read_byte(address); }
- virtual u16 mem_prd16(offs_t address) { return m_program->read_word(address); }
- virtual u32 mem_prd32(offs_t address) { return m_program->read_dword(address); }
- virtual void mem_pwd8(offs_t address, u8 data) { m_program->write_byte(address, data); }
- virtual void mem_pwd16(offs_t address, u16 data) { m_program->write_word(address, data); }
- virtual void mem_pwd32(offs_t address, u32 data) { m_program->write_dword(address, data); }
address_space_config m_program_config;
address_space_config m_io_config;
@@ -295,10 +280,11 @@ protected:
uint8_t m_irq_state;
address_space *m_program;
+ std::function<u8 (offs_t)> m_pr8;
+ std::function<u16 (offs_t)> m_pr16;
+ std::function<u32 (offs_t)> m_pr32;
address_space *m_io;
uint32_t m_a20_mask;
- memory_access_cache<1, 0, ENDIANNESS_LITTLE> *macache16;
- memory_access_cache<2, 0, ENDIANNESS_LITTLE> *macache32;
int m_cpuid_max_input_value_eax; // Highest CPUID standard function available
uint32_t m_cpuid_id0, m_cpuid_id1, m_cpuid_id2;
@@ -1509,13 +1495,9 @@ class i386sx_device : public i386_device
public:
// construction/destruction
i386sx_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- virtual u8 mem_pr8(offs_t address) override { return macache16->read_byte(address); };
- virtual u16 mem_pr16(offs_t address) override { return macache16->read_word(address); };
- virtual u32 mem_pr32(offs_t address) override { return macache16->read_dword(address); };
};
+
class i486_device : public i386_device
{
public:
@@ -1632,34 +1614,10 @@ protected:
virtual void opcode_cpuid() override;
virtual uint64_t opcode_rdmsr(bool &valid_msr) override;
virtual void opcode_wrmsr(uint64_t data, bool &valid_msr) override;
- virtual void opcode_invd() override;
- virtual void opcode_wbinvd() override;
virtual void device_start() override;
virtual void device_reset() override;
- virtual u8 mem_pr8(offs_t address) override { return opcode_read_cache<u8, NATIVE_ENDIAN_VALUE_LE_BE(0, 3)>(address); }
- virtual u16 mem_pr16(offs_t address) override { return opcode_read_cache<u16, NATIVE_ENDIAN_VALUE_LE_BE(0, 2)>(address); }
- virtual u32 mem_pr32(offs_t address) override { return opcode_read_cache<u32, 0>(address); }
- virtual u8 mem_prd8(offs_t address) override { return program_read_cache<u8, NATIVE_ENDIAN_VALUE_LE_BE(0, 3)>(address); }
- virtual u16 mem_prd16(offs_t address) override { return program_read_cache<u16, NATIVE_ENDIAN_VALUE_LE_BE(0, 2)>(address); }
- virtual u32 mem_prd32(offs_t address) override { return program_read_cache<u32, 0>(address); }
- virtual void mem_pwd8(offs_t address, u8 data) override { program_write_cache<u8, NATIVE_ENDIAN_VALUE_LE_BE(0, 3)>(address, data); }
- virtual void mem_pwd16(offs_t address, u16 data) override { program_write_cache<u16, NATIVE_ENDIAN_VALUE_LE_BE(0, 2)>(address, data); }
- virtual void mem_pwd32(offs_t address, u32 data) override { program_write_cache<u32, 0>(address, data); }
-
-private:
- void parse_mtrrfix(u64 mtrr, offs_t base, int kblock);
- int check_cacheable(offs_t address);
- void invalidate_cache(bool writeback);
-
- template <class dt, offs_t xorle> dt opcode_read_cache(offs_t address);
- template <class dt, offs_t xorle> dt program_read_cache(offs_t address);
- template <class dt, offs_t xorle> void program_write_cache(offs_t address, dt data);
-
uint8_t m_processor_name_string[48];
- uint64_t m_msr_mtrrfix[11];
- uint8_t m_memory_ranges_1m[1024 / 4];
- cpucache<17, 9, Cache2Way, CacheLineBytes64> cache; // 512 sets, 2 ways (cachelines per set), 64 bytes per cacheline
};
diff --git a/src/devices/cpu/i386/i386priv.h b/src/devices/cpu/i386/i386priv.h
index 0343cf74ef1..954e49ee6c7 100644
--- a/src/devices/cpu/i386/i386priv.h
+++ b/src/devices/cpu/i386/i386priv.h
@@ -386,7 +386,7 @@ uint8_t i386_device::FETCH()
if(!translate_address(m_CPL,TRANSLATE_FETCH,&address,&error))
PF_THROW(error);
- value = mem_pr8(address & m_a20_mask);
+ value = m_pr8(address & m_a20_mask);
#ifdef DEBUG_MISSING_OPCODE
m_opcode_bytes[m_opcode_bytes_length] = value;
m_opcode_bytes_length = (m_opcode_bytes_length + 1) & 15;
@@ -407,7 +407,7 @@ uint16_t i386_device::FETCH16()
if(!translate_address(m_CPL,TRANSLATE_FETCH,&address,&error))
PF_THROW(error);
address &= m_a20_mask;
- value = mem_pr16(address);
+ value = m_pr16(address);
m_eip += 2;
m_pc += 2;
}
@@ -428,7 +428,7 @@ uint32_t i386_device::FETCH32()
PF_THROW(error);
address &= m_a20_mask;
- value = mem_pr32(address);
+ value = m_pr32(address);
m_eip += 4;
m_pc += 4;
}
@@ -443,7 +443,7 @@ uint8_t i386_device::READ8(uint32_t ea)
PF_THROW(error);
address &= m_a20_mask;
- return mem_prd8(address);
+ return m_program->read_byte(address);
}
uint16_t i386_device::READ16(uint32_t ea)
{
@@ -458,7 +458,7 @@ uint16_t i386_device::READ16(uint32_t ea)
PF_THROW(error);
address &= m_a20_mask;
- value = mem_prd16( address );
+ value = m_program->read_word( address );
}
return value;
}
@@ -477,7 +477,7 @@ uint32_t i386_device::READ32(uint32_t ea)
PF_THROW(error);
address &= m_a20_mask;
- value = mem_prd32( address );
+ value = m_program->read_dword( address );
}
return value;
}
@@ -501,8 +501,8 @@ uint64_t i386_device::READ64(uint32_t ea)
PF_THROW(error);
address &= m_a20_mask;
- value = (((uint64_t) mem_prd32( address+0 )) << 0);
- value |= (((uint64_t) mem_prd32( address+4 )) << 32);
+ value = (((uint64_t) m_program->read_dword( address+0 )) << 0);
+ value |= (((uint64_t) m_program->read_dword( address+4 )) << 32);
}
return value;
}
@@ -514,7 +514,7 @@ uint8_t i386_device::READ8PL0(uint32_t ea)
PF_THROW(error);
address &= m_a20_mask;
- return mem_prd8(address);
+ return m_program->read_byte(address);
}
uint16_t i386_device::READ16PL0(uint32_t ea)
{
@@ -529,7 +529,7 @@ uint16_t i386_device::READ16PL0(uint32_t ea)
PF_THROW(error);
address &= m_a20_mask;
- value = mem_prd16( address );
+ value = m_program->read_word( address );
}
return value;
}
@@ -549,7 +549,7 @@ uint32_t i386_device::READ32PL0(uint32_t ea)
PF_THROW(error);
address &= m_a20_mask;
- value = mem_prd32( address );
+ value = m_program->read_dword( address );
}
return value;
}
@@ -569,7 +569,7 @@ void i386_device::WRITE8(uint32_t ea, uint8_t value)
PF_THROW(error);
address &= m_a20_mask;
- mem_pwd8(address, value);
+ m_program->write_byte(address, value);
}
void i386_device::WRITE16(uint32_t ea, uint16_t value)
{
@@ -583,7 +583,7 @@ void i386_device::WRITE16(uint32_t ea, uint16_t value)
PF_THROW(error);
address &= m_a20_mask;
- mem_pwd16(address, value);
+ m_program->write_word(address, value);
}
}
void i386_device::WRITE32(uint32_t ea, uint32_t value)
@@ -600,7 +600,7 @@ void i386_device::WRITE32(uint32_t ea, uint32_t value)
PF_THROW(error);
ea &= m_a20_mask;
- mem_pwd32(address, value);
+ m_program->write_dword(address, value);
}
}
@@ -622,8 +622,8 @@ void i386_device::WRITE64(uint32_t ea, uint64_t value)
PF_THROW(error);
ea &= m_a20_mask;
- mem_pwd32(address+0, value & 0xffffffff);
- mem_pwd32(address+4, (value >> 32) & 0xffffffff);
+ m_program->write_dword(address+0, value & 0xffffffff);
+ m_program->write_dword(address+4, (value >> 32) & 0xffffffff);
}
}
diff --git a/src/devices/cpu/i386/i486ops.hxx b/src/devices/cpu/i386/i486ops.hxx
index 6946e463796..77e9ee3dd2d 100644
--- a/src/devices/cpu/i386/i486ops.hxx
+++ b/src/devices/cpu/i386/i486ops.hxx
@@ -44,15 +44,13 @@ void i386_device::i486_cpuid() // Opcode 0x0F A2
void i386_device::i486_invd() // Opcode 0x0f 08
{
- // TODO: manage the cache if present
- opcode_invd();
+ // Nothing to do ?
CYCLES(CYCLES_INVD);
}
void i386_device::i486_wbinvd() // Opcode 0x0f 09
{
- // TODO: manage the cache if present
- opcode_wbinvd();
+ // Nothing to do ?
}
void i386_device::i486_cmpxchg_rm8_r8() // Opcode 0x0f b0
@@ -235,8 +233,6 @@ void i386_device::i486_group0F01_16() // Opcode 0x0f 01
ea = GetEA(modrm,1);
}
WRITE16(ea, m_gdtr.limit);
- // Win32s requires all 32 bits to be stored here, despite various Intel docs
- // claiming that the upper 8 bits are either zeroed or undefined in 16-bit mode
WRITE32(ea + 2, m_gdtr.base);
CYCLES(CYCLES_SGDT);
break;
diff --git a/src/devices/cpu/i386/pentops.hxx b/src/devices/cpu/i386/pentops.hxx
index b44ce8c40ed..d5f6f6ca592 100644
--- a/src/devices/cpu/i386/pentops.hxx
+++ b/src/devices/cpu/i386/pentops.hxx
@@ -203,7 +203,6 @@ void i386_device::pentium_prefetch_m8() // Opcode 0x0f 18
{
uint8_t modrm = FETCH();
uint32_t ea = GetEA(modrm,0);
- // TODO: manage the cache if present
CYCLES(1+(ea & 1)); // TODO: correct cycle count
}
@@ -1046,7 +1045,7 @@ void i386_device::pentium_movnti_m16_r16() // Opcode 0f c3
// unsupported by cpu
CYCLES(1); // TODO: correct cycle count
} else {
- // TODO: manage the cache if present
+ // since cache is not implemented
uint32_t ea = GetEA(modrm, 0);
WRITE16(ea,LOAD_RM16(modrm));
CYCLES(1); // TODO: correct cycle count
@@ -1060,7 +1059,7 @@ void i386_device::pentium_movnti_m32_r32() // Opcode 0f c3
// unsupported by cpu
CYCLES(1); // TODO: correct cycle count
} else {
- // TODO: manage the cache if present
+ // since cache is not implemented
uint32_t ea = GetEA(modrm, 0);
WRITE32(ea,LOAD_RM32(modrm));
CYCLES(1); // TODO: correct cycle count
@@ -1117,7 +1116,7 @@ void i386_device::pentium_movntq_m64_r64() // Opcode 0f e7
if( modrm >= 0xc0 ) {
CYCLES(1); // unsupported
} else {
- // TODO: manage the cache if present
+ // since cache is not implemented
uint32_t ea = GetEA(modrm, 0);
WRITEMMX(ea, MMX((modrm >> 3) & 0x7));
CYCLES(1); // TODO: correct cycle count
@@ -3318,7 +3317,7 @@ void i386_device::sse_movntps_m128_r128() // Opcode 0f 2b
// unsupported by cpu
CYCLES(1); // TODO: correct cycle count
} else {
- // TODO: manage the cache if present
+ // since cache is not implemented
uint32_t ea = GetEA(modrm, 0);
WRITEXMM(ea, XMM((modrm >> 3) & 0x7));
CYCLES(1); // TODO: correct cycle count
@@ -5963,7 +5962,7 @@ void i386_device::sse_movntdq_m128_r128() // Opcode 66 0f e7
if( modrm >= 0xc0 ) {
CYCLES(1); // unsupported
} else {
- // TODO: manage the cache if present
+ // since cache is not implemented
uint32_t ea = GetEA(modrm, 0);
WRITEXMM(ea, XMM((modrm >> 3) & 0x7));
CYCLES(1); // TODO: correct cycle count
@@ -6277,7 +6276,7 @@ void i386_device::sse_movntpd_m128_r128() // Opcode 66 0f 2b
// unsupported by cpu
CYCLES(1); // TODO: correct cycle count
} else {
- // TODO: manage the cache if present
+ // since cache is not implemented
uint32_t ea = GetEA(modrm, 0);
WRITEXMM(ea, XMM((modrm >> 3) & 0x7));
CYCLES(1); // TODO: correct cycle count
diff --git a/src/devices/cpu/i8089/i8089.cpp b/src/devices/cpu/i8089/i8089.cpp
index 7e9371de36c..cf694d53cfb 100644
--- a/src/devices/cpu/i8089/i8089.cpp
+++ b/src/devices/cpu/i8089/i8089.cpp
@@ -16,7 +16,7 @@
// MACROS/CONSTANTS
//**************************************************************************
-#define VERBOSE 0
+#define VERBOSE 1
//**************************************************************************
diff --git a/src/devices/cpu/i8089/i8089_channel.cpp b/src/devices/cpu/i8089/i8089_channel.cpp
index 02bb12daa8c..433a3ca792c 100644
--- a/src/devices/cpu/i8089/i8089_channel.cpp
+++ b/src/devices/cpu/i8089/i8089_channel.cpp
@@ -20,7 +20,7 @@
// MACROS/CONSTANTS
//**************************************************************************
-#define VERBOSE 0
+#define VERBOSE 1
#define VERBOSE_DMA 0
// channel control register fields
@@ -374,10 +374,11 @@ int i8089_channel_device::execute_run()
// do we need to read another byte?
if (BIT(m_r[PSW].w, 1) && !BIT(m_r[PSW].w, 0) && !m_store_hi)
{
- m_store_hi = true;
-
if (CC_SYNC == 0x02)
+ {
+ m_store_hi = true;
m_dma_state = DMA_WAIT_FOR_DEST_DRQ;
+ }
else
m_dma_state = DMA_STORE_BYTE_HIGH;
}
diff --git a/src/devices/cpu/i86/i186.cpp b/src/devices/cpu/i86/i186.cpp
index 48329288bf5..7738ee64d6c 100644
--- a/src/devices/cpu/i86/i186.cpp
+++ b/src/devices/cpu/i86/i186.cpp
@@ -173,22 +173,6 @@ void i80186_cpu_device::execute_run()
{
while(m_icount > 0 )
{
- if((m_dma[0].drq_state && (m_dma[0].control & ST_STOP)) || (m_dma[1].drq_state && (m_dma[1].control & ST_STOP)))
- {
- int channel = m_last_dma ? 0 : 1;
- m_last_dma = !m_last_dma;
- if(!(m_dma[1].drq_state && (m_dma[1].control & ST_STOP)))
- channel = 0;
- else if(!(m_dma[0].drq_state && (m_dma[0].control & ST_STOP)))
- channel = 1;
- else if((m_dma[0].control & CHANNEL_PRIORITY) && !(m_dma[1].control & CHANNEL_PRIORITY))
- channel = 0;
- else if((m_dma[1].control & CHANNEL_PRIORITY) && !(m_dma[0].control & CHANNEL_PRIORITY))
- channel = 1;
- m_icount--;
- drq_callback(channel);
- continue;
- }
if ( m_seg_prefix_next )
{
m_seg_prefix = true;
@@ -603,18 +587,6 @@ void i80186_cpu_device::device_start()
state_add( I80186_T_COUNT + 2, "T2_COUNT", m_timer[2].count ).formatstr("%04X");
state_add( I80186_T_MAX_A + 2, "T2_MAX", m_timer[2].maxA ).formatstr("%04X");
state_add( I80186_T_CONTROL + 2, "T2_CONTROL", m_timer[2].control ).formatstr("%04X");
- state_add( I80186_ISR, "ISR", m_intr.in_service ).formatstr("%04X");
- state_add( I80186_IRR, "IRR", m_intr.request ).formatstr("%04X");
- state_add( I80186_PMR, "PMR", m_intr.priority_mask ).formatstr("%04X");
- state_add( I80186_ICSR, "ICSR", m_intr.status ).formatstr("%04X");
- state_add( I80186_TMRCR, "TMRCR", m_intr.timer ).formatstr("%04X");
- state_add( I80186_D0CR, "D0CR", m_intr.dma[0] ).formatstr("%04X");
- state_add( I80186_D1CR, "D1CR", m_intr.dma[1] ).formatstr("%04X");
- state_add( I80186_I0CR, "I0CR", m_intr.ext[0] ).formatstr("%04X");
- state_add( I80186_I1CR, "I1CR", m_intr.ext[1] ).formatstr("%04X");
- state_add( I80186_I2CR, "I2CR", m_intr.ext[2] ).formatstr("%04X");
- state_add( I80186_I3CR, "I3CR", m_intr.ext[3] ).formatstr("%04X");
- state_add( I80186_POLL, "POLL", m_intr.poll_status ).formatstr("%04X");
// register for savestates
save_item(NAME(m_timer[0].control));
@@ -655,7 +627,6 @@ void i80186_cpu_device::device_start()
save_item(NAME(m_mem.middle_size));
save_item(NAME(m_mem.peripheral));
save_item(NAME(m_reloc));
- save_item(NAME(m_last_dma));
// zerofill
memset(m_timer, 0, sizeof(m_timer));
diff --git a/src/devices/cpu/i86/i186.h b/src/devices/cpu/i86/i186.h
index a968f5ef3dd..01960a619f5 100644
--- a/src/devices/cpu/i86/i186.h
+++ b/src/devices/cpu/i86/i186.h
@@ -22,8 +22,8 @@ public:
auto tmrout1_handler() { return m_out_tmrout1_func.bind(); }
IRQ_CALLBACK_MEMBER(int_callback);
- DECLARE_WRITE_LINE_MEMBER(drq0_w) { m_dma[0].drq_state = state; }
- DECLARE_WRITE_LINE_MEMBER(drq1_w) { m_dma[1].drq_state = state; }
+ DECLARE_WRITE_LINE_MEMBER(drq0_w) { if(state) drq_callback(0); m_dma[0].drq_state = state; }
+ DECLARE_WRITE_LINE_MEMBER(drq1_w) { if(state) drq_callback(1); m_dma[1].drq_state = state; }
DECLARE_WRITE_LINE_MEMBER(tmrin0_w) { if(state && (m_timer[0].control & 0x8004) == 0x8004) { inc_timer(0); } }
DECLARE_WRITE_LINE_MEMBER(tmrin1_w) { if(state && (m_timer[1].control & 0x8004) == 0x8004) { inc_timer(1); } }
DECLARE_WRITE_LINE_MEMBER(int0_w) { external_int(0, state); }
@@ -46,12 +46,7 @@ protected:
I80186_T_COUNT = I80186_DMA_CR + 2,
I80186_T_MAX_A = I80186_T_COUNT + 3,
I80186_T_MAX_B = I80186_T_MAX_A + 3,
- I80186_T_CONTROL = I80186_T_MAX_B + 2,
- I80186_ISR = I80186_T_CONTROL + 3,
- I80186_IRR, I80186_PMR, I80186_ICSR,
- I80186_TMRCR, I80186_D0CR, I80186_D1CR,
- I80186_I0CR, I80186_I1CR, I80186_I2CR, I80186_I3CR,
- I80186_POLL
+ I80186_T_CONTROL = I80186_T_MAX_B + 2
};
i80186_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int data_bus_size);
@@ -137,7 +132,6 @@ private:
dma_state m_dma[2];
intr_state m_intr;
mem_state m_mem;
- bool m_last_dma;
static const device_timer_id TIMER_INT0 = 0;
static const device_timer_id TIMER_INT1 = 1;
diff --git a/src/devices/cpu/i86/i86.cpp b/src/devices/cpu/i86/i86.cpp
index 4f1d6f07afd..d578c6f3a2c 100644
--- a/src/devices/cpu/i86/i86.cpp
+++ b/src/devices/cpu/i86/i86.cpp
@@ -317,7 +317,7 @@ void i8086_cpu_device::execute_run()
case 0xdd:
case 0xde:
case 0xdf:
- m_esc_opcode_handler(m_pc);
+ m_esc_opcode_handler(m_pc - 1);
m_modrm = fetch();
if(m_modrm < 0xc0)
m_esc_data_handler(get_ea(1, I8086_READ));
diff --git a/src/devices/cpu/m6502/dxavix2000.lst b/src/devices/cpu/m6502/dxavix2000.lst
index fc2e7bde133..c96f6987dd5 100644
--- a/src/devices/cpu/m6502/dxavix2000.lst
+++ b/src/devices/cpu/m6502/dxavix2000.lst
@@ -6,7 +6,7 @@ bpl_rel xavora_idy phx_imp orapa_imp asr_zpx ora_zpx asl_zpx
jsr_adr xavand_idx callf_xa3 andj_imp bit_zpg and_zpg rol_zpg andk_imp plp_imp and_imm rol_acc andl_imp bit_aba and_aba rol_aba andm_imp
bmi_rel xavand_idy plx_imp andpa_imp bit_zpx and_zpx rol_zpx andpb_imp sec_imp and_aby bit_imm lpa0_imp bit_abx and_abx rol_abx lpb0_imp
rti_xav_imp xaveor_idx nop_imp eorj_imp nop_imp eor_zpg lsr_zpg eork_imp pha_imp eor_imm lsr_acc eorl_imp jmp_adr eor_aba lsr_aba eorm_imp
-bvc_rel xaveor_idy phy_imp eorpa_imp nop_imp eor_zpx lsr_zpx eorpb_imp cli_imp eor_aby nop_imp spa1_imp jmp_xa3 eor_abx lsr_abx spb1_imp
+bvc_rel xaveor_idy phy_imp eorpa_imp nop_imp eor_zpx lsr_zpx eorpb_imp cli_imp eor_aby nop_imp spa1_imp callf_aba eor_abx lsr_abx spb1_imp
rts_imp xavadc_idx nop_imp adcj_imp nop_imp adc_zpg ror_zpg adck_imp pla_imp adc_imm ror_acc adcl_imp jmp_ind adc_aba ror_aba adcm_imp
bvs_rel xavadc_idy ply_imp adcpa_imp nop_imp adc_zpx ror_zpx adcpb_imp sei_imp adc_aby nop_imp lpa1_imp jmpf_ind adc_abx ror_abx lpb1_imp
retf_imp xavsta_idx stz_zpg staj_imp sty_zpg sta_zpg stx_zpg stak_imp dey_imp sev_imp txa_imp stal_imp sty_aba sta_aba stx_aba stam_imp
diff --git a/src/devices/cpu/m6502/oxavix.lst b/src/devices/cpu/m6502/oxavix.lst
index 437a86ffc5f..38b8eadee1a 100644
--- a/src/devices/cpu/m6502/oxavix.lst
+++ b/src/devices/cpu/m6502/oxavix.lst
@@ -18,14 +18,6 @@ callf_xa3
set_codebank(TMP2);
prefetch();
-jmp_xa3
- TMP2 = read_pc();
- TMP = read_pc();
- TMP = set_h(TMP, read_pc());
- PC = TMP;
- set_codebank(TMP2);
- prefetch();
-
retf_imp
read_pc_noinc();
read(SP);
diff --git a/src/devices/cpu/m6502/oxavix2000.lst b/src/devices/cpu/m6502/oxavix2000.lst
index 3341c6eccf2..c51b0263e1a 100644
--- a/src/devices/cpu/m6502/oxavix2000.lst
+++ b/src/devices/cpu/m6502/oxavix2000.lst
@@ -448,12 +448,8 @@ asr_zpg
prefetch();
asr_aba
- TMP = read_pc();
- TMP = set_h(TMP, read_pc());
- TMP2 = read(TMP);
- write(TMP, TMP2);
- TMP2 = do_asr(TMP2); // used by xavbox, see 14e8
- write(TMP, TMP2);
+ fatalerror("unhandled opcode %02x%04x: %02x\n", m_codebank, PPC, inst_state);
+ read_pc_noinc();
prefetch();
asr_zpx
@@ -480,6 +476,11 @@ sev_imp
P |= F_V;
prefetch();
+callf_aba
+ fatalerror("unhandled opcode %02x%04x: %02x\n", m_codebank, PPC, inst_state);
+ read_pc_noinc();
+ prefetch();
+
jmpf_ind
TMP = read_pc();
TMP = set_h(TMP, read_pc());
diff --git a/src/devices/cpu/m6502/xavix.h b/src/devices/cpu/m6502/xavix.h
index 3e20ec8a899..9b28a429dad 100644
--- a/src/devices/cpu/m6502/xavix.h
+++ b/src/devices/cpu/m6502/xavix.h
@@ -15,6 +15,7 @@
class xavix_device : public m6502_device {
public:
xavix_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ xavix_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
virtual void do_exec_full() override;
@@ -24,7 +25,6 @@ public:
// xaviv opcodes
O(callf_xa3);
- O(jmp_xa3);
O(retf_imp);
O(brk_xav_imp);
O(rti_xav_imp);
@@ -101,8 +101,6 @@ protected:
uint8_t m_codebank;
uint32_t XPC;
- xavix_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
-
uint32_t adr_with_codebank(uint16_t adr) { return adr | (get_codebank() << 16); }
virtual void device_start() override;
diff --git a/src/devices/cpu/m6502/xavix2000.cpp b/src/devices/cpu/m6502/xavix2000.cpp
index 94b56308e0d..0c928ce159d 100644
--- a/src/devices/cpu/m6502/xavix2000.cpp
+++ b/src/devices/cpu/m6502/xavix2000.cpp
@@ -7,8 +7,8 @@
The dies for these are marked
SSD 2000 NEC 85605-621
-
- SSD 2002 NEC 85054-611
+ and possibly
+ SSD 2002 NEC 85054-611 (although this might use even more opcodes and need it's own file)
6502 with custom opcodes
integrated gfx / sound
@@ -17,12 +17,77 @@
see xavix.cpp for basic notes
- the 2000 chip has more opcodes than the 97/98 chips in xavix.cpp, and
- is a similar die structure to the 2002 chip, but doesn't seem to have any
- additional capabilities.
-
- the 2002 chip seems to be the one that was officially dubbed 'SuperXaviX'
- and has additional video capabilities on top of the extended opcodes.
+ the machines using the '2000' series chips seem to have more extra
+ opcodes, so presumably these were only available in those models.
+ of note, push x / push y and pull x / pull y
+
+ Dirt Rebel MX, which is confirmed as 2000 type however seems to require
+ some of the documented but 'undocumented' opcodes on the 6502 to have additonal
+ meaning for one specific function on startup
+
+ this just seems to be some very buggy checksum code where the games don't even care about the result...
+ (actually it looks like some games might be using it as a PRNG seed?)
+
+ a is 80 when entering here?
+
+ 01BC37: A0 3F ldy #$3f
+ 01BC39: B2 clr a // clear acculuator
+ 01BC3A: 1B spa0 a // store 'accumulator' into byte 0 of PA 'address' register
+ 01BC3B: 9B spa2 a // store 'accumulator' into byte 2 of PA 'address' register
+
+ -- loop point 2
+ 01BC3C: 98 tya // y -> a (3f on first run of loop)
+ 01BC3D: 5B spa1 a // store 'accumulator' into byte 1 of PA 'address' register (003f00 on first loop?)
+
+ -- loop point 1
+ 01BC3E: A3 ldal0 a // read byte 0 of 32-bit 'long' register into accumulator
+ 01BC3F: 73 adcpa // adc ($Address PA)
+ 01BC40: 83 stal0 a // store accumulator back in byte 0 of 32-bit 'long' register (even byte checksum?)
+ 01BC41: FB incpa // increase 'address' register PA
+ 01BC42: A7 ldal1 a // read byte 1 of 32-bit 'long' register into accumulator
+ 01BC43: 73 adcpa // adc ($Address PA)
+ 01BC44: 87 stal1 a // store accumulator back in byte 0 of 32-bit 'long' register (odd byte checksum?)
+ 01BC45: FB incpa // increase 'address' register PA
+ 01BC46: D0 F6 bne $1bc3e // (branch based on PA increase, so PA must set flags?, probably overflows after 0xffff if upper byte is 'bank'? or at 0xff if this really is a mirror of the function below
+
+ 01BC48: 88 dey // decrease y, which contained 3f at the start
+ 01BC49: 10 F1 bpl $1bc3c // branch back to loop point 2 to reload counter
+
+ // contains the odd byte checksum once we drop out the loop
+ 01BC4B: 8D FB 00 sta $00fb // store it in zero page memory
+ 01BC4E: A3 ldal0 a // get the even byte checksum from byte 0 of 32-bit 'long' register
+ 01BC4F: 8D FA 00 sta $00fa // store it in zero page memory
+ 01BC52: 07 oral1 a // why do we want to do this? (routine below does it too)
+ 01BC53: D0 03 bne $1bc58
+ 01BC55: CE FA 00 dec $00fa
+ 01BC58: 80 retf
+
+ this is presumably meant to be similar to the function found in Namco
+ Nostalgia 2
+
+ // A is 80 on entry
+ 09FFD8: A9 3F lda #$3f
+ 09FFDA: 85 01 sta $01 // set upper bit of pointer at 0x0000 to 3f (it completely fails to initialize the ram at 00, we currently init it to ff, but should probably be 0?)
+ 09FFDC: A0 00 ldy #$00 // clear inner loop counter
+ -- loop point 1 and 2
+ 09FFDE: AD FA 00 lda $00fa // read current even byte checksum value from zero page ram fa (game also completely fails to initialize this)
+ 09FFE1: 71 00 adc ($00), y // so 3f00 + y first outer loop, 3e00 + y second outer loop with y increasing in inner loop (add byte read to even checksum byte?)
+ 09FFE3: 8D FA 00 sta $00fa // store even checksum at 0xfa in zero page ram
+ 09FFE6: C8 iny // increase counter y
+ 09FFE7: AD FB 00 lda $00fb // read current odd byte checksum value from zero page ram fb (likewise never initialized!)
+ 09FFEA: 71 00 adc ($00), y // 3f00 + y (add byte read to odd checksum byte)
+ 09FFEC: 8D FB 00 sta $00fb // store odd checksum byte at 0xfb in zero page ram
+ 09FFEF: C8 iny // increase y
+ 09FFF0: D0 EC bne $9ffde // branch back if y hasn't overflowed (so work on 0x100 bytes, looping back 0x7f times)
+ 09FFF2: C6 01 dec $01 // decrease accumulator (started at 3f) (inner loop counter already 0 because it overflowed)
+ 09FFF4: 10 E8 bpl $9ffde // branch back
+
+ // checksums are already in place after loop so no need to copy them like in above
+ 09FFF6: 0D FA 00 ora $00fa // same weird 'or' call
+ --
+ 09FFF9: D0 03 bne $9fffe
+ 09FFFB: CE FA 00 dec $00fa
+ 09FFFE: 80 retf
***************************************************************************/
@@ -31,13 +96,10 @@
#include "xavix2000.h"
#include "xavix2000d.h"
-DEFINE_DEVICE_TYPE(XAVIX2000, xavix2000_device, "xavix2000", "XaviX (SSD 2000)")
-DEFINE_DEVICE_TYPE(XAVIX2002, xavix2002_device, "xavix2002", "XaviX (SSD 2002) (SuperXaviX)")
-
-
+DEFINE_DEVICE_TYPE(XAVIX2000, xavix2000_device, "xavix2000", "XaviX (SSD 2000 / 2002)")
-xavix2000_device::xavix2000_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) :
- xavix_device(mconfig, type, tag, owner, clock)
+xavix2000_device::xavix2000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
+ xavix_device(mconfig, XAVIX2000, tag, owner, clock)
{
program_config.m_addr_width = 24;
program_config.m_logaddr_width = 24;
@@ -45,17 +107,6 @@ xavix2000_device::xavix2000_device(const machine_config &mconfig, device_type ty
sprogram_config.m_logaddr_width = 24;
}
-xavix2000_device::xavix2000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- xavix2000_device(mconfig, XAVIX2000, tag, owner, clock)
-{
-}
-
-xavix2002_device::xavix2002_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- xavix2000_device(mconfig, XAVIX2002, tag, owner, clock)
-{
-}
-
-
void xavix2000_device::device_start()
{
xavix_device::device_start();
diff --git a/src/devices/cpu/m6502/xavix2000.h b/src/devices/cpu/m6502/xavix2000.h
index 425c15c8816..6eec3db88d5 100644
--- a/src/devices/cpu/m6502/xavix2000.h
+++ b/src/devices/cpu/m6502/xavix2000.h
@@ -17,9 +17,6 @@ public:
xavix2000_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
-
-protected:
- xavix2000_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
virtual void do_exec_full() override;
virtual void do_exec_partial() override;
@@ -139,6 +136,7 @@ protected:
O(cmc_imp);
O(sev_imp);
+ O(callf_aba);
O(jmpf_ind);
#undef O
@@ -162,13 +160,6 @@ enum {
SXAVIX_PB
};
-class xavix2002_device : public xavix2000_device {
-public:
- xavix2002_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-};
-
-
DECLARE_DEVICE_TYPE(XAVIX2000, xavix2000_device)
-DECLARE_DEVICE_TYPE(XAVIX2002, xavix2002_device)
#endif // MAME_CPU_M6502_XAVIX2000_H
diff --git a/src/devices/cpu/m68000/m68000.h b/src/devices/cpu/m68000/m68000.h
index 0ee41f348b5..0596dd07976 100644
--- a/src/devices/cpu/m68000/m68000.h
+++ b/src/devices/cpu/m68000/m68000.h
@@ -148,7 +148,6 @@ public:
void set_tas_write_callback(write8_delegate callback);
uint16_t get_fc();
void set_hmmu_enable(int enable);
- int get_pmmu_enable() {return m_pmmu_enabled;};
void set_fpu_enable(int enable);
void set_buserror_details(uint32_t fault_addr, uint8_t rw, uint8_t fc);
@@ -350,8 +349,6 @@ protected:
#include "m68kops.h"
#include "m68kfpu.hxx"
#include "m68kmmu.h"
-
- virtual void m68k_reset_peripherals() { }
};
@@ -378,6 +375,21 @@ protected:
const device_type type, uint32_t prg_data_width, uint32_t prg_address_bits, address_map_constructor internal_map);
};
+class m68301_device : public m68000_base_device
+{
+public:
+ // construction/destruction
+ m68301_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
+
+ virtual uint32_t execute_min_cycles() const override { return 4; };
+ virtual uint32_t execute_max_cycles() const override { return 158; };
+
+ // device-level overrides
+ virtual void device_start() override;
+};
+
@@ -635,6 +647,7 @@ public:
DECLARE_DEVICE_TYPE(M68000, m68000_device)
+DECLARE_DEVICE_TYPE(M68301, m68301_device)
DECLARE_DEVICE_TYPE(M68008, m68008_device)
DECLARE_DEVICE_TYPE(M68008PLCC, m68008plcc_device)
DECLARE_DEVICE_TYPE(M68010, m68010_device)
diff --git a/src/devices/cpu/m68000/m68k_in.cpp b/src/devices/cpu/m68000/m68k_in.cpp
index 0eed7fbe629..b5751811530 100644
--- a/src/devices/cpu/m68000/m68k_in.cpp
+++ b/src/devices/cpu/m68000/m68k_in.cpp
@@ -8286,7 +8286,6 @@ M68KMAKE_OP(reset, 0, ., .)
{
if (!m_reset_instr_callback.isnull())
(m_reset_instr_callback)(1);
- m68k_reset_peripherals();
m_remaining_cycles -= m_cyc_reset;
return;
}
diff --git a/src/devices/cpu/m68000/m68kcpu.cpp b/src/devices/cpu/m68000/m68kcpu.cpp
index 851c27163ea..e875b377af3 100644
--- a/src/devices/cpu/m68000/m68kcpu.cpp
+++ b/src/devices/cpu/m68000/m68kcpu.cpp
@@ -2019,6 +2019,11 @@ std::unique_ptr<util::disasm_interface> m68000_device::create_disassembler()
return std::make_unique<m68k_disassembler>(m68k_disassembler::TYPE_68000);
}
+std::unique_ptr<util::disasm_interface> m68301_device::create_disassembler()
+{
+ return std::make_unique<m68k_disassembler>(m68k_disassembler::TYPE_68000);
+}
+
std::unique_ptr<util::disasm_interface> m68008_device::create_disassembler()
{
return std::make_unique<m68k_disassembler>(m68k_disassembler::TYPE_68008);
@@ -2357,6 +2362,7 @@ device_memory_interface::space_config_vector m68000_base_device::memory_space_co
DEFINE_DEVICE_TYPE(M68000, m68000_device, "m68000", "Motorola MC68000")
+DEFINE_DEVICE_TYPE(M68301, m68301_device, "m68301", "Motorola MC68301")
DEFINE_DEVICE_TYPE(M68008, m68008_device, "m68008", "Motorola MC68008")
DEFINE_DEVICE_TYPE(M68008PLCC, m68008plcc_device, "m68008plcc", "Motorola MC68008PLCC")
DEFINE_DEVICE_TYPE(M68010, m68010_device, "m68010", "Motorola MC68010")
@@ -2399,6 +2405,21 @@ m68000_device::m68000_device(const machine_config &mconfig, const char *tag, dev
+m68301_device::m68301_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : m68000_base_device(mconfig, tag, owner, clock, M68301, 16,24)
+{
+}
+
+
+void m68301_device::device_start()
+{
+ init_cpu_m68000();
+}
+
+
+
+
+
/* m68008_device */
diff --git a/src/devices/cpu/m68000/m68kmmu.h b/src/devices/cpu/m68000/m68kmmu.h
index 99481039b0f..114d89ff5c1 100644
--- a/src/devices/cpu/m68000/m68kmmu.h
+++ b/src/devices/cpu/m68000/m68kmmu.h
@@ -33,7 +33,7 @@ static constexpr uint32_t M68K_MMU_DF_WP = 0x00000004;
static constexpr uint32_t M68K_MMU_DF_USED = 0x00000008;
static constexpr uint32_t M68K_MMU_DF_MODIFIED = 0x00000010;
static constexpr uint32_t M68K_MMU_DF_CI = 0x00000040;
-static constexpr uint32_t M68K_MMU_DF_SUPERVISOR = 0x00000100;
+static constexpr uint32_t M68K_MMU_DF_SUPERVISOR = 0000000100;
static constexpr uint32_t M68K_MMU_DF_ADDR_MASK = 0xfffffff0;
static constexpr uint32_t M68K_MMU_DF_IND_ADDR_MASK = 0xfffffffc;
diff --git a/src/devices/cpu/m6809/6x09dasm.cpp b/src/devices/cpu/m6809/6x09dasm.cpp
index bc366a567fe..9b7721ab268 100644
--- a/src/devices/cpu/m6809/6x09dasm.cpp
+++ b/src/devices/cpu/m6809/6x09dasm.cpp
@@ -214,10 +214,6 @@ offs_t m6x09_base_disassembler::disassemble(std::ostream &stream, offs_t pc, con
else if (numoperands == 2)
{
ea = params.r16(ppc);
- if( !(ea & 0xff00) )
- {
- stream << '>'; // need the '>' to force an assembler to use EXT addressing
- }
util::stream_format(stream, "$%04X", ea);
}
break;
@@ -234,7 +230,7 @@ offs_t m6x09_base_disassembler::disassemble(std::ostream &stream, offs_t pc, con
pb = params.r8(ppc);
}
- indexed(stream, pb, params, p);
+ indirect(stream, pb, params, p);
break;
case IMM:
@@ -814,10 +810,10 @@ m6x09_disassembler::m6x09_disassembler(m6x09_instruction_level level, const char
}
//-------------------------------------------------
-// indexed addressing mode for M6809/HD6309
+// indirect addressing mode for M6809/HD6309
//-------------------------------------------------
-void m6x09_disassembler::indexed(std::ostream &stream, uint8_t pb, const data_buffer &params, offs_t &p)
+void m6x09_disassembler::indirect(std::ostream &stream, uint8_t pb, const data_buffer &params, offs_t &p)
{
uint8_t reg = (pb >> 5) & 3;
uint8_t pbm = pb & 0x8f;
@@ -912,14 +908,16 @@ void m6x09_disassembler::indexed(std::ostream &stream, uint8_t pb, const data_bu
break;
case 0x8c: // (+/- 7 bit offset),PC
- offset = (int8_t)params.r8(p++);
- util::stream_format(stream, "$%04X,PCR", (p+offset)); // PC Relative addressing (assembler computes offset from specified absolute address)
+ offset = (int8_t)params.r8(p);
+ util::stream_format(stream, "%s", (offset < 0) ? "-" : "");
+ util::stream_format(stream, "$%02X,PC", (offset < 0) ? -offset : offset);
break;
case 0x8d: // (+/- 15 bit offset),PC
offset = (int16_t)params.r16(p);
p += 2;
- util::stream_format(stream, "$%04X,PCR", (p+offset)); // PC Relative addressing (assembler computes offset from specified absolute address)
+ util::stream_format(stream, "%s", (offset < 0) ? "-" : "");
+ util::stream_format(stream, "$%04X,PC", (offset < 0) ? -offset : offset);
break;
case 0x8e: // (+/- W),R
@@ -1242,10 +1240,10 @@ konami_disassembler::konami_disassembler() : m6x09_base_disassembler(konami_opco
}
//-------------------------------------------------
-// indexed addressing mode for Konami
+// indirect addressing mode for Konami
//-------------------------------------------------
-void konami_disassembler::indexed(std::ostream &stream, uint8_t mode, const data_buffer &params, offs_t &p)
+void konami_disassembler::indirect(std::ostream &stream, uint8_t mode, const data_buffer &params, offs_t &p)
{
static const char index_reg[8][3] =
{
diff --git a/src/devices/cpu/m6809/6x09dasm.h b/src/devices/cpu/m6809/6x09dasm.h
index e6320038b54..a14de7849c9 100644
--- a/src/devices/cpu/m6809/6x09dasm.h
+++ b/src/devices/cpu/m6809/6x09dasm.h
@@ -101,7 +101,7 @@ protected:
static const char *const hd6309_tfmregs[16];
static const char *const tfm_s[];
- virtual void indexed(std::ostream &stream, uint8_t pb, const data_buffer &params, offs_t &p) = 0;
+ virtual void indirect(std::ostream &stream, uint8_t pb, const data_buffer &params, offs_t &p) = 0;
virtual void register_register(std::ostream &stream, uint8_t pb) = 0;
private:
@@ -123,7 +123,7 @@ public:
m6x09_disassembler(m6x09_instruction_level level, const char teregs[16][4]);
protected:
- virtual void indexed(std::ostream &stream, uint8_t pb, const data_buffer &params, offs_t &p) override;
+ virtual void indirect(std::ostream &stream, uint8_t pb, const data_buffer &params, offs_t &p) override;
virtual void register_register(std::ostream &stream, uint8_t pb) override;
private:
@@ -138,7 +138,7 @@ public:
konami_disassembler();
protected:
- virtual void indexed(std::ostream &stream, uint8_t pb, const data_buffer &params, offs_t &p) override;
+ virtual void indirect(std::ostream &stream, uint8_t pb, const data_buffer &params, offs_t &p) override;
virtual void register_register(std::ostream &stream, uint8_t pb) override;
private:
diff --git a/src/devices/cpu/mcs51/mcs51.cpp b/src/devices/cpu/mcs51/mcs51.cpp
index c307c19a611..60d39a25139 100644
--- a/src/devices/cpu/mcs51/mcs51.cpp
+++ b/src/devices/cpu/mcs51/mcs51.cpp
@@ -874,8 +874,6 @@ uint8_t mcs51_cpu_device::bit_address_r(uint8_t offset)
int distance; /* distance between bit addressable words */
/* 1 for normal bits, 8 for sfr bit addresses */
- m_last_bit = offset;
-
//User defined bit addresses 0x20-0x2f (values are 0x0-0x7f)
if (offset < 0x80) {
distance = 1;
@@ -1360,8 +1358,6 @@ void mcs51_cpu_device::execute_op(uint8_t op)
m_recalc_parity = 0;
}
- m_last_op = op;
-
switch( op )
{
case 0x00: nop(op); break; //NOP
@@ -1781,10 +1777,6 @@ void mcs51_cpu_device::check_irqs()
return;
}
- // Hack to work around polling latency issue with JB INT0/INT1
- if (m_last_op == 0x20 && ((int_vec == V_IE0 && m_last_bit == 0xb2) || (int_vec == V_IE1 && m_last_bit == 0xb3)))
- PC = PPC + 3;
-
//Save current pc to stack, set pc to new interrupt vector
push_pc();
PC = int_vec;
@@ -2134,8 +2126,6 @@ void mcs51_cpu_device::device_start()
save_item(NAME(m_ppc));
save_item(NAME(m_pc));
- save_item(NAME(m_last_op));
- save_item(NAME(m_last_bit));
save_item(NAME(m_rwm) );
save_item(NAME(m_cur_irq_prio) );
save_item(NAME(m_last_line_state) );
@@ -2223,8 +2213,6 @@ void mcs51_cpu_device::device_reset()
/* Flag as NO IRQ in Progress */
m_irq_active = 0;
m_cur_irq_prio = -1;
- m_last_op = 0;
- m_last_bit = 0;
/* these are all defined reset states */
PC = 0;
diff --git a/src/devices/cpu/mcs51/mcs51.h b/src/devices/cpu/mcs51/mcs51.h
index bd7b6d7b085..e0d4028f493 100644
--- a/src/devices/cpu/mcs51/mcs51.h
+++ b/src/devices/cpu/mcs51/mcs51.h
@@ -122,10 +122,6 @@ protected:
uint8_t m_forced_inputs[4]; /* allow read even if configured as output */
- // JB-related hacks
- uint8_t m_last_op;
- uint8_t m_last_bit;
-
int m_icount;
struct mcs51_uart
diff --git a/src/devices/cpu/mips/mips1.cpp b/src/devices/cpu/mips/mips1.cpp
index 1ed202c0d63..72479a6065d 100644
--- a/src/devices/cpu/mips/mips1.cpp
+++ b/src/devices/cpu/mips/mips1.cpp
@@ -7,6 +7,8 @@
* while those without have hard-wired address translation.
*
* TODO
+ * - FPU support
+ * - further cleanup on coprocessors
* - R3041 features
* - cache emulation
*
@@ -15,32 +17,37 @@
#include "mips1.h"
#include "mips1dsm.h"
#include "debugger.h"
-#include "softfloat3/source/include/softfloat.h"
#define LOG_GENERAL (1U << 0)
#define LOG_TLB (1U << 1)
-#define LOG_IOP (1U << 2)
-#define LOG_RISCOS (1U << 3)
//#define VERBOSE (LOG_GENERAL|LOG_TLB)
-
#include "logmacro.h"
+#define ENABLE_IOP_KPUTS (0)
+
#define RSREG ((op >> 21) & 31)
#define RTREG ((op >> 16) & 31)
#define RDREG ((op >> 11) & 31)
#define SHIFT ((op >> 6) & 31)
-#define FTREG ((op >> 16) & 31)
-#define FSREG ((op >> 11) & 31)
-#define FDREG ((op >> 6) & 31)
+#define RSVAL m_r[RSREG]
+#define RTVAL m_r[RTREG]
+#define RDVAL m_r[RDREG]
#define SIMMVAL s16(op)
#define UIMMVAL u16(op)
#define LIMMVAL (op & 0x03ffffff)
-#define SR m_cop0[COP0_Status]
-#define CAUSE m_cop0[COP0_Cause]
+#define ADDPC(x) do { m_branch_state = BRANCH; m_branch_target = m_pc + 4 + ((x) << 2); } while (0)
+#define ADDPCL(x,l) do { m_branch_state = BRANCH; m_branch_target = m_pc + 4 + ((x) << 2); m_r[l] = m_pc + 8; } while (0)
+#define ABSPC(x) do { m_branch_state = BRANCH; m_branch_target = ((m_pc + 4) & 0xf0000000) | ((x) << 2); } while (0)
+#define ABSPCL(x,l) do { m_branch_state = BRANCH; m_branch_target = ((m_pc + 4) & 0xf0000000) | ((x) << 2); m_r[l] = m_pc + 8; } while (0)
+#define SETPC(x) do { m_branch_state = BRANCH; m_branch_target = (x); } while (0)
+#define SETPCL(x,l) do { m_branch_state = BRANCH; m_branch_target = (x); m_r[l] = m_pc + 8; } while (0)
+
+#define SR m_cpr[0][COP0_Status]
+#define CAUSE m_cpr[0][COP0_Cause]
DEFINE_DEVICE_TYPE(R2000, r2000_device, "r2000", "MIPS R2000")
DEFINE_DEVICE_TYPE(R2000A, r2000a_device, "r2000a", "MIPS R2000A")
@@ -63,6 +70,8 @@ mips1core_device_base::mips1core_device_base(const machine_config &mconfig, devi
, m_icache_config("icache", ENDIANNESS_BIG, 32, 32)
, m_dcache_config("dcache", ENDIANNESS_BIG, 32, 32)
, m_cpurev(cpurev)
+ , m_hasfpu(false)
+ , m_fpurev(0)
, m_endianness(ENDIANNESS_BIG)
, m_icount(0)
, m_icache_size(icache_size)
@@ -73,7 +82,6 @@ mips1core_device_base::mips1core_device_base(const machine_config &mconfig, devi
mips1_device_base::mips1_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 cpurev, size_t icache_size, size_t dcache_size)
: mips1core_device_base(mconfig, type, tag, owner, clock, cpurev, icache_size, dcache_size)
- , m_fcr0(0)
{
}
@@ -118,14 +126,14 @@ r3052e_device::r3052e_device(const machine_config &mconfig, const char *tag, dev
}
r3071_device::r3071_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, size_t icache_size, size_t dcache_size)
- : mips1_device_base(mconfig, R3071, tag, owner, clock, 0x0200, icache_size, dcache_size)
+ : mips1core_device_base(mconfig, R3071, tag, owner, clock, 0x0200, icache_size, dcache_size)
{
}
r3081_device::r3081_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, size_t icache_size, size_t dcache_size)
- : mips1_device_base(mconfig, R3081, tag, owner, clock, 0x0200, icache_size, dcache_size)
+ : mips1core_device_base(mconfig, R3081, tag, owner, clock, 0x0200, icache_size, dcache_size)
{
- set_fpu(0x0300);
+ set_fpurev(0x0300);
}
iop_device::iop_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
@@ -145,6 +153,18 @@ void mips1core_device_base::device_add_mconfig(machine_config &config)
set_addrmap(2, &mips1core_device_base::dcache_map);
}
+void mips1core_device_base::icache_map(address_map &map)
+{
+ if (m_icache_size)
+ map(0, m_icache_size - 1).ram().mirror(~(m_icache_size - 1));
+}
+
+void mips1core_device_base::dcache_map(address_map &map)
+{
+ if (m_dcache_size)
+ map(0, m_dcache_size - 1).ram().mirror(~(m_dcache_size - 1));
+}
+
void mips1core_device_base::device_start()
{
// set our instruction counter
@@ -157,32 +177,49 @@ void mips1core_device_base::device_start()
// register our state for the debugger
state_add(STATE_GENPC, "GENPC", m_pc).noshow();
state_add(STATE_GENPCBASE, "CURPC", m_pc).noshow();
+ state_add(STATE_GENSP, "GENSP", m_r[31]).noshow();
+ state_add(STATE_GENFLAGS, "GENFLAGS", m_cpr[0][COP0_Status]).noshow();
- state_add(MIPS1_PC, "PC", m_pc);
- state_add(MIPS1_COP0 + COP0_Status, "SR", m_cop0[COP0_Status]);
+ state_add(MIPS1_PC, "PC", m_pc);
+ state_add(MIPS1_COP0_SR, "SR", m_cpr[0][COP0_Status]);
- for (unsigned i = 0; i < ARRAY_LENGTH(m_r); i++)
+ for (int i = 0; i < 32; i++)
state_add(MIPS1_R0 + i, util::string_format("R%d", i).c_str(), m_r[i]);
state_add(MIPS1_HI, "HI", m_hi);
state_add(MIPS1_LO, "LO", m_lo);
-
- // cop0 exception registers
- state_add(MIPS1_COP0 + COP0_BadVAddr, "BadVAddr", m_cop0[COP0_BadVAddr]);
- state_add(MIPS1_COP0 + COP0_Cause, "Cause", m_cop0[COP0_Cause]);
- state_add(MIPS1_COP0 + COP0_EPC, "EPC", m_cop0[COP0_EPC]);
+ state_add(MIPS1_COP0_BADVADDR, "BadVAddr", m_cpr[0][COP0_BadVAddr]);
+ state_add(MIPS1_COP0_CAUSE, "Cause", m_cpr[0][COP0_Cause]);
+ state_add(MIPS1_COP0_EPC, "EPC", m_cpr[0][COP0_EPC]);
// register our state for saving
save_item(NAME(m_pc));
save_item(NAME(m_hi));
save_item(NAME(m_lo));
save_item(NAME(m_r));
- save_item(NAME(m_cop0));
+ save_item(NAME(m_cpr));
+ save_item(NAME(m_ccr));
save_item(NAME(m_branch_state));
save_item(NAME(m_branch_target));
- // initialise cpu id register
- m_cop0[COP0_PRId] = m_cpurev;
+ // initialise cpu and fpu id registers
+ m_cpr[0][COP0_PRId] = m_cpurev;
+ m_ccr[1][0] = m_fpurev;
+}
+
+void mips1_device_base::device_start()
+{
+ mips1core_device_base::device_start();
+
+ // cop0 tlb registers
+ state_add(MIPS1_COP0_INDEX, "Index", m_cpr[0][COP0_Index]);
+ state_add(MIPS1_COP0_RANDOM, "Random", m_cpr[0][COP0_Random]);
+ state_add(MIPS1_COP0_ENTRYLO, "EntryLo", m_cpr[0][COP0_EntryLo]);
+ state_add(MIPS1_COP0_ENTRYHI, "EntryHi", m_cpr[0][COP0_EntryHi]);
+ state_add(MIPS1_COP0_CONTEXT, "Context", m_cpr[0][COP0_Context]);
+
+ save_item(NAME(m_reset_time));
+ save_item(NAME(m_tlb));
}
void r3041_device::device_start()
@@ -190,11 +227,11 @@ void r3041_device::device_start()
mips1core_device_base::device_start();
// cop0 r3041 registers
- state_add(MIPS1_COP0 + COP0_BusCtrl, "BusCtrl", m_cop0[COP0_BusCtrl]);
- state_add(MIPS1_COP0 + COP0_Config, "Config", m_cop0[COP0_Config]);
- state_add(MIPS1_COP0 + COP0_Count, "Count", m_cop0[COP0_Count]);
- state_add(MIPS1_COP0 + COP0_PortSize, "PortSize", m_cop0[COP0_PortSize]);
- state_add(MIPS1_COP0 + COP0_Compare, "Compare", m_cop0[COP0_Compare]);
+ state_add(MIPS1_COP0_BUSCTRL, "BusCtrl", m_cpr[0][COP0_BusCtrl]);
+ state_add(MIPS1_COP0_CONFIG, "Config", m_cpr[0][COP0_Config]);
+ state_add(MIPS1_COP0_COUNT, "Count", m_cpr[0][COP0_Count]);
+ state_add(MIPS1_COP0_PORTSIZE, "PortSize", m_cpr[0][COP0_PortSize]);
+ state_add(MIPS1_COP0_COMPARE, "Compare", m_cpr[0][COP0_Compare]);
}
void mips1core_device_base::device_reset()
@@ -204,402 +241,19 @@ void mips1core_device_base::device_reset()
m_branch_state = NONE;
// non-tlb devices have tlb shut down
- m_cop0[COP0_Status] = SR_BEV | SR_TS;
+ m_cpr[0][COP0_Status] = SR_BEV | SR_TS;
m_data_spacenum = 0;
}
-void mips1core_device_base::execute_run()
-{
- // check for interrupts
- check_irqs();
-
- // core execution loop
- while (m_icount-- > 0)
- {
- // debugging
- debugger_instruction_hook(m_pc);
-
- if (VERBOSE & LOG_IOP)
- {
- if ((m_pc & 0x1fffffff) == 0x00012C48 || (m_pc & 0x1fffffff) == 0x0001420C || (m_pc & 0x1fffffff) == 0x0001430C)
- {
- u32 ptr = m_r[5];
- u32 length = m_r[6];
- if (length >= 4096)
- length = 4095;
- while (length)
- {
- load<u8>(ptr, [](char c) { printf("%c", c); });
- ptr++;
- length--;
- }
- fflush(stdout);
- }
- }
-
- // fetch and execute instruction
- fetch(m_pc, [this](u32 const op)
- {
- // parse the instruction
- switch (op >> 26)
- {
- case 0x00: // SPECIAL
- switch (op & 63)
- {
- case 0x00: // SLL
- m_r[RDREG] = m_r[RTREG] << SHIFT;
- break;
- case 0x02: // SRL
- m_r[RDREG] = m_r[RTREG] >> SHIFT;
- break;
- case 0x03: // SRA
- m_r[RDREG] = s32(m_r[RTREG]) >> SHIFT;
- break;
- case 0x04: // SLLV
- m_r[RDREG] = m_r[RTREG] << (m_r[RSREG] & 31);
- break;
- case 0x06: // SRLV
- m_r[RDREG] = m_r[RTREG] >> (m_r[RSREG] & 31);
- break;
- case 0x07: // SRAV
- m_r[RDREG] = s32(m_r[RTREG]) >> (m_r[RSREG] & 31);
- break;
- case 0x08: // JR
- m_branch_state = BRANCH;
- m_branch_target = m_r[RSREG];
- break;
- case 0x09: // JALR
- m_branch_state = BRANCH;
- m_branch_target = m_r[RSREG];
- m_r[RDREG] = m_pc + 8;
- break;
- case 0x0c: // SYSCALL
- generate_exception(EXCEPTION_SYSCALL);
- break;
- case 0x0d: // BREAK
- generate_exception(EXCEPTION_BREAK);
- break;
- case 0x10: // MFHI
- m_r[RDREG] = m_hi;
- break;
- case 0x11: // MTHI
- m_hi = m_r[RSREG];
- break;
- case 0x12: // MFLO
- m_r[RDREG] = m_lo;
- break;
- case 0x13: // MTLO
- m_lo = m_r[RSREG];
- break;
- case 0x18: // MULT
- {
- u64 product = mul_32x32(m_r[RSREG], m_r[RTREG]);
-
- m_lo = product;
- m_hi = product >> 32;
- m_icount -= 11;
- }
- break;
- case 0x19: // MULTU
- {
- u64 product = mulu_32x32(m_r[RSREG], m_r[RTREG]);
-
- m_lo = product;
- m_hi = product >> 32;
- m_icount -= 11;
- }
- break;
- case 0x1a: // DIV
- if (m_r[RTREG])
- {
- m_lo = s32(m_r[RSREG]) / s32(m_r[RTREG]);
- m_hi = s32(m_r[RSREG]) % s32(m_r[RTREG]);
- }
- m_icount -= 34;
- break;
- case 0x1b: // DIVU
- if (m_r[RTREG])
- {
- m_lo = m_r[RSREG] / m_r[RTREG];
- m_hi = m_r[RSREG] % m_r[RTREG];
- }
- m_icount -= 34;
- break;
- case 0x20: // ADD
- {
- u32 const sum = m_r[RSREG] + m_r[RTREG];
-
- // overflow: (sign(addend0) == sign(addend1)) && (sign(addend0) != sign(sum))
- if (!BIT(m_r[RSREG] ^ m_r[RTREG], 31) && BIT(m_r[RSREG] ^ sum, 31))
- generate_exception(EXCEPTION_OVERFLOW);
- else
- m_r[RDREG] = sum;
- }
- break;
- case 0x21: // ADDU
- m_r[RDREG] = m_r[RSREG] + m_r[RTREG];
- break;
- case 0x22: // SUB
- {
- u32 const difference = m_r[RSREG] - m_r[RTREG];
-
- // overflow: (sign(minuend) != sign(subtrahend)) && (sign(minuend) != sign(difference))
- if (BIT(m_r[RSREG] ^ m_r[RTREG], 31) && BIT(m_r[RSREG] ^ difference, 31))
- generate_exception(EXCEPTION_OVERFLOW);
- else
- m_r[RDREG] = difference;
- }
- break;
- case 0x23: // SUBU
- m_r[RDREG] = m_r[RSREG] - m_r[RTREG];
- break;
- case 0x24: // AND
- m_r[RDREG] = m_r[RSREG] & m_r[RTREG];
- break;
- case 0x25: // OR
- m_r[RDREG] = m_r[RSREG] | m_r[RTREG];
- break;
- case 0x26: // XOR
- m_r[RDREG] = m_r[RSREG] ^ m_r[RTREG];
- break;
- case 0x27: // NOR
- m_r[RDREG] = ~(m_r[RSREG] | m_r[RTREG]);
- break;
- case 0x2a: // SLT
- m_r[RDREG] = s32(m_r[RSREG]) < s32(m_r[RTREG]);
- break;
- case 0x2b: // SLTU
- m_r[RDREG] = u32(m_r[RSREG]) < u32(m_r[RTREG]);
- break;
- default:
- generate_exception(EXCEPTION_INVALIDOP);
- break;
- }
- break;
- case 0x01: // REGIMM
- switch (RTREG)
- {
- case 0x00: // BLTZ
- if (s32(m_r[RSREG]) < 0)
- {
- m_branch_state = BRANCH;
- m_branch_target = m_pc + 4 + (s32(SIMMVAL) << 2);
- }
- break;
- case 0x01: // BGEZ
- if (s32(m_r[RSREG]) >= 0)
- {
- m_branch_state = BRANCH;
- m_branch_target = m_pc + 4 + (s32(SIMMVAL) << 2);
- }
- break;
- case 0x10: // BLTZAL
- if (s32(m_r[RSREG]) < 0)
- {
- m_branch_state = BRANCH;
- m_branch_target = m_pc + 4 + (s32(SIMMVAL) << 2);
- m_r[31] = m_pc + 8;
- }
- break;
- case 0x11: // BGEZAL
- if (s32(m_r[RSREG]) >= 0)
- {
- m_branch_state = BRANCH;
- m_branch_target = m_pc + 4 + (s32(SIMMVAL) << 2);
- m_r[31] = m_pc + 8;
- }
- break;
- default:
- generate_exception(EXCEPTION_INVALIDOP);
- break;
- }
- break;
- case 0x02: // J
- m_branch_state = BRANCH;
- m_branch_target = ((m_pc + 4) & 0xf0000000) | (LIMMVAL << 2);
- break;
- case 0x03: // JAL
- m_branch_state = BRANCH;
- m_branch_target = ((m_pc + 4) & 0xf0000000) | (LIMMVAL << 2);
- m_r[31] = m_pc + 8;
- break;
- case 0x04: // BEQ
- if (m_r[RSREG] == m_r[RTREG])
- {
- m_branch_state = BRANCH;
- m_branch_target = m_pc + 4 + (s32(SIMMVAL) << 2);
- }
- break;
- case 0x05: // BNE
- if (m_r[RSREG] != m_r[RTREG])
- {
- m_branch_state = BRANCH;
- m_branch_target = m_pc + 4 + (s32(SIMMVAL) << 2);
- }
- break;
- case 0x06: // BLEZ
- if (s32(m_r[RSREG]) <= 0)
- {
- m_branch_state = BRANCH;
- m_branch_target = m_pc + 4 + (s32(SIMMVAL) << 2);
- }
- break;
- case 0x07: // BGTZ
- if (s32(m_r[RSREG]) > 0)
- {
- m_branch_state = BRANCH;
- m_branch_target = m_pc + 4 + (s32(SIMMVAL) << 2);
- }
- break;
- case 0x08: // ADDI
- {
- u32 const sum = m_r[RSREG] + SIMMVAL;
-
- // overflow: (sign(addend0) == sign(addend1)) && (sign(addend0) != sign(sum))
- if (!BIT(m_r[RSREG] ^ s32(SIMMVAL), 31) && BIT(m_r[RSREG] ^ sum, 31))
- generate_exception(EXCEPTION_OVERFLOW);
- else
- m_r[RTREG] = sum;
- }
- break;
- case 0x09: // ADDIU
- m_r[RTREG] = m_r[RSREG] + SIMMVAL;
- break;
- case 0x0a: // SLTI
- m_r[RTREG] = s32(m_r[RSREG]) < s32(SIMMVAL);
- break;
- case 0x0b: // SLTIU
- m_r[RTREG] = u32(m_r[RSREG]) < u32(SIMMVAL);
- break;
- case 0x0c: // ANDI
- m_r[RTREG] = m_r[RSREG] & UIMMVAL;
- break;
- case 0x0d: // ORI
- m_r[RTREG] = m_r[RSREG] | UIMMVAL;
- break;
- case 0x0e: // XORI
- m_r[RTREG] = m_r[RSREG] ^ UIMMVAL;
- break;
- case 0x0f: // LUI
- m_r[RTREG] = UIMMVAL << 16;
- break;
- case 0x10: // COP0
- if (!(SR & SR_KUc) || (SR & SR_COP0))
- handle_cop0(op);
- else
- generate_exception(EXCEPTION_BADCOP0);
- break;
- case 0x11: // COP1
- handle_cop1(op);
- break;
- case 0x12: // COP2
- handle_cop2(op);
- break;
- case 0x13: // COP3
- handle_cop3(op);
- break;
- case 0x20: // LB
- load<u8>(SIMMVAL + m_r[RSREG], [this, op](s8 temp) { m_r[RTREG] = temp; });
- break;
- case 0x21: // LH
- load<u16>(SIMMVAL + m_r[RSREG], [this, op](s16 temp) { m_r[RTREG] = temp; });
- break;
- case 0x22: // LWL
- lwl(op);
- break;
- case 0x23: // LW
- load<u32>(SIMMVAL + m_r[RSREG], [this, op](u32 temp) { m_r[RTREG] = temp; });
- break;
- case 0x24: // LBU
- load<u8>(SIMMVAL + m_r[RSREG], [this, op](u8 temp) { m_r[RTREG] = temp; });
- break;
- case 0x25: // LHU
- load<u16>(SIMMVAL + m_r[RSREG], [this, op](u16 temp) { m_r[RTREG] = temp; });
- break;
- case 0x26: // LWR
- lwr(op);
- break;
- case 0x28: // SB
- store<u8>(SIMMVAL + m_r[RSREG], m_r[RTREG]);
- break;
- case 0x29: // SH
- store<u16>(SIMMVAL + m_r[RSREG], m_r[RTREG]);
- break;
- case 0x2a: // SWL
- swl(op);
- break;
- case 0x2b: // SW
- store<u32>(SIMMVAL + m_r[RSREG], m_r[RTREG]);
- break;
- case 0x2e: // SWR
- swr(op);
- break;
- case 0x31: // LWC1
- handle_cop1(op);
- break;
- case 0x32: // LWC2
- handle_cop2(op);
- break;
- case 0x33: // LWC3
- handle_cop3(op);
- break;
- case 0x39: // SWC1
- handle_cop1(op);
- break;
- case 0x3a: // SWC2
- handle_cop2(op);
- break;
- case 0x3b: // SWC3
- handle_cop3(op);
- break;
- default:
- generate_exception(EXCEPTION_INVALIDOP);
- break;
- }
-
- // update pc and branch state
- switch (m_branch_state)
- {
- case NONE:
- m_pc += 4;
- break;
-
- case DELAY:
- m_branch_state = NONE;
- m_pc = m_branch_target;
- break;
-
- case BRANCH:
- m_branch_state = DELAY;
- m_pc += 4;
- break;
-
- case EXCEPTION:
- m_branch_state = NONE;
- break;
- }
-
- // clear register 0
- m_r[0] = 0;
- });
- }
-}
-
-void mips1core_device_base::execute_set_input(int irqline, int state)
+void mips1_device_base::device_reset()
{
- if (state != CLEAR_LINE)
- {
- CAUSE |= CAUSE_IPEX0 << irqline;
+ mips1core_device_base::device_reset();
- // enable debugger interrupt breakpoints
- if ((SR & SR_IEc) && (SR & (SR_IMEX0 << irqline)))
- standard_irq_callback(irqline);
- }
- else
- CAUSE &= ~(CAUSE_IPEX0 << irqline);
+ // tlb is not shut down
+ m_cpr[0][COP0_Status] &= ~SR_TS;
- check_irqs();
+ m_reset_time = total_cycles();
}
device_memory_interface::space_config_vector mips1core_device_base::memory_space_config() const
@@ -611,228 +265,29 @@ device_memory_interface::space_config_vector mips1core_device_base::memory_space
};
}
-bool mips1core_device_base::memory_translate(int spacenum, int intention, offs_t &address)
-{
- // check for kernel memory address
- if (BIT(address, 31))
- {
- // check debug or kernel mode
- if ((intention & TRANSLATE_DEBUG_MASK) || !(SR & SR_KUc))
- {
- switch (address & 0xe0000000)
- {
- case 0x80000000: // kseg0: unmapped, cached, privileged
- case 0xa0000000: // kseg1: unmapped, uncached, privileged
- address &= ~0xe0000000;
- break;
-
- case 0xc0000000: // kseg2: mapped, cached, privileged
- case 0xe0000000:
- break;
- }
- }
- else if (SR & SR_KUc)
- {
- if (!machine().side_effects_disabled())
- {
- // exception
- m_cop0[COP0_BadVAddr] = address;
-
- generate_exception((intention & TRANSLATE_WRITE) ? EXCEPTION_ADDRSTORE : EXCEPTION_ADDRLOAD);
- }
- return false;
- }
- }
- else
- // kuseg physical addresses have a 1GB offset
- address += 0x40000000;
-
- return true;
-}
-
std::unique_ptr<util::disasm_interface> mips1core_device_base::create_disassembler()
{
return std::make_unique<mips1_disassembler>();
}
-void mips1core_device_base::icache_map(address_map &map)
-{
- if (m_icache_size)
- map(0, m_icache_size - 1).ram().mirror(~(m_icache_size - 1));
-}
-
-void mips1core_device_base::dcache_map(address_map &map)
-{
- if (m_dcache_size)
- map(0, m_dcache_size - 1).ram().mirror(~(m_dcache_size - 1));
-}
-
-void mips1core_device_base::generate_exception(u32 exception, bool refill)
+void mips1core_device_base::generate_exception(int exception, bool refill)
{
- if ((VERBOSE & LOG_RISCOS) && (exception == EXCEPTION_SYSCALL))
- {
- static char const *const sysv_syscalls[] =
- {
- "syscall", "exit", "fork", "read", "write", "open", "close", "wait", "creat", "link",
- "unlink", "execv", "chdir", "time", "mknod", "chmod", "chown", "brk", "stat", "lseek",
- "getpid", "mount", "umount", "setuid", "getuid", "stime", "ptrace", "alarm", "fstat", "pause",
- "utime", "stty", "gtty", "access", "nice", "statfs", "sync", "kill", "fstatfs", "setpgrp",
- nullptr, "dup", "pipe", "times", "profil", "plock", "setgid", "getgid", "signal", "msgsys",
- "sysmips", "acct", "shmsys", "semsys", "ioctl", "uadmin", nullptr, "utssys", nullptr, "execve",
- "umask", "chroot", "ofcntl", "ulimit", nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- "advfs", "unadvfs", "rmount", "rumount", "rfstart", nullptr, "rdebug", "rfstop", "rfsys", "rmdir",
- "mkdir", "getdents", nullptr, nullptr, "sysfs", "getmsg", "putmsg", "poll", "sigreturn", "accept",
- "bind", "connect", "gethostid", "getpeername", "getsockname", "getsockopt", "listen", "recv", "recvfrom", "recvmsg",
- "select", "send", "sendmsg", "sendto", "sethostid", "setsockopt", "shutdown", "socket", "gethostname", "sethostname",
- "getdomainname","setdomainname","truncate", "ftruncate", "rename", "symlink", "readlink", "lstat", "nfsmount", "nfssvc",
- "getfh", "async_daemon", "old_exportfs", "mmap", "munmap", "getitimer", "setitimer", nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, nullptr,
- "cacheflush", "cachectl", "fchown", "fchmod", "wait3", "mmap", "munmap", "madvise", "getpagesize", "setreuid",
- "setregid", "setpgid", "getgroups", "setgroups", "gettimeofday", "getrusage", "getrlimit", "setrlimit", "exportfs", "fcntl"
- };
-
- static char const *const bsd_syscalls[] =
- {
- "syscall", "exit", "fork", "read", "write", "open", "close", nullptr, "creat", "link",
- "unlink", "execv", "chdir", nullptr, "mknod", "chmod", "chown", "brk", nullptr, "lseek",
- "getpid", "omount", "oumount", nullptr, "getuid", nullptr, "ptrace", nullptr, nullptr, nullptr,
- nullptr, nullptr, nullptr, "access", nullptr, nullptr, "sync", "kill", "stat", nullptr,
- "lstat", "dup", "pipe", nullptr, "profil", nullptr, nullptr, "getgid", nullptr, nullptr,
- nullptr, "acct", nullptr, nullptr, "ioctl", "reboot", nullptr, "symlink", "readlink", "execve",
- "umask", "chroot", "fstat", nullptr, "getpagesize", "mremap", "vfork", nullptr, nullptr, "sbrk",
- "sstk", "mmap", "vadvise", "munmap", "mprotec", "madvise", "vhangup", nullptr, "mincore", "getgroups",
- "setgroups", "getpgrp", "setpgrp", "setitimer", "wait3", "swapon", "getitimer", "gethostname", "sethostname", "getdtablesize",
- "dup2", "getdopt", "fcntl", "select", "setdopt", "fsync", "setpriority", "socket", "connect", "accept",
- "getpriority", "send", "recv", "sigreturn", "bind", "setsockopt", "listen", nullptr, "sigvec", "sigblock",
- "sigsetmask", "sigpause", "sigstack", "recvmsg", "sendmsg", nullptr, "gettimeofday", "getrusage", "getsockopt", nullptr,
- "readv", "writev", "settimeofday", "fchown", "fchmod", "recvfrom", "setreuid", "setregid", "rename", "truncate",
- "ftruncate", "flock", nullptr, "sendto", "shutdown", "socketpair", "mkdir", "rmdir", "utimes", "sigcleanup",
- "adjtime", "getpeername", "gethostid", "sethostid", "getrlimit", "setrlimit", "killpg", nullptr, "setquota", "quota",
- "getsockname", "sysmips", "cacheflush", "cachectl", "debug", nullptr, nullptr, nullptr, "nfssvc", "getdirentries",
- "statfs", "fstatfs", "unmount", "async_daemon", "getfh", "getdomainname","setdomainname",nullptr, "quotactl", "old_exportfs",
- "mount", "hdwconf", "exportfs", "nfsfh_open", "libattach", "libdetach"
- };
-
- static char const *const msg_syscalls[] = { "msgget", "msgctl", "msgrcv", "msgsnd" };
- static char const *const shm_syscalls[] = { "shmat", "shmctl", "shmdt", "shmget" };
- static char const *const sem_syscalls[] = { "semctl", "semget", "semop" };
- static char const *const mips_syscalls[] = { "mipskopt", "mipshwconf", "mipsgetrusage", "mipswait", "mipscacheflush", "mipscachectl" };
-
- unsigned const asid = (m_cop0[COP0_EntryHi] & EH_ASID) >> 6;
- switch (m_r[2])
- {
- case 1000: // indirect
- switch (m_r[4])
- {
- case 1049: // msgsys
- LOGMASKED(LOG_RISCOS, "asid %d syscall msgsys:%s() (%s)\n",
- asid, (m_r[5] < ARRAY_LENGTH(msg_syscalls)) ? msg_syscalls[m_r[5]] : "unknown", machine().describe_context());
- break;
-
- case 1052: // shmsys
- LOGMASKED(LOG_RISCOS, "asid %d syscall shmsys:%s() (%s)\n",
- asid, (m_r[5] < ARRAY_LENGTH(shm_syscalls)) ? shm_syscalls[m_r[5]] : "unknown", machine().describe_context());
- break;
-
- case 1053: // semsys
- LOGMASKED(LOG_RISCOS, "asid %d syscall semsys:%s() (%s)\n",
- asid, (m_r[5] < ARRAY_LENGTH(sem_syscalls)) ? sem_syscalls[m_r[5]] : "unknown", machine().describe_context());
- break;
-
- case 2151: // bsd_sysmips
- switch (m_r[5])
- {
- case 0x100: // mipskopt
- LOGMASKED(LOG_RISCOS, "asid %d syscall bsd_sysmips:mipskopt(\"%s\") (%s)\n",
- asid, debug_string(m_r[6]), machine().describe_context());
- break;
-
- default:
- if ((m_r[5] > 0x100) && (m_r[5] - 0x100) < ARRAY_LENGTH(mips_syscalls))
- LOGMASKED(LOG_RISCOS, "asid %d syscall bsd_sysmips:%s() (%s)\n",
- asid, mips_syscalls[m_r[5] - 0x100], machine().describe_context());
- else
- LOGMASKED(LOG_RISCOS, "asid %d syscall bsd_sysmips:unknown %d (%s)\n",
- asid, m_r[5], machine().describe_context());
- break;
- }
- break;
-
- default:
- if ((m_r[4] > 2000) && (m_r[4] - 2000 < ARRAY_LENGTH(bsd_syscalls)) && bsd_syscalls[m_r[4] - 2000])
- LOGMASKED(LOG_RISCOS, "asid %d syscall bsd_%s() (%s)\n",
- asid, bsd_syscalls[m_r[4] - 2000], machine().describe_context());
- else
- LOGMASKED(LOG_RISCOS, "asid %d syscall indirect:unknown %d (%s)\n",
- asid, m_r[4], machine().describe_context());
- break;
- }
- break;
-
- case 1003: // read
- case 1006: // close
- case 1054: // ioctl
- case 1169: // fcntl
- LOGMASKED(LOG_RISCOS, "asid %d syscall %s(%d) (%s)\n",
- asid, sysv_syscalls[m_r[2] - 1000], m_r[4], machine().describe_context());
- break;
-
- case 1004: // write
- if (m_r[4] == 1 || m_r[4] == 2)
- LOGMASKED(LOG_RISCOS, "asid %d syscall %s(%d, \"%s\") (%s)\n",
- asid, sysv_syscalls[m_r[2] - 1000], m_r[4], debug_string(m_r[5], m_r[6]), machine().describe_context());
- else
- LOGMASKED(LOG_RISCOS, "asid %d syscall %s(%d) (%s)\n",
- asid, sysv_syscalls[m_r[2] - 1000], m_r[4], machine().describe_context());
- break;
-
- case 1005: // open
- case 1008: // creat
- case 1009: // link
- case 1010: // unlink
- case 1012: // chdir
- case 1018: // stat
- case 1033: // access
- LOGMASKED(LOG_RISCOS, "asid %d syscall %s(\"%s\") (%s)\n",
- asid, sysv_syscalls[m_r[2] - 1000], debug_string(m_r[4]), machine().describe_context());
- break;
-
- case 1059: // execve
- LOGMASKED(LOG_RISCOS, "asid %d syscall execve(\"%s\", [ %s ], [ %s ]) (%s)\n",
- asid, debug_string(m_r[4]), debug_string_array(m_r[5]), debug_string_array(m_r[6]), machine().describe_context());
- break;
-
- case 1060: // umask
- LOGMASKED(LOG_RISCOS, "asid %d syscall umask(%#o) (%s)\n",
- asid, m_r[4] & 0777, machine().describe_context());
- break;
-
- default:
- if ((m_r[2] > 1000) && (m_r[2] - 1000 < ARRAY_LENGTH(sysv_syscalls)) && sysv_syscalls[m_r[2] - 1000])
- LOGMASKED(LOG_RISCOS, "asid %d syscall %s() (%s)\n", asid, sysv_syscalls[m_r[2] - 1000], machine().describe_context());
- else
- LOGMASKED(LOG_RISCOS, "asid %d syscall unknown %d (%s)\n", asid, m_r[2], machine().describe_context());
- break;
- }
- }
-
// set the exception PC
- m_cop0[COP0_EPC] = m_pc;
+ m_cpr[0][COP0_EPC] = m_pc;
- // load the cause register
- CAUSE = (CAUSE & CAUSE_IP) | exception;
+ // put the cause in the low 8 bits and clear the branch delay flag
+ CAUSE = (CAUSE & ~0x800000ff) | (exception << 2);
// if in a branch delay slot, restart the branch
if (m_branch_state == DELAY)
{
- m_cop0[COP0_EPC] -= 4;
- CAUSE |= CAUSE_BD;
+ m_cpr[0][COP0_EPC] -= 4;
+ CAUSE |= 0x80000000;
}
m_branch_state = EXCEPTION;
// shift the exception bits
- SR = (SR & ~SR_KUIE) | ((SR << 2) & SR_KUIEop);
+ SR = (SR & 0xffffffc0) | ((SR << 2) & 0x3c);
if (refill)
m_pc = (SR & SR_BEV) ? 0xbfc00100 : 0x80000000;
@@ -840,369 +295,109 @@ void mips1core_device_base::generate_exception(u32 exception, bool refill)
m_pc = (SR & SR_BEV) ? 0xbfc00180 : 0x80000080;
debugger_exception_hook(exception);
-
- if (SR & SR_KUp)
- debugger_privilege_hook();
}
void mips1core_device_base::check_irqs()
{
- if ((CAUSE & SR & SR_IM) && (SR & SR_IEc))
+ if ((CAUSE & SR & 0xff00) && (SR & SR_IEc))
generate_exception(EXCEPTION_INTERRUPT);
}
-void mips1core_device_base::handle_cop0(u32 const op)
-{
- switch (RSREG)
- {
- case 0x00: // MFC0
- m_r[RTREG] = get_cop0_reg(RDREG);
- break;
- case 0x04: // MTC0
- set_cop0_reg(RDREG, m_r[RTREG]);
- break;
- case 0x08: // BC0
- switch (RTREG)
- {
- case 0x00: // BC0F
- if (!m_in_brcond[0]())
- {
- m_branch_state = BRANCH;
- m_branch_target = m_pc + 4 + (s32(SIMMVAL) << 2);
- }
- break;
- case 0x01: // BC0T
- if (m_in_brcond[0]())
- {
- m_branch_state = BRANCH;
- m_branch_target = m_pc + 4 + (s32(SIMMVAL) << 2);
- }
- break;
- default:
- generate_exception(EXCEPTION_INVALIDOP);
- break;
- }
- break;
- case 0x10: // COP0
- switch (op & 31)
- {
- case 0x10: // RFE
- SR = (SR & ~SR_KUIEpc) | ((SR >> 2) & SR_KUIEpc);
- if (bool(SR & SR_KUc) ^ bool(SR & SR_KUp))
- debugger_privilege_hook();
- break;
- default:
- generate_exception(EXCEPTION_INVALIDOP);
- break;
- }
- break;
- default:
- generate_exception(EXCEPTION_INVALIDOP);
- break;
- }
-}
-
-u32 mips1core_device_base::get_cop0_reg(unsigned const reg)
-{
- return m_cop0[reg];
-}
-
-void mips1core_device_base::set_cop0_reg(unsigned const reg, u32 const data)
-{
- switch (reg)
- {
- case COP0_Context:
- m_cop0[COP0_Context] = (m_cop0[COP0_Context] & ~PTE_BASE) | (data & PTE_BASE);
- break;
- case COP0_Status:
- {
- u32 const delta = SR ^ data;
-
- m_cop0[COP0_Status] = data;
-
- // handle cache isolation and swap
- m_data_spacenum = (data & SR_IsC) ? ((data & SR_SwC) ? 1 : 2) : 0;
-
- // update interrupts
- if (delta & (SR_IEc | SR_IM))
- check_irqs();
-
- if ((delta & SR_KUc) && (m_branch_state != EXCEPTION))
- debugger_privilege_hook();
- }
- break;
- case COP0_Cause:
- CAUSE = (CAUSE & CAUSE_IPEX) | (data & ~CAUSE_IPEX);
-
- // update interrupts -- software ints can occur this way
- check_irqs();
- break;
- case COP0_PRId:
- // read-only register
- break;
-
- default:
- m_cop0[reg] = data;
- break;
- }
-}
-
-void mips1core_device_base::handle_cop1(u32 const op)
-{
- if (!(SR & SR_COP1))
- generate_exception(EXCEPTION_BADCOP1);
-}
-
-void mips1core_device_base::handle_cop2(u32 const op)
-{
- if (SR & SR_COP2)
- {
- switch (RSREG)
- {
- case 0x08: // BC2
- switch (RTREG)
- {
- case 0x00: // BC2F
- if (!m_in_brcond[2]())
- {
- m_branch_state = BRANCH;
- m_branch_target = m_pc + 4 + (s32(SIMMVAL) << 2);
- }
- break;
- case 0x01: // BC2T
- if (m_in_brcond[2]())
- {
- m_branch_state = BRANCH;
- m_branch_target = m_pc + 4 + (s32(SIMMVAL) << 2);
- }
- break;
- default:
- generate_exception(EXCEPTION_INVALIDOP);
- break;
- }
- break;
- default:
- generate_exception(EXCEPTION_INVALIDOP);
- break;
- }
- }
- else
- generate_exception(EXCEPTION_BADCOP2);
-}
-
-void mips1core_device_base::handle_cop3(u32 const op)
+void mips1core_device_base::set_irq_line(int irqline, int state)
{
- if (SR & SR_COP3)
- {
- switch (RSREG)
- {
- case 0x08: // BC3
- switch (RTREG)
- {
- case 0x00: // BC3F
- if (!m_in_brcond[3]())
- {
- m_branch_state = BRANCH;
- m_branch_target = m_pc + 4 + (s32(SIMMVAL) << 2);
- }
- break;
- case 0x01: // BC3T
- if (m_in_brcond[3]())
- {
- m_branch_state = BRANCH;
- m_branch_target = m_pc + 4 + (s32(SIMMVAL) << 2);
- }
- break;
- default:
- generate_exception(EXCEPTION_INVALIDOP);
- break;
- }
- break;
- default:
- generate_exception(EXCEPTION_INVALIDOP);
- break;
- }
- }
+ if (state != CLEAR_LINE)
+ CAUSE |= 0x400 << irqline;
else
- generate_exception(EXCEPTION_BADCOP3);
-}
+ CAUSE &= ~(0x400 << irqline);
-void mips1core_device_base::lwl(u32 const op)
-{
- offs_t const offset = SIMMVAL + m_r[RSREG];
- load<u32>(offset & ~3, [this, op, offset](u32 temp)
- {
- unsigned const shift = ((offset & 3) ^ ENDIAN_VALUE_LE_BE(m_endianness, 3, 0)) << 3;
-
- m_r[RTREG] = (m_r[RTREG] & ~u32(0xffffffffU << shift)) | (temp << shift);
- });
-}
-
-void mips1core_device_base::lwr(u32 const op)
-{
- offs_t const offset = SIMMVAL + m_r[RSREG];
- load<u32>(offset & ~3, [this, op, offset](u32 temp)
- {
- unsigned const shift = ((offset & 0x3) ^ ENDIAN_VALUE_LE_BE(m_endianness, 0, 3)) << 3;
-
- m_r[RTREG] = (m_r[RTREG] & ~u32(0xffffffffU >> shift)) | (temp >> shift);
- });
+ check_irqs();
}
-void mips1core_device_base::swl(u32 const op)
+u32 mips1core_device_base::get_cop0_reg(int const index)
{
- offs_t const offset = SIMMVAL + m_r[RSREG];
- unsigned const shift = ((offset & 3) ^ ENDIAN_VALUE_LE_BE(m_endianness, 3, 0)) << 3;
-
- store<u32>(offset & ~3, m_r[RTREG] >> shift, 0xffffffffU >> shift);
+ return m_cpr[0][index];
}
-void mips1core_device_base::swr(u32 const op)
+u32 mips1_device_base::get_cop0_reg(int const index)
{
- offs_t const offset = SIMMVAL + m_r[RSREG];
- unsigned const shift = ((offset & 3) ^ ENDIAN_VALUE_LE_BE(m_endianness, 0, 3)) << 3;
+ // assume 64-entry tlb with 8 wired entries
+ if (index == COP0_Random)
+ m_cpr[0][index] = (63 - ((total_cycles() - m_reset_time) % 56)) << 8;
- store<u32>(offset & ~3, m_r[RTREG] << shift, 0xffffffffU << shift);
+ return m_cpr[0][index];
}
-template <typename T, typename U> std::enable_if_t<std::is_convertible<U, std::function<void(T)>>::value, void> mips1core_device_base::load(u32 address, U &&apply)
+void mips1core_device_base::set_cop0_reg(int const index, u32 const data)
{
- if (memory_translate(m_data_spacenum, TRANSLATE_READ, address))
+ if (index == COP0_Cause)
{
- switch (sizeof(T))
- {
- case 1: apply(T(space(m_data_spacenum).read_byte(address))); break;
- case 2: apply(T(space(m_data_spacenum).read_word(address))); break;
- case 4: apply(T(space(m_data_spacenum).read_dword(address))); break;
- }
- }
-}
+ CAUSE = (CAUSE & 0xfc00) | (data & ~0xfc00);
-template <typename T, typename U> std::enable_if_t<std::is_convertible<U, T>::value, void> mips1core_device_base::store(u32 address, U data, T mem_mask)
-{
- if (memory_translate(m_data_spacenum, TRANSLATE_WRITE, address))
- {
- switch (sizeof(T))
- {
- case 1: space(m_data_spacenum).write_byte(address, T(data)); break;
- case 2: space(m_data_spacenum).write_word(address, T(data), mem_mask); break;
- case 4: space(m_data_spacenum).write_dword(address, T(data), mem_mask); break;
- }
+ // update interrupts -- software ints can occur this way
+ check_irqs();
}
-}
-
-bool mips1core_device_base::fetch(u32 address, std::function<void(u32)> &&apply)
-{
- if (memory_translate(0, TRANSLATE_FETCH, address))
+ else if (index == COP0_Status)
{
- apply(space(0).read_dword(address));
+ m_cpr[0][index] = data;
- return true;
+ // handle cache isolation and swap
+ m_data_spacenum = (data & SR_IsC) ? ((data & SR_SwC) ? 1 : 2) : 0;
+
+ // update interrupts
+ check_irqs();
}
- else
- return false;
+ else if (index == COP0_Context)
+ m_cpr[0][index] = (m_cpr[0][index] & ~PTE_BASE) | (data & PTE_BASE);
+ else if (index != COP0_PRId)
+ m_cpr[0][index] = data;
}
-std::string mips1core_device_base::debug_string(u32 string_pointer, unsigned const limit)
+void mips1core_device_base::handle_cop0(u32 const op)
{
- auto const suppressor(machine().disable_side_effects());
-
- bool done = false;
- bool mapped = false;
- std::string result("");
-
- while (!done)
+ switch (RSREG)
{
- done = true;
- load<u8>(string_pointer++, [limit, &done, &mapped, &result](u8 byte)
- {
- mapped = true;
- if (byte != 0)
+ case 0x00: /* MFCz */ if (RTREG) RTVAL = get_cop0_reg(RDREG); break;
+ case 0x02: /* CFCz */ if (RTREG) RTVAL = get_cop_creg<0>(RDREG); break;
+ case 0x04: /* MTCz */ set_cop0_reg(RDREG, RTVAL); break;
+ case 0x06: /* CTCz */ set_cop_creg<0>(RDREG, RTVAL); break;
+ case 0x08: /* BC */
+ switch (RTREG)
{
- result += byte;
-
- done = result.length() == limit;
+ case 0x00: /* BCzF */ if (!m_in_brcond[0]()) ADDPC(SIMMVAL); break;
+ case 0x01: /* BCzT */ if (m_in_brcond[0]()) ADDPC(SIMMVAL); break;
+ case 0x02: /* BCzFL */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x03: /* BCzTL */ generate_exception(EXCEPTION_INVALIDOP); break;
+ default: generate_exception(EXCEPTION_INVALIDOP); break;
}
- });
- }
-
- if (!mapped)
- result.assign("[unmapped]");
-
- return result;
-}
-
-std::string mips1core_device_base::debug_string_array(u32 array_pointer)
-{
- auto const suppressor(machine().disable_side_effects());
-
- bool done = false;
- std::string result("");
-
- while (!done)
- {
- done = true;
- load<u32>(array_pointer, [this, &done, &result](u32 string_pointer)
- {
- if (string_pointer != 0)
+ break;
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ case 0x18:
+ case 0x19:
+ case 0x1a:
+ case 0x1b:
+ case 0x1c:
+ case 0x1d:
+ case 0x1e:
+ case 0x1f: /* COP */
+ switch (op & 0x01ffffff)
{
- if (!result.empty())
- result += ", ";
-
- result += '\"' + debug_string(string_pointer) + '\"';
-
- done = false;
+ case 0x01: /* TLBR */ break;
+ case 0x02: /* TLBWI */ break;
+ case 0x06: /* TLBWR */ break;
+ case 0x08: /* TLBP */ break;
+ case 0x10: /* RFE */ SR = (SR & 0xfffffff0) | ((SR >> 2) & 0x0f); break;
+ case 0x18: /* ERET */ generate_exception(EXCEPTION_INVALIDOP); break;
+ default: generate_exception(EXCEPTION_INVALIDOP); break;
}
- });
-
- array_pointer += 4;
- }
-
- return result;
-}
-
-void mips1_device_base::device_start()
-{
- mips1core_device_base::device_start();
-
- // cop0 tlb registers
- state_add(MIPS1_COP0 + COP0_Index, "Index", m_cop0[COP0_Index]);
- state_add(MIPS1_COP0 + COP0_Random, "Random", m_cop0[COP0_Random]);
- state_add(MIPS1_COP0 + COP0_EntryLo, "EntryLo", m_cop0[COP0_EntryLo]);
- state_add(MIPS1_COP0 + COP0_EntryHi, "EntryHi", m_cop0[COP0_EntryHi]);
- state_add(MIPS1_COP0 + COP0_Context, "Context", m_cop0[COP0_Context]);
-
- // cop1 registers
- if (m_fcr0)
- {
- state_add(MIPS1_FCR31, "FCSR", m_fcr31);
- for (unsigned i = 0; i < ARRAY_LENGTH(m_f); i++)
- state_add(MIPS1_F0 + i, util::string_format("F%d", i).c_str(), m_f[i]);
- }
-
- save_item(NAME(m_reset_time));
- save_item(NAME(m_tlb));
-
- save_item(NAME(m_fcr30));
- save_item(NAME(m_fcr31));
- save_item(NAME(m_f));
-}
-
-void mips1_device_base::device_reset()
-{
- mips1core_device_base::device_reset();
-
- // tlb is not shut down
- m_cop0[COP0_Status] &= ~SR_TS;
-
- m_reset_time = total_cycles();
-
- // initialize tlb mru index with identity mapping
- for (unsigned i = 0; i < ARRAY_LENGTH(m_tlb); i++)
- {
- m_tlb_mru[TRANSLATE_READ][i] = i;
- m_tlb_mru[TRANSLATE_WRITE][i] = i;
- m_tlb_mru[TRANSLATE_FETCH][i] = i;
+ break;
+ default: generate_exception(EXCEPTION_INVALIDOP); break;
}
}
@@ -1212,26 +407,26 @@ void mips1_device_base::handle_cop0(u32 const op)
{
case 0x42000001: // TLBR - read tlb
{
- u8 const index = (m_cop0[COP0_Index] >> 8) & 0x3f;
+ u8 const index = (m_cpr[0][COP0_Index] >> 8) & 0x3f;
- m_cop0[COP0_EntryHi] = m_tlb[index][0];
- m_cop0[COP0_EntryLo] = m_tlb[index][1];
+ m_cpr[0][COP0_EntryHi] = m_tlb[index][0];
+ m_cpr[0][COP0_EntryLo] = m_tlb[index][1];
}
break;
case 0x42000002: // TLBWI - write tlb (indexed)
{
- u8 const index = (m_cop0[COP0_Index] >> 8) & 0x3f;
+ u8 const index = (m_cpr[0][COP0_Index] >> 8) & 0x3f;
- m_tlb[index][0] = m_cop0[COP0_EntryHi];
- m_tlb[index][1] = m_cop0[COP0_EntryLo];
+ m_tlb[index][0] = m_cpr[0][COP0_EntryHi];
+ m_tlb[index][1] = m_cpr[0][COP0_EntryLo];
LOGMASKED(LOG_TLB, "tlb write index %d asid %d vpn 0x%08x pfn 0x%08x %c%c%c%c (%s)\n",
- index, (m_cop0[COP0_EntryHi] & EH_ASID) >> 6, m_cop0[COP0_EntryHi] & EH_VPN, m_cop0[COP0_EntryLo] & EL_PFN,
- m_cop0[COP0_EntryLo] & EL_N ? 'N' : '-',
- m_cop0[COP0_EntryLo] & EL_D ? 'D' : '-',
- m_cop0[COP0_EntryLo] & EL_V ? 'V' : '-',
- m_cop0[COP0_EntryLo] & EL_G ? 'G' : '-',
+ index, (m_cpr[0][COP0_EntryHi] & EH_ASID) >> 6, m_cpr[0][COP0_EntryHi] & EH_VPN, m_cpr[0][COP0_EntryLo] & EL_PFN,
+ m_cpr[0][COP0_EntryLo] & EL_N ? 'N' : '-',
+ m_cpr[0][COP0_EntryLo] & EL_D ? 'D' : '-',
+ m_cpr[0][COP0_EntryLo] & EL_V ? 'V' : '-',
+ m_cpr[0][COP0_EntryLo] & EL_G ? 'G' : '-',
machine().describe_context());
}
break;
@@ -1240,37 +435,37 @@ void mips1_device_base::handle_cop0(u32 const op)
{
u8 const random = get_cop0_reg(COP0_Random) >> 8;
- m_tlb[random][0] = m_cop0[COP0_EntryHi];
- m_tlb[random][1] = m_cop0[COP0_EntryLo];
+ m_tlb[random][0] = m_cpr[0][COP0_EntryHi];
+ m_tlb[random][1] = m_cpr[0][COP0_EntryLo];
LOGMASKED(LOG_TLB, "tlb write random %d asid %d vpn 0x%08x pfn 0x%08x %c%c%c%c (%s)\n",
- random, (m_cop0[COP0_EntryHi] & EH_ASID) >> 6, m_cop0[COP0_EntryHi] & EH_VPN, m_cop0[COP0_EntryLo] & EL_PFN,
- m_cop0[COP0_EntryLo] & EL_N ? 'N' : '-',
- m_cop0[COP0_EntryLo] & EL_D ? 'D' : '-',
- m_cop0[COP0_EntryLo] & EL_V ? 'V' : '-',
- m_cop0[COP0_EntryLo] & EL_G ? 'G' : '-',
+ random, (m_cpr[0][COP0_EntryHi] & EH_ASID) >> 6, m_cpr[0][COP0_EntryHi] & EH_VPN, m_cpr[0][COP0_EntryLo] & EL_PFN,
+ m_cpr[0][COP0_EntryLo] & EL_N ? 'N' : '-',
+ m_cpr[0][COP0_EntryLo] & EL_D ? 'D' : '-',
+ m_cpr[0][COP0_EntryLo] & EL_V ? 'V' : '-',
+ m_cpr[0][COP0_EntryLo] & EL_G ? 'G' : '-',
machine().describe_context());
}
break;
case 0x42000008: // TLBP - probe tlb
- m_cop0[COP0_Index] = 0x80000000;
+ m_cpr[0][COP0_Index] = 0x80000000;
for (u8 index = 0; index < 64; index++)
{
// test vpn and optionally asid
u32 const mask = (m_tlb[index][1] & EL_G) ? EH_VPN : EH_VPN | EH_ASID;
- if ((m_tlb[index][0] & mask) == (m_cop0[COP0_EntryHi] & mask))
+ if ((m_tlb[index][0] & mask) == (m_cpr[0][COP0_EntryHi] & mask))
{
LOGMASKED(LOG_TLB, "tlb probe hit vpn 0x%08x index %d (%s)\n",
- m_cop0[COP0_EntryHi] & mask, index, machine().describe_context());
+ m_cpr[0][COP0_EntryHi] & mask, index, machine().describe_context());
- m_cop0[COP0_Index] = index << 8;
+ m_cpr[0][COP0_Index] = index << 8;
break;
}
}
- if ((VERBOSE & LOG_TLB) && BIT(m_cop0[COP0_Index], 31))
+ if ((VERBOSE & LOG_TLB) && BIT(m_cpr[0][COP0_Index], 31))
LOGMASKED(LOG_TLB, "tlb probe miss asid %d vpn 0x%08x(%s)\n",
- (m_cop0[COP0_EntryHi] & EH_ASID) >> 6, m_cop0[COP0_EntryHi] & EH_VPN, machine().describe_context());
+ (m_cpr[0][COP0_EntryHi] & EH_ASID) >> 6, m_cpr[0][COP0_EntryHi] & EH_VPN, machine().describe_context());
break;
default:
@@ -1278,558 +473,491 @@ void mips1_device_base::handle_cop0(u32 const op)
}
}
-u32 mips1_device_base::get_cop0_reg(unsigned const reg)
+void mips1core_device_base::set_cop1_creg(int idx, u32 val)
{
- // assume 64-entry tlb with 8 wired entries
- if (reg == COP0_Random)
- m_cop0[reg] = (63 - ((total_cycles() - m_reset_time) % 56)) << 8;
-
- return m_cop0[reg];
+ // fpu revision register is read-only
+ if (idx)
+ m_ccr[1][idx] = val;
}
-void mips1_device_base::handle_cop1(u32 const op)
+void mips1core_device_base::handle_cop1(u32 const op)
{
- if (!(SR & SR_COP1))
- {
- generate_exception(EXCEPTION_BADCOP1);
- return;
- }
-
- if (!m_fcr0)
+ if (!m_hasfpu)
return;
- switch (op >> 26)
+ switch (RSREG)
{
- case 0x11: // COP1
- switch ((op >> 21) & 0x1f)
- {
- case 0x00: // MFC1
- if (FSREG & 1)
- // move the high half of the floating point register
- m_r[RTREG] = m_f[FSREG >> 1] >> 32;
- else
- // move the low half of the floating point register
- m_r[RTREG] = m_f[FSREG >> 1] >> 0;
- break;
- case 0x02: // CFC1
- switch (FSREG)
+ case 0x00: /* MFCz */ if (RTREG) RTVAL = get_cop_reg<1>(RDREG); break;
+ case 0x02: /* CFCz */ if (RTREG) RTVAL = get_cop_creg<1>(RDREG); break;
+ case 0x04: /* MTCz */ set_cop_reg<1>(RDREG, RTVAL); break;
+ case 0x06: /* CTCz */ set_cop1_creg(RDREG, RTVAL); break;
+ case 0x08: /* BC */
+ switch (RTREG)
{
- case 0: m_r[RTREG] = m_fcr0; break;
- case 30: m_r[RTREG] = m_fcr30; break;
- case 31: m_r[RTREG] = m_fcr31; break;
- break;
-
- default:
- logerror("cfc1 undefined fpu control register %d (%s)\n", FSREG, machine().describe_context());
- break;
+ case 0x00: /* BCzF */ if (!m_in_brcond[1]()) ADDPC(SIMMVAL); break;
+ case 0x01: /* BCzT */ if (m_in_brcond[1]()) ADDPC(SIMMVAL); break;
+ case 0x02: /* BCzFL */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x03: /* BCzTL */ generate_exception(EXCEPTION_INVALIDOP); break;
+ default: generate_exception(EXCEPTION_INVALIDOP); break;
}
break;
- case 0x04: // MTC1
- if (FSREG & 1)
- // load the high half of the floating point register
- m_f[FSREG >> 1] = (u64(m_r[RTREG]) << 32) | u32(m_f[FSREG >> 1]);
- else
- // load the low half of the floating point register
- m_f[FSREG >> 1] = (m_f[FSREG >> 1] & ~0xffffffffULL) | m_r[RTREG];
- break;
- case 0x06: // CTC1
- switch (RDREG)
- {
- case 0: // register is read-only
- break;
-
- case 30:
- m_fcr30 = m_r[RTREG];
- break;
-
- case 31:
- m_fcr31 = m_r[RTREG];
-
- // update rounding mode
- switch (m_fcr31 & FCR31_RM)
- {
- case 0: softfloat_roundingMode = softfloat_round_near_even; break;
- case 1: softfloat_roundingMode = softfloat_round_minMag; break;
- case 2: softfloat_roundingMode = softfloat_round_max; break;
- case 3: softfloat_roundingMode = softfloat_round_min; break;
- }
-
- // exception check
- if ((m_fcr31 & FCR31_CE) || ((m_fcr31 & FCR31_CM) >> 5) & (m_fcr31 & FCR31_EM))
- execute_set_input(m_fpu_irq, ASSERT_LINE);
- break;
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ case 0x18:
+ case 0x19:
+ case 0x1a:
+ case 0x1b:
+ case 0x1c:
+ case 0x1d:
+ case 0x1e:
+ case 0x1f: /* COP */ generate_exception(EXCEPTION_INVALIDOP); break;
+ default: generate_exception(EXCEPTION_INVALIDOP); break;
+ }
+}
- default:
- logerror("ctc1 undefined fpu control register %d (%s)\n", RDREG, machine().describe_context());
- break;
- }
- break;
- case 0x08: // BC
- switch ((op >> 16) & 0x1f)
+template <unsigned Coprocessor> void mips1core_device_base::handle_cop(u32 const op)
+{
+ switch (RSREG)
+ {
+ case 0x00: /* MFCz */ if (RTREG) RTVAL = get_cop_reg<Coprocessor>(RDREG); break;
+ case 0x02: /* CFCz */ if (RTREG) RTVAL = get_cop_creg<Coprocessor>(RDREG); break;
+ case 0x04: /* MTCz */ set_cop_reg<Coprocessor>(RDREG, RTVAL); break;
+ case 0x06: /* CTCz */ set_cop_creg<Coprocessor>(RDREG, RTVAL); break;
+ case 0x08: /* BC */
+ switch (RTREG)
{
- case 0x00: // BC1F
- if (!(m_fcr31 & FCR31_C))
- {
- m_branch_state = BRANCH;
- m_branch_target = m_pc + 4 + (s32(SIMMVAL) << 2);
- }
- break;
- case 0x01: // BC1T
- if (m_fcr31 & FCR31_C)
- {
- m_branch_state = BRANCH;
- m_branch_target = m_pc + 4 + (s32(SIMMVAL) << 2);
- }
- break;
-
- default:
- // unimplemented operation
- m_fcr31 |= FCR31_CE;
- execute_set_input(m_fpu_irq, ASSERT_LINE);
- break;
+ case 0x00: /* BCzF */ if (!m_in_brcond[Coprocessor]()) ADDPC(SIMMVAL); break;
+ case 0x01: /* BCzT */ if (m_in_brcond[Coprocessor]()) ADDPC(SIMMVAL); break;
+ case 0x02: /* BCzFL */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x03: /* BCzTL */ generate_exception(EXCEPTION_INVALIDOP); break;
+ default: generate_exception(EXCEPTION_INVALIDOP); break;
}
break;
- case 0x10: // S
- switch (op & 0x3f)
- {
- case 0x00: // ADD.S
- set_cop1_reg(FDREG >> 1, f32_add(float32_t{ u32(m_f[FSREG >> 1]) }, float32_t{ u32(m_f[FTREG >> 1]) }).v);
- break;
- case 0x01: // SUB.S
- set_cop1_reg(FDREG >> 1, f32_sub(float32_t{ u32(m_f[FSREG >> 1]) }, float32_t{ u32(m_f[FTREG >> 1]) }).v);
- break;
- case 0x02: // MUL.S
- set_cop1_reg(FDREG >> 1, f32_mul(float32_t{ u32(m_f[FSREG >> 1]) }, float32_t{ u32(m_f[FTREG >> 1]) }).v);
- break;
- case 0x03: // DIV.S
- set_cop1_reg(FDREG >> 1, f32_div(float32_t{ u32(m_f[FSREG >> 1]) }, float32_t{ u32(m_f[FTREG >> 1]) }).v);
- break;
- case 0x05: // ABS.S
- if (f32_lt(float32_t{ u32(m_f[FSREG >> 1]) }, float32_t{ 0 }))
- set_cop1_reg(FDREG >> 1, f32_mul(float32_t{ u32(m_f[FSREG >> 1]) }, i32_to_f32(-1)).v);
- else
- set_cop1_reg(FDREG >> 1, m_f[FSREG >> 1]);
- break;
- case 0x06: // MOV.S
- m_f[FDREG >> 1] = m_f[FSREG >> 1];
- break;
- case 0x07: // NEG.S
- set_cop1_reg(FDREG >> 1, f32_mul(float32_t{ u32(m_f[FSREG >> 1]) }, i32_to_f32(-1)).v);
- break;
-
- case 0x21: // CVT.D.S
- set_cop1_reg(FDREG >> 1, f32_to_f64(float32_t{ u32(m_f[FSREG >> 1]) }).v);
- break;
- case 0x24: // CVT.W.S
- set_cop1_reg(FDREG >> 1, f32_to_i32(float32_t{ u32(m_f[FSREG >> 1]) }, softfloat_roundingMode, true));
- break;
+ case 0x10:
+ case 0x11:
+ case 0x12:
+ case 0x13:
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ case 0x18:
+ case 0x19:
+ case 0x1a:
+ case 0x1b:
+ case 0x1c:
+ case 0x1d:
+ case 0x1e:
+ case 0x1f: /* COP */ generate_exception(EXCEPTION_INVALIDOP); break;
+ default: generate_exception(EXCEPTION_INVALIDOP); break;
+ }
+}
- case 0x30: // C.F.S (false)
- m_fcr31 &= ~FCR31_C;
- break;
- case 0x31: // C.UN.S (unordered)
- f32_eq(float32_t{ u32(m_f[FSREG >> 1]) }, float32_t{ u32(m_f[FTREG >> 1]) });
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
- break;
- case 0x32: // C.EQ.S (equal)
- if (f32_eq(float32_t{ u32(m_f[FSREG >> 1]) }, float32_t{ u32(m_f[FTREG >> 1]) }))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
- break;
- case 0x33: // C.UEQ.S (unordered equal)
- if (f32_eq(float32_t{ u32(m_f[FSREG >> 1]) }, float32_t{ u32(m_f[FTREG >> 1]) }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
- break;
- case 0x34: // C.OLT.S (less than)
- if (f32_lt(float32_t{ u32(m_f[FSREG >> 1]) }, float32_t{ u32(m_f[FTREG >> 1]) }))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
- break;
- case 0x35: // C.ULT.S (unordered less than)
- if (f32_lt(float32_t{ u32(m_f[FSREG >> 1]) }, float32_t{ u32(m_f[FTREG >> 1]) }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
- break;
- case 0x36: // C.OLE.S (less than or equal)
- if (f32_le(float32_t{ u32(m_f[FSREG >> 1]) }, float32_t{ u32(m_f[FTREG >> 1]) }))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
- break;
- case 0x37: // C.ULE.S (unordered less than or equal)
- if (f32_le(float32_t{ u32(m_f[FSREG >> 1]) }, float32_t{ u32(m_f[FTREG >> 1]) }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
- break;
+void mips1core_device_base::execute_run()
+{
+ // check for IRQs
+ check_irqs();
- case 0x38: // C.SF.S (signalling false)
- f32_eq(float32_t{ u32(m_f[FSREG >> 1]) }, float32_t{ u32(m_f[FTREG >> 1]) });
+ // core execution loop
+ do
+ {
+ // debugging
+ debugger_instruction_hook(m_pc);
- m_fcr31 &= ~FCR31_C;
+#if ENABLE_IOP_KPUTS
+ if ((m_pc & 0x1fffffff) == 0x00012C48 || (m_pc & 0x1fffffff) == 0x0001420C || (m_pc & 0x1fffffff) == 0x0001430C)
+ {
+ u32 ptr = m_r[5];
+ u32 length = m_r[6];
+ if (length >= 4096)
+ length = 4095;
+ while (length)
+ {
+ load<u8>(ptr, [this](char c) { printf("%c", c); });
+ ptr++;
+ length--;
+ }
+ fflush(stdout);
+ }
+#endif
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
+ // fetch and execute instruction
+ fetch(m_pc, [this](u32 const op)
+ {
+ // parse the instruction
+ switch (op >> 26)
{
- m_fcr31 |= FCR31_CV;
- execute_set_input(m_fpu_irq, ASSERT_LINE);
- }
- break;
- case 0x39: // C.NGLE.S (not greater, less than or equal)
- f32_eq(float32_t{ u32(m_f[FSREG >> 1]) }, float32_t{ u32(m_f[FTREG >> 1]) });
+ case 0x00: /* SPECIAL */
+ switch (op & 63)
+ {
+ case 0x00: /* SLL */ if (RDREG) RDVAL = RTVAL << SHIFT; break;
+ case 0x02: /* SRL */ if (RDREG) RDVAL = RTVAL >> SHIFT; break;
+ case 0x03: /* SRA */ if (RDREG) RDVAL = s32(RTVAL) >> SHIFT; break;
+ case 0x04: /* SLLV */ if (RDREG) RDVAL = RTVAL << (RSVAL & 31); break;
+ case 0x06: /* SRLV */ if (RDREG) RDVAL = RTVAL >> (RSVAL & 31); break;
+ case 0x07: /* SRAV */ if (RDREG) RDVAL = s32(RTVAL) >> (RSVAL & 31); break;
+ case 0x08: /* JR */ SETPC(RSVAL); break;
+ case 0x09: /* JALR */ SETPCL(RSVAL, RDREG); break;
+ case 0x0c: /* SYSCALL */ generate_exception(EXCEPTION_SYSCALL); break;
+ case 0x0d: /* BREAK */ generate_exception(EXCEPTION_BREAK); break;
+ case 0x0f: /* SYNC */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x10: /* MFHI */ if (RDREG) RDVAL = m_hi; break;
+ case 0x11: /* MTHI */ m_hi = RSVAL; break;
+ case 0x12: /* MFLO */ if (RDREG) RDVAL = m_lo; break;
+ case 0x13: /* MTLO */ m_lo = RSVAL; break;
+ case 0x18: /* MULT */
+ {
+ u64 product = mul_32x32(RSVAL, RTVAL);
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- {
- m_fcr31 |= FCR31_C | FCR31_CV;
- execute_set_input(m_fpu_irq, ASSERT_LINE);
- }
- else
- m_fcr31 &= ~FCR31_C;
- break;
- case 0x3a: // C.SEQ.S (signalling equal)
- if (f32_eq(float32_t{ u32(m_f[FSREG >> 1]) }, float32_t{ u32(m_f[FTREG >> 1]) }))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
+ m_lo = product;
+ m_hi = product >> 32;
+ m_icount -= 11;
+ }
+ break;
+ case 0x19: /* MULTU */
+ {
+ u64 product = mulu_32x32(RSVAL, RTVAL);
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- {
- m_fcr31 |= FCR31_CV;
- execute_set_input(m_fpu_irq, ASSERT_LINE);
- }
- break;
- case 0x3b: // C.NGL.S (not greater or less than)
- if (f32_eq(float32_t{ u32(m_f[FSREG >> 1]) }, float32_t{ u32(m_f[FTREG >> 1]) }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
+ m_lo = product;
+ m_hi = product >> 32;
+ m_icount -= 11;
+ }
+ break;
+ case 0x1a: /* DIV */
+ if (RTVAL)
+ {
+ m_lo = s32(RSVAL) / s32(RTVAL);
+ m_hi = s32(RSVAL) % s32(RTVAL);
+ }
+ m_icount -= 34;
+ break;
+ case 0x1b: /* DIVU */
+ if (RTVAL)
+ {
+ m_lo = RSVAL / RTVAL;
+ m_hi = RSVAL % RTVAL;
+ }
+ m_icount -= 34;
+ break;
+ case 0x20: /* ADD */
+ {
+ u32 const sum = RSVAL + RTVAL;
+
+ // overflow: (sign(addend0) == sign(addend1)) && (sign(addend0) != sign(sum))
+ if (!BIT(RSVAL ^ RTVAL, 31) && BIT(RSVAL ^ sum, 31))
+ generate_exception(EXCEPTION_OVERFLOW);
+ else if (RDREG)
+ RDVAL = sum;
+ }
+ break;
+ case 0x21: /* ADDU */ if (RDREG) RDVAL = RSVAL + RTVAL; break;
+ case 0x22: /* SUB */
+ {
+ u32 const difference = RSVAL - RTVAL;
+
+ // overflow: (sign(minuend) != sign(subtrahend)) && (sign(minuend) != sign(difference))
+ if (BIT(RSVAL ^ RTVAL, 31) && BIT(RSVAL ^ difference, 31))
+ generate_exception(EXCEPTION_OVERFLOW);
+ else if (RDREG)
+ RDVAL = difference;
+ }
+ break;
+ case 0x23: /* SUBU */ if (RDREG) RDVAL = RSVAL - RTVAL; break;
+ case 0x24: /* AND */ if (RDREG) RDVAL = RSVAL & RTVAL; break;
+ case 0x25: /* OR */ if (RDREG) RDVAL = RSVAL | RTVAL; break;
+ case 0x26: /* XOR */ if (RDREG) RDVAL = RSVAL ^ RTVAL; break;
+ case 0x27: /* NOR */ if (RDREG) RDVAL = ~(RSVAL | RTVAL); break;
+ case 0x2a: /* SLT */ if (RDREG) RDVAL = s32(RSVAL) < s32(RTVAL); break;
+ case 0x2b: /* SLTU */ if (RDREG) RDVAL = u32(RSVAL) < u32(RTVAL); break;
+ case 0x30: /* TEQ */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x31: /* TGEU */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x32: /* TLT */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x33: /* TLTU */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x34: /* TGE */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x36: /* TNE */ generate_exception(EXCEPTION_INVALIDOP); break;
+ default: /* ??? */ generate_exception(EXCEPTION_INVALIDOP); break;
+ }
+ break;
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- {
- m_fcr31 |= FCR31_CV;
- execute_set_input(m_fpu_irq, ASSERT_LINE);
- }
- break;
- case 0x3c: // C.LT.S (less than)
- if (f32_lt(float32_t{ u32(m_f[FSREG >> 1]) }, float32_t{ u32(m_f[FTREG >> 1]) }))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
+ case 0x01: /* REGIMM */
+ switch (RTREG)
+ {
+ case 0x00: /* BLTZ */ if (s32(RSVAL) < 0) ADDPC(SIMMVAL); break;
+ case 0x01: /* BGEZ */ if (s32(RSVAL) >= 0) ADDPC(SIMMVAL); break;
+ case 0x02: /* BLTZL */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x03: /* BGEZL */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x08: /* TGEI */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x09: /* TGEIU */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x0a: /* TLTI */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x0b: /* TLTIU */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x0c: /* TEQI */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x0e: /* TNEI */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x10: /* BLTZAL */ if (s32(RSVAL) < 0) ADDPCL(SIMMVAL, 31); break;
+ case 0x11: /* BGEZAL */ if (s32(RSVAL) >= 0) ADDPCL(SIMMVAL, 31); break;
+ case 0x12: /* BLTZALL */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x13: /* BGEZALL */ generate_exception(EXCEPTION_INVALIDOP); break;
+ default: /* ??? */ generate_exception(EXCEPTION_INVALIDOP); break;
+ }
+ break;
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- {
- m_fcr31 |= FCR31_CV;
- execute_set_input(m_fpu_irq, ASSERT_LINE);
- }
- break;
- case 0x3d: // C.NGE.S (not greater or equal)
- if (f32_lt(float32_t{ u32(m_f[FSREG >> 1]) }, float32_t{ u32(m_f[FTREG >> 1]) }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
+ case 0x02: /* J */ ABSPC(LIMMVAL); break;
+ case 0x03: /* JAL */ ABSPCL(LIMMVAL, 31); break;
+ case 0x04: /* BEQ */ if (RSVAL == RTVAL) ADDPC(SIMMVAL); break;
+ case 0x05: /* BNE */ if (RSVAL != RTVAL) ADDPC(SIMMVAL); break;
+ case 0x06: /* BLEZ */ if (s32(RSVAL) <= 0) ADDPC(SIMMVAL); break;
+ case 0x07: /* BGTZ */ if (s32(RSVAL) > 0) ADDPC(SIMMVAL); break;
+ case 0x08: /* ADDI */
+ {
+ u32 const sum = RSVAL + SIMMVAL;
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- {
- m_fcr31 |= FCR31_CV;
- execute_set_input(m_fpu_irq, ASSERT_LINE);
+ // overflow: (sign(addend0) == sign(addend1)) && (sign(addend0) != sign(sum))
+ if (!BIT(RSVAL ^ s32(SIMMVAL), 31) && BIT(RSVAL ^ sum, 31))
+ generate_exception(EXCEPTION_OVERFLOW);
+ else if (RTREG)
+ RTVAL = sum;
+ }
+ break;
+ case 0x09: /* ADDIU */ if (RTREG) RTVAL = RSVAL + SIMMVAL; break;
+ case 0x0a: /* SLTI */ if (RTREG) RTVAL = s32(RSVAL) < s32(SIMMVAL); break;
+ case 0x0b: /* SLTIU */ if (RTREG) RTVAL = u32(RSVAL) < u32(SIMMVAL); break;
+ case 0x0c: /* ANDI */ if (RTREG) RTVAL = RSVAL & UIMMVAL; break;
+ case 0x0d: /* ORI */ if (RTREG) RTVAL = RSVAL | UIMMVAL; break;
+ case 0x0e: /* XORI */ if (RTREG) RTVAL = RSVAL ^ UIMMVAL; break;
+ case 0x0f: /* LUI */ if (RTREG) RTVAL = UIMMVAL << 16; break;
+ case 0x10: /* COP0 */
+ if (!(SR & SR_KUc) || (SR & SR_COP0))
+ handle_cop0(op);
+ else
+ generate_exception(EXCEPTION_BADCOP);
+ break;
+ case 0x11: // COP1
+ if (SR & SR_COP1)
+ handle_cop1(op);
+ else
+ generate_exception(EXCEPTION_BADCOP);
+ break;
+ case 0x12: // COP2
+ if (SR & SR_COP2)
+ handle_cop<2>(op);
+ else
+ generate_exception(EXCEPTION_BADCOP);
+ break;
+ case 0x13: // COP3
+ if (SR & SR_COP3)
+ handle_cop<3>(op);
+ else
+ generate_exception(EXCEPTION_BADCOP);
+ break;
+ case 0x14: /* BEQL */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x15: /* BNEL */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x16: /* BLEZL */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x17: /* BGTZL */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x20: /* LB */ load<u8>(SIMMVAL + RSVAL, [this, op](s8 temp) { if (RTREG) RTVAL = temp; }); break;
+ case 0x21: /* LH */ load<u16>(SIMMVAL + RSVAL, [this, op](s16 temp) { if (RTREG) RTVAL = temp; }); break;
+ case 0x22: /* LWL */ lwl(op); break;
+ case 0x23: /* LW */ load<u32>(SIMMVAL + RSVAL, [this, op](u32 temp) { if (RTREG) RTVAL = temp; }); break;
+ case 0x24: /* LBU */ load<u8>(SIMMVAL + RSVAL, [this, op](u8 temp) { if (RTREG) RTVAL = temp; }); break;
+ case 0x25: /* LHU */ load<u16>(SIMMVAL + RSVAL, [this, op](u16 temp) { if (RTREG) RTVAL = temp; }); break;
+ case 0x26: /* LWR */ lwr(op); break;
+ case 0x28: /* SB */ store<u8>(SIMMVAL + RSVAL, RTVAL); break;
+ case 0x29: /* SH */ store<u16>(SIMMVAL + RSVAL, RTVAL); break;
+ case 0x2a: /* SWL */ swl(op); break;
+ case 0x2b: /* SW */ store<u32>(SIMMVAL + RSVAL, RTVAL); break;
+ case 0x2e: /* SWR */ swr(op); break;
+ case 0x2f: /* CACHE */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x30: /* LL */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x31: /* LWC1 */ load<u32>(SIMMVAL + RSVAL, [this, op](u32 temp) { set_cop_reg<1>(RTREG, temp); }); break;
+ case 0x32: /* LWC2 */ load<u32>(SIMMVAL + RSVAL, [this, op](u32 temp) { set_cop_reg<2>(RTREG, temp); }); break;
+ case 0x33: /* LWC3 */ load<u32>(SIMMVAL + RSVAL, [this, op](u32 temp) { set_cop_reg<3>(RTREG, temp); }); break;
+ case 0x34: /* LDC0 */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x35: /* LDC1 */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x36: /* LDC2 */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x37: /* LDC3 */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x38: /* SC */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x39: /* LWC1 */ store<u32>(SIMMVAL + RSVAL, get_cop_reg<1>(RTREG)); break;
+ case 0x3a: /* LWC2 */ store<u32>(SIMMVAL + RSVAL, get_cop_reg<2>(RTREG)); break;
+ case 0x3b: /* LWC3 */ store<u32>(SIMMVAL + RSVAL, get_cop_reg<3>(RTREG)); break;
+ case 0x3c: /* SDC0 */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x3d: /* SDC1 */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x3e: /* SDC2 */ generate_exception(EXCEPTION_INVALIDOP); break;
+ case 0x3f: /* SDC3 */ generate_exception(EXCEPTION_INVALIDOP); break;
+ default: /* ??? */ generate_exception(EXCEPTION_INVALIDOP); break;
}
+
+ // update pc and branch state
+ switch (m_branch_state)
+ {
+ case NONE:
+ m_pc += 4;
break;
- case 0x3e: // C.LE.S (less than or equal)
- if (f32_le(float32_t{ u32(m_f[FSREG >> 1]) }, float32_t{ u32(m_f[FTREG >> 1]) }))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- {
- m_fcr31 |= FCR31_CV;
- execute_set_input(m_fpu_irq, ASSERT_LINE);
- }
+ case DELAY:
+ m_branch_state = NONE;
+ m_pc = m_branch_target;
break;
- case 0x3f: // C.NGT.S (not greater than)
- if (f32_le(float32_t{ u32(m_f[FSREG >> 1]) }, float32_t{ u32(m_f[FTREG >> 1]) }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- {
- m_fcr31 |= FCR31_CV;
- execute_set_input(m_fpu_irq, ASSERT_LINE);
- }
+ case BRANCH:
+ m_branch_state = DELAY;
+ m_pc += 4;
break;
- default: // unimplemented operation
- m_fcr31 |= FCR31_CE;
- execute_set_input(m_fpu_irq, ASSERT_LINE);
+ case EXCEPTION:
+ m_branch_state = NONE;
break;
}
- break;
- case 0x11: // D
- switch (op & 0x3f)
- {
- case 0x00: // ADD.D
- set_cop1_reg(FDREG >> 1, f64_add(float64_t{ m_f[FSREG >> 1] }, float64_t{ m_f[FTREG >> 1] }).v);
- break;
- case 0x01: // SUB.D
- set_cop1_reg(FDREG >> 1, f64_sub(float64_t{ m_f[FSREG >> 1] }, float64_t{ m_f[FTREG >> 1] }).v);
- break;
- case 0x02: // MUL.D
- set_cop1_reg(FDREG >> 1, f64_mul(float64_t{ m_f[FSREG >> 1] }, float64_t{ m_f[FTREG >> 1] }).v);
- break;
- case 0x03: // DIV.D
- set_cop1_reg(FDREG >> 1, f64_div(float64_t{ m_f[FSREG >> 1] }, float64_t{ m_f[FTREG >> 1] }).v);
- break;
+ });
+ m_icount--;
- case 0x05: // ABS.D
- if (f64_lt(float64_t{ m_f[FSREG >> 1] }, float64_t{ 0 }))
- set_cop1_reg(FDREG >> 1, f64_mul(float64_t{ m_f[FSREG >> 1] }, i32_to_f64(-1)).v);
- else
- set_cop1_reg(FDREG >> 1, m_f[FSREG >> 1]);
- break;
- case 0x06: // MOV.D
- m_f[FDREG >> 1] = m_f[FSREG >> 1];
- break;
- case 0x07: // NEG.D
- set_cop1_reg(FDREG >> 1, f64_mul(float64_t{ m_f[FSREG >> 1] }, i32_to_f64(-1)).v);
- break;
+ } while (m_icount > 0 || m_branch_state);
+}
- case 0x20: // CVT.S.D
- set_cop1_reg(FDREG >> 1, f64_to_f32(float64_t{ m_f[FSREG >> 1] }).v);
- break;
- case 0x24: // CVT.W.D
- set_cop1_reg(FDREG >> 1, f64_to_i32(float64_t{ m_f[FSREG >> 1] }, softfloat_roundingMode, true));
- break;
+void mips1core_device_base::lwl(u32 const op)
+{
+ offs_t const offset = SIMMVAL + RSVAL;
+ load<u32>(offset & ~3, [this, op, offset](u32 temp)
+ {
+ if (RTREG)
+ {
+ unsigned const shift = ((offset & 3) ^ ENDIAN_VALUE_LE_BE(m_endianness, 3, 0)) << 3;
- case 0x30: // C.F.D (false)
- m_fcr31 &= ~FCR31_C;
- break;
- case 0x31: // C.UN.D (unordered)
- f64_eq(float64_t{ m_f[FSREG >> 1] }, float64_t{ m_f[FTREG >> 1] });
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
- break;
- case 0x32: // C.EQ.D (equal)
- if (f64_eq(float64_t{ m_f[FSREG >> 1] }, float64_t{ m_f[FTREG >> 1] }))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
- break;
- case 0x33: // C.UEQ.D (unordered equal)
- if (f64_eq(float64_t{ m_f[FSREG >> 1] }, float64_t{ m_f[FTREG >> 1] }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
- break;
- case 0x34: // C.OLT.D (less than)
- if (f64_lt(float64_t{ m_f[FSREG >> 1] }, float64_t{ m_f[FTREG >> 1] }))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
- break;
- case 0x35: // C.ULT.D (unordered less than)
- if (f64_lt(float64_t{ m_f[FSREG >> 1] }, float64_t{ m_f[FTREG >> 1] }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
- break;
- case 0x36: // C.OLE.D (less than or equal)
- if (f64_le(float64_t{ m_f[FSREG >> 1] }, float64_t{ m_f[FTREG >> 1] }))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
- break;
- case 0x37: // C.ULE.D (unordered less than or equal)
- if (f64_le(float64_t{ m_f[FSREG >> 1] }, float64_t{ m_f[FTREG >> 1] }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
- break;
+ RTVAL = (RTVAL & ~u32(0xffffffffU << shift)) | (temp << shift);
+ }
+ });
+}
- case 0x38: // C.SF.D (signalling false)
- f64_eq(float64_t{ m_f[FSREG >> 1] }, float64_t{ m_f[FTREG >> 1] });
+void mips1core_device_base::lwr(u32 const op)
+{
+ offs_t const offset = SIMMVAL + RSVAL;
+ load<u32>(offset & ~3, [this, op, offset](u32 temp)
+ {
+ if (RTREG)
+ {
+ unsigned const shift = ((offset & 0x3) ^ ENDIAN_VALUE_LE_BE(m_endianness, 0, 3)) << 3;
- m_fcr31 &= ~FCR31_C;
+ RTVAL = (RTVAL & ~u32(0xffffffffU >> shift)) | (temp >> shift);
+ }
+ });
+}
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- {
- m_fcr31 |= FCR31_CV;
- execute_set_input(m_fpu_irq, ASSERT_LINE);
- }
- break;
- case 0x39: // C.NGLE.D (not greater, less than or equal)
- f64_eq(float64_t{ m_f[FSREG >> 1] }, float64_t{ m_f[FTREG >> 1] });
+void mips1core_device_base::swl(u32 const op)
+{
+ offs_t const offset = SIMMVAL + RSVAL;
+ unsigned const shift = ((offset & 3) ^ ENDIAN_VALUE_LE_BE(m_endianness, 3, 0)) << 3;
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- {
- m_fcr31 |= FCR31_C | FCR31_CV;
- execute_set_input(m_fpu_irq, ASSERT_LINE);
- }
- else
- m_fcr31 &= ~FCR31_C;
- break;
- case 0x3a: // C.SEQ.D (signalling equal)
- if (f64_eq(float64_t{ m_f[FSREG >> 1] }, float64_t{ m_f[FTREG >> 1] }))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
+ // only load if necessary
+ if (shift)
+ {
+ load<u32>(offset & ~3, [this, op, offset, shift](u32 temp)
+ {
+ store<u32>(offset & ~3, (temp & ~u32(0xffffffffU >> shift)) | (RTVAL >> shift));
+ });
+ }
+ else
+ store<u32>(offset & ~3, RTVAL);
+}
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- {
- m_fcr31 |= FCR31_CV;
- execute_set_input(m_fpu_irq, ASSERT_LINE);
- }
- break;
- case 0x3b: // C.NGL.D (not greater or less than)
- if (f64_eq(float64_t{ m_f[FSREG >> 1] }, float64_t{ m_f[FTREG >> 1] }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- {
- m_fcr31 |= FCR31_CV;
- execute_set_input(m_fpu_irq, ASSERT_LINE);
- }
- break;
- case 0x3c: // C.LT.D (less than)
- if (f64_lt(float64_t{ m_f[FSREG >> 1] }, float64_t{ m_f[FTREG >> 1] }))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
+void mips1core_device_base::swr(u32 const op)
+{
+ offs_t const offset = SIMMVAL + RSVAL;
+ unsigned const shift = ((offset & 3) ^ ENDIAN_VALUE_LE_BE(m_endianness, 0, 3)) << 3;
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- {
- m_fcr31 |= FCR31_CV;
- execute_set_input(m_fpu_irq, ASSERT_LINE);
- }
- break;
- case 0x3d: // C.NGE.D (not greater or equal)
- if (f64_lt(float64_t{ m_f[FSREG >> 1] }, float64_t{ m_f[FTREG >> 1] }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
+ // only load if necessary
+ if (shift)
+ {
+ load<u32>(offset & ~3, [this, op, offset, shift](u32 temp)
+ {
+ store<u32>(offset & ~3, (temp & ~u32(0xffffffffU << shift)) | (RTVAL << shift));
+ });
+ }
+ else
+ store<u32>(offset & ~3, RTVAL);
+}
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- {
- m_fcr31 |= FCR31_CV;
- execute_set_input(m_fpu_irq, ASSERT_LINE);
- }
- break;
- case 0x3e: // C.LE.D (less than or equal)
- if (f64_le(float64_t{ m_f[FSREG >> 1] }, float64_t{ m_f[FTREG >> 1] }))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
+template <typename T, typename U> std::enable_if_t<std::is_convertible<U, std::function<void(T)>>::value, void> mips1core_device_base::load(u32 program_address, U &&apply)
+{
+ offs_t translated_address = program_address;
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- {
- m_fcr31 |= FCR31_CV;
- execute_set_input(m_fpu_irq, ASSERT_LINE);
- }
- break;
- case 0x3f: // C.NGT.D (not greater than)
- if (f64_le(float64_t{ m_f[FSREG >> 1] }, float64_t{ m_f[FTREG >> 1] }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
+ if (memory_translate(m_data_spacenum, TRANSLATE_READ, translated_address))
+ {
+ switch (sizeof(T))
+ {
+ case 1: apply(T(space(m_data_spacenum).read_byte(translated_address))); break;
+ case 2: apply(T(space(m_data_spacenum).read_word(translated_address))); break;
+ case 4: apply(T(space(m_data_spacenum).read_dword(translated_address))); break;
+ }
+ }
+}
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- {
- m_fcr31 |= FCR31_CV;
- execute_set_input(m_fpu_irq, ASSERT_LINE);
- }
- break;
+template <typename T, typename U> std::enable_if_t<std::is_convertible<U, T>::value, void> mips1core_device_base::store(u32 program_address, U data)
+{
+ offs_t translated_address = program_address;
- default: // unimplemented operation
- m_fcr31 |= FCR31_CE;
- execute_set_input(m_fpu_irq, ASSERT_LINE);
- break;
- }
- break;
- case 0x14: // W
- switch (op & 0x3f)
- {
- case 0x20: // CVT.S.W
- set_cop1_reg(FDREG >> 1, i32_to_f32(s32(m_f[FSREG >> 1])).v);
- break;
- case 0x21: // CVT.D.W
- set_cop1_reg(FDREG >> 1, i32_to_f64(s32(m_f[FSREG >> 1])).v);
- break;
+ if (memory_translate(m_data_spacenum, TRANSLATE_WRITE, translated_address))
+ {
+ switch (sizeof(T))
+ {
+ case 1: space(m_data_spacenum).write_byte(translated_address, T(data)); break;
+ case 2: space(m_data_spacenum).write_word(translated_address, T(data)); break;
+ case 4: space(m_data_spacenum).write_dword(translated_address, T(data)); break;
+ }
+ }
+}
- default: // unimplemented operation
- m_fcr31 |= FCR31_CE;
- execute_set_input(m_fpu_irq, ASSERT_LINE);
- break;
- }
- break;
+bool mips1core_device_base::fetch(u32 program_address, std::function<void(u32)> &&apply)
+{
+ offs_t translated_address = program_address;
- default: // unimplemented operation
- m_fcr31 |= FCR31_CE;
- execute_set_input(m_fpu_irq, ASSERT_LINE);
- break;
- }
- break;
- case 0x31: // LWC1
- load<u32>(SIMMVAL + m_r[RSREG],
- [this, op](u32 data)
- {
- if (FTREG & 1)
- // load the high half of the floating point register
- m_f[FTREG >> 1] = (u64(data) << 32) | u32(m_f[FTREG >> 1]);
- else
- // load the low half of the floating point register
- m_f[FTREG >> 1] = (m_f[FTREG >> 1] & ~0xffffffffULL) | data;
- });
- break;
- case 0x39: // SWC1
- if (FTREG & 1)
- // store the high half of the floating point register
- store<u32>(SIMMVAL + m_r[RSREG], m_f[FTREG >> 1] >> 32);
- else
- // store the low half of the floating point register
- store<u32>(SIMMVAL + m_r[RSREG], m_f[FTREG >> 1]);
- break;
+ if (memory_translate(0, TRANSLATE_FETCH, translated_address))
+ {
+ apply(space(0).read_dword(translated_address));
+
+ return true;
}
+ else
+ return false;
}
-void mips1_device_base::set_cop1_reg(unsigned const reg, u64 const data)
+bool mips1core_device_base::memory_translate(int spacenum, int intention, offs_t &address)
{
- // translate softfloat exception flags to cause register
- if (softfloat_exceptionFlags)
+ // check for kernel memory address
+ if (BIT(address, 31))
{
- if (softfloat_exceptionFlags & softfloat_flag_inexact)
- m_fcr31 |= FCR31_CI;
- if (softfloat_exceptionFlags & softfloat_flag_underflow)
- m_fcr31 |= FCR31_CU;
- if (softfloat_exceptionFlags & softfloat_flag_overflow)
- m_fcr31 |= FCR31_CO;
- if (softfloat_exceptionFlags & softfloat_flag_infinite)
- m_fcr31 |= FCR31_CZ;
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- m_fcr31 |= FCR31_CV;
-
- // check if exception is enabled
- if (((m_fcr31 & FCR31_CM) >> 5) & (m_fcr31 & FCR31_EM))
+ // check debug or kernel mode
+ if ((intention & TRANSLATE_DEBUG_MASK) || !(SR & SR_KUc))
{
- execute_set_input(m_fpu_irq, ASSERT_LINE);
- return;
+ switch (address & 0xe0000000)
+ {
+ case 0x80000000: // kseg0: unmapped, cached, privileged
+ case 0xa0000000: // kseg1: unmapped, uncached, privileged
+ address &= ~0xe0000000;
+ break;
+
+ case 0xc0000000: // kseg2: mapped, cached, privileged
+ case 0xe0000000:
+ break;
+ }
}
+ else if (SR & SR_KUc)
+ {
+ // exception
+ m_cpr[0][COP0_BadVAddr] = address;
- // set flags
- m_fcr31 |= ((m_fcr31 & FCR31_CM) >> 10);
+ generate_exception((intention & TRANSLATE_WRITE) ? EXCEPTION_ADDRSTORE : EXCEPTION_ADDRLOAD);
+ return false;
+ }
}
+ else
+ // kuseg physical addresses have a 1GB offset
+ address += 0x40000000;
- m_f[reg] = data;
+ return true;
}
bool mips1_device_base::memory_translate(int spacenum, int intention, offs_t &address)
@@ -1854,30 +982,21 @@ bool mips1_device_base::memory_translate(int spacenum, int intention, offs_t &ad
}
else if (SR & SR_KUc)
{
- if (!machine().side_effects_disabled())
- {
- // exception
- m_cop0[COP0_BadVAddr] = address;
+ // exception
+ m_cpr[0][COP0_BadVAddr] = address;
- generate_exception((intention & TRANSLATE_WRITE) ? EXCEPTION_ADDRSTORE : EXCEPTION_ADDRLOAD);
- }
+ generate_exception((intention & TRANSLATE_WRITE) ? EXCEPTION_ADDRSTORE : EXCEPTION_ADDRLOAD);
return false;
}
}
// key is a combination of VPN and ASID
- u32 const key = (address & EH_VPN) | (m_cop0[COP0_EntryHi] & EH_ASID);
-
- unsigned *mru = m_tlb_mru[intention & TRANSLATE_TYPE_MASK];
-
+ u32 const key = (address & EH_VPN) | (m_cpr[0][COP0_EntryHi] & EH_ASID);
bool refill = !BIT(address, 31);
- bool modify = false;
+ bool dirty = false;
- for (unsigned i = 0; i < ARRAY_LENGTH(m_tlb); i++)
+ for (u32 const *entry : m_tlb)
{
- unsigned const index = mru[i];
- u32 const *const entry = m_tlb[index];
-
// test vpn and optionally asid
u32 const mask = (entry[1] & EL_G) ? EH_VPN : EH_VPN | EH_ASID;
if ((entry[0] & mask) != (key & mask))
@@ -1894,39 +1013,28 @@ bool mips1_device_base::memory_translate(int spacenum, int intention, offs_t &ad
if ((intention & TRANSLATE_WRITE) && !(entry[1] & EL_D))
{
refill = false;
- modify = true;
+ dirty = true;
break;
}
// translate the address
address &= ~EH_VPN;
address |= (entry[1] & EL_PFN);
-
- // promote the entry in the mru index
- if (i > 0)
- std::swap(mru[i - 1], mru[i]);
-
return true;
}
- if (!machine().side_effects_disabled() && !(intention & TRANSLATE_DEBUG_MASK))
+ if (!(intention & TRANSLATE_DEBUG_MASK))
{
- if (VERBOSE & LOG_TLB)
- {
- if (modify)
- LOGMASKED(LOG_TLB, "tlb modify asid %d address 0x%08x (%s)\n",
- (m_cop0[COP0_EntryHi] & EH_ASID) >> 6, address, machine().describe_context());
- else
- LOGMASKED(LOG_TLB, "tlb miss %c asid %d address 0x%08x (%s)\n",
- (intention & TRANSLATE_WRITE) ? 'w' : 'r', (m_cop0[COP0_EntryHi] & EH_ASID) >> 6, address, machine().describe_context());
- }
+ if ((VERBOSE & LOG_TLB) && !dirty)
+ LOGMASKED(LOG_TLB, "tlb miss %c asid %d address 0x%08x (%s)\n",
+ (intention & TRANSLATE_WRITE) ? 'w' : 'r', (m_cpr[0][COP0_EntryHi] & EH_ASID) >> 6, address, machine().describe_context());
// load tlb exception registers
- m_cop0[COP0_BadVAddr] = address;
- m_cop0[COP0_EntryHi] = key;
- m_cop0[COP0_Context] = (m_cop0[COP0_Context] & PTE_BASE) | ((address >> 10) & BAD_VPN);
+ m_cpr[0][COP0_BadVAddr] = address;
+ m_cpr[0][COP0_EntryHi] = key;
+ m_cpr[0][COP0_Context] = (m_cpr[0][COP0_Context] & PTE_BASE) | ((address >> 10) & BAD_VPN);
- generate_exception(modify ? EXCEPTION_TLBMOD : (intention & TRANSLATE_WRITE) ? EXCEPTION_TLBSTORE : EXCEPTION_TLBLOAD, refill);
+ generate_exception(dirty ? EXCEPTION_TLBMOD : (intention & TRANSLATE_WRITE) ? EXCEPTION_TLBSTORE : EXCEPTION_TLBLOAD, refill);
}
return false;
diff --git a/src/devices/cpu/mips/mips1.h b/src/devices/cpu/mips/mips1.h
index 3ae34e4b69f..d77bdef3cdb 100644
--- a/src/devices/cpu/mips/mips1.h
+++ b/src/devices/cpu/mips/mips1.h
@@ -9,8 +9,21 @@
class mips1core_device_base : public cpu_device
{
public:
+ // floating point coprocessor revision numbers recognised by RISC/os 4.52 and IRIX
+ enum fpu_rev_t : u32
+ {
+ MIPS_R2360 = 0x0100, // MIPS R2360 Floating Point Board
+ MIPS_R2010 = 0x0200, // MIPS R2010 VLSI Floating Point Chip
+ MIPS_R2010A = 0x0310, // MIPS R2010A VLSI Floating Point Chip
+ MIPS_R3010 = 0x0320, // MIPS R3010 VLSI Floating Point Chip
+ MIPS_R3010A = 0x0330, // MIPS R3010A VLSI Floating Point Chip
+ MIPS_R3010Av4 = 0x0340, // MIPS R3010A VLSI Floating Point Chip
+ MIPS_R6010 = 0x0400, // MIPS R6010 Floating Point Chip
+ };
+
// device configuration
void set_endianness(endianness_t endianness) { m_endianness = endianness; }
+ void set_fpurev(u32 revision) { m_hasfpu = true; m_fpurev = revision; }
// input lines
template <unsigned Coprocessor> auto in_brcond() { return m_in_brcond[Coprocessor].bind(); }
@@ -18,40 +31,53 @@ public:
protected:
mips1core_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 cpurev, size_t icache_size, size_t dcache_size);
- enum registers : unsigned
+ enum registers
{
- MIPS1_R0 = 0,
- MIPS1_COP0 = 32,
- MIPS1_F0 = 64,
+ // general purpose cpu registers
+ MIPS1_R0, MIPS1_R1, MIPS1_R2, MIPS1_R3, MIPS1_R4, MIPS1_R5, MIPS1_R6, MIPS1_R7,
+ MIPS1_R8, MIPS1_R9, MIPS1_R10, MIPS1_R11, MIPS1_R12, MIPS1_R13, MIPS1_R14, MIPS1_R15,
+ MIPS1_R16, MIPS1_R17, MIPS1_R18, MIPS1_R19, MIPS1_R20, MIPS1_R21, MIPS1_R22, MIPS1_R23,
+ MIPS1_R24, MIPS1_R25, MIPS1_R26, MIPS1_R27, MIPS1_R28, MIPS1_R29, MIPS1_R30, MIPS1_R31,
- MIPS1_PC = 80,
+ // other cpu registers
MIPS1_HI,
MIPS1_LO,
- MIPS1_FCR30,
- MIPS1_FCR31,
+ MIPS1_PC,
+
+ // coprocessor 0 registers
+ MIPS1_COP0_INDEX, // reg 0, tlb only
+ MIPS1_COP0_RANDOM, // reg 1, tlb only
+ MIPS1_COP0_ENTRYLO, // reg 2, tlb only
+ MIPS1_COP0_BUSCTRL, // reg 2, r3041 only
+ MIPS1_COP0_CONFIG, // reg 3, r3041/r3071/r3081 only
+ MIPS1_COP0_CONTEXT, // reg 4, tlb only
+ MIPS1_COP0_BADVADDR, // reg 8
+ MIPS1_COP0_COUNT, // reg 9, r3041 only
+ MIPS1_COP0_ENTRYHI, // reg 10, tlb only
+ MIPS1_COP0_PORTSIZE, // reg 10, r3041 only
+ MIPS1_COP0_COMPARE, // reg 11, r3041 only
+ MIPS1_COP0_SR, // reg 12
+ MIPS1_COP0_CAUSE, // reg 13
+ MIPS1_COP0_EPC, // reg 14
+ MIPS1_COP0_PRID, // reg 15
};
- enum exception : u32
+ enum exception : int
{
- EXCEPTION_INTERRUPT = 0x00000000,
- EXCEPTION_TLBMOD = 0x00000004,
- EXCEPTION_TLBLOAD = 0x00000008,
- EXCEPTION_TLBSTORE = 0x0000000c,
- EXCEPTION_ADDRLOAD = 0x00000010,
- EXCEPTION_ADDRSTORE = 0x00000014,
- EXCEPTION_BUSINST = 0x00000018,
- EXCEPTION_BUSDATA = 0x0000001c,
- EXCEPTION_SYSCALL = 0x00000020,
- EXCEPTION_BREAK = 0x00000024,
- EXCEPTION_INVALIDOP = 0x00000028,
- EXCEPTION_BADCOP = 0x0000002c,
- EXCEPTION_OVERFLOW = 0x00000030,
- EXCEPTION_TRAP = 0x00000034,
-
- EXCEPTION_BADCOP0 = 0x0000002c,
- EXCEPTION_BADCOP1 = 0x1000002c,
- EXCEPTION_BADCOP2 = 0x2000002c,
- EXCEPTION_BADCOP3 = 0x3000002c,
+ EXCEPTION_INTERRUPT = 0,
+ EXCEPTION_TLBMOD = 1,
+ EXCEPTION_TLBLOAD = 2,
+ EXCEPTION_TLBSTORE = 3,
+ EXCEPTION_ADDRLOAD = 4,
+ EXCEPTION_ADDRSTORE = 5,
+ EXCEPTION_BUSINST = 6,
+ EXCEPTION_BUSDATA = 7,
+ EXCEPTION_SYSCALL = 8,
+ EXCEPTION_BREAK = 9,
+ EXCEPTION_INVALIDOP = 10,
+ EXCEPTION_BADCOP = 11,
+ EXCEPTION_OVERFLOW = 12,
+ EXCEPTION_TRAP = 13,
};
enum cop0_reg : u8
@@ -101,29 +127,6 @@ protected:
SR_COP1 = 0x20000000, // coprocessor 1 usable
SR_COP2 = 0x40000000, // coprocessor 2 usable
SR_COP3 = 0x80000000, // coprocessor 3 usable
-
- SR_KUIE = 0x0000003f, // all interrupt enable and user mode bits
- SR_KUIEpc = 0x0000000f, // previous and current interrupt enable and user mode bits
- SR_KUIEop = 0x0000003c, // old and previous interrupt enable and user mode bits
- SR_IM = 0x0000ff00, // all interrupt mask bits
- };
-
- enum cause_mask : u32
- {
- CAUSE_EXCCODE = 0x0000007c, // exception code
- CAUSE_IPSW0 = 0x00000100, // software interrupt 0 pending
- CAUSE_IPSW1 = 0x00000200, // software interrupt 1 pending
- CAUSE_IPEX0 = 0x00000400, // external interrupt 0 pending
- CAUSE_IPEX1 = 0x00000800, // external interrupt 1 pending
- CAUSE_IPEX2 = 0x00001000, // external interrupt 2 pending
- CAUSE_IPEX3 = 0x00002000, // external interrupt 3 pending
- CAUSE_IPEX4 = 0x00004000, // external interrupt 4 pending
- CAUSE_IPEX5 = 0x00008000, // external interrupt 5 pending
- CAUSE_IP = 0x0000ff00, // interrupt pending
- CAUSE_CE = 0x30000000, // co-processor error
- CAUSE_BD = 0x80000000, // branch delay
-
- CAUSE_IPEX = 0x0000fc00, // external interrupt pending
};
enum entryhi_mask : u32
@@ -155,7 +158,7 @@ protected:
virtual u32 execute_max_cycles() const override { return 40; }
virtual u32 execute_input_lines() const override { return 6; }
virtual void execute_run() override;
- virtual void execute_set_input(int inputnum, int state) override;
+ virtual void execute_set_input(int inputnum, int state) override { set_irq_line(inputnum, state); }
// device_memory_interface overrides
virtual space_config_vector memory_space_config() const override;
@@ -168,18 +171,25 @@ protected:
void dcache_map(address_map &map);
// interrupts
- void generate_exception(u32 exception, bool refill = false);
+ void generate_exception(int exception, bool refill = false);
void check_irqs();
+ void set_irq_line(int irqline, int state);
// cop0
+ virtual u32 get_cop0_reg(int const index);
+ void set_cop0_reg(int const index, u32 const data);
virtual void handle_cop0(u32 const op);
- virtual u32 get_cop0_reg(unsigned const reg);
- virtual void set_cop0_reg(unsigned const reg, u32 const data);
- // other coprocessors
- virtual void handle_cop1(u32 const op);
- virtual void handle_cop2(u32 const op);
- virtual void handle_cop3(u32 const op);
+ // cop1
+ void set_cop1_creg(int const index, u32 const data);
+ void handle_cop1(u32 const op);
+
+ // generic coprocessor implementation
+ template <unsigned Coprocessor> void handle_cop(u32 const op);
+ template <unsigned Coprocessor> u32 get_cop_reg(int const index) { return m_cpr[Coprocessor][index]; }
+ template <unsigned Coprocessor> void set_cop_reg(int const index, u32 const data) { m_cpr[Coprocessor][index] = data; }
+ template <unsigned Coprocessor> u32 get_cop_creg(int const index) { return m_ccr[Coprocessor][index]; }
+ template <unsigned Coprocessor> void set_cop_creg(int const index, u32 const data) { m_ccr[Coprocessor][index] = data; }
// load/store left/right opcodes
void lwl(u32 const op);
@@ -188,13 +198,9 @@ protected:
void swr(u32 const op);
// memory accessors
- template <typename T, typename U> std::enable_if_t<std::is_convertible<U, std::function<void(T)>>::value, void> load(u32 address, U &&apply);
- template <typename T, typename U> std::enable_if_t<std::is_convertible<U, T>::value, void> store(u32 address, U data, T mem_mask = ~T(0));
- bool fetch(u32 address, std::function<void(u32)> &&apply);
-
- // debug helpers
- std::string debug_string(u32 string_pointer, unsigned const limit = 0);
- std::string debug_string_array(u32 array_pointer);
+ template <typename T, typename U> std::enable_if_t<std::is_convertible<U, std::function<void(T)>>::value, void> load(u32 program_address, U &&apply);
+ template <typename T, typename U> std::enable_if_t<std::is_convertible<U, T>::value, void> store(u32 program_address, U data);
+ bool fetch(u32 program_address, std::function<void(u32)> &&apply);
// address spaces
const address_space_config m_program_config_be;
@@ -206,16 +212,19 @@ protected:
// configuration
u32 m_cpurev;
+ bool m_hasfpu;
+ u32 m_fpurev;
endianness_t m_endianness;
// core registers
u32 m_pc;
- u32 m_r[32];
u32 m_hi;
u32 m_lo;
+ u32 m_r[32];
- // cop0 registers
- u32 m_cop0[32];
+ // COP registers
+ u32 m_cpr[4][32];
+ u32 m_ccr[4][32];
// internal stuff
int m_icount;
@@ -239,54 +248,9 @@ protected:
class mips1_device_base : public mips1core_device_base
{
-public:
- // floating point coprocessor revision numbers recognised by RISC/os 4.52 and IRIX
- enum fpu_rev_t : u32
- {
- MIPS_R2360 = 0x0100, // MIPS R2360 Floating Point Board
- MIPS_R2010 = 0x0200, // MIPS R2010 VLSI Floating Point Chip
- MIPS_R2010A = 0x0310, // MIPS R2010A VLSI Floating Point Chip
- MIPS_R3010 = 0x0320, // MIPS R3010 VLSI Floating Point Chip
- MIPS_R3010A = 0x0330, // MIPS R3010A VLSI Floating Point Chip
- MIPS_R3010Av4 = 0x0340, // MIPS R3010A VLSI Floating Point Chip
- MIPS_R6010 = 0x0400, // MIPS R6010 Floating Point Chip
- };
-
- void set_fpu(u32 revision, unsigned interrupt = 3) { m_fcr0 = revision; m_fpu_irq = interrupt; }
-
protected:
mips1_device_base(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 cpurev, size_t icache_size, size_t dcache_size);
- enum cp1_fcr31_mask : u32
- {
- FCR31_RM = 0x00000003, // rounding mode
-
- FCR31_FI = 0x00000004, // inexact operation flag
- FCR31_FU = 0x00000008, // underflow flag
- FCR31_FO = 0x00000010, // overflow flag
- FCR31_FZ = 0x00000020, // divide by zero flag
- FCR31_FV = 0x00000040, // invalid operation flag
-
- FCR31_EI = 0x00000080, // inexact operation enable
- FCR31_EU = 0x00000100, // underflow enable
- FCR31_EO = 0x00000200, // overflow enable
- FCR31_EZ = 0x00000400, // divide by zero enable
- FCR31_EV = 0x00000800, // invalid operation enable
-
- FCR31_CI = 0x00001000, // inexact operation cause
- FCR31_CU = 0x00002000, // underflow cause
- FCR31_CO = 0x00004000, // overflow cause
- FCR31_CZ = 0x00008000, // divide by zero cause
- FCR31_CV = 0x00010000, // invalid operation cause
- FCR31_CE = 0x00020000, // unimplemented operation cause
-
- FCR31_C = 0x00800000, // condition
-
- FCR31_FM = 0x0000007c, // flag mask
- FCR31_EM = 0x00000f80, // enable mask
- FCR31_CM = 0x0001f000, // cause mask (except unimplemented)
- };
-
// device_t overrides
virtual void device_start() override;
virtual void device_reset() override;
@@ -294,24 +258,12 @@ protected:
// device_memory_interface overrides
virtual bool memory_translate(int spacenum, int intention, offs_t &address) override;
+ virtual u32 get_cop0_reg(int idx) override;
virtual void handle_cop0(u32 const op) override;
- virtual u32 get_cop0_reg(unsigned const reg) override;
-
- virtual void handle_cop1(u32 const op) override;
- virtual void set_cop1_reg(unsigned const reg, u64 const data);
private:
u64 m_reset_time;
u32 m_tlb[64][2]; // 0 is hi, 1 is lo
- unsigned m_tlb_mru[3][64];
-
- // cop1 registers
- u64 m_f[16];
- u32 m_fcr0;
- u32 m_fcr30;
- u32 m_fcr31;
-
- unsigned m_fpu_irq;
};
class r2000_device : public mips1_device_base
@@ -365,13 +317,13 @@ public:
r3052e_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
};
-class r3071_device : public mips1_device_base
+class r3071_device : public mips1core_device_base
{
public:
r3071_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, size_t icache_size = 16384, size_t dcache_size = 4096);
};
-class r3081_device : public mips1_device_base
+class r3081_device : public mips1core_device_base
{
public:
r3081_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock, size_t icache_size = 16384, size_t dcache_size = 4096);
diff --git a/src/devices/cpu/mips/mips3.cpp b/src/devices/cpu/mips/mips3.cpp
index 178d81fadbd..8c8816b8e23 100644
--- a/src/devices/cpu/mips/mips3.cpp
+++ b/src/devices/cpu/mips/mips3.cpp
@@ -16,10 +16,9 @@
#include "ps2vu.h"
#include <cmath>
-#define ENABLE_OVERFLOWS (0)
-#define ENABLE_EE_ELF_LOADER (0)
-#define ENABLE_EE_DECI2 (0)
-#define DELAY_SLOT_EXCEPTION_HACK (0)
+#define ENABLE_OVERFLOWS (0)
+#define ENABLE_EE_ELF_LOADER (0)
+#define ENABLE_EE_DECI2 (0)
/***************************************************************************
HELPER MACROS
@@ -161,15 +160,13 @@ mips3_device::mips3_device(const machine_config &mconfig, device_type type, cons
, m_pfnmask(flavor == MIPS3_TYPE_VR4300 ? 0x000fffff : 0x00ffffff)
, m_tlbentries(flavor == MIPS3_TYPE_VR4300 ? 32 : MIPS3_MAX_TLB_ENTRIES)
, m_bigendian(endianness == ENDIANNESS_BIG)
- , m_byte_xor(data_bits == 64 ? (m_bigendian ? BYTE8_XOR_BE(0) : BYTE8_XOR_LE(0)) : (m_bigendian ? BYTE4_XOR_BE(0) : BYTE4_XOR_LE(0)))
- , m_word_xor(data_bits == 64 ? (m_bigendian ? WORD2_XOR_BE(0) : WORD2_XOR_LE(0)) : (m_bigendian ? WORD_XOR_BE(0) : WORD_XOR_LE(0)))
- , m_dword_xor(data_bits == 64 ? (m_bigendian ? DWORD_XOR_BE(0) : DWORD_XOR_LE(0)) : 0)
+ , m_byte_xor(m_bigendian ? BYTE4_XOR_BE(0) : BYTE4_XOR_LE(0))
+ , m_word_xor(m_bigendian ? WORD_XOR_BE(0) : WORD_XOR_LE(0))
, c_icache_size(0)
, c_dcache_size(0)
- , c_secondary_cache_line_size(0)
, m_fastram_select(0)
, m_debugger_temp(0)
- , m_drc_cache(DRC_CACHE_SIZE + sizeof(internal_mips3_state) + 0x800000)
+ , m_drc_cache(DRC_CACHE_SIZE + sizeof(internal_mips3_state) + 0x80000)
, m_drcuml(nullptr)
, m_drcfe(nullptr)
, m_drcoptions(0)
@@ -316,11 +313,7 @@ void mips3_device::generate_exception(int exception, int backup)
if (!(SR & SR_EXL))
{
/* if we were in a branch delay slot, adjust */
-#if DELAY_SLOT_EXCEPTION_HACK
- if (((m_nextpc != ~0) || (m_delayslot)) && (m_ppc == m_core->pc - 4))
-#else
if ((m_nextpc != ~0) || (m_delayslot))
-#endif
{
m_delayslot = false;
m_nextpc = ~0;
@@ -343,7 +336,6 @@ void mips3_device::generate_exception(int exception, int backup)
if ((CAUSE & 0x7f) == 0)
logerror("Took interrupt -- Cause = %08X, PC = %08X\n", (uint32_t)CAUSE, m_core->pc);
*/
- debugger_exception_hook(exception);
}
@@ -1241,7 +1233,7 @@ inline bool mips3_device::RWORD(offs_t address, uint32_t *result, bool insn)
{
continue;
}
- *result = m_fastram[ramnum].offset_base32[(tlbaddress ^ m_dword_xor) >> 2];
+ *result = m_fastram[ramnum].offset_base32[tlbaddress >> 2];
return true;
}
*result = (*m_memory.read_dword)(*m_program, tlbaddress);
@@ -1411,7 +1403,7 @@ inline void mips3_device::WWORD(offs_t address, uint32_t data)
{
continue;
}
- m_fastram[ramnum].offset_base32[(tlbaddress ^ m_dword_xor) >> 2] = data;
+ m_fastram[ramnum].offset_base32[tlbaddress >> 2] = data;
return;
}
(*m_memory.write_dword)(*m_program, tlbaddress, data);
@@ -1780,7 +1772,7 @@ inline void mips3_device::set_cop0_creg(int idx, uint64_t val)
void mips3_device::handle_cop0(uint32_t op)
{
- if ((SR & SR_KSU_MASK) != SR_KSU_KERNEL && !(SR & SR_COP0) && !(SR & (SR_EXL | SR_ERL)))
+ if ((SR & SR_KSU_MASK) != SR_KSU_KERNEL && !(SR & SR_COP0))
{
m_badcop_value = 0;
generate_exception(EXCEPTION_BADCOP, 1);
@@ -1840,13 +1832,7 @@ void mips3_device::handle_cop0(uint32_t op)
break;
case 0x10: /* RFE */ invalid_instruction(op); break;
- case 0x18: /* ERET */
- m_core->pc = m_core->cpr[0][COP0_EPC];
- SR &= ~SR_EXL;
- check_irqs();
- m_lld_value ^= 0xffffffff;
- m_ll_value ^= 0xffffffff;
- break;
+ case 0x18: /* ERET */ m_core->pc = m_core->cpr[0][COP0_EPC]; SR &= ~SR_EXL; check_irqs(); m_lld_value ^= 0xffffffff; m_ll_value ^= 0xffffffff; break;
case 0x20: /* WAIT */ break;
default: handle_extra_cop0(op); break;
}
@@ -3530,13 +3516,47 @@ void mips3_device::handle_special(uint32_t op)
m_core->icount -= 35;
break;
case 0x1c: /* DMULT */
- LOVAL64 = mul_64x64(RSVAL64, RTVAL64, reinterpret_cast<s64 *>(&HIVAL64));
+ {
+ uint64_t a_hi = (uint32_t)(RSVAL64 >> 32);
+ uint64_t b_hi = (uint32_t)(RTVAL64 >> 32);
+ uint64_t a_lo = (uint32_t)RSVAL64;
+ uint64_t b_lo = (uint32_t)RTVAL64;
+ uint64_t p1 = a_lo * b_lo;
+ uint64_t p2 = a_hi * b_lo;
+ uint64_t p3 = a_lo * b_hi;
+ uint64_t p4 = a_hi * b_hi;
+ uint64_t carry = (uint32_t)(((p1 >> 32) + (uint32_t)p2 + (uint32_t)p3) >> 32);
+
+ LOVAL64 = p1 + (p2 << 32) + (p3 << 32);
+ HIVAL64 = p4 + (p2 >> 32) + (p3 >> 32) + carry;
+
+ // Adjust for sign
+ if (RSVAL64 < 0)
+ HIVAL64 -= RTVAL64;
+ if (RTVAL64 < 0)
+ HIVAL64 -= RSVAL64;
+
m_core->icount -= 7;
break;
+ }
case 0x1d: /* DMULTU */
- LOVAL64 = mulu_64x64(RSVAL64, RTVAL64, &HIVAL64);
+ {
+ uint64_t a_hi = (uint32_t)(RSVAL64 >> 32);
+ uint64_t b_hi = (uint32_t)(RTVAL64 >> 32);
+ uint64_t a_lo = (uint32_t)RSVAL64;
+ uint64_t b_lo = (uint32_t)RTVAL64;
+ uint64_t p1 = a_lo * b_lo;
+ uint64_t p2 = a_hi * b_lo;
+ uint64_t p3 = a_lo * b_hi;
+ uint64_t p4 = a_hi * b_hi;
+ uint64_t carry = (uint32_t)(((p1 >> 32) + (uint32_t)p2 + (uint32_t)p3) >> 32);
+
+ LOVAL64 = p1 + (p2 << 32) + (p3 << 32);
+ HIVAL64 = p4 + (p2 >> 32) + (p3 >> 32) + carry;
+
m_core->icount -= 7;
break;
+ }
case 0x1e: /* DDIV */
if (RTVAL64)
{
@@ -5480,7 +5500,7 @@ void mips3_device::load_elf()
void r5000be_device::handle_cache(uint32_t op)
{
- if ((SR & SR_KSU_MASK) != SR_KSU_KERNEL && !(SR & SR_COP0) && !(SR & (SR_EXL | SR_ERL)))
+ if ((SR & SR_KSU_MASK) != SR_KSU_KERNEL && !(SR & SR_COP0))
{
m_badcop_value = 0;
generate_exception(EXCEPTION_BADCOP, 1);
diff --git a/src/devices/cpu/mips/mips3.h b/src/devices/cpu/mips/mips3.h
index 0afa4ef610b..8d16c6cbd84 100644
--- a/src/devices/cpu/mips/mips3.h
+++ b/src/devices/cpu/mips/mips3.h
@@ -297,7 +297,6 @@ public:
void set_icache_size(size_t icache_size) { c_icache_size = icache_size; }
void set_dcache_size(size_t dcache_size) { c_dcache_size = dcache_size; }
- void set_secondary_cache_line_size(uint8_t secondary_cache_line_size) { c_secondary_cache_line_size = secondary_cache_line_size; }
void set_system_clock(uint32_t system_clock) { c_system_clock = system_clock; }
TIMER_CALLBACK_MEMBER(compare_int_callback);
@@ -437,13 +436,11 @@ protected:
bool m_bigendian;
uint32_t m_byte_xor;
uint32_t m_word_xor;
- uint32_t m_dword_xor;
data_accessors m_memory;
/* cache memory */
size_t c_icache_size;
size_t c_dcache_size;
- uint8_t c_secondary_cache_line_size;
/* MMU */
mips3_tlb_entry m_tlb[MIPS3_MAX_TLB_ENTRIES];
diff --git a/src/devices/cpu/mips/mips3com.cpp b/src/devices/cpu/mips/mips3com.cpp
index 04225d86da7..0cab50ca894 100644
--- a/src/devices/cpu/mips/mips3com.cpp
+++ b/src/devices/cpu/mips/mips3com.cpp
@@ -273,13 +273,6 @@ uint32_t mips3_device::compute_config_register()
else if (c_icache_size <= 0x40000) configreg |= 6 << 9;
else configreg |= 7 << 9;
- if (c_secondary_cache_line_size != 0) {
- configreg &= ~((0xf << 20) | (1 << 17));
- if (c_secondary_cache_line_size <= 0x10) configreg |= 0 << 22;
- else if (c_secondary_cache_line_size <= 0x20) configreg |= 1 << 22;
- else if (c_secondary_cache_line_size <= 0x40) configreg |= 2 << 22;
- else configreg |= 3 << 22;
- }
/* set the system clock divider */
int divisor = 2;
if (c_system_clock != 0)
diff --git a/src/devices/cpu/mips/mips3drc.cpp b/src/devices/cpu/mips/mips3drc.cpp
index 02439727608..abedfd59a8d 100644
--- a/src/devices/cpu/mips/mips3drc.cpp
+++ b/src/devices/cpu/mips/mips3drc.cpp
@@ -318,9 +318,8 @@ void mips3_device::code_compile_block(uint8_t mode, offs_t pc)
/* if we don't have a hash for this mode/pc, or if we are overriding all, add one */
if (override || !m_drcuml->hash_exists(mode, seqhead->pc))
- {
UML_HASH(block, mode, seqhead->pc); // hash mode,pc
- }
+
/* if we already have a hash, and this is the first sequence, assume that we */
/* are recompiling due to being out of sync and allow future overrides */
else if (seqhead == desclist)
@@ -333,7 +332,8 @@ void mips3_device::code_compile_block(uint8_t mode, offs_t pc)
else
{
UML_LABEL(block, seqhead->pc | 0x80000000); // label seqhead->pc | 0x80000000
- UML_HASHJMP(block, m_core->mode, seqhead->pc, *m_nocode); // hashjmp <mode>,seqhead->pc,nocode
+ UML_HASHJMP(block, m_core->mode, seqhead->pc, *m_nocode);
+ // hashjmp <mode>,seqhead->pc,nocode
continue;
}
@@ -343,15 +343,11 @@ void mips3_device::code_compile_block(uint8_t mode, offs_t pc)
/* label this instruction, if it may be jumped to locally */
if (seqhead->flags & OPFLAG_IS_BRANCH_TARGET)
- {
UML_LABEL(block, seqhead->pc | 0x80000000); // label seqhead->pc | 0x80000000
- }
/* iterate over instructions in the sequence and compile them */
for (curdesc = seqhead; curdesc != seqlast->next(); curdesc = curdesc->next())
- {
generate_sequence_instruction(block, compiler, curdesc);
- }
/* if we need to return to the start, do it */
if (seqlast->flags & OPFLAG_RETURN_TO_START)
@@ -366,13 +362,11 @@ void mips3_device::code_compile_block(uint8_t mode, offs_t pc)
/* if the last instruction can change modes, use a variable mode; otherwise, assume the same mode */
if (seqlast->flags & OPFLAG_CAN_CHANGE_MODES)
- {
- UML_HASHJMP(block, mem(&m_core->mode), nextpc, *m_nocode); // hashjmp <mode>,nextpc,nocode
- }
+ UML_HASHJMP(block, mem(&m_core->mode), nextpc, *m_nocode);
+ // hashjmp <mode>,nextpc,nocode
else if (seqlast->next() == nullptr || seqlast->next()->pc != nextpc)
- {
- UML_HASHJMP(block, m_core->mode, nextpc, *m_nocode); // hashjmp <mode>,nextpc,nocode
- }
+ UML_HASHJMP(block, m_core->mode, nextpc, *m_nocode);
+ // hashjmp <mode>,nextpc,nocode
}
/* end the sequence */
@@ -1064,6 +1058,7 @@ void mips3_device::generate_update_cycles(drcuml_block &block, compiler_state &c
compiler.cycles = 0;
}
+
/*-------------------------------------------------
generate_checksum_block - generate code to
validate a sequence of opcodes
@@ -1082,17 +1077,15 @@ void mips3_device::generate_checksum_block(drcuml_block &block, compiler_state &
{
uint32_t sum = seqhead->opptr.l[0];
const void *base = m_prptr(seqhead->physpc);
- uint32_t low_bits = (seqhead->physpc & (m_data_bits == 64 ? 4 : 0)) ^ m_dword_xor;
- UML_LOAD(block, I0, base, low_bits, SIZE_DWORD, SCALE_x1); // load i0,base,0,dword
+ UML_LOAD(block, I0, base, 0, SIZE_DWORD, SCALE_x4); // load i0,base,0,dword
if (seqhead->delay.first() != nullptr
&& !(seqhead->delay.first()->flags & OPFLAG_VIRTUAL_NOOP)
&& seqhead->physpc != seqhead->delay.first()->physpc)
{
- uint32_t low_bits = (seqhead->delay.first()->physpc & (m_data_bits == 64 ? 4 : 0)) ^ m_dword_xor;
base = m_prptr(seqhead->delay.first()->physpc);
assert(base != nullptr);
- UML_LOAD(block, I1, base, low_bits, SIZE_DWORD, SCALE_x1); // load i1,base,dword
+ UML_LOAD(block, I1, base, 0, SIZE_DWORD, SCALE_x4); // load i1,base,dword
UML_ADD(block, I0, I0, I1); // add i0,i0,i1
sum += seqhead->delay.first()->opptr.l[0];
@@ -1111,24 +1104,21 @@ void mips3_device::generate_checksum_block(drcuml_block &block, compiler_state &
if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP))
{
const void *base = m_prptr(seqhead->physpc);
- UML_LOAD(block, I0, base, m_dword_xor, SIZE_DWORD, SCALE_x1); // load i0,base,0,dword
+ UML_LOAD(block, I0, base, 0, SIZE_DWORD, SCALE_x4); // load i0,base,0,dword
UML_CMP(block, I0, curdesc->opptr.l[0]); // cmp i0,opptr[0]
UML_EXHc(block, COND_NE, *m_nocode, epc(seqhead)); // exne nocode,seqhead->pc
}
#else
uint32_t sum = 0;
const void *base = m_prptr(seqhead->physpc);
- uint32_t low_bits = (seqhead->physpc & (m_data_bits == 64 ? 4 : 0)) ^ m_dword_xor;
- UML_LOAD(block, I0, base, low_bits, SIZE_DWORD, SCALE_x1); // load i0,base,0,dword
+ UML_LOAD(block, I0, base, 0, SIZE_DWORD, SCALE_x4); // load i0,base,0,dword
sum += seqhead->opptr.l[0];
for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next())
- {
if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP))
{
base = m_prptr(curdesc->physpc);
assert(base != nullptr);
- uint32_t low_bits = (curdesc->physpc & (m_data_bits == 64 ? 4 : 0)) ^ m_dword_xor;
- UML_LOAD(block, I1, base, low_bits, SIZE_DWORD, SCALE_x1); // load i1,base,dword
+ UML_LOAD(block, I1, base, 0, SIZE_DWORD, SCALE_x4); // load i1,base,dword
UML_ADD(block, I0, I0, I1); // add i0,i0,i1
sum += curdesc->opptr.l[0];
@@ -1138,13 +1128,11 @@ void mips3_device::generate_checksum_block(drcuml_block &block, compiler_state &
{
base = m_prptr(curdesc->delay.first()->physpc);
assert(base != nullptr);
- uint32_t low_bits = (curdesc->delay.first()->physpc & (m_data_bits == 64 ? 4 : 0)) ^ m_dword_xor;
- UML_LOAD(block, I1, base, low_bits, SIZE_DWORD, SCALE_x1); // load i1,base,dword
+ UML_LOAD(block, I1, base, 0, SIZE_DWORD, SCALE_x4); // load i1,base,dword
UML_ADD(block, I0, I0, I1); // add i0,i0,i1
sum += curdesc->delay.first()->opptr.l[0];
}
}
- }
UML_CMP(block, I0, sum); // cmp i0,sum
UML_EXHc(block, COND_NE, *m_nocode, epc(seqhead)); // exne nocode,seqhead->pc
#endif
@@ -1303,18 +1291,17 @@ void mips3_device::generate_delay_slot_and_branch(drcuml_block &block, compiler_
{
generate_update_cycles(block, compiler_temp, desc->targetpc, true); // <subtract cycles>
if (desc->flags & OPFLAG_INTRABLOCK_BRANCH)
- {
UML_JMP(block, desc->targetpc | 0x80000000); // jmp desc->targetpc | 0x80000000
- }
else
- {
- UML_HASHJMP(block, m_core->mode, desc->targetpc, *m_nocode); // hashjmp <mode>,desc->targetpc,nocode
- }
+ UML_HASHJMP(block, m_core->mode, desc->targetpc, *m_nocode);
+ // hashjmp <mode>,desc->targetpc,nocode
}
else
{
- generate_update_cycles(block, compiler_temp, uml::mem(&m_core->jmpdest), true); // <subtract cycles>
- UML_HASHJMP(block, m_core->mode, mem(&m_core->jmpdest), *m_nocode); // hashjmp <mode>,<rsreg>,nocode
+ generate_update_cycles(block, compiler_temp, uml::mem(&m_core->jmpdest), true);
+ // <subtract cycles>
+ UML_HASHJMP(block, m_core->mode, mem(&m_core->jmpdest), *m_nocode);
+ // hashjmp <mode>,<rsreg>,nocode
}
/* update the label */
@@ -2628,8 +2615,10 @@ bool mips3_device::generate_cop0(drcuml_block &block, compiler_state &compiler,
UML_MOV(block, CPR032(COP0_Status), I0); // mov [Status],i0
generate_update_mode(block);
compiler.checkints = true;
- generate_update_cycles(block, compiler, CPR032(COP0_ErrorPC), true); // <subtract cycles>
- UML_HASHJMP(block, mem(&m_core->mode), CPR032(COP0_ErrorPC), *m_nocode); // hashjmp <mode>,[EPC],nocode
+ generate_update_cycles(block, compiler, CPR032(COP0_ErrorPC), true);
+ // <subtract cycles>
+ UML_HASHJMP(block, mem(&m_core->mode), CPR032(COP0_ErrorPC), *m_nocode);
+ // hashjmp <mode>,[EPC],nocode
return true;
case 0x20: /* WAIT */
diff --git a/src/devices/cpu/mips/mips3fe.cpp b/src/devices/cpu/mips/mips3fe.cpp
index 77b72c9b48b..ff0c59797d9 100644
--- a/src/devices/cpu/mips/mips3fe.cpp
+++ b/src/devices/cpu/mips/mips3fe.cpp
@@ -316,13 +316,13 @@ bool mips3_frontend::describe_special(uint32_t op, opcode_desc &desc)
return true;
case 0x10: // MFHI
- desc.regin[2] |= REGFLAG_HI;
+ desc.regin[0] |= REGFLAG_HI;
desc.regout[0] |= REGFLAG_R(RDREG);
return true;
case 0x11: // MTHI
desc.regin[0] |= REGFLAG_R(RSREG);
- desc.regout[2] |= REGFLAG_HI;
+ desc.regout[0] |= REGFLAG_HI;
return true;
case 0x12: // MFLO
diff --git a/src/devices/cpu/mips/r4000.cpp b/src/devices/cpu/mips/r4000.cpp
deleted file mode 100644
index ca95b107c65..00000000000
--- a/src/devices/cpu/mips/r4000.cpp
+++ /dev/null
@@ -1,3067 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Patrick Mackinlay
-
-/*
- * This is a stripped-down MIPS-III CPU derived from the main mips3 code. Its
- * primary purpose is to act as a test-bed to aid in debugging MIPS-based
- * systems, after which the changes/improvements from here are expected to
- * be back-ported and incorporated into the original mips3 device.
- *
- * Because of this specific approach, no attempt is made to support many of the
- * current features of the mips3 device at this time. Key differences bewteen
- * this implementation and mips3 include:
- *
- * - only supports MIPS R4000/R4400 and QED R4600
- * - no dynamic recompilation
- * - reworked address translation logic, including 64-bit modes
- * - reworked softfloat3-based floating point
- * - experimental primary instruction cache
- * - memory tap based ll/sc
- * - configurable endianness
- * - it's very very very slow
- *
- * TODO
- * - try to eliminate mode check in address calculations
- * - find a better way to deal with software interrupts
- * - enforce mode checks for cp1
- * - cache instructions
- * - check/improve instruction timing
- *
- */
-
-#include "emu.h"
-#include "debugger.h"
-#include "r4000.h"
-#include "mips3dsm.h"
-
-#include "softfloat3/source/include/softfloat.h"
-
-#define LOG_GENERAL (1U << 0)
-#define LOG_TLB (1U << 1)
-#define LOG_CACHE (1U << 2)
-#define LOG_EXCEPTION (1U << 3)
-#define LOG_SYSCALL (1U << 4)
-#define LOG_STATS (1U << 5)
-
-#define VERBOSE (LOG_GENERAL)
-
-// operating system specific system call logging
-#define SYSCALL_IRIX53 (1U << 0)
-#define SYSCALL_WINNT4 (1U << 1)
-#if VERBOSE & LOG_SYSCALL
-#define SYSCALL_MASK (SYSCALL_IRIX53)
-#else
-#define SYSCALL_MASK (0)
-#endif
-
-// experimental primary instruction cache
-#define ICACHE 0
-
-#include "logmacro.h"
-
-#define USE_ABI_REG_NAMES 1
-
-// cpu instruction fiels
-#define RSREG ((op >> 21) & 31)
-#define RTREG ((op >> 16) & 31)
-#define RDREG ((op >> 11) & 31)
-#define SHIFT ((op >> 6) & 31)
-
-// cop1 instruction fields
-#define FRREG ((op >> 21) & 31)
-#define FTREG ((op >> 16) & 31)
-#define FSREG ((op >> 11) & 31)
-#define FDREG ((op >> 6) & 31)
-
-#define R4000_ENDIAN_LE_BE(le, be) ((m_cp0[CP0_Config] & CONFIG_BE) ? (be) : (le))
-
-// identify odd-numbered cop1 registers
-#define ODD_REGS 0x00010840U
-
-// address computation
-#define ADDR(r, o) (cp0_64() ? ((r) + (o)) : s64(s32((r) + (o))))
-
-#define SR m_cp0[CP0_Status]
-#define CAUSE m_cp0[CP0_Cause]
-
-DEFINE_DEVICE_TYPE(R4000, r4000_device, "r4000", "MIPS R4000")
-DEFINE_DEVICE_TYPE(R4400, r4400_device, "r4400", "MIPS R4400")
-DEFINE_DEVICE_TYPE(R4600, r4600_device, "r4600", "QED R4600")
-
-r4000_base_device::r4000_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 prid, cache_size_t icache_size, cache_size_t dcache_size)
- : cpu_device(mconfig, type, tag, owner, clock)
- , m_program_config_le("program", ENDIANNESS_LITTLE, 64, 32)
- , m_program_config_be("program", ENDIANNESS_BIG, 64, 32)
- , m_ll_watch(nullptr)
- , m_fcr0(0x00000500U)
-{
- m_cp0[CP0_PRId] = prid;
-
- // default configuration
- m_cp0[CP0_Config] = CONFIG_BE | (icache_size << 9) | (dcache_size << 6);
-}
-
-void r4000_base_device::device_start()
-{
- // TODO: save state
-
- state_add(STATE_GENPC, "GENPC", m_pc).noshow();
- state_add(STATE_GENPCBASE, "CURPC", m_pc).noshow();
- state_add(MIPS3_PC, "PC", m_pc).formatstr("%016X");
-
- // exception processing
- state_add(MIPS3_CP0 + CP0_Status, "SR", m_cp0[CP0_Status]).formatstr("%08X");
- state_add(MIPS3_CP0 + CP0_EPC, "EPC", m_cp0[CP0_EPC]).formatstr("%016X");
- state_add(MIPS3_CP0 + CP0_Cause, "Cause", m_cp0[CP0_Cause]).formatstr("%08X");
- state_add(MIPS3_CP0 + CP0_Context, "Context", m_cp0[CP0_Context]).formatstr("%016X");
- state_add(MIPS3_CP0 + CP0_BadVAddr, "BadVAddr", m_cp0[CP0_BadVAddr]).formatstr("%016X");
- state_add(MIPS3_CP0 + CP0_Compare, "Compare", m_cp0[CP0_Compare]).formatstr("%08X");
- state_add(MIPS3_CP0 + CP0_WatchLo, "WatchLo", m_cp0[CP0_WatchLo]).formatstr("%08X");
- state_add(MIPS3_CP0 + CP0_WatchHi, "WatchHi", m_cp0[CP0_WatchHi]).formatstr("%08X");
- state_add(MIPS3_CP0 + CP0_XContext, "XContext", m_cp0[CP0_XContext]).formatstr("%016X");
-
- // memory management
- state_add(MIPS3_CP0 + CP0_Index, "Index", m_cp0[CP0_Index]).formatstr("%08X");
- state_add(MIPS3_CP0 + CP0_EntryLo0, "EntryLo0", m_cp0[CP0_EntryLo0]).formatstr("%016X");
- state_add(MIPS3_CP0 + CP0_EntryLo1, "EntryLo1", m_cp0[CP0_EntryLo1]).formatstr("%016X");
- state_add(MIPS3_CP0 + CP0_PageMask, "PageMask", m_cp0[CP0_PageMask]).formatstr("%08X");
- state_add(MIPS3_CP0 + CP0_Wired, "Wired", m_cp0[CP0_Wired]).formatstr("%08X");
- state_add(MIPS3_CP0 + CP0_EntryHi, "EntryHi", m_cp0[CP0_EntryHi]).formatstr("%016X");
- state_add(MIPS3_CP0 + CP0_LLAddr, "LLAddr", m_cp0[CP0_LLAddr]).formatstr("%08X");
-
-#if USE_ABI_REG_NAMES
- state_add(MIPS3_R0 + 0, "zero", m_r[0]).callimport().formatstr("%016X"); // Can't change R0
- state_add(MIPS3_R0 + 1, "at", m_r[1]).formatstr("%016X");
- state_add(MIPS3_R0 + 2, "v0", m_r[2]).formatstr("%016X");
- state_add(MIPS3_R0 + 3, "v1", m_r[3]).formatstr("%016X");
- state_add(MIPS3_R0 + 4, "a0", m_r[4]).formatstr("%016X");
- state_add(MIPS3_R0 + 5, "a1", m_r[5]).formatstr("%016X");
- state_add(MIPS3_R0 + 6, "a2", m_r[6]).formatstr("%016X");
- state_add(MIPS3_R0 + 7, "a3", m_r[7]).formatstr("%016X");
- state_add(MIPS3_R0 + 8, "t0", m_r[8]).formatstr("%016X");
- state_add(MIPS3_R0 + 9, "t1", m_r[9]).formatstr("%016X");
- state_add(MIPS3_R0 + 10, "t2", m_r[10]).formatstr("%016X");
- state_add(MIPS3_R0 + 11, "t3", m_r[11]).formatstr("%016X");
- state_add(MIPS3_R0 + 12, "t4", m_r[12]).formatstr("%016X");
- state_add(MIPS3_R0 + 13, "t5", m_r[13]).formatstr("%016X");
- state_add(MIPS3_R0 + 14, "t6", m_r[14]).formatstr("%016X");
- state_add(MIPS3_R0 + 15, "t7", m_r[15]).formatstr("%016X");
- state_add(MIPS3_R0 + 16, "s0", m_r[16]).formatstr("%016X");
- state_add(MIPS3_R0 + 17, "s1", m_r[17]).formatstr("%016X");
- state_add(MIPS3_R0 + 18, "s2", m_r[18]).formatstr("%016X");
- state_add(MIPS3_R0 + 19, "s3", m_r[19]).formatstr("%016X");
- state_add(MIPS3_R0 + 20, "s4", m_r[20]).formatstr("%016X");
- state_add(MIPS3_R0 + 21, "s5", m_r[21]).formatstr("%016X");
- state_add(MIPS3_R0 + 22, "s6", m_r[22]).formatstr("%016X");
- state_add(MIPS3_R0 + 23, "s7", m_r[23]).formatstr("%016X");
- state_add(MIPS3_R0 + 24, "t8", m_r[24]).formatstr("%016X");
- state_add(MIPS3_R0 + 25, "t9", m_r[25]).formatstr("%016X");
- state_add(MIPS3_R0 + 26, "k0", m_r[26]).formatstr("%016X");
- state_add(MIPS3_R0 + 27, "k1", m_r[27]).formatstr("%016X");
- state_add(MIPS3_R0 + 28, "gp", m_r[28]).formatstr("%016X");
- state_add(MIPS3_R0 + 29, "sp", m_r[29]).formatstr("%016X");
- state_add(MIPS3_R0 + 30, "fp", m_r[30]).formatstr("%016X");
- state_add(MIPS3_R0 + 31, "ra", m_r[31]).formatstr("%016X");
-#else
- state_add(MIPS3_R0, "R0", m_r[0]).callimport().formatstr("%016X");
- for (unsigned i = 1; i < 32; i++)
- state_add(MIPS3_R0 + i, util::string_format("R%d", i).c_str(), m_r[i]);
-#endif
-
- state_add(MIPS3_HI, "HI", m_hi).formatstr("%016X");
- state_add(MIPS3_LO, "LO", m_lo).formatstr("%016X");
-
- // floating point registers
- state_add(MIPS3_FCR30, "FCR30", m_fcr30).formatstr("%08X");
- state_add(MIPS3_FCR31, "FCR31", m_fcr31).formatstr("%08X");
- for (unsigned i = 0; i < 32; i++)
- state_add(MIPS3_F0 + i, util::string_format("F%d", i).c_str(), m_f[i]);
-
- set_icountptr(m_icount);
-
- m_cp0_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(r4000_base_device::cp0_timer_callback), this));
-
- // compute icache line selection mask and allocate tag and data
- unsigned const config_ic = (m_cp0[CP0_Config] & CONFIG_IC) >> 9;
-
- m_icache_mask_hi = (0x1000U << config_ic) - 1;
- m_icache_tag = std::make_unique<u32[]>(0x100U << config_ic);
- m_icache_data = std::make_unique<u32 []>((0x1000U << config_ic) >> 2);
-}
-
-void r4000_base_device::device_reset()
-{
- m_branch_state = NONE;
- m_pc = s64(s32(0xbfc00000));
-
- m_cp0[CP0_Status] = SR_BEV | SR_ERL;
- m_cp0[CP0_Wired] = 0;
- m_cp0[CP0_Compare] = 0;
- m_cp0[CP0_Count] = 0;
-
- m_cp0_timer_zero = total_cycles();
-
- if (m_ll_watch)
- {
- m_ll_watch->remove();
- m_ll_watch = nullptr;
- }
-
- m_cp0[CP0_WatchLo] = 0;
- m_cp0[CP0_WatchHi] = 0;
-
- // initialize tlb mru index with identity mapping
- for (unsigned i = 0; i < ARRAY_LENGTH(m_tlb); i++)
- {
- m_tlb_mru[TRANSLATE_READ][i] = i;
- m_tlb_mru[TRANSLATE_WRITE][i] = i;
- m_tlb_mru[TRANSLATE_FETCH][i] = i;
- }
-
- // initialize statistics
- m_tlb_scans = 0;
- m_tlb_loops = 0;
- m_icache_hits = 0;
- m_icache_misses = 0;
-}
-
-void r4000_base_device::device_stop()
-{
- if ((m_icache_hits + m_icache_misses) > 0)
- LOGMASKED(LOG_STATS, "icache hit ratio %.3f%% (%d hits %d misses)\n",
- double(m_icache_hits) / double(m_icache_hits + m_icache_misses) * 100.0, m_icache_hits, m_icache_misses);
-
- if (m_tlb_scans > 0)
- LOGMASKED(LOG_STATS, "tlb scans %d loops %d average %.3f loops per scan\n", m_tlb_scans, m_tlb_loops, double(m_tlb_loops) / double(m_tlb_scans));
-}
-
-device_memory_interface::space_config_vector r4000_base_device::memory_space_config() const
-{
- return space_config_vector{
- std::make_pair(AS_PROGRAM, R4000_ENDIAN_LE_BE(&m_program_config_le, &m_program_config_be))
- };
-}
-
-bool r4000_base_device::memory_translate(int spacenum, int intention, offs_t &address)
-{
- // FIXME: address truncation
- u64 placeholder = s32(address);
-
- translate_t const t = translate(intention, placeholder);
-
- if (t == ERROR || t == MISS)
- return false;
-
- address = placeholder;
- return true;
-}
-
-std::unique_ptr<util::disasm_interface> r4000_base_device::create_disassembler()
-{
- return std::make_unique<mips3_disassembler>();
-}
-
-void r4000_base_device::execute_run()
-{
- // check interrupts
- if ((CAUSE & SR & CAUSE_IP) && (SR & SR_IE) && !(SR & (SR_EXL | SR_ERL)))
- cpu_exception(EXCEPTION_INT);
-
- while (m_icount > 0)
- {
- debugger_instruction_hook(m_pc);
-
- fetch(m_pc,
- [this](u32 const op)
- {
- cpu_execute(op);
-
- // zero register zero
- m_r[0] = 0;
- });
-
- // update pc and branch state
- switch (m_branch_state)
- {
- case NONE:
- m_pc += 4;
- break;
-
- case DELAY:
- m_branch_state = NONE;
- m_pc = m_branch_target;
- break;
-
- case BRANCH:
- m_branch_state = DELAY;
- m_pc += 4;
- break;
-
- case EXCEPTION:
- m_branch_state = NONE;
- break;
-
- case NULLIFY:
- m_branch_state = NONE;
- m_pc += 8;
- break;
- }
-
- m_icount--;
- }
-}
-
-void r4000_base_device::execute_set_input(int inputnum, int state)
-{
- if (state)
- m_cp0[CP0_Cause] |= (CAUSE_IPEX0 << inputnum);
- else
- m_cp0[CP0_Cause] &= ~(CAUSE_IPEX0 << inputnum);
-}
-
-void r4000_base_device::cpu_execute(u32 const op)
-{
- switch (op >> 26)
- {
- case 0x00: // SPECIAL
- switch (op & 0x3f)
- {
- case 0x00: // SLL
- m_r[RDREG] = s64(s32(m_r[RTREG] << SHIFT));
- break;
- //case 0x01: // *
- case 0x02: // SRL
- m_r[RDREG] = s64(s32(u32(m_r[RTREG]) >> SHIFT));
- break;
- case 0x03: // SRA
- m_r[RDREG] = s64(s32(m_r[RTREG]) >> SHIFT);
- break;
- case 0x04: // SLLV
- m_r[RDREG] = s64(s32(m_r[RTREG] << (m_r[RSREG] & 31)));
- break;
- //case 0x05: // *
- case 0x06: // SRLV
- m_r[RDREG] = s64(s32(u32(m_r[RTREG]) >> (m_r[RSREG] & 31)));
- break;
- case 0x07: // SRAV
- m_r[RDREG] = s64(s32(m_r[RTREG]) >> (m_r[RSREG] & 31));
- break;
- case 0x08: // JR
- m_branch_state = BRANCH;
- m_branch_target = ADDR(m_r[RSREG], 0);
- break;
- case 0x09: // JALR
- m_branch_state = BRANCH;
- m_branch_target = ADDR(m_r[RSREG], 0);
- m_r[RDREG] = ADDR(m_pc, 8);
- break;
- //case 0x0a: // *
- //case 0x0b: // *
- case 0x0c: // SYSCALL
- if (VERBOSE & LOG_SYSCALL)
- {
- if (SYSCALL_MASK & SYSCALL_IRIX53)
- {
- switch (m_r[2])
- {
- case 0x3e9: // 1001 = exit
- LOGMASKED(LOG_SYSCALL, "exit(%d) (%s)\n", m_r[4], machine().describe_context());
- break;
-
- case 0x3ea: // 1002 = fork
- LOGMASKED(LOG_SYSCALL, "fork() (%s)\n", machine().describe_context());
- break;
-
- case 0x3eb: // 1003 = read
- LOGMASKED(LOG_SYSCALL, "read(%d, 0x%x, %d) (%s)\n", m_r[4], m_r[5], m_r[6], machine().describe_context());
- break;
-
- case 0x3ec: // 1004 = write
- LOGMASKED(LOG_SYSCALL, "write(%d, 0x%x, %d) (%s)\n", m_r[4], m_r[5], m_r[6], machine().describe_context());
- if (m_r[4] == 1 || m_r[4] == 2)
- printf("%s", debug_string(m_r[5], m_r[6]).c_str());
- break;
-
- case 0x3ed: // 1005 = open
- LOGMASKED(LOG_SYSCALL, "open(\"%s\", %#o) (%s)\n", debug_string(m_r[4]), m_r[5], machine().describe_context());
- break;
-
- case 0x3ee: // 1006 = close
- LOGMASKED(LOG_SYSCALL, "close(%d) (%s)\n", m_r[4], machine().describe_context());
- break;
-
- case 0x3ef: // 1007 = creat
- LOGMASKED(LOG_SYSCALL, "creat(\"%s\", %#o) (%s)\n", debug_string(m_r[4]), m_r[5], machine().describe_context());
- break;
-
- case 0x423: // 1059 = exece
- LOGMASKED(LOG_SYSCALL, "exece(\"%s\", [ %s ], [ %s ]) (%s)\n", debug_string(m_r[4]), debug_string_array(m_r[5]), debug_string_array(m_r[6]), machine().describe_context());
- break;
-
- default:
- LOGMASKED(LOG_SYSCALL, "syscall 0x%x (%s)\n", m_r[2], machine().describe_context());
- break;
- }
- }
- else if (SYSCALL_MASK & SYSCALL_WINNT4)
- {
- switch (m_r[2])
- {
- case 0x4f:
- load<s32>(m_r[7] + 8,
- [this](s64 string_pointer)
- {
- LOGMASKED(LOG_SYSCALL, "NtOpenFile(%s) (%s)\n", debug_string(string_pointer), machine().describe_context());
- });
- break;
-
- default:
- LOGMASKED(LOG_SYSCALL, "syscall 0x%x (%s)\n", m_r[2], machine().describe_context());
- break;
- }
- }
- }
- cpu_exception(EXCEPTION_SYS);
- break;
- case 0x0d: // BREAK
- cpu_exception(EXCEPTION_BP);
- break;
- //case 0x0e: // *
- case 0x0f: // SYNC
- break;
- case 0x10: // MFHI
- m_r[RDREG] = m_hi;
- break;
- case 0x11: // MTHI
- m_hi = m_r[RSREG];
- break;
- case 0x12: // MFLO
- m_r[RDREG] = m_lo;
- break;
- case 0x13: // MTLO
- m_lo = m_r[RSREG];
- break;
- case 0x14: // DSLLV
- m_r[RDREG] = m_r[RTREG] << (m_r[RSREG] & 63);
- break;
- //case 0x15: // *
- case 0x16: // DSRLV
- m_r[RDREG] = m_r[RTREG] >> (m_r[RSREG] & 63);
- break;
- case 0x17: // DSRAV
- m_r[RDREG] = s64(m_r[RTREG]) >> (m_r[RSREG] & 63);
- break;
- case 0x18: // MULT
- {
- u64 const product = mul_32x32(s32(m_r[RSREG]), s32(m_r[RTREG]));
-
- m_lo = s64(s32(product));
- m_hi = s64(s32(product >> 32));
- m_icount -= 3;
- }
- break;
- case 0x19: // MULTU
- {
- u64 const product = mulu_32x32(u32(m_r[RSREG]), u32(m_r[RTREG]));
-
- m_lo = s64(s32(product));
- m_hi = s64(s32(product >> 32));
- m_icount -= 3;
- }
- break;
- case 0x1a: // DIV
- if (m_r[RTREG])
- {
- m_lo = s64(s32(m_r[RSREG]) / s32(m_r[RTREG]));
- m_hi = s64(s32(m_r[RSREG]) % s32(m_r[RTREG]));
- }
- m_icount -= 35;
- break;
- case 0x1b: // DIVU
- if (m_r[RTREG])
- {
- m_lo = s64(s32(u32(m_r[RSREG]) / u32(m_r[RTREG])));
- m_hi = s64(s32(u32(m_r[RSREG]) % u32(m_r[RTREG])));
- }
- m_icount -= 35;
- break;
- case 0x1c: // DMULT
- m_lo = mul_64x64(m_r[RSREG], m_r[RTREG], reinterpret_cast<s64 *>(&m_hi));
- m_icount -= 7;
- break;
- case 0x1d: // DMULTU
- m_lo = mulu_64x64(m_r[RSREG], m_r[RTREG], &m_hi);
- m_icount -= 7;
- break;
- case 0x1e: // DDIV
- if (m_r[RTREG])
- {
- m_lo = s64(m_r[RSREG]) / s64(m_r[RTREG]);
- m_hi = s64(m_r[RSREG]) % s64(m_r[RTREG]);
- }
- m_icount -= 67;
- break;
- case 0x1f: // DDIVU
- if (m_r[RTREG])
- {
- m_lo = m_r[RSREG] / m_r[RTREG];
- m_hi = m_r[RSREG] % m_r[RTREG];
- }
- m_icount -= 67;
- break;
- case 0x20: // ADD
- {
- u32 const sum = u32(m_r[RSREG]) + u32(m_r[RTREG]);
-
- // overflow: (sign(addend0) == sign(addend1)) && (sign(addend0) != sign(sum))
- if (!BIT(u32(m_r[RSREG]) ^ u32(m_r[RTREG]), 31) && BIT(u32(m_r[RSREG]) ^ sum, 31))
- cpu_exception(EXCEPTION_OV);
- else
- m_r[RDREG] = s64(s32(sum));
- }
- break;
- case 0x21: // ADDU
- m_r[RDREG] = s64(s32(u32(m_r[RSREG]) + u32(m_r[RTREG])));
- break;
- case 0x22: // SUB
- {
- u32 const difference = u32(m_r[RSREG]) - u32(m_r[RTREG]);
-
- // overflow: (sign(minuend) != sign(subtrahend)) && (sign(minuend) != sign(difference))
- if (BIT(u32(m_r[RSREG]) ^ u32(m_r[RTREG]), 31) && BIT(u32(m_r[RSREG]) ^ difference, 31))
- cpu_exception(EXCEPTION_OV);
- else
- m_r[RDREG] = s64(s32(difference));
- }
- break;
- case 0x23: // SUBU
- m_r[RDREG] = s64(s32(u32(m_r[RSREG]) - u32(m_r[RTREG])));
- break;
- case 0x24: // AND
- m_r[RDREG] = m_r[RSREG] & m_r[RTREG];
- break;
- case 0x25: // OR
- m_r[RDREG] = m_r[RSREG] | m_r[RTREG];
- break;
- case 0x26: // XOR
- m_r[RDREG] = m_r[RSREG] ^ m_r[RTREG];
- break;
- case 0x27: // NOR
- m_r[RDREG] = ~(m_r[RSREG] | m_r[RTREG]);
- break;
- //case 0x28: // *
- //case 0x29: // *
- case 0x2a: // SLT
- m_r[RDREG] = s64(m_r[RSREG]) < s64(m_r[RTREG]);
- break;
- case 0x2b: // SLTU
- m_r[RDREG] = m_r[RSREG] < m_r[RTREG];
- break;
- case 0x2c: // DADD
- {
- u64 const sum = m_r[RSREG] + m_r[RTREG];
-
- // overflow: (sign(addend0) == sign(addend1)) && (sign(addend0) != sign(sum))
- if (!BIT(m_r[RSREG] ^ m_r[RTREG], 63) && BIT(m_r[RSREG] ^ sum, 63))
- cpu_exception(EXCEPTION_OV);
- else
- m_r[RDREG] = sum;
- }
- break;
- case 0x2d: // DADDU
- m_r[RDREG] = m_r[RSREG] + m_r[RTREG];
- break;
- case 0x2e: // DSUB
- {
- u64 const difference = m_r[RSREG] - m_r[RTREG];
-
- // overflow: (sign(minuend) != sign(subtrahend)) && (sign(minuend) != sign(difference))
- if (BIT(m_r[RSREG] ^ m_r[RTREG], 63) && BIT(m_r[RSREG] ^ difference, 63))
- cpu_exception(EXCEPTION_OV);
- else
- m_r[RDREG] = difference;
- }
- break;
- case 0x2f: // DSUBU
- m_r[RDREG] = m_r[RSREG] - m_r[RTREG];
- break;
- case 0x30: // TGE
- if (s64(m_r[RSREG]) >= s64(m_r[RTREG]))
- cpu_exception(EXCEPTION_TR);
- break;
- case 0x31: // TGEU
- if (m_r[RSREG] >= m_r[RTREG])
- cpu_exception(EXCEPTION_TR);
- break;
- case 0x32: // TLT
- if (s64(m_r[RSREG]) < s64(m_r[RTREG]))
- cpu_exception(EXCEPTION_TR);
- break;
- case 0x33: // TLTU
- if (m_r[RSREG] < m_r[RTREG])
- cpu_exception(EXCEPTION_TR);
- break;
- case 0x34: // TEQ
- if (m_r[RSREG] == m_r[RTREG])
- cpu_exception(EXCEPTION_TR);
- break;
- //case 0x35: // *
- case 0x36: // TNE
- if (m_r[RSREG] != m_r[RTREG])
- cpu_exception(EXCEPTION_TR);
- break;
- //case 0x37: // *
- case 0x38: // DSLL
- m_r[RDREG] = m_r[RTREG] << SHIFT;
- break;
- //case 0x39: // *
- case 0x3a: // DSRL
- m_r[RDREG] = m_r[RTREG] >> SHIFT;
- break;
- case 0x3b: // DSRA
- m_r[RDREG] = s64(m_r[RTREG]) >> SHIFT;
- break;
- case 0x3c: // DSLL32
- m_r[RDREG] = m_r[RTREG] << (SHIFT + 32);
- break;
- //case 0x3d: // *
- case 0x3e: // DSRL32
- m_r[RDREG] = m_r[RTREG] >> (SHIFT + 32);
- break;
- case 0x3f: // DSRA32
- m_r[RDREG] = s64(m_r[RTREG]) >> (SHIFT + 32);
- break;
-
- default:
- // * Operation codes marked with an asterisk cause reserved
- // instruction exceptions in all current implementations and are
- // reserved for future versions of the architecture.
- cpu_exception(EXCEPTION_RI);
- break;
- }
- break;
- case 0x01: // REGIMM
- switch ((op >> 16) & 0x1f)
- {
- case 0x00: // BLTZ
- if (s64(m_r[RSREG]) < 0)
- {
- m_branch_state = BRANCH;
- m_branch_target = ADDR(m_pc + 4, s32(s16(op)) << 2);
- }
- break;
- case 0x01: // BGEZ
- if (s64(m_r[RSREG]) >= 0)
- {
- m_branch_state = BRANCH;
- m_branch_target = ADDR(m_pc + 4, s32(s16(op)) << 2);
- }
- break;
- case 0x02: // BLTZL
- if (s64(m_r[RSREG]) < 0)
- {
- m_branch_state = BRANCH;
- m_branch_target = ADDR(m_pc + 4, s32(s16(op)) << 2);
- }
- else
- m_branch_state = NULLIFY;
- break;
- case 0x03: // BGEZL
- if (s64(m_r[RSREG]) >= 0)
- {
- m_branch_state = BRANCH;
- m_branch_target = ADDR(m_pc + 4, s32(s16(op)) << 2);
- }
- else
- m_branch_state = NULLIFY;
- break;
- //case 0x04: // *
- //case 0x05: // *
- //case 0x06: // *
- //case 0x07: // *
- case 0x08: // TGEI
- if (s64(m_r[RSREG]) >= s16(op))
- cpu_exception(EXCEPTION_TR);
- break;
- case 0x09: // TGEIU
- if (m_r[RSREG] >= u64(s64(s16(op))))
- cpu_exception(EXCEPTION_TR);
- break;
- case 0x0a: // TLTI
- if (s64(m_r[RSREG]) < s16(op))
- cpu_exception(EXCEPTION_TR);
- break;
- case 0x0b: // TLTIU
- if (m_r[RSREG] >= u64(s64(s16(op))))
- cpu_exception(EXCEPTION_TR);
- break;
- case 0x0c: // TEQI
- if (m_r[RSREG] == u64(s64(s16(op))))
- cpu_exception(EXCEPTION_TR);
- break;
- //case 0x0d: // *
- case 0x0e: // TNEI
- if (m_r[RSREG] != u64(s64(s16(op))))
- cpu_exception(EXCEPTION_TR);
- break;
- //case 0x0f: // *
- case 0x10: // BLTZAL
- if (s64(m_r[RSREG]) < 0)
- {
- m_branch_state = BRANCH;
- m_branch_target = ADDR(m_pc + 4, s32(s16(op)) << 2);
- }
- m_r[31] = ADDR(m_pc, 8);
- break;
- case 0x11: // BGEZAL
- if (s64(m_r[RSREG]) >= 0)
- {
- m_branch_state = BRANCH;
- m_branch_target = ADDR(m_pc + 4, s32(s16(op)) << 2);
- }
- m_r[31] = ADDR(m_pc, 8);
- break;
- case 0x12: // BLTZALL
- if (s64(m_r[RSREG]) < 0)
- {
- m_branch_state = BRANCH;
- m_branch_target = ADDR(m_pc + 4, s32(s16(op)) << 2);
- }
- else
- m_branch_state = NULLIFY;
- m_r[31] = ADDR(m_pc, 8);
- break;
- case 0x13: // BGEZALL
- if (s64(m_r[RSREG]) >= 0)
- {
- m_branch_state = BRANCH;
- m_branch_target = ADDR(m_pc + 4, s32(s16(op)) << 2);
- }
- else
- m_branch_state = NULLIFY;
- m_r[31] = ADDR(m_pc, 8);
- break;
- //case 0x14: // *
- //case 0x15: // *
- //case 0x16: // *
- //case 0x17: // *
- //case 0x18: // *
- //case 0x19: // *
- //case 0x1a: // *
- //case 0x1b: // *
- //case 0x1c: // *
- //case 0x1d: // *
- //case 0x1e: // *
- //case 0x1f: // *
-
- default:
- // * Operation codes marked with an asterisk cause reserved
- // instruction exceptions in all current implementations and are
- // reserved for future versions of the architecture.
- cpu_exception(EXCEPTION_RI);
- break;
- }
- break;
- case 0x02: // J
- m_branch_state = BRANCH;
- m_branch_target = (ADDR(m_pc, 4) & ~0x0fffffffULL) | ((op & 0x03ffffffU) << 2);
- break;
- case 0x03: // JAL
- m_branch_state = BRANCH;
- m_branch_target = (ADDR(m_pc, 4) & ~0x0fffffffULL) | ((op & 0x03ffffffU) << 2);
- m_r[31] = ADDR(m_pc, 8);
- break;
- case 0x04: // BEQ
- if (m_r[RSREG] == m_r[RTREG])
- {
- m_branch_state = BRANCH;
- m_branch_target = ADDR(m_pc + 4, s32(s16(op)) << 2);
- }
- break;
- case 0x05: // BNE
- if (m_r[RSREG] != m_r[RTREG])
- {
- m_branch_state = BRANCH;
- m_branch_target = ADDR(m_pc + 4, s32(s16(op)) << 2);
- }
- break;
- case 0x06: // BLEZ
- if (s64(m_r[RSREG]) <= 0)
- {
- m_branch_state = BRANCH;
- m_branch_target = ADDR(m_pc + 4, s32(s16(op)) << 2);
- }
- break;
- case 0x07: // BGTZ
- if (s64(m_r[RSREG]) > 0)
- {
- m_branch_state = BRANCH;
- m_branch_target = ADDR(m_pc + 4, s32(s16(op)) << 2);
- }
- break;
- case 0x08: // ADDI
- {
- u32 const sum = u32(m_r[RSREG]) + s16(op);
-
- // overflow: (sign(addend0) == sign(addend1)) && (sign(addend0) != sign(sum))
- if (!BIT(u32(m_r[RSREG]) ^ s32(s16(op)), 31) && BIT(u32(m_r[RSREG]) ^ sum, 31))
- cpu_exception(EXCEPTION_OV);
- else
- m_r[RTREG] = s64(s32(sum));
- }
- break;
- case 0x09: // ADDIU
- m_r[RTREG] = s64(s32(u32(m_r[RSREG]) + s16(op)));
- break;
- case 0x0a: // SLTI
- m_r[RTREG] = s64(m_r[RSREG]) < s64(s16(op));
- break;
- case 0x0b: // SLTIU
- m_r[RTREG] = m_r[RSREG] < u64(s64(s16(op)));
- break;
- case 0x0c: // ANDI
- m_r[RTREG] = m_r[RSREG] & u16(op);
- break;
- case 0x0d: // ORI
- m_r[RTREG] = m_r[RSREG] | u16(op);
- break;
- case 0x0e: // XORI
- m_r[RTREG] = m_r[RSREG] ^ u16(op);
- break;
- case 0x0f: // LUI
- m_r[RTREG] = s64(s16(op)) << 16;
- break;
- case 0x10: // COP0
- cp0_execute(op);
- break;
- case 0x11: // COP1
- cp1_execute(op);
- break;
- case 0x12: // COP2
- cp2_execute(op);
- break;
- //case 0x13: // *
- case 0x14: // BEQL
- if (m_r[RSREG] == m_r[RTREG])
- {
- m_branch_state = BRANCH;
- m_branch_target = ADDR(m_pc + 4, s32(s16(op)) << 2);
- }
- else
- m_branch_state = NULLIFY;
- break;
- case 0x15: // BNEL
- if (m_r[RSREG] != m_r[RTREG])
- {
- m_branch_state = BRANCH;
- m_branch_target = ADDR(m_pc + 4, s32(s16(op)) << 2);
- }
- else
- m_branch_state = NULLIFY;
- break;
- case 0x16: // BLEZL
- if (s64(m_r[RSREG]) <= 0)
- {
- m_branch_state = BRANCH;
- m_branch_target = ADDR(m_pc + 4, s32(s16(op)) << 2);
- }
- else
- m_branch_state = NULLIFY;
- break;
- case 0x17: // BGTZL
- if (s64(m_r[RSREG]) > 0)
- {
- m_branch_state = BRANCH;
- m_branch_target = ADDR(m_pc + 4, s32(s16(op)) << 2);
- }
- else
- m_branch_state = NULLIFY;
- break;
- case 0x18: // DADDI
- {
- u64 const sum = m_r[RSREG] + s64(s16(op));
-
- // overflow: (sign(addend0) == sign(addend1)) && (sign(addend0) != sign(sum))
- if (!BIT(m_r[RSREG] ^ s64(s16(op)), 63) && BIT(m_r[RSREG] ^ sum, 63))
- cpu_exception(EXCEPTION_OV);
- else
- m_r[RTREG] = sum;
- }
- break;
- case 0x19: // DADDIU
- m_r[RTREG] = m_r[RSREG] + s64(s16(op));
- break;
- case 0x1a: // LDL
- if (!(SR & SR_KSU) || (SR & (SR_EXL | SR_ERL)) || cp0_64())
- cpu_ldl(op);
- else
- cpu_exception(EXCEPTION_RI);
- break;
- case 0x1b: // LDR
- if (!(SR & SR_KSU) || (SR & (SR_EXL | SR_ERL)) || cp0_64())
- cpu_ldr(op);
- else
- cpu_exception(EXCEPTION_RI);
- break;
- //case 0x1c: // *
- //case 0x1d: // *
- //case 0x1e: // *
- //case 0x1f: // *
- case 0x20: // LB
- load<s8>(ADDR(m_r[RSREG], s16(op)),
- [this, op](s8 data)
- {
- m_r[RTREG] = data;
- });
- break;
- case 0x21: // LH
- load<s16>(ADDR(m_r[RSREG], s16(op)),
- [this, op](s16 data)
- {
- m_r[RTREG] = data;
- });
- break;
- case 0x22: // LWL
- cpu_lwl(op);
- break;
- case 0x23: // LW
- load<s32>(ADDR(m_r[RSREG], s16(op)),
- [this, op](s32 data)
- {
- m_r[RTREG] = data;
- });
- break;
- case 0x24: // LBU
- load<s8>(ADDR(m_r[RSREG], s16(op)),
- [this, op](u8 data)
- {
- m_r[RTREG] = data;
- });
- break;
- case 0x25: // LHU
- load<u16>(ADDR(m_r[RSREG], s16(op)),
- [this, op](u16 data)
- {
- m_r[RTREG] = data;
- });
- break;
- case 0x26: // LWR
- cpu_lwr(op);
- break;
- case 0x27: // LWU
- load<u32>(ADDR(m_r[RSREG], s16(op)),
- [this, op](u32 data)
- {
- m_r[RTREG] = data;
- });
- break;
- case 0x28: // SB
- store<u8>(ADDR(m_r[RSREG], s16(op)), u8(m_r[RTREG]));
- break;
- case 0x29: // SH
- store<u16>(ADDR(m_r[RSREG], s16(op)), u16(m_r[RTREG]));
- break;
- case 0x2a: // SWL
- cpu_swl(op);
- break;
- case 0x2b: // SW
- store<u32>(ADDR(m_r[RSREG], s16(op)), u32(m_r[RTREG]));
- break;
- case 0x2c: // SDL
- if (!(SR & SR_KSU) || (SR & (SR_EXL | SR_ERL)) || cp0_64())
- cpu_sdl(op);
- else
- cpu_exception(EXCEPTION_RI);
- break;
- case 0x2d: // SDR
- if (!(SR & SR_KSU) || (SR & (SR_EXL | SR_ERL)) || cp0_64())
- cpu_sdr(op);
- else
- cpu_exception(EXCEPTION_RI);
- break;
- case 0x2e: // SWR
- cpu_swr(op);
- break;
- case 0x2f: // CACHE
- if ((SR & SR_KSU) && !(SR & SR_CU0) && !(SR & (SR_EXL | SR_ERL)))
- {
- cpu_exception(EXCEPTION_CP0);
- break;
- }
-
- switch ((op >> 16) & 0x1f)
- {
- case 0x00: // index invalidate (I)
- if (ICACHE)
- {
- m_icache_tag[(ADDR(m_r[RSREG], s16(op)) & m_icache_mask_hi) >> m_icache_shift] &= ~ICACHE_V;
- break;
- }
-
- case 0x04: // index load tag (I)
- if (ICACHE)
- {
- u32 const tag = m_icache_tag[(ADDR(m_r[RSREG], s16(op)) & m_icache_mask_hi) >> m_icache_shift];
-
- m_cp0[CP0_TagLo] = ((tag & ICACHE_PTAG) << 8) | ((tag & ICACHE_V) >> 18) | ((tag & ICACHE_P) >> 25);
- m_cp0[CP0_ECC] = 0; // data ecc or parity
-
- break;
- }
-
- case 0x08: // index store tag (I)
- if (ICACHE)
- {
- // FIXME: compute parity
- m_icache_tag[(ADDR(m_r[RSREG], s16(op)) & m_icache_mask_hi) >> m_icache_shift] =
- (m_cp0[CP0_TagLo] & TAGLO_PTAGLO) >> 8 | (m_cp0[CP0_TagLo] & TAGLO_PSTATE) << 18;
-
- break;
- }
-
- case 0x01: // index writeback invalidate (D)
- case 0x02: // index invalidate (SI)
- case 0x03: // index writeback invalidate (SD)
-
- case 0x05: // index load tag (D)
- case 0x06: // index load tag (SI)
- case 0x07: // index load tag (SI)
-
- case 0x09: // index store tag (D)
- case 0x0a: // index store tag (SI)
- case 0x0b: // index store tag (SD)
-
- case 0x0d: // create dirty exclusive (D)
- case 0x0f: // create dirty exclusive (SD)
-
- case 0x10: // hit invalidate (I)
- case 0x11: // hit invalidate (D)
- case 0x12: // hit invalidate (SI)
- case 0x13: // hit invalidate (SD)
-
- case 0x14: // fill (I)
- case 0x15: // hit writeback invalidate (D)
- case 0x17: // hit writeback invalidate (SD)
-
- case 0x18: // hit writeback (I)
- case 0x19: // hit writeback (D)
- case 0x1b: // hit writeback (SD)
-
- case 0x1e: // hit set virtual (SI)
- case 0x1f: // hit set virtual (SD)
- //LOGMASKED(LOG_CACHE, "cache 0x%08x unimplemented (%s)\n", op, machine().describe_context());
- break;
- }
- break;
- case 0x30: // LL
- load_linked<s32>(ADDR(m_r[RSREG], s16(op)),
- [this, op](u64 address, s32 data)
- {
- // remove existing tap
- if (m_ll_watch)
- m_ll_watch->remove();
-
- m_r[RTREG] = data;
- m_cp0[CP0_LLAddr] = u32(address >> 4);
-
- // install write tap
- // FIXME: physical address truncation
- m_ll_watch = space(0).install_write_tap(offs_t(address & ~7), offs_t(address | 7), "ll",
- [this, hi(bool(BIT(address, 2)))](offs_t offset, u64 &data, u64 mem_mask)
- {
- if (hi ? ACCESSING_BITS_32_63 : ACCESSING_BITS_0_31)
- {
- m_ll_watch->remove();
- m_ll_watch = nullptr;
- }
- });
- });
- break;
- case 0x31: // LWC1
- cp1_execute(op);
- break;
- case 0x32: // LWC2
- cp2_execute(op);
- break;
- //case 0x33: // *
- case 0x34: // LLD
- load_linked<u64>(ADDR(m_r[RSREG], s16(op)),
- [this, op](u64 address, u64 data)
- {
- // remove existing tap
- if (m_ll_watch)
- m_ll_watch->remove();
-
- m_r[RTREG] = data;
- m_cp0[CP0_LLAddr] = u32(address >> 4);
-
- // install write tap
- // FIXME: address truncation
- m_ll_watch = space(0).install_write_tap(offs_t(address & ~7), offs_t(address | 7), "lld",
- [this](offs_t offset, u64 &data, u64 mem_mask)
- {
- m_ll_watch->remove();
- m_ll_watch = nullptr;
- });
- });
- break;
- case 0x35: // LDC1
- cp1_execute(op);
- break;
- case 0x36: // LDC2
- cp2_execute(op);
- break;
- case 0x37: // LD
- load<u64>(ADDR(m_r[RSREG], s16(op)),
- [this, op](u64 data)
- {
- m_r[RTREG] = data;
- });
- break;
- case 0x38: // SC
- if (m_ll_watch)
- {
- m_ll_watch->remove();
- m_ll_watch = nullptr;
-
- store<u32>(ADDR(m_r[RSREG], s16(op)), u32(m_r[RTREG]));
- m_r[RTREG] = 1;
- }
- else
- m_r[RTREG] = 0;
- break;
- case 0x39: // SWC1
- cp1_execute(op);
- break;
- case 0x3a: // SWC2
- cp2_execute(op);
- break;
- //case 0x3b: // *
- case 0x3c: // SCD
- if (m_ll_watch)
- {
- m_ll_watch->remove();
- m_ll_watch = nullptr;
-
- store<u64>(ADDR(m_r[RSREG], s16(op)), m_r[RTREG]);
- m_r[RTREG] = 1;
- }
- else
- m_r[RTREG] = 0;
- break;
- case 0x3d: // SDC1
- cp1_execute(op);
- break;
- case 0x3e: // SDC2
- cp2_execute(op);
- break;
- case 0x3f: // SD
- store<u64>(ADDR(m_r[RSREG], s16(op)), m_r[RTREG]);
- break;
-
- default:
- // * Operation codes marked with an asterisk cause reserved instruction
- // exceptions in all current implementations and are reserved for future
- // versions of the architecture.
- cpu_exception(EXCEPTION_RI);
- break;
- }
-}
-
-void r4000_base_device::cpu_exception(u32 exception, u16 const vector)
-{
- if (exception != EXCEPTION_INT)
- LOGMASKED(LOG_EXCEPTION, "exception 0x%08x\n", exception);
-
- if (!(SR & SR_EXL))
- {
- m_cp0[CP0_EPC] = m_pc;
-
- CAUSE = (CAUSE & CAUSE_IP) | exception;
-
- // if in a branch delay slot, restart at the branch instruction
- if (m_branch_state == DELAY)
- {
- m_cp0[CP0_EPC] -= 4;
- CAUSE |= CAUSE_BD;
- }
-
- SR |= SR_EXL;
- }
- else
- CAUSE = (CAUSE & (CAUSE_BD | CAUSE_IP)) | exception;
-
- m_branch_state = EXCEPTION;
- m_pc = ((SR & SR_BEV) ? s64(s32(0xbfc00200)) : s64(s32(0x80000000))) + vector;
-
- if (exception != EXCEPTION_INT)
- debugger_exception_hook(exception);
-}
-
-void r4000_base_device::cpu_lwl(u32 const op)
-{
- u64 const offset = ADDR(m_r[RSREG], s16(op));
- unsigned const shift = ((offset & 3) ^ R4000_ENDIAN_LE_BE(3, 0)) << 3;
-
- load<u32>(offset & ~3,
- [this, op, shift](u32 const data)
- {
- m_r[RTREG] = s32((m_r[RTREG] & ~u32(~u32(0) << shift)) | (data << shift));
- });
-}
-
-void r4000_base_device::cpu_lwr(u32 const op)
-{
- u64 const offset = ADDR(m_r[RSREG], s16(op));
- unsigned const shift = ((offset & 0x3) ^ R4000_ENDIAN_LE_BE(0, 3)) << 3;
-
- load<u32>(offset & ~3,
- [this, op, shift](u32 const data)
- {
- m_r[RTREG] = s32((m_r[RTREG] & ~u32(~u32(0) >> shift)) | (data >> shift));
- });
-}
-
-void r4000_base_device::cpu_swl(u32 const op)
-{
- u64 const offset = ADDR(m_r[RSREG], s16(op));
- unsigned const shift = ((offset & 3) ^ R4000_ENDIAN_LE_BE(3, 0)) << 3;
-
- store<u32>(offset & ~3, u32(m_r[RTREG]) >> shift, ~u32(0) >> shift);
-}
-
-void r4000_base_device::cpu_swr(u32 const op)
-{
- u64 const offset = ADDR(m_r[RSREG], s16(op));
- unsigned const shift = ((offset & 3) ^ R4000_ENDIAN_LE_BE(0, 3)) << 3;
-
- store<u32>(offset & ~3, u32(m_r[RTREG]) << shift, ~u32(0) << shift);
-}
-
-void r4000_base_device::cpu_ldl(u32 const op)
-{
- u64 const offset = ADDR(m_r[RSREG], s16(op));
- unsigned const shift = ((offset & 7) ^ R4000_ENDIAN_LE_BE(7, 0)) << 3;
-
- load<u64>(offset & ~7,
- [this, op, shift](u64 const data)
- {
- m_r[RTREG] = (m_r[RTREG] & ~u64(~u64(0) << shift)) | (data << shift);
- });
-}
-
-void r4000_base_device::cpu_ldr(u32 const op)
-{
- u64 const offset = ADDR(m_r[RSREG], s16(op));
- unsigned const shift = ((offset & 7) ^ R4000_ENDIAN_LE_BE(0, 7)) << 3;
-
- load<u64>(offset & ~7,
- [this, op, shift](u64 const data)
- {
- m_r[RTREG] = (m_r[RTREG] & ~u64(~u64(0) >> shift)) | (data >> shift);
- });
-}
-
-void r4000_base_device::cpu_sdl(u32 const op)
-{
- u64 const offset = ADDR(m_r[RSREG], s16(op));
- unsigned const shift = ((offset & 7) ^ R4000_ENDIAN_LE_BE(7, 0)) << 3;
-
- store<u64>(offset & ~7, m_r[RTREG] >> shift, ~u64(0) >> shift);
-}
-
-void r4000_base_device::cpu_sdr(u32 const op)
-{
- u64 const offset = ADDR(m_r[RSREG], s16(op));
- unsigned const shift = ((offset & 7) ^ R4000_ENDIAN_LE_BE(0, 7)) << 3;
-
- store<u64>(offset & ~7, m_r[RTREG] << shift, ~u64(0) << shift);
-}
-
-void r4000_base_device::cp0_execute(u32 const op)
-{
- if ((SR & SR_KSU) && !(SR & SR_CU0) && !(SR & (SR_EXL | SR_ERL)))
- {
- cpu_exception(EXCEPTION_CP0);
- return;
- }
-
- switch ((op >> 21) & 0x1f)
- {
- case 0x00: // MFC0
- m_r[RTREG] = s32(cp0_get(RDREG));
- break;
- case 0x01: // DMFC0
- // ε Operation codes marked with epsilon are valid when the
- // processor is operating either in the Kernel mode or in the
- // 64-bit non-Kernel (User or Supervisor) mode. These instructions
- // cause a reserved instruction exception if 64-bit operation is
- // not enabled in User or Supervisor mode.
- if (!(SR & SR_KSU) || (SR & (SR_EXL | SR_ERL)) || cp0_64())
- m_r[RTREG] = cp0_get(RDREG);
- else
- cpu_exception(EXCEPTION_RI);
- break;
- case 0x02: // CFC0
- break;
-
- case 0x04: // MTC0
- cp0_set(RDREG, s64(s32(m_r[RTREG])));
- break;
- case 0x05: // DMTC0
- // ε Operation codes marked with epsilon are valid when the
- // processor is operating either in the Kernel mode or in the
- // 64-bit non-Kernel (User or Supervisor) mode. These instructions
- // cause a reserved instruction exception if 64-bit operation is
- // not enabled in User or Supervisor mode.
- if (!(SR & SR_KSU) || (SR & (SR_EXL | SR_ERL)) || cp0_64())
- cp0_set(RDREG, m_r[RTREG]);
- else
- cpu_exception(EXCEPTION_RI);
- break;
- case 0x06: // CTC0
- break;
-
- case 0x08: // BC0
- switch ((op >> 16) & 0x1f)
- {
- case 0x00: // BC0F
- case 0x01: // BC0T
- case 0x02: // BC0FL
- case 0x03: // BC0TL
- // fall through
-
- default:
- // γ Operation codes marked with a gamma cause a reserved
- // instruction exception. They are reserved for future versions
- // of the architecture.
- cpu_exception(EXCEPTION_RI);
- break;
- }
- break;
-
- case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
- case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
- // CP0 function
- switch (op & 0x3f)
- {
- case 0x01: // TLBR
- cp0_tlbr();
- break;
- case 0x02: // TLBWI
- cp0_tlbwi(m_cp0[CP0_Index] & 0x3f);
- break;
-
- case 0x06: // TLBWR
- cp0_tlbwr();
- break;
-
- case 0x08: // TLBP
- cp0_tlbp();
- break;
-
- case 0x10: // RFE
- // ξ Operation codes marked with a xi cause a reserved
- // instruction exception on R4000 processors.
- cpu_exception(EXCEPTION_RI);
- break;
-
- case 0x18: // ERET
- if (SR & SR_ERL)
- {
- logerror("eret from error\n");
- m_branch_state = EXCEPTION;
- m_pc = m_cp0[CP0_ErrorEPC];
- SR &= ~SR_ERL;
- }
- else
- {
- m_branch_state = EXCEPTION;
- m_pc = m_cp0[CP0_EPC];
- SR &= ~SR_EXL;
- }
-
- if (m_ll_watch)
- {
- m_ll_watch->remove();
- m_ll_watch = nullptr;
- }
- break;
-
- default:
- // Φ Operation codes marked with a phi are invalid but do not
- // cause reserved instruction exceptions in R4000 implementations.
- break;
- }
- break;
-
- default:
- // γ Operation codes marked with a gamma cause a reserved
- // instruction exception. They are reserved for future versions
- // of the architecture.
- cpu_exception(EXCEPTION_RI);
- break;
- }
-}
-
-u64 r4000_base_device::cp0_get(unsigned const reg)
-{
- switch (reg)
- {
- case CP0_Count:
- return u32((total_cycles() - m_cp0_timer_zero) / 2);
-
- case CP0_Random:
- {
- u8 const wired = m_cp0[CP0_Wired] & 0x3f;
-
- if (wired < ARRAY_LENGTH(m_tlb))
- return ((total_cycles() - m_cp0_timer_zero) % (ARRAY_LENGTH(m_tlb) - wired) + wired) & 0x3f;
- else
- return ARRAY_LENGTH(m_tlb) - 1;
- }
- break;
-
- default:
- return m_cp0[reg];
- }
-}
-
-void r4000_base_device::cp0_set(unsigned const reg, u64 const data)
-{
- switch (reg)
- {
- case CP0_Count:
- m_cp0[CP0_Count] = u32(data);
- m_cp0_timer_zero = total_cycles() - m_cp0[CP0_Count] * 2;
-
- cp0_update_timer();
- break;
-
- case CP0_EntryHi:
- m_cp0[CP0_EntryHi] = data & (EH_R | EH_VPN2_64 | EH_ASID);
- break;
-
- case CP0_Compare:
- m_cp0[CP0_Compare] = u32(data);
- CAUSE &= ~CAUSE_IPEX5;
-
- cp0_update_timer(true);
- break;
-
- case CP0_Status:
- m_cp0[CP0_Status] = u32(data);
-
- // FIXME: software interrupt check
- if (CAUSE & SR & SR_IMSW)
- m_icount = 0;
-
- if (data & SR_RE)
- fatalerror("unimplemented reverse endian mode enabled (%s)\n", machine().describe_context().c_str());
- break;
-
- case CP0_Cause:
- CAUSE = (CAUSE & ~CAUSE_IPSW) | (data & CAUSE_IPSW);
-
- // FIXME: software interrupt check
- if (CAUSE & SR & SR_IMSW)
- m_icount = 0;
- break;
-
- case CP0_PRId:
- // read-only register
- break;
-
- case CP0_Config:
- m_cp0[CP0_Config] = (m_cp0[CP0_Config] & ~CONFIG_WM) | (data & CONFIG_WM);
-
- if (m_cp0[CP0_Config] & CONFIG_IB)
- {
- m_icache_line_size = 32;
- m_icache_shift = 5;
- m_icache_mask_lo = ~u32(0x1f);
- }
- else
- {
- m_icache_line_size = 16;
- m_icache_shift = 4;
- m_icache_mask_lo = ~u32(0xf);
- }
-
- LOGMASKED(LOG_CACHE, "icache/dcache line sizes %d/%d bytes\n",
- m_icache_line_size, m_cp0[CP0_Config] & CONFIG_DB ? 32 : 16);
- break;
-
- default:
- m_cp0[reg] = data;
- break;
- }
-}
-
-void r4000_base_device::cp0_tlbr()
-{
- u8 const index = m_cp0[CP0_Index] & 0x3f;
-
- if (index < ARRAY_LENGTH(m_tlb))
- {
- tlb_entry_t const &entry = m_tlb[index];
-
- m_cp0[CP0_PageMask] = entry.mask;
- m_cp0[CP0_EntryHi] = entry.vpn;
- m_cp0[CP0_EntryLo0] = entry.pfn[0];
- m_cp0[CP0_EntryLo1] = entry.pfn[1];
- }
-}
-
-void r4000_base_device::cp0_tlbwi(u8 const index)
-{
- if (index < ARRAY_LENGTH(m_tlb))
- {
- tlb_entry_t &entry = m_tlb[index];
-
- entry.mask = m_cp0[CP0_PageMask];
- entry.vpn = m_cp0[CP0_EntryHi];
- if ((m_cp0[CP0_EntryLo0] & EL_G) && (m_cp0[CP0_EntryLo1] & EL_G))
- entry.vpn |= EH_G;
- entry.pfn[0] = m_cp0[CP0_EntryLo0];
- entry.pfn[1] = m_cp0[CP0_EntryLo1];
-
- entry.low_bit = 32 - count_leading_zeros((entry.mask >> 1) | 0xfff);
-
- LOGMASKED(LOG_TLB, "tlb write index %02d mask 0x%016x vpn2 0x%016x %c asid 0x%02x pfn0 0x%016x %c%c pfn1 0x%016x %c%c (%s)\n",
- index, entry.mask,
- entry.vpn, entry.vpn & EH_G ? 'G' : '-', entry.vpn & EH_ASID,
- entry.pfn[0] & EL_PFN, entry.pfn[0] & EL_D ? 'D' : '-', entry.pfn[0] & EL_V ? 'V' : '-',
- entry.pfn[1] & EL_PFN, entry.pfn[1] & EL_D ? 'D' : '-', entry.pfn[1] & EL_V ? 'V' : '-',
- machine().describe_context());
- }
-}
-
-void r4000_base_device::cp0_tlbwr()
-{
- u8 const wired = m_cp0[CP0_Wired] & 0x3f;
- u8 const unwired = ARRAY_LENGTH(m_tlb) - wired;
-
- u8 const index = (unwired > 0) ? ((total_cycles() - m_cp0_timer_zero) % unwired + wired) & 0x3f : (ARRAY_LENGTH(m_tlb) - 1);
-
- cp0_tlbwi(index);
-}
-
-void r4000_base_device::cp0_tlbp()
-{
- m_cp0[CP0_Index] = 0x80000000;
- for (u8 index = 0; index < ARRAY_LENGTH(m_tlb); index++)
- {
- tlb_entry_t const &entry = m_tlb[index];
-
- u64 const mask = (cp0_64() ? EH_R | (EH_VPN2_64 & ~entry.mask) : (EH_VPN2_32 & ~entry.mask))
- | ((entry.vpn & EH_G) ? 0 : EH_ASID);
-
- if ((entry.vpn & mask) == (m_cp0[CP0_EntryHi] & mask))
- {
- m_cp0[CP0_Index] = index;
- break;
- }
- }
-
- if (m_cp0[CP0_Index] == 0x80000000)
- LOGMASKED(LOG_TLB, "tlbp miss 0x%08x\n", m_cp0[CP0_EntryHi]);
- else
- LOGMASKED(LOG_TLB, "tlbp hit 0x%08x index %02d\n", m_cp0[CP0_EntryHi], m_cp0[CP0_Index]);
-}
-
-void r4000_base_device::cp0_update_timer(bool start)
-{
- if (start || m_cp0_timer->enabled())
- {
- u32 const count = (total_cycles() - m_cp0_timer_zero) / 2;
- u32 const delta = m_cp0[CP0_Compare] - count;
-
- m_cp0_timer->adjust(cycles_to_attotime(u64(delta) * 2));
- }
-}
-
-TIMER_CALLBACK_MEMBER(r4000_base_device::cp0_timer_callback)
-{
- m_cp0[CP0_Cause] |= CAUSE_IPEX5;
-}
-
-bool r4000_base_device::cp0_64() const
-{
- switch (SR & (SR_KSU | SR_ERL | SR_EXL))
- {
- case SR_KSU_U: return bool(SR & SR_UX);
- case SR_KSU_S: return bool(SR & SR_SX);
-
- default:
- return bool(SR & SR_KX);
- }
-}
-
-void r4000_base_device::cp1_execute(u32 const op)
-{
- if (!(SR & SR_CU1))
- {
- cpu_exception(EXCEPTION_CP1);
- return;
- }
-
- softfloat_exceptionFlags = 0;
- switch (op >> 26)
- {
- case 0x11: // COP1
- switch ((op >> 21) & 0x1f)
- {
- case 0x00: // MFC1
- if (SR & SR_FR)
- m_r[RTREG] = s64(s32(m_f[RDREG]));
- else
- if (RDREG & 1)
- // move the high half of the even floating point register
- m_r[RTREG] = s64(s32(m_f[RDREG & ~1] >> 32));
- else
- // move the low half of the even floating point register
- m_r[RTREG] = s64(s32(m_f[RDREG & ~1] >> 0));
- break;
- case 0x01: // DMFC1
- // TODO: MIPS3 only
- if ((SR & SR_FR) || !(RDREG & 1))
- m_r[RTREG] = m_f[RDREG];
- break;
- case 0x02: // CFC1
- switch (RDREG)
- {
- case 0: m_r[RTREG] = m_fcr0; break;
- case 30: m_r[RTREG] = m_fcr30; break;
- case 31: m_r[RTREG] = m_fcr31; break;
-
- default:
- logerror("cfc1 undefined fpu control register %d (%s)\n", RDREG, machine().describe_context());
- break;
- }
- break;
- case 0x04: // MTC1
- if (SR & SR_FR)
- m_f[RDREG] = u32(m_r[RTREG]);
- else
- if (RDREG & 1)
- // load the high half of the even floating point register
- m_f[RDREG & ~1] = (m_r[RTREG] << 32) | u32(m_f[RDREG & ~1]);
- else
- // load the low half of the even floating point register
- m_f[RDREG & ~1] = (m_f[RDREG & ~1] & ~0xffffffffULL) | u32(m_r[RTREG]);
- break;
- case 0x05: // DMTC1
- // TODO: MIPS3 only
- if ((SR & SR_FR) || !(RDREG & 1))
- m_f[RDREG] = m_r[RTREG];
- break;
- case 0x06: // CTC1
- switch (RDREG)
- {
- case 0: // register is read-only
- break;
-
- case 30: // unknown
- m_fcr30 = u32(m_r[RTREG]);
- break;
-
- case 31:
- m_fcr31 = u32(m_r[RTREG]);
-
- // update rounding mode
- switch (m_fcr31 & FCR31_RM)
- {
- case 0: softfloat_roundingMode = softfloat_round_near_even; break;
- case 1: softfloat_roundingMode = softfloat_round_minMag; break;
- case 2: softfloat_roundingMode = softfloat_round_max; break;
- case 3: softfloat_roundingMode = softfloat_round_min; break;
- }
-
- // exception check
- if ((m_fcr31 & FCR31_CE) || ((m_fcr31 & FCR31_CM) >> 5) & (m_fcr31 & FCR31_EM))
- cpu_exception(EXCEPTION_FPE);
-
- break;
-
- default:
- logerror("ctc1 undefined fpu control register %d (%s)\n", RDREG, machine().describe_context());
- break;
- }
- break;
- case 0x08: // BC
- switch ((op >> 16) & 0x1f)
- {
- case 0x00: // BC1F
- if (!(m_fcr31 & FCR31_C))
- {
- m_branch_state = BRANCH;
- m_branch_target = ADDR(m_pc + 4, s32(s16(op)) << 2);
- }
- break;
- case 0x01: // BC1T
- if (m_fcr31 & FCR31_C)
- {
- m_branch_state = BRANCH;
- m_branch_target = ADDR(m_pc + 4, s32(s16(op)) << 2);
- }
- break;
- case 0x02: // BC1FL
- if (!(m_fcr31 & FCR31_C))
- {
- m_branch_state = BRANCH;
- m_branch_target = ADDR(m_pc + 4, s32(s16(op)) << 2);
- }
- else
- m_branch_state = NULLIFY;
- break;
- case 0x03: // BC1TL
- if (m_fcr31 & FCR31_C)
- {
- m_branch_state = BRANCH;
- m_branch_target = ADDR(m_pc + 4, s32(s16(op)) << 2);
- }
- else
- m_branch_state = NULLIFY;
- break;
-
- default:
- // reserved instructions
- cpu_exception(EXCEPTION_RI);
- break;
- }
- break;
-
- case 0x10: // S
- switch (op & 0x3f)
- {
- case 0x00: // ADD.S
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f32_add(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) }).v);
- break;
- case 0x01: // SUB.S
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f32_sub(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) }).v);
- break;
- case 0x02: // MUL.S
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f32_mul(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) }).v);
- break;
- case 0x03: // DIV.S
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f32_div(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) }).v);
- break;
- case 0x04: // SQRT.S
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f32_sqrt(float32_t{ u32(m_f[FSREG]) }).v);
- break;
- case 0x05: // ABS.S
- if ((SR & SR_FR) || !(op & ODD_REGS))
- {
- if (f32_lt(float32_t{ u32(m_f[FSREG]) }, float32_t{ 0 }))
- cp1_set(FDREG, f32_mul(float32_t{ u32(m_f[FSREG]) }, i32_to_f32(-1)).v);
- else
- cp1_set(FDREG, m_f[FSREG]);
- }
- break;
- case 0x06: // MOV.S
- if ((SR & SR_FR) || !(op & ODD_REGS))
- m_f[FDREG] = m_f[FSREG];
- break;
- case 0x07: // NEG.S
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f32_mul(float32_t{ u32(m_f[FSREG]) }, i32_to_f32(-1)).v);
- break;
- case 0x08: // ROUND.L.S
- // TODO: MIPS3 only
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f32_to_i64(float32_t{ u32(m_f[FSREG]) }, softfloat_round_near_even, true));
- break;
- case 0x09: // TRUNC.L.S
- // TODO: MIPS3 only
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f32_to_i64(float32_t{ u32(m_f[FSREG]) }, softfloat_round_minMag, true));
- break;
- case 0x0a: // CEIL.L.S
- // TODO: MIPS3 only
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f32_to_i64(float32_t{ u32(m_f[FSREG]) }, softfloat_round_max, true));
- break;
- case 0x0b: // FLOOR.L.S
- // TODO: MIPS3 only
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f32_to_i64(float32_t{ u32(m_f[FSREG]) }, softfloat_round_min, true));
- break;
- case 0x0c: // ROUND.W.S
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f32_to_i32(float32_t{ u32(m_f[FSREG]) }, softfloat_round_near_even, true));
- break;
- case 0x0d: // TRUNC.W.S
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f32_to_i32(float32_t{ u32(m_f[FSREG]) }, softfloat_round_minMag, true));
- break;
- case 0x0e: // CEIL.W.S
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f32_to_i32(float32_t{ u32(m_f[FSREG]) }, softfloat_round_max, true));
- break;
- case 0x0f: // FLOOR.W.S
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f32_to_i32(float32_t{ u32(m_f[FSREG]) }, softfloat_round_min, true));
- break;
-
- case 0x21: // CVT.D.S
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f32_to_f64(float32_t{ u32(m_f[FSREG]) }).v);
- break;
- case 0x24: // CVT.W.S
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f32_to_i32(float32_t{ u32(m_f[FSREG]) }, softfloat_roundingMode, true));
- break;
- case 0x25: // CVT.L.S
- // TODO: MIPS3 only
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f32_to_i64(float32_t{ u32(m_f[FSREG]) }, softfloat_roundingMode, true));
- break;
-
- case 0x30: // C.F.S (false)
- if ((SR & SR_FR) || !(op & ODD_REGS))
- m_fcr31 &= ~FCR31_C;
- break;
- case 0x31: // C.UN.S (unordered)
- if ((SR & SR_FR) || !(op & ODD_REGS))
- {
- // detect unordered
- f32_eq(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) });
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
- }
- break;
- case 0x32: // C.EQ.S (equal)
- if ((SR & SR_FR) || !(op & ODD_REGS))
- {
- if (f32_eq(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) }))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
- }
- break;
- case 0x33: // C.UEQ.S (unordered equal)
- if ((SR & SR_FR) || !(op & ODD_REGS))
- {
- if (f32_eq(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
- }
- break;
- case 0x34: // C.OLT.S (less than)
- if ((SR & SR_FR) || !(op & ODD_REGS))
- {
- if (f32_lt(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) }))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
- }
- break;
- case 0x35: // C.ULT.S (unordered less than)
- if ((SR & SR_FR) || !(op & ODD_REGS))
- {
- if (f32_lt(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
- }
- break;
- case 0x36: // C.OLE.S (less than or equal)
- if ((SR & SR_FR) || !(op & ODD_REGS))
- {
- if (f32_le(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) }))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
- }
- break;
- case 0x37: // C.ULE.S (unordered less than or equal)
- if ((SR & SR_FR) || !(op & ODD_REGS))
- {
- if (f32_le(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
- }
- break;
-
- case 0x38: // C.SF.S (signalling false)
- if ((SR & SR_FR) || !(op & ODD_REGS))
- {
- // detect unordered
- f32_eq(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) });
-
- m_fcr31 &= ~FCR31_C;
-
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- {
- m_fcr31 |= FCR31_CV;
- cpu_exception(EXCEPTION_FPE);
- }
- }
- break;
- case 0x39: // C.NGLE.S (not greater, less than or equal)
- if ((SR & SR_FR) || !(op & ODD_REGS))
- {
- // detect unordered
- f32_eq(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) });
-
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- {
- m_fcr31 |= FCR31_C | FCR31_CV;
- cpu_exception(EXCEPTION_FPE);
- }
- else
- m_fcr31 &= ~FCR31_C;
- }
- break;
- case 0x3a: // C.SEQ.S (signalling equal)
- if ((SR & SR_FR) || !(op & ODD_REGS))
- {
- if (f32_eq(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) }))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
-
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- {
- m_fcr31 |= FCR31_CV;
- cpu_exception(EXCEPTION_FPE);
- }
- }
- break;
- case 0x3b: // C.NGL.S (not greater or less than)
- if ((SR & SR_FR) || !(op & ODD_REGS))
- {
- if (f32_eq(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
-
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- {
- m_fcr31 |= FCR31_CV;
- cpu_exception(EXCEPTION_FPE);
- }
- }
- break;
- case 0x3c: // C.LT.S (less than)
- if ((SR & SR_FR) || !(op & ODD_REGS))
- {
- if (f32_lt(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) }))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
-
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- {
- m_fcr31 |= FCR31_CV;
- cpu_exception(EXCEPTION_FPE);
- }
- }
- break;
- case 0x3d: // C.NGE.S (not greater or equal)
- if ((SR & SR_FR) || !(op & ODD_REGS))
- {
- if (f32_lt(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
-
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- {
- m_fcr31 |= FCR31_CV;
- cpu_exception(EXCEPTION_FPE);
- }
- }
- break;
- case 0x3e: // C.LE.S (less than or equal)
- if ((SR & SR_FR) || !(op & ODD_REGS))
- {
- if (f32_le(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) }))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
-
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- {
- m_fcr31 |= FCR31_CV;
- cpu_exception(EXCEPTION_FPE);
- }
- }
- break;
- case 0x3f: // C.NGT.S (not greater than)
- if ((SR & SR_FR) || !(op & ODD_REGS))
- {
- if (f32_le(float32_t{ u32(m_f[FSREG]) }, float32_t{ u32(m_f[FTREG]) }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
-
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- {
- m_fcr31 |= FCR31_CV;
- cpu_exception(EXCEPTION_FPE);
- }
- }
- break;
-
- default: // unimplemented operations
- m_fcr31 |= FCR31_CE;
- cpu_exception(EXCEPTION_FPE);
- break;
- }
- break;
- case 0x11: // D
- switch (op & 0x3f)
- {
- case 0x00: // ADD.D
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f64_add(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] }).v);
- break;
- case 0x01: // SUB.D
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f64_sub(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] }).v);
- break;
- case 0x02: // MUL.D
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f64_mul(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] }).v);
- break;
- case 0x03: // DIV.D
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f64_div(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] }).v);
- break;
- case 0x04: // SQRT.D
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f64_sqrt(float64_t{ m_f[FSREG] }).v);
- break;
- case 0x05: // ABS.D
- if ((SR & SR_FR) || !(op & ODD_REGS))
- {
- if (f64_lt(float64_t{ m_f[FSREG] }, float64_t{ 0 }))
- cp1_set(FDREG, f64_mul(float64_t{ m_f[FSREG] }, i32_to_f64(-1)).v);
- else
- cp1_set(FDREG, m_f[FSREG]);
- }
- break;
- case 0x06: // MOV.D
- if ((SR & SR_FR) || !(op & ODD_REGS))
- m_f[FDREG] = m_f[FSREG];
- break;
- case 0x07: // NEG.D
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f64_mul(float64_t{ m_f[FSREG] }, i32_to_f64(-1)).v);
- break;
- case 0x08: // ROUND.L.D
- // TODO: MIPS3 only
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f64_to_i64(float64_t{ m_f[FSREG] }, softfloat_round_near_even, true));
- break;
- case 0x09: // TRUNC.L.D
- // TODO: MIPS3 only
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f64_to_i64(float64_t{ m_f[FSREG] }, softfloat_round_minMag, true));
- break;
- case 0x0a: // CEIL.L.D
- // TODO: MIPS3 only
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f64_to_i64(float64_t{ m_f[FSREG] }, softfloat_round_max, true));
- break;
- case 0x0b: // FLOOR.L.D
- // TODO: MIPS3 only
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f64_to_i64(float64_t{ m_f[FSREG] }, softfloat_round_min, true));
- break;
- case 0x0c: // ROUND.W.D
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f64_to_i32(float64_t{ m_f[FSREG] }, softfloat_round_near_even, true));
- break;
- case 0x0d: // TRUNC.W.D
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f64_to_i32(float64_t{ m_f[FSREG] }, softfloat_round_minMag, true));
- break;
- case 0x0e: // CEIL.W.D
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f64_to_i32(float64_t{ m_f[FSREG] }, softfloat_round_max, true));
- break;
- case 0x0f: // FLOOR.W.D
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f64_to_i32(float64_t{ m_f[FSREG] }, softfloat_round_min, true));
- break;
-
- case 0x20: // CVT.S.D
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f64_to_f32(float64_t{ m_f[FSREG] }).v);
- break;
- case 0x24: // CVT.W.D
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f64_to_i32(float64_t{ m_f[FSREG] }, softfloat_roundingMode, true));
- break;
- case 0x25: // CVT.L.D
- // TODO: MIPS3 only
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, f64_to_i64(float64_t{ m_f[FSREG] }, softfloat_roundingMode, true));
- break;
-
- case 0x30: // C.F.D (false)
- if ((SR & SR_FR) || !(op & ODD_REGS))
- m_fcr31 &= ~FCR31_C;
- break;
- case 0x31: // C.UN.D (unordered)
- if ((SR & SR_FR) || !(op & ODD_REGS))
- {
- // detect unordered
- f64_eq(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] });
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
- }
- break;
- case 0x32: // C.EQ.D (equal)
- if ((SR & SR_FR) || !(op & ODD_REGS))
- {
- if (f64_eq(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] }))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
- }
- break;
- case 0x33: // C.UEQ.D (unordered equal)
- if ((SR & SR_FR) || !(op & ODD_REGS))
- {
- if (f64_eq(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
- }
- break;
- case 0x34: // C.OLT.D (less than)
- if ((SR & SR_FR) || !(op & ODD_REGS))
- {
- if (f64_lt(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] }))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
- }
- break;
- case 0x35: // C.ULT.D (unordered less than)
- if ((SR & SR_FR) || !(op & ODD_REGS))
- {
- if (f64_lt(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
- }
- break;
- case 0x36: // C.OLE.D (less than or equal)
- if ((SR & SR_FR) || !(op & ODD_REGS))
- {
- if (f64_le(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] }))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
- }
- break;
- case 0x37: // C.ULE.D (unordered less than or equal)
- if ((SR & SR_FR) || !(op & ODD_REGS))
- {
- if (f64_le(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
- }
- break;
-
- case 0x38: // C.SF.D (signalling false)
- if ((SR & SR_FR) || !(op & ODD_REGS))
- {
- // detect unordered
- f64_eq(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] });
-
- m_fcr31 &= ~FCR31_C;
-
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- {
- m_fcr31 |= FCR31_CV;
- cpu_exception(EXCEPTION_FPE);
- }
- }
- break;
- case 0x39: // C.NGLE.D (not greater, less than or equal)
- if ((SR & SR_FR) || !(op & ODD_REGS))
- {
- // detect unordered
- f64_eq(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] });
-
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- {
- m_fcr31 |= FCR31_C | FCR31_CV;
- cpu_exception(EXCEPTION_FPE);
- }
- else
- m_fcr31 &= ~FCR31_C;
- }
- break;
- case 0x3a: // C.SEQ.D (signalling equal)
- if ((SR & SR_FR) || !(op & ODD_REGS))
- {
- if (f64_eq(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] }))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
-
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- {
- m_fcr31 |= FCR31_CV;
- cpu_exception(EXCEPTION_FPE);
- }
- }
- break;
- case 0x3b: // C.NGL.D (not greater or less than)
- if ((SR & SR_FR) || !(op & ODD_REGS))
- {
- if (f64_eq(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
-
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- {
- m_fcr31 |= FCR31_CV;
- cpu_exception(EXCEPTION_FPE);
- }
- }
- break;
- case 0x3c: // C.LT.D (less than)
- if ((SR & SR_FR) || !(op & ODD_REGS))
- {
- if (f64_lt(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] }))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
-
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- {
- m_fcr31 |= FCR31_CV;
- cpu_exception(EXCEPTION_FPE);
- }
- }
- break;
- case 0x3d: // C.NGE.D (not greater or equal)
- if ((SR & SR_FR) || !(op & ODD_REGS))
- {
- if (f64_lt(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
-
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- {
- m_fcr31 |= FCR31_CV;
- cpu_exception(EXCEPTION_FPE);
- }
- }
- break;
- case 0x3e: // C.LE.D (less than or equal)
- if ((SR & SR_FR) || !(op & ODD_REGS))
- {
- if (f64_le(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] }))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
-
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- {
- m_fcr31 |= FCR31_CV;
- cpu_exception(EXCEPTION_FPE);
- }
- }
- break;
- case 0x3f: // C.NGT.D (not greater than)
- if ((SR & SR_FR) || !(op & ODD_REGS))
- {
- if (f64_le(float64_t{ m_f[FSREG] }, float64_t{ m_f[FTREG] }) || (softfloat_exceptionFlags & softfloat_flag_invalid))
- m_fcr31 |= FCR31_C;
- else
- m_fcr31 &= ~FCR31_C;
-
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- {
- m_fcr31 |= FCR31_CV;
- cpu_exception(EXCEPTION_FPE);
- }
- }
- break;
-
- default: // unimplemented operations
- m_fcr31 |= FCR31_CE;
- cpu_exception(EXCEPTION_FPE);
- break;
- }
- break;
- case 0x14: // W
- switch (op & 0x3f)
- {
- case 0x20: // CVT.S.W
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, i32_to_f32(s32(m_f[FSREG])).v);
- break;
- case 0x21: // CVT.D.W
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, i32_to_f64(s32(m_f[FSREG])).v);
- break;
-
- default: // unimplemented operations
- m_fcr31 |= FCR31_CE;
- cpu_exception(EXCEPTION_FPE);
- break;
- }
- break;
- case 0x15: // L
- // TODO: MIPS3 only
- switch (op & 0x3f)
- {
- case 0x02a00020: // CVT.S.L
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, i64_to_f32(s64(m_f[FSREG])).v);
- break;
- case 0x02a00021: // CVT.D.L
- if ((SR & SR_FR) || !(op & ODD_REGS))
- cp1_set(FDREG, i64_to_f64(s64(m_f[FSREG])).v);
- break;
-
- default: // unimplemented operations
- m_fcr31 |= FCR31_CE;
- cpu_exception(EXCEPTION_FPE);
- break;
- }
- break;
-
- default: // unimplemented operations
- m_fcr31 |= FCR31_CE;
- cpu_exception(EXCEPTION_FPE);
- break;
- }
- break;
-
- case 0x31: // LWC1
- load<u32>(ADDR(m_r[RSREG], s16(op)),
- [this, op](u32 data)
- {
- if (SR & SR_FR)
- m_f[RTREG] = data;
- else
- if (RTREG & 1)
- // load the high half of the even floating point register
- m_f[RTREG & ~1] = (u64(data) << 32) | u32(m_f[RTREG & ~1]);
- else
- // load the low half of the even floating point register
- m_f[RTREG & ~1] = (m_f[RTREG & ~1] & ~0xffffffffULL) | data;
- });
- break;
-
- case 0x35: // LDC1
- load<u64>(ADDR(m_r[RSREG], s16(op)),
- [this, op](u64 data)
- {
- if ((SR & SR_FR) || !(RTREG & 1))
- m_f[RTREG] = data;
- });
- break;
-
- case 0x39: // SWC1
- if (SR & SR_FR)
- store<u32>(ADDR(m_r[RSREG], s16(op)), u32(m_f[RTREG]));
- else
- if (RTREG & 1)
- // store the high half of the even floating point register
- store<u32>(ADDR(m_r[RSREG], s16(op)), u32(m_f[RTREG & ~1] >> 32));
- else
- // store the low half of the even floating point register
- store<u32>(ADDR(m_r[RSREG], s16(op)), u32(m_f[RTREG & ~1]));
- break;
-
- case 0x3d: // SDC1
- if ((SR & SR_FR) || !(RTREG & 1))
- store<u64>(ADDR(m_r[RSREG], s16(op)), m_f[RTREG]);
- break;
- }
-}
-
-void r4000_base_device::cp1_set(unsigned const reg, u64 const data)
-{
- // translate softfloat exception flags to cause register
- if (softfloat_exceptionFlags)
- {
- if (softfloat_exceptionFlags & softfloat_flag_inexact)
- m_fcr31 |= FCR31_CI;
- if (softfloat_exceptionFlags & softfloat_flag_underflow)
- m_fcr31 |= FCR31_CU;
- if (softfloat_exceptionFlags & softfloat_flag_overflow)
- m_fcr31 |= FCR31_CO;
- if (softfloat_exceptionFlags & softfloat_flag_infinite)
- m_fcr31 |= FCR31_CZ;
- if (softfloat_exceptionFlags & softfloat_flag_invalid)
- m_fcr31 |= FCR31_CV;
-
- // check if exception is enabled
- if (((m_fcr31 & FCR31_CM) >> 5) & (m_fcr31 & FCR31_EM))
- {
- cpu_exception(EXCEPTION_FPE);
- return;
- }
-
- // set flags
- m_fcr31 |= ((m_fcr31 & FCR31_CM) >> 10);
- }
-
- m_f[reg] = data;
-}
-
-void r4000_base_device::cp2_execute(u32 const op)
-{
- if (!(SR & SR_CU2))
- {
- cpu_exception(EXCEPTION_CP2);
- return;
- }
-
- switch (op >> 26)
- {
- case 0x12: // COP2
- switch ((op >> 21) & 0x1f)
- {
- case 0x00: // MFC2
- logerror("mfc2 unimplemented (%s)\n", machine().describe_context());
- break;
- case 0x01: // DMFC2
- // ε Operation codes marked with epsilon are valid when the
- // processor is operating either in the Kernel mode or in the
- // 64-bit non-Kernel (User or Supervisor) mode. These instructions
- // cause a reserved instruction exception if 64-bit operation is
- // not enabled in User or Supervisor mode.
- if (!(SR & SR_KSU) || (SR & (SR_EXL | SR_ERL)) || cp0_64())
- logerror("dmfc2 unimplemented (%s)\n", machine().describe_context());
- else
- cpu_exception(EXCEPTION_RI);
- break;
- case 0x02: // CFC2
- logerror("cfc2 unimplemented (%s)\n", machine().describe_context());
- break;
-
- case 0x04: // MTC2
- logerror("mtc2 unimplemented (%s)\n", machine().describe_context());
- break;
- case 0x05: // DMTC2
- // ε Operation codes marked with epsilon are valid when the
- // processor is operating either in the Kernel mode or in the
- // 64-bit non-Kernel (User or Supervisor) mode. These instructions
- // cause a reserved instruction exception if 64-bit operation is
- // not enabled in User or Supervisor mode.
- if (!(SR & SR_KSU) || (SR & (SR_EXL | SR_ERL)) || cp0_64())
- logerror("dmtc2 unimplemented (%s)\n", machine().describe_context());
- else
- cpu_exception(EXCEPTION_RI);
- break;
- case 0x06: // CTC2
- logerror("ctc2 unimplemented (%s)\n", machine().describe_context());
- break;
-
- case 0x08: // BC2
- switch ((op >> 16) & 0x1f)
- {
- case 0x00: // BC2F
- case 0x01: // BC2F
- case 0x02: // BC2FL
- case 0x03: // BC2TL
- logerror("bc2 unimplemented (%s)\n", machine().describe_context());
- break;
-
- default:
- // γ Operation codes marked with a gamma cause a reserved
- // instruction exception. They are reserved for future versions
- // of the architecture.
- cpu_exception(EXCEPTION_RI);
- break;
- }
- break;
-
- case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17:
- case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: case 0x1d: case 0x1e: case 0x1f:
- // CP2 function
- logerror("function unimplemented (%s)\n", machine().describe_context());
- break;
-
- default:
- // γ Operation codes marked with a gamma cause a reserved
- // instruction exception. They are reserved for future versions
- // of the architecture.
- cpu_exception(EXCEPTION_RI);
- break;
- }
- break;
-
- case 0x32: // LWC2
- logerror("lwc2 unimplemented (%s)\n", machine().describe_context());
- break;
-
- case 0x36: // LDC2
- logerror("ldc2 unimplemented (%s)\n", machine().describe_context());
- break;
-
- case 0x3a: // SWC2
- logerror("swc2 unimplemented (%s)\n", machine().describe_context());
- break;
-
- case 0x3e: // SDC2
- logerror("sdc2 unimplemented (%s)\n", machine().describe_context());
- break;
- }
-}
-
-r4000_base_device::translate_t r4000_base_device::translate(int intention, u64 &address)
-{
- /*
- * Decode the program address into one of the following ranges depending on
- * the active status register bits.
- *
- * 32-bit modes
- * user: 0x0000'0000-0x7fff'ffff (useg, mapped)
- *
- * super: 0x0000'0000-0x7fff'ffff (suseg, mapped)
- * 0xc000'0000-0xdfff'ffff (ssseg, mapped)
- *
- * kernel: 0x0000'0000-0x7fff'ffff (kuseg, mapped)
- * 0x8000'0000-0x9fff'ffff (kseg0, unmapped, cached)
- * 0xa000'0000-0xbfff'ffff (kseg1, unmapped, uncached)
- * 0xc000'0000-0xdfff'ffff (ksseg, mapped)
- * 0xe000'0000-0xffff'ffff (kseg3, mapped)
- *
- * 64-bit modes
- * user: 0x0000'0000'0000'0000-0x0000'00ff'ffff'ffff (xuseg, mapped)
- *
- * super: 0x0000'0000'0000'0000-0x0000'00ff'ffff'ffff (xsuseg, mapped)
- * 0x4000'0000'0000'0000-0x4000'00ff'ffff'ffff (xsseg, mapped)
- * 0xffff'ffff'c000'0000-0xffff'ffff'dfff'ffff (csseg, mapped)
- *
- * kernel: 0x0000'0000'0000'0000-0x0000'00ff'ffff'ffff (xkuseg, mapped)
- * 0x4000'0000'0000'0000-0x4000'00ff'ffff'ffff (xksseg, mapped)
- * 0x8000'0000'0000'0000-0xbfff'ffff'ffff'ffff (xkphys, unmapped)
- * 0xc000'0000'0000'0000-0xc000'00ff'7fff'ffff (xkseg, mapped)
- * 0xffff'ffff'8000'0000-0xffff'ffff'9fff'ffff (ckseg0, unmapped, cached)
- * 0xffff'ffff'a000'0000-0xffff'ffff'bfff'ffff (ckseg1, unmapped, uncached)
- * 0xffff'ffff'c000'0000-0xffff'ffff'dfff'ffff (cksseg, mapped)
- * 0xffff'ffff'e000'0000-0xffff'ffff'ffff'ffff (ckseg3, mapped)
- */
-
- bool extended = false;
-
- switch (SR & (SR_KSU | SR_ERL | SR_EXL))
- {
- case SR_KSU_U:
- // user mode
- if (SR & SR_UX)
- {
- // 64-bit user mode
- if (address & 0xffff'ff00'0000'0000)
- return ERROR; // exception
- else
- extended = true; // xuseg
- }
- else
- {
- // 32-bit user mode
- if (address & 0xffff'ffff'8000'0000)
- return ERROR; // exception
- else
- extended = false; // useg
- }
- break;
-
- case SR_KSU_S:
- // supervisor mode
- if (SR & SR_SX)
- {
- // 64-bit supervisor mode
- if (address & 0xffff'ff00'0000'0000)
- if ((address & 0xffff'ff00'0000'0000) == 0x4000'0000'0000'0000)
- extended = true; // xsseg
- else
- if ((address & 0xffff'ffff'e000'0000) == 0xffff'ffff'c000'0000)
- extended = true; // csseg
- else
- return ERROR; // exception
- else
- extended = true; // xsuseg
- }
- else
- {
- // 32-bit supervisor mode
- if (address & 0xffff'ffff'8000'0000)
- if ((address & 0xffff'ffff'e000'0000) == 0xffff'ffff'c000'0000)
- extended = false; // sseg
- else
- return ERROR; // exception
- else
- extended = false; // suseg
- }
- break;
-
- case SR_KSU_U | SR_KSU_S:
- fatalerror("invalid ksu bits 0x%08x (%s)\n", u32(SR), machine().describe_context().c_str());
- break;
-
- default:
- // kernel mode
- if (SR & SR_KX)
- {
- // 64-bit kernel mode
- if (address & 0xffff'ff00'0000'0000)
- if ((address & 0xffff'ff00'0000'0000) == 0x4000'0000'0000'0000)
- extended = true; // xksseg
- else
- if ((address & 0xc000'0000'0000'0000) == 0x8000'0000'0000'0000)
- {
- address &= 0x0000'000f'ffff'ffff; // xkphys
-
- // FIXME: caching depends on top three bits
- return CACHED;
- }
- else
- if ((address & 0xffff'ff00'0000'0000) == 0xc000'0000'0000'0000)
- if ((address & 0x0000'00ff'8000'0000) == 0x0000'00ff'8000'0000)
- return ERROR; // exception
- else
- extended = true; // xkseg
- else
- // FIXME: ckseg0 caching depends on config regiter
- switch (address & 0xffff'ffff'e000'0000)
- {
- case 0xffff'ffff'8000'0000: address &= 0x7fff'ffff; return CACHED; // ckseg0
- case 0xffff'ffff'a000'0000: address &= 0x1fff'ffff; return UNCACHED; // ckseg1
- case 0xffff'ffff'c000'0000: extended = true; break; // cksseg
- case 0xffff'ffff'e000'0000: extended = true; break; // ckseg3
- default: return ERROR; // exception
- }
- else
- if (SR & SR_ERL)
- // FIXME: documentation says 2^31, but assume it should be 2^40
- return UNCACHED; // xkuseg (unmapped, uncached)
- else
- extended = true; // xkuseg
- }
- else
- {
- // 32-bit kernel mode
- if (address & 0xffff'ffff'8000'0000)
- switch (address & 0xffff'ffff'e000'0000)
- {
- case 0xffff'ffff'8000'0000: address &= 0x7fff'ffff; return CACHED; // kseg0
- case 0xffff'ffff'a000'0000: address &= 0x1fff'ffff; return UNCACHED; // kseg1
- case 0xffff'ffff'c000'0000: extended = false; break; // ksseg
- case 0xffff'ffff'e000'0000: extended = false; break; // kseg3
- default: return ERROR; // exception
- }
- else
- if (SR & SR_ERL)
- return UNCACHED; // kuseg (unmapped, uncached)
- else
- extended = false; // kuseg
- }
- break;
- }
-
- // address needs translation, using a combination of VPN2 and ASID
- u64 const key = (address & (extended ? (EH_R | EH_VPN2_64) : EH_VPN2_32)) | (m_cp0[CP0_EntryHi] & EH_ASID);
-
- unsigned *mru = m_tlb_mru[intention & TRANSLATE_TYPE_MASK];
- if (LOG_STATS)
- m_tlb_scans++;
-
- bool invalid = false;
- bool modify = false;
- for (unsigned i = 0; i < ARRAY_LENGTH(m_tlb); i++)
- {
- unsigned const index = mru[i];
- tlb_entry_t const &entry = m_tlb[index];
-
- // test vpn and asid
- u64 const mask = (extended ? EH_R | (EH_VPN2_64 & ~entry.mask) : (EH_VPN2_32 & ~entry.mask))
- | ((entry.vpn & EH_G) ? 0 : EH_ASID);
-
- if ((entry.vpn & mask) != (key & mask))
- continue;
-
- if (LOG_STATS)
- m_tlb_loops += i + 1;
-
- u64 const pfn = entry.pfn[BIT(address, entry.low_bit)];
-
- // test valid
- if (!(pfn & EL_V))
- {
- invalid = true;
- break;
- }
-
- // test dirty
- if ((intention & TRANSLATE_WRITE) && !(pfn & EL_D))
- {
- modify = true;
- break;
- }
-
- // translate the address
- address &= (entry.mask >> 1) | 0xfff;
- address |= ((pfn & EL_PFN) << 6) & ~(entry.mask >> 1);
-
- // promote the entry in the mru index
- if (i > 0)
- std::swap(mru[i - 1], mru[i]);
-
- return ((pfn & EL_C) == C_2) ? UNCACHED : CACHED;
- }
-
- // tlb miss, invalid entry, or a store to a non-dirty entry
- if (!machine().side_effects_disabled() && !(intention & TRANSLATE_DEBUG_MASK))
- {
- if (VERBOSE & LOG_TLB)
- {
- char const mode[] = { 'r', 'w', 'x' };
-
- if (modify)
- LOGMASKED(LOG_TLB, "tlb modify asid %d address 0x%016x (%s)\n",
- m_cp0[CP0_EntryHi] & EH_ASID, address, machine().describe_context());
- else
- LOGMASKED(LOG_TLB, "tlb miss %c asid %d address 0x%016x (%s)\n",
- mode[intention & TRANSLATE_TYPE_MASK], m_cp0[CP0_EntryHi] & EH_ASID, address, machine().describe_context());
- }
-
- // load tlb exception registers
- m_cp0[CP0_BadVAddr] = address;
- m_cp0[CP0_EntryHi] = key;
- m_cp0[CP0_Context] = (m_cp0[CP0_Context] & CONTEXT_PTEBASE) | ((address >> 9) & CONTEXT_BADVPN2);
- m_cp0[CP0_XContext] = (m_cp0[CP0_XContext] & XCONTEXT_PTEBASE) | ((address >> 31) & XCONTEXT_R) | ((address >> 9) & XCONTEXT_BADVPN2);
-
- if (invalid || modify || (SR & SR_EXL))
- cpu_exception(modify ? EXCEPTION_MOD : (intention & TRANSLATE_WRITE) ? EXCEPTION_TLBS : EXCEPTION_TLBL);
- else
- cpu_exception((intention & TRANSLATE_WRITE) ? EXCEPTION_TLBS : EXCEPTION_TLBL, extended ? 0x000 : 0x080);
- }
-
- return MISS;
-}
-
-void r4000_base_device::address_error(int intention, u64 const address)
-{
- if (!machine().side_effects_disabled() && !(intention & TRANSLATE_DEBUG_MASK))
- {
- logerror("address_error 0x%016x (%s)\n", address, machine().describe_context());
-
- // TODO: check this
- if (!(SR & SR_EXL))
- m_cp0[CP0_BadVAddr] = address;
-
- cpu_exception((intention & TRANSLATE_WRITE) ? EXCEPTION_ADES : EXCEPTION_ADEL);
-
- // address errors shouldn't typically occur, so a breakpoint is handy
- machine().debug_break();
- }
-}
-
-template <typename T, typename U> std::enable_if_t<std::is_convertible<U, std::function<void(T)>>::value, bool> r4000_base_device::load(u64 address, U &&apply)
-{
- // alignment error
- if (address & (sizeof(T) - 1))
- {
- address_error(TRANSLATE_READ, address);
- return false;
- }
-
- translate_t const t = translate(TRANSLATE_READ, address);
-
- // address error
- if (t == ERROR)
- {
- address_error(TRANSLATE_READ, address);
-
- return false;
- }
-
- // tlb miss
- if (t == MISS)
- return false;
-
- // watchpoint
- if ((m_cp0[CP0_WatchLo] & WATCHLO_R) && !(SR & SR_EXL))
- {
- u64 const watch_address = ((m_cp0[CP0_WatchHi] & WATCHHI_PADDR1) << 32) | (m_cp0[CP0_WatchLo] & WATCHLO_PADDR0);
-
- if ((address & ~7) == watch_address)
- {
- cpu_exception(EXCEPTION_WATCH);
- return false;
- }
- }
-
- // TODO: cache lookup
-
- switch (sizeof(T))
- {
- case 1: apply(T(space(0).read_byte(address))); break;
- case 2: apply(T(space(0).read_word(address))); break;
- case 4: apply(T(space(0).read_dword(address))); break;
- case 8: apply(T(space(0).read_qword(address))); break;
- }
-
- return true;
-}
-
-template <typename T, typename U> std::enable_if_t<std::is_convertible<U, std::function<void(u64, T)>>::value, bool> r4000_base_device::load_linked(u64 address, U &&apply)
-{
- // alignment error
- if (address & (sizeof(T) - 1))
- {
- address_error(TRANSLATE_READ, address);
- return false;
- }
-
- translate_t const t = translate(TRANSLATE_READ, address);
-
- // address error
- if (t == ERROR)
- {
- address_error(TRANSLATE_READ, address);
- return false;
- }
-
- // tlb miss
- if (t == MISS)
- return false;
-
- // watchpoint
- if ((m_cp0[CP0_WatchLo] & WATCHLO_R) && !(SR & SR_EXL))
- {
- u64 const watch_address = ((m_cp0[CP0_WatchHi] & WATCHHI_PADDR1) << 32) | (m_cp0[CP0_WatchLo] & WATCHLO_PADDR0);
-
- if ((address & ~7) == watch_address)
- {
- cpu_exception(EXCEPTION_WATCH);
- return false;
- }
- }
-
- // TODO: cache lookup
-
- switch (sizeof(T))
- {
- case 4: apply(address, T(space(0).read_dword(address))); break;
- case 8: apply(address, T(space(0).read_qword(address))); break;
- }
-
- return true;
-}
-
-template <typename T, typename U> std::enable_if_t<std::is_convertible<U, T>::value, bool> r4000_base_device::store(u64 address, U data, T mem_mask)
-{
- // alignment error
- if (address & (sizeof(T) - 1))
- {
- address_error(TRANSLATE_READ, address);
- return false;
- }
-
- translate_t const t = translate(TRANSLATE_WRITE, address);
-
- // address error
- if (t == ERROR)
- {
- address_error(TRANSLATE_WRITE, address);
- return false;
- }
-
- // tlb miss
- if (t == MISS)
- return false;
-
- // watchpoint
- if ((m_cp0[CP0_WatchLo] & WATCHLO_W) && !(SR & SR_EXL))
- {
- u64 const watch_address = ((m_cp0[CP0_WatchHi] & WATCHHI_PADDR1) << 32) | (m_cp0[CP0_WatchLo] & WATCHLO_PADDR0);
-
- if ((address & ~7) == watch_address)
- {
- cpu_exception(EXCEPTION_WATCH);
- return false;
- }
- }
-
- // TODO: cache lookup
-
- switch (sizeof(T))
- {
- case 1: space(0).write_byte(address, T(data)); break;
- case 2: space(0).write_word(address, T(data), mem_mask); break;
- case 4: space(0).write_dword(address, T(data), mem_mask); break;
- case 8: space(0).write_qword(address, T(data), mem_mask); break;
- }
-
- return true;
-}
-
-bool r4000_base_device::fetch(u64 address, std::function<void(u32)> &&apply)
-{
- u64 const program_address = address;
-
- // alignment error
- if (address & 3)
- {
- address_error(TRANSLATE_FETCH, address);
-
- return false;
- }
-
- translate_t const t = translate(TRANSLATE_FETCH, address);
-
- // address error
- if (t == ERROR)
- {
- address_error(TRANSLATE_FETCH, address);
-
- return false;
- }
-
- // tlb miss
- if (t == MISS)
- return false;
-
- if (ICACHE)
- {
- if (t == UNCACHED)
- {
- apply(space(0).read_dword(address));
-
- return true;
- }
-
- // look up the tag
- u32 const cache_address = (program_address & m_icache_mask_hi);
- u32 &tag = m_icache_tag[cache_address >> m_icache_shift];
-
- // check for cache miss
- if (!(tag & ICACHE_V) || (tag & ICACHE_PTAG) != (address >> 12))
- {
- // cache miss
- m_icache_misses++;
-
- // reload the cache line
- tag = ICACHE_V | (address >> 12);
- for (unsigned i = 0; i < m_icache_line_size; i += 8)
- {
- u64 const data = space(0).read_qword((address & m_icache_mask_lo) | i);
-
- m_icache_data[(((cache_address & m_icache_mask_lo) | i) >> 2) + 0] = u32(data);
- m_icache_data[(((cache_address & m_icache_mask_lo) | i) >> 2) + 1] = data >> 32;
- }
- }
- else
- m_icache_hits++;
-
- // apply the result
- apply(m_icache_data[cache_address >> 2]);
- }
- else
- apply(space(0).read_dword(address));
-
- return true;
-}
-
-std::string r4000_base_device::debug_string(u64 string_pointer, unsigned limit)
-{
- auto const suppressor(machine().disable_side_effects());
-
- bool done = false;
- bool mapped = false;
- std::string result("");
-
- while (!done)
- {
- done = true;
- load<u8>(string_pointer++, [limit, &done, &mapped, &result](u8 byte)
- {
- mapped = true;
- if (byte != 0)
- {
- result += byte;
-
- done = result.length() == limit;
- }
- });
- }
-
- if (!mapped)
- result.assign("[unmapped]");
-
- return result;
-}
-
-std::string r4000_base_device::debug_string_array(u64 array_pointer)
-{
- auto const suppressor(machine().disable_side_effects());
-
- bool done = false;
- std::string result("");
-
- while (!done)
- {
- done = true;
- load<s32>(array_pointer, [this, &done, &result](u64 string_pointer)
- {
- if (string_pointer != 0)
- {
- if (!result.empty())
- result += ", ";
-
- result += '\"' + debug_string(string_pointer) + '\"';
-
- done = false;
- }
- });
-
- array_pointer += 4;
- }
-
- return result;
-}
-
-std::string r4000_base_device::debug_unicode_string(u64 unicode_string_pointer)
-{
- auto const suppressor(machine().disable_side_effects());
-
- std::wstring result(L"");
-
- if (!load<u16>(unicode_string_pointer,
- [this, unicode_string_pointer, &result](u16 const length)
- {
- if (length)
- if (!load<u32>(unicode_string_pointer + 4,
- [this, length, &result](s32 buffer)
- {
- for (int i = 0; i < length; i += 2)
- load<u16>(buffer + i, [&result](wchar_t const character) { result += character; });
- }))
- result.assign(L"[unmapped]");
- }))
- result.assign(L"[unmapped]");
-
- return utf8_from_wstring(result);
-}
diff --git a/src/devices/cpu/mips/r4000.h b/src/devices/cpu/mips/r4000.h
deleted file mode 100644
index 8c3a1760ba3..00000000000
--- a/src/devices/cpu/mips/r4000.h
+++ /dev/null
@@ -1,463 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Patrick Mackinlay
-
-#ifndef MAME_CPU_MIPS_R4000_H
-#define MAME_CPU_MIPS_R4000_H
-
-#pragma once
-
-DECLARE_DEVICE_TYPE(R4000, r4000_device)
-DECLARE_DEVICE_TYPE(R4400, r4400_device)
-DECLARE_DEVICE_TYPE(R4600, r4600_device)
-
-class r4000_base_device : public cpu_device
-{
-public:
- enum config_mask : u32
- {
- CONFIG_K0 = 0x00000007, // kseg0 cache coherency
- CONFIG_CU = 0x00000080, // store conditional cache coherent
- CONFIG_DB = 0x00000010, // primary d-cache line 32 bytes
- CONFIG_IB = 0x00000020, // primary i-cache line 32 bytes
- CONFIG_DC = 0x000001c0, // primary d-cache size
- CONFIG_IC = 0x00000e00, // primary i-cache size
- CONFIG_EB = 0x00002000, // sub-block ordering
- CONFIG_EM = 0x00004000, // parity mode enable
- CONFIG_BE = 0x00008000, // big endian
- CONFIG_SM = 0x00010000, // dirty shared disable
- CONFIG_SC = 0x00020000, // secondary cache absent
- CONFIG_EW = 0x000c0000, // system port width
- CONFIG_SW = 0x00100000, // secondary cache port width
- CONFIG_SS = 0x00200000, // split secondary cache mode
- CONFIG_SB = 0x00c00000, // secondary cache line size
- CONFIG_EP = 0x0f000000, // transmit data pattern
- CONFIG_EC = 0x70000000, // system clock ratio
- CONFIG_CM = 0x80000000, // master/checker enable
-
- CONFIG_WM = 0x0000003f, // runtime-writable bits
- };
- void set_config(u32 data, u32 mem_mask = ~u32(0))
- {
- if (!configured())
- COMBINE_DATA(&m_cp0[CP0_Config]);
- }
-
-protected:
- enum cache_size_t
- {
- CACHE_4K = 0,
- CACHE_8K = 1,
- CACHE_16K = 2,
- CACHE_32K = 3,
- CACHE_64K = 4,
- CACHE_128K = 5,
- CACHE_256K = 6,
- CACHE_512K = 7,
- };
- r4000_base_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 prid, cache_size_t icache_size, cache_size_t dcache_size);
-
- enum cp0_reg : int
- {
- CP0_Index = 0,
- CP0_Random = 1,
- CP0_EntryLo0 = 2,
- CP0_EntryLo1 = 3,
- CP0_Context = 4,
- CP0_PageMask = 5,
- CP0_Wired = 6,
- CP0_BadVAddr = 8,
- CP0_Count = 9,
- CP0_EntryHi = 10,
- CP0_Compare = 11,
- CP0_Status = 12,
- CP0_Cause = 13,
- CP0_EPC = 14,
- CP0_PRId = 15,
- CP0_Config = 16,
- CP0_LLAddr = 17,
- CP0_WatchLo = 18,
- CP0_WatchHi = 19,
- CP0_XContext = 20,
- CP0_ECC = 26,
- CP0_CacheErr = 27,
- CP0_TagLo = 28,
- CP0_TagHi = 29,
- CP0_ErrorEPC = 30,
- };
-
- enum cp0_sr_mask : u32
- {
- SR_IE = 0x00000001, // interrupt enable
- SR_EXL = 0x00000002, // exception level
- SR_ERL = 0x00000004, // error level
- SR_KSU = 0x00000018, // kernel/supervisor/user mode
- SR_UX = 0x00000020, // 64-bit addressing user mode
- SR_SX = 0x00000040, // 64-bit addressing supervisor mode
- SR_KX = 0x00000080, // 64-bit addressing kernel mode
- SR_IMSW0 = 0x00000100, // software interrupt 0 enable
- SR_IMSW1 = 0x00000200, // software interrupt 1 enable
- SR_IMEX0 = 0x00000400, // external interrupt 0 enable
- SR_IMEX1 = 0x00000800, // external interrupt 1 enable
- SR_IMEX2 = 0x00001000, // external interrupt 2 enable
- SR_IMEX3 = 0x00002000, // external interrupt 3 enable
- SR_IMEX4 = 0x00004000, // external interrupt 4 enable
- SR_IMEX5 = 0x00008000, // external interrupt 5 enable
- SR_DE = 0x00010000, // disable cache parity/ecc exceptions
- SR_CE = 0x00020000, // cache ecc check enable
- SR_CH = 0x00040000, // cache hit
- SR_SR = 0x00100000, // soft reset
- SR_TS = 0x00200000, // tlb shutdown (read only)
- SR_BEV = 0x00400000, // bootstrap exception vectors
- SR_RE = 0x02000000, // reverse endian
- SR_FR = 0x04000000, // enable additional floating-point registers
- SU_RP = 0x08000000, // reduced power
- SR_CU0 = 0x10000000, // coprocessor usable 0
- SR_CU1 = 0x20000000, // coprocessor usable 1
- SR_CU2 = 0x40000000, // coprocessor usable 2
- SR_CU3 = 0x80000000, // coprocessor usable 3
-
- SR_IMSW = 0x00000300,
- SR_IM = 0x0000ff00, // interrupt mask
- SR_DS = 0x01ff0000, // diagnostic status
- };
-
- enum cp0_sr_ksu_mode : u32
- {
- SR_KSU_K = 0x00000000, // kernel mode
- SR_KSU_S = 0x00000008, // supervisor mode
- SR_KSU_U = 0x00000010, // user mode
- };
-
- enum cp0_cause_mask : u32
- {
- CAUSE_EXCCODE = 0x0000007c, // exception code
- CAUSE_IPSW0 = 0x00000100, // software interrupt 0 pending
- CAUSE_IPSW1 = 0x00000200, // software interrupt 1 pending
- CAUSE_IPEX0 = 0x00000400, // external interrupt 0 pending
- CAUSE_IPEX1 = 0x00000800, // external interrupt 1 pending
- CAUSE_IPEX2 = 0x00001000, // external interrupt 2 pending
- CAUSE_IPEX3 = 0x00002000, // external interrupt 3 pending
- CAUSE_IPEX4 = 0x00004000, // external interrupt 4 pending
- CAUSE_IPEX5 = 0x00008000, // external interrupt 5 pending
- CAUSE_CE = 0x30000000, // coprocessor unit
- CAUSE_BD = 0x80000000, // branch delay slot
-
- CAUSE_IPSW = 0x00000300,
- CAUSE_IPHW = 0x0000fc00,
- CAUSE_IP = 0x0000ff00,
- };
-
- enum cp0_watchlo_mask : u32
- {
- WATCHLO_W = 0x00000001, // trap on store
- WATCHLO_R = 0x00000002, // trap on load
- WATCHLO_PADDR0 = 0xfffffff8, // physical address bits 31:3
- };
- enum cp0_watchhi_mask : u32
- {
- WATCHHI_PADDR1 = 0x0000000f, // physical address bits 35:32
- };
-
- enum cp0_tlb_mask : u64
- {
- TLB_MASK = 0x0000'0000'01ff'e000,
- };
- enum cp0_tlb_eh : u64
- {
- EH_ASID = 0x0000'0000'0000'00ff, // address space id
- EH_G = 0x0000'0000'0000'1000, // global (tlb only)
- EH_VPN2_32 = 0x0000'0000'ffff'e000, // virtual page number (32-bit mode)
- EH_VPN2_64 = 0x0000'00ff'ffff'e000, // virtual page number (64-bit mode)
- EH_R = 0xc000'0000'0000'0000, // region (64-bit mode)
- };
- enum cp0_tlb_el : u64
- {
- EL_G = 0x0000'0000'0000'0001, // global (entrylo only)
- EL_V = 0x0000'0000'0000'0002, // valid
- EL_D = 0x0000'0000'0000'0004, // dirty
- EL_C = 0x0000'0000'0000'0038, // coherency
- EL_PFN = 0x0000'0000'3fff'ffc0, // page frame number
- };
- enum cp0_tlb_el_c : u64
- {
- C_0 = 0x00, // reserved
- C_1 = 0x08, // reserved
- C_2 = 0x10, // uncached
- C_3 = 0x18, // cacheable noncoherent (noncoherent)
- C_4 = 0x20, // cacheable coherent exclusive (exclusive)
- C_5 = 0x28, // cacheable coherent exclusive on write (sharable)
- C_6 = 0x30, // cacheable coherent update on write (update)
- C_7 = 0x38, // reserved
- };
-
- enum cp0_context_mask : u64
- {
- CONTEXT_PTEBASE = 0xffff'ffff'ff80'0000,
- CONTEXT_BADVPN2 = 0x0000'0000'007f'fff0,
- };
-
- enum cp0_xcontext_mask : u64
- {
- XCONTEXT_PTEBASE = 0xffff'fffe'0000'0000, // page table entry base
- XCONTEXT_R = 0x0000'0001'8000'0000, // region
- XCONTEXT_BADVPN2 = 0x0000'0000'7fff'fff0, // bad virtual page number / 2
- };
-
- enum cp0_pagemask_mask : u32
- {
- PAGEMASK = 0x01ff'e000,
- };
-
- enum exception_mask : u32
- {
- EXCEPTION_INT = 0x00000000, // interrupt
- EXCEPTION_MOD = 0x00000004, // tlb modification
- EXCEPTION_TLBL = 0x00000008, // tlb load
- EXCEPTION_TLBS = 0x0000000c, // tlb store
- EXCEPTION_ADEL = 0x00000010, // address error load
- EXCEPTION_ADES = 0x00000014, // address error store
- EXCEPTION_IBE = 0x00000018, // bus error (instruction fetch)
- EXCEPTION_DBE = 0x0000001c, // bus error (data reference: load or store)
- EXCEPTION_SYS = 0x00000020, // syscall
- EXCEPTION_BP = 0x00000024, // breakpoint
- EXCEPTION_RI = 0x00000028, // reserved instruction
- EXCEPTION_CPU = 0x0000002c, // coprocessor unusable
- EXCEPTION_OV = 0x00000030, // arithmetic overflow
- EXCEPTION_TR = 0x00000034, // trap
- EXCEPTION_VCEI = 0x00000038, // virtual coherency exception instruction
- EXCEPTION_FPE = 0x0000003c, // floating point
- EXCEPTION_WATCH = 0x0000005c, // reference to watchhi/watchlo address
- EXCEPTION_VCED = 0x0000007c, // virtual coherency exception data
-
- EXCEPTION_CP0 = 0x0000002c, // coprocessor 0 unusable
- EXCEPTION_CP1 = 0x1000002c, // coprocessor 1 unusable
- EXCEPTION_CP2 = 0x2000002c, // coprocessor 2 unusable
- EXCEPTION_CP3 = 0x3000002c, // coprocessor 3 unusable
- };
-
- enum cp1_fcr31_mask : u32
- {
- FCR31_RM = 0x00000003, // rounding mode
-
- FCR31_FI = 0x00000004, // inexact operation flag
- FCR31_FU = 0x00000008, // underflow flag
- FCR31_FO = 0x00000010, // overflow flag
- FCR31_FZ = 0x00000020, // divide by zero flag
- FCR31_FV = 0x00000040, // invalid operation flag
-
- FCR31_EI = 0x00000080, // inexact operation enable
- FCR31_EU = 0x00000100, // underflow enable
- FCR31_EO = 0x00000200, // overflow enable
- FCR31_EZ = 0x00000400, // divide by zero enable
- FCR31_EV = 0x00000800, // invalid operation enable
-
- FCR31_CI = 0x00001000, // inexact operation cause
- FCR31_CU = 0x00002000, // underflow cause
- FCR31_CO = 0x00004000, // overflow cause
- FCR31_CZ = 0x00008000, // divide by zero cause
- FCR31_CV = 0x00010000, // invalid operation cause
- FCR31_CE = 0x00020000, // unimplemented operation cause
-
- FCR31_C = 0x00800000, // condition
- FCR31_FS = 0x01000000, // flush denormalized results
-
- FCR31_FM = 0x0000007c, // flag mask
- FCR31_EM = 0x00000f80, // enable mask
- FCR31_CM = 0x0001f000, // cause mask (except unimplemented)
- };
-
- enum mips3_registers : unsigned
- {
- MIPS3_R0 = 0,
- MIPS3_CP0 = 32,
- MIPS3_F0 = 64,
-
- MIPS3_PC = 96,
- MIPS3_HI,
- MIPS3_LO,
- MIPS3_FCR30,
- MIPS3_FCR31,
- };
-
- enum cp0_taglo_mask : u32
- {
- TAGLO_PTAGLO = 0xffffff00, // physical adddress bits 35:12
- TAGLO_PSTATE = 0x000000c0, // primary cache state
- TAGLO_P = 0x00000001, // primary tag even parity
- };
- enum icache_mask : u32
- {
- ICACHE_PTAG = 0x00ffffff, // physical tag
- ICACHE_V = 0x01000000, // valid
- ICACHE_P = 0x02000000, // even parity
- };
- enum dcache_mask : u32
- {
- DCACHE_PTAG = 0x00ffffff, // physical tag
- DCACHE_CS = 0x01000000, // primary cache state
- DCACHE_P = 0x02000000, // even parity for ptag and cs
- DCACHE_W = 0x02000000, // write-back
- DCACHE_WP = 0x02000000, // even parity for write-back
- };
-
- // device_t overrides
- virtual void device_start() override;
- virtual void device_reset() override;
- virtual void device_stop() override;
-
- // device_memory_interface overrides
- virtual space_config_vector memory_space_config() const override;
- virtual bool memory_translate(int spacenum, int intention, offs_t &address) override;
-
- // device_disasm_interface overrides
- virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
-
- // device_execute_interface overrides
- virtual u32 execute_min_cycles() const override { return 1; }
- virtual u32 execute_max_cycles() const override { return 40; }
- virtual u32 execute_input_lines() const override { return 6; }
- virtual void execute_run() override;
- virtual void execute_set_input(int inputnum, int state) override;
-
- // cpu implementation
- void cpu_execute(u32 const op);
- void cpu_exception(u32 exception, u16 const vector = 0x180);
- void cpu_lwl(u32 const op);
- void cpu_lwr(u32 const op);
- void cpu_ldl(u32 const op);
- void cpu_ldr(u32 const op);
- void cpu_swl(u32 const op);
- void cpu_swr(u32 const op);
- void cpu_sdl(u32 const op);
- void cpu_sdr(u32 const op);
-
- // cp0 implementation
- void cp0_execute(u32 const op);
- u64 cp0_get(unsigned const reg);
- void cp0_set(unsigned const reg, u64 const data);
- void cp0_tlbr();
- void cp0_tlbwi(u8 const index);
- void cp0_tlbwr();
- void cp0_tlbp();
-
- // cp0 helpers
- TIMER_CALLBACK_MEMBER(cp0_timer_callback);
- void cp0_update_timer(bool start = false);
- bool cp0_64() const;
-
- // cp1 implementation
- void cp1_execute(u32 const op);
- void cp1_set(unsigned const reg, u64 const data);
-
- // cp2 implementation
- void cp2_execute(u32 const op);
-
- // address and memory handling
- enum translate_t { ERROR, MISS, UNCACHED, CACHED };
- translate_t translate(int intention, u64 &address);
- void address_error(int intention, u64 const address);
-
- template <typename T, typename U> std::enable_if_t<std::is_convertible<U, std::function<void(T)>>::value, bool> load(u64 program_address, U &&apply);
- template <typename T, typename U> std::enable_if_t<std::is_convertible<U, std::function<void(u64, T)>>::value, bool> load_linked(u64 program_address, U &&apply);
- template <typename T, typename U> std::enable_if_t<std::is_convertible<U, T>::value, bool> store(u64 program_address, U data, T mem_mask = ~T(0));
- bool fetch(u64 address, std::function<void(u32)> &&apply);
-
- // debugging helpers
- std::string debug_string(u64 string_pointer, unsigned limit = 0);
- std::string debug_string_array(u64 array_pointer);
- std::string debug_unicode_string(u64 unicode_string_pointer);
-
- // device configuration state
- address_space_config m_program_config_le;
- address_space_config m_program_config_be;
-
- // runtime state
- int m_icount;
-
- // cpu state
- u64 m_pc;
- u64 m_r[32];
- u64 m_hi;
- u64 m_lo;
- enum branch_state_t : unsigned
- {
- NONE = 0,
- DELAY = 1, // delay slot instruction active
- BRANCH = 2, // branch instruction active
- EXCEPTION = 3, // exception triggered
- NULLIFY = 4, // next instruction nullified
- }
- m_branch_state;
- u64 m_branch_target;
-
- // cp0 state
- u64 m_cp0[32];
- u64 m_cp0_timer_zero;
- emu_timer *m_cp0_timer;
- memory_passthrough_handler *m_ll_watch;
- struct tlb_entry_t
- {
- u64 mask;
- u64 vpn;
- u64 pfn[2];
-
- unsigned low_bit;
- }
- m_tlb[48];
- unsigned m_tlb_mru[3][48];
-
- // cp1 state
- u64 m_f[32]; // floating point registers
- u32 m_fcr0; // implementation and revision register
- u32 m_fcr30; // unknown
- u32 m_fcr31; // control/status register
-
- // experimental icache state
- u32 m_icache_mask_hi;
- u32 m_icache_mask_lo;
- unsigned m_icache_line_size;
- unsigned m_icache_shift;
- std::unique_ptr<u32[]> m_icache_tag;
- std::unique_ptr<u32[]> m_icache_data;
-
- // statistics
- u64 m_tlb_scans;
- u64 m_tlb_loops;
- u64 m_icache_hits;
- u64 m_icache_misses;
-};
-
-class r4000_device : public r4000_base_device
-{
-public:
- // NOTE: R4000 chips prior to 3.0 have an xtlb bug
- r4000_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : r4000_base_device(mconfig, R4000, tag, owner, clock, 0x0430, CACHE_8K, CACHE_8K)
- {
- // no secondary cache
- m_cp0[CP0_Config] |= CONFIG_SC;
- }
-};
-
-class r4400_device : public r4000_base_device
-{
-public:
- r4400_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : r4000_base_device(mconfig, R4400, tag, owner, clock, 0x0440, CACHE_16K, CACHE_16K)
- {
- // no secondary cache
- m_cp0[CP0_Config] |= CONFIG_SC;
- }
-};
-
-class r4600_device : public r4000_base_device
-{
-public:
- r4600_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : r4000_base_device(mconfig, R4600, tag, owner, clock, 0x2000, CACHE_16K, CACHE_16K)
- {
- // no secondary cache
- m_cp0[CP0_Config] |= CONFIG_SC;
- }
-};
-#endif // MAME_CPU_MIPS_R4000_H
diff --git a/src/devices/cpu/nec/v5x.cpp b/src/devices/cpu/nec/v5x.cpp
index bed8b42bc73..533a112a7a4 100644
--- a/src/devices/cpu/nec/v5x.cpp
+++ b/src/devices/cpu/nec/v5x.cpp
@@ -199,8 +199,8 @@ void v53_device::install_peripheral_io()
}
else // uPD71071 mode
space(AS_IO).install_readwrite_handler(base + 0x00, base + 0x0f,
- read8sm_delegate(FUNC(v5x_dmau_device::read), m_dmau.target()),
- write8sm_delegate(FUNC(v5x_dmau_device::write), m_dmau.target()), 0xffff);
+ read8_delegate(FUNC(v5x_dmau_device::read), m_dmau.target()),
+ write8_delegate(FUNC(v5x_dmau_device::write), m_dmau.target()), 0xffff);
}
if (m_OPSEL & OPSEL_IS)
@@ -264,8 +264,8 @@ void v50_device::install_peripheral_io()
u16 const base = ((m_OPHA << 8) | m_DULA) & 0xfffe;
space(AS_IO).install_readwrite_handler(base + 0x00, base + 0x0f,
- read8sm_delegate(FUNC(v5x_dmau_device::read), m_dmau.target()),
- write8sm_delegate(FUNC(v5x_dmau_device::write), m_dmau.target()), 0xffff);
+ read8_delegate(FUNC(v5x_dmau_device::read), m_dmau.target()),
+ write8_delegate(FUNC(v5x_dmau_device::write), m_dmau.target()), 0xffff);
}
if (m_OPSEL & OPSEL_IS)
diff --git a/src/devices/cpu/ns32000/ns32000.cpp b/src/devices/cpu/ns32000/ns32000.cpp
deleted file mode 100644
index 6bf23e28289..00000000000
--- a/src/devices/cpu/ns32000/ns32000.cpp
+++ /dev/null
@@ -1,160 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nigel Barnes
-/*****************************************************************************
-*
-* ns32000.cpp
-*
-* NS32000 CPU family
-*
-*****************************************************************************/
-
-#include "emu.h"
-#include "ns32000.h"
-#include "ns32000dasm.h"
-#include "debugger.h"
-
-//**************************************************************************
-// DEVICE INTERFACE
-//**************************************************************************
-
-DEFINE_DEVICE_TYPE(NS32008, ns32008_cpu_device, "ns32008", "National Semiconductor NS32008")
-DEFINE_DEVICE_TYPE(NS32016, ns32016_cpu_device, "ns32016", "National Semiconductor NS32016")
-DEFINE_DEVICE_TYPE(NS32032, ns32032_cpu_device, "ns32032", "National Semiconductor NS32032")
-
-
-//-------------------------------------------------
-// ns32000_cpu_device - constructor
-//-------------------------------------------------
-
-ns32000_cpu_device::ns32000_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int databits, int addrbits)
- : cpu_device(mconfig, type, tag, owner, clock)
- , m_program_config("program", ENDIANNESS_LITTLE, databits, addrbits, 0)
- , m_icount(0)
-{
-}
-
-ns32008_cpu_device::ns32008_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : ns32000_cpu_device(mconfig, NS32008, tag, owner, clock, 8, 24)
-{
-}
-
-ns32016_cpu_device::ns32016_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : ns32000_cpu_device(mconfig, NS32016, tag, owner, clock, 16, 24)
-{
-}
-
-ns32032_cpu_device::ns32032_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
- : ns32000_cpu_device(mconfig, NS32032, tag, owner, clock, 32, 24)
-{
-}
-
-//-------------------------------------------------
-// device_start - device-specific startup
-//-------------------------------------------------
-
-void ns32000_cpu_device::device_start()
-{
- set_icountptr(m_icount);
-
- save_item(NAME(m_pc));
- save_item(NAME(m_r));
- save_item(NAME(m_f));
-
- state_add(STATE_GENPC, "GENPC", m_pc).noshow();
- state_add(STATE_GENPCBASE, "CURPC", m_pc).noshow();
-
- // dedicated registers
- state_add(NS32000_PC, "PC", m_pc);
- state_add(NS32000_SB, "SB", m_sb);
- state_add(NS32000_FP, "FP", m_fp);
- state_add(NS32000_SP1, "SP1", m_sp1);
- state_add(NS32000_SP0, "SP0", m_sp0);
- state_add(NS32000_INTBASE, "INTBASE", m_intbase);
- state_add(NS32000_PSR, "PSR", m_psr);
- state_add(NS32000_MOD, "MOD", m_mod);
-
- // general registers
- for (unsigned i = 0; i < 8; i++)
- state_add(NS32000_R0 + i, util::string_format("R%d", i).c_str(), m_r[i]);
-
- // floating point registers
- //for (unsigned i = 0; i < 8; i++)
- // state_add(NS32000_R7 + i, util::string_format("F%d", i).c_str(), m_f[i]);
-
- // set our instruction counter
- //set_icountptr(m_icount);
-}
-
-//-------------------------------------------------
-// device_reset - device-specific reset
-//-------------------------------------------------
-
-void ns32000_cpu_device::device_reset()
-{
- m_nmi_line = false;
- m_irq_line = false;
-
- m_pc = 0;
-}
-
-//-------------------------------------------------
-// execute_run - execute a timeslice's worth of
-// opcodes
-//-------------------------------------------------
-
-void ns32000_cpu_device::execute_run()
-{
- while (m_icount > 0)
- {
- debugger_instruction_hook(m_pc);
-
- m_icount--;
- }
-}
-
-//-------------------------------------------------
-// execute_set_input - act on a changed input/
-// interrupt line
-//-------------------------------------------------
-
-void ns32000_cpu_device::execute_set_input(int inputnum, int state)
-{
- switch (inputnum)
- {
- case INPUT_LINE_NMI:
- // NMI is edge triggered
- m_nmi_line = m_nmi_line || (state == ASSERT_LINE);
- break;
-
- case INPUT_LINE_IRQ0:
- // IRQ is line triggered
- m_irq_line = state == ASSERT_LINE;
- break;
- }
-}
-
-//-------------------------------------------------
-// memory_space_config - return the configuration
-// of the specified address space, or nullptr if
-// the space doesn't exist
-//-------------------------------------------------
-
-device_memory_interface::space_config_vector ns32000_cpu_device::memory_space_config() const
-{
- return space_config_vector{ std::make_pair(AS_PROGRAM, &m_program_config) };
-}
-
-bool ns32000_cpu_device::memory_translate(int spacenum, int intention, offs_t &address)
-{
- return true;
-}
-
-//-------------------------------------------------
-// disassemble - call the disassembly
-// helper function
-//-------------------------------------------------
-
-std::unique_ptr<util::disasm_interface> ns32000_cpu_device::create_disassembler()
-{
- return std::make_unique<ns32000_disassembler>();
-}
diff --git a/src/devices/cpu/ns32000/ns32000.h b/src/devices/cpu/ns32000/ns32000.h
deleted file mode 100644
index 7b17cafba99..00000000000
--- a/src/devices/cpu/ns32000/ns32000.h
+++ /dev/null
@@ -1,149 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nigel Barnes
-/*****************************************************************************
-*
-* ns32000.h
-*
-* NS32000 CPU family
-*
-*****************************************************************************/
-
-#ifndef MAME_CPU_NS32016_NS32016_H
-#define MAME_CPU_NS32016_NS32016_H
-
-#pragma once
-
-
-/***********************************************************************
- CONSTANTS
-***********************************************************************/
-
-
-
-/***********************************************************************
- TYPE DEFINITIONS
-***********************************************************************/
-
-class ns32000_cpu_device : public cpu_device
-{
-public:
- // construction/destruction
- ns32000_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock);
-
-protected:
- ns32000_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, int databits, int addrbits);
-
- // device-level overrides
- virtual void device_start() override;
- virtual void device_reset() override;
-
- // device_execute_interface overrides
- virtual u32 execute_min_cycles() const override { return 1; }
- virtual u32 execute_max_cycles() const override { return 6; }
- virtual u32 execute_input_lines() const override { return 2; }
- virtual void execute_run() override;
- virtual void execute_set_input(int inputnum, int state) override;
- virtual bool execute_input_edge_triggered(int inputnum) const override { return inputnum == INPUT_LINE_NMI; }
-
-
- // device_memory_interface overrides
- virtual space_config_vector memory_space_config() const override;
- virtual bool memory_translate(int spacenum, int intention, offs_t &address) override;
-
- // device_disasm_interface overrides
- virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
-
- // addressing modes
- enum
- {
- ADDRESSING_MODE_REGISTER_0 = 0,
- ADDRESSING_MODE_REGISTER_1,
- ADDRESSING_MODE_REGISTER_2,
- ADDRESSING_MODE_REGISTER_3,
- ADDRESSING_MODE_REGISTER_4,
- ADDRESSING_MODE_REGISTER_5,
- ADDRESSING_MODE_REGISTER_6,
- ADDRESSING_MODE_REGISTER_7,
- ADDRESSING_MODE_REGISTER_0_RELATIVE,
- ADDRESSING_MODE_REGISTER_1_RELATIVE,
- ADDRESSING_MODE_REGISTER_2_RELATIVE,
- ADDRESSING_MODE_REGISTER_3_RELATIVE,
- ADDRESSING_MODE_REGISTER_4_RELATIVE,
- ADDRESSING_MODE_REGISTER_5_RELATIVE,
- ADDRESSING_MODE_REGISTER_6_RELATIVE,
- ADDRESSING_MODE_REGISTER_7_RELATIVE,
- ADDRESSING_MODE_FRAME_MEMORY_RELATIVE,
- ADDRESSING_MODE_STACK_MEMORY_RELATIVE,
- ADDRESSING_MODE_STATIC_MEMORY_RELATIVE,
- ADDRESSING_MODE_RESERVED,
- ADDRESSING_MODE_IMMEDIATE,
- ADDRESSING_MODE_ABSOLUTE,
- ADDRESSING_MODE_EXTERNAL,
- ADDRESSING_MODE_TOP_OF_STACK,
- ADDRESSING_MODE_FRAME_MEMORY,
- ADDRESSING_MODE_STACK_MEMORY,
- ADDRESSING_MODE_STATIC_MEMORY,
- ADDRESSING_MODE_PROGRAM_MEMORY,
- ADDRESSING_MODE_INDEX_BYTES,
- ADDRESSING_MODE_INDEX_WORDS,
- ADDRESSING_MODE_INDEX_DOUBLE_WORDS,
- ADDRESSING_MODE_INDEX_QUAD_WORDS,
- };
-
- // registers
- enum
- {
- NS32000_PC = 1,
- NS32000_SB, NS32000_FP, NS32000_SP1, NS32000_SP0, NS32000_INTBASE, NS32000_PSR, NS32000_MOD,
- NS32000_R0, NS32000_R1, NS32000_R2, NS32000_R3, NS32000_R4, NS32000_R5, NS32000_R6, NS32000_R7,
- };
-
-private:
- // configuration
- address_space_config m_program_config;
-
- // emulation state
- int m_icount;
-
- u32 m_pc;
- u32 m_sb;
- u32 m_fp;
- u32 m_sp1;
- u32 m_sp0;
- u32 m_intbase;
- u32 m_psr;
- u32 m_mod;
- u32 m_r[8];
- u32 m_f[8];
-
- u8 m_irq_line;
- u8 m_nmi_line;
-};
-
-class ns32008_cpu_device : public ns32000_cpu_device
-{
-public:
- ns32008_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-};
-
-class ns32016_cpu_device : public ns32000_cpu_device
-{
-public:
- ns32016_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-};
-
-class ns32032_cpu_device : public ns32000_cpu_device
-{
-public:
- ns32032_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
-};
-
-/***********************************************************************
- DEVICE TYPE DECLARATIONS
-***********************************************************************/
-
-DECLARE_DEVICE_TYPE(NS32008, ns32008_cpu_device)
-DECLARE_DEVICE_TYPE(NS32016, ns32016_cpu_device)
-DECLARE_DEVICE_TYPE(NS32032, ns32032_cpu_device)
-
-#endif // MAME_CPU_NS32016_NS32016_H
diff --git a/src/devices/cpu/ns32000/ns32000dasm.cpp b/src/devices/cpu/ns32000/ns32000dasm.cpp
deleted file mode 100644
index 8bc25f48c60..00000000000
--- a/src/devices/cpu/ns32000/ns32000dasm.cpp
+++ /dev/null
@@ -1,835 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nigel Barnes
-/*****************************************************************************
-*
-* ns32000dasm.cpp
-*
-* NS32000 CPU Disassembly
-*
-*****************************************************************************/
-
-#include "emu.h"
-#include "ns32000dasm.h"
-
-// instruction field extraction
-#define Format0cond(x) ((x >> 4) & 0x0f)
-
-#define Format1op(x) ((x >> 4) & 0x0f)
-
-#define Format2i(x) ((x >> 0) & 0x03)
-#define Format2op(x) ((x >> 4) & 0x07)
-#define Format2short(x) ((x >> 7) & 0x0f)
-#define Format2gen(x) ((x >> 11) & 0x1f)
-
-#define Format3i(x) ((x >> 0) & 0x03)
-#define Format3op(x) ((x >> 7) & 0x0f)
-#define Format3gen(x) ((x >> 11) & 0x1f)
-
-#define Format4i(x) ((x >> 0) & 0x03)
-#define Format4op(x) ((x >> 2) & 0x0f)
-#define Format4gen2(x) ((x >> 6) & 0x1f)
-#define Format4gen1(x) ((x >> 11) & 0x1f)
-
-#define Format5i(x) ((x >> 8) & 0x03)
-#define Format5op(x) ((x >> 10) & 0x07)
-#define Format5short(x) ((x >> 15) & 0x0f)
-
-#define Format6i(x) ((x >> 8) & 0x03)
-#define Format6op(x) ((x >> 10) & 0x0f)
-#define Format6gen2(x) ((x >> 14) & 0x1f)
-#define Format6gen1(x) ((x >> 19) & 0x1f)
-
-#define Format7i(x) ((x >> 8) & 0x03)
-#define Format7op(x) ((x >> 10) & 0x0f)
-#define Format7gen2(x) ((x >> 14) & 0x1f)
-#define Format7gen1(x) ((x >> 19) & 0x1f)
-
-#define Format8i(x) ((x >> 8) & 0x03)
-#define Format8op(x) (((x >> 8) & 0x04) | ((x >> 6) & 0x03))
-#define Format8reg(x) ((x >> 11) & 0x07)
-#define Format8gen2(x) ((x >> 14) & 0x1f)
-#define Format8gen1(x) ((x >> 19) & 0x1f)
-
-#define Format9i(x) ((x >> 8) & 0x03)
-#define Format9f(x) ((x >> 10) & 0x01)
-#define Format9op(x) ((x >> 11) & 0x07)
-#define Format9gen2(x) ((x >> 14) & 0x1f)
-#define Format9gen1(x) ((x >> 19) & 0x1f)
-
-#define Format11f(x) ((x >> 8) & 0x01)
-#define Format11op(x) ((x >> 10) & 0x0f)
-#define Format11gen2(x) ((x >> 14) & 0x1f)
-#define Format11gen1(x) ((x >> 19) & 0x1f)
-
-#define Format14i(x) ((x >> 8) & 0x01)
-#define Format14op(x) ((x >> 10) & 0x0f)
-#define Format14short(x) ((x >> 15) & 0x1f)
-#define Format14gen1(x) ((x >> 19) & 0x1f)
-
-// instructions
-const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format0_op[1] =
-{
- { "Bcond", DISP, 0, 0, 0, 0 }
-};
-const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format1_op[16] =
-{
- { "BSR", DISP, 0, 0, 0, STEP_OVER },
- { "RET", DISP, 0, 0, 0, STEP_OUT },
- { "CXP", DISP, 0, 0, 0, STEP_OVER },
- { "RXP", DISP, 0, 0, 0, STEP_OUT },
- { "RETT", 0, 0, 0, 0, STEP_OUT },
- { "RETI", DISP, 0, 0, 0, STEP_OUT },
- { "SAVE", IMM, 0, 0, 0, 0 },
- { "RESTORE", IMM, 0, 0, 0, 0 },
- { "ENTER", IMM, DISP, 0, 0, 0 },
- { "EXIT", IMM, 0, 0, 0, 0 },
- { "NOP", 0, 0, 0, 0, 0 },
- { "WAIT", 0, 0, 0, 0, 0 },
- { "DIA", 0, 0, 0, 0, 0 },
- { "FLAG", 0, 0, 0, 0, 0 },
- { "SVC", 0, 0, 0, 0, 0 },
- { "BPT", 0, 0, 0, 0, 0 },
-};
-const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format2_op[8] =
-{
- { "ADDQi", QUICK, GEN | RMW | I, 0, 0, 0 },
- { "CMPQi", QUICK, GEN | READ | I, 0, 0, 0 },
- { "SPRi", SHORT, GEN | WRITE | I, 0, 0, 0 },
- { "Scondi", GEN | WRITE | I, 0, 0, 0, 0 },
- { "ACBi", QUICK, GEN | RMW | I, DISP, 0, 0 },
- { "MOVQi", QUICK, GEN | WRITE | I, 0, 0, 0 },
- { "LPRi", SHORT, GEN | READ | I, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
-};
-const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format3_op[16] =
-{
- { "CXPD", GEN | ADDR, 0, 0, 0, STEP_OVER },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "BICPSRi", GEN | READ | I, 0, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "JUMP", GEN | ADDR, 0, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "BISPSRB", GEN | READ | B, 0, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "ADJSPi", GEN | READ | I, 0, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "JSR", GEN | ADDR, 0, 0, 0, STEP_OVER },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "CASEi", GEN | READ | I, 0, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
-};
-const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format4_op[16] =
-{
- { "ADDi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 },
- { "CMPi", GEN | READ | I, GEN | READ | I, 0, 0, 0 },
- { "BICi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "ADDCi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 },
- { "MOVi", GEN | READ | I, GEN | WRITE | I, 0, 0, 0 },
- { "ORi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "SUBi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 },
- { "ADDR", GEN | ADDR, GEN | WRITE | D, 0, 0, 0 },
- { "ANDi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "SUBCi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 },
- { "TBITi", GEN | READ | I, GEN | REGADDR, 0, 0, 0 },
- { "XORi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
-};
-const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format5_op[16] =
-{
- { "MOVSi", OPTIONS, 0, 0, 0, 0 },
- { "CMPSi", OPTIONS, 0, 0, 0, 0 },
- { "SETCFG", SHORT, 0, 0, 0, 0 },
- { "SKPSi", OPTIONS, 0, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
-};
-const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format6_op[16] =
-{
- { "ROTi", GEN | READ | B, GEN | RMW | I, 0, 0, 0 },
- { "ASHi", GEN | READ | B, GEN | RMW | I, 0, 0, 0 },
- { "CBITi", GEN | READ | I, GEN | REGADDR, 0, 0, 0 },
- { "CBITIi", GEN | READ | I, GEN | REGADDR, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "LSHi", GEN | READ | B, GEN | RMW | I, 0, 0, 0 },
- { "SBITi", GEN | READ | I, GEN | REGADDR, 0, 0, 0 },
- { "SBITIi", GEN | READ | I, GEN | REGADDR, 0, 0, 0 },
- { "NEGi", GEN | READ | I, GEN | WRITE | I, 0, 0, 0 },
- { "NOTi", GEN | READ | I, GEN | WRITE | I, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "SUBPi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 },
- { "ABSi", GEN | READ | I, GEN | READ | I, 0, 0, 0 },
- { "COM", GEN | READ | I, GEN | WRITE | I, 0, 0, 0 },
- { "IBITi", GEN | READ | I, GEN | REGADDR, 0, 0, 0 },
- { "ADDPi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 },
-};
-const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format7_op[16] =
-{
- { "MOVMi", GEN | ADDR, GEN | ADDR, DISP, 0, 0 },
- { "CMPMi", GEN | ADDR, GEN | ADDR, DISP, 0, 0 },
- { "INSSi", GEN | READ | I, GEN | REGADDR, IMM, 0, 0 },
- { "EXTSi", GEN | REGADDR, GEN | WRITE | I, IMM, 0, 0 },
- { "MOVXBW", GEN | READ | B, GEN | WRITE | W, 0, 0, 0 },
- { "MOVZBW", GEN | READ | B, GEN | WRITE | W, 0, 0, 0 },
- { "MOVZiD", GEN | READ | I, GEN | WRITE | D, 0, 0, 0 },
- { "MOVXiD", GEN | READ | I, GEN | WRITE | D, 0, 0, 0 },
- { "MULi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 },
- { "MEIi", GEN | READ | I, GEN | RMW | I2, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "DEIi", GEN | READ | I, GEN | RMW | I2, 0, 0, 0 },
- { "QUOi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 },
- { "REMi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 },
- { "MODi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 },
- { "DIVi", GEN | READ | I, GEN | RMW | I, 0, 0, 0 },
-};
-const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format8_op[] =
-{
- { "EXTi", REG, GEN | REGADDR, GEN | WRITE | I, DISP, 0 },
- { "CVTP", REG, GEN | ADDR, GEN | WRITE | D, 0, 0 },
- { "INSi", REG, GEN | READ | I, GEN | REGADDR, DISP, 0 },
- { "CHECKi", REG, GEN | ADDR, GEN | READ | I, 0, 0 },
- { "INDEXi", REG, GEN | READ | I, GEN | READ | I, 0, 0 },
- { "FFSi", GEN | READ | I, GEN | RMW | B, 0, 0, 0 },
- { "MOVSUi", GEN | ADDR, GEN | ADDR, 0, 0, 0 },
- { "MOVUSi", GEN | ADDR, GEN | ADDR, 0, 0, 0 }
-};
-const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format9_op[] =
-{
- { "MOVif", GEN | READ | I, GEN | WRITE | F, 0, 0, 0 },
- { "LFSR", GEN | READ | D, 0, 0, 0, 0 },
- { "MOVLF", GEN | READ | L, GEN | WRITE | F, 0, 0, 0 },
- { "MOVFL", GEN | READ | F, GEN | WRITE | L, 0, 0, 0 },
- { "ROUNDfi", GEN | READ | F, GEN | WRITE | I, 0, 0, 0 },
- { "TRUNCfi", GEN | READ | F, GEN | WRITE | I, 0, 0, 0 },
- { "SFSR", GEN | WRITE | D, 0, 0, 0, 0 },
- { "FLOORfi", GEN | READ | F, GEN | WRITE | I, 0, 0, 0 },
-};
-const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format11_op[] =
-{
- { "ADDf", GEN | READ | F, GEN | RMW | F, 0, 0, 0 },
- { "MOVf", GEN | READ | F, GEN | WRITE | F, 0, 0, 0 },
- { "CMPf", GEN | READ | F, GEN | READ | F, 0, 0, 0 }, // POLYf
- { "Trap (SLAVE)", 0, 0, 0, 0, 0 }, // DOTf
- { "SUBf", GEN | READ | F, GEN | RMW | F, 0, 0, 0 }, // SCALBf
- { "NEGf", GEN | READ | F, GEN | WRITE | F, 0, 0, 0 }, // LOGBf
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "DIVf", GEN | READ | F, GEN | RMW | F, 0, 0, 0 },
- { "Trap (SLAVE)", 0, 0, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "MULf", GEN | READ | F, GEN | RMW | F, 0, 0, 0 },
- { "ABSf", GEN | READ | F, GEN | READ | F, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
-};
-const ns32000_disassembler::NS32000_OPCODE ns32000_disassembler::format14_op[] =
-{
- { "RDVAL", GEN | ADDR, 0, 0, 0, 0 },
- { "WRVAL", GEN | ADDR, 0, 0, 0, 0 },
- { "LMR", SHORT, GEN | READ | D, 0, 0, 0 },
- { "SMR", SHORT, GEN | WRITE | D, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 }, // CINV
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
- { "Trap (UND)", 0, 0, 0, 0, 0 },
-};
-
-
-const char *const ns32000_disassembler::Format0[] =
-{
- "Bcond"
-};
-const char *const ns32000_disassembler::Format1[] =
-{
- "BSR", "RET", "CXP", "RXP", "RETT", "RETI", "SAVE", "RESTORE", "ENTER", "EXIT", "NOP", "WAIT", "DIA", "FLAG", "SVC", "BPT"
-};
-const char *const ns32000_disassembler::Format2[] =
-{
- "ADDQi", "CMPQi", "SPRi", "Scondi", "ACBi", "MOVQi", "LPRi"
-};
-const char *const ns32000_disassembler::Format3[] =
-{
- "CXPD", "Trap (UND)", "BICPSR", "Trap (UND)", "JUMP", "Trap (UND)", "BISPSR", "Trap (UND)", "Trap (UND)", "Trap (UND)", "ADJSPi", "Trap (UND)", "JSR", "Trap (UND)", "CASEi", "Trap (UND)"
-};
-const char *const ns32000_disassembler::Format4[] =
-{
- "ADDi", "CMPi", "BICi", "Trap (UND)", "ADDCi", "MOVi", "ORi", "Trap (UND)", "SUBi", "ADDR", "ANDi", "Trap (UND)", "SUBCi", "TBITi", "XORi", "Trap (UND)"
-};
-const char *const ns32000_disassembler::Format5[] =
-{
- "MOVSi", "CMPSi", "SETCFG", "SKPSi", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)"
-};
-const char *const ns32000_disassembler::Format6[] =
-{
- "ROTi", "ASHi", "CBITi", "CBITIi", "Trap (UND)", "LSHi", "SBITi", "SBITIi", "NEGi", "NOTi", "Trap (UND)", "SUBPi", "ABSi", "COM", "IBITi", "ADDPi"
-};
-const char *const ns32000_disassembler::Format7[] =
-{
- "MOVMi", "CMPMi", "INSSi", "EXTSi", "MOVXBW", "MOVZBW", "MOVZiD", "MOVXiD", "MULi", "MEIi", "Trap (UND)", "DEIi", "QUOi", "REMi", "MODi", "DIVi"
-};
-const char *const ns32000_disassembler::Format8[] =
-{
- "EXTi", "CVTP", "INSi", "CHECKi", "INDEXi", "FFSi", "MOVSUi", "MOVUSi"
-};
-const char *const ns32000_disassembler::Format9[] =
-{
- "MOVif", "LFSR", "MOVLF", "MOVFL", "ROUNDfi", "TRUNCfi", "SFSR", "FLOORfi"
-};
-const char *const ns32000_disassembler::Format11[] =
-{
- "ADDf", "MOVf", "CMPf", "Trap (SLAVE)", "SUBf", "NEGf", "Trap (UND)", "Trap (UND)", "DIVf", "Trap (SLAVE)", "Trap (UND)", "Trap (UND)", "MULf", "ABSf", "Trap (UND)", "Trap (UND)"
-};
-const char *const ns32000_disassembler::Format14[] =
-{
- "RDVAL", "WRVAL", "LMR", "SMR", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)", "Trap (UND)"
-};
-
-// types
-const char *const ns32000_disassembler::iType[] =
-{
- "B", "W", " ", "D"
-};
-const char *const ns32000_disassembler::fType[] =
-{
- "L", "F"
-};
-const char *const ns32000_disassembler::cType[] =
-{
- "Q", "D"
-};
-
-// index byte sizes
-const char *const ns32000_disassembler::indexSize[] =
-{
- "B", "W", "D", "Q"
-};
-
-// short codes
-const char *const ns32000_disassembler::cond[] =
-{
- "EQ", "NE", "CS", "CC", "HI", "LS", "GT", "LE", "FS", "FC", "LO", "HS", "LT", "GE", "R", "N"
-};
-const char *const ns32000_disassembler::areg[] =
-{
- "US", "(reserved)", "(reserved)", "(reserved)", "(reserved)", "(reserved)", "(reserved)", "(reserved)", "FP", "SP", "SB", "(reserved)", "(reserved)", "PSR", "INTBASE", "MOD"
-};
-const char *const ns32000_disassembler::mreg[] =
-{
- "BPR0", "BPR1", "(reserved)", "(reserved)", "(reserved)", "(reserved)", "(reserved)", "(reserved)", "(reserved)", "(reserved)", "MSR", "BCNT", "PTB0", "PTB1", "(reserved)", "EIA"
-};
-
-// register names
-const char *const ns32000_disassembler::R[] =
-{
- "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7"
-};
-const char *const ns32000_disassembler::M[] =
-{
- "FP", "SP", "SB"
-};
-const char *const ns32000_disassembler::PR[] =
-{
- "UPSR", "DCR", "BPC", "DSR", "CAR", "", "", "", "FP", "SP", "SB", "USP", "CFG", "PSR", "INTBASE", "MOD"
-};
-
-int8_t ns32000_disassembler::short2int(uint8_t val)
-{
- return (val & 0x08) ? val | 0xf0 : val;
-}
-
-std::string ns32000_disassembler::mnemonic_index(std::string form, std::string itype, std::string ftype)
-{
- if (itype.size() && form.find('i') != std::string::npos)
- form.replace(form.find('i'), 1, itype);
- if (ftype.size() && form.find('f') != std::string::npos)
- form.replace(form.find('f'), 1, ftype);
- return form;
-}
-
-uint8_t ns32000_disassembler::opcode_format(uint8_t byte)
-{
- switch (byte & 0x0f)
- {
- case 0x0a: return 0;
- case 0x02: return 1;
- case 0x0c:
- case 0x0d:
- case 0x0f:
- if ((byte & 0x70) != 0x70)
- return 2;
- else
- return 3;
- }
-
- if ((byte & 0x03) != 0x02) return 4;
-
- switch (byte)
- {
- case 0x0e: return 5;
- case 0x4e: return 6;
- case 0xce: return 7;
- case 0x2e:
- case 0x6e:
- case 0xae:
- case 0xee: return 8;
- case 0x3e: return 9;
- case 0x7e: return 10;
- case 0xbe: return 11;
- case 0xfe: return 12;
- case 0x9e: return 13;
- case 0x1e: return 14;
- }
-
- return 99; /* unknown format */
-}
-
-inline std::string ns32000_disassembler::get_option_list(uint8_t cfg)
-{
- std::string option_list;
-
- option_list.append("[");
- if (BIT(cfg, 0)) option_list.append("I,");
- if (BIT(cfg, 1)) option_list.append("F,");
- if (BIT(cfg, 2)) option_list.append("M,");
- if (BIT(cfg, 3)) option_list.append("C,");
- if (option_list.back() == ',') option_list.pop_back();
- option_list.append("]");
-
- return option_list;
-}
-
-inline std::string ns32000_disassembler::get_options(uint8_t opts)
-{
- std::string options;
-
- options.append(" ");
- if ((opts & 0x02) == 0x02) options.append("B,");
- if ((opts & 0x04) == 0x04) options.append("W,");
- if ((opts & 0x0c) == 0x0c) options.append("U,");
- if (options.back() == ',') options.pop_back();
-
- return options;
-}
-
-inline int32_t ns32000_disassembler::get_disp(offs_t &pc, const data_buffer &opcodes)
-{
- /* displacement can be upto 3 bytes */
- uint32_t disp = bitswap<32>(opcodes.r32(pc), 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24);
-
- switch ((disp >> 29) & 0x07)
- {
- case 0: case 1: /* 7 bit positive */
- disp = (disp >> 24);
- pc += 1;
- break;
-
- case 2: case 3: /* 7 bit negative */
- disp = (disp >> 24) | 0xffffff80;
- pc += 1;
- break;
-
- case 4: /* 14 bit positive */
- disp = (disp >> 16) & 0x3fff;
- pc += 2;
- break;
-
- case 5: /* 14 bit negative */
- disp = (disp >> 16) | 0xffffc000;
- pc += 2;
- break;
-
- case 6: /* 30 bit positive */
- disp = disp & 0x3fffffff;
- pc += 4;
- break;
-
- case 7: /* 30 bit negative */
- pc += 4;
- break;
- }
-
- return disp;
-}
-
-inline std::string ns32000_disassembler::get_reg_list(offs_t &pc, const data_buffer &opcodes, bool reverse)
-{
- std::string reg_list;
-
- uint8_t byte = opcodes.r8(pc++);
-
- reg_list.append("[");
- for (int i = 0; i < 8; i++)
- {
- if (BIT(byte, i)) reg_list.append(R[reverse ? (~i & 7) : (i & 7)]).append(",");
- }
- if (reg_list.back() == ',') reg_list.pop_back();
- reg_list.append("]");
-
- return reg_list;
-}
-
-void ns32000_disassembler::stream_gen(std::ostream &stream, u8 gen_addr, u8 op_len, offs_t &pc, const data_buffer &opcodes)
-{
- uint8_t index_byte;
- int32_t disp1, disp2;
-
- switch (gen_addr)
- {
- case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
- /* Register */
- util::stream_format(stream, "%s", R[gen_addr & 0x07]);
- break;
- case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
- /* Register Relative */
- disp1 = get_disp(pc, opcodes);
- util::stream_format(stream, "%+d(%s)", disp1, R[gen_addr & 0x07]);
- break;
- case 0x10: case 0x11: case 0x12:
- /* Memory Relative */
- disp1 = get_disp(pc, opcodes);
- disp2 = get_disp(pc, opcodes);
- util::stream_format(stream, "#X%02X(#X%02X(%s))", disp2, disp1, M[gen_addr & 0x03]);
- break;
- case 0x13:
- /* Reserved */
- util::stream_format(stream, "(reserved)");
- break;
- case 0x14:
- /* Immediate */
- disp1 = bitswap<32>(opcodes.r32(pc), 7, 6, 5, 4, 3, 2, 1, 0, 15, 14, 13, 12, 11, 10, 9, 8, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26, 25, 24);
- util::stream_format(stream, "#X%02X", (op_len == 0 ? (disp1 >> 24) : (op_len == 1 ? (disp1 >> 16) : disp1)));
- pc += op_len + 1;
- break;
- case 0x15:
- /* Absolute */
- disp1 = get_disp(pc, opcodes);
- util::stream_format(stream, "@#X%02X", disp1);
- break;
- case 0x16:
- /* External */
- disp1 = get_disp(pc, opcodes);
- disp2 = get_disp(pc, opcodes);
- util::stream_format(stream, "EXT(%d)+%d", disp1, disp2);
- break;
- case 0x17:
- /* Top Of Stack */
- util::stream_format(stream, "TOS");
- break;
- case 0x18: case 0x19: case 0x1a:
- /* Memory Space */
- disp1 = get_disp(pc, opcodes);
- util::stream_format(stream, "#X%02X(%s)", disp1, M[gen_addr & 0x03]);
- break;
- case 0x1b:
- /* Memory Space */
- disp1 = get_disp(pc, opcodes);
- util::stream_format(stream, "#X%06X", m_base_pc + disp1);
- break;
- case 0x1c:
- /* Scaled Index */
- index_byte = opcodes.r8(pc++);
- stream_gen(stream, index_byte >> 3, op_len, pc, opcodes);
- util::stream_format(stream, "[%s:%c]", R[index_byte & 0x07], indexSize[gen_addr & 0x03]);
- break;
- }
-}
-
-offs_t ns32000_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params)
-{
- uint32_t flags = SUPPORTED;
-
- uint32_t opcode;
- std::string mnemonic;
- uint8_t temp8;
-
- /* opcode can be upto 3 bytes */
- opcode = opcodes.r32(pc);
- m_base_pc = pc;
-
- switch (opcode_format(opcode))
- {
- case 0: /* Format 0 */
- pc += 1;
- util::stream_format(stream, "%-8s #X%06X", std::string("B").append(cond[Format0cond(opcode)]), m_base_pc + get_disp(pc, opcodes));
- break;
-
- case 0x01: /* Format 1 */
- pc += 1;
- switch (Format1op(opcode))
- {
- case 0x00:
- util::stream_format(stream, "%-8s #X%06X", Format1[Format1op(opcode)], m_base_pc + get_disp(pc, opcodes));
- break;
- case 0x01:
- util::stream_format(stream, "%-8s #X%02X", Format1[Format1op(opcode)], get_disp(pc, opcodes) & 0xffffff);
- break;
- case 0x02:
- util::stream_format(stream, "%-8s EXT(%d)", Format1[Format1op(opcode)], get_disp(pc, opcodes));
- break;
- case 0x03: case 0x04:
- util::stream_format(stream, "%-8s #X%02X", Format1[Format1op(opcode)], get_disp(pc, opcodes) & 0xffffff);
- break;
- case 0x05:
- util::stream_format(stream, "%-8s", Format1[Format1op(opcode)]);
- break;
- case 0x06:
- util::stream_format(stream, "%-8s %s", Format1[Format1op(opcode)], get_reg_list(pc, opcodes, false));
- break;
- case 0x07: case 0x09:
- util::stream_format(stream, "%-8s %s", Format1[Format1op(opcode)], get_reg_list(pc, opcodes, true));
- break;
- case 0x08:
- util::stream_format(stream, "%-8s %s, %d", Format1[Format1op(opcode)], get_reg_list(pc, opcodes, false), get_disp(pc, opcodes));
- break;
- case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
- util::stream_format(stream, "%-8s", Format1[Format1op(opcode)]);
- break;
- }
- break;
-
- case 0x02: /* Format 2 */
- pc += 2;
- mnemonic = mnemonic_index(Format2[Format2op(opcode)], iType[Format2i(opcode)], "");
- switch (Format2op(opcode))
- {
- case 0x00: case 0x01: case 0x05:
- util::stream_format(stream, "%-8s %+d, ", mnemonic, short2int(Format2short(opcode)));
- stream_gen(stream, Format2gen(opcode), Format2i(opcode), pc, opcodes);
- break;
- case 0x02: case 0x06:
- util::stream_format(stream, "%-8s %s, ", mnemonic, areg[Format2short(opcode)]);
- stream_gen(stream, Format2gen(opcode), Format2i(opcode), pc, opcodes);
- break;
- case 0x03:
- util::stream_format(stream, "%-8s ", std::string("S").append(cond[Format2short(opcode)]).append(iType[Format2i(opcode)]));
- stream_gen(stream, Format2gen(opcode), Format2i(opcode), pc, opcodes);
- break;
- case 0x04:
- util::stream_format(stream, "%-8s %+d, ", mnemonic, short2int(Format2short(opcode)));
- stream_gen(stream, Format2gen(opcode), Format2i(opcode), pc, opcodes);
- util::stream_format(stream, ", #X%06x", m_base_pc + get_disp(pc, opcodes));
- break;
- }
- break;
-
- case 0x03: /* Format 3 */
- pc += 2;
- mnemonic = mnemonic_index(Format3[Format3op(opcode)], iType[Format3i(opcode)], "");
- switch (Format3op(opcode))
- {
- case 0x00: case 0x02: case 0x04: case 0x06: case 0x0a: case 0x0c: case 0x0e:
- util::stream_format(stream, "%-8s ", mnemonic);
- stream_gen(stream, Format3gen(opcode), Format3i(opcode), pc, opcodes);
- break;
- default: /* Trap */
- util::stream_format(stream, "%-8s ", mnemonic);
- break;
- }
- break;
-
- case 0x04: /* Format 4 */
- pc += 2;
- mnemonic = mnemonic_index(Format4[Format4op(opcode)], iType[Format4i(opcode)], "");
- util::stream_format(stream, "%-8s ", mnemonic);
- stream_gen(stream, Format4gen1(opcode), Format4i(opcode), pc, opcodes);
- util::stream_format(stream, ", ");
- stream_gen(stream, Format4gen2(opcode), Format4i(opcode), pc, opcodes);
- break;
-
- case 0x05: /* Format 5 */
- pc += 3;
- mnemonic = mnemonic_index(Format5[Format5op(opcode)], iType[Format5i(opcode)], "");
- switch ((opcode >> 10) & 0x0f)
- {
- case 0x00: case 0x01: case 0x03:
- if (Format5short(opcode) & 0x01)
- util::stream_format(stream, "%-8s %s", std::string(Format5[Format5op(opcode)]).append("T"), get_options(Format5short(opcode)));
- else
- util::stream_format(stream, "%-8s %s", mnemonic, get_options(Format5short(opcode)));
- break;
- case 0x02:
- util::stream_format(stream, "%-8s %s", Format5[Format5op(opcode)], get_option_list(Format5short(opcode)));
- break;
- default: /* Trap */
- util::stream_format(stream, "%-8s ", mnemonic);
- break;
- }
- break;
-
- case 0x06: /* Format 6 */
- pc += 3;
- mnemonic = mnemonic_index(Format6[Format6op(opcode)], iType[Format6i(opcode)], "");
- switch ((opcode >> 10) & 0x0f)
- {
- case 0x00: case 0x01: case 0x02: case 0x03: case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
- util::stream_format(stream, "%-8s ", mnemonic);
- stream_gen(stream, Format6gen1(opcode), Format6i(opcode), pc, opcodes);
- util::stream_format(stream, ", ");
- stream_gen(stream, Format6gen2(opcode), Format6i(opcode), pc, opcodes);
- break;
- default: /* Trap */
- util::stream_format(stream, "%-8s ", mnemonic);
- break;
- }
- break;
-
- case 0x07: /* Format 7 */
- pc += 3;
- mnemonic = mnemonic_index(Format7[Format7op(opcode)], iType[Format7i(opcode)], "");
- switch (Format7op(opcode))
- {
- case 0x00: case 0x01:
- util::stream_format(stream, "%-8s ", mnemonic);
- stream_gen(stream, Format7gen1(opcode), Format7i(opcode), pc, opcodes);
- util::stream_format(stream, ", ");
- stream_gen(stream, Format7gen2(opcode), Format7i(opcode), pc, opcodes);
- util::stream_format(stream, ", %d", get_disp(pc, opcodes));
- break;
- case 0x02: case 0x03:
- util::stream_format(stream, "%-8s ", mnemonic);
- stream_gen(stream, Format7gen1(opcode), Format7i(opcode), pc, opcodes);
- util::stream_format(stream, ", ");
- stream_gen(stream, Format7gen2(opcode), Format7i(opcode), pc, opcodes);
- temp8 = opcodes.r8(pc++);
- util::stream_format(stream, ", %d, %d", temp8 >> 5, temp8 + 1);
- break;
- case 0x04: case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f:
- util::stream_format(stream, "%-8s ", mnemonic);
- stream_gen(stream, Format7gen1(opcode), Format7i(opcode), pc, opcodes);
- util::stream_format(stream, ", ");
- stream_gen(stream, Format7gen2(opcode), Format7i(opcode), pc, opcodes);
- break;
- default: /* Trap */
- util::stream_format(stream, "%-8s ", mnemonic);
- break;
- }
- break;
-
- case 0x08: /* Format 8 */
- pc += 3;
- mnemonic = mnemonic_index(Format8[Format8op(opcode)], iType[Format8i(opcode)], "");
- switch (Format8op(opcode))
- {
- case 0x00: case 0x02:
- util::stream_format(stream, "%-8s %s, ", mnemonic, R[Format8reg(opcode)]);
- stream_gen(stream, Format8gen2(opcode), Format8i(opcode), pc, opcodes);
- util::stream_format(stream, ", ");
- stream_gen(stream, Format8gen1(opcode), Format8i(opcode), pc, opcodes);
- util::stream_format(stream, ", %d", get_disp(pc, opcodes));
- break;
- case 0x01: case 0x03: case 0x04:
- util::stream_format(stream, "%-8s %s, ", mnemonic, R[Format8reg(opcode)]);
- stream_gen(stream, Format8gen2(opcode), Format8i(opcode), pc, opcodes);
- util::stream_format(stream, ", ");
- stream_gen(stream, Format8gen1(opcode), Format8i(opcode), pc, opcodes);
- break;
- case 0x05:
- util::stream_format(stream, "%-8s ", mnemonic);
- stream_gen(stream, Format8gen2(opcode), Format8i(opcode), pc, opcodes);
- util::stream_format(stream, ", ");
- stream_gen(stream, Format8gen1(opcode), Format8i(opcode), pc, opcodes);
- break;
- case 0x06:
- if (Format8reg(opcode) == 0x01)
- util::stream_format(stream, "%-8s ", std::string(Format8[Format8op(opcode)]).append(iType[Format8i(opcode)]));
- else
- util::stream_format(stream, "%-8s ", std::string(Format8[Format8op(opcode) + 1]).append(iType[Format8i(opcode)]));
- stream_gen(stream, Format8gen2(opcode), Format8i(opcode), pc, opcodes);
- util::stream_format(stream, ", ");
- stream_gen(stream, Format8gen1(opcode), Format8i(opcode), pc, opcodes);
- break;
- }
- break;
-
- case 0x09: /* Format 9 */
- pc += 3;
- mnemonic = mnemonic_index(Format9[Format9op(opcode)], iType[Format9i(opcode)], fType[Format9f(opcode)]);
- switch (Format9op(opcode))
- {
- case 0x00: case 0x02: case 0x04: case 0x05: case 0x07:
- util::stream_format(stream, "%-8s ", mnemonic);
- stream_gen(stream, Format9gen1(opcode), Format9i(opcode), pc, opcodes);
- util::stream_format(stream, ", ");
- stream_gen(stream, Format9gen2(opcode), Format9i(opcode), pc, opcodes);
- break;
- case 0x01: case 0x06:
- util::stream_format(stream, "%-8s ", mnemonic);
- stream_gen(stream, Format9gen1(opcode), Format9i(opcode), pc, opcodes);
- break;
- }
- break;
-
- case 0x0b: /* Format 11 */
- pc += 3;
- mnemonic = mnemonic_index(Format11[Format11op(opcode)], "", fType[Format11f(opcode)]);
- switch (Format11op(opcode))
- {
- case 0x00: case 0x01: case 0x02: case 0x04: case 0x05 : case 0x08: case 0x0c : case 0x0d:
- util::stream_format(stream, "%-8s ", mnemonic);
- stream_gen(stream, Format11gen1(opcode), Format11f(opcode), pc, opcodes);
- util::stream_format(stream, ",");
- stream_gen(stream, Format11gen2(opcode), Format11f(opcode), pc, opcodes);
- break;
- default: /* Trap */
- util::stream_format(stream, "%-8s ", mnemonic);
- break;
- }
- break;
-
- case 0x0a: /* Format 10 */
- case 0x0c: /* Format 12 */
- case 0x0d: /* Format 13 */
- pc += 3;
- util::stream_format(stream, "Trap (UND)");
- break;
-
- case 0x0e: /* Format 14 */
- pc += 3;
- mnemonic = mnemonic_index(Format14[Format14op(opcode)], iType[Format14i(opcode)], "");
- switch (Format14op(opcode))
- {
- case 0x00: case 0x01:
- util::stream_format(stream, "%-8s ", mnemonic);
- stream_gen(stream, Format14gen1(opcode), Format14i(opcode), pc, opcodes);
- break;
- case 0x02: case 0x03:
- util::stream_format(stream, "%-8s %s, ", mnemonic, mreg[Format14short(opcode)]);
- stream_gen(stream, Format14gen1(opcode), Format14i(opcode), pc, opcodes);
- break;
- default: /* Trap */
- util::stream_format(stream, "%-8s ", mnemonic);
- break;
- }
- break;
-
- default:
- pc += 1;
- util::stream_format(stream, "unknown instruction format");
- break;
- }
-
- return (pc - m_base_pc) | flags;
-}
diff --git a/src/devices/cpu/ns32000/ns32000dasm.h b/src/devices/cpu/ns32000/ns32000dasm.h
deleted file mode 100644
index 4cbf4cf3bda..00000000000
--- a/src/devices/cpu/ns32000/ns32000dasm.h
+++ /dev/null
@@ -1,117 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Nigel Barnes
-/*****************************************************************************
-*
-* ns32000dasm.cpp
-*
-* NS32000 CPU Disassembly
-*
-*****************************************************************************/
-
-#ifndef MAME_CPU_NS32000_NS32000DASM_H
-#define MAME_CPU_NS32000_NS32000DASM_H
-
-#pragma once
-
-class ns32000_disassembler : public util::disasm_interface
-{
-public:
-
- ns32000_disassembler() = default;
- virtual ~ns32000_disassembler() = default;
-
- virtual u32 opcode_alignment() const override { return 1; }
- virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params) override;
-
-private:
- /* implied operand attributes */
- enum
- {
- REG = 16,
- QUICK,
- SHORT,
- IMM,
- DISP,
- GEN,
- OPTIONS,
- };
- /* access classes */
- enum
- {
- READ = 8,
- WRITE,
- RMW,
- ADDR,
- REGADDR
- };
- /* length attributes */
- enum
- {
- B = 0,
- W = 1,
- D = 3,
- I,
- I2,
- F,
- L
- };
- struct NS32000_OPCODE {
- const char *mnemonic;
- u32 operand1;
- u32 operand;
- u32 operand3;
- u32 operand4;
- offs_t dasm_flags;
- };
-
- static const NS32000_OPCODE format0_op[1];
- static const NS32000_OPCODE format1_op[16];
- static const NS32000_OPCODE format2_op[8];
- static const NS32000_OPCODE format3_op[16];
- static const NS32000_OPCODE format4_op[16];
- static const NS32000_OPCODE format5_op[16];
- static const NS32000_OPCODE format6_op[16];
- static const NS32000_OPCODE format7_op[16];
- static const NS32000_OPCODE format8_op[16];
- static const NS32000_OPCODE format9_op[16];
- static const NS32000_OPCODE format11_op[16];
- static const NS32000_OPCODE format14_op[16];
-
-
- static char const *const Format0[];
- static char const *const Format1[];
- static char const *const Format2[];
- static char const *const Format3[];
- static char const *const Format4[];
- static char const *const Format5[];
- static char const *const Format6[];
- static char const *const Format7[];
- static char const *const Format8[];
- static char const *const Format9[];
- static char const *const Format11[];
- static char const *const Format14[];
- static char const *const iType[];
- static char const *const fType[];
- static char const *const cType[];
- static char const *const indexSize[];
- static char const *const cond[];
- static char const *const areg[];
- static char const *const mreg[];
- static char const *const R[];
- static char const *const M[];
- static char const *const PR[];
-
- std::string mnemonic_index(std::string form, std::string itype, std::string ftype);
- uint8_t opcode_format(uint8_t byte);
- int8_t short2int(uint8_t val);
- static inline int32_t get_disp(offs_t &pc, const data_buffer &opcodes);
- static inline std::string get_option_list(uint8_t cfg);
- static inline std::string get_options(uint8_t opts);
- static inline std::string get_reg_list(offs_t &pc, const data_buffer &opcodes, bool reverse);
-
- void stream_gen(std::ostream &stream, u8 gen_addr, u8 op_len, offs_t &pc, const data_buffer &opcodes);
-
- u32 m_base_pc;
-};
-
-#endif
diff --git a/src/devices/cpu/pic16c5x/pic16c5x.cpp b/src/devices/cpu/pic16c5x/pic16c5x.cpp
index 21907b7d369..fe1b0280d2a 100644
--- a/src/devices/cpu/pic16c5x/pic16c5x.cpp
+++ b/src/devices/cpu/pic16c5x/pic16c5x.cpp
@@ -83,8 +83,8 @@ DEFINE_DEVICE_TYPE(PIC16C56, pic16c56_device, "pic16c56", "Microchip PIC16C56")
DEFINE_DEVICE_TYPE(PIC16C57, pic16c57_device, "pic16c57", "Microchip PIC16C57")
DEFINE_DEVICE_TYPE(PIC16C58, pic16c58_device, "pic16c58", "Microchip PIC16C58")
-DEFINE_DEVICE_TYPE(PIC1650, pic1650_device, "pic1650", "GI PIC1650")
-DEFINE_DEVICE_TYPE(PIC1655, pic1655_device, "pic1655", "GI PIC1655")
+DEFINE_DEVICE_TYPE(PIC1650, pic1650_device, "pic1650", "Microchip PIC1650")
+DEFINE_DEVICE_TYPE(PIC1655, pic1655_device, "pic1655", "Microchip PIC1655")
/****************************************************************************
diff --git a/src/devices/cpu/sh/sh2.cpp b/src/devices/cpu/sh/sh2.cpp
index d3660a52209..6eebabea4ac 100644
--- a/src/devices/cpu/sh/sh2.cpp
+++ b/src/devices/cpu/sh/sh2.cpp
@@ -402,7 +402,7 @@ void sh2_device::execute_run()
{
debugger_instruction_hook(m_sh2_state->pc);
- const uint16_t opcode = m_decrypted_program->read_word(m_sh2_state->pc >= 0x40000000 ? m_sh2_state->pc : m_sh2_state->pc & SH12_AM);
+ const uint16_t opcode = m_program->read_word(m_sh2_state->pc & SH12_AM);
if (m_sh2_state->m_delay)
{
diff --git a/src/devices/cpu/sm510/sm510base.cpp b/src/devices/cpu/sm510/sm510base.cpp
index 919fcea9e17..b3bef1d67b7 100644
--- a/src/devices/cpu/sm510/sm510base.cpp
+++ b/src/devices/cpu/sm510/sm510base.cpp
@@ -15,6 +15,7 @@
TODO:
- source organiziation between files is a mess
+ - LCD bs pin blink mode via Y register (0.5s off, 0.5s on)
- wake up after CEND doesn't work right
for more, see the *core.cpp file notes
@@ -199,8 +200,7 @@ void sm510_base_device::lcd_update()
m_write_segs(h | SM510_PORT_SEGC, get_lcd_row(h, m_lcd_ram_c), 0xffff);
// bs output from L/X and Y regs
- u8 blink = (m_div & 0x4000) ? m_y : 0;
- u8 bs = ((m_l & ~blink) >> h & 1) | ((m_x*2) >> h & 2);
+ u8 bs = (m_l >> h & 1) | ((m_x*2) >> h & 2);
m_write_segs(h | SM510_PORT_SEGBS, (m_bc || !m_bp) ? 0 : bs, 0xffff);
}
}
diff --git a/src/devices/cpu/tms1000/tms0270.cpp b/src/devices/cpu/tms1000/tms0270.cpp
index 899e3eb1ba3..5d1eb2b14d1 100644
--- a/src/devices/cpu/tms1000/tms0270.cpp
+++ b/src/devices/cpu/tms1000/tms0270.cpp
@@ -24,6 +24,9 @@ DEFINE_DEVICE_TYPE(TMS0270, tms0270_cpu_device, "tms0270", "Texas Instruments TM
// device definitions
tms0270_cpu_device::tms0270_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock)
: tms0980_cpu_device(mconfig, TMS0270, tag, owner, clock, 16 /* o pins */, 16 /* r pins */, 7 /* pc bits */, 9 /* byte width */, 4 /* x width */, 11 /* prg width */, address_map_constructor(FUNC(tms0270_cpu_device::program_11bit_9), this), 8 /* data width */, address_map_constructor(FUNC(tms0270_cpu_device::data_144x4), this))
+ , m_read_ctl(*this)
+ , m_write_ctl(*this)
+ , m_write_pdc(*this)
{
}
@@ -44,6 +47,10 @@ void tms0270_cpu_device::device_start()
// common init
tms1k_base_device::device_start();
+ m_read_ctl.resolve_safe(0);
+ m_write_ctl.resolve_safe();
+ m_write_pdc.resolve_safe();
+
// zerofill
m_r_prev = 0;
m_chipsel = 0;
diff --git a/src/devices/cpu/tms1000/tms0270.h b/src/devices/cpu/tms1000/tms0270.h
index 45c231a950a..3043119e2aa 100644
--- a/src/devices/cpu/tms1000/tms0270.h
+++ b/src/devices/cpu/tms1000/tms0270.h
@@ -19,6 +19,11 @@ class tms0270_cpu_device : public tms0980_cpu_device
public:
tms0270_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
+ // TMS0270 was designed to interface with TMS5100, set it up at driver level
+ auto read_ctl() { return m_read_ctl.bind(); }
+ auto write_ctl() { return m_write_ctl.bind(); }
+ auto write_pdc() { return m_write_pdc.bind(); }
+
protected:
// overrides
virtual void device_start() override;
@@ -45,6 +50,10 @@ private:
u8 m_o_latch_low;
u8 m_o_latch;
u8 m_o_latch_prev;
+
+ devcb_read8 m_read_ctl;
+ devcb_write8 m_write_ctl;
+ devcb_write_line m_write_pdc;
};
diff --git a/src/devices/cpu/tms1000/tms1000c.cpp b/src/devices/cpu/tms1000/tms1000c.cpp
index b69a683f280..defc8482eef 100644
--- a/src/devices/cpu/tms1000/tms1000c.cpp
+++ b/src/devices/cpu/tms1000/tms1000c.cpp
@@ -52,3 +52,21 @@ u32 tms1000c_cpu_device::decode_micro(u8 sel)
return decode;
}
+
+
+// execute
+void tms1000c_cpu_device::execute_run()
+{
+ while (m_icount > 0)
+ {
+ if (m_halt_pin)
+ {
+ // not running (output pins remain unchanged)
+ m_icount = 0;
+ return;
+ }
+
+ m_icount--;
+ execute_one();
+ }
+}
diff --git a/src/devices/cpu/tms1000/tms1000c.h b/src/devices/cpu/tms1000/tms1000c.h
index 7857bf07f0c..364dd56879f 100644
--- a/src/devices/cpu/tms1000/tms1000c.h
+++ b/src/devices/cpu/tms1000/tms1000c.h
@@ -23,6 +23,7 @@ protected:
// overrides
virtual void device_add_mconfig(machine_config &config) override;
virtual u32 decode_micro(u8 sel) override;
+ virtual void execute_run() override;
virtual void op_br() override { op_br3(); } // 3-level stack
virtual void op_call() override { op_call3(); } // "
diff --git a/src/devices/cpu/tms1000/tms1k_base.cpp b/src/devices/cpu/tms1000/tms1k_base.cpp
index 3f14dba6c5e..432e43e0d7b 100644
--- a/src/devices/cpu/tms1000/tms1k_base.cpp
+++ b/src/devices/cpu/tms1000/tms1k_base.cpp
@@ -90,9 +90,6 @@ tms1k_base_device::tms1k_base_device(const machine_config &mconfig, device_type
, m_write_o(*this)
, m_write_r(*this)
, m_power_off(*this)
- , m_read_ctl(*this)
- , m_write_ctl(*this)
- , m_write_pdc(*this)
{
}
@@ -134,9 +131,6 @@ void tms1k_base_device::device_start()
m_write_o.resolve_safe();
m_write_r.resolve_safe();
m_power_off.resolve_safe();
- m_read_ctl.resolve_safe(0);
- m_write_ctl.resolve_safe();
- m_write_pdc.resolve_safe();
// zerofill
m_pc = 0;
@@ -153,6 +147,7 @@ void tms1k_base_device::device_start()
m_r = 0;
m_o = 0;
m_o_index = 0;
+ m_halt_pin = false;
m_cki_bus = 0;
m_c4 = 0;
m_p = 0;
@@ -192,6 +187,7 @@ void tms1k_base_device::device_start()
save_item(NAME(m_r));
save_item(NAME(m_o));
save_item(NAME(m_o_index));
+ save_item(NAME(m_halt_pin));
save_item(NAME(m_cki_bus));
save_item(NAME(m_c4));
save_item(NAME(m_p));
@@ -301,7 +297,7 @@ void tms1k_base_device::read_opcode()
{
debugger_instruction_hook(m_rom_address);
m_opcode = m_program->read_byte(m_rom_address);
- m_c4 = bitswap<4>(m_opcode,0,1,2,3); // opcode operand is bitswapped for most opcodes
+ m_c4 = bitswap<8>(m_opcode,7,6,5,4,0,1,2,3) & 0xf; // opcode operand is bitswapped for most opcodes
m_fixed = m_fixed_decode[m_opcode];
m_micro = m_micro_decode[m_opcode];
@@ -315,6 +311,15 @@ void tms1k_base_device::read_opcode()
// i/o handling
//-------------------------------------------------
+void tms1k_base_device::execute_set_input(int line, int state)
+{
+ if (line != TMS1XXX_INPUT_LINE_HALT)
+ return;
+
+ // HALT pin (CMOS only)
+ m_halt_pin = bool(state);
+}
+
void tms1k_base_device::write_o_output(u8 index)
{
// a hardcoded table is supported if the output pla is unknown
diff --git a/src/devices/cpu/tms1000/tms1k_base.h b/src/devices/cpu/tms1000/tms1k_base.h
index d7681329c93..7a394b8dfbb 100644
--- a/src/devices/cpu/tms1000/tms1k_base.h
+++ b/src/devices/cpu/tms1000/tms1k_base.h
@@ -17,6 +17,10 @@
#include "machine/pla.h"
+// HALT input pin on CMOS chips (use set_input_line)
+#define TMS1XXX_INPUT_LINE_HALT 0
+
+
// pinout reference
/*
@@ -74,14 +78,6 @@ public:
// OFF request on TMS0980 and up
auto power_off() { return m_power_off.bind(); }
- // note: for HALT input pin on CMOS chips, use set_input_line with INPUT_LINE_HALT
- // similarly with the INIT pin, simply use INPUT_LINE_RESET
-
- // TMS0270 was designed to interface with TMS5100, set it up at driver level
- auto read_ctl() { return m_read_ctl.bind(); }
- auto write_ctl() { return m_write_ctl.bind(); }
- auto write_pdc() { return m_write_pdc.bind(); }
-
// Use this if the output PLA is unknown:
// If the microinstructions (or other) PLA is unknown, try using one from another romset.
void set_output_pla(const u16 *output_pla) { m_output_pla_table = output_pla; }
@@ -99,6 +95,8 @@ protected:
// device_execute_interface overrides
virtual u32 execute_min_cycles() const override { return 1; }
virtual u32 execute_max_cycles() const override { return 1; }
+ virtual u32 execute_input_lines() const override { return 1; }
+ virtual void execute_set_input(int line, int state) override;
virtual void execute_run() override;
virtual void execute_one();
@@ -247,6 +245,7 @@ protected:
int m_subcycle;
int m_icount;
u8 m_o_index;
+ bool m_halt_pin;
u8 m_o_pins; // how many O pins
u8 m_r_pins; // how many R pins
@@ -262,9 +261,6 @@ protected:
devcb_write16 m_write_o;
devcb_write16 m_write_r;
devcb_write_line m_power_off;
- devcb_read8 m_read_ctl;
- devcb_write8 m_write_ctl;
- devcb_write_line m_write_pdc;
u32 m_o_mask;
u32 m_r_mask;
diff --git a/src/devices/cpu/tms34010/tms34010.cpp b/src/devices/cpu/tms34010/tms34010.cpp
index 79e9cf42fb6..3851b16dd37 100644
--- a/src/devices/cpu/tms34010/tms34010.cpp
+++ b/src/devices/cpu/tms34010/tms34010.cpp
@@ -7,9 +7,6 @@
Copyright Alex Pasadyn/Zsolt Vasvari
Parts based on code by Aaron Giles
- TMS34020 TODO:
- - Big endian mode isn't implemented
-
***************************************************************************/
#include "emu.h"
@@ -29,80 +26,36 @@
#define LOGCONTROLREGS(...) LOGMASKED(LOG_CONTROL_REGS, __VA_ARGS__)
#define LOGGRAPHICSOPS(...) LOGMASKED(LOG_GRAPHICS_OPS, __VA_ARGS__)
-void tms34010_device::internal_regs_map(address_map &map)
-{
- //map(0x00000000, 0xbfffffff); General use
- map(0xc0000000, 0xc00001ff).rw(FUNC(tms34010_device::io_register_r), FUNC(tms34010_device::io_register_w)); // IO registers
- //map(0xc0000200, 0xc0001fff).noprw(); Reserved (for IO registers?)
- //map(0xc0002000, 0xffffdfff); General use
- //map(0xffffe000, 0xfffffbff).noprw(); Reserved (for interrupt vectors, maybe)
- //map(0xfffffc00, 0xffffffff); Interrupt Vectors
-}
-
-void tms34020_device::internal_regs_map(address_map &map)
-{
- //map(0x00000000, 0x000fffff); General use and extended trap vectors
- //map(0x00100000, 0xbfffffff); General use
- map(0xc0000000, 0xc00003ff).rw(FUNC(tms34020_device::io_register_r), FUNC(tms34020_device::io_register_w)); // IO registers
- //map(0xc0000400, 0xc0001fff).noprw(); Reserved for IO registers
- //map(0xc0002000, 0xffefffff); General use
- //map(0xfff00000, 0xffffdfff); General use and extended trap vectors
- //map(0xffffe000, 0xfffffbbf).noprw(); Reserved for interrupt vectors and extended trap vectors
- //map(0xfffffbc0, 0xffffffff); Interrupt vectors and trap vectors
-}
-DEFINE_DEVICE_TYPE(TMS34010, tms34010_device, "tms34010", "Texas Instruments TMS34010")
-DEFINE_DEVICE_TYPE(TMS34020, tms34020_device, "tms34020", "Texas Instruments TMS34020")
+DEFINE_DEVICE_TYPE(TMS34010, tms34010_device, "tms34010", "TMS34010")
+DEFINE_DEVICE_TYPE(TMS34020, tms34020_device, "tms34020", "TMS34020")
/***************************************************************************
GLOBAL VARIABLES
***************************************************************************/
-tms340x0_device::tms340x0_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor internal_regs_map)
+tms340x0_device::tms340x0_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
: cpu_device(mconfig, type, tag, owner, clock)
, device_video_interface(mconfig, *this)
- , m_program_config("program", ENDIANNESS_LITTLE, 16, 32, 3, internal_regs_map)
- , m_pc(0)
- , m_ppc(0)
- , m_st(0)
- , m_pixel_write(nullptr)
- , m_pixel_read(nullptr)
- , m_raster_op(nullptr)
- , m_pixel_op(nullptr)
- , m_pixel_op_timing(0)
- , m_convsp(0)
- , m_convdp(0)
- , m_convmp(0)
- , m_gfxcycles(0)
- , m_pixelshift(0)
- , m_is_34020(0)
- , m_reset_deferred(false)
- , m_halt_on_reset(false)
- , m_hblank_stable(0)
- , m_external_host_access(0)
- , m_executing(0)
- , m_program(nullptr)
- , m_cache(nullptr)
+ , m_program_config("program", ENDIANNESS_LITTLE, 16, 32, 3), m_pc(0), m_ppc(0), m_st(0), m_pixel_write(nullptr), m_pixel_read(nullptr), m_raster_op(nullptr), m_pixel_op(nullptr), m_pixel_op_timing(0), m_convsp(0), m_convdp(0), m_convmp(0), m_gfxcycles(0), m_pixelshift(0), m_is_34020(0), m_reset_deferred(false)
+ , m_halt_on_reset(false), m_hblank_stable(0), m_external_host_access(0), m_executing(0), m_program(nullptr), m_cache(nullptr)
, m_pixclock(0)
- , m_pixperclock(0)
- , m_scantimer(nullptr)
- , m_icount(0)
+ , m_pixperclock(0), m_scantimer(nullptr), m_icount(0)
, m_output_int_cb(*this)
- , m_ioreg_pre_write_cb(*this)
{
}
tms34010_device::tms34010_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : tms340x0_device(mconfig, TMS34010, tag, owner, clock, address_map_constructor(FUNC(tms34010_device::internal_regs_map), this))
+ : tms340x0_device(mconfig, TMS34010, tag, owner, clock)
{
m_is_34020 = 0;
}
tms34020_device::tms34020_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : tms340x0_device(mconfig, TMS34020, tag, owner, clock, address_map_constructor(FUNC(tms34020_device::internal_regs_map), this))
+ : tms340x0_device(mconfig, TMS34020, tag, owner, clock)
{
m_is_34020 = 1;
}
@@ -629,7 +582,6 @@ void tms340x0_device::device_start()
m_scanline_ind16_cb.bind_relative_to(*owner());
m_scanline_rgb32_cb.bind_relative_to(*owner());
m_output_int_cb.resolve();
- m_ioreg_pre_write_cb.resolve();
m_to_shiftreg_cb.bind_relative_to(*owner());
m_from_shiftreg_cb.bind_relative_to(*owner());
@@ -673,6 +625,7 @@ void tms340x0_device::device_start()
save_item(NAME(m_pixelshift));
save_item(NAME(m_gfxcycles));
save_pointer(NAME(&m_regs[0].reg), ARRAY_LENGTH(m_regs));
+ machine().save().register_postload(save_prepost_delegate(FUNC(tms340x0_device::tms34010_state_postload), this));
set_icountptr(m_icount);
}
@@ -708,7 +661,7 @@ void tms340x0_device::device_reset()
if (m_reset_deferred)
{
- io_register_w(REG_HSTCTLH, 0x8000, 0xffff);
+ io_register_w(*m_program, REG_HSTCTLH, 0x8000, 0xffff);
}
}
@@ -1136,11 +1089,8 @@ static const char *const ioreg_name[] =
"HCOUNT", "VCOUNT", "DPYADR", "REFCNT"
};
-void tms34010_device::io_register_w(offs_t offset, u16 data, u16 mem_mask)
+WRITE16_MEMBER( tms34010_device::io_register_w )
{
- if (!m_ioreg_pre_write_cb.isnull())
- m_ioreg_pre_write_cb(offset, data, mem_mask);
-
int oldreg, newreg;
/* Set register */
@@ -1287,11 +1237,8 @@ static const char *const ioreg020_name[] =
"IHOST3L", "IHOST3H", "IHOST4L", "IHOST4H"
};
-void tms34020_device::io_register_w(offs_t offset, u16 data, u16 mem_mask)
+WRITE16_MEMBER( tms34020_device::io_register_w )
{
- if (!m_ioreg_pre_write_cb.isnull())
- m_ioreg_pre_write_cb(offset, data, mem_mask);
-
int oldreg, newreg;
/* Set register */
@@ -1451,7 +1398,7 @@ void tms34020_device::io_register_w(offs_t offset, u16 data, u16 mem_mask)
I/O REGISTER READS
***************************************************************************/
-u16 tms34010_device::io_register_r(offs_t offset)
+READ16_MEMBER( tms34010_device::io_register_r )
{
int result, total;
@@ -1492,7 +1439,7 @@ u16 tms34010_device::io_register_r(offs_t offset)
}
-u16 tms34020_device::io_register_r(offs_t offset)
+READ16_MEMBER( tms34020_device::io_register_r )
{
int result, total;
@@ -1532,7 +1479,7 @@ u16 tms34020_device::io_register_r(offs_t offset)
SAVE STATE
***************************************************************************/
-void tms340x0_device::device_post_load()
+void tms340x0_device::tms34010_state_postload()
{
set_raster_op();
set_pixel_function();
@@ -1543,7 +1490,7 @@ void tms340x0_device::device_post_load()
HOST INTERFACE WRITES
***************************************************************************/
-void tms340x0_device::host_w(offs_t offset, u16 data, u16 mem_mask)
+WRITE16_MEMBER( tms340x0_device::host_w )
{
int reg = offset;
unsigned int addr;
@@ -1580,8 +1527,8 @@ void tms340x0_device::host_w(offs_t offset, u16 data, u16 mem_mask)
case TMS34010_HOST_CONTROL:
{
m_external_host_access = true;
- if (mem_mask&0xff00) io_register_w(REG_HSTCTLH, data & 0xff00, 0xff00);
- if (mem_mask&0x00ff) io_register_w(REG_HSTCTLL, data & 0x00ff, 0x00ff);
+ if (mem_mask&0xff00) io_register_w(*m_program, REG_HSTCTLH, data & 0xff00, 0xff00);
+ if (mem_mask&0x00ff) io_register_w(*m_program, REG_HSTCTLL, data & 0x00ff, 0x00ff);
m_external_host_access = false;
break;
}
@@ -1599,7 +1546,7 @@ void tms340x0_device::host_w(offs_t offset, u16 data, u16 mem_mask)
HOST INTERFACE READS
***************************************************************************/
-u16 tms340x0_device::host_r(offs_t offset)
+READ16_MEMBER( tms340x0_device::host_r )
{
int reg = offset;
unsigned int addr;
diff --git a/src/devices/cpu/tms34010/tms34010.h b/src/devices/cpu/tms34010/tms34010.h
index 313f94d3503..299282fe743 100644
--- a/src/devices/cpu/tms34010/tms34010.h
+++ b/src/devices/cpu/tms34010/tms34010.h
@@ -135,7 +135,6 @@ public:
void set_pixels_per_clock(int pixperclock) { m_pixperclock = pixperclock; }
auto output_int() { return m_output_int_cb.bind(); }
- auto ioreg_pre_write() { return m_ioreg_pre_write_cb.bind(); }
// Setters for ind16 scanline callback
template <class FunctionClass>
@@ -206,15 +205,16 @@ public:
}
void get_display_params(display_params *params);
+ void tms34010_state_postload();
uint32_t tms340x0_ind16(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
uint32_t tms340x0_rgb32(screen_device &screen, bitmap_rgb32 &bitmap, const rectangle &cliprect);
- virtual void io_register_w(offs_t offset, u16 data, u16 mem_mask = ~u16(0)) = 0;
- virtual u16 io_register_r(offs_t offset) = 0;
+ virtual DECLARE_WRITE16_MEMBER(io_register_w) = 0;
+ virtual DECLARE_READ16_MEMBER(io_register_r) = 0;
- void host_w(offs_t offset, u16 data, u16 mem_mask = ~u16(0));
- u16 host_r(offs_t offset);
+ DECLARE_WRITE16_MEMBER(host_w);
+ DECLARE_READ16_MEMBER(host_r);
TIMER_CALLBACK_MEMBER(internal_interrupt_callback);
TIMER_CALLBACK_MEMBER(scanline_callback);
@@ -292,12 +292,11 @@ protected:
};
// construction/destruction
- tms340x0_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor internal_regs_map = address_map_constructor());
+ tms340x0_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
- virtual void device_post_load() override;
// device_execute_interface overrides
virtual uint32_t execute_min_cycles() const override { return 1; }
@@ -368,7 +367,6 @@ protected:
scanline_ind16_cb_delegate m_scanline_ind16_cb;
scanline_rgb32_cb_delegate m_scanline_rgb32_cb;
devcb_write_line m_output_int_cb; /* output interrupt callback */
- devcb_write16 m_ioreg_pre_write_cb;
shiftreg_in_cb_delegate m_to_shiftreg_cb; /* shift register write */
shiftreg_out_cb_delegate m_from_shiftreg_cb; /* shift register read */
@@ -1052,14 +1050,13 @@ public:
tms34010_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
/* Reads & writes to the 34010 I/O registers; place at 0xc0000000 */
- virtual void io_register_w(offs_t offset, u16 data, u16 mem_mask = ~u16(0)) override;
- virtual u16 io_register_r(offs_t offset) override;
+ virtual DECLARE_WRITE16_MEMBER( io_register_w ) override;
+ virtual DECLARE_READ16_MEMBER( io_register_r ) override;
protected:
virtual uint64_t execute_clocks_to_cycles(uint64_t clocks) const override { return (clocks + 8 - 1) / 8; }
virtual uint64_t execute_cycles_to_clocks(uint64_t cycles) const override { return (cycles * 8); }
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
- void internal_regs_map(address_map &map);
};
DECLARE_DEVICE_TYPE(TMS34010, tms34010_device)
@@ -1069,15 +1066,14 @@ class tms34020_device : public tms340x0_device
public:
tms34020_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- /* Reads & writes to the 34020 I/O registers; place at 0xc0000000 */
- virtual void io_register_w(offs_t offset, u16 data, u16 mem_mask = ~u16(0)) override;
- virtual u16 io_register_r(offs_t offset) override;
+ /* Reads & writes to the 34010 I/O registers; place at 0xc0000000 */
+ virtual DECLARE_WRITE16_MEMBER( io_register_w ) override;
+ virtual DECLARE_READ16_MEMBER( io_register_r ) override;
protected:
virtual uint64_t execute_clocks_to_cycles(uint64_t clocks) const override { return (clocks + 4 - 1) / 4; }
virtual uint64_t execute_cycles_to_clocks(uint64_t cycles) const override { return (cycles * 4); }
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
- void internal_regs_map(address_map &map);
};
DECLARE_DEVICE_TYPE(TMS34020, tms34020_device)
diff --git a/src/devices/cpu/tms9900/tms9900.cpp b/src/devices/cpu/tms9900/tms9900.cpp
index 840fd5d631a..8f092a3159d 100644
--- a/src/devices/cpu/tms9900/tms9900.cpp
+++ b/src/devices/cpu/tms9900/tms9900.cpp
@@ -182,11 +182,11 @@ tms99xx_device::tms99xx_device(const machine_config &mconfig, device_type type,
: cpu_device(mconfig, type, tag, owner, clock),
m_program_config("program", ENDIANNESS_BIG, data_width, prg_addr_bits),
m_setoffset_config("setoffset", ENDIANNESS_BIG, data_width, prg_addr_bits),
- m_io_config("cru", ENDIANNESS_LITTLE, 8, cru_addr_bits + 1, 1),
+ m_io_config("cru", ENDIANNESS_BIG, 8, cru_addr_bits),
m_prgspace(nullptr),
m_cru(nullptr),
m_prgaddr_mask((1<<prg_addr_bits)-1),
- m_cruaddr_mask((2<<cru_addr_bits)-2),
+ m_cruaddr_mask((1<<cru_addr_bits)-1),
m_clock_out_line(*this),
m_wait_line(*this),
m_holda_line(*this),
@@ -1625,70 +1625,67 @@ void tms99xx_device::register_write()
idempotent (i.e. they must not change the state of the queried device).
Read returns the number of consecutive CRU bits, with increasing CRU address
- from the least significant to the most significant bit; right-aligned (in
- other words, little-endian as opposed to the big-endian order of memory words).
+ from the least significant to the most significant bit; right-aligned
There seems to be no handling of wait states during CRU operations on the
TMS9900. The TMS9995, in contrast, respects wait states during the transmission
of each single bit.
- The current emulation of the CRU space involves a 1-bit address shift,
- reflecting the one-to-one correspondence between CRU bits and words (not
- bytes) in the lower part of the memory space. (On the TMS9980A and TMS9995,
- CRUOUT is multiplexed with the least significant address line.) Thus, what
- TI's documentation calls the software address (the R12 base value plus the
- bit offset multiplied by 2) is used in address maps and CPU-side operations.
- MAME's memory architecture automatically translates these to right-justified
- hardware addresses in the process of decoding offsets for read/write handlers,
- which is more typical of what peripheral devices expect. (Note also that
- address spaces do not support data widths narrower than 8 bits, so these
- handlers must specify 8-bit types despite only one bit being useful.)
-
Usage of this method:
CRU write: First bit is at rightmost position of m_value.
*/
void tms99xx_device::cru_input_operation()
{
- offs_t cruaddr = m_cru_address & m_cruaddr_mask;
- uint16_t value = 0;
+ int value, value1;
+ int offset, location;
- for (int i = 0; i < m_count; i++)
- {
- // Poll one bit at a time
- bool cruin = BIT(m_cru->read_byte(cruaddr), 0);
- if (cruin)
- value |= 1 << i;
+ location = (m_cru_address >> 4) & (m_cruaddr_mask>>3);
+ offset = (m_cru_address>>1) & 0x07;
- if (TRACE_CRU) logerror("CRU input operation, address %04x, value %d\n", cruaddr, cruin ? 1 : 0);
+ // Read 8 bits (containing the desired bits)
+ value = m_cru->read_byte(location);
- // Increment the CRU address
- cruaddr = (cruaddr + 2) & m_cruaddr_mask;
+ if ((offset + m_count) > 8) // spans two 8 bit cluster
+ {
+ // Read next 8 bits
+ location = (location + 1) & (m_cruaddr_mask>>3);
+ value1 = m_cru->read_byte(location);
+ value |= (value1 << 8);
- // On each machine cycle (2 clocks) only one CRU bit is transmitted
- pulse_clock(2);
+ if ((offset + m_count) > 16) // spans three 8 bit cluster
+ {
+ // Read next 8 bits
+ location = (location + 1) & (m_cruaddr_mask>>3);
+ value1 = m_cru->read_byte(location);
+ value |= (value1 << 16);
+ }
}
- m_value = value;
+ // On each machine cycle (2 clocks) only one CRU bit is transmitted
+ pulse_clock(m_count<<1);
+
+ // Shift back the bits so that the first bit is at the rightmost place
+ m_value = (value >> offset);
+
+ // Mask out what we want
+ m_value &= (0x0000ffff >> (16-m_count));
}
void tms99xx_device::cru_output_operation()
{
- offs_t cruaddr = m_cru_address & m_cruaddr_mask;
- uint16_t value = m_value;
+ int value;
+ int location;
+ location = (m_cru_address >> 1) & m_cruaddr_mask;
+ value = m_value;
// Write m_count bits from cru_address
- for (int i = 0; i < m_count; i++)
+ for (int i=0; i < m_count; i++)
{
- if (TRACE_CRU) logerror("CRU output operation, address %04x, value %d\n", cruaddr, BIT(value, 0));
-
- // Write one bit at a time
- m_cru->write_byte(cruaddr, BIT(value, 0));
+ if (TRACE_CRU) logerror("CRU output operation, address %04x, value %d\n", location<<1, value & 0x01);
+ m_cru->write_byte(location, (value & 0x01));
value >>= 1;
-
- // Increment the CRU address
- cruaddr = (cruaddr + 2) & m_cruaddr_mask;
-
+ location = (location + 1) & m_cruaddr_mask;
pulse_clock(2);
}
}
@@ -2167,7 +2164,6 @@ void tms99xx_device::alu_clr_swpb()
bool setstatus = true;
bool check_ov = true;
- bool check_c = true;
switch (m_command)
{
@@ -2185,7 +2181,6 @@ void tms99xx_device::alu_clr_swpb()
// LAE
dest_new = ~src_val & 0xffff;
check_ov = false;
- check_c = false;
break;
case NEG:
// LAECO
@@ -2228,7 +2223,7 @@ void tms99xx_device::alu_clr_swpb()
if (setstatus)
{
if (check_ov) set_status_bit(ST_OV, ((src_val & 0x8000)==sign) && ((dest_new & 0x8000)!=sign));
- if (check_c) set_status_bit(ST_C, (dest_new & 0x10000) != 0);
+ set_status_bit(ST_C, (dest_new & 0x10000) != 0);
m_current_value = dest_new & 0xffff;
compare_and_set_lae(m_current_value, 0);
}
@@ -2520,7 +2515,6 @@ void tms99xx_device::alu_shift()
uint16_t sign = 0;
uint32_t value;
int count;
- bool check_ov = false;
switch (m_state)
{
@@ -2578,7 +2572,6 @@ void tms99xx_device::alu_shift()
case SLA:
carry = ((value & 0x8000)!=0);
value <<= 1;
- check_ov = true;
if (carry != ((value&0x8000)!=0)) overflow = true;
break;
case SRC:
@@ -2591,7 +2584,7 @@ void tms99xx_device::alu_shift()
m_current_value = value & 0xffff;
set_status_bit(ST_C, carry);
- if (check_ov) set_status_bit(ST_OV, overflow); // only SLA
+ set_status_bit(ST_OV, overflow);
compare_and_set_lae(m_current_value, 0);
m_address = m_address_saved; // Register address
if (TRACE_STATUS) logerror("ST = %04x (val=%04x)\n", ST, m_current_value);
diff --git a/src/devices/cpu/tms9900/tms9995.cpp b/src/devices/cpu/tms9900/tms9995.cpp
index 09509f4623e..c83f74ac073 100644
--- a/src/devices/cpu/tms9900/tms9995.cpp
+++ b/src/devices/cpu/tms9900/tms9995.cpp
@@ -170,7 +170,7 @@ tms9995_device::tms9995_device(const machine_config &mconfig, device_type type,
PC_debug(0),
m_program_config("program", ENDIANNESS_BIG, 8, 16),
m_setoffset_config("setoffset", ENDIANNESS_BIG, 8, 16),
- m_io_config("cru", ENDIANNESS_LITTLE, 8, 16, 1),
+ m_io_config("cru", ENDIANNESS_BIG, 8, 16),
m_prgspace(nullptr),
m_sospace(nullptr),
m_cru(nullptr),
@@ -288,6 +288,8 @@ void tms9995_device::device_start()
save_item(NAME(m_cru_address));
save_item(NAME(m_cru_value));
save_item(NAME(m_cru_first_read));
+ save_item(NAME(m_cru_bits_left));
+ save_item(NAME(m_cru_read));
save_pointer(NAME(m_flag),16);
save_item(NAME(IR));
save_item(NAME(m_pre_IR));
@@ -1508,13 +1510,10 @@ void tms9995_device::int_prefetch_and_decode()
// If the current command is XOP or BLWP, ignore the interrupt
if (m_command != XOP && m_command != BLWP)
{
- // The actual interrupt trigger is an OR of the latch and of
- // the interrupt line (for INT1 and INT4); see [1],
- // section 2.3.2.1.3
- if ((m_int1_active || m_flag[2]) && intmask >= 1) m_int_pending |= PENDING_LEVEL1;
+ if (m_flag[2] && intmask >= 1) m_int_pending |= PENDING_LEVEL1;
if (m_int_overflow && intmask >= 2) m_int_pending |= PENDING_OVERFLOW;
if (m_flag[3] && intmask >= 3) m_int_pending |= PENDING_DECR;
- if ((m_int4_active || m_flag[4]) && intmask >= 4) m_int_pending |= PENDING_LEVEL4;
+ if (m_flag[4] && intmask >= 4) m_int_pending |= PENDING_LEVEL4;
}
if (m_int_pending!=0)
@@ -1563,7 +1562,7 @@ void tms9995_device::prefetch_and_decode()
m_value_copy = m_current_value;
if (!m_iaq_line.isnull()) m_iaq_line(ASSERT_LINE);
m_address = PC;
- LOGMASKED(LOG_DETAIL, "** Prefetching new instruction at %04x **\n", PC);
+ LOGMASKED(LOG_DETAIL, "**** Prefetching new instruction at %04x ****\n", PC);
}
word_read(); // changes m_mem_phase
@@ -1576,7 +1575,7 @@ void tms9995_device::prefetch_and_decode()
m_current_value = m_value_copy; // restore m_current_value
PC = (PC + 2) & 0xfffe; // advance PC
if (!m_iaq_line.isnull()) m_iaq_line(CLEAR_LINE);
- LOGMASKED(LOG_DETAIL, "++ Prefetch done ++\n");
+ LOGMASKED(LOG_DETAIL, "++++ Prefetch done ++++\n");
}
}
@@ -1689,7 +1688,7 @@ void tms9995_device::service_interrupt()
vectorpos = 0x0008;
m_intmask = 0x0001;
PC = (PC + 2) & 0xfffe;
- LOGMASKED(LOG_INT, "** MID pending\n");
+ LOGMASKED(LOG_INT, "***** MID pending\n");
m_mid_active = false;
}
else
@@ -1699,7 +1698,7 @@ void tms9995_device::service_interrupt()
vectorpos = 0xfffc;
m_int_pending &= ~PENDING_NMI;
m_intmask = 0;
- LOGMASKED(LOG_INT, "** NMI pending\n");
+ LOGMASKED(LOG_INT, "***** NMI pending\n");
}
else
{
@@ -1707,12 +1706,9 @@ void tms9995_device::service_interrupt()
{
vectorpos = 0x0004;
m_int_pending &= ~PENDING_LEVEL1;
- // Latches must be reset when the interrupt is serviced
- // Since the latch is edge-triggered, we should be allowed
- // to clear it right here, without considering the line state
- m_flag[2] = false;
+ if (!m_int1_active) m_flag[2] = false;
m_intmask = 0;
- LOGMASKED(LOG_INT, "** INT1 pending\n");
+ LOGMASKED(LOG_INT, "***** INT1 pending\n");
}
else
{
@@ -1721,7 +1717,7 @@ void tms9995_device::service_interrupt()
vectorpos = 0x0008;
m_int_pending &= ~PENDING_OVERFLOW;
m_intmask = 0x0001;
- LOGMASKED(LOG_INT, "** OVERFL pending\n");
+ LOGMASKED(LOG_INT, "***** OVERFL pending\n");
}
else
{
@@ -1731,16 +1727,15 @@ void tms9995_device::service_interrupt()
m_intmask = 0x0002;
m_int_pending &= ~PENDING_DECR;
m_flag[3] = false;
- LOGMASKED(LOG_DEC, "** DECR pending\n");
+ LOGMASKED(LOG_DEC, "***** DECR pending\n");
}
else
{
vectorpos = 0x0010;
m_intmask = 0x0003;
m_int_pending &= ~PENDING_LEVEL4;
- // See above for clearing the latch
- m_flag[4] = false;
- LOGMASKED(LOG_INT, "** INT4 pending\n");
+ if (!m_int4_active) m_flag[4] = false;
+ LOGMASKED(LOG_INT, "***** INT4 pending\n");
}
}
}
@@ -1748,7 +1743,7 @@ void tms9995_device::service_interrupt()
}
}
- LOGMASKED(LOG_INTD, "*** triggered an interrupt with vector %04x/%04x\n", vectorpos, vectorpos+2);
+ LOGMASKED(LOG_INT, "********* triggered an interrupt with vector %04x/%04x\n", vectorpos, vectorpos+2);
// just for debugging purposes
if (!m_reset) m_log_interrupt = true;
@@ -2085,7 +2080,8 @@ void tms9995_device::return_with_address_copy()
1FDA MID flag (only indication, does not trigger when set)
The TMS9995 allows for wait states during external CRU access. Therefore
- we do iterations for each bit, checking every time for the READY line
+ we read one block of 8 bits in one go (as given by the MESS architecture)
+ but we do iterations for each bit, checking every time for the READY line
in the main loop.
(write)
@@ -2096,8 +2092,8 @@ void tms9995_device::return_with_address_copy()
*/
-#define CRUREADMASK 0xfffe
-#define CRUWRITEMASK 0xfffe
+#define CRUREADMASK 0x0fff
+#define CRUWRITEMASK 0x7fff
void tms9995_device::cru_output_operation()
{
@@ -2133,7 +2129,7 @@ void tms9995_device::cru_output_operation()
// of the CPU. However, no wait states are generated for internal
// accesses. ([1], section 2.3.3.2)
- m_cru->write_byte(m_cru_address & CRUWRITEMASK, (m_cru_value & 0x01));
+ m_cru->write_byte((m_cru_address >> 1)& CRUWRITEMASK, (m_cru_value & 0x01));
m_cru_value >>= 1;
m_cru_address = (m_cru_address + 2) & 0xfffe;
m_count--;
@@ -2154,29 +2150,55 @@ void tms9995_device::cru_output_operation()
void tms9995_device::cru_input_operation()
{
- if (m_cru_first_read)
+ uint16_t crubit;
+ uint8_t crubyte;
+
+ // Reading is different, since MESS uses 8 bit transfers
+ // We read 8 bits in one go, then iterate another min(n-1,7) times to allow
+ // for wait states.
+
+ // read_byte for CRU delivers the first bit on the rightmost position
+
+ int offset = (m_cru_address>>1) & 0x07;
+
+ if (m_cru_first_read || m_cru_bits_left == 0)
{
- m_cru_value = 0;
- m_cru_first_read = false;
- m_pass = m_count;
+ // Read next 8 bits
+ // 00000000 0rrrrrrr r
+ // v
+ // ........ ........ X....... ........
+ //
+ crubyte = m_cru->read_byte((m_cru_address >> 4)& CRUREADMASK);
+ LOGMASKED(LOG_DETAIL, "Need to get next 8 bits (addresses %04x-%04x): %02x\n", (m_cru_address&0xfff0)+14, m_cru_address&0xfff0, crubyte);
+ m_cru_read = crubyte << 15;
+ m_cru_bits_left = 8;
+
+ if (m_cru_first_read)
+ {
+ m_cru_read >>= offset;
+ m_cru_bits_left -= offset;
+ m_cru_value = 0;
+ m_cru_first_read = false;
+ m_pass = m_count;
+ }
+ LOGMASKED(LOG_DETAIL, "adjusted value for shift: %06x\n", m_cru_read);
}
- // Read a single CRU bit
- bool crubit = BIT(m_cru->read_byte(m_cru_address & CRUREADMASK), 0);
+ crubit = (m_cru_read & 0x8000);
m_cru_value = (m_cru_value >> 1) & 0x7fff;
// During internal reading, the CRUIN line will be ignored. We emulate this
// by overwriting the bit which we got from outside. Also, READY is ignored.
if (m_cru_address == 0x1fda)
{
- crubit = m_mid_flag;
+ crubit = m_mid_flag? 0x8000 : 0x0000;
m_check_ready = false;
}
else
{
if ((m_cru_address & 0xffe0)==0x1ee0)
{
- crubit = m_flag[(m_cru_address>>1)&0x000f];
+ crubit = (m_flag[(m_cru_address>>1)&0x000f]==true)? 0x8000 : 0x0000;
m_check_ready = false;
}
else
@@ -2185,14 +2207,18 @@ void tms9995_device::cru_input_operation()
}
}
- LOGMASKED(LOG_CRU, "CRU input operation, address %04x, value %d\n", m_cru_address, crubit ? 1 : 0);
+ LOGMASKED(LOG_CRU, "CRU input operation, address %04x, value %d\n", m_cru_address, (crubit & 0x8000)>>15);
- if (crubit)
- m_cru_value |= 0x8000;
+ m_cru_value |= crubit;
m_cru_address = (m_cru_address + 2) & 0xfffe;
+ m_cru_bits_left--;
- if (m_pass == 1)
+ if (m_pass > 1)
+ {
+ m_cru_read >>= 1;
+ }
+ else
{
// This is the final shift. For both byte and word length transfers,
// the first bit is always m_cru_value & 0x0001.
@@ -3090,7 +3116,6 @@ void tms9995_device::alu_shift()
uint16_t sign = 0;
uint32_t value;
int count;
- bool check_ov = false;
switch (m_inst_state)
{
@@ -3139,7 +3164,6 @@ void tms9995_device::alu_shift()
case SLA:
carry = ((value & 0x8000)!=0);
value <<= 1;
- check_ov = true;
if (carry != ((value&0x8000)!=0)) overflow = true;
break;
case SRC:
@@ -3152,7 +3176,7 @@ void tms9995_device::alu_shift()
m_current_value = value & 0xffff;
set_status_bit(ST_C, carry);
- if (check_ov) set_status_bit(ST_OV, overflow); // only SLA
+ set_status_bit(ST_OV, overflow);
compare_and_set_lae(m_current_value, 0);
m_address = m_address_saved; // Register address
LOGMASKED(LOG_STATUS, "ST = %04x (val=%04x)\n", ST, m_current_value);
@@ -3170,7 +3194,6 @@ void tms9995_device::alu_single_arithm()
uint32_t src_val = m_current_value & 0x0000ffff;
uint16_t sign = 0;
bool check_ov = true;
- bool check_c = true;
switch (m_command)
{
@@ -3221,7 +3244,6 @@ void tms9995_device::alu_single_arithm()
// LAE
dest_new = ~src_val & 0xffff;
check_ov = false;
- check_c = false;
break;
case NEG:
// LAECO
@@ -3249,7 +3271,7 @@ void tms9995_device::alu_single_arithm()
}
if (check_ov) set_status_bit(ST_OV, ((src_val & 0x8000)==sign) && ((dest_new & 0x8000)!=sign));
- if (check_c) set_status_bit(ST_C, (dest_new & 0x10000) != 0);
+ set_status_bit(ST_C, (dest_new & 0x10000) != 0);
m_current_value = dest_new & 0xffff;
compare_and_set_lae(m_current_value, 0);
diff --git a/src/devices/cpu/tms9900/tms9995.h b/src/devices/cpu/tms9900/tms9995.h
index 531e5208a41..72dfc2960a1 100644
--- a/src/devices/cpu/tms9900/tms9995.h
+++ b/src/devices/cpu/tms9900/tms9995.h
@@ -245,6 +245,8 @@ private:
uint16_t m_cru_address;
uint16_t m_cru_value;
bool m_cru_first_read;
+ int m_cru_bits_left;
+ uint32_t m_cru_read;
// CPU-internal CRU flags
bool m_flag[16];
diff --git a/src/devices/cpu/unsp/unsp.cpp b/src/devices/cpu/unsp/unsp.cpp
index 7d1359896af..af964f713f9 100644
--- a/src/devices/cpu/unsp/unsp.cpp
+++ b/src/devices/cpu/unsp/unsp.cpp
@@ -14,41 +14,28 @@
#include "emu.h"
#include "unsp.h"
-#include "unspfe.h"
-
-#include "debugger.h"
-
-#include "unspdefs.h"
#include "unspdasm.h"
+#include "debugger.h"
DEFINE_DEVICE_TYPE(UNSP, unsp_device, "unsp", "SunPlus u'nSP")
-/* size of the execution code cache */
-#define CACHE_SIZE (64 * 1024 * 1024)
unsp_device::unsp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: cpu_device(mconfig, UNSP, tag, owner, clock)
, m_program_config("program", ENDIANNESS_BIG, 16, 23, -1)
+ , m_enable_irq(false)
+ , m_enable_fiq(false)
+ , m_irq(false)
+ , m_fiq(false)
+ , m_curirq(0)
+ , m_sirq(0)
+ , m_sb(0)
, m_program(nullptr)
- , m_core(nullptr)
+ , m_icount(0)
, m_debugger_temp(0)
-#if UNSP_LOG_OPCODES || UNSP_LOG_REGS
+#if UNSP_LOG_OPCODES
, m_log_ops(0)
#endif
- , m_cache(CACHE_SIZE + sizeof(unsp_device))
- , m_drcuml(nullptr)
- , m_drcfe(nullptr)
- , m_drcoptions(0)
- , m_cache_dirty(0)
- , m_entry(nullptr)
- , m_nocode(nullptr)
- , m_out_of_cycles(nullptr)
- , m_check_interrupts(nullptr)
- , m_trigger_fiq(nullptr)
- , m_trigger_irq(nullptr)
- , m_mem_read(nullptr)
- , m_mem_write(nullptr)
- , m_enable_drc(false)
{
}
@@ -64,6 +51,29 @@ std::unique_ptr<util::disasm_interface> unsp_device::create_disassembler()
return std::make_unique<unsp_disassembler>();
}
+
+/*****************************************************************************/
+
+#define OP0 (op >> 12)
+#define OPA ((op >> 9) & 7)
+#define OP1 ((op >> 6) & 7)
+#define OPN ((op >> 3) & 7)
+#define OPB (op & 7)
+#define OPIMM (op & 0x3f)
+
+#define UNSP_LPC (((UNSP_REG(SR) & 0x3f) << 16) | UNSP_REG(PC))
+
+#define UNSP_REG(reg) m_r[UNSP_##reg - 1]
+#define UNSP_REG_I(reg) m_r[reg]
+#define UNSP_LREG_I(reg) (((UNSP_REG(SR) << 6) & 0x3f0000) | UNSP_REG_I(reg))
+
+#define UNSP_N 0x0200
+#define UNSP_Z 0x0100
+#define UNSP_S 0x0080
+#define UNSP_C 0x0040
+
+/*****************************************************************************/
+
void unsp_device::unimplemented_opcode(uint16_t op)
{
fatalerror("UNSP: unknown opcode %04x at %04x\n", op, UNSP_LPC);
@@ -78,9 +88,6 @@ uint16_t unsp_device::read16(uint32_t address)
void unsp_device::write16(uint32_t address, uint16_t data)
{
-#if UNSP_LOG_REGS
- log_write(address, data);
-#endif
m_program->write_word(address, data);
}
@@ -88,141 +95,60 @@ void unsp_device::write16(uint32_t address, uint16_t data)
void unsp_device::device_start()
{
- m_core = (internal_unsp_state *)m_cache.alloc_near(sizeof(internal_unsp_state));
- memset(m_core, 0, sizeof(internal_unsp_state));
-
-#if ENABLE_UNSP_DRC
- m_enable_drc = allow_drc();
-#else
- m_enable_drc = false;
-#endif
-
-#if UNSP_LOG_REGS
- if (m_enable_drc)
- m_log_file = fopen("unsp_drc.bin", "wb");
- else
- m_log_file = fopen("unsp_interp.bin", "wb");
-#endif
-
+ memset(m_r, 0, sizeof(uint16_t) * 16);
+ m_enable_irq = false;
+ m_enable_fiq = false;
+ m_irq = false;
+ m_fiq = false;
+ m_curirq = 0;
+ m_sirq = 0;
+ m_sb = 0;
+ memset(m_saved_sb, 0, sizeof(uint8_t) * 3);
m_debugger_temp = 0;
m_program = &space(AS_PROGRAM);
- auto cache = m_program->cache<1, -1, ENDIANNESS_BIG>();
- m_pr16 = [cache](offs_t address) -> u16 { return cache->read_word(address); };
- m_prptr = [cache](offs_t address) -> const void * { return cache->read_ptr(address); };
-
- uint32_t umlflags = 0;
- m_drcuml = std::make_unique<drcuml_state>(*this, m_cache, umlflags, 1, 23, 0);
-
- // add UML symbols-
- m_drcuml->symbol_add(&m_core->m_r[REG_SP], sizeof(uint32_t), "SP");
- m_drcuml->symbol_add(&m_core->m_r[REG_R1], sizeof(uint32_t), "R1");
- m_drcuml->symbol_add(&m_core->m_r[REG_R2], sizeof(uint32_t), "R2");
- m_drcuml->symbol_add(&m_core->m_r[REG_R3], sizeof(uint32_t), "R3");
- m_drcuml->symbol_add(&m_core->m_r[REG_R4], sizeof(uint32_t), "R4");
- m_drcuml->symbol_add(&m_core->m_r[REG_BP], sizeof(uint32_t), "BP");
- m_drcuml->symbol_add(&m_core->m_r[REG_SR], sizeof(uint32_t), "SR");
- m_drcuml->symbol_add(&m_core->m_r[REG_PC], sizeof(uint32_t), "PC");
- m_drcuml->symbol_add(&m_core->m_enable_irq, sizeof(uint32_t), "IRQE");
- m_drcuml->symbol_add(&m_core->m_enable_fiq, sizeof(uint32_t), "FIQE");
- m_drcuml->symbol_add(&m_core->m_irq, sizeof(uint32_t), "IRQ");
- m_drcuml->symbol_add(&m_core->m_fiq, sizeof(uint32_t), "FIQ");
- m_drcuml->symbol_add(&m_core->m_sb, sizeof(uint32_t), "SB");
- m_drcuml->symbol_add(&m_core->m_icount, sizeof(m_core->m_icount), "icount");
-
- /* initialize the front-end helper */
- m_drcfe = std::make_unique<unsp_frontend>(this, COMPILE_BACKWARDS_BYTES, COMPILE_FORWARDS_BYTES, SINGLE_INSTRUCTION_MODE ? 1 : COMPILE_MAX_SEQUENCE);
-
- /* mark the cache dirty so it is updated on next execute */
- m_cache_dirty = true;
-
- // register our state for the debugger
- state_add(STATE_GENFLAGS, "GENFLAGS", m_core->m_r[REG_SR]).callimport().callexport().formatstr("%4s").noshow();
- state_add(UNSP_SP, "SP", m_core->m_r[REG_SP]).formatstr("%04X");
- state_add(UNSP_R1, "R1", m_core->m_r[REG_R1]).formatstr("%04X");
- state_add(UNSP_R2, "R2", m_core->m_r[REG_R2]).formatstr("%04X");
- state_add(UNSP_R3, "R3", m_core->m_r[REG_R3]).formatstr("%04X");
- state_add(UNSP_R4, "R4", m_core->m_r[REG_R4]).formatstr("%04X");
- state_add(UNSP_BP, "BP", m_core->m_r[REG_BP]).formatstr("%04X");
- state_add(UNSP_SR, "SR", m_core->m_r[REG_SR]).formatstr("%04X");
+
+ state_add(STATE_GENFLAGS, "GENFLAGS", UNSP_REG(SR)).callimport().callexport().formatstr("%4s").noshow();
+ state_add(UNSP_SP, "SP", UNSP_REG(SP)).formatstr("%04X");
+ state_add(UNSP_R1, "R1", UNSP_REG(R1)).formatstr("%04X");
+ state_add(UNSP_R2, "R2", UNSP_REG(R2)).formatstr("%04X");
+ state_add(UNSP_R3, "R3", UNSP_REG(R3)).formatstr("%04X");
+ state_add(UNSP_R4, "R4", UNSP_REG(R4)).formatstr("%04X");
+ state_add(UNSP_BP, "BP", UNSP_REG(BP)).formatstr("%04X");
+ state_add(UNSP_SR, "SR", UNSP_REG(SR)).formatstr("%04X");
state_add(UNSP_PC, "PC", m_debugger_temp).callimport().callexport().formatstr("%06X");
- state_add(UNSP_IRQ_EN, "IRQE", m_core->m_enable_irq).formatstr("%1u");
- state_add(UNSP_FIQ_EN, "FIQE", m_core->m_enable_fiq).formatstr("%1u");
- state_add(UNSP_IRQ, "IRQ", m_core->m_irq).formatstr("%1u");
- state_add(UNSP_FIQ, "FIQ", m_core->m_fiq).formatstr("%1u");
- state_add(UNSP_SB, "SB", m_core->m_sb).formatstr("%1u");
-#if UNSP_LOG_OPCODES || UNSP_LOG_REGS
+ state_add(UNSP_IRQ_EN, "IRQE", m_enable_irq).formatstr("%1u");
+ state_add(UNSP_FIQ_EN, "FIQE", m_enable_fiq).formatstr("%1u");
+ state_add(UNSP_IRQ, "IRQ", m_irq).formatstr("%1u");
+ state_add(UNSP_FIQ, "FIQ", m_fiq).formatstr("%1u");
+ state_add(UNSP_SB, "SB", m_sb).formatstr("%1u");
+#if UNSP_LOG_OPCODES
state_add(UNSP_LOG_OPS,"LOG", m_log_ops).formatstr("%1u");
#endif
state_add(STATE_GENPC, "GENPC", m_debugger_temp).callexport().noshow();
state_add(STATE_GENPCBASE, "CURPC", m_debugger_temp).callexport().noshow();
- save_item(NAME(m_core->m_r));
- save_item(NAME(m_core->m_enable_irq));
- save_item(NAME(m_core->m_enable_fiq));
- save_item(NAME(m_core->m_irq));
- save_item(NAME(m_core->m_fiq));
- save_item(NAME(m_core->m_curirq));
- save_item(NAME(m_core->m_sirq));
- save_item(NAME(m_core->m_sb));
- save_item(NAME(m_core->m_saved_sb));
-
- set_icountptr(m_core->m_icount);
-}
-
-void unsp_device::device_reset()
-{
- memset(m_core->m_r, 0, sizeof(uint32_t) * 8);
-
- m_core->m_r[REG_PC] = read16(0xfff7);
- m_core->m_enable_irq = 0;
- m_core->m_enable_fiq = 0;
- m_core->m_irq = 0;
- m_core->m_fiq = 0;
+ set_icountptr(m_icount);
+
+ save_item(NAME(m_r));
+ save_item(NAME(m_enable_irq));
+ save_item(NAME(m_enable_fiq));
+ save_item(NAME(m_irq));
+ save_item(NAME(m_fiq));
+ save_item(NAME(m_curirq));
+ save_item(NAME(m_sirq));
+ save_item(NAME(m_sb));
+ save_item(NAME(m_saved_sb));
}
-void unsp_device::device_stop()
-{
- if (m_drcfe != nullptr)
- {
- m_drcfe = nullptr;
- }
- if (m_drcuml != nullptr)
- {
- m_drcuml = nullptr;
- }
-#if UNSP_LOG_REGS
- fclose(m_log_file);
-#endif
-}
-
-#if UNSP_LOG_REGS
-void unsp_device::log_regs()
-{
- if (m_log_ops == 0)
- return;
- fwrite(m_core->m_r, sizeof(uint32_t), 8, m_log_file);
- fwrite(&m_core->m_sb, sizeof(uint32_t), 1, m_log_file);
- fwrite(&m_core->m_icount, sizeof(uint32_t), 1, m_log_file);
-}
-
-void unsp_device::log_write(uint32_t addr, uint32_t data)
-{
- addr |= 0x80000000;
- fwrite(&addr, sizeof(uint32_t), 1, m_log_file);
- fwrite(&data, sizeof(uint32_t), 1, m_log_file);
-}
-
-#endif
-
void unsp_device::state_string_export(const device_state_entry &entry, std::string &str) const
{
switch (entry.index())
{
case STATE_GENFLAGS:
{
- const uint16_t sr = m_core->m_r[REG_SR];
+ const uint16_t sr = UNSP_REG(SR);
str = string_format("%c%c%c%c", (sr & UNSP_N) ? 'N' : ' ', (sr & UNSP_Z) ? 'Z' : ' ', (sr & UNSP_S) ? 'S' : ' ', (sr & UNSP_C) ? 'C' : ' ');
}
}
@@ -245,91 +171,105 @@ void unsp_device::state_import(const device_state_entry &entry)
switch (entry.index())
{
case UNSP_PC:
- m_core->m_r[REG_PC] = m_debugger_temp & 0x0000ffff;
- m_core->m_r[REG_SR] = (m_core->m_r[REG_SR] & 0xffc0) | ((m_debugger_temp & 0x003f0000) >> 16);
+ UNSP_REG(PC) = m_debugger_temp & 0x0000ffff;
+ UNSP_REG(SR) = (UNSP_REG(SR) & 0xffc0) | ((m_debugger_temp & 0x003f0000) >> 16);
break;
}
}
-/*****************************************************************************/
-
-void unsp_device::update_nzsc(uint32_t value, uint16_t r0, uint16_t r1)
+void unsp_device::device_reset()
{
- m_core->m_r[REG_SR] &= ~(UNSP_N | UNSP_Z | UNSP_S | UNSP_C);
- if (int16_t(r0) < int16_t(~r1))
- m_core->m_r[REG_SR] |= UNSP_S;
- if (BIT(value, 15))
- m_core->m_r[REG_SR] |= UNSP_N;
- if((uint16_t)value == 0)
- m_core->m_r[REG_SR] |= UNSP_Z;
- if (BIT(value, 16))
- m_core->m_r[REG_SR] |= UNSP_C;
+ memset(m_r, 0, sizeof(uint16_t) * 16);
+
+ UNSP_REG(PC) = read16(0xfff7);
+ m_enable_irq = false;
+ m_enable_fiq = false;
+ m_irq = false;
+ m_fiq = false;
}
+/*****************************************************************************/
+
void unsp_device::update_nz(uint32_t value)
{
- m_core->m_r[REG_SR] &= ~(UNSP_N | UNSP_Z);
+ UNSP_REG(SR) &= ~(UNSP_N | UNSP_Z);
if(value & 0x8000)
- m_core->m_r[REG_SR] |= UNSP_N;
+ {
+ UNSP_REG(SR) |= UNSP_N;
+ }
if((uint16_t)value == 0)
- m_core->m_r[REG_SR] |= UNSP_Z;
+ {
+ UNSP_REG(SR) |= UNSP_Z;
+ }
+}
+
+void unsp_device::update_sc(uint32_t value, uint16_t r0, uint16_t r1)
+{
+ UNSP_REG(SR) &= ~(UNSP_C | UNSP_S);
+ if(value != (uint16_t)value)
+ {
+ UNSP_REG(SR) |= UNSP_C;
+ }
+
+ if((int16_t)r0 < (int16_t)r1)
+ {
+ UNSP_REG(SR) |= UNSP_S;
+ }
}
-void unsp_device::push(uint32_t value, uint32_t *reg)
+void unsp_device::push(uint16_t value, uint16_t *reg)
{
- write16(*reg, (uint16_t)value);
- *reg = (uint16_t)(*reg - 1);
+ write16((*reg)--, value);
}
-uint16_t unsp_device::pop(uint32_t *reg)
+uint16_t unsp_device::pop(uint16_t *reg)
{
- *reg = (uint16_t)(*reg + 1);
- return (uint16_t)read16(*reg);
+ return read16(++(*reg));
}
void unsp_device::trigger_fiq()
{
- if (!m_core->m_enable_fiq || m_core->m_fiq || m_core->m_irq)
+ if (!m_enable_fiq || m_fiq || m_irq)
{
return;
}
- m_core->m_fiq = 1;
+ m_fiq = true;
- m_core->m_saved_sb[m_core->m_irq ? 1 : 0] = m_core->m_sb;
- m_core->m_sb = m_core->m_saved_sb[2];
+ m_saved_sb[m_irq ? 1 : 0] = m_sb;
+ m_sb = m_saved_sb[2];
- push(m_core->m_r[REG_PC], &m_core->m_r[REG_SP]);
- push(m_core->m_r[REG_SR], &m_core->m_r[REG_SP]);
- m_core->m_r[REG_PC] = read16(0xfff6);
- m_core->m_r[REG_SR] = 0;
+ push(UNSP_REG(PC), &UNSP_REG(SP));
+ push(UNSP_REG(SR), &UNSP_REG(SP));
+ UNSP_REG(PC) = read16(0xfff6);
+ UNSP_REG(SR) = 0;
}
void unsp_device::trigger_irq(int line)
{
- if (!m_core->m_enable_irq || m_core->m_irq || m_core->m_fiq)
+ if (!m_enable_irq || m_irq || m_fiq)
return;
- m_core->m_irq = 1;
+ m_irq = true;
- m_core->m_saved_sb[0] = m_core->m_sb;
- m_core->m_sb = m_core->m_saved_sb[1];
+ m_saved_sb[0] = m_sb;
+ m_sb = m_saved_sb[1];
- push(m_core->m_r[REG_PC], &m_core->m_r[REG_SP]);
- push(m_core->m_r[REG_SR], &m_core->m_r[REG_SP]);
- m_core->m_r[REG_PC] = read16(0xfff8 + line);
- m_core->m_r[REG_SR] = 0;
+ push(UNSP_REG(PC), &UNSP_REG(SP));
+ push(UNSP_REG(SR), &UNSP_REG(SP));
+ UNSP_REG(PC) = read16(0xfff8 + line);
+ UNSP_REG(SR) = 0;
}
void unsp_device::check_irqs()
{
- if (!m_core->m_sirq)
+ if (!m_sirq)
return;
int highest_irq = -1;
for (int i = 0; i <= 8; i++)
{
- if (BIT(m_core->m_sirq, i))
+ if (BIT(m_sirq, i))
{
highest_irq = i;
break;
@@ -345,9 +285,9 @@ void unsp_device::check_irqs()
void unsp_device::add_lpc(const int32_t offset)
{
const uint32_t new_lpc = UNSP_LPC + offset;
- m_core->m_r[REG_PC] = (uint16_t)new_lpc;
- m_core->m_r[REG_SR] &= 0xffc0;
- m_core->m_r[REG_SR] |= (new_lpc >> 16) & 0x3f;
+ UNSP_REG(PC) = (uint16_t)new_lpc;
+ UNSP_REG(SR) &= 0xffc0;
+ UNSP_REG(SR) |= (new_lpc >> 16) & 0x3f;
}
inline void unsp_device::execute_one(const uint16_t op)
@@ -357,154 +297,147 @@ inline void unsp_device::execute_one(const uint16_t op)
uint16_t r1 = 0;
uint32_t r2 = 0;
- const uint16_t op0 = (op >> 12) & 15;
- const uint16_t opa = (op >> 9) & 7;
- const uint16_t op1 = (op >> 6) & 7;
- const uint16_t opn = (op >> 3) & 7;
- const uint16_t opb = op & 7;
-
- const uint8_t lower_op = (op1 << 4) | op0;
+ const uint8_t lower_op = (OP1 << 4) | OP0;
- if(op0 < 0xf && opa == 0x7 && op1 < 2)
+ if(OP0 < 0xf && OPA == 0x7 && OP1 < 2)
{
- const uint32_t opimm = op & 0x3f;
- switch(op0)
+ switch(OP0)
{
case 0: // JB
- if(!(m_core->m_r[REG_SR] & UNSP_C))
+ if(!(UNSP_REG(SR) & UNSP_C))
{
- m_core->m_icount -= 4;
- add_lpc((op1 == 0) ? opimm : (0 - opimm));
+ m_icount -= 4;
+ add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
}
else
{
- m_core->m_icount -= 2;
+ m_icount -= 2;
}
return;
case 1: // JAE
- if(m_core->m_r[REG_SR] & UNSP_C)
+ if(UNSP_REG(SR) & UNSP_C)
{
- m_core->m_icount -= 4;
- add_lpc((op1 == 0) ? opimm : (0 - opimm));
+ m_icount -= 4;
+ add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
}
else
{
- m_core->m_icount -= 2;
+ m_icount -= 2;
}
return;
case 2: // JGE
- if(!(m_core->m_r[REG_SR] & UNSP_S))
+ if(!(UNSP_REG(SR) & UNSP_S))
{
- m_core->m_icount -= 4;
- add_lpc((op1 == 0) ? opimm : (0 - opimm));
+ m_icount -= 4;
+ add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
}
else
{
- m_core->m_icount -= 2;
+ m_icount -= 2;
}
return;
case 3: // JL
- if(m_core->m_r[REG_SR] & UNSP_S)
+ if(UNSP_REG(SR) & UNSP_S)
{
- m_core->m_icount -= 4;
- add_lpc((op1 == 0) ? opimm : (0 - opimm));
+ m_icount -= 4;
+ add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
}
else
{
- m_core->m_icount -= 2;
+ m_icount -= 2;
}
return;
case 4: // JNE
- if(!(m_core->m_r[REG_SR] & UNSP_Z))
+ if(!(UNSP_REG(SR) & UNSP_Z))
{
- m_core->m_icount -= 4;
- add_lpc((op1 == 0) ? opimm : (0 - opimm));
+ m_icount -= 4;
+ add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
}
else
{
- m_core->m_icount -= 2;
+ m_icount -= 2;
}
return;
case 5: // JE
- if(m_core->m_r[REG_SR] & UNSP_Z)
+ if(UNSP_REG(SR) & UNSP_Z)
{
- m_core->m_icount -= 4;
- add_lpc((op1 == 0) ? opimm : (0 - opimm));
+ m_icount -= 4;
+ add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
}
else
{
- m_core->m_icount -= 2;
+ m_icount -= 2;
}
return;
case 6: // JPL
- if(!(m_core->m_r[REG_SR] & UNSP_N))
+ if(!(UNSP_REG(SR) & UNSP_N))
{
- m_core->m_icount -= 4;
- add_lpc((op1 == 0) ? opimm : (0 - opimm));
+ m_icount -= 4;
+ add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
}
else
{
- m_core->m_icount -= 2;
+ m_icount -= 2;
}
return;
case 7: // JMI
- if(m_core->m_r[REG_SR] & UNSP_N)
+ if(UNSP_REG(SR) & UNSP_N)
{
- m_core->m_icount -= 4;
- add_lpc((op1 == 0) ? opimm : (0 - opimm));
+ m_icount -= 4;
+ add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
}
else
{
- m_core->m_icount -= 2;
+ m_icount -= 2;
}
return;
case 8: // JBE
- if((m_core->m_r[REG_SR] & (UNSP_Z | UNSP_C)) != UNSP_C) // branch if (!UNSP_Z && !UNSP_C) || UNSP_Z
+ if((UNSP_REG(SR) & (UNSP_Z | UNSP_C)) != UNSP_C)
{
- m_core->m_icount -= 4;
- add_lpc((op1 == 0) ? opimm : (0 - opimm));
+ m_icount -= 4;
+ add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
}
else
{
- m_core->m_icount -= 2;
+ m_icount -= 2;
}
return;
case 9: // JA
- if((m_core->m_r[REG_SR] & (UNSP_Z | UNSP_C)) == UNSP_C) // branch if !UNSP_Z && UNSP_C
+ if((UNSP_REG(SR) & (UNSP_Z | UNSP_C)) == UNSP_C)
{
- m_core->m_icount -= 4;
- add_lpc((op1 == 0) ? opimm : (0 - opimm));
+ m_icount -= 4;
+ add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
}
else
{
- m_core->m_icount -= 2;
+ m_icount -= 2;
}
return;
case 10: // JLE
- if(m_core->m_r[REG_SR] & (UNSP_Z | UNSP_S))
+ if(UNSP_REG(SR) & (UNSP_Z | UNSP_S))
{
- m_core->m_icount -= 4;
- add_lpc((op1 == 0) ? opimm : (0 - opimm));
+ m_icount -= 4;
+ add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
}
else
{
- m_core->m_icount -= 2;
+ m_icount -= 2;
}
return;
case 11: // JG
- if(!(m_core->m_r[REG_SR] & (UNSP_Z | UNSP_S)))
+ if(!(UNSP_REG(SR) & (UNSP_Z | UNSP_S)))
{
- m_core->m_icount -= 4;
- add_lpc((op1 == 0) ? opimm : (0 - opimm));
+ m_icount -= 4;
+ add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
}
else
{
- m_core->m_icount -= 2;
+ m_icount -= 2;
}
return;
case 14: // JMP
- add_lpc((op1 == 0) ? opimm : (0 - opimm));
- m_core->m_icount -= 4;
+ add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM));
+ m_icount -= 4;
return;
default:
unimplemented_opcode(op);
@@ -513,68 +446,69 @@ inline void unsp_device::execute_one(const uint16_t op)
}
else if (lower_op == 0x2d) // Push
{
- r0 = opn;
- r1 = opa;
- m_core->m_icount -= 4 + 2 * r0;
+ r0 = OPN;
+ r1 = OPA;
+ m_icount -= 4 + 2 * r0;
while (r0--)
{
- push(m_core->m_r[r1--], &m_core->m_r[opb]);
+ push(UNSP_REG_I(r1--), &UNSP_REG_I(OPB));
}
return;
}
- else if (lower_op == 0x29)
+ else if (lower_op == 0x29) // Pop
{
if (op == 0x9a98) // reti
{
- m_core->m_icount -= 8;
- m_core->m_r[REG_SR] = pop(&m_core->m_r[REG_SP]);
- m_core->m_r[REG_PC] = pop(&m_core->m_r[REG_SP]);
+ m_icount -= 8;
+ UNSP_REG(SR) = pop(&UNSP_REG(SP));
+ UNSP_REG(PC) = pop(&UNSP_REG(SP));
- if(m_core->m_fiq)
+ if(m_fiq)
{
- m_core->m_fiq = 0;
- m_core->m_saved_sb[2] = m_core->m_sb;
- m_core->m_sb = m_core->m_saved_sb[m_core->m_irq ? 1 : 0];
+ m_fiq = false;
+ m_saved_sb[2] = m_sb;
+ m_sb = m_saved_sb[m_irq ? 1 : 0];
}
- else if(m_core->m_irq)
+ else if(m_irq)
{
- m_core->m_irq = 0;
- m_core->m_saved_sb[1] = m_core->m_sb;
- m_core->m_sb = m_core->m_saved_sb[0];
+ m_irq = false;
+ m_saved_sb[1] = m_sb;
+ m_sb = m_saved_sb[0];
}
- m_core->m_curirq = 0;
+ m_curirq = 0;
+
check_irqs();
return;
}
- else // pop
+ else
{
- r0 = opn;
- r1 = opa;
- m_core->m_icount -= 4 + 2 * r0;
+ r0 = OPN;
+ r1 = OPA;
+ m_icount -= 4 + 2 * r0;
while (r0--)
{
- m_core->m_r[++r1] = pop(&m_core->m_r[opb]);
+ UNSP_REG_I(++r1) = pop(&UNSP_REG_I(OPB));
}
return;
}
}
- else if (op0 == 0xf)
+ else if (OP0 == 0xf)
{
- switch (op1)
+ switch (OP1)
{
case 0x00: // Multiply, Unsigned * Signed
- if(opn == 1 && opa != 7)
+ if(OPN == 1 && OPA != 7)
{
- m_core->m_icount -= 12;
- lres = m_core->m_r[opa] * m_core->m_r[opb];
- if(m_core->m_r[opb] & 0x8000)
+ m_icount -= 12;
+ lres = UNSP_REG_I(OPA) * UNSP_REG_I(OPB);
+ if(UNSP_REG_I(OPB) & 0x8000)
{
- lres -= m_core->m_r[opa] << 16;
+ lres -= UNSP_REG_I(OPA) << 16;
}
- m_core->m_r[REG_R4] = lres >> 16;
- m_core->m_r[REG_R3] = (uint16_t)lres;
+ UNSP_REG(R4) = lres >> 16;
+ UNSP_REG(R3) = (uint16_t)lres;
}
else
{
@@ -583,16 +517,16 @@ inline void unsp_device::execute_one(const uint16_t op)
return;
case 0x01: // Call
- if(!(opa & 1))
+ if(!(OPA & 1))
{
- m_core->m_icount -= 9;
+ m_icount -= 9;
r1 = read16(UNSP_LPC);
add_lpc(1);
- push(m_core->m_r[REG_PC], &m_core->m_r[REG_SP]);
- push(m_core->m_r[REG_SR], &m_core->m_r[REG_SP]);
- m_core->m_r[REG_PC] = r1;
- m_core->m_r[REG_SR] &= 0xffc0;
- m_core->m_r[REG_SR] |= op & 0x3f;
+ push(UNSP_REG(PC), &UNSP_REG(SP));
+ push(UNSP_REG(SR), &UNSP_REG(SP));
+ UNSP_REG(PC) = r1;
+ UNSP_REG(SR) &= 0xffc0;
+ UNSP_REG(SR) |= OPIMM;
}
else
{
@@ -601,12 +535,12 @@ inline void unsp_device::execute_one(const uint16_t op)
return;
case 0x02: // Far Jump
- if (opa == 7)
+ if (OPA == 7)
{
- m_core->m_icount -= 5;
- m_core->m_r[REG_PC] = read16(UNSP_LPC);
- m_core->m_r[REG_SR] &= 0xffc0;
- m_core->m_r[REG_SR] |= op & 0x3f;
+ m_icount -= 5;
+ UNSP_REG(PC) = read16(UNSP_LPC);
+ UNSP_REG(SR) &= 0xffc0;
+ UNSP_REG(SR) |= OPIMM;
}
else
{
@@ -615,20 +549,20 @@ inline void unsp_device::execute_one(const uint16_t op)
return;
case 0x04: // Multiply, Signed * Signed
- if(opn == 1 && opa != 7)
+ if(OPN == 1 && OPA != 7)
{
- m_core->m_icount -= 12;
- lres = m_core->m_r[opa] * m_core->m_r[opb];
- if(m_core->m_r[opb] & 0x8000)
+ m_icount -= 12;
+ lres = UNSP_REG_I(OPA) * UNSP_REG_I(OPB);
+ if(UNSP_REG_I(OPB) & 0x8000)
{
- lres -= m_core->m_r[opa] << 16;
+ lres -= UNSP_REG_I(OPA) << 16;
}
- if(m_core->m_r[opa] & 0x8000)
+ if(UNSP_REG_I(OPA) & 0x8000)
{
- lres -= m_core->m_r[opb] << 16;
+ lres -= UNSP_REG_I(OPB) << 16;
}
- m_core->m_r[REG_R4] = lres >> 16;
- m_core->m_r[REG_R3] = (uint16_t)lres;
+ UNSP_REG(R4) = lres >> 16;
+ UNSP_REG(R3) = (uint16_t)lres;
}
else
{
@@ -637,36 +571,36 @@ inline void unsp_device::execute_one(const uint16_t op)
return;
case 0x05: // Interrupt flags
- m_core->m_icount -= 2;
- switch(op & 0x3f)
+ m_icount -= 2;
+ switch(OPIMM)
{
case 0:
- m_core->m_enable_irq = 0;
- m_core->m_enable_fiq = 0;
+ m_enable_irq = false;
+ m_enable_fiq = false;
break;
case 1:
- m_core->m_enable_irq = 1;
- m_core->m_enable_fiq = 0;
+ m_enable_irq = true;
+ m_enable_fiq = false;
break;
case 2:
- m_core->m_enable_irq = 0;
- m_core->m_enable_fiq = 1;
+ m_enable_irq = false;
+ m_enable_fiq = true;
break;
case 3:
- m_core->m_enable_irq = 1;
- m_core->m_enable_fiq = 1;
+ m_enable_irq = true;
+ m_enable_fiq = true;
break;
case 8: // irq off
- m_core->m_enable_irq = 0;
+ m_enable_irq = false;
break;
case 9: // irq on
- m_core->m_enable_irq = 1;
+ m_enable_irq = true;
break;
case 12: // fiq off
- m_core->m_enable_fiq = 0;
+ m_enable_fiq = false;
break;
case 14: // fiq on
- m_core->m_enable_fiq = 1;
+ m_enable_fiq = true;
break;
case 37: // nop
break;
@@ -684,61 +618,65 @@ inline void unsp_device::execute_one(const uint16_t op)
// At this point, we should be dealing solely with ALU ops.
- r0 = m_core->m_r[opa];
+ r0 = UNSP_REG_I(OPA);
- switch (op1)
+ switch (OP1)
{
case 0x00: // r, [bp+imm6]
- m_core->m_icount -= 6;
+ m_icount -= 6;
- r2 = (uint16_t)(m_core->m_r[REG_BP] + (op & 0x3f));
- if (op0 != 0x0d)
+ r2 = (uint16_t)(UNSP_REG(BP) + OPIMM);
+ if (OP0 != 0x0d)
r1 = read16(r2);
break;
case 0x01: // r, imm6
- m_core->m_icount -= 2;
+ m_icount -= 2;
- r1 = op & 0x3f;
+ r1 = OPIMM;
break;
case 0x03: // Indirect
{
- m_core->m_icount -= (opa == 7 ? 7 : 6);
+ m_icount -= 6;
+ if (OPA == 7)
+ {
+ m_icount -= 1;
+ }
- const uint8_t lsbits = opn & 3;
- if (opn & 4)
+ const uint8_t lsbits = OPN & 3;
+ const uint8_t opb = OPB;
+ if (OPN & 4)
{
switch (lsbits)
{
- case 0: // r, [<ds:>r]
+ case 0: // r, [r]
r2 = UNSP_LREG_I(opb);
- if (op0 != 0x0d)
+ if (OP0 != 0x0d)
r1 = read16(r2);
break;
-
case 1: // r, [<ds:>r--]
r2 = UNSP_LREG_I(opb);
- if (op0 != 0x0d)
+ if (OP0 != 0x0d)
r1 = read16(r2);
- m_core->m_r[opb] = (uint16_t)(m_core->m_r[opb] - 1);
- if (m_core->m_r[opb] == 0xffff)
- m_core->m_r[REG_SR] -= 0x0400;
+ UNSP_REG_I(opb)--;
+ if (UNSP_REG_I(opb) == 0xffff)
+ UNSP_REG(SR) -= 0x0400;
break;
case 2: // r, [<ds:>r++]
r2 = UNSP_LREG_I(opb);
- if (op0 != 0x0d)
+ if (OP0 != 0x0d)
r1 = read16(r2);
- m_core->m_r[opb] = (uint16_t)(m_core->m_r[opb] + 1);
- if (m_core->m_r[opb] == 0x0000)
- m_core->m_r[REG_SR] += 0x0400;
+ UNSP_REG_I(opb)++;
+ if (UNSP_REG_I(opb) == 0x0000)
+ UNSP_REG(SR) += 0x0400;
break;
case 3: // r, [<ds:>++r]
- m_core->m_r[opb] = (uint16_t)(m_core->m_r[opb] + 1);
- if (m_core->m_r[opb] == 0x0000)
- m_core->m_r[REG_SR] += 0x0400;
+ UNSP_REG_I(opb)++;
+ if (UNSP_REG_I(opb) == 0x0000)
+ UNSP_REG(SR) += 0x0400;
r2 = UNSP_LREG_I(opb);
- if (op0 != 0x0d)
+ if (OP0 != 0x0d)
r1 = read16(r2);
break;
default:
@@ -750,26 +688,26 @@ inline void unsp_device::execute_one(const uint16_t op)
switch (lsbits)
{
case 0: // r, [r]
- r2 = m_core->m_r[opb];
- if (op0 != 0x0d)
+ r2 = UNSP_REG_I(opb);
+ if (OP0 != 0x0d)
r1 = read16(r2);
break;
case 1: // r, [r--]
- r2 = m_core->m_r[opb];
- if (op0 != 0x0d)
+ r2 = UNSP_REG_I(opb);
+ if (OP0 != 0x0d)
r1 = read16(r2);
- m_core->m_r[opb] = (uint16_t)(m_core->m_r[opb] - 1);
+ UNSP_REG_I(opb)--;
break;
case 2: // r, [r++]
- r2 = m_core->m_r[opb];
- if (op0 != 0x0d)
+ r2 = UNSP_REG_I(opb);
+ if (OP0 != 0x0d)
r1 = read16(r2);
- m_core->m_r[opb] = (uint16_t)(m_core->m_r[opb] + 1);
+ UNSP_REG_I(opb)++;
break;
case 3: // r, [++r]
- m_core->m_r[opb] = (uint16_t)(m_core->m_r[opb] + 1);
- r2 = m_core->m_r[opb];
- if (op0 != 0x0d)
+ UNSP_REG_I(opb)++;
+ r2 = UNSP_REG_I(opb);
+ if (OP0 != 0x0d)
r1 = read16(r2);
break;
default:
@@ -780,48 +718,73 @@ inline void unsp_device::execute_one(const uint16_t op)
}
case 0x04: // 16-bit ops
- switch (opn)
+ switch (OPN)
{
case 0x00: // r
- m_core->m_icount -= (opa == 7 ? 5 : 3);
- r1 = m_core->m_r[opb];
+ m_icount -= 3;
+ if (OPA == 7)
+ {
+ m_icount -= 2;
+ }
+
+ r1 = UNSP_REG_I(OPB);
break;
case 0x01: // imm16
- m_core->m_icount -= (opa == 7 ? 5 : 4);
- r0 = m_core->m_r[opb];
+ m_icount -= 4;
+ if (OPA == 7)
+ {
+ m_icount -= 1;
+ }
+
+ r0 = UNSP_REG_I(OPB);
r1 = read16(UNSP_LPC);
add_lpc(1);
break;
case 0x02: // [imm16]
- m_core->m_icount -= (opa == 7 ? 8 : 7);
- r0 = m_core->m_r[opb];
+ m_icount -= 7;
+ if (OPA == 7)
+ {
+ m_icount -= 1;
+ }
+
+ r0 = UNSP_REG_I(OPB);
r2 = read16(UNSP_LPC);
add_lpc(1);
- if (op0 != 0x0d)
+ if (OP0 != 0x0d)
{
r1 = read16(r2);
}
break;
case 0x03: // store [imm16], r
- m_core->m_icount -= (opa == 7 ? 8 : 7);
+ m_icount -= 7;
+ if (OPA == 7)
+ {
+ m_icount -= 1;
+ }
+
r1 = r0;
- r0 = m_core->m_r[opb];
+ r0 = UNSP_REG_I(OPB);
r2 = read16(UNSP_LPC);
add_lpc(1);
break;
default: // Shifted ops
{
- m_core->m_icount -= (opa == 7 ? 5 : 3);
- uint32_t shift = (m_core->m_r[opb] << 4) | m_core->m_sb;
+ m_icount -= 3;
+ if (OPA == 7)
+ {
+ m_icount -= 2;
+ }
+
+ uint32_t shift = (UNSP_REG_I(OPB) << 4) | m_sb;
if (shift & 0x80000)
shift |= 0xf00000;
- shift >>= (opn - 3);
- m_core->m_sb = shift & 0x0f;
+ shift >>= (OPN - 3);
+ m_sb = shift & 0x0f;
r1 = (uint16_t)(shift >> 4);
break;
}
@@ -829,116 +792,99 @@ inline void unsp_device::execute_one(const uint16_t op)
break;
case 0x05: // More shifted ops
- m_core->m_icount -= (opa == 7 ? 5 : 3);
+ m_icount -= 3;
+ if (OPA == 7)
+ {
+ m_icount -= 2;
+ }
- if (opn & 4) // Shift right
+ if (OPN & 4) // Shift right
{
- const uint32_t shift = ((m_core->m_r[opb] << 4) | m_core->m_sb) >> (opn - 3);
- m_core->m_sb = shift & 0x0f;
+ const uint32_t shift = ((UNSP_REG_I(OPB) << 4) | m_sb) >> (OPN - 3);
+ m_sb = shift & 0x0f;
r1 = (uint16_t)(shift >> 4);
}
else // Shift left
{
- const uint32_t shift = ((m_core->m_sb << 16) | m_core->m_r[opb]) << (opn + 1);
- m_core->m_sb = (shift >> 16) & 0x0f;
+ const uint32_t shift = ((m_sb << 16) | UNSP_REG_I(OPB)) << (OPN + 1);
+ m_sb = (shift >> 16) & 0x0f;
r1 = (uint16_t)shift;
}
break;
case 0x06: // Rotated ops
{
- m_core->m_icount -= (opa == 7 ? 5 : 3);
+ m_icount -= 3;
+ if (OPA == 7)
+ {
+ m_icount -= 2;
+ }
- uint32_t shift = (((m_core->m_sb << 16) | m_core->m_r[opb]) << 4) | m_core->m_sb;
- if (opn & 4) // Rotate right
+ uint32_t shift = (((m_sb << 16) | UNSP_REG_I(OPB)) << 4) | m_sb;
+ if (OPN & 4) // Rotate right
{
- shift >>= (opn - 3);
- m_core->m_sb = shift & 0x0f;
+ shift >>= (OPN - 3);
+ m_sb = shift & 0x0f;
}
else
{
- shift <<= (opn + 1);
- m_core->m_sb = (shift >> 20) & 0x0f;
+ shift <<= (OPN + 1);
+ m_sb = (shift >> 20) & 0x0f;
}
r1 = (uint16_t)(shift >> 4);
break;
}
case 0x07: // Direct 8
- m_core->m_icount -= (opa == 7 ? 6 : 5);
- r2 = op & 0x3f;
- r1 = read16(r2);
+ m_icount -= 5;
+ if (OPA == 7)
+ {
+ m_icount -= 1;
+ }
+
+ r2 = OPIMM;
+ r1 = read16(OPIMM);
break;
default:
break;
}
- switch (op0)
+ switch (OP0)
{
case 0x00: // Add
- {
lres = r0 + r1;
- if (opa != 7)
- update_nzsc(lres, r0, r1);
break;
- }
case 0x01: // Add w/ carry
- {
- uint32_t c = (m_core->m_r[REG_SR] & UNSP_C) ? 1 : 0;
- lres = r0 + r1 + c;
- if (opa != 7)
- update_nzsc(lres, r0, r1);
+ lres = r0 + r1;
+ if(UNSP_REG(SR) & UNSP_C)
+ lres++;
break;
- }
case 0x02: // Subtract
- lres = r0 + (uint16_t)(~r1) + uint32_t(1);
- if (opa != 7)
- update_nzsc(lres, r0, ~r1);
+ case 0x04: // Compare
+ lres = r0 + (uint16_t)(~r1) + 1;
break;
case 0x03: // Subtract w/ carry
- {
- uint32_t c = (m_core->m_r[REG_SR] & UNSP_C) ? 1 : 0;
- lres = r0 + (uint16_t)(~r1) + c;
- if (opa != 7)
- update_nzsc(lres, r0, ~r1);
+ lres = r0 + (uint16_t)(~r1);
+ if(UNSP_REG(SR) & UNSP_C)
+ lres++;
break;
- }
- case 0x04: // Compare
- lres = r0 + (uint16_t)(~r1) + uint32_t(1);
- if (opa != 7)
- update_nzsc(lres, r0, ~r1);
- return;
case 0x06: // Negate
lres = -r1;
- if (opa != 7)
- update_nz(lres);
break;
case 0x08: // XOR
lres = r0 ^ r1;
- if (opa != 7)
- update_nz(lres);
break;
case 0x09: // Load
lres = r1;
- if (opa != 7)
- update_nz(lres);
break;
case 0x0a: // OR
lres = r0 | r1;
- if (opa != 7)
- update_nz(lres);
break;
case 0x0b: // AND
- lres = r0 & r1;
- if (opa != 7)
- update_nz(lres);
- break;
case 0x0c: // Test
lres = r0 & r1;
- if (opa != 7)
- update_nz(lres);
- return;
+ break;
case 0x0d: // Store
write16(r2, r0);
return;
@@ -947,33 +893,34 @@ inline void unsp_device::execute_one(const uint16_t op)
return;
}
- if (op1 == 0x04 && opn == 0x03) // store [imm16], r
+ if (OP0 != 0x0d && OPA != 7) // If not a store opcode and not updating the PC, update negative/zero flags.
+ {
+ update_nz(lres);
+ }
+
+ if (OP0 < 0x05 && OPA != 7) // If Add, Add w/ Carry, Subtract, Subtract w/ Carry, Compare, and not updating the PC, update sign/carry flags.
+ update_sc(lres, r0, r1);
+
+ if (OP0 == 0x04 || OP0 == 0x0c) // Compare and Test don't write back results.
+ return;
+
+ if (OP1 == 0x04 && OPN == 0x03) // store [imm16], r
write16(r2, lres);
else
- m_core->m_r[opa] = (uint16_t)lres;
+ UNSP_REG_I(OPA) = lres;
}
void unsp_device::execute_run()
{
- if (m_enable_drc)
- {
- execute_run_drc();
- return;
- }
-
#if UNSP_LOG_OPCODES
unsp_disassembler dasm;
#endif
- while (m_core->m_icount >= 0)
+ while (m_icount > 0)
{
debugger_instruction_hook(UNSP_LPC);
const uint32_t op = read16(UNSP_LPC);
-#if UNSP_LOG_REGS
- log_regs();
-#endif
-
#if UNSP_LOG_OPCODES
if (m_log_ops)
{
@@ -994,26 +941,16 @@ void unsp_device::execute_run()
/*****************************************************************************/
-void unsp_device::execute_set_input(int inputnum, int state)
-{
- set_state_unsynced(inputnum, state);
-}
-
-uint8_t unsp_device::get_csb()
-{
- return 1 << ((UNSP_LPC >> 20) & 3);
-}
-
-void unsp_device::set_state_unsynced(int inputnum, int state)
+void unsp_device::execute_set_input(int irqline, int state)
{
- m_core->m_sirq &= ~(1 << inputnum);
+ m_sirq &= ~(1 << irqline);
if(!state)
{
return;
}
- switch (inputnum)
+ switch (irqline)
{
case UNSP_IRQ0_LINE:
case UNSP_IRQ1_LINE:
@@ -1024,20 +961,9 @@ void unsp_device::set_state_unsynced(int inputnum, int state)
case UNSP_IRQ6_LINE:
case UNSP_IRQ7_LINE:
case UNSP_FIQ_LINE:
- m_core->m_sirq |= (1 << inputnum);
+ m_sirq |= (1 << irqline);
break;
case UNSP_BRK_LINE:
break;
}
}
-
-uint16_t unsp_device::get_ds()
-{
- return (m_core->m_r[REG_SR] >> 10) & 0x3f;
-}
-
-void unsp_device::set_ds(uint16_t ds)
-{
- m_core->m_r[REG_SR] &= 0x03ff;
- m_core->m_r[REG_SR] |= (ds & 0x3f) << 10;
-}
diff --git a/src/devices/cpu/unsp/unsp.h b/src/devices/cpu/unsp/unsp.h
index 460198451fa..ad3f8250785 100644
--- a/src/devices/cpu/unsp/unsp.h
+++ b/src/devices/cpu/unsp/unsp.h
@@ -17,32 +17,7 @@
#pragma once
-#include "cpu/drcfe.h"
-#include "cpu/drcuml.h"
-#include "cpu/drcumlsh.h"
-
-/***************************************************************************
- CONSTANTS
-***************************************************************************/
-
-/* map variables */
-#define MAPVAR_PC M0
-#define MAPVAR_CYCLES M1
-
-#define SINGLE_INSTRUCTION_MODE (0)
-
-#define ENABLE_UNSP_DRC (1)
-
#define UNSP_LOG_OPCODES (0)
-#define UNSP_LOG_REGS (0)
-
-//**************************************************************************
-// TYPE DEFINITIONS
-//**************************************************************************
-
-class unsp_frontend;
-
-// ======================> unsp_device
enum
{
@@ -61,7 +36,7 @@ enum
UNSP_FIQ_EN,
UNSP_IRQ,
UNSP_FIQ,
-#if UNSP_LOG_OPCODES || UNSP_LOG_REGS
+#if UNSP_LOG_OPCODES
UNSP_SB,
UNSP_LOG_OPS
#else
@@ -87,38 +62,16 @@ enum
class unsp_device : public cpu_device
{
- friend class unsp_frontend;
-
public:
// construction/destruction
unsp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
- // HACK: IRQ line state can only be modified directly by hardware on-board the SPG SoC itself.
- // Therefore, to avoid an unnecessary scheduler sync when the external spg2xx_device sets or
- // clears an interrupt line, we provide this direct accessor.
- // A more correct but longer-term solution will be to move spg2xx_device to be internal to
- // a subclass of unsp_device rather than its own standalone device.
- void set_state_unsynced(int inputnum, int state);
-
- uint8_t get_csb();
-
- void set_ds(uint16_t ds);
- uint16_t get_ds();
-
- inline void ccfunc_unimplemented();
- void invalidate_cache();
-
-#if UNSP_LOG_REGS
- void log_regs();
- void log_write(uint32_t addr, uint32_t data);
- void cfunc_log_write();
-#endif
+ void set_timer_interval(int timer, uint32_t interval);
protected:
// device-level overrides
virtual void device_start() override;
virtual void device_reset() override;
- virtual void device_stop() override;
// device_execute_interface overrides
virtual uint32_t execute_min_cycles() const override { return 5; }
@@ -139,69 +92,27 @@ protected:
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
private:
- // compilation boundaries -- how far back/forward does the analysis extend?
- enum : uint32_t
- {
- COMPILE_BACKWARDS_BYTES = 128,
- COMPILE_FORWARDS_BYTES = 512,
- COMPILE_MAX_INSTRUCTIONS = (COMPILE_BACKWARDS_BYTES / 4) + (COMPILE_FORWARDS_BYTES / 4),
- COMPILE_MAX_SEQUENCE = 64
- };
-
- // exit codes
- enum : int
- {
- EXECUTE_OUT_OF_CYCLES = 0,
- EXECUTE_MISSING_CODE = 1,
- EXECUTE_UNMAPPED_CODE = 2,
- EXECUTE_RESET_CACHE = 3
- };
-
- enum : uint32_t
- {
- REG_SP = 0,
- REG_R1,
- REG_R2,
- REG_R3,
- REG_R4,
- REG_BP,
- REG_SR,
- REG_PC
- };
-
void add_lpc(const int32_t offset);
inline void execute_one(const uint16_t op);
- struct internal_unsp_state
- {
- uint32_t m_r[8];
- uint32_t m_enable_irq;
- uint32_t m_enable_fiq;
- uint32_t m_irq;
- uint32_t m_fiq;
- uint32_t m_curirq;
- uint32_t m_sirq;
- uint32_t m_sb;
- uint32_t m_saved_sb[3];
-
- uint32_t m_arg0;
- uint32_t m_arg1;
- uint32_t m_jmpdest;
+ address_space_config m_program_config;
- int m_icount;
- };
+ uint16_t m_r[16];
+ bool m_enable_irq;
+ bool m_enable_fiq;
+ bool m_irq;
+ bool m_fiq;
+ uint16_t m_curirq;
+ uint16_t m_sirq;
+ uint8_t m_sb;
+ uint8_t m_saved_sb[3];
- address_space_config m_program_config;
address_space *m_program;
- std::function<u16 (offs_t)> m_pr16;
- std::function<const void * (offs_t)> m_prptr;
-
- /* core state */
- internal_unsp_state *m_core;
+ int m_icount;
uint32_t m_debugger_temp;
-#if UNSP_LOG_OPCODES || UNSP_LOG_REGS
+#if UNSP_LOG_OPCODES
uint32_t m_log_ops;
#endif
@@ -209,70 +120,12 @@ private:
inline uint16_t read16(uint32_t address);
inline void write16(uint32_t address, uint16_t data);
inline void update_nz(uint32_t value);
- inline void update_nzsc(uint32_t value, uint16_t r0, uint16_t r1);
- inline void push(uint32_t value, uint32_t *reg);
- inline uint16_t pop(uint32_t *reg);
+ inline void update_sc(uint32_t value, uint16_t r0, uint16_t r1);
+ inline void push(uint16_t value, uint16_t *reg);
+ inline uint16_t pop(uint16_t *reg);
inline void trigger_fiq();
inline void trigger_irq(int line);
inline void check_irqs();
-
- drc_cache m_cache;
- std::unique_ptr<drcuml_state> m_drcuml;
- std::unique_ptr<unsp_frontend> m_drcfe;
- uint32_t m_drcoptions;
- uint8_t m_cache_dirty;
-
- uml::parameter m_regmap[16];
- uml::code_handle *m_entry;
- uml::code_handle *m_nocode;
- uml::code_handle *m_out_of_cycles;
- uml::code_handle *m_check_interrupts;
- uml::code_handle *m_trigger_fiq;
- uml::code_handle *m_trigger_irq;
-
- uml::code_handle *m_mem_read;
- uml::code_handle *m_mem_write;
-
- bool m_enable_drc;
-
- /* internal compiler state */
- struct compiler_state
- {
- compiler_state(compiler_state const &) = delete;
- compiler_state &operator=(compiler_state const &) = delete;
-
- uint32_t m_cycles; /* accumulated cycles */
- uml::code_label m_labelnum; /* index for local labels */
- };
-
- void execute_run_drc();
- void flush_drc_cache();
- void code_flush_cache();
- void code_compile_block(offs_t pc);
- void load_fast_iregs(drcuml_block &block);
- void save_fast_iregs(drcuml_block &block);
-
- void static_generate_entry_point();
- void static_generate_nocode_handler();
- void static_generate_out_of_cycles();
- void static_generate_check_interrupts();
- void static_generate_trigger_fiq();
- void static_generate_trigger_irq();
- void static_generate_memory_accessor(bool iswrite, const char *name, uml::code_handle *&handleptr);
-
- void generate_branch(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
- void generate_check_cycles(drcuml_block &block, compiler_state &compiler, uml::parameter param);
- void generate_checksum_block(drcuml_block &block, compiler_state &compiler, const opcode_desc *seqhead, const opcode_desc *seqlast);
- void generate_sequence_instruction(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
- void generate_add_lpc(drcuml_block &block, int32_t offset);
- void generate_update_nzsc(drcuml_block &block);
- void generate_update_nz(drcuml_block &block);
- void log_add_disasm_comment(drcuml_block &block, uint32_t pc, uint32_t op);
- bool generate_opcode(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc);
-
-#if UNSP_LOG_REGS
- FILE *m_log_file;
-#endif
};
diff --git a/src/devices/cpu/unsp/unspdefs.h b/src/devices/cpu/unsp/unspdefs.h
deleted file mode 100644
index 382e25a0dac..00000000000
--- a/src/devices/cpu/unsp/unspdefs.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Ryan Holtz
-
-#ifndef MAME_CPU_UNSP_UNSPDEFS_H
-#define MAME_CPU_UNSP_UNSPDEFS_H
-
-#pragma once
-
-#define UNSP_LPC (((m_core->m_r[REG_SR] & 0x3f) << 16) | m_core->m_r[REG_PC])
-#define UNSP_LREG_I(reg) (((m_core->m_r[REG_SR] << 6) & 0x3f0000) | m_core->m_r[reg])
-
-#define UNSP_N 0x0200
-#define UNSP_Z 0x0100
-#define UNSP_S 0x0080
-#define UNSP_C 0x0040
-
-#define UNSP_N_SHIFT 9
-#define UNSP_Z_SHIFT 8
-#define UNSP_S_SHIFT 7
-#define UNSP_C_SHIFT 6
-
-#endif // MAME_CPU_UNSP_UNSPDEFS_H
diff --git a/src/devices/cpu/unsp/unspdrc.cpp b/src/devices/cpu/unsp/unspdrc.cpp
deleted file mode 100644
index 3ee90c8c1c9..00000000000
--- a/src/devices/cpu/unsp/unspdrc.cpp
+++ /dev/null
@@ -1,1316 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Ryan Holtz
-
-#include "emu.h"
-#include "unsp.h"
-#include "unspfe.h"
-#include "unspdefs.h"
-
-void unsp_device::invalidate_cache()
-{
- m_cache_dirty = true;
-}
-
-void unsp_device::execute_run_drc()
-{
- int execute_result;
-
- /* reset the cache if dirty */
- if (m_cache_dirty)
- {
- code_flush_cache();
- m_cache_dirty = false;
- }
-
-
- /* execute */
- do
- {
- /* run as much as we can */
- execute_result = m_drcuml->execute(*m_entry);
-
- /* if we need to recompile, do it */
- if (execute_result == EXECUTE_MISSING_CODE)
- {
- code_compile_block(UNSP_LPC);
- }
- else if (execute_result == EXECUTE_UNMAPPED_CODE)
- {
- fatalerror("Attempted to execute unmapped code at PC=%08X\n", UNSP_LPC);
- }
- else if (execute_result == EXECUTE_RESET_CACHE)
- {
- code_flush_cache();
- }
- } while (execute_result != EXECUTE_OUT_OF_CYCLES);
-}
-
-
-/***************************************************************************
- C FUNCTION CALLBACKS
-***************************************************************************/
-
-/*-------------------------------------------------
- cfunc_unimplemented - handler for
- unimplemented opcdes
--------------------------------------------------*/
-
-inline void unsp_device::ccfunc_unimplemented()
-{
- fatalerror("PC=%08X: Unimplemented op %04x\n", UNSP_LPC, (uint16_t)m_core->m_arg0);
-}
-
-static void cfunc_unimplemented(void *param)
-{
- ((unsp_device *)param)->ccfunc_unimplemented();
-}
-
-#if UNSP_LOG_REGS
-void unsp_device::cfunc_log_write()
-{
- log_write(m_core->m_arg0, m_core->m_arg1);
-}
-
-static void cfunc_log_regs(void *param)
-{
- ((unsp_device *)param)->log_regs();
-}
-
-static void ccfunc_log_write(void *param)
-{
- ((unsp_device *)param)->cfunc_log_write();
-}
-#endif
-
-/***************************************************************************
- CACHE MANAGEMENT
-***************************************************************************/
-
-/*-------------------------------------------------
- flush_drc_cache - outward-facing accessor to
- code_flush_cache
--------------------------------------------------*/
-
-void unsp_device::flush_drc_cache()
-{
- if (!m_enable_drc)
- return;
- m_cache_dirty = true;
-}
-
-/*-------------------------------------------------
- code_flush_cache - flush the cache and
- regenerate static code
--------------------------------------------------*/
-
-void unsp_device::code_flush_cache()
-{
- /* empty the transient cache contents */
- m_drcuml->reset();
-
- try
- {
- /* generate the entry point and out-of-cycles handlers */
- static_generate_entry_point();
- static_generate_nocode_handler();
- static_generate_out_of_cycles();
-
- static_generate_memory_accessor(false, "read", m_mem_read);
- static_generate_memory_accessor(true, "write", m_mem_write);
- static_generate_trigger_fiq();
- static_generate_trigger_irq();
- static_generate_check_interrupts();
- }
-
- catch (drcuml_block::abort_compilation &)
- {
- fatalerror("Unable to generate static u'nSP code\n"); fflush(stdout);
- }
-}
-
-/*-------------------------------------------------
- code_compile_block - compile a block of the
- given mode at the specified pc
--------------------------------------------------*/
-
-void unsp_device::code_compile_block(offs_t pc)
-{
- compiler_state compiler = { 0 };
- const opcode_desc *seqhead, *seqlast;
- bool override = false;
-
- g_profiler.start(PROFILER_DRC_COMPILE);
-
- /* get a description of this sequence */
- const opcode_desc *desclist = m_drcfe->describe_code(pc);
-
- bool succeeded = false;
- while (!succeeded)
- {
- try
- {
- /* start the block */
- drcuml_block &block(m_drcuml->begin_block(1024*8));
-
- /* loop until we get through all instruction sequences */
- for (seqhead = desclist; seqhead != nullptr; seqhead = seqlast->next())
- {
- const opcode_desc *curdesc;
- uint32_t nextpc;
-
- /* add a code log entry */
- if (m_drcuml->logging())
- block.append_comment("-------------------------");
-
- /* determine the last instruction in this sequence */
- for (seqlast = seqhead; seqlast != nullptr; seqlast = seqlast->next())
- if (seqlast->flags & OPFLAG_END_SEQUENCE)
- break;
- assert(seqlast != nullptr);
-
- /* if we don't have a hash for this mode/pc, or if we are overriding all, add one */
- if (override || !m_drcuml->hash_exists(0, seqhead->pc))
- UML_HASH(block, 0, seqhead->pc);
-
- /* if we already have a hash, and this is the first sequence, assume that we */
- /* are recompiling due to being out of sync and allow future overrides */
- else if (seqhead == desclist)
- {
- override = true;
- UML_HASH(block, 0, seqhead->pc);
- }
-
- /* otherwise, redispatch to that fixed PC and skip the rest of the processing */
- else
- {
- UML_LABEL(block, seqhead->pc | 0x80000000);
- UML_HASHJMP(block, 0, seqhead->pc, *m_nocode);
- continue;
- }
-
- /* validate this code block if we're not pointing into ROM */
- if (m_program->get_write_ptr(seqhead->physpc) != nullptr)
- generate_checksum_block(block, compiler, seqhead, seqlast);
-
- /* label this instruction, if it may be jumped to locally */
- if (seqhead->flags & OPFLAG_IS_BRANCH_TARGET)
- UML_LABEL(block, seqhead->pc | 0x80000000);
-
- /* iterate over instructions in the sequence and compile them */
- for (curdesc = seqhead; curdesc != seqlast->next(); curdesc = curdesc->next())
- {
- generate_check_cycles(block, compiler, curdesc->pc + curdesc->length);
- generate_sequence_instruction(block, compiler, curdesc);
- UML_CALLH(block, *m_check_interrupts);
- }
-
- nextpc = seqlast->pc + seqlast->length;
-
- /* if the last instruction can change modes, use a variable mode; otherwise, assume the same mode */
- if (seqlast->next() == nullptr || seqlast->next()->pc != nextpc)
- {
- UML_HASHJMP(block, 0, nextpc, *m_nocode); // hashjmp <mode>,nextpc,nocode
- }
- }
-
- /* end the sequence */
- block.end();
- g_profiler.stop();
- succeeded = true;
- }
- catch (drcuml_block::abort_compilation &)
- {
- code_flush_cache();
- }
- }
-}
-
-/***************************************************************************
- STATIC CODEGEN
-***************************************************************************/
-
-/*-------------------------------------------------
- alloc_handle - allocate a handle if not
- already allocated
--------------------------------------------------*/
-
-static inline void alloc_handle(drcuml_state &drcuml, uml::code_handle *&handleptr, const char *name)
-{
- if (!handleptr)
- handleptr = drcuml.handle_alloc(name);
-}
-
-/*-------------------------------------------------
- generate_entry_point - generate a
- static entry point
--------------------------------------------------*/
-
-void unsp_device::static_generate_entry_point()
-{
- /* begin generating */
- drcuml_block &block(m_drcuml->begin_block(32));
-
- /* forward references */
- alloc_handle(*m_drcuml, m_nocode, "nocode");
-
- alloc_handle(*m_drcuml, m_entry, "entry");
- UML_HANDLE(block, *m_entry);
-
- /* load fast integer registers */
- //load_fast_iregs(block);
-
- /* generate a hash jump via the current mode and PC */
- UML_ROLAND(block, I1, mem(&m_core->m_r[REG_SR]), 16, 0x003f0000);
- UML_OR(block, I1, I1, mem(&m_core->m_r[REG_PC]));
- UML_HASHJMP(block, 0, I1, *m_nocode);
- block.end();
-}
-
-
-/*-------------------------------------------------
- static_generate_nocode_handler - generate an
- exception handler for "out of code"
--------------------------------------------------*/
-
-void unsp_device::static_generate_nocode_handler()
-{
- /* begin generating */
- drcuml_block &block(m_drcuml->begin_block(10));
-
- /* generate a hash jump via the current mode and PC */
- alloc_handle(*m_drcuml, m_nocode, "nocode");
- UML_HANDLE(block, *m_nocode);
- UML_GETEXP(block, I0);
-
- UML_ROLINS(block, mem(&m_core->m_r[REG_SR]), I0, 16, 0x3f);
- UML_AND(block, mem(&m_core->m_r[REG_PC]), I0, 0x0000ffff);
- //save_fast_iregs(block);
- UML_EXIT(block, EXECUTE_MISSING_CODE);
-
- block.end();
-}
-
-
-/*-------------------------------------------------
- static_generate_out_of_cycles - generate an
- out of cycles exception handler
--------------------------------------------------*/
-
-void unsp_device::static_generate_out_of_cycles()
-{
- /* begin generating */
- drcuml_block &block(m_drcuml->begin_block(10));
-
- /* generate a hash jump via the current mode and PC */
- alloc_handle(*m_drcuml, m_out_of_cycles, "out_of_cycles");
- UML_HANDLE(block, *m_out_of_cycles);
- //save_fast_iregs(block);
- UML_EXIT(block, EXECUTE_OUT_OF_CYCLES);
-
- block.end();
-}
-
-/*------------------------------------------------------------------
- static_generate_memory_accessor
-------------------------------------------------------------------*/
-
-void unsp_device::static_generate_memory_accessor(bool iswrite, const char *name, uml::code_handle *&handleptr)
-{
- /* on entry, address is in I0; data for writes is in I1 */
- /* on exit, read result is in I1 */
-
- /* begin generating */
- drcuml_block &block(m_drcuml->begin_block(32));
-
- /* add a global entry for this */
- alloc_handle(*m_drcuml, handleptr, name);
- UML_HANDLE(block, *handleptr);
-
- if (iswrite)
- {
-#if UNSP_LOG_REGS
- UML_MOV(block, mem(&m_core->m_arg0), I0);
- UML_MOV(block, mem(&m_core->m_arg1), I1);
- UML_CALLC(block, ccfunc_log_write, this);
-#endif
- UML_WRITE(block, I0, I1, SIZE_WORD, SPACE_PROGRAM);
- }
- else
- UML_READ(block, I1, I0, SIZE_WORD, SPACE_PROGRAM);
- UML_RET(block);
-
- block.end();
-}
-
-
-
-/***************************************************************************
- CODE GENERATION
-***************************************************************************/
-
-void unsp_device::static_generate_check_interrupts()
-{
- uml::code_label test_loop = 1;
- uml::code_label found = 2;
- uml::code_label do_irq = 3;
-
- /* begin generating */
- drcuml_block &block(m_drcuml->begin_block(256));
-
- /* generate a hash jump via the current mode and PC */
- alloc_handle(*m_drcuml, m_check_interrupts, "check_interrupts");
- UML_HANDLE(block, *m_check_interrupts);
-
- UML_CMP(block, mem(&m_core->m_sirq), 0);
- UML_RETc(block, uml::COND_Z);
-
- UML_MOV(block, I2, 0);
- UML_MOV(block, I0, 1);
- UML_MOV(block, I1, mem(&m_core->m_sirq));
-
- UML_LABEL(block, test_loop);
- UML_TEST(block, I1, I0);
- UML_JMPc(block, uml::COND_NZ, found);
- UML_SHL(block, I0, I0, 1);
- UML_ADD(block, I2, I2, 1);
- UML_CMP(block, I0, 1 << 9);
- UML_JMPc(block, uml::COND_NE, test_loop);
- UML_RET(block);
-
- UML_LABEL(block, found);
- UML_CMP(block, I0, 1);
- UML_JMPc(block, uml::COND_NE, do_irq);
- UML_CALLH(block, *m_trigger_fiq);
- UML_RET(block);
-
- UML_LABEL(block, do_irq);
- UML_CALLH(block, *m_trigger_irq);
- UML_RET(block);
-
- block.end();
-}
-
-void unsp_device::static_generate_trigger_fiq()
-{
- /* begin generating */
- drcuml_block &block(m_drcuml->begin_block(256));
-
- /* generate a hash jump via the current mode and PC */
- alloc_handle(*m_drcuml, m_trigger_fiq, "trigger_fiq");
- UML_HANDLE(block, *m_trigger_fiq);
-
- UML_OR(block, I0, mem(&m_core->m_fiq), mem(&m_core->m_irq));
- UML_TEST(block, I0, 1);
- UML_RETc(block, uml::COND_NZ);
-
- UML_TEST(block, mem(&m_core->m_enable_fiq), 1);
- UML_RETc(block, uml::COND_Z);
-
- UML_MOV(block, mem(&m_core->m_fiq), 1);
-
- UML_MOV(block, I0, mem(&m_core->m_sb));
- UML_MOV(block, I1, mem(&m_core->m_irq));
- UML_STORE(block, (void*)m_core->m_saved_sb, I1, I0, SIZE_DWORD, SCALE_x4);
- UML_MOV(block, mem(&m_core->m_sb), mem(&m_core->m_saved_sb[2]));
-
- UML_MOV(block, I0, mem(&m_core->m_r[REG_SP]));
-
- UML_MOV(block, I1, mem(&m_core->m_r[REG_PC]));
- UML_CALLH(block, *m_mem_write);
- UML_SUB(block, I0, I0, 1);
-
- UML_MOV(block, I1, mem(&m_core->m_r[REG_SR]));
- UML_CALLH(block, *m_mem_write);
- UML_SUB(block, I0, I0, 1);
-
- UML_AND(block, mem(&m_core->m_r[REG_SP]), I0, 0x0000ffff);
-
- UML_MOV(block, I0, 0x0000fff6);
- UML_CALLH(block, *m_mem_read);
- UML_MOV(block, mem(&m_core->m_r[REG_PC]), I1);
- UML_MOV(block, mem(&m_core->m_r[REG_SR]), 0);
- UML_HASHJMP(block, 0, I1, *m_nocode);
- UML_RET(block);
-
- block.end();
-}
-
-void unsp_device::static_generate_trigger_irq()
-{
- /* begin generating */
- drcuml_block &block(m_drcuml->begin_block(256));
-
- /* generate a hash jump via the current mode and PC */
- alloc_handle(*m_drcuml, m_trigger_irq, "trigger_irq");
- UML_HANDLE(block, *m_trigger_irq);
-
- UML_OR(block, I0, mem(&m_core->m_fiq), mem(&m_core->m_irq));
- UML_TEST(block, I0, 1);
- UML_RETc(block, uml::COND_NZ);
-
- UML_TEST(block, mem(&m_core->m_enable_irq), 1);
- UML_RETc(block, uml::COND_Z);
-
- UML_MOV(block, mem(&m_core->m_irq), 1);
-
- UML_MOV(block, mem(&m_core->m_saved_sb[0]), mem(&m_core->m_sb));
- UML_MOV(block, mem(&m_core->m_sb), mem(&m_core->m_saved_sb[1]));
-
- UML_MOV(block, I0, mem(&m_core->m_r[REG_SP]));
- UML_MOV(block, I1, mem(&m_core->m_r[REG_PC]));
- UML_CALLH(block, *m_mem_write);
- UML_SUB(block, I0, I0, 1);
-
- UML_MOV(block, I1, mem(&m_core->m_r[REG_SR]));
- UML_CALLH(block, *m_mem_write);
- UML_SUB(block, I0, I0, 1);
-
- UML_AND(block, mem(&m_core->m_r[REG_SP]), I0, 0x0000ffff);
-
- UML_ADD(block, I0, I2, 0x0000fff7);
-
- UML_CALLH(block, *m_mem_read);
-
- UML_MOV(block, mem(&m_core->m_r[REG_PC]), I1);
- UML_MOV(block, mem(&m_core->m_r[REG_SR]), 0);
- UML_HASHJMP(block, 0, I1, *m_nocode);
- UML_RET(block);
-
- block.end();
-}
-
-/*-------------------------------------------------
- generate_check_cycles - generate code to
- generate an exception if cycles are out
--------------------------------------------------*/
-
-void unsp_device::generate_check_cycles(drcuml_block &block, compiler_state &compiler, uml::parameter param)
-{
- UML_CMP(block, mem(&m_core->m_icount), 0);
- UML_EXHc(block, uml::COND_L, *m_out_of_cycles, param);
-}
-
-/*-------------------------------------------------
- generate_checksum_block - generate code to
- validate a sequence of opcodes
--------------------------------------------------*/
-
-void unsp_device::generate_checksum_block(drcuml_block &block, compiler_state &compiler, const opcode_desc *seqhead, const opcode_desc *seqlast)
-{
- const opcode_desc *curdesc;
- if (m_drcuml->logging())
- {
- block.append_comment("[Validation for %08X]", seqhead->pc);
- }
-
- /* full verification; sum up everything */
- void *memptr = m_program->get_write_ptr(seqhead->physpc);
- UML_LOAD(block, I0, memptr, 0, SIZE_WORD, SCALE_x2);
- uint32_t sum = seqhead->opptr.w[0];
- for (int i = 1; i < seqhead->length; i++)
- {
- UML_LOAD(block, I1, memptr, i, SIZE_WORD, SCALE_x2);
- UML_ADD(block, I0, I0, I1);
- sum += ((uint16_t*)memptr)[i];
- }
- for (curdesc = seqhead->next(); curdesc != seqlast->next(); curdesc = curdesc->next())
- {
- if (!(curdesc->flags & OPFLAG_VIRTUAL_NOOP))
- {
- memptr = m_program->get_write_ptr(curdesc->physpc);
- UML_LOAD(block, I1, memptr, 0, SIZE_WORD, SCALE_x2);
- UML_ADD(block, I0, I0, I1);
- sum += curdesc->opptr.w[0];
- for (int i = 1; i < curdesc->length; i++)
- {
- UML_LOAD(block, I1, memptr, i, SIZE_WORD, SCALE_x2);
- UML_ADD(block, I0, I0, I1);
- sum += ((uint16_t*)memptr)[i];
- }
- }
- }
- UML_CMP(block, I0, sum);
- UML_EXHc(block, COND_NE, *m_nocode, seqhead->pc);
-}
-
-
-/*-------------------------------------------------
- log_add_disasm_comment - add a comment
- including disassembly of a MIPS instruction
--------------------------------------------------*/
-
-void unsp_device::log_add_disasm_comment(drcuml_block &block, uint32_t pc, uint32_t op)
-{
- if (m_drcuml->logging())
- {
- block.append_comment("%08X: %08x", pc, op);
- }
-}
-
-
-/*------------------------------------------------------------------
- generate_branch
-------------------------------------------------------------------*/
-
-void unsp_device::generate_branch(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc)
-{
- if (desc->targetpc == BRANCH_TARGET_DYNAMIC)
- {
- UML_ROLAND(block, I0, mem(&m_core->m_r[REG_SR]), 16, 0x3f0000);
- UML_OR(block, mem(&m_core->m_jmpdest), I0, mem(&m_core->m_r[REG_PC]));
- }
-
- /* update the cycles and jump through the hash table to the target */
- if (desc->targetpc != BRANCH_TARGET_DYNAMIC)
- {
- UML_CALLH(block, *m_check_interrupts);
- UML_HASHJMP(block, 0, desc->targetpc, *m_nocode);
- }
- else
- {
- UML_CALLH(block, *m_check_interrupts);
- UML_HASHJMP(block, 0, mem(&m_core->m_jmpdest), *m_nocode);
- }
-}
-
-
-/*-------------------------------------------------
- generate_sequence_instruction - generate code
- for a single instruction in a sequence
--------------------------------------------------*/
-
-void unsp_device::generate_sequence_instruction(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc)
-{
- /* add an entry for the log */
- if (m_drcuml->logging() && !(desc->flags & OPFLAG_VIRTUAL_NOOP))
- log_add_disasm_comment(block, desc->pc, desc->opptr.w[0]);
-
- /* set the PC map variable */
- UML_MAPVAR(block, MAPVAR_PC, desc->pc);
-
- /* if we are debugging, call the debugger */
- if ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0)
- {
- //save_fast_iregs(block);
- UML_DEBUG(block, desc->pc);
- }
-
-#if UNSP_LOG_REGS
- UML_CALLC(block, cfunc_log_regs, this);
-#endif
-
- if (!(desc->flags & OPFLAG_VIRTUAL_NOOP))
- {
- /* compile the instruction */
- if (!generate_opcode(block, compiler, desc))
- {
- UML_ROLINS(block, mem(&m_core->m_r[REG_SR]), desc->pc, 16, 0x3f);
- UML_AND(block, mem(&m_core->m_r[REG_PC]), desc->pc, 0x0000ffff);
- UML_MOV(block, mem(&m_core->m_arg0), desc->opptr.w[0]);
- UML_CALLC(block, cfunc_unimplemented, this);
- }
- }
-}
-
-
-/*------------------------------------------------------------------
- generate_add_lpc - adds an offset to the long program counter
- comprised of PC and the low 6 bits of SR
-------------------------------------------------------------------*/
-
-void unsp_device::generate_add_lpc(drcuml_block &block, int32_t offset)
-{
- UML_ROLAND(block, I0, mem(&m_core->m_r[REG_SR]), 16, 0x3f0000);
- UML_OR(block, I0, I0, mem(&m_core->m_r[REG_PC]));
- UML_ADD(block, I0, I0, offset);
- UML_ROLINS(block, mem(&m_core->m_r[REG_SR]), I0, 16, 0x3f);
- UML_AND(block, mem(&m_core->m_r[REG_PC]), I0, 0x0000ffff);
-}
-
-
-/*------------------------------------------------------------------
- generate_update_nzsc - perform a full flag update
-------------------------------------------------------------------*/
-
-void unsp_device::generate_update_nzsc(drcuml_block &block)
-{
- UML_XOR(block, I1, I1, 0x0000ffff);
- UML_SEXT(block, I1, I1, SIZE_WORD);
- UML_SEXT(block, I2, I2, SIZE_WORD);
- UML_CMP(block, I2, I1);
- UML_SETc(block, uml::COND_L, I1);
- UML_ROLINS(block, mem(&m_core->m_r[REG_SR]), I1, UNSP_S_SHIFT, UNSP_S);
-
- UML_TEST(block, I3, 0x8000);
- UML_SETc(block, uml::COND_NZ, I1);
- UML_ROLINS(block, mem(&m_core->m_r[REG_SR]), I1, UNSP_N_SHIFT, UNSP_N);
-
- UML_TEST(block, I3, 0x10000);
- UML_SETc(block, uml::COND_NZ, I1);
- UML_ROLINS(block, mem(&m_core->m_r[REG_SR]), I1, UNSP_C_SHIFT, UNSP_C);
-
- UML_TEST(block, I3, 0x0000ffff);
- UML_SETc(block, uml::COND_Z, I1);
- UML_ROLINS(block, mem(&m_core->m_r[REG_SR]), I1, UNSP_Z_SHIFT, UNSP_Z);
-}
-
-
-/*------------------------------------------------------------------
- generate_update_nz - perform a partial flag update
-------------------------------------------------------------------*/
-
-void unsp_device::generate_update_nz(drcuml_block &block)
-{
- UML_TEST(block, I3, 0x8000);
- UML_SETc(block, uml::COND_NZ, I1);
- UML_ROLINS(block, mem(&m_core->m_r[REG_SR]), I1, UNSP_N_SHIFT, UNSP_N);
-
- UML_AND(block, I2, I3, 0x0000ffff);
- UML_CMP(block, I2, 0);
- UML_SETc(block, uml::COND_E, I1);
- UML_ROLINS(block, mem(&m_core->m_r[REG_SR]), I1, UNSP_Z_SHIFT, UNSP_Z);
-}
-
-
-/*------------------------------------------------------------------
- generate_opcode - main handler which generates the UML for a
- single opcode
-------------------------------------------------------------------*/
-
-bool unsp_device::generate_opcode(drcuml_block &block, compiler_state &compiler, const opcode_desc *desc)
-{
- uint32_t op = (uint32_t)desc->opptr.w[0];
-
- generate_add_lpc(block, 1);
-
- const uint16_t op0 = (op >> 12) & 15;
- const uint16_t opa = (op >> 9) & 7;
- const uint16_t op1 = (op >> 6) & 7;
- const uint16_t opn = (op >> 3) & 7;
- const uint16_t opb = op & 7;
-
- const uint8_t lower_op = (op1 << 4) | op0;
-
- uml::code_label skip_branch = compiler.m_labelnum++;
- uml::code_label clear_fiq = compiler.m_labelnum++;
- uml::code_label clear_irq = compiler.m_labelnum++;
- uml::code_label reti_done = compiler.m_labelnum++;
- uml::code_label mul_opa_nohi = compiler.m_labelnum++;
- uml::code_label mul_opb_nohi = compiler.m_labelnum++;
- uml::code_label shift_no_sign = compiler.m_labelnum++;
- uml::code_label no_carry = compiler.m_labelnum++;
-
- if(op0 < 0xf && opa == 0x7 && op1 < 2)
- {
- const uint32_t opimm = op & 0x3f;
- switch(op0)
- {
- case 0: // JB
- UML_TEST(block, mem(&m_core->m_r[REG_SR]), UNSP_C);
- UML_JMPc(block, uml::COND_NZ, skip_branch);
- break;
-
- case 1: // JAE
- UML_TEST(block, mem(&m_core->m_r[REG_SR]), UNSP_C);
- UML_JMPc(block, uml::COND_Z, skip_branch);
- break;
-
- case 2: // JGE
- UML_TEST(block, mem(&m_core->m_r[REG_SR]), UNSP_S);
- UML_JMPc(block, uml::COND_NZ, skip_branch);
- break;
-
- case 3: // JL
- UML_TEST(block, mem(&m_core->m_r[REG_SR]), UNSP_S);
- UML_JMPc(block, uml::COND_Z, skip_branch);
- break;
-
- case 4: // JNE
- UML_TEST(block, mem(&m_core->m_r[REG_SR]), UNSP_Z);
- UML_JMPc(block, uml::COND_NZ, skip_branch);
- break;
-
- case 5: // JE
- UML_TEST(block, mem(&m_core->m_r[REG_SR]), UNSP_Z);
- UML_JMPc(block, uml::COND_Z, skip_branch);
- break;
-
- case 6: // JPL
- UML_TEST(block, mem(&m_core->m_r[REG_SR]), UNSP_N);
- UML_JMPc(block, uml::COND_NZ, skip_branch);
- break;
-
- case 7: // JMI
- UML_TEST(block, mem(&m_core->m_r[REG_SR]), UNSP_N);
- UML_JMPc(block, uml::COND_Z, skip_branch);
- break;
-
- case 8: // JBE
- UML_AND(block, I0, mem(&m_core->m_r[REG_SR]), UNSP_Z | UNSP_C);
- UML_CMP(block, I0, UNSP_C);
- UML_JMPc(block, uml::COND_E, skip_branch);
- break;
-
- case 9: // JA
- UML_AND(block, I0, mem(&m_core->m_r[REG_SR]), UNSP_Z | UNSP_C);
- UML_CMP(block, I0, UNSP_C);
- UML_JMPc(block, uml::COND_NE, skip_branch);
- break;
-
- case 10: // JLE
- UML_TEST(block, mem(&m_core->m_r[REG_SR]), UNSP_Z | UNSP_S);
- UML_JMPc(block, uml::COND_Z, skip_branch);
- break;
-
- case 11: // JG
- UML_TEST(block, mem(&m_core->m_r[REG_SR]), UNSP_Z);
- UML_JMPc(block, uml::COND_NZ, skip_branch);
- UML_TEST(block, mem(&m_core->m_r[REG_SR]), UNSP_S);
- UML_JMPc(block, uml::COND_NZ, skip_branch);
- break;
-
- case 14: // JMP
- UML_SUB(block, mem(&m_core->m_icount), mem(&m_core->m_icount), 4);
- UML_MOV(block, I0, desc->targetpc);
- UML_AND(block, mem(&m_core->m_r[REG_PC]), I0, 0x0000ffff);
- generate_branch(block, compiler, desc);
- return true;
-
- default:
- return false;
- }
- UML_SUB(block, mem(&m_core->m_icount), mem(&m_core->m_icount), 4);
- generate_add_lpc(block, (op1 == 0) ? opimm : (0 - opimm));
- generate_branch(block, compiler, desc);
- UML_LABEL(block, skip_branch);
- UML_SUB(block, mem(&m_core->m_icount), mem(&m_core->m_icount), 2);
- return true;
- }
-
- UML_SUB(block, mem(&m_core->m_icount), mem(&m_core->m_icount), desc->cycles);
-
- if (lower_op == 0x2d) // Push
- {
- uint32_t r0 = opn;
- uint32_t r1 = opa;
- UML_MOV(block, I0, mem(&m_core->m_r[opb]));
- while (r0)
- {
- UML_MOV(block, I1, mem(&m_core->m_r[r1]));
- UML_CALLH(block, *m_mem_write);
- UML_SUB(block, I0, I0, 1);
- UML_AND(block, mem(&m_core->m_r[opb]), I0, 0x0000ffff);
- r0--;
- r1--;
- }
- return true;
- }
- else if (lower_op == 0x29)
- {
- if (op == 0x9a98) // reti
- {
- UML_ADD(block, I0, mem(&m_core->m_r[REG_SP]), 1);
- UML_CALLH(block, *m_mem_read);
- UML_MOV(block, mem(&m_core->m_r[REG_SR]), I1);
-
- UML_ADD(block, I0, I0, 1);
- UML_CALLH(block, *m_mem_read);
- UML_MOV(block, mem(&m_core->m_r[REG_PC]), I1);
-
- UML_AND(block, mem(&m_core->m_r[REG_SP]), I0, 0x0000ffff);
-
- UML_TEST(block, mem(&m_core->m_fiq), 1);
- UML_JMPc(block, uml::COND_NZ, clear_fiq);
- UML_TEST(block, mem(&m_core->m_irq), 1);
- UML_JMPc(block, uml::COND_NZ, clear_irq);
- UML_JMP(block, reti_done);
-
- UML_LABEL(block, clear_fiq);
- UML_MOV(block, mem(&m_core->m_fiq), 0);
- UML_MOV(block, mem(&m_core->m_saved_sb[2]), mem(&m_core->m_sb));
- UML_LOAD(block, mem(&m_core->m_sb), (void*)m_core->m_saved_sb, mem(&m_core->m_irq), SIZE_DWORD, SCALE_x4);
- UML_JMP(block, reti_done);
-
- UML_LABEL(block, clear_irq);
- UML_MOV(block, mem(&m_core->m_irq), 0);
- UML_MOV(block, mem(&m_core->m_saved_sb[1]), mem(&m_core->m_sb));
- UML_MOV(block, mem(&m_core->m_sb), mem(&m_core->m_saved_sb[0]));
-
- UML_LABEL(block, reti_done);
- UML_MOV(block, mem(&m_core->m_curirq), 0);
- generate_branch(block, compiler, desc);
- }
- else // pop
- {
- uint32_t r0 = opn;
- uint32_t r1 = opa;
- bool do_branch = false;
-
- UML_MOV(block, I0, mem(&m_core->m_r[opb]));
- while (r0)
- {
- r1++;
- UML_ADD(block, I0, I0, 1);
- UML_AND(block, mem(&m_core->m_r[opb]), I0, 0x0000ffff);
- UML_CALLH(block, *m_mem_read);
- UML_MOV(block, mem(&m_core->m_r[r1]), I1);
- if (r1 == REG_PC)
- do_branch = true;
- r0--;
- }
- if (do_branch)
- generate_branch(block, compiler, desc);
- }
- return true;
- }
- else if (op0 == 0xf)
- {
- switch (op1)
- {
- case 0x00: // Multiply, Unsigned * Signed
- if(opn == 1 && opa != 7)
- {
- UML_MOV(block, I0, mem(&m_core->m_r[opa]));
- UML_MOV(block, I1, mem(&m_core->m_r[opb]));
- UML_MULU(block, I2, I2, I0, I1);
-
- UML_TEST(block, I1, 0x00008000);
- UML_JMPc(block, uml::COND_Z, mul_opb_nohi);
- UML_SHL(block, I0, I0, 16);
- UML_SUB(block, I2, I2, I0);
-
- UML_LABEL(block, mul_opb_nohi);
- UML_SHR(block, mem(&m_core->m_r[REG_R4]), I2, 16);
- UML_AND(block, mem(&m_core->m_r[REG_R3]), I2, 0x0000ffff);
- return true;
- }
- return false;
-
- case 0x01: // Call
- if(!(opa & 1))
- {
- generate_add_lpc(block, 1);
-
- UML_MOV(block, I0, mem(&m_core->m_r[REG_SP]));
-
- UML_MOV(block, I1, mem(&m_core->m_r[REG_PC]));
- UML_CALLH(block, *m_mem_write);
- UML_SUB(block, I0, I0, 1);
-
- UML_MOV(block, I1, mem(&m_core->m_r[REG_SR]));
- UML_CALLH(block, *m_mem_write);
- UML_SUB(block, I0, I0, 1);
-
- UML_AND(block, mem(&m_core->m_r[REG_SP]), I0, 0x0000ffff);
-
- UML_MOV(block, I0, desc->targetpc);
- UML_AND(block, mem(&m_core->m_r[REG_PC]), I0, 0x0000ffff);
- UML_ROLINS(block, mem(&m_core->m_r[REG_SR]), I0, 16, 0x3f);
- generate_branch(block, compiler, desc);
- return true;
- }
- return false;
-
- case 0x02: // Far Jump
- if (opa == 7)
- {
- UML_MOV(block, I0, desc->targetpc);
- UML_AND(block, mem(&m_core->m_r[REG_PC]), I0, 0x0000ffff);
- UML_ROLINS(block, mem(&m_core->m_r[REG_SR]), I0, 16, 0x3f);
- generate_branch(block, compiler, desc);
- return true;
- }
- return false;
-
- case 0x04: // Multiply, Signed * Signed
- if(opn == 1 && opa != 7)
- {
- UML_MOV(block, I0, mem(&m_core->m_r[opa]));
- UML_MOV(block, I1, mem(&m_core->m_r[opb]));
- UML_MULU(block, I2, I2, I0, I1);
-
- UML_TEST(block, I1, 0x00008000);
- UML_JMPc(block, uml::COND_Z, mul_opb_nohi);
- UML_SHL(block, I0, I0, 16);
- UML_SUB(block, I2, I2, I0);
-
- UML_LABEL(block, mul_opb_nohi);
- UML_TEST(block, I0, 0x00008000);
- UML_JMPc(block, uml::COND_Z, mul_opa_nohi);
- UML_SHL(block, I1, I1, 16);
- UML_SUB(block, I2, I2, I1);
-
- UML_LABEL(block, mul_opa_nohi);
- UML_SHR(block, mem(&m_core->m_r[REG_R4]), I2, 16);
- UML_AND(block, mem(&m_core->m_r[REG_R3]), I2, 0x0000ffff);
- return true;
- }
- return false;
-
- case 0x05: // Interrupt flags
- switch(op & 0x3f)
- {
- case 0:
- UML_MOV(block, mem(&m_core->m_enable_irq), 0);
- UML_MOV(block, mem(&m_core->m_enable_fiq), 0);
- break;
-
- case 1:
- UML_MOV(block, mem(&m_core->m_enable_irq), 1);
- UML_MOV(block, mem(&m_core->m_enable_fiq), 0);
- break;
-
- case 2:
- UML_MOV(block, mem(&m_core->m_enable_irq), 0);
- UML_MOV(block, mem(&m_core->m_enable_fiq), 1);
- break;
-
- case 3:
- UML_MOV(block, mem(&m_core->m_enable_irq), 1);
- UML_MOV(block, mem(&m_core->m_enable_fiq), 1);
- break;
-
- case 8:
- UML_MOV(block, mem(&m_core->m_enable_irq), 0);
- break;
-
- case 9:
- UML_MOV(block, mem(&m_core->m_enable_irq), 1);
- break;
-
- case 12:
- UML_MOV(block, mem(&m_core->m_enable_fiq), 0);
- break;
-
- case 14:
- UML_MOV(block, mem(&m_core->m_enable_fiq), 1);
- break;
-
- case 37:
- // nop
- break;
-
- default:
- return false;
- }
- return true;
-
- default:
- return false;
- }
- }
-
- // At this point, we should be dealing solely with ALU ops.
- UML_MOV(block, I2, mem(&m_core->m_r[opa]));
-
- switch (op1)
- {
- case 0x00: // r, [bp+imm6]
- UML_ADD(block, I0, mem(&m_core->m_r[REG_BP]), op & 0x3f);
- UML_AND(block, I0, I0, 0x0000ffff);
- if (op0 != 0x0d)
- UML_CALLH(block, *m_mem_read);
- break;
-
- case 0x01: // r, imm6
- UML_MOV(block, I1, op & 0x3f);
- break;
-
- case 0x03: // Indirect
- {
- const uint8_t lsbits = opn & 3;
- if (opn & 4)
- {
- switch (lsbits)
- {
- case 0: // r, [<ds:>r]
- UML_ROLAND(block, I0, mem(&m_core->m_r[REG_SR]), 6, 0x3f0000);
- UML_OR(block, I0, I0, mem(&m_core->m_r[opb]));
- if (op0 != 0x0d)
- UML_CALLH(block, *m_mem_read);
- break;
-
- case 1: // r, [<ds:>r--]
- UML_ROLAND(block, I0, mem(&m_core->m_r[REG_SR]), 6, 0x3f0000);
- UML_OR(block, I0, I0, mem(&m_core->m_r[opb]));
- if (op0 != 0x0d)
- UML_CALLH(block, *m_mem_read);
- UML_SUB(block, I3, I0, 1);
- UML_ROLINS(block, mem(&m_core->m_r[REG_SR]), I3, 32-6, 0x0000fc00);
- UML_AND(block, mem(&m_core->m_r[opb]), I3, 0x0000ffff);
- break;
-
- case 2: // r, [<ds:>r++]
- UML_ROLAND(block, I0, mem(&m_core->m_r[REG_SR]), 6, 0x3f0000);
- UML_OR(block, I0, I0, mem(&m_core->m_r[opb]));
- if (op0 != 0x0d)
- UML_CALLH(block, *m_mem_read);
- UML_ADD(block, I3, I0, 1);
- UML_ROLINS(block, mem(&m_core->m_r[REG_SR]), I3, 32-6, 0x0000fc00);
- UML_AND(block, mem(&m_core->m_r[opb]), I3, 0x0000ffff);
- break;
-
- case 3: // r, [<ds:>++r]
- UML_ROLAND(block, I0, mem(&m_core->m_r[REG_SR]), 6, 0x3f0000);
- UML_OR(block, I0, I0, mem(&m_core->m_r[opb]));
- UML_ADD(block, I0, I0, 1);
- UML_ROLINS(block, mem(&m_core->m_r[REG_SR]), I0, 32-6, 0x0000fc00);
- UML_AND(block, mem(&m_core->m_r[opb]), I0, 0x0000ffff);
- if (op0 != 0x0d)
- UML_CALLH(block, *m_mem_read);
- break;
-
- default:
- // can't happen
- break;
- }
- }
- else
- {
- switch (lsbits)
- {
- case 0: // r, [r]
- UML_MOV(block, I0, mem(&m_core->m_r[opb]));
- if (op0 != 0x0d)
- UML_CALLH(block, *m_mem_read);
- break;
-
- case 1: // r, [r--]
- UML_MOV(block, I0, mem(&m_core->m_r[opb]));
- if (op0 != 0x0d)
- UML_CALLH(block, *m_mem_read);
- UML_SUB(block, I3, I0, 1);
- UML_AND(block, mem(&m_core->m_r[opb]), I3, 0x0000ffff);
- break;
-
- case 2: // r, [r++]
- UML_MOV(block, I0, mem(&m_core->m_r[opb]));
- if (op0 != 0x0d)
- UML_CALLH(block, *m_mem_read);
- UML_ADD(block, I3, I0, 1);
- UML_AND(block, mem(&m_core->m_r[opb]), I3, 0x0000ffff);
- break;
-
- case 3: // r, [++r]
- UML_ADD(block, I0, mem(&m_core->m_r[opb]), 1);
- UML_AND(block, I0, I0, 0x0000ffff);
- UML_MOV(block, mem(&m_core->m_r[opb]), I0);
- if (op0 != 0x0d)
- UML_CALLH(block, *m_mem_read);
- break;
- default:
- // can't happen
- break;
- }
- }
- break;
- }
-
- case 0x04: // 16-bit ops
- switch (opn)
- {
- case 0x00: // r
- UML_MOV(block, I1, mem(&m_core->m_r[opb]));
- break;
-
- case 0x01: // imm16
- {
- UML_MOV(block, I2, mem(&m_core->m_r[opb]));
- const uint16_t r1 = m_pr16(desc->pc + 1);
- generate_add_lpc(block, 1);
- UML_MOV(block, I1, r1);
- break;
- }
-
- case 0x02: // [imm16]
- {
- UML_MOV(block, I2, mem(&m_core->m_r[opb]));
- const uint16_t r1 = m_pr16(desc->pc + 1);
- generate_add_lpc(block, 1);
- UML_MOV(block, I0, r1);
- if (op0 != 0x0d)
- UML_CALLH(block, *m_mem_read);
- break;
- }
-
- case 0x03: // store [imm16], r
- {
- UML_MOV(block, I1, I2);
- UML_MOV(block, I2, mem(&m_core->m_r[opb]));
- const uint16_t r2 = m_pr16(desc->pc + 1);
- generate_add_lpc(block, 1);
- UML_MOV(block, I0, r2);
- break;
- }
-
- default: // Shifted ops
- {
- UML_SHL(block, I0, mem(&m_core->m_r[opb]), 4);
- UML_OR(block, I0, I0, mem(&m_core->m_sb));
- UML_TEST(block, I0, 0x80000);
- UML_JMPc(block, uml::COND_Z, shift_no_sign);
- UML_OR(block, I0, I0, 0xf00000);
-
- UML_LABEL(block, shift_no_sign);
- UML_SHR(block, I0, I0, opn - 3);
- UML_AND(block, mem(&m_core->m_sb), I0, 0xf);
- UML_SHR(block, I1, I0, 4);
- UML_AND(block, I1, I1, 0x0000ffff);
- break;
- }
- }
- break;
-
- case 0x05: // More shifted ops
- if (opn & 4) // Shift right
- {
- UML_SHL(block, I0, mem(&m_core->m_r[opb]), 4);
- UML_OR(block, I0, I0, mem(&m_core->m_sb));
- UML_SHR(block, I0, I0, opn - 3);
- UML_AND(block, mem(&m_core->m_sb), I0, 0xf);
- UML_SHR(block, I1, I0, 4);
- UML_AND(block, I1, I1, 0x0000ffff);
- }
- else // Shift left
- {
- UML_SHL(block, I0, mem(&m_core->m_sb), 16);
- UML_OR(block, I0, I0, mem(&m_core->m_r[opb]));
- UML_SHL(block, I0, I0, opn + 1);
- UML_SHR(block, I1, I0, 16);
- UML_AND(block, mem(&m_core->m_sb), I1, 0xf);
- UML_AND(block, I1, I0, 0x0000ffff);
- }
- break;
-
- case 0x06: // Rotated ops
- {
- UML_SHL(block, I0, mem(&m_core->m_sb), 16);
- UML_OR(block, I0, I0, mem(&m_core->m_r[opb]));
- UML_SHL(block, I0, I0, 4);
- UML_OR(block, I0, I0, mem(&m_core->m_sb));
- if (opn & 4) // Rotate right
- {
- UML_SHR(block, I0, I0, opn - 3);
- UML_AND(block, mem(&m_core->m_sb), I0, 0xf);
- }
- else // Rotate left
- {
- UML_SHL(block, I0, I0, opn + 1);
- UML_SHR(block, I1, I0, 20);
- UML_AND(block, mem(&m_core->m_sb), I1, 0xf);
- }
- UML_SHR(block, I1, I0, 4);
- UML_AND(block, I1, I1, 0x0000ffff);
- break;
- }
-
- case 0x07: // Direct 8
- UML_MOV(block, I0, op & 0x3f);
- UML_CALLH(block, *m_mem_read);
- break;
-
- default:
- break;
- }
-
- switch (op0)
- {
- case 0x00: // Add
- UML_ADD(block, I3, I2, I1);
- if (opa != 7)
- generate_update_nzsc(block);
- break;
-
- case 0x01: // Add w/ carry
- UML_ROLAND(block, I3, mem(&m_core->m_r[REG_SR]), 32-UNSP_C_SHIFT, 1);
- UML_ADD(block, I3, I3, I2);
- UML_ADD(block, I3, I3, I1);
- if (opa != 7)
- generate_update_nzsc(block);
- break;
-
- case 0x02: // Subtract
- UML_XOR(block, I1, I1, 0x0000ffff);
- UML_ADD(block, I3, I1, I2);
- UML_ADD(block, I3, I3, 1);
- if (opa != 7)
- generate_update_nzsc(block);
- break;
-
- case 0x03: // Subtract w/ carry
- UML_XOR(block, I1, I1, 0x0000ffff);
- UML_ADD(block, I3, I1, I2);
- UML_TEST(block, mem(&m_core->m_r[REG_SR]), UNSP_C);
- UML_JMPc(block, uml::COND_Z, no_carry);
- UML_ADD(block, I3, I3, 1);
-
- UML_LABEL(block, no_carry);
- if (opa != 7)
- generate_update_nzsc(block);
- break;
-
- case 0x04: // Compare
- UML_XOR(block, I1, I1, 0x0000ffff);
- UML_ADD(block, I3, I1, I2);
- UML_ADD(block, I3, I3, 1);
- if (opa != 7)
- generate_update_nzsc(block);
- return true;
-
- case 0x06: // Negate
- UML_SUB(block, I3, 0, I1);
- if (opa != 7)
- generate_update_nz(block);
- break;
-
- case 0x08: // XOR
- UML_XOR(block, I3, I2, I1);
- if (opa != 7)
- generate_update_nz(block);
- break;
-
- case 0x09: // Load
- UML_MOV(block, I3, I1);
- if (opa != 7)
- generate_update_nz(block);
- break;
-
- case 0x0a: // OR
- UML_OR(block, I3, I2, I1);
- if (opa != 7)
- generate_update_nz(block);
- break;
-
- case 0x0b: // AND
- UML_AND(block, I3, I2, I1);
- if (opa != 7)
- generate_update_nz(block);
- break;
-
- case 0x0c: // Test
- UML_AND(block, I3, I2, I1);
- if (opa != 7)
- generate_update_nz(block);
- return true;
-
- case 0x0d: // Store
- UML_MOV(block, I1, I2);
- UML_CALLH(block, *m_mem_write);
- return true;
-
- default:
- return false;
- }
-
- if (op1 == 0x04 && opn == 0x03)
- {
- UML_MOV(block, I1, I3);
- UML_CALLH(block, *m_mem_write);
- return true;
- }
-
- UML_AND(block, mem(&m_core->m_r[opa]), I3, 0x0000ffff);
- if (opa == REG_PC)
- generate_branch(block, compiler, desc);
- return true;
-}
diff --git a/src/devices/cpu/unsp/unspfe.cpp b/src/devices/cpu/unsp/unspfe.cpp
deleted file mode 100644
index 3eb38b2198c..00000000000
--- a/src/devices/cpu/unsp/unspfe.cpp
+++ /dev/null
@@ -1,357 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Ryan Holtz
-/***************************************************************************
-
- unspfe.cpp
-
- Front end for u'nSP recompiler
-
-***************************************************************************/
-
-#include "emu.h"
-#include "unspfe.h"
-#include "unspdefs.h"
-
-/***************************************************************************
- INSTRUCTION PARSERS
-***************************************************************************/
-
-unsp_frontend::unsp_frontend(unsp_device *unsp, uint32_t window_start, uint32_t window_end, uint32_t max_sequence)
- : drc_frontend(*unsp, window_start, window_end, max_sequence)
- , m_cpu(unsp)
-{
-}
-
-inline uint16_t unsp_frontend::read_op_word(opcode_desc &desc, int offset)
-{
- return m_cpu->m_pr16(desc.physpc + offset);
-}
-
-/*-------------------------------------------------
- describe - build a description of a single
- instruction
--------------------------------------------------*/
-
-bool unsp_frontend::describe(opcode_desc &desc, const opcode_desc *prev)
-{
- uint16_t op = desc.opptr.w[0] = read_op_word(desc, 0);
-
- /* most instructions are 1 word */
- desc.length = 1;
- desc.delayslots = 0;
-
- const uint16_t op0 = (op >> 12) & 15;
- const uint16_t opa = (op >> 9) & 7;
- const uint16_t op1 = (op >> 6) & 7;
- const uint16_t opn = (op >> 3) & 7;
- const uint16_t opb = op & 7;
-
- const uint8_t lower_op = (op1 << 4) | op0;
-
- if(op0 < 0xf && opa == 0x7 && op1 < 2)
- {
- desc.cycles = 2; // cycles for a taken branch will be added at execute time
-
- const uint32_t opimm = op & 0x3f;
- switch(op0)
- {
- case 0: // JB
- case 1: // JAE
- case 2: // JGE
- case 3: // JL
- case 4: // JNE
- case 5: // JE
- case 6: // JPL
- case 7: // JMI
- case 8: // JBE
- case 9: // JA
- case 10: // JLE
- case 11: // JG
- desc.regin[0] |= 1 << unsp_device::REG_SR;
- desc.regout[0] |= 1 << unsp_device::REG_SR;
- desc.regout[0] |= 1 << unsp_device::REG_PC;
- desc.targetpc = BRANCH_TARGET_DYNAMIC;
- desc.flags |= OPFLAG_IS_CONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
- return true;
- case 14: // JMP
- desc.regout[0] |= 1 << unsp_device::REG_SR;
- desc.regout[0] |= 1 << unsp_device::REG_PC;
- desc.targetpc = desc.pc + 1 + ((op1 == 0) ? opimm : (0 - opimm));
- desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
- return true;
- default:
- return false;
- }
- }
- else if (lower_op == 0x2d) // Push
- {
- uint16_t r0 = opn;
- uint16_t r1 = opa;
- desc.cycles = 4 + 2 * r0;
- desc.regin[0] |= 1 << opb;
- desc.regout[0] |= 1 << opb;
- desc.flags |= OPFLAG_WRITES_MEMORY;
- while (r0--)
- {
- desc.regin[0] |= 1 << r1;
- r1--;
- }
- return true;
- }
- else if (lower_op == 0x29) // Pop
- {
- if (op == 0x9a98) // reti
- {
- desc.cycles = 8;
- desc.regin[0] |= 1 << unsp_device::REG_SP;
- desc.regout[0] |= 1 << unsp_device::REG_SP;
- desc.regout[0] |= 1 << unsp_device::REG_SR;
- desc.regout[0] |= 1 << unsp_device::REG_PC;
- desc.targetpc = BRANCH_TARGET_DYNAMIC;
- desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE | OPFLAG_READS_MEMORY;
- return true;
- }
- else
- {
- uint16_t r0 = opn;
- uint16_t r1 = opa;
- desc.cycles = 4 + 2 * r0;
- desc.regin[0] |= 1 << opb;
- desc.regout[0] |= 1 << opb;
- desc.flags |= OPFLAG_READS_MEMORY;
-
- while (r0--)
- {
- r1++;
- desc.regout[0] |= 1 << r1;
- }
- return true;
- }
- }
- else if (op0 == 0xf)
- {
- switch (op1)
- {
- case 0x00: // Multiply, Unsigned * Signed
- case 0x04: // Multiply, Signed * Signed
- if(opn == 1 && opa != 7)
- {
- desc.cycles = 12;
- desc.regin[0] |= 1 << opa;
- desc.regin[0] |= 1 << opb;
- desc.regout[0] |= 1 << unsp_device::REG_R3;
- desc.regout[0] |= 1 << unsp_device::REG_R4;
- return true;
- }
- return false;
-
- case 0x01: // Call
- if(!(opa & 1))
- {
- desc.cycles = 9;
- desc.length = 2;
- desc.targetpc = read_op_word(desc, 1) | ((op & 0x3f) << 16);
- desc.flags = OPFLAG_READS_MEMORY | OPFLAG_WRITES_MEMORY | OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
- desc.regin[0] |= 1 << unsp_device::REG_PC;
- desc.regin[0] |= 1 << unsp_device::REG_SP;
- desc.regout[0] |= 1 << unsp_device::REG_SP;
- desc.regout[0] |= 1 << unsp_device::REG_SR;
- desc.regout[0] |= 1 << unsp_device::REG_PC;
- return true;
- }
- return false;
-
- case 0x02: // Far Jump
- if (opa == 7)
- {
- desc.cycles = 5;
- desc.length = 2;
- desc.targetpc = read_op_word(desc, 1) | ((op & 0x3f) << 16);
- desc.flags = OPFLAG_READS_MEMORY | OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
- desc.regin[0] |= 1 << unsp_device::REG_PC;
- desc.regout[0] |= 1 << unsp_device::REG_SR;
- desc.regout[0] |= 1 << unsp_device::REG_PC;
- return true;
- }
- return false;
-
- case 0x05: // Interrupt flags
- desc.cycles = 2;
- switch(op & 0x3f)
- {
- case 0:
- case 1:
- case 2:
- case 3:
- case 8:
- case 9:
- case 12:
- case 14:
- case 37:
- return true;
- }
- return false;
-
- default:
- return false;
- }
- }
-
- // At this point, we should be dealing solely with ALU ops.
-
- desc.regin[0] |= 1 << opa;
-
- switch (op1)
- {
- case 0x00: // r, [bp+imm6]
- desc.cycles = 6;
- desc.regin[0] |= 1 << unsp_device::REG_BP;
- if (op0 != 0x0d)
- desc.flags |= OPFLAG_READS_MEMORY;
- break;
-
- case 0x01: // r, imm6
- desc.cycles = 2;
- break;
-
- case 0x03: // Indirect
- {
- desc.cycles = (opa == 7 ? 7 : 6);
- const uint8_t lsbits = opn & 3;
- if (opn & 4)
- {
- switch (lsbits)
- {
- case 0: // r, [r]
- desc.regin[0] |= 1 << unsp_device::REG_SR;
- desc.regin[0] |= 1 << opb;
- if (op0 != 0x0d)
- desc.flags |= OPFLAG_READS_MEMORY;
- break;
-
- case 1: // r, [<ds:>r--]
- case 2: // r, [<ds:>r++]
- case 3: // r, [<ds:>++r]
- desc.regin[0] |= 1 << unsp_device::REG_SR;
- desc.regin[0] |= 1 << opb;
- desc.regout[0] |= 1 << unsp_device::REG_SR;
- desc.regout[0] |= 1 << opb;
- if (op0 != 0x0d)
- desc.flags |= OPFLAG_READS_MEMORY;
- break;
- }
- }
- else
- {
- switch (lsbits)
- {
- case 0: // r, [r]
- desc.regin[0] |= 1 << opb;
- if (op0 != 0x0d)
- desc.flags |= OPFLAG_READS_MEMORY;
- break;
- case 1: // r, [r--]
- case 2: // r, [r++]
- case 3: // r, [++r]
- desc.regin[0] |= 1 << opb;
- desc.regout[0] |= 1 << opb;
- if (op0 != 0x0d)
- desc.flags |= OPFLAG_READS_MEMORY;
- break;
- }
- }
- break;
- }
-
- case 0x04: // 16-bit ops
- switch (opn)
- {
- case 0x00: // r
- desc.cycles = (opa == 7 ? 5 : 3);
- desc.regin[0] |= 1 << opb;
- break;
-
- case 0x01: // imm16
- desc.cycles = (opa == 7 ? 5 : 4);
- desc.length = 2;
- desc.regin[0] |= 1 << opb;
- desc.regin[0] |= 1 << unsp_device::REG_SR;
- desc.regin[0] |= 1 << unsp_device::REG_PC;
- desc.regout[0] |= 1 << unsp_device::REG_SR;
- desc.regout[0] |= 1 << unsp_device::REG_PC;
- desc.flags |= OPFLAG_READS_MEMORY;
- break;
-
- case 0x02: // [imm16]
- case 0x03: // store [imm16], r
- desc.cycles = (opa == 7 ? 8 : 7);
- desc.length = 2;
- desc.regin[0] |= 1 << opb;
- desc.regin[0] |= 1 << unsp_device::REG_SR;
- desc.regin[0] |= 1 << unsp_device::REG_PC;
- desc.regout[0] |= 1 << unsp_device::REG_SR;
- desc.regout[0] |= 1 << unsp_device::REG_PC;
- desc.flags |= OPFLAG_READS_MEMORY;
- break;
-
- default: // Shifted ops
- desc.cycles = (opa == 7 ? 5 : 3);
- desc.regin[0] |= 1 << opb;
- break;
- }
- break;
-
- case 0x05: // More shifted ops
- case 0x06: // Rotated ops
- desc.cycles = (opa == 7 ? 5 : 3);
- desc.regin[0] |= 1 << opb;
- break;
-
- case 0x07: // Direct 8
- desc.cycles = (opa == 7 ? 6 : 5);
- desc.flags |= OPFLAG_READS_MEMORY;
- break;
-
- default:
- // Can't happen
- break;
- }
-
- switch (op0)
- {
- case 0x00: // Add
- case 0x01: // Add w/ carry
- case 0x02: // Subtract
- case 0x03: // Subtract w/ carry
- case 0x06: // Negate
- case 0x08: // XOR
- case 0x09: // Load
- case 0x0a: // OR
- case 0x0b: // AND
- desc.regout[0] |= 1 << unsp_device::REG_SR;
- break;
- case 0x04: // Compare
- case 0x0c: // Test
- desc.regout[0] |= 1 << unsp_device::REG_SR;
- return true;
- case 0x0d: // Store
- desc.flags |= OPFLAG_WRITES_MEMORY;
- return true;
- }
-
- if (op1 == 0x04 && opn == 0x03) // store [imm16], r
- {
- desc.flags |= OPFLAG_WRITES_MEMORY;
- }
- else
- {
- desc.regout[0] |= 1 << opa;
- if (opa == 7)
- {
- desc.targetpc = BRANCH_TARGET_DYNAMIC;
- desc.flags |= OPFLAG_IS_UNCONDITIONAL_BRANCH | OPFLAG_END_SEQUENCE;
- }
- }
-
- return true;
-}
diff --git a/src/devices/cpu/unsp/unspfe.h b/src/devices/cpu/unsp/unspfe.h
deleted file mode 100644
index c30b2721e0a..00000000000
--- a/src/devices/cpu/unsp/unspfe.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// license:BSD-3-Clause
-// copyright-holders:Ryan Holtz
-#ifndef MAME_CPU_UNSP_UNSPFE_H
-#define MAME_CPU_UNSP_UNSPFE_H
-
-#pragma once
-
-#include "unsp.h"
-#include "cpu/drcfe.h"
-
-class unsp_frontend : public drc_frontend
-{
-public:
- unsp_frontend(unsp_device *unsp, uint32_t window_start, uint32_t window_end, uint32_t max_sequence);
- void flush();
-
-protected:
- // required overrides
- virtual bool describe(opcode_desc &desc, const opcode_desc *prev) override;
-
-private:
- inline uint16_t read_op_word(opcode_desc &desc, int offset);
-
- unsp_device *m_cpu;
-};
-
-#endif /* MAME_CPU_UNSP_UNSPFE_H */
diff --git a/src/devices/cpu/z8/z8.cpp b/src/devices/cpu/z8/z8.cpp
index 1359fea831f..d5e19fe831f 100644
--- a/src/devices/cpu/z8/z8.cpp
+++ b/src/devices/cpu/z8/z8.cpp
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Curt Coder, AJR
+// copyright-holders:Curt Coder
/**********************************************************************
Zilog Z8 Single-Chip MCU emulation
@@ -11,6 +11,8 @@
TODO:
- strobed I/O
+ - timer Tin/Tout modes
+ - serial
- instruction pipeline
- internal diagnostic ROM in data space (requires high voltage reset)
@@ -31,14 +33,14 @@
#define Z8_P3_RDY0 0x20 /* not supported */
#define Z8_P3_RDY1 0x10 /* not supported */
#define Z8_P3_RDY2 0x40 /* not supported */
-#define Z8_P3_IRQ0 0x04
-#define Z8_P3_IRQ1 0x08
-#define Z8_P3_IRQ2 0x02
-#define Z8_P3_IRQ3 0x01
-#define Z8_P3_SIN 0x01
-#define Z8_P3_SOUT 0x80
-#define Z8_P3_TIN 0x02
-#define Z8_P3_TOUT 0x40
+#define Z8_P3_IRQ0 0x04 /* not supported */
+#define Z8_P3_IRQ1 0x08 /* not supported */
+#define Z8_P3_IRQ2 0x02 /* not supported */
+#define Z8_P3_IRQ3 0x01 /* not supported */
+#define Z8_P3_DI 0x01 /* not supported */
+#define Z8_P3_DO 0x80 /* not supported */
+#define Z8_P3_TIN 0x02 /* not supported */
+#define Z8_P3_TOUT 0x40 /* not supported */
#define Z8_P3_DM 0x10 /* not supported */
#define Z8_PRE0_COUNT_MODULO_N 0x01
@@ -50,15 +52,15 @@
#define Z8_TMR_ENABLE_T0 0x02
#define Z8_TMR_LOAD_T1 0x04
#define Z8_TMR_ENABLE_T1 0x08
-#define Z8_TMR_TIN_MASK 0x30
-#define Z8_TMR_TIN_EXTERNAL_CLK 0x00
-#define Z8_TMR_TIN_GATE 0x10
-#define Z8_TMR_TIN_TRIGGER 0x20
-#define Z8_TMR_TIN_RETRIGGER 0x30
-#define Z8_TMR_TOUT_MASK 0xc0
-#define Z8_TMR_TOUT_OFF 0x00
-#define Z8_TMR_TOUT_T0 0x40
-#define Z8_TMR_TOUT_T1 0x80
+#define Z8_TMR_TIN_MASK 0x30 /* not supported */
+#define Z8_TMR_TIN_EXTERNAL_CLK 0x00 /* not supported */
+#define Z8_TMR_TIN_GATE 0x10 /* not supported */
+#define Z8_TMR_TIN_TRIGGER 0x20 /* not supported */
+#define Z8_TMR_TIN_RETRIGGER 0x30 /* not supported */
+#define Z8_TMR_TOUT_MASK 0xc0 /* not supported */
+#define Z8_TMR_TOUT_OFF 0x00 /* not supported */
+#define Z8_TMR_TOUT_T0 0x40 /* not supported */
+#define Z8_TMR_TOUT_T1 0x80 /* not supported */
#define Z8_TMR_TOUT_INTERNAL_CLK 0xc0 /* not supported */
#define Z8_P01M_P0L_MODE_MASK 0x03
@@ -117,7 +119,6 @@ DEFINE_DEVICE_TYPE(UB8830D, ub8830d_device, "ub8830d", "UB8830D")
DEFINE_DEVICE_TYPE(Z8611, z8611_device, "z8611", "Zilog Z8611")
DEFINE_DEVICE_TYPE(Z8671, z8671_device, "z8671", "Zilog Z8671")
DEFINE_DEVICE_TYPE(Z8681, z8681_device, "z8681", "Zilog Z8681")
-DEFINE_DEVICE_TYPE(Z8682, z8682_device, "z8682", "Zilog Z8682")
/***************************************************************************
@@ -169,7 +170,6 @@ z8_device::z8_device(const machine_config &mconfig, device_type type, const char
, m_input_cb{{*this}, {*this}, {*this}, {*this}}
, m_output_cb{{*this}, {*this}, {*this}, {*this}}
, m_rom_size(rom_size)
- , m_input{0xff, 0xff, 0xff, 0x0f}
{
assert(((rom_size - 1) & rom_size) == 0);
}
@@ -215,23 +215,6 @@ z8681_device::z8681_device(const machine_config &mconfig, const char *tag, devic
}
-z8682_device::z8682_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : z8_device(mconfig, Z8682, tag, owner, clock, 0x800, true)
-{
-}
-
-ROM_START(z8682)
- // Zilog admits that this nominally ROMless type uses a "small internal ROM"
- ROM_REGION(0x0800, "internal", ROMREGION_ERASEFF)
- ROM_LOAD("testrom.bin", 0x0000, 0x0038, CRC(b2239f28) SHA1(9d27957ba0f15657eac5a7295157af6ee51cb261) BAD_DUMP) // typed in from "Z8 MCU Test Mode" application note
-ROM_END
-
-const tiny_rom_entry *z8682_device::device_rom_region() const
-{
- return ROM_NAME(z8682);
-}
-
-
std::unique_ptr<util::disasm_interface> z8_device::create_disassembler()
{
return std::make_unique<z8_disassembler>();
@@ -435,257 +418,43 @@ void z8_device::p2_write(uint8_t data)
m_output_cb[2](0, data & mask, mask);
}
-void z8_device::p3_update_output()
-{
- uint8_t output = m_output[3] & 0xf0;
-
- if ((m_tmr & Z8_TMR_TOUT_MASK) != Z8_TMR_TOUT_OFF)
- output = (output & ~Z8_P3_TOUT) | (m_tout ? Z8_P3_TOUT : 0);
- if ((m_p3m & Z8_P3M_P3_SERIAL) != 0)
- output = (output & ~Z8_P3_SOUT) | ((m_transmit_sr == 0 || BIT(m_transmit_sr, 0)) ? Z8_P3_SOUT : 0);
-
- if (m_p3_output != output)
- {
- m_output_cb[3](0, output, output ^ m_p3_output);
- m_p3_output = output;
- }
-}
-
uint8_t z8_device::p3_read()
{
uint8_t mask = 0x0f;
- uint8_t inputs = m_input[3] & m_input_cb[3](0, mask);
// TODO: special port 3 modes
//if (!(m_p3m & 0x7c))
//{
//}
- return (inputs & mask) | (m_p3_output & ~mask);
+ if (mask)
+ m_input[3] = m_input_cb[3](0, mask);
+
+ return (m_input[3] & mask) | (m_output[3] & ~mask);
}
void z8_device::p3_write(uint8_t data)
{
- m_output[3] = data & 0xf0;
+ uint8_t mask = 0xf0;
+
+ m_output[3] = data;
// TODO: special port 3 modes
//if (!(m_p3m & 0x7c))
//{
//}
- p3_update_output();
-}
-
-bool z8_device::get_serial_in()
-{
- return (m_input[3] & Z8_P3_SIN) != 0;
-}
-
-void z8_device::sio_receive()
-{
- if (m_receive_started)
- {
- m_receive_count = (m_receive_count + 1) & 15;
- if (m_receive_count == 8)
- {
- if (m_receive_sr == 0)
- {
- if (!get_serial_in())
- {
- // start bit validated
- m_receive_sr |= 1 << 9;
- m_receive_parity = false;
- }
- else
- {
- // false start bit
- m_receive_started = false;
- m_receive_count = 0;
- }
- }
- else
- {
- // shift in data, parity or stop bit
- m_receive_sr >>= 1;
- if (get_serial_in())
- m_receive_sr |= 1 << 9;
-
- if (BIT(m_receive_sr, 0))
- {
- // received full character
- m_receive_buffer = (m_receive_sr & 0x1fe) >> 1;
- request_interrupt(3);
- m_receive_started = false;
- m_receive_count = 0;
- }
- else
- {
- if (BIT(m_receive_sr, 9))
- m_receive_parity = !m_receive_parity;
-
- // parity replaces received bit 7 if selected
- if (BIT(m_receive_sr, 1) && (m_p3m & Z8_P3M_PARITY) != 0)
- {
- if (m_receive_parity)
- m_receive_sr |= 1 << 9;
- else
- m_receive_sr &= ~(1 << 9);
- }
- }
- }
- }
- }
- else
- {
- // start bit is high-low transition
- m_receive_sr >>= 1;
- if (get_serial_in())
- m_receive_sr |= 1 << 9;
- else if (BIT(m_receive_sr, 8))
- {
- m_receive_started = true;
- m_receive_sr = 0;
- m_receive_count = 0;
- }
- }
-}
-
-void z8_device::sio_transmit()
-{
- if (m_transmit_sr == 0)
- return;
-
- m_transmit_count = (m_transmit_count + 1) & 15;
- if (m_transmit_count == 0)
- {
- m_transmit_sr >>= 1;
- if (m_transmit_sr == 0)
- request_interrupt(4);
- else
- {
- // parity replaces received bit 7 if selected
- if ((m_transmit_sr >> 1) == 3 && (m_p3m & Z8_P3M_PARITY) != 0)
- {
- if (m_transmit_parity)
- m_transmit_sr |= 1;
- else
- m_transmit_sr &= ~1;
- }
- else if (BIT(m_transmit_sr, 0))
- m_transmit_parity = !m_transmit_parity;
-
- // serial output
- p3_update_output();
- }
- }
+ if (mask)
+ m_output_cb[3](0, data & mask, mask);
}
uint8_t z8_device::sio_read()
{
- return m_receive_buffer;
+ return 0xff;
}
void z8_device::sio_write(uint8_t data)
{
- // overwrite shift register with data + 1 start bit + 2 stop bits
- m_transmit_sr = (m_transmit_sr & 1) | (uint16_t(data) << 2) | (3 << 10);
- m_transmit_parity = false;
-
- // synchronize the shift clock
- m_transmit_count = 15;
-}
-
-template <int T>
-void z8_device::timer_start()
-{
- unsigned prescaler = (m_pre[T] >> 2) ? (m_pre[T] >> 2) : 64;
- unsigned full_count = (m_count[T] ? m_count[T] - 1 : 255) * prescaler + (m_pre_count[T] ? m_pre_count[T] : 64);
- m_internal_timer[T]->adjust(cycles_to_attotime(4 * full_count));
-}
-
-template <int T>
-void z8_device::timer_stop()
-{
- if (!m_internal_timer[T]->enabled())
- return;
-
- unsigned prescaler = (m_pre[T] >> 2) ? (m_pre[T] >> 2) : 64;
- unsigned remaining = attotime_to_cycles(m_internal_timer[T]->remaining() / 4);
-
- m_count[T] = remaining / prescaler + 1;
- m_pre_count[T] = (remaining % prescaler + 1) & 0x3f;
-
- m_internal_timer[T]->enable(false);
-}
-
-template <int T>
-void z8_device::timer_end()
-{
- if ((m_tmr & Z8_TMR_TOUT_MASK) == (T == 0 ? Z8_TMR_TOUT_T0 : Z8_TMR_TOUT_T1))
- tout_toggle();
-
- if (T == 0 && (m_p3m & Z8_P3M_P3_SERIAL) != 0)
- {
- sio_receive();
- sio_transmit();
- }
- else
- request_interrupt(4 + T);
-
- m_pre_count[T] = m_pre[T] >> 2;
- if (m_pre[T] & Z8_PRE0_COUNT_MODULO_N)
- m_count[T] = m_t[T];
- else
- m_tmr &= ~(T == 0 ? Z8_TMR_ENABLE_T0 : Z8_TMR_ENABLE_T1);
-}
-
-void z8_device::t1_trigger()
-{
- switch (m_tmr & Z8_TMR_TIN_MASK)
- {
- case Z8_TMR_TIN_EXTERNAL_CLK:
- m_pre_count[1]--;
- if (m_pre_count[1] == 0)
- {
- m_pre_count[1] = m_pre[1];
- if ((m_tmr & Z8_TMR_ENABLE_T1) != 0)
- {
- m_count[1]--;
- if (m_count[1] == 0)
- timer_end<1>();
- }
- }
- break;
-
- case Z8_TMR_TIN_GATE:
- timer_stop<1>();
- break;
-
- case Z8_TMR_TIN_TRIGGER:
- if (m_internal_timer[1]->enabled())
- break;
-
- case Z8_TMR_TIN_RETRIGGER:
- if ((m_tmr & Z8_TMR_ENABLE_T1) != 0)
- {
- m_count[1] = m_t[1];
- m_pre_count[1] = m_pre[1] >> 2;
- timer_start<1>();
- }
- break;
- }
-}
-
-void z8_device::tout_init()
-{
- m_tout = true;
- p3_update_output();
-}
-
-void z8_device::tout_toggle()
-{
- m_tout = !m_tout;
- p3_update_output();
}
uint8_t z8_device::tmr_read()
@@ -695,80 +464,28 @@ uint8_t z8_device::tmr_read()
void z8_device::tmr_write(uint8_t data)
{
- m_tmr = data & ~(Z8_TMR_LOAD_T0 | Z8_TMR_LOAD_T1); // actually reset on next internal clock
-
- bool t1_internal = (m_pre[1] & Z8_PRE1_INTERNAL_CLOCK) != 0;
- bool t0_load = (data & Z8_TMR_LOAD_T0) != 0;
- bool t1_load = (data & Z8_TMR_LOAD_T1) != 0;
- bool t0_enable = (data & Z8_TMR_ENABLE_T0) != 0;
- bool t1_enable = (data & Z8_TMR_ENABLE_T1) != 0;
+ m_tmr = data;
- if (!t1_internal && ((data & Z8_TMR_TIN_MASK) == Z8_TMR_TIN_GATE))
- {
- if ((m_input[3] & Z8_P3_TIN) != 0)
- t1_internal = true;
- else
- t1_enable = false;
- }
-
- if (t0_load)
+ if (data & Z8_TMR_LOAD_T0)
{
m_count[0] = m_t[0];
- m_pre_count[0] = m_pre[0] >> 2;
-
- if ((m_pre[0] & Z8_PRE0_COUNT_MODULO_N) != 0)
- {
- unsigned prescaler = (m_pre[0] >> 2) ? (m_pre[0] >> 2) : 64;
- unsigned count = (m_t[0] ? m_t[0] : 256) * prescaler;
- logerror("(%04X): Load T0 at %.2f Hz\n", m_ppc, clock() / 8.0 / count);
- }
-
- if ((data & Z8_TMR_TOUT_MASK) == Z8_TMR_TOUT_T0)
- tout_init();
+ m_t0_timer->adjust(attotime::zero, 0, cycles_to_attotime(4 * ((m_pre[0] >> 2) + 1)));
}
- if (t0_enable)
- {
- if (t0_load || !m_internal_timer[0]->enabled())
- timer_start<0>();
- }
- else
- timer_stop<0>();
+ m_t0_timer->enable(data & Z8_TMR_ENABLE_T0);
- if (t1_load)
+ if (data & Z8_TMR_LOAD_T1)
{
m_count[1] = m_t[1];
- m_pre_count[1] = m_pre[1] >> 2;
-
- if (t1_internal && (m_pre[1] & Z8_PRE0_COUNT_MODULO_N) != 0)
- {
- unsigned prescaler = (m_pre[1] >> 2) ? (m_pre[1] >> 2) : 64;
- unsigned count = (m_t[1] ? m_t[1] : 256) * prescaler;
- logerror("(%04X): Load T1 at %.2f Hz\n", m_ppc, clock() / 8.0 / count);
- }
-
- if ((data & Z8_TMR_TOUT_MASK) == Z8_TMR_TOUT_T1)
- tout_init();
+ m_t1_timer->adjust(attotime::zero, 0, cycles_to_attotime(4 * ((m_pre[1] >> 2) + 1)));
}
- if (t1_enable)
- {
- if (t1_internal && (t1_load || !m_internal_timer[1]->enabled()))
- timer_start<1>();
- }
- else
- timer_stop<1>();
+ m_t1_timer->enable(data & Z8_TMR_ENABLE_T1);
}
uint8_t z8_device::t0_read()
{
- if (!m_internal_timer[0]->enabled())
- return m_count[0];
-
- unsigned prescaler = (m_pre[0] >> 2) ? (m_pre[0] >> 2) : 64;
- unsigned remaining = attotime_to_cycles(m_internal_timer[0]->remaining() / 4);
-
- return remaining / prescaler + 1;
+ return m_count[0];
}
void z8_device::t0_write(uint8_t data)
@@ -778,13 +495,7 @@ void z8_device::t0_write(uint8_t data)
uint8_t z8_device::t1_read()
{
- if (!m_internal_timer[1]->enabled())
- return m_count[1];
-
- unsigned prescaler = (m_pre[1] >> 2) ? (m_pre[1] >> 2) : 64;
- unsigned remaining = attotime_to_cycles(m_internal_timer[1]->remaining() / 4);
-
- return remaining / prescaler + 1;
+ return m_count[1];
}
void z8_device::t1_write(uint8_t data)
@@ -794,28 +505,12 @@ void z8_device::t1_write(uint8_t data)
void z8_device::pre0_write(uint8_t data)
{
- if (m_internal_timer[0]->enabled())
- {
- timer_stop<0>();
- m_pre[0] = data;
- timer_start<0>();
- }
- else
- m_pre[0] = data;
+ m_pre[0] = data;
}
void z8_device::pre1_write(uint8_t data)
{
- bool was_enabled = m_internal_timer[1]->enabled();
- if (was_enabled)
- timer_stop<1>();
-
m_pre[1] = data;
-
- if ((data & Z8_PRE1_INTERNAL_CLOCK) != 0
- ? (m_tmr & Z8_TMR_ENABLE_T1) != 0
- : was_enabled && (m_tmr & Z8_TMR_TIN_MASK) != Z8_TMR_TIN_EXTERNAL_CLK)
- timer_start<1>();
}
void z8_device::p01m_write(uint8_t data)
@@ -830,16 +525,7 @@ void z8_device::p2m_write(uint8_t data)
void z8_device::p3m_write(uint8_t data)
{
- if ((data & Z8_P3M_P3_SERIAL) == 0)
- {
- m_transmit_sr = 0;
- m_transmit_count = 0;
- m_receive_started = false;
- m_receive_count = 0;
- }
-
m_p3m = data;
- p3_update_output();
}
void z8_device::ipr_write(uint8_t data)
@@ -919,12 +605,12 @@ void z8_device::register_pair_write(uint8_t offset, uint16_t data)
m_regs->write_word_unaligned(offset, data);
}
-uint8_t z8_device::get_working_register(int offset) const
+uint8_t z8_device::get_working_register(int offset)
{
return (m_rp & 0xf0) | (offset & 0x0f);
}
-uint8_t z8_device::get_register(uint8_t offset) const
+uint8_t z8_device::get_register(uint8_t offset)
{
if ((offset & 0xf0) == 0xe0)
return get_working_register(offset & 0x0f);
@@ -1152,17 +838,29 @@ const z8_device::z8_opcode_map z8_device::Z8601_OPCODE_MAP[256] =
TIMER CALLBACKS
***************************************************************************/
-template <int T>
-TIMER_CALLBACK_MEMBER(z8_device::timeout)
+TIMER_CALLBACK_MEMBER( z8_device::t0_tick )
{
- timer_end<T>();
+ m_count[0]--;
- if (m_pre[T] & Z8_PRE0_COUNT_MODULO_N)
- timer_start<T>();
- else
+ if (m_count[0] == 0)
{
- m_count[T] = 0;
- m_internal_timer[T]->enable(false);
+ m_count[0] = m_t[0];
+ m_t0_timer->adjust(attotime::zero, 0, cycles_to_attotime(4 * ((m_pre[0] >> 2) + 1)));
+ m_t0_timer->enable(m_pre[0] & Z8_PRE0_COUNT_MODULO_N);
+ request_interrupt(4);
+ }
+}
+
+TIMER_CALLBACK_MEMBER( z8_device::t1_tick )
+{
+ m_count[1]--;
+
+ if (m_count[1] == 0)
+ {
+ m_count[1] = m_t[1];
+ m_t1_timer->adjust(attotime::zero, 0, cycles_to_attotime(4 * ((m_pre[1] >> 2) + 1)));
+ m_t1_timer->enable(m_pre[1] & Z8_PRE0_COUNT_MODULO_N);
+ request_interrupt(5);
}
}
@@ -1202,7 +900,6 @@ void z8_device::device_start()
state_add(Z8_PRE1, "PRE1", m_pre[1]);
state_add(Z8_T1, "T1", m_t[1]);
state_add(Z8_TMR, "TMR", m_tmr);
- state_add(Z8_TOUT, "TOUT", m_tout);
for (int regnum = 0; regnum < 16; regnum++)
state_add(Z8_R0 + regnum, string_format("R%d", regnum).c_str(), m_fake_r[regnum]).callimport().callexport();
@@ -1215,16 +912,16 @@ void z8_device::device_start()
m_regs = &space(AS_IO);
/* allocate timers */
- m_internal_timer[0] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(z8_device::timeout<0>), this));
- m_internal_timer[1] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(z8_device::timeout<1>), this));
+ m_t0_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(z8_device::t0_tick), this));
+ m_t1_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(z8_device::t1_tick), this));
/* Clear state */
std::fill(std::begin(m_irq_line), std::end(m_irq_line), CLEAR_LINE);
+ std::fill(std::begin(m_input), std::end(m_input), 0);
std::fill(std::begin(m_output), std::end(m_output), 0);
std::fill(std::begin(m_t), std::end(m_t), 0);
std::fill(std::begin(m_count), std::end(m_count), 0);
std::fill(std::begin(m_pre), std::end(m_pre), 0);
- std::fill(std::begin(m_pre_count), std::end(m_pre_count), 0);
std::fill(std::begin(m_fake_r), std::end(m_fake_r), 0);
m_pc = 0;
m_ppc = 0;
@@ -1234,17 +931,7 @@ void z8_device::device_start()
m_p01m = 0;
m_p2m = 0;
m_p3m = 0;
- m_p3_output = 0;
m_tmr = 0;
- m_tout = true;
- m_transmit_sr = 0;
- m_transmit_count = 0;
- m_transmit_parity = false;
- m_receive_buffer = 0;
- m_receive_sr = 0;
- m_receive_count = 0;
- m_receive_parity = false;
- m_receive_started = false;
m_irq_taken = false;
m_irq_initialized = false;
@@ -1259,21 +946,10 @@ void z8_device::device_start()
save_item(NAME(m_p01m));
save_item(NAME(m_p2m));
save_item(NAME(m_p3m));
- save_item(NAME(m_p3_output));
save_item(NAME(m_tmr));
save_item(NAME(m_t));
- save_item(NAME(m_tout));
- save_item(NAME(m_transmit_sr));
- save_item(NAME(m_transmit_count));
- save_item(NAME(m_transmit_parity));
- save_item(NAME(m_receive_buffer));
- save_item(NAME(m_receive_sr));
- save_item(NAME(m_receive_count));
- save_item(NAME(m_receive_parity));
- save_item(NAME(m_receive_started));
save_item(NAME(m_count));
save_item(NAME(m_pre));
- save_item(NAME(m_pre_count));
save_item(NAME(m_irq_line));
save_item(NAME(m_irq_taken));
save_item(NAME(m_irq_initialized));
@@ -1303,7 +979,6 @@ void z8_device::take_interrupt(int irq)
// acknowledge the IRQ
m_irq &= ~(1 << irq);
- standard_irq_callback(irq);
// get the interrupt vector address
uint16_t vector = irq * 2;
@@ -1474,16 +1149,14 @@ void z8_device::device_reset()
m_imr &= ~Z8_IMR_ENABLE;
m_irq_initialized = false;
- m_pre[0] &= ~Z8_PRE0_COUNT_MODULO_N;
- m_pre[1] &= ~(Z8_PRE1_COUNT_MODULO_N | Z8_PRE1_INTERNAL_CLOCK);
- m_tmr = 0x00;
- timer_stop<0>();
- timer_stop<1>();
-
- m_output[3] = 0xf0;
p01m_write(0x4d);
p2m_write(0xff);
p3m_write(0x00);
+ p3_write(m_output[3] | 0xf0);
+
+ m_pre[0] &= ~Z8_PRE0_COUNT_MODULO_N;
+ m_pre[1] &= ~(Z8_PRE1_COUNT_MODULO_N | Z8_PRE1_INTERNAL_CLOCK);
+ tmr_write(0x00);
}
@@ -1507,7 +1180,7 @@ void z8_device::state_import(const device_state_entry &entry)
case Z8_R0: case Z8_R1: case Z8_R2: case Z8_R3: case Z8_R4: case Z8_R5: case Z8_R6: case Z8_R7: case Z8_R8: case Z8_R9: case Z8_R10: case Z8_R11: case Z8_R12: case Z8_R13: case Z8_R14: case Z8_R15:
{
auto dis = machine().disable_side_effects();
- register_write((m_rp & 0xf0) + (entry.index() - Z8_R0), m_fake_r[entry.index() - Z8_R0]);
+ register_write(m_rp + (entry.index() - Z8_R0), m_fake_r[entry.index() - Z8_R0]);
break;
}
@@ -1523,7 +1196,7 @@ void z8_device::state_export(const device_state_entry &entry)
case Z8_R0: case Z8_R1: case Z8_R2: case Z8_R3: case Z8_R4: case Z8_R5: case Z8_R6: case Z8_R7: case Z8_R8: case Z8_R9: case Z8_R10: case Z8_R11: case Z8_R12: case Z8_R13: case Z8_R14: case Z8_R15:
{
auto dis = machine().disable_side_effects();
- m_fake_r[entry.index() - Z8_R0] = register_read((m_rp & 0xf0) + (entry.index() - Z8_R0));
+ m_fake_r[entry.index() - Z8_R0] = register_read(m_rp + (entry.index() - Z8_R0));
break;
}
@@ -1551,60 +1224,29 @@ void z8_device::execute_set_input(int inputnum, int state)
{
switch ( inputnum )
{
- case INPUT_LINE_IRQ0:
- if (state != CLEAR_LINE && m_irq_line[0] == CLEAR_LINE)
- request_interrupt(0);
- m_irq_line[0] = state;
-
- if (state != CLEAR_LINE && (m_input[3] & Z8_P3_IRQ0) != 0)
- m_input[3] &= ~Z8_P3_IRQ0;
- else if (state == CLEAR_LINE && (m_input[3] & Z8_P3_IRQ0) == 0)
- m_input[3] |= Z8_P3_IRQ0;
-
- break;
-
- case INPUT_LINE_IRQ1:
- if (state != CLEAR_LINE && m_irq_line[1] == CLEAR_LINE)
- request_interrupt(1);
- m_irq_line[1] = state;
-
- if (state != CLEAR_LINE && (m_input[3] & Z8_P3_IRQ1) != 0)
- m_input[3] &= ~Z8_P3_IRQ1;
- else if (state == CLEAR_LINE && (m_input[3] & Z8_P3_IRQ1) == 0)
- m_input[3] |= Z8_P3_IRQ1;
-
- break;
-
- case INPUT_LINE_IRQ2:
- if (state != CLEAR_LINE && m_irq_line[2] == CLEAR_LINE)
- request_interrupt(2);
- m_irq_line[2] = state;
-
- if (state != CLEAR_LINE && (m_input[3] & Z8_P3_IRQ2) != 0)
- {
- m_input[3] &= ~Z8_P3_IRQ2;
- if ((m_pre[1] & Z8_PRE1_INTERNAL_CLOCK) == 0)
- t1_trigger();
- }
- else if (state == CLEAR_LINE && (m_input[3] & Z8_P3_IRQ2) == 0)
- {
- m_input[3] |= Z8_P3_IRQ2;
- if ((m_pre[1] & Z8_PRE1_INTERNAL_CLOCK) == 0 && (m_tmr & Z8_TMR_TIN_MASK) == Z8_TMR_TIN_GATE)
- timer_start<1>();
- }
+ case INPUT_LINE_IRQ0:
+ if (state != CLEAR_LINE && m_irq_line[0] == CLEAR_LINE)
+ request_interrupt(0);
+ m_irq_line[0] = state;
+ break;
- break;
+ case INPUT_LINE_IRQ1:
+ if (state != CLEAR_LINE && m_irq_line[1] == CLEAR_LINE)
+ request_interrupt(1);
+ m_irq_line[1] = state;
+ break;
- case INPUT_LINE_IRQ3:
- if (state != CLEAR_LINE && m_irq_line[3] == CLEAR_LINE && (m_p3m & Z8_P3M_P3_SERIAL) == 0)
- request_interrupt(3);
- m_irq_line[3] = state;
+ case INPUT_LINE_IRQ2:
+ if (state != CLEAR_LINE && m_irq_line[2] == CLEAR_LINE)
+ request_interrupt(2);
+ m_irq_line[2] = state;
+ break;
- if (state != CLEAR_LINE && (m_input[3] & Z8_P3_IRQ3) != 0)
- m_input[3] &= ~Z8_P3_IRQ3;
- else if (state == CLEAR_LINE && (m_input[3] & Z8_P3_IRQ3) == 0)
- m_input[3] |= Z8_P3_IRQ3;
+ case INPUT_LINE_IRQ3:
+ if (state != CLEAR_LINE && m_irq_line[3] == CLEAR_LINE)
+ request_interrupt(3);
+ m_irq_line[3] = state;
+ break;
- break;
}
}
diff --git a/src/devices/cpu/z8/z8.h b/src/devices/cpu/z8/z8.h
index c74f3ec839f..0bdd235d7c2 100644
--- a/src/devices/cpu/z8/z8.h
+++ b/src/devices/cpu/z8/z8.h
@@ -1,5 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:Curt Coder, AJR
+// copyright-holders:Curt Coder
/**********************************************************************
Zilog Z8 Single-Chip MCU emulation
@@ -32,7 +32,7 @@ protected:
Z8_IMR, Z8_IRQ, Z8_IPR,
Z8_P0, Z8_P1, Z8_P2, Z8_P3,
Z8_P01M, Z8_P3M, Z8_P2M,
- Z8_PRE0, Z8_T0, Z8_PRE1, Z8_T1, Z8_TMR, Z8_TOUT,
+ Z8_PRE0, Z8_T0, Z8_PRE1, Z8_T1, Z8_TMR,
Z8_R0, Z8_R1, Z8_R2, Z8_R3, Z8_R4, Z8_R5, Z8_R6, Z8_R7, Z8_R8, Z8_R9, Z8_R10, Z8_R11, Z8_R12, Z8_R13, Z8_R14, Z8_R15
};
@@ -101,33 +101,18 @@ private:
uint8_t m_p01m; // port 0/1 mode
uint8_t m_p2m; // port 2 mode
uint8_t m_p3m; // port 3 mode
- uint8_t m_p3_output; // port 3 output (alternate functions included)
// timer registers
uint8_t m_tmr; // timer mode
uint8_t m_t[2]; // initial values
uint8_t m_count[2]; // current counts
uint8_t m_pre[2]; // prescalers
- uint8_t m_pre_count[2]; // prescaler counts
- bool m_tout; // toggle output
-
- // serial transmitter registers
- uint16_t m_transmit_sr; // transmitter shift register
- uint8_t m_transmit_count; // counter for transmitter timing
- bool m_transmit_parity; // transmitter parity calculation
-
- // serial receiver registers
- uint8_t m_receive_buffer; // received character
- uint16_t m_receive_sr; // receiver shift register
- uint8_t m_receive_count; // counter for receiver timing
- bool m_receive_parity; // receiver parity calculation
- bool m_receive_started; // true if receiver has seen start bit
// fake registers
uint8_t m_fake_r[16]; // fake working registers
// interrupts
- int m_irq_line[4];
+ int m_irq_line[4]; // IRQ line state
bool m_irq_taken;
bool m_irq_initialized; // IRQ must be unlocked by EI after reset
@@ -135,20 +120,11 @@ private:
int32_t m_icount; // instruction counter
// timers
- emu_timer *m_internal_timer[2];
-
- bool get_serial_in();
- void sio_receive();
- void sio_transmit();
-
- template <int T> void timer_start();
- template <int T> void timer_stop();
- template <int T> void timer_end();
- void t1_trigger();
- void tout_init();
- void tout_toggle();
+ emu_timer *m_t0_timer;
+ emu_timer *m_t1_timer;
- template <int T> TIMER_CALLBACK_MEMBER(timeout);
+ TIMER_CALLBACK_MEMBER( t0_tick );
+ TIMER_CALLBACK_MEMBER( t1_tick );
void request_interrupt(int irq);
void take_interrupt(int irq);
@@ -162,7 +138,6 @@ private:
void p2_write(uint8_t data);
uint8_t p3_read();
void p3_write(uint8_t data);
- void p3_update_output();
uint8_t sio_read();
void sio_write(uint8_t data);
uint8_t tmr_read();
@@ -198,8 +173,8 @@ private:
inline uint16_t register_pair_read(uint8_t offset);
inline void register_write(uint8_t offset, uint8_t data) { m_regs->write_byte(offset, data); }
inline void register_pair_write(uint8_t offset, uint16_t data);
- inline uint8_t get_working_register(int offset) const;
- inline uint8_t get_register(uint8_t offset) const;
+ inline uint8_t get_working_register(int offset);
+ inline uint8_t get_register(uint8_t offset);
inline uint8_t get_intermediate_register(int offset);
inline void stack_push_byte(uint8_t src);
inline void stack_push_word(uint16_t src);
@@ -421,16 +396,6 @@ public:
};
-class z8682_device : public z8_device
-{
-public:
- z8682_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
-
-protected:
- const tiny_rom_entry *device_rom_region() const override;
-};
-
-
// Zilog Z8601
DECLARE_DEVICE_TYPE(Z8601, z8601_device)
@@ -446,7 +411,4 @@ DECLARE_DEVICE_TYPE(Z8671, z8671_device)
// Zilog Z8681 ROMless
DECLARE_DEVICE_TYPE(Z8681, z8681_device)
-// Zilog Z8682 ROMless (boot to 0812H)
-DECLARE_DEVICE_TYPE(Z8682, z8682_device)
-
#endif // MAME_CPU_Z8_Z8_H
diff --git a/src/devices/cpu/z8/z8dasm.cpp b/src/devices/cpu/z8/z8dasm.cpp
index 08e50ca1eae..35d18fab880 100644
--- a/src/devices/cpu/z8/z8dasm.cpp
+++ b/src/devices/cpu/z8/z8dasm.cpp
@@ -39,7 +39,6 @@ const char *const z8_disassembler::CONDITION_CODE[16] =
***************************************************************************/
#define r "R%u"
-#define rr "RR%u"
#define Ir "@R%u"
#define R "%02Xh"
#define RR "%02Xh"
@@ -65,7 +64,7 @@ const char *const z8_disassembler::CONDITION_CODE[16] =
#define arg_Ir(_value) ARG(Ir, _value)
#define arg_Irr(_value) ARG(Irr, _value & 0x0f)
#define arg_R(_value) if ((_value & 0xf0) == 0xe0) ARG(r, _value & 0x0f) else if ((_value < 4) || (_value >= 0xf0)) arg_name(_value) else ARG(R, _value)
-#define arg_RR(_value) if ((_value & 0xf0) == 0xe0) ARG(rr, _value & 0x0f) else ARG(R, _value)
+#define arg_RR(_value) if ((_value & 0xf0) == 0xe0) ARG(r, _value & 0x0f) else ARG(R, _value)
#define arg_IR(_value) if ((_value & 0xf0) == 0xe0) ARG(Ir, _value & 0x0f) else ARG(IR, _value)
#define arg_IRR(_value) if ((_value & 0xf0) == 0xe0) ARG(Irr, _value & 0x0f) else ARG(IRR, _value)
#define arg_IM(_value) ARG(IM, _value)
@@ -367,7 +366,7 @@ offs_t z8_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_
case 0xf2: illegal; break;
case 0xf3: mnemonic("LD"); arg_Ir(B0H); arg_r(B0L); bytes(2); break;
case 0xf4: illegal; break;
- case 0xf5: mnemonic("LD"); arg_IR(B1); arg_R(B0); bytes(3); break;
+ case 0xf5: mnemonic("LD"); arg_IR(B0); arg_R(B1); bytes(3); break;
case 0xf6: illegal; break;
case 0xf7: illegal; break;
case 0xf8: mnemonic("LD"); arg_r(OPH); arg_R(B0); bytes(2); break;
diff --git a/src/devices/cpu/z80/kl5c80a12.cpp b/src/devices/cpu/z80/kl5c80a12.cpp
index a061f3e7cf3..44e1d9256b3 100644
--- a/src/devices/cpu/z80/kl5c80a12.cpp
+++ b/src/devices/cpu/z80/kl5c80a12.cpp
@@ -46,6 +46,5 @@ void kl5c80a12_device::device_reset()
/* CPU interface */
-void kl5c80a12_device::device_add_mconfig(machine_config &config)
-{
-}
+MACHINE_CONFIG_START(kl5c80a12_device::device_add_mconfig)
+MACHINE_CONFIG_END