summaryrefslogtreecommitdiffstatshomepage
path: root/trunk/src/emu/cpu/tms0980/tms0980.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/emu/cpu/tms0980/tms0980.c')
-rw-r--r--trunk/src/emu/cpu/tms0980/tms0980.c1285
1 files changed, 1285 insertions, 0 deletions
diff --git a/trunk/src/emu/cpu/tms0980/tms0980.c b/trunk/src/emu/cpu/tms0980/tms0980.c
new file mode 100644
index 00000000000..084f5c3f662
--- /dev/null
+++ b/trunk/src/emu/cpu/tms0980/tms0980.c
@@ -0,0 +1,1285 @@
+/*
+
+
+TMS0980/TMS1000-family CPU cores
+
+The tms0980 and tms1000-family cpu cores are very similar. The tms0980 has a
+slightly bigger addressable area and uses 9bit instructions where the tms1000
+family uses 8bit instruction. The instruction set themselves are very similar
+though. The table below shows the differences between the different models.
+
+Mode | ROM | RAM | R pins | O pins | K pins | ids
+---------+-----------+----------+--------+--------+--------|----------
+tms0970* | 1024 * 8 | 64 * 4 | | | | tms0972
+tms0920* | 511?* 9 | 40 * 5 | | | | tmc0921
+tms0980 | 2048 * 9 | 64 * 9 | | | | tmc0981
+tms1000 | 1024 * 8 | 64 * 4 | 11 | 8 | 4 | tms1001
+tms1040* | 1024 * 8 | 64 * 4 | | | | tms1043
+tms1070 | 1024 * 8 | 64 * 4 | 11 | 8 | 4 | tms1071
+tms1100 | 2048 * 8 | 128 * 4 | 11 | 8 | 4 | tms1111/tms1115
+tms1170* | 2048 * 8 | 128 * 4 | | | | tmc1172
+tms1200 | 1024 * 8 | 64 * 4 | 13 | 8 | 4 | tms1215
+tms1270 | 1024 * 8 | 64 * 4 | 13 | 10 | 4 | tms1278
+tms1300 | 2048 * 8 | 128 * 4 | 16 | 8 | 4 | tms1309
+tms1370* | 2048 * 8 | 128 * 4 | | | | za0543
+tms1400* | 4096 * 8 | 128 * 4 | | | |
+tms1470* | 4096 * 8 | 128 * 4 | | | | tms1470
+tms1500* | 2048 * 13 | 64 * 20 | | | | tmc1501
+tms1600* | 4096 * 8 | 128 * 4 | | | |
+tms1670* | 4096 * 8 | 128 * 4 | | | |
+tms1700* | 512 * 8 | 32 * 4 | | | |
+tms1980* | 2048 * 9 | 64 * 9 | | | | tmc1982
+tms1990* | 1024 * 8 | 64 * 4 | | | | tmc1991
+tp0310* | 511?* 9 | 40 * 5 | | | | tp0311
+tp0320* | 2048 * 9 | 64 * 13 | | | | tp0321
+tp0455* | | | | | | cd4501
+tp0456* | | | | | | cd4555
+tp0458* | | | | | | cd4812
+tp0485* | | | | | | cd2901
+tp0530* | | | | | | cd5402
+
+* = not supported yet
+
+The TMS1000 core has been tested with some example code, the other models
+have not been tested lacking rom dumps.
+
+Each instruction takes 12 cycles to execute in 2 phases: a fetch phase and an
+execution phase. The execution phase takes place at the same time as the fetch
+phase of the next instruction. So, during execution there are both fetch and
+execution operations taking place. The operation can be split up as follows:
+cycle #0
+ - Fetch:
+ 1. ROM address 0
+ - Execute:
+ 1. Read RAM
+ 2. Clear ALU inputs
+ 3. Execute BRANCH/CALL/RETN part #2
+ 4. K input valid
+cycle #1
+ - Fetch:
+ 1. ROM address 1
+ - Execute:
+ 1. Update ALU inputs
+cycle #2
+ - Fetch:
+ 1. nothing/wait(?)
+ - Execute:
+ 1. Perform ALU operation
+ 2. Write RAM
+cycle #3
+ - Fetch:
+ 1. Fetch/Update PC/RAM address #1
+ - Execute:
+ 1. Register store part #1
+cycle #4
+ - Fetch:
+ 1. Fetch/Update PC/RAM address #2
+ - Execute:
+ 1. Register store part #2
+cycle #5
+ - Fetch:
+ 1. Instruction decode
+ - Execute:
+ 1. Execute BRANCH/CALL/RETN part #1
+
+
+The CPU cores contains a set of fixed instructions and a set of
+instructions created using microinstructions. A subset of the
+instruction set could be defined from the microinstructions by
+TI customers. Currently we only support the standard instruction
+set as defined by TI.
+
+The microinstructions are:
+15TN - 15 to -ALU
+ATN - ACC to -ALU
+AUTA - ALU to ACC
+AUTY - ALU to Y
+C8 - CARRY8 to STATUS
+CIN - Carry In to ALU
+CKM - CKB to MEM
+CKN - CKB to -ALU
+CKP - CKB to +ALU
+CME - Conditional Memory Enable
+DMTP - DAM to +ALU
+MTN - MEM to -ALU
+MTP - MEM to +ALU
+NATN - ~ACC to -ALU
+NDMTP - ~DAM to +ALU
+NE - COMP to STATUS
+SSE - Special Status Enable
+SSS - Special Status Sample
+STO - ACC to MEM
+YTP - Y to +ALU
+
+cycle #0: 15TN, ATN, CIN, CKN, CKP, DMTP, MTN, MTP, NATN, NDMTP, YTP
+cycle #2: C8(?), CKM, NE(?), STO
+cycle #3,#4: AUTA, AUTY
+
+unknown cycle: CME, SSE, SSS
+
+*/
+
+#include "emu.h"
+#include "debugger.h"
+#include "tms0980.h"
+
+#define LOG 0
+
+#define MICRO_MASK 0x80000000
+#define FIXED_INSTRUCTION 0x00000000
+
+
+/* Standard/fixed intructions */
+#define F_ILL 0x00000000
+#define F_BR 0x00000001
+#define F_CALL 0x00000002
+#define F_CLO 0x00000004
+#define F_COMC 0x00000008
+#define F_COMX 0x00000010
+#define F_COMX8 0x00000020
+#define F_LDP 0x00000040
+#define F_LDX 0x00000080
+#define F_OFF 0x00000100
+#define F_RBIT 0x00000200
+#define F_REAC 0x00000400
+#define F_RETN 0x00000800
+#define F_RSTR 0x00001000
+#define F_SAL 0x00002000
+#define F_SBIT 0x00004000
+#define F_SBL 0x00008000
+#define F_SEAC 0x00010000
+#define F_SETR 0x00020000
+#define F_TDO 0x00040000
+
+
+/* Microinstructions */
+#define M_15TN 0x00000001
+#define M_ATN 0x00000002
+#define M_AUTA 0x00000004
+#define M_AUTY 0x00000008
+#define M_C8 0x00000010
+#define M_CIN 0x00000020
+#define M_CKM 0x00000040
+#define M_CKN 0x00000080
+#define M_CKP 0x00000100
+#define M_CME 0x00000200
+#define M_DMTP 0x00000400
+#define M_MTN 0x00000800
+#define M_MTP 0x00001000
+#define M_NATN 0x00002000
+#define M_NDMTP 0x00004000
+#define M_NE 0x00008000
+#define M_SSE 0x00010000
+#define M_SSS 0x00020000
+#define M_STO 0x00040000
+#define M_STSL 0x00080000
+#define M_YTP 0x00100000
+
+
+/* instructions built from microinstructions */
+#define I_AC1AC ( MICRO_MASK | M_CKP | M_ATN | M_CIN | M_C8 | M_AUTA )
+#define I_A6AAC I_ACACC
+#define I_A8AAC I_ACACC
+#define I_A10AAC I_ACACC
+#define I_ACACC ( MICRO_MASK | M_CKP | M_ATN | M_C8 | M_AUTA )
+#define I_ACNAA ( MICRO_MASK | M_CKP | M_NATN | M_AUTA )
+#define I_ALEC ( MICRO_MASK | M_CKP | M_NATN | M_CIN | M_C8 )
+#define I_ALEM ( MICRO_MASK | M_MTP | M_NATN | M_CIN | M_C8 )
+#define I_AMAAC ( MICRO_MASK | M_MTP | M_ATN | M_C8 | M_AUTA )
+#define I_CCLA ( MICRO_MASK | M_AUTA | M_SSS )
+#define I_CLA ( MICRO_MASK | M_AUTA )
+#define I_CPAIZ ( MICRO_MASK | M_NATN | M_CIN | M_C8 | M_AUTA )
+#define I_CTMDYN ( MICRO_MASK | M_YTP | M_15TN | M_C8 | M_AUTY | M_CME )
+#define I_DAN ( MICRO_MASK | M_CKP | M_ATN | M_CIN | M_C8 | M_AUTA )
+#define I_DMAN ( MICRO_MASK | M_MTP | M_15TN | M_C8 | M_AUTA )
+#define I_DMEA ( MICRO_MASK | M_MTP | M_DMTP | M_SSS | M_AUTA )
+#define I_DNAA ( MICRO_MASK | M_DMTP | M_NATN | M_SSS | M_AUTA )
+#define I_DYN ( MICRO_MASK | M_YTP | M_15TN | M_C8 | M_AUTY )
+#define I_IA ( MICRO_MASK | M_ATN | M_CIN | M_AUTA )
+#define I_IMAC ( MICRO_MASK | M_MTP | M_CIN | M_C8 | M_AUTA )
+#define I_IYC ( MICRO_MASK | M_YTP | M_CIN | M_C8 | M_AUTY )
+#define I_KNEZ ( MICRO_MASK | M_CKP | M_NE )
+#define I_MNEA ( MICRO_MASK | M_MTP | M_ATN | M_NE )
+#define I_MNEZ ( MICRO_MASK | M_MTP | M_NE )
+#define I_M_NDMEA ( MICRO_MASK | M_MTN | M_NDTMP | M_SSS | M_AUTA )
+#define I_SAMAN ( MICRO_MASK | M_MTP | M_NATN | M_CIN | M_C8 | M_AUTA )
+#define I_SETR ( MICRO_MASK | M_YTP | M_15TN | M_AUTY | M_C8 )
+#define I_TAM ( MICRO_MASK | M_STO )
+#define I_TAMACS ( MICRO_MASK | M_STO | M_ATN | M_CKP | M_AUTA | M_SSE )
+#define I_TAMDYN ( MICRO_MASK | M_STO | M_YTP | M_15TN | M_AUTY | M_C8 )
+#define I_TAMIY ( MICRO_MASK | M_STO | M_YTP | M_CIN | M_AUTY )
+#define I_TAMIYC ( MICRO_MASK | M_STO | M_YTP | M_CIN | M_C8 | M_AUTY )
+#define I_TAMZA ( MICRO_MASK | M_STO | M_AUTA )
+#define I_TAY ( MICRO_MASK | M_ATN | M_AUTY )
+#define I_TBIT ( MICRO_MASK | M_CKP | M_CKN | M_MTP | M_NE )
+#define I_TCY ( MICRO_MASK | M_CKP | M_AUTY )
+#define I_TCMIY ( MICRO_MASK | M_CKM | M_YTP | M_CIN | M_AUTY )
+#define I_TKA ( MICRO_MASK | M_CKP | M_AUTA )
+#define I_TKM ( MICRO_MASK | M_CKM )
+#define I_TMA ( MICRO_MASK | M_MTP | M_AUTA )
+#define I_TMY ( MICRO_MASK | M_MTP | M_AUTY )
+#define I_TYA ( MICRO_MASK | M_YTP | M_AUTA )
+#define I_XDA ( MICRO_MASK | M_DMTP | M_AUTA | M_STO )
+#define I_XMA ( MICRO_MASK | M_MTP | M_STO | M_AUTA )
+#define I_YMCY ( MICRO_MASK | M_CIN | M_YTP | M_CKN | M_AUTY )
+#define I_YNEA ( MICRO_MASK | M_YTP | M_ATN | M_NE )
+#define I_YNEC ( MICRO_MASK | M_YTP | M_CKN | M_NE )
+
+
+typedef struct _tms0980_state tms0980_state;
+struct _tms0980_state
+{
+ UINT8 prev_pc; /* previous program counter */
+ UINT8 prev_pa; /* previous page address register */
+ UINT8 pc; /* program counter is a 7 bit register on tms0980, 6 bit register on tms1000/1070/1200/1270/1100/1300 */
+ UINT8 pa; /* page address register is a 4 bit register */
+ UINT8 sr; /* subroutine return register is a 7 bit register */
+ UINT8 pb; /* page buffer register is a 4 bit register */
+ UINT8 a; /* Accumulator is a 4 bit register (?) */
+ UINT8 x; /* X-register is a 2 bit register */
+ UINT8 y; /* Y-register is a 4 bit register */
+ UINT8 dam; /* DAM register is a 4 bit register */
+ UINT8 ca; /* Chapter address bit */
+ UINT8 cb; /* Chapter buffer bit */
+ UINT8 cs; /* Chapter subroutine bit */
+ UINT16 r;
+ UINT8 o;
+ UINT8 cki_bus; /* CKI bus */
+ UINT8 p; /* adder p-input */
+ UINT8 n; /* adder n-input */
+ UINT8 adder_result; /* adder result */
+ UINT8 carry_in; /* carry in */
+ UINT8 status;
+ UINT8 status_latch;
+ UINT8 special_status;
+ UINT8 call_latch;
+ UINT8 add_latch;
+ UINT8 branch_latch;
+ int subcycle;
+ UINT8 ram_address;
+ UINT16 ram_data;
+ UINT16 rom_address;
+ UINT16 opcode;
+ UINT32 decode;
+ int icount;
+ UINT16 o_mask; /* mask to determine the number of O outputs */
+ UINT16 r_mask; /* mask to determine the number of R outputs */
+ UINT8 pc_size; /* how bits in the PC register */
+ UINT8 byte_size; /* 8 or 9 bit bytes */
+ const UINT32 *decode_table;
+ const tms0980_config *config;
+ address_space *program;
+ address_space *data;
+};
+
+
+static const UINT8 tms0980_c2_value[4] =
+{
+ 0x00, 0x02, 0x01, 0x03
+};
+static const UINT8 tms0980_c4_value[16] =
+{
+ 0x00, 0x08, 0x04, 0x0C, 0x02, 0x0A, 0x06, 0x0E, 0x01, 0x09, 0x05, 0x0D, 0x03, 0x0B, 0x07, 0x0F
+};
+static const UINT8 tms0980_bit_value[4] = { 1, 4, 2, 8 };
+static const UINT8 tms0980_nbit_value[4] = { 0x0E, 0x0B, 0x0D, 0x07 };
+
+
+static const UINT32 tms0980_decode[512] =
+{
+ /* 0x000 */
+ F_COMX, I_ALEM, I_YNEA, I_XMA, I_DYN, I_IYC, I_CLA, I_DMAN,
+ I_TKA, I_MNEA, I_TKM, F_ILL, F_ILL, F_SETR, I_KNEZ, F_ILL,
+ I_DMEA, I_DNAA, I_CCLA, I_DMEA, F_ILL, I_AMAAC, F_ILL, F_ILL,
+ I_CTMDYN, I_XDA, F_ILL, F_ILL, F_ILL, F_ILL, F_ILL, F_ILL,
+ I_TBIT, I_TBIT, I_TBIT, I_TBIT, F_ILL, F_ILL, F_ILL, F_ILL,
+ I_TAY, I_TMA, I_TMY, I_TYA, I_TAMDYN, I_TAMIYC, I_TAMZA, I_TAM,
+ I_SAMAN, I_CPAIZ, I_IMAC, I_MNEZ, F_ILL, F_ILL, F_ILL, F_ILL,
+ I_TCY, I_YNEC, I_TCMIY, I_ACACC, I_ACNAA, I_TAMACS, I_ALEC, I_YMCY,
+ /* 0x040 */
+ I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY,
+ I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY,
+ I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC,
+ I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC,
+ I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY,
+ I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY,
+ I_ACACC, I_ACACC, I_ACACC, I_ACACC, I_ACACC, I_ACACC, I_ACACC, I_ACACC,
+ I_ACACC, I_ACACC, I_ACACC, I_ACACC, I_ACACC, I_ACACC, I_ACACC, I_ACACC,
+ /* 0x080 */
+ F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP,
+ F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP,
+ F_LDX, F_LDX, F_LDX, F_LDX, F_LDX, F_LDX, F_LDX, F_LDX,
+ F_LDX, F_LDX, F_LDX, F_LDX, F_LDX, F_LDX, F_LDX, F_LDX,
+ F_SBIT, F_SBIT, F_SBIT, F_SBIT, F_RBIT, F_RBIT, F_RBIT, F_RBIT,
+ F_ILL, F_ILL, F_ILL, F_ILL, F_ILL, F_ILL, F_ILL, F_ILL,
+ F_TDO, F_SAL, F_COMX8, F_SBL, F_REAC, F_SEAC, F_OFF, F_ILL,
+ F_ILL, F_ILL, F_ILL, F_ILL, F_ILL, F_ILL, F_ILL, F_RETN,
+ /* 0x0c0 */
+ I_ACNAA, I_ACNAA, I_ACNAA, I_ACNAA, I_ACNAA, I_ACNAA, I_ACNAA, I_ACNAA,
+ I_ACNAA, I_ACNAA, I_ACNAA, I_ACNAA, I_ACNAA, I_ACNAA, I_ACNAA, I_ACNAA,
+ I_TAMACS, I_TAMACS, I_TAMACS, I_TAMACS, I_TAMACS, I_TAMACS, I_TAMACS, I_TAMACS,
+ I_TAMACS, I_TAMACS, I_TAMACS, I_TAMACS, I_TAMACS, I_TAMACS, I_TAMACS, I_TAMACS,
+ I_ALEC, I_ALEC, I_ALEC, I_ALEC, I_ALEC, I_ALEC, I_ALEC, I_ALEC,
+ I_ALEC, I_ALEC, I_ALEC, I_ALEC, I_ALEC, I_ALEC, I_ALEC, I_ALEC,
+ I_YMCY, I_YMCY, I_YMCY, I_YMCY, I_YMCY, I_YMCY, I_YMCY, I_YMCY,
+ I_YMCY, I_YMCY, I_YMCY, I_YMCY, I_YMCY, I_YMCY, I_YMCY, I_YMCY,
+ /* 0x100 */
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ /* 0x140 */
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ /* 0x180 */
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ /* 0x1c0 */
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL
+};
+
+
+static const UINT32 tms1000_default_decode[256] = {
+ /* 0x00 */
+ F_COMX, I_A8AAC, I_YNEA, I_TAM, I_TAMZA, I_A10AAC, I_A6AAC, I_DAN,
+ I_TKA, I_KNEZ, F_TDO, F_CLO, F_RSTR, F_SETR, I_IA, F_RETN,
+ F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP,
+ F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP,
+ /* 0x20 */
+ I_TAMIY, I_TMA, I_TMY, I_TYA, I_TAY, I_AMAAC, I_MNEZ, I_SAMAN,
+ I_IMAC, I_ALEM, I_DMAN, I_IYC, I_DYN, I_CPAIZ, I_XMA, I_CLA,
+ F_SBIT, F_SBIT, F_SBIT, F_SBIT, F_RBIT, F_RBIT, F_RBIT, F_RBIT,
+ I_TBIT, I_TBIT, I_TBIT, I_TBIT, F_LDX, F_LDX, F_LDX, F_LDX,
+ /* 0x40 */
+ I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY,
+ I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY,
+ I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC,
+ I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC,
+ /* 0x60 */
+ I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY,
+ I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY,
+ I_ALEC, I_ALEC, I_ALEC, I_ALEC, I_ALEC, I_ALEC, I_ALEC, I_ALEC,
+ I_ALEC, I_ALEC, I_ALEC, I_ALEC, I_ALEC, I_ALEC, I_ALEC, I_ALEC,
+ /* 0x80 */
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ /* 0xC0 */
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+};
+
+
+static const UINT32 tms1100_default_decode[256] = {
+ /* 0x00 */
+ I_MNEA, I_ALEM, I_YNEA, I_XMA, I_DYN, I_IYC, I_AMAAC, I_DMAN,
+ I_TKA, F_COMX, F_TDO, F_COMC, F_RSTR, F_SETR, I_KNEZ, F_RETN,
+ F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP,
+ F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP, F_LDP,
+ /* 0x20 */
+ I_TAY, I_TMA, I_TMY, I_TYA, I_TAMDYN, I_TAMIYC, I_TAMZA, I_TAM,
+ F_LDX, F_LDX, F_LDX, F_LDX, F_LDX, F_LDX, F_LDX, F_LDX,
+ F_SBIT, F_SBIT, F_SBIT, F_SBIT, F_RBIT, F_RBIT, F_RBIT, F_RBIT,
+ I_TBIT, I_TBIT, I_TBIT, I_TBIT, I_SAMAN, I_CPAIZ, I_IMAC, I_MNEZ,
+ /* 0x40 */
+ I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY,
+ I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY, I_TCY,
+ I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC,
+ I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC, I_YNEC,
+ /* 0x60 */
+ I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY,
+ I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY, I_TCMIY,
+ I_AC1AC, I_AC1AC, I_AC1AC, I_AC1AC, I_AC1AC, I_AC1AC, I_AC1AC, I_AC1AC,
+ I_AC1AC, I_AC1AC, I_AC1AC, I_AC1AC, I_AC1AC, I_AC1AC, I_AC1AC, I_CLA,
+ /* 0x80 */
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR, F_BR,
+ /* 0xC0 */
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+ F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL, F_CALL,
+};
+
+
+INLINE tms0980_state *get_safe_token(device_t *device)
+{
+ assert(device != NULL);
+ assert(device->type() == TMS0980 ||
+ device->type() == TMS1000 ||
+ device->type() == TMS1070 ||
+ device->type() == TMS1100 ||
+ device->type() == TMS1200 ||
+ device->type() == TMS1270 ||
+ device->type() == TMS1300 );
+ return (tms0980_state *)downcast<legacy_cpu_device *>(device)->token();
+}
+
+
+static ADDRESS_MAP_START(tms0980_internal_rom, AS_PROGRAM, 16)
+ AM_RANGE( 0x0000, 0x0FFF ) AM_ROM
+ADDRESS_MAP_END
+
+
+static ADDRESS_MAP_START(tms0980_internal_ram, AS_DATA, 8)
+ AM_RANGE( 0x0000, 0x0FFF ) AM_RAM
+ADDRESS_MAP_END
+
+
+static ADDRESS_MAP_START(program_10bit_8, AS_PROGRAM, 8)
+ AM_RANGE( 0x000, 0x3ff ) AM_ROM
+ADDRESS_MAP_END
+
+
+static ADDRESS_MAP_START(program_11bit_8, AS_PROGRAM, 8)
+ AM_RANGE( 0x000, 0x7ff ) AM_ROM
+ADDRESS_MAP_END
+
+
+static ADDRESS_MAP_START(data_6bit, AS_DATA, 8)
+ AM_RANGE( 0x00, 0x3f ) AM_RAM
+ADDRESS_MAP_END
+
+
+static ADDRESS_MAP_START(data_7bit, AS_DATA, 8)
+ AM_RANGE( 0x00, 0x7f ) AM_RAM
+ADDRESS_MAP_END
+
+
+static void cpu_init_tms_common( legacy_cpu_device *device, const UINT32* decode_table, UINT16 o_mask, UINT16 r_mask, UINT8 pc_size, UINT8 byte_size )
+{
+ tms0980_state *cpustate = get_safe_token( device );
+
+ cpustate->config = (const tms0980_config *) device->static_config();
+
+ assert( cpustate->config != NULL );
+
+ cpustate->decode_table = decode_table;
+ cpustate->o_mask = o_mask;
+ cpustate->r_mask = r_mask;
+ cpustate->pc_size = pc_size;
+ cpustate->byte_size = byte_size;
+
+ cpustate->program = device->space( AS_PROGRAM );
+ cpustate->data = device->space( AS_PROGRAM );
+
+ device->save_item( NAME(cpustate->prev_pc) );
+ device->save_item( NAME(cpustate->prev_pa) );
+ device->save_item( NAME(cpustate->pc) );
+ device->save_item( NAME(cpustate->pa) );
+ device->save_item( NAME(cpustate->sr) );
+ device->save_item( NAME(cpustate->pb) );
+ device->save_item( NAME(cpustate->a) );
+ device->save_item( NAME(cpustate->x) );
+ device->save_item( NAME(cpustate->y) );
+ device->save_item( NAME(cpustate->dam) );
+ device->save_item( NAME(cpustate->ca) );
+ device->save_item( NAME(cpustate->cb) );
+ device->save_item( NAME(cpustate->cs) );
+ device->save_item( NAME(cpustate->r) );
+ device->save_item( NAME(cpustate->o) );
+ device->save_item( NAME(cpustate->cki_bus) );
+ device->save_item( NAME(cpustate->p) );
+ device->save_item( NAME(cpustate->n) );
+ device->save_item( NAME(cpustate->adder_result) );
+ device->save_item( NAME(cpustate->carry_in) );
+ device->save_item( NAME(cpustate->status) );
+ device->save_item( NAME(cpustate->status_latch) );
+ device->save_item( NAME(cpustate->special_status) );
+ device->save_item( NAME(cpustate->call_latch) );
+ device->save_item( NAME(cpustate->add_latch) );
+ device->save_item( NAME(cpustate->branch_latch) );
+ device->save_item( NAME(cpustate->subcycle) );
+ device->save_item( NAME(cpustate->ram_address) );
+ device->save_item( NAME(cpustate->ram_data) );
+ device->save_item( NAME(cpustate->rom_address) );
+ device->save_item( NAME(cpustate->opcode) );
+ device->save_item( NAME(cpustate->decode) );
+}
+
+
+static CPU_INIT( tms0980 )
+{
+ cpu_init_tms_common( device, tms0980_decode, 0x00ff, 0x07ff, 7, 9 );
+}
+
+
+static CPU_INIT( tms1000 )
+{
+ cpu_init_tms_common( device, tms1000_default_decode, 0x00ff, 0x07ff, 6, 8 );
+}
+
+
+static CPU_INIT( tms1070 )
+{
+ cpu_init_tms_common( device, tms1000_default_decode, 0x00ff, 0x07ff, 6, 8 );
+}
+
+
+static CPU_INIT( tms1200 )
+{
+ cpu_init_tms_common( device, tms1000_default_decode, 0x00ff, 0x1fff, 6, 8 );
+}
+
+
+static CPU_INIT( tms1270 )
+{
+ cpu_init_tms_common( device, tms1000_default_decode, 0x03ff, 0x1fff, 6, 8 );
+}
+
+
+static CPU_INIT( tms1100 )
+{
+ cpu_init_tms_common( device, tms1100_default_decode, 0x00ff, 0x07ff, 6, 8 );
+}
+
+
+static CPU_INIT( tms1300 )
+{
+ cpu_init_tms_common( device, tms1100_default_decode, 0x00ff, 0xffff, 6, 8 );
+}
+
+
+static CPU_RESET( tms0980 )
+{
+ tms0980_state *cpustate = get_safe_token( device );
+
+ cpustate->pa = 0x0F;
+ cpustate->pb = 0x0F;
+ cpustate->pc = 0;
+ cpustate->dam = 0;
+ cpustate->ca = 0;
+ cpustate->cb = 0;
+ cpustate->cs = 0;
+ cpustate->subcycle = 0;
+ cpustate->status = 1;
+ cpustate->status_latch = 0;
+ cpustate->call_latch = 0;
+ cpustate->add_latch = 0;
+ cpustate->branch_latch = 0;
+ cpustate->r = 0;
+ cpustate->o = 0;
+ cpustate->ram_address = 0;
+ cpustate->decode = F_ILL;
+ cpustate->opcode = 0;
+}
+
+
+/*
+The program counter is implemented using PRNG logic and gets incremented as follows:
+
+00, 01, 03, 07, 0F, 1F, 3F, 3E,
+3D, 3B, 37, 2F, 1E, 3C, 39, 33
+27, 0E, 1D, 3A, 35, 2B, 16, 2C,
+18, 30, 21, 02, 05, 0B, 17, 2E,
+1C, 38, 31, 23, 06, 0D, 1B, 36,
+2D, 1A, 34, 29, 12, 24, 08, 11,
+22, 04, 09, 13, 26, 0C, 19, 32,
+25, 0A, 15, 2A, 14, 28, 10, 20
+
+There is also a strange address (AD) to location (LOC) mapping performed by the
+tms1000 family.
+
+From tms1000 family pdf:
+AD LOC
+000 000000 003 000011
+001 000001 004 000100
+003 000011 00C 001100
+007 000111 01C 011100
+00F 001111 03C 111100
+01F 011111 03F 111111
+03F 111111 03E 111110
+03E 111110 039 111001
+03D 111101 036 110110
+03B 111011 02E 101110
+037 110111 01E 011110
+02F 101111 03D 111101
+01E 011110 038 111000
+03C 111100 031 110001
+039 111001 026 100110
+033 110011 00E 001110
+027 100111 01D 011101
+00E 001110 03B 111011
+01D 011101 037 110111
+03A 111010 029 101001
+035 110101 016 010110
+02B 101011 02D 101101
+016 010110 018 011000
+02C 101100 032 110010
+018 011000 020 100000
+030 110000 001 000001
+021 100001 005 000101
+002 000010 00B 001011
+005 000101 014 010100
+00B 001011 02C 101100
+017 010111 01F 011111
+02E 101110 03A 111010
+01C 011100 030 110000
+038 111000 021 100001
+031 110001 006 000110
+023 100011 00D 001101
+006 000110 01B 011011
+00D 001101 034 110100
+01B 011011 02F 101111
+036 110110 019 011001
+02D 101101 035 110101
+01A 011010 028 101000
+034 110100 011 010001
+029 101001 025 100101
+012 010010 008 001000
+024 100100 012 010010
+008 001000 023 100011
+011 010001 007 000111
+022 100010 00A 001010
+004 000100 013 010011
+009 001001 024 100100
+013 010011 00F 001111
+026 100110 01A 011010
+00C 001100 033 110011
+019 011001 027 100111
+032 110010 009 001001
+025 100101 015 010101
+00A 001010 02B 101011
+015 010101 017 010111
+02A 101010 02A 101010
+014 010100 010 010000
+028 101000 022 100010
+010 010000 000 000000
+020 100000 002 000010
+
+The following formula seems to be used to decode a program counter
+into a rom address:
+location{5:2} = pc{3:0}
+location{1:0} = ( pc{5:4} == 00 && pc{0} == 0 ) => 11
+ ( pc{5:4} == 00 && pc{0} == 1 ) => 00
+ ( pc{5:4} == 01 && pc{0} == 0 ) => 00
+ ( pc{5:4} == 01 && pc{0} == 1 ) => 11
+ ( pc{5:4} == 10 && pc{0} == 0 ) => 10
+ ( pc{5:4} == 10 && pc{0} == 1 ) => 01
+ ( pc{5:4} == 11 && pc{0} == 0 ) => 01
+ ( pc{5:4} == 11 && pc{0} == 1 ) => 10
+
+*/
+static const UINT8 tms1000_next_pc[64] = {
+ 0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0D, 0x0F, 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1D, 0x1F,
+ 0x20, 0x22, 0x24, 0x26, 0x28, 0x2A, 0x2C, 0x2E, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3A, 0x3C, 0x3F,
+ 0x00, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1C, 0x1E,
+ 0x21, 0x23, 0x25, 0x27, 0x29, 0x2B, 0x2D, 0x2F, 0x31, 0x33, 0x35, 0x37, 0x39, 0x3B, 0x3D, 0x3E,
+};
+
+/* emulator for the program counter increment on the tms0980/tmc0980 mcu;
+ see patent 4064554 figure 19 (on page 13) for an explanation of feedback:
+
+ nand324 = NAND of PC0 through pc4, i.e. output is true if ((pc&0x1f) != 0x1f)
+ nand323 = NAND of pc5, pc6 and nand324
+ i.e. output is true, if ((pc&0x1f)==0x1f) || pc5 is 0 || pc 6 is 0
+ or321 = OR of pc5 and pc6, i.e. output is true if ((pc&0x60) != 0)
+ nand322 = NAND of pc0 through pc5 plus /pc6,
+ i.e. output is true if (pc != 0x3f)
+ nand325 = nand pf nand323, or321 and nand322
+ This one is complex:
+ / or321 means if pc&0x60 is zero, output MUST be true
+ \ nand323 means if (pc&0x60=0x60) && (pc&0x1f != 0x1f), output MUST be true
+ nand322 means if pc = 0x3f, output MUST be true
+ hence, nand325 is if pc = 0x7f, false. if pc = 0x3f, true. if pc&0x60 is zero OR pc&0x60 is 0x60, true. otherwise, false.
+
+ tms0980_nect_pc below implements an indentical function to this in a somewhat more elegant way.
+*/
+INLINE void tms0980_next_pc( tms0980_state *cpustate )
+{
+ if ( cpustate->byte_size > 8 )
+ {
+ UINT8 xorval = ( cpustate->pc & 0x3F ) == 0x3F ? 1 : 0;
+ UINT8 new_bit = ( ( cpustate->pc ^ ( cpustate->pc << 1 ) ) & 0x40 ) ? xorval : 1 - xorval;
+
+ cpustate->pc = ( cpustate->pc << 1 ) | new_bit;
+ }
+ else
+ {
+ cpustate->pc = tms1000_next_pc[ cpustate->pc & 0x3f ];
+ }
+}
+
+
+static const UINT8 tms1000_pc_decode[64] =
+{
+ 0x03, 0x04, 0x0B, 0x0C, 0x13, 0x14, 0x1B, 0x1C,
+ 0x23, 0x24, 0x2B, 0x2C, 0x33, 0x34, 0x3B, 0x3C,
+ 0x00, 0x07, 0x08, 0x0F, 0x10, 0x17, 0x18, 0x1F,
+ 0x20, 0x27, 0x28, 0x2F, 0x30, 0x37, 0x38, 0x3F,
+ 0x02, 0x05, 0x0A, 0x0D, 0x12, 0x15, 0x1A, 0x1D,
+ 0x22, 0x25, 0x2A, 0x2D, 0x32, 0x35, 0x3A, 0x3D,
+ 0x01, 0x06, 0x09, 0x0E, 0x11, 0x16, 0x19, 0x1E,
+ 0x21, 0x26, 0x29, 0x2E, 0x31, 0x36, 0x39, 0x3E
+};
+
+
+static void tms0980_set_cki_bus( device_t *device )
+{
+ tms0980_state *cpustate = get_safe_token( device );
+
+ switch( cpustate->opcode & 0x1F8 )
+ {
+ case 0x008:
+ if ( cpustate->config->read_k )
+ {
+ cpustate->cki_bus = cpustate->config->read_k( device, 0 );
+ }
+ else
+ {
+ cpustate->cki_bus = 0x0F;
+ }
+ break;
+ case 0x020: case 0x028:
+ cpustate->cki_bus = 0;
+ break;
+ case 0x030: case 0x038:
+ cpustate->cki_bus = tms0980_nbit_value[ cpustate->opcode & 0x03 ];
+ break;
+ case 0x000:
+ case 0x040: case 0x048:
+ case 0x050: case 0x058:
+ case 0x060: case 0x068:
+ case 0x070: case 0x078:
+ case 0x080: case 0x088:
+ case 0x090: case 0x098:
+ case 0x0c0: case 0x0c8:
+ case 0x0d0: case 0x0d8:
+ case 0x0e0: case 0x0e8:
+ case 0x0f0: case 0x0f8:
+ cpustate->cki_bus = tms0980_c4_value[ cpustate->opcode & 0x0F ];
+ break;
+ default:
+ cpustate->cki_bus = 0x0F;
+ break;
+ }
+}
+
+
+static CPU_EXECUTE( tms0980 )
+{
+ tms0980_state *cpustate = get_safe_token( device );
+
+ do
+ {
+// debugger_instruction_hook( device, ( ( cpustate->pa << cpustate->pc_size ) | cpustate->pc ) << 1 );
+ cpustate->icount--;
+ switch( cpustate->subcycle )
+ {
+ case 0:
+ /* fetch: rom address 0 */
+ /* execute: read ram, alu input, execute br/call, k input valid */
+ tms0980_set_cki_bus( device );
+ cpustate->ram_data = cpustate->data->read_byte( cpustate->ram_address );
+ cpustate->status = 1;
+ cpustate->p = 0;
+ cpustate->n = 0;
+ cpustate->carry_in = 0;
+ break;
+ case 1:
+ /* fetch: rom address 1 */
+ if ( cpustate->pc_size == 6 )
+ cpustate->rom_address = ( cpustate->pa << 6 ) | tms1000_pc_decode[ cpustate->pc ];
+ else
+ cpustate->rom_address = ( cpustate->pa << 7 ) | cpustate->pc;
+ /* execute: k input valid */
+ if ( cpustate->decode & MICRO_MASK )
+ {
+ /* Check N inputs */
+ if ( cpustate->decode & ( M_15TN | M_ATN | M_CKN | M_MTN | M_NATN ) )
+ {
+ cpustate->n = 0;
+ if ( cpustate->decode & M_15TN )
+ {
+ cpustate->n |= 0x0F;
+ }
+ if ( cpustate->decode & M_ATN )
+ {
+ cpustate->n |= cpustate->a;
+ }
+ if ( cpustate->decode & M_CKN )
+ {
+ cpustate->n |= cpustate->cki_bus;
+ }
+ if ( cpustate->decode & M_MTN )
+ {
+ cpustate->n |= cpustate->ram_data;
+ }
+ if ( cpustate->decode & M_NATN )
+ {
+ cpustate->n |= ( ( ~cpustate->a ) & 0x0F );
+ }
+ }
+
+
+ /* Check P inputs */
+ if ( cpustate->decode & ( M_CKP | M_DMTP | M_MTP | M_NDMTP | M_YTP ) )
+ {
+ cpustate->p = 0;
+ if ( cpustate->decode & M_CKP )
+ {
+ cpustate->p |= cpustate->cki_bus;
+ }
+ if ( cpustate->decode & M_DMTP )
+ {
+ cpustate->p |= cpustate->dam;
+ }
+ if ( cpustate->decode & M_MTP )
+ {
+ cpustate->p |= cpustate->ram_data;
+ }
+ if ( cpustate->decode & M_NDMTP )
+ {
+ cpustate->p |= ( ( ~cpustate->dam ) & 0x0F );
+ }
+ if ( cpustate->decode & M_YTP )
+ {
+ cpustate->p |= cpustate->y;
+ }
+ }
+
+ /* Carry In input */
+ if ( cpustate->decode & M_CIN )
+ {
+ cpustate->carry_in = 1;
+ }
+ }
+ break;
+ case 2:
+ /* fetch: nothing */
+ /* execute: write ram */
+ /* perform adder logic */
+ cpustate->adder_result = cpustate->p + cpustate->n + cpustate->carry_in;
+ if ( cpustate->decode & MICRO_MASK )
+ {
+ if ( cpustate->decode & M_NE )
+ {
+ if ( cpustate->n == cpustate->p )
+ {
+ cpustate->status = 0;
+ }
+ }
+ if ( cpustate->decode & M_C8 )
+ {
+ cpustate->status = cpustate->adder_result >> 4;
+ }
+ if ( cpustate->decode & M_STO )
+ {
+ cpustate->data->write_byte( cpustate->ram_address, cpustate->a );
+ }
+ if ( cpustate->decode & M_CKM )
+ {
+ cpustate->data->write_byte( cpustate->ram_address, cpustate->cki_bus );
+ }
+ }
+ else
+ {
+ if ( cpustate->decode & F_SBIT )
+ {
+ cpustate->data->write_byte( cpustate->ram_address, cpustate->ram_data | tms0980_bit_value[ cpustate->opcode & 0x03 ] );
+ }
+ if ( cpustate->decode & F_RBIT )
+ {
+ cpustate->data->write_byte( cpustate->ram_address, cpustate->ram_data & tms0980_nbit_value[ cpustate->opcode & 0x03 ] );
+ }
+ if ( cpustate->decode & F_SETR )
+ {
+ cpustate->r = cpustate->r | ( 1 << cpustate->y );
+ if ( cpustate->config->write_r )
+ {
+ cpustate->config->write_r( device, 0, cpustate->r & cpustate->r_mask, 0xffff );
+ }
+ }
+ if ( cpustate->decode & F_RSTR )
+ {
+ cpustate->r = cpustate->r & ( ~( 1 << cpustate->y ) );
+ if ( cpustate->config->write_r )
+ {
+ cpustate->config->write_r( device, 0, cpustate->r & cpustate->r_mask, 0xffff );
+ }
+ }
+ if ( cpustate->decode & F_TDO )
+ {
+ int i = 0;
+
+ /* Calculate O-outputs based on status latch, A, and the output PLA configuration */
+ cpustate->o = 0;
+ for ( i = 0; i < 20; i++ )
+ {
+ if ( ( ( cpustate->status_latch << 4 ) | cpustate->a ) == cpustate->config->o_pla[i].value )
+ {
+ cpustate->o = cpustate->config->o_pla[i].output;
+ }
+ }
+
+ if ( cpustate->config->write_o )
+ {
+ cpustate->config->write_o( device, 0, cpustate->o & cpustate->o_mask, 0xffff );
+ }
+ }
+ if ( cpustate->decode & F_CLO )
+ {
+ cpustate->o = 0;
+ if ( cpustate->config->write_o )
+ {
+ cpustate->config->write_o( device, 0, cpustate->o & cpustate->o_mask, 0xffff );
+ }
+ }
+ if ( cpustate->decode & F_LDX )
+ {
+ cpustate->x = tms0980_c2_value[ cpustate->opcode & 0x03 ];
+ }
+ if ( cpustate->decode & F_COMX )
+ {
+ cpustate->x = cpustate->x ^ 0x03;
+ }
+ if ( cpustate->decode & F_COMC )
+ {
+ cpustate->cb = cpustate->cb ^ 0x01;
+ }
+ if ( cpustate->decode & F_LDP )
+ {
+ cpustate->pb = tms0980_c4_value[ cpustate->opcode & 0x0F ];
+ }
+ if ( cpustate->decode & F_REAC )
+ {
+ cpustate->special_status = 0;
+ }
+ if ( cpustate->decode & F_SEAC )
+ {
+ cpustate->special_status = 1;
+ }
+ if ( cpustate->decode == F_SAL )
+ {
+ cpustate->add_latch = 1;
+ }
+ if ( cpustate->decode == F_SBL )
+ {
+ cpustate->branch_latch = 1;
+ }
+ }
+ break;
+ case 3:
+ /* fetch: fetch, update pc, ram address */
+ /* execute: register store */
+ break;
+ case 4:
+ /* execute: register store */
+ if ( cpustate->decode & MICRO_MASK )
+ {
+ if ( cpustate->decode & M_AUTA )
+ {
+ cpustate->a = cpustate->adder_result & 0x0F;
+ }
+ if ( cpustate->decode & M_AUTY )
+ {
+ cpustate->y = cpustate->adder_result & 0x0F;
+ }
+ if ( cpustate->decode & M_STSL )
+ {
+ cpustate->status_latch = cpustate->status;
+ }
+ }
+ /* fetch: fetch, update pc, ram address */
+ if ( cpustate->byte_size > 8 )
+ {
+ debugger_instruction_hook( device, cpustate->rom_address << 1 );
+ cpustate->opcode = cpustate->program->read_word( cpustate->rom_address << 1 ) & 0x1FF;
+ }
+ else
+ {
+ debugger_instruction_hook( device, cpustate->rom_address );
+ cpustate->opcode = cpustate->program->read_word( cpustate->rom_address ) & 0xFF;
+ }
+ tms0980_next_pc( cpustate );
+ if (LOG)
+ logerror( "tms0980: read opcode %04x from %04x. Set pc to %04x\n", cpustate->opcode, cpustate->rom_address, cpustate->pc );
+
+ /* ram address */
+ cpustate->ram_address = ( cpustate->x << 4 ) | cpustate->y;
+ break;
+ case 5:
+ /* fetch: instruction decode */
+ cpustate->decode = cpustate->decode_table[ cpustate->opcode ];
+ /* execute: execute br/call */
+ if ( cpustate->status )
+ {
+ if ( cpustate->decode == F_BR )
+ {
+ if ( cpustate->call_latch == 0 )
+ {
+ cpustate->pa = cpustate->pb;
+ }
+ cpustate->pc = cpustate->opcode & ( ( 1 << cpustate->pc_size ) - 1 );
+ }
+ if ( cpustate->decode == F_CALL )
+ {
+ UINT8 t = cpustate->pa;
+ if ( cpustate->call_latch == 0 )
+ {
+ cpustate->sr = cpustate->pc;
+ cpustate->call_latch = 1;
+ cpustate->pa = cpustate->pb;
+ }
+ cpustate->pb = t;
+ cpustate->pc = cpustate->opcode & ( ( 1 << cpustate->pc_size ) - 1 );
+ }
+ }
+ if ( cpustate->decode == F_RETN )
+ {
+ if ( cpustate->call_latch == 1 )
+ {
+ cpustate->pc = cpustate->sr;
+ cpustate->call_latch = 0;
+ }
+ cpustate->add_latch = 0;
+ cpustate->pa = cpustate->pb;
+ } else {
+ cpustate->branch_latch = 0;
+ }
+ break;
+ }
+ cpustate->subcycle = ( cpustate->subcycle + 1 ) % 6;
+ } while( cpustate->icount > 0 );
+}
+
+
+static CPU_SET_INFO( tms0980 )
+{
+ tms0980_state *cpustate = get_safe_token( device );
+
+ switch( state )
+ {
+ case CPUINFO_INT_PC: cpustate->pc = ( info->i >> 1 ) & 0x7f; cpustate->pa = info->i >> 8; break;
+ case CPUINFO_INT_REGISTER + TMS0980_PC: cpustate->pc = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS0980_SR: cpustate->sr = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS0980_PA: cpustate->pa = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS0980_PB: cpustate->pb = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS0980_A: cpustate->a = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS0980_X: cpustate->x = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS0980_Y: cpustate->y = info->i; break;
+ case CPUINFO_INT_REGISTER + TMS0980_STATUS: cpustate->status = info->i; break;
+ }
+}
+
+
+static CPU_GET_INFO( tms_generic )
+{
+ tms0980_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch(state)
+ {
+ case CPUINFO_INT_CONTEXT_SIZE: info->i = sizeof(tms0980_state); break;
+ case CPUINFO_INT_INPUT_LINES: info->i = 1; break;
+ case DEVINFO_INT_ENDIANNESS: info->i = ENDIANNESS_BIG; break;
+ case CPUINFO_INT_CLOCK_MULTIPLIER: info->i = 1; break;
+ case CPUINFO_INT_CLOCK_DIVIDER: info->i = 1; break;
+ case CPUINFO_INT_MIN_CYCLES: info->i = 1; break;
+ case CPUINFO_INT_MAX_CYCLES: info->i = 6; break;
+
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_PROGRAM: info->i = 0; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_DATA: info->i = 8 /* 4 */; break;
+ case DEVINFO_INT_ADDRBUS_SHIFT + AS_DATA: info->i = 0; break;
+
+ case CPUINFO_INT_PREVIOUSPC: info->i = ( ( cpustate->prev_pa << 7 ) | cpustate->prev_pc ) << 1; break;
+ case CPUINFO_INT_PC: info->i = ( ( cpustate->pa << 7 ) | cpustate->pc ) << 1; break;
+ case CPUINFO_INT_SP: info->i = 0xFFFF; break;
+ case CPUINFO_INT_REGISTER + TMS0980_PC: info->i = cpustate->pc; break;
+ case CPUINFO_INT_REGISTER + TMS0980_SR: info->i = cpustate->sr; break;
+ case CPUINFO_INT_REGISTER + TMS0980_PA: info->i = cpustate->pa; break;
+ case CPUINFO_INT_REGISTER + TMS0980_PB: info->i = cpustate->pb; break;
+ case CPUINFO_INT_REGISTER + TMS0980_A: info->i = cpustate->a; break;
+ case CPUINFO_INT_REGISTER + TMS0980_X: info->i = cpustate->x; break;
+ case CPUINFO_INT_REGISTER + TMS0980_Y: info->i = cpustate->y; break;
+ case CPUINFO_INT_REGISTER + TMS0980_STATUS: info->i = cpustate->status; break;
+
+ case CPUINFO_FCT_SET_INFO: info->setinfo = CPU_SET_INFO_NAME( tms0980 ); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME( tms0980 ); break;
+ case CPUINFO_FCT_RESET: info->reset = CPU_RESET_NAME( tms0980 ); break;
+ case CPUINFO_FCT_EXECUTE: info->execute = CPU_EXECUTE_NAME( tms0980 ); break;
+ case CPUINFO_PTR_INSTRUCTION_COUNTER: info->icount = &cpustate->icount; break;
+
+ case DEVINFO_STR_FAMILY: strcpy( info->s, "Texas Instruments TMS0980/TMS1000" ); break;
+ case DEVINFO_STR_VERSION: strcpy( info->s, "0.2" ); break;
+ case DEVINFO_STR_SOURCE_FILE: strcpy( info->s, __FILE__ ); break;
+ case DEVINFO_STR_CREDITS: strcpy( info->s, "Copyright the MESS and MAME teams" ); break;
+
+ case CPUINFO_STR_FLAGS: strcpy( info->s, "N/A" ); break;
+
+ case CPUINFO_STR_REGISTER + TMS0980_PC: sprintf( info->s, "PC:%02X", cpustate->pc ); break;
+ case CPUINFO_STR_REGISTER + TMS0980_SR: sprintf( info->s, "SR:%01X", cpustate->sr ); break;
+ case CPUINFO_STR_REGISTER + TMS0980_PA: sprintf( info->s, "PA:%01X", cpustate->pa ); break;
+ case CPUINFO_STR_REGISTER + TMS0980_PB: sprintf( info->s, "PB:%01X", cpustate->pb ); break;
+ case CPUINFO_STR_REGISTER + TMS0980_A: sprintf( info->s, "A:%01X", cpustate->a ); break;
+ case CPUINFO_STR_REGISTER + TMS0980_X: sprintf( info->s, "X:%01X", cpustate->x ); break;
+ case CPUINFO_STR_REGISTER + TMS0980_Y: sprintf( info->s, "Y:%01X", cpustate->y ); break;
+ case CPUINFO_STR_REGISTER + TMS0980_STATUS: sprintf( info->s, "STATUS:%01X", cpustate->status ); break;
+
+ }
+}
+
+
+CPU_GET_INFO( tms0980 )
+{
+ tms0980_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch(state)
+ {
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 2; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 2; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 16 /* 9 */; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 12; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 7; break;
+ case CPUINFO_INT_PREVIOUSPC: info->i = ( ( cpustate->prev_pa << 7 ) | cpustate->prev_pc ) << 1; break;
+ case CPUINFO_INT_PC: info->i = ( ( cpustate->pa << 7 ) | cpustate->pc ) << 1; break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map16 = ADDRESS_MAP_NAME( tms0980_internal_rom ); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME( tms0980_internal_ram ); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME( tms0980 ); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME( tms0980 ); break;
+ case DEVINFO_STR_NAME: strcpy( info->s, "TMS0980" ); break;
+ default: CPU_GET_INFO_CALL( tms_generic );
+ }
+}
+
+
+CPU_GET_INFO( tms1000 )
+{
+ tms0980_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch(state)
+ {
+ case CPUINFO_INT_MIN_INSTRUCTION_BYTES: info->i = 1; break;
+ case CPUINFO_INT_MAX_INSTRUCTION_BYTES: info->i = 1; break;
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 10; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 6; break;
+ case CPUINFO_INT_PREVIOUSPC: info->i = ( cpustate->prev_pa << 6 ) | tms1000_pc_decode[ cpustate->prev_pc ]; break;
+ case CPUINFO_INT_PC: info->i = ( cpustate->pa << 6 ) | tms1000_pc_decode[ cpustate->pc ]; break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME( program_10bit_8 ); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME( data_6bit ); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME( tms1000 ); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME( tms1000 ); break;
+ case DEVINFO_STR_NAME: strcpy( info->s, "TMS1000" ); break;
+ default: CPU_GET_INFO_CALL( tms_generic );
+ }
+}
+
+
+CPU_GET_INFO( tms1070 )
+{
+ switch(state)
+ {
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME( tms1070 ); break;
+ case DEVINFO_STR_NAME: strcpy( info->s, "TMS1070" ); break;
+ default: CPU_GET_INFO_CALL( tms1000 );
+ }
+}
+
+
+CPU_GET_INFO( tms1200 )
+{
+ switch(state)
+ {
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME( tms1200 ); break;
+ case DEVINFO_STR_NAME: strcpy( info->s, "TMS1200" ); break;
+ default: CPU_GET_INFO_CALL( tms1000 );
+ }
+}
+
+
+CPU_GET_INFO( tms1270 )
+{
+ switch(state)
+ {
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME( tms1270 ); break;
+ case DEVINFO_STR_NAME: strcpy( info->s, "TMS1270" ); break;
+ default: CPU_GET_INFO_CALL( tms1000 );
+ }
+}
+
+
+
+CPU_GET_INFO( tms1100 )
+{
+ tms0980_state *cpustate = (device != NULL && device->token() != NULL) ? get_safe_token(device) : NULL;
+
+ switch(state)
+ {
+ case DEVINFO_INT_DATABUS_WIDTH + AS_PROGRAM: info->i = 8; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_PROGRAM: info->i = 11; break;
+ case DEVINFO_INT_ADDRBUS_WIDTH + AS_DATA: info->i = 7; break;
+ case CPUINFO_INT_PREVIOUSPC: info->i = ( cpustate->prev_pa << 6 ) | tms1000_pc_decode[ cpustate->prev_pc ]; break;
+ case CPUINFO_INT_PC: info->i = ( cpustate->pa << 6 ) | tms1000_pc_decode[ cpustate->pc ]; break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_PROGRAM: info->internal_map8 = ADDRESS_MAP_NAME( program_11bit_8 ); break;
+ case DEVINFO_PTR_INTERNAL_MEMORY_MAP + AS_DATA: info->internal_map8 = ADDRESS_MAP_NAME( data_7bit ); break;
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME( tms1100 ); break;
+ case CPUINFO_FCT_DISASSEMBLE: info->disassemble = CPU_DISASSEMBLE_NAME( tms1100 ); break;
+ case DEVINFO_STR_NAME: strcpy( info->s, "TMS1100" ); break;
+ default: CPU_GET_INFO_CALL( tms_generic );
+ }
+}
+
+
+CPU_GET_INFO( tms1300 )
+{
+ switch(state)
+ {
+ case CPUINFO_FCT_INIT: info->init = CPU_INIT_NAME( tms1300 ); break;
+ case DEVINFO_STR_NAME: strcpy( info->s, "TMS1300" ); break;
+ default: CPU_GET_INFO_CALL( tms1100 );
+ }
+}
+
+
+DEFINE_LEGACY_CPU_DEVICE(TMS0980, tms0980);
+
+DEFINE_LEGACY_CPU_DEVICE(TMS1000, tms1000);
+DEFINE_LEGACY_CPU_DEVICE(TMS1070, tms1070);
+DEFINE_LEGACY_CPU_DEVICE(TMS1100, tms1100);
+DEFINE_LEGACY_CPU_DEVICE(TMS1200, tms1200);
+DEFINE_LEGACY_CPU_DEVICE(TMS1270, tms1270);
+DEFINE_LEGACY_CPU_DEVICE(TMS1300, tms1300);