diff options
Diffstat (limited to 'src/devices/cpu/ks0164/ks0164.cpp')
-rw-r--r-- | src/devices/cpu/ks0164/ks0164.cpp | 80 |
1 files changed, 55 insertions, 25 deletions
diff --git a/src/devices/cpu/ks0164/ks0164.cpp b/src/devices/cpu/ks0164/ks0164.cpp index 5b8f57fb776..436415f1b34 100644 --- a/src/devices/cpu/ks0164/ks0164.cpp +++ b/src/devices/cpu/ks0164/ks0164.cpp @@ -9,11 +9,6 @@ DEFINE_DEVICE_TYPE(KS0164CPU, ks0164_cpu_device, "ks0164cpu", "Samsung KS0164 audio processor") -const u16 ks0164_cpu_device::imask[16] = { - 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff, - 0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff -}; - ks0164_cpu_device::ks0164_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : cpu_device(mconfig, KS0164CPU, tag, owner, clock) , m_program_config("program", ENDIANNESS_BIG, 16, 16) @@ -105,7 +100,7 @@ void ks0164_cpu_device::state_string_export(const device_state_entry &entry, std void ks0164_cpu_device::handle_irq() { - u16 mask = m_irq & imask[m_r[R_PSW] & 15]; + u16 mask = m_irq & util::make_bitmask<u16>((m_r[R_PSW] & 15) + 1); if(mask) { int index; for(index = 0; !(mask & (1 << index)); index ++); @@ -113,6 +108,7 @@ void ks0164_cpu_device::handle_irq() // Normal irq (not reset), save pc and psw if(m_r[R_PSW] & F_I) return; + standard_irq_callback(0, m_r[R_PC]); m_program.write_word(m_r[R_SP] - 2, m_r[R_PC]); m_program.write_word(m_r[R_SP] - 4, m_r[R_PSW]); m_r[R_SP] -= 4; @@ -123,8 +119,6 @@ void ks0164_cpu_device::handle_irq() m_r[R_PSW] = (m_r[R_PSW] & 0xfff0) | (index ? index - 1 : 0); m_r[R_PC] = m_program_cache.read_word(index*2); m_icount --; - if(index) - standard_irq_callback(0); } } @@ -259,16 +253,13 @@ void ks0164_cpu_device::execute_run() case 0x9: cond = !(m_r[R_PSW] & F_Z) && !(m_r[R_PSW] & F_C); break; case 0xa: cond = (m_r[R_PSW] & F_Z) || (m_r[R_PSW] & F_C); break; case 0xb: cond = (!(m_r[R_PSW] & F_Z) && (m_r[R_PSW] & F_N) && (m_r[R_PSW] & F_V)) || (!(m_r[R_PSW] & F_Z) && !(m_r[R_PSW] & F_V) && !(m_r[R_PSW] & F_N)); break; - case 0xc: cond = (m_r[R_PSW] & F_Z) || ((m_r[R_PSW] & F_N) && !(m_r[R_PSW] & F_V)) || ((m_r[R_PSW] & F_V) && !(m_r[R_PSW] & F_N)); break; - case 0xd: cond = ((m_r[R_PSW] & F_N) && (m_r[R_PSW] & F_V)) || (!(m_r[R_PSW] & F_V) && !(m_r[R_PSW] & F_N)); break; + case 0xc: cond = ((m_r[R_PSW] & F_N) && (m_r[R_PSW] & F_V)) || (!(m_r[R_PSW] & F_V) && !(m_r[R_PSW] & F_N)); break; + case 0xd: cond = (m_r[R_PSW] & F_Z) || ((m_r[R_PSW] & F_N) && !(m_r[R_PSW] & F_V)) || ((m_r[R_PSW] & F_V) && !(m_r[R_PSW] & F_N)); break; case 0xe: cond = ((m_r[R_PSW] & F_N) && !(m_r[R_PSW] & F_V)) || ((m_r[R_PSW] & F_V) && !(m_r[R_PSW] & F_N)); break; case 0xf: default: cond = true; break; } if(cond) { - if(opcode & 0x200) - m_r[R_PC] += opcode | 0xfc00; - else - m_r[R_PC] += opcode & 0x3ff; + m_r[R_PC] += util::sext(opcode, 10); } break; } @@ -344,16 +335,16 @@ void ks0164_cpu_device::execute_run() case 1: { // Min/max with immediate - // 1101 Mrrr Ssss 1000 - u16 v1 = m_r[(opcode >> 4) & 7]; + // 1101 Mrrr S000 1000 + u16 v1 = m_r[(opcode >> 8) & 7]; u16 v2 = m_program_cache.read_word(m_r[R_PC]); m_r[R_PC] += 2; u16 res; switch(bitswap<2>(opcode, 11, 7)) { - case 0: res = v1 > v2 ? v1 : v2; break; - case 1: res = s16(v1) > s16(v2) ? v1 : v2; break; - case 2: res = v1 < v2 ? v1 : v2; break; - case 3: default: res = s16(v1) < s16(v2) ? v1 : v2; break; + case 0: res = std::max<u16>(v1, v2); break; + case 1: res = std::max<s16>(v1, v2); break; + case 2: res = std::min<u16>(v1, v2); break; + case 3: default: res = std::min<s16>(v1, v2); break; } m_r[(opcode >> 8) & 7] = res; break; @@ -471,7 +462,7 @@ void ks0164_cpu_device::execute_run() case 0x1b: { switch((opcode >> 12) & 3) { case 0: { - // Push all registers + // Pop all registers // 1100 .... .... .011 m_r[0] = m_program.read_word(m_r[R_SP] + 6); @@ -559,7 +550,7 @@ void ks0164_cpu_device::execute_run() case 2: { // Bit clear in register - // 1110 .rrr bbbb .001 + // 1110 .rrr bbbb .100 if(m_r[(opcode >> 8) & 7] & (1 << ((opcode >> 4) & 0xf))) { m_r[(opcode >> 8) & 7] &= ~(1 << ((opcode >> 4) & 0xf)); m_r[R_PSW] &= ~F_Z; @@ -570,6 +561,7 @@ void ks0164_cpu_device::execute_run() case 3: { // Decrement and branch + // 1111 .rrr .... .100 int r = (opcode >> 8) & 7; u16 a = m_program_cache.read_word(m_r[R_PC]); m_r[R_PC] += 2; @@ -616,13 +608,14 @@ void ks0164_cpu_device::execute_run() case 1: { // Neg/not - // 1101 .rrr Ssss .101 + // 1101 .rrr S... .101 - u16 v = m_r[(opcode >> 4) & 7]; + u16 v = m_r[(opcode >> 8) & 7]; if(opcode & 0x0080) v = -s16(v); else v = ~v; + m_r[(opcode >> 8) & 7] = v; m_r[R_PSW] = (m_r[R_PSW] & ~F_MASK) | (v ? v & 0x8000 ? F_N : 0 : F_Z); break; } @@ -652,7 +645,44 @@ void ks0164_cpu_device::execute_run() case 0x1e: { switch((opcode >> 12) & 3) { case 0: { - unk(opcode); + // Rotate without carry? + // 1100 drrr nnnn .110 + /* + From btplay2k flash.u22: + Surrounding code gives some context to usage here? + opcode is sandwiched between other shift/rotate commands + 6E2C: 7010 r0 = 10 + 6E2E: 8817 0001 r0 -= (r1 + 1).bu + 6E32: 0406 beq 6e3a + 6E34: CA1C r2 >>= 1 + 6E36: F004 6E34 dbra r0, 6e34 + ... + 6E52: B017 0001 r0 = (r1 + 1).bu + 6E56: CA1E ?ca1e + 6E58: F004 6E56 dbra r0, 6e56 + */ + + int r = (opcode >> 8) & 7; + int shift = (opcode >> 4) & 0xf; + u16 v1 = m_r[r]; + u16 res; + + if(!shift) { + m_r[R_PSW] = (m_r[R_PSW] & ~F_MASK) | (v1 ? v1 & 0x8000 ? F_N : 0 : F_Z); + res = v1; + } else if(opcode & 0x0800) { + res = (v1 >> shift) | (v1 << (16 - shift)); + u16 f = res ? 0 : F_Z; + if(v1 & (1 << (shift - 1))) + f |= F_C; + m_r[R_PSW] = (m_r[R_PSW] & ~F_MASK) | f; + } else { + res = (v1 << shift) | (v1 >> (16 - shift)); + u16 f = res ? res & 0x8000 ? F_N : 0 : F_Z; + if(v1 & (1 << (16-shift))) + f |= F_C; + m_r[R_PSW] = (m_r[R_PSW] & ~F_MASK) | f; + } + m_r[r] = res; break; } |