summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/cpu/tms32025/tms32025.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/cpu/tms32025/tms32025.c')
-rw-r--r--src/emu/cpu/tms32025/tms32025.c2477
1 files changed, 2477 insertions, 0 deletions
diff --git a/src/emu/cpu/tms32025/tms32025.c b/src/emu/cpu/tms32025/tms32025.c
new file mode 100644
index 00000000000..a4935a38c8d
--- /dev/null
+++ b/src/emu/cpu/tms32025/tms32025.c
@@ -0,0 +1,2477 @@
+ /**************************************************************************\
+ * Texas Instruments TMS320x25 DSP Emulator *
+ * *
+ * Copyright (C) 2001-2002+ 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 mulit-cycle instruction cycle counts
+ # Add support to set ROM & RAM as Internal/External in order to correctly
+ compute cycle timings
+ # Possibly add internal memory into here (instead of having it in the driver)
+ # 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 "tms32025.h"
+#include "debugger.h"
+
+
+#define CLK 4 /* 1 cycle equals 4 clock ticks */ /* PE/DI */
+
+
+#ifndef INLINE
+#define INLINE static inline
+#endif
+
+
+UINT16 *tms32025_pgmmap[0x200];
+UINT16 *tms32025_datamap[0x200];
+
+#define SET_PC(x) do { R.PC = (x); change_pc(R.PC<<1); } while (0)
+
+INLINE UINT16 M_RDROM(offs_t addr)
+{
+ UINT16 *ram;
+ addr &= 0xffff;
+ ram = tms32025_pgmmap[addr >> 7];
+ if (ram) return ram[addr & 0x7f];
+ return program_read_word_16be(addr << 1);
+}
+
+INLINE void M_WRTROM(offs_t addr, UINT16 data)
+{
+ UINT16 *ram;
+ addr &= 0xffff;
+ ram = tms32025_pgmmap[addr >> 7];
+ if (ram) { ram[addr & 0x7f] = data; }
+ else program_write_word_16be(addr << 1, data);
+}
+
+INLINE UINT16 M_RDRAM(offs_t addr)
+{
+ UINT16 *ram;
+ addr &= 0xffff;
+ ram = tms32025_datamap[addr >> 7];
+ if (ram) return ram[addr & 0x7f];
+ return data_read_word_16be(addr << 1);
+}
+
+INLINE void M_WRTRAM(offs_t addr, UINT16 data)
+{
+ UINT16 *ram;
+ addr &= 0xffff;
+ ram = tms32025_datamap[addr >> 7];
+ if (ram) { ram[addr & 0x7f] = data; }
+ else data_write_word_16be(addr << 1, data);
+}
+
+#define P_IN(A) (io_read_word_16be((A)<<1))
+#define P_OUT(A,V) (io_write_word_16be(((A)<<1),(V)))
+#define S_IN(A) (io_read_word_16be((A)<<1))
+#define S_OUT(A,V) (io_write_word_16be(((A)<<1),(V)))
+
+#define M_RDOP(A) ((tms32025_pgmmap[(A) >> 7]) ? (tms32025_pgmmap[(A) >> 7][(A) & 0x7f]) : cpu_readop16((A)<<1))
+#define M_RDOP_ARG(A) ((tms32025_pgmmap[(A) >> 7]) ? (tms32025_pgmmap[(A) >> 7][(A) & 0x7f]) : cpu_readop16((A)<<1))
+
+
+
+typedef struct /* Page 3-6 (45) shows all registers */
+{
+ /******************** CPU Internal Registers *******************/
+ UINT16 PREVPC; /* previous program counter */
+ UINT16 PC;
+ UINT16 PFC;
+ UINT16 STR0, STR1;
+ UINT8 IFR;
+ UINT8 RPTC;
+ PAIR ACC; /* PAIR defined in os/osd_cpu.h */
+ PAIR Preg;
+ UINT16 Treg;
+ UINT16 AR[8];
+ UINT16 STACK[8];
+ PAIR ALU;
+ UINT16 *intRAM;
+ UINT8 timerover;
+
+ /********************** Status data ****************************/
+ PAIR opcode;
+ int idle;
+ int hold;
+ int external_mem_access; /** required for hold mode. Implement it ! */
+ int init_load_addr; /* 0=No, 1=Yes, 2=Once for repeat mode */
+ int tms32025_irq_cycles;
+ int tms32025_dec_cycles;
+ int (*irq_callback)(int irqline);
+ UINT16 *datamap_save[16];
+ UINT16 *pgmmap_save[12];
+} tms32025_Regs;
+
+static tms32025_Regs R;
+static PAIR oldacc;
+static UINT32 memaccess;
+static int tms32025_icount;
+typedef void (*opcode_fn) (void);
+
+
+/************************** Memory mapped registers ****************/
+#define DRR R.intRAM[0]
+#define DXR R.intRAM[1]
+#define TIM R.intRAM[2]
+#define PRD R.intRAM[3]
+#define IMR R.intRAM[4]
+#define GREG R.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 ( R.STR0 & OV_FLAG) /* OV (Overflow flag) */
+#define OVM ( R.STR0 & OVM_FLAG) /* OVM (Overflow Mode bit) 1 indicates an overflow */
+#define INTM ( R.STR0 & INTM_FLAG) /* INTM (Interrupt enable flag) 0 enables maskable interrupts */
+#define ARP ((R.STR0 & ARP_REG) >> 13) /* ARP (Auxiliary Register Pointer) */
+#define DP ((R.STR0 & DP_REG) << 7) /* DP (Data memory Pointer bit) */
+#define ARB ( R.STR1 & ARB_REG) /* ARB (Backup Auxiliary Register pointer) */
+#define CNF0 ( R.STR1 & CNF0_REG) /* CNF0 (Onchip Ram Config register) */
+#define TC ( R.STR1 & TC_FLAG) /* TC (Test Control Flag) */
+#define SXM ( R.STR1 & SXM_FLAG) /* SXM (Sign Extension Mode) */
+#define CARRY ( R.STR1 & C_FLAG) /* C (Carry Flag for accumulator) */
+#define HM ( R.STR1 & HM_FLAG) /* HM (Processor Hold Mode) */
+#define FSM ( R.STR1 & FSM_FLAG) /* FSM (Frame Synchronization Mode - for serial port) */
+#define XF ( R.STR1 & FSM_FLAG) /* XF (XF output pin status) */
+#define FO ( R.STR1 & FO_FLAG) /* FO (Serial port Format In/Out mode) */
+#define TXM ( R.STR1 & TXM_FLAG) /* TXM (Transmit Mode - for serial port) */
+#define PM ( R.STR1 & PM_REG) /* PM (P register shift Mode. See SHIFT_Preg_TO_ALU below )*/
+
+#define DMA (DP | (R.opcode.b.l & 0x7f)) /* address used in direct memory access operations */
+#define DMApg0 (R.opcode.b.l & 0x7f) /* address used in direct memory access operations for sst instruction */
+#define IND R.AR[ARP] /* address used in indirect memory access operations */
+
+INLINE void CLR0(UINT16 flag) { R.STR0 &= ~flag; R.STR0 |= 0x0400; }
+INLINE void SET0(UINT16 flag) { R.STR0 |= flag; R.STR0 |= 0x0400; }
+INLINE void CLR1(UINT16 flag) { R.STR1 &= ~flag; R.STR1 |= 0x0180; }
+INLINE void SET1(UINT16 flag) { R.STR1 |= flag; R.STR1 |= 0x0180; }
+INLINE void MODIFY_DP (int data) { R.STR0 &= ~DP_REG; R.STR0 |= (data & DP_REG); R.STR0 |= 0x0400; }
+INLINE void MODIFY_PM (int data) { R.STR1 &= ~PM_REG; R.STR1 |= (data & PM_REG); R.STR1 |= 0x0180; }
+INLINE void MODIFY_ARP(int data) { R.STR1 &= ~ARB_REG; R.STR1 |= (R.STR0 & ARP_REG); R.STR1 |= 0x0180; \
+ R.STR0 &= ~ARP_REG; R.STR0 |= ((data << 13) & ARP_REG); R.STR0 |= 0x0400; }
+INLINE void MODIFY_ARB(int data) { R.STR1 &= ~ARB_REG; R.STR1 |= ((data << 13) & ARB_REG); R.STR1 |= 0x0180; }
+
+static int mHackIgnoreARP; /* special handling for lst, lst1 instructions */
+
+static UINT16 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;
+}
+
+INLINE void MODIFY_AR_ARP(void)
+{ /* modify address register referenced by ARP */
+ switch (R.opcode.b.l & 0x70) /* Cases ordered by predicted useage */
+ {
+ case 0x00: /* 000 nop */
+ break;
+
+ case 0x10: /* 001 *- */
+ R.AR[ARP] -- ;
+ break;
+
+ case 0x20: /* 010 *+ */
+ R.AR[ARP] ++ ;
+ break;
+
+ case 0x30: /* 011 reserved */
+ break;
+
+ case 0x40: /* 100 *BR0- */
+ R.AR[ARP] = reverse_carry_add(R.AR[ARP],-R.AR[0]);
+ break;
+
+ case 0x50: /* 101 *0- */
+ R.AR[ARP] -= R.AR[0];
+ break;
+
+ case 0x60: /* 110 *0+ */
+ R.AR[ARP] += R.AR[0];
+ break;
+
+ case 0x70: /* 111 *BR0+ */
+ R.AR[ARP] += reverse_carry_add(R.AR[ARP],R.AR[0]);
+ break;
+
+ default:
+ break;
+ }
+
+ if( !mHackIgnoreARP )
+ {
+ if (R.opcode.b.l & 8)
+ { /* bit 3 determines if new value is loaded into ARP */
+ MODIFY_ARP(R.opcode.b.l & 7);
+ }
+ }
+}
+
+INLINE void CALCULATE_ADD_CARRY(void)
+{
+ if ( (UINT32)(oldacc.d) > (UINT32)(R.ACC.d) ) {
+ SET1(C_FLAG);
+ }
+ else {
+ CLR1(C_FLAG);
+ }
+}
+
+INLINE void CALCULATE_SUB_CARRY(void)
+{
+ if ( (UINT32)(oldacc.d) < (UINT32)(R.ACC.d) ) {
+ CLR1(C_FLAG);
+ }
+ else {
+ SET1(C_FLAG);
+ }
+}
+
+INLINE void CALCULATE_ADD_OVERFLOW(INT32 addval)
+{
+ if ((INT32)(~(oldacc.d ^ addval) & (oldacc.d ^ R.ACC.d)) < 0)
+ {
+ SET0(OV_FLAG);
+ if (OVM)
+ {
+ // Stroff:HACK! support for overflow capping as implemented results in bad DSP floating point math in many
+ // System22 games - for example, the score display in Prop Cycle.
+ // R.ACC.d = ((INT32)oldacc.d < 0) ? 0x80000000 : 0x7fffffff;
+ }
+ }
+}
+INLINE void CALCULATE_SUB_OVERFLOW(INT32 subval)
+{
+ if ((INT32)((oldacc.d ^ subval) & (oldacc.d ^ R.ACC.d)) < 0)
+ {
+ SET0(OV_FLAG);
+ if (OVM)
+ {
+ R.ACC.d = ((INT32)oldacc.d < 0) ? 0x80000000 : 0x7fffffff;
+ }
+ }
+}
+
+INLINE UINT16 POP_STACK(void)
+{
+ UINT16 data = R.STACK[7];
+ R.STACK[7] = R.STACK[6];
+ R.STACK[6] = R.STACK[5];
+ R.STACK[5] = R.STACK[4];
+ R.STACK[4] = R.STACK[3];
+ R.STACK[3] = R.STACK[2];
+ R.STACK[2] = R.STACK[1];
+ R.STACK[1] = R.STACK[0];
+ return data;
+}
+INLINE void PUSH_STACK(UINT16 data)
+{
+ R.STACK[0] = R.STACK[1];
+ R.STACK[1] = R.STACK[2];
+ R.STACK[2] = R.STACK[3];
+ R.STACK[3] = R.STACK[4];
+ R.STACK[4] = R.STACK[5];
+ R.STACK[5] = R.STACK[6];
+ R.STACK[6] = R.STACK[7];
+ R.STACK[7] = data;
+}
+
+INLINE void SHIFT_Preg_TO_ALU(void)
+{
+ switch(PM) /* PM (in STR1) is the shift mode for Preg */
+ {
+ case 0: R.ALU.d = R.Preg.d; break;
+ case 1: R.ALU.d = (R.Preg.d << 1); break;
+ case 2: R.ALU.d = (R.Preg.d << 4); break;
+ case 3: R.ALU.d = (R.Preg.d >> 6); if (R.Preg.d & 0x80000000) R.ALU.d |= 0xfc000000; break;
+ default: break;
+ }
+}
+
+INLINE void GETDATA(int shift,int signext)
+{
+ if (R.opcode.b.l & 0x80)
+ { /* indirect memory access */
+ memaccess = IND;
+ }
+ else
+ { /* direct memory address */
+ memaccess = DMA;
+ }
+
+ if (memaccess >= 0x800)
+ {
+ R.external_mem_access = 1; /* Pause if hold pin is active */
+ }
+ else
+ {
+ R.external_mem_access = 0;
+ }
+
+ R.ALU.d = (UINT16)M_RDRAM(memaccess);
+ if (signext) R.ALU.d = (INT16)R.ALU.d;
+ R.ALU.d <<= shift;
+
+ /* next ARP */
+ if (R.opcode.b.l & 0x80) MODIFY_AR_ARP();
+}
+
+INLINE void PUTDATA(UINT16 data)
+{
+ if (R.opcode.b.l & 0x80) {
+ if (memaccess >= 0x800) R.external_mem_access = 1; /* Pause if hold pin is active */
+ else R.external_mem_access = 0;
+
+ M_WRTRAM(IND,data);
+ MODIFY_AR_ARP();
+ }
+ else {
+ if (memaccess >= 0x800) R.external_mem_access = 1; /* Pause if hold pin is active */
+ else R.external_mem_access = 0;
+
+ M_WRTRAM(DMA,data);
+ }
+}
+INLINE void PUTDATA_SST(UINT16 data)
+{
+ if (R.opcode.b.l & 0x80) memaccess = IND;
+ else memaccess = DMApg0;
+
+ if (memaccess >= 0x800) R.external_mem_access = 1; /* Pause if hold pin is active */
+ else R.external_mem_access = 0;
+
+ if (R.opcode.b.l & 0x80) {
+ R.opcode.b.l &= 0xf7; /* Stop ARP changes */
+ MODIFY_AR_ARP();
+ }
+ M_WRTRAM(memaccess,data);
+}
+
+
+/* The following functions are here to fill the void for the */
+/* opcode call functions. These functions are never actually called. */
+static void opcodes_CE(void) { }
+static void opcodes_DX(void) { }
+
+static void illegal(void)
+{
+ logerror("TMS32025: PC = %04x, Illegal opcode = %04x\n", (R.PC-1), R.opcode.w.l);
+}
+
+static void abst(void)
+{
+ if ( (INT32)(R.ACC.d) < 0 ) {
+ R.ACC.d = -R.ACC.d;
+ if (R.ACC.d == 0x80000000)
+ {
+ SET0(OV_FLAG);
+ if (OVM) R.ACC.d-- ;
+ }
+ }
+ CLR1(C_FLAG);
+}
+static void add(void) /* #### add carry support - see page 3-31 (70) #### */
+{ /* page 10-13 (348) spru031d */
+ oldacc.d = R.ACC.d;
+ GETDATA((R.opcode.b.h & 0xf),SXM);
+ R.ACC.d += R.ALU.d;
+
+ CALCULATE_ADD_OVERFLOW(R.ALU.d);
+ CALCULATE_ADD_CARRY();
+}
+static void addc(void)
+{
+ oldacc.d = R.ACC.d;
+ GETDATA(0,0);
+ if (CARRY) R.ALU.d++;
+ R.ACC.d += R.ALU.d;
+ CALCULATE_ADD_OVERFLOW(R.ALU.d);
+ CALCULATE_ADD_CARRY();
+}
+static void addh(void)
+{
+ oldacc.d = R.ACC.d;
+ GETDATA(0,0);
+ R.ACC.w.h += R.ALU.w.l;
+ if ((INT16)(~(oldacc.w.h ^ R.ALU.w.l) & (oldacc.w.h ^ R.ACC.w.h)) < 0) {
+ SET0(OV_FLAG);
+ if (OVM)
+ R.ACC.w.h = ((INT16)oldacc.w.h < 0) ? 0x8000 : 0x7fff;
+ }
+ if ( ((INT16)(oldacc.w.h) < 0) && ((INT16)(R.ACC.w.h) >= 0) ) {
+ SET1(C_FLAG);
+ }
+ /* Carry flag is not cleared, if no carry occured */
+}
+static void addk(void)
+{
+ oldacc.d = R.ACC.d;
+ R.ALU.d = (UINT8)R.opcode.b.l;
+ R.ACC.d += R.ALU.d;
+ CALCULATE_ADD_OVERFLOW(R.ALU.d);
+ CALCULATE_ADD_CARRY();
+}
+static void adds(void)
+{
+ oldacc.d = R.ACC.d;
+ GETDATA(0,0);
+ R.ACC.d += R.ALU.d;
+ CALCULATE_ADD_OVERFLOW(R.ALU.d);
+ CALCULATE_ADD_CARRY();
+}
+static void addt(void)
+{
+ oldacc.d = R.ACC.d;
+ GETDATA((R.Treg & 0xf),SXM);
+ R.ACC.d += R.ALU.d;
+ CALCULATE_ADD_OVERFLOW(R.ALU.d);
+ CALCULATE_ADD_CARRY();
+}
+static void adlk(void)
+{
+ oldacc.d = R.ACC.d;
+ if (SXM) R.ALU.d = (INT16)M_RDOP_ARG(R.PC);
+ else R.ALU.d = (UINT16)M_RDOP_ARG(R.PC);
+ R.PC++;
+ R.ALU.d <<= (R.opcode.b.h & 0xf);
+ R.ACC.d += R.ALU.d;
+ CALCULATE_ADD_OVERFLOW(R.ALU.d);
+ CALCULATE_ADD_CARRY();
+}
+static void adrk(void)
+{
+ R.AR[ARP] += R.opcode.b.l;
+}
+static void and(void)
+{
+ GETDATA(0,0);
+ R.ACC.d &= R.ALU.d;
+}
+static void andk(void)
+{
+ oldacc.d = R.ACC.d;
+ R.ALU.d = (UINT16)M_RDOP_ARG(R.PC);
+ R.PC++;
+ R.ALU.d <<= (R.opcode.b.h & 0xf);
+ R.ACC.d &= R.ALU.d;
+ R.ACC.d &= 0x7fffffff;
+}
+static void apac(void)
+{
+ oldacc.d = R.ACC.d;
+ SHIFT_Preg_TO_ALU();
+ R.ACC.d += R.ALU.d;
+ CALCULATE_ADD_OVERFLOW(R.ALU.d);
+ CALCULATE_ADD_CARRY();
+}
+static void br(void)
+{
+ SET_PC(M_RDOP_ARG(R.PC));
+ MODIFY_AR_ARP();
+}
+static void bacc(void)
+{
+ SET_PC(R.ACC.w.l);
+}
+static void banz(void)
+{
+ if (R.AR[ARP]) SET_PC(M_RDOP_ARG(R.PC));
+ else R.PC++ ;
+ MODIFY_AR_ARP();
+}
+static void bbnz(void)
+{
+ if (TC) SET_PC(M_RDOP_ARG(R.PC));
+ else R.PC++ ;
+ MODIFY_AR_ARP();
+}
+static void bbz(void)
+{
+ if (TC == 0) SET_PC(M_RDOP_ARG(R.PC));
+ else R.PC++ ;
+ MODIFY_AR_ARP();
+}
+static void bc(void)
+{
+ if (CARRY) SET_PC(M_RDOP_ARG(R.PC));
+ else R.PC++ ;
+ MODIFY_AR_ARP();
+}
+static void bgez(void)
+{
+ if ( (INT32)(R.ACC.d) >= 0 ) SET_PC(M_RDOP_ARG(R.PC));
+ else R.PC++ ;
+ MODIFY_AR_ARP();
+}
+static void bgz(void)
+{
+ if ( (INT32)(R.ACC.d) > 0 ) SET_PC(M_RDOP_ARG(R.PC));
+ else R.PC++ ;
+ MODIFY_AR_ARP();
+}
+static void bioz(void)
+{
+ if (S_IN(TMS32025_BIO) != CLEAR_LINE) SET_PC(M_RDOP_ARG(R.PC));
+ else R.PC++ ;
+ MODIFY_AR_ARP();
+}
+static void bit(void)
+{
+ GETDATA(0,0);
+ if (R.ALU.d & (0x8000 >> (R.opcode.b.h & 0xf))) SET1(TC_FLAG);
+ else CLR1(TC_FLAG);
+}
+static void bitt(void)
+{
+ GETDATA(0,0);
+ if (R.ALU.d & (0x8000 >> (R.Treg & 0xf))) SET1(TC_FLAG);
+ else CLR1(TC_FLAG);
+}
+static void blez(void)
+{
+ if ( (INT32)(R.ACC.d) <= 0 ) SET_PC(M_RDOP_ARG(R.PC));
+ else R.PC++ ;
+ MODIFY_AR_ARP();
+}
+static void blkd(void)
+{ /** Fix cycle timing **/
+ if (R.init_load_addr) {
+ R.PFC = M_RDOP_ARG(R.PC);
+ R.PC++;
+ }
+ R.ALU.d = M_RDRAM(R.PFC);
+ PUTDATA(R.ALU.d);
+ R.PFC++;
+ R.tms32025_dec_cycles += (1*CLK);
+}
+static void blkp(void)
+{ /** Fix cycle timing **/
+ if (R.init_load_addr) {
+ R.PFC = M_RDOP_ARG(R.PC);
+ R.PC++;
+ }
+ R.ALU.d = M_RDROM(R.PFC);
+ PUTDATA(R.ALU.d);
+ R.PFC++;
+ R.tms32025_dec_cycles += (2*CLK);
+}
+static void blz(void)
+{
+ if ( (INT32)(R.ACC.d) < 0 ) SET_PC(M_RDOP_ARG(R.PC));
+ else R.PC++ ;
+ MODIFY_AR_ARP();
+}
+static void bnc(void)
+{
+ if (CARRY == 0) SET_PC(M_RDOP_ARG(R.PC));
+ else R.PC++ ;
+ MODIFY_AR_ARP();
+}
+static void bnv(void)
+{
+ if (OV == 0) SET_PC(M_RDOP_ARG(R.PC));
+ else {
+ R.PC++ ;
+ CLR0(OV_FLAG);
+ }
+ MODIFY_AR_ARP();
+}
+static void bnz(void)
+{
+ if (R.ACC.d != 0) SET_PC(M_RDOP_ARG(R.PC));
+ else R.PC++ ;
+ MODIFY_AR_ARP();
+}
+static void bv(void)
+{
+ if (OV) {
+ SET_PC(M_RDOP_ARG(R.PC));
+ CLR0(OV_FLAG);
+ }
+ else R.PC++ ;
+ MODIFY_AR_ARP();
+}
+static void bz(void)
+{
+ if (R.ACC.d == 0) SET_PC(M_RDOP_ARG(R.PC));
+ else R.PC++ ;
+ MODIFY_AR_ARP();
+}
+static void cala(void)
+{
+ PUSH_STACK(R.PC);
+ SET_PC(R.ACC.w.l);
+}
+static void call(void)
+{
+ R.PC++ ;
+ PUSH_STACK(R.PC);
+ SET_PC(M_RDOP_ARG((R.PC - 1)));
+ MODIFY_AR_ARP();
+}
+static void cmpl(void)
+{
+ R.ACC.d = (~R.ACC.d);
+}
+static void cmpr(void)
+{
+ switch (R.opcode.b.l & 3)
+ {
+ case 00: if ( (UINT16)(R.AR[ARP]) == (UINT16)(R.AR[0]) ) SET1(TC_FLAG); else CLR1(TC_FLAG); break;
+ case 01: if ( (UINT16)(R.AR[ARP]) < (UINT16)(R.AR[0]) ) SET1(TC_FLAG); else CLR1(TC_FLAG); break;
+ case 02: if ( (UINT16)(R.AR[ARP]) > (UINT16)(R.AR[0]) ) SET1(TC_FLAG); else CLR1(TC_FLAG); break;
+ case 03: if ( (UINT16)(R.AR[ARP]) != (UINT16)(R.AR[0]) ) SET1(TC_FLAG); else CLR1(TC_FLAG); break;
+ default: break;
+ }
+}
+static void cnfd(void) /** next two fetches need to use previous CNF value ! **/
+{
+ CLR1(CNF0_REG);
+ tms32025_datamap[4] = &R.intRAM[0x200]; /* B0 */
+ tms32025_datamap[5] = &R.intRAM[0x280]; /* B0 */
+ tms32025_pgmmap[510] = NULL;
+ tms32025_pgmmap[511] = NULL;
+}
+static void cnfp(void) /** next two fetches need to use previous CNF value ! **/
+{
+ SET1(CNF0_REG);
+ tms32025_datamap[4] = NULL; /* B0 */
+ tms32025_datamap[5] = NULL; /* B0 */
+ tms32025_pgmmap[510] = &R.intRAM[0x200];
+ tms32025_pgmmap[511] = &R.intRAM[0x280];
+}
+static void conf(void) /** Need to reconfigure the memory blocks */
+{
+ switch (R.opcode.b.l & 3)
+ {
+ case 00: CLR1(CNF1_REG); CLR1(CNF0_REG);
+ tms32025_datamap[4] = &R.intRAM[0x200]; /* B0 */
+ tms32025_datamap[5] = &R.intRAM[0x280]; /* B0 */
+ tms32025_datamap[6] = &R.intRAM[0x300]; /* B0 */
+ tms32025_datamap[7] = &R.intRAM[0x380]; /* B0 */
+ tms32025_datamap[8] = &R.intRAM[0x400]; /* B1 */
+ tms32025_datamap[9] = &R.intRAM[0x480]; /* B1 */
+ tms32025_datamap[10] = &R.intRAM[0x500]; /* B1 */
+ tms32025_datamap[11] = &R.intRAM[0x580]; /* B1 */
+ tms32025_datamap[12] = &R.intRAM[0x600]; /* B3 */
+ tms32025_datamap[13] = &R.intRAM[0x680]; /* B3 */
+ tms32025_datamap[14] = &R.intRAM[0x700]; /* B3 */
+ tms32025_datamap[15] = &R.intRAM[0x780]; /* B3 */
+ tms32025_pgmmap[500] = NULL;
+ tms32025_pgmmap[501] = NULL;
+ tms32025_pgmmap[502] = NULL;
+ tms32025_pgmmap[503] = NULL;
+ tms32025_pgmmap[504] = NULL;
+ tms32025_pgmmap[505] = NULL;
+ tms32025_pgmmap[506] = NULL;
+ tms32025_pgmmap[507] = NULL;
+ tms32025_pgmmap[508] = NULL;
+ tms32025_pgmmap[509] = NULL;
+ tms32025_pgmmap[510] = NULL;
+ tms32025_pgmmap[511] = NULL;
+ break;
+ case 01: CLR1(CNF1_REG); SET1(CNF0_REG);
+ tms32025_datamap[4] = NULL;
+ tms32025_datamap[5] = NULL;
+ tms32025_datamap[6] = NULL;
+ tms32025_datamap[7] = NULL;
+ tms32025_datamap[8] = &R.intRAM[0x400]; /* B1 */
+ tms32025_datamap[9] = &R.intRAM[0x480]; /* B1 */
+ tms32025_datamap[10] = &R.intRAM[0x500]; /* B1 */
+ tms32025_datamap[11] = &R.intRAM[0x580]; /* B1 */
+ tms32025_datamap[12] = &R.intRAM[0x600]; /* B3 */
+ tms32025_datamap[13] = &R.intRAM[0x680]; /* B3 */
+ tms32025_datamap[14] = &R.intRAM[0x700]; /* B3 */
+ tms32025_datamap[15] = &R.intRAM[0x780]; /* B3 */
+ tms32025_pgmmap[500] = &R.intRAM[0x200]; /* B0 */
+ tms32025_pgmmap[501] = &R.intRAM[0x280]; /* B0 */
+ tms32025_pgmmap[502] = &R.intRAM[0x300]; /* B0 */
+ tms32025_pgmmap[503] = &R.intRAM[0x380]; /* B0 */
+ tms32025_pgmmap[504] = NULL;
+ tms32025_pgmmap[505] = NULL;
+ tms32025_pgmmap[506] = NULL;
+ tms32025_pgmmap[507] = NULL;
+ tms32025_pgmmap[508] = NULL;
+ tms32025_pgmmap[509] = NULL;
+ tms32025_pgmmap[510] = NULL;
+ tms32025_pgmmap[511] = NULL;
+ break;
+ case 02: SET1(CNF1_REG); CLR1(CNF0_REG);
+ tms32025_datamap[4] = NULL;
+ tms32025_datamap[5] = NULL;
+ tms32025_datamap[6] = NULL;
+ tms32025_datamap[7] = NULL;
+ tms32025_datamap[8] = NULL;
+ tms32025_datamap[9] = NULL;
+ tms32025_datamap[10] = NULL;
+ tms32025_datamap[11] = NULL;
+ tms32025_datamap[12] = &R.intRAM[0x600]; /* B3 */
+ tms32025_datamap[13] = &R.intRAM[0x680]; /* B3 */
+ tms32025_datamap[14] = &R.intRAM[0x700]; /* B3 */
+ tms32025_datamap[15] = &R.intRAM[0x780]; /* B3 */
+ tms32025_pgmmap[500] = &R.intRAM[0x200]; /* B0 */
+ tms32025_pgmmap[501] = &R.intRAM[0x280]; /* B0 */
+ tms32025_pgmmap[502] = &R.intRAM[0x300]; /* B0 */
+ tms32025_pgmmap[503] = &R.intRAM[0x380]; /* B0 */
+ tms32025_pgmmap[504] = &R.intRAM[0x400]; /* B1 */
+ tms32025_pgmmap[505] = &R.intRAM[0x480]; /* B1 */
+ tms32025_pgmmap[506] = &R.intRAM[0x500]; /* B1 */
+ tms32025_pgmmap[507] = &R.intRAM[0x580]; /* B1 */
+ tms32025_pgmmap[508] = NULL;
+ tms32025_pgmmap[509] = NULL;
+ tms32025_pgmmap[510] = NULL;
+ tms32025_pgmmap[511] = NULL;
+ break;
+ case 03: SET1(CNF1_REG); SET1(CNF0_REG);
+ tms32025_datamap[4] = NULL;
+ tms32025_datamap[5] = NULL;
+ tms32025_datamap[6] = NULL;
+ tms32025_datamap[7] = NULL;
+ tms32025_datamap[8] = NULL;
+ tms32025_datamap[9] = NULL;
+ tms32025_datamap[10] = NULL;
+ tms32025_datamap[11] = NULL;
+ tms32025_datamap[12] = NULL;
+ tms32025_datamap[13] = NULL;
+ tms32025_datamap[14] = NULL;
+ tms32025_datamap[15] = NULL;
+ tms32025_pgmmap[500] = &R.intRAM[0x200]; /* B0 */
+ tms32025_pgmmap[501] = &R.intRAM[0x280]; /* B0 */
+ tms32025_pgmmap[502] = &R.intRAM[0x300]; /* B0 */
+ tms32025_pgmmap[503] = &R.intRAM[0x380]; /* B0 */
+ tms32025_pgmmap[504] = &R.intRAM[0x400]; /* B1 */
+ tms32025_pgmmap[505] = &R.intRAM[0x480]; /* B1 */
+ tms32025_pgmmap[506] = &R.intRAM[0x500]; /* B1 */
+ tms32025_pgmmap[507] = &R.intRAM[0x580]; /* B1 */
+ tms32025_pgmmap[508] = &R.intRAM[0x600]; /* B3 */
+ tms32025_pgmmap[509] = &R.intRAM[0x680]; /* B3 */
+ tms32025_pgmmap[510] = &R.intRAM[0x700]; /* B3 */
+ tms32025_pgmmap[511] = &R.intRAM[0x780]; /* B3 */
+ break;
+ default: break;
+ }
+}
+static void dint(void)
+{
+ SET0(INTM_FLAG);
+}
+static void dmov(void) /** Careful with how memory is configured !! */
+{
+ GETDATA(0,0);
+ M_WRTRAM((memaccess + 1),R.ALU.w.l);
+}
+static void eint(void)
+{
+ CLR0(INTM_FLAG);
+}
+static void fort(void)
+{
+ if (R.opcode.b.l & 1) SET1(FO_FLAG);
+ else CLR1(FO_FLAG);
+}
+static void idle(void)
+{
+ CLR0(INTM_FLAG);
+ R.idle = 1;
+}
+static void in(void)
+{
+ R.ALU.w.l = P_IN( (R.opcode.b.h & 0xf) );
+ PUTDATA(R.ALU.w.l);
+}
+static void lac(void)
+{
+ GETDATA( (R.opcode.b.h & 0xf),SXM );
+ R.ACC.d = R.ALU.d;
+}
+static void lack(void) /* ZAC is a subset of this instruction */
+{
+ R.ACC.d = (UINT8)R.opcode.b.l;
+}
+static void lact(void)
+{
+ GETDATA( (R.Treg & 0xf),SXM );
+ R.ACC.d = R.ALU.d;
+}
+static void lalk(void)
+{
+ if (SXM) {
+ R.ALU.d = (INT16)M_RDOP_ARG(R.PC);
+ R.ACC.d = R.ALU.d << (R.opcode.b.h & 0xf);
+ }
+ else {
+ R.ALU.d = (UINT16)M_RDOP_ARG(R.PC);
+ R.ACC.d = R.ALU.d << (R.opcode.b.h & 0xf);
+ R.ACC.d &= 0x7fffffff;
+ }
+ R.PC++;
+}
+static void lar_ar0(void) { GETDATA(0,0); R.AR[0] = R.ALU.w.l; }
+static void lar_ar1(void) { GETDATA(0,0); R.AR[1] = R.ALU.w.l; }
+static void lar_ar2(void) { GETDATA(0,0); R.AR[2] = R.ALU.w.l; }
+static void lar_ar3(void) { GETDATA(0,0); R.AR[3] = R.ALU.w.l; }
+static void lar_ar4(void) { GETDATA(0,0); R.AR[4] = R.ALU.w.l; }
+static void lar_ar5(void) { GETDATA(0,0); R.AR[5] = R.ALU.w.l; }
+static void lar_ar6(void) { GETDATA(0,0); R.AR[6] = R.ALU.w.l; }
+static void lar_ar7(void) { GETDATA(0,0); R.AR[7] = R.ALU.w.l; }
+static void lark_ar0(void) { R.AR[0] = R.opcode.b.l; }
+static void lark_ar1(void) { R.AR[1] = R.opcode.b.l; }
+static void lark_ar2(void) { R.AR[2] = R.opcode.b.l; }
+static void lark_ar3(void) { R.AR[3] = R.opcode.b.l; }
+static void lark_ar4(void) { R.AR[4] = R.opcode.b.l; }
+static void lark_ar5(void) { R.AR[5] = R.opcode.b.l; }
+static void lark_ar6(void) { R.AR[6] = R.opcode.b.l; }
+static void lark_ar7(void) { R.AR[7] = R.opcode.b.l; }
+static void ldp(void)
+{
+ GETDATA(0,0);
+ MODIFY_DP(R.ALU.d & 0x1ff);
+}
+static void ldpk(void)
+{
+ MODIFY_DP(R.opcode.w.l & 0x1ff);
+}
+static void lph(void)
+{
+ GETDATA(0,0);
+ R.Preg.w.h = R.ALU.w.l;
+}
+static void lrlk(void)
+{
+ R.ALU.d = (UINT16)M_RDOP_ARG(R.PC);
+ R.PC++;
+ R.AR[R.opcode.b.h & 7] = R.ALU.w.l;
+}
+static void lst(void)
+{
+ mHackIgnoreARP = 1;
+ GETDATA(0,0);
+ mHackIgnoreARP = 0;
+
+ R.ALU.w.l &= (~INTM_FLAG);
+ R.STR0 &= INTM_FLAG;
+ R.STR0 |= R.ALU.w.l; /* Must not affect INTM */
+ R.STR0 |= 0x0400;
+}
+static void lst1(void)
+{
+ mHackIgnoreARP = 1;
+ GETDATA(0,0);
+ mHackIgnoreARP = 0;
+
+ R.STR1 = R.ALU.w.l;
+ R.STR1 |= 0x0180;
+ R.STR0 &= (~ARP_REG); /* ARB also gets copied to ARP */
+ R.STR0 |= (R.STR1 & ARB_REG);
+}
+static void lt(void)
+{
+ GETDATA(0,0);
+ R.Treg = R.ALU.w.l;
+}
+static void lta(void)
+{
+ oldacc.d = R.ACC.d;
+ GETDATA(0,0);
+ R.Treg = R.ALU.w.l;
+ SHIFT_Preg_TO_ALU();
+ R.ACC.d += R.ALU.d;
+ CALCULATE_ADD_OVERFLOW(R.ALU.d);
+ CALCULATE_ADD_CARRY();
+}
+static void ltd(void) /** Careful with how memory is configured !! */
+{
+ oldacc.d = R.ACC.d;
+ GETDATA(0,0);
+ R.Treg = R.ALU.w.l;
+ M_WRTRAM((memaccess+1),R.ALU.w.l);
+ SHIFT_Preg_TO_ALU();
+ R.ACC.d += R.ALU.d;
+ CALCULATE_ADD_OVERFLOW(R.ALU.d);
+ CALCULATE_ADD_CARRY();
+}
+static void ltp(void)
+{
+ oldacc.d = R.ACC.d;
+ GETDATA(0,0);
+ R.Treg = R.ALU.w.l;
+ SHIFT_Preg_TO_ALU();
+ R.ACC.d = R.ALU.d;
+}
+static void lts(void)
+{
+ oldacc.d = R.ACC.d;
+ GETDATA(0,0);
+ R.Treg = R.ALU.w.l;
+ SHIFT_Preg_TO_ALU();
+ R.ACC.d -= R.ALU.d;
+ CALCULATE_SUB_OVERFLOW(R.ALU.d);
+ CALCULATE_SUB_CARRY();
+}
+static void mac(void) /** RAM blocks B0,B1,B2 may be important ! */
+{ /** Fix cycle timing **/
+ oldacc.d = R.ACC.d;
+ if (R.init_load_addr) {
+ R.PFC = M_RDOP_ARG(R.PC);
+ R.PC++;
+ }
+ SHIFT_Preg_TO_ALU();
+ R.ACC.d += R.ALU.d;
+ CALCULATE_ADD_OVERFLOW(R.ALU.d);
+ CALCULATE_ADD_CARRY();
+ GETDATA(0,0);
+ R.Treg = R.ALU.w.l;
+ R.Preg.d = ( (INT16)R.ALU.w.l * (INT16)M_RDROM(R.PFC) );
+ R.PFC++;
+ R.tms32025_dec_cycles += (2*CLK);
+}
+static void macd(void) /** RAM blocks B0,B1,B2 may be important ! */
+{ /** Fix cycle timing **/
+ oldacc.d = R.ACC.d;
+ if (R.init_load_addr) {
+ R.PFC = M_RDOP_ARG(R.PC);
+ R.PC++;
+ }
+ SHIFT_Preg_TO_ALU();
+ R.ACC.d += R.ALU.d;
+ CALCULATE_ADD_OVERFLOW(R.ALU.d);
+ CALCULATE_ADD_CARRY();
+ GETDATA(0,0);
+ if ( (R.opcode.b.l & 0x80) || R.init_load_addr ) { /* No writing during repitition, or DMA mode */
+ M_WRTRAM((memaccess+1),R.ALU.w.l);
+ }
+ R.Treg = R.ALU.w.l;
+ R.Preg.d = ( (INT16)R.ALU.w.l * (INT16)M_RDROM(R.PFC) );
+ R.PFC++;
+ R.tms32025_dec_cycles += (2*CLK);
+}
+static void mar(void) /* LARP and NOP are a subset of this instruction */
+{
+ if (R.opcode.b.l & 0x80) MODIFY_AR_ARP();
+}
+static void mpy(void)
+{
+ GETDATA(0,0);
+ R.Preg.d = (INT16)(R.ALU.w.l) * (INT16)(R.Treg);
+}
+static void mpya(void)
+{
+ oldacc.d = R.ACC.d;
+ SHIFT_Preg_TO_ALU();
+ R.ACC.d += R.ALU.d;
+ CALCULATE_ADD_OVERFLOW(R.ALU.d);
+ CALCULATE_ADD_CARRY();
+ GETDATA(0,0);
+ R.Preg.d = (INT16)(R.ALU.w.l) * (INT16)(R.Treg);
+}
+static void mpyk(void)
+{
+ R.Preg.d = (INT16)R.Treg * ((INT16)(R.opcode.w.l << 3) >> 3);
+
+}
+static void mpys(void)
+{
+ oldacc.d = R.ACC.d;
+ SHIFT_Preg_TO_ALU();
+ R.ACC.d -= R.ALU.d;
+ CALCULATE_SUB_OVERFLOW(R.ALU.d);
+ CALCULATE_SUB_CARRY();
+ GETDATA(0,0);
+ R.Preg.d = (INT16)(R.ALU.w.l) * (INT16)(R.Treg);
+}
+static void mpyu(void)
+{
+ GETDATA(0,0); R.Preg.d = (UINT16)(R.ALU.w.l) * (UINT16)(R.Treg);
+}
+static void neg(void)
+{
+ if (R.ACC.d == 0x80000000) {
+ SET0(OV_FLAG);
+ if (OVM) R.ACC.d = 0x7fffffff;
+ }
+ else R.ACC.d = -R.ACC.d;
+ if (R.ACC.d) CLR0(C_FLAG);
+ else SET0(C_FLAG);
+}
+/*
+static void nop(void) { } // NOP is a subset of the MAR instruction
+*/
+static void norm(void)
+{
+ UINT32 acc = R.ACC.d;
+
+ if( acc == 0 || ((acc^(acc<<1))&(1<<31))!=0 )
+ {
+ SET1(TC_FLAG); /* 1 -> TC */
+ }
+ else
+ {
+ CLR1(TC_FLAG); /* 0 -> TC */
+ R.ACC.d <<= 1; /* (ACC)*2 -> ACC */
+ MODIFY_AR_ARP();
+ }
+}
+static void or(void)
+{
+ GETDATA(0,0);
+ R.ACC.w.l |= R.ALU.w.l;
+}
+static void ork(void)
+{
+ R.ALU.d = (UINT16)M_RDOP_ARG(R.PC);
+ R.PC++;
+ R.ALU.d <<= (R.opcode.b.h & 0xf);
+ R.ACC.d |= (R.ALU.d & 0x7fffffff);
+}
+static void out(void)
+{
+ GETDATA(0,0);
+ P_OUT( (R.opcode.b.h & 0xf), R.ALU.w.l );
+}
+static void pac(void)
+{
+ SHIFT_Preg_TO_ALU();
+ R.ACC.d = R.ALU.d;
+}
+static void pop(void)
+{
+ R.ACC.d = (UINT16)POP_STACK();
+}
+static void popd(void)
+{
+ R.ALU.d = (UINT16)POP_STACK();
+ PUTDATA(R.ALU.w.l);
+}
+static void pshd(void)
+{
+ GETDATA(0,0);
+ PUSH_STACK(R.ALU.w.l);
+}
+static void push(void)
+{
+ PUSH_STACK(R.ACC.w.l);
+}
+static void rc(void)
+{
+ CLR1(C_FLAG);
+}
+static void ret(void)
+{
+ SET_PC(POP_STACK());
+}
+static void rfsm(void) /** serial port mode */
+{
+ CLR1(FSM_FLAG);
+}
+static void rhm(void)
+{
+ CLR1(HM_FLAG);
+}
+static void rol(void)
+{
+ R.ALU.d = R.ACC.d;
+ R.ACC.d <<= 1;
+ if (CARRY) R.ACC.d |= 1;
+ if (R.ALU.d & 0x80000000) SET1(C_FLAG);
+ else CLR1(C_FLAG);
+}
+static void ror(void)
+{
+ R.ALU.d = R.ACC.d;
+ R.ACC.d >>= 1;
+ if (CARRY) R.ACC.d |= 0x80000000;
+ if (R.ALU.d & 1) SET1(C_FLAG);
+ else CLR1(C_FLAG);
+}
+static void rovm(void)
+{
+ CLR0(OVM_FLAG);
+}
+static void rpt(void)
+{
+ GETDATA(0,0);
+ R.RPTC = R.ALU.b.l;
+ R.init_load_addr = 2; /* Initiate repeat mode */
+}
+static void rptk(void)
+{
+ R.RPTC = R.opcode.b.l;
+ R.init_load_addr = 2; /* Initiate repeat mode */
+}
+static void rsxm(void)
+{
+ CLR1(SXM_FLAG);
+}
+static void rtc(void)
+{
+ CLR1(TC_FLAG);
+}
+static void rtxm(void) /** serial port stuff */
+{
+ CLR1(TXM_FLAG);
+}
+static void rxf(void)
+{
+ CLR1(XF_FLAG);
+ S_OUT(TMS32025_XF,CLEAR_LINE);
+}
+static void sach(void)
+{
+ R.ALU.d = (R.ACC.d << (R.opcode.b.h & 7));
+ PUTDATA(R.ALU.w.h);
+}
+static void sacl(void)
+{
+ R.ALU.d = (R.ACC.d << (R.opcode.b.h & 7));
+ PUTDATA(R.ALU.w.l);
+}
+static void sar_ar0(void) { PUTDATA(R.AR[0]); }
+static void sar_ar1(void) { PUTDATA(R.AR[1]); }
+static void sar_ar2(void) { PUTDATA(R.AR[2]); }
+static void sar_ar3(void) { PUTDATA(R.AR[3]); }
+static void sar_ar4(void) { PUTDATA(R.AR[4]); }
+static void sar_ar5(void) { PUTDATA(R.AR[5]); }
+static void sar_ar6(void) { PUTDATA(R.AR[6]); }
+static void sar_ar7(void) { PUTDATA(R.AR[7]); }
+
+static void sblk(void)
+{
+ oldacc.d = R.ACC.d;
+ if (SXM) R.ALU.d = (INT16)M_RDOP_ARG(R.PC);
+ else R.ALU.d = (UINT16)M_RDOP_ARG(R.PC);
+ R.PC++;
+ R.ALU.d <<= (R.opcode.b.h & 0xf);
+ R.ACC.d -= R.ALU.d;
+ CALCULATE_SUB_OVERFLOW(R.ALU.d);
+ CALCULATE_SUB_CARRY();
+}
+static void tms_sbrk(void)
+{
+ R.AR[ARP] -= R.opcode.b.l;
+}
+static void sc(void)
+{
+ SET1(C_FLAG);
+}
+static void sfl(void)
+{
+ R.ALU.d = R.ACC.d;
+ R.ACC.d <<= 1;
+ if (R.ALU.d & 0x80000000) SET1(C_FLAG);
+ else CLR1(C_FLAG);
+}
+static void sfr(void)
+{
+ R.ALU.d = R.ACC.d;
+ R.ACC.d >>= 1;
+ if (SXM) {
+ if (R.ALU.d & 0x80000000) R.ACC.d |= 0x80000000;
+ }
+ if (R.ALU.d & 1) SET1(C_FLAG);
+ else CLR1(C_FLAG);
+}
+static void sfsm(void) /** serial port mode */
+{
+ SET1(FSM_FLAG);
+}
+static void shm(void)
+{
+ SET1(HM_FLAG);
+}
+static void sovm(void)
+{
+ SET0(OVM_FLAG);
+}
+static void spac(void)
+{
+ oldacc.d = R.ACC.d;
+ SHIFT_Preg_TO_ALU();
+ R.ACC.d -= R.ALU.d;
+ CALCULATE_SUB_OVERFLOW(R.ALU.d);
+ CALCULATE_SUB_CARRY();
+}
+static void sph(void)
+{
+ SHIFT_Preg_TO_ALU();
+ PUTDATA(R.ALU.w.h);
+}
+static void spl(void)
+{
+ SHIFT_Preg_TO_ALU();
+ PUTDATA(R.ALU.w.l);
+}
+static void spm(void)
+{
+ MODIFY_PM( (R.opcode.b.l & 3) );
+}
+static void sqra(void)
+{
+ oldacc.d = R.ACC.d;
+ SHIFT_Preg_TO_ALU();
+ R.ACC.d += R.ALU.d;
+ CALCULATE_ADD_OVERFLOW(R.ALU.d);
+ CALCULATE_ADD_CARRY();
+ GETDATA(0,0);
+ R.Treg = R.ALU.w.l;
+ R.Preg.d = ((INT16)R.ALU.w.l * (INT16)R.ALU.w.l);
+}
+static void sqrs(void)
+{
+ oldacc.d = R.ACC.d;
+ SHIFT_Preg_TO_ALU();
+ R.ACC.d -= R.ALU.d;
+ CALCULATE_SUB_OVERFLOW(R.ALU.d);
+ CALCULATE_SUB_CARRY();
+ GETDATA(0,0);
+ R.Treg = R.ALU.w.l;
+ R.Preg.d = ((INT16)R.ALU.w.l * (INT16)R.ALU.w.l);
+}
+static void sst(void)
+{
+ PUTDATA_SST(R.STR0);
+}
+static void sst1(void)
+{
+ PUTDATA_SST(R.STR1);
+}
+static void ssxm(void)
+{ /** Check instruction description, and make sure right instructions use SXM */
+ SET1(SXM_FLAG);
+}
+static void stc(void)
+{
+ SET1(TC_FLAG);
+}
+static void stxm(void) /** serial port stuff */
+{
+ SET1(TXM_FLAG);
+}
+static void sub(void)
+{
+ oldacc.d = R.ACC.d;
+ GETDATA((R.opcode.b.h & 0xf),SXM);
+ R.ACC.d -= R.ALU.d;
+ CALCULATE_SUB_OVERFLOW(R.ALU.d);
+ CALCULATE_SUB_CARRY();
+}
+static void subb(void)
+{
+ oldacc.d = R.ACC.d;
+ GETDATA(0,0);
+ if (CARRY == 0) R.ALU.d--;
+ R.ACC.d -= R.ALU.d;
+ CALCULATE_SUB_OVERFLOW(R.ALU.d);
+ CALCULATE_SUB_CARRY();
+}
+
+
+static void subc(void)
+{
+ /**
+ * conditional subtraction, which may be used for division
+ * execute 16 times for 16-bit division
+ *
+ * input: 32 bit numerator in accumulator
+ * 16 bit denominator in data memory
+ *
+ * output: remainder in upper 16 bits
+ * quotient in lower 16 bits
+ */
+ GETDATA(15,SXM);
+ if( R.ACC.d >= R.ALU.d )
+ {
+ R.ACC.d = (R.ACC.d - R.ALU.d)*2+1;
+ }
+ else
+ {
+ R.ACC.d = R.ACC.d*2;
+ }
+// Stroff: HACK! support for overflow capping as implemented results in bad DSP floating point math in many
+// System22 games - for example, the score display in Prop Cycle.
+// R.ACC.d = ((INT32)oldacc.d < 0) ? 0x80000000 : 0x7fffffff;
+
+// if ((INT32)((oldacc.d ^ subval ) & (oldacc.d ^ R.ALU.d)) < 0)
+// {
+// SET0(OV_FLAG);
+// }
+// CALCULATE_SUB_CARRY();
+}
+
+static void subh(void)
+{
+ oldacc.d = R.ACC.d;
+ GETDATA(0,0);
+ R.ACC.w.h -= R.ALU.w.l;
+ if ((INT16)((oldacc.w.h ^ R.ALU.w.l) & (oldacc.w.h ^ R.ACC.w.h)) < 0) {
+ SET0(OV_FLAG);
+ if (OVM)
+ R.ACC.w.h = ((INT16)oldacc.w.h < 0) ? 0x8000 : 0x7fff;
+ }
+ if ( ((INT16)(oldacc.w.h) >= 0) && ((INT16)(R.ACC.w.h) < 0) ) {
+ CLR1(C_FLAG);
+ }
+ /* Carry flag is not affected, if no borrow occured */
+}
+static void subk(void)
+{
+ oldacc.d = R.ACC.d;
+ R.ALU.d = (UINT8)R.opcode.b.l;
+ R.ACC.d -= R.ALU.b.l;
+ CALCULATE_SUB_OVERFLOW(R.ALU.d);
+ CALCULATE_SUB_CARRY();
+}
+static void subs(void)
+{
+ oldacc.d = R.ACC.d;
+ GETDATA(0,0);
+ R.ACC.d -= R.ALU.w.l;
+ CALCULATE_SUB_OVERFLOW(R.ALU.d);
+ CALCULATE_SUB_CARRY();
+}
+static void subt(void)
+{
+ oldacc.d = R.ACC.d;
+ GETDATA((R.Treg & 0xf),SXM);
+ R.ACC.d -= R.ALU.d;
+ CALCULATE_SUB_OVERFLOW(R.ALU.d);
+ CALCULATE_SUB_CARRY();
+}
+static void sxf(void)
+{
+ SET1(XF_FLAG);
+ S_OUT(TMS32025_XF,ASSERT_LINE);
+}
+static void tblr(void)
+{
+ if (R.init_load_addr)
+ {
+ R.PFC = R.ACC.w.l;
+ }
+ R.ALU.w.l = M_RDROM(R.PFC);
+ if ( (CNF0) && ( (UINT16)(R.PFC) >= 0xff00 ) ) {} /** TMS32025 only */
+ else R.tms32025_dec_cycles += (1*CLK);
+ PUTDATA(R.ALU.w.l);
+ R.PFC++;
+}
+static void tblw(void)
+{
+ if (R.init_load_addr)
+ {
+ R.PFC = R.ACC.w.l;
+ }
+ R.tms32025_dec_cycles += (1*CLK);
+ GETDATA(0,0);
+ if (R.external_mem_access) R.tms32025_dec_cycles += (1*CLK);
+ M_WRTROM(R.PFC, R.ALU.w.l);
+ R.PFC++;
+}
+static void trap(void)
+{
+ PUSH_STACK(R.PC);
+ SET_PC(0x001E); /* Trap vector */
+}
+static void xor(void)
+{
+ GETDATA(0,0);
+ R.ACC.w.l ^= R.ALU.w.l;
+}
+static void xork(void)
+{
+ oldacc.d = R.ACC.d;
+ R.ALU.d = M_RDOP_ARG(R.PC);
+ R.PC++;
+ R.ALU.d <<= (R.opcode.b.h & 0xf);
+ R.ACC.d ^= R.ALU.d;
+ R.ACC.d |= (oldacc.d & 0x80000000);
+}
+static void zalh(void)
+{
+ GETDATA(0,0);
+ R.ACC.w.h = R.ALU.w.l;
+ R.ACC.w.l = 0x0000;
+}
+static void zalr(void)
+{
+ GETDATA(0,0);
+ R.ACC.w.h = R.ALU.w.l;
+ R.ACC.w.l = 0x8000;
+}
+static void zals(void)
+{
+ GETDATA(0,0);
+ R.ACC.w.l = R.ALU.w.l;
+ R.ACC.w.h = 0x0000;
+}
+
+
+/***********************************************************************
+ * Cycle Timings
+ ***********************************************************************/
+
+static unsigned cycles_main[256]=
+{
+/*00*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
+/*08*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
+/*10*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
+/*18*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
+/*20*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
+/*28*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
+/*30*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
+/*38*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
+/*40*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
+/*48*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
+/*50*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
+/*58*/ 3*CLK, 2*CLK, 1*CLK, 1*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK,
+/*60*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
+/*68*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
+/*70*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
+/*78*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
+/*80*/ 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK,
+/*88*/ 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK,
+/*90*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
+/*98*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
+/*A0*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
+/*A8*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
+/*B0*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
+/*B8*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
+/*C0*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
+/*C8*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
+/*D0*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 0*CLK,
+/*D8*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
+/*E0*/ 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK,
+/*E8*/ 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK,
+/*F0*/ 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK,
+/*F8*/ 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK
+};
+
+static unsigned cycles_DX_subset[8]=
+{
+/*00*/ 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 2*CLK, 0
+};
+
+static unsigned cycles_CE_subset[256]=
+{
+/*00*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
+/*08*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
+/*10*/ 0*CLK, 0*CLK, 0*CLK, 0*CLK, 1*CLK, 1*CLK, 1*CLK, 0*CLK,
+/*18*/ 1*CLK, 1*CLK, 0*CLK, 1*CLK, 1*CLK, 1*CLK, 2*CLK, 3*CLK,
+/*20*/ 1*CLK, 1*CLK, 0*CLK, 1*CLK, 2*CLK, 2*CLK, 2*CLK, 1*CLK,
+/*28*/ 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK,
+/*30*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
+/*38*/ 1*CLK, 1*CLK, 0*CLK, 0*CLK, 1*CLK, 1*CLK, 1*CLK, 1*CLK,
+/*40*/ 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK,
+/*48*/ 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK,
+/*50*/ 1*CLK, 1*CLK, 1*CLK, 1*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK,
+/*58*/ 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK,
+/*60*/ 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK,
+/*68*/ 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK,
+/*70*/ 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK,
+/*78*/ 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK,
+/*80*/ 0*CLK, 0*CLK, 1*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK,
+/*88*/ 0*CLK, 0*CLK, 1*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK,
+/*90*/ 0*CLK, 0*CLK, 1*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK,
+/*98*/ 0*CLK, 0*CLK, 1*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK,
+/*A0*/ 0*CLK, 0*CLK, 1*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK,
+/*A8*/ 0*CLK, 0*CLK, 1*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK,
+/*B0*/ 0*CLK, 0*CLK, 1*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK,
+/*B8*/ 0*CLK, 0*CLK, 1*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK,
+/*C0*/ 0*CLK, 0*CLK, 1*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK,
+/*C8*/ 0*CLK, 0*CLK, 1*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK,
+/*D0*/ 0*CLK, 0*CLK, 1*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK,
+/*D8*/ 0*CLK, 0*CLK, 1*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK,
+/*E0*/ 0*CLK, 0*CLK, 1*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK,
+/*E8*/ 0*CLK, 0*CLK, 1*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK,
+/*F0*/ 0*CLK, 0*CLK, 1*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK,
+/*F8*/ 0*CLK, 0*CLK, 1*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK, 0*CLK
+};
+
+
+/***********************************************************************
+ * Opcode Table
+ ***********************************************************************/
+
+static opcode_fn opcode_main[256]=
+{
+/*00*/ add, add, add, add, add, add, add, add,
+/*08*/ add, add, add, add, add, add, add, add,
+/*10*/ sub, sub, sub, sub, sub, sub, sub, sub,
+/*18*/ sub, sub, sub, sub, sub, sub, sub, sub,
+/*20*/ lac, lac, lac, lac, lac, lac, lac, lac,
+/*28*/ lac, lac, lac, lac, lac, lac, lac, lac,
+/*30*/ lar_ar0, lar_ar1, lar_ar2, lar_ar3, lar_ar4, lar_ar5, lar_ar6, lar_ar7,
+/*38*/ mpy, sqra, mpya, mpys, lt, lta, ltp, ltd,
+/*40*/ zalh, zals, lact, addc, subh, subs, subt, subc,
+/*48*/ addh, adds, addt, rpt, xor, or, and, subb,
+/*50*/ lst, lst1, ldp, lph, pshd, mar, dmov, bitt,
+/*58*/ tblr, tblw, sqrs, lts, macd, mac, bc, bnc,
+/*60*/ sacl, sacl, sacl, sacl, sacl, sacl, sacl, sacl,
+/*68*/ sach, sach, sach, sach, sach, sach, sach, sach,
+/*70*/ sar_ar0, sar_ar1, sar_ar2, sar_ar3, sar_ar4, sar_ar5, sar_ar6, sar_ar7,
+/*78*/ sst, sst1, popd, zalr, spl, sph, adrk, tms_sbrk,
+/*80*/ in, in, in, in, in, in, in, in,
+/*88*/ in, in, in, in, in, in, in, in,
+/*90*/ bit, bit, bit, bit, bit, bit, bit, bit,
+/*98*/ bit, bit, bit, bit, bit, bit, bit, bit,
+/*A0*/ mpyk, mpyk, mpyk, mpyk, mpyk, mpyk, mpyk, mpyk,
+/*A8*/ mpyk, mpyk, mpyk, mpyk, mpyk, mpyk, mpyk, mpyk,
+/*B0*/ mpyk, mpyk, mpyk, mpyk, mpyk, mpyk, mpyk, mpyk,
+/*B8*/ mpyk, mpyk, mpyk, mpyk, mpyk, mpyk, mpyk, mpyk,
+/*C0*/ lark_ar0, lark_ar1, lark_ar2, lark_ar3, lark_ar4, lark_ar5, lark_ar6, lark_ar7,
+/*C8*/ ldpk, ldpk, lack, rptk, addk, subk, opcodes_CE, mpyu,
+/*D0*/ opcodes_DX, opcodes_DX, opcodes_DX, opcodes_DX, opcodes_DX, opcodes_DX, opcodes_DX, opcodes_DX,
+/*D8*/ opcodes_DX, opcodes_DX, opcodes_DX, opcodes_DX, opcodes_DX, opcodes_DX, opcodes_DX, opcodes_DX,
+/*E0*/ out, out, out, out, out, out, out, out,
+/*E8*/ out, out, out, out, out, out, out, out,
+/*F0*/ bv, bgz, blez, blz, bgez, bnz, bz, bnv,
+/*F8*/ bbz, bbnz, bioz, banz, blkp, blkd, call, br
+};
+
+static opcode_fn opcode_DX_subset[8]= /* Instructions living under the Dxxx opcode */
+{
+/*00*/ lrlk, lalk, adlk, sblk, andk, ork, xork, illegal
+};
+
+static opcode_fn opcode_CE_subset[256]=
+{
+/*00*/ eint, dint, rovm, sovm, cnfd, cnfp, rsxm, ssxm,
+/*08*/ spm, spm, spm, spm, rxf, sxf, fort, fort,
+/*10*/ illegal, illegal, illegal, illegal, pac, apac, spac, illegal,
+/*18*/ sfl, sfr, illegal, abst, push, pop, trap, idle,
+/*20*/ rtxm, stxm, illegal, neg, cala, bacc, ret, cmpl,
+/*28*/ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+/*30*/ rc, sc, rtc, stc, rol, ror, rfsm, sfsm,
+/*38*/ rhm, shm, illegal, illegal, conf, conf, conf, conf,
+/*40*/ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+/*48*/ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+/*50*/ cmpr, cmpr, cmpr, cmpr, illegal, illegal, illegal, illegal,
+/*58*/ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+/*60*/ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+/*68*/ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+/*70*/ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+/*78*/ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+/*80*/ illegal, illegal, norm, illegal, illegal, illegal, illegal, illegal,
+/*88*/ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+/*90*/ illegal, illegal, norm, illegal, illegal, illegal, illegal, illegal,
+/*98*/ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+/*A0*/ illegal, illegal, norm, illegal, illegal, illegal, illegal, illegal,
+/*A8*/ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+/*B0*/ illegal, illegal, norm, illegal, illegal, illegal, illegal, illegal,
+/*B8*/ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+/*C0*/ illegal, illegal, norm, illegal, illegal, illegal, illegal, illegal,
+/*C8*/ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+/*D0*/ illegal, illegal, norm, illegal, illegal, illegal, illegal, illegal,
+/*D8*/ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+/*E0*/ illegal, illegal, norm, illegal, illegal, illegal, illegal, illegal,
+/*E8*/ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal,
+/*F0*/ illegal, illegal, norm, illegal, illegal, illegal, illegal, illegal,
+/*F8*/ illegal, illegal, illegal, illegal, illegal, illegal, illegal, illegal
+};
+
+
+
+/****************************************************************************
+ * Inits CPU emulation
+ ****************************************************************************/
+static void tms32025_init (int index, int clock, const void *config, int (*irqcallback)(int))
+{
+ R.intRAM = auto_malloc(0x800*2);
+ R.irq_callback = irqcallback;
+
+ state_save_register_item("tms32025", index, R.PC);
+ state_save_register_item("tms32025", index, R.STR0);
+ state_save_register_item("tms32025", index, R.STR1);
+ state_save_register_item("tms32025", index, R.PFC);
+ state_save_register_item("tms32025", index, R.IFR);
+ state_save_register_item("tms32025", index, R.RPTC);
+ state_save_register_item("tms32025", index, R.ACC.d);
+ state_save_register_item("tms32025", index, R.ALU.d);
+ state_save_register_item("tms32025", index, R.Preg.d);
+ state_save_register_item("tms32025", index, R.Treg);
+ state_save_register_item("tms32025", index, R.AR[0]);
+ state_save_register_item("tms32025", index, R.AR[1]);
+ state_save_register_item("tms32025", index, R.AR[2]);
+ state_save_register_item("tms32025", index, R.AR[3]);
+ state_save_register_item("tms32025", index, R.AR[4]);
+ state_save_register_item("tms32025", index, R.AR[5]);
+ state_save_register_item("tms32025", index, R.AR[6]);
+ state_save_register_item("tms32025", index, R.AR[7]);
+ state_save_register_item("tms32025", index, R.STACK[0]);
+ state_save_register_item("tms32025", index, R.STACK[1]);
+ state_save_register_item("tms32025", index, R.STACK[2]);
+ state_save_register_item("tms32025", index, R.STACK[3]);
+ state_save_register_item("tms32025", index, R.STACK[4]);
+ state_save_register_item("tms32025", index, R.STACK[5]);
+ state_save_register_item("tms32025", index, R.STACK[6]);
+ state_save_register_item("tms32025", index, R.STACK[7]);
+
+ state_save_register_item("tms32025", index, R.idle);
+ state_save_register_item("tms32025", index, R.hold);
+ state_save_register_item("tms32025", index, R.external_mem_access);
+ state_save_register_item("tms32025", index, R.init_load_addr);
+ state_save_register_item("tms32025", index, R.PREVPC);
+}
+
+/****************************************************************************
+ * Reset registers to their initial values
+ ****************************************************************************/
+static void tms32025_reset (void)
+{
+ SET_PC(0); /* Starting address on a reset */
+ R.STR0 |= 0x0600; /* INTM and unused bit set to 1 */
+ R.STR0 &= 0xefff; /* OV cleared to 0. Remaining bits undefined */
+ R.STR1 |= 0x07f0; /* SXM, C, HM, FSM, XF and unused bits set to 1 */
+ R.STR1 &= 0xeff0; /* CNF, FO, TXM, PM bits cleared to 0. Remaining bits undefined */
+ R.RPTC = 0; /* Reset repeat counter to 0 */
+ R.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;
+
+ R.idle = 0;
+ R.hold = 0;
+ R.init_load_addr = 1;
+
+ /* Reset the Data/Program address banks */
+ memset(tms32025_pgmmap, 0, sizeof(tms32025_pgmmap));
+ memset(tms32025_datamap, 0, sizeof(tms32025_datamap));
+
+ tms32025_datamap[0] = &R.intRAM[0x000]; /* B2 */
+ tms32025_datamap[4] = &R.intRAM[0x200]; /* B0 */
+ tms32025_datamap[5] = &R.intRAM[0x280]; /* B0 */
+ tms32025_datamap[6] = &R.intRAM[0x300]; /* B1 */
+ tms32025_datamap[7] = &R.intRAM[0x380]; /* B1 */
+}
+
+#if (HAS_TMS32026)
+static void tms32026_reset (void)
+{
+ tms32025_reset();
+
+ /* Reset the Data/Program address banks */
+ memset(tms32025_pgmmap, 0, sizeof(tms32025_pgmmap));
+ memset(tms32025_datamap, 0, sizeof(tms32025_datamap));
+
+ tms32025_datamap[0] = &R.intRAM[0x000]; /* B2 */
+ tms32025_datamap[4] = &R.intRAM[0x200]; /* B0 */
+ tms32025_datamap[5] = &R.intRAM[0x280]; /* B0 */
+ tms32025_datamap[6] = &R.intRAM[0x300]; /* B0 */
+ tms32025_datamap[7] = &R.intRAM[0x380]; /* B0 */
+ tms32025_datamap[8] = &R.intRAM[0x400]; /* B1 */
+ tms32025_datamap[9] = &R.intRAM[0x480]; /* B1 */
+ tms32025_datamap[10] = &R.intRAM[0x500]; /* B1 */
+ tms32025_datamap[11] = &R.intRAM[0x580]; /* B1 */
+ tms32025_datamap[12] = &R.intRAM[0x600]; /* B3 */
+ tms32025_datamap[13] = &R.intRAM[0x680]; /* B3 */
+ tms32025_datamap[14] = &R.intRAM[0x700]; /* B3 */
+ tms32025_datamap[15] = &R.intRAM[0x780]; /* B3 */
+}
+#endif
+
+
+/****************************************************************************
+ * Shut down CPU emulation
+ ****************************************************************************/
+static void tms32025_exit (void)
+{
+}
+
+
+/****************************************************************************
+ * Issue an interrupt if necessary
+ ****************************************************************************/
+static int process_IRQs(void)
+{
+ /********** Interrupt Flag Register (IFR) **********
+ | 5 | 4 | 3 | 2 | 1 | 0 |
+ | XINT| RINT| TINT| INT2| INT1| INT0|
+ */
+ R.tms32025_irq_cycles = 0;
+
+ /* Dont service Interrupts if masked, or prev instruction was EINT ! */
+
+ if ( (INTM == 0) && (R.opcode.w.l != 0xce00) && (R.IFR & IMR) )
+ {
+ R.tms32025_irq_cycles = (3*CLK); /* 3 clock cycles used due to PUSH and DINT operation ? */
+ PUSH_STACK(R.PC);
+
+ if ((R.IFR & 0x01) && (IMR & 0x01)) { /* IRQ line 0 */
+ //logerror("TMS32025: Active INT0\n");
+ SET_PC(0x0002);
+ (*R.irq_callback)(0);
+ R.idle = 0;
+ R.IFR &= (~0x01);
+ SET0(INTM_FLAG);
+ return R.tms32025_irq_cycles;
+ }
+ if ((R.IFR & 0x02) && (IMR & 0x02)) { /* IRQ line 1 */
+ //logerror("TMS32025: Active INT1\n");
+ SET_PC(0x0004);
+ (*R.irq_callback)(1);
+ R.idle = 0;
+ R.IFR &= (~0x02);
+ SET0(INTM_FLAG);
+ return R.tms32025_irq_cycles;
+ }
+ if ((R.IFR & 0x04) && (IMR & 0x04)) { /* IRQ line 2 */
+ //logerror("TMS32025: Active INT2\n");
+ SET_PC(0x0006);
+ (*R.irq_callback)(2);
+ R.idle = 0;
+ R.IFR &= (~0x04);
+ SET0(INTM_FLAG);
+ return R.tms32025_irq_cycles;
+ }
+ if ((R.IFR & 0x08) && (IMR & 0x08)) { /* Timer IRQ (internal) */
+// logerror("TMS32025: Active TINT (Timer)\n");
+ SET_PC(0x0018);
+ R.idle = 0;
+ R.IFR &= (~0x08);
+ SET0(INTM_FLAG);
+ return R.tms32025_irq_cycles;
+ }
+ if ((R.IFR & 0x10) && (IMR & 0x10)) { /* Serial port receive IRQ (internal) */
+// logerror("TMS32025: Active RINT (Serial recieve)\n");
+ DRR = S_IN(TMS32025_DR);
+ SET_PC(0x001A);
+ R.idle = 0;
+ R.IFR &= (~0x10);
+ SET0(INTM_FLAG);
+ return R.tms32025_irq_cycles;
+ }
+ if ((R.IFR & 0x20) && (IMR & 0x20)) { /* Serial port transmit IRQ (internal) */
+// logerror("TMS32025: Active XINT (Serial transmit)\n");
+ S_OUT(TMS32025_DX,DXR);
+ SET_PC(0x001C);
+ R.idle = 0;
+ R.IFR &= (~0x20);
+ SET0(INTM_FLAG);
+ return R.tms32025_irq_cycles;
+ }
+ }
+ return R.tms32025_irq_cycles;
+}
+
+INLINE void process_timer(int clocks)
+{
+ int preclocks, ticks;
+
+ /* easy case: no actual ticks */
+again:
+ preclocks = CLK - R.timerover;
+ if (clocks < preclocks)
+ {
+ R.timerover += clocks;
+ tms32025_icount -= clocks;
+ return;
+ }
+
+ /* if we're not going to overflow the timer, just count the clocks */
+ ticks = 1 + (clocks - preclocks) / CLK;
+ if (ticks <= TIM)
+ {
+ tms32025_icount -= clocks;
+ R.timerover = clocks - (ticks - 1) * CLK - preclocks;
+ TIM -= ticks;
+ }
+
+ /* otherwise, overflow the timer and signal an interrupt */
+ else
+ {
+ tms32025_icount -= preclocks + CLK * TIM;
+ R.timerover = 0;
+ TIM = PRD;
+
+ R.IFR |= 0x08;
+ clocks = process_IRQs(); /* Handle Timer IRQ */
+ goto again;
+ }
+}
+
+
+/****************************************************************************
+ * Execute ICount cycles. Exit when 0 or less
+ ****************************************************************************/
+static int tms32025_execute(int cycles)
+{
+ tms32025_icount = cycles;
+
+
+ /**** Respond to external hold signal */
+ if (S_IN(TMS32025_HOLD) == ASSERT_LINE) {
+ if (R.hold == 0) {
+ S_OUT(TMS32025_HOLDA,ASSERT_LINE); /* Hold-Ack (active low) */
+ }
+ R.hold = 1;
+ if (HM) {
+ tms32025_icount = 0; /* Exit */
+ }
+ else {
+ if (R.external_mem_access) {
+ tms32025_icount = 0; /* Exit */
+ }
+ }
+ }
+ else {
+ if (R.hold == 1) {
+ S_OUT(TMS32025_HOLDA,CLEAR_LINE); /* Hold-Ack (active low) */
+ process_timer(3);
+ }
+ R.hold = 0;
+ }
+
+ /**** If idling, update timer and/or exit execution */
+ while (R.idle && tms32025_icount > 0)
+ process_timer(tms32025_icount);
+
+ if (tms32025_icount <= 0) CALL_MAME_DEBUG;
+
+
+ while (tms32025_icount > 0)
+ {
+ R.tms32025_dec_cycles = (1*CLK);
+
+ if (R.IFR) { /* Check IRQ Flag Register for pending IRQs */
+ R.tms32025_dec_cycles += process_IRQs();
+ }
+
+ R.PREVPC = R.PC;
+
+ CALL_MAME_DEBUG;
+
+ R.opcode.d = M_RDOP(R.PC);
+ R.PC++;
+
+ if (R.opcode.b.h == 0xCE) /* Opcode 0xCExx has many opcodes in its minor byte */
+ {
+ R.tms32025_dec_cycles = cycles_CE_subset[R.opcode.b.l];
+ (*(opcode_CE_subset[R.opcode.b.l]))();
+ }
+ else if ((R.opcode.w.l & 0xf0f8) == 0xd000) /* Opcode 0xDxxx has many opcodes in its minor byte */
+ {
+ R.tms32025_dec_cycles = cycles_DX_subset[R.opcode.b.l];
+ (*(opcode_DX_subset[R.opcode.b.l]))();
+ }
+ else /* Do all opcodes except the CExx and Dxxx ones */
+ {
+ R.tms32025_dec_cycles = cycles_main[R.opcode.b.h];
+ (*(opcode_main[R.opcode.b.h]))();
+ }
+
+
+ if (R.init_load_addr == 2) { /* Repeat next instruction */
+ R.PREVPC = R.PC;
+
+ CALL_MAME_DEBUG;
+
+ R.opcode.d = M_RDOP(R.PC);
+ R.PC++;
+ R.tms32025_dec_cycles += (1*CLK);
+
+ do {
+ if (R.opcode.b.h == 0xCE)
+ { /* Do all 0xCExx Opcodes */
+ if (R.init_load_addr) {
+ R.tms32025_dec_cycles += (1*CLK);
+ }
+ else {
+ R.tms32025_dec_cycles += (1*CLK);
+ }
+ (*(opcode_CE_subset[R.opcode.b.l]))();
+ }
+ if ((R.opcode.w.l & 0xf0f8) == 0xd000)
+ { /* Do all valid 0xDxxx Opcodes */
+ if (R.init_load_addr) {
+ R.tms32025_dec_cycles += (1*CLK);
+ }
+ else {
+ R.tms32025_dec_cycles += (1*CLK);
+ }
+ (*(opcode_DX_subset[R.opcode.b.l]))();
+ }
+ else
+ { /* Do all other opcodes */
+ if (R.init_load_addr) {
+ R.tms32025_dec_cycles += (1*CLK);
+ }
+ else {
+ R.tms32025_dec_cycles += (1*CLK);
+ }
+ (*(opcode_main[R.opcode.b.h]))();
+ }
+ R.init_load_addr = 0;
+ R.RPTC-- ;
+ } while ((INT8)(R.RPTC) != -1);
+ R.RPTC = 0;
+ R.PFC = R.PC;
+ R.init_load_addr = 1;
+ }
+
+ process_timer(R.tms32025_dec_cycles);
+
+ /**** If device is put into idle mode, exit and wait for an interrupt */
+ while (R.idle && tms32025_icount > 0)
+ process_timer(tms32025_icount);
+
+
+ /**** If hold pin is active, exit if accessing external memory or if HM is set */
+ if (R.hold) {
+ if (R.external_mem_access || (HM)) {
+ if (tms32025_icount > 0) {
+ tms32025_icount = 0;
+ }
+ }
+ }
+ }
+
+ return (cycles - tms32025_icount);
+}
+
+
+/****************************************************************************
+ * Get all registers in given buffer
+ ****************************************************************************/
+static void tms32025_get_context (void *dst)
+{
+ if (dst)
+ {
+ memcpy(&R.datamap_save, &tms32025_datamap[0], sizeof(R.datamap_save));
+ memcpy(&R.pgmmap_save, &tms32025_pgmmap[500], sizeof(R.pgmmap_save));
+ *(tms32025_Regs*)dst = R;
+ }
+}
+
+
+/****************************************************************************
+ * Set all registers to given values
+ ****************************************************************************/
+static void tms32025_set_context (void *src)
+{
+ if (src)
+ {
+ R = *(tms32025_Regs*)src;
+ memcpy(&tms32025_datamap[0], &R.datamap_save, sizeof(R.datamap_save));
+ memcpy(&tms32025_pgmmap[500], &R.pgmmap_save, sizeof(R.pgmmap_save));
+ }
+}
+
+
+/****************************************************************************
+ * Set IRQ line state
+ ****************************************************************************/
+static void set_irq_line(int irqline, int state)
+{
+ /* Pending IRQs cannot be cleared */
+
+ if (state != CLEAR_LINE)
+ {
+ R.IFR |= (1 << irqline);
+// R.IFR &= 0x07;
+ }
+}
+
+
+/****************************************************************************
+ * Opcode fetcher
+ ****************************************************************************/
+static int tms32025_readop(UINT32 offset, int size, UINT64 *value)
+{
+ void *ptr;
+
+ /* skip if not custom */
+ if (!tms32025_pgmmap[offset >> 8])
+ return 0;
+
+ ptr = &((UINT8 *)&tms32025_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
+ ****************************************************************************/
+static int tms32025_read(int space, UINT32 offset, int size, UINT64 *value)
+{
+ void *ptr = NULL;
+ UINT64 temp = 0;
+
+ switch (space)
+ {
+ case ADDRESS_SPACE_PROGRAM:
+ ptr = tms32025_pgmmap[offset >> 8];
+ if (!ptr)
+ return 0;
+ break;
+
+ case ADDRESS_SPACE_DATA:
+ ptr = tms32025_datamap[offset >> 8];
+ if (!ptr)
+ return 0;
+ break;
+
+ case ADDRESS_SPACE_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:
+ tms32025_read(space, offset + 0, 2, &temp);
+ *value = temp << 16;
+ tms32025_read(space, offset + 2, 2, &temp);
+ *value |= temp & 0xffff;
+ break;
+ case 8:
+ tms32025_read(space, offset + 0, 4, &temp);
+ *value = temp << 32;
+ tms32025_read(space, offset + 4, 4, &temp);
+ *value |= temp & 0xffffffff;
+ break;
+ }
+ return 1;
+}
+
+
+/****************************************************************************
+ * Memory writer
+ ****************************************************************************/
+static int tms32025_write(int space, UINT32 offset, int size, UINT64 value)
+{
+ void *ptr = NULL;
+
+ switch (space)
+ {
+ case ADDRESS_SPACE_PROGRAM:
+ ptr = tms32025_pgmmap[offset >> 8];
+ if (!ptr)
+ return 0;
+ break;
+
+ case ADDRESS_SPACE_DATA:
+ ptr = tms32025_datamap[offset >> 8];
+ if (!ptr)
+ return 0;
+ break;
+
+ case ADDRESS_SPACE_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:
+ tms32025_write(space, offset + 0, 2, value >> 16);
+ tms32025_write(space, offset + 2, 2, value);
+ break;
+ case 8:
+ tms32025_write(space, offset + 0, 4, value >> 32);
+ tms32025_write(space, offset + 4, 4, value);
+ break;
+ }
+ return 1;
+}
+
+
+/**************************************************************************
+ * Generic set_info
+ **************************************************************************/
+
+static void tms32025_set_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are set as 64-bit signed integers --- */
+ case CPUINFO_INT_INPUT_STATE + TMS32025_INT0: set_irq_line(TMS32025_INT0, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + TMS32025_INT1: set_irq_line(TMS32025_INT1, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + TMS32025_INT2: set_irq_line(TMS32025_INT2, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + TMS32025_TINT: set_irq_line(TMS32025_TINT, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + TMS32025_RINT: set_irq_line(TMS32025_RINT, info->i); break;
+ case CPUINFO_INT_INPUT_STATE + TMS32025_XINT: set_irq_line(TMS32025_XINT, info->i); break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + TMS32025_PC: R.PC = info->i; break;
+ /* This is actually not a stack pointer, but the stack contents */
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + TMS32025_STK7: R.STACK[7] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STK6: R.STACK[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STK5: R.STACK[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STK4: R.STACK[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STK3: R.STACK[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STK2: R.STACK[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STK1: R.STACK[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STK0: R.STACK[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STR0: R.STR0 = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STR1: R.STR1 = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_IFR: R.IFR = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_RPTC: R.RPTC = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_ACC: R.ACC.d = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_PREG: R.Preg.d = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_TREG: R.Treg = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_AR0: R.AR[0] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_AR1: R.AR[1] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_AR2: R.AR[2] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_AR3: R.AR[3] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_AR4: R.AR[4] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_AR5: R.AR[5] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_AR6: R.AR[6] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_AR7: R.AR[7] = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS32025_DRR: M_WRTRAM(0,info->i); break;
+ case CPUINFO_INT_REGISTER + TMS32025_DXR: M_WRTRAM(1,info->i); break;
+ case CPUINFO_INT_REGISTER + TMS32025_TIM: M_WRTRAM(2,info->i); break;
+ case CPUINFO_INT_REGISTER + TMS32025_PRD: M_WRTRAM(3,info->i); break;
+ case CPUINFO_INT_REGISTER + TMS32025_IMR: M_WRTRAM(4,info->i); break;
+ case CPUINFO_INT_REGISTER + TMS32025_GREG: M_WRTRAM(5,info->i); break;
+ }
+}
+
+
+
+/**************************************************************************
+ * Generic get_info
+ **************************************************************************/
+
+void tms32025_get_info(UINT32 state, cpuinfo *info)
+{
+ switch (state)
+ {
+ /* --- the following bits of info are returned as 64-bit signed integers --- */
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(R); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 6; break;
+ case CPUINFO_INT_DEFAULT_IRQ_VECTOR: info->i = 0; break;
+ case CPUINFO_INT_ENDIANNESS: info->i = CPU_IS_BE; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 2; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 4; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1*CLK; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 5*CLK; break;
+
+ case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16; break;
+ case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 16; break;
+ case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = -1; break;
+ case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 16; break;
+ case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: info->i = 16; break;
+ case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: info->i = -1; break;
+ case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO: info->i = 16; break;
+ case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: info->i = 17; break;
+ case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: info->i = -1; break;
+
+ case CPUINFO_INT_INPUT_STATE + TMS32025_INT0: info->i = (R.IFR & 0x01) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + TMS32025_INT1: info->i = (R.IFR & 0x02) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + TMS32025_INT2: info->i = (R.IFR & 0x04) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + TMS32025_TINT: info->i = (R.IFR & 0x08) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + TMS32025_RINT: info->i = (R.IFR & 0x10) ? ASSERT_LINE : CLEAR_LINE; break;
+ case CPUINFO_INT_INPUT_STATE + TMS32025_XINT: info->i = (R.IFR & 0x20) ? ASSERT_LINE : CLEAR_LINE; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = R.PREVPC; break;
+
+ case CPUINFO_INT_PC:
+ case CPUINFO_INT_REGISTER + TMS32025_PC: info->i = R.PC; break;
+ /* This is actually not a stack pointer, but the stack contents */
+ case CPUINFO_INT_SP:
+ case CPUINFO_INT_REGISTER + TMS32025_STK7: info->i = R.STACK[7]; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STK6: info->i = R.STACK[6]; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STK5: info->i = R.STACK[5]; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STK4: info->i = R.STACK[4]; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STK3: info->i = R.STACK[3]; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STK2: info->i = R.STACK[2]; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STK1: info->i = R.STACK[1]; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STK0: info->i = R.STACK[0]; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STR0: info->i = R.STR0; break;
+ case CPUINFO_INT_REGISTER + TMS32025_STR1: info->i = R.STR1; break;
+ case CPUINFO_INT_REGISTER + TMS32025_IFR: info->i = R.IFR; break;
+ case CPUINFO_INT_REGISTER + TMS32025_RPTC: info->i = R.RPTC; break;
+ case CPUINFO_INT_REGISTER + TMS32025_ACC: info->i = R.ACC.d; break;
+ case CPUINFO_INT_REGISTER + TMS32025_PREG: info->i = R.Preg.d; break;
+ case CPUINFO_INT_REGISTER + TMS32025_TREG: info->i = R.Treg; break;
+ case CPUINFO_INT_REGISTER + TMS32025_AR0: info->i = R.AR[0]; break;
+ case CPUINFO_INT_REGISTER + TMS32025_AR1: info->i = R.AR[1]; break;
+ case CPUINFO_INT_REGISTER + TMS32025_AR2: info->i = R.AR[2]; break;
+ case CPUINFO_INT_REGISTER + TMS32025_AR3: info->i = R.AR[3]; break;
+ case CPUINFO_INT_REGISTER + TMS32025_AR4: info->i = R.AR[4]; break;
+ case CPUINFO_INT_REGISTER + TMS32025_AR5: info->i = R.AR[5]; break;
+ case CPUINFO_INT_REGISTER + TMS32025_AR6: info->i = R.AR[6]; break;
+ case CPUINFO_INT_REGISTER + TMS32025_AR7: info->i = R.AR[7]; break;
+ case CPUINFO_INT_REGISTER + TMS32025_DRR: info->i = M_RDRAM(0); break;
+ case CPUINFO_INT_REGISTER + TMS32025_DXR: info->i = M_RDRAM(1); break;
+ case CPUINFO_INT_REGISTER + TMS32025_TIM: info->i = M_RDRAM(2); break;
+ case CPUINFO_INT_REGISTER + TMS32025_PRD: info->i = M_RDRAM(3); break;
+ case CPUINFO_INT_REGISTER + TMS32025_IMR: info->i = M_RDRAM(4); break;
+ case CPUINFO_INT_REGISTER + TMS32025_GREG: info->i = M_RDRAM(5); break;
+
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_PTR_SET_INFO: info->setinfo = tms32025_set_info; break;
+ case CPUINFO_PTR_GET_CONTEXT: info->getcontext = tms32025_get_context; break;
+ case CPUINFO_PTR_SET_CONTEXT: info->setcontext = tms32025_set_context; break;
+ case CPUINFO_PTR_INIT: info->init = tms32025_init; break;
+ case CPUINFO_PTR_RESET: info->reset = tms32025_reset; break;
+ case CPUINFO_PTR_EXIT: info->exit = tms32025_exit; break;
+ case CPUINFO_PTR_EXECUTE: info->execute = tms32025_execute; break;
+ case CPUINFO_PTR_BURN: info->burn = NULL; break;
+#ifdef MAME_DEBUG
+ case CPUINFO_PTR_DISASSEMBLE: info->disassemble = tms32025_dasm; break;
+#endif /* MAME_DEBUG */
+ case CPUINFO_PTR_READ: info->read = tms32025_read; break;
+ case CPUINFO_PTR_WRITE: info->write = tms32025_write; break;
+ case CPUINFO_PTR_READOP: info->readop = tms32025_readop; break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &tms32025_icount; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_NAME: strcpy(info->s, "TMS32025"); break;
+ case CPUINFO_STR_CORE_FAMILY: strcpy(info->s, "Texas Instruments TMS320x25"); break;
+ case CPUINFO_STR_CORE_VERSION: strcpy(info->s, "1.10"); break;
+ case CPUINFO_STR_CORE_FILE: strcpy(info->s, __FILE__); break;
+ case CPUINFO_STR_CORE_CREDITS: strcpy(info->s, "Copyright (C) 2001 by Tony La Porta"); break;
+
+ case CPUINFO_STR_FLAGS:
+ sprintf(info->s, "arp%d%c%c%c%cdp%03x arb%d%c%c%c%c%c%c%c%c%c%c%cpm%d",
+ (R.STR0 & 0xe000) >> 13,
+ R.STR0 & 0x1000 ? 'O':'.',
+ R.STR0 & 0x0800 ? 'M':'.',
+ R.STR0 & 0x0400 ? '.':'?',
+ R.STR0 & 0x0200 ? 'I':'.',
+ (R.STR0 & 0x01ff),
+
+ (R.STR1 & 0xe000) >> 13,
+ R.STR1 & 0x1000 ? 'P':'D',
+ R.STR1 & 0x0800 ? 'T':'.',
+ R.STR1 & 0x0400 ? 'S':'.',
+ R.STR1 & 0x0200 ? 'C':'?',
+ R.STR0 & 0x0100 ? '.':'?',
+ R.STR1 & 0x0080 ? '.':'?',
+ R.STR1 & 0x0040 ? 'H':'.',
+ R.STR1 & 0x0020 ? 'F':'.',
+ R.STR1 & 0x0010 ? 'X':'.',
+ R.STR1 & 0x0008 ? 'f':'.',
+ R.STR1 & 0x0004 ? 'o':'i',
+ (R.STR1 & 0x0003) );
+ break;
+
+ case CPUINFO_STR_REGISTER + TMS32025_PC: sprintf(info->s, "PC:%04X", R.PC); break;
+ case CPUINFO_STR_REGISTER + TMS32025_STR0: sprintf(info->s, "STR0:%04X", R.STR0); break;
+ case CPUINFO_STR_REGISTER + TMS32025_STR1: sprintf(info->s, "STR1:%04X", R.STR1); break;
+ case CPUINFO_STR_REGISTER + TMS32025_IFR: sprintf(info->s, "IFR:%04X", R.IFR); break;
+ case CPUINFO_STR_REGISTER + TMS32025_RPTC: sprintf(info->s, "RPTC:%02X", R.RPTC); break;
+ case CPUINFO_STR_REGISTER + TMS32025_STK7: sprintf(info->s, "STK7:%04X", R.STACK[7]); break;
+ case CPUINFO_STR_REGISTER + TMS32025_STK6: sprintf(info->s, "STK6:%04X", R.STACK[6]); break;
+ case CPUINFO_STR_REGISTER + TMS32025_STK5: sprintf(info->s, "STK5:%04X", R.STACK[5]); break;
+ case CPUINFO_STR_REGISTER + TMS32025_STK4: sprintf(info->s, "STK4:%04X", R.STACK[4]); break;
+ case CPUINFO_STR_REGISTER + TMS32025_STK3: sprintf(info->s, "STK3:%04X", R.STACK[3]); break;
+ case CPUINFO_STR_REGISTER + TMS32025_STK2: sprintf(info->s, "STK2:%04X", R.STACK[2]); break;
+ case CPUINFO_STR_REGISTER + TMS32025_STK1: sprintf(info->s, "STK1:%04X", R.STACK[1]); break;
+ case CPUINFO_STR_REGISTER + TMS32025_STK0: sprintf(info->s, "STK0:%04X", R.STACK[0]); break;
+ case CPUINFO_STR_REGISTER + TMS32025_ACC: sprintf(info->s, "ACC:%08X", R.ACC.d); break;
+ case CPUINFO_STR_REGISTER + TMS32025_PREG: sprintf(info->s, "P:%08X", R.Preg.d); break;
+ case CPUINFO_STR_REGISTER + TMS32025_TREG: sprintf(info->s, "T:%04X", R.Treg); break;
+ case CPUINFO_STR_REGISTER + TMS32025_AR0: sprintf(info->s, "AR0:%04X", R.AR[0]); break;
+ case CPUINFO_STR_REGISTER + TMS32025_AR1: sprintf(info->s, "AR1:%04X", R.AR[1]); break;
+ case CPUINFO_STR_REGISTER + TMS32025_AR2: sprintf(info->s, "AR2:%04X", R.AR[2]); break;
+ case CPUINFO_STR_REGISTER + TMS32025_AR3: sprintf(info->s, "AR3:%04X", R.AR[3]); break;
+ case CPUINFO_STR_REGISTER + TMS32025_AR4: sprintf(info->s, "AR4:%04X", R.AR[4]); break;
+ case CPUINFO_STR_REGISTER + TMS32025_AR5: sprintf(info->s, "AR5:%04X", R.AR[5]); break;
+ case CPUINFO_STR_REGISTER + TMS32025_AR6: sprintf(info->s, "AR6:%04X", R.AR[6]); break;
+ case CPUINFO_STR_REGISTER + TMS32025_AR7: sprintf(info->s, "AR7:%04X", R.AR[7]); break;
+ case CPUINFO_STR_REGISTER + TMS32025_DRR: sprintf(info->s, "DRR:%04X", M_RDRAM(0)); break;
+ case CPUINFO_STR_REGISTER + TMS32025_DXR: sprintf(info->s, "DXR:%04X", M_RDRAM(1)); break;
+ case CPUINFO_STR_REGISTER + TMS32025_TIM: sprintf(info->s, "TIM:%04X", M_RDRAM(2)); break;
+ case CPUINFO_STR_REGISTER + TMS32025_PRD: sprintf(info->s, "PRD:%04X", M_RDRAM(3)); break;
+ case CPUINFO_STR_REGISTER + TMS32025_IMR: sprintf(info->s, "IMR:%04X", M_RDRAM(4)); break;
+ case CPUINFO_STR_REGISTER + TMS32025_GREG: sprintf(info->s, "GREG:%04X", M_RDRAM(5)); break;
+ }
+}
+
+
+#if (HAS_TMS32026)
+/**************************************************************************
+ * CPU-specific set_info
+ **************************************************************************/
+
+void tms32026_get_info(UINT32 _state, cpuinfo *info)
+{
+ switch (_state)
+ {
+ /* --- the following bits of info are returned as pointers to data or functions --- */
+ case CPUINFO_PTR_RESET: info->reset = tms32026_reset; break;
+
+ /* --- the following bits of info are returned as NULL-terminated strings --- */
+ case CPUINFO_STR_NAME: strcpy(info->s, "TMS32026"); break;
+
+ default: tms32025_get_info(_state, info); break;
+ }
+}
+#endif