summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/c33
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/c33')
-rw-r--r--src/devices/cpu/c33/c33common.h29
-rw-r--r--src/devices/cpu/c33/c33dasm.cpp674
-rw-r--r--src/devices/cpu/c33/c33dasm.h37
-rw-r--r--src/devices/cpu/c33/c33helpers.ipp64
-rw-r--r--src/devices/cpu/c33/c33std.cpp117
-rw-r--r--src/devices/cpu/c33/c33std.h58
-rw-r--r--src/devices/cpu/c33/s1c33209.cpp331
-rw-r--r--src/devices/cpu/c33/s1c33209.h57
8 files changed, 1367 insertions, 0 deletions
diff --git a/src/devices/cpu/c33/c33common.h b/src/devices/cpu/c33/c33common.h
new file mode 100644
index 00000000000..4cfd1167c72
--- /dev/null
+++ b/src/devices/cpu/c33/c33common.h
@@ -0,0 +1,29 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/*
+ Common Epson C33 family stuff
+*/
+
+#ifndef MAME_CPU_C33_C33COMMON_H
+#define MAME_CPU_C33_C33COMMON_H
+
+#pragma once
+
+
+class c33_cpu_common
+{
+public:
+ // state indices
+ enum
+ {
+ C33_R0 = 1, C33_R1, C33_R2, C33_R3, C33_R4, C33_R5, C33_R6, C33_R7,
+ C33_R8, C33_R9, C33_R10, C33_R11, C33_R12, C33_R13, C33_R14, C33_R15,
+ C33_PSR, C33_SP,
+ C33_ALR, C33_AHR,
+ C33_LCO, C33_LSA, C33_LEA,
+ C33_SOR, C33_TTBR, C33_DP, C33_DBBR,
+ C33_USP, C33_SSP
+ };
+};
+
+#endif // MAME_CPU_C33_C33COMMON_H
diff --git a/src/devices/cpu/c33/c33dasm.cpp b/src/devices/cpu/c33/c33dasm.cpp
new file mode 100644
index 00000000000..08daaf81155
--- /dev/null
+++ b/src/devices/cpu/c33/c33dasm.cpp
@@ -0,0 +1,674 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/*
+ Epson C33 disassembler
+
+ TODO:
+ * Only C33 ADV Core is currently supported - add support for C33 STD Core, C33 PE Core, etc.
+ * Reconstruct more assembler synthetics
+ * Should psrset and psrclr use symbolic names for bits?
+ * Should 32-bit extended displacements always be displayed as signed?
+ * Should loop instructions have friendlier syntax?
+*/
+
+#include "emu.h"
+#include "c33dasm.h"
+
+#include <tuple>
+#include <utility>
+
+
+namespace {
+
+char const *const special_reg_names[16] = {
+ "%psr",
+ "%sp",
+ "%alr",
+ "%ahr",
+ "%lco",
+ "%lca",
+ "%lea",
+ "%sor",
+ "%ttbr",
+ "%dp",
+ "%idir",
+ "%dbbr",
+ nullptr,
+ "%usp",
+ "%ssp",
+ "%pc" };
+
+std::pair<char const *, unsigned> const class_0_00_ops[32] = {
+ { "nop", 0 }, // 000 0000 0 00 00
+ { "slp", 0 }, // 000 0000 0 01 00
+ { "halt", 0 }, // 000 0000 0 10 00
+ { nullptr, 0 },
+ { nullptr, 0 },
+ { nullptr, 0 },
+ { nullptr, 0 },
+ { nullptr, 0 },
+ { "pushn %%r%1$u", 4 }, // 000 0001 0 00 00
+ { "popn %%r%1$u", 4 }, // 000 0001 0 01 00
+ { nullptr, 0 },
+ { "jpr %%r%1$u", 4 }, // 000 0001 0 11 00
+ { nullptr, 0 },
+ { nullptr, 0 },
+ { nullptr, 0 },
+ { "jpr.d %%r%1$u", 4 }, // 000 0001 1 11 00
+ { "brk", 0 }, // 000 0010 0 00 00
+ { "retd", 0 }, // 000 0010 0 01 00
+ { "int %1$u", 2 }, // 000 0010 0 10 00
+ { "reti", 0 }, // 000 0010 0 11 00
+ { nullptr, 0 },
+ { nullptr, 0 },
+ { nullptr, 0 },
+ { nullptr, 0 },
+ { "call %%r%1$u", 4 }, // 000 0011 0 00 00
+ { "ret", 0 }, // 000 0011 0 01 00
+ { "jp %%r%1$u", 4 }, // 000 0011 0 10 00
+ { "retm", 0 }, // 000 0011 0 11 00
+ { "call.d %%r%1$u", 4 }, // 000 0011 1 00 00
+ { "ret.d", 0 }, // 000 0011 1 01 00
+ { "jp.d %%r%1$u", 4 }, // 000 0011 1 10 00
+ { nullptr, 0 } };
+
+std::tuple<char const *, char const *, char const *, bool, bool> const class_0_01_ops[32] = {
+ { "push %%r%1$u", nullptr, nullptr, false, false }, // 000 0000 000 01
+ { "pop %%r%1$u", nullptr, nullptr, false, false }, // 000 0000 001 01
+ { "pushs %%r%3$s", nullptr, nullptr, true, false }, // 000 0000 010 01
+ { "pops %%r%3$s", nullptr, nullptr, true, false }, // 000 0000 011 01
+ { "mac.w %%r%1$u", nullptr, nullptr, false, false }, // 000 0000 100 01
+ { "mac.hw %%r%1$u", nullptr, nullptr, false, false }, // 000 0000 101 01
+ { "macclr", nullptr, nullptr, false, true }, // 000 0000 110 01
+ { "ld.cf", nullptr, nullptr, false, true }, // 000 0000 111 01
+ { "divu.w %%r%1$u", nullptr, nullptr, false, false }, // 000 0001 000 01
+ { "div.w %%r%1$u", nullptr, nullptr, false, false }, // 000 0001 001 01
+ { "repeat %%r%1$u", nullptr, nullptr, false, false }, // 000 0001 010 01
+ { "repeat %1$u", nullptr, nullptr, false, false }, // 000 0001 011 01
+ { nullptr, nullptr, nullptr, false, false },
+ { "add %%r%1$u,%%dp", "xadd %%r%1$u,%%dp,0x%2$x", "xadd %%r%1$u,%%dp,%%r%2$u", false, false }, // 000 0001 101 01
+ { nullptr, nullptr, nullptr, false, false },
+ { nullptr, nullptr, nullptr, false, false },
+ { nullptr, nullptr, nullptr, false, false },
+ { nullptr, nullptr, nullptr, false, false },
+ { nullptr, nullptr, nullptr, false, false },
+ { nullptr, nullptr, nullptr, false, false },
+ { nullptr, nullptr, nullptr, false, false },
+ { nullptr, nullptr, nullptr, false, false },
+ { nullptr, nullptr, nullptr, false, false },
+ { nullptr, nullptr, nullptr, false, false },
+ { nullptr, nullptr, nullptr, false, false },
+ { nullptr, nullptr, nullptr, false, false },
+ { nullptr, nullptr, nullptr, false, false },
+ { nullptr, nullptr, nullptr, false, false },
+ { nullptr, nullptr, nullptr, false, false },
+ { nullptr, nullptr, nullptr, false, false },
+ { nullptr, nullptr, nullptr, false, false },
+ { nullptr, nullptr, nullptr, false, false } };
+
+std::pair<char const *, char const *> const class_0_jumps[16] = {
+ { nullptr, nullptr },
+ { nullptr, nullptr },
+ { nullptr, nullptr },
+ { nullptr, nullptr },
+ { "jrgt%1$s 0x%2$x", "xjrgt%1$s 0x%2$x" }, // 000 0100
+ { "jrge%1$s 0x%2$x", "xjrge%1$s 0x%2$x" }, // 000 0101
+ { "jrlt%1$s 0x%2$x", "xjrlt%1$s 0x%2$x" }, // 000 0110
+ { "jrle%1$s 0x%2$x", "xjrle%1$s 0x%2$x" }, // 000 0111
+ { "jrugt%1$s 0x%2$x", "xjrugt%1$s 0x%2$x" }, // 000 1000
+ { "jruge%1$s 0x%2$x", "xjruge%1$s 0x%2$x" }, // 000 1001
+ { "jrult%1$s 0x%2$x", "xjrult%1$s 0x%2$x" }, // 000 1010
+ { "jrule%1$s 0x%2$x", "xjrule%1$s 0x%2$x" }, // 000 1011
+ { "jreq%1$s 0x%2$x", "xjreq%1$s 0x%2$x" }, // 000 1100
+ { "jrne%1$s 0x%2$x", "xjrne%1$s 0x%2$x" }, // 000 1101
+ { "call%1$s 0x%2$x", "xcall%1$s 0x%2$x" }, // 000 1110
+ { "jp%1$s 0x%2$x", "xjp%1$s 0x%2$x" } }; // 000 1111
+
+std::tuple<char const *, char const *, char const *> const class_1_ops[32] = {
+ { "ld.b %%r%1$u,[%%r%2$u]", "xld.b %%r%1$u,[%%r%2$u + 0x%4$x]", "xld.b %%r%1$u,[%%r%2$u + %%r%4$u]" }, // 001 000 00
+ { "ld.b %%r%1$u,[%%r%2$u]+", nullptr, nullptr }, // 001 000 01
+ { "add %%r%1$u,%%r%2$u", "xadd %%r%1$u,%%r%2$u,0x%4$x", "xadd %%r%1$u,%%r%2$u,%%r%4$u" }, // 001 000 10
+ { "srl %%r%1$u,%3$u", nullptr, "xsrl %%r%1$u,%%r%4$u,%3$u" }, // 001 000 11
+ { "ld.ub %%r%1$u,[%%r%2$u]", "xld.ub %%r%1$u,[%%r%2$u + 0x%4$x]", "xld.ub %%r%1$u,[%%r%2$u + %%r%4$u]" }, // 001 001 00
+ { "ld.ub %%r%1$u,[%%r%2$u]+", nullptr, nullptr }, // 001 001 01
+ { "sub %%r%1$u,%%r%2$u", "xsub %%r%1$u,%%r%2$u,0x%4$x", "xsub %%r%1$u,%%r%2$u,%%r%4$u" }, // 001 001 10
+ { "sll %%r%1$u,%3$u", nullptr, "xsll %%r%1$u,%%r%4$u,%3$u" }, // 001 001 11
+ { "ld.h %%r%1$u,[%%r%2$u]", "xld.h %%r%1$u,[%%r%2$u + 0x%4$x]", "xld.h %%r%1$u,[%%r%2$u + %%r%4$u]" }, // 001 010 00
+ { "ld.h %%r%1$u,[%%r%2$u]+", nullptr, nullptr }, // 001 010 01
+ { "cmp %%r%1$u,%%r%2$u", nullptr, nullptr }, // 001 010 10
+ { "sra %%r%1$u,%3$u", nullptr, "xsra %%r%1$u,%%r%4$u,%3$u" }, // 001 010 11
+ { "ld.uh %%r%1$u,[%%r%2$u]", "xld.uh %%r%1$u,[%%r%2$u + 0x%4$x]", "xld.uh %%r%1$u,[%%r%2$u + %%r%4$u]" }, // 001 011 00
+ { "ld.uh %%r%1$u,[%%r%2$u]+", nullptr, nullptr }, // 001 011 01
+ { "ld.w %%r%1$u,%%r%2$u", nullptr, nullptr }, // 001 011 10
+ { "sla %%r%1$u,%3$u", nullptr, "xsla %%r%1$u,%%r%4$u,%3$u" }, // 001 011 11
+ { "ld.w %%r%1$u,[%%r%2$u]", "xld.w %%r%1$u,[%%r%2$u + 0x%4$x]", "xld.w %%r%1$u,[%%r%2$u + %%r%4$u]" }, // 001 100 00
+ { "ld.w %%r%1$u,[%%r%2$u]+", nullptr, nullptr }, // 001 100 01
+ { "and %%r%1$u,%%r%2$u", "xand %%r%1$u,%%r%2$u,0x%4$x", "xand %%r%1$u,%%r%2$u,%%r%4$u" }, // 001 100 10
+ { "rr %%r%1$u,%3$u", nullptr, "xrr %%r%1$u,%%r%4$u,%3$u" }, // 001 100 11
+ { "ld.b [%%r%2$u],%%r%1$u", "xld.b [%%r%2$u + 0x%4$x],%%r%1$u", "xld.b [%%r%2$u + %%r%4$u],%%r%1$u" }, // 001 101 00
+ { "ld.b [%%r%2$u]+,%%r%1$u", nullptr, nullptr }, // 001 101 01
+ { "or %%r%1$u,%%r%2$u", "xoor %%r%1$u,%%r%2$u,0x%4$x", "xoor %%r%1$u,%%r%2$u,%%r%4$u" }, // 001 101 10
+ { "rl %%r%1$u,%3$u", nullptr, "xrl %%r%1$u,%%r%4$u,%3$u" }, // 001 101 11
+ { "ld.h [%%r%2$u],%%r%1$u", "xld.h [%%r%2$u + 0x%4$x],%%r%1$u", "xld.h [%%r%2$u + %%r%4$u],%%r%1$u" }, // 001 110 00
+ { "ld.h [%%r%2$u]+,%%r%1$u", nullptr, nullptr }, // 001 110 01
+ { "xor %%r%1$u,%%r%2$u", "xxor %%r%1$u,%%r%2$u,0x%4$x", "xxor %%r%1$u,%%r%2$u,%%r%4$u" }, // 001 110 10
+ { nullptr, nullptr, nullptr },
+ { "ld.w [%%r%2$u],%%r%1$u", "xld.w [%%r%2$u + 0x%4$x],%%r%1$u", "xld.w [%%r%2$u + %%r%4$u],%%r%1$u" }, // 001 111 00
+ { "ld.w [%%r%2$u]+,%%r%1$u", nullptr, nullptr }, // 001 111 01
+ { "not %%r%1$u,%%r%2$u", nullptr, nullptr }, // 001 111 10
+ { nullptr, nullptr, nullptr } };
+
+char const *const class_1_ext_shifts[4] = {
+ nullptr,
+ "ext sra,%1$u", // 001 110 11 0000 01
+ "ext srl,%1$u", // 001 110 11 0000 10
+ "ext sll,%1$u" }; // 001 110 11 0000 11
+
+char const *const class_1_ext_predicates[16] = {
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ "ext gt", // 001 110 11 0100
+ "ext ge", // 001 110 11 0101
+ "ext lt", // 001 110 11 0110
+ "ext le", // 001 110 11 0111
+ "ext ugt", // 001 110 11 1000
+ "ext uge", // 001 110 11 1001
+ "ext ult", // 001 110 11 1010
+ "ext ule", // 001 110 11 1011
+ "ext eq", // 001 110 11 1100
+ "ext ne", // 001 110 11 1101
+ nullptr,
+ nullptr };
+
+std::pair<char const *, bool> class_1_ext_3[4] = {
+ { "ext %%r%1$u", true },
+ { "ext %%r%1$u,sra,%2$u", false },
+ { "ext %%r%1$u,srl,%2$u", false },
+ { "ext %%r%1$u,sll,%2$u", false } };
+
+std::tuple<char const *, char const *, unsigned> const class_2_3_ops[16] = {
+ { "ld.b %%r%1$u,[%%sp + 0x%2$x]", "xld.b %%r%1$u,[%%sp + 0x%2$x]", 1 }, // 010 000
+ { "ld.ub %%r%1$u,[%%sp + 0x%2$x]", "xld.ub %%r%1$u,[%%sp + 0x%2$x]", 1 }, // 010 001
+ { "ld.h %%r%1$u,[%%sp + 0x%2$x]", "xld.h %%r%1$u,[%%sp + 0x%2$x]", 2 }, // 010 010
+ { "ld.uh %%r%1$u,[%%sp + 0x%2$x]", "xld.uh %%r%1$u,[%%sp + 0x%2$x]", 2 }, // 010 011
+ { "ld.w %%r%1$u,[%%sp + 0x%2$x]", "xld.w %%r%1$u,[%%sp + 0x%2$x]", 4 }, // 010 100
+ { "ld.b [%%sp + 0x%2$x],%%r%1$u", "xld.b [%%sp + 0x%2$x],%%r%1$u", 1 }, // 010 101
+ { "ld.h [%%sp + 0x%2$x],%%r%1$u", "xld.h [%%sp + 0x%2$x],%%r%1$u", 2 }, // 010 110
+ { "ld.w [%%sp + 0x%2$x],%%r%1$u", "xld.w [%%sp + 0x%2$x],%%r%1$u", 4 }, // 010 111
+ { "add %%r%1$u,0x%2$x", "xadd %%r%1$u,0x%2$x", 1 }, // 011 000
+ { "sub %%r%1$u,0x%2$x", "xsub %%r%1$u,0x%2$x", 1 }, // 011 001
+ { "cmp %%r%1$u,%5$s0x%4$x", "xcmp %%r%1$u,%5$s0x%4$x", 1 }, // 011 010
+ { "ld.w %%r%1$u,%5$s0x%4$x", "xld.w %%r%1$u,%5$s0x%4$x", 1 }, // 011 011
+ { "and %%r%1$u,0x%3$x", "xand %%r%1$u,0x%3$x", 1 }, // 011 100
+ { "or %%r%1$u,0x%3$x", "xoor %%r%1$u,0x%3$x", 1 }, // 011 101
+ { "xor %%r%1$u,0x%3$x", "xxor %%r%1$u,0x%3$x", 1 }, // 011 110
+ { "not %%r%1$u,0x%3$x", "xnot %%r%1$u,0x%3$x", 1 } }; // 011 111
+
+std::tuple<char const *, char const *, bool> const class_4_ops[32] = {
+ { nullptr, nullptr, false },
+ { nullptr, nullptr, false },
+ { nullptr, nullptr, false },
+ { nullptr, nullptr, false },
+ { nullptr, nullptr, false },
+ { nullptr, nullptr, false },
+ { nullptr, nullptr, false },
+ { nullptr, nullptr, false },
+ { "srl %%r%1$u,%2$u", "xsrl %%r%1$u,%%r%3$u,%2$u", false }, // 100 010 00
+ { "srl %%r%1$u,%%r%2$u", "xsrl %%r%1$u,%%r%3$u,%%r%2$u", false }, // 100 010 01
+ { "scan0 %%r%1$u,%%r%2$u", nullptr, false }, // 100 010 10
+ { "div0s %%r%2$u", nullptr, true }, // 100 010 11
+ { "sll %%r%1$u,%2$u", "xsll %%r%1$u,%%r%3$u,%2$u", false }, // 100 011 00
+ { "sll %%r%1$u,%%r%2$u", "xsll %%r%1$u,%%r%3$u,%%r%2$u", false }, // 100 011 01
+ { "scan1 %%r%1$u,%%r%2$u", nullptr, false }, // 100 011 10
+ { "div0u %%r%2$u", nullptr, true }, // 100 011 11
+ { "sra %%r%1$u,%2$u", "xsra %%r%1$u,%%r%3$u,%2$u", false }, // 100 100 00
+ { "sra %%r%1$u,%%r%2$u", "xsra %%r%1$u,%%r%3$u,%%r%2$u", false }, // 100 100 01
+ { "swap %%r%1$u,%%r%2$u", nullptr, false }, // 100 100 10
+ { "div1 %%r%2$u", nullptr, true }, // 100 100 11
+ { "sla %%r%1$u,%2$u", "xsla %%r%1$u,%%r%3$u,%2$u", false }, // 100 101 00
+ { "sla %%r%1$u,%%r%2$u", "xsla %%r%1$u,%%r%3$u,%%r%2$u", false }, // 100 101 01
+ { "mirror %%r%1$u,%%r%2$u", nullptr, false }, // 100 101 10
+ { "div2s %%r%2$u", nullptr, true }, // 100 101 11
+ { "rr %%r%1$u,%2$u", "xrr %%r%1$u,%%r%3$u,%2$u", false }, // 100 110 00
+ { "rr %%r%1$u,%%r%2$u", "xrr %%r%1$u,%%r%3$u,%%r%2$u", false }, // 100 110 01
+ { "swaph %%r%1$u,%%r%2$u", nullptr, false }, // 100 110 10
+ { "div3s %%r%2$u", nullptr, true }, // 100 110 11
+ { "rl %%r%1$u,%2$u", "xrl %%r%1$u,%%r%3$u,%2$u", false }, // 100 111 00
+ { "rl %%r%1$u,%%r%2$u", "xrl %%r%1$u,%%r%3$u,%%r%2$u", false }, // 100 111 01
+ { "sat.b %%r%1$u,%%r%2$u", nullptr, false }, // 100 111 10
+ { "sat.ub %%r%1$u,%%r%2$u", nullptr, false } }; // 100 111 11
+
+std::tuple<char const *, char const *, char const *, unsigned, unsigned> const class_5_ops[32] = {
+ { "ld.w %4$s,%%r%2$d", nullptr, nullptr, 4, 1 }, // 101 000 00
+ { "ld.b %%r%1$u,%%r%2$u", nullptr, nullptr, 4, 0 }, // 101 000 01
+ { "mlt.h %%r%1$u,%%r%2$u", nullptr, nullptr, 4, 0 }, // 101 000 10
+ { "mlt.hw %%r%1$u,%%r%2$u", nullptr, nullptr, 4, 0 }, // 101 000 11
+ { "ld.w %%r%1$d,%4$s", nullptr, nullptr, 4, 2 }, // 101 001 00
+ { "ld.ub %%r%1$u,%%r%2$u", nullptr, nullptr, 4, 0 }, // 101 001 01
+ { "mltu.h %%r%1$u,%%r%2$u", nullptr, nullptr, 4, 0 }, // 101 001 10
+ { "mac1.h %%r%1$u,%%r%2$u", nullptr, nullptr, 4, 0 }, // 101 001 11
+ { "btst [%%r%2$u],%1$u", "xbtst [%%r%2$u + 0x%3$x],%1$u", nullptr, 3, 0 }, // 101 010 00
+ { "ld.h %%r%1$u,%%r%2$u", nullptr, nullptr, 4, 0 }, // 101 010 01
+ { "mlt.w %%r%1$u,%%r%2$u", nullptr, nullptr, 4, 0 }, // 101 010 10
+ { "mac1.hw %%r%1$u,%%r%2$u", nullptr, nullptr, 4, 0 }, // 101 010 11
+ { "bclr [%%r%2$u],%1$u", "xbclr [%%r%2$u + 0x%3$x],%1$u", nullptr, 3, 0 }, // 101 011 00
+ { "ld.uh %%r%1$u,%%r%2$u", nullptr, nullptr, 4, 0 }, // 101 011 01
+ { "mltu.w %%r%1$u,%%r%2$u", nullptr, nullptr, 4, 0 }, // 101 011 10
+ { nullptr, nullptr, nullptr, 0, 0 },
+ { "bset [%%r%2$u],%1$u", "xbset [%%r%2$u + 0x%3$x],%1$u", nullptr, 3, 0 }, // 101 100 00
+ { "ld.c %%r%1$u,0x%2$x", nullptr, nullptr, 4, 0 }, // 101 100 01
+ { "mac %%r%2$u", nullptr, nullptr, 0, 0 }, // 101 100 10
+ { "mac1.w %%r%1$u,%%r%2$u", nullptr, nullptr, 4, 0 }, // 101 100 11
+ { "bnot [%%r%2$u],%1$u", "xbnot [%%r%2$u + 0x%3$x],%1$u", nullptr, 3, 0 }, // 101 101 00
+ { "ld.c 0x%2$x,%%r%1$u", nullptr, nullptr, 4, 0 }, // 101 101 01
+ { "sat.h %%r%1$u,%%r%2$u", nullptr, nullptr, 4, 0 }, // 101 101 10
+ { "sat.uh %%r%1$u,%%r%2$u", nullptr, nullptr, 4, 0 }, // 101 101 11
+ { "adc %%r%1$u,%%r%2$u", nullptr, "xadc %%r%1$u,%%r%2$u,%%r%3$u", 4, 0 }, // 101 110 00
+ { "loop %%r%1$u,%%r%2$u", nullptr, nullptr, 4, 0 }, // 101 110 01
+ { "loop %%r%1$u,%2$u", nullptr, nullptr, 4, 0 }, // 101 110 10
+ { "loop %1$u,%2$u", nullptr, nullptr, 4, 0 }, // 101 110 11
+ { "sbc %%r%1$u,%%r%2$u", nullptr, "xsbc %%r%1$u,%%r%2$u,%%r%3$u", 4, 0 }, // 101 111 00
+ { "sat.w %%r%1$u,%%r%2$u", nullptr, nullptr, 4, 0 }, // 101 111 01
+ { "sat.uw %%r%1$u,%%r%2$u", nullptr, nullptr, 4, 0 }, // 101 111 10
+ { nullptr, nullptr, nullptr, 0, 0 } };
+
+std::tuple<char const *, char const *, unsigned> const class_7_ops[8] = {
+ { "ld.b %%r%1$u,[%%dp + 0x%2$x]", "xld.b %%r%1$u,[%%dp + 0x%2$x]", 1 }, // 111 000
+ { "ld.ub %%r%1$u,[%%dp + 0x%2$x]", "xld.ub %%r%1$u,[%%dp + 0x%2$x]", 1 }, // 111 001
+ { "ld.h %%r%1$u,[%%dp + 0x%2$x]", "xld.h %%r%1$u,[%%dp + 0x%2$x]", 2 }, // 111 010
+ { "ld.uh %%r%1$u,[%%dp + 0x%2$x]", "xld.uh %%r%1$u,[%%dp + 0x%2$x]", 2 }, // 111 011
+ { "ld.w %%r%1$u,[%%dp + 0x%2$x]", "xld.w %%r%1$u,[%%dp + 0x%2$x]", 4 }, // 111 100
+ { "ld.b [%%dp + 0x%2$x],%%r%1$u", "xld.b [%%dp + 0x%2$x],%%r%1$u", 1 }, // 111 101
+ { "ld.h [%%dp + 0x%2$x],%%r%1$u", "xld.h [%%dp + 0x%2$x],%%r%1$u", 2 }, // 111 110
+ { "ld.w [%%dp + 0x%2$x],%%r%1$u", "xld.w [%%dp + 0x%2$x],%%r%1$u", 4 } }; // 111 111
+
+} // anonymous namespace
+
+
+struct c33_disassembler::ext_info
+{
+ offs_t size() const
+ {
+ switch (type)
+ {
+ case ext_type::NONE:
+ return 0;
+ case ext_type::IMM13:
+ return 2;
+ case ext_type::IMM26:
+ return 4;
+ case ext_type::REG:
+ return 2;
+ }
+
+ throw false; // something is very wrong if we get here
+ }
+
+ unsigned bits() const
+ {
+ switch (type)
+ {
+ case ext_type::NONE:
+ return 0;
+ case ext_type::IMM13:
+ return 13;
+ case ext_type::IMM26:
+ return 26;
+ case ext_type::REG:
+ return 4;
+ }
+
+ throw false; // something is very wrong if we get here
+ }
+
+ char const *inst(char const *base, char const *ext_imm, char const *ext_reg) const
+ {
+ switch (type)
+ {
+ case ext_type::NONE:
+ return base;
+ case ext_type::IMM13:
+ case ext_type::IMM26:
+ return ext_imm;
+ case ext_type::REG:
+ return ext_reg;
+ }
+
+ throw false; // something is very wrong if we get here
+ }
+
+ ext_type type = ext_type::NONE;
+ u32 val = 0;
+ u16 op = 0;
+};
+
+
+c33_disassembler::c33_disassembler()
+{
+}
+
+
+u32 c33_disassembler::opcode_alignment() const
+{
+ return 2;
+}
+
+
+offs_t c33_disassembler::disassemble(
+ std::ostream &stream,
+ offs_t pc,
+ data_buffer const &opcodes,
+ data_buffer const &params)
+{
+ u16 op;
+
+ ext_info ext;
+ op = opcodes.r16(pc);
+ if (BIT(op, 13, 3) == 6)
+ {
+ ext.type = ext_type::IMM13;
+ ext.val = BIT(op, 0, 13);
+ ext.op = op;
+ op = opcodes.r16(pc + 2);
+ if (BIT(op, 13, 3) == 6)
+ {
+ ext.type = ext_type::IMM26;
+ ext.val = (ext.val << 13) | BIT(op, 0, 13);
+ op = opcodes.r16(pc + 4);
+ }
+ }
+ else if ((op & 0b111'111'11'0000'1111) == 0b001'111'11'0000'0000)
+ {
+ ext.type = ext_type::REG;
+ ext.val = BIT(op, 4, 4);
+ ext.op = op;
+ op = opcodes.r16(pc + 2);
+ }
+
+ return dasm(stream, pc, op, ext);
+}
+
+
+offs_t c33_disassembler::dasm(std::ostream &stream, offs_t pc, u16 op, ext_info const &ext) const
+{
+ switch (BIT(op, 13, 3))
+ {
+ case 0:
+ if (offs_t const r = dasm_class_0(stream, pc, op, ext); r)
+ return r;
+ break;
+ case 1:
+ if (offs_t const r = dasm_class_1(stream, op, ext); r)
+ return r;
+ break;
+ case 2:
+ case 3:
+ if (offs_t const r = dasm_class_2_3(stream, op, ext); r)
+ return r;
+ break;
+ case 4:
+ if (offs_t const r = dasm_class_4(stream, op, ext); r)
+ return r;
+ break;
+ case 5:
+ if (offs_t const r = dasm_class_5(stream, op, ext); r)
+ return r;
+ break;
+ case 6:
+ if (offs_t const r = dasm_class_6(stream, op, ext); r)
+ return r;
+ break;
+ case 7:
+ if (offs_t const r = dasm_class_7(stream, op, ext); r)
+ return r;
+ break;
+ };
+
+ if (ext_type::NONE != ext.type)
+ return dasm(stream, pc, ext.op, ext_info());
+
+ stream << "<invalid>";
+ return 2;
+}
+
+
+offs_t c33_disassembler::dasm_class_0(std::ostream &stream, offs_t pc, u16 op, ext_info const &ext) const
+{
+ switch (BIT(op, 9, 4))
+ {
+ case 0b0000:
+ case 0b0001:
+ case 0b0010:
+ case 0b0011:
+ if (BIT(op, 4, 2) == 0)
+ {
+ auto const [inst, target_bits] = class_0_00_ops[BIT(op, 6, 5)];
+ if (inst && ((4 == target_bits) || !BIT(op, target_bits, 4 - target_bits)))
+ {
+ if (ext_type::NONE != ext.type)
+ return 0;
+
+ util::stream_format(stream, inst, BIT(op, 0, 4));
+ return 2;
+ }
+ }
+ else if (BIT(op, 4, 2) == 1)
+ {
+ auto const [inst, inst_ext_imm, inst_ext_reg, use_special_reg, no_arg] = class_0_01_ops[BIT(op, 6, 5)];
+ char const *const special_reg = use_special_reg ? special_reg_names[BIT(op, 0, 4)] : nullptr;
+ if (inst && (!use_special_reg || special_reg) && (!no_arg || !BIT(op, 0, 4)))
+ {
+ char const *const fmt = ext.inst(inst, inst_ext_imm, inst_ext_reg);
+ if (!fmt)
+ return 0;
+
+ util::stream_format(stream, fmt, BIT(op, 0, 4), ext.val, special_reg);
+ return 2 + ext.size();
+ }
+ }
+ break;
+
+ default:
+ {
+ auto const [inst, inst_ext_imm] = class_0_jumps[BIT(op, 9, 5)];
+ char const *const fmt = ext.inst(inst, inst_ext_imm, nullptr);
+ if (!fmt)
+ return 0;
+
+ s32 imm = (BIT(ext.val, 16, 10) << 22) | (BIT(ext.val, 0, 13) << 9) | (BIT(op, 0, 8) << 1);
+ if (ext_type::NONE == ext.type)
+ imm = util::sext(imm, 9);
+ else if (ext_type::IMM13 == ext.type)
+ imm = util::sext(imm, 22);
+
+ util::stream_format(stream, fmt, BIT(op, 8) ? ".d" : " ", pc + ext.size() + imm);
+ return 2 + ext.size();
+ }
+ }
+
+ return 0; // catch invalid forms
+}
+
+offs_t c33_disassembler::dasm_class_1(std::ostream &stream, u16 op, ext_info const &ext) const
+{
+ switch (BIT(op, 8, 5))
+ {
+ case 0b110'11:
+ if (!BIT(op, 4, 4))
+ {
+ char const *const inst = class_1_ext_shifts[BIT(op, 2, 2)];
+ if (inst)
+ {
+ if (ext_type::NONE != ext.type)
+ return 0;
+
+ util::stream_format(stream, inst, BIT(op, 0, 2));
+ return 2;
+ }
+ }
+ else
+ {
+ char const *const inst = class_1_ext_predicates[BIT(op, 4, 4)];
+ if (inst && !BIT(op, 0, 4))
+ {
+ if (ext_type::NONE != ext.type)
+ return 0;
+
+ stream << inst;
+ return 2;
+ }
+ }
+ break;
+
+ case 0b111'11:
+ {
+ auto const [inst, no_imm] = class_1_ext_3[BIT(op, 2, 2)];
+ if (!no_imm || !BIT(op, 0, 2))
+ {
+ if (ext_type::NONE != ext.type)
+ return 0;
+
+ util::stream_format(stream, inst, BIT(op, 4, 4), BIT(op, 0, 2));
+ return 2;
+ }
+ }
+ break;
+
+ default:
+ {
+ auto const [inst, inst_ext_imm, inst_ext_reg] = class_1_ops[BIT(op, 8, 5)];
+ char const *const fmt = ext.inst(inst, inst_ext_imm, inst_ext_reg);
+ if (!fmt)
+ return 0;
+
+ util::stream_format(stream, fmt, BIT(op, 0, 4), BIT(op, 4, 4), 0x10 | BIT(op, 4, 4), ext.val);
+ return 2 + ext.size();
+ }
+ }
+
+ return 0; // catch invalid ext forms
+}
+
+
+offs_t c33_disassembler::dasm_class_2_3(std::ostream &stream, u16 op, ext_info const &ext) const
+{
+ auto const [inst, inst_ext_imm, mul] = class_2_3_ops[BIT(op, 10, 4)];
+ char const *const fmt = ext.inst(inst, inst_ext_imm, nullptr);
+ if (!fmt)
+ return 0;
+
+ u8 const reg = BIT(op, 0, 4);
+ u32 imm = (ext.val << 6) | BIT(op, 4, 6);
+ s32 simm = util::sext(imm, 6 + ext.bits());
+ u32 abs = std::abs(simm);
+ char const *const sign = (0 > simm) ? "-" : "";
+ if (ext_type::NONE == ext.type)
+ {
+ imm *= mul;
+ simm *= mul;
+ abs *= mul;
+ }
+ util::stream_format(stream, fmt, reg, imm, simm, abs, sign);
+ return 2 + ext.size();
+}
+
+
+offs_t c33_disassembler::dasm_class_4(std::ostream &stream, u16 op, ext_info const &ext) const
+{
+ if (BIT(op, 11, 2) == 0)
+ {
+ if (ext_type::NONE != ext.type)
+ return 0;
+
+ util::stream_format(stream, BIT(op, 10) ? "sub %%sp,0x%1$x" : "add %%sp,0x%1$x", BIT(op, 0, 10) * 4);
+ return 2;
+ }
+ else
+ {
+ auto const [inst, inst_ext_reg, no_dest] = class_4_ops[BIT(op, 8, 5)];
+ if (!no_dest || !BIT(op, 0, 4))
+ {
+ char const *const fmt = ext.inst(inst, nullptr, inst_ext_reg);
+ if (!fmt)
+ return 0;
+
+ util::stream_format(stream, fmt, BIT(op, 0, 4), BIT(op, 4, 4), ext.val);
+ return 2 + ext.size();
+ }
+ }
+
+ return 0; // catch invalid forms of division instructions
+}
+
+
+offs_t c33_disassembler::dasm_class_5(std::ostream &stream, u16 op, ext_info const &ext) const
+{
+ if (BIT(op, 6, 7) == 0b111'11'00)
+ {
+ if (ext_type::NONE != ext.type)
+ return 0;
+
+ util::stream_format(stream, "do.c 0x%1$x", BIT(op, 0, 6));
+ return 2;
+ }
+ else if (BIT(op, 5, 8) == 0b111'11'01'0)
+ {
+ if (ext_type::NONE != ext.type)
+ return 0;
+
+ util::stream_format(stream, "psrset %1$u", BIT(op, 0, 5));
+ return 2;
+ }
+ else if (BIT(op, 5, 8) == 0b111'11'10'0)
+ {
+ if (ext_type::NONE != ext.type)
+ return 0;
+
+ util::stream_format(stream, "psrclr %1$u", BIT(op, 0, 5));
+ return 2;
+ }
+ else
+ {
+ auto const [inst, inst_ext_imm, inst_ext_reg, target_bits, special_reg_pos] = class_5_ops[BIT(op, 8, 5)];
+ char const *const special_reg = special_reg_pos ? special_reg_names[BIT(op, (special_reg_pos - 1) * 4, 4)] : nullptr;
+ if (inst && (!special_reg_pos || special_reg) && ((4 == target_bits) || !BIT(op, target_bits, 4 - target_bits)))
+ {
+ char const *const fmt = ext.inst(inst, inst_ext_imm, inst_ext_reg);
+ if (!fmt)
+ return 0;
+
+ util::stream_format(stream, fmt, BIT(op, 0, 4), BIT(op, 4, 4), ext.val, special_reg);
+ return 2 + ext.size();
+ }
+ }
+
+ return 0; // catch invalid forms
+}
+
+
+offs_t c33_disassembler::dasm_class_6(std::ostream &stream, u16 op, ext_info const &ext) const
+{
+ if (ext_type::NONE != ext.type)
+ return 0;
+
+ util::stream_format(stream, "ext 0x%1$x", BIT(op, 0, 13));
+ return 2;
+}
+
+
+offs_t c33_disassembler::dasm_class_7(std::ostream &stream, u16 op, ext_info const &ext) const
+{
+ auto const [inst, inst_ext_imm, mul] = class_7_ops[BIT(op, 10, 3)];
+ char const *const fmt = ext.inst(inst, inst_ext_imm, nullptr);
+ if (!fmt)
+ return 0;
+
+ u8 const reg = BIT(op, 0, 4);
+ u32 imm = (ext.val << 6) | BIT(op, 4, 6);
+ if (ext_type::NONE == ext.type)
+ imm *= mul;
+ util::stream_format(stream, fmt, reg, imm);
+ return 2 + ext.size();
+}
diff --git a/src/devices/cpu/c33/c33dasm.h b/src/devices/cpu/c33/c33dasm.h
new file mode 100644
index 00000000000..4eee7652526
--- /dev/null
+++ b/src/devices/cpu/c33/c33dasm.h
@@ -0,0 +1,37 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/*
+ Epson C33 disassembler
+*/
+
+#ifndef MAME_CPU_C33_C33DASM_H
+#define MAME_CPU_C33_C33DASM_H
+
+#pragma once
+
+
+class c33_disassembler : public util::disasm_interface
+{
+public:
+ c33_disassembler();
+
+ virtual u32 opcode_alignment() const override;
+ virtual offs_t disassemble(std::ostream &stream, offs_t pc, data_buffer const &opcodes, data_buffer const &params) override;
+
+private:
+ enum class ext_type { NONE, IMM13, IMM26, REG };
+
+ struct ext_info;
+
+ offs_t dasm(std::ostream &stream, offs_t pc, u16 op, ext_info const &ext) const;
+
+ offs_t dasm_class_0(std::ostream &stream, offs_t pc, u16 op, ext_info const &ext) const;
+ offs_t dasm_class_1(std::ostream &stream, u16 op, ext_info const &ext) const;
+ offs_t dasm_class_2_3(std::ostream &stream, u16 op, ext_info const &ext) const;
+ offs_t dasm_class_4(std::ostream &stream, u16 op, ext_info const &ext) const;
+ offs_t dasm_class_6(std::ostream &stream, u16 op, ext_info const &ext) const;
+ offs_t dasm_class_5(std::ostream &stream, u16 op, ext_info const &ext) const;
+ offs_t dasm_class_7(std::ostream &stream, u16 op, ext_info const &ext) const;
+};
+
+#endif // MAME_CPU_C33_C33DASM_H
diff --git a/src/devices/cpu/c33/c33helpers.ipp b/src/devices/cpu/c33/c33helpers.ipp
new file mode 100644
index 00000000000..38aaaa0a2f7
--- /dev/null
+++ b/src/devices/cpu/c33/c33helpers.ipp
@@ -0,0 +1,64 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/*
+ Epson C33 shared helper functions and constants
+*/
+#ifndef MAME_CPU_C33_C33HELPERS_IPP
+#define MAME_CPU_C33_C33HELPERS_IPP
+
+#pragma once
+
+
+enum
+{
+ PSR_BIT_N = 0,
+ PSR_BIT_Z = 1,
+ PSR_BIT_V = 2,
+ PSR_BIT_C = 3,
+ PSR_BIT_IE = 4,
+ PSR_BIT_DS = 6,
+ PSR_BIT_MO = 7,
+ PSR_BIT_IL = 8,
+ PSR_BIT_SV = 12,
+ PSR_BIT_ME = 13,
+ PSR_BIT_DE = 14,
+ PSR_BIT_S = 15,
+ PSR_BIT_HC = 16,
+ PSR_BIT_LC = 17,
+ PSR_BIT_SE = 20,
+ PSR_BIT_OC = 21,
+ PSR_BIT_SW = 22,
+ PSR_BIT_RC = 24,
+ PSR_BIT_PM = 28,
+ PSR_BIT_LM = 29,
+ PSR_BIT_RM = 30,
+ PSR_BIT_HE = 31
+};
+
+enum : u32
+{
+ PSR_MASK_N = u32(0x1) << PSR_BIT_N,
+ PSR_MASK_Z = u32(0x1) << PSR_BIT_Z,
+ PSR_MASK_V = u32(0x1) << PSR_BIT_V,
+ PSR_MASK_C = u32(0x1) << PSR_BIT_C,
+ PSR_MASK_IE = u32(0x1) << PSR_BIT_IE,
+ PSR_MASK_DS = u32(0x1) << PSR_BIT_DS,
+ PSR_MASK_MO = u32(0x1) << PSR_BIT_MO,
+ PSR_MASK_IL = u32(0xf) << PSR_BIT_IL,
+ PSR_MASK_SV = u32(0x1) << PSR_BIT_SV,
+ PSR_MASK_ME = u32(0x1) << PSR_BIT_ME,
+ PSR_MASK_DE = u32(0x1) << PSR_BIT_DE,
+ PSR_MASK_S = u32(0x1) << PSR_BIT_S,
+ PSR_MASK_HC = u32(0x1) << PSR_BIT_HC,
+ PSR_MASK_LC = u32(0x1) << PSR_BIT_LC,
+ PSR_MASK_SE = u32(0x1) << PSR_BIT_SE,
+ PSR_MASK_OC = u32(0x1) << PSR_BIT_OC,
+ PSR_MASK_SW = u32(0x1) << PSR_BIT_SW,
+ PSR_MASK_RC = u32(0xf) << PSR_BIT_RC,
+ PSR_MASK_PM = u32(0x1) << PSR_BIT_PM,
+ PSR_MASK_LM = u32(0x1) << PSR_BIT_LM,
+ PSR_MASK_RM = u32(0x1) << PSR_BIT_RM,
+ PSR_MASK_HE = u32(0x1) << PSR_BIT_HE
+};
+
+#endif // MAME_CPU_C33_C33HELPERS_IPP
diff --git a/src/devices/cpu/c33/c33std.cpp b/src/devices/cpu/c33/c33std.cpp
new file mode 100644
index 00000000000..a4b0438d1b3
--- /dev/null
+++ b/src/devices/cpu/c33/c33std.cpp
@@ -0,0 +1,117 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/*
+ Epson C33 STD Core (S1C33000)
+*/
+
+#include "emu.h"
+#include "c33std.h"
+
+#include "c33dasm.h"
+
+#include <algorithm>
+#include <iterator>
+#include <utility>
+
+#include "c33helpers.ipp"
+
+
+c33std_cpu_device_base::c33std_cpu_device_base(
+ machine_config const &mconfig,
+ device_type type,
+ char const *tag,
+ device_t *owner,
+ u32 clock,
+ address_map_constructor internal_map) :
+ cpu_device(mconfig, type, tag, owner, clock),
+ m_memory_config("memory", ENDIANNESS_LITTLE, 16, 28, 0, internal_map),
+ m_icount(0)
+{
+}
+
+
+void c33std_cpu_device_base::device_start()
+{
+ set_icountptr(m_icount);
+
+ space(AS_PROGRAM).cache(m_opcodes);
+ space(AS_PROGRAM).specific(m_data);
+
+ std::fill(std::begin(m_gprs), std::end(m_gprs), 0);
+ m_pc = 0;
+ m_psr = 0;
+ m_sp = 0;
+ m_alr = 0;
+ m_ahr = 0;
+
+ save_item(NAME(m_gprs));
+ save_item(NAME(m_pc));
+ save_item(NAME(m_psr));
+ save_item(NAME(m_sp));
+ save_item(NAME(m_alr));
+ save_item(NAME(m_ahr));
+
+ state_add(STATE_GENPC, "PC", m_pc ).mask(0xffff'fffe);
+ state_add(STATE_GENPCBASE, "PCBASE", m_pc ).mask(0xffff'fffe).noshow();
+ state_add(STATE_GENFLAGS, "GENGLAGS", m_psr ).mask(0x0000'0fdf).formatstr("%4s").noshow();
+ state_add(C33_R0, "R0", m_gprs[0] );
+ state_add(C33_R1, "R1", m_gprs[1] );
+ state_add(C33_R2, "R2", m_gprs[2] );
+ state_add(C33_R3, "R3", m_gprs[3] );
+ state_add(C33_R4, "R4", m_gprs[4] );
+ state_add(C33_R5, "R5", m_gprs[5] );
+ state_add(C33_R6, "R6", m_gprs[6] );
+ state_add(C33_R7, "R7", m_gprs[7] );
+ state_add(C33_R8, "R8", m_gprs[8] );
+ state_add(C33_R9, "R9", m_gprs[9] );
+ state_add(C33_R10, "R10", m_gprs[10]);
+ state_add(C33_R11, "R11", m_gprs[11]);
+ state_add(C33_R12, "R12", m_gprs[12]);
+ state_add(C33_R13, "R13", m_gprs[13]);
+ state_add(C33_R14, "R14", m_gprs[14]);
+ state_add(C33_R15, "R15", m_gprs[15]);
+ state_add(C33_PSR, "PSR", m_psr ).mask(0x0000'0fdf);
+ state_add(C33_SP, "SP", m_sp );
+ state_add(C33_ALR, "ALR", m_alr );
+ state_add(C33_AHR, "AHR", m_ahr );
+}
+
+
+void c33std_cpu_device_base::device_reset()
+{
+ m_psr = 0;
+}
+
+
+void c33std_cpu_device_base::execute_run()
+{
+ debugger_instruction_hook(m_pc);
+ m_icount = 0;
+}
+
+
+device_memory_interface::space_config_vector c33std_cpu_device_base::memory_space_config() const
+{
+ return space_config_vector{ std::make_pair(AS_PROGRAM, &m_memory_config) };
+}
+
+
+std::unique_ptr<util::disasm_interface> c33std_cpu_device_base::create_disassembler()
+{
+ return std::make_unique<c33_disassembler>();
+}
+
+
+void c33std_cpu_device_base::state_string_export(device_state_entry const &entry, std::string &str) const
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ str = util::string_format("%c%c%c%c",
+ (m_psr & PSR_MASK_C) ? 'C' : 'c',
+ (m_psr & PSR_MASK_V) ? 'V' : 'v',
+ (m_psr & PSR_MASK_Z) ? 'Z' : 'z',
+ (m_psr & PSR_MASK_N) ? 'N' : 'n');
+ break;
+ }
+}
diff --git a/src/devices/cpu/c33/c33std.h b/src/devices/cpu/c33/c33std.h
new file mode 100644
index 00000000000..41ae2058210
--- /dev/null
+++ b/src/devices/cpu/c33/c33std.h
@@ -0,0 +1,58 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/*
+ Epson C33 STD Core (S1C33000)
+*/
+
+#ifndef MAME_CPU_C33_C33STD_H
+#define MAME_CPU_C33_C33STD_H
+
+#pragma once
+
+#include "c33common.h"
+
+#include <memory>
+#include <string>
+
+
+class c33std_cpu_device_base : public cpu_device, public c33_cpu_common
+{
+protected:
+ c33std_cpu_device_base(
+ machine_config const &mconfig,
+ device_type type,
+ char const *tag,
+ device_t *owner,
+ u32 clock,
+ address_map_constructor internal_map);
+
+ // device_t implementation
+ virtual void device_start() override ATTR_COLD;
+ virtual void device_reset() override ATTR_COLD;
+
+ // device_execute_interface implementation
+ virtual void execute_run() override;
+
+ // device_memory_interface implementation
+ virtual space_config_vector memory_space_config() const override ATTR_COLD;
+
+ // device_disassembler_interface implementation
+ std::unique_ptr<util::disasm_interface> create_disassembler() override ATTR_COLD;
+
+ // device_state_interface implementation
+ void state_string_export(device_state_entry const &entry, std::string &str) const override;
+
+ address_space_config const m_memory_config;
+ memory_access<28, 1, 0, ENDIANNESS_LITTLE>::cache m_opcodes;
+ memory_access<28, 1, 0, ENDIANNESS_LITTLE>::specific m_data;
+
+ int m_icount;
+ u32 m_gprs[16];
+ u32 m_pc;
+ u32 m_psr;
+ u32 m_sp;
+ u32 m_alr;
+ u32 m_ahr;
+};
+
+#endif // MAME_CPU_C33_C33STD_H
diff --git a/src/devices/cpu/c33/s1c33209.cpp b/src/devices/cpu/c33/s1c33209.cpp
new file mode 100644
index 00000000000..20a8a546f11
--- /dev/null
+++ b/src/devices/cpu/c33/s1c33209.cpp
@@ -0,0 +1,331 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/*
+ Epson S1C33209/221/222 CMOS 32-bit single chip microcomputer
+*/
+
+#include "emu.h"
+#include "s1c33209.h"
+
+
+DEFINE_DEVICE_TYPE(S1C33209, s1c33209_device, "s1c33209", "Epson S1C33209")
+DEFINE_DEVICE_TYPE(S1C33221, s1c33221_device, "s1c33221", "Epson S1C33221")
+DEFINE_DEVICE_TYPE(S1C33222, s1c33222_device, "s1c33222", "Epson S1C33222")
+
+
+s1c33209_device::s1c33209_device(
+ machine_config const &mconfig,
+ device_type type,
+ char const *tag,
+ device_t *owner,
+ u32 clock,
+ address_map_constructor internal_map) :
+ c33std_cpu_device_base(mconfig, type, tag, owner, clock, internal_map)
+{
+}
+
+s1c33209_device::s1c33209_device(
+ machine_config const &mconfig,
+ char const *tag,
+ device_t *owner,
+ u32 clock) :
+ s1c33209_device(
+ mconfig,
+ S1C33209,
+ tag,
+ owner,
+ clock,
+ address_map_constructor(FUNC(s1c33209_device::memory_map<0>), this))
+{
+}
+
+s1c33221_device::s1c33221_device(
+ machine_config const &mconfig,
+ char const *tag,
+ device_t *owner,
+ u32 clock) :
+ s1c33209_device(
+ mconfig,
+ S1C33221,
+ tag,
+ owner,
+ clock,
+ address_map_constructor(FUNC(s1c33221_device::memory_map<128 * 1024>), this))
+{
+}
+
+s1c33222_device::s1c33222_device(
+ machine_config const &mconfig,
+ char const *tag,
+ device_t *owner,
+ u32 clock) :
+ s1c33209_device(
+ mconfig,
+ S1C33222,
+ tag,
+ owner,
+ clock,
+ address_map_constructor(FUNC(s1c33222_device::memory_map<64 * 1024>), this))
+{
+}
+
+
+void s1c33209_device::device_reset()
+{
+ c33std_cpu_device_base::device_reset();
+
+ u32 const boot_vector = m_data.read_dword(0x0c0'0000);
+ m_pc = boot_vector;
+}
+
+
+template <offs_t RomBytes>
+void s1c33209_device::memory_map(address_map &map)
+{
+ map(0x000'0000, 0x000'1fff).mirror(0x000'2000).ram(); // actually 32 bits wide (single cycle word access)
+ map(0x003'0000, 0x003'ffff).m(*this, FUNC(s1c33209_device::peripheral_map));
+ map(0x004'0000, 0x004'ffff).mirror(0x001'0000).m(*this, FUNC(s1c33209_device::peripheral_map));
+ //map(0x006'0000, 0x007'ffff) area 2 reserved for debug mode
+ //map(0x008'0000, 0xfff'ffff) area 3 reserved for middleware
+ //map(0x010'0000, 0x02f'ffff) area 4-5 external memory
+ //map(0x030'0000, 0x037'ffff) area 6 external 8-bit I/O
+ //map(0x038'0000, 0x03f'ffff) area 6 external 8-bit I/O
+ //map(0x040'0000, 0x0bf'ffff) area 7-9 external memory
+ if (RomBytes)
+ map(0xc0'0000, 0x0c0'0000 + RomBytes - 1).rom().region(DEVICE_SELF, 0);
+ //map(0x0c.'...., 0x0ff'ffff) area 10 external memory
+ //map(0x100'0000, 0xfff'ffff) area 11-18 external memory
+}
+
+void s1c33209_device::peripheral_map(address_map &map)
+{
+ //map(0x0140, 0x0140) 8-bit timer 4-5 clock select
+ //map(0x0145, 0x0145) 8-bit timer 4-5 clock control
+ //map(0x0146, 0x0146) 8-bit timer 0-3 clock select
+ //map(0x0147, 0x0147) 16-bit timer 0 clock control
+ //map(0x0148, 0x0148) 16-bit timer 1 clock control
+ //map(0x0149, 0x0149) 16-bit timer 2 clock control
+ //map(0x014a, 0x014a) 16-bit timer 3 clock control
+ //map(0x014b, 0x014b) 16-bit timer 4 clock control
+ //map(0x014c, 0x014c) 16-bit timer 5 clock control
+ //map(0x014d, 0x014d) 8-bit timer 0-1 clock control
+ //map(0x014e, 0x014e) 8-bit timer 2-3 clock control
+ //map(0x014f, 0x014f) A/D clock control
+
+ //map(0x0151, 0x0151) clock timer run/stop
+ //map(0x0152, 0x0152) clock timer interrupt control
+ //map(0x0153, 0x0153) clock timer divider
+ //map(0x0154, 0x0154) clock timer second
+ //map(0x0155, 0x0155) clock timer minute
+ //map(0x0156, 0x0156) clock timer hour
+ //map(0x0157, 0x0157) clock day (low)
+ //map(0x0158, 0x0158) clock day (high)
+ //map(0x0159, 0x0159) clock minute comparison
+ //map(0x015a, 0x015a) clock hour comparison
+ //map(0x015b, 0x015b) clock day comparison
+
+ //map(0x0160, 0x0160) 8-bit timer 0 control
+ //map(0x0161, 0x0161) 8-bit timer 0 reload
+ //map(0x0162, 0x0162) 8-bit timer 0 counter data
+ //map(0x0164, 0x0164) 8-bit timer 1 control
+ //map(0x0165, 0x0165) 8-bit timer 1 reload
+ //map(0x0166, 0x0166) 8-bit timer 1 counter data
+ //map(0x0168, 0x0168) 8-bit timer 2 control
+ //map(0x0169, 0x0169) 8-bit timer 2 reload
+ //map(0x016a, 0x016a) 8-bit timer 2 counter data
+ //map(0x016c, 0x016c) 8-bit timer 3 control
+ //map(0x016d, 0x016d) 8-bit timer 3 reload
+ //map(0x016e, 0x016e) 8-bit timer 3 counter data
+ //map(0x0170, 0x0170) watchdog timer write-protect
+ //map(0x0171, 0x0171) watchdog timer enable
+ //map(0x0174, 0x0174) 8-bit timer 4 control
+ //map(0x0175, 0x0175) 8-bit timer 4 reload
+ //map(0x0176, 0x0176) 8-bit timer 4 counter data
+ //map(0x0178, 0x0178) 8-bit timer 5 control
+ //map(0x0179, 0x0179) 8-bit timer 5 reload
+ //map(0x017a, 0x017a) 8-bit timer 5 counter data
+ //map(0x0180, 0x0180) power control
+ //map(0x0181, 0x0181) prescaler clock select
+ //map(0x0190, 0x0190) clock option
+ //map(0x019e, 0x019e) power control protect
+
+ //map(0x01e0, 0x01e0) serial interface ch. 0 transmit data
+ //map(0x01e1, 0x01e1) serial interface ch. 0 receive data
+ //map(0x01e2, 0x01e2) serial interface ch. 0 status
+ //map(0x01e3, 0x01e3) serial interface ch. 0 control
+ //map(0x01e4, 0x01e4) serial interface ch. 0 IrDA
+ //map(0x01e5, 0x01e5) serial interface ch. 1 transmit data
+ //map(0x01e6, 0x01e6) serial interface ch. 1 receive data
+ //map(0x01e7, 0x01e7) serial interface ch. 1 status
+ //map(0x01e8, 0x01e8) serial interface ch. 1 control
+ //map(0x01e9, 0x01e9) serial interface ch. 1 IrDA
+ //map(0x01f0, 0x01f0) serial interface ch. 2 transmit data
+ //map(0x01f1, 0x01f1) serial interface ch. 2 receive data
+ //map(0x01f2, 0x01f2) serial interface ch. 2 status
+ //map(0x01f3, 0x01f3) serial interface ch. 2 control
+ //map(0x01f4, 0x01f4) serial interface ch. 2 IrDA
+ //map(0x01f5, 0x01f5) serial interface ch. 3 transmit data
+ //map(0x01f6, 0x01f6) serial interface ch. 3 receive data
+ //map(0x01f7, 0x01f7) serial interface ch. 3 status
+ //map(0x01f8, 0x01f8) serial interface ch. 3 control
+ //map(0x01f9, 0x01f9) serial interface ch. 3 IrDA
+
+ //map(0x0240, 0x0240) A/D conversion result (low)
+ //map(0x0241, 0x0241) A/D conversion result (high)
+ //map(0x0242, 0x0242) A/D trigger
+ //map(0x0243, 0x0243) A/D channel
+ //map(0x0244, 0x0244) A/D enable
+ //map(0x0245, 0x0245) A/D sampling
+
+ //map(0x0260, 0x0260) port 0-1 interrupt priority
+ //map(0x0261, 0x0261) port 2-3 interrupt priority
+ //map(0x0262, 0x0262) key input interrupt priority
+ //map(0x0263, 0x0263) high-speed DMA ch.0-1 interrupt priority
+ //map(0x0264, 0x0264) high-speed DMA ch.2-3 interrupt priority
+ //map(0x0265, 0x0265) IDMA interrupt priority
+ //map(0x0266, 0x0266) 16-bit timer 0-1 interrupt priority
+ //map(0x0267, 0x0267) 16-bit timer 2-3 interrupt priority
+ //map(0x0268, 0x0268) 16-bit timer 4-5 interrupt priority
+ //map(0x0269, 0x0269) 8-bit timer and serial interface ch. 0 interrupt priority
+ //map(0x026a, 0x026a) serial interface ch. 1 and A/D interrupt priority
+ //map(0x026b, 0x026b) clock timer interrupt priority
+ //map(0x026c, 0x026c) port input 4-5 interrupt priority
+ //map(0x026d, 0x026d) port input 6-7 interrupt priority
+ //map(0x0270, 0x0270) key input and port 0-3 interrupt enable
+ //map(0x0271, 0x0271) DMA interrupt enable
+ //map(0x0272, 0x0272) 16-bit timer 0-1 interrupt enable
+ //map(0x0273, 0x0273) 16-bit timer 2-3 interrupt enable
+ //map(0x0274, 0x0274) 16-bit timer 4-5 interrupt enable
+ //map(0x0275, 0x0275) 8-bit timer interrupt enable
+ //map(0x0276, 0x0276) serial interface interrupt enable
+ //map(0x0277, 0x0277) port input 4-7, clock timer and A/D interrupt enable
+ //map(0x0280, 0x0280) key input and port 0-3 interrupt factor flag
+ //map(0x0281, 0x0281) DMA interrupt factor flag
+ //map(0x0282, 0x0282) 16-bit timer 0-1 interrupt factor flag
+ //map(0x0283, 0x0283) 16-bit timer 2-3 interrupt factor flag
+ //map(0x0284, 0x0284) 16-bit timer 4-5 interrupt factor flag
+ //map(0x0285, 0x0285) 8-bit timer interrupt factor flag
+ //map(0x0286, 0x0286) serial interface interrupt factor flag
+ //map(0x0287, 0x0287) port input 4-7, clock timer and A/D interrupt factor flag
+ //map(0x0290, 0x0290) port input 0-3, high-speed DMA ch. 0-1 and 16-bit timer 0 IDMA request
+ //map(0x0291, 0x0291) 16-bit timer 1-4 IDMA request
+ //map(0x0292, 0x0292) 16-bit timer 5, 8-bit timer and serial interface ch. 0 IDMA request
+ //map(0x0293, 0x0293) serial interface ch. 1, A/D and port input 4-7 IDMA request
+ //map(0x0294, 0x0294) port input 0-3, high-speed DMA ch. 0-1 and 16-bit timer 0 IDMA enable
+ //map(0x0295, 0x0295) 16-bit timer 1-4 IDMA enable
+ //map(0x0296, 0x0296) 16-bit timer 5, 8-bit timer and serial interface ch. 0 IDMA enable
+ //map(0x0297, 0x0297) serial interface ch. 1, A/D and port input 4-7 IDMA enable
+ //map(0x0298, 0x0298) high-speed DMA ch. 0-1 trigger setup
+ //map(0x0299, 0x0299) high-speed DMA ch. 2-3 trigger setup
+ //map(0x029a, 0x029a) high-speed DMA software trigger
+ //map(0x029f, 0x029f) flag set/reset method select
+
+ //map(0x02c0, 0x02c0) K5 function select
+ //map(0x02c1, 0x02c1) K5 input port data
+ //map(0x02c3, 0x02c3) K6 function select
+ //map(0x02c4, 0x02c4) K6 input port data
+ //map(0x02c5, 0x02c5) interrupt factor FP function switching
+ //map(0x02c6, 0x02c6) port input interrupt select 1
+ //map(0x02c7, 0x02c7) port input interrupt select 2
+ //map(0x02c8, 0x02c8) port input interrupt input polarity select
+ //map(0x02c9, 0x02c9) port input interrupt edge/level select
+ //map(0x02ca, 0x02ca) key input interrupt select
+ //map(0x02cb, 0x02cb) interrupt factor TM16 function switching
+ //map(0x02cc, 0x02cc) key input interrupt (FPK0) input comparison
+ //map(0x02cd, 0x02cd) key input interrupt (FPK1) input comparison
+ //map(0x02ce, 0x02ce) key input interrupt (FPK0) input mask
+ //map(0x02cf, 0x02cf) key input interrupt (FPK1) input mask
+ //map(0x02d0, 0x02d0) P0 function select
+ //map(0x02d1, 0x02d1) P0 I/O port data
+ //map(0x02d2, 0x02d2) P0 I/O control
+ //map(0x02d4, 0x02d4) P1 function select
+ //map(0x02d5, 0x02d5) P1 I/O port data
+ //map(0x02d6, 0x02d6) P1 I/O control
+ //map(0x02d7, 0x02d7) port SIO function extension
+ //map(0x02d8, 0x02d8) P2 function select
+ //map(0x02d9, 0x02d9) P2 I/O port data
+ //map(0x02da, 0x02da) P2 I/O control
+ //map(0x02db, 0x02db) port SIO function extension
+ //map(0x02dc, 0x02dc) P2 function select
+ //map(0x02dd, 0x02dd) P2 I/O port data
+ //map(0x02de, 0x02de) P2 I/O control
+ //map(0x02df, 0x02df) port function extension
+
+ //map(0x8120, 0x8121) area 15-18 setup
+ //map(0x8122, 0x8123) area 13-14 setup
+ //map(0x8124, 0x8125) area 11-12 setup
+ //map(0x8126, 0x8127) area 9-10 setup
+ //map(0x8128, 0x8129) area 7-8 setup
+ //map(0x812a, 0x812b) area 4-6 setup
+ //map(0x812d, 0x812d) TTBR write protect
+ //map(0x812e, 0x812e) bus control
+ //map(0x8130, 0x8131) DRAM timing setup
+ //map(0x8132, 0x8133) access control
+ //map(0x8134, 0x8135) TTBR low
+ //map(0x8136, 0x8137) TTBR high
+ //map(0x8138, 0x8139) G/A read signal control
+ //map(0x813a, 0x813a) BCLK select
+
+ //map(0x8180, 0x8181) 16-bit timer 0 comparison A
+ //map(0x8182, 0x8183) 16-bit timer 0 comparison B
+ //map(0x8184, 0x8185) 16-bit timer 0 counter data
+ //map(0x8186, 0x8186) 16-bit timer 0 control
+ //map(0x8188, 0x8189) 16-bit timer 1 comparison A
+ //map(0x818a, 0x818b) 16-bit timer 1 comparison B
+ //map(0x818c, 0x818d) 16-bit timer 1 counter data
+ //map(0x818e, 0x818e) 16-bit timer 1 control
+ //map(0x8190, 0x8191) 16-bit timer 2 comparison A
+ //map(0x8192, 0x8193) 16-bit timer 2 comparison B
+ //map(0x8194, 0x8195) 16-bit timer 2 counter data
+ //map(0x8196, 0x8196) 16-bit timer 2 control
+ //map(0x8198, 0x8199) 16-bit timer 3 comparison A
+ //map(0x819a, 0x819b) 16-bit timer 3 comparison B
+ //map(0x819c, 0x819d) 16-bit timer 3 counter data
+ //map(0x819e, 0x819e) 16-bit timer 3 control
+ //map(0x81a0, 0x81a1) 16-bit timer 4 comparison A
+ //map(0x81a2, 0x81a3) 16-bit timer 4 comparison B
+ //map(0x81a4, 0x81a5) 16-bit timer 4 counter data
+ //map(0x81a6, 0x81a6) 16-bit timer 4 control
+ //map(0x81a8, 0x81a9) 16-bit timer 5 comparison A
+ //map(0x81aa, 0x81ab) 16-bit timer 5 comparison B
+ //map(0x81ac, 0x81ad) 16-bit timer 5 counter data
+ //map(0x81ae, 0x81ae) 16-bit timer 5 control
+
+ //map(0x8200, 0x8201) IDMA base address low
+ //map(0x8202, 0x8203) IDMA base address high
+ //map(0x8204, 0x8204) IDMA start
+ //map(0x8205, 0x8205) IDMA enable
+
+ //map(0x8220, 0x8221) high-speed DMA ch. 0 transfer counter
+ //map(0x8222, 0x8223) high-speed DMA ch. 0 control
+ //map(0x8224, 0x8225) high-speed DMA ch. 0 low-order source address set-up
+ //map(0x8226, 0x8227) high-speed DMA ch. 0 high-order source address set-up
+ //map(0x8228, 0x8229) high-speed DMA ch. 0 low-order destination address set-up
+ //map(0x822a, 0x822b) high-speed DMA ch. 0 high-order destination address set-up
+ //map(0x822c, 0x822d) high-speed DMA ch. 0 enable
+ //map(0x822e, 0x822f) high-speed DMA ch. 0 trigger flag
+ //map(0x8230, 0x8231) high-speed DMA ch. 1 transfer counter
+ //map(0x8232, 0x8233) high-speed DMA ch. 1 control
+ //map(0x8234, 0x8235) high-speed DMA ch. 1 low-order source address set-up
+ //map(0x8236, 0x8237) high-speed DMA ch. 1 high-order source address set-up
+ //map(0x8238, 0x8239) high-speed DMA ch. 1 low-order destination address set-up
+ //map(0x823a, 0x823b) high-speed DMA ch. 1 high-order destination address set-up
+ //map(0x823c, 0x823d) high-speed DMA ch. 1 enable
+ //map(0x823e, 0x823f) high-speed DMA ch. 1 trigger flag
+ //map(0x8240, 0x8241) high-speed DMA ch. 2 transfer counter
+ //map(0x8242, 0x8243) high-speed DMA ch. 2 control
+ //map(0x8244, 0x8245) high-speed DMA ch. 2 low-order source address set-up
+ //map(0x8246, 0x8247) high-speed DMA ch. 2 high-order source address set-up
+ //map(0x8248, 0x8249) high-speed DMA ch. 2 low-order destination address set-up
+ //map(0x824a, 0x824b) high-speed DMA ch. 2 high-order destination address set-up
+ //map(0x824c, 0x824d) high-speed DMA ch. 2 enable
+ //map(0x824e, 0x824f) high-speed DMA ch. 2 trigger flag
+ //map(0x8250, 0x8251) high-speed DMA ch. 3 transfer counter
+ //map(0x8252, 0x8253) high-speed DMA ch. 3 control
+ //map(0x8254, 0x8255) high-speed DMA ch. 3 low-order source address set-up
+ //map(0x8256, 0x8257) high-speed DMA ch. 3 high-order source address set-up
+ //map(0x8258, 0x8259) high-speed DMA ch. 3 low-order destination address set-up
+ //map(0x825a, 0x825b) high-speed DMA ch. 3 high-order destination address set-up
+ //map(0x825c, 0x825d) high-speed DMA ch. 3 enable
+ //map(0x825e, 0x825f) high-speed DMA ch. 3 trigger flag
+}
diff --git a/src/devices/cpu/c33/s1c33209.h b/src/devices/cpu/c33/s1c33209.h
new file mode 100644
index 00000000000..b92fd094d5c
--- /dev/null
+++ b/src/devices/cpu/c33/s1c33209.h
@@ -0,0 +1,57 @@
+// license:BSD-3-Clause
+// copyright-holders:Vas Crabb
+/*
+ Epson S1C33209/221/222 CMOS 32-bit single chip microcomputer
+*/
+
+#ifndef MAME_CPU_C33_S1C33209_H
+#define MAME_CPU_C33_S1C33209_H
+
+#pragma once
+
+#include "c33std.h"
+
+
+class s1c33209_device : public c33std_cpu_device_base
+{
+public:
+ s1c33209_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+
+protected:
+ s1c33209_device(
+ machine_config const &mconfig,
+ device_type type,
+ char const *tag,
+ device_t *owner,
+ u32 clock,
+ address_map_constructor internal_map);
+
+ template <offs_t RomBytes> void memory_map(address_map &map) ATTR_COLD;
+
+protected:
+ void device_reset() override ATTR_COLD;
+
+private:
+ void peripheral_map(address_map &map) ATTR_COLD;
+};
+
+
+class s1c33221_device : public s1c33209_device
+{
+public:
+ s1c33221_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+};
+
+
+class s1c33222_device : public s1c33209_device
+{
+public:
+ s1c33222_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
+};
+
+
+DECLARE_DEVICE_TYPE(S1C33209, s1c33209_device)
+DECLARE_DEVICE_TYPE(S1C33221, s1c33221_device)
+DECLARE_DEVICE_TYPE(S1C33222, s1c33222_device)
+
+#endif // MAME_CPU_C33_S1C33209_H