summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
author mamehaze <140764005+mamehaze@users.noreply.github.com>2024-05-08 04:24:43 +0100
committer GitHub <noreply@github.com>2024-05-08 10:24:43 +0700
commit37c3bbb02d5b804034ffc6a6de21f54238eddfc8 (patch)
treea9c2a6aebc5f088102aada34a3a17b5361f0a88e /src
parentc34c2144e136f3bd2ed4fe6a8011e64d7d3264c8 (diff)
add MIPS-X CPU and Tomy Kiss-Site system (#12331)
* cpu/mipsx: add MIPS-X CPU stub device and disassembler [David Haywood] New systems marked not working ------------------------------ Tomy Kiss-Site [TeamEurope] New software list items marked not working ------------------------------------------ kisssite_cd.xml Anime Karaoke Series - Pocket Monsters 1 (Japan) [redump.org] Dance Karaoke Series 01 - Mickey Mouse March - Eurobeat Version and White Love (Japan) [redump.org] Dance Karaoke Series 02 - LOVE Machine and Goldfinger '99 (Japan) [redump.org] Dance Karaoke Series 03 - Happy Summer Wedding and Nanda Kanda (Japan) [redump.org] Dance Karaoke Series 04 - Koi no Dance Site and Night of Fire (Japan) [redump.org] Dance Karaoke Series 05 - Fly High - Euro-Power Mix and Respect the Power of Love (Japan) [redump.org] Dance Karaoke Series 06 - Chokotto Love and My Graduation (Japan) [redump.org] Dance Karaoke Series 07 - Daite Hold on Me! and Try Me - Watashi o Shinjite (Japan) [redump.org] Dance Karaoke Series 08 - Akai Nikkichou and Time After Time (Japan) [redump.org] Dance Karaoke Series 09 - Kiiroi Osora de Boom Boom Boom and Don't Wanna Cry (Japan) [redump.org] Dance Karaoke Series 10 - Manatsu no Kousen and A Walk in the Park (Japan) [redump.org] Dance Karaoke Series 11 - Com'on! Be My Girl! and Crazy Beat Goes On! (Japan) [redump.org] Dance Karaoke Series 12 - Kore ga Watashi no Ikiru Michi and Ai no Shirushi (Japan) [redump.org] Dance Karaoke Series 13 - UFO and Southpaw (Japan) [redump.org] Dance Karaoke Series 14 - Body and Soul and Long Way Home (Japan) [redump.org] Dance Karaoke Series 15 - Steady and Alive (Japan) [redump.org] Dance Karaoke Series 16 - Wake Me Up! and Timing (Japan) [redump.org] Dance Karaoke Series 17 - Red Beat of My Life and Bright Daylight (Japan) [redump.org] Dance Karaoke Series 18 - Nakatta Koto ni Shite and Otome Pasta ni Kandou (Japan) [redump.org] Dance Karaoke Series 19 - Ride on Time and Give Me a Shake (Japan) [redump.org] Dance Karaoke Series 20 - Love 2000 and Seishun Jidai 1.2.3! (Japan) [redump.org] Dance Karaoke Series 21 - I Wish and Luv Is Magic (Japan) [redump.org] Dance Karaoke Series 22 - Barashoku no Hibi and Ginga no Chikai (Japan) [redump.org] Dance Karaoke Series 23 - Please Smile Again and Treasure (Japan) [redump.org] Dance Karaoke Series 24 - Koi wa Thrill, Shock, Suspense and Love is Energy! (Japan) [redump.org] Dance Karaoke Series 25 - Renai Revolution 21 and S.O.S (Japan) [redump.org] Dance Karaoke Series - Best Selection (Japan) [redump.org] Movie Karaoke Series - Best Selection - Ballade 1 (Japan) [redump.org] Oha Star Series 01 - Zonapara (Japan) [redump.org] Oha Star Series 02 - Oha Ska! (Japan) [redump.org]
Diffstat (limited to 'src')
-rw-r--r--src/devices/cpu/mipsx/mipsx.cpp62
-rw-r--r--src/devices/cpu/mipsx/mipsx.h38
-rw-r--r--src/devices/cpu/mipsx/mipsxdasm.cpp578
-rw-r--r--src/devices/cpu/mipsx/mipsxdasm.h33
-rw-r--r--src/mame/mame.lst3
-rw-r--r--src/mame/tomy/kisssite.cpp106
-rw-r--r--src/tools/unidasm.cpp2
7 files changed, 822 insertions, 0 deletions
diff --git a/src/devices/cpu/mipsx/mipsx.cpp b/src/devices/cpu/mipsx/mipsx.cpp
new file mode 100644
index 00000000000..72e45f84d1a
--- /dev/null
+++ b/src/devices/cpu/mipsx/mipsx.cpp
@@ -0,0 +1,62 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+
+// https://apps.dtic.mil/sti/tr/pdf/ADA181619.pdf
+
+#include "emu.h"
+#include "mipsx.h"
+#include "mipsxdasm.h"
+
+DEFINE_DEVICE_TYPE(MIPSX, mipsx_cpu_device, "mipsx", "MIPS-X")
+
+mipsx_cpu_device::mipsx_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : cpu_device(mconfig, MIPSX, tag, owner, clock)
+ , m_program_config("program", ENDIANNESS_BIG, 32, 24, 0)
+ , m_pc(0)
+ , m_program(nullptr)
+ , m_icount(0)
+{
+}
+
+std::unique_ptr<util::disasm_interface> mipsx_cpu_device::create_disassembler()
+{
+ return std::make_unique<mipsx_disassembler>();
+}
+
+/*****************************************************************************/
+
+device_memory_interface::space_config_vector mipsx_cpu_device::memory_space_config() const
+{
+ return space_config_vector {
+ std::make_pair(AS_PROGRAM, &m_program_config)
+ };
+}
+
+
+/*****************************************************************************/
+
+void mipsx_cpu_device::device_start()
+{
+ m_program = &space(AS_PROGRAM);
+
+ state_add(STATE_GENPC, "GENPC", m_pc).formatstr("%08X");
+ state_add(STATE_GENPCBASE, "CURPC", m_pc).callexport().noshow();
+
+ set_icountptr(m_icount);
+}
+
+void mipsx_cpu_device::device_reset()
+{
+}
+
+/*****************************************************************************/
+
+void mipsx_cpu_device::execute_run()
+{
+ while (m_icount > 0)
+ {
+ debugger_instruction_hook(m_pc);
+ m_pc += 4;
+ m_icount--;
+ }
+}
diff --git a/src/devices/cpu/mipsx/mipsx.h b/src/devices/cpu/mipsx/mipsx.h
new file mode 100644
index 00000000000..208bc2249eb
--- /dev/null
+++ b/src/devices/cpu/mipsx/mipsx.h
@@ -0,0 +1,38 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+
+#ifndef MAME_CPU_MIPSX_MIPSX_H
+#define MAME_CPU_MIPSX_MIPSX_H
+
+#pragma once
+
+class mipsx_cpu_device : public cpu_device
+{
+public:
+ mipsx_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+protected:
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
+ virtual uint32_t execute_min_cycles() const noexcept override { return 5; }
+ virtual uint32_t execute_max_cycles() const noexcept override { return 5; }
+ virtual uint32_t execute_input_lines() const noexcept override { return 0; }
+ virtual void execute_run() override;
+
+ virtual space_config_vector memory_space_config() const override;
+
+ virtual std::unique_ptr<util::disasm_interface> create_disassembler() override;
+
+private:
+ address_space_config m_program_config;
+
+ uint32_t m_pc;
+
+ address_space *m_program;
+ int m_icount;
+};
+
+DECLARE_DEVICE_TYPE(MIPSX, mipsx_cpu_device)
+
+#endif // MAME_CPU_MIPSX_MIPSX_H
diff --git a/src/devices/cpu/mipsx/mipsxdasm.cpp b/src/devices/cpu/mipsx/mipsxdasm.cpp
new file mode 100644
index 00000000000..dbd8c9e25a3
--- /dev/null
+++ b/src/devices/cpu/mipsx/mipsxdasm.cpp
@@ -0,0 +1,578 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+
+#include "emu.h"
+#include "mipsxdasm.h"
+
+static const bool SHOW_R0_AS_0 = false;
+
+u32 mipsx_disassembler::opcode_alignment() const
+{
+ return 4;
+}
+
+int mipsx_disassembler::get_ty(u32 opcode)
+{
+ return BIT(opcode, 30, 2);
+}
+
+int mipsx_disassembler::get_op(u32 opcode)
+{
+ return BIT(opcode, 27, 3);
+}
+
+int mipsx_disassembler::get_src1(u32 opcode)
+{
+ return BIT(opcode, 22, 5);
+}
+
+int mipsx_disassembler::get_src2_dest(u32 opcode)
+{
+ return BIT(opcode, 17, 5);
+}
+
+int mipsx_disassembler::get_compute_dest(u32 opcode)
+{
+ return BIT(opcode, 12, 5);
+}
+
+int mipsx_disassembler::get_compute_compfunc(u32 opcode)
+{
+ return BIT(opcode, 0, 12);
+}
+
+int mipsx_disassembler::get_offset(u32 opcode)
+{
+ return BIT(opcode, 0, 17);
+}
+
+int mipsx_disassembler::get_sq(u32 opcode)
+{
+ return BIT(opcode, 16, 1);
+}
+
+int mipsx_disassembler::get_asr_amount(int shift)
+{
+ // TODO
+ return shift;
+}
+
+int mipsx_disassembler::get_sh_amount(int shift)
+{
+ // TODO
+ return shift;
+}
+
+static const char *regnames[32] = { "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 *mipsx_disassembler::get_regname(u8 reg)
+{
+ // general purpose register 0 just acts as a constant 0, it can't be changed, if desired simply show it as a non-canonical 0 for readability
+ if ((reg == 0) && (SHOW_R0_AS_0))
+ return "#0";
+
+ return regnames[reg];
+}
+
+offs_t mipsx_disassembler::disassemble(std::ostream& stream, offs_t pc, const data_buffer& opcodes, const data_buffer& params)
+{
+ const u32 opcode = opcodes.r32(pc);
+ const u8 ty = get_ty(opcode);
+
+ switch (ty)
+ {
+ case 0:
+ {
+ const u8 op = get_op(opcode);
+ const int disp = util::sext(opcode, 16) * 4;
+ const u32 basepc = pc + 8;
+ const int src1 = get_src1(opcode);
+ const int src2 = get_src2_dest(opcode);
+ const std::string squash = get_sq(opcode) ? "sq" : "";
+
+ switch (op)
+ {
+ case 1:
+ {
+ if ((src1 == 0) && (src2 == 0))
+ {
+ // beq #0, #0, offset is used as an alias for unconditional branch
+ util::stream_format(stream, "bra%s 0x%08x", squash, basepc + disp);
+ }
+ else
+ {
+ util::stream_format(stream, "beq%s %s,%s,0x%08x", squash, get_regname(src1), get_regname(src2), basepc + disp);
+ }
+ break;
+ }
+ case 2:
+ {
+ util::stream_format(stream, "bhs%s %s,%s,0x%08x", squash, get_regname(src1), get_regname(src2), basepc + disp);
+ break;
+ }
+ case 3:
+ {
+ util::stream_format(stream, "blt%s %s,%s,0x%08x", squash, get_regname(src1), get_regname(src2), basepc + disp);
+ break;
+ }
+ case 5:
+ {
+ util::stream_format(stream, "bne%s %s,%s,0x%08x", squash, get_regname(src1), get_regname(src2), basepc + disp);
+ break;
+ }
+ case 6:
+ {
+ util::stream_format(stream, "blo%s %s,%s,0x%08x", squash, get_regname(src1), get_regname(src2), basepc + disp);
+ break;
+ }
+ case 7:
+ {
+ util::stream_format(stream, "bge%s %s,%s,0x%08x", squash, get_regname(src1), get_regname(src2), basepc + disp);
+ break;
+ }
+
+ default:
+ {
+ util::stream_format(stream, "Unhandled TY0 (%08x)", opcode);
+ break;
+ }
+ }
+ break;
+ }
+
+ case 1:
+ {
+ u8 op = get_op(opcode);
+
+ switch (op)
+ {
+ case 0:
+ {
+ const u16 comp = get_compute_compfunc(opcode);
+ if (comp == 0x0e6)
+ {
+ u8 src1 = get_src1(opcode);
+
+ if (src1 == 0)
+ {
+ util::stream_format(stream, "mstart %s,%s", get_regname(get_src2_dest(opcode)), get_regname(get_compute_dest(opcode)));
+ }
+ else
+ {
+ util::stream_format(stream, "illegal mstart form");
+ }
+ }
+ else if (comp == 0x099)
+ {
+ util::stream_format(stream, "mstep %s,%s,%s", get_regname(get_src1(opcode)), get_regname(get_src2_dest(opcode)), get_regname(get_compute_dest(opcode)));
+ }
+ else if (comp == 0x166)
+ {
+ util::stream_format(stream, "dstep %s,%s,%s", get_regname(get_src1(opcode)), get_regname(get_src2_dest(opcode)), get_regname(get_compute_dest(opcode)));
+ }
+ else
+ {
+ util::stream_format(stream, "unknown TY1 subcase 0 (%02x, %02x, %02x %04x)", get_src1(opcode), get_src2_dest(opcode), get_compute_dest(opcode), get_compute_compfunc(opcode));
+ }
+ break;
+ }
+
+ case 1:
+ {
+ const u16 comp = get_compute_compfunc(opcode);
+
+ if (comp == 0x080)
+ {
+ util::stream_format(stream, "rotlcb %s,%s,%s", get_regname(get_src1(opcode)), get_regname(get_src2_dest(opcode)), get_regname(get_compute_dest(opcode)));
+ }
+ else if (comp == 0x0c0)
+ {
+ util::stream_format(stream, "rotlb %s,%s,%s", get_regname(get_src1(opcode)), get_regname(get_src2_dest(opcode)), get_regname(get_compute_dest(opcode)));
+ }
+ else if ((comp & 0xf80) == 0x200)
+ {
+ int shift = get_sh_amount(get_compute_compfunc(opcode) & 0x7f);
+ util::stream_format(stream, "sh %s,%s,%s,#%d", get_regname(get_src1(opcode)), get_regname(get_src2_dest(opcode)), get_regname(get_compute_dest(opcode)), shift);
+ }
+ else if ((comp & 0xf80) == 0x100)
+ {
+ const u8 src2 = get_src2_dest(opcode);
+
+ if (src2 == 0x0)
+ {
+ int shift = get_asr_amount((get_compute_compfunc(opcode) & 0x7f));
+ util::stream_format(stream, "asr %s,%s,#%d", get_regname(get_src1(opcode)), get_regname(get_compute_dest(opcode)), shift);
+ }
+ else
+ {
+ util::stream_format(stream, "illegal asr form");
+ }
+ }
+ else
+ {
+ util::stream_format(stream, "unknown TY1 subcase 1 (%02x, %02x, %02x %04x)", get_src1(opcode), get_src2_dest(opcode), get_compute_dest(opcode), get_compute_compfunc(opcode));
+ }
+ break;
+ }
+
+ case 4:
+ {
+ const u16 comp = get_compute_compfunc(opcode);
+
+ if (comp == 0x00b)
+ {
+ util::stream_format(stream, "blc %s,%s,%s", get_regname(get_src1(opcode)), get_regname(get_src2_dest(opcode)), get_regname(get_compute_dest(opcode)));
+ }
+ else if (comp == 0x00f)
+ {
+ if (get_src2_dest(opcode) == 0x00)
+ {
+ util::stream_format(stream, "not %s,%s", get_regname(get_src1(opcode)), get_regname(get_compute_dest(opcode)));
+ }
+ else
+ {
+ util::stream_format(stream, "illegal not form");
+ }
+ }
+ else if (comp == 0x019)
+ {
+ u8 src2 = get_src2_dest(opcode);
+ if (src2 == 0)
+ {
+ const u8 src1 = get_src1(opcode);
+ const u8 dest = get_compute_dest(opcode);
+
+ if ((src1 == 0) && (dest == 0))
+ {
+ util::stream_format(stream, "nop");
+ }
+ else
+ {
+ util::stream_format(stream, "mov %s,%s", get_regname(get_src1(opcode)), get_regname(get_compute_dest(opcode)));
+ }
+ }
+ else
+ {
+ util::stream_format(stream, "add %s,%s,%s", get_regname(get_src1(opcode)), get_regname(get_src2_dest(opcode)), get_regname(get_compute_dest(opcode)));
+ }
+ }
+ else if (comp == 0x01b)
+ {
+ util::stream_format(stream, "xor %s,%s,%s", get_regname(get_src1(opcode)), get_regname(get_src2_dest(opcode)), get_regname(get_compute_dest(opcode)));
+ }
+ else if (comp == 0x023)
+ {
+ util::stream_format(stream, "and %s,%s,%s", get_regname(get_src1(opcode)), get_regname(get_src2_dest(opcode)), get_regname(get_compute_dest(opcode)));
+ }
+ else if (comp == 0x026)
+ {
+ util::stream_format(stream, "subnc %s,%s,%s", get_regname(get_src1(opcode)), get_regname(get_src2_dest(opcode)), get_regname(get_compute_dest(opcode)));
+ }
+ else if (comp == 0x03b)
+ {
+ util::stream_format(stream, "or %s,%s,%s", get_regname(get_src1(opcode)), get_regname(get_src2_dest(opcode)), get_regname(get_compute_dest(opcode)));
+ }
+ else if (comp == 0x066)
+ {
+ util::stream_format(stream, "sub %s,%s,%s", get_regname(get_src1(opcode)), get_regname(get_src2_dest(opcode)), get_regname(get_compute_dest(opcode)));
+ }
+ else
+ {
+ util::stream_format(stream, "unknown compute (%02x, %02x, %02x %04x)", get_src1(opcode), get_src2_dest(opcode), get_compute_dest(opcode), get_compute_compfunc(opcode));
+ }
+ break;
+ }
+
+ default:
+ {
+ util::stream_format(stream, "Unhandled TY1 (%08x)", opcode);
+ break;
+ }
+ }
+ break;
+
+ }
+
+ case 2:
+ {
+ const u8 op = get_op(opcode);
+ const int imm17 = util::sext(opcode, 17);
+
+ switch (op)
+ {
+ case 0:
+ {
+ // ld - Load
+ // ld Offset[rSrc1], rDest
+ util::stream_format(stream, "ld 0x%08x[%s],%s", imm17, get_regname(get_src1(opcode)), get_regname(get_src2_dest(opcode)));
+ break;
+ }
+ case 1:
+ {
+ // ldt - Load Through
+ // ldt Offset[rSrc1], rDest
+ util::stream_format(stream, "ldt 0x%08x[%s],%s", imm17, get_regname(get_src1(opcode)), get_regname(get_src2_dest(opcode)));
+ break;
+ }
+ case 2:
+ {
+ // st - Store
+ // st Offset[rSrc1], rDest
+ util::stream_format(stream, "st 0x%08x[%s],%s", imm17, get_regname(get_src1(opcode)), get_regname(get_src2_dest(opcode)));
+ break;
+ }
+ case 3:
+ {
+ // stt - Store Through
+ // stt Offset[rSrc1], rDest
+ util::stream_format(stream, "stt 0x%08x[%s],%s", imm17, get_regname(get_src1(opcode)), get_regname(get_src2_dest(opcode)));
+ break;
+ }
+ case 4:
+ {
+ // ldf - Load Floating Point
+ // ldf Offset[rSrc1], rDest
+ util::stream_format(stream, "ldf 0x%08x[%s],%s", imm17, get_regname(get_src1(opcode)), get_regname(get_src2_dest(opcode)));
+ break;
+
+ }
+ case 5: // movfrc or aluc
+ {
+ // this is just a suggested form
+ const u8 c2 = BIT(opcode, 0, 4);
+ const u8 c1 = BIT(opcode, 4, 4);
+ const u8 func = BIT(opcode, 8, 6);
+ const u8 op = BIT(opcode, 14, 3);
+ const u8 dest = get_src2_dest(opcode);
+ const u8 src = get_src1(opcode);
+
+ if (src == 0)
+ {
+ util::stream_format(stream, "movfrc %s,(%02x,%02x,%02x,%02x)", get_regname(dest), op, func, c1, c2);
+ }
+ else
+ {
+ util::stream_format(stream, "illegal movfrc form");
+ }
+ break;
+
+ }
+ case 6:
+ {
+ // stf - Store Floating Point
+ // stf Offset[rSrc1], rDest
+ util::stream_format(stream, "stf 0x%08x[%s],%s", imm17, get_regname(get_src1(opcode)), get_regname(get_src2_dest(opcode)));
+ break;
+ }
+ case 7: // movtoc
+ {
+ // this is just a suggested form
+ const u8 c2 = BIT(opcode, 0, 4);
+ const u8 c1 = BIT(opcode, 4, 4);
+ const u8 func = BIT(opcode, 8, 6);
+ const u8 op = BIT(opcode, 14, 3);
+ const u8 dest = get_src2_dest(opcode);
+ const u8 src = get_src1(opcode);
+
+ if (src == 0)
+ {
+ util::stream_format(stream, "movtoc %s,(%02x,%02x,%02x,%02x)", get_regname(dest), op, func, c1, c2);
+ }
+ else
+ {
+ //util::stream_format(stream, "illegal movtoc form");
+ // this form appears to be used
+ util::stream_format(stream, "movtoc %s,(%02x,%02x,%02x,%02x) (src1 == %s)", get_regname(dest), op, func, c1, c2, get_regname(src));
+ }
+ break;
+
+ }
+ default:
+ {
+ util::stream_format(stream, "Unhandled TY2 (%08x)", opcode);
+ break;
+ }
+ }
+ break;
+ }
+
+ case 3:
+ {
+ const u8 op = get_op(opcode);
+
+ switch (op)
+ {
+ case 0:
+ {
+ // jspci - Jump Indexed and Store PC
+ // jspci rSrc1,#Immed,Rdest
+ const int imm17 = util::sext(opcode, 17) * 2;
+ util::stream_format(stream, "jspci %s,#%02x,%s", get_regname(get_src1(opcode)), imm17, get_regname(get_src2_dest(opcode)));
+ break;
+ }
+
+ case 1:
+ {
+ // Halt and Spontaneously Combust
+ if ((opcode & 0x07ffffff) == 0x07c00000)
+ {
+ util::stream_format(stream, "hsc");
+ }
+ else
+ {
+ util::stream_format(stream, "illegal hsc form");
+ }
+ break;
+ }
+
+ case 2:
+ {
+ // movtos - Move to Special Register
+ // movtos rSrc1, SpecialReg
+
+ // psw 001
+ // md 010
+ // pcm1 100
+ const u16 comp = get_compute_compfunc(opcode);
+ if ((comp & 0xffe) == 0x000)
+ {
+ u8 dest = get_src2_dest(opcode);
+
+ if (dest == 0x00)
+ {
+ u8 src = get_src1(opcode);
+ // TODO: name register?
+ util::stream_format(stream, "movtos %s,%01x", get_regname(src), comp & 0x7);
+ }
+ else
+ {
+ util::stream_format(stream, "illegal movtos form");
+ }
+ }
+ else
+ {
+ util::stream_format(stream, "illegal movtos form");
+ }
+ break;
+
+ }
+
+ case 3:
+ {
+ // movfrs - Move from Special Register
+ // movfrs SpecialReg, rDest
+
+ // psw 001
+ // md 010
+ // pcm4 100
+ const u16 comp = get_compute_compfunc(opcode);
+ if ((comp & 0xffe) == 0x000)
+ {
+ u8 src = get_src1(opcode);
+ if (src == 0x00)
+ {
+ const u8 dest = get_src2_dest(opcode);
+ // TODO: name register?
+ util::stream_format(stream, "movfrs %01x,%s", comp & 0x7, get_regname(dest));
+ }
+ else
+ {
+ util::stream_format(stream, "illegal movfrs form");
+ }
+ }
+ else
+ {
+ util::stream_format(stream, "illegal movfrs form");
+ }
+ break;
+
+ }
+
+ case 4:
+ {
+ const int imm17 = util::sext(opcode, 17);
+ util::stream_format(stream, "addi %s,%s,0x%08x", get_regname(get_src1(opcode)), get_regname(get_src2_dest(opcode)), imm17);
+ break;
+ }
+
+ case 5:
+ {
+ const u16 comp = get_compute_compfunc(opcode);
+ if (comp == 0x03)
+ {
+ const u8 dest = get_src2_dest(opcode);
+ const u8 src = get_src1(opcode);
+
+ if ((src == 0x00) && (dest == 0x00))
+ {
+ util::stream_format(stream, "jpc");
+ }
+ else
+ {
+ util::stream_format(stream, "illegal jpc form");
+ }
+ }
+ else
+ {
+ util::stream_format(stream, "illegal jpc form");
+ }
+ break;
+ }
+
+ case 6:
+ {
+ if ((opcode & 0x07fff807) == 0x00000003)
+ {
+ const int vector = (opcode & 0x000007f8) >> 3;
+ util::stream_format(stream, "trap %02x", vector);
+ }
+ else
+ {
+ util::stream_format(stream, "illegal trap form");
+ }
+ break;
+ }
+
+ case 7:
+ {
+ const u16 comp = get_compute_compfunc(opcode);
+ if (comp == 0x03)
+ {
+ const u8 dest = get_src2_dest(opcode);
+ const u8 src = get_src1(opcode);
+
+ if ((src == 0x00) && (dest == 0x00))
+ {
+ util::stream_format(stream, "jpcrs");
+ }
+ else
+ {
+ util::stream_format(stream, "illegal jpcrs form");
+ }
+ }
+ else
+ {
+ util::stream_format(stream, "illegal jpcrs form");
+ }
+ break;
+ }
+
+ default:
+ {
+ util::stream_format(stream, "Unhandled TY3 (%08x)", opcode);
+ break;
+ }
+ }
+ break;
+ }
+
+ default:
+ {
+ util::stream_format(stream, "Unhandled (%08x)", opcode);
+ break;
+ }
+ }
+
+ return 4;
+}
diff --git a/src/devices/cpu/mipsx/mipsxdasm.h b/src/devices/cpu/mipsx/mipsxdasm.h
new file mode 100644
index 00000000000..96f788d4526
--- /dev/null
+++ b/src/devices/cpu/mipsx/mipsxdasm.h
@@ -0,0 +1,33 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+
+#ifndef MAME_CPU_MIPSX_MIPSXDASM_H
+#define MAME_CPU_MIPSX_MIPSXDASM_H
+
+#pragma once
+
+class mipsx_disassembler : public util::disasm_interface
+{
+public:
+ mipsx_disassembler() = default;
+ virtual ~mipsx_disassembler() = default;
+
+ virtual u32 opcode_alignment() const override;
+ virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer &params) override;
+
+private:
+ int get_ty(u32 opcode);
+ int get_op(u32 opcode);
+ int get_src1(u32 opcode);
+ int get_src2_dest(u32 opcode);
+ int get_offset(u32 opcode);
+ int get_sq(u32 opcode);
+ int get_compute_dest(u32 opcode);
+ int get_compute_compfunc(u32 opcode);
+ int get_asr_amount(int shift);
+ int get_sh_amount(int shift);
+
+ const char *get_regname(u8 reg);
+};
+
+#endif
diff --git a/src/mame/mame.lst b/src/mame/mame.lst
index 95f1ae4e412..bf35bacf9a1 100644
--- a/src/mame/mame.lst
+++ b/src/mame/mame.lst
@@ -44770,6 +44770,9 @@ wardnerb // bootleg
wardnerj // B25 / TP-009 (c) 1987 Taito Corporation (Japan)
wardnerjb // bootleg
+@source:tomy/kisssite.cpp
+kisssite
+
@source:tomy/tomy_princ.cpp
princ // Tomy Prin-C (Japan)
princnt // Tomy Prin-C (without touch-pad)
diff --git a/src/mame/tomy/kisssite.cpp b/src/mame/tomy/kisssite.cpp
new file mode 100644
index 00000000000..b053565741a
--- /dev/null
+++ b/src/mame/tomy/kisssite.cpp
@@ -0,0 +1,106 @@
+// license:BSD-3-Clause
+// copyright-holders:David Haywood
+
+/*
+
+PCB contains the following major components
+
+
+ESS VideoDrive
+ES3207FP B390
+TTV32098A
+
+ESS VideoDrive
+ES3210F Q390
+TTT22869A
+
+SAMSUNG C039A
+S1L9223A01-Q0
+
+SAMSUNG C031
+S5L9284D01-Q0
+
+ASD AE43BH40I16I-35
+50G00290919D
+
+F 037B
+KA9259D
+
+HOLTEK
+GT27C020-70
+A039K1523-2
+
+PT6312LQ
+PTC 0014Z
+
+74F125D
+C034205
+fnn0040L
+
+74F125D
+C034205
+fnn0040L
+
+*/
+
+#include "emu.h"
+
+#include "softlist_dev.h"
+
+#include "bus/ata/atapicdr.h"
+#include "cpu/mipsx/mipsx.h"
+
+namespace {
+
+class kisssite_state : public driver_device
+
+{
+public:
+ kisssite_state(machine_config const &mconfig, device_type type, char const *tag) :
+ driver_device(mconfig, type, tag),
+ m_maincpu(*this, "maincpu")
+ {
+ }
+
+ void kisssite(machine_config &config) ATTR_COLD;
+
+protected:
+ virtual void machine_reset() override;
+
+private:
+ required_device<cpu_device> m_maincpu;
+
+ void mem(address_map &map);
+};
+
+
+void kisssite_state::machine_reset()
+{
+ m_maincpu->set_state_int(STATE_GENPC, 0xe2cc); // temp, there is code here, but this is unlikely to be the entry point
+}
+
+void kisssite_state::mem(address_map &map)
+{
+ map(0x0000000, 0x003ffff).rom();
+}
+
+void kisssite_state::kisssite(machine_config &config)
+{
+ MIPSX(config, m_maincpu, 60'000'000); // there is MIPS-X code at at around 0xe2e0 in the ROM, 0x60000019 is "r0 + r0 -> r0" which acts as a NOP
+ m_maincpu->set_addrmap(AS_PROGRAM, &kisssite_state::mem);
+
+ CDROM(config, "cdrom").set_interface("cdrom");
+ SOFTWARE_LIST(config, "cd_list").set_original("kisssite_cd");
+}
+
+INPUT_PORTS_START(kisssite)
+INPUT_PORTS_END
+
+ROM_START(kisssite)
+ ROM_REGION32_BE(0x040000, "maincpu", 0 )
+ ROM_LOAD("ht27c020.u10", 0x000000, 0x040000, CRC(ccedce2b) SHA1(28dd3dfd0b8de0c5aa1c37d193ffc479d46563a1) )
+ROM_END
+
+} // anonymous namespace
+
+SYST(200?, kisssite, 0, 0, kisssite, kisssite, kisssite_state, empty_init, "Tomy", "Kiss-Site", MACHINE_IS_SKELETON)
diff --git a/src/tools/unidasm.cpp b/src/tools/unidasm.cpp
index a8fd8a97649..6f83949a231 100644
--- a/src/tools/unidasm.cpp
+++ b/src/tools/unidasm.cpp
@@ -122,6 +122,7 @@ using util::BIT;
#include "cpu/minx/minxd.h"
#include "cpu/mips/mips3dsm.h"
#include "cpu/mips/mips1dsm.h"
+#include "cpu/mipsx/mipsxdasm.h"
#include "cpu/mk1/mk1dasm.h"
#include "cpu/mn1400/mn1400d.h"
#include "cpu/mn1610/mn1610d.h"
@@ -545,6 +546,7 @@ static const dasm_table_entry dasm_table[] =
{ "mips1le", le, 0, []() -> util::disasm_interface * { return new mips1_disassembler; } },
{ "mips3be", be, 0, []() -> util::disasm_interface * { return new mips3_disassembler; } },
{ "mips3le", le, 0, []() -> util::disasm_interface * { return new mips3_disassembler; } },
+ { "mipsx", be, 0, []() -> util::disasm_interface * { return new mipsx_disassembler; } },
{ "mk1", le, 0, []() -> util::disasm_interface * { return new mk1_disassembler; } },
{ "mm5799", le, 0, []() -> util::disasm_interface * { return new mm5799_disassembler; } },
{ "mm76", le, 0, []() -> util::disasm_interface * { return new mm76_disassembler; } },