trunk/src/emu/cpu/tms0980/tms0980.c
| r242935 | r242936 | |
| 69 | 69 | */ |
| 70 | 70 | |
| 71 | 71 | /* Microinstructions */ |
| 72 | | #define M_15TN 0x00000001 /* 15 to -ALU */ |
| 73 | | #define M_ATN 0x00000002 /* ACC to -ALU */ |
| 74 | | #define M_AUTA 0x00000004 /* ALU to ACC */ |
| 75 | | #define M_AUTY 0x00000008 /* ALU to Y */ |
| 76 | | #define M_C8 0x00000010 /* CARRY8 to STATUS */ |
| 77 | | #define M_CIN 0x00000020 /* Carry In to ALU */ |
| 78 | | #define M_CKM 0x00000040 /* CKB to MEM */ |
| 79 | | #define M_CKN 0x00000080 /* CKB to -ALU */ |
| 80 | | #define M_CKP 0x00000100 /* CKB to +ALU */ |
| 81 | | #define M_MTN 0x00000200 /* MEM to -ALU */ |
| 82 | | #define M_MTP 0x00000400 /* MEM to +ALU */ |
| 83 | | #define M_NATN 0x00000800 /* ~ACC to -ALU */ |
| 84 | | #define M_NE 0x00001000 /* COMP to STATUS */ |
| 85 | | #define M_STO 0x00002000 /* ACC to MEM */ |
| 86 | | #define M_STSL 0x00004000 /* STATUS to Status Latch */ |
| 87 | | #define M_YTP 0x00008000 /* Y to +ALU */ |
| 72 | #define M_15TN (1<<0) /* 15 to -ALU */ |
| 73 | #define M_ATN (1<<1) /* ACC to -ALU */ |
| 74 | #define M_AUTA (1<<2) /* ALU to ACC */ |
| 75 | #define M_AUTY (1<<3) /* ALU to Y */ |
| 76 | #define M_C8 (1<<4) /* CARRY8 to STATUS */ |
| 77 | #define M_CIN (1<<5) /* Carry In to ALU */ |
| 78 | #define M_CKM (1<<6) /* CKB to MEM */ |
| 79 | #define M_CKN (1<<7) /* CKB to -ALU */ |
| 80 | #define M_CKP (1<<8) /* CKB to +ALU */ |
| 81 | #define M_MTN (1<<9) /* MEM to -ALU */ |
| 82 | #define M_MTP (1<<10) /* MEM to +ALU */ |
| 83 | #define M_NATN (1<<11) /* ~ACC to -ALU */ |
| 84 | #define M_NE (1<<12) /* COMP to STATUS */ |
| 85 | #define M_STO (1<<13) /* ACC to MEM */ |
| 86 | #define M_STSL (1<<14) /* STATUS to Status Latch */ |
| 87 | #define M_YTP (1<<15) /* Y to +ALU */ |
| 88 | 88 | |
| 89 | | #define M_CME 0x00010000 /* Conditional Memory Enable */ |
| 90 | | #define M_DMTP 0x00020000 /* DAM to +ALU */ |
| 91 | | #define M_NDMTP 0x00040000 /* ~DAM to +ALU */ |
| 92 | | #define M_SSE 0x00080000 /* Special Status Enable */ |
| 93 | | #define M_SSS 0x00100000 /* Special Status Sample */ |
| 89 | #define M_CME (1<<16) /* Conditional Memory Enable */ |
| 90 | #define M_DMTP (1<<17) /* DAM to +ALU */ |
| 91 | #define M_NDMTP (1<<18) /* ~DAM to +ALU */ |
| 92 | #define M_SSE (1<<19) /* Special Status Enable */ |
| 93 | #define M_SSS (1<<20) /* Special Status Sample */ |
| 94 | 94 | |
| 95 | | #define M_RSTR 0x00200000 /* -> line #36, F_RSTR (TMS02x0 custom) */ |
| 96 | | #define M_UNK1 0x00400000 /* -> line #37, F_???? (TMS0270 custom) */ |
| 95 | #define M_RSTR (1<<21) /* -> line #36, F_RSTR (TMS02x0 custom) */ |
| 96 | #define M_UNK1 (1<<22) /* -> line #37, F_???? (TMS0270 custom) */ |
| 97 | 97 | |
| 98 | 98 | /* Standard/fixed instructions - these are documented more in their specific handlers below */ |
| 99 | | #define F_BR 0x00000001 |
| 100 | | #define F_CALL 0x00000002 |
| 101 | | #define F_CLO 0x00000004 |
| 102 | | #define F_COMC 0x00000008 |
| 103 | | #define F_COMX 0x00000010 |
| 104 | | #define F_COMX8 0x00000020 |
| 105 | | #define F_LDP 0x00000040 |
| 106 | | #define F_LDX 0x00000080 |
| 107 | | #define F_RBIT 0x00000100 |
| 108 | | #define F_RETN 0x00000200 |
| 109 | | #define F_RSTR 0x00000400 |
| 110 | | #define F_SBIT 0x00000800 |
| 111 | | #define F_SETR 0x00001000 |
| 112 | | #define F_TDO 0x00002000 |
| 99 | #define F_BR (1<<0) |
| 100 | #define F_CALL (1<<1) |
| 101 | #define F_CLO (1<<2) |
| 102 | #define F_COMC (1<<3) |
| 103 | #define F_COMX (1<<4) |
| 104 | #define F_COMX8 (1<<5) |
| 105 | #define F_LDP (1<<6) |
| 106 | #define F_LDX (1<<7) |
| 107 | #define F_RBIT (1<<8) |
| 108 | #define F_RETN (1<<9) |
| 109 | #define F_RSTR (1<<10) |
| 110 | #define F_SBIT (1<<11) |
| 111 | #define F_SETR (1<<12) |
| 112 | #define F_TDO (1<<13) |
| 113 | #define F_TPC (1<<14) |
| 113 | 114 | |
| 114 | | #define F_OFF 0x00004000 |
| 115 | | #define F_REAC 0x00008000 |
| 116 | | #define F_SAL 0x00010000 |
| 117 | | #define F_SBL 0x00020000 |
| 118 | | #define F_SEAC 0x00040000 |
| 119 | | #define F_XDA 0x00080000 |
| 115 | #define F_OFF (1<<15) |
| 116 | #define F_REAC (1<<16) |
| 117 | #define F_SAL (1<<17) |
| 118 | #define F_SBL (1<<18) |
| 119 | #define F_SEAC (1<<19) |
| 120 | #define F_XDA (1<<20) |
| 120 | 121 | |
| 121 | 122 | |
| 122 | 123 | // supported types: |
| r242935 | r242936 | |
| 132 | 133 | // - 20-term output PLA(opla) at the top-left |
| 133 | 134 | // - the ALU is between the opla and mpla |
| 134 | 135 | const device_type TMS1000 = &device_creator<tms1000_cpu_device>; // 28-pin DIP, 11 R pins |
| 135 | | const device_type TMS1070 = &device_creator<tms1070_cpu_device>; // same as tms1000, just supports higher voltage |
| 136 | const device_type TMS1070 = &device_creator<tms1070_cpu_device>; // almost same as tms1000, just supports higher voltage |
| 136 | 137 | const device_type TMS1200 = &device_creator<tms1200_cpu_device>; // 40-pin DIP, 13 R pins |
| 137 | 138 | // TMS1270 has 10 O pins, how does that work? |
| 138 | 139 | |
| 139 | 140 | // TMS1100 is nearly the same as TMS1000, some different opcodes, and with double the RAM and ROM |
| 140 | 141 | const device_type TMS1100 = &device_creator<tms1100_cpu_device>; // 28-pin DIP, 11 R pins |
| 142 | const device_type TMS1170 = &device_creator<tms1170_cpu_device>; // almost same as tms1100, just supports higher voltage |
| 141 | 143 | const device_type TMS1300 = &device_creator<tms1300_cpu_device>; // 40-pin DIP, 16 R pins |
| 144 | const device_type TMS1370 = &device_creator<tms1370_cpu_device>; // almost same as tms1300, just supports higher voltage |
| 142 | 145 | |
| 146 | // TMS1400 follows the TMS1100, it doubles the ROM size again (4 chapters of 16 pages), and adds a 3-level callstack |
| 147 | // - rotate the view and mirror the OR-mask to get the proper layout of the mpla, the default is identical to tms1100 |
| 148 | // - the opla size is increased from 20 to 32 terms |
| 149 | const device_type TMS1400 = &device_creator<tms1400_cpu_device>; // 28-pin DIP, 11 R pins |
| 150 | const device_type TMS1470 = &device_creator<tms1470_cpu_device>; // almost same as tms1400, just supports higher voltage |
| 151 | |
| 143 | 152 | // TMS0980 |
| 144 | 153 | // - 64x9bit RAM array at the bottom-left (set up as 144x4) |
| 145 | 154 | // - 2048x9bit ROM array at the bottom-left |
| r242935 | r242936 | |
| 177 | 186 | AM_RANGE(0x000, 0x7ff) AM_ROM |
| 178 | 187 | ADDRESS_MAP_END |
| 179 | 188 | |
| 189 | static ADDRESS_MAP_START(program_12bit_8, AS_PROGRAM, 8, tms1xxx_cpu_device) |
| 190 | AM_RANGE(0x000, 0xfff) AM_ROM |
| 191 | ADDRESS_MAP_END |
| 180 | 192 | |
| 193 | |
| 181 | 194 | static ADDRESS_MAP_START(data_64x4, AS_DATA, 8, tms1xxx_cpu_device) |
| 182 | 195 | AM_RANGE(0x00, 0x3f) AM_RAM |
| 183 | 196 | ADDRESS_MAP_END |
| r242935 | r242936 | |
| 217 | 230 | : tms1000_cpu_device(mconfig, type, name, tag, owner, clock, o_pins, r_pins, pc_bits, byte_bits, x_bits, prgwidth, program, datawidth, data, shortname, source) |
| 218 | 231 | { } |
| 219 | 232 | |
| 233 | tms1170_cpu_device::tms1170_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 234 | : tms1100_cpu_device(mconfig, TMS1170, "TMS1170", tag, owner, clock, 8, 11, 6, 8, 3, 11, ADDRESS_MAP_NAME(program_11bit_8), 7, ADDRESS_MAP_NAME(data_128x4), "tms1170", __FILE__) |
| 235 | { } |
| 236 | |
| 220 | 237 | tms1300_cpu_device::tms1300_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 221 | | : tms1100_cpu_device(mconfig, TMS1300, "TMS1200", tag, owner, clock, 8, 16, 6, 8, 3, 11, ADDRESS_MAP_NAME(program_11bit_8), 7, ADDRESS_MAP_NAME(data_128x4), "tms1300", __FILE__) |
| 238 | : tms1100_cpu_device(mconfig, TMS1300, "TMS1300", tag, owner, clock, 8, 16, 6, 8, 3, 11, ADDRESS_MAP_NAME(program_11bit_8), 7, ADDRESS_MAP_NAME(data_128x4), "tms1300", __FILE__) |
| 222 | 239 | { } |
| 223 | 240 | |
| 241 | tms1370_cpu_device::tms1370_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 242 | : tms1100_cpu_device(mconfig, TMS1370, "TMS1370", tag, owner, clock, 8, 16, 6, 8, 3, 11, ADDRESS_MAP_NAME(program_11bit_8), 7, ADDRESS_MAP_NAME(data_128x4), "tms1370", __FILE__) |
| 243 | { } |
| 224 | 244 | |
| 245 | |
| 246 | tms1400_cpu_device::tms1400_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 247 | : tms1100_cpu_device(mconfig, TMS1400, "TMS1400", tag, owner, clock, 8, 11, 6, 8, 3, 12, ADDRESS_MAP_NAME(program_12bit_8), 7, ADDRESS_MAP_NAME(data_128x4), "tms1400", __FILE__) |
| 248 | { } |
| 249 | |
| 250 | tms1400_cpu_device::tms1400_cpu_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, UINT8 o_pins, UINT8 r_pins, UINT8 pc_bits, UINT8 byte_bits, UINT8 x_bits, int prgwidth, address_map_constructor program, int datawidth, address_map_constructor data, const char *shortname, const char *source) |
| 251 | : tms1100_cpu_device(mconfig, type, name, tag, owner, clock, o_pins, r_pins, pc_bits, byte_bits, x_bits, prgwidth, program, datawidth, data, shortname, source) |
| 252 | { } |
| 253 | |
| 254 | tms1470_cpu_device::tms1470_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 255 | : tms1400_cpu_device(mconfig, TMS1470, "TMS1470", tag, owner, clock, 8, 10, 6, 8, 3, 12, ADDRESS_MAP_NAME(program_12bit_8), 7, ADDRESS_MAP_NAME(data_128x4), "tms1470", __FILE__) |
| 256 | { } |
| 257 | |
| 258 | |
| 225 | 259 | tms0970_cpu_device::tms0970_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) |
| 226 | 260 | : tms1000_cpu_device(mconfig, TMS0970, "TMS0970", tag, owner, clock, 8, 11, 6, 8, 2, 10, ADDRESS_MAP_NAME(program_10bit_8), 6, ADDRESS_MAP_NAME(data_64x4), "tms0970", __FILE__) |
| 227 | 261 | { } |
| r242935 | r242936 | |
| 264 | 298 | } |
| 265 | 299 | |
| 266 | 300 | |
| 301 | static MACHINE_CONFIG_FRAGMENT(tms1400) |
| 302 | |
| 303 | // microinstructions PLA, output PLA |
| 304 | MCFG_PLA_ADD("mpla", 8, 16, 30) |
| 305 | MCFG_PLA_FILEFORMAT(PLA_FMT_BERKELEY) |
| 306 | MCFG_PLA_ADD("opla", 5, 8, 32) |
| 307 | MCFG_PLA_FILEFORMAT(PLA_FMT_BERKELEY) |
| 308 | MACHINE_CONFIG_END |
| 309 | |
| 310 | machine_config_constructor tms1400_cpu_device::device_mconfig_additions() const |
| 311 | { |
| 312 | return MACHINE_CONFIG_NAME(tms1400); |
| 313 | } |
| 314 | |
| 315 | |
| 267 | 316 | static MACHINE_CONFIG_FRAGMENT(tms0970) |
| 268 | 317 | |
| 269 | 318 | // main opcodes PLA, microinstructions PLA, output PLA, segment PLA |
| r242935 | r242936 | |
| 582 | 631 | for (int i = 0x3c; i < 0x40; i++) m_fixed_decode[i] = 0; |
| 583 | 632 | } |
| 584 | 633 | |
| 634 | void tms1400_cpu_device::device_reset() |
| 635 | { |
| 636 | tms1100_cpu_device::device_reset(); |
| 585 | 637 | |
| 638 | // small differences in 00-3f area |
| 639 | m_fixed_decode[0x09] = F_COMX; // ! |
| 640 | m_fixed_decode[0x0b] = F_TPC; |
| 641 | } |
| 642 | |
| 643 | |
| 586 | 644 | void tms0970_cpu_device::device_reset() |
| 587 | 645 | { |
| 588 | 646 | // common reset |
| r242935 | r242936 | |
| 899 | 957 | // fixed opcode set |
| 900 | 958 | //------------------------------------------------- |
| 901 | 959 | |
| 960 | // handle branches: |
| 961 | // note: add(latch) and bl(branch latch) are specific to 0980 series, |
| 962 | // c(chapter) bits are specific to 1100(and 1400) series |
| 963 | |
| 902 | 964 | // TMS1000/common: |
| 903 | 965 | |
| 966 | void tms1xxx_cpu_device::op_br() |
| 967 | { |
| 968 | // BR/BL: conditional branch |
| 969 | if (!m_status) |
| 970 | return; |
| 971 | |
| 972 | if (!m_clatch) |
| 973 | m_pa = m_pb; |
| 974 | m_ca = m_cb; |
| 975 | m_pc = m_opcode & m_pc_mask; |
| 976 | } |
| 977 | |
| 978 | void tms1xxx_cpu_device::op_call() |
| 979 | { |
| 980 | // CALL/CALLL: conditional call |
| 981 | if (!m_status) |
| 982 | return; |
| 983 | |
| 984 | UINT8 prev_pa = m_pa; |
| 985 | if (!m_clatch) |
| 986 | { |
| 987 | m_sr = m_pc; |
| 988 | m_clatch = 1; |
| 989 | m_pa = m_pb; |
| 990 | m_cs = m_ca; |
| 991 | } |
| 992 | m_ca = m_cb; |
| 993 | m_pb = prev_pa; |
| 994 | m_pc = m_opcode & m_pc_mask; |
| 995 | } |
| 996 | |
| 997 | void tms1xxx_cpu_device::op_retn() |
| 998 | { |
| 999 | // RETN: return from subroutine |
| 1000 | if (m_clatch) |
| 1001 | { |
| 1002 | m_pc = m_sr; |
| 1003 | m_clatch = 0; |
| 1004 | m_ca = m_cs; |
| 1005 | } |
| 1006 | m_add = 0; |
| 1007 | m_bl = 0; |
| 1008 | m_pa = m_pb; |
| 1009 | } |
| 1010 | |
| 1011 | |
| 1012 | // TMS1400-specific |
| 1013 | |
| 1014 | void tms1400_cpu_device::op_br() |
| 1015 | { |
| 1016 | // BR/BL: conditional branch |
| 1017 | if (!m_status) |
| 1018 | return; |
| 1019 | |
| 1020 | //.. |
| 1021 | } |
| 1022 | |
| 1023 | void tms1400_cpu_device::op_call() |
| 1024 | { |
| 1025 | // CALL/CALLL: conditional call |
| 1026 | if (!m_status) |
| 1027 | return; |
| 1028 | |
| 1029 | //.. |
| 1030 | } |
| 1031 | |
| 1032 | void tms1400_cpu_device::op_retn() |
| 1033 | { |
| 1034 | // RETN: return from subroutine |
| 1035 | //.. |
| 1036 | } |
| 1037 | |
| 1038 | |
| 1039 | // handle other: |
| 1040 | |
| 1041 | // TMS1000/common: |
| 1042 | |
| 904 | 1043 | void tms1xxx_cpu_device::op_sbit() |
| 905 | 1044 | { |
| 906 | 1045 | // SBIT: set memory bit |
| r242935 | r242936 | |
| 992 | 1131 | } |
| 993 | 1132 | |
| 994 | 1133 | |
| 1134 | // TMS1400-specific |
| 1135 | |
| 1136 | void tms1xxx_cpu_device::op_tpc() |
| 1137 | { |
| 1138 | // TPC: transfer page buffer to chapter buffer |
| 1139 | m_cb = m_pb & 3; |
| 1140 | } |
| 1141 | |
| 1142 | |
| 995 | 1143 | // TMS0970-specific (and possibly child classes) |
| 996 | 1144 | void tms0970_cpu_device::op_setr() |
| 997 | 1145 | { |
| r242935 | r242936 | |
| 1095 | 1243 | // fetch: rom address 1/2 |
| 1096 | 1244 | |
| 1097 | 1245 | // execute: br/call 2/2 |
| 1098 | | // note: add(latch) and bl(branch latch) are specific to 0980 series, |
| 1099 | | // c(chapter) bits are specific to 1100 series |
| 1100 | | if (m_status) |
| 1101 | | { |
| 1102 | | UINT8 new_pc = m_opcode & m_pc_mask; |
| 1246 | if (m_fixed & F_BR) op_br(); |
| 1247 | if (m_fixed & F_CALL) op_call(); |
| 1248 | if (m_fixed & F_RETN) op_retn(); |
| 1103 | 1249 | |
| 1104 | | // BR: conditional branch |
| 1105 | | if (m_fixed & F_BR) |
| 1106 | | { |
| 1107 | | if (m_clatch == 0) |
| 1108 | | m_pa = m_pb; |
| 1109 | | m_ca = m_cb; |
| 1110 | | m_pc = new_pc; |
| 1111 | | } |
| 1112 | | |
| 1113 | | // CALL: conditional call |
| 1114 | | if (m_fixed & F_CALL) |
| 1115 | | { |
| 1116 | | UINT8 prev_pa = m_pa; |
| 1117 | | if (m_clatch == 0) |
| 1118 | | { |
| 1119 | | m_sr = m_pc; |
| 1120 | | m_clatch = 1; |
| 1121 | | m_pa = m_pb; |
| 1122 | | m_cs = m_ca; |
| 1123 | | } |
| 1124 | | m_ca = m_cb; |
| 1125 | | m_pb = prev_pa; |
| 1126 | | m_pc = new_pc; |
| 1127 | | } |
| 1128 | | } |
| 1129 | | |
| 1130 | | // RETN: return from subroutine |
| 1131 | | if (m_fixed & F_RETN) |
| 1132 | | { |
| 1133 | | if (m_clatch == 1) |
| 1134 | | { |
| 1135 | | m_pc = m_sr; |
| 1136 | | m_clatch = 0; |
| 1137 | | m_ca = m_cs; |
| 1138 | | } |
| 1139 | | m_add = 0; |
| 1140 | | m_bl = 0; |
| 1141 | | m_pa = m_pb; |
| 1142 | | } |
| 1143 | | |
| 1144 | 1250 | // execute: k input valid, read ram, clear alu inputs |
| 1145 | 1251 | dynamic_output(); |
| 1146 | 1252 | set_cki_bus(); |
| r242935 | r242936 | |
| 1216 | 1322 | if (m_fixed & F_COMX8) op_comx8(); |
| 1217 | 1323 | if (m_fixed & F_LDP) op_ldp(); |
| 1218 | 1324 | if (m_fixed & F_COMC) op_comc(); |
| 1325 | if (m_fixed & F_TPC) op_tpc(); |
| 1219 | 1326 | if (m_fixed & F_OFF) op_off(); |
| 1220 | 1327 | if (m_fixed & F_SEAC) op_seac(); |
| 1221 | 1328 | if (m_fixed & F_REAC) op_reac(); |