diff options
Diffstat (limited to 'src/devices/cpu/unsp/unsp_fxxx.cpp')
-rw-r--r-- | src/devices/cpu/unsp/unsp_fxxx.cpp | 431 |
1 files changed, 431 insertions, 0 deletions
diff --git a/src/devices/cpu/unsp/unsp_fxxx.cpp b/src/devices/cpu/unsp/unsp_fxxx.cpp new file mode 100644 index 00000000000..c63b02c4ad0 --- /dev/null +++ b/src/devices/cpu/unsp/unsp_fxxx.cpp @@ -0,0 +1,431 @@ +// license:GPL-2.0+ +// copyright-holders:Segher Boessenkool, Ryan Holtz, David Haywood + +#include "emu.h" +#include "unsp.h" +#include "unspfe.h" + +#include "debugger.h" + +#include "unspdasm.h" + +inline void unsp_device::execute_fxxx_000_group(uint16_t op) +{ + // | | | + // DS16 1 1 1 1 1 1 1 0 0 0 i i i i i i + // DS Reg 1 1 1 1 - - - 0 0 0 1 0 w r r r + // FR Reg 1 1 1 1 - - - 0 0 0 1 1 w r r r + + if (((op & 0xffc0) == 0xfe00) && m_iso >= 12) + { + // ds = imm6 + int imm = op & 0x003f; + set_ds(imm); + return; + } + else if (((op & 0xf1f8) == 0xf020) && m_iso >= 12) + { + // rx = ds + int r = op & 0x7; + m_core->m_r[r] = get_ds(); + return; + } + else if (((op & 0xf1f8) == 0xf028) && m_iso >= 12) + { + // ds = rx + int r = op & 0x7; + set_ds(m_core->m_r[r]); + return; + } + else if (((op & 0xf1f8) == 0xf030) && m_iso >= 12) + { + int r = op & 0x7; + logerror("%s = fr\n", regs[r]); + unimplemented_opcode(op); + return; + } + else if (((op & 0xf1f8) == 0xf038) && m_iso >= 12) + { + int r = op & 0x7; + logerror("fr = %s\n", regs[r]); + unimplemented_opcode(op); + return; + } + + // everything else falls through to the multiply + + // signed * unsigned + // MUL 1 1 1 1* r r r 0* 0 0 0 0 1 r r r (** = sign bits, fixed here) + const uint16_t opa = (op >> 9) & 7; + const uint16_t opb = op & 7; + m_core->m_icount -= 12; + uint32_t lres = m_core->m_r[opa] * m_core->m_r[opb]; + if (m_core->m_r[opb] & 0x8000) + { + lres -= m_core->m_r[opa] << 16; + } + m_core->m_r[REG_R4] = lres >> 16; + m_core->m_r[REG_R3] = (uint16_t)lres; + + return; +} + +inline void unsp_device::execute_fxxx_001_group(uint16_t op) +{ + // | | | + // CALL16 1 1 1 1 - - 0 0 0 1 a a a a a a (+imm16) + + if ((op & 0xf3c0) == 0xf040) + { + m_core->m_icount -= 9; + uint16_t r1 = read16(UNSP_LPC); + add_lpc(1); + push(m_core->m_r[REG_PC], &m_core->m_r[REG_SP]); + push(m_core->m_r[REG_SR], &m_core->m_r[REG_SP]); + m_core->m_r[REG_PC] = r1; + m_core->m_r[REG_SR] &= 0xffc0; + m_core->m_r[REG_SR] |= op & 0x3f; + return; + } + // MEM bitop 1 1 1 1 - D 1 0 0 1 b b o o o o (+imm16) ( BITOP {ds:}[A16],offset ) + else if (((op & 0xf3c0) == 0xf240) && m_iso >= 20) + { + uint8_t bitop = (op & 0x0030) >> 4; + uint8_t offset = (op & 0x000f) >> 0; + uint8_t d = (op & 0x0400) >> 10; + + if (d) + { + logerror("%s ds:[$04x],%d\n", bitops[bitop], offset); + unimplemented_opcode(op); + } + else + { + logerror("%s [$04x],%d\n", bitops[bitop], offset); + unimplemented_opcode(op); + } + + return; + } + + logerror("<DUNNO>\n"); + unimplemented_opcode(op); + return; +} + +inline void unsp_device::execute_fxxx_010_group(uint16_t op) +{ + // | | | + // JMPF 1 1 1 1 1 1 1 0 1 0 a a a a a a (+imm16) + + if ((op & 0xffc0) == 0xfe80) // apparently 1.2 and above, but jak_capb needs it and otherwise seems 1.0 / 1.1? + { + m_core->m_icount -= 5; + m_core->m_r[REG_PC] = read16(UNSP_LPC); + m_core->m_r[REG_SR] &= 0xffc0; + m_core->m_r[REG_SR] |= op & 0x3f; + return; + } + + // signed * unsigned (size 16,1,2,3,4,5,6,7) + // MULS 1 1 1 1* r r r 0* 1 0*s s s r r r (1* = sign bit, 0* = sign bit 0* = upper size bit) + + // MULS us with upper size bit not set + logerror("MULS us\n"); + unimplemented_opcode(op); + return; +} + +inline void unsp_device::execute_fxxx_011_group(uint16_t op) +{ + // | | | + // JMPR 1 1 1 1 1 1 1 0 1 1 - - - - - - + if (((op & 0xffc0) == 0xfec0) && m_iso >= 12) + { + logerror("goto mr\n"); + unimplemented_opcode(op); + return; + } + + // signed * unsigned (size 8,9,10,11,12,13,14,15) + // MULS 1 1 1 1* r r r 0* 1 1*s s s r r r (1* = sign bit, 0* = sign bit 1* = upper size bit) + + // MULS us with upper size bit set + logerror("MULS us\n"); + unimplemented_opcode(op); + + return; +} + +inline void unsp_device::execute_fxxx_100_group(uint16_t op) +{ + // | | | + // signed * signed + // MUL 1 1 1 1* r r r 1* 0 0 0 0 1 r r r (** = sign bits, fixed here) + + if ((op & 0xf1f8) == 0xf108) + { + uint32_t lres = 0; + + const uint16_t opa = (op >> 9) & 7; + const uint16_t opb = op & 7; + + m_core->m_icount -= 12; + lres = m_core->m_r[opa] * m_core->m_r[opb]; + if (m_core->m_r[opb] & 0x8000) + { + lres -= m_core->m_r[opa] << 16; + } + if (m_core->m_r[opa] & 0x8000) + { + lres -= m_core->m_r[opb] << 16; + } + m_core->m_r[REG_R4] = lres >> 16; + m_core->m_r[REG_R3] = (uint16_t)lres; + return; + } + + logerror("<DUNNO>\n"); + unimplemented_opcode(op); + return; +} + + +inline void unsp_12_device::execute_fxxx_101_group(uint16_t op) +{ + // FIR_MOV 1 1 1 1 - - - 1 0 1 0 0 0 1 0 f + // Fraction 1 1 1 1 - - - 1 0 1 0 0 0 1 1 f + // SECBANK 1 1 1 1 - - - 1 0 1 0 0 1 0 1 S + // NESTMODE 1 1 1 1 - - - 1 0 1 0 0 1 1 N 1 + // CALLR 1 1 1 1 - - - 1 0 1 1 - - 0 0 1 + // DIVS 1 1 1 1 - - - 1 0 1 1 - - 0 1 0 + // DIVQ 1 1 1 1 - - - 1 0 1 1 - - 0 1 1 + // EXP 1 1 1 1 - - - 1 0 1 1 - - 1 0 0 + + switch (op) + { + case 0xf146: case 0xf346: case 0xf546: case 0xf746: case 0xf946: case 0xfb46: case 0xfd46: case 0xff46: + logerror("fraction off\n"); + unimplemented_opcode(op); + return; + + case 0xf147: case 0xf347: case 0xf547: case 0xf747: case 0xf947: case 0xfb47: case 0xfd47: case 0xff47: + logerror("fraction on\n"); + unimplemented_opcode(op); + return; + + case 0xf14a: case 0xf34a: case 0xf54a: case 0xf74a: case 0xf94a: case 0xfb4a: case 0xfd4a: case 0xff4a: + logerror("secbank off\n"); + unimplemented_opcode(op); + return; + + case 0xf14b: case 0xf34b: case 0xf54b: case 0xf74b: case 0xf94b: case 0xfb4b: case 0xfd4b: case 0xff4b: + logerror("secbank on\n"); + unimplemented_opcode(op); + return; + + case 0xf14d: case 0xf34d: case 0xf54d: case 0xf74d: case 0xf94d: case 0xfb4d: case 0xfd4d: case 0xff4d: + logerror("irqnest off\n"); + unimplemented_opcode(op); + return; + + case 0xf14f: case 0xf34f: case 0xf54f: case 0xf74f: case 0xf94f: case 0xfb4f: case 0xfd4f: case 0xff4f: + logerror("irqnest on\n"); + unimplemented_opcode(op); + return; + + case 0xf144: case 0xf344: case 0xf544: case 0xf744: case 0xf944: case 0xfb44: case 0xfd44: case 0xff44: + logerror("fir_mov on\n"); + unimplemented_opcode(op); + return; + + case 0xf145: case 0xf345: case 0xf545: case 0xf745: case 0xf945: case 0xfb45: case 0xfd45: case 0xff45: + logerror("fir_mov off\n"); + unimplemented_opcode(op); + return; + + case 0xf161: case 0xf361: case 0xf561: case 0xf761: case 0xf961: case 0xfb61: case 0xfd61: case 0xff61: + case 0xf169: case 0xf369: case 0xf569: case 0xf769: case 0xf969: case 0xfb69: case 0xfd69: case 0xff69: + case 0xf171: case 0xf371: case 0xf571: case 0xf771: case 0xf971: case 0xfb71: case 0xfd71: case 0xff71: + case 0xf179: case 0xf379: case 0xf579: case 0xf779: case 0xf979: case 0xfb79: case 0xfd79: case 0xff79: + { + m_core->m_icount -= 1; // unknown count + uint32_t addr = m_core->m_r[REG_R3] | ((m_core->m_r[REG_R4] & 0x3f) << 16); + add_lpc(1); + push(m_core->m_r[REG_PC], &m_core->m_r[REG_SP]); + push(m_core->m_r[REG_SR], &m_core->m_r[REG_SP]); + m_core->m_r[REG_PC] = addr & 0x0000ffff; + m_core->m_r[REG_SR] &= 0xffc0; + m_core->m_r[REG_SR] |= ((addr & 0x003f0000) >> 16); + return; + } + + case 0xf162: case 0xf362: case 0xf562: case 0xf762: case 0xf962: case 0xfb62: case 0xfd62: case 0xff62: + case 0xf16a: case 0xf36a: case 0xf56a: case 0xf76a: case 0xf96a: case 0xfb6a: case 0xfd6a: case 0xff6a: + case 0xf172: case 0xf372: case 0xf572: case 0xf772: case 0xf972: case 0xfb72: case 0xfd72: case 0xff72: + case 0xf17a: case 0xf37a: case 0xf57a: case 0xf77a: case 0xf97a: case 0xfb7a: case 0xfd7a: case 0xff7a: + logerror("divs mr, r2\n"); + unimplemented_opcode(op); + return; + + case 0xf163: case 0xf363: case 0xf563: case 0xf763: case 0xf963: case 0xfb63: case 0xfd63: case 0xff63: + case 0xf16b: case 0xf36b: case 0xf56b: case 0xf76b: case 0xf96b: case 0xfb6b: case 0xfd6b: case 0xff6b: + case 0xf173: case 0xf373: case 0xf573: case 0xf773: case 0xf973: case 0xfb73: case 0xfd73: case 0xff73: + case 0xf17b: case 0xf37b: case 0xf57b: case 0xf77b: case 0xf97b: case 0xfb7b: case 0xfd7b: case 0xff7b: + logerror("divq mr, r2\n"); + unimplemented_opcode(op); + return; + + case 0xf164: case 0xf364: case 0xf564: case 0xf764: case 0xf964: case 0xfb64: case 0xfd64: case 0xff64: + case 0xf16c: case 0xf36c: case 0xf56c: case 0xf76c: case 0xf96c: case 0xfb6c: case 0xfd6c: case 0xff6c: + case 0xf174: case 0xf374: case 0xf574: case 0xf774: case 0xf974: case 0xfb74: case 0xfd74: case 0xff74: + case 0xf17c: case 0xf37c: case 0xf57c: case 0xf77c: case 0xf97c: case 0xfb7c: case 0xfd7c: case 0xff7c: + //unimplemented_opcode(op); + // what is this, sign extend / sign expand / zero expand? it doesn't seem to be exponent + logerror("r2 = exp r4 (with r2 = %04x r4 = %04x)\n", m_core->m_r[REG_R2], m_core->m_r[REG_R4]); + m_core->m_r[REG_R2] = 0x0001; // WRONG!! + return; + + + default: + return unsp_device::execute_fxxx_101_group(op); + } +} + + +inline void unsp_device::execute_fxxx_101_group(uint16_t op) +{ + // | | | + // INT SET 1 1 1 1 - - - 1 0 1 0 0 0 0 F I + // BREAK 1 1 1 1 - - - 1 0 1 1 - - 0 0 0 + // NOP 1 1 1 1 - - - 1 0 1 1 - - 1 0 1 + + // IRQ 1 1 1 1 - - - 1 0 1 0 0 1 0 0 I + // FIRQ 1 1 1 1 - - - 1 0 1 0 0 1 1 F 0 + + m_core->m_icount -= 2; + + switch (op) + { + case 0xf140: case 0xf340: case 0xf540: case 0xf740: case 0xf940: case 0xfb40: case 0xfd40: case 0xff40: + m_core->m_enable_irq = 0; + m_core->m_enable_fiq = 0; + return; + + case 0xf141: case 0xf341: case 0xf541: case 0xf741: case 0xf941: case 0xfb41: case 0xfd41: case 0xff41: + m_core->m_enable_irq = 1; + m_core->m_enable_fiq = 0; + return; + + case 0xf142: case 0xf342: case 0xf542: case 0xf742: case 0xf942: case 0xfb42: case 0xfd42: case 0xff42: + m_core->m_enable_irq = 0; + m_core->m_enable_fiq = 1; + return; + + case 0xf143: case 0xf343: case 0xf543: case 0xf743: case 0xf943: case 0xfb43: case 0xfd43: case 0xff43: + m_core->m_enable_irq = 1; + m_core->m_enable_fiq = 1; + return; + + case 0xf160: case 0xf360: case 0xf560: case 0xf760: case 0xf960: case 0xfb60: case 0xfd60: case 0xff60: + case 0xf168: case 0xf368: case 0xf568: case 0xf768: case 0xf968: case 0xfb68: case 0xfd68: case 0xff68: + case 0xf170: case 0xf370: case 0xf570: case 0xf770: case 0xf970: case 0xfb70: case 0xfd70: case 0xff70: + case 0xf178: case 0xf378: case 0xf578: case 0xf778: case 0xf978: case 0xfb78: case 0xfd78: case 0xff78: + unimplemented_opcode(op); + return; + + case 0xf165: case 0xf365: case 0xf565: case 0xf765: case 0xf965: case 0xfb65: case 0xfd65: case 0xff65: + case 0xf16d: case 0xf36d: case 0xf56d: case 0xf76d: case 0xf96d: case 0xfb6d: case 0xfd6d: case 0xff6d: + case 0xf175: case 0xf375: case 0xf575: case 0xf775: case 0xf975: case 0xfb75: case 0xfd75: case 0xff75: + case 0xf17d: case 0xf37d: case 0xf57d: case 0xf77d: case 0xf97d: case 0xfb7d: case 0xfd7d: case 0xff7d: + // nothing + return; + + // these are in code that otherwise seems like ISA1.0 / 1.1 (jak_disf for example) but spec says it's only in ISA 1.2? + case 0xf148: case 0xf348: case 0xf548: case 0xf748: case 0xf948: case 0xfb48: case 0xfd48: case 0xff48: + m_core->m_enable_irq = 0; + return; + + case 0xf149: case 0xf349: case 0xf549: case 0xf749: case 0xf949: case 0xfb49: case 0xfd49: case 0xff49: + m_core->m_enable_irq = 1; + return; + + case 0xf14c: case 0xf34c: case 0xf54c: case 0xf74c: case 0xf94c: case 0xfb4c: case 0xfd4c: case 0xff4c: + m_core->m_enable_fiq = 0; + return; + + case 0xf14e: case 0xf34e: case 0xf54e: case 0xf74e: case 0xf94e: case 0xfb4e: case 0xfd4e: case 0xff4e: + m_core->m_enable_fiq = 1; + return; + + default: + unimplemented_opcode(op); + return; + } + + return; +} + + +inline void unsp_device::execute_fxxx_110_group(uint16_t op) +{ + //uint32_t len = 1; + // | | | + // signed * signed (size 16,1,2,3,4,5,6,7) + // MULS 1 1 1 1* r r r 1* 1 0*s s s r r r (1* = sign bit, 1* = sign bit 0* = upper size bit) + + // MULS ss with upper size bit not set + unimplemented_opcode(op); + //return; +} + +inline void unsp_device::execute_fxxx_111_group(uint16_t op) +{ + //uint32_t len = 1; + // | | | + // EXTOP 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 (+16 bit imm) + if ((op == 0xffc0) && m_iso >= 20) + { + return execute_extended_group(op); + } + + // signed * signed (size 8,9,10,11,12,13,14,15) + // MULS 1 1 1 1* r r r 1* 1 1*s s s r r r (1* = sign bit, 1* = sign bit 1* = upper size bit) + + // MULS ss with upper size bit set. + unimplemented_opcode(op); + //return; +} + +void unsp_device::execute_fxxx_group(uint16_t op) +{ + switch ((op & 0x01c0) >> 6) + { + case 0x0: + return execute_fxxx_000_group(op); + + case 0x1: + return execute_fxxx_001_group(op); + + case 0x2: + return execute_fxxx_010_group(op); + + case 0x3: + return execute_fxxx_011_group(op); + + case 0x4: + return execute_fxxx_100_group(op); + + case 0x5: + return execute_fxxx_101_group(op); + + case 0x6: + return execute_fxxx_110_group(op); + + case 0x7: + return execute_fxxx_111_group(op); + + } + + return; +} |