diff options
Diffstat (limited to 'src/devices/cpu')
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 ¶ms) @@ -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 ¶ms) -{ - 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 ¶ms) 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 ¶ms) -{ - 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 ¶ms) 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 ¶ms, offs_t &p) +void m6x09_disassembler::indirect(std::ostream &stream, uint8_t pb, const data_buffer ¶ms, 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 ¶ms, offs_t &p) +void konami_disassembler::indirect(std::ostream &stream, uint8_t mode, const data_buffer ¶ms, 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 ¶ms, offs_t &p) = 0; + virtual void indirect(std::ostream &stream, uint8_t pb, const data_buffer ¶ms, 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 ¶ms, offs_t &p) override; + virtual void indirect(std::ostream &stream, uint8_t pb, const data_buffer ¶ms, 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 ¶ms, offs_t &p) override; + virtual void indirect(std::ostream &stream, uint8_t pb, const data_buffer ¶ms, 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 ¶ms) -{ - 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 ¶ms) 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 |