summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/ks0164/ks0164.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/ks0164/ks0164.cpp')
-rw-r--r--src/devices/cpu/ks0164/ks0164.cpp80
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;
}