summaryrefslogtreecommitdiffstats
path: root/src/emu/cpu/pps4/pps4.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/cpu/pps4/pps4.c')
-rw-r--r--src/emu/cpu/pps4/pps4.c1776
1 files changed, 1469 insertions, 307 deletions
diff --git a/src/emu/cpu/pps4/pps4.c b/src/emu/cpu/pps4/pps4.c
index 130b70d5b39..2611bbab53e 100644
--- a/src/emu/cpu/pps4/pps4.c
+++ b/src/emu/cpu/pps4/pps4.c
@@ -1,5 +1,6 @@
// license:BSD-3-Clause
-// copyright-holders:Miodrag Milanovic
+// copyright-holders:Juergen Buchmueller <pullmoll@t-online.de>
+
/*****************************************************************************
*
* pps4.c
@@ -31,300 +32,1448 @@
#include "debugger.h"
#include "pps4.h"
-#define VERBOSE 0
-#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
+#define VERBOSE 0 //!< set to 1 to log certain instruction conditions
+#if VERBOSE
+#define LOG(x) logerror x
+#else
+#define LOG(x)
+#endif
const device_type PPS4 = &device_creator<pps4_device>;
-
pps4_device::pps4_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
- : cpu_device(mconfig, PPS4, "PPS4", tag, owner, clock, "pps4", __FILE__ )
- , m_program_config("program", ENDIANNESS_LITTLE, 8, 12)
- , m_data_config("data", ENDIANNESS_LITTLE, 8, 12) // 4bit RAM
- , m_io_config("io", ENDIANNESS_LITTLE, 8, 8) // 4bit IO
+ : cpu_device(mconfig, PPS4, "PPS4", tag, owner, clock, "pps4", __FILE__ )
+ , m_program_config("program", ENDIANNESS_LITTLE, 8, 12)
+ , m_data_config("data", ENDIANNESS_LITTLE, 8, 12) // 4bit RAM
+ , m_io_config("io", ENDIANNESS_LITTLE, 8, 8) // 4bit IO
{
}
+/**
+ * @brief pps4_device::M Return the memory at address B
+ * @return ROM/RAM(B)
+ */
+UINT8 pps4_device::M()
+{
+ UINT8 ret = m_data->read_byte(m_B & ~m_SAG);
+ m_SAG = 0;
+ return ret;
+}
-offs_t pps4_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
+
+/**
+ * @brief pps4_device::W Write to the memory address at B
+ * @return ROM/RAM(B)
+ */
+void pps4_device::W(UINT8 data)
{
- extern CPU_DISASSEMBLE( pps4 );
- return CPU_DISASSEMBLE_NAME(pps4)(this, buffer, pc, oprom, opram, options);
+ m_data->write_byte(m_B & ~m_SAG, data);
+ m_SAG = 0;
}
+offs_t pps4_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
+{
+ extern CPU_DISASSEMBLE( pps4 );
+ return CPU_DISASSEMBLE_NAME(pps4)(this, buffer, pc, oprom, opram, options);
+}
+/**
+ * @brief pps4_device::ROP Read the next opcode (instruction)
+ * @return m_I
+ */
inline UINT8 pps4_device::ROP()
{
- UINT8 retVal = m_direct->read_decrypted_byte(m_P.w.l);
- m_P.w.l = (m_P.w.l + 1) & 0x0fff;
- return retVal;
+ m_Ip = m_I & 0xf0; // set previous opcode mask
+ m_I = m_direct->read_decrypted_byte(m_P & 0xFFF);
+ m_P = (m_P + 1) & 0xFFF;
+ m_icount -= 1;
+ return m_I;
}
+/**
+ * @brief pps4_device::ARG Read the next argument (instrunction 2)
+ * @return m_I2
+ */
inline UINT8 pps4_device::ARG()
{
- UINT8 retVal = m_direct->read_raw_byte(m_P.w.l);
- m_P.w.l = (m_P.w.l + 1) & 0x0fff;
- return retVal;
-}
-
-inline void pps4_device::DO_SKIP()
-{
- m_P.w.l = (m_P.w.l + 1) & 0x0fff;
-}
-
-void pps4_device::execute_one(int opcode)
-{
- m_icount -= 1;
- switch (opcode)
- {
- // Arithmetic instructions
- case 0x0b: // AD
- break;
- case 0x0a: // ADC
- break;
- case 0x09: // ADSK
- break;
- case 0x08: // ADCSK
- break;
- case 0x60: case 0x61: case 0x62: case 0x63:
- case 0x64: case 0x66: case 0x67: case 0x68:
- case 0x69: case 0x6a: case 0x6b: case 0x6c:
- case 0x6d: case 0x6e:
- // ADI
- break;
- case 0x65: //DC
- m_A = (m_A + 10) & 0x0f;
- break;
- // Logical instructions
- case 0x0d: // AND
- break;
- case 0x0f: // OR
- break;
- case 0x0c: // EOR
- break;
- case 0x0e: // COMP
- m_A ^= 0x0f;
- break;
- // Data transfer instructions
- case 0x20: // SC
- m_C = 1;
- break;
- case 0x24: //RC
- m_C = 0;
- break;
- case 0x22: // SF1
- m_FF1 = 1;
- break;
- case 0x26: // RF1
- m_FF1 = 0;
- break;
- case 0x21: // SF2
- m_FF2 = 1;
- break;
- case 0x25: // RF2
- m_FF2 = 0;
- break;
- case 0x30: case 0x31: case 0x32: case 0x33:
- case 0x34: case 0x35: case 0x36: case 0x37:
- // LD
- break;
- case 0x38: case 0x39: case 0x3a: case 0x3b:
- case 0x3c: case 0x3d: case 0x3e: case 0x3f:
- // EX
- break;
- case 0x28: case 0x29: case 0x2a: case 0x2b:
- case 0x2c: case 0x2d: case 0x2e: case 0x2f:
- // EXD
- break;
- 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:
- // LDI
- m_A = opcode & 0x0f;
- break;
- case 0x12: // LAX
- m_A = m_X;
- break;
- case 0x1b: // LXA
- m_X = m_A;
- break;
- case 0x11: // LABL
- m_A = m_B.w.l & 0x00f;
- break;
- case 0x10: // LBMX
- m_B.w.l &= 0xf0f;
- m_B.w.l |= (m_X << 4);
- break;
- case 0x04: // LBUA
- break;
- case 0x19: // XABL
- {
- UINT8 tmp = m_B.w.l & 0x00f;
- m_B.w.l &= 0xff0;
- m_B.w.l |= m_A;
- m_A = tmp;
- }
- break;
- case 0x18: // XBMX
- {
- UINT8 tmp = (m_B.w.l & 0x0f0) >> 4;
- m_B.w.l &= 0xf0f;
- m_B.w.l |= (m_X << 4);
- m_X = tmp;
- }
- break;
- case 0x1a: // XAX
- {
- UINT8 tmp = m_A;
- m_A = m_X;
- m_X = tmp;
- }
- break;
- case 0x06: // XS
- {
- PAIR tmp = m_SA;
- m_SA = m_SB;
- m_SB = tmp;
- }
- break;
- case 0x6f: // CYS
- break;
- case 0xc0: case 0xc1: case 0xc2: case 0xc3:
- case 0xc4: case 0xc5: case 0xc6: case 0xc7:
- case 0xc8: case 0xc9: case 0xca: case 0xcb:
- case 0xcc: case 0xcd: case 0xce: case 0xcf:
- // LB
- {
- //UINT8 tmp = ARG();
- m_icount -= 1;
- }
- break;
- case 0x00: // LBL
- {
- UINT8 tmp = ARG();
- m_icount -= 1;
- m_B.w.l = tmp;
- }
- break;
- case 0x17: // INCB
- if ((m_B.w.l & 0x0f) == 0x0f) {
- m_B.w.l &= 0xff0;
- DO_SKIP();
- } else {
- m_B.w.l += 1;
- }
- break;
- case 0x1f: // DECB
- if ((m_B.w.l & 0x0f) == 0x00) {
- m_B.w.l |= 0x00f;
- DO_SKIP();
- } else {
- m_B.w.l -= 1;
- }
- break;
- // Control transfer instructions
- case 0x80: case 0x81: case 0x82: case 0x83:
- case 0x84: case 0x85: case 0x86: case 0x87:
- case 0x88: case 0x89: case 0x8a: case 0x8b:
- case 0x8c: case 0x8d: case 0x8e: case 0x8f:
- case 0x90: case 0x91: case 0x92: case 0x93:
- case 0x94: case 0x95: case 0x96: case 0x97:
- case 0x98: case 0x99: case 0x9a: case 0x9b:
- case 0x9c: case 0x9d: case 0x9e: case 0x9f:
- case 0xa0: case 0xa1: case 0xa2: case 0xa3:
- case 0xa4: case 0xa5: case 0xa6: case 0xa7:
- case 0xa8: case 0xa9: case 0xaa: case 0xab:
- case 0xac: case 0xad: case 0xae: case 0xaf:
- case 0xb0: case 0xb1: case 0xb2: case 0xb3:
- case 0xb4: case 0xb5: case 0xb6: case 0xb7:
- case 0xb8: case 0xb9: case 0xba: case 0xbb:
- case 0xbc: case 0xbd: case 0xbe: case 0xbf:
- // T
- m_P.w.l = (m_P.w.l & 0xfc0) | (opcode & 0x3f);
- break;
- case 0xd0: case 0xd1: case 0xd2: case 0xd3:
- case 0xd4: case 0xd5: case 0xd6: case 0xd7:
- case 0xd8: case 0xd9: case 0xda: case 0xdb:
- case 0xdc: case 0xdd: case 0xde: case 0xdf:
- case 0xe0: case 0xe1: case 0xe2: case 0xe3:
- case 0xe4: case 0xe5: case 0xe6: case 0xe7:
- case 0xe8: case 0xe9: case 0xea: case 0xeb:
- case 0xec: case 0xed: case 0xee: case 0xef:
- case 0xf0: case 0xf1: case 0xf2: case 0xf3:
- case 0xf4: case 0xf5: case 0xf6: case 0xf7:
- case 0xf8: case 0xf9: case 0xfa: case 0xfb:
- case 0xfc: case 0xfd: case 0xfe: case 0xff:
- // TM
- break;
- 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:
- // TL
- {
- //UINT8 tmp = ARG();
- m_icount -= 1;
- }
- break;
- case 0x01: case 0x02: case 0x03:
- // TML
- {
- //UINT8 tmp = ARG();
- m_icount -= 1;
- }
- break;
- case 0x15: // SKC
- break;
- case 0x1e: // SKZ
- 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:
- // SKBI
- break;
- case 0x16: // SKF1
- break;
- case 0x14: // SKF2
- break;
- case 0x05: // RTN
- break;
- case 0x07: // RTNSK
- break;
- // Input/Output instructions
- case 0x1c: // IOL
- {
- //UINT8 tmp = ARG();
- m_icount -= 1;
- }
- break;
- case 0x27: // DIA
- break;
- case 0x23: // DIB
- break;
- case 0x1d: // DOA
- break;
- // Special instructions
- case 0x13: // SAG
- break;
- }
+ m_I2 = m_direct->read_raw_byte(m_P & 0xFFF);
+ m_P = (m_P + 1) & 0xFFF;
+ m_icount -= 1;
+ return m_I2;
+}
+
+/**
+ * @brief Note3
+ *
+ * Instructions ADI, LD, EX, EXD, LDI, LB and LBL have a numeric
+ * value coded as part of the instruction in the immediate field.
+ * This numeric value must be in complementary form on the bus.
+ * All of these immediate fields which are inverted are shown
+ * in brackets.
+ * For example: ADI 1, as written by the programmer who wishes
+ * to add one to the value in the accumulator, is converted to
+ * 0x6E = 01001 [1110]; the bracketed binary value is the value
+ * as seen on the data bus.
+ * If the programmer is using the Rockwell Assembler he does not
+ * have to manually determine the proper inverted value as the
+ * assembler does this for him.
+ *
+ * [And we do in MAME as well :-]
+ */
+
+/**
+ * @brief pps4_device::iAD Add
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0000 1011 1 cyc AD
+ *
+ * Symbolic equation
+ * -----------------------------
+ * C, A <- A + M
+ *
+ * The result of the binary addition of contents of accumulator
+ * and 4-bit contents of RAM currently addressed by B register,
+ * replaces the contents of the accumulator. The resulting
+ * carry-out is loaded into C flip-flop.
+ */
+void pps4_device::iAD()
+{
+ m_A = m_A + M();
+ m_C = m_A >> 4;
+ m_A = m_A & 15;
+}
+
+/**
+ * @brief pps4_device::iADC Add with carry-in
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0000 1010 1 cyc ADC
+ *
+ * Symbolic equation
+ * -----------------------------
+ * C, A <- A + M + C
+ *
+ * Same as AD except the C flip-flop serves as a carry-in
+ * to the adder.
+ */
+void pps4_device::iADC()
+{
+ m_A = m_A + M() + m_C;
+ m_C = m_A >> 4;
+ m_A = m_A & 15;
+}
+
+/**
+ * @brief pps4_device::iADSK Add and skip if carry-out
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0000 1001 1 cyc ADSK
+ *
+ * Symbolic equation
+ * -----------------------------
+ * C, A <- A + M
+ * Skip if C = 1
+ *
+ * Same as AD except the next ROM word will be
+ * skipped (ignored) if a carry-out is generated.
+ */
+void pps4_device::iADSK()
+{
+ m_A = m_A + M();
+ m_C = m_A >> 4;
+ m_A = m_A & 15;
+ m_P = (m_P + m_C) & 0xFFF;
+}
+
+/**
+ * @brief pps4_device::iADCSK Add with carry-in and skip if carry-out
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0000 1000 1 cyc ADCSK
+ *
+ * Symbolic equation
+ * -----------------------------
+ * C, A <- A + M + C
+ * Skip if C = 1
+ *
+ * Same as ADC except the next ROM word will be
+ * skipped (ignored) if a carry-out is generated.
+ */
+void pps4_device::iADCSK()
+{
+ m_A = m_A + M() + m_C;
+ m_C = m_A >> 4;
+ m_A = m_A & 15;
+ m_P = (m_P + m_C) & 0xFFF;
+}
+
+/**
+ * @brief pps4_device::iAND Logical AND
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0000 1101 1 cyc AND
+ *
+ * Symbolic equation
+ * -----------------------------
+ * A <- A & M
+ *
+ * The result of logical AND of accumulator and
+ * 4-bit contents of RAM currently addressed by
+ * B register replaces contents of accumulator.
+ */
+void pps4_device::iAND()
+{
+ m_A = m_A & M();
+}
+
+/**
+ * @brief pps4_device::iADI Add immediate
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0110 xxxx 1 cyc ADI #x
+ *
+ * Symbolic equation
+ * -----------------------------
+ * A <- A + [I(4:1)]
+ *
+ * The result of the binary addition of contents of
+ * accumulator and 4-bit immediate field of instruction
+ * word replaces the contents of accumulator.
+ * The next ROM word will be skipped (ignored) if a
+ * carry-out is generated.
+ * __ The instruction does not use or change the C flip-flop. __
+ * The immediate field I(4:1) of this instruction may not
+ * be equal to binary 0 (CYS) or 0101 (DC)
+ *
+ * See %Note3
+ */
+void pps4_device::iADI()
+{
+ const UINT8 imm = ~m_I & 15;
+ m_A = m_A + imm;
+ m_P = m_P + (m_A > 15) ? 1 : 0;
+ m_A = m_A & 15;
+ m_P = m_P & 0xFFF;
+}
+
+/**
+ * @brief pps4_device::iDC Decimal correction
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0110 0110 1 cyc DC
+ *
+ * Symbolic equation
+ * -----------------------------
+ * A <- A + 1010b
+ *
+ * Decimal correction of accumulator.
+ * Binary 1010 is added to the contents of the accumulator.
+ * Result is stored in accumulator. Instruction does not
+ * use or change carry flip-flop or skip.
+ */
+void pps4_device::iDC()
+{
+ m_A = m_A + 10;
+}
+
+/**
+ * @brief pps4_device::iOR Logical OR
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0000 1111 1 cyc OR
+ *
+ * Symbolic equation
+ * -----------------------------
+ * A <- A | M
+ *
+ * The result of logical OIR of accumulator and
+ * 4-bit contents of RAM currently addressed by
+ * B register replaces contents of accumulator.
+ */
+void pps4_device::iOR()
+{
+ m_A = m_A | M();
+}
+
+/**
+ * @brief pps4_device::iEOR Logical exclusive-OR
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0000 1100 1 cyc EOR
+ *
+ * Symbolic equation
+ * -----------------------------
+ * A <- A ^ M
+ *
+ * The result of logical exclusive-OR of
+ * accumulator and 4-bit contents of RAM
+ * currently addressed by B register
+ * replaces contents of accumulator.
+ */
+void pps4_device::iEOR()
+{
+ m_A = m_A ^ M();
+}
+
+/**
+ * @brief pps4_device::iCOMP Complement
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0000 1110 1 cyc COMP
+ *
+ * Symbolic equation
+ * -----------------------------
+ * A <- ~A
+ *
+ * Each bit of the accumulator is logically
+ * complemented and placed in accumulator.
+ */
+void pps4_device::iCOMP()
+{
+ m_A = ~m_A & 15;
+}
+
+/**
+ * @brief pps4_device::iSC Set carry flip-flop
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0010 0000 1 cyc SC
+ *
+ * Symbolic equation
+ * -----------------------------
+ * C <- 1
+ *
+ * The C flip-flop is set to 1.
+ */
+void pps4_device::iSC()
+{
+ m_C = 1;
+}
+
+/**
+ * @brief pps4_device::iRC Reset carry flip-flop
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0010 0100 1 cyc RC
+ *
+ * Symbolic equation
+ * -----------------------------
+ * C <- 0
+ *
+ * The C flip-flop is set to 0.
+ */
+void pps4_device::iRC()
+{
+ m_C = 0;
+}
+
+/**
+ * @brief pps4_device::iSF1 Set flip-flop FF1
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0010 0010 1 cyc SF1
+ *
+ * Symbolic equation
+ * -----------------------------
+ * FF1 <- 1
+ *
+ * The Flip-flop FF1 is set to 1.
+ */
+void pps4_device::iSF1()
+{
+ m_FF1 = 1;
+}
+
+/**
+ * @brief pps4_device::iRF1 Reset flip-flop FF1
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0010 0100 1 cyc RF1
+ *
+ * Symbolic equation
+ * -----------------------------
+ * FF1 <- 0
+ *
+ * The Flip-flop FF1 is set to 0.
+ */
+void pps4_device::iRF1()
+{
+ m_FF1 = 0;
+}
+
+/**
+ * @brief pps4_device::iSF2 Set flip-flop FF2
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0010 0001 1 cyc SF2
+ *
+ * Symbolic equation
+ * -----------------------------
+ * FF2 <- 1
+ *
+ * The Flip-flop FF2 is set to 1.
+ */
+void pps4_device::iSF2()
+{
+ m_FF2 = 1;
+}
+
+/**
+ * @brief pps4_device::iRF2 Reset flip-flop FF2
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0010 0101 1 cyc RF2
+ *
+ * Symbolic equation
+ * -----------------------------
+ * FF2 <- 0
+ *
+ * The flip-flop FF2 is set to 0.
+ */
+void pps4_device::iRF2()
+{
+ m_FF2 = 0;
+}
+
+/**
+ * @brief pps4_device::iLD Load accumulator from memory
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0011 0xxx 1 cyc LDx
+ *
+ * Symbolic equation
+ * -----------------------------
+ * A <- M
+ * B(7:5) <- B(7:5) ^ [I(3:1)]
+ *
+ * The 4-bit contents of RAM currently addressed
+ * by B register are placed in the accumulator.
+ * The RAM address in the B register is then
+ * modified by the result of an exclusive-OR of
+ * the 3-b it immediate field I(3:1) and B(7:5)
+ *
+ * See %Note3
+ */
+void pps4_device::iLD()
+{
+ const UINT16 imm = ~m_I & 7;
+ m_A = M();
+ m_B = m_B ^ (imm << 4);
+}
+
+/**
+ * @brief pps4_device::iEX Exchange accumulator and memory
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0011 1xxx 1 cyc EXx
+ *
+ * Symbolic equation
+ * -----------------------------
+ * A <-> M
+ * B(7:5) <- B(7:5) ^ [I(3:1)]
+ *
+ * The same as LD except the contents of accumulator
+ * are also placed in currently addressed RAM location.
+ *
+ * See %Note3
+ */
+void pps4_device::iEX()
+{
+ const UINT16 imm = ~m_I & 7;
+ const UINT8 mem = M();
+ W(m_A);
+ m_A = mem;
+ m_B = m_B ^ (imm << 4);
+}
+
+/**
+ * @brief pps4_device::iEXD Exchange accumulator and memory and decrement BL
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0010 1xxx 1 cyc EXD x
+ *
+ * Symbolic equation
+ * -----------------------------
+ * A <-> M
+ * B(7:5) <- B(7:5) ^ [I(3:1)]
+ * BL <- BL - 1
+ * Skip on BL = 1111b
+ *
+ * The same as EX except RAM address in B register
+ * is further modified by decrementing BL by 1.
+ * If the new contents of BL is 1111, the next
+ * ROM word will be ignored.
+ *
+ * See %Note3
+ */
+void pps4_device::iEXD()
+{
+ const UINT8 imm = ~m_I & 7;
+ const UINT8 mem = M();
+ UINT8 bl = m_B & 15;
+ W(m_A);
+ m_A = mem;
+ m_B = m_B ^ (imm << 4);
+ if (0 == bl) {
+ // decrement BL wraps to 1111b
+ bl = 15;
+ m_P = (m_P + 1) & 0xFFF;
+ } else {
+ // decrement BL
+ bl = bl - 1;
+ }
+ m_B = (m_B & ~15) | bl;
}
+/**
+ * @brief pps4_device::iLDI Load accumualtor immediate
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0111 xxxx 1 cyc LDI x
+ *
+ * Symbolic equation
+ * -----------------------------
+ * A <- [I(4:1)]
+ *
+ * The 4-bit contents, immediate field I(4:1),
+ * of the instruction are placed in the accumulator.
+ *
+ * Note: Only the first occurence of an LDI in a consecutive
+ * string of LDIs will be executed. The program will ignore
+ * remaining LDIs and execute next valid instruction.
+ *
+ * See %Note3
+ */
+void pps4_device::iLDI()
+{
+ // previous LDI instruction?
+ if (0x70 == m_Ip) {
+ LOG(("%s: skip prev:%02x\n", __FUNCTION__, m_Ip));
+ return;
+ }
+ m_A = ~m_I & 15;
+}
+
+/**
+ * @brief pps4_device::iLAX
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0001 0010 1 cyc LAX
+ *
+ * Symbolic equation
+ * -----------------------------
+ * A <- X
+ *
+ * The 4-bit contents of the X register are
+ * placed in the accumulator.
+ */
+void pps4_device::iLAX()
+{
+ m_A = m_X;
+}
+
+/**
+ * @brief pps4_device::iLXA
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0001 1011 1 cyc LAX
+ *
+ * Symbolic equation
+ * -----------------------------
+ * X <- A
+ *
+ * The contents of the accumulator are
+ * tansferred to the X register.
+ */
+void pps4_device::iLXA()
+{
+ m_X = m_A;
+}
+
+/**
+ * @brief pps4_device::iLABL
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0001 0001 1 cyc LABL
+ *
+ * Symbolic equation
+ * -----------------------------
+ * A <- BL
+ *
+ * The contents of BL register are
+ * tansferred to the accumulator.
+ */
+void pps4_device::iLABL()
+{
+ m_A = m_B & 15;
+}
+
+/**
+ * @brief pps4_device::iLBMX
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0001 0000 1 cyc LBMX
+ *
+ * Symbolic equation
+ * -----------------------------
+ * BM <- X
+ *
+ * The contents of X register are
+ * tansferred to BM register.
+ */
+void pps4_device::iLBMX()
+{
+ m_B = (m_B & ~(15 << 4)) | (m_X << 4);
+}
+
+/**
+ * @brief pps4_device::iLBUA
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0001 0000 1 cyc LBUA
+ *
+ * Symbolic equation
+ * -----------------------------
+ * BU <- A
+ * A <- M
+ *
+ * The contents of accumulator are tansferred to
+ * BU register. Also, the contents of the currently
+ * addressed RAM are transferred to accumulator.
+ */
+void pps4_device::iLBUA()
+{
+ m_B = (m_B & ~(15 << 8)) | (m_A << 8);
+ m_A = M();
+}
+
+/**
+ * @brief pps4_device::iXABL
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0001 1001 1 cyc XABL
+ *
+ * Symbolic equation
+ * -----------------------------
+ * A <-> BL
+ *
+ * The contents of accumulator and BL register
+ * are exchanged.
+ */
+void pps4_device::iXABL()
+{
+ // swap A and BL
+ UINT8 bl = m_B & 15;
+ m_B = (m_B & ~15) | m_A;
+ m_A = bl;
+}
+
+/**
+ * @brief pps4_device::iXMBX
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0001 1000 1 cyc XMBX
+ *
+ * Symbolic equation
+ * -----------------------------
+ * X <-> BM
+ *
+ * The contents of accumulator and BL register
+ * are exchanged.
+ */
+void pps4_device::iXBMX()
+{
+ // swap X and BM
+ UINT8 bm = (m_B >> 4) & 15;
+ m_B = (m_B & ~(15 << 4)) | (m_X << 4);
+ m_X = bm;
+}
+
+/**
+ * @brief pps4_device::iXAX
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0001 1010 1 cyc XAX
+ *
+ * Symbolic equation
+ * -----------------------------
+ * A <-> X
+ *
+ * The contents of accumulator and X register
+ * are exchanged.
+ */
+void pps4_device::iXAX()
+{
+ // swap A and X
+ m_A ^= m_X;
+ m_X ^= m_A;
+ m_A ^= m_X;
+}
+
+/**
+ * @brief pps4_device::iXS
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0000 0110 1 cyc XS
+ *
+ * Symbolic equation
+ * -----------------------------
+ * SA <-> SB
+ *
+ * The 12-bit contents of SA and SB register
+ * are exchanged.
+ */
+void pps4_device::iXS()
+{
+ // swap SA and SB
+ m_SA ^= m_SB;
+ m_SB ^= m_SA;
+ m_SA ^= m_SB;
+}
+
+/**
+ * @brief pps4_device::iCYS
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0110 1111 1 cyc CYS
+ *
+ * Symbolic equation
+ * -----------------------------
+ * A <- SA(4:1)
+ * SA(4:1) <- SA(8:5)
+ * SA(8:5) <- SA(12:9)
+ * SA(12:9) <- A
+ *
+ * A 4-bit right shift of the SA register takes place
+ * with the four bits which are shifted off the end
+ * of SA being transferred into the accumulator.
+ * The contents of the accumulator are placed in the
+ * left end of the SA register
+ *
+ */
+void pps4_device::iCYS()
+{
+ const UINT16 sa = (m_SA >> 4) | (m_A << 12);
+ m_A = m_SA & 15;
+ m_SA = sa;
+}
+
+/**
+ * @brief pps4_device::iLB
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 1100 0000 2 cyc LB
+ *
+ * Symbolic equation
+ * -----------------------------
+ * SB <- SA, SA <- P
+ * P(12:5) <- 0000 1100
+ * P(4:1) <- I(4:1)
+ *
+ * BU <- 0000
+ * B(8:1) <- [I2(8:1)]
+ * P <- SA, SA <-> SB
+ *
+ * Sixteen consecutive locations on ROM page 3 (I2) contain
+ * data which can be loaded into the eight least significant
+ * bits of the B register by use of any LB instruction.
+ * The four most significant bits of B register will be loaded
+ * with zeros. The contents of the SB register will be destroyed.
+ * This instruction takes two cycles to execute but occupies
+ * only one ROM word. (Automatic return)
+ *
+ * Only the first occurence of an LB or LBL instruction in a
+ * consecutive string of LB or LBL will be executed. The
+ * program will ignore the remaining LB or LBL and execute
+ * the next valid instruction. Within subroutines the LB
+ * instruction must be used with caution because the contents
+ * of SB have been modified.
+ *
+ * See %Note3 and %Note4
+ */
+void pps4_device::iLB()
+{
+ // previous LB or LBL instruction?
+ if (0xc0 == m_Ip|| 0x00 == m_Ip) {
+ LOG(("%s: skip prev:%02X\n", __FUNCTION__, m_Ip));
+ return;
+ }
+ m_SB = m_SA;
+ m_SA = (m_P + 1) & 0xFFF;
+ m_P = (3 << 8) | (m_I & 15);
+ m_B = ~ARG() & 255;
+ m_P = m_SA;
+ // swap SA and SB
+ m_SA ^= m_SB;
+ m_SB ^= m_SA;
+ m_SA ^= m_SB;
+}
+
+/**
+ * @brief pps4_device::iLBL
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0000 0000 2 cyc LBL
+ *
+ * Symbolic equation
+ * -----------------------------
+ * BU <- 0000
+ * B(8:1) <- [I2(8:1)]
+ *
+ * This instruction occupies two ROM words, the second of
+ * which will be loaded into the eight least significant
+ * bits of the B register. The four most significant bits
+ * of B (BU) will be loaded with zeroes.
+ *
+ * Only the first occurence of an LB or LBL instruction in a
+ * consecutive string of LB or LBL will be executed. The
+ * program will ignore the remaining LB or LBL and execute
+ * the next valid instruction.
+ *
+ * See %Note3
+ */
+void pps4_device::iLBL()
+{
+ // previous LB or LBL instruction?
+ if (0xc0 == m_Ip || 0x00 == m_Ip) {
+ LOG(("%s: skip prev:%02X\n", __FUNCTION__, m_Ip));
+ return;
+ }
+ m_B = ~ARG() & 255;
+}
+
+/**
+ * @brief pps4_device::INCB
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0001 0111 1 cyc INCB
+ *
+ * Symbolic equation
+ * -----------------------------
+ * BL <- BL + 1
+ * Skip on BL = 0000
+ *
+ * BL register (least significant four bits of B register)
+ * is incremented by 1. If the new contents of BL is 0000b,
+ * then the next ROM word will be ignored.
+ */
+void pps4_device::iINCB()
+{
+ UINT8 bl = m_B & 15;
+ bl = (bl + 1) & 15;
+ if (0 == bl) {
+ LOG(("%s: skip BL=%x\n", __FUNCTION__, bl));
+ m_P = (m_P + 1) & 0xFFF;
+ }
+ m_B = (m_B & ~15) | bl;
+}
+
+/**
+ * @brief pps4_device::iDECB
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0001 1111 1 cyc DECB
+ *
+ * Symbolic equation
+ * -----------------------------
+ * BL <- BL - 1
+ * Skip on BL = 1111
+ *
+ * BL register is decremented by 1. If the new
+ * contents of BL is 1111b, then the next ROM
+ * word will be ignored.
+ */
+void pps4_device::iDECB()
+{
+ UINT8 bl = m_B & 15;
+ bl = (bl - 1) & 15;
+ if (15 == bl) {
+ LOG(("%s: skip BL=%x\n", __FUNCTION__, bl));
+ m_P = (m_P + 1) & 0xFFF;
+ }
+ m_B = (m_B & ~15) | bl;
+}
+
+/**
+ * @brief pps4_device::iT Transfer
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 10xx xxxx 1 cyc T *
+ *
+ * Symbolic equation
+ * -----------------------------
+ * P(6:1) <- I(6:1)
+ *
+ * An unconditional transfer to a ROM word on the current
+ * page takes place. The least significant 6-bits of P
+ * register P(6:1) are replaced by six bit immediate
+ * field I(6:1)
+ */
+void pps4_device::iT()
+{
+ const UINT16 p = (m_P & ~63) | (m_I & 63);
+ LOG(("%s: P=%03x I=%02x -> P=%03x\n", __FUNCTION__, m_P, m_I, p));
+ m_P = p;
+}
+
+/**
+ * @brief pps4_device::iTM Transfer and mark indirect
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 11xx xxxx 2 cyc TM *
+ * yyyy yyyy from page 3
+ *
+ * Symbolic equation
+ * -----------------------------
+ * SB <- SA, SA <- P
+ * P(12:7) <- 000011
+ * P(6:1) <- I1(6:1)
+ *
+ * P(12:9) <- 0001
+ * P(8:1) <- I2(8:1)
+ *
+ * 48 consecutive locations on ROM page 3 contains pointer data
+ * which indentify subroutine entry addresses. These subroutine
+ * entry addresses are limited to pages 4 through 7. This TM
+ * instruction will save the address of the next ROM word in
+ * the SA register after loading the original contents of SA
+ * into SB. A transfer then occurs to one of the subroutine
+ * entry addresses. This instruction occupies one ROM word
+ * but takes two cycles for execution.
+ */
+void pps4_device::iTM()
+{
+ m_SB = m_SA;
+ m_SA = m_P;
+ m_P = 3 << 6;
+ m_P = m_P | (m_I & 63);
+ ARG();
+ m_P = 1 << 8;
+ m_P |= m_I2;
+}
+
+/**
+ * @brief pps4_device::iTL Transfer long
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0101 xxxx 2 cyc TL *
+ * yyyy yyyy
+ *
+ * Symbolic equation
+ * -----------------------------
+ * P(12:9) <- I1(4:1)
+ * P(8:1) <- I2(8:1)
+ *
+ * The instruction executes a transfer to any ROM word on any
+ * page. It occupies two ROM words an requires two cycles for
+ * execution. The first byte loads P(12:9) with field I1(4:1)
+ * and then the second byte I2(8:1) is placed in P(8:1).
+ */
+void pps4_device::iTL()
+{
+ ARG();
+ m_P = (m_I & 15) << 8;
+ m_P = m_P | m_I2;
+}
+
+/**
+ * @brief pps4_device::iTML Transfer and mark long
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0101 xxxx 2 cyc TML *
+ * yyyy yyyy
+ *
+ * Symbolic equation
+ * -----------------------------
+ * SB <- SA, SA <- P
+ * P(12:9) <- I1(4:1)
+ * P(8:1) <- I2(8:1)
+ *
+ * Note I1(2:1) != 00
+ *
+ * This instruction executes a transfer and mark to any
+ * location on ROM pages 4 through 15. It occupies two
+ * ROM words and requires two cycle times for execution.
+ */
+void pps4_device::iTML()
+{
+ ARG();
+ m_SB = m_SA;
+ m_SA = m_P;
+ m_P = (m_I & 15) << 8;
+ m_P = m_P | m_I2;
+}
+
+/**
+ * @brief pps4_device::iSKC Skip on carry flip-flop
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0001 0101 1 cyc SKC
+ *
+ * Symbolic equation
+ * -----------------------------
+ * Skip if C = 1
+ *
+ * The next ROM word will be ignored if C flip-flop is 1.
+ */
+void pps4_device::iSKC()
+{
+ m_P = m_P + m_C;
+ m_P = m_P & 0xFFF;
+}
+
+/**
+ * @brief pps4_device::iSKC Skip on carry flip-flop
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0001 1110 1 cyc SKZ
+ *
+ * Symbolic equation
+ * -----------------------------
+ * Skip if A = 0
+ *
+ * The next ROM word will be ignored if C flip-flop is 1.
+ */
+void pps4_device::iSKZ()
+{
+ m_P = m_P + (0 == m_A) ? 1 : 0;
+ m_P = m_P & 0xFFF;
+}
+
+/**
+ * @brief pps4_device::iSKBI Skip if BL equal to immediate
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0100 xxxx 1 cyc SKBI x
+ *
+ * Symbolic equation
+ * -----------------------------
+ * Skip if BL = I(4:1)
+ *
+ * The next ROM word will be ignored if the least significant
+ * four bits of B register (BL) is equal to the 4-bit immediate
+ * field I(4:1) of instruction.
+ */
+void pps4_device::iSKBI()
+{
+ const unsigned imm = m_I & 15;
+ m_P = m_P + (imm == (m_B & 15)) ? 1 : 0;
+ m_P = m_P & 0xFFF;
+}
+
+/**
+ * @brief pps4_device::iSKF1 Skip if FF1 equals 1
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0001 0110 1 cyc SKF1
+ *
+ * Symbolic equation
+ * -----------------------------
+ * Skip if FF1 = 1
+ */
+void pps4_device::iSKF1()
+{
+ m_P = m_P + m_FF1;
+ m_P = m_P & 0xFFF;
+}
+
+/**
+ * @brief pps4_device::iSKF2 Skip if FF2 equals 1
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0001 0100 1 cyc SKF2
+ *
+ * Symbolic equation
+ * -----------------------------
+ * Skip if FF2 = 1
+ */
+void pps4_device::iSKF2()
+{
+ m_P = m_P + m_FF2;
+ m_P = m_P & 0xFFF;
+}
+
+/**
+ * @brief pps4_device::iRTN Return
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0000 0101 1 cyc RET
+ *
+ * Symbolic equation
+ * -----------------------------
+ * P <- SA, SA <-> SB
+ *
+ * This instruction executes a return from subroutine
+ * by loading contents of SA register into P register
+ * and interchanges the SB and SA registers.
+ */
+void pps4_device::iRTN()
+{
+ m_P = m_SA;
+ // swap SA and SB
+ m_SA ^= m_SB;
+ m_SB ^= m_SA;
+ m_SA ^= m_SB;
+}
+
+/**
+ * @brief pps4_device::iRTN Return
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0000 0111 1 cyc RETSK
+ *
+ * Symbolic equation
+ * -----------------------------
+ * P <- SA, SA <-> SB
+ * P <- P + 1
+ *
+ * Same as RTN expect the first ROM word encountered
+ * after the return from subroutine is skipped.
+ */
+void pps4_device::iRTNSK()
+{
+ m_P = m_SA;
+ ROP(); // ignored
+ m_I = 0; // avoid LB/LBL or LDI skipping
+ // swap SA and SB
+ m_SA ^= m_SB;
+ m_SB ^= m_SA;
+ m_SA ^= m_SB;
+ m_P = m_P & 0xFFF;
+}
+
+/**
+ * @brief pps4_device::IOL
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0001 1100 2 cyc IOL
+ * yyyy yyyy
+ *
+ * Symbolic equation
+ * -----------------------------
+ * ~A -> Data Bus
+ * A <- ~Data Bus
+ * I2 -> I/O device
+ *
+ * This instruction occupies two ROM words and requires two
+ * cycles for execution. The first ROM word is received by
+ * the CPU and sets up the I/O enable signal. The second
+ * ROM word is then received by the I/O devices and decoded
+ * for address and command. The contents of the accumulator
+ * inverted are placed on the data lines for acceptance by
+ * the I/O. At the same time, input data received by the I/O
+ * device is transferred to the accumulator inverted.
+ */
+void pps4_device::iIOL()
+{
+ const unsigned a = ~m_A & 15;
+ ARG();
+ LOG(("%s: port:%X <- %02X\n", __FUNCTION__, m_I2, a));
+ m_io->write_byte(m_I2, a);
+ m_A = ~m_io->read_byte(m_I2) & 15;
+ LOG(("%s: port:%X -> %02X\n", __FUNCTION__, m_I2, m_A));
+}
+
+/**
+ * @brief pps4_device::iDIA Discrete input group A
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0010 0111 1 cyc DIA
+ *
+ * Symbolic equation
+ * -----------------------------
+ * A <- DIA
+ *
+ * Data at the inputs to discrete group A is
+ * transferred to the accumulator.
+ */
+void pps4_device::iDIA()
+{
+ m_A = m_io->read_byte(PPS4_PORT_A);
+}
+
+/**
+ * @brief pps4_device::iDIB Discrete input group B
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0010 0011 1 cyc DIB
+ *
+ * Symbolic equation
+ * -----------------------------
+ * A <- DIB
+ *
+ * Data at the inputs to discrete group B is
+ * transferred to the accumulator.
+ */
+void pps4_device::iDIB()
+{
+ m_A = m_io->read_byte(PPS4_PORT_B);
+}
+
+/**
+ * @brief pps4_device::iDIA Discrete input group A
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0010 1101 1 cyc DOA
+ *
+ * Symbolic equation
+ * -----------------------------
+ * DOA <- A
+ *
+ * The contents of the accumulator are transferred
+ * to the discrete output register.
+ */
+void pps4_device::iDOA()
+{
+ m_io->write_byte(PPS4_PORT_A, m_A);
+}
+
+/**
+ * @brief pps4_device::iSAG Special address generation
+ * OPCODE cycles mnemonic
+ * -----------------------------
+ * 0010 1101 1 cyc SAG
+ *
+ * Symbolic equation
+ * -----------------------------
+ * A/B Bus (12:5) <- 0000 0000
+ * A/B Bus (4:1) <- BL(4:1)
+ * Contents of B remains unchanged
+ *
+ * The instruction causes the eight most significant bits
+ * of the RAM address output to be zeroed during the next
+ * cycle only. Note that this instruction does not alter
+ * the contents of the B register.
+ */
+void pps4_device::iSAG()
+{
+ // mask bits 12:5
+ m_SAG = 0xff0;
+}
/***************************************************************************
COMMON EXECUTION
***************************************************************************/
+void pps4_device::execute_one()
+{
+ m_I = ROP();
+ switch (m_I) {
+ case 0x00:
+ iLBL();
+ break;
+ case 0x01:
+ iTML();
+ break;
+ case 0x02:
+ iTML();
+ break;
+ case 0x03:
+ iTML();
+ break;
+ case 0x04:
+ iLBUA();
+ break;
+ case 0x05:
+ iRTN();
+ break;
+ case 0x06:
+ iXS();
+ break;
+ case 0x07:
+ iRTNSK();
+ break;
+ case 0x08:
+ iADCSK();
+ break;
+ case 0x09:
+ iADSK();
+ break;
+ case 0x0a:
+ iADC();
+ break;
+ case 0x0b:
+ iAD();
+ break;
+ case 0x0c:
+ iEOR();
+ break;
+ case 0x0d:
+ iAND();
+ break;
+ case 0x0e:
+ iCOMP();
+ break;
+ case 0x0f:
+ iOR();
+ break;
+
+ case 0x10:
+ iLBMX();
+ break;
+ case 0x11:
+ iLABL();
+ break;
+ case 0x12:
+ iLAX();
+ break;
+ case 0x13:
+ iSAG();
+ break;
+ case 0x14:
+ iSKF2();
+ break;
+ case 0x15:
+ iSKC();
+ break;
+ case 0x16:
+ iSKF1();
+ break;
+ case 0x17:
+ iINCB();
+ break;
+ case 0x18:
+ iXBMX();
+ break;
+ case 0x19:
+ iXABL();
+ break;
+ case 0x1a:
+ iXAX();
+ break;
+ case 0x1b:
+ iLXA();
+ break;
+ case 0x1c:
+ iIOL();
+ break;
+ case 0x1d:
+ iDOA();
+ break;
+ case 0x1e:
+ iSKZ();
+ break;
+ case 0x1f:
+ iDECB();
+ break;
+
+ case 0x20:
+ iSC();
+ break;
+ case 0x21:
+ iSF2();
+ break;
+ case 0x22:
+ iSF1();
+ break;
+ case 0x23:
+ iDIB();
+ break;
+ case 0x24:
+ iRC();
+ break;
+ case 0x25:
+ iRF2();
+ break;
+ case 0x26:
+ iRF1();
+ break;
+ case 0x27:
+ iDIA();
+ break;
+
+ case 0x28: case 0x29: case 0x2a: case 0x2b:
+ case 0x2c: case 0x2d: case 0x2e: case 0x2f:
+ iEXD();
+ break;
+
+ case 0x30: case 0x31: case 0x32: case 0x33:
+ case 0x34: case 0x35: case 0x36: case 0x37:
+ iLD();
+ break;
+
+ case 0x38: case 0x39: case 0x3a: case 0x3b:
+ case 0x3c: case 0x3d: case 0x3e: case 0x3f:
+ iEX();
+ 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:
+ iSKBI();
+ break;
+
+ 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:
+ iTL();
+ break;
+
+ case 0x65:
+ iDC();
+ break;
+
+ case 0x60: case 0x61: case 0x62: case 0x63:
+ case 0x64: case 0x66: case 0x67:
+ case 0x68: case 0x69: case 0x6a: case 0x6b:
+ case 0x6c: case 0x6d: case 0x6e:
+ iADI();
+ break;
+
+ case 0x6f:
+ iCYS();
+ break;
+
+ 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:
+ iLDI();
+ break;
+
+ case 0x80: case 0x81: case 0x82: case 0x83:
+ case 0x84: case 0x85: case 0x86: case 0x87:
+ case 0x88: case 0x89: case 0x8a: case 0x8b:
+ case 0x8c: case 0x8d: case 0x8e: case 0x8f:
+ case 0x90: case 0x91: case 0x92: case 0x93:
+ case 0x94: case 0x95: case 0x96: case 0x97:
+ case 0x98: case 0x99: case 0x9a: case 0x9b:
+ case 0x9c: case 0x9d: case 0x9e: case 0x9f:
+ case 0xa0: case 0xa1: case 0xa2: case 0xa3:
+ case 0xa4: case 0xa5: case 0xa6: case 0xa7:
+ case 0xa8: case 0xa9: case 0xaa: case 0xab:
+ case 0xac: case 0xad: case 0xae: case 0xaf:
+ case 0xb0: case 0xb1: case 0xb2: case 0xb3:
+ case 0xb4: case 0xb5: case 0xb6: case 0xb7:
+ case 0xb8: case 0xb9: case 0xba: case 0xbb:
+ case 0xbc: case 0xbd: case 0xbe: case 0xbf:
+ iT();
+ break;
+
+
+ case 0xc0: case 0xc1: case 0xc2: case 0xc3:
+ case 0xc4: case 0xc5: case 0xc6: case 0xc7:
+ case 0xc8: case 0xc9: case 0xca: case 0xcb:
+ case 0xcc: case 0xcd: case 0xce: case 0xcf:
+ iLB();
+ break;
+
+ default:
+ iTM();
+ }
+}
+
void pps4_device::execute_run()
{
- do
- {
- debugger_instruction_hook(this, m_P.d);
- execute_one(ROP());
+ do
+ {
+ debugger_instruction_hook(this, m_P);
+ execute_one();
- } while (m_icount > 0);
+ } while (m_icount > 0);
}
/***************************************************************************
@@ -333,44 +1482,51 @@ void pps4_device::execute_run()
void pps4_device::device_start()
{
- m_program = &space(AS_PROGRAM);
- m_direct = &m_program->direct();
- m_data = &space(AS_DATA);
- m_io = &space(AS_IO);
-
- save_item(NAME(m_A));
- save_item(NAME(m_X));
- save_item(NAME(m_P));
- save_item(NAME(m_SA));
- save_item(NAME(m_SB));
- save_item(NAME(m_B));
- save_item(NAME(m_C));
- save_item(NAME(m_FF1));
- save_item(NAME(m_FF2));
-
- state_add( PPS4_PC, "PC", m_P.d ).mask(0xfff).formatstr("%03X");
- state_add( PPS4_A, "A", m_A ).formatstr("%02X"); // TODO: size?
- state_add( PPS4_X, "X", m_X ).formatstr("%02X"); // TODO: size?
- state_add( PPS4_SA, "SA", m_SA.d ).formatstr("%04X"); // TODO: size?
- state_add( PPS4_SB, "SB", m_SB.d ).formatstr("%04X"); // TODO: size?
- state_add( PPS4_B, "B", m_B.d ).formatstr("%04X"); // TODO: size?
- state_add( STATE_GENPC, "GENPC", m_P.d ).noshow();
- state_add( STATE_GENFLAGS, "GENFLAGS", m_C ).formatstr("%3s").noshow();
-
- m_icountptr = &m_icount;
+ m_program = &space(AS_PROGRAM);
+ m_direct = &m_program->direct();
+ m_data = &space(AS_DATA);
+ m_io = &space(AS_IO);
+
+ save_item(NAME(m_A));
+ save_item(NAME(m_X));
+ save_item(NAME(m_P));
+ save_item(NAME(m_SA));
+ save_item(NAME(m_SB));
+ save_item(NAME(m_SAG));
+ save_item(NAME(m_B));
+ save_item(NAME(m_C));
+ save_item(NAME(m_FF1));
+ save_item(NAME(m_FF2));
+ save_item(NAME(m_I));
+ save_item(NAME(m_I2));
+ save_item(NAME(m_Ip));
+
+ state_add( PPS4_PC, "PC", m_P ).mask(0xFFF).formatstr("%03X");
+ state_add( PPS4_A, "A", m_A ).formatstr("%01X");
+ state_add( PPS4_X, "X", m_X ).formatstr("%01X");
+ state_add( PPS4_SA, "SA", m_SA ).formatstr("%03X");
+ state_add( PPS4_SB, "SB", m_SB ).formatstr("%03X");
+ state_add( PPS4_B, "B", m_B ).formatstr("%03X");
+ state_add( PPS4_SAG, "SAG", m_SAG ).formatstr("%03X");
+ state_add( PPS4_I2, "I2", m_I2 ).formatstr("%02X").noshow();
+ state_add( PPS4_Ip, "Ip", m_Ip ).formatstr("%02X").noshow();
+ state_add( STATE_GENPC, "GENPC", m_P ).noshow();
+ state_add( STATE_GENFLAGS, "GENFLAGS", m_C).formatstr("%3s").noshow();
+
+ m_icountptr = &m_icount;
}
void pps4_device::state_string_export(const device_state_entry &entry, astring &string)
{
- switch (entry.index())
- {
- case STATE_GENFLAGS:
- string.printf("%c%c%c",
- m_C ? 'C':'.',
- m_FF1 ? '1':'.',
- m_FF2 ? '2':'.');
- break;
- }
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ string.printf("%c%c%c",
+ m_C ? 'C':'.',
+ m_FF1 ? '1':'.',
+ m_FF2 ? '2':'.');
+ break;
+ }
}
/***************************************************************************
@@ -379,11 +1535,17 @@ void pps4_device::state_string_export(const device_state_entry &entry, astring &
void pps4_device::device_reset()
{
- m_A = m_X = 0;
- m_C = m_FF1 = m_FF2 = 0;
-
- m_P.d = 0;
- m_SA.d = 0;
- m_SB.d = 0;
- m_B.d = 0;
+ m_A = 0; // Accumulator A(4:1)
+ m_X = 0; // X register X(4:1)
+ m_P = 0; // program counter P(12:1)
+ m_SA = 0; // Shift register SA(12:1)
+ m_SB = 0; // Shift register SB(12:1)
+ m_SAG = 0; // Special address generation mask
+ m_B = 0; // B address register B(12:1) (BL, BM and BU)
+ m_C = 0; // Carry flip-flop
+ m_FF1 = 0; // Flip-flop 1
+ m_FF2 = 0; // Flip-flop 2
+ m_I = 0; // Most recent instruction I(8:1)
+ m_I2 = 0; // Most recent parameter I2(8:1)
+ m_Ip = 0; // Previous instruction I(8:1)
}