diff options
Diffstat (limited to 'src/emu/cpu/tms32025/tms32025.c')
-rw-r--r-- | src/emu/cpu/tms32025/tms32025.c | 2477 |
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 |