trunk/src/emu/cpu/ssp1601/ssp1601.c
| r26786 | r26787 | |
| 21 | 21 | #include "debugger.h" |
| 22 | 22 | #include "ssp1601.h" |
| 23 | 23 | |
| 24 | | CPU_DISASSEMBLE( ssp1601 ); |
| 25 | 24 | |
| 26 | 25 | /* detect ops with unimplemented/invalid fields. |
| 27 | 26 | * Useful for homebrew or if a new VR revision pops up. */ |
| 28 | 27 | //#define DO_CHECKS |
| 29 | 28 | |
| 30 | 29 | |
| 31 | | |
| 32 | | struct ssp1601_state_t |
| 33 | | { |
| 34 | | PAIR gr[8]; /* general regs, some are 16bit, some 32bit */ |
| 35 | | union { |
| 36 | | unsigned char r[8]; /* pointer registers, 4 for earch bank */ |
| 37 | | struct { |
| 38 | | unsigned char r0[4]; |
| 39 | | unsigned char r1[4]; |
| 40 | | }; |
| 41 | | }; |
| 42 | | union { |
| 43 | | unsigned short RAM[256*2]; /* 2 256-word internal RAM banks */ |
| 44 | | struct { |
| 45 | | unsigned short RAM0[256]; |
| 46 | | unsigned short RAM1[256]; |
| 47 | | }; |
| 48 | | }; |
| 49 | | UINT16 stack[6]; /* 6-level hardware stack */ |
| 50 | | PAIR ppc; |
| 51 | | |
| 52 | | int g_cycles; |
| 53 | | |
| 54 | | legacy_cpu_device *device; |
| 55 | | address_space *program; |
| 56 | | direct_read_data *direct; |
| 57 | | address_space *io; |
| 58 | | }; |
| 59 | | |
| 60 | | INLINE ssp1601_state_t *get_safe_token(device_t *device) |
| 61 | | { |
| 62 | | assert(device != NULL); |
| 63 | | assert(device->type() == SSP1601); |
| 64 | | return (ssp1601_state_t *)downcast<legacy_cpu_device *>(device)->token(); |
| 65 | | } |
| 66 | | |
| 67 | | |
| 68 | | |
| 69 | 30 | // 0 |
| 70 | | #define rX ssp1601_state->gr[SSP_X].w.h |
| 71 | | #define rY ssp1601_state->gr[SSP_Y].w.h |
| 72 | | #define rA ssp1601_state->gr[SSP_A].w.h |
| 73 | | #define rST ssp1601_state->gr[SSP_ST].w.h // 4 |
| 74 | | #define rSTACK ssp1601_state->gr[SSP_STACK].w.h |
| 75 | | #define rPC ssp1601_state->gr[SSP_PC].w.h |
| 76 | | #define rP ssp1601_state->gr[SSP_P] |
| 31 | #define rX m_gr[SSP_X].w.h |
| 32 | #define rY m_gr[SSP_Y].w.h |
| 33 | #define rA m_gr[SSP_A].w.h |
| 34 | #define rST m_gr[SSP_ST].w.h // 4 |
| 35 | #define rSTACK m_gr[SSP_STACK].w.h |
| 36 | #define rPC m_gr[SSP_PC].w.h |
| 37 | #define rP m_gr[SSP_P] |
| 77 | 38 | |
| 78 | | #define rAL ssp1601_state->gr[SSP_A].w.l |
| 79 | | #define rA32 ssp1601_state->gr[SSP_A].d |
| 80 | | #define rIJ ssp1601_state->r |
| 39 | #define rAL m_gr[SSP_A].w.l |
| 40 | #define rA32 m_gr[SSP_A].d |
| 41 | #define rIJ m_r |
| 81 | 42 | |
| 82 | 43 | #define IJind (((op>>6)&4)|(op&3)) |
| 83 | 44 | |
| 84 | | #define PPC ssp1601_state->ppc.w.h |
| 45 | #define PPC m_ppc.w.h |
| 85 | 46 | |
| 86 | | #define FETCH() ssp1601_state->direct->read_decrypted_word(rPC++ << 1) |
| 87 | | #define PROGRAM_WORD(a) ssp1601_state->program->read_word((a) << 1) |
| 47 | #define FETCH() m_direct->read_decrypted_word(rPC++ << 1) |
| 48 | #define PROGRAM_WORD(a) m_program->read_word((a) << 1) |
| 88 | 49 | #define GET_PPC_OFFS() PPC |
| 89 | 50 | |
| 90 | | #define REG_READ(ssp1601_state,r) (((r) <= 4) ? ssp1601_state->gr[r].w.h : reg_read_handlers[r](ssp1601_state, r)) |
| 91 | | #define REG_WRITE(ssp1601_state,r,d) { \ |
| 51 | #define REG_READ(r) (((r) <= 4) ? m_gr[r].w.h : (this->*reg_read_handlers[r])(r)) |
| 52 | #define REG_WRITE(r,d) { \ |
| 92 | 53 | int r1 = r; \ |
| 93 | | if (r1 >= 4) reg_write_handlers[r1](ssp1601_state, r1,d); \ |
| 94 | | else if (r1 > 0) ssp1601_state->gr[r1].w.h = d; \ |
| 54 | if (r1 >= 4) (this->*reg_write_handlers[r1])(r1,d); \ |
| 55 | else if (r1 > 0) m_gr[r1].w.h = d; \ |
| 95 | 56 | } |
| 96 | 57 | |
| 97 | 58 | // flags |
| r26786 | r26787 | |
| 191 | 152 | |
| 192 | 153 | #define OP_CHECK32(OP) { \ |
| 193 | 154 | if ((op & 0x0f) == SSP_P) { /* A <- P */ \ |
| 194 | | update_P(ssp1601_state); \ |
| 155 | update_P(); \ |
| 195 | 156 | OP(rP.d); \ |
| 196 | 157 | break; \ |
| 197 | 158 | } \ |
| r26786 | r26787 | |
| 228 | 189 | #define CHECK_ST(d) |
| 229 | 190 | #endif |
| 230 | 191 | |
| 192 | |
| 193 | const device_type SSP1601 = &device_creator<ssp1601_device>; |
| 194 | |
| 195 | |
| 196 | ssp1601_device::ssp1601_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 197 | : cpu_device(mconfig, SSP1601, "SSP1601", tag, owner, clock, "ssp1601", __FILE__) |
| 198 | , m_program_config("program", ENDIANNESS_BIG, 16, 16, -1) |
| 199 | , m_io_config("io", ENDIANNESS_BIG, 16, 4, 0) |
| 200 | { |
| 201 | } |
| 202 | |
| 203 | |
| 204 | offs_t ssp1601_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) |
| 205 | { |
| 206 | extern CPU_DISASSEMBLE( ssp1601 ); |
| 207 | return CPU_DISASSEMBLE_NAME(ssp1601)(this, buffer, pc, oprom, opram, options); |
| 208 | } |
| 209 | |
| 210 | |
| 231 | 211 | // ----------------------------------------------------- |
| 232 | 212 | // register i/o handlers |
| 233 | 213 | |
| 234 | | static void update_P(ssp1601_state_t *ssp1601_state) |
| 214 | void ssp1601_device::update_P() |
| 235 | 215 | { |
| 236 | 216 | int m1 = (signed short)rX; |
| 237 | 217 | int m2 = (signed short)rY; |
| 238 | 218 | rP.d = (m1 * m2 * 2); |
| 239 | 219 | } |
| 240 | 220 | |
| 241 | | static UINT32 read_unknown(ssp1601_state_t *ssp1601_state, int reg) |
| 221 | UINT32 ssp1601_device::read_unknown(int reg) |
| 242 | 222 | { |
| 243 | 223 | logerror("%s:%i FIXME\n", __FILE__, __LINE__); |
| 244 | 224 | return 0; |
| 245 | 225 | } |
| 246 | 226 | |
| 247 | | static void write_unknown(ssp1601_state_t *ssp1601_state, int reg, UINT32 d) |
| 227 | void ssp1601_device::write_unknown(int reg, UINT32 d) |
| 248 | 228 | { |
| 249 | 229 | logerror("%s:%i FIXME\n", __FILE__, __LINE__); |
| 250 | 230 | } |
| 251 | 231 | |
| 252 | 232 | /* map EXT regs to virtual I/O range of 0x00-0x0f */ |
| 253 | | static UINT32 read_ext(ssp1601_state_t *ssp1601_state, int reg) |
| 233 | UINT32 ssp1601_device::read_ext(int reg) |
| 254 | 234 | { |
| 255 | 235 | reg &= 7; |
| 256 | | return ssp1601_state->io->read_word((reg << 1)); |
| 236 | return m_io->read_word((reg << 1)); |
| 257 | 237 | } |
| 258 | 238 | |
| 259 | | static void write_ext(ssp1601_state_t *ssp1601_state, int reg, UINT32 d) |
| 239 | void ssp1601_device::write_ext(int reg, UINT32 d) |
| 260 | 240 | { |
| 261 | 241 | reg &= 7; |
| 262 | | ssp1601_state->io->write_word((reg << 1), d); |
| 242 | m_io->write_word((reg << 1), d); |
| 263 | 243 | } |
| 264 | 244 | |
| 265 | 245 | // 4 |
| 266 | | static void write_ST(ssp1601_state_t *ssp1601_state, int reg, UINT32 d) |
| 246 | void ssp1601_device::write_ST(int reg, UINT32 d) |
| 267 | 247 | { |
| 268 | 248 | CHECK_ST(d); |
| 269 | 249 | rST = d; |
| 270 | 250 | } |
| 271 | 251 | |
| 272 | 252 | // 5 |
| 273 | | static UINT32 read_STACK(ssp1601_state_t *ssp1601_state, int reg) |
| 253 | UINT32 ssp1601_device::read_STACK(int reg) |
| 274 | 254 | { |
| 275 | 255 | --rSTACK; |
| 276 | 256 | if ((signed short)rSTACK < 0) { |
| 277 | 257 | rSTACK = 5; |
| 278 | 258 | logerror(__FILE__ " FIXME: stack underflow! (%i) @ %04x\n", rSTACK, GET_PPC_OFFS()); |
| 279 | 259 | } |
| 280 | | return ssp1601_state->stack[rSTACK]; |
| 260 | return m_stack[rSTACK]; |
| 281 | 261 | } |
| 282 | 262 | |
| 283 | | static void write_STACK(ssp1601_state_t *ssp1601_state, int reg, UINT32 d) |
| 263 | void ssp1601_device::write_STACK(int reg, UINT32 d) |
| 284 | 264 | { |
| 285 | 265 | if (rSTACK >= 6) { |
| 286 | 266 | logerror(__FILE__ " FIXME: stack overflow! (%i) @ %04x\n", rSTACK, GET_PPC_OFFS()); |
| 287 | 267 | rSTACK = 0; |
| 288 | 268 | } |
| 289 | | ssp1601_state->stack[rSTACK++] = d; |
| 269 | m_stack[rSTACK++] = d; |
| 290 | 270 | } |
| 291 | 271 | |
| 292 | 272 | // 6 |
| 293 | | static UINT32 read_PC(ssp1601_state_t *ssp1601_state, int reg) |
| 273 | UINT32 ssp1601_device::read_PC(int reg) |
| 294 | 274 | { |
| 295 | 275 | return rPC; |
| 296 | 276 | } |
| 297 | 277 | |
| 298 | | static void write_PC(ssp1601_state_t *ssp1601_state, int reg, UINT32 d) |
| 278 | void ssp1601_device::write_PC(int reg, UINT32 d) |
| 299 | 279 | { |
| 300 | 280 | rPC = d; |
| 301 | | ssp1601_state->g_cycles--; |
| 281 | m_g_cycles--; |
| 302 | 282 | } |
| 303 | 283 | |
| 304 | 284 | // 7 |
| 305 | | static UINT32 read_P(ssp1601_state_t *ssp1601_state, int reg) |
| 285 | UINT32 ssp1601_device::read_P(int reg) |
| 306 | 286 | { |
| 307 | | update_P(ssp1601_state); |
| 287 | update_P(); |
| 308 | 288 | return rP.w.h; |
| 309 | 289 | } |
| 310 | 290 | |
| 311 | 291 | // 15 |
| 312 | | static UINT32 read_AL(ssp1601_state_t *ssp1601_state, int reg) |
| 292 | UINT32 ssp1601_device::read_AL(int reg) |
| 313 | 293 | { |
| 314 | 294 | /* apparently reading AL causes some effect on EXT bus, VR depends on that.. */ |
| 315 | | read_ext(ssp1601_state, reg); |
| 295 | read_ext(reg); |
| 316 | 296 | return rAL; |
| 317 | 297 | } |
| 318 | 298 | |
| 319 | | static void write_AL(ssp1601_state_t *ssp1601_state, int reg, UINT32 d) |
| 299 | void ssp1601_device::write_AL(int reg, UINT32 d) |
| 320 | 300 | { |
| 321 | | write_ext(ssp1601_state, reg, d); |
| 301 | write_ext(reg, d); |
| 322 | 302 | rAL = d; |
| 323 | 303 | } |
| 324 | 304 | |
| 325 | 305 | |
| 326 | | typedef UINT32 (*read_func_t)(ssp1601_state_t *ssp1601_state, int reg); |
| 327 | | typedef void (*write_func_t)(ssp1601_state_t *ssp1601_state, int reg, UINT32 d); |
| 328 | 306 | |
| 329 | | static const read_func_t reg_read_handlers[16] = |
| 307 | const ssp1601_device::read_func_t ssp1601_device::reg_read_handlers[16] = |
| 330 | 308 | { |
| 331 | | read_unknown, read_unknown, read_unknown, read_unknown, // -, X, Y, A |
| 332 | | read_unknown, // 4 ST |
| 333 | | read_STACK, |
| 334 | | read_PC, |
| 335 | | read_P, |
| 336 | | read_ext, // 8 |
| 337 | | read_ext, |
| 338 | | read_ext, |
| 339 | | read_ext, |
| 340 | | read_ext, // 12 |
| 341 | | read_ext, |
| 342 | | read_ext, |
| 343 | | read_AL |
| 309 | &ssp1601_device::read_unknown, &ssp1601_device::read_unknown, &ssp1601_device::read_unknown, &ssp1601_device::read_unknown, // -, X, Y, A |
| 310 | &ssp1601_device::read_unknown, // 4 ST |
| 311 | &ssp1601_device::read_STACK, |
| 312 | &ssp1601_device::read_PC, |
| 313 | &ssp1601_device::read_P, |
| 314 | &ssp1601_device::read_ext, // 8 |
| 315 | &ssp1601_device::read_ext, |
| 316 | &ssp1601_device::read_ext, |
| 317 | &ssp1601_device::read_ext, |
| 318 | &ssp1601_device::read_ext, // 12 |
| 319 | &ssp1601_device::read_ext, |
| 320 | &ssp1601_device::read_ext, |
| 321 | &ssp1601_device::read_AL |
| 344 | 322 | }; |
| 345 | 323 | |
| 346 | | static const write_func_t reg_write_handlers[16] = |
| 324 | const ssp1601_device::write_func_t ssp1601_device::reg_write_handlers[16] = |
| 347 | 325 | { |
| 348 | | write_unknown, write_unknown, write_unknown, write_unknown, // -, X, Y, A |
| 349 | | write_ST, |
| 350 | | write_STACK, |
| 351 | | write_PC, |
| 352 | | write_unknown, // 7 P (not writable) |
| 353 | | write_ext, // 8 |
| 354 | | write_ext, |
| 355 | | write_ext, |
| 356 | | write_ext, |
| 357 | | write_ext, // 12 |
| 358 | | write_ext, |
| 359 | | write_ext, |
| 360 | | write_AL |
| 326 | &ssp1601_device::write_unknown, &ssp1601_device::write_unknown, &ssp1601_device::write_unknown, &ssp1601_device::write_unknown, // -, X, Y, A |
| 327 | &ssp1601_device::write_ST, |
| 328 | &ssp1601_device::write_STACK, |
| 329 | &ssp1601_device::write_PC, |
| 330 | &ssp1601_device::write_unknown, // 7 P (not writable) |
| 331 | &ssp1601_device::write_ext, // 8 |
| 332 | &ssp1601_device::write_ext, |
| 333 | &ssp1601_device::write_ext, |
| 334 | &ssp1601_device::write_ext, |
| 335 | &ssp1601_device::write_ext, // 12 |
| 336 | &ssp1601_device::write_ext, |
| 337 | &ssp1601_device::write_ext, |
| 338 | &ssp1601_device::write_AL |
| 361 | 339 | }; |
| 362 | 340 | |
| 363 | 341 | // ----------------------------------------------------- |
| 364 | 342 | // pointer register handlers |
| 365 | 343 | |
| 366 | 344 | // |
| 367 | | #define ptr1_read(ssp1601_state, op) ptr1_read_(ssp1601_state, op&3,(op>>6)&4,(op<<1)&0x18) |
| 345 | #define ptr1_read(op) ptr1_read_(op&3,(op>>6)&4,(op<<1)&0x18) |
| 368 | 346 | |
| 369 | | static UINT32 ptr1_read_(ssp1601_state_t *ssp1601_state, int ri, int isj2, int modi3) |
| 347 | UINT32 ssp1601_device::ptr1_read_(int ri, int isj2, int modi3) |
| 370 | 348 | { |
| 371 | 349 | //int t = (op&3) | ((op>>6)&4) | ((op<<1)&0x18); |
| 372 | 350 | UINT32 mask, add = 0, t = ri | isj2 | modi3; |
| r26786 | r26787 | |
| 376 | 354 | // mod=0 (00) |
| 377 | 355 | case 0x00: |
| 378 | 356 | case 0x01: |
| 379 | | case 0x02: return ssp1601_state->RAM0[ssp1601_state->r0[t&3]]; |
| 380 | | case 0x03: return ssp1601_state->RAM0[0]; |
| 357 | case 0x02: return m_RAM0[m_r0[t&3]]; |
| 358 | case 0x03: return m_RAM0[0]; |
| 381 | 359 | case 0x04: |
| 382 | 360 | case 0x05: |
| 383 | | case 0x06: return ssp1601_state->RAM1[ssp1601_state->r1[t&3]]; |
| 384 | | case 0x07: return ssp1601_state->RAM1[0]; |
| 361 | case 0x06: return m_RAM1[m_r1[t&3]]; |
| 362 | case 0x07: return m_RAM1[0]; |
| 385 | 363 | // mod=1 (01), "+!" |
| 386 | 364 | case 0x08: |
| 387 | 365 | case 0x09: |
| 388 | | case 0x0a: return ssp1601_state->RAM0[ssp1601_state->r0[t&3]++]; |
| 389 | | case 0x0b: return ssp1601_state->RAM0[1]; |
| 366 | case 0x0a: return m_RAM0[m_r0[t&3]++]; |
| 367 | case 0x0b: return m_RAM0[1]; |
| 390 | 368 | case 0x0c: |
| 391 | 369 | case 0x0d: |
| 392 | | case 0x0e: return ssp1601_state->RAM1[ssp1601_state->r1[t&3]++]; |
| 393 | | case 0x0f: return ssp1601_state->RAM1[1]; |
| 370 | case 0x0e: return m_RAM1[m_r1[t&3]++]; |
| 371 | case 0x0f: return m_RAM1[1]; |
| 394 | 372 | // mod=2 (10), "-" |
| 395 | 373 | case 0x10: |
| 396 | 374 | case 0x11: |
| 397 | | case 0x12: rp = &ssp1601_state->r0[t&3]; t = ssp1601_state->RAM0[*rp]; |
| 375 | case 0x12: rp = &m_r0[t&3]; t = m_RAM0[*rp]; |
| 398 | 376 | if (!(rST&7)) { (*rp)--; return t; } |
| 399 | 377 | add = -1; goto modulo; |
| 400 | | case 0x13: return ssp1601_state->RAM0[2]; |
| 378 | case 0x13: return m_RAM0[2]; |
| 401 | 379 | case 0x14: |
| 402 | 380 | case 0x15: |
| 403 | | case 0x16: rp = &ssp1601_state->r1[t&3]; t = ssp1601_state->RAM1[*rp]; |
| 381 | case 0x16: rp = &m_r1[t&3]; t = m_RAM1[*rp]; |
| 404 | 382 | if (!(rST&7)) { (*rp)--; return t; } |
| 405 | 383 | add = -1; goto modulo; |
| 406 | | case 0x17: return ssp1601_state->RAM1[2]; |
| 384 | case 0x17: return m_RAM1[2]; |
| 407 | 385 | // mod=3 (11), "+" |
| 408 | 386 | case 0x18: |
| 409 | 387 | case 0x19: |
| 410 | | case 0x1a: rp = &ssp1601_state->r0[t&3]; t = ssp1601_state->RAM0[*rp]; |
| 388 | case 0x1a: rp = &m_r0[t&3]; t = m_RAM0[*rp]; |
| 411 | 389 | if (!(rST&7)) { (*rp)++; return t; } |
| 412 | 390 | add = 1; goto modulo; |
| 413 | | case 0x1b: return ssp1601_state->RAM0[3]; |
| 391 | case 0x1b: return m_RAM0[3]; |
| 414 | 392 | case 0x1c: |
| 415 | 393 | case 0x1d: |
| 416 | | case 0x1e: rp = &ssp1601_state->r1[t&3]; t = ssp1601_state->RAM1[*rp]; |
| 394 | case 0x1e: rp = &m_r1[t&3]; t = m_RAM1[*rp]; |
| 417 | 395 | if (!(rST&7)) { (*rp)++; return t; } |
| 418 | 396 | add = 1; goto modulo; |
| 419 | | case 0x1f: return ssp1601_state->RAM1[3]; |
| 397 | case 0x1f: return m_RAM1[3]; |
| 420 | 398 | } |
| 421 | 399 | |
| 422 | 400 | return 0; |
| r26786 | r26787 | |
| 427 | 405 | return t; |
| 428 | 406 | } |
| 429 | 407 | |
| 430 | | static void ptr1_write(ssp1601_state_t *ssp1601_state, int op, UINT32 d) |
| 408 | void ssp1601_device::ptr1_write(int op, UINT32 d) |
| 431 | 409 | { |
| 432 | 410 | int t = (op&3) | ((op>>6)&4) | ((op<<1)&0x18); |
| 433 | 411 | switch (t) |
| r26786 | r26787 | |
| 435 | 413 | // mod=0 (00) |
| 436 | 414 | case 0x00: |
| 437 | 415 | case 0x01: |
| 438 | | case 0x02: ssp1601_state->RAM0[ssp1601_state->r0[t&3]] = d; return; |
| 439 | | case 0x03: ssp1601_state->RAM0[0] = d; return; |
| 416 | case 0x02: m_RAM0[m_r0[t&3]] = d; return; |
| 417 | case 0x03: m_RAM0[0] = d; return; |
| 440 | 418 | case 0x04: |
| 441 | 419 | case 0x05: |
| 442 | | case 0x06: ssp1601_state->RAM1[ssp1601_state->r1[t&3]] = d; return; |
| 443 | | case 0x07: ssp1601_state->RAM1[0] = d; return; |
| 420 | case 0x06: m_RAM1[m_r1[t&3]] = d; return; |
| 421 | case 0x07: m_RAM1[0] = d; return; |
| 444 | 422 | // mod=1 (01), "+!" |
| 445 | 423 | // mod=3, "+" |
| 446 | 424 | case 0x08: |
| 447 | 425 | case 0x09: |
| 448 | | case 0x0a: ssp1601_state->RAM0[ssp1601_state->r0[t&3]++] = d; return; |
| 449 | | case 0x0b: ssp1601_state->RAM0[1] = d; return; |
| 426 | case 0x0a: m_RAM0[m_r0[t&3]++] = d; return; |
| 427 | case 0x0b: m_RAM0[1] = d; return; |
| 450 | 428 | case 0x0c: |
| 451 | 429 | case 0x0d: |
| 452 | | case 0x0e: ssp1601_state->RAM1[ssp1601_state->r1[t&3]++] = d; return; |
| 453 | | case 0x0f: ssp1601_state->RAM1[1] = d; return; |
| 430 | case 0x0e: m_RAM1[m_r1[t&3]++] = d; return; |
| 431 | case 0x0f: m_RAM1[1] = d; return; |
| 454 | 432 | // mod=2 (10), "-" |
| 455 | 433 | case 0x10: |
| 456 | 434 | case 0x11: |
| 457 | | case 0x12: ssp1601_state->RAM0[ssp1601_state->r0[t&3]--] = d; CHECK_RPL(); return; |
| 458 | | case 0x13: ssp1601_state->RAM0[2] = d; return; |
| 435 | case 0x12: m_RAM0[m_r0[t&3]--] = d; CHECK_RPL(); return; |
| 436 | case 0x13: m_RAM0[2] = d; return; |
| 459 | 437 | case 0x14: |
| 460 | 438 | case 0x15: |
| 461 | | case 0x16: ssp1601_state->RAM1[ssp1601_state->r1[t&3]--] = d; CHECK_RPL(); return; |
| 462 | | case 0x17: ssp1601_state->RAM1[2] = d; return; |
| 439 | case 0x16: m_RAM1[m_r1[t&3]--] = d; CHECK_RPL(); return; |
| 440 | case 0x17: m_RAM1[2] = d; return; |
| 463 | 441 | // mod=3 (11), "+" |
| 464 | 442 | case 0x18: |
| 465 | 443 | case 0x19: |
| 466 | | case 0x1a: ssp1601_state->RAM0[ssp1601_state->r0[t&3]++] = d; CHECK_RPL(); return; |
| 467 | | case 0x1b: ssp1601_state->RAM0[3] = d; return; |
| 444 | case 0x1a: m_RAM0[m_r0[t&3]++] = d; CHECK_RPL(); return; |
| 445 | case 0x1b: m_RAM0[3] = d; return; |
| 468 | 446 | case 0x1c: |
| 469 | 447 | case 0x1d: |
| 470 | | case 0x1e: ssp1601_state->RAM1[ssp1601_state->r1[t&3]++] = d; CHECK_RPL(); return; |
| 471 | | case 0x1f: ssp1601_state->RAM1[3] = d; return; |
| 448 | case 0x1e: m_RAM1[m_r1[t&3]++] = d; CHECK_RPL(); return; |
| 449 | case 0x1f: m_RAM1[3] = d; return; |
| 472 | 450 | } |
| 473 | 451 | } |
| 474 | 452 | |
| 475 | | static UINT32 ptr2_read(ssp1601_state_t *ssp1601_state, int op) |
| 453 | UINT32 ssp1601_device::ptr2_read(int op) |
| 476 | 454 | { |
| 477 | 455 | int mv = 0, t = (op&3) | ((op>>6)&4) | ((op<<1)&0x18); |
| 478 | 456 | switch (t) |
| r26786 | r26787 | |
| 480 | 458 | // mod=0 (00) |
| 481 | 459 | case 0x00: |
| 482 | 460 | case 0x01: |
| 483 | | case 0x02: mv = ssp1601_state->RAM0[ssp1601_state->r0[t&3]]++; break; |
| 484 | | case 0x03: mv = ssp1601_state->RAM0[0]++; break; |
| 461 | case 0x02: mv = m_RAM0[m_r0[t&3]]++; break; |
| 462 | case 0x03: mv = m_RAM0[0]++; break; |
| 485 | 463 | case 0x04: |
| 486 | 464 | case 0x05: |
| 487 | | case 0x06: mv = ssp1601_state->RAM1[ssp1601_state->r1[t&3]]++; break; |
| 488 | | case 0x07: mv = ssp1601_state->RAM1[0]++; break; |
| 465 | case 0x06: mv = m_RAM1[m_r1[t&3]]++; break; |
| 466 | case 0x07: mv = m_RAM1[0]++; break; |
| 489 | 467 | // mod=1 (01) |
| 490 | | case 0x0b: mv = ssp1601_state->RAM0[1]++; break; |
| 491 | | case 0x0f: mv = ssp1601_state->RAM1[1]++; break; |
| 468 | case 0x0b: mv = m_RAM0[1]++; break; |
| 469 | case 0x0f: mv = m_RAM1[1]++; break; |
| 492 | 470 | // mod=2 (10) |
| 493 | | case 0x13: mv = ssp1601_state->RAM0[2]++; break; |
| 494 | | case 0x17: mv = ssp1601_state->RAM1[2]++; break; |
| 471 | case 0x13: mv = m_RAM0[2]++; break; |
| 472 | case 0x17: mv = m_RAM1[2]++; break; |
| 495 | 473 | // mod=3 (11) |
| 496 | | case 0x1b: mv = ssp1601_state->RAM0[3]++; break; |
| 497 | | case 0x1f: mv = ssp1601_state->RAM1[3]++; break; |
| 474 | case 0x1b: mv = m_RAM0[3]++; break; |
| 475 | case 0x1f: mv = m_RAM1[3]++; break; |
| 498 | 476 | default: logerror(__FILE__ " FIXME: unimplemented mod in ((rX)) @ %04x\n", GET_PPC_OFFS()); |
| 499 | 477 | return 0; |
| 500 | 478 | } |
| r26786 | r26787 | |
| 506 | 484 | // ----------------------------------------------------- |
| 507 | 485 | |
| 508 | 486 | |
| 509 | | static CPU_INIT( ssp1601 ) |
| 487 | void ssp1601_device::device_start() |
| 510 | 488 | { |
| 511 | | ssp1601_state_t *ssp1601_state = get_safe_token(device); |
| 489 | save_item(NAME(rX)); |
| 490 | save_item(NAME(rY)); |
| 491 | save_item(NAME(rA32)); |
| 492 | save_item(NAME(rST)); |
| 493 | save_item(NAME(rSTACK)); |
| 494 | save_item(NAME(rPC)); |
| 495 | save_item(NAME(rP.d)); |
| 496 | save_item(NAME(PPC)); |
| 497 | save_item(NAME(m_stack)); |
| 498 | save_item(NAME(m_r)); |
| 499 | save_item(NAME(m_RAM)); |
| 512 | 500 | |
| 513 | | device->save_item(NAME(rX)); |
| 514 | | device->save_item(NAME(rY)); |
| 515 | | device->save_item(NAME(rA32)); |
| 516 | | device->save_item(NAME(rST)); |
| 517 | | device->save_item(NAME(rSTACK)); |
| 518 | | device->save_item(NAME(rPC)); |
| 519 | | device->save_item(NAME(rP.d)); |
| 520 | | device->save_item(NAME(PPC)); |
| 521 | | device->save_item(NAME(ssp1601_state->stack)); |
| 522 | | device->save_item(NAME(ssp1601_state->r)); |
| 523 | | device->save_item(NAME(ssp1601_state->RAM)); |
| 524 | | |
| 525 | 501 | /* clear the state */ |
| 526 | | memset(ssp1601_state, 0, sizeof(ssp1601_state_t)); |
| 527 | | ssp1601_state->gr[0].w.h = 0xffff; // constant reg |
| 528 | | ssp1601_state->device = device; |
| 529 | | ssp1601_state->program = &device->space(AS_PROGRAM); |
| 530 | | ssp1601_state->direct = &ssp1601_state->program->direct(); |
| 531 | | ssp1601_state->io = &device->space(AS_IO); |
| 502 | for ( int i = 0; i < 8; i++ ) |
| 503 | { |
| 504 | m_gr[i].d = 0; |
| 505 | m_r[i] = 0; |
| 506 | } |
| 507 | memset( m_RAM, 0, sizeof(m_RAM)); |
| 508 | for ( int i = 0; i < 6; i++ ) |
| 509 | { |
| 510 | m_stack[i] = 0; |
| 511 | } |
| 512 | m_ppc.d = 0; |
| 513 | m_g_cycles = 0; |
| 532 | 514 | |
| 515 | m_gr[0].w.h = 0xffff; // constant reg |
| 516 | m_program = &space(AS_PROGRAM); |
| 517 | m_direct = &m_program->direct(); |
| 518 | m_io = &space(AS_IO); |
| 519 | |
| 520 | state_add( SSP_R0, "REG0", m_gr[0].w.h).formatstr("%04X"); |
| 521 | state_add( SSP_X, "X", rX).formatstr("%04X"); |
| 522 | state_add( SSP_Y, "Y", rY).formatstr("%04X"); |
| 523 | state_add( SSP_A, "A", rA32).formatstr("%08X"); |
| 524 | state_add( SSP_ST, "ST", rST).formatstr("%04X"); |
| 525 | state_add( SSP_STACK, "STACK", rSTACK).formatstr("%04X"); |
| 526 | state_add( SSP_PC, "PC", rPC).formatstr("%04X"); |
| 527 | state_add( SSP_P, "P", rP.d).formatstr("%08X"); |
| 528 | state_add( SSP_STACK0, "STACK0", m_stack[0]).formatstr("%04X"); |
| 529 | state_add( SSP_STACK1, "STACK1", m_stack[1]).formatstr("%04X"); |
| 530 | state_add( SSP_STACK2, "STACK2", m_stack[2]).formatstr("%04X"); |
| 531 | state_add( SSP_STACK3, "STACK3", m_stack[3]).formatstr("%04X"); |
| 532 | state_add( SSP_STACK4, "STACK4", m_stack[4]).formatstr("%04X"); |
| 533 | state_add( SSP_STACK5, "STACK5", m_stack[5]).formatstr("%04X"); |
| 534 | state_add( SSP_PR0, "R0", m_r[0]).formatstr("%02X"); |
| 535 | state_add( SSP_PR1, "R1", m_r[1]).formatstr("%02X"); |
| 536 | state_add( SSP_PR2, "R2", m_r[2]).formatstr("%02X"); |
| 537 | state_add( SSP_PR3, "R3", m_r[3]).formatstr("%02X"); |
| 538 | state_add( SSP_PR4, "R4", m_r[4]).formatstr("%02X"); |
| 539 | state_add( SSP_PR5, "R5", m_r[5]).formatstr("%02X"); |
| 540 | state_add( SSP_PR6, "R6", m_r[6]).formatstr("%02X"); |
| 541 | state_add( SSP_PR7, "R7", m_r[7]).formatstr("%02X"); |
| 542 | |
| 543 | state_add(STATE_GENPC, "GENPC", rPC).noshow(); |
| 544 | state_add(STATE_GENFLAGS, "GENFLAGS", rST).formatstr("%4s").noshow(); |
| 545 | state_add(STATE_GENPCBASE, "GENPCBASE", PPC).noshow(); |
| 546 | |
| 547 | m_icountptr = &m_g_cycles; |
| 533 | 548 | } |
| 534 | 549 | |
| 535 | | static CPU_EXIT( ssp1601 ) |
| 550 | |
| 551 | void ssp1601_device::state_string_export(const device_state_entry &entry, astring &string) |
| 536 | 552 | { |
| 537 | | /* nothing to do */ |
| 553 | switch (entry.index()) |
| 554 | { |
| 555 | case STATE_GENFLAGS: |
| 556 | string.printf( "%c%c%c%c", (rST&SSP_FLAG_N)?'N':'.', (rST&SSP_FLAG_V)?'V':'.', |
| 557 | (rST&SSP_FLAG_Z)?'Z':'.', (rST&SSP_FLAG_L)?'L':'.' |
| 558 | ); |
| 559 | break; |
| 560 | } |
| 538 | 561 | } |
| 539 | 562 | |
| 540 | | static CPU_RESET( ssp1601 ) |
| 541 | | { |
| 542 | | ssp1601_state_t *ssp1601_state = get_safe_token(device); |
| 543 | 563 | |
| 564 | void ssp1601_device::device_reset() |
| 565 | { |
| 544 | 566 | rPC = 0x400; |
| 545 | 567 | rSTACK = 0; // ? using ascending stack |
| 546 | 568 | rST = 0; |
| 547 | 569 | } |
| 548 | 570 | |
| 549 | 571 | |
| 550 | | static CPU_EXECUTE( ssp1601 ) |
| 572 | void ssp1601_device::execute_run() |
| 551 | 573 | { |
| 552 | | ssp1601_state_t *ssp1601_state = get_safe_token(device); |
| 553 | | |
| 554 | | while (ssp1601_state->g_cycles > 0) |
| 574 | while (m_g_cycles > 0) |
| 555 | 575 | { |
| 556 | 576 | int op; |
| 557 | 577 | UINT32 tmpv; |
| 558 | 578 | |
| 559 | 579 | PPC = rPC; |
| 560 | 580 | |
| 561 | | debugger_instruction_hook(device, rPC); |
| 581 | debugger_instruction_hook(this, rPC); |
| 562 | 582 | |
| 563 | 583 | op = FETCH(); |
| 564 | 584 | |
| r26786 | r26787 | |
| 569 | 589 | CHECK_B_SET(); |
| 570 | 590 | if (op == 0) break; // nop |
| 571 | 591 | if (op == ((SSP_A<<4)|SSP_P)) { // A <- P |
| 572 | | update_P(ssp1601_state); |
| 592 | update_P(); |
| 573 | 593 | rA32 = rP.d; |
| 574 | 594 | } |
| 575 | 595 | else |
| 576 | 596 | { |
| 577 | | tmpv = REG_READ(ssp1601_state,op & 0x0f); |
| 578 | | REG_WRITE(ssp1601_state,(op & 0xf0) >> 4, tmpv); |
| 597 | tmpv = REG_READ(op & 0x0f); |
| 598 | REG_WRITE((op & 0xf0) >> 4, tmpv); |
| 579 | 599 | } |
| 580 | 600 | break; |
| 581 | 601 | |
| 582 | 602 | // ld d, (ri) |
| 583 | | case 0x01: tmpv = ptr1_read(ssp1601_state, op); REG_WRITE(ssp1601_state, (op & 0xf0) >> 4, tmpv); break; |
| 603 | case 0x01: tmpv = ptr1_read(op); REG_WRITE((op & 0xf0) >> 4, tmpv); break; |
| 584 | 604 | |
| 585 | 605 | // ld (ri), s |
| 586 | | case 0x02: tmpv = REG_READ(ssp1601_state,(op & 0xf0) >> 4); ptr1_write(ssp1601_state, op, tmpv); break; |
| 606 | case 0x02: tmpv = REG_READ((op & 0xf0) >> 4); ptr1_write(op, tmpv); break; |
| 587 | 607 | |
| 588 | 608 | // ldi d, imm |
| 589 | | case 0x04: CHECK_10f(); tmpv = FETCH(); REG_WRITE(ssp1601_state, (op & 0xf0) >> 4, tmpv);ssp1601_state->g_cycles--; break; |
| 609 | case 0x04: CHECK_10f(); tmpv = FETCH(); REG_WRITE((op & 0xf0) >> 4, tmpv);m_g_cycles--; break; |
| 590 | 610 | |
| 591 | 611 | // ld d, ((ri)) |
| 592 | | case 0x05: CHECK_MOD(); tmpv = ptr2_read(ssp1601_state, op); REG_WRITE(ssp1601_state, (op & 0xf0) >> 4, tmpv); ssp1601_state->g_cycles -= 2; break; |
| 612 | case 0x05: CHECK_MOD(); tmpv = ptr2_read(op); REG_WRITE((op & 0xf0) >> 4, tmpv); m_g_cycles -= 2; break; |
| 593 | 613 | |
| 594 | 614 | // ldi (ri), imm |
| 595 | | case 0x06: tmpv = FETCH(); ptr1_write(ssp1601_state, op, tmpv); ssp1601_state->g_cycles--; break; |
| 615 | case 0x06: tmpv = FETCH(); ptr1_write(op, tmpv); m_g_cycles--; break; |
| 596 | 616 | |
| 597 | 617 | // ld adr, a |
| 598 | | case 0x07: ssp1601_state->RAM[op & 0x1ff] = rA; break; |
| 618 | case 0x07: m_RAM[op & 0x1ff] = rA; break; |
| 599 | 619 | |
| 600 | 620 | // ld d, ri |
| 601 | | case 0x09: CHECK_MOD(); tmpv = rIJ[(op&3)|((op>>6)&4)]; REG_WRITE(ssp1601_state,(op & 0xf0) >> 4, tmpv); break; |
| 621 | case 0x09: CHECK_MOD(); tmpv = rIJ[(op&3)|((op>>6)&4)]; REG_WRITE((op & 0xf0) >> 4, tmpv); break; |
| 602 | 622 | |
| 603 | 623 | // ld ri, s |
| 604 | | case 0x0a: CHECK_MOD(); rIJ[(op&3)|((op>>6)&4)] = REG_READ(ssp1601_state,(op & 0xf0) >> 4); break; |
| 624 | case 0x0a: CHECK_MOD(); rIJ[(op&3)|((op>>6)&4)] = REG_READ((op & 0xf0) >> 4); break; |
| 605 | 625 | |
| 606 | 626 | // ldi ri, simm |
| 607 | 627 | case 0x0c: |
| r26786 | r26787 | |
| 614 | 634 | int cond = 0; |
| 615 | 635 | CHECK_00f(); |
| 616 | 636 | COND_CHECK |
| 617 | | if (cond) { int new_PC = FETCH(); write_STACK(ssp1601_state, SSP_STACK, rPC); rPC = new_PC; } |
| 637 | if (cond) { int new_PC = FETCH(); write_STACK(SSP_STACK, rPC); rPC = new_PC; } |
| 618 | 638 | else rPC++; |
| 619 | | ssp1601_state->g_cycles--; // always 2 cycles |
| 639 | m_g_cycles--; // always 2 cycles |
| 620 | 640 | break; |
| 621 | 641 | } |
| 622 | 642 | |
| r26786 | r26787 | |
| 624 | 644 | case 0x25: |
| 625 | 645 | CHECK_10f(); |
| 626 | 646 | tmpv = PROGRAM_WORD(rA); |
| 627 | | REG_WRITE(ssp1601_state,(op & 0xf0) >> 4, tmpv); |
| 628 | | ssp1601_state->g_cycles -= 2; // 3 cycles total |
| 647 | REG_WRITE((op & 0xf0) >> 4, tmpv); |
| 648 | m_g_cycles -= 2; // 3 cycles total |
| 629 | 649 | break; |
| 630 | 650 | |
| 631 | 651 | // bra cond, addr |
| r26786 | r26787 | |
| 635 | 655 | COND_CHECK |
| 636 | 656 | if (cond) { rPC = FETCH(); } |
| 637 | 657 | else rPC++; |
| 638 | | ssp1601_state->g_cycles--; |
| 658 | m_g_cycles--; |
| 639 | 659 | break; |
| 640 | 660 | } |
| 641 | 661 | |
| r26786 | r26787 | |
| 661 | 681 | // mpys? |
| 662 | 682 | case 0x1b: |
| 663 | 683 | CHECK_B_CLEAR(); |
| 664 | | update_P(ssp1601_state); |
| 684 | update_P(); |
| 665 | 685 | rA32 -= rP.d; |
| 666 | 686 | UPD_ACC_ZN |
| 667 | | rX = ptr1_read_(ssp1601_state, op&3, 0, (op<<1)&0x18); |
| 668 | | rY = ptr1_read_(ssp1601_state, (op>>4)&3, 4, (op>>3)&0x18); |
| 687 | rX = ptr1_read_(op&3, 0, (op<<1)&0x18); |
| 688 | rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); |
| 669 | 689 | break; |
| 670 | 690 | |
| 671 | 691 | // mpya (rj), (ri), b |
| 672 | 692 | case 0x4b: |
| 673 | 693 | CHECK_B_CLEAR(); |
| 674 | | update_P(ssp1601_state); |
| 694 | update_P(); |
| 675 | 695 | rA32 += rP.d; |
| 676 | 696 | UPD_ACC_ZN |
| 677 | | rX = ptr1_read_(ssp1601_state, op&3, 0, (op<<1)&0x18); |
| 678 | | rY = ptr1_read_(ssp1601_state, (op>>4)&3, 4, (op>>3)&0x18); |
| 697 | rX = ptr1_read_(op&3, 0, (op<<1)&0x18); |
| 698 | rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); |
| 679 | 699 | break; |
| 680 | 700 | |
| 681 | 701 | // mld (rj), (ri), b |
| r26786 | r26787 | |
| 684 | 704 | rA32 = 0; |
| 685 | 705 | rST &= 0x0fff; |
| 686 | 706 | rST |= SSP_FLAG_Z; |
| 687 | | rX = ptr1_read_(ssp1601_state, op&3, 0, (op<<1)&0x18); |
| 688 | | rY = ptr1_read_(ssp1601_state, (op>>4)&3, 4, (op>>3)&0x18); |
| 707 | rX = ptr1_read_(op&3, 0, (op<<1)&0x18); |
| 708 | rY = ptr1_read_((op>>4)&3, 4, (op>>3)&0x18); |
| 689 | 709 | break; |
| 690 | 710 | |
| 691 | 711 | // OP a, s |
| 692 | | case 0x10: CHECK_1f0(); OP_CHECK32(OP_SUBA32); tmpv = REG_READ(ssp1601_state,op & 0x0f); OP_SUBA(tmpv); break; |
| 693 | | case 0x30: CHECK_1f0(); OP_CHECK32(OP_CMPA32); tmpv = REG_READ(ssp1601_state,op & 0x0f); OP_CMPA(tmpv); break; |
| 694 | | case 0x40: CHECK_1f0(); OP_CHECK32(OP_ADDA32); tmpv = REG_READ(ssp1601_state,op & 0x0f); OP_ADDA(tmpv); break; |
| 695 | | case 0x50: CHECK_1f0(); OP_CHECK32(OP_ANDA32); tmpv = REG_READ(ssp1601_state,op & 0x0f); OP_ANDA(tmpv); break; |
| 696 | | case 0x60: CHECK_1f0(); OP_CHECK32(OP_ORA32 ); tmpv = REG_READ(ssp1601_state,op & 0x0f); OP_ORA (tmpv); break; |
| 697 | | case 0x70: CHECK_1f0(); OP_CHECK32(OP_EORA32); tmpv = REG_READ(ssp1601_state,op & 0x0f); OP_EORA(tmpv); break; |
| 712 | case 0x10: CHECK_1f0(); OP_CHECK32(OP_SUBA32); tmpv = REG_READ(op & 0x0f); OP_SUBA(tmpv); break; |
| 713 | case 0x30: CHECK_1f0(); OP_CHECK32(OP_CMPA32); tmpv = REG_READ(op & 0x0f); OP_CMPA(tmpv); break; |
| 714 | case 0x40: CHECK_1f0(); OP_CHECK32(OP_ADDA32); tmpv = REG_READ(op & 0x0f); OP_ADDA(tmpv); break; |
| 715 | case 0x50: CHECK_1f0(); OP_CHECK32(OP_ANDA32); tmpv = REG_READ(op & 0x0f); OP_ANDA(tmpv); break; |
| 716 | case 0x60: CHECK_1f0(); OP_CHECK32(OP_ORA32 ); tmpv = REG_READ(op & 0x0f); OP_ORA (tmpv); break; |
| 717 | case 0x70: CHECK_1f0(); OP_CHECK32(OP_EORA32); tmpv = REG_READ(op & 0x0f); OP_EORA(tmpv); break; |
| 698 | 718 | |
| 699 | 719 | // OP a, (ri) |
| 700 | | case 0x11: CHECK_0f0(); tmpv = ptr1_read(ssp1601_state, op); OP_SUBA(tmpv); break; |
| 701 | | case 0x31: CHECK_0f0(); tmpv = ptr1_read(ssp1601_state, op); OP_CMPA(tmpv); break; |
| 702 | | case 0x41: CHECK_0f0(); tmpv = ptr1_read(ssp1601_state, op); OP_ADDA(tmpv); break; |
| 703 | | case 0x51: CHECK_0f0(); tmpv = ptr1_read(ssp1601_state, op); OP_ANDA(tmpv); break; |
| 704 | | case 0x61: CHECK_0f0(); tmpv = ptr1_read(ssp1601_state, op); OP_ORA (tmpv); break; |
| 705 | | case 0x71: CHECK_0f0(); tmpv = ptr1_read(ssp1601_state, op); OP_EORA(tmpv); break; |
| 720 | case 0x11: CHECK_0f0(); tmpv = ptr1_read(op); OP_SUBA(tmpv); break; |
| 721 | case 0x31: CHECK_0f0(); tmpv = ptr1_read(op); OP_CMPA(tmpv); break; |
| 722 | case 0x41: CHECK_0f0(); tmpv = ptr1_read(op); OP_ADDA(tmpv); break; |
| 723 | case 0x51: CHECK_0f0(); tmpv = ptr1_read(op); OP_ANDA(tmpv); break; |
| 724 | case 0x61: CHECK_0f0(); tmpv = ptr1_read(op); OP_ORA (tmpv); break; |
| 725 | case 0x71: CHECK_0f0(); tmpv = ptr1_read(op); OP_EORA(tmpv); break; |
| 706 | 726 | |
| 707 | 727 | // OP a, adr |
| 708 | | case 0x03: tmpv = ssp1601_state->RAM[op & 0x1ff]; OP_LDA (tmpv); break; |
| 709 | | case 0x13: tmpv = ssp1601_state->RAM[op & 0x1ff]; OP_SUBA(tmpv); break; |
| 710 | | case 0x33: tmpv = ssp1601_state->RAM[op & 0x1ff]; OP_CMPA(tmpv); break; |
| 711 | | case 0x43: tmpv = ssp1601_state->RAM[op & 0x1ff]; OP_ADDA(tmpv); break; |
| 712 | | case 0x53: tmpv = ssp1601_state->RAM[op & 0x1ff]; OP_ANDA(tmpv); break; |
| 713 | | case 0x63: tmpv = ssp1601_state->RAM[op & 0x1ff]; OP_ORA (tmpv); break; |
| 714 | | case 0x73: tmpv = ssp1601_state->RAM[op & 0x1ff]; OP_EORA(tmpv); break; |
| 728 | case 0x03: tmpv = m_RAM[op & 0x1ff]; OP_LDA (tmpv); break; |
| 729 | case 0x13: tmpv = m_RAM[op & 0x1ff]; OP_SUBA(tmpv); break; |
| 730 | case 0x33: tmpv = m_RAM[op & 0x1ff]; OP_CMPA(tmpv); break; |
| 731 | case 0x43: tmpv = m_RAM[op & 0x1ff]; OP_ADDA(tmpv); break; |
| 732 | case 0x53: tmpv = m_RAM[op & 0x1ff]; OP_ANDA(tmpv); break; |
| 733 | case 0x63: tmpv = m_RAM[op & 0x1ff]; OP_ORA (tmpv); break; |
| 734 | case 0x73: tmpv = m_RAM[op & 0x1ff]; OP_EORA(tmpv); break; |
| 715 | 735 | |
| 716 | 736 | // OP a, imm |
| 717 | | case 0x14: CHECK_IMM16(); tmpv = FETCH(); OP_SUBA(tmpv); ssp1601_state->g_cycles--; break; |
| 718 | | case 0x34: CHECK_IMM16(); tmpv = FETCH(); OP_CMPA(tmpv); ssp1601_state->g_cycles--; break; |
| 719 | | case 0x44: CHECK_IMM16(); tmpv = FETCH(); OP_ADDA(tmpv); ssp1601_state->g_cycles--; break; |
| 720 | | case 0x54: CHECK_IMM16(); tmpv = FETCH(); OP_ANDA(tmpv); ssp1601_state->g_cycles--; break; |
| 721 | | case 0x64: CHECK_IMM16(); tmpv = FETCH(); OP_ORA (tmpv); ssp1601_state->g_cycles--; break; |
| 722 | | case 0x74: CHECK_IMM16(); tmpv = FETCH(); OP_EORA(tmpv); ssp1601_state->g_cycles--; break; |
| 737 | case 0x14: CHECK_IMM16(); tmpv = FETCH(); OP_SUBA(tmpv); m_g_cycles--; break; |
| 738 | case 0x34: CHECK_IMM16(); tmpv = FETCH(); OP_CMPA(tmpv); m_g_cycles--; break; |
| 739 | case 0x44: CHECK_IMM16(); tmpv = FETCH(); OP_ADDA(tmpv); m_g_cycles--; break; |
| 740 | case 0x54: CHECK_IMM16(); tmpv = FETCH(); OP_ANDA(tmpv); m_g_cycles--; break; |
| 741 | case 0x64: CHECK_IMM16(); tmpv = FETCH(); OP_ORA (tmpv); m_g_cycles--; break; |
| 742 | case 0x74: CHECK_IMM16(); tmpv = FETCH(); OP_EORA(tmpv); m_g_cycles--; break; |
| 723 | 743 | |
| 724 | 744 | // OP a, ((ri)) |
| 725 | | case 0x15: CHECK_MOD(); tmpv = ptr2_read(ssp1601_state, op); OP_SUBA(tmpv); ssp1601_state->g_cycles -= 2; break; |
| 726 | | case 0x35: CHECK_MOD(); tmpv = ptr2_read(ssp1601_state, op); OP_CMPA(tmpv); ssp1601_state->g_cycles -= 2; break; |
| 727 | | case 0x45: CHECK_MOD(); tmpv = ptr2_read(ssp1601_state, op); OP_ADDA(tmpv); ssp1601_state->g_cycles -= 2; break; |
| 728 | | case 0x55: CHECK_MOD(); tmpv = ptr2_read(ssp1601_state, op); OP_ANDA(tmpv); ssp1601_state->g_cycles -= 2; break; |
| 729 | | case 0x65: CHECK_MOD(); tmpv = ptr2_read(ssp1601_state, op); OP_ORA (tmpv); ssp1601_state->g_cycles -= 2; break; |
| 730 | | case 0x75: CHECK_MOD(); tmpv = ptr2_read(ssp1601_state, op); OP_EORA(tmpv); ssp1601_state->g_cycles -= 2; break; |
| 745 | case 0x15: CHECK_MOD(); tmpv = ptr2_read(op); OP_SUBA(tmpv); m_g_cycles -= 2; break; |
| 746 | case 0x35: CHECK_MOD(); tmpv = ptr2_read(op); OP_CMPA(tmpv); m_g_cycles -= 2; break; |
| 747 | case 0x45: CHECK_MOD(); tmpv = ptr2_read(op); OP_ADDA(tmpv); m_g_cycles -= 2; break; |
| 748 | case 0x55: CHECK_MOD(); tmpv = ptr2_read(op); OP_ANDA(tmpv); m_g_cycles -= 2; break; |
| 749 | case 0x65: CHECK_MOD(); tmpv = ptr2_read(op); OP_ORA (tmpv); m_g_cycles -= 2; break; |
| 750 | case 0x75: CHECK_MOD(); tmpv = ptr2_read(op); OP_EORA(tmpv); m_g_cycles -= 2; break; |
| 731 | 751 | |
| 732 | 752 | // OP a, ri |
| 733 | 753 | case 0x19: CHECK_MOD(); tmpv = rIJ[IJind]; OP_SUBA(tmpv); break; |
| r26786 | r26787 | |
| 749 | 769 | logerror(__FILE__ " FIXME unhandled op %04x @ %04x\n", op, GET_PPC_OFFS()); |
| 750 | 770 | break; |
| 751 | 771 | } |
| 752 | | ssp1601_state->g_cycles--; |
| 772 | m_g_cycles--; |
| 753 | 773 | } |
| 754 | 774 | |
| 755 | | update_P(ssp1601_state); |
| 775 | update_P(); |
| 756 | 776 | } |
| 757 | 777 | |
| 758 | 778 | |
| 759 | | /************************************************************************** |
| 760 | | * MAME interface |
| 761 | | **************************************************************************/ |
| 762 | | |
| 763 | | static CPU_SET_INFO( ssp1601 ) |
| 779 | void ssp1601_device::execute_set_input( int inputnum, int state ) |
| 764 | 780 | { |
| 765 | | ssp1601_state_t *ssp1601_state = get_safe_token(device); |
| 766 | | |
| 767 | | switch (state) |
| 768 | | { |
| 769 | | /* --- the following bits of info are set as 64-bit signed integers --- */ |
| 770 | | |
| 771 | | case CPUINFO_INT_REGISTER + SSP_X: rX = info->i; break; |
| 772 | | case CPUINFO_INT_REGISTER + SSP_Y: rY = info->i; break; |
| 773 | | case CPUINFO_INT_REGISTER + SSP_A: rA32 = info->i; break; |
| 774 | | case CPUINFO_INT_REGISTER + SSP_ST: rST = info->i; break; |
| 775 | | case CPUINFO_INT_REGISTER + SSP_STACK: rSTACK = info->i; break; |
| 776 | | case CPUINFO_INT_PC: |
| 777 | | case CPUINFO_INT_REGISTER + SSP_PC: rPC = info->i; break; |
| 778 | | case CPUINFO_INT_REGISTER + SSP_P: rP.d = info->i; break; |
| 779 | | case CPUINFO_INT_REGISTER + SSP_STACK0: ssp1601_state->stack[0] = info->i; break; |
| 780 | | case CPUINFO_INT_REGISTER + SSP_STACK1: ssp1601_state->stack[1] = info->i; break; |
| 781 | | case CPUINFO_INT_REGISTER + SSP_STACK2: ssp1601_state->stack[2] = info->i; break; |
| 782 | | case CPUINFO_INT_REGISTER + SSP_STACK3: ssp1601_state->stack[3] = info->i; break; |
| 783 | | case CPUINFO_INT_REGISTER + SSP_STACK4: ssp1601_state->stack[4] = info->i; break; |
| 784 | | case CPUINFO_INT_REGISTER + SSP_STACK5: ssp1601_state->stack[5] = info->i; break; |
| 785 | | case CPUINFO_INT_REGISTER + SSP_PR0: ssp1601_state->r[0] = info->i; break; |
| 786 | | case CPUINFO_INT_REGISTER + SSP_PR1: ssp1601_state->r[1] = info->i; break; |
| 787 | | case CPUINFO_INT_REGISTER + SSP_PR2: ssp1601_state->r[2] = info->i; break; |
| 788 | | case CPUINFO_INT_REGISTER + SSP_PR3: ssp1601_state->r[3] = info->i; break; |
| 789 | | case CPUINFO_INT_REGISTER + SSP_PR4: ssp1601_state->r[4] = info->i; break; |
| 790 | | case CPUINFO_INT_REGISTER + SSP_PR5: ssp1601_state->r[5] = info->i; break; |
| 791 | | case CPUINFO_INT_REGISTER + SSP_PR6: ssp1601_state->r[6] = info->i; break; |
| 792 | | case CPUINFO_INT_REGISTER + SSP_PR7: ssp1601_state->r[7] = info->i; break; |
| 793 | | |
| 794 | | // case CPUINFO_INT_INPUT_STATE + 0: set_irq_line(0, info->i); break; |
| 795 | | // case CPUINFO_INT_INPUT_STATE + 1: set_irq_line(1, info->i); break; |
| 796 | | // case CPUINFO_INT_INPUT_STATE + 2: set_irq_line(2, info->i); break; |
| 797 | | } |
| 781 | fatalerror("ssp1610: execute_set_input not implemented yet!\n"); |
| 798 | 782 | } |
| 799 | 783 | |
| 800 | | /************************************************************************** |
| 801 | | * Generic get_info |
| 802 | | **************************************************************************/ |
| 803 | | |
| 804 | | CPU_GET_INFO( ssp1601 ) |
| 805 | | { |
| 806 | | ssp1601_state_t *ssp1601_state = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL; |
| 807 | | |
| 808 | | switch (state) |
| 809 | | { |
| 810 | | /* --- the following bits of info are returned as 64-bit signed integers --- */ |
| 811 | | case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(ssp1601_state_t); break; |
| 812 | | case CPUINFO_INT_INPUT_LINES: info->i = 3; break; |
| 813 | | case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break; |
| 814 | | case CPUINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break; |
| 815 | | case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break; |
| 816 | | case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break; |
| 817 | | case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 2; break; |
| 818 | | case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break; |
| 819 | | case CPUINFO_INT_MIN_CYCLES: info->i = 1; break; |
| 820 | | case CPUINFO_INT_MAX_CYCLES: info->i = 4; break; |
| 821 | | |
| 822 | | case CPUINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 16; break; |
| 823 | | case CPUINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 16; break; |
| 824 | | case CPUINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = -1; break; |
| 825 | | case CPUINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 0; break; |
| 826 | | case CPUINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 0; break; |
| 827 | | case CPUINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break; |
| 828 | | case CPUINFO_INT_DATABUS_WIDTH + AS_IO: info->i = 16; break; |
| 829 | | case CPUINFO_INT_ADDRBUS_WIDTH + AS_IO: info->i = 4; break; |
| 830 | | case CPUINFO_INT_ADDRBUS_SHIFT + AS_IO: info->i = 0; break; |
| 831 | | |
| 832 | | case CPUINFO_INT_INPUT_STATE + 0: /* not implemented */ break; |
| 833 | | |
| 834 | | case CPUINFO_INT_PREVIOUSPC: info->i = PPC; break; |
| 835 | | |
| 836 | | case CPUINFO_INT_REGISTER + SSP_R0: info->i = ssp1601_state->gr[0].w.h; break; |
| 837 | | case CPUINFO_INT_REGISTER + SSP_X: info->i = rX; break; |
| 838 | | case CPUINFO_INT_REGISTER + SSP_Y: info->i = rY; break; |
| 839 | | case CPUINFO_INT_REGISTER + SSP_A: info->i = rA32; break; |
| 840 | | case CPUINFO_INT_REGISTER + SSP_ST: info->i = rST; break; |
| 841 | | case CPUINFO_INT_REGISTER + SSP_STACK: info->i = rSTACK; break; |
| 842 | | case CPUINFO_INT_PC: |
| 843 | | case CPUINFO_INT_REGISTER + SSP_PC: info->i = rPC; break; |
| 844 | | case CPUINFO_INT_REGISTER + SSP_P: info->i = rP.d; break; |
| 845 | | case CPUINFO_INT_REGISTER + SSP_STACK0: info->i = ssp1601_state->stack[0]; break; |
| 846 | | case CPUINFO_INT_REGISTER + SSP_STACK1: info->i = ssp1601_state->stack[1]; break; |
| 847 | | case CPUINFO_INT_REGISTER + SSP_STACK2: info->i = ssp1601_state->stack[2]; break; |
| 848 | | case CPUINFO_INT_REGISTER + SSP_STACK3: info->i = ssp1601_state->stack[3]; break; |
| 849 | | case CPUINFO_INT_REGISTER + SSP_STACK4: info->i = ssp1601_state->stack[4]; break; |
| 850 | | case CPUINFO_INT_REGISTER + SSP_STACK5: info->i = ssp1601_state->stack[5]; break; |
| 851 | | case CPUINFO_INT_REGISTER + SSP_PR0: info->i = ssp1601_state->r[0]; break; |
| 852 | | case CPUINFO_INT_REGISTER + SSP_PR1: info->i = ssp1601_state->r[1]; break; |
| 853 | | case CPUINFO_INT_REGISTER + SSP_PR2: info->i = ssp1601_state->r[2]; break; |
| 854 | | case CPUINFO_INT_REGISTER + SSP_PR3: info->i = ssp1601_state->r[3]; break; |
| 855 | | case CPUINFO_INT_REGISTER + SSP_PR4: info->i = ssp1601_state->r[4]; break; |
| 856 | | case CPUINFO_INT_REGISTER + SSP_PR5: info->i = ssp1601_state->r[5]; break; |
| 857 | | case CPUINFO_INT_REGISTER + SSP_PR6: info->i = ssp1601_state->r[6]; break; |
| 858 | | case CPUINFO_INT_REGISTER + SSP_PR7: info->i = ssp1601_state->r[7]; break; |
| 859 | | |
| 860 | | /* --- the following bits of info are returned as pointers to data or functions --- */ |
| 861 | | case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME(ssp1601); break; |
| 862 | | case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME(ssp1601); break; |
| 863 | | case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME(ssp1601); break; |
| 864 | | case CPUINFO_FCT_EXIT: info->exit = CPU_EXIT_NAME(ssp1601); break; |
| 865 | | case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME(ssp1601); break; |
| 866 | | case CPUINFO_FCT_BURN: info->burn = NULL; break; |
| 867 | | case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME(ssp1601); break; |
| 868 | | case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &ssp1601_state->g_cycles; break; |
| 869 | | |
| 870 | | case CPUINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map16 = NULL; break; |
| 871 | | case CPUINFO_PTR_INTERNAL_MEMORY_MAP + AS_IO: info->internal_map16 = NULL; break; |
| 872 | | |
| 873 | | /* --- the following bits of info are returned as NULL-terminated strings --- */ |
| 874 | | case CPUINFO_STR_NAME: strcpy(info->s, "SSP1601"); break; |
| 875 | | case CPUINFO_STR_SHORTNAME: strcpy(info->s, "ssp1601"); break; |
| 876 | | case CPUINFO_STR_FAMILY: strcpy(info->s, "SSP1601 DSP"); break; |
| 877 | | case CPUINFO_STR_VERSION: strcpy(info->s, "1.0"); break; |
| 878 | | case CPUINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break; |
| 879 | | case CPUINFO_STR_CREDITS: strcpy(info->s, "Copyright Grazvydas Ignotas"); break; |
| 880 | | |
| 881 | | case CPUINFO_STR_FLAGS: |
| 882 | | sprintf(info->s, "%c%c%c%c", (rST&SSP_FLAG_N)?'N':'.', (rST&SSP_FLAG_V)?'V':'.', |
| 883 | | (rST&SSP_FLAG_Z)?'Z':'.', (rST&SSP_FLAG_L)?'L':'.'); |
| 884 | | break; |
| 885 | | |
| 886 | | case CPUINFO_STR_REGISTER + SSP_R0: sprintf(info->s, "REG0 :%04X", ssp1601_state->gr[0].w.h); break; |
| 887 | | case CPUINFO_STR_REGISTER + SSP_X: sprintf(info->s, "X :%04X", rX); break; |
| 888 | | case CPUINFO_STR_REGISTER + SSP_Y: sprintf(info->s, "Y :%04X", rY); break; |
| 889 | | case CPUINFO_STR_REGISTER + SSP_A: sprintf(info->s, "A :%08X", rA32); break; |
| 890 | | case CPUINFO_STR_REGISTER + SSP_ST: sprintf(info->s, "ST :%04X", rST); break; |
| 891 | | case CPUINFO_STR_REGISTER + SSP_STACK: sprintf(info->s, "STACK :%04X", rSTACK); break; |
| 892 | | case CPUINFO_STR_REGISTER + SSP_PC: sprintf(info->s, "PC :%04X", rPC); break; |
| 893 | | case CPUINFO_STR_REGISTER + SSP_P: sprintf(info->s, "P :%08X", rP.d); break; |
| 894 | | case CPUINFO_STR_REGISTER + SSP_STACK0: sprintf(info->s, "STACK0 :%04X", ssp1601_state->stack[0]); break; |
| 895 | | case CPUINFO_STR_REGISTER + SSP_STACK1: sprintf(info->s, "STACK1 :%04X", ssp1601_state->stack[1]); break; |
| 896 | | case CPUINFO_STR_REGISTER + SSP_STACK2: sprintf(info->s, "STACK2 :%04X", ssp1601_state->stack[2]); break; |
| 897 | | case CPUINFO_STR_REGISTER + SSP_STACK3: sprintf(info->s, "STACK3 :%04X", ssp1601_state->stack[3]); break; |
| 898 | | case CPUINFO_STR_REGISTER + SSP_STACK4: sprintf(info->s, "STACK4 :%04X", ssp1601_state->stack[4]); break; |
| 899 | | case CPUINFO_STR_REGISTER + SSP_STACK5: sprintf(info->s, "STACK5 :%04X", ssp1601_state->stack[5]); break; |
| 900 | | case CPUINFO_STR_REGISTER + SSP_PR0: sprintf(info->s, "R0 :%02X", ssp1601_state->r[0]); break; |
| 901 | | case CPUINFO_STR_REGISTER + SSP_PR1: sprintf(info->s, "R1 :%02X", ssp1601_state->r[1]); break; |
| 902 | | case CPUINFO_STR_REGISTER + SSP_PR2: sprintf(info->s, "R2 :%02X", ssp1601_state->r[2]); break; |
| 903 | | case CPUINFO_STR_REGISTER + SSP_PR3: sprintf(info->s, "R3 :%02X", ssp1601_state->r[3]); break; |
| 904 | | case CPUINFO_STR_REGISTER + SSP_PR4: sprintf(info->s, "R4 :%02X", ssp1601_state->r[4]); break; |
| 905 | | case CPUINFO_STR_REGISTER + SSP_PR5: sprintf(info->s, "R5 :%02X", ssp1601_state->r[5]); break; |
| 906 | | case CPUINFO_STR_REGISTER + SSP_PR6: sprintf(info->s, "R6 :%02X", ssp1601_state->r[6]); break; |
| 907 | | case CPUINFO_STR_REGISTER + SSP_PR7: sprintf(info->s, "R7 :%02X", ssp1601_state->r[7]); break; |
| 908 | | } |
| 909 | | } |
| 910 | | |
| 911 | | // vim:ts=4 |
| 912 | | |
| 913 | | |
| 914 | | DEFINE_LEGACY_CPU_DEVICE(SSP1601, ssp1601); |