summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/tms32025/tms32025.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/tms32025/tms32025.c')
-rw-r--r--src/devices/cpu/tms32025/tms32025.c2282
1 files changed, 2282 insertions, 0 deletions
diff --git a/src/devices/cpu/tms32025/tms32025.c b/src/devices/cpu/tms32025/tms32025.c
new file mode 100644
index 00000000000..9acc4a31f8c
--- /dev/null
+++ b/src/devices/cpu/tms32025/tms32025.c
@@ -0,0 +1,2282 @@
+// license:BSD-3-Clause
+// copyright-holders:Tony La Porta, hap
+ /**************************************************************************\
+ * Texas Instruments TMS320x25 DSP Emulator *
+ * *
+ * Copyright Tony La Porta *
+ * Written for the MAME project. *
+ * *
+ * *
+ * Three versions of the chip are available, and they are: *
+ * TMS320C25 Internal ROM one time programmed at TI *
+ * TMS320E25 Internal ROM programmable as a normal EPROM *
+ * TMS320P25 Internal ROM programmable once as a normal EPROM only *
+ * These devices can also be used as a MicroController with external ROM *
+ * *
+ * *
+ * Notes : The term 'DMA' within this document, is in reference *
+ * to Direct Memory Addressing, and NOT the usual term *
+ * of Direct Memory Access. *
+ * This is a word based microcontroller, with addressing *
+ * architecture based on the Harvard addressing scheme. *
+ * *
+ * *
+ * *
+ * **** Change Log **** *
+ * *
+ * TLP (2x-May-2001) *
+ * - Work began on this emulator *
+ * TLP (12-Jul-2001) *
+ * - First private release *
+ * TLP (xx-Dec-2001) Ver 0.11 *
+ * - Various undocumented fixes *
+ * TLP (13-Jul-2002) Ver 0.12 *
+ * - Corrected IRQ2 vector pointer *
+ * - Fixed the signedness in many equation based instructions *
+ * - Adjusted the level sensing for the Signal inputs *
+ * - Added the ability to view the CPU in the debugger when it's halted *
+ * TLP (16-Nov-2002) *
+ * - First public release after nearly 1.5 years! *
+ * - Adjusted more signedness instructions (ADDH, SUBC, SUBH, etc) *
+ * TLP (21-Dec-2002) *
+ * - Added memory banking for the CNFD, CNFP and CONF instructions *
+ * - Corrected IRQ masking checks *
+ * TLP (25-Dec-2002) Ver 1.10 *
+ * - Added internal timer *
+ * *
+ \**************************************************************************/
+
+/*****************************************************************************
+ To fix, or currently lacking from this emulator are:
+
+ Fix the levels for S_IN and S_OUT - use assert/release line
+
+ # Support for the built in Timer/Counter Page 91
+ When idling, Counter must still be activly counting down. When counter
+ reaches 0 it should issue a TINT (if it's not masked), then come out of
+ IDLE mode.
+ If TINT is masked, the Timer still needs to count down.
+
+ # Support for the built in Serial Port
+ # Support for the Global memory register
+ # Support for the switch for RAM block 0 banking between RAM and ROM space
+ # Correct the multi-cycle instruction cycle counts
+ # Add support to set ROM & RAM as Internal/External in order to correctly
+ compute cycle timings
+ # Check (read) Hold signal level during execution loop ?
+ # Fix bugs
+ # Fix more bugs :-)
+ # Add/fix other things I forgot
+*****************************************************************************/
+
+/*
+ TMS32025 CONF Mode Decoding Table
+|=======================================|
+| Status bit | Blocks |
+| CNF | B0 | B1 | B2 |
+|------------+---------+---------+------|
+| 0 0 | data | data | data |
+| 1 1 | program | data | data |
+|=======================================|
+
+
+ TMS32026 CONF Mode Decoding Table
+|==================================================|
+| Status bits | Blocks |
+| CNF1 | CNF0 | B0 | B1 | B2 | B3 |
+|------+------+---------+---------+------+---------|
+| 0 | 0 | data | data | data | data |
+| 0 | 1 | program | data | data | data |
+| 1 | 0 | program | program | data | data |
+| 1 | 1 | program | program | data | program |
+|==================================================|
+
+
+
+Table 3-2. TMS32025/26 Memory Blocks
+|=========================================================|
+| Configured As Data Memory |
+|-------+-------TMS320C25--------+-------TMS320C26--------|
+| | | Hexadecimal | | Hexadecimal |
+| Block | Pages | Address | Pages | Address |
+|-------+---------+--------------+---------+--------------|
+| B2 | 0 | 0060h-007Fh | 0 | 0060h-007Fh |
+| B0 | 4-5 | 0200h-02FFh | 4-7 | 0200h-03FFh |
+| B1 | 6-7 | 0300h-03FFh | 8-11 | 0400h-05FFh |
+| B3 | B3 does not exist | 12-15 | 0600h-07FFh |
+|=========================================================|
+| Configured As Program Memory |
+|-------+-------TMS320C25--------+-------TMS320C26--------|
+| | | Hexadecimal | | Hexadecimal |
+| Block | Pages | Address | Pages | Address |
+|-------+---------+--------------+---------+--------------|
+| B2 | B2 is not configurable | B2 is not configurable |
+| B0 | 510-511 | FF00h-FFFFh | 500-503 | FA00h-FBFFh |
+| B1 | B1 is not configurable | 504-507 | FC00h-FDFFh |
+| B3 | B3 does not exist | 508-511 | FE00h-FFFFh |
+|=========================================================|
+*/
+
+
+#include "emu.h"
+#include "debugger.h"
+#include "tms32025.h"
+
+
+#define CLK 4 /* 1 cycle equals 4 clock ticks */ /* PE/DI */
+
+
+
+#define SET_PC(x) do { m_PC = (x); } while (0)
+
+#define P_IN(A) (m_io->read_word((A)<<1))
+#define P_OUT(A,V) (m_io->write_word(((A)<<1),(V)))
+#define S_IN(A) (m_io->read_word((A)<<1))
+#define S_OUT(A,V) (m_io->write_word(((A)<<1),(V)))
+
+#define M_RDOP(A) ((m_pgmmap[(A) >> 7]) ? (m_pgmmap[(A) >> 7][(A) & 0x7f]) : m_direct->read_word((A)<<1))
+#define M_RDOP_ARG(A) ((m_pgmmap[(A) >> 7]) ? (m_pgmmap[(A) >> 7][(A) & 0x7f]) : m_direct->read_word((A)<<1))
+
+
+/************************** Memory mapped registers ****************/
+#define DRR m_intRAM[0]
+#define DXR m_intRAM[1]
+#define TIM m_intRAM[2]
+#define PRD m_intRAM[3]
+#define IMR m_intRAM[4]
+#define GREG m_intRAM[5]
+
+
+/****************************************************************************
+ ******* The following is the Status (Flag) register 0 definition. ********
+| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+| <----ARP---> | OV | OVM | 1 | INTM | <--------------DP---------------> | */
+
+#define ARP_REG 0xe000 /* ARP (Auxiliary Register Pointer) */
+#define OV_FLAG 0x1000 /* OV (Overflow flag) 1 indicates an overflow */
+#define OVM_FLAG 0x0800 /* OVM (Overflow Mode bit) 1 forces ACC overflow to greatest positive or negative saturation value */
+#define INTM_FLAG 0x0200 /* INTM (Interrupt Mask flag) 0 enables maskable interrupts */
+#define DP_REG 0x01ff /* DP (Data bank memory Pointer) */
+
+
+/***********************************************************************************
+ *** The following is the Status (Flag) register 1 definition for TMS32025. ********
+| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+| <----ARB---> | CNF0 | TC | SXM | C | 1 | 1 | HM | FSM | XF | FO | TXM | <-PM-> | */
+
+/*** The following is the Status (Flag) register 1 definition for TMS32026. ***********
+| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+| <----ARB---> | CNF0 | TC | SXM | C | 1 | CNF1 | HM | FSM | XF | FO | TXM | <-PM-> | */
+
+#define ARB_REG 0xe000 /* ARB (Auxiliary Register pointer Backup) */
+#define CNF0_REG 0x1000 /* CNF0 (Onchip RAM CoNFiguration) 0 means B0=data memory, 1means B0=program memory */
+#define CNF1_REG 0x0080 /* CNF1 (Onchip RAM CoNFiguration) 0 means B0=data memory, 1means B0=program memory */
+#define TC_FLAG 0x0800 /* TC (Test Control flag) */
+#define SXM_FLAG 0x0400 /* SXM (Sign eXtension Mode) */
+#define C_FLAG 0x0200 /* C (Carry flag) */
+#define HM_FLAG 0x0040 /* HM (Processor Hold Mode) */
+#define FSM_FLAG 0x0020 /* FSM (Frame Synchronization Mode - for serial port) */
+#define XF_FLAG 0x0010 /* XF (XF output pin status) */
+#define FO_FLAG 0x0008 /* FO (Serial port Format In/Out mode) */
+#define TXM_FLAG 0x0004 /* TXM (Transmit Mode - for serial port) */
+#define PM_REG 0x0003 /* PM (Product shift Mode) */
+
+
+#define OV ( m_STR0 & OV_FLAG) /* OV (Overflow flag) */
+#define OVM ( m_STR0 & OVM_FLAG) /* OVM (Overflow Mode bit) 1 indicates an overflow */
+#define INTM ( m_STR0 & INTM_FLAG) /* INTM (Interrupt enable flag) 0 enables maskable interrupts */
+#define ARP ((m_STR0 & ARP_REG) >> 13) /* ARP (Auxiliary Register Pointer) */
+#define DP ((m_STR0 & DP_REG) << 7) /* DP (Data memory Pointer bit) */
+#define ARB ( m_STR1 & ARB_REG) /* ARB (Backup Auxiliary Register pointer) */
+#define CNF0 ( m_STR1 & CNF0_REG) /* CNF0 (Onchip Ram Config register) */
+#define TC ( m_STR1 & TC_FLAG) /* TC (Test Control Flag) */
+#define SXM ( m_STR1 & SXM_FLAG) /* SXM (Sign Extension Mode) */
+#define CARRY ( m_STR1 & C_FLAG) /* C (Carry Flag for accumulator) */
+#define HM ( m_STR1 & HM_FLAG) /* HM (Processor Hold Mode) */
+#define FSM ( m_STR1 & FSM_FLAG) /* FSM (Frame Synchronization Mode - for serial port) */
+#define XF ( m_STR1 & FSM_FLAG) /* XF (XF output pin status) */
+#define FO ( m_STR1 & FO_FLAG) /* FO (Serial port Format In/Out mode) */
+#define TXM ( m_STR1 & TXM_FLAG) /* TXM (Transmit Mode - for serial port) */
+#define PM ( m_STR1 & PM_REG) /* PM (P register shift Mode. See SHIFT_Preg_TO_ALU below )*/
+
+#define DMA (DP | (m_opcode.b.l & 0x7f)) /* address used in direct memory access operations */
+#define DMApg0 (m_opcode.b.l & 0x7f) /* address used in direct memory access operations for sst instruction */
+#define IND m_AR[ARP] /* address used in indirect memory access operations */
+
+
+const device_type TMS32025 = &device_creator<tms32025_device>;
+const device_type TMS32026 = &device_creator<tms32026_device>;
+
+
+tms32025_device::tms32025_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : cpu_device(mconfig, TMS32025, "TMS32025", tag, owner, clock, "tms32025", __FILE__)
+ , m_program_config("program", ENDIANNESS_BIG, 16, 16, -1)
+ , m_data_config("data", ENDIANNESS_BIG, 16, 16, -1)
+ , m_io_config("io", ENDIANNESS_BIG, 16, 17, -1)
+{
+}
+
+
+tms32025_device::tms32025_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
+ : cpu_device(mconfig, type, name, tag, owner, clock, shortname, source)
+ , m_program_config("program", ENDIANNESS_BIG, 16, 16, -1)
+ , m_data_config("data", ENDIANNESS_BIG, 16, 16, -1)
+ , m_io_config("io", ENDIANNESS_BIG, 16, 16, -1)
+{
+}
+
+
+tms32026_device::tms32026_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : tms32025_device(mconfig, TMS32026, "TMS32026", tag, owner, clock, "tms32026", __FILE__)
+{
+}
+
+
+offs_t tms32025_device::disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options)
+{
+ extern CPU_DISASSEMBLE( tms32025 );
+ return CPU_DISASSEMBLE_NAME(tms32025)(this, buffer, pc, oprom, opram, options);
+}
+
+
+void tms32025_device::CLR0(UINT16 flag) { m_STR0 &= ~flag; m_STR0 |= 0x0400; }
+void tms32025_device::SET0(UINT16 flag) { m_STR0 |= flag; m_STR0 |= 0x0400; }
+void tms32025_device::CLR1(UINT16 flag) { m_STR1 &= ~flag; m_STR1 |= 0x0180; }
+void tms32025_device::SET1(UINT16 flag) { m_STR1 |= flag; m_STR1 |= 0x0180; }
+
+void tms32025_device::MODIFY_DP(int data)
+{
+ m_STR0 &= ~DP_REG;
+ m_STR0 |= (data & DP_REG);
+ m_STR0 |= 0x0400;
+}
+void tms32025_device::MODIFY_PM(int data)
+{
+ m_STR1 &= ~PM_REG;
+ m_STR1 |= (data & PM_REG);
+ m_STR1 |= 0x0180;
+}
+void tms32025_device::MODIFY_ARP(int data)
+{
+ m_STR1 &= ~ARB_REG;
+ m_STR1 |= (m_STR0 & ARP_REG);
+ m_STR1 |= 0x0180;
+ m_STR0 &= ~ARP_REG;
+ m_STR0 |= ((data << 13) & ARP_REG);
+ m_STR0 |= 0x0400;
+}
+
+UINT16 tms32025_device::M_RDROM(offs_t addr)
+{
+ UINT16 *ram;
+ addr &= 0xffff;
+ ram = m_pgmmap[addr >> 7];
+ if (ram) return ram[addr & 0x7f];
+ return m_program->read_word(addr << 1);
+}
+
+void tms32025_device::M_WRTROM(offs_t addr, UINT16 data)
+{
+ UINT16 *ram;
+ addr &= 0xffff;
+ ram = m_pgmmap[addr >> 7];
+ if (ram) { ram[addr & 0x7f] = data; }
+ else m_program->write_word(addr << 1, data);
+}
+
+UINT16 tms32025_device::M_RDRAM(offs_t addr)
+{
+ UINT16 *ram;
+ addr &= 0xffff;
+ ram = m_datamap[addr >> 7];
+ if (ram) return ram[addr & 0x7f];
+ return m_data->read_word(addr << 1);
+}
+
+void tms32025_device::M_WRTRAM(offs_t addr, UINT16 data)
+{
+ UINT16 *ram;
+ addr &= 0xffff;
+ ram = m_datamap[addr >> 7];
+ if (ram) {
+ ram[addr & 0x7f] = data;
+ if(addr == 1 && ram == m_intRAM && TXM) {
+ if(FSM)
+ m_waiting_for_serial_frame = 1;
+ else
+ m_IFR |= 0x20;
+ }
+ }
+ else m_data->write_word(addr << 1, data);
+}
+
+
+UINT16 tms32025_device::reverse_carry_add(UINT16 arg0, UINT16 arg1 )
+{
+ UINT16 result = 0;
+ int carry = 0;
+ int count;
+ for( count=0; count<16; count++ )
+ {
+ int sum = (arg0>>15)+(arg1>>15)+carry;
+ result = (result<<1)|(sum&1);
+ carry = sum>>1;
+ arg0<<=1;
+ arg1<<=1;
+ }
+ return result;
+}
+
+void tms32025_device::MODIFY_AR_ARP()
+{ /* modify address register referenced by ARP */
+ switch (m_opcode.b.l & 0x70) /* Cases ordered by predicted useage */
+ {
+ case 0x00: /* 000 nop */
+ break;
+
+ case 0x10: /* 001 *- */
+ m_AR[ARP] -- ;
+ break;
+
+ case 0x20: /* 010 *+ */
+ m_AR[ARP] ++ ;
+ break;
+
+ case 0x30: /* 011 reserved */
+ break;
+
+ case 0x40: /* 100 *BR0- */
+ m_AR[ARP] = reverse_carry_add(m_AR[ARP],-m_AR[0]);
+ break;
+
+ case 0x50: /* 101 *0- */
+ m_AR[ARP] -= m_AR[0];
+ break;
+
+ case 0x60: /* 110 *0+ */
+ m_AR[ARP] += m_AR[0];
+ break;
+
+ case 0x70: /* 111 *BR0+ */
+ m_AR[ARP] += reverse_carry_add(m_AR[ARP],m_AR[0]);
+ break;
+ }
+
+ if( !m_mHackIgnoreARP )
+ {
+ if (m_opcode.b.l & 8)
+ { /* bit 3 determines if new value is loaded into ARP */
+ MODIFY_ARP((m_opcode.b.l & 7) );
+ }
+ }
+}
+
+void tms32025_device::CALCULATE_ADD_CARRY()
+{
+ if ( (UINT32)(m_oldacc.d) > (UINT32)(m_ACC.d) ) {
+ SET1(C_FLAG);
+ }
+ else {
+ CLR1(C_FLAG);
+ }
+}
+
+void tms32025_device::CALCULATE_SUB_CARRY()
+{
+ if ( (UINT32)(m_oldacc.d) < (UINT32)(m_ACC.d) ) {
+ CLR1(C_FLAG);
+ }
+ else {
+ SET1(C_FLAG);
+ }
+}
+
+void tms32025_device::CALCULATE_ADD_OVERFLOW(INT32 addval)
+{
+ if ((INT32)((m_ACC.d ^ addval) & (m_oldacc.d ^ m_ACC.d)) < 0)
+ {
+ SET0(OV_FLAG);
+ if (OVM)
+ {
+ m_ACC.d = ((INT32)m_oldacc.d < 0) ? 0x80000000 : 0x7fffffff;
+ }
+ }
+}
+void tms32025_device::CALCULATE_SUB_OVERFLOW(INT32 subval)
+{
+ if ((INT32)((m_oldacc.d ^ subval) & (m_oldacc.d ^ m_ACC.d)) < 0)
+ {
+ SET0(OV_FLAG);
+ if (OVM)
+ {
+ m_ACC.d = ((INT32)m_oldacc.d < 0) ? 0x80000000 : 0x7fffffff;
+ }
+ }
+}
+
+UINT16 tms32025_device::POP_STACK()
+{
+ UINT16 data = m_STACK[7];
+ m_STACK[7] = m_STACK[6];
+ m_STACK[6] = m_STACK[5];
+ m_STACK[5] = m_STACK[4];
+ m_STACK[4] = m_STACK[3];
+ m_STACK[3] = m_STACK[2];
+ m_STACK[2] = m_STACK[1];
+ m_STACK[1] = m_STACK[0];
+ return data;
+}
+void tms32025_device::PUSH_STACK(UINT16 data)
+{
+ m_STACK[0] = m_STACK[1];
+ m_STACK[1] = m_STACK[2];
+ m_STACK[2] = m_STACK[3];
+ m_STACK[3] = m_STACK[4];
+ m_STACK[4] = m_STACK[5];
+ m_STACK[5] = m_STACK[6];
+ m_STACK[6] = m_STACK[7];
+ m_STACK[7] = data;
+}
+
+void tms32025_device::SHIFT_Preg_TO_ALU()
+{
+ switch(PM) /* PM (in STR1) is the shift mode for Preg */
+ {
+ case 0: m_ALU.d = m_Preg.d; break;
+ case 1: m_ALU.d = (m_Preg.d << 1); break;
+ case 2: m_ALU.d = (m_Preg.d << 4); break;
+ case 3: m_ALU.d = (m_Preg.d >> 6); if (m_Preg.d & 0x80000000) m_ALU.d |= 0xfc000000; break;
+ default: break;
+ }
+}
+
+void tms32025_device::GETDATA(int shift,int signext)
+{
+ if (m_opcode.b.l & 0x80)
+ { /* indirect memory access */
+ m_memaccess = IND;
+ }
+ else
+ { /* direct memory address */
+ m_memaccess = DMA;
+ }
+
+ if (m_memaccess >= 0x800)
+ {
+ m_external_mem_access = 1; /* Pause if hold pin is active */
+ }
+ else
+ {
+ m_external_mem_access = 0;
+ }
+
+ m_ALU.d = (UINT16)M_RDRAM(m_memaccess);
+ if (signext) m_ALU.d = (INT16)m_ALU.d;
+ m_ALU.d <<= shift;
+
+ /* next ARP */
+ if (m_opcode.b.l & 0x80) MODIFY_AR_ARP();
+}
+
+void tms32025_device::PUTDATA(UINT16 data)
+{
+ if (m_opcode.b.l & 0x80) {
+ if (m_memaccess >= 0x800) m_external_mem_access = 1; /* Pause if hold pin is active */
+ else m_external_mem_access = 0;
+
+ M_WRTRAM(IND, data);
+ MODIFY_AR_ARP();
+ }
+ else {
+ if (m_memaccess >= 0x800) m_external_mem_access = 1; /* Pause if hold pin is active */
+ else m_external_mem_access = 0;
+
+ M_WRTRAM(DMA, data);
+ }
+}
+void tms32025_device::PUTDATA_SST(UINT16 data)
+{
+ if (m_opcode.b.l & 0x80) m_memaccess = IND;
+ else m_memaccess = DMApg0;
+
+ if (m_memaccess >= 0x800) m_external_mem_access = 1; /* Pause if hold pin is active */
+ else m_external_mem_access = 0;
+
+ if (m_opcode.b.l & 0x80) {
+ m_opcode.b.l &= 0xf7; /* Stop ARP changes */
+ MODIFY_AR_ARP();
+ }
+ M_WRTRAM(m_memaccess, data);
+}
+
+
+
+/****************************************************************************
+ * Emulate the Instructions
+ ****************************************************************************/
+
+/* The following functions are here to fill the void for the */
+/* opcode call functions. These functions are never actually called. */
+void tms32025_device::opcodes_CE() { fatalerror("Should never get here!\n"); }
+void tms32025_device::opcodes_Dx() { fatalerror("Should never get here!\n"); }
+
+void tms32025_device::illegal()
+{
+ logerror("TMS32025: PC = %04x, Illegal opcode = %04x\n", (m_PC-1), m_opcode.w.l);
+}
+
+void tms32025_device::abst()
+{
+ if ( (INT32)(m_ACC.d) < 0 ) {
+ m_ACC.d = -m_ACC.d;
+ if (m_ACC.d == 0x80000000) {
+ SET0(OV_FLAG);
+ if (OVM) m_ACC.d-- ;
+ }
+ }
+ CLR1(C_FLAG);
+}
+void tms32025_device::add()
+{
+ m_oldacc.d = m_ACC.d;
+ GETDATA((m_opcode.b.h & 0xf), SXM);
+ m_ACC.d += m_ALU.d;
+ CALCULATE_ADD_OVERFLOW(m_ALU.d);
+ CALCULATE_ADD_CARRY();
+}
+void tms32025_device::addc()
+{
+ m_oldacc.d = m_ACC.d;
+ GETDATA(0, 0);
+ if (CARRY) m_ACC.d++;
+ m_ACC.d += m_ALU.d;
+ CALCULATE_ADD_OVERFLOW(m_ALU.d);
+ if (m_ACC.d == m_oldacc.d) {} /* edge case, carry remains same */
+ else CALCULATE_ADD_CARRY();
+}
+void tms32025_device::addh()
+{
+ m_oldacc.d = m_ACC.d;
+ GETDATA(0, 0);
+ m_ACC.w.h += m_ALU.w.l;
+ if ( (UINT16)(m_oldacc.w.h) > (UINT16)(m_ACC.w.h) ) {
+ SET1(C_FLAG); /* Carry flag is not cleared, if no carry occurred */
+ }
+ if ((INT16)((m_ACC.w.h ^ m_ALU.w.l) & (m_oldacc.w.h ^ m_ACC.w.h)) < 0) {
+ SET0(OV_FLAG);
+ if (OVM) m_ACC.w.h = ((INT16)m_oldacc.w.h < 0) ? 0x8000 : 0x7fff;
+ }
+}
+void tms32025_device::addk()
+{
+ m_oldacc.d = m_ACC.d;
+ m_ALU.d = (UINT8)m_opcode.b.l;
+ m_ACC.d += m_ALU.d;
+ CALCULATE_ADD_OVERFLOW(m_ALU.d);
+ CALCULATE_ADD_CARRY();
+}
+void tms32025_device::adds()
+{
+ m_oldacc.d = m_ACC.d;
+ GETDATA(0, 0);
+ m_ACC.d += m_ALU.d;
+ CALCULATE_ADD_OVERFLOW(m_ALU.d);
+ CALCULATE_ADD_CARRY();
+}
+void tms32025_device::addt()
+{
+ m_oldacc.d = m_ACC.d;
+ GETDATA((m_Treg & 0xf), SXM);
+ m_ACC.d += m_ALU.d;
+ CALCULATE_ADD_OVERFLOW(m_ALU.d);
+ CALCULATE_ADD_CARRY();
+}
+void tms32025_device::adlk()
+{
+ m_oldacc.d = m_ACC.d;
+ if (SXM) m_ALU.d = (INT16)M_RDOP_ARG(m_PC);
+ else m_ALU.d = (UINT16)M_RDOP_ARG(m_PC);
+ m_PC++;
+ m_ALU.d <<= (m_opcode.b.h & 0xf);
+ m_ACC.d += m_ALU.d;
+ CALCULATE_ADD_OVERFLOW(m_ALU.d);
+ CALCULATE_ADD_CARRY();
+}
+void tms32025_device::adrk()
+{
+ m_AR[ARP] += m_opcode.b.l;
+}
+void tms32025_device::and_()
+{
+ GETDATA(0, 0);
+ m_ACC.d &= m_ALU.d;
+}
+void tms32025_device::andk()
+{
+ m_oldacc.d = m_ACC.d;
+ m_ALU.d = (UINT16)M_RDOP_ARG(m_PC);
+ m_PC++;
+ m_ALU.d <<= (m_opcode.b.h & 0xf);
+ m_ACC.d &= m_ALU.d;
+}
+void tms32025_device::apac()
+{
+ m_oldacc.d = m_ACC.d;
+ SHIFT_Preg_TO_ALU();
+ m_ACC.d += m_ALU.d;
+ CALCULATE_ADD_OVERFLOW(m_ALU.d);
+ CALCULATE_ADD_CARRY();
+}
+void tms32025_device::br()
+{
+ SET_PC(M_RDOP_ARG(m_PC));
+ MODIFY_AR_ARP();
+}
+void tms32025_device::bacc()
+{
+ SET_PC(m_ACC.w.l);
+}
+void tms32025_device::banz()
+{
+ if (m_AR[ARP]) SET_PC(M_RDOP_ARG(m_PC));
+ else m_PC++ ;
+ MODIFY_AR_ARP();
+}
+void tms32025_device::bbnz()
+{
+ if (TC) SET_PC(M_RDOP_ARG(m_PC));
+ else m_PC++ ;
+ MODIFY_AR_ARP();
+}
+void tms32025_device::bbz()
+{
+ if (TC == 0) SET_PC(M_RDOP_ARG(m_PC));
+ else m_PC++ ;
+ MODIFY_AR_ARP();
+}
+void tms32025_device::bc()
+{
+ if (CARRY) SET_PC(M_RDOP_ARG(m_PC));
+ else m_PC++ ;
+ MODIFY_AR_ARP();
+}
+void tms32025_device::bgez()
+{
+ if ( (INT32)(m_ACC.d) >= 0 ) SET_PC(M_RDOP_ARG(m_PC));
+ else m_PC++ ;
+ MODIFY_AR_ARP();
+}
+void tms32025_device::bgz()
+{
+ if ( (INT32)(m_ACC.d) > 0 ) SET_PC(M_RDOP_ARG(m_PC));
+ else m_PC++ ;
+ MODIFY_AR_ARP();
+}
+void tms32025_device::bioz()
+{
+ if (S_IN(TMS32025_BIO) != CLEAR_LINE) SET_PC(M_RDOP_ARG(m_PC));
+ else m_PC++ ;
+ MODIFY_AR_ARP();
+}
+void tms32025_device::bit()
+{
+ GETDATA(0, 0);
+ if (m_ALU.d & (0x8000 >> (m_opcode.b.h & 0xf))) SET1(TC_FLAG);
+ else CLR1(TC_FLAG);
+}
+void tms32025_device::bitt()
+{
+ GETDATA(0, 0);
+ if (m_ALU.d & (0x8000 >> (m_Treg & 0xf))) SET1(TC_FLAG);
+ else CLR1(TC_FLAG);
+}
+void tms32025_device::blez()
+{
+ if ( (INT32)(m_ACC.d) <= 0 ) SET_PC(M_RDOP_ARG(m_PC));
+ else m_PC++ ;
+ MODIFY_AR_ARP();
+}
+void tms32025_device::blkd()
+{ /** Fix cycle timing **/
+ if (m_init_load_addr) {
+ m_PFC = M_RDOP_ARG(m_PC);
+ m_PC++;
+ }
+ m_ALU.d = M_RDRAM(m_PFC);
+ PUTDATA(m_ALU.d);
+ m_PFC++;
+ m_tms32025_dec_cycles += (1*CLK);
+}
+void tms32025_device::blkp()
+{ /** Fix cycle timing **/
+ if (m_init_load_addr) {
+ m_PFC = M_RDOP_ARG(m_PC);
+ m_PC++;
+ }
+ m_ALU.d = M_RDROM(m_PFC);
+ PUTDATA(m_ALU.d);
+ m_PFC++;
+ m_tms32025_dec_cycles += (2*CLK);
+}
+void tms32025_device::blz()
+{
+ if ( (INT32)(m_ACC.d) < 0 ) SET_PC(M_RDOP_ARG(m_PC));
+ else m_PC++ ;
+ MODIFY_AR_ARP();
+}
+void tms32025_device::bnc()
+{
+ if (CARRY == 0) SET_PC(M_RDOP_ARG(m_PC));
+ else m_PC++ ;
+ MODIFY_AR_ARP();
+}
+void tms32025_device::bnv()
+{
+ if (OV == 0) SET_PC(M_RDOP_ARG(m_PC));
+ else {
+ m_PC++ ;
+ CLR0(OV_FLAG);
+ }
+ MODIFY_AR_ARP();
+}
+void tms32025_device::bnz()
+{
+ if (m_ACC.d != 0) SET_PC(M_RDOP_ARG(m_PC));
+ else m_PC++ ;
+ MODIFY_AR_ARP();
+}
+void tms32025_device::bv()
+{
+ if (OV) {
+ SET_PC(M_RDOP_ARG(m_PC));
+ CLR0(OV_FLAG);
+ }
+ else m_PC++ ;
+ MODIFY_AR_ARP();
+}
+void tms32025_device::bz()
+{
+ if (m_ACC.d == 0) SET_PC(M_RDOP_ARG(m_PC));
+ else m_PC++ ;
+ MODIFY_AR_ARP();
+}
+void tms32025_device::cala()
+{
+ PUSH_STACK(m_PC);
+ SET_PC(m_ACC.w.l);
+}
+void tms32025_device::call()
+{
+ m_PC++ ;
+ PUSH_STACK(m_PC);
+ SET_PC(M_RDOP_ARG((m_PC - 1)));
+ MODIFY_AR_ARP();
+}
+void tms32025_device::cmpl()
+{
+ m_ACC.d = (~m_ACC.d);
+}
+void tms32025_device::cmpr()
+{
+ switch (m_opcode.b.l & 3)
+ {
+ case 00: if ( (UINT16)(m_AR[ARP]) == (UINT16)(m_AR[0]) ) SET1(TC_FLAG);
+ else CLR1(TC_FLAG);
+ break;
+ case 01: if ( (UINT16)(m_AR[ARP]) < (UINT16)(m_AR[0]) ) SET1(TC_FLAG);
+ else CLR1(TC_FLAG);
+ break;
+ case 02: if ( (UINT16)(m_AR[ARP]) > (UINT16)(m_AR[0]) ) SET1(TC_FLAG);
+ else CLR1(TC_FLAG);
+ break;
+ case 03: if ( (UINT16)(m_AR[ARP]) != (UINT16)(m_AR[0]) ) SET1(TC_FLAG);
+ else CLR1(TC_FLAG);
+ break;
+ }
+}
+void tms32025_device::cnfd() /** next two fetches need to use previous CNF value ! **/
+{
+ CLR1(CNF0_REG);
+ m_datamap[4] = &m_intRAM[0x200]; /* B0 */
+ m_datamap[5] = &m_intRAM[0x280]; /* B0 */
+ m_pgmmap[510] = NULL;
+ m_pgmmap[511] = NULL;
+}
+void tms32025_device::cnfp() /** next two fetches need to use previous CNF value ! **/
+{
+ SET1(CNF0_REG);
+ m_datamap[4] = NULL; /* B0 */
+ m_datamap[5] = NULL; /* B0 */
+ m_pgmmap[510] = &m_intRAM[0x200];
+ m_pgmmap[511] = &m_intRAM[0x280];
+}
+void tms32025_device::conf() /** Need to reconfigure the memory blocks */
+{
+ switch (m_opcode.b.l & 3)
+ {
+ case 00: CLR1(CNF1_REG); CLR1(CNF0_REG);
+ m_datamap[4] = &m_intRAM[0x200]; /* B0 */
+ m_datamap[5] = &m_intRAM[0x280]; /* B0 */
+ m_datamap[6] = &m_intRAM[0x300]; /* B0 */
+ m_datamap[7] = &m_intRAM[0x380]; /* B0 */
+ m_datamap[8] = &m_intRAM[0x400]; /* B1 */
+ m_datamap[9] = &m_intRAM[0x480]; /* B1 */
+ m_datamap[10] = &m_intRAM[0x500]; /* B1 */
+ m_datamap[11] = &m_intRAM[0x580]; /* B1 */
+ m_datamap[12] = &m_intRAM[0x600]; /* B3 */
+ m_datamap[13] = &m_intRAM[0x680]; /* B3 */
+ m_datamap[14] = &m_intRAM[0x700]; /* B3 */
+ m_datamap[15] = &m_intRAM[0x780]; /* B3 */
+ m_pgmmap[500] = NULL;
+ m_pgmmap[501] = NULL;
+ m_pgmmap[502] = NULL;
+ m_pgmmap[503] = NULL;
+ m_pgmmap[504] = NULL;
+ m_pgmmap[505] = NULL;
+ m_pgmmap[506] = NULL;
+ m_pgmmap[507] = NULL;
+ m_pgmmap[508] = NULL;
+ m_pgmmap[509] = NULL;
+ m_pgmmap[510] = NULL;
+ m_pgmmap[511] = NULL;
+ break;
+
+ case 01: CLR1(CNF1_REG); SET1(CNF0_REG);
+ m_datamap[4] = NULL;
+ m_datamap[5] = NULL;
+ m_datamap[6] = NULL;
+ m_datamap[7] = NULL;
+ m_datamap[8] = &m_intRAM[0x400]; /* B1 */
+ m_datamap[9] = &m_intRAM[0x480]; /* B1 */
+ m_datamap[10] = &m_intRAM[0x500]; /* B1 */
+ m_datamap[11] = &m_intRAM[0x580]; /* B1 */
+ m_datamap[12] = &m_intRAM[0x600]; /* B3 */
+ m_datamap[13] = &m_intRAM[0x680]; /* B3 */
+ m_datamap[14] = &m_intRAM[0x700]; /* B3 */
+ m_datamap[15] = &m_intRAM[0x780]; /* B3 */
+ m_pgmmap[500] = &m_intRAM[0x200]; /* B0 */
+ m_pgmmap[501] = &m_intRAM[0x280]; /* B0 */
+ m_pgmmap[502] = &m_intRAM[0x300]; /* B0 */
+ m_pgmmap[503] = &m_intRAM[0x380]; /* B0 */
+ m_pgmmap[504] = NULL;
+ m_pgmmap[505] = NULL;
+ m_pgmmap[506] = NULL;
+ m_pgmmap[507] = NULL;
+ m_pgmmap[508] = NULL;
+ m_pgmmap[509] = NULL;
+ m_pgmmap[510] = NULL;
+ m_pgmmap[511] = NULL;
+ break;
+
+ case 02: SET1(CNF1_REG); CLR1(CNF0_REG);
+ m_datamap[4] = NULL;
+ m_datamap[5] = NULL;
+ m_datamap[6] = NULL;
+ m_datamap[7] = NULL;
+ m_datamap[8] = NULL;
+ m_datamap[9] = NULL;
+ m_datamap[10] = NULL;
+ m_datamap[11] = NULL;
+ m_datamap[12] = &m_intRAM[0x600]; /* B3 */
+ m_datamap[13] = &m_intRAM[0x680]; /* B3 */
+ m_datamap[14] = &m_intRAM[0x700]; /* B3 */
+ m_datamap[15] = &m_intRAM[0x780]; /* B3 */
+ m_pgmmap[500] = &m_intRAM[0x200]; /* B0 */
+ m_pgmmap[501] = &m_intRAM[0x280]; /* B0 */
+ m_pgmmap[502] = &m_intRAM[0x300]; /* B0 */
+ m_pgmmap[503] = &m_intRAM[0x380]; /* B0 */
+ m_pgmmap[504] = &m_intRAM[0x400]; /* B1 */
+ m_pgmmap[505] = &m_intRAM[0x480]; /* B1 */
+ m_pgmmap[506] = &m_intRAM[0x500]; /* B1 */
+ m_pgmmap[507] = &m_intRAM[0x580]; /* B1 */
+ m_pgmmap[508] = NULL;
+ m_pgmmap[509] = NULL;
+ m_pgmmap[510] = NULL;
+ m_pgmmap[511] = NULL;
+ break;
+
+ case 03: SET1(CNF1_REG); SET1(CNF0_REG);
+ m_datamap[4] = NULL;
+ m_datamap[5] = NULL;
+ m_datamap[6] = NULL;
+ m_datamap[7] = NULL;
+ m_datamap[8] = NULL;
+ m_datamap[9] = NULL;
+ m_datamap[10] = NULL;
+ m_datamap[11] = NULL;
+ m_datamap[12] = NULL;
+ m_datamap[13] = NULL;
+ m_datamap[14] = NULL;
+ m_datamap[15] = NULL;
+ m_pgmmap[500] = &m_intRAM[0x200]; /* B0 */
+ m_pgmmap[501] = &m_intRAM[0x280]; /* B0 */
+ m_pgmmap[502] = &m_intRAM[0x300]; /* B0 */
+ m_pgmmap[503] = &m_intRAM[0x380]; /* B0 */
+ m_pgmmap[504] = &m_intRAM[0x400]; /* B1 */
+ m_pgmmap[505] = &m_intRAM[0x480]; /* B1 */
+ m_pgmmap[506] = &m_intRAM[0x500]; /* B1 */
+ m_pgmmap[507] = &m_intRAM[0x580]; /* B1 */
+ m_pgmmap[508] = &m_intRAM[0x600]; /* B3 */
+ m_pgmmap[509] = &m_intRAM[0x680]; /* B3 */
+ m_pgmmap[510] = &m_intRAM[0x700]; /* B3 */
+ m_pgmmap[511] = &m_intRAM[0x780]; /* B3 */
+ break;
+ }
+}
+void tms32025_device::dint()
+{
+ SET0(INTM_FLAG);
+}
+void tms32025_device::dmov() /** Careful with how memory is configured !! */
+{
+ GETDATA(0, 0);
+ M_WRTRAM((m_memaccess + 1), m_ALU.w.l);
+}
+void tms32025_device::eint()
+{
+ CLR0(INTM_FLAG);
+}
+void tms32025_device::fort()
+{
+ if (m_opcode.b.l & 1) SET1(FO_FLAG);
+ else CLR1(FO_FLAG);
+}
+void tms32025_device::idle()
+{
+ CLR0(INTM_FLAG);
+ m_idle = 1;
+}
+void tms32025_device::in()
+{
+ m_ALU.w.l = P_IN( (m_opcode.b.h & 0xf) );
+ PUTDATA(m_ALU.w.l);
+}
+void tms32025_device::lac()
+{
+ GETDATA((m_opcode.b.h & 0xf), SXM);
+ m_ACC.d = m_ALU.d;
+}
+void tms32025_device::lack() /* ZAC is a subset of this instruction */
+{
+ m_ACC.d = (UINT8)m_opcode.b.l;
+}
+void tms32025_device::lact()
+{
+ GETDATA((m_Treg & 0xf), SXM);
+ m_ACC.d = m_ALU.d;
+}
+void tms32025_device::lalk()
+{
+ if (SXM) m_ALU.d = (INT16)M_RDOP_ARG(m_PC);
+ else m_ALU.d = (UINT16)M_RDOP_ARG(m_PC);
+ m_PC++;
+ m_ALU.d <<= (m_opcode.b.h & 0xf);
+ m_ACC.d = m_ALU.d;
+}
+void tms32025_device::lar_ar0() { GETDATA(0, 0); m_AR[0] = m_ALU.w.l; }
+void tms32025_device::lar_ar1() { GETDATA(0, 0); m_AR[1] = m_ALU.w.l; }
+void tms32025_device::lar_ar2() { GETDATA(0, 0); m_AR[2] = m_ALU.w.l; }
+void tms32025_device::lar_ar3() { GETDATA(0, 0); m_AR[3] = m_ALU.w.l; }
+void tms32025_device::lar_ar4() { GETDATA(0, 0); m_AR[4] = m_ALU.w.l; }
+void tms32025_device::lar_ar5() { GETDATA(0, 0); m_AR[5] = m_ALU.w.l; }
+void tms32025_device::lar_ar6() { GETDATA(0, 0); m_AR[6] = m_ALU.w.l; }
+void tms32025_device::lar_ar7() { GETDATA(0, 0); m_AR[7] = m_ALU.w.l; }
+void tms32025_device::lark_ar0() { m_AR[0] = m_opcode.b.l; }
+void tms32025_device::lark_ar1() { m_AR[1] = m_opcode.b.l; }
+void tms32025_device::lark_ar2() { m_AR[2] = m_opcode.b.l; }
+void tms32025_device::lark_ar3() { m_AR[3] = m_opcode.b.l; }
+void tms32025_device::lark_ar4() { m_AR[4] = m_opcode.b.l; }
+void tms32025_device::lark_ar5() { m_AR[5] = m_opcode.b.l; }
+void tms32025_device::lark_ar6() { m_AR[6] = m_opcode.b.l; }
+void tms32025_device::lark_ar7() { m_AR[7] = m_opcode.b.l; }
+void tms32025_device::ldp()
+{
+ GETDATA(0, 0);
+ MODIFY_DP(m_ALU.d & 0x1ff);
+}
+void tms32025_device::ldpk()
+{
+ MODIFY_DP(m_opcode.w.l & 0x1ff);
+}
+void tms32025_device::lph()
+{
+ GETDATA(0, 0);
+ m_Preg.w.h = m_ALU.w.l;
+}
+void tms32025_device::lrlk()
+{
+ m_ALU.d = (UINT16)M_RDOP_ARG(m_PC);
+ m_PC++;
+ m_AR[m_opcode.b.h & 7] = m_ALU.w.l;
+}
+void tms32025_device::lst()
+{
+ m_mHackIgnoreARP = 1;
+ GETDATA(0, 0);
+ m_mHackIgnoreARP = 0;
+
+ m_ALU.w.l &= (~INTM_FLAG);
+ m_STR0 &= INTM_FLAG;
+ m_STR0 |= m_ALU.w.l; /* Must not affect INTM */
+ m_STR0 |= 0x0400;
+}
+void tms32025_device::lst1()
+{
+ m_mHackIgnoreARP = 1;
+ GETDATA(0, 0);
+ m_mHackIgnoreARP = 0;
+
+ m_STR1 = m_ALU.w.l;
+ m_STR1 |= 0x0180;
+ m_STR0 &= (~ARP_REG); /* ARB also gets copied to ARP */
+ m_STR0 |= (m_STR1 & ARB_REG);
+}
+void tms32025_device::lt()
+{
+ GETDATA(0, 0);
+ m_Treg = m_ALU.w.l;
+}
+void tms32025_device::lta()
+{
+ m_oldacc.d = m_ACC.d;
+ GETDATA(0, 0);
+ m_Treg = m_ALU.w.l;
+ SHIFT_Preg_TO_ALU();
+ m_ACC.d += m_ALU.d;
+ CALCULATE_ADD_OVERFLOW(m_ALU.d);
+ CALCULATE_ADD_CARRY();
+}
+void tms32025_device::ltd() /** Careful with how memory is configured !! */
+{
+ m_oldacc.d = m_ACC.d;
+ GETDATA(0, 0);
+ m_Treg = m_ALU.w.l;
+ M_WRTRAM((m_memaccess+1), m_ALU.w.l);
+ SHIFT_Preg_TO_ALU();
+ m_ACC.d += m_ALU.d;
+ CALCULATE_ADD_OVERFLOW(m_ALU.d);
+ CALCULATE_ADD_CARRY();
+}
+void tms32025_device::ltp()
+{
+ m_oldacc.d = m_ACC.d;
+ GETDATA(0, 0);
+ m_Treg = m_ALU.w.l;
+ SHIFT_Preg_TO_ALU();
+ m_ACC.d = m_ALU.d;
+}
+void tms32025_device::lts()
+{
+ m_oldacc.d = m_ACC.d;
+ GETDATA(0, 0);
+ m_Treg = m_ALU.w.l;
+ SHIFT_Preg_TO_ALU();
+ m_ACC.d -= m_ALU.d;
+ CALCULATE_SUB_OVERFLOW(m_ALU.d);
+ CALCULATE_SUB_CARRY();
+}
+void tms32025_device::mac() /** RAM blocks B0,B1,B2 may be important ! */
+{ /** Fix cycle timing **/
+ m_oldacc.d = m_ACC.d;
+ if (m_init_load_addr) {
+ m_PFC = M_RDOP_ARG(m_PC);
+ m_PC++;
+ }
+ SHIFT_Preg_TO_ALU();
+ m_ACC.d += m_ALU.d;
+ CALCULATE_ADD_OVERFLOW(m_ALU.d);
+ CALCULATE_ADD_CARRY();
+ GETDATA(0, 0);
+ m_Treg = m_ALU.w.l;
+ m_Preg.d = ( (INT16)m_ALU.w.l * (INT16)M_RDROM(m_PFC) );
+ m_PFC++;
+ m_tms32025_dec_cycles += (2*CLK);
+}
+void tms32025_device::macd() /** RAM blocks B0,B1,B2 may be important ! */
+{ /** Fix cycle timing **/
+ m_oldacc.d = m_ACC.d;
+ if (m_init_load_addr) {
+ m_PFC = M_RDOP_ARG(m_PC);
+ m_PC++;
+ }
+ SHIFT_Preg_TO_ALU();
+ m_ACC.d += m_ALU.d;
+ CALCULATE_ADD_OVERFLOW(m_ALU.d);
+ CALCULATE_ADD_CARRY();
+ GETDATA(0, 0);
+ if ( (m_opcode.b.l & 0x80) || m_init_load_addr ) { /* No writing during repetition, or DMA mode */
+ M_WRTRAM((m_memaccess+1), m_ALU.w.l);
+ }
+ m_Treg = m_ALU.w.l;
+ m_Preg.d = ( (INT16)m_ALU.w.l * (INT16)M_RDROM(m_PFC) );
+ m_PFC++;
+ m_tms32025_dec_cycles += (2*CLK);
+}
+void tms32025_device::mar() /* LARP and NOP are a subset of this instruction */
+{
+ if (m_opcode.b.l & 0x80) MODIFY_AR_ARP();
+}
+void tms32025_device::mpy()
+{
+ GETDATA(0, 0);
+ m_Preg.d = (INT16)(m_ALU.w.l) * (INT16)(m_Treg);
+}
+void tms32025_device::mpya()
+{
+ m_oldacc.d = m_ACC.d;
+ SHIFT_Preg_TO_ALU();
+ m_ACC.d += m_ALU.d;
+ CALCULATE_ADD_OVERFLOW(m_ALU.d);
+ CALCULATE_ADD_CARRY();
+ GETDATA(0, 0);
+ m_Preg.d = (INT16)(m_ALU.w.l) * (INT16)(m_Treg);
+}
+void tms32025_device::mpyk()
+{
+ m_Preg.d = (INT16)m_Treg * ((INT16)(m_opcode.w.l << 3) >> 3);
+
+}
+void tms32025_device::mpys()
+{
+ m_oldacc.d = m_ACC.d;
+ SHIFT_Preg_TO_ALU();
+ m_ACC.d -= m_ALU.d;
+ CALCULATE_SUB_OVERFLOW(m_ALU.d);
+ CALCULATE_SUB_CARRY();
+ GETDATA(0, 0);
+ m_Preg.d = (INT16)(m_ALU.w.l) * (INT16)(m_Treg);
+}
+void tms32025_device::mpyu()
+{
+ GETDATA(0, 0);
+ m_Preg.d = (UINT16)(m_ALU.w.l) * (UINT16)(m_Treg);
+}
+void tms32025_device::neg()
+{
+ if (m_ACC.d == 0x80000000) {
+ SET0(OV_FLAG);
+ if (OVM) m_ACC.d = 0x7fffffff;
+ }
+ else m_ACC.d = -m_ACC.d;
+ if (m_ACC.d) CLR0(C_FLAG);
+ else SET0(C_FLAG);
+}
+/*
+void tms32025_device::nop() { } // NOP is a subset of the MAR instruction
+*/
+void tms32025_device::norm()
+{
+ if (m_ACC.d !=0 && (INT32)(m_ACC.d ^ (m_ACC.d << 1)) >= 0)
+ {
+ CLR1(TC_FLAG);
+ m_ACC.d <<= 1;
+ MODIFY_AR_ARP();
+ }
+ else SET1(TC_FLAG);
+}
+void tms32025_device::or_()
+{
+ GETDATA(0, 0);
+ m_ACC.w.l |= m_ALU.w.l;
+}
+void tms32025_device::ork()
+{
+ m_ALU.d = (UINT16)M_RDOP_ARG(m_PC);
+ m_PC++;
+ m_ALU.d <<= (m_opcode.b.h & 0xf);
+ m_ACC.d |= (m_ALU.d);
+}
+void tms32025_device::out()
+{
+ GETDATA(0, 0);
+ P_OUT( (m_opcode.b.h & 0xf), m_ALU.w.l );
+}
+void tms32025_device::pac()
+{
+ SHIFT_Preg_TO_ALU();
+ m_ACC.d = m_ALU.d;
+}
+void tms32025_device::pop()
+{
+ m_ACC.d = (UINT16)POP_STACK();
+}
+void tms32025_device::popd()
+{
+ m_ALU.d = (UINT16)POP_STACK();
+ PUTDATA(m_ALU.w.l);
+}
+void tms32025_device::pshd()
+{
+ GETDATA(0, 0);
+ PUSH_STACK(m_ALU.w.l);
+}
+void tms32025_device::push()
+{
+ PUSH_STACK(m_ACC.w.l);
+}
+void tms32025_device::rc()
+{
+ CLR1(C_FLAG);
+}
+void tms32025_device::ret()
+{
+ SET_PC(POP_STACK());
+}
+void tms32025_device::rfsm() /** serial port mode */
+{
+ CLR1(FSM_FLAG);
+}
+void tms32025_device::rhm()
+{
+ CLR1(HM_FLAG);
+}
+void tms32025_device::rol()
+{
+ m_ALU.d = m_ACC.d;
+ m_ACC.d <<= 1;
+ if (CARRY) m_ACC.d |= 1;
+ if (m_ALU.d & 0x80000000) SET1(C_FLAG);
+ else CLR1(C_FLAG);
+}
+void tms32025_device::ror()
+{
+ m_ALU.d = m_ACC.d;
+ m_ACC.d >>= 1;
+ if (CARRY) m_ACC.d |= 0x80000000;
+ if (m_ALU.d & 1) SET1(C_FLAG);
+ else CLR1(C_FLAG);
+}
+void tms32025_device::rovm()
+{
+ CLR0(OVM_FLAG);
+}
+void tms32025_device::rpt()
+{
+ GETDATA(0, 0);
+ m_RPTC = m_ALU.b.l;
+ m_init_load_addr = 2; /* Initiate repeat mode */
+}
+void tms32025_device::rptk()
+{
+ m_RPTC = m_opcode.b.l;
+ m_init_load_addr = 2; /* Initiate repeat mode */
+}
+void tms32025_device::rsxm()
+{
+ CLR1(SXM_FLAG);
+}
+void tms32025_device::rtc()
+{
+ CLR1(TC_FLAG);
+}
+void tms32025_device::rtxm() /** Serial port stuff */
+{
+ CLR1(TXM_FLAG);
+}
+void tms32025_device::rxf()
+{
+ CLR1(XF_FLAG);
+ S_OUT(TMS32025_XF,CLEAR_LINE);
+}
+void tms32025_device::sach()
+{
+ m_ALU.d = (m_ACC.d << (m_opcode.b.h & 7));
+ PUTDATA(m_ALU.w.h);
+}
+void tms32025_device::sacl()
+{
+ m_ALU.d = (m_ACC.d << (m_opcode.b.h & 7));
+ PUTDATA(m_ALU.w.l);
+}
+void tms32025_device::sar_ar0() { PUTDATA(m_AR[0]); }
+void tms32025_device::sar_ar1() { PUTDATA(m_AR[1]); }
+void tms32025_device::sar_ar2() { PUTDATA(m_AR[2]); }
+void tms32025_device::sar_ar3() { PUTDATA(m_AR[3]); }
+void tms32025_device::sar_ar4() { PUTDATA(m_AR[4]); }
+void tms32025_device::sar_ar5() { PUTDATA(m_AR[5]); }
+void tms32025_device::sar_ar6() { PUTDATA(m_AR[6]); }
+void tms32025_device::sar_ar7() { PUTDATA(m_AR[7]); }
+
+void tms32025_device::sblk()
+{
+ m_oldacc.d = m_ACC.d;
+ if (SXM) m_ALU.d = (INT16)M_RDOP_ARG(m_PC);
+ else m_ALU.d = (UINT16)M_RDOP_ARG(m_PC);
+ m_PC++;
+ m_ALU.d <<= (m_opcode.b.h & 0xf);
+ m_ACC.d -= m_ALU.d;
+ CALCULATE_SUB_OVERFLOW(m_ALU.d);
+ CALCULATE_SUB_CARRY();
+}
+void tms32025_device::sbrk_ar()
+{
+ m_AR[ARP] -= m_opcode.b.l;
+}
+void tms32025_device::sc()
+{
+ SET1(C_FLAG);
+}
+void tms32025_device::sfl()
+{
+ m_ALU.d = m_ACC.d;
+ m_ACC.d <<= 1;
+ if (m_ALU.d & 0x80000000) SET1(C_FLAG);
+ else CLR1(C_FLAG);
+}
+void tms32025_device::sfr()
+{
+ m_ALU.d = m_ACC.d;
+ m_ACC.d >>= 1;
+ if (SXM) {
+ if (m_ALU.d & 0x80000000) m_ACC.d |= 0x80000000;
+ }
+ if (m_ALU.d & 1) SET1(C_FLAG);
+ else CLR1(C_FLAG);
+}
+void tms32025_device::sfsm() /** Serial port mode */
+{
+ SET1(FSM_FLAG);
+}
+void tms32025_device::shm()
+{
+ SET1(HM_FLAG);
+}
+void tms32025_device::sovm()
+{
+ SET0(OVM_FLAG);
+}
+void tms32025_device::spac()
+{
+ m_oldacc.d = m_ACC.d;
+ SHIFT_Preg_TO_ALU();
+ m_ACC.d -= m_ALU.d;
+ CALCULATE_SUB_OVERFLOW(m_ALU.d);
+ CALCULATE_SUB_CARRY();
+}
+void tms32025_device::sph()
+{
+ SHIFT_Preg_TO_ALU();
+ PUTDATA(m_ALU.w.h);
+}
+void tms32025_device::spl()
+{
+ SHIFT_Preg_TO_ALU();
+ PUTDATA(m_ALU.w.l);
+}
+void tms32025_device::spm()
+{
+ MODIFY_PM((m_opcode.b.l & 3) );
+}
+void tms32025_device::sqra()
+{
+ m_oldacc.d = m_ACC.d;
+ SHIFT_Preg_TO_ALU();
+ m_ACC.d += m_ALU.d;
+ CALCULATE_ADD_OVERFLOW(m_ALU.d);
+ CALCULATE_ADD_CARRY();
+ GETDATA(0, 0);
+ m_Treg = m_ALU.w.l;
+ m_Preg.d = ((INT16)m_ALU.w.l * (INT16)m_ALU.w.l);
+}
+void tms32025_device::sqrs()
+{
+ m_oldacc.d = m_ACC.d;
+ SHIFT_Preg_TO_ALU();
+ m_ACC.d -= m_ALU.d;
+ CALCULATE_SUB_OVERFLOW(m_ALU.d);
+ CALCULATE_SUB_CARRY();
+ GETDATA(0, 0);
+ m_Treg = m_ALU.w.l;
+ m_Preg.d = ((INT16)m_ALU.w.l * (INT16)m_ALU.w.l);
+}
+void tms32025_device::sst()
+{
+ PUTDATA_SST(m_STR0);
+}
+void tms32025_device::sst1()
+{
+ PUTDATA_SST(m_STR1);
+}
+void tms32025_device::ssxm()
+{
+ SET1(SXM_FLAG);
+}
+void tms32025_device::stc()
+{
+ SET1(TC_FLAG);
+}
+void tms32025_device::stxm() /** Serial port stuff */
+{
+ SET1(TXM_FLAG);
+}
+void tms32025_device::sub()
+{
+ m_oldacc.d = m_ACC.d;
+ GETDATA((m_opcode.b.h & 0xf), SXM);
+ m_ACC.d -= m_ALU.d;
+ CALCULATE_SUB_OVERFLOW(m_ALU.d);
+ CALCULATE_SUB_CARRY();
+}
+void tms32025_device::subb()
+{
+ m_oldacc.d = m_ACC.d;
+ GETDATA(0, 0);
+ if (CARRY == 0) m_ACC.d--;
+ m_ACC.d -= m_ALU.d;
+ CALCULATE_SUB_OVERFLOW(m_ALU.d);
+ if (m_ACC.d == m_oldacc.d) {} /* edge case, carry remains same */
+ else CALCULATE_SUB_CARRY();
+}
+void tms32025_device::subc()
+{
+ m_oldacc.d = m_ACC.d;
+ GETDATA(15, SXM);
+ m_ACC.d -= m_ALU.d; /* Temporary switch to ACC. Actual calculation is done as (ACC)-[mem] -> ALU, will be preserved later on. */
+ if ((INT32)((m_oldacc.d ^ m_ALU.d) & (m_oldacc.d ^ m_ACC.d)) < 0) {
+ SET0(OV_FLAG); /* Not affected by OVM */
+ }
+ CALCULATE_SUB_CARRY();
+ if( m_oldacc.d >= m_ALU.d ) {
+ m_ALU.d = m_ACC.d;
+ m_ACC.d = m_ACC.d << 1 | 1;
+ }
+ else {
+ m_ALU.d = m_ACC.d;
+ m_ACC.d = m_oldacc.d << 1;
+ }
+}
+void tms32025_device::subh()
+{
+ m_oldacc.d = m_ACC.d;
+ GETDATA(0, 0);
+ m_ACC.w.h -= m_ALU.w.l;
+ if ( (UINT16)(m_oldacc.w.h) < (UINT16)(m_ACC.w.h) ) {
+ CLR1(C_FLAG); /* Carry flag is not affected, if no borrow occurred */
+ }
+ if ((INT16)((m_oldacc.w.h ^ m_ALU.w.l) & (m_oldacc.w.h ^ m_ACC.w.h)) < 0) {
+ SET0(OV_FLAG);
+ if (OVM) m_ACC.w.h = ((INT16)m_oldacc.w.h < 0) ? 0x8000 : 0x7fff;
+ }
+}
+void tms32025_device::subk()
+{
+ m_oldacc.d = m_ACC.d;
+ m_ALU.d = (UINT8)m_opcode.b.l;
+ m_ACC.d -= m_ALU.b.l;
+ CALCULATE_SUB_OVERFLOW(m_ALU.d);
+ CALCULATE_SUB_CARRY();
+}
+void tms32025_device::subs()
+{
+ m_oldacc.d = m_ACC.d;
+ GETDATA(0, 0);
+ m_ACC.d -= m_ALU.w.l;
+ CALCULATE_SUB_OVERFLOW(m_ALU.d);
+ CALCULATE_SUB_CARRY();
+}
+void tms32025_device::subt()
+{
+ m_oldacc.d = m_ACC.d;
+ GETDATA((m_Treg & 0xf), SXM);
+ m_ACC.d -= m_ALU.d;
+ CALCULATE_SUB_OVERFLOW(m_ALU.d);
+ CALCULATE_SUB_CARRY();
+}
+void tms32025_device::sxf()
+{
+ SET1(XF_FLAG);
+ S_OUT(TMS32025_XF,ASSERT_LINE);
+}
+void tms32025_device::tblr()
+{
+ if (m_init_load_addr) {
+ m_PFC = m_ACC.w.l;
+ }
+ m_ALU.w.l = M_RDROM(m_PFC);
+ if ( (CNF0) && ( (UINT16)(m_PFC) >= 0xff00 ) ) {} /** TMS32025 only */
+ else m_tms32025_dec_cycles += (1*CLK);
+ PUTDATA(m_ALU.w.l);
+ m_PFC++;
+}
+void tms32025_device::tblw()
+{
+ if (m_init_load_addr) {
+ m_PFC = m_ACC.w.l;
+ }
+ m_tms32025_dec_cycles += (1*CLK);
+ GETDATA(0, 0);
+ if (m_external_mem_access) m_tms32025_dec_cycles += (1*CLK);
+ M_WRTROM(m_PFC, m_ALU.w.l);
+ m_PFC++;
+}
+void tms32025_device::trap()
+{
+ PUSH_STACK(m_PC);
+ SET_PC(0x001E); /* Trap vector */
+}
+void tms32025_device::xor_()
+{
+ GETDATA(0, 0);
+ m_ACC.w.l ^= m_ALU.w.l;
+}
+void tms32025_device::xork()
+{
+ m_ALU.d = M_RDOP_ARG(m_PC);
+ m_PC++;
+ m_ALU.d <<= (m_opcode.b.h & 0xf);
+ m_ACC.d ^= m_ALU.d;
+}
+void tms32025_device::zalh()
+{
+ GETDATA(0, 0);
+ m_ACC.w.h = m_ALU.w.l;
+ m_ACC.w.l = 0x0000;
+}
+void tms32025_device::zalr()
+{
+ GETDATA(0, 0);
+ m_ACC.w.h = m_ALU.w.l;
+ m_ACC.w.l = 0x8000;
+}
+void tms32025_device::zals()
+{
+ GETDATA(0, 0);
+ m_ACC.w.l = m_ALU.w.l;
+ m_ACC.w.h = 0x0000;
+}
+
+
+/***********************************************************************
+ * Opcode Table (Cycles, Instruction)
+ ***********************************************************************/
+
+const tms32025_device::tms32025_opcode tms32025_device::s_opcode_main[256]=
+{
+/*00*/ {1*CLK, &tms32025_device::add },{1*CLK, &tms32025_device::add },{1*CLK, &tms32025_device::add },{1*CLK, &tms32025_device::add },{1*CLK, &tms32025_device::add },{1*CLK, &tms32025_device::add },{1*CLK, &tms32025_device::add },{1*CLK, &tms32025_device::add },
+/*08*/ {1*CLK, &tms32025_device::add },{1*CLK, &tms32025_device::add },{1*CLK, &tms32025_device::add },{1*CLK, &tms32025_device::add },{1*CLK, &tms32025_device::add },{1*CLK, &tms32025_device::add },{1*CLK, &tms32025_device::add },{1*CLK, &tms32025_device::add },
+/*10*/ {1*CLK, &tms32025_device::sub },{1*CLK, &tms32025_device::sub },{1*CLK, &tms32025_device::sub },{1*CLK, &tms32025_device::sub },{1*CLK, &tms32025_device::sub },{1*CLK, &tms32025_device::sub },{1*CLK, &tms32025_device::sub },{1*CLK, &tms32025_device::sub },
+/*18*/ {1*CLK, &tms32025_device::sub },{1*CLK, &tms32025_device::sub },{1*CLK, &tms32025_device::sub },{1*CLK, &tms32025_device::sub },{1*CLK, &tms32025_device::sub },{1*CLK, &tms32025_device::sub },{1*CLK, &tms32025_device::sub },{1*CLK, &tms32025_device::sub },
+/*20*/ {1*CLK, &tms32025_device::lac },{1*CLK, &tms32025_device::lac },{1*CLK, &tms32025_device::lac },{1*CLK, &tms32025_device::lac },{1*CLK, &tms32025_device::lac },{1*CLK, &tms32025_device::lac },{1*CLK, &tms32025_device::lac },{1*CLK, &tms32025_device::lac },
+/*28*/ {1*CLK, &tms32025_device::lac },{1*CLK, &tms32025_device::lac },{1*CLK, &tms32025_device::lac },{1*CLK, &tms32025_device::lac },{1*CLK, &tms32025_device::lac },{1*CLK, &tms32025_device::lac },{1*CLK, &tms32025_device::lac },{1*CLK, &tms32025_device::lac },
+/*30*/ {1*CLK, &tms32025_device::lar_ar0 },{1*CLK, &tms32025_device::lar_ar1 },{1*CLK, &tms32025_device::lar_ar2 },{1*CLK, &tms32025_device::lar_ar3 },{1*CLK, &tms32025_device::lar_ar4 },{1*CLK, &tms32025_device::lar_ar5 },{1*CLK, &tms32025_device::lar_ar6 },{1*CLK, &tms32025_device::lar_ar7 },
+/*38*/ {1*CLK, &tms32025_device::mpy },{1*CLK, &tms32025_device::sqra },{1*CLK, &tms32025_device::mpya },{1*CLK, &tms32025_device::mpys },{1*CLK, &tms32025_device::lt },{1*CLK, &tms32025_device::lta },{1*CLK, &tms32025_device::ltp },{1*CLK, &tms32025_device::ltd },
+/*40*/ {1*CLK, &tms32025_device::zalh },{1*CLK, &tms32025_device::zals },{1*CLK, &tms32025_device::lact },{1*CLK, &tms32025_device::addc },{1*CLK, &tms32025_device::subh },{1*CLK, &tms32025_device::subs },{1*CLK, &tms32025_device::subt },{1*CLK, &tms32025_device::subc },
+/*48*/ {1*CLK, &tms32025_device::addh },{1*CLK, &tms32025_device::adds },{1*CLK, &tms32025_device::addt },{1*CLK, &tms32025_device::rpt },{1*CLK, &tms32025_device::xor_ },{1*CLK, &tms32025_device::or_ },{1*CLK, &tms32025_device::and_ },{1*CLK, &tms32025_device::subb },
+/*50*/ {1*CLK, &tms32025_device::lst },{1*CLK, &tms32025_device::lst1 },{1*CLK, &tms32025_device::ldp },{1*CLK, &tms32025_device::lph },{1*CLK, &tms32025_device::pshd },{1*CLK, &tms32025_device::mar },{1*CLK, &tms32025_device::dmov },{1*CLK, &tms32025_device::bitt },
+/*58*/ {3*CLK, &tms32025_device::tblr },{2*CLK, &tms32025_device::tblw },{1*CLK, &tms32025_device::sqrs },{1*CLK, &tms32025_device::lts },{2*CLK, &tms32025_device::macd },{2*CLK, &tms32025_device::mac },{2*CLK, &tms32025_device::bc },{2*CLK, &tms32025_device::bnc },
+/*60*/ {1*CLK, &tms32025_device::sacl },{1*CLK, &tms32025_device::sacl },{1*CLK, &tms32025_device::sacl },{1*CLK, &tms32025_device::sacl },{1*CLK, &tms32025_device::sacl },{1*CLK, &tms32025_device::sacl },{1*CLK, &tms32025_device::sacl },{1*CLK, &tms32025_device::sacl },
+/*68*/ {1*CLK, &tms32025_device::sach },{1*CLK, &tms32025_device::sach },{1*CLK, &tms32025_device::sach },{1*CLK, &tms32025_device::sach },{1*CLK, &tms32025_device::sach },{1*CLK, &tms32025_device::sach },{1*CLK, &tms32025_device::sach },{1*CLK, &tms32025_device::sach },
+/*70*/ {1*CLK, &tms32025_device::sar_ar0 },{1*CLK, &tms32025_device::sar_ar1 },{1*CLK, &tms32025_device::sar_ar2 },{1*CLK, &tms32025_device::sar_ar3 },{1*CLK, &tms32025_device::sar_ar4 },{1*CLK, &tms32025_device::sar_ar5 },{1*CLK, &tms32025_device::sar_ar6 },{1*CLK, &tms32025_device::sar_ar7 },
+/*78*/ {1*CLK, &tms32025_device::sst },{1*CLK, &tms32025_device::sst1 },{1*CLK, &tms32025_device::popd },{1*CLK, &tms32025_device::zalr },{1*CLK, &tms32025_device::spl },{1*CLK, &tms32025_device::sph },{1*CLK, &tms32025_device::adrk },{1*CLK, &tms32025_device::sbrk_ar },
+/*80*/ {2*CLK, &tms32025_device::in },{2*CLK, &tms32025_device::in },{2*CLK, &tms32025_device::in },{2*CLK, &tms32025_device::in },{2*CLK, &tms32025_device::in },{2*CLK, &tms32025_device::in },{2*CLK, &tms32025_device::in },{2*CLK, &tms32025_device::in },
+/*88*/ {2*CLK, &tms32025_device::in },{2*CLK, &tms32025_device::in },{2*CLK, &tms32025_device::in },{2*CLK, &tms32025_device::in },{2*CLK, &tms32025_device::in },{2*CLK, &tms32025_device::in },{2*CLK, &tms32025_device::in },{2*CLK, &tms32025_device::in },
+/*90*/ {1*CLK, &tms32025_device::bit },{1*CLK, &tms32025_device::bit },{1*CLK, &tms32025_device::bit },{1*CLK, &tms32025_device::bit },{1*CLK, &tms32025_device::bit },{1*CLK, &tms32025_device::bit },{1*CLK, &tms32025_device::bit },{1*CLK, &tms32025_device::bit },
+/*98*/ {1*CLK, &tms32025_device::bit },{1*CLK, &tms32025_device::bit },{1*CLK, &tms32025_device::bit },{1*CLK, &tms32025_device::bit },{1*CLK, &tms32025_device::bit },{1*CLK, &tms32025_device::bit },{1*CLK, &tms32025_device::bit },{1*CLK, &tms32025_device::bit },
+/*A0*/ {1*CLK, &tms32025_device::mpyk },{1*CLK, &tms32025_device::mpyk },{1*CLK, &tms32025_device::mpyk },{1*CLK, &tms32025_device::mpyk },{1*CLK, &tms32025_device::mpyk },{1*CLK, &tms32025_device::mpyk },{1*CLK, &tms32025_device::mpyk },{1*CLK, &tms32025_device::mpyk },
+/*A8*/ {1*CLK, &tms32025_device::mpyk },{1*CLK, &tms32025_device::mpyk },{1*CLK, &tms32025_device::mpyk },{1*CLK, &tms32025_device::mpyk },{1*CLK, &tms32025_device::mpyk },{1*CLK, &tms32025_device::mpyk },{1*CLK, &tms32025_device::mpyk },{1*CLK, &tms32025_device::mpyk },
+/*B0*/ {1*CLK, &tms32025_device::mpyk },{1*CLK, &tms32025_device::mpyk },{1*CLK, &tms32025_device::mpyk },{1*CLK, &tms32025_device::mpyk },{1*CLK, &tms32025_device::mpyk },{1*CLK, &tms32025_device::mpyk },{1*CLK, &tms32025_device::mpyk },{1*CLK, &tms32025_device::mpyk },
+/*B8*/ {1*CLK, &tms32025_device::mpyk },{1*CLK, &tms32025_device::mpyk },{1*CLK, &tms32025_device::mpyk },{1*CLK, &tms32025_device::mpyk },{1*CLK, &tms32025_device::mpyk },{1*CLK, &tms32025_device::mpyk },{1*CLK, &tms32025_device::mpyk },{1*CLK, &tms32025_device::mpyk },
+/*C0*/ {1*CLK, &tms32025_device::lark_ar0 },{1*CLK, &tms32025_device::lark_ar1 },{1*CLK, &tms32025_device::lark_ar2 },{1*CLK, &tms32025_device::lark_ar3 },{1*CLK, &tms32025_device::lark_ar4 },{1*CLK, &tms32025_device::lark_ar5 },{1*CLK, &tms32025_device::lark_ar6 },{1*CLK, &tms32025_device::lark_ar7 },
+/*C8*/ {1*CLK, &tms32025_device::ldpk },{1*CLK, &tms32025_device::ldpk },{1*CLK, &tms32025_device::lack },{1*CLK, &tms32025_device::rptk },{1*CLK, &tms32025_device::addk },{1*CLK, &tms32025_device::subk },{1*CLK, &tms32025_device::opcodes_CE},{1*CLK, &tms32025_device::mpyu },
+/*D0*/ {1*CLK, &tms32025_device::opcodes_Dx},{1*CLK, &tms32025_device::opcodes_Dx},{1*CLK, &tms32025_device::opcodes_Dx},{1*CLK, &tms32025_device::opcodes_Dx},{1*CLK, &tms32025_device::opcodes_Dx},{1*CLK, &tms32025_device::opcodes_Dx},{1*CLK, &tms32025_device::opcodes_Dx},{0*CLK, &tms32025_device::opcodes_Dx},
+/*D8*/ {1*CLK, &tms32025_device::opcodes_Dx},{1*CLK, &tms32025_device::opcodes_Dx},{1*CLK, &tms32025_device::opcodes_Dx},{1*CLK, &tms32025_device::opcodes_Dx},{1*CLK, &tms32025_device::opcodes_Dx},{1*CLK, &tms32025_device::opcodes_Dx},{1*CLK, &tms32025_device::opcodes_Dx},{1*CLK, &tms32025_device::opcodes_Dx},
+/*E0*/ {2*CLK, &tms32025_device::out },{2*CLK, &tms32025_device::out },{2*CLK, &tms32025_device::out },{2*CLK, &tms32025_device::out },{2*CLK, &tms32025_device::out },{2*CLK, &tms32025_device::out },{2*CLK, &tms32025_device::out },{2*CLK, &tms32025_device::out },
+/*E8*/ {2*CLK, &tms32025_device::out },{2*CLK, &tms32025_device::out },{2*CLK, &tms32025_device::out },{2*CLK, &tms32025_device::out },{2*CLK, &tms32025_device::out },{2*CLK, &tms32025_device::out },{2*CLK, &tms32025_device::out },{2*CLK, &tms32025_device::out },
+/*F0*/ {2*CLK, &tms32025_device::bv },{2*CLK, &tms32025_device::bgz },{2*CLK, &tms32025_device::blez },{2*CLK, &tms32025_device::blz },{2*CLK, &tms32025_device::bgez },{2*CLK, &tms32025_device::bnz },{2*CLK, &tms32025_device::bz },{2*CLK, &tms32025_device::bnv },
+/*F8*/ {2*CLK, &tms32025_device::bbz },{2*CLK, &tms32025_device::bbnz },{2*CLK, &tms32025_device::bioz },{2*CLK, &tms32025_device::banz },{2*CLK, &tms32025_device::blkp },{2*CLK, &tms32025_device::blkd },{2*CLK, &tms32025_device::call },{2*CLK, &tms32025_device::br }
+};
+
+const tms32025_device::tms32025_opcode tms32025_device::s_opcode_CE_subset[256]= /* Instructions living under the CExx opcode */
+{
+/*00*/ {1*CLK, &tms32025_device::eint },{1*CLK, &tms32025_device::dint },{1*CLK, &tms32025_device::rovm },{1*CLK, &tms32025_device::sovm },{1*CLK, &tms32025_device::cnfd },{1*CLK, &tms32025_device::cnfp },{1*CLK, &tms32025_device::rsxm },{1*CLK, &tms32025_device::ssxm },
+/*08*/ {1*CLK, &tms32025_device::spm },{1*CLK, &tms32025_device::spm },{1*CLK, &tms32025_device::spm },{1*CLK, &tms32025_device::spm },{1*CLK, &tms32025_device::rxf },{1*CLK, &tms32025_device::sxf },{1*CLK, &tms32025_device::fort },{1*CLK, &tms32025_device::fort },
+/*10*/ {0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{1*CLK, &tms32025_device::pac },{1*CLK, &tms32025_device::apac },{1*CLK, &tms32025_device::spac },{0*CLK, &tms32025_device::illegal },
+/*18*/ {1*CLK, &tms32025_device::sfl },{1*CLK, &tms32025_device::sfr },{0*CLK, &tms32025_device::illegal },{1*CLK, &tms32025_device::abst },{1*CLK, &tms32025_device::push },{1*CLK, &tms32025_device::pop },{2*CLK, &tms32025_device::trap },{3*CLK, &tms32025_device::idle },
+/*20*/ {1*CLK, &tms32025_device::rtxm },{1*CLK, &tms32025_device::stxm },{0*CLK, &tms32025_device::illegal },{1*CLK, &tms32025_device::neg },{2*CLK, &tms32025_device::cala },{2*CLK, &tms32025_device::bacc },{2*CLK, &tms32025_device::ret },{1*CLK, &tms32025_device::cmpl },
+/*28*/ {0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },
+/*30*/ {1*CLK, &tms32025_device::rc },{1*CLK, &tms32025_device::sc },{1*CLK, &tms32025_device::rtc },{1*CLK, &tms32025_device::stc },{1*CLK, &tms32025_device::rol },{1*CLK, &tms32025_device::ror },{1*CLK, &tms32025_device::rfsm },{1*CLK, &tms32025_device::sfsm },
+/*38*/ {1*CLK, &tms32025_device::rhm },{1*CLK, &tms32025_device::shm },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{1*CLK, &tms32025_device::conf },{1*CLK, &tms32025_device::conf },{1*CLK, &tms32025_device::conf },{1*CLK, &tms32025_device::conf },
+/*40*/ {0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },
+/*48*/ {0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },
+/*50*/ {1*CLK, &tms32025_device::cmpr },{1*CLK, &tms32025_device::cmpr },{1*CLK, &tms32025_device::cmpr },{1*CLK, &tms32025_device::cmpr },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },
+/*58*/ {0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },
+/*60*/ {0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },
+/*68*/ {0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },
+/*70*/ {0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },
+/*78*/ {0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },
+/*80*/ {0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{1*CLK, &tms32025_device::norm },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },
+/*88*/ {0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },
+/*90*/ {0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{1*CLK, &tms32025_device::norm },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },
+/*98*/ {0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },
+/*A0*/ {0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{1*CLK, &tms32025_device::norm },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },
+/*A8*/ {0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },
+/*B0*/ {0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{1*CLK, &tms32025_device::norm },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },
+/*B8*/ {0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },
+/*C0*/ {0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{1*CLK, &tms32025_device::norm },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },
+/*C8*/ {0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },
+/*D0*/ {0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{1*CLK, &tms32025_device::norm },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },
+/*D8*/ {0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },
+/*E0*/ {0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{1*CLK, &tms32025_device::norm },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },
+/*E8*/ {0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },
+/*F0*/ {0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{1*CLK, &tms32025_device::norm },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },
+/*F8*/ {0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal },{0*CLK, &tms32025_device::illegal }
+};
+
+const tms32025_device::tms32025_opcode tms32025_device::s_opcode_Dx_subset[8]= /* Instructions living under the Dxxx opcode */
+{
+/*00*/ {2*CLK, &tms32025_device::lrlk },{2*CLK, &tms32025_device::lalk },{2*CLK, &tms32025_device::adlk },{2*CLK, &tms32025_device::sblk },{2*CLK, &tms32025_device::andk },{2*CLK, &tms32025_device::ork },{2*CLK, &tms32025_device::xork },{0*CLK, &tms32025_device::illegal }
+};
+
+
+
+/****************************************************************************
+ * Initialise the CPU emulation
+ ****************************************************************************/
+void tms32025_device::device_start()
+{
+ m_program = &space(AS_PROGRAM);
+ m_direct = &m_program->direct();
+ m_data = &space(AS_DATA);
+ m_io = &space(AS_IO);
+
+ m_PREVPC = 0;
+ m_PFC = 0;
+ m_STR0 = 0;
+ m_STR1 = 0;
+ m_ACC.d = 0;
+ m_Preg.d = 0;
+ m_Treg = 0;
+ m_AR[0] = m_AR[1] = m_AR[2] = m_AR[3] = m_AR[4] = m_AR[5] = m_AR[6] = m_AR[7] = 0;
+ m_STACK[0] = m_STACK[1] = m_STACK[2] = m_STACK[3] = m_STACK[4] = m_STACK[5] = m_STACK[6] = m_STACK[7] = 0;
+ m_ALU.d = 0;
+ memset(m_intRAM, 0, sizeof(m_intRAM));
+ m_timerover = 0;
+ m_opcode.d = 0;
+ m_external_mem_access = 0;
+ m_tms32025_irq_cycles = 0;
+ m_oldacc.d = 0;
+ m_memaccess = 0;
+ m_mHackIgnoreARP = 0;
+ m_waiting_for_serial_frame = 0;
+
+ save_item(NAME(m_PC));
+ save_item(NAME(m_STR0));
+ save_item(NAME(m_STR1));
+ save_item(NAME(m_PFC));
+ save_item(NAME(m_IFR));
+ save_item(NAME(m_RPTC));
+ save_item(NAME(m_ACC.d));
+ save_item(NAME(m_ALU.d));
+ save_item(NAME(m_Preg.d));
+ save_item(NAME(m_Treg));
+ save_item(NAME(m_AR[0]));
+ save_item(NAME(m_AR[1]));
+ save_item(NAME(m_AR[2]));
+ save_item(NAME(m_AR[3]));
+ save_item(NAME(m_AR[4]));
+ save_item(NAME(m_AR[5]));
+ save_item(NAME(m_AR[6]));
+ save_item(NAME(m_AR[7]));
+ save_item(NAME(m_STACK[0]));
+ save_item(NAME(m_STACK[1]));
+ save_item(NAME(m_STACK[2]));
+ save_item(NAME(m_STACK[3]));
+ save_item(NAME(m_STACK[4]));
+ save_item(NAME(m_STACK[5]));
+ save_item(NAME(m_STACK[6]));
+ save_item(NAME(m_STACK[7]));
+
+ save_item(NAME(m_oldacc));
+ save_item(NAME(m_memaccess));
+ save_item(NAME(m_mHackIgnoreARP));
+
+ save_item(NAME(m_idle));
+ save_item(NAME(m_hold));
+ save_item(NAME(m_external_mem_access));
+ save_item(NAME(m_init_load_addr));
+ save_item(NAME(m_PREVPC));
+
+ save_item(NAME(m_intRAM));
+
+ state_add( TMS32025_PC, "PC", m_PC).formatstr("%04X");
+ state_add( TMS32025_STR0, "STR0", m_STR0).formatstr("%04X");
+ state_add( TMS32025_STR1, "STR1", m_STR1).formatstr("%04X");
+ state_add( TMS32025_IFR, "IFR", m_IFR).formatstr("%04X");
+ state_add( TMS32025_RPTC, "RPTC", m_RPTC).formatstr("%02X");
+ state_add( TMS32025_STK7, "STK7", m_STACK[7]).formatstr("%04X");
+ state_add( TMS32025_STK6, "STK6", m_STACK[6]).formatstr("%04X");
+ state_add( TMS32025_STK5, "STK5", m_STACK[5]).formatstr("%04X");
+ state_add( TMS32025_STK4, "STK4", m_STACK[4]).formatstr("%04X");
+ state_add( TMS32025_STK3, "STK3", m_STACK[3]).formatstr("%04X");
+ state_add( TMS32025_STK2, "STK2", m_STACK[2]).formatstr("%04X");
+ state_add( TMS32025_STK1, "STK1", m_STACK[1]).formatstr("%04X");
+ state_add( TMS32025_STK0, "STK0", m_STACK[0]).formatstr("%04X");
+ state_add( TMS32025_ACC, "ACC", m_ACC.d).formatstr("%08X");
+ state_add( TMS32025_PREG, "P", m_Preg.d).formatstr("%08X");
+ state_add( TMS32025_TREG, "T", m_Treg).formatstr("%04X");
+ state_add( TMS32025_AR0, "AR0", m_AR[0]).formatstr("%04X");
+ state_add( TMS32025_AR1, "AR1", m_AR[1]).formatstr("%04X");
+ state_add( TMS32025_AR2, "AR2", m_AR[2]).formatstr("%04X");
+ state_add( TMS32025_AR3, "AR3", m_AR[3]).formatstr("%04X");
+ state_add( TMS32025_AR4, "AR4", m_AR[4]).formatstr("%04X");
+ state_add( TMS32025_AR5, "AR5", m_AR[5]).formatstr("%04X");
+ state_add( TMS32025_AR6, "AR6", m_AR[6]).formatstr("%04X");
+ state_add( TMS32025_AR7, "AR7", m_AR[7]).formatstr("%04X");
+ state_add( TMS32025_DRR, "DRR", m_debugger_temp).callimport().callexport().formatstr("%04X");
+ state_add( TMS32025_DXR, "DXR", m_debugger_temp).callimport().callexport().formatstr("%04X");
+ state_add( TMS32025_TIM, "TIM", m_debugger_temp).callimport().callexport().formatstr("%04X");
+ state_add( TMS32025_PRD, "PRD", m_debugger_temp).callimport().callexport().formatstr("%04X");
+ state_add( TMS32025_IMR, "IMR", m_debugger_temp).callimport().callexport().formatstr("%04X");
+ state_add( TMS32025_GREG, "GREG", m_debugger_temp).callimport().callexport().formatstr("%04X");
+
+ state_add(STATE_GENPC, "GENPC", m_PC).formatstr("%04X").noshow();
+ /* This is actually not a stack pointer, but the stack contents */
+ state_add(STATE_GENSP, "GENSP", m_STACK[7]).formatstr("%04X").noshow();
+ state_add(STATE_GENFLAGS, "GENFLAGS", m_STR0).formatstr("%33s").noshow();
+ state_add(STATE_GENPCBASE, "GENPCBASE", m_PREVPC).formatstr("%04X").noshow();
+
+ m_icountptr = &m_icount;
+}
+
+
+void tms32025_device::state_import(const device_state_entry &entry)
+{
+ switch (entry.index())
+ {
+ case TMS32025_DRR:
+ M_WRTRAM(0, m_debugger_temp);
+ break;
+
+ case TMS32025_DXR:
+ M_WRTRAM(1, m_debugger_temp);
+ break;
+
+ case TMS32025_TIM:
+ M_WRTRAM(2, m_debugger_temp);
+ break;
+
+ case TMS32025_PRD:
+ M_WRTRAM(3, m_debugger_temp);
+ break;
+
+ case TMS32025_IMR:
+ M_WRTRAM(4,m_debugger_temp);
+ break;
+
+ case TMS32025_GREG:
+ M_WRTRAM(5, m_debugger_temp);
+ break;
+ }
+}
+
+
+void tms32025_device::state_export(const device_state_entry &entry)
+{
+ switch (entry.index())
+ {
+ case TMS32025_DRR:
+ m_debugger_temp = M_RDRAM(0);
+ break;
+
+ case TMS32025_DXR:
+ m_debugger_temp = M_RDRAM(1);
+ break;
+
+ case TMS32025_TIM:
+ m_debugger_temp = M_RDRAM(2);
+ break;
+
+ case TMS32025_PRD:
+ m_debugger_temp = M_RDRAM(3);
+ break;
+
+ case TMS32025_IMR:
+ m_debugger_temp = M_RDRAM(4);
+ break;
+
+ case TMS32025_GREG:
+ m_debugger_temp = M_RDRAM(5);
+ break;
+ }
+}
+
+
+void tms32025_device::state_string_export(const device_state_entry &entry, std::string &str)
+{
+ switch (entry.index())
+ {
+ case STATE_GENFLAGS:
+ strprintf(str, "arp%d%c%c%c%cdp%03x arb%d%c%c%c%c%c%c%c%c%c%c%cpm%d",
+ (m_STR0 & 0xe000) >> 13,
+ m_STR0 & 0x1000 ? 'O':'.',
+ m_STR0 & 0x0800 ? 'M':'.',
+ m_STR0 & 0x0400 ? '.':'?',
+ m_STR0 & 0x0200 ? 'I':'.',
+ (m_STR0 & 0x01ff),
+
+ (m_STR1 & 0xe000) >> 13,
+ m_STR1 & 0x1000 ? 'P':'D',
+ m_STR1 & 0x0800 ? 'T':'.',
+ m_STR1 & 0x0400 ? 'S':'.',
+ m_STR1 & 0x0200 ? 'C':'?',
+ m_STR0 & 0x0100 ? '.':'?',
+ m_STR1 & 0x0080 ? '.':'?',
+ m_STR1 & 0x0040 ? 'H':'.',
+ m_STR1 & 0x0020 ? 'F':'.',
+ m_STR1 & 0x0010 ? 'X':'.',
+ m_STR1 & 0x0008 ? 'f':'.',
+ m_STR1 & 0x0004 ? 'o':'i',
+ (m_STR1 & 0x0003)
+ );
+ break;
+ }
+}
+
+
+/****************************************************************************
+ * Reset registers to their initial values
+ ****************************************************************************/
+void tms32025_device::device_reset()
+{
+ SET_PC(0); /* Starting address on a reset */
+ m_STR0 |= 0x0600; /* INTM and unused bit set to 1 */
+ m_STR0 &= 0xefff; /* OV cleared to 0. Remaining bits undefined */
+ m_STR1 |= 0x07f0; /* SXM, C, HM, FSM, XF and unused bits set to 1 */
+ m_STR1 &= 0xeff0; /* CNF, FO, TXM, PM bits cleared to 0. Remaining bits undefined */
+ m_RPTC = 0; /* Reset repeat counter to 0 */
+ m_IFR = 0; /* IRQ pending flags */
+
+ S_OUT(TMS32025_XF,ASSERT_LINE); /* XF flag is high. Must set the pin */
+
+ /* Set the internal memory mapped registers */
+ GREG = 0;
+ TIM = 0xffff;
+ PRD = 0xffff;
+ IMR = 0xffc0;
+
+ m_idle = 0;
+ m_hold = 0;
+ m_tms32025_dec_cycles = 0;
+ m_init_load_addr = 1;
+
+ /* Reset the Data/Program address banks */
+ memset(m_pgmmap, 0, sizeof(m_pgmmap));
+ memset(m_datamap, 0, sizeof(m_datamap));
+
+ m_datamap[0] = &m_intRAM[0x000]; /* B2 */
+ m_datamap[4] = &m_intRAM[0x200]; /* B0 */
+ m_datamap[5] = &m_intRAM[0x280]; /* B0 */
+ m_datamap[6] = &m_intRAM[0x300]; /* B1 */
+ m_datamap[7] = &m_intRAM[0x380]; /* B1 */
+}
+
+void tms32026_device::device_reset()
+{
+ tms32025_device::device_reset();
+
+ m_datamap[8] = &m_intRAM[0x400]; /* B1 */
+ m_datamap[9] = &m_intRAM[0x480]; /* B1 */
+ m_datamap[10] = &m_intRAM[0x500]; /* B1 */
+ m_datamap[11] = &m_intRAM[0x580]; /* B1 */
+ m_datamap[12] = &m_intRAM[0x600]; /* B3 */
+ m_datamap[13] = &m_intRAM[0x680]; /* B3 */
+ m_datamap[14] = &m_intRAM[0x700]; /* B3 */
+ m_datamap[15] = &m_intRAM[0x780]; /* B3 */
+}
+
+
+/****************************************************************************
+ * Issue an interrupt if necessary
+ ****************************************************************************/
+int tms32025_device::process_IRQs()
+{
+ /********** Interrupt Flag Register (IFR) **********
+ | 5 | 4 | 3 | 2 | 1 | 0 |
+ | XINT| RINT| TINT| INT2| INT1| INT0|
+ */
+
+ m_tms32025_irq_cycles = 0;
+
+ /* Dont service Interrupts if masked, or prev instruction was EINT ! */
+
+ if ( (INTM == 0) && (m_opcode.w.l != 0xce00) && (m_IFR & IMR) )
+ {
+ m_tms32025_irq_cycles = (3*CLK); /* 3 clock cycles used due to PUSH and DINT operation ? */
+ PUSH_STACK(m_PC);
+
+ if ((m_IFR & 0x01) && (IMR & 0x01)) { /* IRQ line 0 */
+ //logerror("TMS32025: Active INT0\n");
+ SET_PC(0x0002);
+ standard_irq_callback(0);
+ m_idle = 0;
+ m_IFR &= (~0x01);
+ SET0(INTM_FLAG);
+ return m_tms32025_irq_cycles;
+ }
+ if ((m_IFR & 0x02) && (IMR & 0x02)) { /* IRQ line 1 */
+ //logerror("TMS32025: Active INT1\n");
+ SET_PC(0x0004);
+ standard_irq_callback(1);
+ m_idle = 0;
+ m_IFR &= (~0x02);
+ SET0(INTM_FLAG);
+ return m_tms32025_irq_cycles;
+ }
+ if ((m_IFR & 0x04) && (IMR & 0x04)) { /* IRQ line 2 */
+ //logerror("TMS32025: Active INT2\n");
+ SET_PC(0x0006);
+ standard_irq_callback(2);
+ m_idle = 0;
+ m_IFR &= (~0x04);
+ SET0(INTM_FLAG);
+ return m_tms32025_irq_cycles;
+ }
+ if ((m_IFR & 0x08) && (IMR & 0x08)) { /* Timer IRQ (internal) */
+// logerror("TMS32025: Active TINT (Timer)\n");
+ SET_PC(0x0018);
+ m_idle = 0;
+ m_IFR &= (~0x08);
+ SET0(INTM_FLAG);
+ return m_tms32025_irq_cycles;
+ }
+ if ((m_IFR & 0x10) && (IMR & 0x10)) { /* Serial port receive IRQ (internal) */
+// logerror("TMS32025: Active RINT (Serial receive)\n");
+ DRR = S_IN(TMS32025_DR);
+ SET_PC(0x001A);
+ m_idle = 0;
+ m_IFR &= (~0x10);
+ SET0(INTM_FLAG);
+ return m_tms32025_irq_cycles;
+ }
+ if ((m_IFR & 0x20) && (IMR & 0x20)) { /* Serial port transmit IRQ (internal) */
+// logerror("TMS32025: Active XINT (Serial transmit)\n");
+ S_OUT(TMS32025_DX,DXR);
+ SET_PC(0x001C);
+ m_idle = 0;
+ m_IFR &= (~0x20);
+ SET0(INTM_FLAG);
+ return m_tms32025_irq_cycles;
+ }
+ }
+ return m_tms32025_irq_cycles;
+}
+
+
+void tms32025_device::process_timer(int clocks)
+{
+ int preclocks, ticks;
+
+ /* easy case: no actual ticks */
+again:
+ preclocks = CLK - m_timerover;
+ if (clocks < preclocks)
+ {
+ m_timerover += clocks;
+ m_icount -= clocks;
+ return;
+ }
+
+ /* if we're not going to overflow the timer, just count the clocks */
+ ticks = 1 + (clocks - preclocks) / CLK;
+ if (ticks <= TIM)
+ {
+ m_icount -= clocks;
+ m_timerover = clocks - (ticks - 1) * CLK - preclocks;
+ TIM -= ticks;
+ }
+
+ /* otherwise, overflow the timer and signal an interrupt */
+ else
+ {
+ m_icount -= preclocks + CLK * TIM;
+ m_timerover = 0;
+ TIM = PRD;
+
+ m_IFR |= 0x08;
+ clocks = process_IRQs(); /* Handle Timer IRQ */
+ goto again;
+ }
+}
+
+
+/****************************************************************************
+ * Execute ICount cycles. Exit when 0 or less
+ ****************************************************************************/
+void tms32025_device::execute_run()
+{
+ /**** Respond to external hold signal */
+ if (S_IN(TMS32025_HOLD) == ASSERT_LINE) {
+ if (m_hold == 0) {
+ S_OUT(TMS32025_HOLDA,ASSERT_LINE); /* Hold-Ack (active low) */
+ }
+ m_hold = 1;
+ if (HM) {
+ m_icount = 0; /* Exit */
+ }
+ else {
+ if (m_external_mem_access) {
+ m_icount = 0; /* Exit */
+ }
+ }
+ }
+ else {
+ if (m_hold == 1) {
+ S_OUT(TMS32025_HOLDA,CLEAR_LINE); /* Hold-Ack (active low) */
+ process_timer(3);
+ }
+ m_hold = 0;
+ }
+
+ /**** If idling, update timer and/or exit execution, but test for irqs first */
+ if (m_idle && m_IFR && m_icount > 0)
+ m_icount -= process_IRQs();
+
+ while (m_idle && m_icount > 0)
+ process_timer(m_icount);
+
+ if (m_icount <= 0) debugger_instruction_hook(this, m_PC);
+
+
+ while (m_icount > 0)
+ {
+ m_tms32025_dec_cycles = 0;
+
+ if (m_IFR) { /* Check IRQ Flag Register for pending IRQs */
+ m_tms32025_dec_cycles += process_IRQs();
+ }
+
+ m_PREVPC = m_PC;
+
+ debugger_instruction_hook(this, m_PC);
+
+ m_opcode.d = M_RDOP(m_PC);
+ m_PC++;
+
+ if (m_opcode.b.h == 0xCE) /* Opcode 0xCExx has many sub-opcodes in its minor byte */
+ {
+ m_tms32025_dec_cycles += s_opcode_CE_subset[m_opcode.b.l].cycles;
+ (this->*s_opcode_CE_subset[m_opcode.b.l].function)();
+ }
+ else if ((m_opcode.w.l & 0xf0f8) == 0xd000) /* Opcode 0xDxxx has many sub-opcodes in its minor byte */
+ {
+ m_tms32025_dec_cycles += s_opcode_Dx_subset[m_opcode.b.l].cycles;
+ (this->*s_opcode_Dx_subset[m_opcode.b.l].function)();
+ }
+ else /* Do all opcodes except the CExx and Dxxx ones */
+ {
+ m_tms32025_dec_cycles += s_opcode_main[m_opcode.b.h].cycles;
+ (this->*s_opcode_main[m_opcode.b.h].function)();
+ }
+
+
+ if (m_init_load_addr == 2) { /* Repeat next instruction */
+ /****************************************************\
+ ******* These instructions are not repeatable ********
+ ** ADLK, ANDK, LALK, LRLK, ORK, SBLK, XORK **
+ ** ADDK, ADRK, LACK, LARK, LDPK, MPYK, RPTK **
+ ** SBRK, SPM, SUBK, ZAC, IDLE, RPT, TRAP **
+ ** BACC, CALA, RET **
+ ** B, BANZ, BBNZ, BBZ, BC, BGEZ, BGZ, BIOZ **
+ ** BNC, BNV, BNZ, BV, BZ, CALL, BLEZ, BLZ **
+ \****************************************************/
+ m_PREVPC = m_PC;
+
+ debugger_instruction_hook(this, m_PC);
+
+ m_opcode.d = M_RDOP(m_PC);
+ m_PC++;
+ m_tms32025_dec_cycles += (1*CLK);
+
+ do {
+ if (m_opcode.b.h == 0xCE)
+ { /* Do all 0xCExx Opcodes */
+ if (m_init_load_addr) {
+ m_tms32025_dec_cycles += (1*CLK);
+ }
+ else {
+ m_tms32025_dec_cycles += (1*CLK);
+ }
+ (this->*s_opcode_CE_subset[m_opcode.b.l].function)();
+ }
+ else
+ { /* Do all other opcodes */
+ if (m_init_load_addr) {
+ m_tms32025_dec_cycles += (1*CLK);
+ }
+ else {
+ m_tms32025_dec_cycles += (1*CLK);
+ }
+ (this->*s_opcode_main[m_opcode.b.h].function)();
+ }
+ m_init_load_addr = 0;
+ m_RPTC-- ;
+ } while ((INT8)(m_RPTC) != -1);
+ m_RPTC = 0;
+ m_PFC = m_PC;
+ m_init_load_addr = 1;
+ }
+
+ process_timer(m_tms32025_dec_cycles);
+
+ /**** If device is put into idle mode, exit and wait for an interrupt */
+ while (m_idle && m_icount > 0)
+ process_timer(m_icount);
+
+
+ /**** If hold pin is active, exit if accessing external memory or if HM is set */
+ if (m_hold) {
+ if (m_external_mem_access || (HM)) {
+ if (m_icount > 0) {
+ m_icount = 0;
+ }
+ }
+ }
+ }
+}
+
+
+
+/****************************************************************************
+ * Set IRQ line state
+ ****************************************************************************/
+void tms32025_device::execute_set_input(int irqline, int state)
+{
+ if ( irqline == TMS32025_FSX ) {
+ if (state != CLEAR_LINE && m_waiting_for_serial_frame)
+ {
+ m_waiting_for_serial_frame = 0;
+ m_IFR = 0x20;
+ }
+ }
+ else
+ {
+ /* Pending IRQs cannot be cleared */
+ if (state != CLEAR_LINE)
+ {
+ m_IFR |= (1 << irqline);
+ }
+ }
+}
+
+
+/****************************************************************************
+ * Opcode fetcher
+ ****************************************************************************/
+bool tms32025_device::memory_readop(offs_t offset, int size, UINT64 &value)
+{
+ void *ptr;
+
+ /* skip if not custom */
+ if (!m_pgmmap[offset >> 8])
+ return 0;
+
+ ptr = &((UINT8 *)&m_pgmmap[offset >> 8])[offset & 0xff];
+ switch (size)
+ {
+ case 1: value = *((UINT8 *) ptr);
+ case 2: value = *((UINT16 *) ptr);
+ case 4: value = *((UINT32 *) ptr);
+ case 8: value = *((UINT64 *) ptr);
+ }
+ return 1;
+}
+
+
+/****************************************************************************
+ * Memory reader
+ ****************************************************************************/
+bool tms32025_device::memory_read(address_spacenum spacenum, offs_t offset, int size, UINT64 &value)
+{
+ void *ptr = NULL;
+ UINT64 temp = 0;
+
+ switch (spacenum)
+ {
+ case AS_PROGRAM:
+ ptr = m_pgmmap[offset >> 8];
+ if (!ptr)
+ return 0;
+ break;
+
+ case AS_DATA:
+ ptr = m_datamap[offset >> 8];
+ if (!ptr)
+ return 0;
+ break;
+
+ default:
+ case AS_IO:
+ return 0;
+ }
+
+ switch (size)
+ {
+ case 1:
+ value = ((UINT8 *)ptr)[BYTE_XOR_BE(offset & 0xff)];
+ break;
+ case 2:
+ value = ((UINT16 *)ptr)[(offset & 0xff) / 2];
+ break;
+ case 4:
+ memory_read(spacenum, offset + 0, 2, temp);
+ value = temp << 16;
+ memory_read(spacenum, offset + 2, 2, temp);
+ value |= temp & 0xffff;
+ break;
+ case 8:
+ memory_read(spacenum, offset + 0, 4, temp);
+ value = temp << 32;
+ memory_read(spacenum, offset + 4, 4, temp);
+ value |= temp & 0xffffffff;
+ break;
+ }
+ return 1;
+}
+
+
+/****************************************************************************
+ * Memory writer
+ ****************************************************************************/
+bool tms32025_device::memory_write(address_spacenum spacenum, offs_t offset, int size, UINT64 value)
+{
+ void *ptr = NULL;
+
+ switch (spacenum)
+ {
+ case AS_PROGRAM:
+ ptr = m_pgmmap[offset >> 8];
+ if (!ptr)
+ return 0;
+ break;
+
+ case AS_DATA:
+ ptr = m_datamap[offset >> 8];
+ if (!ptr)
+ return 0;
+ break;
+
+ default:
+ case AS_IO:
+ return 0;
+ }
+
+ switch (size)
+ {
+ case 1:
+ ((UINT8 *)ptr)[BYTE_XOR_BE(offset & 0xff)] = value;
+ break;
+ case 2:
+ ((UINT16 *)ptr)[(offset & 0xff) / 2] = value;
+ break;
+ case 4:
+ memory_write(spacenum, offset + 0, 2, value >> 16);
+ memory_write(spacenum, offset + 2, 2, value);
+ break;
+ case 8:
+ memory_write(spacenum, offset + 0, 4, value >> 32);
+ memory_write(spacenum, offset + 4, 4, value);
+ break;
+ }
+
+ return 1;
+}