trunk/src/emu/cpu/es5510/es5510.c
r24765 | r24766 | |
14 | 14 | #define VERBOSE 0 |
15 | 15 | |
16 | 16 | #if VERBOSE |
17 | | #define LOG(x) do { logerror x; } while(0) |
| 17 | void log_to_stderr(const char *format, ...) { |
| 18 | va_list ap; |
| 19 | va_start(ap, format); |
| 20 | vfprintf(stderr, format, ap); |
| 21 | va_end(ap); |
| 22 | } |
| 23 | |
| 24 | #define LOG(x) do { log_to_stderr x; } while(0) |
18 | 25 | #else |
19 | 26 | #define LOG(x) |
20 | 27 | #endif |
21 | 28 | |
| 29 | #define VERBOSE_EXEC 0 |
| 30 | |
| 31 | #if VERBOSE_EXEC |
| 32 | static int exec_cc = 0; |
| 33 | #define LOG_EXEC(x) do { if (!exec_cc) LOG(x); } while(0) |
| 34 | #else |
| 35 | #define LOG_EXEC(x) |
| 36 | #endif |
| 37 | |
22 | 38 | const device_type ES5510 = &device_creator<es5510_device>; |
23 | 39 | |
24 | 40 | #define FLAG_N (1 << 7) |
r24765 | r24766 | |
54 | 70 | |
55 | 71 | inline static INT32 add(INT32 a, INT32 b, UINT8 &flags) { |
56 | 72 | INT32 aSign = a & 0x00800000; |
57 | | INT32 bSign = (b & 0x00800000) == 0; |
| 73 | INT32 bSign = b & 0x00800000; |
58 | 74 | INT32 result = a + b; |
59 | 75 | INT32 resultSign = result & 0x00800000; |
60 | 76 | bool overflow = (aSign == bSign) && (aSign != resultSign); |
r24765 | r24766 | |
90 | 106 | return saturate(result, flags); |
91 | 107 | } |
92 | 108 | |
93 | | |
94 | 109 | es5510_device::es5510_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
95 | 110 | : cpu_device(mconfig, ES5510, "ES5510", tag, owner, clock, "es5510", __FILE__) |
96 | 111 | { |
r24765 | r24766 | |
135 | 150 | instr_latch = 0; |
136 | 151 | ram_sel = 0; |
137 | 152 | host_control = 0; |
138 | | |
| 153 | |
| 154 | pc = 0; |
139 | 155 | memset(&alu, 0, sizeof(alu)); |
140 | 156 | memset(&mulacc, 0, sizeof(mulacc)); |
141 | 157 | } |
r24765 | r24766 | |
146 | 162 | |
147 | 163 | static inline INT32 SX(INT32 x) { return (x & 0x00800000) ? x | 0xff000000 : x & 0x00ffffff; } |
148 | 164 | static inline INT32 SC(INT32 x) { return x & 0x00ffffff; } |
149 | | static inline INT64 SX64(INT64 x) { return (x & U64(0x0000800000000000)) ? x | U64(0xffff000000000000) : x & U64(0x0000ffffffffffff); } |
150 | | static inline INT64 SC64(INT64 x) { return x & U64(0x0000ffffffffffff); } |
| 165 | static inline INT64 SX64(INT64 x) { return (x & S64(0x0000800000000000)) ? x | S64(0xffff000000000000) : x & S64(0x0000ffffffffffff); } |
| 166 | static inline INT64 SC64(INT64 x) { return x & S64(0x0000ffffffffffff); } |
151 | 167 | |
152 | 168 | static inline const char * const REGNAME(UINT8 r) { |
153 | 169 | static char rn[8]; |
r24765 | r24766 | |
179 | 195 | return NULL; |
180 | 196 | } |
181 | 197 | |
182 | | static inline char * DESCRIBE_REG(char *s, UINT8 r) { |
183 | | return stpcpy_int(s, REGNAME(r)); |
| 198 | static inline char * DESCRIBE_REG(char *s, UINT8 r, const char *name) { |
| 199 | if (name) { |
| 200 | return s + sprintf(s, "%s/%s", REGNAME(r), name); |
| 201 | } else { |
| 202 | return stpcpy_int(s, REGNAME(r)); |
| 203 | } |
184 | 204 | } |
185 | 205 | |
186 | 206 | const alu_op_t es5510_device::ALU_OPS[16] = { |
r24765 | r24766 | |
224 | 244 | { es5510_device::SRC_DST_DELAY, es5510_device::SRC_DST_BOTH, es5510_device::SRC_DST_DELAY, es5510_device::SRC_DST_REG }, |
225 | 245 | }; |
226 | 246 | |
227 | | static inline char * DESCRIBE_SRC_DST(char *s, UINT8 reg, op_src_dst_t src_dst) { |
| 247 | static inline char * DESCRIBE_SRC_DST(char *s, UINT8 reg, const char *regname, op_src_dst_t src_dst) { |
228 | 248 | switch (src_dst) { |
229 | 249 | case es5510_device::SRC_DST_REG: |
230 | | return DESCRIBE_REG(s, reg); |
| 250 | return DESCRIBE_REG(s, reg, regname); |
231 | 251 | case es5510_device::SRC_DST_DELAY: |
232 | 252 | return stpcpy_int(s, "Delay"); |
233 | 253 | case es5510_device::SRC_DST_BOTH: |
234 | | s = DESCRIBE_REG(s, reg); |
| 254 | s = DESCRIBE_REG(s, reg, regname); |
235 | 255 | return stpcpy_int(s, ",Delay"); |
236 | 256 | } |
237 | 257 | // should never happen! |
r24765 | r24766 | |
245 | 265 | { es5510_device::RAM_CYCLE_WRITE, es5510_device::RAM_CONTROL_TABLE_A, "Write Table A+%06x" }, |
246 | 266 | { es5510_device::RAM_CYCLE_READ, es5510_device::RAM_CONTROL_TABLE_B, "Read Table B+%06x" }, |
247 | 267 | { es5510_device::RAM_CYCLE_DUMP_FIFO, es5510_device::RAM_CONTROL_DELAY, "Read Delay+%06x and Dump FIFO" }, |
248 | | { es5510_device::RAM_CYCLE_READ, es5510_device::RAM_CONTROL_IO, "Read I/O at %06x" }, |
249 | | { es5510_device::RAM_CYCLE_WRITE, es5510_device::RAM_CONTROL_IO, "Write I/o %06x" }, |
| 268 | { es5510_device::RAM_CYCLE_READ, es5510_device::RAM_CONTROL_IO, "Read from I/O at %06x" }, |
| 269 | { es5510_device::RAM_CYCLE_WRITE, es5510_device::RAM_CONTROL_IO, "Write to I/O at %06x" }, |
250 | 270 | }; |
251 | 271 | |
252 | 272 | static inline char * DESCRIBE_RAM(char *s, UINT8 ramControl, UINT32 gprContents) { |
253 | 273 | return s + sprintf(s, es5510_device::RAM_CONTROL[ramControl].description, SC(gprContents)); |
254 | 274 | } |
255 | 275 | |
256 | | static inline char * DESCRIBE_ALU(char *s, UINT8 opcode, UINT8 aReg, UINT8 bReg, const op_select_t &opSelect) { |
| 276 | static inline char * DESCRIBE_ALU(char *s, UINT8 opcode, UINT8 aReg, const char *aName, UINT8 bReg, const char *bName, const op_select_t &opSelect) { |
257 | 277 | const alu_op_t &op = es5510_device::ALU_OPS[opcode]; |
258 | 278 | |
259 | 279 | switch (op.operands) { |
r24765 | r24766 | |
261 | 281 | return stpcpy_int(s, op.opcode); |
262 | 282 | |
263 | 283 | case 1: |
264 | | s += sprintf(s, "%s %s >", op.opcode, REGNAME(bReg)); |
265 | | return DESCRIBE_SRC_DST(s, aReg, opSelect.alu_dst); |
| 284 | s += sprintf(s, "%s ", op.opcode); |
| 285 | s = DESCRIBE_SRC_DST(s, bReg, bName, opSelect.alu_src); |
| 286 | s += sprintf(s, " >"); |
| 287 | return DESCRIBE_SRC_DST(s, aReg, aName, opSelect.alu_dst); |
266 | 288 | |
267 | 289 | case 2: |
268 | | s += sprintf(s, "%s %s,", op.opcode, REGNAME(bReg)); |
269 | | s = DESCRIBE_SRC_DST(s, aReg, opSelect.alu_src); |
| 290 | s += sprintf(s, "%s ", op.opcode); |
| 291 | s = DESCRIBE_REG(s, bReg, bName); |
| 292 | s += sprintf(s, " "); |
| 293 | s = DESCRIBE_SRC_DST(s, aReg, aName, opSelect.alu_src); |
270 | 294 | s += sprintf(s, " >"); |
271 | | return DESCRIBE_SRC_DST(s, aReg, opSelect.alu_dst); |
| 295 | return DESCRIBE_SRC_DST(s, aReg, aName, opSelect.alu_dst); |
272 | 296 | } |
273 | 297 | return s; |
274 | 298 | } |
275 | 299 | |
276 | | static inline char * DESCRIBE_MAC(char *s, UINT8 mac, UINT8 cReg, UINT8 dReg, const op_select_t &opSelect) |
| 300 | static inline char * DESCRIBE_MAC(char *s, UINT8 mac, UINT8 cReg, const char *cName, UINT8 dReg, const char *dName, const op_select_t &opSelect) |
277 | 301 | { |
278 | 302 | if (mac) |
279 | 303 | { |
280 | 304 | s += sprintf(s, "MAC + "); |
281 | 305 | } |
282 | | s = DESCRIBE_REG(s, dReg); |
| 306 | s = DESCRIBE_REG(s, dReg, dName); |
283 | 307 | s += sprintf(s, " * "); |
284 | | s = DESCRIBE_SRC_DST(s, cReg, opSelect.mac_src); |
| 308 | s = DESCRIBE_SRC_DST(s, cReg, cName, opSelect.mac_src); |
285 | 309 | s += sprintf(s, " >"); |
286 | | return DESCRIBE_SRC_DST(s, cReg, opSelect.mac_dst); |
| 310 | return DESCRIBE_SRC_DST(s, cReg, cName, opSelect.mac_dst); |
287 | 311 | } |
288 | 312 | |
289 | | static inline char * DESCRIBE_INSTR(char *s, UINT64 instr, UINT32 gpr) |
| 313 | static inline char * DESCRIBE_INSTR(char *s, UINT64 instr, UINT32 gpr, const char *aName, const char *bName, const char *cName, const char *dName) |
290 | 314 | { |
291 | 315 | UINT8 dReg = (UINT8)((instr >> 40) & 0xff); |
292 | 316 | UINT8 cReg = (UINT8)((instr >> 32) & 0xff); |
r24765 | r24766 | |
300 | 324 | |
301 | 325 | const op_select_t &opSelect = es5510_device::OPERAND_SELECT[operandSelect]; |
302 | 326 | |
303 | | s = DESCRIBE_ALU(s, aluOpcode, aReg, bReg, opSelect); |
| 327 | s = DESCRIBE_ALU(s, aluOpcode, aReg, aName, bReg, bName, opSelect); |
304 | 328 | s += sprintf(s, "; "); |
305 | | s = DESCRIBE_MAC(s, mac, cReg, dReg, opSelect); |
| 329 | s = DESCRIBE_MAC(s, mac, cReg, cName, dReg, dName, opSelect); |
306 | 330 | s += sprintf(s, "; "); |
307 | 331 | s = DESCRIBE_RAM(s, ramControl, gpr); |
308 | 332 | if (skip) { |
r24765 | r24766 | |
341 | 365 | |
342 | 366 | case 0x09: LOG(("ES5510: Host Read DIL latch[2]: %02x\n", (dil_latch >> 16) & 0xff)); return (dil_latch >> 16) & 0xff; |
343 | 367 | case 0x0a: LOG(("ES5510: Host Read DIL latch[1]: %02x\n", (dil_latch >> 8) & 0xff)); return (dil_latch >> 8) & 0xff; |
344 | | case 0x0b: LOG(("ES5510: Host Read DIL latch[0]: %02x\n", (dil_latch >> 0) & 0xff)); return (dil_latch >> 0) & 0xff; //TODO: docs says that this always returns 0 |
| 368 | case 0x0b: LOG(("ES5510: Host Read DIL latch[0]: %02x\n", 0)); return 0; |
345 | 369 | |
346 | 370 | case 0x0c: LOG(("ES5510: Host Read DOL latch[2]: %02x\n", (dol_latch >> 16) & 0xff)); return (dol_latch >> 16) & 0xff; |
347 | 371 | case 0x0d: LOG(("ES5510: Host Read DOL latch[1]: %02x\n", (dol_latch >> 8) & 0xff)); return (dol_latch >> 8) & 0xff; |
348 | | case 0x0e: LOG(("ES5510: Host Read DOL latch[0]: %02x\n", (dol_latch >> 0) & 0xff)); return (dol_latch >> 0) & 0xff; //TODO: docs says that this always returns 0 |
| 372 | case 0x0e: LOG(("ES5510: Host Read DOL latch[0]: %02x\n", 0xff)); return 0xff; |
349 | 373 | |
350 | 374 | case 0x0f: LOG(("ES5510: Host Read DADR latch[2]: %02x\n", (dadr_latch >> 16) & 0xff)); return (dadr_latch >> 16) & 0xff; |
351 | 375 | case 0x10: LOG(("ES5510: Host Read DADR latch[1]: %02x\n", (dadr_latch >> 8) & 0xff)); return (dadr_latch >> 8) & 0xff; |
r24765 | r24766 | |
397 | 421 | dadr_latch = (dadr_latch&0x00ffff) | ((data&0xff)<<16); |
398 | 422 | if (ram_sel) |
399 | 423 | { |
400 | | dil_latch = dram[dadr_latch]; |
| 424 | dil_latch = dram[dadr_latch] << 8; |
401 | 425 | } |
402 | 426 | else |
403 | 427 | { |
404 | | dram[dadr_latch] = dol_latch; |
| 428 | dram[dadr_latch] = dol_latch >> 8; |
405 | 429 | } |
406 | 430 | break; |
407 | 431 | |
r24765 | r24766 | |
455 | 479 | |
456 | 480 | case 0xc0: /* Write select - INSTR */ |
457 | 481 | #if VERBOSE |
458 | | DESCRIBE_INSTR(buf, instr_latch, gpr[data]); |
| 482 | DESCRIBE_INSTR(buf, instr_latch, gpr[data], NULL, NULL, NULL, NULL); |
459 | 483 | LOG(("ES5510: Host Write INSTR %02x %012" I64FMT "x: %s\n", data, instr_latch&U64(0xffffffffffff), buf)); |
460 | 484 | #endif |
461 | 485 | if (data < 0xa0) { |
r24765 | r24766 | |
465 | 489 | |
466 | 490 | case 0xe0: /* Write select - GPR + INSTR */ |
467 | 491 | #if VERBOSE |
468 | | DESCRIBE_INSTR(buf, instr_latch, gpr_latch); |
| 492 | DESCRIBE_INSTR(buf, instr_latch, gpr_latch, NULL, NULL, NULL, NULL); |
469 | 493 | LOG(("ES5510: Host Write INSTR+GPR %02x (%s): %012" I64FMT "x %06x (%d): %s\n", data, REGNAME(data&0xff), instr_latch, gpr_latch, SX(gpr_latch), buf)); |
470 | 494 | #endif |
471 | 495 | if (data < 0xa0) { |
r24765 | r24766 | |
560 | 584 | void es5510_device::list_program(void(p)(const char *, ...)) { |
561 | 585 | LOG(("ES5501: Starting!\n")); |
562 | 586 | |
563 | | UINT8 addr; |
564 | 587 | char buf[1024]; |
| 588 | bool is_written[0xff], is_read[0xff]; |
| 589 | char name[0xff][16]; |
| 590 | int addr; |
| 591 | |
| 592 | for (int i = 0; i < 0x100; i++) { |
| 593 | is_written[i] = is_read[i] = false; |
| 594 | name[i][0] = '\0'; |
| 595 | } |
| 596 | |
565 | 597 | for (addr = 0; addr < 0xa0; addr++) { |
566 | | DESCRIBE_INSTR(buf, instr[addr], gpr[addr]); |
567 | | p("%02x: %012" I64FMT "x %06x %s\n", addr, instr[addr], gpr[addr]&0xffffff, buf); |
| 598 | DESCRIBE_INSTR(buf, instr[addr], gpr[addr], NULL, NULL, NULL, NULL); |
| 599 | UINT64 inst = instr[addr]; |
| 600 | UINT8 aReg = (UINT8)((inst >> 16) & 0xff); |
| 601 | UINT8 bReg = (UINT8)((inst >> 24) & 0xff); |
| 602 | UINT8 cReg = (UINT8)((inst >> 32) & 0xff); |
| 603 | UINT8 dReg = (UINT8)((inst >> 40) & 0xff); |
| 604 | UINT8 alu_op = (inst >> 12) & 0x0f; |
| 605 | if (alu_op == 0x0f) { |
| 606 | // END! |
| 607 | break; |
| 608 | } |
| 609 | |
| 610 | UINT8 operandSelect = (UINT8)((inst >> 8) & 0x0f); |
| 611 | const op_select_t &opSelect = OPERAND_SELECT[operandSelect]; |
| 612 | |
| 613 | if (opSelect.mac_src == SRC_DST_REG) { |
| 614 | is_read[cReg] = true; |
| 615 | } |
| 616 | is_read[dReg] = true; |
| 617 | if (opSelect.mac_dst != SRC_DST_DELAY) { // either REG or BOTH |
| 618 | is_written[cReg] = true; |
| 619 | } |
| 620 | |
| 621 | alu_op_t aluOp = ALU_OPS[alu_op]; |
| 622 | if (aluOp.operands == 1) { |
| 623 | if (opSelect.alu_src == SRC_DST_REG) { |
| 624 | is_read[bReg] = true; |
| 625 | } |
| 626 | } else if (aluOp.operands == 2) { |
| 627 | if (opSelect.alu_src == SRC_DST_REG) { |
| 628 | is_read[aReg] = true; |
| 629 | } |
| 630 | is_read[bReg] = true; |
| 631 | } |
| 632 | if (opSelect.mac_dst != SRC_DST_DELAY) { // either REG or BOTH |
| 633 | is_written[aReg] = true; |
| 634 | } |
568 | 635 | } |
| 636 | |
| 637 | int varIndex = 1; |
| 638 | int constIndex = 1; |
| 639 | for (int i = 0; i < 0xc0; i++) { |
| 640 | if (is_written[i]) { |
| 641 | // this is a variable |
| 642 | sprintf(name[i], "v_%03d", varIndex++); |
| 643 | } else if (is_read[i]) { |
| 644 | // this is only read, so a constant - or possibly something updated by the CPU |
| 645 | sprintf(name[i], "c_%03d", constIndex++); |
| 646 | } else { |
| 647 | name[i][0] = 0; |
| 648 | } |
| 649 | } |
| 650 | for (int i = 0xc0; i < 0x100; i++) { |
| 651 | name[i][0] = 0; |
| 652 | } |
| 653 | |
| 654 | for (addr = 0; addr < 0xa0; addr++) { |
| 655 | UINT8 aReg = (UINT8)((instr[addr] >> 16) & 0xff); |
| 656 | UINT8 bReg = (UINT8)((instr[addr] >> 24) & 0xff); |
| 657 | UINT8 cReg = (UINT8)((instr[addr] >> 32) & 0xff); |
| 658 | UINT8 dReg = (UINT8)((instr[addr] >> 40) & 0xff); |
| 659 | DESCRIBE_INSTR(buf, instr[addr], gpr[addr], name[aReg], name[bReg], name[cReg], name[dReg]); |
| 660 | p("%02x: %012" I64FMT "x %06x (%8d) %s\n", addr, instr[addr], gpr[addr]&0xffffff, SX(gpr[addr]&0xffffff), buf); |
| 661 | } |
569 | 662 | for (; addr < 0xc0; addr++) { |
570 | | p("%02x: %06x (%d)\n", addr, gpr[addr]&0xffffff, gpr[addr]); |
| 663 | p("%02x: %06x (%d)\n", addr, gpr[addr]&0xffffff, SX(gpr[addr]&0xffffff)); |
571 | 664 | } |
572 | 665 | } |
573 | 666 | |
r24765 | r24766 | |
587 | 680 | } else { |
588 | 681 | // currently running, execute one instruction. |
589 | 682 | |
590 | | #if VERBOSE |
| 683 | #if VERBOSE_EXEC |
591 | 684 | char buf[1024]; |
592 | | DESCRIBE_INSTR(buf, instr[pc], gpr[pc]); |
593 | | LOG(("%02x: %012" I64FMT "x %06x %s\n", pc, instr[pc], gpr[pc]&0xffffff, buf)); |
| 685 | DESCRIBE_INSTR(buf, instr[pc], gpr[pc], NULL, NULL, NULL, NULL); |
| 686 | LOG_EXEC(("EXECUTING %02x: %012" I64FMT "x %06x %s\n", pc, instr[pc], gpr[pc]&0xffffff, buf)); |
594 | 687 | #endif |
595 | 688 | |
596 | 689 | ram_pp = ram_p; |
597 | 690 | ram_p = ram; |
598 | 691 | |
| 692 | LOG_EXEC(("- T0\n")); |
| 693 | |
599 | 694 | // *** T0, clock high |
600 | 695 | // --- nothing to do! |
601 | 696 | |
r24765 | r24766 | |
608 | 703 | if (ram_pp.io) { // read from I/O and store into DIL |
609 | 704 | dil = 0; // read_io(ram_pp.address);; |
610 | 705 | } else { // read from DRAM and store into DIL |
611 | | dil = dram[ram_pp.address]; |
| 706 | dil = dram[ram_pp.address] << 8; |
| 707 | LOG_EXEC((" . RAM: read %x (%d) from address %x\n", dil, dil, ram_pp.address)); |
612 | 708 | } |
613 | 709 | } |
614 | 710 | |
r24765 | r24766 | |
621 | 717 | INT32 offset = gpr[pc]; |
622 | 718 | switch(ramControl.access) { |
623 | 719 | case RAM_CONTROL_DELAY: |
624 | | ram.address = (((dbase + offset) % (dlength + 1)) & memmask) >> memshift; |
| 720 | ram.address = (((dbase + offset) % (dlength + memincrement)) & memmask) >> memshift; |
| 721 | LOG_EXEC((". Ram Control: Delay, base=%x, offset=%x, length=%x => address=%x\n", dbase >> memshift, offset >> memshift, (dlength + memincrement) >> memshift, ram.address)); |
625 | 722 | break; |
626 | 723 | case RAM_CONTROL_TABLE_A: |
627 | 724 | ram.address = ((abase + offset) & memmask) >> memshift; |
| 725 | LOG_EXEC((". Ram Control: table A = %x, offset=%x => address=%x\n", abase >> memshift, offset >> memshift, ram.address)); |
628 | 726 | break; |
629 | 727 | case RAM_CONTROL_TABLE_B: |
630 | 728 | ram.address = ((bbase + offset) & memmask) >> memshift; |
| 729 | LOG_EXEC((". Ram Control: table B = %x, offset=%x => address=%x\n", bbase >> memshift, offset >> memshift, ram.address)); |
631 | 730 | break; |
632 | 731 | case RAM_CONTROL_IO: |
633 | 732 | ram.address = offset & 0x00fffff0; // mask off the low 4 bits |
| 733 | LOG_EXEC((". Ram Control: I/O at address=%x\n", ram.address)); |
634 | 734 | break; |
635 | 735 | } |
636 | 736 | |
r24765 | r24766 | |
638 | 738 | // --- Decode instruction N; |
639 | 739 | // we will do this both here and in stages as the different parts of the instruction complete & recommence. |
640 | 740 | |
| 741 | LOG_EXEC(("- T1.1\n")); |
| 742 | |
641 | 743 | UINT8 operandSelect = (UINT8)((instr >> 8) & 0x0f); |
642 | 744 | const op_select_t &opSelect = OPERAND_SELECT[operandSelect]; |
643 | | bool skip = false; |
644 | | bool skippable = ((instr >> 7) & 0x01) != 0; // aka the 'SKIP' bit in the instruction word |
| 745 | bool skip; |
| 746 | bool skippable = (instr & (0x01 << 7)) != 0; // aka the 'SKIP' bit in the instruction word |
645 | 747 | if (skippable) { |
646 | 748 | bool skipConditionSatisfied = (ccr & cmr & FLAG_MASK) != 0; |
647 | 749 | if (isFlagSet(cmr, FLAG_NOT)) { |
648 | 750 | skipConditionSatisfied = !skipConditionSatisfied; |
649 | 751 | } |
650 | 752 | skip = skipConditionSatisfied; |
| 753 | LOG_EXEC((". skippable: %x vs %x => skippable = %d\n", ccr, cmr, skip)); |
| 754 | } else { |
| 755 | skip = false; |
651 | 756 | } |
652 | 757 | |
653 | 758 | // --- Write Multiplier result N-1 |
| 759 | LOG_EXEC((". write mulacc:\n")); |
654 | 760 | if (mulacc.write_result) { |
655 | | mulacc.product = (mulacc.cValue * mulacc.dValue) << mulshift; |
656 | | mulacc.result = (mulacc.accumulate ? machl : 0) + mulacc.product; |
657 | | INT32 tmp = (mulacc.result & U64(0x0000ffffff000000)) >> 24; |
| 761 | mulacc.product = ((INT64)SX(mulacc.cValue) * (INT64)SX(mulacc.dValue)) << mulshift; |
| 762 | if (mulacc.accumulate) { |
| 763 | mulacc.result = mulacc.product + machl; |
| 764 | } else { |
| 765 | mulacc.result = mulacc.product; |
| 766 | } |
| 767 | |
| 768 | INT64 result_min = ~0LL << 47; |
| 769 | INT64 result_max = (1LL << 48) - 1; |
| 770 | |
| 771 | if (mulacc.result < result_min || mulacc.result > result_max) { |
| 772 | mac_overflow = true; |
| 773 | } else { |
| 774 | mac_overflow = false; |
| 775 | } |
| 776 | #if VERBOSE_EXEC |
| 777 | if (mulacc.cValue || mulacc.dValue || (mulacc.accumulate && machl)) { |
| 778 | LOG_EXEC((". mulacc: %x (%d) * %x (%d) << %d", SX(mulacc.cValue), SX(mulacc.cValue), SX(mulacc.dValue), SX(mulacc.dValue), mulshift)); |
| 779 | if (mulacc.accumulate) LOG_EXEC((" + %llx (%lld) ", machl, machl)); |
| 780 | LOG_EXEC((" = %llx (%lld)", mulacc.result, mulacc.result)); |
| 781 | if (mac_overflow) { |
| 782 | LOG_EXEC((" overflow!\n")); |
| 783 | } else { |
| 784 | LOG_EXEC(("\n")); |
| 785 | } |
| 786 | } |
| 787 | #endif |
| 788 | machl = mulacc.result; |
| 789 | INT32 tmp = mac_overflow ? (machl < 0 ? 0x00800000 : 0x007fffff) : (mulacc.result & U64(0x0000ffffff000000)) >> 24; |
658 | 790 | if (mulacc.dst & SRC_DST_REG) { |
659 | | machl = mulacc.result; |
660 | 791 | write_reg(mulacc.cReg, tmp); |
661 | 792 | } |
662 | 793 | if (mulacc.dst & SRC_DST_DELAY) { |
r24765 | r24766 | |
665 | 796 | } |
666 | 797 | |
667 | 798 | // *** T1, clock low |
| 799 | |
| 800 | LOG_EXEC(("- T1.0\n")); |
| 801 | |
668 | 802 | // --- Start of multiplier cycle N |
| 803 | LOG_EXEC((". start mulacc:\n")); |
669 | 804 | mulacc.cReg = (UINT8)((instr >> 32) & 0xff); |
670 | 805 | mulacc.dReg = (UINT8)((instr >> 40) & 0xff); |
671 | 806 | mulacc.src = opSelect.mac_src; |
r24765 | r24766 | |
677 | 812 | if (mulacc.src == SRC_DST_REG) { |
678 | 813 | mulacc.cValue = read_reg(mulacc.cReg); |
679 | 814 | } else { // must be SRC_DST_DELAY |
| 815 | LOG_EXEC((" . reading %x (%d) from dil\n", dil, SX(dil))); |
680 | 816 | mulacc.cValue = dil; |
681 | 817 | } |
682 | 818 | mulacc.dValue = read_reg(mulacc.dReg); |
683 | 819 | |
684 | 820 | // *** T2, clock high |
| 821 | |
| 822 | LOG_EXEC(("- T2.1\n")); |
| 823 | |
685 | 824 | // --- Write ALU Result N-1 |
| 825 | LOG_EXEC((". write ALU:\n")); |
686 | 826 | if (alu.write_result) { |
687 | 827 | UINT8 flags = ccr; |
688 | 828 | alu.result = alu_operation(alu.op, alu.aValue, alu.bValue, flags); |
r24765 | r24766 | |
698 | 838 | } |
699 | 839 | |
700 | 840 | // *** T2, clock low |
| 841 | |
| 842 | LOG_EXEC(("- T2.0\n")); |
| 843 | |
701 | 844 | // --- Start of ALU cycle N |
| 845 | LOG_EXEC((". start ALU:\n")); |
702 | 846 | alu.aReg = (instr >> 16) & 0xff; |
703 | 847 | alu.bReg = (instr >> 24) & 0xff; |
704 | 848 | alu.op = (instr >> 12) & 0x0f; |
r24765 | r24766 | |
712 | 856 | } else { |
713 | 857 | // --- Read ALU Operands N |
714 | 858 | alu_op_t aluOp = ALU_OPS[alu.op]; |
715 | | if (aluOp.operands == 2) { |
| 859 | if (aluOp.operands == 1) { |
716 | 860 | if (alu.src == SRC_DST_REG) { |
| 861 | alu.bValue = read_reg(alu.bReg); |
| 862 | } else { // must be SRC_DST_DELAY |
| 863 | alu.bValue = dil; |
| 864 | } |
| 865 | } else { |
| 866 | if (alu.src == SRC_DST_REG) { |
717 | 867 | alu.aValue = read_reg(alu.aReg); |
718 | 868 | } else { // must be SRC_DST_DELAY |
719 | 869 | alu.aValue = dil; |
720 | 870 | } |
721 | | } |
722 | | if (aluOp.operands >= 1) { |
723 | 871 | alu.bValue = read_reg(alu.bReg); |
724 | 872 | } |
725 | 873 | } |
r24765 | r24766 | |
731 | 879 | if (ram_p.io) { |
732 | 880 | // write_io(ram_p.io, dol[0]); |
733 | 881 | } else { |
734 | | dram[ram_p.address] = dol[0]; |
| 882 | dram[ram_p.address] = dol[0] >> 8; |
| 883 | LOG_EXEC((" . RAM: writing %x (%d) [of %x (%d)] to address %x\n", dol[0]&0xffff00, SX(dol[0]&0xffff00), dol[0], SX(dol[0]), ram_p.address)); |
735 | 884 | } |
736 | 885 | } |
737 | 886 | // If this is a Write or Dump cycle, eject the frontmost DL value. |
| 887 | #if VERBOSE_EXEC |
| 888 | LOG_EXEC((" . ejecting from DOL: [ ")); |
| 889 | if (dol_count >= 1) LOG_EXEC(("{ %x (%d) }", dol[0], SX(dol[0]))); |
| 890 | if (dol_count == 2) LOG_EXEC((", { %x (%d) }", dol[1], SX(dol[1]))); |
| 891 | LOG_EXEC((" ] -> [ ")); |
| 892 | #endif |
738 | 893 | dol[0] = dol[1]; |
739 | 894 | if (dol_count > 0) { |
740 | 895 | --dol_count; |
741 | 896 | } |
| 897 | #if VERBOSE_EXEC |
| 898 | if (dol_count >= 1) LOG_EXEC(("{ %x (%d) }", dol[0], SX(dol[0]))); |
| 899 | if (dol_count == 2) LOG_EXEC((", { %x (%d) }", dol[1], SX(dol[1]))); |
| 900 | LOG_EXEC((" ]\n")); |
| 901 | #endif |
742 | 902 | } |
743 | 903 | |
744 | 904 | ++pc; |
r24765 | r24766 | |
762 | 922 | return pc; |
763 | 923 | } |
764 | 924 | |
| 925 | #if VERBOSE_EXEC |
| 926 | #define RETURN_GPR(r, x) do { INT32 v = (x); LOG_EXEC((" . reading %x (%d) from gpr_%02x\n", v, SX(v), r)); return v; } while(0) |
| 927 | #define RETURN(r, x) do { INT32 v = (x); LOG_EXEC((" . reading %x (%d) from " #r "\n", v, SX(v))); return v; } while(0) |
| 928 | #define RETURN16(r, x) do { INT16 vv = (x); INT32 v = vv << 8; LOG_EXEC((" . reading %x (%d) as %x (%d) from " #r "\n", vv, vv, v, SX(v))); return v; } while(0) |
| 929 | #else |
| 930 | #define RETURN_GPR(r, x) return x |
| 931 | #define RETURN(r, x) return x |
| 932 | #define RETURN16(r, x) return (x) << 8 |
| 933 | #endif |
| 934 | |
765 | 935 | INT32 es5510_device::read_reg(UINT8 reg) |
766 | 936 | { |
767 | 937 | if (reg < 0xc0) { |
768 | | return gpr[reg]; |
| 938 | RETURN_GPR(reg, gpr[reg]); |
769 | 939 | } else { |
770 | 940 | switch(reg) |
771 | 941 | { |
772 | | case 234: return ser0r; |
773 | | case 235: return ser0l; |
774 | | case 236: return ser1r; |
775 | | case 237: return ser1l; |
776 | | case 238: return ser2r; |
777 | | case 239: return ser2l; |
778 | | case 240: return ser3r; |
779 | | case 241: return ser3l; |
780 | | case 242: return (machl >> 0) & 0x00ffffff; |
781 | | case 243: return (machl >> 24) & 0x00ffffff; |
782 | | case 244: return dil; // DIL when reading |
783 | | case 245: return dlength; |
784 | | case 246: return abase; |
785 | | case 247: return bbase; |
786 | | case 248: return dbase; |
787 | | case 249: return sigreg; |
788 | | case 250: return ccr; |
789 | | case 251: return cmr; |
790 | | case 252: return 0x00ffffff; |
791 | | case 253: return 0x00800000; |
792 | | case 254: return 0x007fffff; |
793 | | case 255: return 0x00000000; |
| 942 | case 234: RETURN16(ser0r, ser0r); |
| 943 | case 235: RETURN16(ser0l, ser0l); |
| 944 | case 236: RETURN16(ser1r, ser1r); |
| 945 | case 237: RETURN16(ser1l, ser1l); |
| 946 | case 238: RETURN16(ser2r, ser2r); |
| 947 | case 239: RETURN16(ser2l, ser2l); |
| 948 | case 240: RETURN16(ser3r, ser3r); |
| 949 | case 241: RETURN16(ser3l, ser3l); |
| 950 | case 242: /* macl */ RETURN(macl, mac_overflow ? (machl < 0 ? 0x00fffffe : 0x00000000) : (machl >> 0) & 0x00ffffff); |
| 951 | case 243: /* mach */ RETURN(mach, mac_overflow ? (machl < 0 ? 0x007fffff : 0x00800000) : (machl >> 24) & 0x00ffffff); |
| 952 | case 244: RETURN(dil, dil); // DIL when reading |
| 953 | case 245: RETURN(dlength, dlength); |
| 954 | case 246: RETURN(abase, abase); |
| 955 | case 247: RETURN(bbase, bbase); |
| 956 | case 248: RETURN(dbase, dbase); |
| 957 | case 249: RETURN(sigreg, sigreg); |
| 958 | case 250: RETURN(ccr, ccr); |
| 959 | case 251: RETURN(cmr, cmr); |
| 960 | case 252: RETURN(minus_one, 0x00ffffff); |
| 961 | case 253: RETURN(min, 0x00800000); |
| 962 | case 254: RETURN(max, 0x007fffff); |
| 963 | case 255: RETURN(zero, 0x00000000); |
794 | 964 | default: |
795 | 965 | // unknown SPR |
796 | | return 0; |
| 966 | RETURN(unknown, 0);; |
797 | 967 | } |
798 | 968 | } |
799 | 969 | } |
r24765 | r24766 | |
826 | 996 | return n; |
827 | 997 | } |
828 | 998 | |
| 999 | #if VERBOSE_EXEC |
| 1000 | #define WRITE_REG(r, x) do { r = value; LOG_EXEC((" . writing %x (%d) to " #r "\n", r, SX(r))); } while(0) |
| 1001 | #define WRITE_REG16(r, x) do { r = ((value >> 8) & 0xffff); LOG_EXEC((" . writing %x (%d) as %x (%d) to " #r "\n", value, SX(value), r, r)); } while(0) |
| 1002 | #else |
| 1003 | #define WRITE_REG(r, x) do { r = value; } while(0) |
| 1004 | #define WRITE_REG16(r, x) do { r = ((value >> 8) & 0xffff); } while(0) |
| 1005 | #endif |
| 1006 | |
829 | 1007 | void es5510_device::write_reg(UINT8 reg, INT32 value) |
830 | 1008 | { |
| 1009 | #if VERBOSE_EXEC |
| 1010 | INT64 old; |
| 1011 | #endif |
831 | 1012 | value &= 0x00ffffff; |
832 | 1013 | if (reg < 0xc0) { |
| 1014 | LOG_EXEC((" . writing %x (%d) to gpr_%02x\n", value, SX(value), reg)); |
833 | 1015 | gpr[reg] = value; |
834 | 1016 | } else { |
835 | 1017 | switch(reg) |
836 | 1018 | { |
837 | | case 234: ser0r = value; |
| 1019 | case 234: WRITE_REG16(ser0r, value); |
838 | 1020 | break; |
839 | | case 235: ser0l = value; |
| 1021 | case 235: WRITE_REG16(ser0l, value); |
840 | 1022 | break; |
841 | | case 236: ser1r = value; |
| 1023 | case 236: WRITE_REG16(ser1r, value); |
842 | 1024 | break; |
843 | | case 237: ser1l = value; |
| 1025 | case 237: WRITE_REG16(ser1l, value); |
844 | 1026 | break; |
845 | | case 238: ser2r = value; |
| 1027 | case 238: WRITE_REG16(ser2r, value); |
846 | 1028 | break; |
847 | | case 239: ser2l = value; |
| 1029 | case 239: WRITE_REG16(ser2l, value); |
848 | 1030 | break; |
849 | | case 240: ser3r = value; |
| 1031 | case 240: WRITE_REG16(ser3r, value); |
850 | 1032 | break; |
851 | | case 241: ser3l = value; |
| 1033 | case 241: WRITE_REG16(ser3l, value); |
852 | 1034 | break; |
853 | | case 242: machl = (machl & ~((INT64)0x00ffffff << 0)) | (value << 0); |
| 1035 | case 242: /* macl */ { |
| 1036 | #if VERBOSE_EXEC |
| 1037 | old = machl; |
| 1038 | #endif |
| 1039 | INT64 masked = machl & (S64(0x00ffffff) << 24); |
| 1040 | INT64 shifted = (INT64)(value & 0x00ffffff) << 0; |
| 1041 | machl = SX64(masked | shifted); |
| 1042 | #if VERBOSE_EXEC |
| 1043 | LOG_EXEC((" . writing machl: l -> %06x => %llx -> %llx\n", value, old, machl)); |
| 1044 | #endif |
854 | 1045 | break; |
855 | | case 243: machl = (machl & ~((INT64)0x00ffffff << 24)) | (value << 24); |
| 1046 | } |
| 1047 | case 243: /* mach */ { |
| 1048 | #if VERBOSE_EXEC |
| 1049 | old = machl; |
| 1050 | #endif |
| 1051 | INT64 masked = machl & (S64(0x00ffffff) << 0); |
| 1052 | INT64 shifted = (INT64)(value & 0x00ffffff) << 24; |
| 1053 | machl = SX64(masked | shifted); |
| 1054 | mac_overflow = false; |
| 1055 | #if VERBOSE_EXEC |
| 1056 | LOG_EXEC((" . writing machl: h -> %06x => %llx -> %llx\n", value, old, machl)); |
| 1057 | #endif |
856 | 1058 | break; |
857 | | case 244: |
| 1059 | } |
| 1060 | case 244: /* MEMSIZ when writing */ |
858 | 1061 | memshift = countLowOnes(value); |
859 | 1062 | memsiz = 0x00ffffff >> (24 - memshift); |
860 | 1063 | memmask = 0x00ffffff & ~memsiz; |
861 | 1064 | memincrement = 1 << memshift; |
| 1065 | LOG_EXEC((" . writing %x (%d) to memsiz => memsiz=%x, shift=%d, mask=%x, increment=%x\n", value, SX(value), memsiz, memshift, memmask, memincrement)); |
862 | 1066 | break; |
863 | | case 245: dlength = value; |
| 1067 | case 245: WRITE_REG(dlength, value); |
864 | 1068 | break; |
865 | | case 246: abase = value; |
| 1069 | case 246: WRITE_REG(abase, value); |
866 | 1070 | break; |
867 | | case 247: bbase = value; |
| 1071 | case 247: WRITE_REG(bbase, value); |
868 | 1072 | break; |
869 | | case 248: dbase = value; |
| 1073 | case 248: WRITE_REG(dbase, value); |
870 | 1074 | break; |
871 | | case 249: sigreg = (value != 0); |
| 1075 | case 249: WRITE_REG(sigreg, (value != 0)); |
872 | 1076 | break; |
873 | | case 250: ccr = (value >> 16) & FLAG_MASK; |
| 1077 | case 250: WRITE_REG(ccr, (value >> 16) & FLAG_MASK); |
874 | 1078 | break; |
875 | | case 251: cmr = (value >> 16) & (FLAG_MASK | FLAG_NOT); |
| 1079 | case 251: WRITE_REG(cmr, (value >> 16) & (FLAG_MASK | FLAG_NOT)); |
876 | 1080 | break; |
877 | | case 252: // no-op |
| 1081 | case 252: LOG_EXEC((". not writing %x (%d) to minus_one\n", value, SX(value))); // no-op |
878 | 1082 | break; |
879 | | case 253: // no-op |
| 1083 | case 253: LOG_EXEC((". not writing %x (%d) to min\n", value, SX(value))); // no-op |
880 | 1084 | break; |
881 | | case 254: // no-op |
| 1085 | case 254: LOG_EXEC((". not writing %x (%d) to max\n", value, SX(value))); // no-op |
882 | 1086 | break; |
883 | | case 255: // no-op |
| 1087 | case 255: LOG_EXEC((". not writing %x (%d) to zero\n", value, SX(value))); // no-op |
884 | 1088 | break; |
885 | 1089 | default: // unknown register |
886 | 1090 | break; |
r24765 | r24766 | |
889 | 1093 | } |
890 | 1094 | |
891 | 1095 | void es5510_device::write_to_dol(INT32 value) { |
| 1096 | #if VERBOSE_EXEC |
| 1097 | LOG_EXEC((". writing %x (%d) to DOL: [ ", value, value)); |
| 1098 | if (dol_count >= 1) LOG_EXEC(("{ %x (%d) }", dol[0], SX(dol[0]))); |
| 1099 | if (dol_count == 2) LOG_EXEC((", { %x (%d) }", dol[1], SX(dol[1]))); |
| 1100 | LOG_EXEC((" ] -> [ ")); |
| 1101 | #endif |
892 | 1102 | if (dol_count >= 2) { |
893 | 1103 | dol[0] = dol[1]; |
894 | 1104 | dol[1] = value; |
895 | 1105 | } else { |
896 | 1106 | dol[dol_count++] = value; |
897 | 1107 | } |
| 1108 | #if VERBOSE_EXEC |
| 1109 | LOG_EXEC(("{%x (%d)}", dol[0], SX(dol[0]))); |
| 1110 | if (dol_count == 2) LOG_EXEC((", {%x (%d)}", dol[1], SX(dol[1]))); |
| 1111 | LOG_EXEC((" ]\n")); |
| 1112 | #endif |
898 | 1113 | } |
899 | 1114 | |
900 | 1115 | void es5510_device::alu_operation_end() { |
901 | 1116 | // Handle the END instruction separately |
902 | | LOG(("ES5510: END\n")); |
| 1117 | LOG_EXEC(("ES5510: END\n")); |
903 | 1118 | // sample the HALT line |
904 | 1119 | if (halt_asserted) { |
905 | 1120 | // halt |
r24765 | r24766 | |
911 | 1126 | if (dbase < 0) { |
912 | 1127 | dbase = dlength; |
913 | 1128 | } |
| 1129 | // Possibly reset the PC |
| 1130 | if (state == STATE_RUNNING) { |
| 1131 | pc = 0; |
| 1132 | } |
| 1133 | |
| 1134 | #if VERBOSE_EXEC |
| 1135 | // update the verbose-execution counter. |
| 1136 | exec_cc = (exec_cc + 1) % 10000; |
| 1137 | #endif |
914 | 1138 | } |
915 | 1139 | |
916 | 1140 | INT32 es5510_device::alu_operation(UINT8 op, INT32 a, INT32 b, UINT8 &flags) { |
| 1141 | INT32 tmp; |
917 | 1142 | switch(op) { |
918 | 1143 | case 0x0: // ADD |
919 | | return saturate(add(a, b, flags), flags); |
| 1144 | tmp = add(a, b, flags); |
| 1145 | return saturate(tmp, flags); |
920 | 1146 | |
921 | 1147 | case 0x1: // SUB |
922 | | return saturate(add(a, negate(b), flags), flags); |
| 1148 | tmp = add(a, negate(b), flags); |
| 1149 | return saturate(tmp, flags); |
923 | 1150 | |
924 | 1151 | case 0x2: // ADDU |
925 | 1152 | return add(a, b, flags); |
r24765 | r24766 | |
954 | 1181 | clearFlag(flags, FLAG_N); |
955 | 1182 | bool isNegative = (a & 0x00800000) != 0; |
956 | 1183 | setFlagTo(flags, FLAG_C, isNegative); |
957 | | if (isNegative) { |
958 | | a = (a ^ 0x00ffffff) + 1; |
959 | | } |
960 | | return a; |
| 1184 | return isNegative ? negate(a) : a; |
961 | 1185 | } |
962 | 1186 | |
963 | 1187 | case 0x9: // MOV |
trunk/src/mess/drivers/esq5505.c
r24765 | r24766 | |
143 | 143 | va_end(arg); |
144 | 144 | } |
145 | 145 | |
146 | | #define PUMP_DETECT_SILENCE 1 |
| 146 | #define PUMP_DETECT_SILENCE 0 |
147 | 147 | #define PUMP_TRACK_SAMPLES 0 |
148 | | #define PUMP_FAKE_ESP_PROCESSING 1 |
| 148 | #define PUMP_FAKE_ESP_PROCESSING 0 |
| 149 | #define PUMP_REPLACE_ESP_PROGRAM 0 |
| 150 | |
149 | 151 | class esq_5505_5510_pump : public device_t, |
150 | 152 | public device_sound_interface |
151 | 153 | { |
r24765 | r24766 | |
158 | 160 | m_esp_halted = esp_halted; |
159 | 161 | logerror("ESP-halted -> %d\n", m_esp_halted); |
160 | 162 | if (!esp_halted) { |
161 | | m_esp->list_program(print_to_stderr); |
| 163 | |
| 164 | #if PUMP_REPLACE_ESP_PROGRAM |
| 165 | m_esp->write_reg(245, 0x1d0f << 8); // dlength = 0x3fff, 16-sample delay |
| 166 | |
| 167 | int pc = 0; |
| 168 | for (pc = 0; pc < 0xc0; pc++) { |
| 169 | m_esp->write_reg(pc, 0); |
| 170 | } |
| 171 | pc = 0; |
| 172 | // replace the ESP program with a simple summing & single-sample delay |
| 173 | m_esp->_instr(pc++) = 0xffffeaa09000; // MOV SER0R > grp_a0 |
| 174 | m_esp->_instr(pc++) = 0xffffeba00000; // ADD SER0L, gpr_a0 > gpr_a0 |
| 175 | m_esp->_instr(pc++) = 0xffffeca00000; // ADD SER1R, gpr_a0 > gpr_a0 |
| 176 | m_esp->_instr(pc++) = 0xffffeda00000; // ADD SER1L, gpr_a0 > gpr_a0 |
| 177 | m_esp->_instr(pc++) = 0xffffeea00000; // ADD SER2R, gpr_a0 > gpr_a0 |
| 178 | |
| 179 | m_esp->_instr(pc ) = 0xffffefa00000; // ADD SER2L, gpr_a0 > gpr_a0; prepare to read from delay 2 instructions from now, offset = 0 |
| 180 | m_esp->write_reg(pc++, 0); //offset into delay |
| 181 | |
| 182 | m_esp->_instr(pc ) = 0xffffa0a09508; // MOV gpr_a0 > delay + offset |
| 183 | m_esp->write_reg(pc++, 1 << 8); // offset into delay - -1 samples |
| 184 | |
| 185 | m_esp->_instr(pc++) = 0xffff00a19928; // MOV DIL > gpr_a1; read Delay and dump FIFO (so that the value gets written) |
| 186 | |
| 187 | m_esp->_instr(pc++) = 0xffffa1f09000; // MOV gpr_a1 > SER3R |
| 188 | m_esp->_instr(pc++) = 0xffffa1f19000; // MOV gpr_a1 > SER3L |
| 189 | |
| 190 | m_esp->_instr(pc++) = 0xffffffff0000; // NO-OP |
| 191 | m_esp->_instr(pc++) = 0xffffffff0000; // NO-OP |
| 192 | m_esp->_instr(pc++) = 0xfffffffff000; // END |
| 193 | |
| 194 | while (pc < 160) { |
| 195 | m_esp->_instr(pc++) = 0xffffffffffff; // no-op |
| 196 | } |
| 197 | #endif |
| 198 | |
| 199 | // m_esp->list_program(print_to_stderr); |
162 | 200 | } |
163 | 201 | } |
164 | 202 | bool get_esp_halted() { |
r24765 | r24766 | |
174 | 212 | // sound stream update overrides |
175 | 213 | virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples); |
176 | 214 | |
177 | | // timer callback overridea |
| 215 | // timer callback overrides |
178 | 216 | virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr); |
179 | 217 | |
180 | 218 | private: |
r24765 | r24766 | |
209 | 247 | osd_ticks_t last_ticks; |
210 | 248 | osd_ticks_t next_report_ticks; |
211 | 249 | #endif |
| 250 | |
| 251 | #if !PUMP_FAKE_ESP_PROCESSING && PUMP_REPLACE_ESP_PROGRAM |
| 252 | INT16 e[0x4000]; |
| 253 | int ei; |
| 254 | #endif |
212 | 255 | }; |
213 | 256 | |
214 | 257 | const device_type ESQ_5505_5510_PUMP = &device_creator<esq_5505_5510_pump>; |
r24765 | r24766 | |
222 | 265 | |
223 | 266 | void esq_5505_5510_pump::device_start() |
224 | 267 | { |
225 | | INT64 nsec_per_sample = 100 * 16 * 21; |
226 | | attotime sample_time(0, 1000000000 * nsec_per_sample); |
227 | | attotime initial_delay(0, 0); |
228 | 268 | logerror("Clock = %d\n", clock()); |
| 269 | |
229 | 270 | m_stream = machine().sound().stream_alloc(*this, 8, 2, clock(), this); |
230 | 271 | m_timer = timer_alloc(0); |
231 | | m_timer->adjust(initial_delay, 0, sample_time); |
232 | | m_timer->enable(true); |
| 272 | m_timer->enable(false); |
233 | 273 | |
234 | 274 | #if PUMP_DETECT_SILENCE |
235 | 275 | silent_for = 500; |
r24765 | r24766 | |
244 | 284 | last_ticks = osd_ticks(); |
245 | 285 | next_report_ticks = last_ticks + osd_ticks_per_second(); |
246 | 286 | #endif |
| 287 | |
| 288 | #if !PUMP_FAKE_ESP_PROCESSING && PUMP_REPLACE_ESP_PROGRAM |
| 289 | memset(e, 0, 0x4000 * sizeof(e[0])); |
| 290 | ei = 0; |
| 291 | #endif |
247 | 292 | } |
248 | 293 | |
249 | 294 | void esq_5505_5510_pump::device_stop() |
r24765 | r24766 | |
253 | 298 | |
254 | 299 | void esq_5505_5510_pump::device_reset() |
255 | 300 | { |
| 301 | INT64 nsec_per_sample = 100 * 16 * 21; |
| 302 | attotime sample_time(0, 1000000000 * nsec_per_sample); |
| 303 | attotime initial_delay(0, 0); |
| 304 | |
| 305 | m_timer->adjust(initial_delay, 0, sample_time); |
| 306 | m_timer->enable(true); |
256 | 307 | } |
257 | 308 | |
258 | 309 | void esq_5505_5510_pump::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) |
r24765 | r24766 | |
264 | 315 | stream_sample_t *left = outputs[0], *right = outputs[1]; |
265 | 316 | for (int i = 0; i < samples; i++) |
266 | 317 | { |
267 | | // anything for the 'aux' output? |
268 | | INT32 l = inputs[0][i] >> 4; |
269 | | INT32 r = inputs[1][i] >> 4; |
| 318 | // anything for the 'aux' output? |
| 319 | INT16 l = inputs[0][i] >> 4; |
| 320 | INT16 r = inputs[1][i] >> 4; |
270 | 321 | |
271 | 322 | // push the samples into the ESP |
272 | 323 | m_esp->ser_w(0, inputs[2][i] >> 4); |
r24765 | r24766 | |
276 | 327 | m_esp->ser_w(4, inputs[6][i] >> 4); |
277 | 328 | m_esp->ser_w(5, inputs[7][i] >> 4); |
278 | 329 | |
279 | | m_esp->ser_w(6, 0); |
280 | | m_esp->ser_w(7, 0); |
281 | | |
282 | 330 | #if PUMP_FAKE_ESP_PROCESSING |
283 | 331 | m_esp->ser_w(6, m_esp->ser_r(0) + m_esp->ser_r(2) + m_esp->ser_r(4)); |
284 | 332 | m_esp->ser_w(7, m_esp->ser_r(1) + m_esp->ser_r(3) + m_esp->ser_r(5)); |
r24765 | r24766 | |
294 | 342 | #endif |
295 | 343 | |
296 | 344 | // read the processed result from the ESP and add to the saved AUX data |
297 | | l += m_esp->ser_r(6); |
298 | | r += m_esp->ser_r(7); |
| 345 | INT16 ll = m_esp->ser_r(6); |
| 346 | INT16 rr = m_esp->ser_r(7); |
| 347 | l += ll; |
| 348 | r += rr; |
299 | 349 | |
| 350 | #if !PUMP_FAKE_ESP_PROCESSING && PUMP_REPLACE_ESP_PROGRAM |
| 351 | // if we're processing the fake program through the ESP, the result should just be that of adding the inputs |
| 352 | INT32 el = (inputs[2][i]) + (inputs[4][i]) + (inputs[6][i]); |
| 353 | INT32 er = (inputs[3][i]) + (inputs[5][i]) + (inputs[7][i]); |
| 354 | INT32 e_next = el + er; |
| 355 | e[(ei + 0x1d0f) % 0x4000] = e_next; |
| 356 | |
| 357 | if (l != e[ei]) { |
| 358 | fprintf(stderr, "expected (%d) but have (%d)\n", e[ei], l); |
| 359 | } |
| 360 | ei = (ei + 1) % 0x4000; |
| 361 | #endif |
| 362 | |
300 | 363 | // write the combined data to the output |
301 | 364 | *left++ = l; |
302 | 365 | *right++ = r; |
r24765 | r24766 | |
876 | 939 | MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") |
877 | 940 | |
878 | 941 | MCFG_SOUND_ADD("pump", ESQ_5505_5510_PUMP, XTAL_10MHz / (16 * 21)) |
879 | | MCFG_SOUND_ROUTE(0, "lspeaker", 2.0) |
880 | | MCFG_SOUND_ROUTE(1, "rspeaker", 2.0) |
| 942 | MCFG_SOUND_ROUTE(0, "lspeaker", 1.0) |
| 943 | MCFG_SOUND_ROUTE(1, "rspeaker", 1.0) |
881 | 944 | |
882 | 945 | MCFG_SOUND_ADD("otis", ES5505, XTAL_10MHz) |
883 | 946 | MCFG_SOUND_CONFIG(es5505_config) |
r24765 | r24766 | |
930 | 993 | MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker") |
931 | 994 | |
932 | 995 | MCFG_SOUND_ADD("pump", ESQ_5505_5510_PUMP, XTAL_30_4761MHz / (2 * 16 * 32)) |
933 | | MCFG_SOUND_ROUTE(0, "lspeaker", 2.0) |
934 | | MCFG_SOUND_ROUTE(1, "rspeaker", 2.0) |
| 996 | MCFG_SOUND_ROUTE(0, "lspeaker", 1.0) |
| 997 | MCFG_SOUND_ROUTE(1, "rspeaker", 1.0) |
935 | 998 | |
936 | 999 | MCFG_SOUND_ADD("otis", ES5505, XTAL_30_4761MHz / 2) |
937 | 1000 | MCFG_SOUND_CONFIG(es5505_config) |