1 /*
2 	99xxcore.h : generic tms99xx emulation
3 
4 	The TMS99XX_MODEL switch tell which emulator we want to build.  Set the switch, then include
5 	99xxcore.h, and you will have an emulator for this processor.
6 
7 	Only tms9900, tms9980a/9981, and tms9995 work OK for now.  Note that tms9995 has not been tested
8 	extensively.
9 
10 	I think all software aspects of tms9940, tms9985 and tms9989 are implemented (though there
11 	must be some mistakes, particularily in tms9940 BCD support).  You'll just have to implement
12 	bus interfaces, provided you know them.  (I don't...)
13 
14 	Original tms9900 emulator by Edward Swartz
15 	Smoothed out by Raphael Nabet
16 	Originally converted for Mame by M.Coates
17 	Processor timing, support for tms9980 and tms9995, and many bug fixes by R Nabet
18 */
19 
20 /*
21 	tms9900 is derived from the TI990/x minicomputer series (with multi-chip processors, except with
22 	cheaper or later models, which used microprocessors).  However, tms99xx (and even extension-less
23 	tms99xxx) only implement a reduced subset of the huge instruction set available on big TI990
24 	systems.
25 
26 	AFAIK, tms9900, tms9980, and tms9985 have exactly the same programming model, and are actually
27 	the same CPU with different bus interfaces.  The former affirmation is (almost) true with
28 	tms9940, so I guess the later is true, too.  (The only problem with tms9940 is I have no idea
29 	what its bus interfaces are - I have a pinout, but it does not help much, although it is obvious
30 	that the beast is a microcontroller.)  tms9985 had on-chip RAM and timer, like tms9995, although
31 	I don't know how the memory and CRU were mapped exactly.
32 
33 	tms9989 is mostly alien to me.  I assumed it was more related to tms9900 than tms9995, although
34 	it has most of the additionnal features tms9995 has.
35 
36 	tms9995 belongs to another generation.  As a matter of fact, it quite faster than tms9900.
37 
38 	tms99xxx include all tms9995 advances, and add some advances of their own.  I know they support
39 	many extra opcodes (84 instructions types on tms99105a, vs. 69 on tms9900), and support
40 	privileges (i.e. supervisor mode), flags in multiprocessor environment, 32-bit operations...
41 	There was yet other features (Macrostore to define custom instructions, op code compression...),
42 	which are completely alien to me.
43 
44 	I have written code to recognize every tms99xxx opcode, and all other TI990 instructions I have
45 	heard of.  I cannot complete this code, since I have no documentation on tms99xxx.  I am not
46 	even sure the instruction set I guessed for tms99xxx is correct.  Also, the proposed meaning for
47 	these extra memnonics could be wrong.
48 
49 References :
50 * 9900 family systems design, chapter 6, 7, 8
51 * TMS 9980A/ TMS 9981 Product Data Book
52 * TMS 9995 16-Bit Microcomputer Data Manual
53 
54 Tons of thanks to the guy who posted these, whoever he is...
55 <http://www.stormaster.com/Spies/arcade/simulation/processors/index.html>
56 */
57 
58 /* Set this to 1 to support HOLD_LINE */
59 /* This is a weird HOLD_LINE, actually : we hold the interrupt line only until IAQ
60 	(instruction acquisition) is enabled.  Well, this scheme could possibly exist on
61 	a tms9900-based system, unlike a real HOLD_LINE.  (OK, this is just a pretext, I was just too
62 	lazy to implement a true HOLD_LINE ;-) .) */
63 /* BTW, this only works with tms9900 ! */
64 #define SILLY_INTERRUPT_HACK 0
65 
66 #if SILLY_INTERRUPT_HACK
67 	#define IRQ_MAGIC_LEVEL -2
68 #endif
69 
70 
71 #include "memory.h"
72 #include "tms9900.h"
73 #include <math.h>
74 
75 #include <retro_inline.h>
76 
77 
78 #if (TMS99XX_MODEL == TMS9900_ID)
79 
80 	#define TMS99XX_ICOUNT tms9900_ICount
81 	#define TMS99XX_RESET tms9900_reset
82 	#define TMS99XX_EXIT tms9900_exit
83 	#define TMS99XX_EXECUTE tms9900_execute
84 	#define TMS99XX_GET_CONTEXT tms9900_get_context
85 	#define TMS99XX_SET_CONTEXT tms9900_set_context
86 	#define TMS99XX_GET_PC tms9900_get_pc
87 	#define TMS99XX_SET_PC tms9900_set_pc
88 	#define TMS99XX_GET_SP tms9900_get_sp
89 	#define TMS99XX_SET_SP tms9900_set_sp
90 	#define TMS99XX_GET_REG tms9900_get_reg
91 	#define TMS99XX_SET_REG tms9900_set_reg
92 	#define TMS99XX_SET_IRQ_CALLBACK tms9900_set_irq_callback
93 	#define TMS99XX_INFO tms9900_info
94 	#define TMS99XX_DASM tms9900_dasm
95 
96 	#define TMS99XX_CPU_NAME "TMS9900"
97 
98 #elif (TMS99XX_MODEL == TMS9940_ID)
99 
100 	#define TMS99XX_ICOUNT tms9940_ICount
101 	#define TMS99XX_RESET tms9940_reset
102 	#define TMS99XX_EXIT tms9940_exit
103 	#define TMS99XX_EXECUTE tms9940_execute
104 	#define TMS99XX_GET_CONTEXT tms9940_get_context
105 	#define TMS99XX_SET_CONTEXT tms9940_set_context
106 	#define TMS99XX_GET_PC tms9940_get_pc
107 	#define TMS99XX_SET_PC tms9940_set_pc
108 	#define TMS99XX_GET_SP tms9940_get_sp
109 	#define TMS99XX_SET_SP tms9940_set_sp
110 	#define TMS99XX_GET_REG tms9940_get_reg
111 	#define TMS99XX_SET_REG tms9940_set_reg
112 	#define TMS99XX_SET_IRQ_CALLBACK tms9940_set_irq_callback
113 	#define TMS99XX_INFO tms9940_info
114 	#define TMS99XX_DASM tms9940_dasm
115 
116 	#define TMS99XX_CPU_NAME "TMS9940"
117 
118 	#error "tms9940 is not yet supported"
119 
120 #elif (TMS99XX_MODEL == TMS9980_ID)
121 
122 	#define TMS99XX_ICOUNT tms9980a_ICount
123 	#define TMS99XX_RESET tms9980a_reset
124 	#define TMS99XX_EXIT tms9980a_exit
125 	#define TMS99XX_EXECUTE tms9980a_execute
126 	#define TMS99XX_GET_CONTEXT tms9980a_get_context
127 	#define TMS99XX_SET_CONTEXT tms9980a_set_context
128 	#define TMS99XX_GET_PC tms9980a_get_pc
129 	#define TMS99XX_SET_PC tms9980a_set_pc
130 	#define TMS99XX_GET_SP tms9980a_get_sp
131 	#define TMS99XX_SET_SP tms9980a_set_sp
132 	#define TMS99XX_GET_REG tms9980a_get_reg
133 	#define TMS99XX_SET_REG tms9980a_set_reg
134 	#define TMS99XX_SET_IRQ_CALLBACK tms9980a_set_irq_callback
135 	#define TMS99XX_INFO tms9980a_info
136 	#define TMS99XX_DASM tms9980a_dasm
137 
138 	#define TMS99XX_CPU_NAME "TMS9980A/TMS9981"
139 
140 #elif (TMS99XX_MODEL == TMS9985_ID)
141 
142 	#define TMS99XX_ICOUNT tms9985_ICount
143 	#define TMS99XX_RESET tms9985_reset
144 	#define TMS99XX_EXIT tms9985_exit
145 	#define TMS99XX_EXECUTE tms9985_execute
146 	#define TMS99XX_GET_CONTEXT tms9985_get_context
147 	#define TMS99XX_SET_CONTEXT tms9985_set_context
148 	#define TMS99XX_GET_PC tms9985_get_pc
149 	#define TMS99XX_SET_PC tms9985_set_pc
150 	#define TMS99XX_GET_SP tms9985_get_sp
151 	#define TMS99XX_SET_SP tms9985_set_sp
152 	#define TMS99XX_GET_REG tms9985_get_reg
153 	#define TMS99XX_SET_REG tms9985_set_reg
154 	#define TMS99XX_SET_IRQ_CALLBACK tms9985_set_irq_callback
155 	#define TMS99XX_INFO tms9985_info
156 	#define TMS99XX_DASM tms9985_dasm
157 
158 	#define TMS99XX_CPU_NAME "TMS9985"
159 
160 	#error "tms9985 is not yet supported"
161 
162 #elif (TMS99XX_MODEL == TMS9989_ID)
163 
164 	#define TMS99XX_ICOUNT tms9989_ICount
165 	#define TMS99XX_RESET tms9989_reset
166 	#define TMS99XX_EXIT tms9989_exit
167 	#define TMS99XX_EXECUTE tms9989_execute
168 	#define TMS99XX_GET_CONTEXT tms9989_get_context
169 	#define TMS99XX_SET_CONTEXT tms9989_set_context
170 	#define TMS99XX_GET_PC tms9989_get_pc
171 	#define TMS99XX_SET_PC tms9989_set_pc
172 	#define TMS99XX_GET_SP tms9989_get_sp
173 	#define TMS99XX_SET_SP tms9989_set_sp
174 	#define TMS99XX_GET_REG tms9989_get_reg
175 	#define TMS99XX_SET_REG tms9989_set_reg
176 	#define TMS99XX_SET_IRQ_CALLBACK tms9989_set_irq_callback
177 	#define TMS99XX_INFO tms9989_info
178 	#define TMS99XX_DASM tms9989_dasm
179 
180 	#define TMS99XX_CPU_NAME "TMS9989"
181 
182 	#error "tms9989 is not yet supported"
183 
184 #elif (TMS99XX_MODEL == TMS9995_ID)
185 
186 	#define TMS99XX_ICOUNT tms9995_ICount
187 	#define TMS99XX_RESET tms9995_reset
188 	#define TMS99XX_EXIT tms9995_exit
189 	#define TMS99XX_EXECUTE tms9995_execute
190 	#define TMS99XX_GET_CONTEXT tms9995_get_context
191 	#define TMS99XX_SET_CONTEXT tms9995_set_context
192 	#define TMS99XX_GET_PC tms9995_get_pc
193 	#define TMS99XX_SET_PC tms9995_set_pc
194 	#define TMS99XX_GET_SP tms9995_get_sp
195 	#define TMS99XX_SET_SP tms9995_set_sp
196 	#define TMS99XX_GET_REG tms9995_get_reg
197 	#define TMS99XX_SET_REG tms9995_set_reg
198 	#define TMS99XX_SET_IRQ_CALLBACK tms9995_set_irq_callback
199 	#define TMS99XX_INFO tms9995_info
200 	#define TMS99XX_DASM tms9995_dasm
201 
202 	#define TMS99XX_CPU_NAME "TMS9995"
203 
204 #elif (TMS99XX_MODEL == TMS99105A_ID)
205 
206 	#define TMS99XX_ICOUNT tms99105a_ICount
207 	#define TMS99XX_RESET tms99105a_reset
208 	#define TMS99XX_EXIT tms99105a_exit
209 	#define TMS99XX_EXECUTE tms99105a_execute
210 	#define TMS99XX_GET_CONTEXT tms99105a_get_context
211 	#define TMS99XX_SET_CONTEXT tms99105a_set_context
212 	#define TMS99XX_GET_PC tms99105a_get_pc
213 	#define TMS99XX_SET_PC tms99105a_set_pc
214 	#define TMS99XX_GET_SP tms99105a_get_sp
215 	#define TMS99XX_SET_SP tms99105a_set_sp
216 	#define TMS99XX_GET_REG tms99105a_get_reg
217 	#define TMS99XX_SET_REG tms99105a_set_reg
218 	#define TMS99XX_SET_IRQ_CALLBACK tms99105a_set_irq_callback
219 	#define TMS99XX_INFO tms99105a_info
220 	#define TMS99XX_DASM tms99105a_dasm
221 
222 	#define TMS99XX_CPU_NAME "TMS99105A"
223 
224 	#error "tms99105a is not yet supported"
225 
226 #elif (TMS99XX_MODEL == TMS99110A_ID)
227 
228 	#define TMS99XX_ICOUNT tms99110a_ICount
229 	#define TMS99XX_RESET tms99110a_reset
230 	#define TMS99XX_EXIT tms99110a_exit
231 	#define TMS99XX_EXECUTE tms99110a_execute
232 	#define TMS99XX_GET_CONTEXT tms99110a_get_context
233 	#define TMS99XX_SET_CONTEXT tms99110a_set_context
234 	#define TMS99XX_GET_PC tms99110a_get_pc
235 	#define TMS99XX_SET_PC tms99110a_set_pc
236 	#define TMS99XX_GET_SP tms99110a_get_sp
237 	#define TMS99XX_SET_SP tms99110a_set_sp
238 	#define TMS99XX_GET_REG tms99110a_get_reg
239 	#define TMS99XX_SET_REG tms99110a_set_reg
240 	#define TMS99XX_SET_IRQ_CALLBACK tms99110a_set_irq_callback
241 	#define TMS99XX_INFO tms99110a_info
242 	#define TMS99XX_DASM tms99110a_dasm
243 
244 	#define TMS99XX_CPU_NAME "TMS99110A"
245 
246 	#error "tms99110a is not yet supported"
247 
248 #endif
249 
250 
251 static INLINE void execute(UINT16 opcode);
252 
253 static void external_instruction_notify(int ext_op_ID);
254 static UINT16 fetch(void);
255 static UINT16 decipheraddr(UINT16 opcode);
256 static UINT16 decipheraddrbyte(UINT16 opcode);
257 static void contextswitch(UINT16 addr);
258 
259 static void field_interrupt(void);
260 
261 /***************************/
262 /* Mame Interface Routines */
263 /***************************/
264 
265 int TMS99XX_ICOUNT = 0;
266 
267 
268 /* tms9900 ST register bits. */
269 
270 /* These bits are set by every compare, move and arithmetic or logical operation : */
271 /* (Well, COC, CZC and TB only set the E bit, but these are kind of exceptions.) */
272 #define ST_LGT 0x8000 /* Logical Greater Than (strictly) */
273 #define ST_AGT 0x4000 /* Arithmetical Greater Than (strictly) */
274 #define ST_EQ  0x2000 /* Equal */
275 
276 /* These bits are set by arithmetic operations, when it makes sense to update them. */
277 #define ST_C   0x1000 /* Carry */
278 #define ST_OV  0x0800 /* OVerflow (overflow with operations on signed integers, */
279                       /* and when the result of a 32bits:16bits division cannot fit in a 16-bit word.) */
280 
281 /* This bit is set by move and arithmetic operations WHEN THEY USE BYTE OPERANDS. */
282 #define ST_OP  0x0400 /* Odd Parity */
283 
284 #if (TMS99XX_MODEL != TMS9940_ID)
285 
286 /* This bit is set by the XOP instruction. */
287 #define ST_X   0x0200 /* Xop */
288 
289 #endif
290 
291 #if (TMS99XX_MODEL == TMS9940_ID)
292 
293 /* This bit is set by arithmetic operations to support BCD */
294 #define ST_DC  0x0100 /* Digit Carry */
295 
296 #endif
297 
298 #if (TMS99XX_MODEL == TMS99105A_ID)
299 
300 /* This bit is set in user (i.e. non-supervisor) mode */
301 #define ST_PRIVILEGED 0x0100
302 
303 #endif
304 
305 #if (TMS99XX_MODEL >= TMS9995_ID)
306 
307 /* This bit is set in TMS9995 and later chips to generate a level-2 interrupt when the Overflow
308 status bit is set */
309 #define ST_OV_EN 0x0020 /* OVerflow interrupt ENable */
310 
311 #endif
312 
313 /* On models before TMS9995 (TMS9989 ?), unused ST bits are always forced to 0, so we define
314 a ST_MASK */
315 #if TMS99XX_MODEL == TMS9940_ID
316 
317 #define ST_MASK 0xFD03
318 
319 #elif TMS99XX_MODEL <= TMS9985_ID
320 
321 #define ST_MASK 0xFE0F
322 
323 #endif
324 
325 
326 /* Offsets for registers. */
327 #define R0   0
328 #define R1   2
329 #define R2   4
330 #define R3   6
331 #define R4   8
332 #define R5  10
333 #define R6  12
334 #define R7  14
335 #define R8  16
336 #define R9  18
337 #define R10 20
338 #define R11 22
339 #define R12 24
340 #define R13 26
341 #define R14 28
342 #define R15 30
343 
344 typedef struct
345 {
346 /* "actual" tms9900 registers : */
347 	UINT16 WP;  /* Workspace pointer */
348 	UINT16 PC;  /* Program counter */
349 	UINT16 STATUS;  /* STatus register */
350 
351 /* Now, data used for emulation */
352 	UINT16 IR;  /* Instruction register, with the currently parsed opcode */
353 
354 	int interrupt_pending;  /* true if an interrupt must be honored... */
355 
356 	int load_state; /* nonzero if the LOAD* line is active (low) */
357 
358 #if ((TMS99XX_MODEL == TMS9900_ID) || (TMS99XX_MODEL == TMS9980_ID))
359 	/* On tms9900, we cache the state of INTREQ* and IC0-IC3 here */
360 	/* On tms9980/9981, we translate the state of IC0-IC2 to the equivalent state for a tms9900,
361 	and store the result here */
362 	int irq_level;	/* when INTREQ* is active, interrupt level on IC0-IC3 ; else always 16 */
363 	int irq_state;	/* nonzero if the INTREQ* line is active (low) */
364 #elif (TMS99XX_MODEL == TMS9995_ID)
365 	/* tms9995 is quite different : it latches the interrupt inputs */
366 	int irq_level;    /* We store the level of the request with the highest level here */
367 	int int_state;    /* interrupt lines state */
368 	int int_latch;	  /* interrupt latches state */
369 #endif
370 
371 	/* interrupt callback */
372 	/* note that this callback is used by tms9900_set_irq_line() and tms9980a_set_irq_line() to
373 	retreive the value on IC0-IC3 (non-standard behaviour) */
374 	int (*irq_callback)(int irq_line);
375 
376 	int IDLE;       /* nonzero if processor is IDLE - i.e waiting for interrupt while writing
377 	                    special data on CRU bus */
378 
379 #if (TMS99XX_MODEL == TMS9985_ID) || (TMS99XX_MODEL == TMS9995_ID)
380 	unsigned char RAM[256]; /* on-chip RAM (yes, sir !) */
381 #endif
382 
383 #if (TMS99XX_MODEL == TMS9995_ID)
384 	/* on-chip event counter/timer*/
385 	int decrementer_enabled;
386 	UINT16 decrementer_interval;
387 	UINT16 decrementer_count;	/* used in event counter mode*/
388 	void *timer;  /* used in timer mode */
389 #endif
390 
391 #if (TMS99XX_MODEL == TMS9995_ID)
392 	/* additionnal registers */
393 	UINT16 flag; 	  /* flag register */
394 	int MID_flag;   /* MID flag register */
395 #endif
396 
397 #if (TMS99XX_MODEL == TMS9995_ID)
398 	/* chip config, which can be set on reset */
399 	int memory_wait_states_byte;
400 	int memory_wait_states_word;
401 #endif
402 }	tms99xx_Regs;
403 
404 static tms99xx_Regs I =
405 {
406 	0,0,0,0,  /* don't care */
407 	0,        /* no pending interrupt */
408 	0,        /* LOAD* inactive */
409   16, 0,    /* INTREQ* inactive */
410 };
411 static UINT8 lastparity;  /* rather than handling ST_OP directly, we copy the last value which
412                                   would set it here */
413 /* Some instructions (i.e. XOP, BLWP, and MID) disable interrupt recognition until another
414 instruction is executed : so they set this flag */
415 static int disable_interrupt_recognition = 0;
416 
417 #if (TMS99XX_MODEL == TMS9995_ID)
418 static void reset_decrementer(void);
419 #endif
420 
421 #if (TMS99XX_MODEL == TMS9900_ID)
422 	/*16-bit data bus, 16-bit address bus*/
423 	/*Note that tms9900 actually never accesses a single byte : when performing byte operations,
424 	it reads a 16-bit word, changes the revelant byte, then write a complete word.  You should
425 	remember this when writing memory handlers.*/
426 	/*This does not apply to tms9995 and tms99xxx, but does apply to tms9980 (see below).*/
427 
428 	#define readword(addr)        cpu_readmem16bew_word(addr)
429 	#define writeword(addr,data)  cpu_writemem16bew_word((addr), (data))
430 
431 	#define readbyte(addr)        cpu_readmem16bew(addr)
432 	#define writebyte(addr,data)  cpu_writemem16bew((addr),(data))
433 
434 #elif (TMS99XX_MODEL == TMS9980_ID)
435 	/*8-bit data bus, 14-bit address*/
436 	/*Note that tms9980 never accesses a single byte (however crazy it may seem).  Although this
437 	makes memory access slower, I have emulated this feature, because if I did otherwise,
438 	there would be some implementation problems in some driver sooner or later.*/
439 
440 	/*Macros instead of true 14-bit handlers.  You may want to change this*/
441 	#define cpu_readmem14(addr) cpu_readmem16((addr) & 0x3fff)
442 	#define cpu_writemem14(addr, data) cpu_writemem16((addr) & 0x3fff, data)
443 
444 	#define readword(addr)        ( TMS99XX_ICOUNT -= 2, (cpu_readmem14(addr) << 8) + cpu_readmem14((addr)+1) )
445 	#define writeword(addr,data)  { TMS99XX_ICOUNT -= 2; cpu_writemem14((addr), (data) >> 8); cpu_writemem14((addr) + 1, (data) & 0xff); }
446 
447 #if 0
448 	#define readbyte(addr)        (TMS99XX_ICOUNT -= 2, cpu_readmem14(addr))
449 	#define writebyte(addr,data)  { TMS99XX_ICOUNT -= 2; cpu_writemem14((addr),(data)); }
450 #else
451 	/*This is how it really works*/
452 	/*Note that every writebyte must match a readbyte (which is the case on a real-world tms9980)*/
453 	static int extra_byte;
454 
readbyte(int addr)455 	static int readbyte(int addr)
456 	{
457 		TMS99XX_ICOUNT -= 2;
458 		if (addr & 1)
459 		{
460 			extra_byte = cpu_readmem14(addr-1);
461 			return cpu_readmem14(addr);
462 		}
463 		else
464 		{
465 			int val = cpu_readmem14(addr);
466 			extra_byte = cpu_readmem14(addr+1);
467 			return val;
468 		}
469 	}
writebyte(int addr,int data)470 	static void writebyte (int addr, int data)
471 	{
472 		TMS99XX_ICOUNT -= 2;
473 		if (addr & 1)
474 		{
475 			extra_byte = cpu_readmem14(addr-1);
476 
477 			cpu_writemem14(addr-1, extra_byte);
478 			cpu_writemem14(addr, data);
479 		}
480 		else
481 		{
482 			extra_byte = cpu_readmem14(addr+1);
483 
484 			cpu_writemem14(addr, data);
485 			cpu_writemem14(addr+1, extra_byte);
486 		}
487 	}
488 #endif
489 
490 #elif (TMS99XX_MODEL == TMS9995_ID)
491 	/*8-bit external data bus, with on-chip 16-bit RAM, and 16-bit address bus*/
492 	/*The code is complex, so we use functions rather than macros*/
493 
494 	/* Why aren't these in memory.h ??? */
495 #ifdef MSB_FIRST
496 	#define BYTE_XOR_BE(a) (a)
497 #else
498 	#define BYTE_XOR_BE(a) ((a) ^ 1)
499 #endif
500 
readword(int addr)501 	static int readword(int addr)
502 	{
503 		if (addr < 0xf000)
504 		{
505 			TMS99XX_ICOUNT -= I.memory_wait_states_word;
506 			return (cpu_readmem16(addr) << 8) + cpu_readmem16(addr + 1);
507 		}
508 		else if (addr < 0xf0fc)
509 		{
510 			return READ_WORD(& I.RAM[addr - 0xf000]);
511 		}
512 		else if (addr < 0xfffa)
513 		{
514 			TMS99XX_ICOUNT -= I.memory_wait_states_word;
515 			return (cpu_readmem16(addr) << 8) + cpu_readmem16(addr + 1);
516 		}
517 		else if (addr < 0xfffc)
518 		{
519 			/* read decrementer */
520 			if (I.flag & 1)
521 				/* event counter mode */
522 				return I.decrementer_count;
523 			else if (I.timer)
524 				/* timer mode, timer enabled */
525 				//return ceil(TIME_TO_CYCLES(cpu_getactivecpu(), timer_timeleft(I.timer)) / 16);
526 				return TIME_TO_CYCLES(cpu_getactivecpu(), timer_timeleft(I.timer)) / 16;
527 			else
528 				/* timer mode, timer disabled */
529 				return 0;
530 		}
531 		else
532 		{
533 			return READ_WORD(& I.RAM[addr - 0xff00]);
534 		}
535 	}
536 
writeword(int addr,int data)537 	static void writeword (int addr, int data)
538 	{
539 		if (addr < 0xf000)
540 		{
541 			TMS99XX_ICOUNT -= I.memory_wait_states_word;
542 			cpu_writemem16(addr, data >> 8);
543 			cpu_writemem16(addr + 1, data & 0xff);
544 		}
545 		else if (addr < 0xf0fc)
546 		{
547 			WRITE_WORD(& I.RAM[addr - 0xf000], data);
548 		}
549 		else if (addr < 0xfffa)
550 		{
551 			TMS99XX_ICOUNT -= I.memory_wait_states_word;
552 			cpu_writemem16(addr, data >> 8);
553 			cpu_writemem16(addr + 1, data & 0xff);
554 		}
555 		else if (addr < 0xfffc)
556 		{
557 			/* write decrementer */
558 			I.decrementer_interval = data;
559 			reset_decrementer();
560 		}
561 		else
562 		{
563 			WRITE_WORD(& I.RAM[addr - 0xff00], data);
564 		}
565 	}
566 
readbyte(int addr)567 	static int readbyte(int addr)
568 	{
569 		if (addr < 0xf000)
570 		{
571 			TMS99XX_ICOUNT -= I.memory_wait_states_byte;
572 			return cpu_readmem16(addr);
573 		}
574 		else if (addr < 0xf0fc)
575 		{
576 			return I.RAM[BYTE_XOR_BE(addr - 0xf000)];
577 		}
578 		else if (addr < 0xfffa)
579 		{
580 			TMS99XX_ICOUNT -= I.memory_wait_states_byte;
581 			return cpu_readmem16(addr);;
582 		}
583 		else if (addr < 0xfffc)
584 		{
585 			/* read decrementer */
586 			int value;
587 
588 			if (I.flag & 1)
589 				/* event counter mode */
590 				value = I.decrementer_count;
591 			else if (I.timer)
592 				/* timer mode, timer enabled */
593 				//value = ceil(TIME_TO_CYCLES(cpu_getactivecpu(), timer_timeleft(I.timer)) / 16);
594 				value = TIME_TO_CYCLES(cpu_getactivecpu(), timer_timeleft(I.timer)) / 16;
595 			else
596 				/* timer mode, timer disabled */
597 				value = 0;
598 
599 			if (addr & 1)
600 				return (value & 0xFF);
601 			else
602 				return (value >> 8);
603 		}
604 		else
605 		{
606 			return I.RAM[BYTE_XOR_BE(addr - 0xff00)];
607 		}
608 	}
609 
writebyte(int addr,int data)610 	static void writebyte (int addr, int data)
611 	{
612 		if (addr < 0xf000)
613 		{
614 			TMS99XX_ICOUNT -= I.memory_wait_states_byte;
615 			cpu_writemem16(addr, data);
616 		}
617 		else if (addr < 0xf0fc)
618 		{
619 			I.RAM[BYTE_XOR_BE(addr - 0xf000)] = data;
620 		}
621 		else if (addr < 0xfffa)
622 		{
623 			TMS99XX_ICOUNT -= I.memory_wait_states_byte;
624 			cpu_writemem16(addr, data);
625 		}
626 		else if (addr < 0xfffc)
627 		{
628 			/* write decrementer */
629 			/* Note that a byte write to tms9995 timer messes everything up. */
630 			I.decrementer_interval = (data << 8) | data;
631 			reset_decrementer();
632 		}
633 		else
634 		{
635 			I.RAM[BYTE_XOR_BE(addr - 0xff00)] = data;
636 		}
637 	}
638 
639 #else
640 
641 	#error "memory access not implemented"
642 
643 #endif
644 
645 #define READREG(reg)          readword(I.WP+reg)
646 #define WRITEREG(reg,data)    writeword(I.WP+reg,data)
647 
648 /* Interrupt mask */
649 #if (TMS99XX_MODEL != TMS9940_ID)
650 	#define IMASK       (I.STATUS & 0x0F)
651 #else
652 	#define IMASK       (I.STATUS & 0x03)
653 #endif
654 
655 /*
656 	CYCLES macro : you provide timings for tms9900 and tms9995, and the macro chooses for you.
657 
658 	BTW, I have no idea what the timings are for tms9989 and tms99xxx...
659 */
660 #if TMS99XX_MODEL <= TMS9989_ID
661 	/* Use TMS9900/TMS9980 timings*/
662 	#define CYCLES(a,b) TMS99XX_ICOUNT -= a
663 #else
664 	/* Use TMS9995 timings*/
665 	#define CYCLES(a,b) TMS99XX_ICOUNT -= b*4
666 #endif
667 
668 #if (TMS99XX_MODEL == TMS9995_ID)
669 
670 static void set_flag0(int val);
671 static void set_flag1(int val);
672 
673 #endif
674 
675 /************************************************************************
676  * Status register functions
677  ************************************************************************/
678 #include "99xxstat.h"
679 
680 /**************************************************************************/
681 
682 /*
683 	TMS9900 hard reset
684 */
TMS99XX_RESET(void * param)685 void TMS99XX_RESET(void *param)
686 {
687 	contextswitch(0x0000);
688 
689 	I.STATUS = 0; /* TMS9980 and TMS9995 Data Book say so */
690 	setstat();
691 
692 	I.IDLE = 0;   /* clear IDLE condition */
693 
694 #if (TMS99XX_MODEL == TMS9995_ID)
695 	/* we can ask at reset time that the CPU always generates one wait state automatically */
696 	if (param == NULL)
697 	{	/* if no param, the default is currently "wait state added" */
698 		I.memory_wait_states_byte = 4;
699 		I.memory_wait_states_word = 12;
700 	}
701 	else
702 	{
703 		I.memory_wait_states_byte = (((tms9995reset_param *) param)->auto_wait_state) ? 4 : 0;
704 		I.memory_wait_states_word = (((tms9995reset_param *) param)->auto_wait_state) ? 12 : 4;
705 	}
706 
707 	I.MID_flag = 0;
708 
709 	/* Clear flag bits 0 & 1 */
710 	set_flag0(0);
711 	set_flag1(0);
712 
713 	/* Clear internal interupt latches */
714 	I.int_latch = 0;
715 	I.flag &= 0xFFE3;
716 #endif
717 
718 	/* The ST register and interrupt latches changed, didn't it ? */
719 	field_interrupt();
720 
721 	CYCLES(26, 14);
722 }
723 
TMS99XX_EXIT(void)724 void TMS99XX_EXIT(void)
725 {
726 	/* nothing to do ? */
727 }
728 
TMS99XX_EXECUTE(int cycles)729 int TMS99XX_EXECUTE(int cycles)
730 {
731 	TMS99XX_ICOUNT = cycles;
732 
733 	do
734 	{
735 		if (I.IDLE)
736 		{	/* IDLE instruction has halted execution */
737 			external_instruction_notify(2);
738 			CYCLES(2, 2); /* 2 cycles per CRU write */
739 		}
740 		else
741 		{	/* we execute an instruction */
742 			disable_interrupt_recognition = 0;  /* default value */
743 			I.IR = fetch();
744 			execute(I.IR);
745 
746 #if (TMS99XX_MODEL >= TMS9995_ID)
747 			/* Note that TI had some problem implementing this...  I don't know if this feature works on
748 			a real-world TMS9995. */
749 			if ((I.STATUS & ST_OV_EN) && (I.STATUS & ST_OV) && (I.irq_level > 2))
750 				I.irq_level = 2;  /* interrupt request */
751 #endif
752 		}
753 
754 		/*
755 		  We handle interrupts here because :
756 		  a) LOAD and level-0 (reset) interrupts are non-maskable, so, AFAIK, if the LOAD* line or
757 		     INTREQ* line (with IC0-3 == 0) remain active, we will execute repeatedly the first
758 		     instruction of the interrupt routine.
759 		  b) if we did otherwise, we could have weird, buggy behavior if IC0-IC3 changed more than
760 		     once in too short a while (i.e. before tms9900 executes another instruction).  Yes, this
761 		     is rather pedantic, the probability is really small.
762 		*/
763 		if (I.interrupt_pending)
764 		{
765 			int level;
766 
767 #if SILLY_INTERRUPT_HACK
768 			if (I.irq_level == IRQ_MAGIC_LEVEL)
769 			{
770 				level = (* I.irq_callback)(0);
771 				if (I.irq_state)
772 				{ /* if callback didn't clear the line */
773 					I.irq_level = level;
774 					if (level > IMASK)
775 						I.interrupt_pending = 0;
776 				}
777 			}
778 			else
779 #endif
780 			level = I.irq_level;
781 
782 			if (I.load_state)
783 			{	/* LOAD has the highest priority */
784 
785 				contextswitch(0xFFFC);  /* load vector, save PC, WP and ST */
786 
787 				I.STATUS &= 0xFFF0;     /* clear mask */
788 
789 				/* clear IDLE status if necessary */
790 				I.IDLE = 0;
791 
792 				CYCLES(22, 14);
793 			}
794 			/* all TMS9900 chips I know do not honor interrupts after XOP, BLWP or MID (after any
795 			  interrupt-like instruction, actually) */
796 			else if (! disable_interrupt_recognition)
797 			{
798 				if (level <= IMASK)
799 				{	/* a maskable interrupt is honored only if its level isn't greater than IMASK */
800 
801 					contextswitch(level*4); /* load vector, save PC, WP and ST */
802 
803 					/* change interrupt mask */
804 					if (level)
805 					{
806 						I.STATUS = (I.STATUS & 0xFFF0) | (level -1);  /* decrement mask */
807 						I.interrupt_pending = 0;  /* as a consequence, the interrupt request will be subsequently ignored */
808 					}
809 					else
810 						I.STATUS &= 0xFFF0; /* clear mask (is this correct ???) */
811 
812 #if (TMS99XX_MODEL == TMS9995_ID)
813 					I.STATUS &= 0xFE00;
814 #endif
815 
816 					/* clear IDLE status if necessary */
817 					I.IDLE = 0;
818 
819 #if (TMS99XX_MODEL == TMS9995_ID)
820 					/* Clear bit in latch */
821 					/* I think tms9989 does this, too */
822 					if (level != 2)
823 					{	/* Only do this on level 1, 3, 4 interrupts */
824 						int mask = 1 << level;
825 						int flag_mask = (level == 1) ? 4 : mask;
826 
827 						I.int_latch &= ~ mask;
828 						I.flag &= ~ flag_mask;
829 
830 						/* unlike tms9900, we can call the callback */
831 						if (level == 1)
832 							(* I.irq_callback)(0);
833 						else if (level == 4)
834 							(* I.irq_callback)(1);
835 					}
836 #endif
837 
838 					CYCLES(22, 14);
839 				}
840 				else
841 #if SILLY_INTERRUPT_HACK
842 				if (I.interrupt_pending)  /* we may have just cleared this */
843 #endif
844 				{
845 					//logerror("tms9900.c : the interrupt_pending flag was set incorrectly\n");
846 					I.interrupt_pending = 0;
847 				}
848 			}
849 		}
850 
851 	} while (TMS99XX_ICOUNT > 0);
852 
853 	return cycles - TMS99XX_ICOUNT;
854 }
855 
TMS99XX_GET_CONTEXT(void * dst)856 unsigned TMS99XX_GET_CONTEXT(void *dst)
857 {
858 	setstat();
859 
860 	if( dst )
861 		*(tms99xx_Regs*)dst = I;
862 
863 	return sizeof(tms99xx_Regs);
864 }
865 
TMS99XX_SET_CONTEXT(void * src)866 void TMS99XX_SET_CONTEXT(void *src)
867 {
868 	if( src )
869 	{
870 		I = *(tms99xx_Regs*)src;
871 		/* We have to make additionnal checks this, because Mame debugger can foolishly initialize
872 		the context to all 0s */
873 #if (TMS99XX_MODEL == TMS9900_ID)
874 		if (! I.irq_state)
875 			I.irq_level = 16;
876 #elif ((TMS99XX_MODEL == TMS9980_ID) || (TMS99XX_MODEL == TMS9995_ID))
877 		/* Our job is simpler, since there is no level-0 request... */
878 		if (! I.irq_level)
879 			I.irq_level = 16;
880 #else
881 		#warning "You may want to have a look at this problem"
882 #endif
883 
884 		getstat();  /* set last_parity */
885 	}
886 }
887 
TMS99XX_GET_PC(void)888 unsigned TMS99XX_GET_PC(void)
889 {
890 	return I.PC;
891 }
892 
TMS99XX_SET_PC(unsigned val)893 void TMS99XX_SET_PC(unsigned val)
894 {
895 	I.PC = val;
896 }
897 
898 /*
899 	Note : the WP register actually has nothing to do with a stack.
900 
901 	To make this even weirder, some later versions of the TMS9900 do have a processor stack.
902 */
TMS99XX_GET_SP(void)903 unsigned TMS99XX_GET_SP(void)
904 {
905 	return I.WP;
906 }
907 
TMS99XX_SET_SP(unsigned val)908 void TMS99XX_SET_SP(unsigned val)
909 {
910 	I.WP = val;
911 }
912 
TMS99XX_GET_REG(int regnum)913 unsigned TMS99XX_GET_REG(int regnum)
914 {
915 	switch( regnum )
916 	{
917 		case TMS9900_PC: return I.PC;
918 		case TMS9900_IR: return I.IR;
919 		case TMS9900_WP: return I.WP;
920 		case TMS9900_STATUS: return I.STATUS;
921 	}
922 	return 0;
923 }
924 
TMS99XX_SET_REG(int regnum,unsigned val)925 void TMS99XX_SET_REG(int regnum, unsigned val)
926 {
927 	switch( regnum )
928 	{
929 		case TMS9900_PC: I.PC = val; break;
930 		case TMS9900_IR: I.IR = val; break;
931 		case TMS9900_WP: I.WP = val; break;
932 		case TMS9900_STATUS: I.STATUS = val; break;
933 	}
934 }
935 
936 #if (TMS99XX_MODEL == TMS9900_ID)
937 
938 /*
939 void tms9900_set_nmi_line(int state) : change the state of the LOAD* line
940 
941 	state == 0 -> LOAD* goes high (inactive)
942 	state != 0 -> LOAD* goes low (active)
943 
944 	While LOAD* is low, we keep triggering LOAD interrupts...
945 
946 	A problem : some peripheral lower the LOAD* line for a fixed time interval (causing the 1st
947 	instruction of the LOAD interrupt routine to be repeated while the line is low), and will be
948 	perfectly happy with the current scheme, but others might be more clever and wait for the IAQ
949 	(Instruction acquisition) line to go high, and this needs a callback function to emulate.
950 */
tms9900_set_nmi_line(int state)951 void tms9900_set_nmi_line(int state)
952 {
953 	I.load_state = state;   /* save new state */
954 
955 	field_interrupt();  /* interrupt status changed */
956 }
957 
958 /*
959 void tms9900_set_irq_line(int irqline, int state) : sets the state of the interrupt line.
960 
961 	irqline is ignored, and should always be 0.
962 
963 	state == 0 -> INTREQ* goes high (inactive)
964 	state != 0 -> INTREQ* goes low (active)
965 */
966 /*
967 	R Nabet 991020, revised 991218 :
968 	In short : interrupt code should call "cpu_set_irq_line(0, 0, ASSERT_LINE);" to set an
969 	interrupt request (level-triggered interrupts).  Also, there MUST be a call to
970 	"cpu_set_irq_line(0, 0, CLEAR_LINE);" in the machine code, when the interrupt line is released by
971 	the hardware (generally in response to an action performed by the interrupt routines).
972 	On tms9995 (9989 ?), you can use PULSE_LINE, too, since the processor latches the line...
973 
974 	**Note** : HOLD_LINE *NEVER* makes sense on the TMS9900 (or 9980, 9995...).  The reason is the
975 	TMS9900 does NOT tell the world it acknoledges an interrupt, so no matter how much hardware you
976 	se, you cannot know when the CPU takes the interrupt, hence you cannot release the line when
977 	the CPU takes the interrupt.  Generally, the interrupt condition is cleared by the interrupt
978 	routine (with some CRU or memory access).
979 
980 	Note that cpu_generate_interrupt uses HOLD_LINE, so your driver interrupt code
981 	should always use the new style, i.e. return "ignore_interrupt()" and call
982 	"cpu_set_irq_line(0, 0, ASSERT_LINE);" explicitely.
983 
984 	Last, many TMS9900-based hardware use a TMS9901 interrupt-handling chip.  If anybody wants
985 	to emulate some hardware which uses it, note that I am writing some emulation in the TI99/4(A)
986 	driver in MESS, so you should ask me.
987 */
988 /*
989  * HJB 990430: changed to use irq_callback() to retrieve the vector
990  * instead of using 16 irqlines.
991  *
992  * R Nabet 990830 : My mistake, I rewrote all these once again ; I think it is now correct.
993  * A driver using the TMS9900 should do :
994  *		cpu_0_irq_line_vector_w(0, level);
995  *		cpu_set_irq_line(0,0,ASSERT_LINE);
996  *
997  * R Nabet 991108 : revised once again, with advice from Juergen Buchmueller, after a discussion
998  * with Nicola...
999  * We use the callback to retreive the interrupt level as soon as INTREQ* is asserted.
1000  * As a consequence, I do not support HOLD_LINE normally...  However, we do not really have to
1001  * support HOLD_LINE, since no real world TMS9900-based system can support this.
1002  * FYI, there are two alternatives to retreiving the interrupt level with the callback :
1003  * a) using 16 pseudo-IRQ lines.  Mostly OK, though it would require a few core changes.
1004  *    However, this could cause some problems if someone tried to set two lines simulteanously...
1005  *    And TMS9900 did NOT have 16 lines ! This is why Juergen and I did not retain this solution.
1006  * b) modifying the interrupt system in order to provide an extra int to every xxx_set_irq_line
1007  *    function.  I think this solution would be fine, but it would require quite a number of
1008  *    changes in the MAME core.  (And I did not feel the courage to check out 4000 drivers and 25
1009  *    cpu cores ;-) .)
1010  *
1011  * Note that this does not apply to tms9995.
1012 */
tms9900_set_irq_line(int irqline,int state)1013 void tms9900_set_irq_line(int irqline, int state)
1014 {
1015 	/*if (I.irq_state == state)
1016 		return;*/
1017 
1018 	I.irq_state = state;
1019 
1020 	if (state == CLEAR_LINE)
1021 		I.irq_level = 16;
1022 		/* trick : 16 will always be bigger than the IM (0-15), so there will never be interrupts */
1023 	else
1024 	{
1025 #if SILLY_INTERRUPT_HACK
1026 		I.irq_level = IRQ_MAGIC_LEVEL;
1027 #else
1028 		I.irq_level = (* I.irq_callback)(0);
1029 #endif
1030 	}
1031 
1032 	field_interrupt();  /* interrupt state is likely to have changed */
1033 }
1034 
1035 #elif (TMS99XX_MODEL == TMS9980_ID)
1036 /*
1037 	interrupt system similar to tms9900, but only 3 interrupt pins (IC0-IC2)
1038 */
1039 
tms9980a_set_nmi_line(int state)1040 void tms9980a_set_nmi_line(int state)
1041 {
1042 	/*no dedicated nmi line*/
1043 }
1044 
tms9980a_set_irq_line(int irqline,int state)1045 void tms9980a_set_irq_line(int irqline, int state)
1046 {
1047 	if (state == CLEAR_LINE)
1048 	{
1049 		I.load_state = 0;
1050 		I.irq_state = 0;
1051 		I.irq_level = 16;
1052 		/* trick : 16 will always be bigger than the IM (0-15), so there will never be interrupts */
1053 	}
1054 	else
1055 	{
1056 #if SILLY_INTERRUPT_HACK
1057 		#error "OK, this does not work with tms9980a"
1058 		/*I.load_state = 0;
1059 		I.irq_state = 1;
1060 		I.irq_level = IRQ_MAGIC_LEVEL;*/
1061 #else
1062 		int level;
1063 
1064 		level = (* I.irq_callback)(0);
1065 
1066 		switch (level)
1067 		{
1068 		case 0:
1069 		case 1:
1070 			I.load_state = 0;
1071 			I.irq_state = 0;
1072 			I.irq_level = 16;
1073 			tms9980a_reset(NULL);
1074 			break;
1075 		case 2:
1076 			I.load_state = 1;
1077 			I.irq_state = 0;
1078 			I.irq_level = 16;
1079 			break;
1080 		case 7:
1081 			I.load_state = 0;
1082 			I.irq_state = 0;
1083 			I.irq_level = 16;
1084 			break;
1085 		default:  /* external levels 1, 2, 3, 4 */
1086 			I.load_state = 0;
1087 			I.irq_state = 1;
1088 			I.irq_level = level - 2;
1089 			break;
1090 		}
1091 #endif
1092 	}
1093 
1094 	field_interrupt();  /* interrupt state is likely to have changed */
1095 }
1096 
1097 #elif (TMS99XX_MODEL == TMS9995_ID)
1098 /*
1099 	we latch interrupts when they make an inactive to active transition
1100 */
1101 
tms9995_set_nmi_line(int state)1102 void tms9995_set_nmi_line(int state)
1103 {
1104 	I.load_state = state;   /* save new state */
1105 
1106 	field_interrupt();  /* interrupt status changed */
1107 }
1108 
1109 
1110 /*
1111   this call-back is called by MESS timer system when the timer reaches 0.
1112 */
decrementer_callback(int ignored)1113 static void decrementer_callback(int ignored)
1114 {
1115 	/* request decrementer interrupt */
1116 	I.int_latch |= 0x8;
1117 	I.flag |= 0x8;
1118 
1119 	field_interrupt();
1120 }
1121 
1122 
1123 /*
1124 	reset and load the timer/decrementer
1125 
1126 	Note that I don't know whether toggling flag0/flag1 causes the decrementer to be reloaded or not
1127 */
reset_decrementer(void)1128 static void reset_decrementer(void)
1129 {
1130 	if (I.timer)
1131 	{
1132 		timer_remove(I.timer);
1133 		I.timer = NULL;
1134 	}
1135 
1136 	/* decrementer / timer enabled ? */
1137 	I.decrementer_enabled = ((I.flag & 2) && (I.decrementer_interval));
1138 
1139 	if (I.decrementer_enabled)
1140 	{
1141 		if (I.flag & 1)
1142 		{	/* decrementer */
1143 			I.decrementer_count = I.decrementer_interval;
1144 		}
1145 		else
1146 		{	/* timer */
1147 			I.timer = timer_pulse(TIME_IN_CYCLES(I.decrementer_interval * 16L, cpu_getactivecpu()),
1148 			                        0, decrementer_callback);
1149 		}
1150 	}
1151 }
1152 
1153 /*
1154 	You have two interrupt line : one triggers level-1 interrupts, the other triggers level-4
1155 	interrupts (or decrements the decrementer register).
1156 
1157 	According to the hardware, you may use PULSE_LINE (edge-triggered interrupts), or ASSERT_LINE
1158 	(level-triggered interrupts).  Edge-triggered interrupts are way simpler, but if multiple devices
1159 	share the same line, they must use level-triggered interrupts.
1160 */
tms9995_set_irq_line(int irqline,int state)1161 void tms9995_set_irq_line(int irqline, int state)
1162 {
1163 	int mask = (irqline == 0) ? 0x2 : 0x10;
1164 	int flag_mask = (irqline == 0) ? 0x4 : 0x10;
1165 
1166 	if (((I.int_state & mask) != 0) ^ (state != 0))
1167 	{	/* only if state changes */
1168 		if (state)
1169 		{
1170 			I.int_state |= mask;
1171 
1172 			if ((irqline == 1) && (I.flag & 1))
1173 			{	/* event counter mode : INT4* triggers no interrupt... */
1174 				if (I.decrementer_enabled)
1175 				{	/* decrement, then interrupt if reach 0 */
1176 					if ((-- I.decrementer_count) == 0)
1177 					{
1178 						decrementer_callback(0);
1179 						I.decrementer_count = I.decrementer_interval;	/* reload */
1180 					}
1181 				}
1182 			}
1183 			else
1184 			{	/* plain interrupt mode */
1185 				I.int_latch |= mask;
1186 				I.flag |= flag_mask;
1187 			}
1188 		}
1189 		else
1190 		{
1191 			I.int_state &= ~ mask;
1192 		}
1193 
1194 		field_interrupt();  /* interrupt status changed */
1195 	}
1196 }
1197 
1198 #else
1199 
1200 #error "interrupt system not implemented"
1201 
1202 #endif
1203 
TMS99XX_SET_IRQ_CALLBACK(int (* callback)(int irqline))1204 void TMS99XX_SET_IRQ_CALLBACK(int (*callback)(int irqline))
1205 {
1206 	I.irq_callback = callback;
1207 }
1208 
1209 /*
1210  * field_interrupt
1211  *
1212  * Determines whether if an interrupt is pending, and sets the revelant flag.
1213  *
1214  * Called when an interrupt pin (LOAD*, INTREQ*, IC0-IC3) is changed, and when the interrupt mask
1215  * is modified.
1216  *
1217  * By using this flag, we save some compares in the execution loop.  Subtle, isn't it ;-) ?
1218  *
1219  * R Nabet.
1220  */
1221 #if (TMS99XX_MODEL == TMS9900_ID) || (TMS99XX_MODEL == TMS9980_ID)
1222 
field_interrupt(void)1223 static void field_interrupt(void)
1224 {
1225 	I.interrupt_pending = ((I.irq_level <= IMASK) || (I.load_state));
1226 }
1227 
1228 #elif (TMS99XX_MODEL == TMS9995_ID)
1229 
field_interrupt(void)1230 static void field_interrupt(void)
1231 {
1232 	if (I.load_state)
1233 	{
1234 		I.interrupt_pending = 1;
1235 	}
1236 	else
1237 	{
1238 		int current_int;
1239 		int level;
1240 
1241 		if (I.flag & 1)
1242 			/* event counter mode : ignore int4* line... */
1243 			current_int = (I.int_state & ~0x10) | I.int_latch;
1244 		else
1245 			/* normal behavior */
1246 			current_int = I.int_state | I.int_latch;
1247 
1248 		if (current_int)
1249 			/* find first bit to 1 */
1250 			/* possible values : 1, 3, 4 */
1251 			for (level=0; ! (current_int & 1); current_int >>= 1, level++)
1252 				;
1253 		else
1254 			level=16;
1255 
1256 		I.irq_level = level;
1257 
1258 		I.interrupt_pending = (level <= IMASK);
1259 	}
1260 }
1261 
1262 #else
1263 
1264 #error "field_interrupt() not written"
1265 
1266 #endif
1267 
1268 /****************************************************************************
1269  * Return a formatted string for a register
1270  ****************************************************************************/
TMS99XX_INFO(void * context,int regnum)1271 const char *TMS99XX_INFO(void *context, int regnum)
1272 {
1273 	switch( regnum )
1274 	{
1275 		case CPU_INFO_NAME: return TMS99XX_CPU_NAME;
1276 		case CPU_INFO_FAMILY: return "Texas Instruments 9900";
1277 		case CPU_INFO_VERSION: return "2.0";
1278 		case CPU_INFO_FILE: return __FILE__;
1279 		case CPU_INFO_CREDITS: return "C TMS9900 emulator by Edward Swartz, initially converted for Mame by M.Coates, updated by R. Nabet";
1280 	}
1281 	return "";
1282 }
1283 
TMS99XX_DASM(char * buffer,unsigned pc)1284 unsigned TMS99XX_DASM(char *buffer, unsigned pc)
1285 {
1286 	sprintf( buffer, "$%04X", readword(pc) );
1287 	return 2;
1288 }
1289 
1290 /**************************************************************************/
1291 
1292 #if (TMS99XX_MODEL == TMS9995_ID)
1293 
1294 /* set decrementer mode flag */
set_flag0(int val)1295 static void set_flag0(int val)
1296 {
1297 	if (val)
1298 		I.flag |= 1;
1299 	else
1300 		I.flag &= ~ 1;
1301 
1302 	reset_decrementer();
1303 }
1304 
1305 /* set decrementer enable flag */
set_flag1(int val)1306 static void set_flag1(int val)
1307 {
1308 	if (val)
1309 		I.flag |= 2;
1310 	else
1311 		I.flag &= ~ 2;
1312 
1313 	reset_decrementer();
1314 }
1315 
1316 #endif
1317 
1318 /*
1319 	performs a normal write to CRU bus (used by SBZ, SBO, LDCR : address range 0 -> 0xFFF)
1320 */
writeCRU(int CRUAddr,int Number,UINT16 Value)1321 static void writeCRU(int CRUAddr, int Number, UINT16 Value)
1322 {
1323 #if (TMS99XX_MODEL == TMS9900_ID)
1324 	/* 3 MSBs are always 0 to support external instructions */
1325 	#define wCRUAddrMask 0xFFF;
1326 #elif (TMS99XX_MODEL == TMS9980_ID)
1327 	/* 2 bits unused, and 2 MSBs are always 0 to support external instructions */
1328 	#define wCRUAddrMask 0x7FF;
1329 #elif (TMS99XX_MODEL == TMS9995_ID)
1330 	/* no such problem here : data bus lines D0-D2 provide the external instruction code */
1331 	#define wCRUAddrMask 0x7FFF;
1332 #else
1333 	#warning "I don't know how your processor handle CRU."
1334 	#define wCRUAddrMask 0x7FFF;
1335 #endif
1336 
1337 	int count;
1338 
1339 	//logerror("PC %4.4x Write CRU %x for %x =%x\n",I.PC,CRUAddr,Number,Value);
1340 
1341 	CRUAddr &= wCRUAddrMask;
1342 
1343 	/* Write Number bits from CRUAddr */
1344 
1345 	for(count=0; count<Number; count++)
1346 	{
1347 #if (TMS99XX_MODEL == TMS9995_ID)
1348 		if (CRUAddr == 0xF70)
1349 			set_flag0(Value & 0x01);
1350 		else if (CRUAddr == 0xF71)
1351 			set_flag1(Value & 0x01);
1352 		else if ((CRUAddr >= 0xF72) && (CRUAddr < 0xF75))
1353 			;     /* ignored */
1354 		else if ((CRUAddr >= 0xF75) && (CRUAddr < 0xF80))
1355 		{	/* user defined flags */
1356 			int mask = 1 << (CRUAddr - 0xF70);
1357 			if (Value & 0x01)
1358 				I.flag |= mask;
1359 			else
1360 				I.flag &= ~ mask;
1361 		}
1362 		else if (CRUAddr == 0x0FED)
1363 			/* MID flag */
1364 			I.MID_flag = Value & 0x01;
1365 		else
1366 			/* External CRU */
1367 #endif
1368 		cpu_writeport(CRUAddr, (Value & 0x01));
1369 		Value >>= 1;
1370 		CRUAddr = (CRUAddr + 1) & wCRUAddrMask;
1371 	}
1372 }
1373 
1374 /*
1375 	Some opcodes perform a dummy write to a special CRU address, so that an external function may be
1376 	triggered.
1377 
1378 	Only the first 3 MSBs of the address matter : other address bits and the written value itself
1379 	are undefined.
1380 
1381 	How should we support this ? With callback functions ? Actually, as long as we do not support
1382 	hardware which makes use of this feature, it does not really matter :-) .
1383 */
external_instruction_notify(int ext_op_ID)1384 static void external_instruction_notify(int ext_op_ID)
1385 {
1386 #if 1
1387 	/* I guess we can support this like normal CRU operations */
1388 #if (TMS99XX_MODEL == TMS9900_ID)
1389 	cpu_writeport(ext_op_ID << 12, 0); /* or is it 1 ??? */
1390 #elif (TMS99XX_MODEL == TMS9980_ID)
1391 	cpu_writeport((ext_op_ID & 3) << 11, (ext_op_ID & 4) ? 1 : 0);
1392 #elif (TMS99XX_MODEL == TMS9995_ID)
1393 	cpu_writeport(ext_op_ID << 15, 0); /* or is it 1 ??? */
1394 #else
1395 	#warning "I don't know how your processor handle external opcodes (maybe you don't need them, though)."
1396 #endif
1397 
1398 #else
1399 	switch (ext_op_ID)
1400 	{
1401 		case 2: /* IDLE */
1402 
1403 			break;
1404 		case 3: /* RSET */
1405 
1406 			break;
1407 		case 5: /* CKON */
1408 
1409 			break;
1410 		case 6: /* CKOF */
1411 
1412 			break;
1413 		case 7: /* LREX */
1414 
1415 			break;
1416 		case 0:
1417 			/* normal CRU write !!! */
1418 			//logerror("PC %4.4x : external_instruction_notify : wrong ext_op_ID",I.PC);
1419 			break;
1420 		default:
1421 			/* unknown address */
1422 			//logerror("PC %4.4x : external_instruction_notify : unknown ext_op_ID",I.PC);
1423 			break;
1424 	}
1425 #endif
1426 }
1427 
1428 /*
1429 	performs a normal read to CRU bus (used by TB, STCR : address range 0->0xFFF)
1430 
1431 	Note that on some hardware, e.g. TI99, all normal memory operations cause unwanted CRU
1432 	read at the same address.
1433 	This seems to be impossible to emulate efficiently.
1434 */
1435 #if (TMS99XX_MODEL != TMS9995_ID)
1436 #define READPORT(Port) cpu_readport(Port)
1437 #else
1438 /* on tms9995, we have to handle internal CRU port */
READPORT(int Port)1439 int READPORT(int Port)
1440 {
1441 	if (Port == 0x1EE)
1442 		/* flag, bits 0-7 */
1443 		return I.flag & 0xFF;
1444 	else if (Port == 0x1EF)
1445 		/* flag, bits 8-15 */
1446 		return (I.flag >> 8) & 0xFF;
1447 	else if (Port == 0x1FD)
1448 		/* MID flag, and extrernal devices */
1449 		if (I.MID_flag)
1450 			return cpu_readport(Port) | 0x10;
1451 		else
1452 			return cpu_readport(Port) & ~ 0x10;
1453 	else
1454 		/* extrernal devices */
1455 		return cpu_readport(Port);
1456 }
1457 #endif
1458 
readCRU(int CRUAddr,int Number)1459 static UINT16 readCRU(int CRUAddr, int Number)
1460 {
1461 #if (TMS99XX_MODEL == TMS9900_ID)
1462 	/* 3 MSBs are always 0 to support external instructions */
1463 	#define rCRUAddrMask 0x1FF
1464 #elif (TMS99XX_MODEL == TMS9980_ID)
1465 	/* 2 bits unused, and 2 MSBs are always 0 to support external instructions */
1466 	#define rCRUAddrMask 0x0FF
1467 #elif (TMS99XX_MODEL == TMS9995_ID)
1468 	/* no such problem here : data bus lines D0-D2 provide the external instruction code */
1469 	#define rCRUAddrMask 0xFFF
1470 #else
1471 	#warning "I don't know how your processor handle CRU."
1472 	#define rCRUAddrMask 0xFFF
1473 #endif
1474 
1475 	static int BitMask[] =
1476 	{
1477 		0, /* filler - saves a subtract to find mask */
1478 		0x0100,0x0300,0x0700,0x0F00,0x1F00,0x3F00,0x7F00,0xFF00,
1479 		0x01FF,0x03FF,0x07FF,0x0FFF,0x1FFF,0x3FFF,0x7FFF,0xFFFF
1480 	};
1481 
1482 	int Offset,Location,Value;
1483 
1484 	//logerror("Read CRU %x for %x\n",CRUAddr,Number);
1485 
1486 	Location = CRUAddr >> 3;
1487 	Offset   = CRUAddr & 07;
1488 
1489 	if (Number <= 8)
1490 	{
1491 		/* Read 16 Bits */
1492 		Value = (READPORT((Location + 1) & rCRUAddrMask) << 8)
1493 		                                | READPORT(Location & rCRUAddrMask);
1494 
1495 		/* Allow for Offset */
1496 		Value >>= Offset;
1497 
1498 		/* Mask out what we want */
1499 		Value = (Value << 8) & BitMask[Number];
1500 
1501 		/* And update */
1502 		return (Value>>8);
1503 	}
1504 	else
1505 	{
1506 		/* Read 24 Bits */
1507 		Value = (READPORT((Location + 2) & rCRUAddrMask) << 16)
1508 		                                | (READPORT((Location + 1) & rCRUAddrMask) << 8)
1509 		                                | READPORT(Location & rCRUAddrMask);
1510 
1511 		/* Allow for Offset */
1512 		Value >>= Offset;
1513 
1514 		/* Mask out what we want */
1515 		Value &= BitMask[Number];
1516 
1517 		/* and Update */
1518 		return Value;
1519 	}
1520 }
1521 
1522 /**************************************************************************/
1523 
1524 /* fetch : read one word at * PC, and increment PC. */
1525 
fetch(void)1526 static UINT16 fetch(void)
1527 {
1528 	register UINT16 value = readword(I.PC);
1529 	I.PC += 2;
1530 	return value;
1531 }
1532 
1533 /* contextswitch : performs a BLWP, ie change PC, WP, and save PC, WP and ST... */
contextswitch(UINT16 addr)1534 static void contextswitch(UINT16 addr)
1535 {
1536 	UINT16 oldWP, oldpc;
1537 
1538 	/* save old state */
1539 	oldWP = I.WP;
1540 	oldpc = I.PC;
1541 
1542 	/* load vector */
1543 	I.WP = readword(addr) & ~1;
1544 	I.PC = readword(addr+2) & ~1;
1545 
1546 	/* write old state to regs */
1547 	WRITEREG(R13, oldWP);
1548 	WRITEREG(R14, oldpc);
1549 	setstat();
1550 	WRITEREG(R15, I.STATUS);
1551 }
1552 
1553 /*
1554  * decipheraddr : compute and return the effective adress in word instructions.
1555  *
1556  * NOTA : the LSB is always ignored in word adresses,
1557  * but we do not set to 0 because of XOP...
1558  */
decipheraddr(UINT16 opcode)1559 static UINT16 decipheraddr(UINT16 opcode)
1560 {
1561 	register UINT16 ts = opcode & 0x30;
1562 	register UINT16 reg = opcode & 0xF;
1563 
1564 	reg += reg;
1565 
1566 	if (ts == 0)
1567 		/* Rx */
1568 		return(reg + I.WP);
1569 	else if (ts == 0x10)
1570 	{	/* *Rx */
1571 		CYCLES(4, 1);
1572 		return(readword(reg + I.WP));
1573 	}
1574 	else if (ts == 0x20)
1575 	{
1576 		register UINT16 imm;
1577 
1578 		imm = fetch();
1579 
1580 		if (reg)
1581 		{	/* @>xxxx(Rx) */
1582 			CYCLES(8, 3);
1583 			return(readword(reg + I.WP) + imm);
1584 		}
1585 		else
1586 		{	/* @>xxxx */
1587 			CYCLES(8, 1);
1588 			return(imm);
1589 		}
1590 	}
1591 	else /*if (ts == 0x30)*/
1592 	{	/* *Rx+ */
1593 		register UINT16 response;
1594 
1595 		reg += I.WP;    /* reg now contains effective address */
1596 
1597 		CYCLES(8, 3);
1598 
1599 		response = readword(reg);
1600 		writeword(reg, response+2); /* we increment register content */
1601 		return(response);
1602 	}
1603 }
1604 
1605 /* decipheraddrbyte : compute and return the effective adress in byte instructions. */
decipheraddrbyte(UINT16 opcode)1606 static UINT16 decipheraddrbyte(UINT16 opcode)
1607 {
1608 	register UINT16 ts = opcode & 0x30;
1609 	register UINT16 reg = opcode & 0xF;
1610 
1611 	reg += reg;
1612 
1613 	if (ts == 0)
1614 		/* Rx */
1615 		return(reg + I.WP);
1616 	else if (ts == 0x10)
1617 	{	/* *Rx */
1618 		CYCLES(4, 1);
1619 		return(readword(reg + I.WP));
1620 	}
1621 	else if (ts == 0x20)
1622 	{
1623 		register UINT16 imm;
1624 
1625 		imm = fetch();
1626 
1627 		if (reg)
1628 		{	/* @>xxxx(Rx) */
1629 			CYCLES(8, 3);
1630 			return(readword(reg + I.WP) + imm);
1631 		}
1632 		else
1633 		{	/* @>xxxx */
1634 			CYCLES(8, 1);
1635 			return(imm);
1636 		}
1637 	}
1638 	else /*if (ts == 0x30)*/
1639 	{	/* *Rx+ */
1640 		register UINT16 response;
1641 
1642 		reg += I.WP;    /* reg now contains effective address */
1643 
1644 		CYCLES(6, 3);
1645 
1646 		response = readword(reg);
1647 		writeword(reg, response+1); /* we increment register content */
1648 		return(response);
1649 	}
1650 }
1651 
1652 
1653 /*************************************************************************/
1654 
1655 #if TMS99XX_MODEL <= TMS9989_ID
1656 	/* TMS9900/TMS9980 merely ignore the instruction */
1657 	#define HANDLE_ILLEGAL TMS99XX_ICOUNT -= 6
1658 #elif TMS99XX_MODEL == TMS9995_ID
1659 	/* TMS9995 generates a MID interrupt */
1660 	#define HANDLE_ILLEGAL \
1661 	{ \
1662 		I.MID_flag = 1; \
1663 		contextswitch(0x0008); \
1664 		I.STATUS = (I.STATUS & 0xFE00) | 0x1; \
1665 		disable_interrupt_recognition = 1; \
1666 	}
1667 #else
1668 #define HANDLE_ILLEGAL
1669 #warning "don't know"
1670 #endif
1671 
1672 /*==========================================================================
1673    Illegal instructions                                        >0000->01FF (not for 9989 and later)
1674                                                                >0C00->0FFF (not for 99xxx)
1675 ============================================================================*/
1676 
illegal(UINT16 opcode)1677 static void illegal(UINT16 opcode)
1678 {
1679 	HANDLE_ILLEGAL;
1680 }
1681 
1682 
1683 #if (TMS99XX_MODEL >= TMS99105A_ID)
1684 /*==========================================================================
1685    Additionnal instructions,                                   >0000->002F
1686    Additionnal single-register instruction,                    >0030->003F
1687  ---------------------------------------------------------------------------
1688 
1689      0 1 2 3-4 5 6 7+8 9 A B-C D E F
1690     ---------------------------------
1691     |     o p c o d e               |
1692     |     o p c o d e       | reg # |
1693     ---------------------------------
1694 
1695 tms99xxx : SRAM, SLAM, AM, SM
1696 ============================================================================*/
h0000(UINT16 opcode)1697 static void h0000(UINT16 opcode)
1698 {
1699 #if 0
1700 	if (opcode & 0x30)
1701 	{	/* STPC STore Program Counter */
1702 
1703 	}
1704 	else
1705 #endif
1706 
1707 	switch (opcode /*& 0x3F*/)
1708 	{
1709 	case 0x1C:  /* SRAM */
1710 		/* SRAM -- Shift Right Arithmetic Multiple */
1711 		/* right shift on a 32-bit operand */
1712 		/* ... */
1713 		break;
1714 	case 0x1D:  /* SLAM */
1715 		/* SLAM -- Shift Left Arithmetic Multiple */
1716 		/* left shift on a 32-bit operand */
1717 		/* ... */
1718 		break;
1719 
1720 	case 0x29:  /* AM (or SM ?) */
1721 		/* AM ---- Add Multiple */
1722 		/* add with 32-bit operands */
1723 		/* ... */
1724 		break;
1725 	case 0x2A:  /* SM (or AM ?) */
1726 		/* SM ---- Subtract Multiple */
1727 		/* substract with 32-bit operands */
1728 		/* ... */
1729 		break;
1730 
1731 #if 0
1732 	case 0x1E:
1733 		/* RTO --- Right Test for One */
1734 	case 0x1F:
1735 		/* LTO --- Left Test for One */
1736 	case 0x20:
1737 		/* CNTO -- CouNT Ones */
1738 	case 0x21:
1739 		/* SLSL -- Search LiSt Logical address */
1740 	case 0x22:
1741 		/* SLSP -- Search LiSt Physical address */
1742 	case 0x23:
1743 		/* BDC --- Binary to Decimal ascii Conversion */
1744 	case 0x24:
1745 		/* DBC --- Decimal ascii to Binary Conversion */
1746 	case 0x25:
1747 		/* SWPM -- SWaP Multiple precision */
1748 	case 0x26:
1749 		/* XORM -- eXclusive OR Multiple precision */
1750 	case 0x27:
1751 		/* ORM --- OR Multiple precision */
1752 	case 0x28:
1753 		/* ANDM -- AND Multiple precision */
1754 
1755 	case 0x2B:
1756 		/* MOVA -- MOVe Address */
1757 	case 0x2D:
1758 		/* EMD --- Execute Micro-Diagnostics */
1759 	case 0x2E:
1760 		/* EINT -- Enable INTerrupts */
1761 	case 0x2F:
1762 		/* DINT -- Disable INTerrupts */
1763 
1764 		break;
1765 #endif
1766 
1767 	default:
1768 		HANDLE_ILLEGAL;
1769 		break;
1770 	}
1771 }
1772 #endif
1773 
1774 
1775 #if (TMS99XX_MODEL >= TMS9989_ID)
1776 /*==========================================================================
1777    Additionnal single-register instructions,                   >0040->00FF
1778  ---------------------------------------------------------------------------
1779 
1780      0 1 2 3-4 5 6 7+8 9 A B-C D E F
1781     ---------------------------------
1782     |     o p c o d e       | reg # |
1783     ---------------------------------
1784 
1785 tms9989 and later : LST, LWP
1786 tms99xxx : BLSK
1787 ============================================================================*/
h0040(UINT16 opcode)1788 static void h0040(UINT16 opcode)
1789 {
1790 	register UINT16 addr;
1791 
1792 	addr = opcode & 0xF;
1793 	addr = ((addr + addr) + I.WP) & ~1;
1794 
1795 	switch ((opcode & 0xF0) >> 4)
1796 	{
1797 	case 8:   /* LST */
1798 		/* LST --- Load STatus register */
1799 		/* ST = *Reg */
1800 		I.STATUS = readword(addr);
1801 		break;
1802 	case 9:   /* LWP */
1803 		/* LWP --- Load Workspace Pointer register */
1804 		/* WP = *Reg */
1805 		I.WP = readword(addr);
1806 		break;
1807 
1808 #if (TMS99XX_MODEL >= TMS99105A_ID)
1809 	case 11:  /* BLSK */
1810 		/* BLSK -- Branch immediate & Link to StacK */
1811 
1812 		break;
1813 #endif
1814 
1815 #if 0
1816 	case 4:
1817 		/* CS ---- Compare Strings */
1818 	case 5:
1819 		/* SEQB -- Search string for EQual Byte */
1820 	case 6:
1821 		/* MOVS -- MOVe String */
1822 	case 7:
1823 		/* LIM --- Load Interrupt Mask	*/
1824 
1825 	case 10:
1826 		/* LCS --- Load writable Control Store */
1827 
1828 	case 12:
1829 		/* MVSR -- MoVe String Reverse */
1830 	case 13:
1831 		/* MVSK -- MoVe String from stacK */
1832 	case 14:
1833 		/* POPS -- POP String from stack	*/
1834 	case 15:
1835 		/* PSHS -- PuSH String to stack */
1836 
1837 		break;
1838 #endif
1839 
1840 	default:
1841 		HANDLE_ILLEGAL;
1842 		break;
1843 	}
1844 }
1845 
1846 
1847 /*==========================================================================
1848    Additionnal single-operand instructions,                    >0100->01FF
1849  ---------------------------------------------------------------------------
1850 
1851      0 1 2 3-4 5 6 7+8 9 A B-C D E F
1852     ---------------------------------
1853     |    o p c o d e    |TS |   S   |
1854     ---------------------------------
1855 
1856 tms9989 and later : DIVS, MPYS
1857 tms99xxx : BIND
1858 ============================================================================*/
h0100(UINT16 opcode)1859 static void h0100(UINT16 opcode)
1860 {
1861 	register UINT16 src;
1862 
1863 	src = decipheraddr(opcode) & ~1;
1864 
1865   switch ((opcode & 0xC0) >> 6)
1866   {
1867 #if (TMS99XX_MODEL >= TMS99105A_ID)
1868 	case 1:
1869 		/* BIND -- Branch INDirect */
1870 
1871 		break;
1872 #endif
1873 
1874   case 2:   /* DIVS */
1875 		/* DIVS -- DIVide Signed */
1876 		/* R0 = (R0:R1)/S   R1 = (R0:R1)%S */
1877 		{
1878 			INT16 d = readword(src);
1879 			long divq = (READREG(R0) << 16) | READREG(R1);
1880 			long q = divq/d;
1881 
1882 			if ((q < -32768L) || (q > 32767L))
1883 			{
1884 				I.STATUS |= ST_OV;
1885 				CYCLES(24 /*don't know*/, 10);
1886 			}
1887 			else
1888 			{
1889 				I.STATUS &= ~ST_OV;
1890 				setst_lae(q);
1891 				WRITEREG(R0, q);
1892 				WRITEREG(R1, divq%d);
1893 				/* tms9995 : 33 is the worst case */
1894 				CYCLES(102 /*don't know*/, 33);
1895 			}
1896 		}
1897 		break;
1898 
1899   case 3:   /* MPYS */
1900 		/* MPYS -- MultiPlY Signed */
1901 		/* Results:  R0:R1 = R0*S */
1902 		{
1903 			long prod = ((long) (INT16) READREG(R0)) * ((long) (INT16) readword(src));
1904 
1905 			I.STATUS &= ~ (ST_LGT | ST_AGT | ST_EQ);
1906 			if (prod > 0)
1907 				I.STATUS |= (ST_LGT | ST_AGT);
1908 			else if (prod < 0)
1909 				I.STATUS |= ST_LGT;
1910 			else
1911 				I.STATUS |= ST_EQ;
1912 
1913 			WRITEREG(R0, prod >> 16);
1914 			WRITEREG(R1, prod);
1915 		}
1916 		CYCLES(56 /*don't know*/, 25);
1917 		break;
1918 
1919 #if 0
1920 	case 0:
1921 		/* EVAD -- EValuate ADdress instruction */
1922 
1923 		break;
1924 #endif
1925 
1926 	default:
1927 		HANDLE_ILLEGAL;
1928 		break;
1929   }
1930 }
1931 #endif
1932 
1933 
1934 /*==========================================================================
1935    Immediate, Control instructions,                            >0200->03FF
1936  ---------------------------------------------------------------------------
1937 
1938      0 1 2 3-4 5 6 7+8 9 A B-C D E F
1939     ---------------------------------
1940     |     o p c o d e     |0| reg # |
1941     ---------------------------------
1942 
1943   LI, AI, ANDI, ORI, CI, STWP, STST, LIMI, LWPI, IDLE, RSET, RTWP, CKON, CKOF, LREX
1944 ============================================================================*/
h0200(UINT16 opcode)1945 static void h0200(UINT16 opcode)
1946 {
1947 	register UINT16 addr;
1948 	register UINT16 value;	/* used for anything */
1949 
1950 	addr = opcode & 0xF;
1951 	addr = ((addr + addr) + I.WP) & ~1;
1952 
1953 #if 0
1954 	if ((opcode >= 0x0320) && (opcode < 0x0340))
1955 	{	/* LMF */
1956 		/* LMF --- Load memory Map File */
1957 		/* I don't know what it does exactly.  I guess it was used by some paging system on some
1958 		TI990/10 variant.
1959 		Syntax : LMF Rx,x; where Rx can be any workspace register from 0 thru 15, and x can be
1960 		a `0' or a `1'. */
1961 		/* ... */
1962 		return;
1963 	}
1964 #endif
1965 
1966 #if (TMS99XX_MODEL >= TMS9995_ID)
1967 	/* better instruction decoding on tms9995 */
1968 	if (((opcode < 0x2E0) && (opcode & 0x10)) || ((opcode >= 0x2E0) && (opcode & 0x1F)))
1969 	{
1970 #if 0
1971 		if (opcode == 0x0301)
1972 		{	/* CR ---- Compare Reals */
1973 		}
1974 		else if (opcode == 0x0301)
1975 		{	/* MM ---- Multiply Multiple */
1976 		}
1977 		else if (opcode >= 0x03F0)
1978 		{	/* EP ---- Extend Precision */
1979 		}
1980 		else
1981 #endif
1982 		HANDLE_ILLEGAL;
1983 		return;
1984 	}
1985 #endif
1986 
1987 	switch ((opcode & 0x1e0) >> 5)
1988 	{
1989 	case 0:   /* LI */
1990 		/* LI ---- Load Immediate */
1991 		/* *Reg = *PC+ */
1992 		value = fetch();
1993 		writeword(addr, value);
1994 		setst_lae(value);
1995 		CYCLES(12, 3);
1996 		break;
1997 	case 1:   /* AI */
1998 		/* AI ---- Add Immediate */
1999 		/* *Reg += *PC+ */
2000 		value = fetch();
2001 		wadd(addr, value);
2002 		CYCLES(14, 4);
2003 		break;
2004 	case 2:   /* ANDI */
2005 		/* ANDI -- AND Immediate */
2006 		/* *Reg &= *PC+ */
2007 		value = fetch();
2008 		value = readword(addr) & value;
2009 		writeword(addr, value);
2010 		setst_lae(value);
2011 		CYCLES(14, 4);
2012 		break;
2013 	case 3:   /* ORI */
2014 		/* ORI --- OR Immediate */
2015 		/* *Reg |= *PC+ */
2016 		value = fetch();
2017 		value = readword(addr) | value;
2018 		writeword(addr, value);
2019 		setst_lae(value);
2020 		CYCLES(14, 4);
2021 		break;
2022 	case 4:   /* CI */
2023 		/* CI ---- Compare Immediate */
2024 		/* status = (*Reg-*PC+) */
2025 		value = fetch();
2026 		setst_c_lae(value, readword(addr));
2027 		CYCLES(14, 4);
2028 		break;
2029 	case 5:   /* STWP */
2030 		/* STWP -- STore Workspace Pointer */
2031 		/* *Reg = WP */
2032 		writeword(addr, I.WP);
2033 		CYCLES(8, 3);
2034 		break;
2035 	case 6:   /* STST */
2036 		/* STST -- STore STatus register */
2037 		/* *Reg = ST */
2038 		setstat();
2039 		writeword(addr, I.STATUS);
2040 		CYCLES(8, 3);
2041 		break;
2042 	case 7:   /* LWPI */
2043 		/* LWPI -- Load Workspace Pointer Immediate */
2044 		/* WP = *PC+ */
2045 		I.WP = fetch();
2046 		CYCLES(10, 4);
2047 		break;
2048 	case 8:   /* LIMI */
2049 		/* LIMI -- Load Interrupt Mask Immediate */
2050 		/* ST&15 |= (*PC+)&15 */
2051 		value = fetch();
2052 #if (TMS99XX_MODEL == TMS9940_ID)
2053 		/* Interrupt mask is only two-bit-long on tms9940 */
2054 		I.STATUS = (I.STATUS & ~ 0x3) | (value & 0x3);
2055 #else
2056 		I.STATUS = (I.STATUS & ~ 0xF) | (value & 0xF);
2057 #endif
2058 		field_interrupt();  /*IM has been modified.*/
2059 		CYCLES(16, 5);
2060 		break;
2061 	case 9:   /* LMF is implemented elsewhere - when it is implemented */
2062 		HANDLE_ILLEGAL;
2063 		break;
2064 	case 10:  /* IDLE */
2065 		/* IDLE -- IDLE until a reset, interrupt, load */
2066 		/* The TMS99000 locks until an interrupt happen (like with 68k STOP instruction),
2067 		   and continuously performs a special CRU write (code 2). */
2068 		I.IDLE = 1;
2069 		external_instruction_notify(2);
2070 		CYCLES(12, 7);
2071 		/* we take care of further external_instruction_notify(2); in execute() */
2072 		break;
2073 	case 11:  /* RSET */
2074 		/* RSET -- ReSET */
2075 		/* Reset the Interrupt Mask, and perform a special CRU write (code 3). */
2076 		/* Does not actually cause a reset, but an external circuitery could trigger one. */
2077 		I.STATUS &= 0xFFF0; /*clear IM.*/
2078 		field_interrupt();  /*IM has been modified.*/
2079 		external_instruction_notify(3);
2080 		CYCLES(12, 7);
2081 		break;
2082 	case 12:  /* RTWP */
2083 		/* RTWP -- Return with Workspace Pointer */
2084 		/* WP = R13, PC = R14, ST = R15 */
2085 		I.STATUS = READREG(R15);
2086 		getstat();  /* set last_parity */
2087 		I.PC = READREG(R14);
2088 		I.WP = READREG(R13);
2089 		field_interrupt();  /*IM has been modified.*/
2090 		CYCLES(14, 6);
2091 		break;
2092 	case 13:  /* CKON */
2093 	case 14:  /* CKOF */
2094 	case 15:  /* LREX */
2095 		/* CKON -- ClocK ON */
2096 		/* Perform a special CRU write (code 5). */
2097 		/* An external circuitery could, for instance, enable a "decrement-and-interrupt" timer. */
2098 		/* CKOF -- ClocK OFf */
2099 		/* Perform a special CRU write (code 6). */
2100 		/* An external circuitery could, for instance, disable a "decrement-and-interrupt" timer. */
2101 		/* LREX -- Load or REstart eXecution */
2102 		/* Perform a special CRU write (code 7). */
2103 		/* An external circuitery could, for instance, activate the LOAD* line,
2104 		   causing a non-maskable LOAD interrupt (vector -1). */
2105 		external_instruction_notify((opcode & 0x00e0) >> 5);
2106 		CYCLES(12, 7);
2107 		break;
2108 	}
2109 }
2110 
2111 
2112 /*==========================================================================
2113    Single-operand instructions,                                >0400->07FF
2114  ---------------------------------------------------------------------------
2115 
2116      0 1 2 3-4 5 6 7+8 9 A B-C D E F
2117     ---------------------------------
2118     |    o p c o d e    |TS |   S   |
2119     ---------------------------------
2120 
2121   BLWP, B, X, CLR, NEG, INV, INC, INCT, DEC, DECT, BL, SWPB, SETO, ABS
2122 tms99xxx : LDD, LDS
2123 ============================================================================*/
h0400(UINT16 opcode)2124 static void h0400(UINT16 opcode)
2125 {
2126 	register UINT16 addr = decipheraddr(opcode) & ~1;
2127 	register UINT16 value;  /* used for anything */
2128 
2129 	switch ((opcode & 0x3C0) >> 6)
2130 	{
2131 	case 0:   /* BLWP */
2132 		/* BLWP -- Branch and Link with Workspace Pointer */
2133 		/* Result: WP = *S+, PC = *S */
2134 		/*         New R13=old WP, New R14=Old PC, New R15=Old ST */
2135 		contextswitch(addr);
2136 		CYCLES(26, 11);
2137 		disable_interrupt_recognition = 1;
2138 		break;
2139 	case 1:   /* B */
2140 		/* B ----- Branch */
2141 		/* PC = S */
2142 		I.PC = addr;
2143 		CYCLES(8, 3);
2144 		break;
2145 	case 2:   /* X */
2146 		/* X ----- eXecute */
2147 		/* Executes instruction *S */
2148 		execute(readword(addr));
2149 		/* On tms9900, the X instruction actually takes 8 cycles, but we gain 4 cycles on the next
2150 		instruction, as we don't need to fetch it. */
2151 		CYCLES(4, 2);
2152 		break;
2153 	case 3:   /* CLR */
2154 		/* CLR --- CLeaR */
2155 		/* *S = 0 */
2156 		writeword(addr, 0);
2157 		CYCLES(10, 3);
2158 		break;
2159 	case 4:   /* NEG */
2160 		/* NEG --- NEGate */
2161 		/* *S = -*S */
2162 		value = - (INT16) readword(addr);
2163 		if (value)
2164 			I.STATUS &= ~ ST_C;
2165 		else
2166 			I.STATUS |= ST_C;
2167 #if (TMS99XX_MODEL == TMS9940_ID)
2168 		if (value & 0x0FFF)
2169 			I.STATUS &= ~ ST_DC;
2170 		else
2171 			I.STATUS |= ST_DC;
2172 #endif
2173 		setst_laeo(value);
2174 		writeword(addr, value);
2175 		CYCLES(12, 3);
2176 		break;
2177 	case 5:   /* INV */
2178 		/* INV --- INVert */
2179 		/* *S = ~*S */
2180 		value = ~ readword(addr);
2181 		writeword(addr, value);
2182 		setst_lae(value);
2183 		CYCLES(10, 3);
2184 		break;
2185 	case 6:   /* INC */
2186 		/* INC --- INCrement */
2187 		/* (*S)++ */
2188 		wadd(addr, 1);
2189 		CYCLES(10, 3);
2190 		break;
2191 	case 7:   /* INCT */
2192 		/* INCT -- INCrement by Two */
2193 		/* (*S) +=2 */
2194 		wadd(addr, 2);
2195 		CYCLES(10, 3);
2196 		break;
2197 	case 8:   /* DEC */
2198 		/* DEC --- DECrement */
2199 		/* (*S)-- */
2200 		wsub(addr, 1);
2201 		CYCLES(10, 3);
2202 		break;
2203 	case 9:   /* DECT */
2204 		/* DECT -- DECrement by Two */
2205 		/* (*S) -= 2 */
2206 		wsub(addr, 2);
2207 		CYCLES(10, 3);
2208 		break;
2209 	case 10:  /* BL */
2210 		/* BL ---- Branch and Link */
2211 		/* IP=S, R11=old IP */
2212 		WRITEREG(R11, I.PC);
2213 		I.PC = addr;
2214 		CYCLES(12, 5);
2215 		break;
2216 	case 11:  /* SWPB */
2217 		/* SWPB -- SWaP Bytes */
2218 		/* *S = swab(*S) */
2219 		value = readword(addr);
2220 		value = logical_right_shift(value, 8) | (value << 8);
2221 		writeword(addr, value);
2222 		CYCLES(10, 13);
2223 		break;
2224 	case 12:  /* SETO */
2225 		/* SETO -- SET Ones */
2226 		/* *S = #$FFFF */
2227 		writeword(addr, 0xFFFF);
2228 		CYCLES(10, 3);
2229 		break;
2230 	case 13:  /* ABS */
2231 		/* ABS --- ABSolute value */
2232 		/* *S = |*S| */
2233 		/* clearing ST_C seems to be necessary, although ABS will never set it. */
2234 #if (TMS99XX_MODEL <= TMS9985_ID)
2235 		/* tms9900/tms9980 only write the result if it has changed */
2236 		I.STATUS &= ~ (ST_LGT | ST_AGT | ST_EQ | ST_C | ST_OV);
2237 #if (TMS99XX_MODEL == TMS9940_ID)
2238 		/* I guess ST_DC is cleared here, too*/
2239 		I.STATUS &= ~ ST_DC;
2240 #endif
2241 		value = readword(addr);
2242 
2243 		CYCLES(12, Mooof!);
2244 
2245 		if (((INT16) value) > 0)
2246 			I.STATUS |= ST_LGT | ST_AGT;
2247 		else if (((INT16) value) < 0)
2248 		{
2249 			I.STATUS |= ST_LGT;
2250 			if (value == 0x8000)
2251 				I.STATUS |= ST_OV;
2252 #if (TMS99XX_MODEL == TMS9940_ID)
2253 			if (! (value & 0x0FFF))
2254 				I.STATUS |= ST_DC;
2255 #endif
2256 			writeword(addr, - ((INT16) value));
2257 			CYCLES(2, Mooof!);
2258 		}
2259 		else
2260 			I.STATUS |= ST_EQ;
2261 
2262 #else
2263 		/* tms9995 always write the result */
2264 		I.STATUS &= ~ (ST_LGT | ST_AGT | ST_EQ | ST_C | ST_OV);
2265 		value = readword(addr);
2266 
2267 		CYCLES(12 /*Don't know for tms9989*/, 3);
2268 		if (((INT16) value) > 0)
2269 			I.STATUS |= ST_LGT | ST_AGT;
2270 		else if (((INT16) value) < 0)
2271 		{
2272 			I.STATUS |= ST_LGT;
2273 			if (value == 0x8000)
2274 				I.STATUS |= ST_OV;
2275 			value = - ((INT16) value);
2276 		}
2277 		else
2278 			I.STATUS |= ST_EQ;
2279 
2280 		writeword(addr, value);
2281 #endif
2282 
2283 		break;
2284 #if (TMS99XX_MODEL >= TMS99105A_ID)
2285 	/* "These opcode are designed to support the 99610 memory mapper, to allow easy access to
2286 	another page without the need of switching a page someplace." */
2287 	case 14:  /* LDS */
2288 		/* LDS --- Long Distance Source */
2289 		/* ... */
2290 		break;
2291 	case 15:  /* LDD */
2292 		/* LDD --- Long Distance Destination */
2293 		/* ... */
2294 		break;
2295 #else
2296 	default:
2297 		/* illegal instructions */
2298 		HANDLE_ILLEGAL;
2299 		break;
2300 #endif
2301 	}
2302 }
2303 
2304 
2305 /*==========================================================================
2306    Shift instructions,                                         >0800->0BFF
2307   --------------------------------------------------------------------------
2308 
2309      0 1 2 3-4 5 6 7+8 9 A B-C D E F
2310     ---------------------------------
2311     | o p c o d e   |   C   |   W   |
2312     ---------------------------------
2313 
2314   SRA, SRL, SLA, SRC
2315 ============================================================================*/
h0800(UINT16 opcode)2316 static void h0800(UINT16 opcode)
2317 {
2318 	register UINT16 addr;
2319 	register UINT16 cnt = (opcode & 0xF0) >> 4;
2320 	register UINT16 value;
2321 
2322 	addr = (opcode & 0xF);
2323 	addr = ((addr+addr) + I.WP) & ~1;
2324 
2325 	CYCLES(12, 5);
2326 
2327 	if (cnt == 0)
2328 	{
2329 		CYCLES(8, 2);
2330 
2331 		cnt = READREG(0) & 0xF;
2332 
2333 		if (cnt == 0)
2334 			cnt = 16;
2335 	}
2336 
2337 	CYCLES(cnt+cnt, cnt);
2338 
2339 	switch ((opcode & 0x300) >> 8)
2340 	{
2341 	case 0:   /* SRA */
2342 		/* SRA --- Shift Right Arithmetic */
2343 		/* *W >>= C   (*W is filled on the left with a copy of the sign bit) */
2344 		value = setst_sra_laec(readword(addr), cnt);
2345 		writeword(addr, value);
2346 		break;
2347 	case 1:   /* SRL */
2348 		/* SRL --- Shift Right Logical */
2349 		/* *W >>= C   (*W is filled on the left with 0) */
2350 		value = setst_srl_laec(readword(addr), cnt);
2351 		writeword(addr, value);
2352 		break;
2353 	case 2:   /* SLA */
2354 		/* SLA --- Shift Left Arithmetic */
2355 		/* *W <<= C */
2356 		value = setst_sla_laeco(readword(addr), cnt);
2357 		writeword(addr, value);
2358 		break;
2359 	case 3:   /* SRC */
2360 		/* SRC --- Shift Right Circular */
2361 		/* *W = rightcircularshift(*W, C) */
2362 		value = setst_src_laec(readword(addr), cnt);
2363 		writeword(addr, value);
2364 		break;
2365 	}
2366 }
2367 
2368 
2369 #if (TMS99XX_MODEL >= TMS99105A_ID)
2370 /*==========================================================================
2371    Additionnal instructions,                                   >0C00->0C0F
2372    Additionnal single-register instructions,                   >0C10->0C3F
2373  ---------------------------------------------------------------------------
2374 
2375      0 1 2 3-4 5 6 7+8 9 A B-C D E F
2376     ---------------------------------
2377     |     o p c o d e               |
2378     |     o p c o d e       | reg # |
2379     ---------------------------------
2380 
2381 tms99xxx : TMB, TCMB, TSMB
2382 tms99110a : CRI, NEGR, CRE, CER
2383 ============================================================================*/
h0c00(UINT16 opcode)2384 static void h0c00(UINT16 opcode)
2385 {
2386 	if (opcode & 0x30)
2387 	{
2388 #if 0
2389 		switch ((opcode & 0x30) >> 4)
2390 		{
2391 		case 1:
2392 			/* INSF -- INSert Field */
2393 		case 2:
2394 			/* XV ---- eXtract Value */
2395 		case 3:
2396 			/* XF ---- eXtract Field */
2397 
2398 			break;
2399 		}
2400 #else
2401 		HANDLE_ILLEGAL;
2402 #endif
2403 	}
2404 	else
2405 	{
2406 		switch (opcode & 0x0F)
2407 		{
2408 #if (TMS99XX_MODEL == TMS99110A_ID)
2409 		/* floating point instructions */
2410 		case 0:
2411 			/* CRI --- Convert Real to Integer */
2412 
2413 			break;
2414 		case 2:
2415 			/* NEGR -- NEGate Real */
2416 
2417 			break;
2418 		case 4:
2419 			/* CRE --- Convert Real to Extended integer */
2420 
2421 			break;
2422 		case 6:
2423 			/* CER --- Convert Extended integer to Real */
2424 
2425 			break;
2426 #endif
2427 
2428 		/* The next three instructions allow to handle multiprocessor systems */
2429 		case 9:
2430 			/* TMB --- Test Memory Bit */
2431 
2432 			break;
2433 		case 10:
2434 			/* TCMB -- Test and Clear Memory Bit */
2435 
2436 			break;
2437 		case 11:
2438 			/* TSMB -- Test and Set Memory Bit */
2439 
2440 			break;
2441 
2442 #if 0
2443 		/* the four next instructions support BCD */
2444 		case 1:
2445 			/* CDI --- Convert Decimal to Integer */
2446 		case 3:
2447 			/* NEGD -- NEGate Decimal */
2448 		case 5:
2449 			/* CDE --- Convert Decimal to Extended integer */
2450 		case 7:
2451 			/* CED --- Convert Extended integer to Decimal */
2452 
2453 		case 8:
2454 			/* NRM --- NoRMalize */
2455 
2456 	case 12:
2457 			/* SRJ --- Subtract from Register and Jump */
2458 		case 13:
2459 			/* ARJ --- Add to Register and Jump */
2460 
2461 		case 14:
2462 		case 15:
2463 			/* XIT --- eXIT from floating point interpreter (???) */
2464 			/* Completely alien to me.  Must have existed on weird TI990 variants. */
2465 
2466 			break;
2467 #endif
2468 		default:
2469 			HANDLE_ILLEGAL;
2470 			break;
2471 		}
2472 	}
2473 }
2474 
2475 
2476 /*==========================================================================
2477    Additionnal single-operand instructions,                    >0C40->0FFF
2478  ---------------------------------------------------------------------------
2479 
2480      0 1 2 3-4 5 6 7+8 9 A B-C D E F
2481     ---------------------------------
2482     |    o p c o d e    |TS |   S   |
2483     ---------------------------------
2484 
2485 tms99110a : AR, CIR, SR, MR, DR, LR, STR
2486 ============================================================================*/
h0c40(UINT16 opcode)2487 static void h0c40(UINT16 opcode)
2488 {
2489 	register UINT16 src;
2490 
2491 	src = decipheraddr(opcode) & ~1;
2492 
2493 	switch ((opcode & 0x03C0) >> 6)
2494 	{
2495 #if (TMS99XX_MODEL == TMS99110A_ID)
2496 	case 1:
2497 		/* AR ---- Add Real */
2498 	case 2:
2499 		/* CIR --- Convert Integer to Real */
2500 	case 3:
2501 		/* SR ---- Subtract Real */
2502 	case 4:
2503 		/* MR ---- Multiply Real */
2504 	case 5:
2505 		/* DR ---- Divide Real */
2506 	case 6:
2507 		/* LR ---- Load Real */
2508 	case 7:
2509 		/* STR --- STore Real */
2510 #endif
2511 #if 0
2512 	case 9:
2513 		/* AD ---- Add Decimal */
2514 	case 10:
2515 		/* CID --- Convert Integer to Decimal */
2516 	case 11:
2517 		/* SD ---- Subtract Decimal */
2518 	case 12:
2519 		/* MD ---- Multiply Decimal */
2520 	case 13:
2521 		/* DD ---- Divide Decimal  */
2522 	case 14:
2523 		/* LD ---- Load Decimal */
2524 	case 15:
2525 		/* SD ---- Store Decimal */
2526 #endif
2527 	default:
2528 		HANDLE_ILLEGAL;
2529 		break;
2530 	}
2531 }
2532 #endif
2533 
2534 
2535 /*==========================================================================
2536    Jump, CRU bit instructions,                                 >1000->1FFF
2537  ---------------------------------------------------------------------------
2538 
2539      0 1 2 3-4 5 6 7+8 9 A B-C D E F
2540     ---------------------------------
2541     |  o p c o d e  | signed offset |
2542     ---------------------------------
2543 
2544   JMP, JLT, JLE, JEQ, JHE, JGT, JNE, JNC, JOC, JNO, JL, JH, JOP
2545   SBO, SBZ, TB
2546 ============================================================================*/
h1000(UINT16 opcode)2547 static void h1000(UINT16 opcode)
2548 {
2549 	/* we convert 8 bit signed word offset to a 16 bit effective word offset. */
2550 	register INT16 offset = ((INT8) opcode);
2551 
2552 
2553 	switch ((opcode & 0xF00) >> 8)
2554 	{
2555 	case 0:   /* JMP */
2556 		/* JMP --- unconditional JuMP */
2557 		/* PC += offset */
2558 		I.PC += (offset + offset);
2559 		CYCLES(10, 3);
2560 		break;
2561 	case 1:   /* JLT */
2562 		/* JLT --- Jump if Less Than (arithmetic) */
2563 		/* if (A==0 && EQ==0), PC += offset */
2564 		if (! (I.STATUS & (ST_AGT | ST_EQ)))
2565 		{
2566 			I.PC += (offset + offset);
2567 			CYCLES(10, 3);
2568 		}
2569 		else
2570 			CYCLES(8, 3);
2571 		break;
2572 	case 2:   /* JLE */
2573 		/* JLE --- Jump if Lower or Equal (logical) */
2574 		/* if (L==0 || EQ==1), PC += offset */
2575 		if ((! (I.STATUS & ST_LGT)) || (I.STATUS & ST_EQ))
2576 		{
2577 			I.PC += (offset + offset);
2578 			CYCLES(10, 3);
2579 		}
2580 		else
2581 			CYCLES(8, 3);
2582 		break;
2583 	case 3:   /* JEQ */
2584 		/* JEQ --- Jump if EQual */
2585 		/* if (EQ==1), PC += offset */
2586 		if (I.STATUS & ST_EQ)
2587 		{
2588 			I.PC += (offset + offset);
2589 			CYCLES(10, 3);
2590 		}
2591 		else
2592 			CYCLES(8, 3);
2593 		break;
2594 	case 4:   /* JHE */
2595 		/* JHE --- Jump if Higher or Equal (logical) */
2596 		/* if (L==1 || EQ==1), PC += offset */
2597 		if (I.STATUS & (ST_LGT | ST_EQ))
2598 		{
2599 			I.PC += (offset + offset);
2600 			CYCLES(10, 3);
2601 		}
2602 		else
2603 			CYCLES(8, 3);
2604 		break;
2605 	case 5:   /* JGT */
2606 		/* JGT --- Jump if Greater Than (arithmetic) */
2607 		/* if (A==1), PC += offset */
2608 		if (I.STATUS & ST_AGT)
2609 		{
2610 			I.PC += (offset + offset);
2611 			CYCLES(10, 3);
2612 		}
2613 		else
2614 			CYCLES(8, 3);
2615 		break;
2616 	case 6:   /* JNE */
2617 		/* JNE --- Jump if Not Equal */
2618 		/* if (EQ==0), PC += offset */
2619 		if (! (I.STATUS & ST_EQ))
2620 		{
2621 			I.PC += (offset + offset);
2622 			CYCLES(10, 3);
2623 		}
2624 		else
2625 			CYCLES(8, 3);
2626 		break;
2627 	case 7:   /* JNC */
2628 		/* JNC --- Jump if No Carry */
2629 		/* if (C==0), PC += offset */
2630 		if (! (I.STATUS & ST_C))
2631 		{
2632 			I.PC += (offset + offset);
2633 			CYCLES(10, 3);
2634 		}
2635 		else
2636 			CYCLES(8, 3);
2637 		break;
2638 	case 8:   /* JOC */
2639 		/* JOC --- Jump On Carry */
2640 		/* if (C==1), PC += offset */
2641 		if (I.STATUS & ST_C)
2642 		{
2643 			I.PC += (offset + offset);
2644 			CYCLES(10, 3);
2645 		}
2646 		else
2647 			CYCLES(8, 3);
2648 		break;
2649 	case 9:   /* JNO */
2650 		/* JNO --- Jump if No Overflow */
2651 		/* if (OV==0), PC += offset */
2652 		if (! (I.STATUS & ST_OV))
2653 		{
2654 			I.PC += (offset + offset);
2655 			CYCLES(10, 3);
2656 		}
2657 		else
2658 			CYCLES(8, 3);
2659 		break;
2660 	case 10:  /* JL */
2661 		/* JL ---- Jump if Lower (logical) */
2662 		/* if (L==0 && EQ==0), PC += offset */
2663 		if (! (I.STATUS & (ST_LGT | ST_EQ)))
2664 		{
2665 			I.PC += (offset + offset);
2666 			CYCLES(10, 3);
2667 		}
2668 		else
2669 			CYCLES(8, 3);
2670 		break;
2671 	case 11:  /* JH */
2672 		/* JH ---- Jump if Higher (logical) */
2673 		/* if (L==1 && EQ==0), PC += offset */
2674 		if ((I.STATUS & ST_LGT) && ! (I.STATUS & ST_EQ))
2675 		{
2676 			I.PC += (offset + offset);
2677 			CYCLES(10, 3);
2678 		}
2679 		else
2680 			CYCLES(8, 3);
2681 		break;
2682 	case 12:  /* JOP */
2683 		/* JOP --- Jump On (odd) Parity */
2684 		/* if (P==1), PC += offset */
2685 		{
2686 			/* Let's set ST_OP. */
2687 			int i;
2688 			UINT8 a;
2689 				a = lastparity;
2690 			i = 0;
2691 
2692 			while (a != 0)
2693 			{
2694 				if (a & 1)  /* If current bit is set, */
2695 					i++;      /* increment bit count. */
2696 				a >>= 1U;   /* Next bit. */
2697 			}
2698 
2699 			/* Set ST_OP bit. */
2700 			/*if (i & 1)
2701 				I.STATUS |= ST_OP;
2702 			else
2703 				I.STATUS &= ~ ST_OP;*/
2704 
2705 			/* Jump accordingly. */
2706 			if (i & 1)  /*(I.STATUS & ST_OP)*/
2707 			{
2708 				I.PC += (offset + offset);
2709 				CYCLES(10, 3);
2710 			}
2711 			else
2712 				CYCLES(8, 3);
2713 		}
2714 
2715 		break;
2716 	case 13:  /* SBO */
2717 		/* SBO --- Set Bit to One */
2718 		/* CRU Bit = 1 */
2719 		writeCRU((READREG(R12) >> 1) + offset, 1, 1);
2720 		CYCLES(12, 8);
2721 		break;
2722 	case 14:  /* SBZ */
2723 		/* SBZ --- Set Bit to Zero */
2724 		/* CRU Bit = 0 */
2725 		writeCRU((READREG(R12) >> 1) + offset, 1, 0);
2726 		CYCLES(12, 8);
2727 		break;
2728 	case 15:  /* TB */
2729 		/* TB ---- Test Bit */
2730 		/* EQ = (CRU Bit == 1) */
2731 		setst_e(readCRU((READREG(R12)>> 1) + offset, 1) & 1, 1);
2732 		CYCLES(12, 8);
2733 		break;
2734 	}
2735 }
2736 
2737 
2738 /*==========================================================================
2739    General and One-Register instructions                       >2000->3FFF
2740  ---------------------------------------------------------------------------
2741 
2742      0 1 2 3-4 5 6 7+8 9 A B-C D E F
2743     ---------------------------------
2744     |  opcode   |   D   |TS |   S   |
2745     ---------------------------------
2746 
2747   COC, CZC, XOR, LDCR, STCR, XOP, MPY, DIV
2748 tms9940 : DCA, DCS, LIIM
2749 ==========================================================================*/
2750 
2751 /* xop, ldcr and stcr are handled elsewhere */
h2000(UINT16 opcode)2752 static void h2000(UINT16 opcode)
2753 {
2754 	register UINT16 dest = (opcode & 0x3C0) >> 6;
2755 	register UINT16 src;
2756 	register UINT16 value;
2757 
2758 	src = decipheraddr(opcode);
2759 
2760 	switch ((opcode & 0x1C00) >> 10)
2761 	{
2762 	case 0:   /* COC */
2763 		/* COC --- Compare Ones Corresponding */
2764 		/* status E bit = (S&D == S) */
2765 		dest = ((dest+dest) + I.WP) & ~1;
2766 		src &= ~1;
2767 		value = readword(src);
2768 		setst_e(value & readword(dest), value);
2769 		CYCLES(14, 4);
2770 		break;
2771 	case 1:   /* CZC */
2772 		/* CZC --- Compare Zeroes Corresponding */
2773 		/* status E bit = (S&~D == S) */
2774 		dest = ((dest+dest) + I.WP) & ~1;
2775 		src &= ~1;
2776 		value = readword(src);
2777 		setst_e(value & (~ readword(dest)), value);
2778 		CYCLES(14, 4);
2779 		break;
2780 	case 2:   /* XOR */
2781 		/* XOR --- eXclusive OR */
2782 		/* D ^= S */
2783 		dest = ((dest+dest) + I.WP) & ~1;
2784 		src &= ~1;
2785 		value = readword(dest) ^ readword(src);
2786 		setst_lae(value);
2787 		writeword(dest,value);
2788 		CYCLES(14, 4);
2789 		break;
2790 	/*case 3:*/   /* XOP is implemented elsewhere */
2791 	/*case 4:*/   /* LDCR is implemented elsewhere */
2792 	/*case 5:*/   /* STCR is implemented elsewhere */
2793 	case 6:   /* MPY */
2794 		/* MPY --- MultiPlY  (unsigned) */
2795 		/* Results:  D:D+1 = D*S */
2796 		/* Note that early TMS9995 reportedly perform an extra dummy read in PC space */
2797 		dest = ((dest+dest) + I.WP) & ~1;
2798 		src &= ~1;
2799 		{
2800 			unsigned long prod = ((unsigned long) readword(dest)) * ((unsigned long) readword(src));
2801 			writeword(dest, prod >> 16);
2802 			writeword(dest+2, prod);
2803 		}
2804 		CYCLES(52, 23);
2805 		break;
2806 	case 7:   /* DIV */
2807 		/* DIV --- DIVide    (unsigned) */
2808 		/* D = D/S    D+1 = D%S */
2809 		dest = ((dest+dest) + I.WP) & ~1;
2810 		src &= ~1;
2811 		{
2812 			UINT16 d = readword(src);
2813 			UINT16 hi = readword(dest);
2814 			unsigned long divq = (((unsigned long) hi) << 16) | readword(dest+2);
2815 
2816 			if (d <= hi)
2817 			{
2818 				I.STATUS |= ST_OV;
2819 				CYCLES(16, 6);
2820 			}
2821 			else
2822 			{
2823 				I.STATUS &= ~ST_OV;
2824 				writeword(dest, divq/d);
2825 				writeword(dest+2, divq%d);
2826 				/* tms9900 : from 92 to 124, possibly 92 + 2*(number of bits to 1 (or 0?) in quotient) */
2827 				/* tms9995 : 28 is the worst case */
2828 				CYCLES(92, 28);
2829 			}
2830 		}
2831 		break;
2832 	}
2833 }
2834 
xop(UINT16 opcode)2835 static void xop(UINT16 opcode)
2836 {	/* XOP */
2837 	/* XOP --- eXtended OPeration */
2838 	/* WP = *(40h+D), PC = *(42h+D) */
2839 	/* New R13=old WP, New R14=Old IP, New R15=Old ST */
2840 	/* New R11=S */
2841 	/* Xop bit set */
2842 
2843 	register UINT16 immediate = (opcode & 0x3C0) >> 6;
2844 	register UINT16 operand;
2845 
2846 #if (TMS99XX_MODEL == TMS9940_ID)
2847 		switch (immediate)
2848 		{
2849 		case 0: /* DCA */
2850 			/* DCA --- Decimal Correct Addition */
2851 			operand = decipheraddrbyte(opcode);
2852 			{
2853 			int value = readbyte(operand);
2854 			int X = (value >> 4) & 0xf;
2855 			int Y = value & 0xf;
2856 
2857 			if (Y >= 10)
2858 			{
2859 				Y -= 10;
2860 				I.STATUS |= ST_DC;
2861 				X++;
2862 			}
2863 			else if (I.STATUS & ST_DC)
2864 			{
2865 				Y += 6;
2866 			}
2867 
2868 			if (X >= 10)
2869 			{
2870 				X -= 10;
2871 				I.STATUS |= ST_C;
2872 			}
2873 			else if (I.STATUS & ST_C)
2874 			{
2875 				X += 6;
2876 			}
2877 
2878 			writebyte(operand, (X << 4) | Y);
2879 			}
2880 			break;
2881 		case 1:	/* DCS */
2882 			/* DCS --- Decimal Correct Substraction */
2883 			operand = decipheraddrbyte(opcode);
2884 			{
2885 			int value = readbyte(operand);
2886 
2887 			if (! (I.STATUS & ST_DC))
2888 			{
2889 				value += 10;
2890 			}
2891 
2892 			if (! (I.STATUS & ST_C))
2893 			{
2894 				value += 10 << 4;
2895 			}
2896 
2897 			I.STATUS ^= ST_DC;
2898 
2899 			writebyte(operand, value);
2900 			}
2901 			break;
2902 		case 2: /* LIIM */
2903 		case 3: /* LIIM */
2904 			/* LIIM - Load Immediate Interrupt Mask */
2905 			/* Does the same job as LIMI, with a different opcode format. */
2906 			/* Note that, unlike TMS9900, the interrupt mask is only 2-bit long. */
2907 			operand = decipheraddr(opcode);	/* dummy decode (personnal guess) */
2908 
2909 			I.STATUS = (I.STATUS & 0xFFFC) | (opcode & 0x0003);
2910 			break;
2911 		default:  /* normal XOP */
2912 #endif
2913 
2914 	operand = decipheraddr(opcode);
2915 
2916 #if (TMS99XX_MODEL <= TMS9989_ID)
2917 		(void)readword(operand & ~1); /*dummy read (personnal guess)*/
2918 #endif
2919 
2920 		contextswitch(0x40 + (immediate << 2));
2921 #if (TMS99XX_MODEL != TMS9940_ID)
2922 		/* The bit is not set on tms9940 */
2923 		I.STATUS |= ST_X;
2924 #endif
2925 		WRITEREG(R11, operand);
2926 		CYCLES(36, 15);
2927 		disable_interrupt_recognition = 1;
2928 
2929 #if (TMS99XX_MODEL == TMS9940_ID)
2930 			break;
2931 		}
2932 #endif
2933 }
2934 
2935 /* LDCR and STCR */
ldcr_stcr(UINT16 opcode)2936 static void ldcr_stcr(UINT16 opcode)
2937 {
2938 	register UINT16 cnt = (opcode & 0x3C0) >> 6;
2939 	register UINT16 addr;
2940 	register UINT16 value;
2941 
2942 	if (cnt == 0)
2943 		cnt = 16;
2944 
2945 	if (cnt <= 8)
2946 		addr = decipheraddrbyte(opcode);
2947 	else
2948 		addr = decipheraddr(opcode) & ~1;
2949 
2950 	if (opcode < 0x3400)
2951 	{	/* LDCR */
2952 		/* LDCR -- LoaD into CRu */
2953 		/* CRU R12--CRU R12+D-1 set to S */
2954 		if (cnt <= 8)
2955 		{
2956 #if (TMS99XX_MODEL != TMS9995_ID)
2957 			value = readbyte(addr);
2958 #else
2959 			/* just for once, tms9995 behaves like earlier 8-bit tms99xx chips */
2960 			/* this must be because instruction decoding is too complex */
2961 			value = readword(addr);
2962 			if (addr & 1)
2963 				value &= 0xFF;
2964 			else
2965 				value = (value >> 8) & 0xFF;
2966 #endif
2967 			(void)READREG(cnt+cnt); /*dummy read (reasonnable guess, cf TMS9995)*/
2968 			setst_byte_laep(value);
2969 			writeCRU((READREG(R12) >> 1), cnt, value);
2970 		}
2971 		else
2972 		{
2973 			value = readword(addr);
2974 			(void)READREG(cnt+cnt); /*dummy read (reasonnable guess, cf TMS9995)*/
2975 			setst_lae(value);
2976 			writeCRU((READREG(R12) >> 1), cnt, value);
2977 		}
2978 		CYCLES(20 + cnt+cnt, 9 + cnt+cnt);
2979 	}
2980 	else
2981 	{	/* STCR */
2982 		/* STCR -- STore from CRu */
2983 		/* S = CRU R12--CRU R12+D-1 */
2984 		if (cnt <= 8)
2985 		{
2986 #if (TMS99XX_MODEL != TMS9995_ID)
2987 			(void)readbyte(addr); /*dummy read*/
2988 			(void)READREG(cnt+cnt); /*dummy read (reasonnable guess, cf TMS9995)*/
2989 			value = readCRU((READREG(R12) >> 1), cnt);
2990 			setst_byte_laep(value);
2991 			writebyte(addr, value);
2992 			CYCLES((cnt != 8) ? 42 : 44, 19 + cnt);
2993 #else
2994 			/* just for once, tms9995 behaves like earlier 8-bit tms99xx chips */
2995 			/* this must be because instruction decoding is too complex */
2996 			int value2 = readword(addr);
2997 
2998 			READREG(cnt+cnt); /*dummy read (guessed from timing table)*/
2999 			value = readCRU((READREG(R12) >> 1), cnt);
3000 			setst_byte_laep(value);
3001 
3002 			if (addr & 1)
3003 				writeword(addr, (value & 0x00FF) | (value2 & 0xFF00));
3004 			else
3005 				writeword(addr, (value2 & 0x00FF) | ((value << 8) & 0xFF00));
3006 
3007 			CYCLES(Mooof!, 19 + cnt);
3008 #endif
3009 		}
3010 		else
3011 		{
3012 			(void)readword(addr); /*dummy read*/
3013 			(void)READREG(cnt+cnt); /*dummy read (reasonnable guess, cf TMS9995)*/
3014 			value = readCRU((READREG(R12) >> 1), cnt);
3015 			setst_lae(value);
3016 			writeword(addr, value);
3017 			CYCLES((cnt != 16) ? 58 : 60, 27 + cnt);
3018 		}
3019 	}
3020 }
3021 
3022 
3023 /*==========================================================================
3024    Two-Operand instructions                                    >4000->FFFF
3025  ---------------------------------------------------------------------------
3026 
3027       0 1 2 3-4 5 6 7+8 9 A B-C D E F
3028     ----------------------------------
3029     |opcode|B|TD |   D   |TS |   S   |
3030     ----------------------------------
3031 
3032   SZC, SZCB, S, SB, C, CB, A, AB, MOV, MOVB, SOC, SOCB
3033 ============================================================================*/
3034 
3035 /* word instructions */
h4000w(UINT16 opcode)3036 static void h4000w(UINT16 opcode)
3037 {
3038 	register UINT16 src;
3039 	register UINT16 dest;
3040 	register UINT16 value;
3041 
3042 	src = decipheraddr(opcode) & ~1;
3043 	dest = decipheraddr(opcode >> 6) & ~1;
3044 
3045 	switch ((opcode >> 13) & 0x0007)    /* ((opcode & 0xE000) >> 13) */
3046 	{
3047 	case 2:   /* SZC */
3048 		/* SZC --- Set Zeros Corresponding */
3049 		/* D &= ~S */
3050 		value = readword(dest) & (~ readword(src));
3051 		setst_lae(value);
3052 		writeword(dest, value);
3053 		CYCLES(14, 4);
3054 		break;
3055 	case 3:   /* S */
3056 		/* S ----- Subtract */
3057 		/* D -= S */
3058 		value = setst_sub_laeco(readword(dest), readword(src));
3059 		writeword(dest, value);
3060 		CYCLES(14, 4);
3061 		break;
3062 	case 4:   /* C */
3063 		/* C ----- Compare */
3064 		/* ST = (D - S) */
3065 		setst_c_lae(readword(dest), readword(src));
3066 		CYCLES(14, 4);
3067 		break;
3068 	case 5:   /* A */
3069 		/* A ----- Add */
3070 		/* D += S */
3071 		value = setst_add_laeco(readword(dest), readword(src));
3072 		writeword(dest, value);
3073 		CYCLES(14, 4);
3074 		break;
3075 	case 6:   /* MOV */
3076 		/* MOV --- MOVe */
3077 		/* D = S */
3078 		value = readword(src);
3079 		setst_lae(value);
3080 #if (TMS99XX_MODEL <= TMS9989_ID)
3081 		/* MOV performs a dummy read... */
3082 		(void)readword(dest);
3083 #endif
3084 		writeword(dest, value);
3085 		CYCLES(14, 3);
3086 		break;
3087 	case 7:   /* SOC */
3088 		/* SOC --- Set Ones Corresponding */
3089 		/* D |= S */
3090 		value = readword(dest) | readword(src);
3091 		setst_lae(value);
3092 		writeword(dest, value);
3093 		CYCLES(14, 4);
3094 		break;
3095 	}
3096 }
3097 
3098 /* byte instruction */
h4000b(UINT16 opcode)3099 static void h4000b(UINT16 opcode)
3100 {
3101 	register UINT16 src;
3102 	register UINT16 dest;
3103 	register UINT16 value;
3104 
3105 	src = decipheraddrbyte(opcode);
3106 	dest = decipheraddrbyte(opcode >> 6);
3107 
3108 	switch ((opcode >> 13) & 0x0007)    /* ((opcode & 0xE000) >> 13) */
3109 	{
3110 	case 2:   /* SZCB */
3111 		/* SZCB -- Set Zeros Corresponding, Byte */
3112 		/* D &= ~S */
3113 		value = readbyte(dest) & (~ readbyte(src));
3114 		setst_byte_laep(value);
3115 		writebyte(dest, value);
3116 		CYCLES(14, 4);
3117 		break;
3118 	case 3:   /* SB */
3119 		/* SB ---- Subtract, Byte */
3120 		/* D -= S */
3121 		value = setst_subbyte_laecop(readbyte(dest), readbyte(src));
3122 		writebyte(dest, value);
3123 		CYCLES(14, 4);
3124 		break;
3125 	case 4:   /* CB */
3126 		/* CB ---- Compare Bytes */
3127 		/* ST = (D - S) */
3128 		value = readbyte(src);
3129 		setst_c_lae(readbyte(dest)<<8, value<<8);
3130 		lastparity = value;
3131 		CYCLES(14, 4);
3132 		break;
3133 	case 5:   /* AB */
3134 		/* AB ---- Add, Byte */
3135 		/* D += S */
3136 		value = setst_addbyte_laecop(readbyte(dest), readbyte(src));
3137 		writebyte(dest, value);
3138 		break;
3139 	case 6:   /* MOVB */
3140 		/* MOVB -- MOVe Bytes */
3141 		/* D = S */
3142 		value = readbyte(src);
3143 		setst_byte_laep(value);
3144 #if (TMS99XX_MODEL <= TMS9989_ID)
3145 		/* on tms9900, MOVB needs to read destination, because it cannot actually read one single byte.
3146 		  It reads a word, replaces the revelant byte, then write the result */
3147 		/* A tms9980 theorically does not need to do so, but still does... */
3148 		readbyte(dest);
3149 #endif
3150 		writebyte(dest, value);
3151 		CYCLES(14, 3);
3152 		break;
3153 	case 7:   /* SOCB */
3154 		/* SOCB -- Set Ones Corresponding, Byte */
3155 		/* D |= S */
3156 		value = readbyte(dest) | readbyte(src);
3157 		setst_byte_laep(value);
3158 		writebyte(dest, value);
3159 		CYCLES(14, 4);
3160 		break;
3161 	}
3162 }
3163 
3164 
execute(UINT16 opcode)3165 static INLINE void execute(UINT16 opcode)
3166 {
3167 #if (TMS99XX_MODEL <= TMS9985_ID)
3168 
3169 	/* tms9900-like instruction set*/
3170 
3171 	static void (* jumptable[128])(UINT16) =
3172 	{
3173 		&illegal,&h0200,&h0400,&h0400,&h0800,&h0800,&illegal,&illegal,
3174 		&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,
3175 		&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,&xop,&xop,
3176 		&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&h2000,&h2000,&h2000,&h2000,
3177 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3178 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3179 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3180 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3181 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3182 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3183 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3184 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3185 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3186 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3187 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3188 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b
3189 	};
3190 
3191 	(* jumptable[opcode >> 9])(opcode);
3192 
3193 #elif (TMS99XX_MODEL <= TMS9995_ID)
3194 
3195 	/* tms9989 and tms9995 include 4 extra instructions, and one additionnal instruction type */
3196 
3197 	static void (* jumptable[256])(UINT16) =
3198 	{
3199 		&h0040,&h0100,&h0200,&h0200,&h0400,&h0400,&h0400,&h0400,
3200 		&h0800,&h0800,&h0800,&h0800,&illegal,&illegal,&illegal,&illegal,
3201 		&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,
3202 		&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,
3203 		&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,
3204 		&h2000,&h2000,&h2000,&h2000,&xop,&xop,&xop,&xop,
3205 		&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,
3206 		&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,
3207 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3208 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3209 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3210 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3211 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3212 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3213 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3214 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3215 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3216 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3217 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3218 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3219 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3220 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3221 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3222 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3223 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3224 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3225 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3226 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3227 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3228 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3229 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3230 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b
3231 	};
3232 
3233 	(* jumptable[opcode >> 8])(opcode);
3234 
3235 #elif (TMS99XX_MODEL >= TMS99105A_ID)
3236 
3237 	/* tms99xxx include even more instruction types */
3238 
3239 	static void (* jumptable[1024])(UINT16) =
3240 	{
3241 		&h0000,&h0040,&h0040,&illegal,&h0100,&h0100,&h0100,&h0100,
3242 		&h0200,&h0200,&h0200,&h0200,&h0200,&h0200,&h0200,&h0200,
3243 		&h0400,&h0400,&h0400,&h0400,&h0400,&h0400,&h0400,&h0400,
3244 		&h0400,&h0400,&h0400,&h0400,&h0400,&h0400,&h0400,&h0400,
3245 		&h0800,&h0800,&h0800,&h0800,&h0800,&h0800,&h0800,&h0800,
3246 		&h0800,&h0800,&h0800,&h0800,&h0800,&h0800,&h0800,&h0800,
3247 #if (TMS99XX_MODEL == TMS99110A_ID)
3248 		&h0c00,&h0c40,&h0c40,&h0c40,&h0c40,&h0c40,&h0c40,&h0c40,
3249 #else
3250 		&h0c00,&illegal,&illegal,&illegal,&illegal,&illegal,&illegal,&illegal,
3251 #endif
3252 		&illegal,&illegal,&illegal,&illegal,&illegal,&illegal,&illegal,&illegal,
3253 		&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,
3254 		&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,
3255 		&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,
3256 		&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,
3257 		&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,
3258 		&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,
3259 		&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,
3260 		&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,&h1000,
3261 		&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,
3262 		&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,
3263 		&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,
3264 		&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,
3265 		&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,
3266 		&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,
3267 		&xop,&xop,&xop,&xop,&xop,&xop,&xop,&xop,
3268 		&xop,&xop,&xop,&xop,&xop,&xop,&xop,&xop,
3269 		&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,
3270 		&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,
3271 		&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,
3272 		&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,&ldcr_stcr,
3273 		&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,
3274 		&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,
3275 		&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,
3276 		&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,&h2000,
3277 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3278 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3279 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3280 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3281 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3282 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3283 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3284 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3285 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3286 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3287 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3288 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3289 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3290 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3291 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3292 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3293 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3294 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3295 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3296 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3297 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3298 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3299 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3300 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3301 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3302 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3303 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3304 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3305 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3306 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3307 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3308 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3309 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3310 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3311 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3312 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3313 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3314 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3315 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3316 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3317 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3318 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3319 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3320 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3321 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3322 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3323 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3324 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3325 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3326 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3327 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3328 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3329 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3330 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3331 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3332 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3333 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3334 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3335 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3336 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3337 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3338 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3339 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3340 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3341 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3342 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3343 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3344 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3345 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3346 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3347 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3348 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3349 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3350 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3351 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3352 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3353 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3354 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3355 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3356 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3357 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3358 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3359 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3360 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3361 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3362 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3363 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3364 		&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,&h4000w,
3365 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3366 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3367 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3368 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3369 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3370 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3371 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,
3372 		&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b,&h4000b
3373 	};
3374 
3375 	(* jumptable[opcode >> 6])(opcode);
3376 
3377 #endif
3378 }
3379