1 // license:BSD-3-Clause
2 // copyright-holders:Michael Zapf
3 /*
4 Texas Instruments TMS9900
5
6 +--------------------+
7 V_BB | 1 o 64| /HOLD
8 V_CC | 2 63| /MEMEN
9 WAIT | 3 62| READY
10 /LOAD | 4 61| /WE
11 HOLDA | 5 60| CRUCLK
12 /RESET | 6 59| V_CC
13 IAQ | 7 58| -
14 PHI1 | 8 57| -
15 PHI2 | 9 56| D15 -+ LSB
16 LSB +- A14 |10 55| D14 |
17 | A13 |11 54| D13 |
18 | A12 |12 53| D12 |
19 | A11 |13 52| D11 |
20 Address | A10 |14 +--------+ 51| D10 | Data
21 bus | A9 |15 | | 50| D9 | bus
22 32K * | A8 |16 | | 49| D8 | 16 bit
23 16bit | A7 |17 | | 48| D7 |
24 | A6 |18 | | 47| D6 |
25 | A5 |19 +--------+ 46| D5 |
26 | A4 |20 45| D4 |
27 | A3 |21 44| D3 |
28 | A2 |22 43| D2 |
29 | A1 |23 42| D1 |
30 MSB +- A0 |24 41| D0 -+ MSB
31 PHI4 |25 40| V_SS
32 V_SS |26 39| -
33 V_DD |27 38| -
34 PHI3 |28 37| -
35 DBIN |29 36| IC0 -+ MSB
36 CRUOUT |30 35| IC1 | Interrupt
37 CRUIN |31 34| IC2 | level
38 /INTREQ |32 33| IC3 -+ LSB
39 +--------------------+
40
41 WAIT out Processor in wait state
42 /LOAD in Non-maskable interrupt
43 HOLDA out Hold acknowledge
44 /RESET in Reset
45 IAQ out Instruction acquisition
46 PHI1-4 in Clock phase inputs
47 DBIN out Data bus in input mode
48 CRUOUT out Communication register unit data output
49 CRUIN in Communication register unit data input
50 /INTREQ in Interrupt request
51 CRUCLK out Communication register unit clock output
52 /WE out Data available for memory write
53 READY in Memory ready for access
54 /MEMEN out Address bus contains memory address
55 /HOLD in External device acquires address and data bus lines
56
57 V_BB -5V supply
58 V_CC +5V supply (pins 2 and 59 connected in parallel)
59 V_DD +12V supply
60 V_SS 0V Ground reference (pins 26 and 40 connected in parallel)
61
62 A0-A14 out Address bus (32768 words of 16 bit width)
63 D0-A15 i/o Data bus
64 IC0-IC3 in Interrupt level (0-15)
65
66 Note that Texas Instruments' bit numberings define bit 0 as the
67 most significant bit (different to most other systems). Also, the
68 system uses big-endian memory organisation: Storing the word 0x1234 at
69 address 0x0000 means that the byte 0x12 is stored at 0x0000 and byte 0x34
70 is stored at 0x0001.
71
72 The processor also knows byte-oriented operations (like add byte (AB),
73 move byte (MOVB)). This makes it necessary for the CPU to read the word
74 from the target memory location first, change the respective byte, and
75 write it back.
76
77 See the TI-99/4A driver for an application of the TMS9900 processor
78 within an 8-bit data bus board layout (using a data bus multiplexer).
79
80 Subcycle handling
81
82 In this implementation we try to emulate the internal operations as
83 precisely as possible, following the technical specifications. We need
84 not try to be clock-precise with every tick; it suffices to perform
85 the proper number of operations within a given time span.
86
87 For each command the CPU executes a microprogram which requires some
88 amount of cycles to complete. During this time the external clock continues
89 to issue pulses which can be used to control wait state creation. As we
90 do not emulate external clocks this implementation offers an extra output
91 "clock_out" (which, however, is available for the TMS9995) which pulses
92 at a rate of 3 MHz. External devices (e.g. memory controllers) may count
93 the pulses and pull down the READY line (with set_ready) as needed.
94
95 Another possibility for creating wait states is to pull down the line
96 for some time set by a timer. This is done, for example, by circuits like
97 GROMs or speech synthesis processors (TMS52xx).
98
99 Michael Zapf, June 2012
100 */
101
102 #include "emu.h"
103 #include "tms9900.h"
104 #include "9900dasm.h"
105
106 #define NOPRG -1
107
108 constexpr int tms99xx_device::AS_SETADDRESS;
109
110 /* tms9900 ST register bits. */
111 enum
112 {
113 ST_LH = 0x8000, // Logical higher (unsigned comparison)
114 ST_AGT = 0x4000, // Arithmetical greater than (signed comparison)
115 ST_EQ = 0x2000, // Equal
116 ST_C = 0x1000, // Carry
117 ST_OV = 0x0800, // Overflow (when using signed operations)
118 ST_OP = 0x0400, // Odd parity (used with byte operations)
119 ST_X = 0x0200, // XOP
120 ST_IM = 0x000f // Interrupt mask
121 };
122
123 /*
124 The following defines can be set to 0 or 1 to disable or enable certain
125 output in the log.
126 */
127 #define LOG_OP (1U<<1) // Current instruction
128 #define LOG_EXEC (1U<<2) // Address of current instruction
129 #define LOG_CYCLES (1U<<4) // Cycles
130 #define LOG_WARN (1U<<5) // Illegal operation or other condition
131 #define LOG_MEM (1U<<6) // Memory access
132 #define LOG_CONTEXT (1U<<7) // Context switch
133 #define LOG_INT (1U<<8) // Interrupts
134 #define LOG_READY (1U<<9) // READY line input
135 #define LOG_CLOCK (1U<<10) // Clock pulses
136 #define LOG_ADDRESSBUS (1U<<11) // Address bus operation
137 #define LOG_STATUS (1U<<12) // Status register
138 #define LOG_CRU (1U<<13) // CRU operations
139 #define LOG_WAIT (1U<<15) // Wait states
140 #define LOG_HOLD (1U<<16) // Hold states
141 #define LOG_IDLE (1U<<17) // Idle states
142 #define LOG_EMU (1U<<18) // Emulation details
143 #define LOG_MICRO (1U<<19) // Microinstruction processing
144 #define LOG_INTD (1U<<20) // Interrupts (detailed phases)
145 #define LOG_LOAD (1U<<21) // LOAD interrupt
146 #define LOG_DETAIL (1U<<31) // Increased detail
147
148 // Minimum log should be warnings
149 #define VERBOSE ( LOG_GENERAL | LOG_WARN )
150
151 #include "logmacro.h"
152
153 /****************************************************************************
154 Common constructor for TMS9900 and TMS9980A
155 The CRU mask is related to the bits, not to their addresses which are
156 twice their number. Accordingly, the TMS9900 has a CRU bitmask 0x0fff.
157 ****************************************************************************/
158
tms99xx_device(const machine_config & mconfig,device_type type,const char * tag,int data_width,int prg_addr_bits,int cru_addr_bits,device_t * owner,uint32_t clock)159 tms99xx_device::tms99xx_device(const machine_config &mconfig, device_type type, const char *tag, int data_width, int prg_addr_bits, int cru_addr_bits, device_t *owner, uint32_t clock)
160 : cpu_device(mconfig, type, tag, owner, clock),
161 m_program_config("program", ENDIANNESS_BIG, data_width, prg_addr_bits),
162 m_setaddress_config("setaddress", ENDIANNESS_BIG, data_width, prg_addr_bits), // choose the same width as the program space
163 m_io_config("cru", ENDIANNESS_LITTLE, 8, cru_addr_bits + 1, 1),
164 m_prgspace(nullptr),
165 m_cru(nullptr),
166 m_prgaddr_mask((1<<prg_addr_bits)-2), // fffe for 16 bits, 3ffe for 14 bits (only even addresses)
167 m_cruaddr_mask((2<<cru_addr_bits)-2), // Address is shifted left by one
168 m_iaq(false),
169 m_clock_out_line(*this),
170 m_wait_line(*this),
171 m_holda_line(*this),
172 m_get_intlevel(*this),
173 m_external_operation(*this),
174 m_ready_bufd(true),
175 m_program_index(NOPRG),
176 m_caller_index(NOPRG)
177 {
178 }
179
~tms99xx_device()180 tms99xx_device::~tms99xx_device()
181 {
182 }
183
184 /****************************************************************************
185 Constructor for TMS9900
186 ****************************************************************************/
187
tms9900_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)188 tms9900_device::tms9900_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
189 : tms99xx_device(mconfig, TMS9900, tag, 16, 16, 12, owner, clock)
190 {
191 }
192
193 enum
194 {
195 TMS9900_PC=0, TMS9900_WP, TMS9900_STATUS, TMS9900_IR,
196 TMS9900_R0, TMS9900_R1, TMS9900_R2, TMS9900_R3,
197 TMS9900_R4, TMS9900_R5, TMS9900_R6, TMS9900_R7,
198 TMS9900_R8, TMS9900_R9, TMS9900_R10, TMS9900_R11,
199 TMS9900_R12, TMS9900_R13, TMS9900_R14, TMS9900_R15
200 };
201
device_start()202 void tms99xx_device::device_start()
203 {
204 // TODO: Restore state save feature
205 resolve_lines();
206 m_prgspace = &space(AS_PROGRAM);
207 m_setaddr = has_space(AS_SETADDRESS) ? &space(AS_SETADDRESS) : nullptr;
208 m_cru = &space(AS_IO);
209
210 // set our instruction counter
211 set_icountptr(m_icount);
212
213 m_state_any = 0;
214 PC = 0;
215 m_hold_state = false;
216
217 // add the states for the debugger
218 for (int i=0; i < 20; i++)
219 {
220 // callimport = need to use the state_import method to write to the state variable
221 // callexport = need to use the state_export method to read the state variable
222 state_add(i, s_statename[i], m_state_any).callimport().callexport().formatstr("%04X");
223 }
224 state_add(STATE_GENPC, "GENPC", PC).formatstr("%4s").noshow();
225 state_add(STATE_GENPCBASE, "CURPC", PC).formatstr("%4s").noshow();
226 state_add(STATE_GENFLAGS, "status", m_state_any).callimport().callexport().formatstr("%16s").noshow();
227
228 build_command_lookup_table();
229
230 // Register persistable state variables
231 save_item(NAME(m_icount));
232 save_item(NAME(WP));
233 save_item(NAME(PC));
234 save_item(NAME(ST));
235 save_item(NAME(IR));
236 save_item(NAME(m_address));
237 save_item(NAME(m_current_value));
238 save_item(NAME(m_command));
239 save_item(NAME(m_byteop));
240 save_item(NAME(m_pass));
241 save_item(NAME(m_check_ready));
242 save_item(NAME(m_mem_phase));
243 save_item(NAME(m_load_state));
244 save_item(NAME(m_irq_state));
245 save_item(NAME(m_log_interrupt));
246 save_item(NAME(m_reset));
247 save_item(NAME(m_irq_level));
248 // save_item(NAME(m_first_cycle)); // only for log output
249 save_item(NAME(m_idle_state));
250 save_item(NAME(m_ready_bufd));
251 save_item(NAME(m_ready));
252 save_item(NAME(m_wait_state));
253 save_item(NAME(m_hold_state));
254 // save_item(NAME(m_state_any)); // only for debugger output
255 save_item(NAME(MPC));
256 save_item(NAME(m_program_index));
257 save_item(NAME(m_caller_index));
258 save_item(NAME(m_caller_MPC));
259 save_item(NAME(m_state));
260 save_item(NAME(m_hold_acknowledged));
261 save_item(NAME(m_source_even));
262 save_item(NAME(m_destination_even));
263 save_item(NAME(m_source_address));
264 save_item(NAME(m_source_value));
265 save_item(NAME(m_address_saved));
266 save_item(NAME(m_address_copy));
267 save_item(NAME(m_register_contents));
268 save_item(NAME(m_regnumber));
269 save_item(NAME(m_cru_address));
270 save_item(NAME(m_count));
271 save_item(NAME(m_value_copy));
272 save_item(NAME(m_value));
273 save_item(NAME(m_get_destination));
274 }
275
device_stop()276 void tms99xx_device::device_stop()
277 {
278 }
279
280 /*
281 External connections
282 */
resolve_lines()283 void tms99xx_device::resolve_lines()
284 {
285 // Resolve our external connections
286 m_external_operation.resolve();
287 m_get_intlevel.resolve();
288 m_clock_out_line.resolve();
289 m_wait_line.resolve();
290 m_holda_line.resolve();
291 }
292
293 /*
294 TMS9900 hard reset
295 The device reset is just the emulator's trigger for the reset procedure
296 which is invoked via the main loop.
297 */
device_reset()298 void tms99xx_device::device_reset()
299 {
300 LOGMASKED(LOG_EMU, "Device reset by emulator\n");
301 m_reset = true;
302 m_check_ready = false;
303 m_wait_state = false;
304 ST = 0;
305 m_irq_state = false;
306 m_log_interrupt = false; // only for debugging
307 }
308
309 char const *const tms99xx_device::s_statename[20] =
310 {
311 "PC", "WP", "ST", "IR",
312 "R0", "R1", "R2", "R3",
313 "R4", "R5", "R6", "R7",
314 "R8", "R9", "R10","R11",
315 "R12","R13","R14","R15"
316 };
317
318 /*
319 Write the contents of a register by external input (debugger)
320 */
state_import(const device_state_entry & entry)321 void tms99xx_device::state_import(const device_state_entry &entry)
322 {
323 int index = entry.index();
324 switch (entry.index())
325 {
326 case STATE_GENFLAGS:
327 // no action here; we do not allow import, as the flags are all
328 // bits of the STATUS register
329 break;
330 case TMS9900_PC:
331 PC = (uint16_t)(m_state_any & m_prgaddr_mask);
332 break;
333 case TMS9900_WP:
334 WP = (uint16_t)(m_state_any & m_prgaddr_mask);
335 break;
336 case TMS9900_STATUS:
337 ST = (uint16_t)m_state_any;
338 break;
339 case TMS9900_IR:
340 IR = (uint16_t)m_state_any;
341 break;
342 default:
343 // Workspace registers
344 if (index <= TMS9900_R15)
345 write_workspace_register_debug(index-TMS9900_R0, (uint16_t)m_state_any);
346 break;
347 }
348 }
349
350 /*
351 Reads the contents of a register for display in the debugger.
352 */
state_export(const device_state_entry & entry)353 void tms99xx_device::state_export(const device_state_entry &entry)
354 {
355 int index = entry.index();
356 switch (entry.index())
357 {
358 case STATE_GENFLAGS:
359 m_state_any = ST;
360 break;
361 case TMS9900_PC:
362 m_state_any = PC;
363 break;
364 case TMS9900_WP:
365 m_state_any = WP;
366 break;
367 case TMS9900_STATUS:
368 m_state_any = ST;
369 break;
370 case TMS9900_IR:
371 m_state_any = IR;
372 break;
373 default:
374 // Workspace registers
375 if (index <= TMS9900_R15)
376 m_state_any = read_workspace_register_debug(index-TMS9900_R0);
377 break;
378 }
379 }
380
381 /*
382 state_string_export - export state as a string for the debugger
383 */
state_string_export(const device_state_entry & entry,std::string & str) const384 void tms99xx_device::state_string_export(const device_state_entry &entry, std::string &str) const
385 {
386 static char const statestr[] = "LAECOPX-----IIII";
387 char flags[17];
388 for (auto &flag : flags) flag = 0x00;
389 uint16_t val = 0x8000;
390 if (entry.index()==STATE_GENFLAGS)
391 {
392 for (int i=0; i < 16; i++)
393 {
394 flags[i] = ((val & ST)!=0)? statestr[i] : '.';
395 val = (val >> 1) & 0x7fff;
396 }
397 }
398 str.assign(flags);
399 }
400
401 /**************************************************************************/
402
read_workspace_register_debug(int reg)403 uint16_t tms99xx_device::read_workspace_register_debug(int reg)
404 {
405 int temp = m_icount;
406 auto dis = machine().disable_side_effects();
407 uint16_t value = m_prgspace->read_word((WP+(reg<<1)) & m_prgaddr_mask);
408 m_icount = temp;
409 return value;
410 }
411
write_workspace_register_debug(int reg,uint16_t data)412 void tms99xx_device::write_workspace_register_debug(int reg, uint16_t data)
413 {
414 int temp = m_icount;
415 auto dis = machine().disable_side_effects();
416 m_prgspace->write_word((WP+(reg<<1)) & m_prgaddr_mask, data);
417 m_icount = temp;
418 }
419
420 /*
421 The setaddress space is used to implement a split-phase memory access
422 where the address bus is first set, then the CPU samples the READY line,
423 (when low, enters wait states,) then the CPU reads the address bus. For
424 writing, setting the address and setting the data bus is done in direct
425 succession.
426
427 It is an optional feature, where drivers may connect to this space to
428 make use of it, or to completely ignore it when there is no need for
429 waitstate control.
430
431 In order to allow for using address maps, the setaddress space shows the
432 same widths as the normal program space. Its values are the levels of
433 certains lines that are set or reset during the memory access, in
434 particular DBIN and IAQ.
435 */
memory_space_config() const436 device_memory_interface::space_config_vector tms99xx_device::memory_space_config() const
437 {
438 if (has_configured_map(AS_SETADDRESS))
439 return space_config_vector {
440 std::make_pair(AS_PROGRAM, &m_program_config),
441 std::make_pair(AS_SETADDRESS, &m_setaddress_config),
442 std::make_pair(AS_IO, &m_io_config)
443 };
444 else
445 return space_config_vector {
446 std::make_pair(AS_PROGRAM, &m_program_config),
447 std::make_pair(AS_IO, &m_io_config)
448 };
449 }
450
451 /**************************************************************************
452 Microprograms for the CPU instructions
453
454 The actions which are specific to the respective instruction are
455 invoked by repeated calls of ALU_xxx; each call increases a state
456 variable so that on the next call, the next part can be processed.
457 This saves us a lot of additional functions.
458 **************************************************************************/
459
460 /*
461 Define the indices for the micro-operation table. This is done for the sake
462 of a simpler microprogram definition as an uint8_t[].
463 */
464 enum
465 {
466 IAQ = 0,
467 MEMORY_READ,
468 MEMORY_WRITE,
469 REG_READ,
470 REG_WRITE,
471 CRU_INPUT,
472 CRU_OUTPUT,
473 DATA_DERIVE,
474 RET,
475 ABORT,
476 END,
477
478 ALU_NOP,
479 ALU_CLR,
480 ALU_SETADDR,
481 ALU_ADDONE,
482 ALU_SETADDR_ADDONE,
483 ALU_PCADDR_ADVANCE,
484 ALU_SOURCE,
485 ALU_ADDREG,
486 ALU_IMM,
487 ALU_REG,
488 ALU_F1,
489 ALU_COMP,
490 ALU_F3,
491 ALU_MPY,
492 ALU_DIV,
493 ALU_XOP,
494 ALU_CLR_SWPB,
495 ALU_ABS,
496 ALU_X,
497 ALU_B,
498 ALU_BLWP,
499 ALU_LDCR,
500 ALU_STCR,
501 ALU_SBZ_SBO,
502 ALU_TB,
503 ALU_JMP,
504 ALU_SHIFT,
505 ALU_AI_ORI,
506 ALU_CI,
507 ALU_LI,
508 ALU_LWPI,
509 ALU_LIMI,
510 ALU_STWP_STST,
511 ALU_EXT,
512 ALU_RTWP,
513 ALU_INT
514 };
515
516
517 #define MICROPROGRAM(_MP) \
518 static const uint8_t _MP[] =
519
520 /*
521 This is a kind of subroutine with 6 variants. Might be done in countless
522 better ways, but will suffice for now. Each variant has at most 8 steps
523 RET will return to the caller.
524 The padding simplifies the calculation of the start address: We just
525 take the Ts field as an index. In the last two cases we add an offset of 8
526 if we have an indexed (resp. a byte) operation.
527 */
MICROPROGRAM(data_derivation)528 MICROPROGRAM(data_derivation)
529 {
530 REG_READ, RET, 0, 0, 0, 0, 0, 0, // Rx (00)
531 0, 0, 0, 0, 0, 0, 0, 0,
532 REG_READ, ALU_SETADDR, MEMORY_READ, RET, 0, 0, 0, 0, // *Rx (01)
533 0, 0, 0, 0, 0, 0, 0, 0,
534 ALU_CLR, ALU_PCADDR_ADVANCE, MEMORY_READ, ALU_ADDREG, MEMORY_READ, RET, 0, 0, // @sym (10)
535 REG_READ, ALU_PCADDR_ADVANCE, MEMORY_READ, ALU_ADDREG, MEMORY_READ, RET, 0, 0, // @sym(Rx) (10)
536 REG_READ, ALU_SETADDR_ADDONE, ALU_ADDONE, REG_WRITE, MEMORY_READ, RET, 0, 0, // *Rx+ (word) (11)
537 REG_READ, ALU_SETADDR_ADDONE, REG_WRITE, MEMORY_READ, RET, 0, 0, 0 // *Rx+ (byte) (11)
538 };
539
MICROPROGRAM(f1_mp)540 MICROPROGRAM(f1_mp)
541 {
542 ALU_NOP,
543 DATA_DERIVE,
544 ALU_SOURCE, // Store the word
545 DATA_DERIVE,
546 ALU_F1,
547 MEMORY_WRITE,
548 END
549 };
550
MICROPROGRAM(comp_mp)551 MICROPROGRAM(comp_mp)
552 {
553 ALU_NOP,
554 DATA_DERIVE,
555 ALU_SOURCE,
556 DATA_DERIVE,
557 ALU_COMP,
558 ALU_NOP, // Compare operations do not write back any data
559 END
560 };
561
MICROPROGRAM(f3_mp)562 MICROPROGRAM(f3_mp)
563 {
564 ALU_NOP,
565 DATA_DERIVE,
566 ALU_F3,
567 MEMORY_READ, // We have to distinguish this from the C/CB microprogram above
568 ALU_F3,
569 ALU_NOP, // Compare operations do not write back any data
570 END
571 };
572
MICROPROGRAM(xor_mp)573 MICROPROGRAM(xor_mp)
574 {
575 ALU_NOP,
576 DATA_DERIVE,
577 ALU_F3,
578 MEMORY_READ,
579 ALU_F3,
580 MEMORY_WRITE, // XOR again must write back data, cannot reuse f3_mp
581 END
582 };
583
MICROPROGRAM(mult_mp)584 MICROPROGRAM(mult_mp)
585 {
586 ALU_NOP,
587 DATA_DERIVE,
588 ALU_MPY, // Save the value; put register number in m_regnumber
589 MEMORY_READ,
590 ALU_MPY, // 18 cycles for multiplication
591 MEMORY_WRITE, // Write the high word
592 ALU_MPY, // Get low word, increase m_address
593 MEMORY_WRITE,
594 END
595 };
596
MICROPROGRAM(div_mp)597 MICROPROGRAM(div_mp)
598 {
599 ALU_NOP,
600 DATA_DERIVE, // Get divisor
601 ALU_DIV, // 0 Store divisor and get register number
602 MEMORY_READ, // Read register
603 ALU_DIV, // 1 Check overflow, increase address (or abort here)
604 ABORT,
605 MEMORY_READ, // Read subsequent word (if reg=15 this is behind the workspace)
606 ALU_DIV, // 2 Calculate quotient (takes variable amount of cycles; at least 32 machine cycles), set register number
607 MEMORY_WRITE, // Write quotient into register
608 ALU_DIV, // 3 Get remainder
609 MEMORY_WRITE, // Write remainder
610 END
611 };
612
MICROPROGRAM(xop_mp)613 MICROPROGRAM(xop_mp)
614 {
615 ALU_NOP,
616 DATA_DERIVE, // Get argument
617 ALU_XOP, // 0 Save the address of the source operand, set address = 0x0040 + xopNr*4, 6 cycles
618 MEMORY_READ, // Read the new WP
619 ALU_XOP, // 1 Save old WP, set new WP, get the source operand address
620 MEMORY_WRITE, // Write the address of the source operand into the new R11
621 ALU_XOP, // 2
622 MEMORY_WRITE, // Write the ST into the new R15
623 ALU_XOP, // 3
624 MEMORY_WRITE, // Write the PC into the new R14
625 ALU_XOP, // 4
626 MEMORY_WRITE, // Write the WP into the new R13
627 ALU_XOP, // 5 Set the X bit in the ST
628 MEMORY_READ, // Read the new PC
629 ALU_XOP, // 6 Set the new PC
630 END
631 };
632
MICROPROGRAM(clr_swpb_mp)633 MICROPROGRAM(clr_swpb_mp)
634 {
635 ALU_NOP,
636 DATA_DERIVE,
637 ALU_CLR_SWPB,
638 MEMORY_WRITE,
639 END
640 };
641
MICROPROGRAM(abs_mp)642 MICROPROGRAM(abs_mp)
643 {
644 ALU_NOP,
645 DATA_DERIVE,
646 ALU_ABS, // two cycles
647 MEMORY_WRITE, // skipped when ABS is not performed
648 ALU_NOP,
649 END
650 };
651
MICROPROGRAM(x_mp)652 MICROPROGRAM(x_mp)
653 {
654 ALU_NOP,
655 DATA_DERIVE,
656 ALU_X,
657 END
658 };
659
MICROPROGRAM(b_mp)660 MICROPROGRAM(b_mp) // Branch
661 {
662 ALU_NOP,
663 DATA_DERIVE,
664 ALU_B,
665 END
666 };
667
MICROPROGRAM(bl_mp)668 MICROPROGRAM(bl_mp) // Branch and Link
669 {
670 ALU_NOP,
671 DATA_DERIVE,
672 ALU_B,
673 ALU_NOP,
674 MEMORY_WRITE,
675 END
676 };
677
MICROPROGRAM(blwp_mp)678 MICROPROGRAM(blwp_mp) // Branch and Load WP
679 {
680 ALU_NOP,
681 DATA_DERIVE, // Get argument
682 ALU_BLWP, // 0 Save old WP, set new WP, save position
683 ALU_NOP,
684 MEMORY_WRITE, // write ST to R15
685 ALU_BLWP, // 1
686 MEMORY_WRITE, // write PC to R14
687 ALU_BLWP, // 2
688 MEMORY_WRITE, // write WP to R13
689 ALU_BLWP, // 3 Get saved position
690 MEMORY_READ, // Read new PC
691 ALU_BLWP, // 4 Set new PC
692 END
693 };
694
MICROPROGRAM(ldcr_mp)695 MICROPROGRAM(ldcr_mp)
696 {
697 ALU_NOP,
698 DATA_DERIVE,
699 ALU_SOURCE,
700 ALU_NOP,
701 ALU_LDCR,
702 ALU_NOP,
703 MEMORY_READ,
704 ALU_LDCR,
705 CRU_OUTPUT,
706 ALU_NOP,
707 END
708 };
709
MICROPROGRAM(stcr_mp)710 MICROPROGRAM(stcr_mp)
711 {
712 ALU_NOP,
713 DATA_DERIVE,
714 ALU_SOURCE, // Store address and value
715 ALU_STCR, // 0 Set register_number = 12; 0 cycles (already done before)
716 MEMORY_READ,
717 ALU_STCR, // 1 Prepare CRU access
718 ALU_NOP,
719 CRU_INPUT,
720 ALU_STCR, // 2 Create result; Cycles = 5 + (8-#C-1) or + (16-#C)
721 ALU_NOP,
722 ALU_NOP,
723 ALU_NOP,
724 MEMORY_WRITE,
725 END
726 };
727
MICROPROGRAM(sbz_sbo_mp)728 MICROPROGRAM(sbz_sbo_mp)
729 {
730 ALU_SBZ_SBO,
731 ALU_NOP,
732 MEMORY_READ,
733 ALU_SBZ_SBO,
734 CRU_OUTPUT,
735 END
736 };
737
MICROPROGRAM(tb_mp)738 MICROPROGRAM(tb_mp)
739 {
740 ALU_TB,
741 MEMORY_READ,
742 ALU_TB,
743 CRU_INPUT,
744 ALU_TB,
745 END
746 };
747
MICROPROGRAM(jmp_mp)748 MICROPROGRAM(jmp_mp)
749 {
750 ALU_NOP,
751 ALU_JMP,
752 ALU_JMP,
753 ALU_NOP,
754 END
755 };
756
MICROPROGRAM(shift_mp)757 MICROPROGRAM(shift_mp)
758 {
759 ALU_SHIFT,
760 MEMORY_READ,
761 ALU_SHIFT, // 2 cycles if count != 0, else 4
762 MEMORY_READ, // skipped if count != 0
763 ALU_SHIFT, // skipped if count != 0 (4 cycles)
764 ALU_SHIFT,
765 MEMORY_WRITE,
766 ALU_NOP,
767 END
768 };
769
MICROPROGRAM(ai_ori_mp)770 MICROPROGRAM(ai_ori_mp)
771 {
772 ALU_REG,
773 MEMORY_READ,
774 ALU_IMM,
775 MEMORY_READ,
776 ALU_AI_ORI,
777 MEMORY_WRITE,
778 END
779 };
780
MICROPROGRAM(ci_mp)781 MICROPROGRAM(ci_mp)
782 {
783 ALU_REG,
784 MEMORY_READ,
785 ALU_IMM,
786 MEMORY_READ,
787 ALU_CI,
788 ALU_NOP,
789 END
790 };
791
MICROPROGRAM(li_mp)792 MICROPROGRAM(li_mp)
793 {
794 ALU_IMM,
795 MEMORY_READ,
796 ALU_LI, // sets status bits
797 ALU_REG, // set register number
798 MEMORY_WRITE,
799 END
800 };
801
MICROPROGRAM(lwpi_mp)802 MICROPROGRAM(lwpi_mp)
803 {
804 ALU_IMM,
805 MEMORY_READ,
806 ALU_NOP,
807 ALU_LWPI, // sets WP
808 END
809 };
810
MICROPROGRAM(limi_mp)811 MICROPROGRAM(limi_mp)
812 {
813 ALU_IMM,
814 MEMORY_READ,
815 ALU_NOP,
816 ALU_LIMI, // sets interrupt mask in ST
817 ALU_NOP,
818 ALU_NOP,
819 END
820 };
821
MICROPROGRAM(stwp_stst_mp)822 MICROPROGRAM(stwp_stst_mp)
823 {
824 ALU_STWP_STST,
825 ALU_REG,
826 MEMORY_WRITE,
827 END
828 };
829
MICROPROGRAM(external_mp)830 MICROPROGRAM(external_mp)
831 {
832 ALU_NOP,
833 ALU_NOP,
834 ALU_EXT,
835 ALU_NOP,
836 ALU_NOP,
837 END
838 };
839
MICROPROGRAM(rtwp_mp)840 MICROPROGRAM(rtwp_mp)
841 {
842 ALU_NOP,
843 ALU_RTWP,
844 MEMORY_READ,
845 ALU_RTWP, // no cycles
846 MEMORY_READ,
847 ALU_RTWP, // no cycles
848 MEMORY_READ,
849 ALU_RTWP,
850 END
851 };
852
MICROPROGRAM(int_mp)853 MICROPROGRAM(int_mp)
854 {
855 ALU_NOP,
856 ALU_INT, // 0 Set address = 0
857 MEMORY_READ,
858 ALU_INT, // 1 Save old WP, set new WP, save position
859 MEMORY_WRITE, // write ST to R15
860 ALU_INT, // 2
861 MEMORY_WRITE, // write PC to R14
862 ALU_INT, // 3
863 MEMORY_WRITE, // write WP to R13
864 ALU_INT, // 4 Get saved position
865 MEMORY_READ, // Read new PC
866 ALU_INT, // 5 Set new PC
867 END
868 };
869
870 const tms99xx_device::ophandler tms99xx_device::s_microoperation[] =
871 {
872 &tms99xx_device::acquire_instruction,
873 &tms99xx_device::mem_read,
874 &tms99xx_device::mem_write,
875 &tms99xx_device::register_read,
876 &tms99xx_device::register_write,
877 &tms99xx_device::cru_input_operation,
878 &tms99xx_device::cru_output_operation,
879 &tms99xx_device::data_derivation_subprogram,
880 &tms99xx_device::return_from_subprogram,
881 &tms99xx_device::abort_operation,
882 &tms99xx_device::command_completed,
883
884 &tms99xx_device::alu_nop,
885 &tms99xx_device::alu_clear,
886 &tms99xx_device::alu_setaddr,
887 &tms99xx_device::alu_addone,
888 &tms99xx_device::alu_setaddr_addone,
889 &tms99xx_device::alu_pcaddr_advance,
890 &tms99xx_device::alu_source,
891 &tms99xx_device::alu_add_register,
892 &tms99xx_device::alu_imm,
893 &tms99xx_device::alu_reg,
894
895 &tms99xx_device::alu_f1,
896 &tms99xx_device::alu_comp,
897 &tms99xx_device::alu_f3,
898 &tms99xx_device::alu_multiply,
899 &tms99xx_device::alu_divide,
900 &tms99xx_device::alu_xop,
901 &tms99xx_device::alu_clr_swpb,
902 &tms99xx_device::alu_abs,
903 &tms99xx_device::alu_x,
904 &tms99xx_device::alu_b,
905 &tms99xx_device::alu_blwp,
906 &tms99xx_device::alu_ldcr,
907 &tms99xx_device::alu_stcr,
908 &tms99xx_device::alu_sbz_sbo,
909 &tms99xx_device::alu_tb,
910 &tms99xx_device::alu_jmp,
911 &tms99xx_device::alu_shift,
912 &tms99xx_device::alu_ai_ori,
913 &tms99xx_device::alu_ci,
914 &tms99xx_device::alu_li,
915 &tms99xx_device::alu_lwpi,
916 &tms99xx_device::alu_limi,
917 &tms99xx_device::alu_stwp_stst,
918 &tms99xx_device::alu_external,
919 &tms99xx_device::alu_rtwp,
920 &tms99xx_device::alu_int
921 };
922
923 /*****************************************************************************
924 CPU instructions
925 *****************************************************************************/
926
927 /*
928 Available instructions
929 */
930 enum
931 {
932 ILL=0, A, AB, ABS, AI, ANDI, B, BL, BLWP, C,
933 CB, CI, CKOF, CKON, CLR, COC, CZC, DEC, DECT, DIV,
934 IDLE, INC, INCT, INV, JEQ, JGT, JH, JHE, JL, JLE,
935 JLT, JMP, JNC, JNE, JNO, JOC, JOP, LDCR, LI, LIMI,
936 LREX, LWPI, MOV, MOVB, MPY, NEG, ORI, RSET, RTWP, S,
937 SB, SBO, SBZ, SETO, SLA, SOC, SOCB, SRA, SRC, SRL,
938 STCR, STST, STWP, SWPB, SZC, SZCB, TB, X, XOP, XOR,
939 INTR
940 };
941
942 /*
943 Formats:
944
945 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
946 ----+------------------------------------------------+
947 1 | Opcode | B | Td | RegNr | Ts | RegNr |
948 +--------+---+----+------------+----+------------+
949 2 | Opcode | Displacement |
950 +-----------------------+------------------------+
951 3 | Opcode | RegNr | Ts | RegNr |
952 +-----------------+------------+----+------------+
953 4 | Opcode | Count | Ts | RegNr |
954 +-----------------+------------+----+------------+
955 5 | Opcode | Count | RegNr |
956 +-----------------------+-----------+------------+
957 6 | Opcode | Ts | RegNr |
958 +------------------------------+----+------------+
959 7 | Opcode |0| 0| 0| 0| 0 |
960 +---------------------------------+-+--+--+--+---+
961 8 | Opcode |0| RegNr |
962 +---------------------------------+-+------------+
963 9 | Opcode | Reg/Nr | Ts | RegNr |
964 +-----------------+------------+----+------------+
965 */
966
967 /*
968 Defines the number of bits from the left which are significant for the
969 command in the respective format.
970 */
971 static const int format_mask_len[] =
972 {
973 0, 4, 8, 6, 6, 8, 10, 16, 12, 6
974 };
975
976 const tms99xx_device::tms_instruction tms99xx_device::s_command[] =
977 {
978 // Opcode, ID, format, microprg
979 { 0x0200, LI, 8, li_mp },
980 { 0x0220, AI, 8, ai_ori_mp },
981 { 0x0240, ANDI, 8, ai_ori_mp },
982 { 0x0260, ORI, 8, ai_ori_mp },
983 { 0x0280, CI, 8, ci_mp },
984 { 0x02a0, STWP, 8, stwp_stst_mp },
985 { 0x02c0, STST, 8, stwp_stst_mp },
986 { 0x02e0, LWPI, 8, lwpi_mp },
987 { 0x0300, LIMI, 8, limi_mp },
988 { 0x0340, IDLE, 7, external_mp },
989 { 0x0360, RSET, 7, external_mp },
990 { 0x0380, RTWP, 7, rtwp_mp },
991 { 0x03a0, CKON, 7, external_mp },
992 { 0x03c0, CKOF, 7, external_mp },
993 { 0x03e0, LREX, 7, external_mp },
994 { 0x0400, BLWP, 6, blwp_mp },
995 { 0x0440, B, 6, b_mp },
996 { 0x0480, X, 6, x_mp },
997 { 0x04c0, CLR, 6, clr_swpb_mp },
998 { 0x0500, NEG, 6, clr_swpb_mp },
999 { 0x0540, INV, 6, clr_swpb_mp },
1000 { 0x0580, INC, 6, clr_swpb_mp },
1001 { 0x05c0, INCT, 6, clr_swpb_mp },
1002 { 0x0600, DEC, 6, clr_swpb_mp },
1003 { 0x0640, DECT, 6, clr_swpb_mp },
1004 { 0x0680, BL, 6, bl_mp },
1005 { 0x06c0, SWPB, 6, clr_swpb_mp },
1006 { 0x0700, SETO, 6, clr_swpb_mp },
1007 { 0x0740, ABS, 6, abs_mp },
1008 { 0x0800, SRA, 5, shift_mp },
1009 { 0x0900, SRL, 5, shift_mp },
1010 { 0x0a00, SLA, 5, shift_mp },
1011 { 0x0b00, SRC, 5, shift_mp },
1012 { 0x1000, JMP, 2, jmp_mp },
1013 { 0x1100, JLT, 2, jmp_mp },
1014 { 0x1200, JLE, 2, jmp_mp },
1015 { 0x1300, JEQ, 2, jmp_mp },
1016 { 0x1400, JHE, 2, jmp_mp },
1017 { 0x1500, JGT, 2, jmp_mp },
1018 { 0x1600, JNE, 2, jmp_mp },
1019 { 0x1700, JNC, 2, jmp_mp },
1020 { 0x1800, JOC, 2, jmp_mp },
1021 { 0x1900, JNO, 2, jmp_mp },
1022 { 0x1a00, JL, 2, jmp_mp },
1023 { 0x1b00, JH, 2, jmp_mp },
1024 { 0x1c00, JOP, 2, jmp_mp },
1025 { 0x1d00, SBO, 2, sbz_sbo_mp },
1026 { 0x1e00, SBZ, 2, sbz_sbo_mp },
1027 { 0x1f00, TB, 2, tb_mp },
1028 { 0x2000, COC, 3, f3_mp },
1029 { 0x2400, CZC, 3, f3_mp },
1030 { 0x2800, XOR, 3, xor_mp },
1031 { 0x2c00, XOP, 3, xop_mp },
1032 { 0x3000, LDCR, 4, ldcr_mp },
1033 { 0x3400, STCR, 4, stcr_mp },
1034 { 0x3800, MPY, 9, mult_mp },
1035 { 0x3c00, DIV, 9, div_mp },
1036 { 0x4000, SZC, 1, f1_mp },
1037 { 0x5000, SZCB, 1, f1_mp },
1038 { 0x6000, S, 1, f1_mp },
1039 { 0x7000, SB, 1, f1_mp },
1040 { 0x8000, C, 1, comp_mp },
1041 { 0x9000, CB, 1, comp_mp },
1042 { 0xa000, A, 1, f1_mp },
1043 { 0xb000, AB, 1, f1_mp },
1044 { 0xc000, MOV, 1, f1_mp },
1045 { 0xd000, MOVB, 1, f1_mp },
1046 { 0xe000, SOC, 1, f1_mp },
1047 { 0xf000, SOCB, 1, f1_mp },
1048 { 0x0000, INTR, 1, int_mp} // special entry for the interrupt microprogram, not in lookup table
1049 };
1050
1051 /*
1052 Create a B-tree for looking up the commands. Each node can carry up to
1053 16 entries, indexed by 4 consecutive bits in the opcode.
1054
1055 Works as follows:
1056
1057 Opcode = 0201 (Load immediate value into register 1)
1058 Opcode = 0284 (Compare immediate value with register 4)
1059
1060 Table: [ Table0, table1, table2, ... tableF ]
1061 |
1062 +-------+
1063 v
1064 table0: [ table00, table01, table02, ... table0f ]
1065 |
1066 +-------------------------+
1067 v
1068 table02: [ table020, table021, ... table028, ... table02f ]
1069 | | |
1070 v v v
1071 Entry NULL Entry
1072 for LI for CI
1073
1074 For each level in the tree, four more bits are compared. The search
1075 terminates when the number of compared bits is equal or higher than
1076 the number of significant bits of the format of this opcode. The entry
1077 points to the respective line in s_command.
1078
1079 This way we can decode all format 1 commands by a single pass (including the
1080 most frequent command MOV), and almost all commands by less than four passes.
1081
1082 The disadvantage is that we have to build these tables from the opcode
1083 list at runtime, and many positions are empty. But we do not need more
1084 than 20 tables for the TMS command set.
1085 */
build_command_lookup_table()1086 void tms99xx_device::build_command_lookup_table()
1087 {
1088 int i = 0;
1089 int cmdindex;
1090 int bitcount;
1091 const tms_instruction *inst;
1092 uint16_t opcode;
1093
1094 m_command_lookup_table = std::make_unique<lookup_entry[]>(16);
1095
1096 lookup_entry* table = m_command_lookup_table.get();
1097 for (int j=0; j < 16; j++)
1098 {
1099 table[j].next_digit = nullptr;
1100 table[j].index = NOPRG;
1101 }
1102
1103 do
1104 {
1105 inst = &s_command[i];
1106 table = m_command_lookup_table.get();
1107 LOGMASKED(LOG_EMU, "=== opcode=%04x, len=%d\n", inst->opcode, format_mask_len[inst->format]);
1108 bitcount = 4;
1109 opcode = inst->opcode;
1110 cmdindex = (opcode>>12) & 0x000f;
1111
1112 while (bitcount < format_mask_len[inst->format])
1113 {
1114 // Descend
1115 if (table[cmdindex].next_digit == nullptr)
1116 {
1117 LOGMASKED(LOG_EMU, "create new table at bitcount=%d for index=%d\n", bitcount, cmdindex);
1118 table[cmdindex].next_digit = std::make_unique<lookup_entry[]>(16);
1119 for (int j=0; j < 16; j++)
1120 {
1121 table[cmdindex].next_digit[j].next_digit = nullptr;
1122 table[cmdindex].next_digit[j].index = NOPRG;
1123 }
1124 }
1125 else
1126 {
1127 LOGMASKED(LOG_EMU, "found a table at bitcount=%d\n", bitcount);
1128 }
1129
1130 table = table[cmdindex].next_digit.get();
1131
1132 bitcount = bitcount+4;
1133 opcode <<= 4;
1134 cmdindex = (opcode>>12) & 0x000f;
1135 LOGMASKED(LOG_EMU, "next index=%x\n", cmdindex);
1136 }
1137
1138 LOGMASKED(LOG_EMU, "bitcount=%d\n", bitcount);
1139 // We are at the target level
1140 // Need to fill in the same entry for all values in the bitcount
1141 // (if a command needs 10 bits we have to copy it four
1142 // times for all combinations with 12 bits)
1143 for (int j=0; j < (1<<(bitcount-format_mask_len[inst->format])); j++)
1144 {
1145 LOGMASKED(LOG_EMU, "opcode=%04x at position %d\n", inst->opcode, cmdindex+j);
1146 table[cmdindex+j].index = i;
1147 }
1148 i++;
1149 } while (inst->opcode != 0xf000);
1150
1151 m_interrupt_mp_index = i;
1152 }
1153
1154 /*
1155 Main execution loop
1156
1157 For each invocation of execute_run, a number of loop iterations has been
1158 calculated before (m_icount). Each loop iteration is one clock cycle.
1159 The loop must be executed for the number of times that corresponds to the
1160 time until the next timer event.
1161
1162 In this implementation, each loop iteration also causes the clock line to
1163 pulse once. External devices may use this pulse to decrement counters
1164 which control the READY line.
1165
1166 Machine cycles to clock input:
1167
1168 +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+
1169 | | | | | | | | | | | | | | | | | | clock (1 of 4 phases)
1170 +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +
1171 |-------|-------|-------|-------|---- cycles (2 clock pulses each)
1172
1173 Wait states only have effect for memory operations. They are processed as
1174 follows:
1175
1176 1) The CPU sets the address bus for reading. If READY is low, the CPU
1177 waits for the next clock tick repeatedly until READY is high again.
1178 When this is the case, the data bus is sampled on the next clock tick
1179 and the read operation is complete.
1180
1181 As we do not have a split-phase read operation in this emulation
1182 we actually read the data bus instantly but wait for the READY line to
1183 be high again.
1184
1185 2) The CPU sets the address bus for writing. In the same moment, the data
1186 bus is loaded with the word to be written. On the next clock tick,
1187 the CPU checks the READY line and waits until it is high. When READY
1188 is high at a clock tick, the operation is complete on the next clock tick.
1189 */
execute_run()1190 void tms99xx_device::execute_run()
1191 {
1192 if (m_reset) service_interrupt();
1193
1194 LOGMASKED(LOG_EMU, "calling execute_run for %d cycles\n", m_icount);
1195 do
1196 {
1197 // Only when last instruction has completed
1198 if (m_program_index == NOPRG)
1199 {
1200 if (m_load_state)
1201 {
1202 m_irq_level = LOAD_INT;
1203 m_irq_state = false;
1204 service_interrupt();
1205 }
1206 else
1207 {
1208 // Interrupts are serviced when
1209 // - an interrupt condition is signaled over INTREQ and
1210 // - the level indicated by IC0-IC3 is lower than the interrupt mask value and
1211 // - the previous instruction is not an XOP or BLWP
1212 if (m_irq_state && (m_irq_level <= (ST & 0x000f)) && (m_command != XOP && m_command != BLWP))
1213 service_interrupt();
1214 }
1215 }
1216
1217 if (m_program_index == NOPRG && m_idle_state)
1218 {
1219 LOGMASKED(LOG_IDLE, "IDLE state\n");
1220 pulse_clock(1);
1221 if (!m_external_operation.isnull())
1222 {
1223 m_external_operation(IDLE_OP, 0, 0xff);
1224 m_external_operation(IDLE_OP, 1, 0xff);
1225 }
1226 }
1227 else
1228 {
1229 const uint8_t* program = nullptr;
1230 // When we are in the data derivation sequence, the caller_index is set
1231 if (m_program_index != NOPRG)
1232 program = (m_caller_index == NOPRG)? (uint8_t*)s_command[m_program_index].prog : data_derivation;
1233
1234 // Handle HOLD
1235 // A HOLD request is signalled through the input line HOLD.
1236 // The hold state will be entered with the next non-memory access cycle.
1237 if (m_hold_state &&
1238 (m_program_index == NOPRG ||
1239 (program[MPC] != IAQ &&
1240 program[MPC] != MEMORY_READ && program[MPC] != MEMORY_WRITE &&
1241 program[MPC] != REG_READ && program[MPC] != REG_WRITE)))
1242 {
1243 LOGMASKED(LOG_HOLD, "HOLD state\n");
1244 if (!m_hold_acknowledged) acknowledge_hold();
1245 pulse_clock(1);
1246 }
1247 else
1248 {
1249 // Normal operation
1250 if (m_check_ready && m_ready == false)
1251 {
1252 // We are in a wait state
1253 set_wait_state(true);
1254 LOGMASKED(LOG_WAIT, "wait state\n");
1255 // The clock output should be used to change the state of an outer
1256 // device which operates the READY line
1257 pulse_clock(1);
1258 }
1259 else
1260 {
1261 set_wait_state(false);
1262 m_check_ready = false;
1263 // If we don't have a microprogram, acquire the next instruction
1264 uint8_t op = (m_program_index==NOPRG)? IAQ : program[MPC];
1265
1266 LOGMASKED(LOG_MICRO, "MPC = %d, op = %d\n", MPC, op);
1267 // Call the operation of the microprogram
1268 (this->*s_microoperation[op])();
1269 // If we have multiple passes (as in the TMS9980)
1270 m_pass--;
1271 if (m_pass<=0)
1272 {
1273 m_pass = 1;
1274 MPC++;
1275 m_mem_phase = 1;
1276 m_iaq = false;
1277 }
1278 }
1279 }
1280 }
1281 } while (m_icount>0 && !m_reset);
1282 LOGMASKED(LOG_EMU, "cycles expired; will return soon.\n");
1283 }
1284
1285 /**************************************************************************/
1286
1287 /*
1288 Interrupt input
1289 */
execute_set_input(int irqline,int state)1290 void tms99xx_device::execute_set_input(int irqline, int state)
1291 {
1292 if (irqline==INT_9900_RESET && state==ASSERT_LINE)
1293 {
1294 m_reset = true;
1295 }
1296 else
1297 {
1298 if (irqline == INT_9900_LOAD)
1299 {
1300 m_load_state = (state==ASSERT_LINE);
1301 m_irq_level = LOAD_INT;
1302 m_reset = false;
1303 }
1304 else
1305 {
1306 m_irq_state = (state==ASSERT_LINE);
1307 if (state==ASSERT_LINE)
1308 {
1309 m_irq_level = get_intlevel(state);
1310 LOGMASKED(LOG_INT, "/INT asserted, level=%d, ST=%04x\n", m_irq_level, ST);
1311 }
1312 else
1313 {
1314 LOGMASKED(LOG_INT, "/INT cleared\n");
1315 }
1316 }
1317 }
1318 }
1319
1320 /*
1321 This can be overloaded by variants of TMS99xx.
1322 */
get_intlevel(int state)1323 int tms99xx_device::get_intlevel(int state)
1324 {
1325 if (!m_get_intlevel.isnull()) return m_get_intlevel(0);
1326 return 0;
1327 }
1328
service_interrupt()1329 void tms99xx_device::service_interrupt()
1330 {
1331 m_program_index = m_interrupt_mp_index;
1332
1333 m_command = INTR;
1334 m_idle_state = false;
1335 if (!m_external_operation.isnull()) m_external_operation(IDLE_OP, 0, 0xff);
1336
1337 m_state = 0;
1338
1339 // If reset, we just start with execution, otherwise we put the MPC
1340 // on the first microinstruction, which also means that the main loop shall
1341 // leave it where it is. So we pretend we have another pass to do.
1342 m_pass = m_reset? 1 : 2;
1343
1344 // just for debugging purposes
1345 if (!m_reset) m_log_interrupt = true;
1346
1347 if (m_reset)
1348 {
1349 m_irq_level = RESET_INT;
1350
1351 m_ready_bufd = true;
1352 m_ready = true;
1353 m_load_state = false;
1354 m_hold_state = false;
1355 m_hold_acknowledged = false;
1356 m_wait_state = false;
1357 IR = 0;
1358 ST = 0;
1359 m_mem_phase = 1;
1360
1361 m_reset = false;
1362 LOG("** RESET triggered\n");
1363 }
1364 else
1365 {
1366 if (m_irq_level==LOAD_INT)
1367 LOGMASKED(LOG_LOAD, "** LOAD interrupt triggered\n");
1368 else
1369 LOGMASKED(LOG_INTD, "** Interrupt on level %d\n", m_irq_level);
1370 }
1371
1372 MPC = 0;
1373 m_first_cycle = m_icount;
1374 }
1375
1376 /*
1377 Issue a pulse on the clock line.
1378 */
pulse_clock(int count)1379 void tms99xx_device::pulse_clock(int count)
1380 {
1381 for (int i=0; i < count; i++)
1382 {
1383 if (!m_clock_out_line.isnull()) m_clock_out_line(ASSERT_LINE);
1384 m_ready = m_ready_bufd; // get the latched READY state
1385 if (!m_clock_out_line.isnull()) m_clock_out_line(CLEAR_LINE);
1386 m_icount--; // This is the only location where we count down the cycles.
1387 if (m_check_ready) LOGMASKED(LOG_CLOCK, "pulse_clock, READY=%d\n", m_ready? 1:0);
1388 else LOGMASKED(LOG_CLOCK, "pulse_clock\n");
1389 }
1390 }
1391
1392 /*
1393 Enter the hold state.
1394 */
set_hold(int state)1395 void tms99xx_device::set_hold(int state)
1396 {
1397 m_hold_state = (state==ASSERT_LINE);
1398 if (!m_hold_state)
1399 {
1400 m_hold_acknowledged = false;
1401 if (!m_holda_line.isnull()) m_holda_line(CLEAR_LINE);
1402 }
1403 }
1404
1405 /*
1406 Acknowledge the HOLD request.
1407 */
acknowledge_hold()1408 inline void tms99xx_device::acknowledge_hold()
1409 {
1410 m_hold_acknowledged = true;
1411 if (!m_holda_line.isnull()) m_holda_line(ASSERT_LINE);
1412 }
1413
1414 /*
1415 Signal READY to the CPU. When cleared, the CPU enters wait states. This
1416 becomes effective on a clock pulse.
1417 */
set_ready(int state)1418 void tms99xx_device::set_ready(int state)
1419 {
1420 bool newready = (state==ASSERT_LINE);
1421
1422 if (newready != m_ready_bufd)
1423 {
1424 if (m_reset)
1425 {
1426 LOGMASKED(LOG_WARN, "Ignoring READY=%d change due to pending RESET\n", state);
1427 }
1428 else
1429 {
1430 m_ready_bufd = newready;
1431 LOGMASKED(LOG_READY, "set READY = %d\n", m_ready_bufd? 1 : 0);
1432 }
1433 }
1434 }
1435
abort_operation()1436 void tms99xx_device::abort_operation()
1437 {
1438 command_completed();
1439 }
1440
1441 /*
1442 Enter or leave the wait state. We only operate the WAIT line when there is a change.
1443 */
set_wait_state(bool state)1444 inline void tms99xx_device::set_wait_state(bool state)
1445 {
1446 if (m_wait_state != state)
1447 if (!m_wait_line.isnull()) m_wait_line(state? ASSERT_LINE : CLEAR_LINE);
1448 m_wait_state = state;
1449 }
1450
1451 /*
1452 Acquire the next word as an instruction. The program counter advances by
1453 one word.
1454 */
decode(uint16_t inst)1455 void tms99xx_device::decode(uint16_t inst)
1456 {
1457 int ix = 0;
1458 lookup_entry* table = m_command_lookup_table.get();
1459 uint16_t opcode = inst;
1460 bool complete = false;
1461
1462 m_state = 0;
1463 IR = inst;
1464 m_get_destination = false;
1465 m_byteop = false;
1466
1467 while (!complete)
1468 {
1469 ix = (opcode >> 12) & 0x000f;
1470 LOGMASKED(LOG_MICRO, "Check next hex digit of instruction %x\n", ix);
1471 if (table[ix].next_digit != nullptr)
1472 {
1473 table = table[ix].next_digit.get();
1474 opcode = opcode << 4;
1475 }
1476 else complete = true;
1477 }
1478 m_program_index = table[ix].index;
1479 if (m_program_index == NOPRG)
1480 {
1481 // not found
1482 LOGMASKED(LOG_WARN, "** %04x: Illegal opcode %04x\n", PC, inst);
1483 IR = 0;
1484 // This will cause another instruction acquisition in the next machine cycle
1485 // with an asserted IAQ line (can be used to indicate this illegal opcode detection).
1486 }
1487 else
1488 {
1489 const tms_instruction decoded = s_command[m_program_index];
1490 MPC = -1;
1491 m_command = decoded.id;
1492 LOGMASKED(LOG_OP, "=== %04x: Op=%04x (%s)\n", PC, IR, opname[m_command]);
1493
1494 // Byte operations are either format 1 with the byte flag set
1495 // or format 4 (CRU multi bit operations) with 1-8 bits to transfer.
1496 // Used by the data derivation sequence.
1497 m_byteop = ((decoded.format==1 && ((IR & 0x1000)!=0))
1498 || (decoded.format==4 && (((IR >> 6)&0x000f) > 0) && (((IR >> 6)&0x000f) < 9)));
1499 }
1500 m_pass = 1;
1501 }
1502
byte_operation()1503 inline bool tms99xx_device::byte_operation()
1504 {
1505 return (IR & 0x1000)!=0;
1506 }
1507
acquire_instruction()1508 void tms99xx_device::acquire_instruction()
1509 {
1510 if (m_mem_phase == 1)
1511 {
1512 m_iaq = true;
1513 m_address = PC;
1514 m_first_cycle = m_icount;
1515 }
1516
1517 mem_read();
1518
1519 if (m_mem_phase == 1)
1520 {
1521 decode(m_current_value);
1522
1523 // Mark logged address as interrupt service
1524 if (m_log_interrupt)
1525 LOGMASKED(LOG_EXEC, "i%04x\n", PC);
1526 else
1527 LOGMASKED(LOG_EXEC, "%04x\n", PC);
1528
1529 debugger_instruction_hook(PC);
1530 PC = (PC + 2) & m_prgaddr_mask;
1531 // IAQ will be cleared in the main loop
1532 }
1533 }
1534
1535 /*
1536 Memory read
1537 Clock cycles: 2 + W, W = number of wait states
1538 */
mem_read()1539 void tms99xx_device::mem_read()
1540 {
1541 // After set_address, any device attached to the address bus may pull down
1542 // READY in order to put the CPU into wait state before the read_word
1543 // operation will be performed
1544 // set_address and read_word should pass the same address as argument
1545 if (m_mem_phase==1)
1546 {
1547 LOGMASKED(LOG_ADDRESSBUS, "set address (r) %04x\n", m_address);
1548 if (m_setaddr)
1549 m_setaddr->write_word(m_address & m_prgaddr_mask, (TMS99xx_BUS_DBIN | (m_iaq? TMS99xx_BUS_IAQ : 0)));
1550 m_check_ready = true;
1551 m_mem_phase = 2;
1552 m_pass = 2;
1553 pulse_clock(1); // Concludes the first cycle
1554 // If READY has been found to be low, the CPU will now stay in the wait state loop
1555 }
1556 else
1557 {
1558 // Second phase (after READY was raised again)
1559 m_current_value = m_prgspace->read_word(m_address & m_prgaddr_mask);
1560 pulse_clock(1);
1561 m_mem_phase = 1; // reset to phase 1
1562 LOGMASKED(LOG_MEM, "mem r %04x -> %04x\n", m_address, m_current_value);
1563 }
1564 }
1565
mem_write()1566 void tms99xx_device::mem_write()
1567 {
1568 if (m_mem_phase==1)
1569 {
1570 LOGMASKED(LOG_ADDRESSBUS, "set address (w) %04x\n", m_address);
1571 // When writing, the data bus is asserted immediately after the address bus
1572 if (m_setaddr)
1573 m_setaddr->write_word(m_address & m_prgaddr_mask, TMS99xx_BUS_WRITE);
1574 LOGMASKED(LOG_MEM, "mem w %04x <- %04x\n", m_address, m_current_value);
1575 m_prgspace->write_word(m_address & m_prgaddr_mask, m_current_value);
1576 m_check_ready = true;
1577 m_mem_phase = 2;
1578 m_pass = 2;
1579 pulse_clock(1);
1580 }
1581 else
1582 {
1583 // Second phase (we arrive here when the wait states are over)
1584 pulse_clock(1);
1585 }
1586 }
1587
register_read()1588 void tms99xx_device::register_read()
1589 {
1590 // Need to set m_address for F1/F3 (we don't know what the data_derive did)
1591 if (m_mem_phase==1)
1592 {
1593 m_address = WP + (m_regnumber<<1);
1594 }
1595
1596 mem_read();
1597
1598 if (m_mem_phase==1)
1599 {
1600 m_register_contents = m_current_value;
1601 }
1602 }
1603
1604 /*
1605 Memory write:
1606
1607 Clock cycles: 2 + W, W = number of wait states
1608 */
register_write()1609 void tms99xx_device::register_write()
1610 {
1611 // This will be called twice; m_pass is set by the embedded mem_write
1612 uint16_t addr_save = m_address;
1613 m_address = (WP + (m_regnumber<<1)) & m_prgaddr_mask;
1614 mem_write();
1615 m_address = addr_save;
1616 }
1617
1618 /*
1619 CRU support code
1620
1621 The CRU bus is a 1-bit-wide I/O bus. The CPU can read or write bits at random address.
1622 Special instructions are dedicated to reading and writing one or several consecutive bits.
1623
1624 The CRU uses the same address bus as the normal memory access. For writing,
1625 the CRUCLK line is pulsed, but not for reading where CRUCLK stays cleared.
1626 This means that each normal memory access also causes read accesses on the
1627 CRU side. The /MEMEN line may be used to distinguish the kinds of accesses
1628 as it stays cleared during CRU operations.
1629
1630 We do not emulate this here as it seems there are no real applications of
1631 this side effect. Real designs must ensure that CRU read operations are
1632 idempotent (i.e. they must not change the state of the queried device).
1633
1634 Read returns the number of consecutive CRU bits, with increasing CRU address
1635 from the least significant to the most significant bit; right-aligned (in
1636 other words, little-endian as opposed to the big-endian order of memory words).
1637
1638 There seems to be no handling of wait states during CRU operations on the
1639 TMS9900. The TMS9995, in contrast, respects wait states during the transmission
1640 of each single bit.
1641
1642 The current emulation of the CRU space involves a 1-bit address shift,
1643 reflecting the one-to-one correspondence between CRU bits and words (not
1644 bytes) in the lower part of the memory space. (On the TMS9980A and TMS9995,
1645 CRUOUT is multiplexed with the least significant address line.) Thus, what
1646 TI's documentation calls the software address (the R12 base value plus the
1647 bit offset multiplied by 2) is used in address maps and CPU-side operations.
1648 MAME's memory architecture automatically translates these to right-justified
1649 hardware addresses in the process of decoding offsets for read/write handlers,
1650 which is more typical of what peripheral devices expect. (Note also that
1651 address spaces do not support data widths narrower than 8 bits, so these
1652 handlers must specify 8-bit types despite only one bit being useful.)
1653
1654 Usage of this method:
1655 CRU write: First bit is at rightmost position of m_value.
1656 */
1657
cru_input_operation()1658 void tms99xx_device::cru_input_operation()
1659 {
1660 offs_t cruaddr = m_cru_address & m_cruaddr_mask;
1661 uint16_t value = 0;
1662
1663 for (int i = 0; i < m_count; i++)
1664 {
1665 // Poll one bit at a time
1666 bool cruin = BIT(m_cru->read_byte(cruaddr), 0);
1667 if (cruin)
1668 value |= 1 << i;
1669
1670 LOGMASKED(LOG_CRU, "CRU input operation, address %04x, value %d\n", cruaddr, cruin ? 1 : 0);
1671
1672 // Increment the CRU address
1673 cruaddr = (cruaddr + 2) & m_cruaddr_mask;
1674
1675 // On each machine cycle (2 clocks) only one CRU bit is transmitted
1676 pulse_clock(2);
1677 }
1678
1679 m_value = value;
1680 }
1681
cru_output_operation()1682 void tms99xx_device::cru_output_operation()
1683 {
1684 offs_t cruaddr = m_cru_address & m_cruaddr_mask;
1685 uint16_t value = m_value;
1686
1687 // Write m_count bits from cru_address
1688 for (int i = 0; i < m_count; i++)
1689 {
1690 LOGMASKED(LOG_CRU, "CRU output operation, address %04x, value %d\n", cruaddr, BIT(value, 0));
1691
1692 // Write one bit at a time
1693 m_cru->write_byte(cruaddr, BIT(value, 0));
1694 value >>= 1;
1695
1696 // Increment the CRU address
1697 cruaddr = (cruaddr + 2) & m_cruaddr_mask;
1698
1699 pulse_clock(2);
1700 }
1701 }
1702
return_from_subprogram()1703 void tms99xx_device::return_from_subprogram()
1704 {
1705 // Return from data derivation
1706 // The result should be in m_current_value
1707 // and the address in m_address
1708 m_program_index = m_caller_index;
1709 m_caller_index = NOPRG;
1710 MPC = m_caller_MPC; // will be increased on return
1711 }
1712
command_completed()1713 void tms99xx_device::command_completed()
1714 {
1715 // Pseudo state at the end of the current instruction cycle sequence
1716 if (LOG_CYCLES & VERBOSE)
1717 {
1718 logerror("+++ Instruction %04x (%s) completed", IR, opname[m_command]);
1719 int cycles = m_first_cycle - m_icount;
1720 // Avoid nonsense values due to expired and resumed main loop
1721 if (cycles > 0 && cycles < 10000) logerror(", %d cycles", cycles);
1722 logerror("+++\n");
1723 }
1724 m_program_index = NOPRG;
1725 }
1726
1727 /*
1728 This is a switch to a subprogram; there is only one, the data
1729 derivation. In terms of cycles, it does not take any time; execution
1730 continues with the first instruction of the subprogram.
1731 */
data_derivation_subprogram()1732 void tms99xx_device::data_derivation_subprogram()
1733 {
1734 uint16_t ircopy = IR;
1735
1736 // Save the return program and position
1737 m_caller_index = m_program_index;
1738 m_caller_MPC = MPC;
1739
1740 // Source or destination argument?
1741 if (m_get_destination) ircopy >>= 6;
1742
1743 m_regnumber = ircopy & 0x000f;
1744
1745 MPC = ircopy & 0x0030;
1746
1747 if (((MPC == 0x0020) && (m_regnumber != 0)) // indexed
1748 || ((MPC == 0x0030) && m_byteop)) // byte operation
1749 {
1750 MPC += 8; // the second option
1751 }
1752 m_get_destination = true; // when we call this the second time before END it's the destination
1753 m_pass = 2;
1754 }
1755
1756
1757 /**************************************************************************
1758 Status bit operations
1759 **************************************************************************/
1760
set_status_bit(int bit,bool state)1761 inline void tms99xx_device::set_status_bit(int bit, bool state)
1762 {
1763 if (state) ST |= bit;
1764 else ST &= ~bit;
1765 }
1766
set_status_parity(uint8_t value)1767 void tms99xx_device::set_status_parity(uint8_t value)
1768 {
1769 int count = 0;
1770 for (int i=0; i < 8; i++)
1771 {
1772 if ((value & 0x80)!=0) count++;
1773 value <<= 1;
1774 }
1775 set_status_bit(ST_OP, (count & 1)!=0);
1776 }
1777
compare_and_set_lae(uint16_t value1,uint16_t value2)1778 inline void tms99xx_device::compare_and_set_lae(uint16_t value1, uint16_t value2)
1779 {
1780 set_status_bit(ST_EQ, value1 == value2);
1781 set_status_bit(ST_LH, value1 > value2);
1782 set_status_bit(ST_AGT, (int16_t)value1 > (int16_t)value2);
1783 LOGMASKED(LOG_STATUS, "ST = %04x (val1=%04x, val2=%04x)\n", ST, value1, value2);
1784 }
1785
1786 /**************************************************************************
1787 ALU operations
1788 **************************************************************************/
1789
alu_nop()1790 void tms99xx_device::alu_nop()
1791 {
1792 // Do nothing (or nothing that is externally visible)
1793 pulse_clock(2);
1794 return;
1795 }
1796
alu_source()1797 void tms99xx_device::alu_source()
1798 {
1799 // Copy the current value into the source data register
1800 m_source_even = ((m_address & 1)==0);
1801 m_source_value = m_current_value;
1802 m_source_address = m_address;
1803 pulse_clock(2);
1804 }
1805
alu_clear()1806 void tms99xx_device::alu_clear()
1807 {
1808 // Clears the register contents
1809 m_register_contents = 0;
1810 pulse_clock(2);
1811 }
1812
alu_setaddr()1813 void tms99xx_device::alu_setaddr()
1814 {
1815 // Load the current value into the address register
1816 m_address = m_current_value;
1817 pulse_clock(2);
1818 }
1819
alu_addone()1820 void tms99xx_device::alu_addone()
1821 {
1822 m_current_value++;
1823 pulse_clock(2);
1824 }
1825
alu_setaddr_addone()1826 void tms99xx_device::alu_setaddr_addone()
1827 {
1828 // Set the address register and increase the recent value
1829 m_address = m_current_value;
1830 m_current_value++;
1831 pulse_clock(2);
1832 }
1833
alu_pcaddr_advance()1834 void tms99xx_device::alu_pcaddr_advance()
1835 {
1836 // Set PC as new read address, increase by 2
1837 m_address = PC;
1838 PC = (PC + 2) & m_prgaddr_mask;
1839 pulse_clock(2);
1840 }
1841
alu_add_register()1842 void tms99xx_device::alu_add_register()
1843 {
1844 // Add the register contents to the current value and set as address
1845 m_address = m_current_value + m_register_contents;
1846 pulse_clock(2);
1847 }
1848
alu_imm()1849 void tms99xx_device::alu_imm()
1850 {
1851 m_value_copy = m_current_value;
1852 m_address_copy = m_address;
1853 m_address = PC;
1854 PC = (PC + 2) & m_prgaddr_mask;
1855 pulse_clock(2);
1856 }
1857
alu_reg()1858 void tms99xx_device::alu_reg()
1859 {
1860 m_address = (WP + ((IR & 0x000f)<<1)) & m_prgaddr_mask;
1861 pulse_clock(2);
1862 }
1863
alu_f1()1864 void tms99xx_device::alu_f1()
1865 {
1866 uint32_t dest_new = 0;
1867
1868 // Save the destination value
1869 uint16_t prev_dest_value = m_current_value;
1870
1871 m_destination_even = ((m_address & 1)==0); // this is the destination address; the source address has already been saved
1872 bool byteop = byte_operation();
1873
1874 if (byteop)
1875 {
1876 if (!m_destination_even) m_current_value <<= 8;
1877 if (!m_source_even) m_source_value <<= 8;
1878 // We have to strip away the low byte, or byte operations may fail
1879 // e.g. 0x10ff + 0x0101 = 0x1200
1880 // or 0x2000 - 0x0101 = 0x1eff
1881 m_source_value &= 0xff00;
1882 m_current_value &= 0xff00;
1883 }
1884
1885 switch (m_command)
1886 {
1887 case A:
1888 case AB:
1889 // Add the contents of the source data to the destination data
1890 // May exceed 0xffff (for carry check)
1891 dest_new = m_current_value + m_source_value;
1892
1893 // 1000 + e000 = f000 (L)
1894 // c000 + c000 = 8000 (LC)
1895 // 7000 + 4000 = b000 (LO)
1896 // 2000 + f000 = 1000 (LAC)
1897 // c000 + b000 = 7000 (LACO)
1898 // 2000 + e000 = 0000 (EC)
1899 // 8000 + 8000 = 0000 (ECO)
1900
1901 // When adding, a carry occurs when we exceed the 0xffff value.
1902 set_status_bit(ST_C, (dest_new & 0x10000) != 0);
1903 // If the result has a sign bit that is different from both arguments, we have an overflow
1904 // (i.e. getting a negative value from two positive values and vice versa)
1905 set_status_bit(ST_OV, ((dest_new ^ m_current_value) & (dest_new ^ m_source_value) & 0x8000)!=0);
1906 break;
1907
1908 case S:
1909 case SB:
1910 // Subtract the contents of the source data from the destination data
1911 dest_new = m_current_value + ((~m_source_value) & 0xffff) + 1;
1912 // LAECO(P)
1913 // 8000 - 8000 = 0000 (EC)
1914 // 2000 - 8000 = a000 (LO)
1915 // 8000 - 2000 = 6000 (LACO)
1916 // 2000 - 1000 = 1000 (LAC)
1917 // 1000 - 2000 = f000 (L)
1918 // 1000 - 1000 = 0000 (EC)
1919 // 1000 - f000 = 2000 (LA)
1920 // f000 - 2000 = d000 (LC)
1921
1922 // Subtraction means adding the 2s complement, so the carry bit
1923 // is set whenever adding the 2s complement exceeds ffff
1924 // In fact the CPU adds the one's complement, then adds a one. This
1925 // explains why subtracting 0 sets the carry bit.
1926 set_status_bit(ST_C, (dest_new & 0x10000) != 0);
1927
1928 // If the arguments have different sign bits and the result has a
1929 // sign bit different from the destination value, we have an overflow
1930 // e.g. value1 = 0x7fff, value2 = 0xffff; value1-value2 = 0x8000
1931 // or value1 = 0x8000, value2 = 0x0001; value1-value2 = 0x7fff
1932 // value1 is the destination value
1933 set_status_bit(ST_OV, (m_current_value ^ m_source_value) & (m_current_value ^ dest_new) & 0x8000);
1934 break;
1935
1936 case SOC:
1937 case SOCB:
1938 // OR the contents of the source data on the destination data
1939 dest_new = m_current_value | m_source_value;
1940 break;
1941
1942 case SZC:
1943 case SZCB:
1944 // AND the one's complement of the contents of the source data on the destination data
1945 dest_new = m_current_value & ~m_source_value;
1946 break;
1947
1948 case MOV:
1949 case MOVB:
1950 // Copy the source data to the destination data
1951 dest_new = m_source_value;
1952 break;
1953 }
1954
1955 if (byteop)
1956 {
1957 set_status_parity((uint8_t)(dest_new>>8));
1958
1959 // destnew is the new value to be written (high byte); needs to be
1960 // merged with the existing word
1961 if (m_destination_even)
1962 m_current_value = (prev_dest_value & 0x00ff) | (dest_new & 0xff00);
1963 else
1964 m_current_value = (prev_dest_value & 0xff00) | ((dest_new >> 8) & 0x00ff);
1965 compare_and_set_lae((uint16_t)(dest_new & 0xff00), 0);
1966 }
1967 else
1968 {
1969 m_current_value = (uint16_t)(dest_new & 0xffff);
1970 compare_and_set_lae((uint16_t)(dest_new & 0xffff), 0);
1971 }
1972
1973 pulse_clock(2);
1974 }
1975
alu_comp()1976 void tms99xx_device::alu_comp()
1977 {
1978 m_destination_even = ((m_address & 1)==0); // this is the destination address; the source address has already been saved
1979 if (byte_operation())
1980 {
1981 if (!m_destination_even) m_current_value <<= 8;
1982 if (!m_source_even) m_source_value <<= 8;
1983 set_status_parity((uint8_t)(m_source_value>>8));
1984 compare_and_set_lae(m_source_value & 0xff00, m_current_value & 0xff00);
1985 }
1986 else
1987 compare_and_set_lae(m_source_value, m_current_value);
1988
1989 pulse_clock(2);
1990 }
1991
alu_f3()1992 void tms99xx_device::alu_f3()
1993 {
1994 switch (m_state)
1995 {
1996 case 0:
1997 // Get register address
1998 m_address = WP + ((IR >> 5) & 0x001e);
1999 m_source_value = m_current_value;
2000 break;
2001 case 1:
2002 if (m_command == COC)
2003 {
2004 set_status_bit(ST_EQ, (m_current_value & m_source_value) == m_source_value);
2005 }
2006 else
2007 {
2008 if (m_command == CZC)
2009 {
2010 set_status_bit(ST_EQ, (~m_current_value & m_source_value) == m_source_value);
2011 }
2012 else
2013 {
2014 // XOR
2015 // The workspace register address is still in m_address
2016 m_current_value = (m_current_value ^ m_source_value);
2017 compare_and_set_lae(m_current_value, 0);
2018 }
2019 }
2020 LOGMASKED(LOG_STATUS, "ST = %04x\n", ST);
2021 break;
2022 }
2023
2024 m_state++;
2025 pulse_clock(2);
2026 }
2027
alu_multiply()2028 void tms99xx_device::alu_multiply()
2029 {
2030 uint32_t result;
2031
2032 switch (m_state)
2033 {
2034 case 0: // After data derivation
2035 m_source_value = m_current_value;
2036 m_address = ((IR >> 5) & 0x001e) + WP;
2037 break;
2038 case 1: // After reading the register (multiplier)
2039 result = (m_source_value & 0x0000ffff) * (m_current_value & 0x0000ffff);
2040 m_current_value = (result >> 16) & 0xffff;
2041 m_value_copy = result & 0xffff;
2042 pulse_clock(34); // add 36 clock cycles (18 machine cycles); last one in main loop
2043 break;
2044 case 2: // After writing the high word to the destination register
2045 m_current_value = m_value_copy; // Prepare to save low word
2046 m_address = (m_address + 2) & m_prgaddr_mask;
2047 break;
2048 }
2049 pulse_clock(2);
2050 m_state++;
2051 }
2052
alu_divide()2053 void tms99xx_device::alu_divide()
2054 {
2055 // Format is DIV Divisor,REG(dividend)
2056 uint32_t uval32;
2057 bool overflow = true;
2058 uint16_t value1;
2059
2060 switch (m_state)
2061 {
2062 case 0:
2063 m_source_value = m_current_value; // store divisor
2064 // Set address of register
2065 m_address = WP + ((IR >> 5) & 0x001e);
2066 m_address_copy = m_address;
2067 break;
2068 case 1:
2069 // We have an overflow when the quotient cannot be stored in 16 bits
2070 // This is the case when the dividend / divisor >= 0x10000,
2071 // or equivalently, dividend / 0x10000 >= divisor
2072
2073 if (m_current_value < m_source_value) // also if source=0
2074 {
2075 MPC++; // skip the abort
2076 overflow = false;
2077 }
2078 set_status_bit(ST_OV, overflow);
2079 m_value_copy = m_current_value; // Save the high word
2080 m_address = (m_address + 2) & m_prgaddr_mask; // Read next word
2081 break;
2082 case 2:
2083 // W2 is in m_current_value
2084 // Create full word and perform division
2085 uval32 = (m_value_copy << 16) | m_current_value;
2086
2087 m_current_value = uval32 / m_source_value;
2088 m_value_copy = uval32 % m_source_value;
2089 m_address = m_address_copy;
2090
2091 // The number of ALU cycles depends on the number of steps in
2092 // the division algorithm. The number of cycles is between 32 and
2093 // 48 (*2 for clock cycles)
2094 // As I don't have a description of the actual algorithm, I'll use
2095 // the following heuristic: We use 32 ALU cycles in general, then
2096 // we need as many cycles as it takes to
2097 // shift away the dividend. Thus, bigger dividends need more cycles.
2098
2099 pulse_clock(62); // one pulse is at the start, one at the end
2100 value1 = m_value_copy & 0xffff;
2101
2102 while (value1 != 0)
2103 {
2104 value1 = (value1 >> 1) & 0xffff;
2105 pulse_clock(2);
2106 }
2107 // We still have m_regnumber; this is where m_current_value will go to
2108 break;
2109 case 3:
2110 // Prepare to write the remainder
2111 m_current_value = m_value_copy;
2112 m_address = m_address + 2;
2113 LOGMASKED(LOG_STATUS, "ST = %04x (div)\n", ST);
2114 break;
2115 }
2116 pulse_clock(2);
2117 m_state++;
2118 }
2119
alu_xop()2120 void tms99xx_device::alu_xop()
2121 {
2122 switch (m_state)
2123 {
2124 case 0:
2125 // We have the effective address of the source operand in m_address
2126 m_address_saved = m_address;
2127 // Now we take the XOP number from the instruction register
2128 // and calculate the vector location
2129 // [0010 11xx xx tt SSSS] shift 6 right, then *4 => shift 4 right
2130 m_address = 0x0040 + ((IR >> 4) & 0x003c);
2131 // Takes some additional cycles
2132 pulse_clock(4);
2133 break;
2134 case 1:
2135 m_value_copy = WP; // save the old WP
2136 WP = m_current_value & m_prgaddr_mask; // the new WP has been read in the previous microoperation
2137 m_current_value = m_address_saved; // we saved the address of the source operand; retrieve it
2138 m_address = WP + 0x0016; // Next register is R11
2139 break;
2140 case 2:
2141 m_address = WP + 0x001e;
2142 m_current_value = ST;
2143 break;
2144 case 3:
2145 m_address = WP + 0x001c;
2146 m_current_value = PC;
2147 break;
2148 case 4:
2149 m_address = WP + 0x001a;
2150 m_current_value = m_value_copy; // old WP into new R13
2151 break;
2152 case 5:
2153 m_address = 0x0042 + ((IR >> 4) & 0x003c); // location of new PC
2154 set_status_bit(ST_X, true);
2155 break;
2156 case 6:
2157 PC = m_current_value & m_prgaddr_mask;
2158 break;
2159 }
2160 pulse_clock(2);
2161 m_state++;
2162 }
2163
alu_clr_swpb()2164 void tms99xx_device::alu_clr_swpb()
2165 {
2166 uint32_t dest_new = 0;
2167 uint32_t src_val = m_current_value & 0x0000ffff;
2168 uint16_t sign = 0;
2169
2170 bool setstatus = true;
2171 bool check_ov = true;
2172 bool check_c = true;
2173
2174 switch (m_command)
2175 {
2176 case CLR:
2177 // no status bits
2178 m_current_value = 0x0000;
2179 setstatus = false;
2180 break;
2181 case SETO:
2182 // no status bits
2183 m_current_value = 0xffff;
2184 setstatus = false;
2185 break;
2186 case INV:
2187 // LAE
2188 dest_new = ~src_val & 0xffff;
2189 check_ov = false;
2190 check_c = false;
2191 break;
2192 case NEG:
2193 // LAECO
2194 // Overflow occurs for value=0x8000
2195 dest_new = ((~src_val) & 0x0000ffff) + 1;
2196 check_ov = false;
2197 set_status_bit(ST_OV, src_val == 0x8000);
2198 break;
2199 case INC:
2200 // LAECO
2201 // Overflow for result value = 0x8000
2202 // Carry for result value = 0x0000
2203 dest_new = src_val + 1;
2204 break;
2205 case INCT:
2206 // LAECO
2207 // Overflow for result value = 0x8000 / 0x8001
2208 // Carry for result value = 0x0000 / 0x0001
2209 dest_new = src_val + 2;
2210 break;
2211 case DEC:
2212 // LAECO
2213 // Carry for result value != 0xffff
2214 // Overflow for result value == 0x7fff
2215 dest_new = src_val + 0xffff;
2216 sign = 0x8000;
2217 break;
2218 case DECT:
2219 // Carry for result value != 0xffff / 0xfffe
2220 // Overflow for result value = 0x7fff / 0x7ffe
2221 dest_new = src_val + 0xfffe;
2222 sign = 0x8000;
2223 break;
2224 case SWPB:
2225 m_current_value = ((m_current_value << 8) | (m_current_value >> 8)) & 0xffff;
2226 setstatus = false;
2227 break;
2228 }
2229
2230 if (setstatus)
2231 {
2232 if (check_ov) set_status_bit(ST_OV, ((src_val & 0x8000)==sign) && ((dest_new & 0x8000)!=sign));
2233 if (check_c) set_status_bit(ST_C, (dest_new & 0x10000) != 0);
2234 m_current_value = dest_new & 0xffff;
2235 compare_and_set_lae(m_current_value, 0);
2236 }
2237
2238 pulse_clock(2);
2239 // No states here
2240 }
2241
alu_abs()2242 void tms99xx_device::alu_abs()
2243 {
2244 // LAECO (from original word!)
2245 // O if >8000
2246 // C is alwas reset
2247 set_status_bit(ST_OV, m_current_value == 0x8000);
2248 set_status_bit(ST_C, false);
2249 compare_and_set_lae(m_current_value, 0);
2250
2251 if ((m_current_value & 0x8000)!=0)
2252 {
2253 m_current_value = (((~m_current_value) & 0x0000ffff) + 1) & 0xffff;
2254 pulse_clock(2); // If ABS is performed it takes one machine cycle more
2255 }
2256 else
2257 {
2258 MPC++; // skips over the next micro operation (MEMORY_WRITE)
2259 }
2260 pulse_clock(2);
2261 }
2262
alu_x()2263 void tms99xx_device::alu_x()
2264 {
2265 decode(m_current_value);
2266 pulse_clock(2);
2267 }
2268
2269 /*
2270 Used by B and BL
2271 */
alu_b()2272 void tms99xx_device::alu_b()
2273 {
2274 // no status bits
2275 // Although we got the contents of the source data, we do not use them
2276 // but directly branch there. That is, we are only interested in the
2277 // address of the source data.
2278 // If we have a B *R5 and R5 contains the value 0xa000, the CPU actually
2279 // retrieves the value at 0xa000, but in fact it will load the PC
2280 // with the address 0xa000
2281 m_current_value = PC;
2282 PC = m_address & m_prgaddr_mask;
2283 m_address = WP + 22;
2284 pulse_clock(2);
2285 }
2286
alu_blwp()2287 void tms99xx_device::alu_blwp()
2288 {
2289 switch (m_state)
2290 {
2291 case 0:
2292 m_value_copy = WP;
2293 WP = m_current_value & m_prgaddr_mask; // set new WP (*m_destination)
2294 m_address_saved = (m_address + 2) & m_prgaddr_mask; // Save the location of the WP
2295 m_address = WP + 30;
2296 m_current_value = ST; // get status register
2297 break;
2298 case 1:
2299 m_current_value = PC; // get program counter
2300 m_address = m_address - 2;
2301 break;
2302 case 2:
2303 m_current_value = m_value_copy; // retrieve the old WP
2304 m_address = m_address - 2;
2305 break;
2306 case 3:
2307 m_address = m_address_saved; // point to PC component of branch vector
2308 break;
2309 case 4:
2310 PC = m_current_value & m_prgaddr_mask;
2311 LOGMASKED(LOG_CONTEXT, "Context switch (blwp): WP=%04x, PC=%04x, ST=%04x\n", WP, PC, ST);
2312 break;
2313 }
2314 pulse_clock(2);
2315 m_state++;
2316 }
2317
alu_ldcr()2318 void tms99xx_device::alu_ldcr()
2319 {
2320 uint16_t value;
2321
2322 // Spec: "If the source operand address is odd, the address is truncated
2323 // to an even address prior to data transfer."
2324 // (Editor/Assembler, page 151)
2325 // This refers to transfers with more than 8 bits. In this case, for
2326 // LDCR the first bit is taken from the least significant bit of the
2327 // source word. If the address is odd (e.g. 0x1001), it is
2328 // treated as 0x1000, that is, truncated to an even address.
2329 // For transfers with 1-8 bits, the first bit is the least significant
2330 // bit of the source byte (any address).
2331
2332 if (m_state == 0)
2333 {
2334 m_address = WP + 24;
2335 }
2336 else
2337 {
2338 value = m_source_value; // copied by ALU_SOURCE
2339 m_count = (IR >> 6) & 0x000f;
2340 if (m_count == 0) m_count = 16;
2341 if (m_count <= 8)
2342 {
2343 if (m_source_even) value>>=8;
2344 set_status_parity((uint8_t)(value & 0xff));
2345 compare_and_set_lae(value<<8, 0);
2346 }
2347 else
2348 {
2349 compare_and_set_lae(value, 0);
2350 }
2351 m_cru_address = m_current_value;
2352 m_value = value;
2353 LOGMASKED(LOG_CRU, "Load CRU address %04x (%d bits), value = %04x\n", m_cru_address, m_count, m_value);
2354 }
2355 m_state++;
2356 pulse_clock(2);
2357 }
2358
alu_stcr()2359 void tms99xx_device::alu_stcr()
2360 {
2361 uint16_t value;
2362 int n = 2;
2363 // For STCR transfers with more than 8 bits, the first CRU bit is
2364 // always put into the least significant bit of the destination word.
2365 // If the address is odd (e.g. 0x1001), it is treated as 0x1000, that is,
2366 // truncated to an even boundary.
2367 // For transfers with 1-8 bits, the destination address is handled as
2368 // in MOVB operations, i.e. the other byte of the word is kept unchanged.
2369
2370 switch (m_state)
2371 {
2372 case 0: // After getting the destination operand and saving the address/value
2373 m_address = WP + 24;
2374 n = 0;
2375 break;
2376 case 1: // After getting R12
2377 m_cru_address = m_current_value;
2378 m_count = (IR >> 6) & 0x000f;
2379 if (m_count == 0) m_count = 16;
2380 break;
2381 case 2: // After the cru operation; value starts at LSB of m_value
2382 value = m_value & 0xffff;
2383 if (m_count < 9)
2384 {
2385 LOGMASKED(LOG_CRU, "Store CRU at %04x (%d bits) in %04x, result = %02x\n", m_cru_address, m_count, m_source_address, value);
2386 set_status_parity((uint8_t)(value & 0xff));
2387 compare_and_set_lae(value<<8, 0);
2388 if (m_source_even)
2389 m_current_value = (m_source_value & 0x00ff) | (value<<8);
2390 else
2391 m_current_value = (m_source_value & 0xff00) | (value & 0xff);
2392
2393 pulse_clock(2*(5 + (8-m_count)));
2394 }
2395 else
2396 {
2397 LOGMASKED(LOG_CRU, "Store CRU at %04x (%d bits) in %04x, result = %04x\n", m_cru_address, m_count, m_source_address, value);
2398 m_current_value = value;
2399 compare_and_set_lae(value, 0);
2400 pulse_clock(2*(5 + (16-m_count)));
2401 }
2402 m_address = m_source_address;
2403 break;
2404 }
2405
2406 m_state++;
2407 pulse_clock(n);
2408 }
2409
alu_sbz_sbo()2410 void tms99xx_device::alu_sbz_sbo()
2411 {
2412 int8_t displacement;
2413 if (m_state==0)
2414 {
2415 m_address = WP + 24;
2416 }
2417 else
2418 {
2419 m_value = (m_command==SBO)? 1 : 0;
2420 displacement = (int8_t)(IR & 0xff);
2421 m_cru_address = m_current_value + (displacement<<1);
2422 m_count = 1;
2423 }
2424 m_state++;
2425 pulse_clock(2);
2426 }
2427
alu_tb()2428 void tms99xx_device::alu_tb()
2429 {
2430 int8_t displacement;
2431 switch (m_state)
2432 {
2433 case 0:
2434 m_address = WP + 24;
2435 break;
2436 case 1:
2437 displacement = (int8_t)(IR & 0xff);
2438 m_cru_address = m_current_value + (displacement<<1);
2439 m_count = 1;
2440 break;
2441 case 2:
2442 set_status_bit(ST_EQ, m_value!=0);
2443 LOGMASKED(LOG_STATUS, "ST = %04x\n", ST);
2444 break;
2445 }
2446 m_state++;
2447 pulse_clock(2);
2448 }
2449
alu_jmp()2450 void tms99xx_device::alu_jmp()
2451 {
2452 int8_t displacement;
2453 bool cond = false;
2454
2455 if (m_state==0)
2456 {
2457 switch (m_command)
2458 {
2459 case JMP:
2460 cond = true;
2461 break;
2462 case JLT: // LAECOP == x00xxx
2463 cond = ((ST & (ST_AGT | ST_EQ))==0);
2464 break;
2465 case JLE: // LAECOP == 0xxxxx
2466 cond = ((ST & ST_LH)==0);
2467 break;
2468 case JEQ: // LAECOP == xx1xxx
2469 cond = ((ST & ST_EQ)!=0);
2470 break;
2471 case JHE: // LAECOP == 1x0xxx, 0x1xxx
2472 cond = ((ST & (ST_LH | ST_EQ)) != 0);
2473 break;
2474 case JGT: // LAECOP == x1xxxx
2475 cond = ((ST & ST_AGT)!=0);
2476 break;
2477 case JNE: // LAECOP == xx0xxx
2478 cond = ((ST & ST_EQ)==0);
2479 break;
2480 case JNC: // LAECOP == xxx0xx
2481 cond = ((ST & ST_C)==0);
2482 break;
2483 case JOC: // LAECOP == xxx1xx
2484 cond = ((ST & ST_C)!=0);
2485 break;
2486 case JNO: // LAECOP == xxxx0x
2487 cond = ((ST & ST_OV)==0);
2488 break;
2489 case JL: // LAECOP == 0x0xxx
2490 cond = ((ST & (ST_LH | ST_EQ)) == 0);
2491 break;
2492 case JH: // LAECOP == 1xxxxx
2493 cond = ((ST & ST_LH)!=0);
2494 break;
2495 case JOP: // LAECOP == xxxxx1
2496 cond = ((ST & ST_OP)!=0);
2497 break;
2498 }
2499 if (!cond)
2500 {
2501 LOGMASKED(LOG_DETAIL, "Jump condition false\n");
2502 MPC+=1; // skip next ALU call
2503 }
2504 else
2505 LOGMASKED(LOG_DETAIL, "Jump condition true\n");
2506 }
2507 else
2508 {
2509 displacement = (IR & 0xff);
2510 PC = (PC + (displacement<<1)) & m_prgaddr_mask;
2511 }
2512 m_state++;
2513 pulse_clock(2);
2514 }
2515
alu_shift()2516 void tms99xx_device::alu_shift()
2517 {
2518 bool carry = false;
2519 bool overflow = false;
2520 uint16_t sign = 0;
2521 uint32_t value;
2522 int count;
2523 bool check_ov = false;
2524
2525 switch (m_state)
2526 {
2527 case 0:
2528 m_address = WP + ((IR & 0x000f)<<1);
2529 pulse_clock(2);
2530 break;
2531 case 1:
2532 // we have the value of the register in m_current_value
2533 // Save it (we may have to read R0)
2534 m_value_copy = m_current_value;
2535 m_address_saved = m_address;
2536 m_address = WP;
2537 m_current_value = (IR >> 4) & 0x000f;
2538
2539 if (m_current_value != 0)
2540 {
2541 // skip the next read and ALU operation
2542 MPC = MPC+2;
2543 m_state++;
2544 }
2545 else
2546 {
2547 LOGMASKED(LOG_DETAIL, "Shift operation gets count from R0\n");
2548 pulse_clock(2);
2549 }
2550 pulse_clock(2);
2551 break;
2552 case 2:
2553 // after READ
2554 pulse_clock(2);
2555 pulse_clock(2);
2556 break;
2557 case 3:
2558 count = m_current_value & 0x000f; // from the instruction or from R0
2559 if (count==0) count = 16;
2560
2561 value = m_value_copy;
2562
2563 // we are re-implementing the shift operations because we have to pulse
2564 // the clock at each single shift anyway.
2565 // Also, it is easier to implement the status bit setting.
2566 // Note that count is never 0
2567 if (m_command == SRA) sign = value & 0x8000;
2568
2569 for (int i=0; i < count; i++)
2570 {
2571 switch (m_command)
2572 {
2573 case SRL:
2574 case SRA:
2575 carry = ((value & 1)!=0);
2576 value = (value >> 1) | sign;
2577 break;
2578 case SLA:
2579 carry = ((value & 0x8000)!=0);
2580 value <<= 1;
2581 check_ov = true;
2582 if (carry != ((value&0x8000)!=0)) overflow = true;
2583 break;
2584 case SRC:
2585 carry = ((value & 1)!=0);
2586 value = (value>>1) | (carry? 0x8000 : 0x0000);
2587 break;
2588 }
2589 pulse_clock(2);
2590 }
2591
2592 m_current_value = value & 0xffff;
2593 set_status_bit(ST_C, carry);
2594 if (check_ov) set_status_bit(ST_OV, overflow); // only SLA
2595 compare_and_set_lae(m_current_value, 0);
2596 m_address = m_address_saved; // Register address
2597 LOGMASKED(LOG_STATUS, "ST = %04x (val=%04x)\n", ST, m_current_value);
2598 break;
2599 }
2600 m_state++;
2601 }
2602
alu_ai_ori()2603 void tms99xx_device::alu_ai_ori()
2604 {
2605 uint32_t dest_new = 0;
2606 switch (m_command)
2607 {
2608 case AI:
2609 dest_new = m_current_value + m_value_copy;
2610 // See status bit handling for Add
2611 set_status_bit(ST_C, (dest_new & 0x10000) != 0);
2612 set_status_bit(ST_OV, ((dest_new ^ m_current_value) & (dest_new ^ m_value_copy) & 0x8000)!=0);
2613 break;
2614 case ANDI:
2615 dest_new = m_current_value & m_value_copy;
2616 break;
2617 case ORI:
2618 dest_new = m_current_value | m_value_copy;
2619 break;
2620 }
2621 m_current_value = dest_new & 0xffff;
2622 m_address = m_address_copy;
2623 compare_and_set_lae(m_current_value, 0);
2624 pulse_clock(2);
2625 }
2626
alu_ci()2627 void tms99xx_device::alu_ci()
2628 {
2629 compare_and_set_lae(m_value_copy, m_current_value);
2630 pulse_clock(2);
2631 }
2632
alu_li()2633 void tms99xx_device::alu_li()
2634 {
2635 compare_and_set_lae(m_current_value, 0);
2636 pulse_clock(2);
2637 }
2638
alu_lwpi()2639 void tms99xx_device::alu_lwpi()
2640 {
2641 WP = m_current_value & m_prgaddr_mask;
2642 pulse_clock(2);
2643 }
2644
alu_limi()2645 void tms99xx_device::alu_limi()
2646 {
2647 ST = (ST & 0xfff0) | (m_current_value & 0x000f);
2648 LOGMASKED(LOG_STATUS, "ST = %04x\n", ST);
2649 pulse_clock(2);
2650 }
2651
alu_stwp_stst()2652 void tms99xx_device::alu_stwp_stst()
2653 {
2654 if (m_command==STST) m_current_value = ST;
2655 else m_current_value = WP;
2656 pulse_clock(2);
2657 }
2658
alu_external()2659 void tms99xx_device::alu_external()
2660 {
2661 // Call some possibly attached external device
2662 // We pass the bit pattern of the address bus to the external function
2663
2664 // IDLE = 0000 0011 0100 0000
2665 // RSET = 0000 0011 0110 0000
2666 // CKON = 0000 0011 1010 0000
2667 // CKOF = 0000 0011 1100 0000
2668 // LREX = 0000 0011 1110 0000
2669 // ---
2670 if (m_command == IDLE)
2671 m_idle_state = true;
2672
2673 if (!m_external_operation.isnull()) m_external_operation((IR >> 5) & 0x07, 1, 0xff);
2674 pulse_clock(2);
2675 }
2676
alu_rtwp()2677 void tms99xx_device::alu_rtwp()
2678 {
2679 switch (m_state)
2680 {
2681 case 0:
2682 m_address = WP + 30; // R15
2683 pulse_clock(2);
2684 break;
2685 case 1:
2686 ST = m_current_value;
2687 m_address -= 2; // R14
2688 break;
2689 case 2:
2690 PC = m_current_value & m_prgaddr_mask;
2691 m_address -= 2; // R13
2692 break;
2693 case 3:
2694 WP = m_current_value & m_prgaddr_mask;
2695 pulse_clock(2);
2696 // Just for debugging purposes
2697 m_log_interrupt = false;
2698 LOGMASKED(LOG_CONTEXT, "Context switch (rtwp): WP=%04x, PC=%04x, ST=%04x\n", WP, PC, ST);
2699 break;
2700 }
2701 m_state++;
2702 }
2703
2704
alu_int()2705 void tms99xx_device::alu_int()
2706 {
2707 switch (m_state)
2708 {
2709 case 0:
2710 if (m_irq_level == RESET_INT)
2711 {
2712 m_address = 0;
2713 pulse_clock(2);
2714 }
2715 else
2716 {
2717 if (m_irq_level == LOAD_INT) m_address = 0xfffc; // will be truncated for TMS9980
2718 else
2719 {
2720 LOGMASKED(LOG_INTD, "interrupt service (0): Prepare to read vector\n");
2721 m_address = (m_irq_level << 2);
2722 }
2723 }
2724 break;
2725 case 1:
2726 m_address_copy = m_address;
2727 m_value_copy = WP; // old WP
2728 WP = m_current_value & m_prgaddr_mask; // new WP
2729 m_current_value = ST;
2730 m_address = (WP + 30) & m_prgaddr_mask;
2731 LOGMASKED(LOG_INTD, "interrupt service (1): Read new WP = %04x, save ST to %04x\n", WP, m_address);
2732 break;
2733 case 2:
2734 m_current_value = PC;
2735 m_address = (WP + 28) & m_prgaddr_mask;
2736 LOGMASKED(LOG_INTD, "interrupt service (2): Save PC to %04x\n", m_address);
2737 break;
2738 case 3:
2739 m_current_value = m_value_copy; // old WP
2740 m_address = (WP + 26) & m_prgaddr_mask;
2741 LOGMASKED(LOG_INTD, "interrupt service (3): Save WP to %04x\n", m_address);
2742 break;
2743 case 4:
2744 m_address = (m_address_copy + 2) & m_prgaddr_mask;
2745 LOGMASKED(LOG_INTD, "interrupt service (4): Read PC from %04x\n", m_address);
2746 break;
2747 case 5:
2748 PC = m_current_value & m_prgaddr_mask;
2749 if (m_irq_level > 0 )
2750 {
2751 ST = (ST & 0xfff0) | (m_irq_level - 1);
2752 }
2753 if (m_irq_level == LOAD_INT)
2754 LOGMASKED(LOG_LOAD, "Context switch (LOAD): WP=%04x, PC=%04x, ST=%04x\n", WP, PC, ST);
2755 else
2756 LOGMASKED(LOG_CONTEXT, "Context switch (int): WP=%04x, PC=%04x, ST=%04x\n", WP, PC, ST);
2757 break;
2758 }
2759 m_state++;
2760 pulse_clock(2);
2761 }
2762
2763 /**************************************************************************/
2764
2765 /*
2766 The minimum number of cycles applies to a command like STWP R0.
2767 */
execute_min_cycles() const2768 uint32_t tms99xx_device::execute_min_cycles() const noexcept
2769 {
2770 return 8;
2771 }
2772
2773 /*
2774 The maximum number of cycles applies to a DIV command, depending on the
2775 data to be divided, and the mode of adressing.
2776 */
execute_max_cycles() const2777 uint32_t tms99xx_device::execute_max_cycles() const noexcept
2778 {
2779 return 124;
2780 }
2781
execute_input_lines() const2782 uint32_t tms99xx_device::execute_input_lines() const noexcept
2783 {
2784 return 2;
2785 }
2786
2787 // clocks to cycles, cycles to clocks = id
2788 // execute_default_irq_vector = 0
2789 // execute_burn = nop
2790
2791 // device_disasm_interface overrides
2792
create_disassembler()2793 std::unique_ptr<util::disasm_interface> tms99xx_device::create_disassembler()
2794 {
2795 return std::make_unique<tms9900_disassembler>(TMS9900_ID);
2796 }
2797
2798
2799 DEFINE_DEVICE_TYPE(TMS9900, tms9900_device, "tms9900", "Texas Instruments TMS9900")
2800