trunk/src/emu/cpu/dsp16/dsp16.c
| r20065 | r20066 | |
| 26 | 26 | dsp16_device::dsp16_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 27 | 27 | : cpu_device(mconfig, DSP16, "DSP16", tag, owner, clock), |
| 28 | 28 | m_program_config("program", ENDIANNESS_LITTLE, 16, 16, -1), |
| 29 | | m_pc(0), |
| 30 | | m_ppc(0), |
| 31 | | m_icount(0) |
| 29 | m_i(0), |
| 30 | m_pc(0), |
| 31 | m_pt(0), |
| 32 | m_pr(0), |
| 33 | m_pi(0), |
| 34 | m_j(0), |
| 35 | m_k(0), |
| 36 | m_rb(0), |
| 37 | m_re(0), |
| 38 | m_r0(0), |
| 39 | m_r1(0), |
| 40 | m_r2(0), |
| 41 | m_r3(0), |
| 42 | m_x(0), |
| 43 | m_y(0), |
| 44 | m_p(0), |
| 45 | m_a0(0), |
| 46 | m_a1(0), |
| 47 | m_auc(0), |
| 48 | m_psw(0), |
| 49 | m_c0(0), |
| 50 | m_c1(0), |
| 51 | m_c2(0), |
| 52 | m_sioc(0), |
| 53 | m_pioc(0), |
| 54 | m_ppc(0), |
| 55 | m_program(NULL), |
| 56 | m_direct(NULL), |
| 57 | m_icount(0) |
| 32 | 58 | { |
| 33 | 59 | // Allocate & setup |
| 34 | 60 | } |
| r20065 | r20066 | |
| 41 | 67 | |
| 42 | 68 | void dsp16_device::device_start() |
| 43 | 69 | { |
| 70 | // register state with the debugger |
| 71 | state_add(STATE_GENPC, "GENPC", m_pc).noshow(); |
| 72 | state_add(STATE_GENFLAGS, "GENFLAGS", m_psw).callimport().callexport().formatstr("%10s").noshow(); |
| 73 | state_add(DSP16_PC, "PC", m_pc); |
| 74 | state_add(DSP16_I, "I", m_i); |
| 75 | state_add(DSP16_PT, "PT", m_pt); |
| 76 | state_add(DSP16_PR, "PR", m_pr); |
| 77 | state_add(DSP16_PI, "PI", m_pi); |
| 78 | state_add(DSP16_J, "J", m_j); |
| 79 | state_add(DSP16_K, "K", m_k); |
| 80 | state_add(DSP16_RB, "RB", m_rb); |
| 81 | state_add(DSP16_RE, "RE", m_re); |
| 82 | state_add(DSP16_R0, "R0", m_r0); |
| 83 | state_add(DSP16_R1, "R1", m_r1); |
| 84 | state_add(DSP16_R2, "R2", m_r2); |
| 85 | state_add(DSP16_R3, "R3", m_r3); |
| 86 | state_add(DSP16_X, "X", m_x); |
| 87 | state_add(DSP16_Y, "Y", m_y); |
| 88 | state_add(DSP16_P, "P", m_p); |
| 89 | state_add(DSP16_A0, "A0", m_a0).mask(0xfffffffff); |
| 90 | state_add(DSP16_A1, "A1", m_a1).mask(0xfffffffff); |
| 91 | state_add(DSP16_AUC, "AUC", m_auc); //.formatstr("%6s"); |
| 92 | state_add(DSP16_PSW, "PSW", m_psw); //.formatstr("%16s"); |
| 93 | state_add(DSP16_C0, "C0", m_c0); |
| 94 | state_add(DSP16_C1, "C1", m_c1); |
| 95 | state_add(DSP16_C2, "C2", m_c2); |
| 96 | state_add(DSP16_SIOC, "SIOC", m_sioc).formatstr("%16s"); |
| 97 | state_add(DSP16_PIOC, "PIOC", m_pioc); //.formatstr("%16s"); |
| 98 | |
| 99 | save_item(NAME(m_i)); |
| 100 | save_item(NAME(m_pc)); |
| 101 | save_item(NAME(m_pt)); |
| 102 | save_item(NAME(m_pr)); |
| 103 | save_item(NAME(m_pi)); |
| 104 | save_item(NAME(m_j)); |
| 105 | save_item(NAME(m_k)); |
| 106 | save_item(NAME(m_rb)); |
| 107 | save_item(NAME(m_re)); |
| 108 | save_item(NAME(m_r0)); |
| 109 | save_item(NAME(m_r1)); |
| 110 | save_item(NAME(m_r2)); |
| 111 | save_item(NAME(m_r3)); |
| 112 | save_item(NAME(m_x)); |
| 113 | save_item(NAME(m_y)); |
| 114 | save_item(NAME(m_p)); |
| 115 | save_item(NAME(m_a0)); |
| 116 | save_item(NAME(m_a1)); |
| 117 | save_item(NAME(m_auc)); |
| 118 | save_item(NAME(m_psw)); |
| 119 | save_item(NAME(m_c0)); |
| 120 | save_item(NAME(m_c1)); |
| 121 | save_item(NAME(m_c2)); |
| 122 | save_item(NAME(m_sioc)); |
| 123 | save_item(NAME(m_pioc)); |
| 124 | |
| 44 | 125 | // get our address spaces |
| 45 | 126 | m_program = &space(AS_PROGRAM); |
| 46 | 127 | m_direct = &m_program->direct(); |
| 47 | 128 | |
| 48 | | save_item(NAME(m_pc)); |
| 49 | | |
| 50 | | // register state with the debugger |
| 51 | | state_add(DSP16_PC, "PC", m_pc); |
| 52 | | |
| 53 | 129 | // set our instruction counter |
| 54 | 130 | m_icountptr = &m_icount; |
| 55 | 131 | } |
| r20065 | r20066 | |
| 78 | 154 | |
| 79 | 155 | |
| 80 | 156 | //------------------------------------------------- |
| 81 | | // state_import - import state into the device, |
| 82 | | // after it has been set |
| 83 | | //------------------------------------------------- |
| 84 | | |
| 85 | | void dsp16_device::state_import(const device_state_entry &entry) |
| 86 | | { |
| 87 | | |
| 88 | | } |
| 89 | | |
| 90 | | |
| 91 | | //------------------------------------------------- |
| 92 | 157 | // state_string_export - export state as a string |
| 93 | 158 | // for the debugger |
| 94 | 159 | //------------------------------------------------- |
| 95 | 160 | |
| 96 | 161 | void dsp16_device::state_string_export(const device_state_entry &entry, astring &string) |
| 97 | 162 | { |
| 98 | | string.printf(""); |
| 163 | switch (entry.index()) |
| 164 | { |
| 165 | case STATE_GENFLAGS: |
| 166 | string.printf("(see below)"); |
| 167 | break; |
| 168 | |
| 169 | // Placeholder for a better view later (TODO) |
| 170 | case DSP16_SIOC: |
| 171 | string.printf("%04x", *(UINT16*)entry.dataptr()); |
| 172 | break; |
| 173 | } |
| 99 | 174 | } |
| 100 | 175 | |
| 101 | 176 | |
| r20065 | r20066 | |
| 128 | 203 | |
| 129 | 204 | offs_t dsp16_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options) |
| 130 | 205 | { |
| 131 | | extern CPU_DISASSEMBLE( dsp16 ); |
| 132 | | return CPU_DISASSEMBLE_NAME(dsp16)(NULL, buffer, pc, oprom, opram, 0); |
| 206 | extern CPU_DISASSEMBLE( dsp16a ); |
| 207 | return CPU_DISASSEMBLE_NAME(dsp16a)(NULL, buffer, pc, oprom, opram, 0); |
| 133 | 208 | } |
| 134 | 209 | |
| 135 | 210 | |
| r20065 | r20066 | |
| 148 | 223 | m_program->write_dword(addr << 1, data & 0xffff); |
| 149 | 224 | } |
| 150 | 225 | |
| 151 | | inline UINT32 dsp16_device::opcode_read() |
| 226 | inline UINT32 dsp16_device::opcode_read(const UINT8 pcOffset) |
| 152 | 227 | { |
| 153 | | return m_direct->read_decrypted_dword(m_pc << 1); |
| 228 | const UINT16 readPC = m_pc + pcOffset; |
| 229 | return m_direct->read_decrypted_dword(readPC << 1); |
| 154 | 230 | } |
| 155 | 231 | |
| 156 | 232 | |
| r20065 | r20066 | |
| 187 | 263 | |
| 188 | 264 | UINT32 dsp16_device::execute_input_lines() const |
| 189 | 265 | { |
| 190 | | return 1; // TODO |
| 266 | return 1; |
| 191 | 267 | } |
| 192 | 268 | |
| 193 | 269 | |
| 194 | 270 | void dsp16_device::execute_set_input(int inputnum, int state) |
| 195 | 271 | { |
| 272 | // Only has one external IRQ line |
| 196 | 273 | } |
| 197 | 274 | |
| 198 | 275 | |
| 199 | 276 | void dsp16_device::execute_run() |
| 200 | 277 | { |
| 201 | | bool check_debugger = ((device_t::machine().debug_flags & DEBUG_FLAG_ENABLED) != 0); |
| 202 | | |
| 203 | 278 | do |
| 204 | 279 | { |
| 205 | 280 | // debugging |
| 206 | 281 | m_ppc = m_pc; // copy PC to previous PC |
| 207 | | if (check_debugger) |
| 208 | | debugger_instruction_hook(this, m_pc); |
| 282 | debugger_instruction_hook(this, m_pc); |
| 209 | 283 | |
| 210 | | // instruction fetch |
| 211 | | //UINT16 op = opcode_read(); |
| 284 | // instruction fetch & execute |
| 285 | UINT8 cycles; |
| 286 | UINT8 pcAdvance; |
| 287 | const UINT16 op = opcode_read(); |
| 288 | execute_one(op, cycles, pcAdvance); |
| 212 | 289 | |
| 213 | | m_icount--; |
| 214 | | } while (m_icount > 0); |
| 290 | // step forward |
| 291 | m_pc += pcAdvance; |
| 292 | m_icount -= cycles; |
| 293 | |
| 294 | } while (m_icount > 0); |
| 215 | 295 | } |
| 296 | |
| 297 | |
| 298 | void dsp16_device::execute_one(const UINT16 op, UINT8& cycles, UINT8& pcAdvance) |
| 299 | { |
| 300 | cycles = 1; |
| 301 | pcAdvance = 1; |
| 302 | |
| 303 | const UINT8 opcode = (op >> 11) & 0x1f; |
| 304 | switch(opcode) |
| 305 | { |
| 306 | // Format 1: Multiply/ALU Read/Write Group |
| 307 | case 0x06: |
| 308 | { |
| 309 | // F1, Y |
| 310 | //const UINT8 Y = (op & 0x000f); |
| 311 | //const UINT8 S = (op & 0x0200) >> 9; |
| 312 | //const UINT8 D = (op & 0x0400) >> 10; |
| 313 | //const UINT8 F1 = (op & 0x01e0) >> 5; |
| 314 | break; |
| 315 | } |
| 316 | case 0x04: case 0x1c: |
| 317 | { |
| 318 | // F1 Y=a0[1] | F1 Y=a1[1] |
| 319 | //const UINT8 Y = (op & 0x000f); |
| 320 | //const UINT8 S = (op & 0x0200) >> 9; |
| 321 | //const UINT8 D = (op & 0x0400) >> 10; |
| 322 | //const UINT8 F1 = (op & 0x01e0) >> 5; |
| 323 | break; |
| 324 | } |
| 325 | case 0x16: |
| 326 | { |
| 327 | // F1, x = Y |
| 328 | //const UINT8 Y = (op & 0x000f); |
| 329 | //const UINT8 S = (op & 0x0200) >> 9; |
| 330 | //const UINT8 D = (op & 0x0400) >> 10; |
| 331 | //const UINT8 F1 = (op & 0x01e0) >> 5; |
| 332 | break; |
| 333 | } |
| 334 | case 0x17: |
| 335 | { |
| 336 | // F1, y[l] = Y |
| 337 | //const UINT8 Y = (op & 0x000f); |
| 338 | //const UINT8 X = (op & 0x0010) >> 4; |
| 339 | //const UINT8 S = (op & 0x0200) >> 9; |
| 340 | //const UINT8 D = (op & 0x0400) >> 10; |
| 341 | //const UINT8 F1 = (op & 0x01e0) >> 5; |
| 342 | break; |
| 343 | } |
| 344 | case 0x1f: |
| 345 | { |
| 346 | // F1, y = Y, x = *pt++[i] |
| 347 | //const UINT8 Y = (op & 0x000f); |
| 348 | //const UINT8 X = (op & 0x0010) >> 4; |
| 349 | //const UINT8 S = (op & 0x0200) >> 9; |
| 350 | //const UINT8 D = (op & 0x0400) >> 10; |
| 351 | //const UINT8 F1 = (op & 0x01e0) >> 5; |
| 352 | break; |
| 353 | } |
| 354 | case 0x19: case 0x1b: |
| 355 | { |
| 356 | // F1, y = a0|1, x = *pt++[i] |
| 357 | //const UINT8 Y = (op & 0x000f); |
| 358 | //const UINT8 X = (op & 0x0010) >> 4; |
| 359 | //const UINT8 S = (op & 0x0200) >> 9; |
| 360 | //const UINT8 D = (op & 0x0400) >> 10; |
| 361 | //const UINT8 F1 = (op & 0x01e0) >> 5; |
| 362 | break; |
| 363 | } |
| 364 | case 0x14: |
| 365 | { |
| 366 | // F1, Y = y[1] |
| 367 | //const UINT8 Y = (op & 0x000f); |
| 368 | //const UINT8 X = (op & 0x0010) >> 4; |
| 369 | //const UINT8 S = (op & 0x0200) >> 9; |
| 370 | //const UINT8 D = (op & 0x0400) >> 10; |
| 371 | //const UINT8 F1 = (op & 0x01e0) >> 5; |
| 372 | break; |
| 373 | } |
| 374 | |
| 375 | // Format 1a: Multiply/ALU Read/Write Group (major typo in docs on p3-51) |
| 376 | case 0x07: |
| 377 | { |
| 378 | // F1, At[1] = Y |
| 379 | //const UINT8 Y = (op & 0x000f); |
| 380 | //const UINT8 S = (op & 0x0200) >> 9; |
| 381 | //const UINT8 aT = (op & 0x0400) >> 10; |
| 382 | //const UINT8 F1 = (op & 0x01e0) >> 5; |
| 383 | break; |
| 384 | } |
| 385 | |
| 386 | // Format 2: Multiply/ALU Read/Write Group |
| 387 | case 0x15: |
| 388 | { |
| 389 | // F1, Z : y[1] |
| 390 | //const UINT8 Z = (op & 0x000f); |
| 391 | //const UINT8 X = (op & 0x0010) >> 4; |
| 392 | //const UINT8 S = (op & 0x0200) >> 9; |
| 393 | //const UINT8 D = (op & 0x0400) >> 10; |
| 394 | //const UINT8 F1 = (op & 0x01e0) >> 5; |
| 395 | break; |
| 396 | } |
| 397 | case 0x1d: |
| 398 | { |
| 399 | // F1, Z : y, x=*pt++[i] |
| 400 | //const UINT8 Z = (op & 0x000f); |
| 401 | //const UINT8 X = (op & 0x0010) >> 4; |
| 402 | //const UINT8 S = (op & 0x0200) >> 9; |
| 403 | //const UINT8 D = (op & 0x0400) >> 10; |
| 404 | //const UINT8 F1 = (op & 0x01e0) >> 5; |
| 405 | break; |
| 406 | } |
| 407 | |
| 408 | // Format 2a: Multiply/ALU Read/Write Group |
| 409 | case 0x05: |
| 410 | { |
| 411 | // F1, Z : aT[1] |
| 412 | //const UINT8 Z = (op & 0x000f); |
| 413 | //const UINT8 X = (op & 0x0010) >> 4; |
| 414 | //const UINT8 S = (op & 0x0200) >> 9; |
| 415 | //const UINT8 aT = (op & 0x0400) >> 10; |
| 416 | //const UINT8 F1 = (op & 0x01e0) >> 5; |
| 417 | break; |
| 418 | } |
| 419 | |
| 420 | // Format 3: Special Functions |
| 421 | case 0x12: |
| 422 | case 0x13: |
| 423 | { |
| 424 | // if|ifc CON F2 |
| 425 | //const UINT8 CON = (op & 0x001f); |
| 426 | //const UINT8 S = (op & 0x0200) >> 9; |
| 427 | //const UINT8 D = (op & 0x0400) >> 10; |
| 428 | //const UINT8 F2 = (op & 0x01e0) >> 5; |
| 429 | break; |
| 430 | } |
| 431 | |
| 432 | // Format 4: Branch Direct Group |
| 433 | case 0x00: case 0x01: |
| 434 | { |
| 435 | // goto JA |
| 436 | const UINT16 JA = (op & 0x0fff) | (m_pc & 0xf000); |
| 437 | m_pc = JA; |
| 438 | pcAdvance = 0; |
| 439 | break; |
| 440 | } |
| 441 | |
| 442 | case 0x10: case 0x11: |
| 443 | { |
| 444 | // call JA |
| 445 | //const UINT16 JA = (op & 0x0fff) | (m_pc & 0xf000); |
| 446 | break; |
| 447 | } |
| 448 | |
| 449 | // Format 5: Branch Indirect Group |
| 450 | case 0x18: |
| 451 | { |
| 452 | // goto B |
| 453 | //const UINT8 B = (op & 0x0700) >> 8; |
| 454 | break; |
| 455 | } |
| 456 | |
| 457 | // Format 6: Contitional Branch Qualifier/Software Interrupt (icall) |
| 458 | case 0x1a: |
| 459 | { |
| 460 | // if CON [goto/call/return] |
| 461 | //const UINT8 CON = (op & 0x001f); |
| 462 | break; |
| 463 | } |
| 464 | |
| 465 | // Format 7: Data Move Group |
| 466 | case 0x09: case 0x0b: |
| 467 | { |
| 468 | // R = aS |
| 469 | //const UINT8 R = (op & 0x03f0) >> 4; |
| 470 | //const UINT8 S = (op & 0x1000) >> 12; |
| 471 | break; |
| 472 | } |
| 473 | case 0x08: |
| 474 | { |
| 475 | // aT = R |
| 476 | //const UINT8 R = (op & 0x03f0) >> 4; |
| 477 | //const UINT8 aT = (op & 0x0400) >> 10; |
| 478 | break; |
| 479 | } |
| 480 | case 0x0f: |
| 481 | { |
| 482 | // R = Y |
| 483 | //const UINT8 Y = (op & 0x000f); |
| 484 | //const UINT8 R = (op & 0x03f0) >> 4; |
| 485 | break; |
| 486 | } |
| 487 | case 0x0c: |
| 488 | { |
| 489 | // Y = R |
| 490 | //const UINT8 Y = (op & 0x000f); |
| 491 | //const UINT8 R = (op & 0x03f0) >> 4; |
| 492 | break; |
| 493 | } |
| 494 | case 0x0d: |
| 495 | { |
| 496 | // Z : R |
| 497 | //const UINT8 Z = (op & 0x000f); |
| 498 | //const UINT8 R = (op & 0x03f0) >> 4; |
| 499 | break; |
| 500 | } |
| 501 | |
| 502 | // Format 8: Data Move (immediate operand - 2 words) |
| 503 | case 0x0a: |
| 504 | { |
| 505 | // R = N |
| 506 | //const UINT8 R = (op & 0x03f0) >> 4; |
| 507 | pcAdvance++; |
| 508 | break; |
| 509 | } |
| 510 | |
| 511 | // Format 9: Short Immediate Group |
| 512 | case 0x02: case 0x03: |
| 513 | { |
| 514 | // R = M |
| 515 | //const UINT8 M = (op & 0x00ff); |
| 516 | //const UINT8 R = (op & 0x0e00) >> 9; |
| 517 | break; |
| 518 | } |
| 519 | |
| 520 | // Format 10: do - redo |
| 521 | case 0x0e: |
| 522 | { |
| 523 | // do|redo K |
| 524 | //const UINT8 K = (op & 0x007f); |
| 525 | //const UINT8 NI = (op & 0x0780) >> 7; |
| 526 | break; |
| 527 | } |
| 528 | |
| 529 | // RESERVED |
| 530 | case 0x1e: |
| 531 | { |
| 532 | break; |
| 533 | } |
| 534 | |
| 535 | // UNKNOWN |
| 536 | default: |
| 537 | { |
| 538 | break; |
| 539 | } |
| 540 | } |
| 541 | } |