trunk/src/emu/cpu/pps4/pps4.c
| r242165 | r242166 | |
| 1 | 1 | // license:BSD-3-Clause |
| 2 | | // copyright-holders:Miodrag Milanovic |
| 2 | // copyright-holders:Juergen Buchmueller <pullmoll@t-online.de> |
| 3 | |
| 3 | 4 | /***************************************************************************** |
| 4 | 5 | * |
| 5 | 6 | * pps4.c |
| r242165 | r242166 | |
| 31 | 32 | #include "debugger.h" |
| 32 | 33 | #include "pps4.h" |
| 33 | 34 | |
| 34 | | #define VERBOSE 0 |
| 35 | 35 | |
| 36 | | #define LOG(x) do { if (VERBOSE) logerror x; } while (0) |
| 36 | #define VERBOSE 0 //!< set to 1 to log certain instruction conditions |
| 37 | 37 | |
| 38 | #if VERBOSE |
| 39 | #define LOG(x) logerror x |
| 40 | #else |
| 41 | #define LOG(x) |
| 42 | #endif |
| 38 | 43 | |
| 39 | 44 | const device_type PPS4 = &device_creator<pps4_device>; |
| 40 | 45 | |
| 41 | | |
| 42 | 46 | pps4_device::pps4_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 43 | | : cpu_device(mconfig, PPS4, "PPS4", tag, owner, clock, "pps4", __FILE__ ) |
| 44 | | , m_program_config("program", ENDIANNESS_LITTLE, 8, 12) |
| 45 | | , m_data_config("data", ENDIANNESS_LITTLE, 8, 12) // 4bit RAM |
| 46 | | , m_io_config("io", ENDIANNESS_LITTLE, 8, 8) // 4bit IO |
| 47 | : cpu_device(mconfig, PPS4, "PPS4", tag, owner, clock, "pps4", __FILE__ ) |
| 48 | , m_program_config("program", ENDIANNESS_LITTLE, 8, 12) |
| 49 | , m_data_config("data", ENDIANNESS_LITTLE, 8, 12) // 4bit RAM |
| 50 | , m_io_config("io", ENDIANNESS_LITTLE, 8, 8) // 4bit IO |
| 47 | 51 | { |
| 48 | 52 | } |
| 49 | 53 | |
| 54 | /** |
| 55 | * @brief pps4_device::M Return the memory at address B |
| 56 | * @return ROM/RAM(B) |
| 57 | */ |
| 58 | UINT8 pps4_device::M() |
| 59 | { |
| 60 | UINT8 ret = m_data->read_byte(m_B & ~m_SAG); |
| 61 | m_SAG = 0; |
| 62 | return ret; |
| 63 | } |
| 50 | 64 | |
| 65 | |
| 66 | /** |
| 67 | * @brief pps4_device::W Write to the memory address at B |
| 68 | * @return ROM/RAM(B) |
| 69 | */ |
| 70 | void pps4_device::W(UINT8 data) |
| 71 | { |
| 72 | m_data->write_byte(m_B & ~m_SAG, data); |
| 73 | m_SAG = 0; |
| 74 | } |
| 75 | |
| 51 | 76 | offs_t pps4_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) |
| 52 | 77 | { |
| 53 | | extern CPU_DISASSEMBLE( pps4 ); |
| 54 | | return CPU_DISASSEMBLE_NAME(pps4)(this, buffer, pc, oprom, opram, options); |
| 78 | extern CPU_DISASSEMBLE( pps4 ); |
| 79 | return CPU_DISASSEMBLE_NAME(pps4)(this, buffer, pc, oprom, opram, options); |
| 55 | 80 | } |
| 56 | 81 | |
| 57 | | |
| 82 | /** |
| 83 | * @brief pps4_device::ROP Read the next opcode (instruction) |
| 84 | * @return m_I |
| 85 | */ |
| 58 | 86 | inline UINT8 pps4_device::ROP() |
| 59 | 87 | { |
| 60 | | UINT8 retVal = m_direct->read_decrypted_byte(m_P.w.l); |
| 61 | | m_P.w.l = (m_P.w.l + 1) & 0x0fff; |
| 62 | | return retVal; |
| 88 | m_Ip = m_I & 0xf0; // set previous opcode mask |
| 89 | m_I = m_direct->read_decrypted_byte(m_P & 0xFFF); |
| 90 | m_P = (m_P + 1) & 0xFFF; |
| 91 | m_icount -= 1; |
| 92 | return m_I; |
| 63 | 93 | } |
| 64 | 94 | |
| 95 | /** |
| 96 | * @brief pps4_device::ARG Read the next argument (instrunction 2) |
| 97 | * @return m_I2 |
| 98 | */ |
| 65 | 99 | inline UINT8 pps4_device::ARG() |
| 66 | 100 | { |
| 67 | | UINT8 retVal = m_direct->read_raw_byte(m_P.w.l); |
| 68 | | m_P.w.l = (m_P.w.l + 1) & 0x0fff; |
| 69 | | return retVal; |
| 101 | m_I2 = m_direct->read_raw_byte(m_P & 0xFFF); |
| 102 | m_P = (m_P + 1) & 0xFFF; |
| 103 | m_icount -= 1; |
| 104 | return m_I2; |
| 70 | 105 | } |
| 71 | 106 | |
| 72 | | inline void pps4_device::DO_SKIP() |
| 107 | /** |
| 108 | * @brief Note3 |
| 109 | * |
| 110 | * Instructions ADI, LD, EX, EXD, LDI, LB and LBL have a numeric |
| 111 | * value coded as part of the instruction in the immediate field. |
| 112 | * This numeric value must be in complementary form on the bus. |
| 113 | * All of these immediate fields which are inverted are shown |
| 114 | * in brackets. |
| 115 | * For example: ADI 1, as written by the programmer who wishes |
| 116 | * to add one to the value in the accumulator, is converted to |
| 117 | * 0x6E = 01001 [1110]; the bracketed binary value is the value |
| 118 | * as seen on the data bus. |
| 119 | * If the programmer is using the Rockwell Assembler he does not |
| 120 | * have to manually determine the proper inverted value as the |
| 121 | * assembler does this for him. |
| 122 | * |
| 123 | * [And we do in MAME as well :-] |
| 124 | */ |
| 125 | |
| 126 | /** |
| 127 | * @brief pps4_device::iAD Add |
| 128 | * OPCODE cycles mnemonic |
| 129 | * ----------------------------- |
| 130 | * 0000 1011 1 cyc AD |
| 131 | * |
| 132 | * Symbolic equation |
| 133 | * ----------------------------- |
| 134 | * C, A <- A + M |
| 135 | * |
| 136 | * The result of the binary addition of contents of accumulator |
| 137 | * and 4-bit contents of RAM currently addressed by B register, |
| 138 | * replaces the contents of the accumulator. The resulting |
| 139 | * carry-out is loaded into C flip-flop. |
| 140 | */ |
| 141 | void pps4_device::iAD() |
| 73 | 142 | { |
| 74 | | m_P.w.l = (m_P.w.l + 1) & 0x0fff; |
| 143 | m_A = m_A + M(); |
| 144 | m_C = m_A >> 4; |
| 145 | m_A = m_A & 15; |
| 75 | 146 | } |
| 76 | 147 | |
| 77 | | void pps4_device::execute_one(int opcode) |
| 148 | /** |
| 149 | * @brief pps4_device::iADC Add with carry-in |
| 150 | * OPCODE cycles mnemonic |
| 151 | * ----------------------------- |
| 152 | * 0000 1010 1 cyc ADC |
| 153 | * |
| 154 | * Symbolic equation |
| 155 | * ----------------------------- |
| 156 | * C, A <- A + M + C |
| 157 | * |
| 158 | * Same as AD except the C flip-flop serves as a carry-in |
| 159 | * to the adder. |
| 160 | */ |
| 161 | void pps4_device::iADC() |
| 78 | 162 | { |
| 79 | | m_icount -= 1; |
| 80 | | switch (opcode) |
| 81 | | { |
| 82 | | // Arithmetic instructions |
| 83 | | case 0x0b: // AD |
| 84 | | break; |
| 85 | | case 0x0a: // ADC |
| 86 | | break; |
| 87 | | case 0x09: // ADSK |
| 88 | | break; |
| 89 | | case 0x08: // ADCSK |
| 90 | | break; |
| 91 | | case 0x60: case 0x61: case 0x62: case 0x63: |
| 92 | | case 0x64: case 0x66: case 0x67: case 0x68: |
| 93 | | case 0x69: case 0x6a: case 0x6b: case 0x6c: |
| 94 | | case 0x6d: case 0x6e: |
| 95 | | // ADI |
| 96 | | break; |
| 97 | | case 0x65: //DC |
| 98 | | m_A = (m_A + 10) & 0x0f; |
| 99 | | break; |
| 100 | | // Logical instructions |
| 101 | | case 0x0d: // AND |
| 102 | | break; |
| 103 | | case 0x0f: // OR |
| 104 | | break; |
| 105 | | case 0x0c: // EOR |
| 106 | | break; |
| 107 | | case 0x0e: // COMP |
| 108 | | m_A ^= 0x0f; |
| 109 | | break; |
| 110 | | // Data transfer instructions |
| 111 | | case 0x20: // SC |
| 112 | | m_C = 1; |
| 113 | | break; |
| 114 | | case 0x24: //RC |
| 115 | | m_C = 0; |
| 116 | | break; |
| 117 | | case 0x22: // SF1 |
| 118 | | m_FF1 = 1; |
| 119 | | break; |
| 120 | | case 0x26: // RF1 |
| 121 | | m_FF1 = 0; |
| 122 | | break; |
| 123 | | case 0x21: // SF2 |
| 124 | | m_FF2 = 1; |
| 125 | | break; |
| 126 | | case 0x25: // RF2 |
| 127 | | m_FF2 = 0; |
| 128 | | break; |
| 129 | | case 0x30: case 0x31: case 0x32: case 0x33: |
| 130 | | case 0x34: case 0x35: case 0x36: case 0x37: |
| 131 | | // LD |
| 132 | | break; |
| 133 | | case 0x38: case 0x39: case 0x3a: case 0x3b: |
| 134 | | case 0x3c: case 0x3d: case 0x3e: case 0x3f: |
| 135 | | // EX |
| 136 | | break; |
| 137 | | case 0x28: case 0x29: case 0x2a: case 0x2b: |
| 138 | | case 0x2c: case 0x2d: case 0x2e: case 0x2f: |
| 139 | | // EXD |
| 140 | | break; |
| 141 | | case 0x70: case 0x71: case 0x72: case 0x73: |
| 142 | | case 0x74: case 0x75: case 0x76: case 0x77: |
| 143 | | case 0x78: case 0x79: case 0x7a: case 0x7b: |
| 144 | | case 0x7c: case 0x7d: case 0x7e: case 0x7f: |
| 145 | | // LDI |
| 146 | | m_A = opcode & 0x0f; |
| 147 | | break; |
| 148 | | case 0x12: // LAX |
| 149 | | m_A = m_X; |
| 150 | | break; |
| 151 | | case 0x1b: // LXA |
| 152 | | m_X = m_A; |
| 153 | | break; |
| 154 | | case 0x11: // LABL |
| 155 | | m_A = m_B.w.l & 0x00f; |
| 156 | | break; |
| 157 | | case 0x10: // LBMX |
| 158 | | m_B.w.l &= 0xf0f; |
| 159 | | m_B.w.l |= (m_X << 4); |
| 160 | | break; |
| 161 | | case 0x04: // LBUA |
| 162 | | break; |
| 163 | | case 0x19: // XABL |
| 164 | | { |
| 165 | | UINT8 tmp = m_B.w.l & 0x00f; |
| 166 | | m_B.w.l &= 0xff0; |
| 167 | | m_B.w.l |= m_A; |
| 168 | | m_A = tmp; |
| 169 | | } |
| 170 | | break; |
| 171 | | case 0x18: // XBMX |
| 172 | | { |
| 173 | | UINT8 tmp = (m_B.w.l & 0x0f0) >> 4; |
| 174 | | m_B.w.l &= 0xf0f; |
| 175 | | m_B.w.l |= (m_X << 4); |
| 176 | | m_X = tmp; |
| 177 | | } |
| 178 | | break; |
| 179 | | case 0x1a: // XAX |
| 180 | | { |
| 181 | | UINT8 tmp = m_A; |
| 182 | | m_A = m_X; |
| 183 | | m_X = tmp; |
| 184 | | } |
| 185 | | break; |
| 186 | | case 0x06: // XS |
| 187 | | { |
| 188 | | PAIR tmp = m_SA; |
| 189 | | m_SA = m_SB; |
| 190 | | m_SB = tmp; |
| 191 | | } |
| 192 | | break; |
| 193 | | case 0x6f: // CYS |
| 194 | | break; |
| 195 | | case 0xc0: case 0xc1: case 0xc2: case 0xc3: |
| 196 | | case 0xc4: case 0xc5: case 0xc6: case 0xc7: |
| 197 | | case 0xc8: case 0xc9: case 0xca: case 0xcb: |
| 198 | | case 0xcc: case 0xcd: case 0xce: case 0xcf: |
| 199 | | // LB |
| 200 | | { |
| 201 | | //UINT8 tmp = ARG(); |
| 202 | | m_icount -= 1; |
| 203 | | } |
| 204 | | break; |
| 205 | | case 0x00: // LBL |
| 206 | | { |
| 207 | | UINT8 tmp = ARG(); |
| 208 | | m_icount -= 1; |
| 209 | | m_B.w.l = tmp; |
| 210 | | } |
| 211 | | break; |
| 212 | | case 0x17: // INCB |
| 213 | | if ((m_B.w.l & 0x0f) == 0x0f) { |
| 214 | | m_B.w.l &= 0xff0; |
| 215 | | DO_SKIP(); |
| 216 | | } else { |
| 217 | | m_B.w.l += 1; |
| 218 | | } |
| 219 | | break; |
| 220 | | case 0x1f: // DECB |
| 221 | | if ((m_B.w.l & 0x0f) == 0x00) { |
| 222 | | m_B.w.l |= 0x00f; |
| 223 | | DO_SKIP(); |
| 224 | | } else { |
| 225 | | m_B.w.l -= 1; |
| 226 | | } |
| 227 | | break; |
| 228 | | // Control transfer instructions |
| 229 | | case 0x80: case 0x81: case 0x82: case 0x83: |
| 230 | | case 0x84: case 0x85: case 0x86: case 0x87: |
| 231 | | case 0x88: case 0x89: case 0x8a: case 0x8b: |
| 232 | | case 0x8c: case 0x8d: case 0x8e: case 0x8f: |
| 233 | | case 0x90: case 0x91: case 0x92: case 0x93: |
| 234 | | case 0x94: case 0x95: case 0x96: case 0x97: |
| 235 | | case 0x98: case 0x99: case 0x9a: case 0x9b: |
| 236 | | case 0x9c: case 0x9d: case 0x9e: case 0x9f: |
| 237 | | case 0xa0: case 0xa1: case 0xa2: case 0xa3: |
| 238 | | case 0xa4: case 0xa5: case 0xa6: case 0xa7: |
| 239 | | case 0xa8: case 0xa9: case 0xaa: case 0xab: |
| 240 | | case 0xac: case 0xad: case 0xae: case 0xaf: |
| 241 | | case 0xb0: case 0xb1: case 0xb2: case 0xb3: |
| 242 | | case 0xb4: case 0xb5: case 0xb6: case 0xb7: |
| 243 | | case 0xb8: case 0xb9: case 0xba: case 0xbb: |
| 244 | | case 0xbc: case 0xbd: case 0xbe: case 0xbf: |
| 245 | | // T |
| 246 | | m_P.w.l = (m_P.w.l & 0xfc0) | (opcode & 0x3f); |
| 247 | | break; |
| 248 | | case 0xd0: case 0xd1: case 0xd2: case 0xd3: |
| 249 | | case 0xd4: case 0xd5: case 0xd6: case 0xd7: |
| 250 | | case 0xd8: case 0xd9: case 0xda: case 0xdb: |
| 251 | | case 0xdc: case 0xdd: case 0xde: case 0xdf: |
| 252 | | case 0xe0: case 0xe1: case 0xe2: case 0xe3: |
| 253 | | case 0xe4: case 0xe5: case 0xe6: case 0xe7: |
| 254 | | case 0xe8: case 0xe9: case 0xea: case 0xeb: |
| 255 | | case 0xec: case 0xed: case 0xee: case 0xef: |
| 256 | | case 0xf0: case 0xf1: case 0xf2: case 0xf3: |
| 257 | | case 0xf4: case 0xf5: case 0xf6: case 0xf7: |
| 258 | | case 0xf8: case 0xf9: case 0xfa: case 0xfb: |
| 259 | | case 0xfc: case 0xfd: case 0xfe: case 0xff: |
| 260 | | // TM |
| 261 | | break; |
| 262 | | case 0x50: case 0x51: case 0x52: case 0x53: |
| 263 | | case 0x54: case 0x55: case 0x56: case 0x57: |
| 264 | | case 0x58: case 0x59: case 0x5a: case 0x5b: |
| 265 | | case 0x5c: case 0x5d: case 0x5e: case 0x5f: |
| 266 | | // TL |
| 267 | | { |
| 268 | | //UINT8 tmp = ARG(); |
| 269 | | m_icount -= 1; |
| 270 | | } |
| 271 | | break; |
| 272 | | case 0x01: case 0x02: case 0x03: |
| 273 | | // TML |
| 274 | | { |
| 275 | | //UINT8 tmp = ARG(); |
| 276 | | m_icount -= 1; |
| 277 | | } |
| 278 | | break; |
| 279 | | case 0x15: // SKC |
| 280 | | break; |
| 281 | | case 0x1e: // SKZ |
| 282 | | break; |
| 283 | | case 0x40: case 0x41: case 0x42: case 0x43: |
| 284 | | case 0x44: case 0x45: case 0x46: case 0x47: |
| 285 | | case 0x48: case 0x49: case 0x4a: case 0x4b: |
| 286 | | case 0x4c: case 0x4d: case 0x4e: case 0x4f: |
| 287 | | // SKBI |
| 288 | | break; |
| 289 | | case 0x16: // SKF1 |
| 290 | | break; |
| 291 | | case 0x14: // SKF2 |
| 292 | | break; |
| 293 | | case 0x05: // RTN |
| 294 | | break; |
| 295 | | case 0x07: // RTNSK |
| 296 | | break; |
| 297 | | // Input/Output instructions |
| 298 | | case 0x1c: // IOL |
| 299 | | { |
| 300 | | //UINT8 tmp = ARG(); |
| 301 | | m_icount -= 1; |
| 302 | | } |
| 303 | | break; |
| 304 | | case 0x27: // DIA |
| 305 | | break; |
| 306 | | case 0x23: // DIB |
| 307 | | break; |
| 308 | | case 0x1d: // DOA |
| 309 | | break; |
| 310 | | // Special instructions |
| 311 | | case 0x13: // SAG |
| 312 | | break; |
| 313 | | } |
| 163 | m_A = m_A + M() + m_C; |
| 164 | m_C = m_A >> 4; |
| 165 | m_A = m_A & 15; |
| 314 | 166 | } |
| 315 | 167 | |
| 168 | /** |
| 169 | * @brief pps4_device::iADSK Add and skip if carry-out |
| 170 | * OPCODE cycles mnemonic |
| 171 | * ----------------------------- |
| 172 | * 0000 1001 1 cyc ADSK |
| 173 | * |
| 174 | * Symbolic equation |
| 175 | * ----------------------------- |
| 176 | * C, A <- A + M |
| 177 | * Skip if C = 1 |
| 178 | * |
| 179 | * Same as AD except the next ROM word will be |
| 180 | * skipped (ignored) if a carry-out is generated. |
| 181 | */ |
| 182 | void pps4_device::iADSK() |
| 183 | { |
| 184 | m_A = m_A + M(); |
| 185 | m_C = m_A >> 4; |
| 186 | m_A = m_A & 15; |
| 187 | m_P = (m_P + m_C) & 0xFFF; |
| 188 | } |
| 316 | 189 | |
| 190 | /** |
| 191 | * @brief pps4_device::iADCSK Add with carry-in and skip if carry-out |
| 192 | * OPCODE cycles mnemonic |
| 193 | * ----------------------------- |
| 194 | * 0000 1000 1 cyc ADCSK |
| 195 | * |
| 196 | * Symbolic equation |
| 197 | * ----------------------------- |
| 198 | * C, A <- A + M + C |
| 199 | * Skip if C = 1 |
| 200 | * |
| 201 | * Same as ADC except the next ROM word will be |
| 202 | * skipped (ignored) if a carry-out is generated. |
| 203 | */ |
| 204 | void pps4_device::iADCSK() |
| 205 | { |
| 206 | m_A = m_A + M() + m_C; |
| 207 | m_C = m_A >> 4; |
| 208 | m_A = m_A & 15; |
| 209 | m_P = (m_P + m_C) & 0xFFF; |
| 210 | } |
| 211 | |
| 212 | /** |
| 213 | * @brief pps4_device::iAND Logical AND |
| 214 | * OPCODE cycles mnemonic |
| 215 | * ----------------------------- |
| 216 | * 0000 1101 1 cyc AND |
| 217 | * |
| 218 | * Symbolic equation |
| 219 | * ----------------------------- |
| 220 | * A <- A & M |
| 221 | * |
| 222 | * The result of logical AND of accumulator and |
| 223 | * 4-bit contents of RAM currently addressed by |
| 224 | * B register replaces contents of accumulator. |
| 225 | */ |
| 226 | void pps4_device::iAND() |
| 227 | { |
| 228 | m_A = m_A & M(); |
| 229 | } |
| 230 | |
| 231 | /** |
| 232 | * @brief pps4_device::iADI Add immediate |
| 233 | * OPCODE cycles mnemonic |
| 234 | * ----------------------------- |
| 235 | * 0110 xxxx 1 cyc ADI #x |
| 236 | * |
| 237 | * Symbolic equation |
| 238 | * ----------------------------- |
| 239 | * A <- A + [I(4:1)] |
| 240 | * |
| 241 | * The result of the binary addition of contents of |
| 242 | * accumulator and 4-bit immediate field of instruction |
| 243 | * word replaces the contents of accumulator. |
| 244 | * The next ROM word will be skipped (ignored) if a |
| 245 | * carry-out is generated. |
| 246 | * __ The instruction does not use or change the C flip-flop. __ |
| 247 | * The immediate field I(4:1) of this instruction may not |
| 248 | * be equal to binary 0 (CYS) or 0101 (DC) |
| 249 | * |
| 250 | * See %Note3 |
| 251 | */ |
| 252 | void pps4_device::iADI() |
| 253 | { |
| 254 | const UINT8 imm = ~m_I & 15; |
| 255 | m_A = m_A + imm; |
| 256 | m_P = m_P + (m_A > 15) ? 1 : 0; |
| 257 | m_A = m_A & 15; |
| 258 | m_P = m_P & 0xFFF; |
| 259 | } |
| 260 | |
| 261 | /** |
| 262 | * @brief pps4_device::iDC Decimal correction |
| 263 | * OPCODE cycles mnemonic |
| 264 | * ----------------------------- |
| 265 | * 0110 0110 1 cyc DC |
| 266 | * |
| 267 | * Symbolic equation |
| 268 | * ----------------------------- |
| 269 | * A <- A + 1010b |
| 270 | * |
| 271 | * Decimal correction of accumulator. |
| 272 | * Binary 1010 is added to the contents of the accumulator. |
| 273 | * Result is stored in accumulator. Instruction does not |
| 274 | * use or change carry flip-flop or skip. |
| 275 | */ |
| 276 | void pps4_device::iDC() |
| 277 | { |
| 278 | m_A = m_A + 10; |
| 279 | } |
| 280 | |
| 281 | /** |
| 282 | * @brief pps4_device::iOR Logical OR |
| 283 | * OPCODE cycles mnemonic |
| 284 | * ----------------------------- |
| 285 | * 0000 1111 1 cyc OR |
| 286 | * |
| 287 | * Symbolic equation |
| 288 | * ----------------------------- |
| 289 | * A <- A | M |
| 290 | * |
| 291 | * The result of logical OIR of accumulator and |
| 292 | * 4-bit contents of RAM currently addressed by |
| 293 | * B register replaces contents of accumulator. |
| 294 | */ |
| 295 | void pps4_device::iOR() |
| 296 | { |
| 297 | m_A = m_A | M(); |
| 298 | } |
| 299 | |
| 300 | /** |
| 301 | * @brief pps4_device::iEOR Logical exclusive-OR |
| 302 | * OPCODE cycles mnemonic |
| 303 | * ----------------------------- |
| 304 | * 0000 1100 1 cyc EOR |
| 305 | * |
| 306 | * Symbolic equation |
| 307 | * ----------------------------- |
| 308 | * A <- A ^ M |
| 309 | * |
| 310 | * The result of logical exclusive-OR of |
| 311 | * accumulator and 4-bit contents of RAM |
| 312 | * currently addressed by B register |
| 313 | * replaces contents of accumulator. |
| 314 | */ |
| 315 | void pps4_device::iEOR() |
| 316 | { |
| 317 | m_A = m_A ^ M(); |
| 318 | } |
| 319 | |
| 320 | /** |
| 321 | * @brief pps4_device::iCOMP Complement |
| 322 | * OPCODE cycles mnemonic |
| 323 | * ----------------------------- |
| 324 | * 0000 1110 1 cyc COMP |
| 325 | * |
| 326 | * Symbolic equation |
| 327 | * ----------------------------- |
| 328 | * A <- ~A |
| 329 | * |
| 330 | * Each bit of the accumulator is logically |
| 331 | * complemented and placed in accumulator. |
| 332 | */ |
| 333 | void pps4_device::iCOMP() |
| 334 | { |
| 335 | m_A = ~m_A & 15; |
| 336 | } |
| 337 | |
| 338 | /** |
| 339 | * @brief pps4_device::iSC Set carry flip-flop |
| 340 | * OPCODE cycles mnemonic |
| 341 | * ----------------------------- |
| 342 | * 0010 0000 1 cyc SC |
| 343 | * |
| 344 | * Symbolic equation |
| 345 | * ----------------------------- |
| 346 | * C <- 1 |
| 347 | * |
| 348 | * The C flip-flop is set to 1. |
| 349 | */ |
| 350 | void pps4_device::iSC() |
| 351 | { |
| 352 | m_C = 1; |
| 353 | } |
| 354 | |
| 355 | /** |
| 356 | * @brief pps4_device::iRC Reset carry flip-flop |
| 357 | * OPCODE cycles mnemonic |
| 358 | * ----------------------------- |
| 359 | * 0010 0100 1 cyc RC |
| 360 | * |
| 361 | * Symbolic equation |
| 362 | * ----------------------------- |
| 363 | * C <- 0 |
| 364 | * |
| 365 | * The C flip-flop is set to 0. |
| 366 | */ |
| 367 | void pps4_device::iRC() |
| 368 | { |
| 369 | m_C = 0; |
| 370 | } |
| 371 | |
| 372 | /** |
| 373 | * @brief pps4_device::iSF1 Set flip-flop FF1 |
| 374 | * OPCODE cycles mnemonic |
| 375 | * ----------------------------- |
| 376 | * 0010 0010 1 cyc SF1 |
| 377 | * |
| 378 | * Symbolic equation |
| 379 | * ----------------------------- |
| 380 | * FF1 <- 1 |
| 381 | * |
| 382 | * The Flip-flop FF1 is set to 1. |
| 383 | */ |
| 384 | void pps4_device::iSF1() |
| 385 | { |
| 386 | m_FF1 = 1; |
| 387 | } |
| 388 | |
| 389 | /** |
| 390 | * @brief pps4_device::iRF1 Reset flip-flop FF1 |
| 391 | * OPCODE cycles mnemonic |
| 392 | * ----------------------------- |
| 393 | * 0010 0100 1 cyc RF1 |
| 394 | * |
| 395 | * Symbolic equation |
| 396 | * ----------------------------- |
| 397 | * FF1 <- 0 |
| 398 | * |
| 399 | * The Flip-flop FF1 is set to 0. |
| 400 | */ |
| 401 | void pps4_device::iRF1() |
| 402 | { |
| 403 | m_FF1 = 0; |
| 404 | } |
| 405 | |
| 406 | /** |
| 407 | * @brief pps4_device::iSF2 Set flip-flop FF2 |
| 408 | * OPCODE cycles mnemonic |
| 409 | * ----------------------------- |
| 410 | * 0010 0001 1 cyc SF2 |
| 411 | * |
| 412 | * Symbolic equation |
| 413 | * ----------------------------- |
| 414 | * FF2 <- 1 |
| 415 | * |
| 416 | * The Flip-flop FF2 is set to 1. |
| 417 | */ |
| 418 | void pps4_device::iSF2() |
| 419 | { |
| 420 | m_FF2 = 1; |
| 421 | } |
| 422 | |
| 423 | /** |
| 424 | * @brief pps4_device::iRF2 Reset flip-flop FF2 |
| 425 | * OPCODE cycles mnemonic |
| 426 | * ----------------------------- |
| 427 | * 0010 0101 1 cyc RF2 |
| 428 | * |
| 429 | * Symbolic equation |
| 430 | * ----------------------------- |
| 431 | * FF2 <- 0 |
| 432 | * |
| 433 | * The flip-flop FF2 is set to 0. |
| 434 | */ |
| 435 | void pps4_device::iRF2() |
| 436 | { |
| 437 | m_FF2 = 0; |
| 438 | } |
| 439 | |
| 440 | /** |
| 441 | * @brief pps4_device::iLD Load accumulator from memory |
| 442 | * OPCODE cycles mnemonic |
| 443 | * ----------------------------- |
| 444 | * 0011 0xxx 1 cyc LDx |
| 445 | * |
| 446 | * Symbolic equation |
| 447 | * ----------------------------- |
| 448 | * A <- M |
| 449 | * B(7:5) <- B(7:5) ^ [I(3:1)] |
| 450 | * |
| 451 | * The 4-bit contents of RAM currently addressed |
| 452 | * by B register are placed in the accumulator. |
| 453 | * The RAM address in the B register is then |
| 454 | * modified by the result of an exclusive-OR of |
| 455 | * the 3-b it immediate field I(3:1) and B(7:5) |
| 456 | * |
| 457 | * See %Note3 |
| 458 | */ |
| 459 | void pps4_device::iLD() |
| 460 | { |
| 461 | const UINT16 imm = ~m_I & 7; |
| 462 | m_A = M(); |
| 463 | m_B = m_B ^ (imm << 4); |
| 464 | } |
| 465 | |
| 466 | /** |
| 467 | * @brief pps4_device::iEX Exchange accumulator and memory |
| 468 | * OPCODE cycles mnemonic |
| 469 | * ----------------------------- |
| 470 | * 0011 1xxx 1 cyc EXx |
| 471 | * |
| 472 | * Symbolic equation |
| 473 | * ----------------------------- |
| 474 | * A <-> M |
| 475 | * B(7:5) <- B(7:5) ^ [I(3:1)] |
| 476 | * |
| 477 | * The same as LD except the contents of accumulator |
| 478 | * are also placed in currently addressed RAM location. |
| 479 | * |
| 480 | * See %Note3 |
| 481 | */ |
| 482 | void pps4_device::iEX() |
| 483 | { |
| 484 | const UINT16 imm = ~m_I & 7; |
| 485 | const UINT8 mem = M(); |
| 486 | W(m_A); |
| 487 | m_A = mem; |
| 488 | m_B = m_B ^ (imm << 4); |
| 489 | } |
| 490 | |
| 491 | /** |
| 492 | * @brief pps4_device::iEXD Exchange accumulator and memory and decrement BL |
| 493 | * OPCODE cycles mnemonic |
| 494 | * ----------------------------- |
| 495 | * 0010 1xxx 1 cyc EXD x |
| 496 | * |
| 497 | * Symbolic equation |
| 498 | * ----------------------------- |
| 499 | * A <-> M |
| 500 | * B(7:5) <- B(7:5) ^ [I(3:1)] |
| 501 | * BL <- BL - 1 |
| 502 | * Skip on BL = 1111b |
| 503 | * |
| 504 | * The same as EX except RAM address in B register |
| 505 | * is further modified by decrementing BL by 1. |
| 506 | * If the new contents of BL is 1111, the next |
| 507 | * ROM word will be ignored. |
| 508 | * |
| 509 | * See %Note3 |
| 510 | */ |
| 511 | void pps4_device::iEXD() |
| 512 | { |
| 513 | const UINT8 imm = ~m_I & 7; |
| 514 | const UINT8 mem = M(); |
| 515 | UINT8 bl = m_B & 15; |
| 516 | W(m_A); |
| 517 | m_A = mem; |
| 518 | m_B = m_B ^ (imm << 4); |
| 519 | if (0 == bl) { |
| 520 | // decrement BL wraps to 1111b |
| 521 | bl = 15; |
| 522 | m_P = (m_P + 1) & 0xFFF; |
| 523 | } else { |
| 524 | // decrement BL |
| 525 | bl = bl - 1; |
| 526 | } |
| 527 | m_B = (m_B & ~15) | bl; |
| 528 | } |
| 529 | |
| 530 | /** |
| 531 | * @brief pps4_device::iLDI Load accumualtor immediate |
| 532 | * OPCODE cycles mnemonic |
| 533 | * ----------------------------- |
| 534 | * 0111 xxxx 1 cyc LDI x |
| 535 | * |
| 536 | * Symbolic equation |
| 537 | * ----------------------------- |
| 538 | * A <- [I(4:1)] |
| 539 | * |
| 540 | * The 4-bit contents, immediate field I(4:1), |
| 541 | * of the instruction are placed in the accumulator. |
| 542 | * |
| 543 | * Note: Only the first occurence of an LDI in a consecutive |
| 544 | * string of LDIs will be executed. The program will ignore |
| 545 | * remaining LDIs and execute next valid instruction. |
| 546 | * |
| 547 | * See %Note3 |
| 548 | */ |
| 549 | void pps4_device::iLDI() |
| 550 | { |
| 551 | // previous LDI instruction? |
| 552 | if (0x70 == m_Ip) { |
| 553 | LOG(("%s: skip prev:%02x\n", __FUNCTION__, m_Ip)); |
| 554 | return; |
| 555 | } |
| 556 | m_A = ~m_I & 15; |
| 557 | } |
| 558 | |
| 559 | /** |
| 560 | * @brief pps4_device::iLAX |
| 561 | * OPCODE cycles mnemonic |
| 562 | * ----------------------------- |
| 563 | * 0001 0010 1 cyc LAX |
| 564 | * |
| 565 | * Symbolic equation |
| 566 | * ----------------------------- |
| 567 | * A <- X |
| 568 | * |
| 569 | * The 4-bit contents of the X register are |
| 570 | * placed in the accumulator. |
| 571 | */ |
| 572 | void pps4_device::iLAX() |
| 573 | { |
| 574 | m_A = m_X; |
| 575 | } |
| 576 | |
| 577 | /** |
| 578 | * @brief pps4_device::iLXA |
| 579 | * OPCODE cycles mnemonic |
| 580 | * ----------------------------- |
| 581 | * 0001 1011 1 cyc LAX |
| 582 | * |
| 583 | * Symbolic equation |
| 584 | * ----------------------------- |
| 585 | * X <- A |
| 586 | * |
| 587 | * The contents of the accumulator are |
| 588 | * tansferred to the X register. |
| 589 | */ |
| 590 | void pps4_device::iLXA() |
| 591 | { |
| 592 | m_X = m_A; |
| 593 | } |
| 594 | |
| 595 | /** |
| 596 | * @brief pps4_device::iLABL |
| 597 | * OPCODE cycles mnemonic |
| 598 | * ----------------------------- |
| 599 | * 0001 0001 1 cyc LABL |
| 600 | * |
| 601 | * Symbolic equation |
| 602 | * ----------------------------- |
| 603 | * A <- BL |
| 604 | * |
| 605 | * The contents of BL register are |
| 606 | * tansferred to the accumulator. |
| 607 | */ |
| 608 | void pps4_device::iLABL() |
| 609 | { |
| 610 | m_A = m_B & 15; |
| 611 | } |
| 612 | |
| 613 | /** |
| 614 | * @brief pps4_device::iLBMX |
| 615 | * OPCODE cycles mnemonic |
| 616 | * ----------------------------- |
| 617 | * 0001 0000 1 cyc LBMX |
| 618 | * |
| 619 | * Symbolic equation |
| 620 | * ----------------------------- |
| 621 | * BM <- X |
| 622 | * |
| 623 | * The contents of X register are |
| 624 | * tansferred to BM register. |
| 625 | */ |
| 626 | void pps4_device::iLBMX() |
| 627 | { |
| 628 | m_B = (m_B & ~(15 << 4)) | (m_X << 4); |
| 629 | } |
| 630 | |
| 631 | /** |
| 632 | * @brief pps4_device::iLBUA |
| 633 | * OPCODE cycles mnemonic |
| 634 | * ----------------------------- |
| 635 | * 0001 0000 1 cyc LBUA |
| 636 | * |
| 637 | * Symbolic equation |
| 638 | * ----------------------------- |
| 639 | * BU <- A |
| 640 | * A <- M |
| 641 | * |
| 642 | * The contents of accumulator are tansferred to |
| 643 | * BU register. Also, the contents of the currently |
| 644 | * addressed RAM are transferred to accumulator. |
| 645 | */ |
| 646 | void pps4_device::iLBUA() |
| 647 | { |
| 648 | m_B = (m_B & ~(15 << 8)) | (m_A << 8); |
| 649 | m_A = M(); |
| 650 | } |
| 651 | |
| 652 | /** |
| 653 | * @brief pps4_device::iXABL |
| 654 | * OPCODE cycles mnemonic |
| 655 | * ----------------------------- |
| 656 | * 0001 1001 1 cyc XABL |
| 657 | * |
| 658 | * Symbolic equation |
| 659 | * ----------------------------- |
| 660 | * A <-> BL |
| 661 | * |
| 662 | * The contents of accumulator and BL register |
| 663 | * are exchanged. |
| 664 | */ |
| 665 | void pps4_device::iXABL() |
| 666 | { |
| 667 | // swap A and BL |
| 668 | UINT8 bl = m_B & 15; |
| 669 | m_B = (m_B & ~15) | m_A; |
| 670 | m_A = bl; |
| 671 | } |
| 672 | |
| 673 | /** |
| 674 | * @brief pps4_device::iXMBX |
| 675 | * OPCODE cycles mnemonic |
| 676 | * ----------------------------- |
| 677 | * 0001 1000 1 cyc XMBX |
| 678 | * |
| 679 | * Symbolic equation |
| 680 | * ----------------------------- |
| 681 | * X <-> BM |
| 682 | * |
| 683 | * The contents of accumulator and BL register |
| 684 | * are exchanged. |
| 685 | */ |
| 686 | void pps4_device::iXBMX() |
| 687 | { |
| 688 | // swap X and BM |
| 689 | UINT8 bm = (m_B >> 4) & 15; |
| 690 | m_B = (m_B & ~(15 << 4)) | (m_X << 4); |
| 691 | m_X = bm; |
| 692 | } |
| 693 | |
| 694 | /** |
| 695 | * @brief pps4_device::iXAX |
| 696 | * OPCODE cycles mnemonic |
| 697 | * ----------------------------- |
| 698 | * 0001 1010 1 cyc XAX |
| 699 | * |
| 700 | * Symbolic equation |
| 701 | * ----------------------------- |
| 702 | * A <-> X |
| 703 | * |
| 704 | * The contents of accumulator and X register |
| 705 | * are exchanged. |
| 706 | */ |
| 707 | void pps4_device::iXAX() |
| 708 | { |
| 709 | // swap A and X |
| 710 | m_A ^= m_X; |
| 711 | m_X ^= m_A; |
| 712 | m_A ^= m_X; |
| 713 | } |
| 714 | |
| 715 | /** |
| 716 | * @brief pps4_device::iXS |
| 717 | * OPCODE cycles mnemonic |
| 718 | * ----------------------------- |
| 719 | * 0000 0110 1 cyc XS |
| 720 | * |
| 721 | * Symbolic equation |
| 722 | * ----------------------------- |
| 723 | * SA <-> SB |
| 724 | * |
| 725 | * The 12-bit contents of SA and SB register |
| 726 | * are exchanged. |
| 727 | */ |
| 728 | void pps4_device::iXS() |
| 729 | { |
| 730 | // swap SA and SB |
| 731 | m_SA ^= m_SB; |
| 732 | m_SB ^= m_SA; |
| 733 | m_SA ^= m_SB; |
| 734 | } |
| 735 | |
| 736 | /** |
| 737 | * @brief pps4_device::iCYS |
| 738 | * OPCODE cycles mnemonic |
| 739 | * ----------------------------- |
| 740 | * 0110 1111 1 cyc CYS |
| 741 | * |
| 742 | * Symbolic equation |
| 743 | * ----------------------------- |
| 744 | * A <- SA(4:1) |
| 745 | * SA(4:1) <- SA(8:5) |
| 746 | * SA(8:5) <- SA(12:9) |
| 747 | * SA(12:9) <- A |
| 748 | * |
| 749 | * A 4-bit right shift of the SA register takes place |
| 750 | * with the four bits which are shifted off the end |
| 751 | * of SA being transferred into the accumulator. |
| 752 | * The contents of the accumulator are placed in the |
| 753 | * left end of the SA register |
| 754 | * |
| 755 | */ |
| 756 | void pps4_device::iCYS() |
| 757 | { |
| 758 | const UINT16 sa = (m_SA >> 4) | (m_A << 12); |
| 759 | m_A = m_SA & 15; |
| 760 | m_SA = sa; |
| 761 | } |
| 762 | |
| 763 | /** |
| 764 | * @brief pps4_device::iLB |
| 765 | * OPCODE cycles mnemonic |
| 766 | * ----------------------------- |
| 767 | * 1100 0000 2 cyc LB |
| 768 | * |
| 769 | * Symbolic equation |
| 770 | * ----------------------------- |
| 771 | * SB <- SA, SA <- P |
| 772 | * P(12:5) <- 0000 1100 |
| 773 | * P(4:1) <- I(4:1) |
| 774 | * |
| 775 | * BU <- 0000 |
| 776 | * B(8:1) <- [I2(8:1)] |
| 777 | * P <- SA, SA <-> SB |
| 778 | * |
| 779 | * Sixteen consecutive locations on ROM page 3 (I2) contain |
| 780 | * data which can be loaded into the eight least significant |
| 781 | * bits of the B register by use of any LB instruction. |
| 782 | * The four most significant bits of B register will be loaded |
| 783 | * with zeros. The contents of the SB register will be destroyed. |
| 784 | * This instruction takes two cycles to execute but occupies |
| 785 | * only one ROM word. (Automatic return) |
| 786 | * |
| 787 | * Only the first occurence of an LB or LBL instruction in a |
| 788 | * consecutive string of LB or LBL will be executed. The |
| 789 | * program will ignore the remaining LB or LBL and execute |
| 790 | * the next valid instruction. Within subroutines the LB |
| 791 | * instruction must be used with caution because the contents |
| 792 | * of SB have been modified. |
| 793 | * |
| 794 | * See %Note3 and %Note4 |
| 795 | */ |
| 796 | void pps4_device::iLB() |
| 797 | { |
| 798 | // previous LB or LBL instruction? |
| 799 | if (0xc0 == m_Ip|| 0x00 == m_Ip) { |
| 800 | LOG(("%s: skip prev:%02X\n", __FUNCTION__, m_Ip)); |
| 801 | return; |
| 802 | } |
| 803 | m_SB = m_SA; |
| 804 | m_SA = (m_P + 1) & 0xFFF; |
| 805 | m_P = (3 << 8) | (m_I & 15); |
| 806 | m_B = ~ARG() & 255; |
| 807 | m_P = m_SA; |
| 808 | // swap SA and SB |
| 809 | m_SA ^= m_SB; |
| 810 | m_SB ^= m_SA; |
| 811 | m_SA ^= m_SB; |
| 812 | } |
| 813 | |
| 814 | /** |
| 815 | * @brief pps4_device::iLBL |
| 816 | * OPCODE cycles mnemonic |
| 817 | * ----------------------------- |
| 818 | * 0000 0000 2 cyc LBL |
| 819 | * |
| 820 | * Symbolic equation |
| 821 | * ----------------------------- |
| 822 | * BU <- 0000 |
| 823 | * B(8:1) <- [I2(8:1)] |
| 824 | * |
| 825 | * This instruction occupies two ROM words, the second of |
| 826 | * which will be loaded into the eight least significant |
| 827 | * bits of the B register. The four most significant bits |
| 828 | * of B (BU) will be loaded with zeroes. |
| 829 | * |
| 830 | * Only the first occurence of an LB or LBL instruction in a |
| 831 | * consecutive string of LB or LBL will be executed. The |
| 832 | * program will ignore the remaining LB or LBL and execute |
| 833 | * the next valid instruction. |
| 834 | * |
| 835 | * See %Note3 |
| 836 | */ |
| 837 | void pps4_device::iLBL() |
| 838 | { |
| 839 | // previous LB or LBL instruction? |
| 840 | if (0xc0 == m_Ip || 0x00 == m_Ip) { |
| 841 | LOG(("%s: skip prev:%02X\n", __FUNCTION__, m_Ip)); |
| 842 | return; |
| 843 | } |
| 844 | m_B = ~ARG() & 255; |
| 845 | } |
| 846 | |
| 847 | /** |
| 848 | * @brief pps4_device::INCB |
| 849 | * OPCODE cycles mnemonic |
| 850 | * ----------------------------- |
| 851 | * 0001 0111 1 cyc INCB |
| 852 | * |
| 853 | * Symbolic equation |
| 854 | * ----------------------------- |
| 855 | * BL <- BL + 1 |
| 856 | * Skip on BL = 0000 |
| 857 | * |
| 858 | * BL register (least significant four bits of B register) |
| 859 | * is incremented by 1. If the new contents of BL is 0000b, |
| 860 | * then the next ROM word will be ignored. |
| 861 | */ |
| 862 | void pps4_device::iINCB() |
| 863 | { |
| 864 | UINT8 bl = m_B & 15; |
| 865 | bl = (bl + 1) & 15; |
| 866 | if (0 == bl) { |
| 867 | LOG(("%s: skip BL=%x\n", __FUNCTION__, bl)); |
| 868 | m_P = (m_P + 1) & 0xFFF; |
| 869 | } |
| 870 | m_B = (m_B & ~15) | bl; |
| 871 | } |
| 872 | |
| 873 | /** |
| 874 | * @brief pps4_device::iDECB |
| 875 | * OPCODE cycles mnemonic |
| 876 | * ----------------------------- |
| 877 | * 0001 1111 1 cyc DECB |
| 878 | * |
| 879 | * Symbolic equation |
| 880 | * ----------------------------- |
| 881 | * BL <- BL - 1 |
| 882 | * Skip on BL = 1111 |
| 883 | * |
| 884 | * BL register is decremented by 1. If the new |
| 885 | * contents of BL is 1111b, then the next ROM |
| 886 | * word will be ignored. |
| 887 | */ |
| 888 | void pps4_device::iDECB() |
| 889 | { |
| 890 | UINT8 bl = m_B & 15; |
| 891 | bl = (bl - 1) & 15; |
| 892 | if (15 == bl) { |
| 893 | LOG(("%s: skip BL=%x\n", __FUNCTION__, bl)); |
| 894 | m_P = (m_P + 1) & 0xFFF; |
| 895 | } |
| 896 | m_B = (m_B & ~15) | bl; |
| 897 | } |
| 898 | |
| 899 | /** |
| 900 | * @brief pps4_device::iT Transfer |
| 901 | * OPCODE cycles mnemonic |
| 902 | * ----------------------------- |
| 903 | * 10xx xxxx 1 cyc T * |
| 904 | * |
| 905 | * Symbolic equation |
| 906 | * ----------------------------- |
| 907 | * P(6:1) <- I(6:1) |
| 908 | * |
| 909 | * An unconditional transfer to a ROM word on the current |
| 910 | * page takes place. The least significant 6-bits of P |
| 911 | * register P(6:1) are replaced by six bit immediate |
| 912 | * field I(6:1) |
| 913 | */ |
| 914 | void pps4_device::iT() |
| 915 | { |
| 916 | const UINT16 p = (m_P & ~63) | (m_I & 63); |
| 917 | LOG(("%s: P=%03x I=%02x -> P=%03x\n", __FUNCTION__, m_P, m_I, p)); |
| 918 | m_P = p; |
| 919 | } |
| 920 | |
| 921 | /** |
| 922 | * @brief pps4_device::iTM Transfer and mark indirect |
| 923 | * OPCODE cycles mnemonic |
| 924 | * ----------------------------- |
| 925 | * 11xx xxxx 2 cyc TM * |
| 926 | * yyyy yyyy from page 3 |
| 927 | * |
| 928 | * Symbolic equation |
| 929 | * ----------------------------- |
| 930 | * SB <- SA, SA <- P |
| 931 | * P(12:7) <- 000011 |
| 932 | * P(6:1) <- I1(6:1) |
| 933 | * |
| 934 | * P(12:9) <- 0001 |
| 935 | * P(8:1) <- I2(8:1) |
| 936 | * |
| 937 | * 48 consecutive locations on ROM page 3 contains pointer data |
| 938 | * which indentify subroutine entry addresses. These subroutine |
| 939 | * entry addresses are limited to pages 4 through 7. This TM |
| 940 | * instruction will save the address of the next ROM word in |
| 941 | * the SA register after loading the original contents of SA |
| 942 | * into SB. A transfer then occurs to one of the subroutine |
| 943 | * entry addresses. This instruction occupies one ROM word |
| 944 | * but takes two cycles for execution. |
| 945 | */ |
| 946 | void pps4_device::iTM() |
| 947 | { |
| 948 | m_SB = m_SA; |
| 949 | m_SA = m_P; |
| 950 | m_P = 3 << 6; |
| 951 | m_P = m_P | (m_I & 63); |
| 952 | ARG(); |
| 953 | m_P = 1 << 8; |
| 954 | m_P |= m_I2; |
| 955 | } |
| 956 | |
| 957 | /** |
| 958 | * @brief pps4_device::iTL Transfer long |
| 959 | * OPCODE cycles mnemonic |
| 960 | * ----------------------------- |
| 961 | * 0101 xxxx 2 cyc TL * |
| 962 | * yyyy yyyy |
| 963 | * |
| 964 | * Symbolic equation |
| 965 | * ----------------------------- |
| 966 | * P(12:9) <- I1(4:1) |
| 967 | * P(8:1) <- I2(8:1) |
| 968 | * |
| 969 | * The instruction executes a transfer to any ROM word on any |
| 970 | * page. It occupies two ROM words an requires two cycles for |
| 971 | * execution. The first byte loads P(12:9) with field I1(4:1) |
| 972 | * and then the second byte I2(8:1) is placed in P(8:1). |
| 973 | */ |
| 974 | void pps4_device::iTL() |
| 975 | { |
| 976 | ARG(); |
| 977 | m_P = (m_I & 15) << 8; |
| 978 | m_P = m_P | m_I2; |
| 979 | } |
| 980 | |
| 981 | /** |
| 982 | * @brief pps4_device::iTML Transfer and mark long |
| 983 | * OPCODE cycles mnemonic |
| 984 | * ----------------------------- |
| 985 | * 0101 xxxx 2 cyc TML * |
| 986 | * yyyy yyyy |
| 987 | * |
| 988 | * Symbolic equation |
| 989 | * ----------------------------- |
| 990 | * SB <- SA, SA <- P |
| 991 | * P(12:9) <- I1(4:1) |
| 992 | * P(8:1) <- I2(8:1) |
| 993 | * |
| 994 | * Note I1(2:1) != 00 |
| 995 | * |
| 996 | * This instruction executes a transfer and mark to any |
| 997 | * location on ROM pages 4 through 15. It occupies two |
| 998 | * ROM words and requires two cycle times for execution. |
| 999 | */ |
| 1000 | void pps4_device::iTML() |
| 1001 | { |
| 1002 | ARG(); |
| 1003 | m_SB = m_SA; |
| 1004 | m_SA = m_P; |
| 1005 | m_P = (m_I & 15) << 8; |
| 1006 | m_P = m_P | m_I2; |
| 1007 | } |
| 1008 | |
| 1009 | /** |
| 1010 | * @brief pps4_device::iSKC Skip on carry flip-flop |
| 1011 | * OPCODE cycles mnemonic |
| 1012 | * ----------------------------- |
| 1013 | * 0001 0101 1 cyc SKC |
| 1014 | * |
| 1015 | * Symbolic equation |
| 1016 | * ----------------------------- |
| 1017 | * Skip if C = 1 |
| 1018 | * |
| 1019 | * The next ROM word will be ignored if C flip-flop is 1. |
| 1020 | */ |
| 1021 | void pps4_device::iSKC() |
| 1022 | { |
| 1023 | m_P = m_P + m_C; |
| 1024 | m_P = m_P & 0xFFF; |
| 1025 | } |
| 1026 | |
| 1027 | /** |
| 1028 | * @brief pps4_device::iSKC Skip on carry flip-flop |
| 1029 | * OPCODE cycles mnemonic |
| 1030 | * ----------------------------- |
| 1031 | * 0001 1110 1 cyc SKZ |
| 1032 | * |
| 1033 | * Symbolic equation |
| 1034 | * ----------------------------- |
| 1035 | * Skip if A = 0 |
| 1036 | * |
| 1037 | * The next ROM word will be ignored if C flip-flop is 1. |
| 1038 | */ |
| 1039 | void pps4_device::iSKZ() |
| 1040 | { |
| 1041 | m_P = m_P + (0 == m_A) ? 1 : 0; |
| 1042 | m_P = m_P & 0xFFF; |
| 1043 | } |
| 1044 | |
| 1045 | /** |
| 1046 | * @brief pps4_device::iSKBI Skip if BL equal to immediate |
| 1047 | * OPCODE cycles mnemonic |
| 1048 | * ----------------------------- |
| 1049 | * 0100 xxxx 1 cyc SKBI x |
| 1050 | * |
| 1051 | * Symbolic equation |
| 1052 | * ----------------------------- |
| 1053 | * Skip if BL = I(4:1) |
| 1054 | * |
| 1055 | * The next ROM word will be ignored if the least significant |
| 1056 | * four bits of B register (BL) is equal to the 4-bit immediate |
| 1057 | * field I(4:1) of instruction. |
| 1058 | */ |
| 1059 | void pps4_device::iSKBI() |
| 1060 | { |
| 1061 | const unsigned imm = m_I & 15; |
| 1062 | m_P = m_P + (imm == (m_B & 15)) ? 1 : 0; |
| 1063 | m_P = m_P & 0xFFF; |
| 1064 | } |
| 1065 | |
| 1066 | /** |
| 1067 | * @brief pps4_device::iSKF1 Skip if FF1 equals 1 |
| 1068 | * OPCODE cycles mnemonic |
| 1069 | * ----------------------------- |
| 1070 | * 0001 0110 1 cyc SKF1 |
| 1071 | * |
| 1072 | * Symbolic equation |
| 1073 | * ----------------------------- |
| 1074 | * Skip if FF1 = 1 |
| 1075 | */ |
| 1076 | void pps4_device::iSKF1() |
| 1077 | { |
| 1078 | m_P = m_P + m_FF1; |
| 1079 | m_P = m_P & 0xFFF; |
| 1080 | } |
| 1081 | |
| 1082 | /** |
| 1083 | * @brief pps4_device::iSKF2 Skip if FF2 equals 1 |
| 1084 | * OPCODE cycles mnemonic |
| 1085 | * ----------------------------- |
| 1086 | * 0001 0100 1 cyc SKF2 |
| 1087 | * |
| 1088 | * Symbolic equation |
| 1089 | * ----------------------------- |
| 1090 | * Skip if FF2 = 1 |
| 1091 | */ |
| 1092 | void pps4_device::iSKF2() |
| 1093 | { |
| 1094 | m_P = m_P + m_FF2; |
| 1095 | m_P = m_P & 0xFFF; |
| 1096 | } |
| 1097 | |
| 1098 | /** |
| 1099 | * @brief pps4_device::iRTN Return |
| 1100 | * OPCODE cycles mnemonic |
| 1101 | * ----------------------------- |
| 1102 | * 0000 0101 1 cyc RET |
| 1103 | * |
| 1104 | * Symbolic equation |
| 1105 | * ----------------------------- |
| 1106 | * P <- SA, SA <-> SB |
| 1107 | * |
| 1108 | * This instruction executes a return from subroutine |
| 1109 | * by loading contents of SA register into P register |
| 1110 | * and interchanges the SB and SA registers. |
| 1111 | */ |
| 1112 | void pps4_device::iRTN() |
| 1113 | { |
| 1114 | m_P = m_SA; |
| 1115 | // swap SA and SB |
| 1116 | m_SA ^= m_SB; |
| 1117 | m_SB ^= m_SA; |
| 1118 | m_SA ^= m_SB; |
| 1119 | } |
| 1120 | |
| 1121 | /** |
| 1122 | * @brief pps4_device::iRTN Return |
| 1123 | * OPCODE cycles mnemonic |
| 1124 | * ----------------------------- |
| 1125 | * 0000 0111 1 cyc RETSK |
| 1126 | * |
| 1127 | * Symbolic equation |
| 1128 | * ----------------------------- |
| 1129 | * P <- SA, SA <-> SB |
| 1130 | * P <- P + 1 |
| 1131 | * |
| 1132 | * Same as RTN expect the first ROM word encountered |
| 1133 | * after the return from subroutine is skipped. |
| 1134 | */ |
| 1135 | void pps4_device::iRTNSK() |
| 1136 | { |
| 1137 | m_P = m_SA; |
| 1138 | ROP(); // ignored |
| 1139 | m_I = 0; // avoid LB/LBL or LDI skipping |
| 1140 | // swap SA and SB |
| 1141 | m_SA ^= m_SB; |
| 1142 | m_SB ^= m_SA; |
| 1143 | m_SA ^= m_SB; |
| 1144 | m_P = m_P & 0xFFF; |
| 1145 | } |
| 1146 | |
| 1147 | /** |
| 1148 | * @brief pps4_device::IOL |
| 1149 | * OPCODE cycles mnemonic |
| 1150 | * ----------------------------- |
| 1151 | * 0001 1100 2 cyc IOL |
| 1152 | * yyyy yyyy |
| 1153 | * |
| 1154 | * Symbolic equation |
| 1155 | * ----------------------------- |
| 1156 | * ~A -> Data Bus |
| 1157 | * A <- ~Data Bus |
| 1158 | * I2 -> I/O device |
| 1159 | * |
| 1160 | * This instruction occupies two ROM words and requires two |
| 1161 | * cycles for execution. The first ROM word is received by |
| 1162 | * the CPU and sets up the I/O enable signal. The second |
| 1163 | * ROM word is then received by the I/O devices and decoded |
| 1164 | * for address and command. The contents of the accumulator |
| 1165 | * inverted are placed on the data lines for acceptance by |
| 1166 | * the I/O. At the same time, input data received by the I/O |
| 1167 | * device is transferred to the accumulator inverted. |
| 1168 | */ |
| 1169 | void pps4_device::iIOL() |
| 1170 | { |
| 1171 | const unsigned a = ~m_A & 15; |
| 1172 | ARG(); |
| 1173 | LOG(("%s: port:%X <- %02X\n", __FUNCTION__, m_I2, a)); |
| 1174 | m_io->write_byte(m_I2, a); |
| 1175 | m_A = ~m_io->read_byte(m_I2) & 15; |
| 1176 | LOG(("%s: port:%X -> %02X\n", __FUNCTION__, m_I2, m_A)); |
| 1177 | } |
| 1178 | |
| 1179 | /** |
| 1180 | * @brief pps4_device::iDIA Discrete input group A |
| 1181 | * OPCODE cycles mnemonic |
| 1182 | * ----------------------------- |
| 1183 | * 0010 0111 1 cyc DIA |
| 1184 | * |
| 1185 | * Symbolic equation |
| 1186 | * ----------------------------- |
| 1187 | * A <- DIA |
| 1188 | * |
| 1189 | * Data at the inputs to discrete group A is |
| 1190 | * transferred to the accumulator. |
| 1191 | */ |
| 1192 | void pps4_device::iDIA() |
| 1193 | { |
| 1194 | m_A = m_io->read_byte(PPS4_PORT_A); |
| 1195 | } |
| 1196 | |
| 1197 | /** |
| 1198 | * @brief pps4_device::iDIB Discrete input group B |
| 1199 | * OPCODE cycles mnemonic |
| 1200 | * ----------------------------- |
| 1201 | * 0010 0011 1 cyc DIB |
| 1202 | * |
| 1203 | * Symbolic equation |
| 1204 | * ----------------------------- |
| 1205 | * A <- DIB |
| 1206 | * |
| 1207 | * Data at the inputs to discrete group B is |
| 1208 | * transferred to the accumulator. |
| 1209 | */ |
| 1210 | void pps4_device::iDIB() |
| 1211 | { |
| 1212 | m_A = m_io->read_byte(PPS4_PORT_B); |
| 1213 | } |
| 1214 | |
| 1215 | /** |
| 1216 | * @brief pps4_device::iDIA Discrete input group A |
| 1217 | * OPCODE cycles mnemonic |
| 1218 | * ----------------------------- |
| 1219 | * 0010 1101 1 cyc DOA |
| 1220 | * |
| 1221 | * Symbolic equation |
| 1222 | * ----------------------------- |
| 1223 | * DOA <- A |
| 1224 | * |
| 1225 | * The contents of the accumulator are transferred |
| 1226 | * to the discrete output register. |
| 1227 | */ |
| 1228 | void pps4_device::iDOA() |
| 1229 | { |
| 1230 | m_io->write_byte(PPS4_PORT_A, m_A); |
| 1231 | } |
| 1232 | |
| 1233 | /** |
| 1234 | * @brief pps4_device::iSAG Special address generation |
| 1235 | * OPCODE cycles mnemonic |
| 1236 | * ----------------------------- |
| 1237 | * 0010 1101 1 cyc SAG |
| 1238 | * |
| 1239 | * Symbolic equation |
| 1240 | * ----------------------------- |
| 1241 | * A/B Bus (12:5) <- 0000 0000 |
| 1242 | * A/B Bus (4:1) <- BL(4:1) |
| 1243 | * Contents of B remains unchanged |
| 1244 | * |
| 1245 | * The instruction causes the eight most significant bits |
| 1246 | * of the RAM address output to be zeroed during the next |
| 1247 | * cycle only. Note that this instruction does not alter |
| 1248 | * the contents of the B register. |
| 1249 | */ |
| 1250 | void pps4_device::iSAG() |
| 1251 | { |
| 1252 | // mask bits 12:5 |
| 1253 | m_SAG = 0xff0; |
| 1254 | } |
| 1255 | |
| 317 | 1256 | /*************************************************************************** |
| 318 | 1257 | COMMON EXECUTION |
| 319 | 1258 | ***************************************************************************/ |
| 1259 | void pps4_device::execute_one() |
| 1260 | { |
| 1261 | m_I = ROP(); |
| 1262 | switch (m_I) { |
| 1263 | case 0x00: |
| 1264 | iLBL(); |
| 1265 | break; |
| 1266 | case 0x01: |
| 1267 | iTML(); |
| 1268 | break; |
| 1269 | case 0x02: |
| 1270 | iTML(); |
| 1271 | break; |
| 1272 | case 0x03: |
| 1273 | iTML(); |
| 1274 | break; |
| 1275 | case 0x04: |
| 1276 | iLBUA(); |
| 1277 | break; |
| 1278 | case 0x05: |
| 1279 | iRTN(); |
| 1280 | break; |
| 1281 | case 0x06: |
| 1282 | iXS(); |
| 1283 | break; |
| 1284 | case 0x07: |
| 1285 | iRTNSK(); |
| 1286 | break; |
| 1287 | case 0x08: |
| 1288 | iADCSK(); |
| 1289 | break; |
| 1290 | case 0x09: |
| 1291 | iADSK(); |
| 1292 | break; |
| 1293 | case 0x0a: |
| 1294 | iADC(); |
| 1295 | break; |
| 1296 | case 0x0b: |
| 1297 | iAD(); |
| 1298 | break; |
| 1299 | case 0x0c: |
| 1300 | iEOR(); |
| 1301 | break; |
| 1302 | case 0x0d: |
| 1303 | iAND(); |
| 1304 | break; |
| 1305 | case 0x0e: |
| 1306 | iCOMP(); |
| 1307 | break; |
| 1308 | case 0x0f: |
| 1309 | iOR(); |
| 1310 | break; |
| 1311 | |
| 1312 | case 0x10: |
| 1313 | iLBMX(); |
| 1314 | break; |
| 1315 | case 0x11: |
| 1316 | iLABL(); |
| 1317 | break; |
| 1318 | case 0x12: |
| 1319 | iLAX(); |
| 1320 | break; |
| 1321 | case 0x13: |
| 1322 | iSAG(); |
| 1323 | break; |
| 1324 | case 0x14: |
| 1325 | iSKF2(); |
| 1326 | break; |
| 1327 | case 0x15: |
| 1328 | iSKC(); |
| 1329 | break; |
| 1330 | case 0x16: |
| 1331 | iSKF1(); |
| 1332 | break; |
| 1333 | case 0x17: |
| 1334 | iINCB(); |
| 1335 | break; |
| 1336 | case 0x18: |
| 1337 | iXBMX(); |
| 1338 | break; |
| 1339 | case 0x19: |
| 1340 | iXABL(); |
| 1341 | break; |
| 1342 | case 0x1a: |
| 1343 | iXAX(); |
| 1344 | break; |
| 1345 | case 0x1b: |
| 1346 | iLXA(); |
| 1347 | break; |
| 1348 | case 0x1c: |
| 1349 | iIOL(); |
| 1350 | break; |
| 1351 | case 0x1d: |
| 1352 | iDOA(); |
| 1353 | break; |
| 1354 | case 0x1e: |
| 1355 | iSKZ(); |
| 1356 | break; |
| 1357 | case 0x1f: |
| 1358 | iDECB(); |
| 1359 | break; |
| 1360 | |
| 1361 | case 0x20: |
| 1362 | iSC(); |
| 1363 | break; |
| 1364 | case 0x21: |
| 1365 | iSF2(); |
| 1366 | break; |
| 1367 | case 0x22: |
| 1368 | iSF1(); |
| 1369 | break; |
| 1370 | case 0x23: |
| 1371 | iDIB(); |
| 1372 | break; |
| 1373 | case 0x24: |
| 1374 | iRC(); |
| 1375 | break; |
| 1376 | case 0x25: |
| 1377 | iRF2(); |
| 1378 | break; |
| 1379 | case 0x26: |
| 1380 | iRF1(); |
| 1381 | break; |
| 1382 | case 0x27: |
| 1383 | iDIA(); |
| 1384 | break; |
| 1385 | |
| 1386 | case 0x28: case 0x29: case 0x2a: case 0x2b: |
| 1387 | case 0x2c: case 0x2d: case 0x2e: case 0x2f: |
| 1388 | iEXD(); |
| 1389 | break; |
| 1390 | |
| 1391 | case 0x30: case 0x31: case 0x32: case 0x33: |
| 1392 | case 0x34: case 0x35: case 0x36: case 0x37: |
| 1393 | iLD(); |
| 1394 | break; |
| 1395 | |
| 1396 | case 0x38: case 0x39: case 0x3a: case 0x3b: |
| 1397 | case 0x3c: case 0x3d: case 0x3e: case 0x3f: |
| 1398 | iEX(); |
| 1399 | break; |
| 1400 | |
| 1401 | case 0x40: case 0x41: case 0x42: case 0x43: |
| 1402 | case 0x44: case 0x45: case 0x46: case 0x47: |
| 1403 | case 0x48: case 0x49: case 0x4a: case 0x4b: |
| 1404 | case 0x4c: case 0x4d: case 0x4e: case 0x4f: |
| 1405 | iSKBI(); |
| 1406 | break; |
| 1407 | |
| 1408 | case 0x50: case 0x51: case 0x52: case 0x53: |
| 1409 | case 0x54: case 0x55: case 0x56: case 0x57: |
| 1410 | case 0x58: case 0x59: case 0x5a: case 0x5b: |
| 1411 | case 0x5c: case 0x5d: case 0x5e: case 0x5f: |
| 1412 | iTL(); |
| 1413 | break; |
| 1414 | |
| 1415 | case 0x65: |
| 1416 | iDC(); |
| 1417 | break; |
| 1418 | |
| 1419 | case 0x60: case 0x61: case 0x62: case 0x63: |
| 1420 | case 0x64: case 0x66: case 0x67: |
| 1421 | case 0x68: case 0x69: case 0x6a: case 0x6b: |
| 1422 | case 0x6c: case 0x6d: case 0x6e: |
| 1423 | iADI(); |
| 1424 | break; |
| 1425 | |
| 1426 | case 0x6f: |
| 1427 | iCYS(); |
| 1428 | break; |
| 1429 | |
| 1430 | case 0x70: case 0x71: case 0x72: case 0x73: |
| 1431 | case 0x74: case 0x75: case 0x76: case 0x77: |
| 1432 | case 0x78: case 0x79: case 0x7a: case 0x7b: |
| 1433 | case 0x7c: case 0x7d: case 0x7e: case 0x7f: |
| 1434 | iLDI(); |
| 1435 | break; |
| 1436 | |
| 1437 | case 0x80: case 0x81: case 0x82: case 0x83: |
| 1438 | case 0x84: case 0x85: case 0x86: case 0x87: |
| 1439 | case 0x88: case 0x89: case 0x8a: case 0x8b: |
| 1440 | case 0x8c: case 0x8d: case 0x8e: case 0x8f: |
| 1441 | case 0x90: case 0x91: case 0x92: case 0x93: |
| 1442 | case 0x94: case 0x95: case 0x96: case 0x97: |
| 1443 | case 0x98: case 0x99: case 0x9a: case 0x9b: |
| 1444 | case 0x9c: case 0x9d: case 0x9e: case 0x9f: |
| 1445 | case 0xa0: case 0xa1: case 0xa2: case 0xa3: |
| 1446 | case 0xa4: case 0xa5: case 0xa6: case 0xa7: |
| 1447 | case 0xa8: case 0xa9: case 0xaa: case 0xab: |
| 1448 | case 0xac: case 0xad: case 0xae: case 0xaf: |
| 1449 | case 0xb0: case 0xb1: case 0xb2: case 0xb3: |
| 1450 | case 0xb4: case 0xb5: case 0xb6: case 0xb7: |
| 1451 | case 0xb8: case 0xb9: case 0xba: case 0xbb: |
| 1452 | case 0xbc: case 0xbd: case 0xbe: case 0xbf: |
| 1453 | iT(); |
| 1454 | break; |
| 1455 | |
| 1456 | |
| 1457 | case 0xc0: case 0xc1: case 0xc2: case 0xc3: |
| 1458 | case 0xc4: case 0xc5: case 0xc6: case 0xc7: |
| 1459 | case 0xc8: case 0xc9: case 0xca: case 0xcb: |
| 1460 | case 0xcc: case 0xcd: case 0xce: case 0xcf: |
| 1461 | iLB(); |
| 1462 | break; |
| 1463 | |
| 1464 | default: |
| 1465 | iTM(); |
| 1466 | } |
| 1467 | } |
| 1468 | |
| 320 | 1469 | void pps4_device::execute_run() |
| 321 | 1470 | { |
| 322 | | do |
| 323 | | { |
| 324 | | debugger_instruction_hook(this, m_P.d); |
| 325 | | execute_one(ROP()); |
| 1471 | do |
| 1472 | { |
| 1473 | debugger_instruction_hook(this, m_P); |
| 1474 | execute_one(); |
| 326 | 1475 | |
| 327 | | } while (m_icount > 0); |
| 1476 | } while (m_icount > 0); |
| 328 | 1477 | } |
| 329 | 1478 | |
| 330 | 1479 | /*************************************************************************** |
| r242165 | r242166 | |
| 333 | 1482 | |
| 334 | 1483 | void pps4_device::device_start() |
| 335 | 1484 | { |
| 336 | | m_program = &space(AS_PROGRAM); |
| 337 | | m_direct = &m_program->direct(); |
| 338 | | m_data = &space(AS_DATA); |
| 339 | | m_io = &space(AS_IO); |
| 1485 | m_program = &space(AS_PROGRAM); |
| 1486 | m_direct = &m_program->direct(); |
| 1487 | m_data = &space(AS_DATA); |
| 1488 | m_io = &space(AS_IO); |
| 340 | 1489 | |
| 341 | | save_item(NAME(m_A)); |
| 342 | | save_item(NAME(m_X)); |
| 343 | | save_item(NAME(m_P)); |
| 344 | | save_item(NAME(m_SA)); |
| 345 | | save_item(NAME(m_SB)); |
| 346 | | save_item(NAME(m_B)); |
| 347 | | save_item(NAME(m_C)); |
| 348 | | save_item(NAME(m_FF1)); |
| 349 | | save_item(NAME(m_FF2)); |
| 1490 | save_item(NAME(m_A)); |
| 1491 | save_item(NAME(m_X)); |
| 1492 | save_item(NAME(m_P)); |
| 1493 | save_item(NAME(m_SA)); |
| 1494 | save_item(NAME(m_SB)); |
| 1495 | save_item(NAME(m_SAG)); |
| 1496 | save_item(NAME(m_B)); |
| 1497 | save_item(NAME(m_C)); |
| 1498 | save_item(NAME(m_FF1)); |
| 1499 | save_item(NAME(m_FF2)); |
| 1500 | save_item(NAME(m_I)); |
| 1501 | save_item(NAME(m_I2)); |
| 1502 | save_item(NAME(m_Ip)); |
| 350 | 1503 | |
| 351 | | state_add( PPS4_PC, "PC", m_P.d ).mask(0xfff).formatstr("%03X"); |
| 352 | | state_add( PPS4_A, "A", m_A ).formatstr("%02X"); // TODO: size? |
| 353 | | state_add( PPS4_X, "X", m_X ).formatstr("%02X"); // TODO: size? |
| 354 | | state_add( PPS4_SA, "SA", m_SA.d ).formatstr("%04X"); // TODO: size? |
| 355 | | state_add( PPS4_SB, "SB", m_SB.d ).formatstr("%04X"); // TODO: size? |
| 356 | | state_add( PPS4_B, "B", m_B.d ).formatstr("%04X"); // TODO: size? |
| 357 | | state_add( STATE_GENPC, "GENPC", m_P.d ).noshow(); |
| 358 | | state_add( STATE_GENFLAGS, "GENFLAGS", m_C ).formatstr("%3s").noshow(); |
| 1504 | state_add( PPS4_PC, "PC", m_P ).mask(0xFFF).formatstr("%03X"); |
| 1505 | state_add( PPS4_A, "A", m_A ).formatstr("%01X"); |
| 1506 | state_add( PPS4_X, "X", m_X ).formatstr("%01X"); |
| 1507 | state_add( PPS4_SA, "SA", m_SA ).formatstr("%03X"); |
| 1508 | state_add( PPS4_SB, "SB", m_SB ).formatstr("%03X"); |
| 1509 | state_add( PPS4_B, "B", m_B ).formatstr("%03X"); |
| 1510 | state_add( PPS4_SAG, "SAG", m_SAG ).formatstr("%03X"); |
| 1511 | state_add( PPS4_I2, "I2", m_I2 ).formatstr("%02X").noshow(); |
| 1512 | state_add( PPS4_Ip, "Ip", m_Ip ).formatstr("%02X").noshow(); |
| 1513 | state_add( STATE_GENPC, "GENPC", m_P ).noshow(); |
| 1514 | state_add( STATE_GENFLAGS, "GENFLAGS", m_C).formatstr("%3s").noshow(); |
| 359 | 1515 | |
| 360 | | m_icountptr = &m_icount; |
| 1516 | m_icountptr = &m_icount; |
| 361 | 1517 | } |
| 362 | 1518 | |
| 363 | 1519 | void pps4_device::state_string_export(const device_state_entry &entry, astring &string) |
| 364 | 1520 | { |
| 365 | | switch (entry.index()) |
| 366 | | { |
| 367 | | case STATE_GENFLAGS: |
| 368 | | string.printf("%c%c%c", |
| 369 | | m_C ? 'C':'.', |
| 370 | | m_FF1 ? '1':'.', |
| 371 | | m_FF2 ? '2':'.'); |
| 372 | | break; |
| 373 | | } |
| 1521 | switch (entry.index()) |
| 1522 | { |
| 1523 | case STATE_GENFLAGS: |
| 1524 | string.printf("%c%c%c", |
| 1525 | m_C ? 'C':'.', |
| 1526 | m_FF1 ? '1':'.', |
| 1527 | m_FF2 ? '2':'.'); |
| 1528 | break; |
| 1529 | } |
| 374 | 1530 | } |
| 375 | 1531 | |
| 376 | 1532 | /*************************************************************************** |
| r242165 | r242166 | |
| 379 | 1535 | |
| 380 | 1536 | void pps4_device::device_reset() |
| 381 | 1537 | { |
| 382 | | m_A = m_X = 0; |
| 383 | | m_C = m_FF1 = m_FF2 = 0; |
| 384 | | |
| 385 | | m_P.d = 0; |
| 386 | | m_SA.d = 0; |
| 387 | | m_SB.d = 0; |
| 388 | | m_B.d = 0; |
| 1538 | m_A = 0; // Accumulator A(4:1) |
| 1539 | m_X = 0; // X register X(4:1) |
| 1540 | m_P = 0; // program counter P(12:1) |
| 1541 | m_SA = 0; // Shift register SA(12:1) |
| 1542 | m_SB = 0; // Shift register SB(12:1) |
| 1543 | m_SAG = 0; // Special address generation mask |
| 1544 | m_B = 0; // B address register B(12:1) (BL, BM and BU) |
| 1545 | m_C = 0; // Carry flip-flop |
| 1546 | m_FF1 = 0; // Flip-flop 1 |
| 1547 | m_FF2 = 0; // Flip-flop 2 |
| 1548 | m_I = 0; // Most recent instruction I(8:1) |
| 1549 | m_I2 = 0; // Most recent parameter I2(8:1) |
| 1550 | m_Ip = 0; // Previous instruction I(8:1) |
| 389 | 1551 | } |
trunk/src/emu/cpu/pps4/pps4.h
| r242165 | r242166 | |
| 1 | 1 | // license:BSD-3-Clause |
| 2 | | // copyright-holders:Miodrag Milanovic |
| 2 | // copyright-holders:Juergen Buchmueller <pullmoll@t-online.de> |
| 3 | 3 | #ifndef __PPS4_H__ |
| 4 | 4 | #define __PPS4_H__ |
| 5 | 5 | |
| r242165 | r242166 | |
| 9 | 9 | ***************************************************************************/ |
| 10 | 10 | enum |
| 11 | 11 | { |
| 12 | | PPS4_PC, |
| 13 | | PPS4_A,PPS4_X,PPS4_SA,PPS4_SB,PPS4_B, |
| 14 | | PPS4_GENPC = STATE_GENPC, |
| 15 | | PPS4_GENSP = STATE_GENSP, |
| 16 | | PPS4_GENPCBASE = STATE_GENPCBASE |
| 12 | PPS4_PC, |
| 13 | PPS4_A, |
| 14 | PPS4_X, |
| 15 | PPS4_SA, |
| 16 | PPS4_SB, |
| 17 | PPS4_B, |
| 18 | PPS4_SAG, |
| 19 | PPS4_I2, |
| 20 | PPS4_Ip, |
| 21 | PPS4_GENPC = STATE_GENPC, |
| 22 | PPS4_GENSP = STATE_GENSP, |
| 23 | PPS4_GENPCBASE = STATE_GENPCBASE, |
| 24 | PPS4_PORT_A = 256, |
| 25 | PPS4_PORT_B = 257 |
| 17 | 26 | }; |
| 18 | 27 | |
| 19 | 28 | /*************************************************************************** |
| r242165 | r242166 | |
| 26 | 35 | |
| 27 | 36 | extern const device_type PPS4; |
| 28 | 37 | |
| 29 | | |
| 30 | 38 | class pps4_device : public cpu_device |
| 31 | 39 | { |
| 32 | 40 | public: |
| 33 | | // construction/destruction |
| 34 | | pps4_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 41 | // construction/destruction |
| 42 | pps4_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock); |
| 35 | 43 | |
| 36 | 44 | protected: |
| 37 | | // device-level overrides |
| 38 | | virtual void device_start(); |
| 39 | | virtual void device_reset(); |
| 45 | // device-level overrides |
| 46 | virtual void device_start(); |
| 47 | virtual void device_reset(); |
| 40 | 48 | |
| 41 | | // device_execute_interface overrides |
| 42 | | virtual UINT32 execute_min_cycles() const { return 1; } |
| 43 | | virtual UINT32 execute_max_cycles() const { return 2; } |
| 44 | | virtual UINT32 execute_input_lines() const { return 0; } |
| 45 | | virtual UINT32 execute_default_irq_vector() const { return 0; } |
| 46 | | virtual void execute_run(); |
| 49 | // device_execute_interface overrides |
| 50 | virtual UINT32 execute_min_cycles() const { return 1; } |
| 51 | virtual UINT32 execute_max_cycles() const { return 3; } |
| 52 | virtual UINT32 execute_input_lines() const { return 0; } |
| 53 | virtual UINT32 execute_default_irq_vector() const { return 0; } |
| 54 | virtual void execute_run(); |
| 47 | 55 | |
| 48 | | // device_memory_interface overrides |
| 49 | | virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const |
| 50 | | { |
| 51 | | return (spacenum == AS_PROGRAM) ? &m_program_config : ( (spacenum == AS_IO) ? &m_io_config : ( (spacenum == AS_DATA) ? &m_data_config : NULL ) ); |
| 52 | | } |
| 56 | // device_memory_interface overrides |
| 57 | virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const |
| 58 | { |
| 59 | return (spacenum == AS_PROGRAM) ? &m_program_config : ( (spacenum == AS_IO) ? &m_io_config : ( (spacenum == AS_DATA) ? &m_data_config : NULL ) ); |
| 60 | } |
| 53 | 61 | |
| 54 | | // device_state_interface overrides |
| 55 | | void state_string_export(const device_state_entry &entry, astring &string); |
| 62 | // device_state_interface overrides |
| 63 | void state_string_export(const device_state_entry &entry, astring &string); |
| 56 | 64 | |
| 57 | | // device_disasm_interface overrides |
| 58 | | virtual UINT32 disasm_min_opcode_bytes() const { return 1; } |
| 59 | | virtual UINT32 disasm_max_opcode_bytes() const { return 2; } |
| 60 | | virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options); |
| 65 | // device_disasm_interface overrides |
| 66 | virtual UINT32 disasm_min_opcode_bytes() const { return 1; } |
| 67 | virtual UINT32 disasm_max_opcode_bytes() const { return 2; } |
| 68 | virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options); |
| 61 | 69 | |
| 62 | 70 | private: |
| 63 | | address_space_config m_program_config; |
| 64 | | address_space_config m_data_config; |
| 65 | | address_space_config m_io_config; |
| 71 | address_space_config m_program_config; |
| 72 | address_space_config m_data_config; |
| 73 | address_space_config m_io_config; |
| 66 | 74 | |
| 67 | | UINT8 m_A; // Accumulator |
| 68 | | UINT8 m_X; |
| 75 | address_space *m_program; |
| 76 | direct_read_data *m_direct; |
| 77 | address_space *m_data; |
| 78 | address_space *m_io; |
| 79 | int m_icount; |
| 69 | 80 | |
| 70 | | PAIR m_P; |
| 71 | | PAIR m_SA; |
| 72 | | PAIR m_SB; |
| 73 | | PAIR m_B; // BU + BM + BL |
| 81 | UINT8 m_A; //!< Accumulator A(4:1) |
| 82 | UINT8 m_X; //!< X register X(4:1) |
| 83 | UINT16 m_P; //!< program counter P(12:1) |
| 84 | UINT16 m_SA; //!< Shift register SA(12:1) |
| 85 | UINT16 m_SB; //!< Shift register SB(12:1) |
| 86 | UINT16 m_SAG; //!< Special address generation mask |
| 87 | UINT16 m_B; //!< B register B(12:1) (BL, BM and BH) |
| 88 | UINT8 m_C; //!< Carry flip-flop |
| 89 | UINT8 m_FF1; //!< Flip-flop 1 |
| 90 | UINT8 m_FF2; //!< Flip-flop 2 |
| 91 | UINT8 m_I; //!< Most recent instruction I(8:1) |
| 92 | UINT8 m_I2; //!< Most recent parameter I2(8:1) |
| 93 | UINT8 m_Ip; //!< Previous instruction I(8:1) |
| 74 | 94 | |
| 75 | | UINT8 m_C; // Carry flag |
| 76 | | UINT8 m_FF1; // Flip-flop 1 |
| 77 | | UINT8 m_FF2; // Flip-flop 2 |
| 95 | //! return the contents of B register (made of BU, BM and BL) |
| 96 | inline UINT16 B() const; |
| 78 | 97 | |
| 79 | | address_space *m_program; |
| 80 | | direct_read_data *m_direct; |
| 81 | | address_space *m_data; |
| 82 | | address_space *m_io; |
| 98 | //! return memory at address B(12:1) |
| 99 | inline UINT8 M(); |
| 83 | 100 | |
| 84 | | int m_icount; |
| 101 | //! write to memory at address B(12:1) |
| 102 | inline void W(UINT8 data); |
| 85 | 103 | |
| 86 | | inline UINT8 ROP(); |
| 87 | | inline UINT8 ARG(); |
| 88 | | inline void DO_SKIP(); |
| 89 | | void execute_one(int opcode); |
| 104 | //! return the next opcode (also in m_I) |
| 105 | inline UINT8 ROP(); |
| 90 | 106 | |
| 107 | //! return the next argument (also in m_I2) |
| 108 | inline UINT8 ARG(); |
| 109 | |
| 110 | void iAD(); //!< Add |
| 111 | void iADC(); //!< Add with carry-in |
| 112 | void iADSK(); //!< Add and skip on carry-out |
| 113 | void iADCSK(); //!< Add with carry-in and skip on carry-out |
| 114 | void iADI(); //!< Add immediate |
| 115 | void iDC(); //!< Decimal correction |
| 116 | void iAND(); //!< Logical AND |
| 117 | void iOR(); //!< Logical OR |
| 118 | void iEOR(); //!< Logical Exclusive-OR |
| 119 | void iCOMP(); //!< Complement |
| 120 | void iSC(); //!< Set Carry flip-flop |
| 121 | void iRC(); //!< Reset Carry flip-flop |
| 122 | void iSF1(); //!< Set FF1 |
| 123 | void iRF1(); //!< Reset FF1 |
| 124 | void iSF2(); //!< Set FF2 |
| 125 | void iRF2(); //!< Reset FF2 |
| 126 | void iLD(); //!< Load accumulator from memory |
| 127 | void iEX(); //!< Exchange accumulator and memory |
| 128 | void iEXD(); //!< Exchange accumulator and memory and decrement BL |
| 129 | void iLDI(); //!< Load accumulator immediate |
| 130 | void iLAX(); //!< Load accumulator from X register |
| 131 | void iLXA(); //!< Load X register from accumulator |
| 132 | void iLABL(); //!< Load accumulator with BL |
| 133 | void iLBMX(); //!< Load BM with X |
| 134 | void iLBUA(); //!< Load BU with A |
| 135 | void iXABL(); //!< Exchange accumulator and BL |
| 136 | void iXBMX(); //!< Exchange BM and X registers |
| 137 | void iXAX(); //!< Exchange accumulator and X |
| 138 | void iXS(); //!< Eychange SA and SB registers |
| 139 | void iCYS(); //!< Cycle SA register and accumulaor |
| 140 | void iLB(); //!< Load B indirect |
| 141 | void iLBL(); //!< Load B long |
| 142 | void iINCB(); //!< Increment BL |
| 143 | void iDECB(); //!< Decrement BL |
| 144 | void iT(); //!< Transfer |
| 145 | void iTM(); //!< Transfer and mark indirect |
| 146 | void iTL(); //!< Transfer long |
| 147 | void iTML(); //!< Transfer and mark long |
| 148 | void iSKC(); //!< Skip on carry flip-flop |
| 149 | void iSKZ(); //!< Skip on accumulator zero |
| 150 | void iSKBI(); //!< Skip if BL equal to immediate |
| 151 | void iSKF1(); //!< Skip if FF1 equals 1 |
| 152 | void iSKF2(); //!< Skip if FF2 equals 1 |
| 153 | void iRTN(); //!< Return |
| 154 | void iRTNSK(); //!< Return and skip |
| 155 | void iIOL(); //!< Input/Output long |
| 156 | void iDIA(); //!< Discrete input group A |
| 157 | void iDIB(); //!< Discrete input group B |
| 158 | void iDOA(); //!< Discrete output group A |
| 159 | void iSAG(); //!< Special address generation |
| 160 | |
| 161 | void execute_one(); //!< execute one instruction |
| 91 | 162 | }; |
| 92 | 163 | |
| 93 | | |
| 94 | | #endif |
| 164 | #endif // __PPS4_H__ |
trunk/src/emu/cpu/pps4/pps4dasm.c
| r242165 | r242166 | |
| 1 | 1 | // license:BSD-3-Clause |
| 2 | | // copyright-holders:Miodrag Milanovic |
| 2 | // copyright-holders:Juergen Buchmueller <pullmoll@t-online.de> |
| 3 | 3 | /***************************************************************************** |
| 4 | 4 | * |
| 5 | 5 | * pps4dasm.c |
| 6 | 6 | * |
| 7 | 7 | * Rockwell PPS-4 CPU Disassembly |
| 8 | 8 | * |
| 9 | * |
| 10 | * TODO: double verify all opcodes with t_Ixx flags |
| 11 | * |
| 9 | 12 | *****************************************************************************/ |
| 10 | | |
| 11 | 13 | #include "emu.h" |
| 12 | 14 | |
| 13 | 15 | #define OP(A) oprom[(A) - PC] |
| 14 | 16 | #define ARG(A) opram[(A) - PC] |
| 15 | 17 | |
| 18 | typedef enum pps4_token_e { |
| 19 | t_AD, t_ADC, t_ADSK, t_ADCSK, t_ADI, |
| 20 | t_DC, t_AND, t_OR, t_EOR, t_COMP, |
| 21 | t_SC, t_RC, t_SF1, t_RF1, t_SF2, |
| 22 | t_RF2, t_LD, t_EX, t_EXD, t_LDI, |
| 23 | t_LAX, t_LXA, t_LABL, t_LBMX, t_LBUA, |
| 24 | t_XABL, t_XBMX, t_XAX, t_XS, t_CYS, |
| 25 | t_LB, t_LBL, t_INCB, t_DECB, t_T, |
| 26 | t_TM, t_TL, t_TML, t_SKC, t_SKZ, |
| 27 | t_SKBI, t_SKF1, t_SKF2, t_RTN, t_RTNSK, |
| 28 | t_IOL, t_DIA, t_DIB, t_DOA, t_SAG, |
| 29 | t_COUNT, |
| 30 | t_MASK = (1 << 6) - 1, |
| 31 | t_I3c = 1 << 6, /* immediate 3 bit constant, complemented */ |
| 32 | t_I4 = 1 << 7, /* immediate 4 bit constant */ |
| 33 | t_I4c = 1 << 8, /* immediate 4 bit constant, complemented */ |
| 34 | t_I4p = 1 << 9, /* immediate 4 bit offset into page 3 */ |
| 35 | t_I6p = 1 << 10, /* immediate 6 bit constant; address in current page */ |
| 36 | t_I8 = 1 << 11, /* immediate 8 bit constant (I/O port number) */ |
| 37 | t_I8c = 1 << 12, /* immediate 8 bit constant inverted */ |
| 38 | } pps4_token_e; |
| 39 | |
| 40 | static const char *token_str[t_COUNT] = { |
| 41 | "ad", /* add */ |
| 42 | "adc", /* add with carry-in */ |
| 43 | "adsk", /* add and skip on carry-out */ |
| 44 | "adcsk", /* add with carry-in and skip on carry-out */ |
| 45 | "adi", /* add immediate */ |
| 46 | "dc", /* decimal correction */ |
| 47 | "and", /* logical and */ |
| 48 | "or", /* logical or */ |
| 49 | "eor", /* logical exclusive-orf */ |
| 50 | "comp", /* complement */ |
| 51 | "sc", /* set C flip-flop */ |
| 52 | "rc", /* reset C flip-flop */ |
| 53 | "sf1", /* set FF1 flip-flop */ |
| 54 | "rf1", /* reset FF1 flip-flop */ |
| 55 | "sf2", /* set FF2 flip-flop */ |
| 56 | "rf2", /* reset FF2 flip-flop */ |
| 57 | "ld", /* load accumulator from memory */ |
| 58 | "ex", /* exchange accumulator and memory */ |
| 59 | "exd", /* exchange accumulator and memory and decrement BL */ |
| 60 | "ldi", /* load accumulator immediate */ |
| 61 | "lax", /* load accumulator from X register */ |
| 62 | "lxa", /* load X register from accumulator */ |
| 63 | "labl", /* load accumulator with BL */ |
| 64 | "lbmx", /* load BM with X */ |
| 65 | "lbua", /* load BU with A */ |
| 66 | "xabl", /* exchange accumulator and BL */ |
| 67 | "xbmx", /* exchange BM and X */ |
| 68 | "xax", /* exchange accumulator and X */ |
| 69 | "xs", /* exchange SA and SB */ |
| 70 | "cys", /* cycle SA register and accumulator */ |
| 71 | "lb", /* load B indirect */ |
| 72 | "lbl", /* load B long */ |
| 73 | "incb", /* increment BL */ |
| 74 | "decb", /* decrement BL */ |
| 75 | "t", /* transfer */ |
| 76 | "tm", /* transfer and mark indirect */ |
| 77 | "tl", /* transfer long */ |
| 78 | "tml", /* transfer and mark long */ |
| 79 | "skc", /* skip on C flip-flop equals 1 */ |
| 80 | "skz", /* skip on accumulator zero */ |
| 81 | "skbi", /* skip on BL equal to immediate */ |
| 82 | "skf1", /* skip on FF1 flip-flop equals 1 */ |
| 83 | "skf2", /* skip on FF2 flip-flop equals 1 */ |
| 84 | "rtn", /* return */ |
| 85 | "rtnsk", /* return and skip */ |
| 86 | "iol", /* input/output long */ |
| 87 | "dia", /* discrete input group A */ |
| 88 | "dib", /* discrete input group B */ |
| 89 | "doa", /* discrete output */ |
| 90 | "sag" /* special address generation */ |
| 91 | }; |
| 92 | |
| 93 | static const UINT16 table[] = { |
| 94 | t_LBL | t_I8c, /* 00 */ |
| 95 | t_TML | t_I4 | t_I8, /* 01 */ |
| 96 | t_TML | t_I4 | t_I8, /* 02 */ |
| 97 | t_TML | t_I4 | t_I8, /* 03 */ |
| 98 | t_LBUA, /* 04 */ |
| 99 | t_RTN, /* 05 */ |
| 100 | t_XS, /* 06 */ |
| 101 | t_RTNSK, /* 07 */ |
| 102 | t_ADCSK, /* 08 */ |
| 103 | t_ADSK, /* 09 */ |
| 104 | t_ADC, /* 0a */ |
| 105 | t_AD, /* 0b */ |
| 106 | t_EOR, /* 0c */ |
| 107 | t_AND, /* 0d */ |
| 108 | t_COMP, /* 0e */ |
| 109 | t_OR, /* 0f */ |
| 110 | |
| 111 | t_LBMX, /* 10 */ |
| 112 | t_LABL, /* 11 */ |
| 113 | t_LAX, /* 12 */ |
| 114 | t_SAG, /* 13 */ |
| 115 | t_SKF2, /* 14 */ |
| 116 | t_SKC, /* 15 */ |
| 117 | t_SKF1, /* 16 */ |
| 118 | t_INCB, /* 17 */ |
| 119 | t_XBMX, /* 18 */ |
| 120 | t_XABL, /* 19 */ |
| 121 | t_XAX, /* 1a */ |
| 122 | t_LXA, /* 1b */ |
| 123 | t_IOL | t_I8, /* 1c */ |
| 124 | t_DOA, /* 1d */ |
| 125 | t_SKZ, /* 1e */ |
| 126 | t_DECB, /* 1f */ |
| 127 | |
| 128 | t_SC, /* 20 */ |
| 129 | t_SF2, /* 21 */ |
| 130 | t_SF1, /* 22 */ |
| 131 | t_DIB, /* 23 */ |
| 132 | t_RC, /* 24 */ |
| 133 | t_RF2, /* 25 */ |
| 134 | t_RF1, /* 26 */ |
| 135 | t_DIA, /* 27 */ |
| 136 | t_EXD | t_I3c, /* 28 */ |
| 137 | t_EXD | t_I3c, /* 29 */ |
| 138 | t_EXD | t_I3c, /* 2a */ |
| 139 | t_EXD | t_I3c, /* 2b */ |
| 140 | t_EXD | t_I3c, /* 2c */ |
| 141 | t_EXD | t_I3c, /* 2d */ |
| 142 | t_EXD | t_I3c, /* 2e */ |
| 143 | t_EXD | t_I3c, /* 2f */ |
| 144 | |
| 145 | t_LD | t_I3c, /* 30 */ |
| 146 | t_LD | t_I3c, /* 31 */ |
| 147 | t_LD | t_I3c, /* 32 */ |
| 148 | t_LD | t_I3c, /* 33 */ |
| 149 | t_LD | t_I3c, /* 34 */ |
| 150 | t_LD | t_I3c, /* 35 */ |
| 151 | t_LD | t_I3c, /* 36 */ |
| 152 | t_LD | t_I3c, /* 37 */ |
| 153 | t_EX | t_I3c, /* 38 */ |
| 154 | t_EX | t_I3c, /* 39 */ |
| 155 | t_EX | t_I3c, /* 3a */ |
| 156 | t_EX | t_I3c, /* 3b */ |
| 157 | t_EX | t_I3c, /* 3c */ |
| 158 | t_EX | t_I3c, /* 3d */ |
| 159 | t_EX | t_I3c, /* 3e */ |
| 160 | t_EX | t_I3c, /* 3f */ |
| 161 | |
| 162 | t_SKBI | t_I4, /* 40 */ |
| 163 | t_SKBI | t_I4, /* 41 */ |
| 164 | t_SKBI | t_I4, /* 42 */ |
| 165 | t_SKBI | t_I4, /* 43 */ |
| 166 | t_SKBI | t_I4, /* 44 */ |
| 167 | t_SKBI | t_I4, /* 45 */ |
| 168 | t_SKBI | t_I4, /* 46 */ |
| 169 | t_SKBI | t_I4, /* 47 */ |
| 170 | t_SKBI | t_I4, /* 48 */ |
| 171 | t_SKBI | t_I4, /* 49 */ |
| 172 | t_SKBI | t_I4, /* 4a */ |
| 173 | t_SKBI | t_I4, /* 4b */ |
| 174 | t_SKBI | t_I4, /* 4c */ |
| 175 | t_SKBI | t_I4, /* 4d */ |
| 176 | t_SKBI | t_I4, /* 4e */ |
| 177 | t_SKBI | t_I4, /* 4f */ |
| 178 | |
| 179 | t_TL | t_I4 | t_I8, /* 50 */ |
| 180 | t_TL | t_I4 | t_I8, /* 51 */ |
| 181 | t_TL | t_I4 | t_I8, /* 52 */ |
| 182 | t_TL | t_I4 | t_I8, /* 53 */ |
| 183 | t_TL | t_I4 | t_I8, /* 54 */ |
| 184 | t_TL | t_I4 | t_I8, /* 55 */ |
| 185 | t_TL | t_I4 | t_I8, /* 56 */ |
| 186 | t_TL | t_I4 | t_I8, /* 57 */ |
| 187 | t_TL | t_I4 | t_I8, /* 58 */ |
| 188 | t_TL | t_I4 | t_I8, /* 59 */ |
| 189 | t_TL | t_I4 | t_I8, /* 5a */ |
| 190 | t_TL | t_I4 | t_I8, /* 5b */ |
| 191 | t_TL | t_I4 | t_I8, /* 5c */ |
| 192 | t_TL | t_I4 | t_I8, /* 5d */ |
| 193 | t_TL | t_I4 | t_I8, /* 5e */ |
| 194 | t_TL | t_I4 | t_I8, /* 5f */ |
| 195 | |
| 196 | t_ADI | t_I4c, /* 60 */ |
| 197 | t_ADI | t_I4c, /* 61 */ |
| 198 | t_ADI | t_I4c, /* 62 */ |
| 199 | t_ADI | t_I4c, /* 63 */ |
| 200 | t_ADI | t_I4c, /* 64 */ |
| 201 | t_DC, /* 65 */ |
| 202 | t_ADI | t_I4c, /* 66 */ |
| 203 | t_ADI | t_I4c, /* 67 */ |
| 204 | t_ADI | t_I4c, /* 68 */ |
| 205 | t_ADI | t_I4c, /* 69 */ |
| 206 | t_ADI | t_I4c, /* 6a */ |
| 207 | t_ADI | t_I4c, /* 6b */ |
| 208 | t_ADI | t_I4c, /* 6c */ |
| 209 | t_ADI | t_I4c, /* 6d */ |
| 210 | t_ADI | t_I4c, /* 6e */ |
| 211 | t_CYS, /* 6f */ |
| 212 | |
| 213 | t_LDI | t_I4c, /* 70 */ |
| 214 | t_LDI | t_I4c, /* 71 */ |
| 215 | t_LDI | t_I4c, /* 72 */ |
| 216 | t_LDI | t_I4c, /* 73 */ |
| 217 | t_LDI | t_I4c, /* 74 */ |
| 218 | t_LDI | t_I4c, /* 75 */ |
| 219 | t_LDI | t_I4c, /* 76 */ |
| 220 | t_LDI | t_I4c, /* 77 */ |
| 221 | t_LDI | t_I4c, /* 78 */ |
| 222 | t_LDI | t_I4c, /* 79 */ |
| 223 | t_LDI | t_I4c, /* 7a */ |
| 224 | t_LDI | t_I4c, /* 7b */ |
| 225 | t_LDI | t_I4c, /* 7c */ |
| 226 | t_LDI | t_I4c, /* 7d */ |
| 227 | t_LDI | t_I4c, /* 7e */ |
| 228 | t_LDI | t_I4c, /* 7f */ |
| 229 | |
| 230 | t_T | t_I6p, /* 80 */ |
| 231 | t_T | t_I6p, /* 81 */ |
| 232 | t_T | t_I6p, /* 82 */ |
| 233 | t_T | t_I6p, /* 83 */ |
| 234 | t_T | t_I6p, /* 84 */ |
| 235 | t_T | t_I6p, /* 85 */ |
| 236 | t_T | t_I6p, /* 86 */ |
| 237 | t_T | t_I6p, /* 87 */ |
| 238 | t_T | t_I6p, /* 88 */ |
| 239 | t_T | t_I6p, /* 89 */ |
| 240 | t_T | t_I6p, /* 8a */ |
| 241 | t_T | t_I6p, /* 8b */ |
| 242 | t_T | t_I6p, /* 8c */ |
| 243 | t_T | t_I6p, /* 8d */ |
| 244 | t_T | t_I6p, /* 8e */ |
| 245 | t_T | t_I6p, /* 8f */ |
| 246 | |
| 247 | t_T | t_I6p, /* 90 */ |
| 248 | t_T | t_I6p, /* 91 */ |
| 249 | t_T | t_I6p, /* 92 */ |
| 250 | t_T | t_I6p, /* 93 */ |
| 251 | t_T | t_I6p, /* 94 */ |
| 252 | t_T | t_I6p, /* 95 */ |
| 253 | t_T | t_I6p, /* 96 */ |
| 254 | t_T | t_I6p, /* 97 */ |
| 255 | t_T | t_I6p, /* 98 */ |
| 256 | t_T | t_I6p, /* 99 */ |
| 257 | t_T | t_I6p, /* 9a */ |
| 258 | t_T | t_I6p, /* 9b */ |
| 259 | t_T | t_I6p, /* 9c */ |
| 260 | t_T | t_I6p, /* 9d */ |
| 261 | t_T | t_I6p, /* 9e */ |
| 262 | t_T | t_I6p, /* 9f */ |
| 263 | |
| 264 | t_T | t_I6p, /* a0 */ |
| 265 | t_T | t_I6p, /* a1 */ |
| 266 | t_T | t_I6p, /* a2 */ |
| 267 | t_T | t_I6p, /* a3 */ |
| 268 | t_T | t_I6p, /* a4 */ |
| 269 | t_T | t_I6p, /* a5 */ |
| 270 | t_T | t_I6p, /* a6 */ |
| 271 | t_T | t_I6p, /* a7 */ |
| 272 | t_T | t_I6p, /* a8 */ |
| 273 | t_T | t_I6p, /* a9 */ |
| 274 | t_T | t_I6p, /* aa */ |
| 275 | t_T | t_I6p, /* ab */ |
| 276 | t_T | t_I6p, /* ac */ |
| 277 | t_T | t_I6p, /* ad */ |
| 278 | t_T | t_I6p, /* ae */ |
| 279 | t_T | t_I6p, /* af */ |
| 280 | |
| 281 | t_T | t_I6p, /* b0 */ |
| 282 | t_T | t_I6p, /* b1 */ |
| 283 | t_T | t_I6p, /* b2 */ |
| 284 | t_T | t_I6p, /* b3 */ |
| 285 | t_T | t_I6p, /* b4 */ |
| 286 | t_T | t_I6p, /* b5 */ |
| 287 | t_T | t_I6p, /* b6 */ |
| 288 | t_T | t_I6p, /* b7 */ |
| 289 | t_T | t_I6p, /* b8 */ |
| 290 | t_T | t_I6p, /* b9 */ |
| 291 | t_T | t_I6p, /* ba */ |
| 292 | t_T | t_I6p, /* bb */ |
| 293 | t_T | t_I6p, /* bc */ |
| 294 | t_T | t_I6p, /* bd */ |
| 295 | t_T | t_I6p, /* be */ |
| 296 | t_T | t_I6p, /* bf */ |
| 297 | |
| 298 | t_LB | t_I4p, /* c0 */ |
| 299 | t_LB | t_I4p, /* c1 */ |
| 300 | t_LB | t_I4p, /* c2 */ |
| 301 | t_LB | t_I4p, /* c3 */ |
| 302 | t_LB | t_I4p, /* c4 */ |
| 303 | t_LB | t_I4p, /* c5 */ |
| 304 | t_LB | t_I4p, /* c6 */ |
| 305 | t_LB | t_I4p, /* c7 */ |
| 306 | t_LB | t_I4p, /* c8 */ |
| 307 | t_LB | t_I4p, /* c9 */ |
| 308 | t_LB | t_I4p, /* ca */ |
| 309 | t_LB | t_I4p, /* cb */ |
| 310 | t_LB | t_I4p, /* cc */ |
| 311 | t_LB | t_I4p, /* cd */ |
| 312 | t_LB | t_I4p, /* ce */ |
| 313 | t_LB | t_I4p, /* cf */ |
| 314 | |
| 315 | t_TM | t_I6p, /* d0 */ |
| 316 | t_TM | t_I6p, /* d1 */ |
| 317 | t_TM | t_I6p, /* d2 */ |
| 318 | t_TM | t_I6p, /* d3 */ |
| 319 | t_TM | t_I6p, /* d4 */ |
| 320 | t_TM | t_I6p, /* d5 */ |
| 321 | t_TM | t_I6p, /* d6 */ |
| 322 | t_TM | t_I6p, /* d7 */ |
| 323 | t_TM | t_I6p, /* d8 */ |
| 324 | t_TM | t_I6p, /* d9 */ |
| 325 | t_TM | t_I6p, /* da */ |
| 326 | t_TM | t_I6p, /* db */ |
| 327 | t_TM | t_I6p, /* dc */ |
| 328 | t_TM | t_I6p, /* dd */ |
| 329 | t_TM | t_I6p, /* de */ |
| 330 | t_TM | t_I6p, /* df */ |
| 331 | |
| 332 | t_TM | t_I6p, /* e0 */ |
| 333 | t_TM | t_I6p, /* e1 */ |
| 334 | t_TM | t_I6p, /* e2 */ |
| 335 | t_TM | t_I6p, /* e3 */ |
| 336 | t_TM | t_I6p, /* e4 */ |
| 337 | t_TM | t_I6p, /* e5 */ |
| 338 | t_TM | t_I6p, /* e6 */ |
| 339 | t_TM | t_I6p, /* e7 */ |
| 340 | t_TM | t_I6p, /* e8 */ |
| 341 | t_TM | t_I6p, /* e9 */ |
| 342 | t_TM | t_I6p, /* ea */ |
| 343 | t_TM | t_I6p, /* eb */ |
| 344 | t_TM | t_I6p, /* ec */ |
| 345 | t_TM | t_I6p, /* ed */ |
| 346 | t_TM | t_I6p, /* ee */ |
| 347 | t_TM | t_I6p, /* ef */ |
| 348 | |
| 349 | t_TM | t_I6p, /* f0 */ |
| 350 | t_TM | t_I6p, /* f1 */ |
| 351 | t_TM | t_I6p, /* f2 */ |
| 352 | t_TM | t_I6p, /* f3 */ |
| 353 | t_TM | t_I6p, /* f4 */ |
| 354 | t_TM | t_I6p, /* f5 */ |
| 355 | t_TM | t_I6p, /* f6 */ |
| 356 | t_TM | t_I6p, /* f7 */ |
| 357 | t_TM | t_I6p, /* f8 */ |
| 358 | t_TM | t_I6p, /* f9 */ |
| 359 | t_TM | t_I6p, /* fa */ |
| 360 | t_TM | t_I6p, /* fb */ |
| 361 | t_TM | t_I6p, /* fc */ |
| 362 | t_TM | t_I6p, /* fd */ |
| 363 | t_TM | t_I6p, /* fe */ |
| 364 | t_TM | t_I6p, /* ff */ |
| 365 | }; |
| 366 | |
| 16 | 367 | CPU_DISASSEMBLE( pps4 ) |
| 17 | 368 | { |
| 18 | | UINT32 flags = 0; |
| 19 | | unsigned PC = pc; |
| 20 | | UINT8 op; |
| 21 | | switch (op = OP(pc++)) |
| 22 | | { |
| 23 | | // Arithmetic instructions |
| 24 | | case 0x0b: sprintf (buffer,"ad"); break; |
| 25 | | case 0x0a: sprintf (buffer,"adc"); break; |
| 26 | | case 0x09: sprintf (buffer,"adsk"); break; |
| 27 | | case 0x08: sprintf (buffer,"adcsk"); break; |
| 28 | | case 0x60: case 0x61: case 0x62: case 0x63: |
| 29 | | case 0x64: case 0x66: case 0x67: case 0x68: |
| 30 | | case 0x69: case 0x6a: case 0x6b: case 0x6c: |
| 31 | | case 0x6d: case 0x6e: |
| 32 | | sprintf (buffer,"adi %01x",(op & 0x0f)); break; |
| 33 | | case 0x65: sprintf (buffer,"dc"); break; |
| 34 | | // Logical instructions |
| 35 | | case 0x0d: sprintf (buffer,"and"); break; |
| 36 | | case 0x0f: sprintf (buffer,"or"); break; |
| 37 | | case 0x0c: sprintf (buffer,"eor"); break; |
| 38 | | case 0x0e: sprintf (buffer,"comp"); break; |
| 39 | | // Data transfer instructions |
| 40 | | case 0x20: sprintf (buffer,"sc"); break; |
| 41 | | case 0x24: sprintf (buffer,"rc"); break; |
| 42 | | case 0x22: sprintf (buffer,"sf1"); break; |
| 43 | | case 0x26: sprintf (buffer,"rf1"); break; |
| 44 | | case 0x21: sprintf (buffer,"sf2"); break; |
| 45 | | case 0x25: sprintf (buffer,"rf2"); break; |
| 46 | | case 0x30: case 0x31: case 0x32: case 0x33: |
| 47 | | case 0x34: case 0x35: case 0x36: case 0x37: |
| 48 | | sprintf (buffer,"ld %01x",(op & 0x07)); break; |
| 49 | | case 0x38: case 0x39: case 0x3a: case 0x3b: |
| 50 | | case 0x3c: case 0x3d: case 0x3e: case 0x3f: |
| 51 | | sprintf (buffer,"ex %01x",(op & 0x07)); break; |
| 52 | | case 0x28: case 0x29: case 0x2a: case 0x2b: |
| 53 | | case 0x2c: case 0x2d: case 0x2e: case 0x2f: |
| 54 | | sprintf (buffer,"exd %01x",(op & 0x07)); break; |
| 55 | | case 0x70: case 0x71: case 0x72: case 0x73: |
| 56 | | case 0x74: case 0x75: case 0x76: case 0x77: |
| 57 | | sprintf (buffer,"ldi %01x",(op & 0x0f)); break; |
| 58 | | case 0x12: sprintf (buffer,"lax"); break; |
| 59 | | case 0x1b: sprintf (buffer,"lxa"); break; |
| 60 | | case 0x11: sprintf (buffer,"labl"); break; |
| 61 | | case 0x10: sprintf (buffer,"lbmx"); break; |
| 62 | | case 0x04: sprintf (buffer,"lbua"); break; |
| 63 | | case 0x19: sprintf (buffer,"xabl"); break; |
| 64 | | case 0x18: sprintf (buffer,"xbmx"); break; |
| 65 | | case 0x1a: sprintf (buffer,"xax"); break; |
| 66 | | case 0x06: sprintf (buffer,"xs"); break; |
| 67 | | case 0x6f: sprintf (buffer,"cys"); break; |
| 68 | | case 0xc0: case 0xc1: case 0xc2: case 0xc3: |
| 69 | | case 0xc4: case 0xc5: case 0xc6: case 0xc7: |
| 70 | | case 0xc8: case 0xc9: case 0xca: case 0xcb: |
| 71 | | case 0xcc: case 0xcd: case 0xce: case 0xcf: |
| 72 | | sprintf (buffer,"lb %02x",ARG(pc)); pc++; break; |
| 73 | | case 0x00: sprintf (buffer,"lbl %02x",ARG(pc)); pc++; break; |
| 74 | | case 0x17: sprintf (buffer,"incb"); break; |
| 75 | | case 0x1f: sprintf (buffer,"decb"); break; |
| 76 | | // Control transfer instructions |
| 77 | | case 0x80: case 0x81: case 0x82: case 0x83: |
| 78 | | case 0x84: case 0x85: case 0x86: case 0x87: |
| 79 | | case 0x88: case 0x89: case 0x8a: case 0x8b: |
| 80 | | case 0x8c: case 0x8d: case 0x8e: case 0x8f: |
| 81 | | case 0x90: case 0x91: case 0x92: case 0x93: |
| 82 | | case 0x94: case 0x95: case 0x96: case 0x97: |
| 83 | | case 0x98: case 0x99: case 0x9a: case 0x9b: |
| 84 | | case 0x9c: case 0x9d: case 0x9e: case 0x9f: |
| 85 | | case 0xa0: case 0xa1: case 0xa2: case 0xa3: |
| 86 | | case 0xa4: case 0xa5: case 0xa6: case 0xa7: |
| 87 | | case 0xa8: case 0xa9: case 0xaa: case 0xab: |
| 88 | | case 0xac: case 0xad: case 0xae: case 0xaf: |
| 89 | | case 0xb0: case 0xb1: case 0xb2: case 0xb3: |
| 90 | | case 0xb4: case 0xb5: case 0xb6: case 0xb7: |
| 91 | | case 0xb8: case 0xb9: case 0xba: case 0xbb: |
| 92 | | case 0xbc: case 0xbd: case 0xbe: case 0xbf: |
| 93 | | sprintf (buffer,"t %02x",(op & 0x3f)); break; |
| 94 | | case 0xd0: case 0xd1: case 0xd2: case 0xd3: |
| 95 | | case 0xd4: case 0xd5: case 0xd6: case 0xd7: |
| 96 | | case 0xd8: case 0xd9: case 0xda: case 0xdb: |
| 97 | | case 0xdc: case 0xdd: case 0xde: case 0xdf: |
| 98 | | case 0xe0: case 0xe1: case 0xe2: case 0xe3: |
| 99 | | case 0xe4: case 0xe5: case 0xe6: case 0xe7: |
| 100 | | case 0xe8: case 0xe9: case 0xea: case 0xeb: |
| 101 | | case 0xec: case 0xed: case 0xee: case 0xef: |
| 102 | | case 0xf0: case 0xf1: case 0xf2: case 0xf3: |
| 103 | | case 0xf4: case 0xf5: case 0xf6: case 0xf7: |
| 104 | | case 0xf8: case 0xf9: case 0xfa: case 0xfb: |
| 105 | | case 0xfc: case 0xfd: case 0xfe: case 0xff: |
| 106 | | sprintf (buffer,"tm %02x %02x",(op & 0x3f),ARG(pc)); pc++; break; |
| 107 | | case 0x50: case 0x51: case 0x52: case 0x53: |
| 108 | | case 0x54: case 0x55: case 0x56: case 0x57: |
| 109 | | case 0x58: case 0x59: case 0x5a: case 0x5b: |
| 110 | | case 0x5c: case 0x5d: case 0x5e: case 0x5f: |
| 111 | | sprintf (buffer,"tl %01x %02x",(op & 0x0f),ARG(pc)); pc++; break; |
| 112 | | case 0x01: case 0x02: case 0x03: |
| 113 | | sprintf (buffer,"tml %02x",ARG(pc)); pc++; break; |
| 114 | | case 0x15: sprintf (buffer,"skc"); break; |
| 115 | | case 0x1e: sprintf (buffer,"skz"); break; |
| 116 | | case 0x40: case 0x41: case 0x42: case 0x43: |
| 117 | | case 0x44: case 0x45: case 0x46: case 0x47: |
| 118 | | case 0x48: case 0x49: case 0x4a: case 0x4b: |
| 119 | | case 0x4c: case 0x4d: case 0x4e: case 0x4f: |
| 120 | | sprintf (buffer,"skbi %01x",(op & 0x0f)); break; |
| 121 | | case 0x16: sprintf (buffer,"skf1"); break; |
| 122 | | case 0x14: sprintf (buffer,"skf2"); break; |
| 123 | | case 0x05: sprintf (buffer,"rtn"); break; |
| 124 | | case 0x07: sprintf (buffer,"rtnsk"); break; |
| 125 | | // Input/Output instructions |
| 126 | | case 0x1c: sprintf (buffer,"iol %02x",ARG(pc)); pc++; break; |
| 127 | | case 0x27: sprintf (buffer,"dia"); break; |
| 128 | | case 0x23: sprintf (buffer,"dib"); break; |
| 129 | | case 0x1d: sprintf (buffer,"doa"); break; |
| 130 | | // Special instructions |
| 131 | | case 0x13: sprintf (buffer,"sag"); break; |
| 132 | | } |
| 369 | UINT32 flags = 0; |
| 370 | unsigned PC = pc; |
| 371 | UINT8 op = OP(pc++); |
| 372 | UINT32 tok = table[op]; |
| 373 | char *dst = 0; |
| 133 | 374 | |
| 134 | | return (pc - PC) | flags | DASMFLAG_SUPPORTED; |
| 375 | if (0 == (tok & t_MASK)) |
| 376 | sprintf(buffer, "%s", token_str[tok & t_MASK]); |
| 377 | else |
| 378 | dst = buffer + sprintf(buffer, "%-7s", token_str[tok & t_MASK]); |
| 379 | |
| 380 | if (tok & t_I3c) { |
| 381 | // 3 bit immediate, complemented |
| 382 | UINT8 i = ~op & 7; |
| 383 | dst += sprintf(dst, "%x", i); |
| 384 | } |
| 385 | |
| 386 | if (tok & t_I4) { |
| 387 | // 4 bit immediate |
| 388 | UINT8 i = op & 15; |
| 389 | dst += sprintf(dst, "%x", i); |
| 390 | } |
| 391 | |
| 392 | if (tok & t_I4c) { |
| 393 | // 4 bit immediate, complemented |
| 394 | UINT8 i = ~op & 15; |
| 395 | dst += sprintf(dst, "%x", i); |
| 396 | } |
| 397 | |
| 398 | if (tok & t_I4p) { |
| 399 | // 4 bit immediate offset into page 3 |
| 400 | UINT8 i = op & 15; |
| 401 | dst += sprintf(dst, "[%x]", 0x0c0 | i); |
| 402 | } |
| 403 | |
| 404 | if (tok & t_I6p) { |
| 405 | // 6 bit immediate offset into current page |
| 406 | UINT8 i = op & 63; |
| 407 | dst += sprintf(dst, "%x", (PC & ~63) | i); |
| 408 | } |
| 409 | |
| 410 | if (tok & t_I8) { |
| 411 | // 8 bit immediate I/O port address |
| 412 | UINT8 arg = ARG(pc++); |
| 413 | dst += sprintf(dst, "%02x", arg); |
| 414 | } |
| 415 | |
| 416 | if (tok & t_I8c) { |
| 417 | // 8 bit immediate offset into page |
| 418 | UINT16 arg = ~ARG(pc++) & 255; |
| 419 | dst += sprintf(dst, "%03x", arg); |
| 420 | } |
| 421 | |
| 422 | if (0x05 == op || 0x07 == op) // RTN or RTNSK |
| 423 | flags |= DASMFLAG_STEP_OUT; |
| 424 | |
| 425 | return (pc - PC) | flags | DASMFLAG_SUPPORTED; |
| 135 | 426 | } |