diff options
Diffstat (limited to 'src/emu/cpu/upd7725/upd7725.c')
-rwxr-xr-x | src/emu/cpu/upd7725/upd7725.c | 420 |
1 files changed, 210 insertions, 210 deletions
diff --git a/src/emu/cpu/upd7725/upd7725.c b/src/emu/cpu/upd7725/upd7725.c index 7918c454f58..a5f9d4ca923 100755 --- a/src/emu/cpu/upd7725/upd7725.c +++ b/src/emu/cpu/upd7725/upd7725.c @@ -24,8 +24,8 @@ const device_type UPD96050 = &device_creator<upd96050_device>; necdsp_device::necdsp_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, UINT32 clock, UINT32 abits, UINT32 dbits, const char *name) : cpu_device(mconfig, type, name, tag, owner, clock), - m_program_config("program", ENDIANNESS_BIG, 32, abits, -2), // data bus width, address bus width, -2 means DWORD-addressable - m_data_config("data", ENDIANNESS_BIG, 16, dbits, -1), // -1 for WORD-addressable + m_program_config("program", ENDIANNESS_BIG, 32, abits, -2), // data bus width, address bus width, -2 means DWORD-addressable + m_data_config("data", ENDIANNESS_BIG, 16, dbits, -1), // -1 for WORD-addressable m_irq(0), m_program(NULL), m_data(NULL), @@ -225,26 +225,26 @@ void necdsp_device::state_string_export(const device_state_entry &entry, astring { case UPD7725_FLAGA: string.printf("%s %s %c%c %s %s %s %s", - regs.flaga.s1 ? "S1" : "s1", - regs.flaga.s0 ? "S0" : "s0", - regs.flaga.c ? "C" : "c", - regs.flaga.z ? "Z" : "z", - regs.flaga.ov1 ? "OV1" : "ov1", - regs.flaga.ov0 ? "OV0" : "ov0", - regs.flaga.ov0p ? "OV0P" : "ov0p", - regs.flaga.ov0pp ? "OV0PP" : "ov0pp"); + regs.flaga.s1 ? "S1" : "s1", + regs.flaga.s0 ? "S0" : "s0", + regs.flaga.c ? "C" : "c", + regs.flaga.z ? "Z" : "z", + regs.flaga.ov1 ? "OV1" : "ov1", + regs.flaga.ov0 ? "OV0" : "ov0", + regs.flaga.ov0p ? "OV0P" : "ov0p", + regs.flaga.ov0pp ? "OV0PP" : "ov0pp"); break; case UPD7725_FLAGB: string.printf("%s %s %c%c %s %s %s %s", - regs.flagb.s1 ? "S1" : "s1", - regs.flagb.s0 ? "S0" : "s0", - regs.flagb.c ? "C" : "c", - regs.flagb.z ? "Z" : "z", - regs.flagb.ov1 ? "OV1" : "ov1", - regs.flagb.ov0 ? "OV0" : "ov0", - regs.flagb.ov0p ? "OV0P" : "ov0p", - regs.flagb.ov0pp ? "OV0PP" : "ov0pp"); + regs.flagb.s1 ? "S1" : "s1", + regs.flagb.s0 ? "S0" : "s0", + regs.flagb.c ? "C" : "c", + regs.flagb.z ? "Z" : "z", + regs.flagb.ov1 ? "OV1" : "ov1", + regs.flagb.ov0 ? "OV0" : "ov0", + regs.flagb.ov0p ? "OV0P" : "ov0p", + regs.flagb.ov0pp ? "OV0PP" : "ov0pp"); break; } } @@ -332,7 +332,7 @@ offs_t necdsp_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *o void necdsp_device::execute_run() { - UINT32 opcode; + UINT32 opcode; do { @@ -346,10 +346,10 @@ void necdsp_device::execute_run() regs.pc++; switch(opcode >> 22) { - case 0: exec_op(opcode); break; - case 1: exec_rt(opcode); break; - case 2: exec_jp(opcode); break; - case 3: exec_ld(opcode); break; + case 0: exec_op(opcode); break; + case 1: exec_rt(opcode); break; + case 2: exec_jp(opcode); break; + case 3: exec_ld(opcode); break; } INT32 result = (INT32)regs.k * regs.l; //sign + 30-bit result @@ -362,38 +362,38 @@ void necdsp_device::execute_run() } void necdsp_device::exec_op(UINT32 opcode) { - UINT8 pselect = (opcode >> 20)&0x3; //P select - UINT8 alu = (opcode >> 16)&0xf; //ALU operation mode - UINT8 asl = (opcode >> 15)&0x1; //accumulator select - UINT8 dpl = (opcode >> 13)&0x3; //DP low modify - UINT8 dphm = (opcode >> 9)&0xf; //DP high XOR modify - UINT8 rpdcr = (opcode >> 8)&0x1; //RP decrement - UINT8 src = (opcode >> 4)&0xf; //move source - UINT8 dst = (opcode >> 0)&0xf; //move destination - - switch(src) { - case 0: regs.idb = regs.trb; break; - case 1: regs.idb = regs.a; break; - case 2: regs.idb = regs.b; break; - case 3: regs.idb = regs.tr; break; - case 4: regs.idb = regs.dp; break; - case 5: regs.idb = regs.rp; break; - case 6: regs.idb = m_data->read_word(regs.rp<<1); break; - case 7: regs.idb = 0x8000 - regs.flaga.s1; break; //SGN - case 8: regs.idb = regs.dr; regs.sr.rqm = 1; break; - case 9: regs.idb = regs.dr; break; - case 10: regs.idb = regs.sr; break; + UINT8 pselect = (opcode >> 20)&0x3; //P select + UINT8 alu = (opcode >> 16)&0xf; //ALU operation mode + UINT8 asl = (opcode >> 15)&0x1; //accumulator select + UINT8 dpl = (opcode >> 13)&0x3; //DP low modify + UINT8 dphm = (opcode >> 9)&0xf; //DP high XOR modify + UINT8 rpdcr = (opcode >> 8)&0x1; //RP decrement + UINT8 src = (opcode >> 4)&0xf; //move source + UINT8 dst = (opcode >> 0)&0xf; //move destination + + switch(src) { + case 0: regs.idb = regs.trb; break; + case 1: regs.idb = regs.a; break; + case 2: regs.idb = regs.b; break; + case 3: regs.idb = regs.tr; break; + case 4: regs.idb = regs.dp; break; + case 5: regs.idb = regs.rp; break; + case 6: regs.idb = m_data->read_word(regs.rp<<1); break; + case 7: regs.idb = 0x8000 - regs.flaga.s1; break; //SGN + case 8: regs.idb = regs.dr; regs.sr.rqm = 1; break; + case 9: regs.idb = regs.dr; break; + case 10: regs.idb = regs.sr; break; case 11: regs.idb = regs.si; break; //MSB case 12: regs.idb = regs.si; break; //LSB - case 13: regs.idb = regs.k; break; - case 14: regs.idb = regs.l; break; - case 15: regs.idb = dataRAM[regs.dp]; break; - } + case 13: regs.idb = regs.k; break; + case 14: regs.idb = regs.l; break; + case 15: regs.idb = dataRAM[regs.dp]; break; + } - if(alu) { - UINT16 p=0, q=0, r=0; - Flag flag; - bool c=0; + if(alu) { + UINT16 p=0, q=0, r=0; + Flag flag; + bool c=0; flag.c = 0; flag.s1 = 0; @@ -402,98 +402,98 @@ void necdsp_device::exec_op(UINT32 opcode) { flag.ov0p = 0; flag.ov0pp = 0; - switch(pselect) { - case 0: p = dataRAM[regs.dp]; break; - case 1: p = regs.idb; break; - case 2: p = regs.m; break; - case 3: p = regs.n; break; - } - - switch(asl) { - case 0: q = regs.a; flag = regs.flaga; c = regs.flagb.c; break; - case 1: q = regs.b; flag = regs.flagb; c = regs.flaga.c; break; - } - - switch(alu) { - case 1: r = q | p; break; //OR - case 2: r = q & p; break; //AND - case 3: r = q ^ p; break; //XOR - case 4: r = q - p; break; //SUB - case 5: r = q + p; break; //ADD - case 6: r = q - p - c; break; //SBB - case 7: r = q + p + c; break; //ADC - case 8: r = q - 1; p = 1; break; //DEC - case 9: r = q + 1; p = 1; break; //INC - case 10: r = ~q; break; //CMP - case 11: r = (q >> 1) | (q & 0x8000); break; //SHR1 (ASR) - case 12: r = (q << 1) | (c ? 1 : 0); break; //SHL1 (ROL) - case 13: r = (q << 2) | 3; break; //SHL2 - case 14: r = (q << 4) | 15; break; //SHL4 - case 15: r = (q << 8) | (q >> 8); break; //XCHG - } - - flag.s0 = (r & 0x8000); - flag.z = (r == 0); - flag.ov0pp = flag.ov0p; - flag.ov0p = flag.ov0; - - switch(alu) { - case 1: case 2: case 3: case 10: case 13: case 14: case 15: { - flag.c = 0; - flag.ov0 = flag.ov0p = flag.ov0pp = 0; // ASSUMPTION: previous ov0 values are nulled here to make ov1 zero - break; - } - case 4: case 5: case 6: case 7: case 8: case 9: { - if(alu & 1) { - //addition - flag.ov0 = (q ^ r) & ~(q ^ p) & 0x8000; - flag.c = (r < q); - } else { - //subtraction - flag.ov0 = (q ^ r) & (q ^ p) & 0x8000; - flag.c = (r > q); - } - break; - } - case 11: { - flag.c = q & 1; - flag.ov0 = flag.ov0p = flag.ov0pp = 0; // ASSUMPTION: previous ov0 values are nulled here to make ov1 zero - break; - } - case 12: { - flag.c = q >> 15; - flag.ov0 = flag.ov0p = flag.ov0pp = 0; // ASSUMPTION: previous ov0 values are nulled here to make ov1 zero - break; - } - } - // flag.ov1 is only set if the number of overflows of the past 3 opcodes (of type 4,5,6,7,8,9) is odd - flag.ov1 = (flag.ov0 + flag.ov0p + flag.ov0pp) & 1; - // flag.s1 is based on ov1: s1 = ov1 ^ s0; - flag.s1 = flag.ov1 ^ flag.s0; - - switch(asl) { - case 0: regs.a = r; regs.flaga = flag; break; - case 1: regs.b = r; regs.flagb = flag; break; - } - } - - exec_ld((regs.idb << 6) + dst); - - switch(dpl) { - case 1: regs.dp = (regs.dp & 0xf0) + ((regs.dp + 1) & 0x0f); break; //DPINC - case 2: regs.dp = (regs.dp & 0xf0) + ((regs.dp - 1) & 0x0f); break; //DPDEC - case 3: regs.dp = (regs.dp & 0xf0); break; //DPCLR - } - - regs.dp ^= dphm << 4; - - if(rpdcr) regs.rp--; + switch(pselect) { + case 0: p = dataRAM[regs.dp]; break; + case 1: p = regs.idb; break; + case 2: p = regs.m; break; + case 3: p = regs.n; break; + } + + switch(asl) { + case 0: q = regs.a; flag = regs.flaga; c = regs.flagb.c; break; + case 1: q = regs.b; flag = regs.flagb; c = regs.flaga.c; break; + } + + switch(alu) { + case 1: r = q | p; break; //OR + case 2: r = q & p; break; //AND + case 3: r = q ^ p; break; //XOR + case 4: r = q - p; break; //SUB + case 5: r = q + p; break; //ADD + case 6: r = q - p - c; break; //SBB + case 7: r = q + p + c; break; //ADC + case 8: r = q - 1; p = 1; break; //DEC + case 9: r = q + 1; p = 1; break; //INC + case 10: r = ~q; break; //CMP + case 11: r = (q >> 1) | (q & 0x8000); break; //SHR1 (ASR) + case 12: r = (q << 1) | (c ? 1 : 0); break; //SHL1 (ROL) + case 13: r = (q << 2) | 3; break; //SHL2 + case 14: r = (q << 4) | 15; break; //SHL4 + case 15: r = (q << 8) | (q >> 8); break; //XCHG + } + + flag.s0 = (r & 0x8000); + flag.z = (r == 0); + flag.ov0pp = flag.ov0p; + flag.ov0p = flag.ov0; + + switch(alu) { + case 1: case 2: case 3: case 10: case 13: case 14: case 15: { + flag.c = 0; + flag.ov0 = flag.ov0p = flag.ov0pp = 0; // ASSUMPTION: previous ov0 values are nulled here to make ov1 zero + break; + } + case 4: case 5: case 6: case 7: case 8: case 9: { + if(alu & 1) { + //addition + flag.ov0 = (q ^ r) & ~(q ^ p) & 0x8000; + flag.c = (r < q); + } else { + //subtraction + flag.ov0 = (q ^ r) & (q ^ p) & 0x8000; + flag.c = (r > q); + } + break; + } + case 11: { + flag.c = q & 1; + flag.ov0 = flag.ov0p = flag.ov0pp = 0; // ASSUMPTION: previous ov0 values are nulled here to make ov1 zero + break; + } + case 12: { + flag.c = q >> 15; + flag.ov0 = flag.ov0p = flag.ov0pp = 0; // ASSUMPTION: previous ov0 values are nulled here to make ov1 zero + break; + } + } + // flag.ov1 is only set if the number of overflows of the past 3 opcodes (of type 4,5,6,7,8,9) is odd + flag.ov1 = (flag.ov0 + flag.ov0p + flag.ov0pp) & 1; + // flag.s1 is based on ov1: s1 = ov1 ^ s0; + flag.s1 = flag.ov1 ^ flag.s0; + + switch(asl) { + case 0: regs.a = r; regs.flaga = flag; break; + case 1: regs.b = r; regs.flagb = flag; break; + } + } + + exec_ld((regs.idb << 6) + dst); + + switch(dpl) { + case 1: regs.dp = (regs.dp & 0xf0) + ((regs.dp + 1) & 0x0f); break; //DPINC + case 2: regs.dp = (regs.dp & 0xf0) + ((regs.dp - 1) & 0x0f); break; //DPDEC + case 3: regs.dp = (regs.dp & 0xf0); break; //DPCLR + } + + regs.dp ^= dphm << 4; + + if(rpdcr) regs.rp--; } void necdsp_device::exec_rt(UINT32 opcode) { - exec_op(opcode); - regs.pc = regs.stack[--regs.sp]; - regs.sp &= 0xf; + exec_op(opcode); + regs.pc = regs.stack[--regs.sp]; + regs.sp &= 0xf; } void necdsp_device::exec_jp(UINT32 opcode) { @@ -505,81 +505,81 @@ void necdsp_device::exec_jp(UINT32 opcode) { UINT16 jpl = (bank << 11) | (na << 0); switch(brch) { - case 0x000: regs.pc = regs.so; return; //JMPSO - - case 0x080: if(regs.flaga.c == 0) regs.pc = jps; return; //JNCA - case 0x082: if(regs.flaga.c == 1) regs.pc = jps; return; //JCA - case 0x084: if(regs.flagb.c == 0) regs.pc = jps; return; //JNCB - case 0x086: if(regs.flagb.c == 1) regs.pc = jps; return; //JCB - - case 0x088: if(regs.flaga.z == 0) regs.pc = jps; return; //JNZA - case 0x08a: if(regs.flaga.z == 1) regs.pc = jps; return; //JZA - case 0x08c: if(regs.flagb.z == 0) regs.pc = jps; return; //JNZB - case 0x08e: if(regs.flagb.z == 1) regs.pc = jps; return; //JZB - - case 0x090: if(regs.flaga.ov0 == 0) regs.pc = jps; return; //JNOVA0 - case 0x092: if(regs.flaga.ov0 == 1) regs.pc = jps; return; //JOVA0 - case 0x094: if(regs.flagb.ov0 == 0) regs.pc = jps; return; //JNOVB0 - case 0x096: if(regs.flagb.ov0 == 1) regs.pc = jps; return; //JOVB0 - - case 0x098: if(regs.flaga.ov1 == 0) regs.pc = jps; return; //JNOVA1 - case 0x09a: if(regs.flaga.ov1 == 1) regs.pc = jps; return; //JOVA1 - case 0x09c: if(regs.flagb.ov1 == 0) regs.pc = jps; return; //JNOVB1 - case 0x09e: if(regs.flagb.ov1 == 1) regs.pc = jps; return; //JOVB1 - - case 0x0a0: if(regs.flaga.s0 == 0) regs.pc = jps; return; //JNSA0 - case 0x0a2: if(regs.flaga.s0 == 1) regs.pc = jps; return; //JSA0 - case 0x0a4: if(regs.flagb.s0 == 0) regs.pc = jps; return; //JNSB0 - case 0x0a6: if(regs.flagb.s0 == 1) regs.pc = jps; return; //JSB0 - - case 0x0a8: if(regs.flaga.s1 == 0) regs.pc = jps; return; //JNSA1 - case 0x0aa: if(regs.flaga.s1 == 1) regs.pc = jps; return; //JSA1 - case 0x0ac: if(regs.flagb.s1 == 0) regs.pc = jps; return; //JNSB1 - case 0x0ae: if(regs.flagb.s1 == 1) regs.pc = jps; return; //JSB1 - - case 0x0b0: if((regs.dp & 0x0f) == 0x00) regs.pc = jps; return; //JDPL0 - case 0x0b1: if((regs.dp & 0x0f) != 0x00) regs.pc = jps; return; //JDPLN0 - case 0x0b2: if((regs.dp & 0x0f) == 0x0f) regs.pc = jps; return; //JDPLF - case 0x0b3: if((regs.dp & 0x0f) != 0x0f) regs.pc = jps; return; //JDPLNF - - case 0x0bc: if(regs.sr.rqm == 0) regs.pc = jps; return; //JNRQM - case 0x0be: if(regs.sr.rqm == 1) regs.pc = jps; return; //JRQM - - case 0x100: regs.pc = 0x0000 | jpl; return; //LJMP - case 0x101: regs.pc = 0x2000 | jpl; return; //HJMP - - case 0x140: regs.stack[regs.sp++] = regs.pc; regs.pc = 0x0000 | jpl; regs.sp &= 0xf; return; //LCALL - case 0x141: regs.stack[regs.sp++] = regs.pc; regs.pc = 0x2000 | jpl; regs.sp &= 0xf; return; //HCALL + case 0x000: regs.pc = regs.so; return; //JMPSO + + case 0x080: if(regs.flaga.c == 0) regs.pc = jps; return; //JNCA + case 0x082: if(regs.flaga.c == 1) regs.pc = jps; return; //JCA + case 0x084: if(regs.flagb.c == 0) regs.pc = jps; return; //JNCB + case 0x086: if(regs.flagb.c == 1) regs.pc = jps; return; //JCB + + case 0x088: if(regs.flaga.z == 0) regs.pc = jps; return; //JNZA + case 0x08a: if(regs.flaga.z == 1) regs.pc = jps; return; //JZA + case 0x08c: if(regs.flagb.z == 0) regs.pc = jps; return; //JNZB + case 0x08e: if(regs.flagb.z == 1) regs.pc = jps; return; //JZB + + case 0x090: if(regs.flaga.ov0 == 0) regs.pc = jps; return; //JNOVA0 + case 0x092: if(regs.flaga.ov0 == 1) regs.pc = jps; return; //JOVA0 + case 0x094: if(regs.flagb.ov0 == 0) regs.pc = jps; return; //JNOVB0 + case 0x096: if(regs.flagb.ov0 == 1) regs.pc = jps; return; //JOVB0 + + case 0x098: if(regs.flaga.ov1 == 0) regs.pc = jps; return; //JNOVA1 + case 0x09a: if(regs.flaga.ov1 == 1) regs.pc = jps; return; //JOVA1 + case 0x09c: if(regs.flagb.ov1 == 0) regs.pc = jps; return; //JNOVB1 + case 0x09e: if(regs.flagb.ov1 == 1) regs.pc = jps; return; //JOVB1 + + case 0x0a0: if(regs.flaga.s0 == 0) regs.pc = jps; return; //JNSA0 + case 0x0a2: if(regs.flaga.s0 == 1) regs.pc = jps; return; //JSA0 + case 0x0a4: if(regs.flagb.s0 == 0) regs.pc = jps; return; //JNSB0 + case 0x0a6: if(regs.flagb.s0 == 1) regs.pc = jps; return; //JSB0 + + case 0x0a8: if(regs.flaga.s1 == 0) regs.pc = jps; return; //JNSA1 + case 0x0aa: if(regs.flaga.s1 == 1) regs.pc = jps; return; //JSA1 + case 0x0ac: if(regs.flagb.s1 == 0) regs.pc = jps; return; //JNSB1 + case 0x0ae: if(regs.flagb.s1 == 1) regs.pc = jps; return; //JSB1 + + case 0x0b0: if((regs.dp & 0x0f) == 0x00) regs.pc = jps; return; //JDPL0 + case 0x0b1: if((regs.dp & 0x0f) != 0x00) regs.pc = jps; return; //JDPLN0 + case 0x0b2: if((regs.dp & 0x0f) == 0x0f) regs.pc = jps; return; //JDPLF + case 0x0b3: if((regs.dp & 0x0f) != 0x0f) regs.pc = jps; return; //JDPLNF + + case 0x0bc: if(regs.sr.rqm == 0) regs.pc = jps; return; //JNRQM + case 0x0be: if(regs.sr.rqm == 1) regs.pc = jps; return; //JRQM + + case 0x100: regs.pc = 0x0000 | jpl; return; //LJMP + case 0x101: regs.pc = 0x2000 | jpl; return; //HJMP + + case 0x140: regs.stack[regs.sp++] = regs.pc; regs.pc = 0x0000 | jpl; regs.sp &= 0xf; return; //LCALL + case 0x141: regs.stack[regs.sp++] = regs.pc; regs.pc = 0x2000 | jpl; regs.sp &= 0xf; return; //HCALL } } void necdsp_device::exec_ld(UINT32 opcode) { - UINT16 id = opcode >> 6; //immediate data - UINT8 dst = (opcode >> 0) & 0xf; //destination - - regs.idb = id; - - switch(dst) { - case 0: break; - case 1: regs.a = id; break; - case 2: regs.b = id; break; - case 3: regs.tr = id; break; - case 4: regs.dp = id; break; - case 5: regs.rp = id; break; - case 6: regs.dr = id; regs.sr.rqm = 1; break; - case 7: regs.sr = (regs.sr & 0x907c) | (id & ~0x907c); - m_out_p0_func(regs.sr&0x1); - m_out_p1_func((regs.sr&0x2)>>1); - break; + UINT16 id = opcode >> 6; //immediate data + UINT8 dst = (opcode >> 0) & 0xf; //destination + + regs.idb = id; + + switch(dst) { + case 0: break; + case 1: regs.a = id; break; + case 2: regs.b = id; break; + case 3: regs.tr = id; break; + case 4: regs.dp = id; break; + case 5: regs.rp = id; break; + case 6: regs.dr = id; regs.sr.rqm = 1; break; + case 7: regs.sr = (regs.sr & 0x907c) | (id & ~0x907c); + m_out_p0_func(regs.sr&0x1); + m_out_p1_func((regs.sr&0x2)>>1); + break; case 8: regs.so = id; break; //LSB case 9: regs.so = id; break; //MSB - case 10: regs.k = id; break; - case 11: regs.k = id; regs.l = m_data->read_word(regs.rp<<1); break; - case 12: regs.l = id; regs.k = dataRAM[regs.dp | 0x40]; break; - case 13: regs.l = id; break; - case 14: regs.trb = id; break; - case 15: dataRAM[regs.dp] = id; break; - } + case 10: regs.k = id; break; + case 11: regs.k = id; regs.l = m_data->read_word(regs.rp<<1); break; + case 12: regs.l = id; regs.k = dataRAM[regs.dp | 0x40]; break; + case 13: regs.l = id; break; + case 14: regs.trb = id; break; + case 15: dataRAM[regs.dp] = id; break; + } } UINT8 necdsp_device::snesdsp_read(bool mode) { |