1 /****************************************************************************
2  *                      Intel 8039 Portable Emulator                        *
3  *                                                                          *
4  *                   Copyright Mirko Buffoni                             *
5  *  Based on the original work Copyright Dan Boris, an 8048 emulator     *
6  *      You are not allowed to distribute this software commercially        *
7  *        Please, notify me, if you make any changes to this file           *
8  *                                                                          *
9  *                                                                          *
10  *  **** Change Log ****                                                    *
11  *                                                                          *
12  *  TLP (19-Jun-2001)                                                       *
13  *   - Changed Ports 1 and 2 to quasi bidirectional output latched ports    *
14  *   - Added the Port 1 & 2 output latch data to the debugger window        *
15  *  TLP (02-Jan-2002)                                                       *
16  *   - External IRQs no longer go pending (sampled as a level state)        *
17  *   - Timer IRQs do not go pending if Timer interrupts are disabled        *
18  *   - Timer IRQs made pending, were incorrectly being cleared if the       *
19  *      external interrupt was being serviced                               *
20  *   - External interrupts now take precedence when simultaneous            *
21  *      internal and external interrupt requests occur                      *
22  *   - 'DIS TCNTI' now removes pending timer IRQs                           *
23  *   - Nested IRQs of any sort are no longer allowed                        *
24  *   - T_flag was not being set in the right place of execution, which      *
25  *      could have lead to it being incorrectly set after being cleared     *
26  *   - Counter overflows now also set the T_flag                            *
27  *   - Added the Timer/Counter register to the debugger window              *
28  *  TLP (09-Jan-2002)                                                       *
29  *   - Changed Interrupt system to instant servicing                        *
30  *   - The Timer and Counter can no longer be 'on' simultaneously           *
31  *   - Added Save State                                                     *
32  *  TLP (15-Feb-2002)                                                       *
33  *   - Corrected Positive signal edge sensing (used on the T1 input)        *
34  ****************************************************************************/
35 
36 #define I8039_NUM		2
37 
38 #include "burnint.h"
39 #include "i8039.h"
40 
41 typedef union
42 {
43 	struct { UINT8 l,h,h2,h3; } b;
44 	struct { UINT16 l,h; } w;
45 	UINT32 d;
46 } I8039_PAIR;
47 
48 /*** Cycle times for the jump on condition instructions, are unusual.
49      Condition is tested during the first cycle, so if condition is not
50      met, second address fetch cycle may not really be taken. For now we
51      just use the cycle counts as listed in the i8048 user manual.
52 ***/
53 
54 #if 0
55 #define ADJUST_CYCLES { inst_cycles -= 1; }	/* Possible real cycles setting */
56 #else
57 #define ADJUST_CYCLES { }					/* User Manual cycles setting */
58 #endif
59 
60 /* There are certain differences between the processors */
61 #define FEATURE_M58715		1
62 
63 /* HJB 01/05/99 changed to positive values to use pending_irq as a flag */
64 #define I8039_NO_INT		0	/* No Interrupts pending or executing   */
65 #define I8039_EXTERNAL_INT	1	/* Execute a normal external interrupt  */
66 #define I8039_TIMCNT_INT	2	/* Execute a Timer/Counter interrupt    */
67 
68 static int Ext_IRQ(void);
69 static int Timer_IRQ(void);
70 
71 #define M_RDMEM(A)		I8039_RDMEM(A)
72 //#define M_RDOP(A)     I8039_RDOP(A)
73 //#define M_RDOP_ARG(A) I8039_RDOP_ARG(A)
74 #define M_IN(A)			I8039_In(A)
75 #define M_OUT(A,V)		I8039_Out(A,V)
76 
77 #define port_r(A)		I8039_In(I8039_p0 + A)
78 #define port_w(A,V)		I8039_Out(I8039_p0 + A,V)
79 #define test_r(A)		I8039_In(I8039_t0 + A)
80 #define test_w(A,V)		I8039_Out(I8039_t0 + A,V)
81 #define bus_r()			I8039_In(I8039_bus)
82 #define bus_w(V)		I8039_Out(I8039_bus,V)
83 
84 #define INTRAM_R(A)		(intRAM[(A) & R.ram_mask])
85 #define INTRAM_W(A,V)	do { intRAM[(A) & R.ram_mask] = V; } while (0);
86 
87 #define C_FLAG			0x80
88 #define A_FLAG			0x40
89 #define F_FLAG			0x20
90 #define B_FLAG			0x10
91 
92 typedef struct
93 {
94 	I8039_PAIR	PREVPC;			/* previous program counter */
95 	I8039_PAIR	PC;				/* program counter */
96 	UINT8	A, SP, PSW;
97 	UINT8	bus, f1;		/* Bus data, and flag1 */
98 	UINT8	P1, P2;			/* Internal Port 1 and 2 latched outputs */
99 	UINT8	EA;				/* latched EA input */
100 	UINT8	cpu_feature;	/* process feature */
101 	UINT8	ram_mask;		/* internal ram size - 1 */
102 	UINT16	int_rom_size;	/* internal rom size */
103 	UINT8	pending_irq, irq_executing, masterClock, regPtr;
104 	UINT8	t_flag, timer, timerON, countON, xirq_en, tirq_en;
105 	UINT16	A11;
106 	UINT8	irq_state, irq_extra_cycles;
107 	INT32   inst_cycles;
108 	UINT8	Old_T1;
109 	double total_cycles;
110 } I8039_Regs;
111 
112 typedef struct
113 {
114 	i8039ReadIoHandler I8039IORead;
115 	i8039WriteIoHandler I8039IOWrite;
116 	i8039ReadProgHandler I8039ProgramRead;
117 	i8039WriteProgHandler I8039ProgramWrite;
118 	i8039ReadOpHandler I8039CPUReadOp;
119 	i8039ReadOpArgHandler I8039CPUReadOpArg;
120 } I8039_Handlers;
121 
122 static I8039_Regs R;
123 static int	   i8039_ICount = 0;
124 static int	   i8039_ICount_cycles = 0;
125 
126 static UINT8 *RAM;
127 
128 static I8039_Regs RegStore[I8039_NUM];
129 static I8039_Handlers Handlers[I8039_NUM];
130 static I8039_Handlers *HPtr;
131 static UINT8 *RAMStore[I8039_NUM] = { NULL, NULL };
132 static int nI8039Active = -1;
133 
134 static void i8039_get_context (void *dst); // forwards
135 static void i8039_set_context (void *src);
136 
I8039Open(INT32 nCpu)137 void I8039Open(INT32 nCpu)
138 {
139 	if (nCpu >= I8039_NUM) {
140 		bprintf (0, _T("I8039Open called with nCpu (%d) greater than maximum (%d)!\n"), nCpu, I8039_NUM);
141 		return;
142 	}
143 
144 	if (nI8039Active == nCpu) {
145 		bprintf (0, _T("I8039Open called with already active cpu (%d)!\n"), nCpu);
146 		return;
147 	}
148 
149 	nI8039Active = nCpu;
150 	RAM = RAMStore[nI8039Active];
151 	i8039_set_context(&RegStore[nI8039Active]);
152 	HPtr = &Handlers[nI8039Active];
153 }
154 
I8039Close()155 void I8039Close()
156 {
157 	if (nI8039Active == -1) {
158 		bprintf (0, _T("I8039Close called no active cpu!\n"));
159 		return;
160 	}
161 
162 	RAM = NULL;
163 	i8039_get_context(&RegStore[nI8039Active]);
164 	HPtr = NULL;
165 	nI8039Active = -1;
166 }
167 
I8039GetActive()168 INT32 I8039GetActive()
169 {
170 	return nI8039Active;
171 }
172 
173 #define I8039_INLINE static inline
174 #define change_pc(newpc)	R.PC.w.l = (newpc)
175 
176 
I8039DummyReadIo(unsigned int)177 unsigned char __fastcall I8039DummyReadIo(unsigned int)
178 {
179 	return 0;
180 }
181 
I8039DummyWriteIo(unsigned int,unsigned char)182 void __fastcall I8039DummyWriteIo(unsigned int, unsigned char)
183 {
184 }
185 
I8039DummyReadProg(unsigned int)186 unsigned char __fastcall I8039DummyReadProg(unsigned int)
187 {
188 	return 0;
189 }
190 
I8039DummyWriteProg(unsigned int,unsigned char)191 void __fastcall I8039DummyWriteProg(unsigned int, unsigned char)
192 {
193 }
194 
I8039DummyReadOp(unsigned int)195 unsigned char __fastcall I8039DummyReadOp(unsigned int)
196 {
197 	return 0;
198 }
199 
I8039DummyReadOpArg(unsigned int)200 unsigned char __fastcall I8039DummyReadOpArg(unsigned int)
201 {
202 	return 0;
203 }
204 
205 /* The opcode table now is a combination of cycle counts and function pointers */
206 typedef struct {
207 	unsigned cycles;
208 	void (*function) (void);
209 }	s_opcode;
210 
211 #define POSITIVE_EDGE_T1  (( (int)(T1-R.Old_T1) > 0) ? 1 : 0)
212 #define NEGATIVE_EDGE_T1  (( (int)(R.Old_T1-T1) > 0) ? 1 : 0)
213 
214 #define M_Cy	((R.PSW & C_FLAG) >> 7)
215 #define M_Cn	(!M_Cy)
216 #define M_Ay	((R.PSW & A_FLAG))
217 #define M_An	(!M_Ay)
218 #define M_F0y	((R.PSW & F_FLAG))
219 #define M_F0n	(!M_F0y)
220 #define M_By	((R.PSW & B_FLAG))
221 #define M_Bn	(!M_By)
222 
223 #define intRAM	RAM
224 #define regPTR	R.regPtr
225 
226 #define R0	intRAM[regPTR  ]
227 #define R1	intRAM[regPTR+1]
228 #define R2	intRAM[regPTR+2]
229 #define R3	intRAM[regPTR+3]
230 #define R4	intRAM[regPTR+4]
231 #define R5	intRAM[regPTR+5]
232 #define R6	intRAM[regPTR+6]
233 #define R7	intRAM[regPTR+7]
234 
ea_r(void)235 I8039_INLINE UINT8 ea_r(void)
236 {
237 	R.EA = I8039_In(I8039_ea);
238 	return R.EA;
239 }
240 
M_RDOP(int A)241 I8039_INLINE UINT8 M_RDOP(int A)
242 {
243 	if (R.cpu_feature & FEATURE_M58715)
244 		if ((A<R.int_rom_size) && !ea_r())
245 			return 0x00;
246 	return I8039_RDOP(A);
247 }
248 
M_RDOP_ARG(int A)249 I8039_INLINE UINT8 M_RDOP_ARG(int A)
250 {
251 	if (R.cpu_feature & FEATURE_M58715)
252 		if ((A<R.int_rom_size) && !ea_r())
253 			return 0x00;
254 	return I8039_RDOP_ARG(A);
255 }
256 
CLR(UINT8 flag)257 I8039_INLINE void CLR (UINT8 flag) { R.PSW &= ~flag; }
SET(UINT8 flag)258 I8039_INLINE void SET (UINT8 flag) { R.PSW |= flag;  }
259 
260 
261 /* Get next opcode argument and increment program counter */
M_RDMEM_OPCODE(void)262 I8039_INLINE unsigned M_RDMEM_OPCODE (void)
263 {
264 	unsigned retval;
265 	retval=M_RDOP_ARG(R.PC.w.l);
266 	R.PC.w.l++;
267 	return retval;
268 }
269 
push(UINT8 d)270 I8039_INLINE void push(UINT8 d)
271 {
272 	intRAM[8+R.SP++] = d;
273 	R.SP  = R.SP & 0x0f;
274 	R.PSW = R.PSW & 0xf8;
275 	R.PSW = R.PSW | (R.SP >> 1);
276 }
277 
pull(void)278 I8039_INLINE UINT8 pull(void) {
279 	R.SP  = (R.SP + 15) & 0x0f;		/*  if (--R.SP < 0) R.SP = 15;  */
280 	R.PSW = R.PSW & 0xf8;
281 	R.PSW = R.PSW | (R.SP >> 1);
282 	/* regPTR = ((M_By) ? 24 : 0);  regPTR should not change */
283 	return intRAM[8+R.SP];
284 }
285 
daa_a(void)286 I8039_INLINE void daa_a(void)
287 {
288 	if ((R.A & 0x0f) > 0x09 || (R.PSW & A_FLAG))
289 	{
290 		R.A += 0x06;
291 		if ( ! ( R.A & 0xf0 ) )
292 			SET(C_FLAG);
293 	}
294 	if ((R.A & 0xf0) > 0x90 || (R.PSW & C_FLAG))
295 	{
296 		R.A += 0x60;
297 		SET(C_FLAG);
298 	} else CLR(C_FLAG);
299 }
300 
M_ADD(UINT8 dat)301 I8039_INLINE void M_ADD(UINT8 dat)
302 {
303 	UINT16 temp;
304 
305 	CLR(C_FLAG | A_FLAG);
306 	if ((R.A & 0xf) + (dat & 0xf) > 0xf) SET(A_FLAG);
307 	temp = R.A + dat;
308 	if (temp > 0xff) SET(C_FLAG);
309 	R.A  = temp & 0xff;
310 }
311 
M_ADDC(UINT8 dat)312 I8039_INLINE void M_ADDC(UINT8 dat)
313 {
314 	UINT16 temp;
315 
316 	CLR(A_FLAG);
317 	if ((R.A & 0xf) + (dat & 0xf) + M_Cy > 0xf) SET(A_FLAG);
318 	temp = R.A + dat + M_Cy;
319 	CLR(C_FLAG);
320 	if (temp > 0xff) SET(C_FLAG);
321 	R.A  = temp & 0xff;
322 }
323 
M_CALL(UINT16 addr)324 I8039_INLINE void M_CALL(UINT16 addr)
325 {
326 	push(R.PC.b.l);
327 	push((R.PC.b.h & 0x0f) | (R.PSW & 0xf0));
328 	R.PC.w.l = addr;
329 	change_pc(addr);
330 }
331 
M_XCHD(UINT8 addr)332 I8039_INLINE void M_XCHD(UINT8 addr)
333 {
334 	UINT8 dat = R.A & 0x0f;
335 	UINT8 val = INTRAM_R(addr);
336 	R.A &= 0xf0;
337 	R.A |= val & 0x0f;
338 	val &= 0xf0;
339 	val |= dat;
340 	INTRAM_W(addr, val);
341 }
342 
343 
M_ILLEGAL(void)344 I8039_INLINE void M_ILLEGAL(void)
345 {
346 //	logerror("I8039:  PC = %04x,  Illegal opcode = %02x\n", R.PC.w.l-1, M_RDMEM(R.PC.w.l-1));
347 }
348 
M_UNDEFINED(void)349 I8039_INLINE void M_UNDEFINED(void)
350 {
351 //	logerror("I8039:  PC = %04x,  Unimplemented opcode = %02x\n", R.PC.w.l-1, M_RDMEM(R.PC.w.l-1));
352 }
353 
illegal(void)354 static void illegal(void)	 { M_ILLEGAL(); }
355 
add_a_n(void)356 static void add_a_n(void)	 { M_ADD(M_RDMEM_OPCODE()); }
add_a_r0(void)357 static void add_a_r0(void)	 { M_ADD(R0); }
add_a_r1(void)358 static void add_a_r1(void)	 { M_ADD(R1); }
add_a_r2(void)359 static void add_a_r2(void)	 { M_ADD(R2); }
add_a_r3(void)360 static void add_a_r3(void)	 { M_ADD(R3); }
add_a_r4(void)361 static void add_a_r4(void)	 { M_ADD(R4); }
add_a_r5(void)362 static void add_a_r5(void)	 { M_ADD(R5); }
add_a_r6(void)363 static void add_a_r6(void)	 { M_ADD(R6); }
add_a_r7(void)364 static void add_a_r7(void)	 { M_ADD(R7); }
add_a_xr0(void)365 static void add_a_xr0(void)	 { M_ADD(INTRAM_R(R0)); }
add_a_xr1(void)366 static void add_a_xr1(void)	 { M_ADD(INTRAM_R(R1)); }
adc_a_n(void)367 static void adc_a_n(void)	 { M_ADDC(M_RDMEM_OPCODE()); }
adc_a_r0(void)368 static void adc_a_r0(void)	 { M_ADDC(R0); }
adc_a_r1(void)369 static void adc_a_r1(void)	 { M_ADDC(R1); }
adc_a_r2(void)370 static void adc_a_r2(void)	 { M_ADDC(R2); }
adc_a_r3(void)371 static void adc_a_r3(void)	 { M_ADDC(R3); }
adc_a_r4(void)372 static void adc_a_r4(void)	 { M_ADDC(R4); }
adc_a_r5(void)373 static void adc_a_r5(void)	 { M_ADDC(R5); }
adc_a_r6(void)374 static void adc_a_r6(void)	 { M_ADDC(R6); }
adc_a_r7(void)375 static void adc_a_r7(void)	 { M_ADDC(R7); }
adc_a_xr0(void)376 static void adc_a_xr0(void)	 { M_ADDC(INTRAM_R(R0)); }
adc_a_xr1(void)377 static void adc_a_xr1(void)	 { M_ADDC(INTRAM_R(R1)); }
anl_a_n(void)378 static void anl_a_n(void)	 { R.A &= M_RDMEM_OPCODE(); }
anl_a_r0(void)379 static void anl_a_r0(void)	 { R.A &= R0; }
anl_a_r1(void)380 static void anl_a_r1(void)	 { R.A &= R1; }
anl_a_r2(void)381 static void anl_a_r2(void)	 { R.A &= R2; }
anl_a_r3(void)382 static void anl_a_r3(void)	 { R.A &= R3; }
anl_a_r4(void)383 static void anl_a_r4(void)	 { R.A &= R4; }
anl_a_r5(void)384 static void anl_a_r5(void)	 { R.A &= R5; }
anl_a_r6(void)385 static void anl_a_r6(void)	 { R.A &= R6; }
anl_a_r7(void)386 static void anl_a_r7(void)	 { R.A &= R7; }
anl_a_xr0(void)387 static void anl_a_xr0(void)	 { R.A &= INTRAM_R(R0); }
anl_a_xr1(void)388 static void anl_a_xr1(void)	 { R.A &= INTRAM_R(R1); }
anl_bus_n(void)389 static void anl_bus_n(void)	 { bus_w( bus_r() & M_RDMEM_OPCODE() ); }
390 
anl_p1_n(void)391 static void anl_p1_n(void)
392 {
393 	R.P1 &= M_RDMEM_OPCODE();
394 	port_w( 1, R.P1 );
395 }
396 
anl_p2_n(void)397 static void anl_p2_n(void)
398 {
399 	R.P2 &= M_RDMEM_OPCODE();
400 	port_w( 2, R.P2 );
401 }
402 
anld_p4_a(void)403 static void anld_p4_a(void)	 { port_w( 4, (port_r(4) & M_RDMEM_OPCODE()) & 0x0f ); }
anld_p5_a(void)404 static void anld_p5_a(void)	 { port_w( 5, (port_r(5) & M_RDMEM_OPCODE()) & 0x0f ); }
anld_p6_a(void)405 static void anld_p6_a(void)	 { port_w( 6, (port_r(6) & M_RDMEM_OPCODE()) & 0x0f ); }
anld_p7_a(void)406 static void anld_p7_a(void)	 { port_w( 7, (port_r(7) & M_RDMEM_OPCODE()) & 0x0f ); }
call(void)407 static void call(void)		 { UINT8 i=M_RDMEM_OPCODE(); UINT16 a11 = (R.irq_executing == I8039_NO_INT) ? R.A11 : 0; M_CALL(i | a11); }
call_1(void)408 static void call_1(void)	 { UINT8 i=M_RDMEM_OPCODE(); UINT16 a11 = (R.irq_executing == I8039_NO_INT) ? R.A11 : 0; M_CALL(i | 0x100 | a11); }
call_2(void)409 static void call_2(void)	 { UINT8 i=M_RDMEM_OPCODE(); UINT16 a11 = (R.irq_executing == I8039_NO_INT) ? R.A11 : 0; M_CALL(i | 0x200 | a11); }
call_3(void)410 static void call_3(void)	 { UINT8 i=M_RDMEM_OPCODE(); UINT16 a11 = (R.irq_executing == I8039_NO_INT) ? R.A11 : 0; M_CALL(i | 0x300 | a11); }
call_4(void)411 static void call_4(void)	 { UINT8 i=M_RDMEM_OPCODE(); UINT16 a11 = (R.irq_executing == I8039_NO_INT) ? R.A11 : 0; M_CALL(i | 0x400 | a11); }
call_5(void)412 static void call_5(void)	 { UINT8 i=M_RDMEM_OPCODE(); UINT16 a11 = (R.irq_executing == I8039_NO_INT) ? R.A11 : 0; M_CALL(i | 0x500 | a11); }
call_6(void)413 static void call_6(void)	 { UINT8 i=M_RDMEM_OPCODE(); UINT16 a11 = (R.irq_executing == I8039_NO_INT) ? R.A11 : 0; M_CALL(i | 0x600 | a11); }
call_7(void)414 static void call_7(void)	 { UINT8 i=M_RDMEM_OPCODE(); UINT16 a11 = (R.irq_executing == I8039_NO_INT) ? R.A11 : 0; M_CALL(i | 0x700 | a11); }
clr_a(void)415 static void clr_a(void)		 { R.A=0; }
clr_c(void)416 static void clr_c(void)		 { CLR(C_FLAG); }
clr_f0(void)417 static void clr_f0(void)	 { CLR(F_FLAG); }
clr_f1(void)418 static void clr_f1(void)	 { R.f1 = 0; }
cpl_a(void)419 static void cpl_a(void)		 { R.A ^= 0xff; }
cpl_c(void)420 static void cpl_c(void)		 { R.PSW ^= C_FLAG; }
cpl_f0(void)421 static void cpl_f0(void)	 { R.PSW ^= F_FLAG; }
cpl_f1(void)422 static void cpl_f1(void)	 { R.f1 ^= 1; }
dec_a(void)423 static void dec_a(void)		 { R.A--; }
dec_r0(void)424 static void dec_r0(void)	 { R0--; }
dec_r1(void)425 static void dec_r1(void)	 { R1--; }
dec_r2(void)426 static void dec_r2(void)	 { R2--; }
dec_r3(void)427 static void dec_r3(void)	 { R3--; }
dec_r4(void)428 static void dec_r4(void)	 { R4--; }
dec_r5(void)429 static void dec_r5(void)	 { R5--; }
dec_r6(void)430 static void dec_r6(void)	 { R6--; }
dec_r7(void)431 static void dec_r7(void)	 { R7--; }
dis_i(void)432 static void dis_i(void)		 { R.xirq_en = 0; }
dis_tcnti(void)433 static void dis_tcnti(void)	 { R.tirq_en = 0; R.pending_irq &= ~I8039_TIMCNT_INT; }
djnz_r0(void)434 static void djnz_r0(void)	{ UINT8 i=M_RDMEM_OPCODE(); R0--; if (R0 != 0) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES }
djnz_r1(void)435 static void djnz_r1(void)	{ UINT8 i=M_RDMEM_OPCODE(); R1--; if (R1 != 0) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES }
djnz_r2(void)436 static void djnz_r2(void)	{ UINT8 i=M_RDMEM_OPCODE(); R2--; if (R2 != 0) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES }
djnz_r3(void)437 static void djnz_r3(void)	{ UINT8 i=M_RDMEM_OPCODE(); R3--; if (R3 != 0) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES }
djnz_r4(void)438 static void djnz_r4(void)	{ UINT8 i=M_RDMEM_OPCODE(); R4--; if (R4 != 0) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES }
djnz_r5(void)439 static void djnz_r5(void)	{ UINT8 i=M_RDMEM_OPCODE(); R5--; if (R5 != 0) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES }
djnz_r6(void)440 static void djnz_r6(void)	{ UINT8 i=M_RDMEM_OPCODE(); R6--; if (R6 != 0) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES }
djnz_r7(void)441 static void djnz_r7(void)	{ UINT8 i=M_RDMEM_OPCODE(); R7--; if (R7 != 0) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES }
en_i(void)442 static void en_i(void)		 { R.xirq_en = 1; if (R.irq_state == I8039_EXTERNAL_INT) { R.irq_extra_cycles += Ext_IRQ(); } }
en_tcnti(void)443 static void en_tcnti(void)	 { R.tirq_en = 1; }
ento_clk(void)444 static void ento_clk(void)	 { M_UNDEFINED(); }
in_a_p1(void)445 static void in_a_p1(void)	 { R.A = port_r(1) & R.P1; }
in_a_p2(void)446 static void in_a_p2(void)	 { R.A = port_r(2) & R.P2; }
ins_a_bus(void)447 static void ins_a_bus(void)	 { R.A = bus_r(); }
inc_a(void)448 static void inc_a(void)		 { R.A++; }
inc_r0(void)449 static void inc_r0(void)	 { R0++; }
inc_r1(void)450 static void inc_r1(void)	 { R1++; }
inc_r2(void)451 static void inc_r2(void)	 { R2++; }
inc_r3(void)452 static void inc_r3(void)	 { R3++; }
inc_r4(void)453 static void inc_r4(void)	 { R4++; }
inc_r5(void)454 static void inc_r5(void)	 { R5++; }
inc_r6(void)455 static void inc_r6(void)	 { R6++; }
inc_r7(void)456 static void inc_r7(void)	 { R7++; }
inc_xr0(void)457 static void inc_xr0(void)	 { INTRAM_W(R0, INTRAM_R(R0) + 1); }
inc_xr1(void)458 static void inc_xr1(void)	 { INTRAM_W(R1, INTRAM_R(R1) + 1); }
459 
jmp(void)460 static void jmp(void)
461 {
462 	UINT8 i=M_RDOP(R.PC.w.l);
463 	UINT16 oldpc,newpc;
464 	UINT16 a11 = (R.irq_executing == I8039_NO_INT) ? R.A11 : 0;
465 
466 	oldpc = R.PC.w.l-1;
467 	R.PC.w.l = i | a11;
468 	change_pc(R.PC.w.l);
469 	newpc = R.PC.w.l;
470 	if (newpc == oldpc) { if (i8039_ICount > 0) i8039_ICount = 0; } /* speed up busy loop */
471 	else if (newpc == oldpc-1 && M_RDOP(newpc) == 0x00)	/* NOP - Gyruss */
472 		{ if (i8039_ICount > 0) i8039_ICount = 0; }
473 }
474 
jmp_1(void)475 static void jmp_1(void)	 	 { UINT8 i=M_RDOP(R.PC.w.l); UINT16 a11 = (R.irq_executing == I8039_NO_INT) ? R.A11 : 0; R.PC.w.l = i | 0x100 | a11; change_pc(R.PC.w.l); }
jmp_2(void)476 static void jmp_2(void)	 	 { UINT8 i=M_RDOP(R.PC.w.l); UINT16 a11 = (R.irq_executing == I8039_NO_INT) ? R.A11 : 0; R.PC.w.l = i | 0x200 | a11; change_pc(R.PC.w.l); }
jmp_3(void)477 static void jmp_3(void)	 	 { UINT8 i=M_RDOP(R.PC.w.l); UINT16 a11 = (R.irq_executing == I8039_NO_INT) ? R.A11 : 0; R.PC.w.l = i | 0x300 | a11; change_pc(R.PC.w.l); }
jmp_4(void)478 static void jmp_4(void)	 	 { UINT8 i=M_RDOP(R.PC.w.l); UINT16 a11 = (R.irq_executing == I8039_NO_INT) ? R.A11 : 0; R.PC.w.l = i | 0x400 | a11; change_pc(R.PC.w.l); }
jmp_5(void)479 static void jmp_5(void)	 	 { UINT8 i=M_RDOP(R.PC.w.l); UINT16 a11 = (R.irq_executing == I8039_NO_INT) ? R.A11 : 0; R.PC.w.l = i | 0x500 | a11; change_pc(R.PC.w.l); }
jmp_6(void)480 static void jmp_6(void)	 	 { UINT8 i=M_RDOP(R.PC.w.l); UINT16 a11 = (R.irq_executing == I8039_NO_INT) ? R.A11 : 0; R.PC.w.l = i | 0x600 | a11; change_pc(R.PC.w.l); }
jmp_7(void)481 static void jmp_7(void)	 	 { UINT8 i=M_RDOP(R.PC.w.l); UINT16 a11 = (R.irq_executing == I8039_NO_INT) ? R.A11 : 0; R.PC.w.l = i | 0x700 | a11; change_pc(R.PC.w.l); }
jmpp_xa(void)482 static void jmpp_xa(void)	 { UINT16 addr = (R.PC.w.l & 0xf00) | R.A; R.PC.w.l = (R.PC.w.l & 0xf00) | M_RDMEM(addr); change_pc(R.PC.w.l); }
jb_0(void)483 static void jb_0(void)	 	 { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x01) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES }
jb_1(void)484 static void jb_1(void)	 	 { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x02) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES }
jb_2(void)485 static void jb_2(void)	 	 { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x04) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES }
jb_3(void)486 static void jb_3(void)	 	 { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x08) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES }
jb_4(void)487 static void jb_4(void)	 	 { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x10) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES }
jb_5(void)488 static void jb_5(void)	 	 { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x20) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES }
jb_6(void)489 static void jb_6(void)	 	 { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x40) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES }
jb_7(void)490 static void jb_7(void)	 	 { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x80) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES }
jf0(void)491 static void jf0(void)	 	 { UINT8 i=M_RDMEM_OPCODE(); if (M_F0y) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES }
jf1(void)492 static void jf1(void)	 	 { UINT8 i=M_RDMEM_OPCODE(); if (R.f1)	{ R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES }
jnc(void)493 static void jnc(void)	 	 { UINT8 i=M_RDMEM_OPCODE(); if (M_Cn)	{ R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES }
jc(void)494 static void jc(void)	 	 { UINT8 i=M_RDMEM_OPCODE(); if (M_Cy)	{ R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES }
jni(void)495 static void jni(void)	 	 { UINT8 i=M_RDMEM_OPCODE(); if (R.irq_state == I8039_EXTERNAL_INT) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES }
jnt_0(void)496 static void jnt_0(void)  	 { UINT8 i=M_RDMEM_OPCODE(); if (!test_r(0)) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES }
jt_0(void)497 static void jt_0(void)	 	 { UINT8 i=M_RDMEM_OPCODE(); if (test_r(0))  { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES }
jnt_1(void)498 static void jnt_1(void)  	 { UINT8 i=M_RDMEM_OPCODE(); if (!test_r(1)) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES }
jt_1(void)499 static void jt_1(void)	 	 { UINT8 i=M_RDMEM_OPCODE(); if (test_r(1))  { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES }
jnz(void)500 static void jnz(void)	 	 { UINT8 i=M_RDMEM_OPCODE(); if (R.A != 0)	 { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES }
jz(void)501 static void jz(void)	 	 { UINT8 i=M_RDMEM_OPCODE(); if (R.A == 0)	 { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); } else ADJUST_CYCLES }
jtf(void)502 static void jtf(void)	 	 { UINT8 i=M_RDMEM_OPCODE(); if (R.t_flag)	 { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; change_pc(R.PC.w.l); R.t_flag = 0; } else ADJUST_CYCLES }
mov_a_n(void)503 static void mov_a_n(void)	 { R.A = M_RDMEM_OPCODE(); }
mov_a_r0(void)504 static void mov_a_r0(void)	 { R.A = R0; }
mov_a_r1(void)505 static void mov_a_r1(void)	 { R.A = R1; }
mov_a_r2(void)506 static void mov_a_r2(void)	 { R.A = R2; }
mov_a_r3(void)507 static void mov_a_r3(void)	 { R.A = R3; }
mov_a_r4(void)508 static void mov_a_r4(void)	 { R.A = R4; }
mov_a_r5(void)509 static void mov_a_r5(void)	 { R.A = R5; }
mov_a_r6(void)510 static void mov_a_r6(void)	 { R.A = R6; }
mov_a_r7(void)511 static void mov_a_r7(void)	 { R.A = R7; }
mov_a_psw(void)512 static void mov_a_psw(void)	 { R.A = R.PSW; }
mov_a_xr0(void)513 static void mov_a_xr0(void)	 { R.A = INTRAM_R(R0); }
mov_a_xr1(void)514 static void mov_a_xr1(void)	 { R.A = INTRAM_R(R1); }
mov_r0_a(void)515 static void mov_r0_a(void)	 { R0 = R.A; }
mov_r1_a(void)516 static void mov_r1_a(void)	 { R1 = R.A; }
mov_r2_a(void)517 static void mov_r2_a(void)	 { R2 = R.A; }
mov_r3_a(void)518 static void mov_r3_a(void)	 { R3 = R.A; }
mov_r4_a(void)519 static void mov_r4_a(void)	 { R4 = R.A; }
mov_r5_a(void)520 static void mov_r5_a(void)	 { R5 = R.A; }
mov_r6_a(void)521 static void mov_r6_a(void)	 { R6 = R.A; }
mov_r7_a(void)522 static void mov_r7_a(void)	 { R7 = R.A; }
mov_psw_a(void)523 static void mov_psw_a(void)	 { R.PSW = R.A; regPTR = ((M_By) ? 24 : 0); R.SP = (R.PSW & 7) << 1; }
mov_r0_n(void)524 static void mov_r0_n(void)	 { R0 = M_RDMEM_OPCODE(); }
mov_r1_n(void)525 static void mov_r1_n(void)	 { R1 = M_RDMEM_OPCODE(); }
mov_r2_n(void)526 static void mov_r2_n(void)	 { R2 = M_RDMEM_OPCODE(); }
mov_r3_n(void)527 static void mov_r3_n(void)	 { R3 = M_RDMEM_OPCODE(); }
mov_r4_n(void)528 static void mov_r4_n(void)	 { R4 = M_RDMEM_OPCODE(); }
mov_r5_n(void)529 static void mov_r5_n(void)	 { R5 = M_RDMEM_OPCODE(); }
mov_r6_n(void)530 static void mov_r6_n(void)	 { R6 = M_RDMEM_OPCODE(); }
mov_r7_n(void)531 static void mov_r7_n(void)	 { R7 = M_RDMEM_OPCODE(); }
mov_a_t(void)532 static void mov_a_t(void)	 { R.A = R.timer; }
mov_t_a(void)533 static void mov_t_a(void)	 { R.timer = R.A; }
mov_xr0_a(void)534 static void mov_xr0_a(void)	 { INTRAM_W(R0, R.A); }
mov_xr1_a(void)535 static void mov_xr1_a(void)	 { INTRAM_W(R1, R.A); }
mov_xr0_n(void)536 static void mov_xr0_n(void)	 { INTRAM_W(R0, M_RDMEM_OPCODE()); }
mov_xr1_n(void)537 static void mov_xr1_n(void)	 { INTRAM_W(R1, M_RDMEM_OPCODE()); }
movd_a_p4(void)538 static void movd_a_p4(void)	 { R.A = port_r(4) & 0x0F; }
movd_a_p5(void)539 static void movd_a_p5(void)	 { R.A = port_r(5) & 0x0F; }
movd_a_p6(void)540 static void movd_a_p6(void)	 { R.A = port_r(6) & 0x0F; }
movd_a_p7(void)541 static void movd_a_p7(void)	 { R.A = port_r(7) & 0x0F; }
movd_p4_a(void)542 static void movd_p4_a(void)	 { port_w(4, R.A & 0x0F); }
movd_p5_a(void)543 static void movd_p5_a(void)	 { port_w(5, R.A & 0x0F); }
movd_p6_a(void)544 static void movd_p6_a(void)	 { port_w(6, R.A & 0x0F); }
movd_p7_a(void)545 static void movd_p7_a(void)	 { port_w(7, R.A & 0x0F); }
movp_a_xa(void)546 static void movp_a_xa(void)	 { R.A = M_RDMEM((R.PC.w.l & 0x0f00) | R.A); }
movp3_a_xa(void)547 static void movp3_a_xa(void) { R.A = M_RDMEM(0x300 | R.A); }
movx_a_xr0(void)548 static void movx_a_xr0(void) { R.A = M_IN(R0); }
movx_a_xr1(void)549 static void movx_a_xr1(void) { R.A = M_IN(R1); }
movx_xr0_a(void)550 static void movx_xr0_a(void) { M_OUT(R0, R.A); }
movx_xr1_a(void)551 static void movx_xr1_a(void) { M_OUT(R1, R.A); }
nop(void)552 static void nop(void) { }
orl_a_n(void)553 static void orl_a_n(void)	 { R.A |= M_RDMEM_OPCODE(); }
orl_a_r0(void)554 static void orl_a_r0(void)	 { R.A |= R0; }
orl_a_r1(void)555 static void orl_a_r1(void)	 { R.A |= R1; }
orl_a_r2(void)556 static void orl_a_r2(void)	 { R.A |= R2; }
orl_a_r3(void)557 static void orl_a_r3(void)	 { R.A |= R3; }
orl_a_r4(void)558 static void orl_a_r4(void)	 { R.A |= R4; }
orl_a_r5(void)559 static void orl_a_r5(void)	 { R.A |= R5; }
orl_a_r6(void)560 static void orl_a_r6(void)	 { R.A |= R6; }
orl_a_r7(void)561 static void orl_a_r7(void)	 { R.A |= R7; }
orl_a_xr0(void)562 static void orl_a_xr0(void)	 { R.A |= INTRAM_R(R0); }
orl_a_xr1(void)563 static void orl_a_xr1(void)	 { R.A |= INTRAM_R(R1); }
orl_bus_n(void)564 static void orl_bus_n(void)	 { bus_w( bus_r() | M_RDMEM_OPCODE() ); }
orl_p1_n(void)565 static void orl_p1_n(void)
566 {
567 	R.P1 |= M_RDMEM_OPCODE();
568 	port_w(1, R.P1);
569 }
570 
orl_p2_n(void)571 static void orl_p2_n(void)
572 {
573 	R.P2 |= M_RDMEM_OPCODE();
574 	port_w(2, R.P2);
575 }
576 
orld_p4_a(void)577 static void orld_p4_a(void)	 { port_w(4, port_r(4) | R.A ); }
orld_p5_a(void)578 static void orld_p5_a(void)	 { port_w(5, port_r(5) | R.A ); }
orld_p6_a(void)579 static void orld_p6_a(void)	 { port_w(6, port_r(6) | R.A ); }
orld_p7_a(void)580 static void orld_p7_a(void)	 { port_w(7, port_r(7) | R.A ); }
outl_bus_a(void)581 static void outl_bus_a(void) { bus_w(R.A); }
outl_p1_a(void)582 static void outl_p1_a(void)	 { port_w(1, R.A); R.P1 = R.A; }
outl_p2_a(void)583 static void outl_p2_a(void)	 { port_w(2, R.A); R.P2 = R.A; }
ret(void)584 static void ret(void)	 { R.PC.w.l = ((pull() & 0x0f) << 8); R.PC.w.l |= pull(); change_pc(R.PC.w.l); }
585 
retr(void)586 static void retr(void)
587 {
588 	UINT8 i=pull();
589 	R.PC.w.l = ((i & 0x0f) << 8) | pull();
590 	change_pc(R.PC.w.l);
591 	R.PSW = (R.PSW & 0x0f) | (i & 0xf0);	/* Stack is already changed by pull */
592 	regPTR = ((M_By) ? 24 : 0);
593 
594 	R.irq_executing = I8039_NO_INT;
595 
596 	/* Take an interrupt if a request is still being made */
597 	if (R.irq_state == I8039_EXTERNAL_INT) {
598 		R.irq_extra_cycles += Ext_IRQ();			/* Service External IRQ */
599 	}
600 	else if (R.pending_irq == I8039_TIMCNT_INT) {
601 		R.irq_extra_cycles += Timer_IRQ();			/* Service pending Timer/Counter IRQ */
602 	}
603 }
rl_a(void)604 static void rl_a(void)		 { UINT8 i=R.A & 0x80; R.A <<= 1; if (i) R.A |= 0x01; else R.A &= 0xfe; }
605 /* NS990113 */
rlc_a(void)606 static void rlc_a(void) 	 { UINT8 i=M_Cy; if (R.A & 0x80) SET(C_FLAG); else CLR(C_FLAG); R.A <<= 1; if (i) R.A |= 0x01; else R.A &= 0xfe; }
rr_a(void)607 static void rr_a(void)		 { UINT8 i=R.A & 1; R.A >>= 1; if (i) R.A |= 0x80; else R.A &= 0x7f; }
608 /* NS990113 */
rrc_a(void)609 static void rrc_a(void)		 { UINT8 i=M_Cy; if (R.A & 1) SET(C_FLAG); else CLR(C_FLAG); R.A >>= 1; if (i) R.A |= 0x80; else R.A &= 0x7f; }
sel_mb0(void)610 static void sel_mb0(void)	 { R.A11 = 0x000; }
sel_mb1(void)611 static void sel_mb1(void)	 { R.A11 = 0x800; }
sel_rb0(void)612 static void sel_rb0(void)	 { CLR(B_FLAG); regPTR = 0;  }
sel_rb1(void)613 static void sel_rb1(void)	 { SET(B_FLAG); regPTR = 24; }
stop_tcnt(void)614 static void stop_tcnt(void)	 { R.timerON = R.countON = 0; }
strt_cnt(void)615 static void strt_cnt(void)	 { R.countON = 1; R.timerON = 0; R.Old_T1 = test_r(1); }	/* NS990113 */
strt_t(void)616 static void strt_t(void)	 { R.timerON = 1; R.countON = 0; R.masterClock = 0; }	/* NS990113 */
swap_a(void)617 static void swap_a(void)	 { UINT8 i=R.A >> 4; R.A <<= 4; R.A |= i; }
xch_a_r0(void)618 static void xch_a_r0(void)	 { UINT8 i=R.A; R.A=R0; R0=i; }
xch_a_r1(void)619 static void xch_a_r1(void)	 { UINT8 i=R.A; R.A=R1; R1=i; }
xch_a_r2(void)620 static void xch_a_r2(void)	 { UINT8 i=R.A; R.A=R2; R2=i; }
xch_a_r3(void)621 static void xch_a_r3(void)	 { UINT8 i=R.A; R.A=R3; R3=i; }
xch_a_r4(void)622 static void xch_a_r4(void)	 { UINT8 i=R.A; R.A=R4; R4=i; }
xch_a_r5(void)623 static void xch_a_r5(void)	 { UINT8 i=R.A; R.A=R5; R5=i; }
xch_a_r6(void)624 static void xch_a_r6(void)	 { UINT8 i=R.A; R.A=R6; R6=i; }
xch_a_r7(void)625 static void xch_a_r7(void)	 { UINT8 i=R.A; R.A=R7; R7=i; }
xch_a_xr0(void)626 static void xch_a_xr0(void)	 { UINT8 i=R.A; R.A=INTRAM_R(R0); INTRAM_W(R0, i); }
xch_a_xr1(void)627 static void xch_a_xr1(void)	 { UINT8 i=R.A; R.A=INTRAM_R(R1); INTRAM_W(R1, i); }
xchd_a_xr0(void)628 static void xchd_a_xr0(void) { M_XCHD(R0); }
xchd_a_xr1(void)629 static void xchd_a_xr1(void) { M_XCHD(R1); }
xrl_a_n(void)630 static void xrl_a_n(void)	 { R.A ^= M_RDMEM_OPCODE(); }
xrl_a_r0(void)631 static void xrl_a_r0(void)	 { R.A ^= R0; }
xrl_a_r1(void)632 static void xrl_a_r1(void)	 { R.A ^= R1; }
xrl_a_r2(void)633 static void xrl_a_r2(void)	 { R.A ^= R2; }
xrl_a_r3(void)634 static void xrl_a_r3(void)	 { R.A ^= R3; }
xrl_a_r4(void)635 static void xrl_a_r4(void)	 { R.A ^= R4; }
xrl_a_r5(void)636 static void xrl_a_r5(void)	 { R.A ^= R5; }
xrl_a_r6(void)637 static void xrl_a_r6(void)	 { R.A ^= R6; }
xrl_a_r7(void)638 static void xrl_a_r7(void)	 { R.A ^= R7; }
xrl_a_xr0(void)639 static void xrl_a_xr0(void)	 { R.A ^= INTRAM_R(R0); }
xrl_a_xr1(void)640 static void xrl_a_xr1(void)	 { R.A ^= INTRAM_R(R1); }
641 
642 static const s_opcode opcode_main[256]=
643 {
644 	{1, nop	 	   },{0, illegal	},{2, outl_bus_a},{2, add_a_n	},{2, jmp 	   	},{1, en_i		},{0, illegal	},{1, dec_a		},
645 	{2, ins_a_bus  },{2, in_a_p1	},{2, in_a_p2	},{0, illegal	},{2, movd_a_p4 },{2, movd_a_p5	},{2, movd_a_p6	},{2, movd_a_p7 },
646 	{1, inc_xr0    },{1, inc_xr1	},{2, jb_0		},{2, adc_a_n	},{2, call	   	},{1, dis_i		},{2, jtf		},{1, inc_a		},
647 	{1, inc_r0	   },{1, inc_r1 	},{1, inc_r2	},{1, inc_r3	},{1, inc_r4	},{1, inc_r5 	},{1, inc_r6	},{1, inc_r7	},
648 	{1, xch_a_xr0  },{1, xch_a_xr1	},{0, illegal	},{2, mov_a_n	},{2, jmp_1	   	},{1, en_tcnti	},{2, jnt_0 	},{1, clr_a	  	},
649 	{1, xch_a_r0   },{1, xch_a_r1	},{1, xch_a_r2	},{1, xch_a_r3  },{1, xch_a_r4  },{1, xch_a_r5	},{1, xch_a_r6	},{1, xch_a_r7  },
650 	{1, xchd_a_xr0 },{1, xchd_a_xr1	},{2, jb_1		},{0, illegal	},{2, call_1	},{1, dis_tcnti	},{2, jt_0		},{1, cpl_a	  	},
651 	{0, illegal    },{2, outl_p1_a	},{2, outl_p2_a	},{0, illegal	},{2, movd_p4_a },{2, movd_p5_a	},{2, movd_p6_a },{2, movd_p7_a },
652 	{1, orl_a_xr0  },{1, orl_a_xr1	},{1, mov_a_t	},{2, orl_a_n	},{2, jmp_2	   	},{1, strt_cnt	},{2, jnt_1 	},{1, swap_a	},
653 	{1, orl_a_r0   },{1, orl_a_r1	},{1, orl_a_r2	},{1, orl_a_r3  },{1, orl_a_r4  },{1, orl_a_r5	},{1, orl_a_r6	},{1, orl_a_r7  },
654 	{1, anl_a_xr0  },{1, anl_a_xr1	},{2, jb_2		},{2, anl_a_n	},{2, call_2	},{1, strt_t 	},{2, jt_1		},{1, daa_a	  	},
655 	{1, anl_a_r0   },{1, anl_a_r1	},{1, anl_a_r2	},{1, anl_a_r3  },{1, anl_a_r4  },{1, anl_a_r5	},{1, anl_a_r6	},{1, anl_a_r7  },
656 	{1, add_a_xr0  },{1, add_a_xr1	},{1, mov_t_a	},{0, illegal	},{2, jmp_3	   	},{1, stop_tcnt	},{0, illegal	},{1, rrc_a	  	},
657 	{1, add_a_r0   },{1, add_a_r1	},{1, add_a_r2	},{1, add_a_r3  },{1, add_a_r4  },{1, add_a_r5	},{1, add_a_r6	},{1, add_a_r7  },
658 	{1, adc_a_xr0  },{1, adc_a_xr1	},{2, jb_3		},{0, illegal	},{2, call_3	},{1, ento_clk	},{2, jf1		},{1, rr_a 	  	},
659 	{1, adc_a_r0   },{1, adc_a_r1	},{1, adc_a_r2	},{1, adc_a_r3  },{1, adc_a_r4  },{1, adc_a_r5	},{1, adc_a_r6	},{1, adc_a_r7  },
660 	{2, movx_a_xr0 },{2, movx_a_xr1 },{0, illegal	},{2, ret		},{2, jmp_4	   	},{1, clr_f0 	},{2, jni		},{0, illegal	},
661 	{2, orl_bus_n  },{2, orl_p1_n	},{2, orl_p2_n	},{0, illegal	},{2, orld_p4_a },{2, orld_p5_a	},{2, orld_p6_a },{2, orld_p7_a },
662 	{2, movx_xr0_a },{2, movx_xr1_a },{2, jb_4		},{2, retr		},{2, call_4	},{1, cpl_f0 	},{2, jnz		},{1, clr_c	  	},
663 	{2, anl_bus_n  },{2, anl_p1_n	},{2, anl_p2_n	},{0, illegal	},{2, anld_p4_a },{2, anld_p5_a	},{2, anld_p6_a },{2, anld_p7_a },
664 	{1, mov_xr0_a  },{1, mov_xr1_a	},{0, illegal	},{2, movp_a_xa },{2, jmp_5	   	},{1, clr_f1 	},{0, illegal	},{1, cpl_c	  	},
665 	{1, mov_r0_a   },{1, mov_r1_a	},{1, mov_r2_a	},{1, mov_r3_a  },{1, mov_r4_a  },{1, mov_r5_a	},{1, mov_r6_a	},{1, mov_r7_a  },
666 	{2, mov_xr0_n  },{2, mov_xr1_n	},{2, jb_5		},{2, jmpp_xa	},{2, call_5	},{1, cpl_f1 	},{2, jf0		},{0, illegal	},
667 	{2, mov_r0_n   },{2, mov_r1_n	},{2, mov_r2_n	},{2, mov_r3_n  },{2, mov_r4_n  },{2, mov_r5_n	},{2, mov_r6_n	},{2, mov_r7_n  },
668 	{0, illegal    },{0, illegal	},{0, illegal	},{0, illegal	},{2, jmp_6	   	},{1, sel_rb0	},{2, jz		},{1, mov_a_psw },
669 	{1, dec_r0	   },{1, dec_r1 	},{1, dec_r2	},{1, dec_r3	},{1, dec_r4	},{1, dec_r5 	},{1, dec_r6	},{1, dec_r7	},
670 	{1, xrl_a_xr0  },{1, xrl_a_xr1	},{2, jb_6		},{2, xrl_a_n	},{2, call_6	},{1, sel_rb1	},{0, illegal	},{1, mov_psw_a },
671 	{1, xrl_a_r0   },{1, xrl_a_r1	},{1, xrl_a_r2	},{1, xrl_a_r3  },{1, xrl_a_r4  },{1, xrl_a_r5	},{1, xrl_a_r6	},{1, xrl_a_r7  },
672 	{0, illegal    },{0, illegal	},{0, illegal	},{2, movp3_a_xa},{2, jmp_7		},{1, sel_mb0	},{2, jnc		},{1, rl_a 	  	},
673 	{2, djnz_r0    },{2, djnz_r1	},{2, djnz_r2	},{2, djnz_r3	},{2, djnz_r4   },{2, djnz_r5	},{2, djnz_r6	},{2, djnz_r7	},
674 	{1, mov_a_xr0  },{1, mov_a_xr1	},{2, jb_7		},{0, illegal	},{2, call_7	},{1, sel_mb1	},{2, jc		},{1, rlc_a	  	},
675 	{1, mov_a_r0   },{1, mov_a_r1	},{1, mov_a_r2	},{1, mov_a_r3  },{1, mov_a_r4  },{1, mov_a_r5	},{1, mov_a_r6	},{1, mov_a_r7  }
676 };
677 
678 
Ext_IRQ(void)679 static int Ext_IRQ(void)
680 {
681 	int extra_cycles = 0;
682 
683 	if (R.xirq_en) {
684 		if (R.irq_executing == I8039_NO_INT) {
685 //          logerror("I8039:  EXT INTERRUPT being serviced\n");
686 			R.irq_executing = I8039_EXTERNAL_INT;
687 			push(R.PC.b.l);
688 			push((R.PC.b.h & 0x0f) | (R.PSW & 0xf0));
689 			R.PC.w.l = 0x03;
690 
691 			extra_cycles = 2;		/* 2 clock cycles used */
692 
693 			if (R.timerON)	/* NS990113 */
694 				R.masterClock += extra_cycles;
695 			//if (R.irq_callback) (*R.irq_callback)(0);
696 		}
697 	}
698 
699 	return extra_cycles;
700 }
701 
Timer_IRQ(void)702 static int Timer_IRQ(void)
703 {
704 	int extra_cycles = 0;
705 
706 	if (R.tirq_en) {
707 		if (R.irq_executing == I8039_NO_INT) {
708 //          logerror("I8039:  TIMER/COUNTER INTERRUPT\n");
709 			R.irq_executing = I8039_TIMCNT_INT;
710 			R.pending_irq &= ~I8039_TIMCNT_INT;
711 			push(R.PC.b.l);
712 			push((R.PC.b.h & 0x0f) | (R.PSW & 0xf0));
713 			R.PC.w.l = 0x07;
714 			change_pc(0x07);
715 
716 			extra_cycles = 2;		/* 2 clock cycles used */
717 
718 			if (R.timerON)	/* NS990113 */
719 				R.masterClock += extra_cycles;
720 		}
721 		else {
722 			if (R.irq_executing == I8039_EXTERNAL_INT) {
723 				R.pending_irq |= I8039_TIMCNT_INT;
724 			}
725 		}
726 	}
727 
728 	R.t_flag = 1;
729 
730 	return extra_cycles;
731 }
732 
i8039_common_init(INT32 nCpu,INT32 rammask,INT32 romsize)733 static void i8039_common_init(INT32 nCpu, INT32 rammask, INT32 romsize)
734 {
735 	if (nCpu >= I8039_NUM) {
736 		bprintf (0, _T("I8039Init called with nCpu (%d) greater than maximum (%d)!\n"), nCpu, I8039_NUM);
737 		return;
738 	}
739 
740 	DebugCPU_I8039Initted = 1;
741 
742 	RAMStore[nCpu] = (UINT8*)BurnMalloc(128 * sizeof(UINT8));
743 	memset (RAMStore[nCpu], 0, 128);
744 
745 	I8039_Regs *ptr = &RegStore[nCpu];
746 	memset (ptr, 0, sizeof(I8039_Regs));
747 
748 	HPtr = &Handlers[nCpu];
749 	memset (HPtr, 0, sizeof(I8039_Handlers));
750 
751 	ptr->cpu_feature = 0;
752 	ptr->ram_mask = rammask;
753 	ptr->int_rom_size = romsize;
754 	/* not changed on reset*/
755 	ptr->timer = 0;
756 
757 	HPtr->I8039IORead = I8039DummyReadIo;
758 	HPtr->I8039IOWrite = I8039DummyWriteIo;
759 	HPtr->I8039ProgramRead = I8039DummyReadProg;
760 	HPtr->I8039ProgramWrite = I8039DummyWriteProg;
761 	HPtr->I8039CPUReadOp = I8039DummyReadOp;
762 	HPtr->I8039CPUReadOpArg = I8039DummyReadOpArg;
763 
764 	i8039_ICount_cycles = 0;
765 	i8039_ICount = 0;
766 }
767 
I8039Init(INT32 nCpu)768 void I8039Init(INT32 nCpu)
769 {
770 	i8039_common_init(nCpu, 0x7F, 0x800);
771 }
772 
I8035Init(INT32 nCpu)773 void I8035Init(INT32 nCpu)
774 {
775 	i8039_common_init(nCpu, 0x3F, 0x400);
776 }
777 
N7751Init(INT32 nCpu)778 void N7751Init(INT32 nCpu)
779 {
780 	i8039_common_init(nCpu, 0x7F, 0x800);
781 }
782 
I8039SetIOReadHandler(i8039ReadIoHandler handler)783 void I8039SetIOReadHandler(i8039ReadIoHandler handler)
784 {
785 #if defined FBA_DEBUG
786 	if (!DebugCPU_I8039Initted) bprintf(PRINT_ERROR, _T("I8039SetIOReadHandler called without init\n"));
787 
788 	if (nI8039Active == -1) {
789 		bprintf (0, _T("I8039SetIOReadHandler called with no active cpu!\n"));
790 		return;
791 	}
792 
793 	if (nI8039Active >= I8039_NUM) {
794 		bprintf (0, _T("I8039SetIOReadHandler called with invalid CPU number (%d), MAX (%d)!\n"), nI8039Active, I8039_NUM);
795 		return;
796 	}
797 #endif
798 
799 	HPtr->I8039IORead = handler;
800 }
801 
I8039SetIOWriteHandler(i8039WriteIoHandler handler)802 void I8039SetIOWriteHandler(i8039WriteIoHandler handler)
803 {
804 #if defined FBA_DEBUG
805 	if (!DebugCPU_I8039Initted) bprintf(PRINT_ERROR, _T("I8039SetIOWriteHandler called without init\n"));
806 
807 	if (nI8039Active == -1) {
808 		bprintf (0, _T("I8039SetIOWriteHandler called with no active cpu!\n"));
809 		return;
810 	}
811 
812 	if (nI8039Active >= I8039_NUM) {
813 		bprintf (0, _T("I8039SetIOWriteHandler called with invalid CPU number (%d), MAX (%d)!\n"), nI8039Active, I8039_NUM);
814 		return;
815 	}
816 #endif
817 
818 	HPtr->I8039IOWrite = handler;
819 }
820 
I8039SetProgramReadHandler(i8039ReadProgHandler handler)821 void I8039SetProgramReadHandler(i8039ReadProgHandler handler)
822 {
823 #if defined FBA_DEBUG
824 	if (!DebugCPU_I8039Initted) bprintf(PRINT_ERROR, _T("I8039SetProgramReadHandler called without init\n"));
825 
826 	if (nI8039Active == -1) {
827 		bprintf (0, _T("I8039SetProgramReadHandler called with no active cpu!\n"));
828 		return;
829 	}
830 
831 	if (nI8039Active >= I8039_NUM) {
832 		bprintf (0, _T("I8039SetProgramReadHandler called with invalid CPU number (%d), MAX (%d)!\n"), nI8039Active, I8039_NUM);
833 		return;
834 	}
835 #endif
836 
837 	HPtr->I8039ProgramRead = handler;
838 }
839 
I8039SetProgramWriteHandler(i8039WriteProgHandler handler)840 void I8039SetProgramWriteHandler(i8039WriteProgHandler handler)
841 {
842 #if defined FBA_DEBUG
843 	if (!DebugCPU_I8039Initted) bprintf(PRINT_ERROR, _T("I8039SetProgramWriteHandler called without init\n"));
844 
845 	if (nI8039Active == -1) {
846 		bprintf (0, _T("I8039SetProgramWriteHandler called with no active cpu!\n"));
847 		return;
848 	}
849 
850 	if (nI8039Active >= I8039_NUM) {
851 		bprintf (0, _T("I8039SetProgramWriteHandler called with invalid CPU number (%d), MAX (%d)!\n"), nI8039Active, I8039_NUM);
852 		return;
853 	}
854 #endif
855 
856 	HPtr->I8039ProgramWrite = handler;
857 }
858 
I8039SetCPUOpReadHandler(i8039ReadOpHandler handler)859 void I8039SetCPUOpReadHandler(i8039ReadOpHandler handler)
860 {
861 #if defined FBA_DEBUG
862 	if (!DebugCPU_I8039Initted) bprintf(PRINT_ERROR, _T("I8039SetCPUOpReadHandler called without init\n"));
863 
864 	if (nI8039Active == -1) {
865 		bprintf (0, _T("I8039SetCPUOpReadHandler called with no active cpu!\n"));
866 		return;
867 	}
868 
869 	if (nI8039Active >= I8039_NUM) {
870 		bprintf (0, _T("I8039SetCPUOpReadHandler called with invalid CPU number (%d), MAX (%d)!\n"), nI8039Active, I8039_NUM);
871 		return;
872 	}
873 #endif
874 
875 	HPtr->I8039CPUReadOp = handler;
876 }
877 
I8039SetCPUOpReadArgHandler(i8039ReadOpArgHandler handler)878 void I8039SetCPUOpReadArgHandler(i8039ReadOpArgHandler handler)
879 {
880 #if defined FBA_DEBUG
881 	if (!DebugCPU_I8039Initted) bprintf(PRINT_ERROR, _T("I8039SetCPUOpArgReadHandler called without init\n"));
882 
883 	if (nI8039Active == -1) {
884 		bprintf (0, _T("I8039SetCPUOpReadArgHandler called with no active cpu!\n"));
885 		return;
886 	}
887 
888 	if (nI8039Active >= I8039_NUM) {
889 		bprintf (0, _T("I8039SetCPUOpReadArgHandler called with invalid CPU number (%d), MAX (%d)!\n"), nI8039Active, I8039_NUM);
890 		return;
891 	}
892 #endif
893 
894 	HPtr->I8039CPUReadOpArg = handler;
895 }
896 
I8039Exit()897 void I8039Exit()
898 {
899 #if defined FBA_DEBUG
900 	if (!DebugCPU_I8039Initted) bprintf(PRINT_ERROR, _T("I8039Exit called without init\n"));
901 #endif
902 
903 	for (INT32 i = 0; i < I8039_NUM; i++)
904 	{
905 		if (RAMStore[i]) {
906 			BurnFree (RAMStore[i]);
907 			RAMStore[i] = NULL;
908 		}
909 	}
910 
911 	i8039_ICount = 0;
912 
913 	DebugCPU_I8039Initted = 0;
914 }
915 
I8039Run(int cycles)916 int I8039Run(int cycles)
917 {
918 #if defined FBA_DEBUG
919 	if (!DebugCPU_I8039Initted) bprintf(PRINT_ERROR, _T("I8039Run called without init\n"));
920 #endif
921 
922 	UINT8 opcode, T1, timerInt;
923 	int count;
924 
925 	i8039_ICount_cycles = cycles;
926 	i8039_ICount = (cycles - R.irq_extra_cycles);
927 	R.irq_extra_cycles = 0;
928 
929 	do
930 	{
931 		R.PREVPC = R.PC;
932 
933 //		CALL_DEBUGGER(R.PC.w.l);
934 
935 		opcode=M_RDOP(R.PC.w.l);
936 
937 /*      logerror("I8039:  PC = %04x,  opcode = %02x\n", R.PC.w.l, opcode); */
938 
939 		R.PC.w.l++;
940 		R.inst_cycles = opcode_main[opcode].cycles;
941 		(*(opcode_main[opcode].function))();
942 		i8039_ICount -= R.inst_cycles; ///
943 
944 		timerInt = 0;
945 		if (R.countON)	/* NS990113 */
946 		{
947 			for ( ; R.inst_cycles > 0; R.inst_cycles-- )
948 			{
949 				T1 = test_r(1);
950 				if (POSITIVE_EDGE_T1)
951 				{
952 					R.timer++;
953 					if (R.timer == 0)
954 						timerInt = 1;
955 				}
956 				R.Old_T1 = T1;
957 			}
958 		}
959 
960 		if (R.timerON) {
961 			R.masterClock += opcode_main[opcode].cycles;
962 			if (R.masterClock >= 32) {	/* NS990113 */
963 				R.masterClock -= 32;
964 				R.timer++;
965 				if (R.timer == 0)
966 					timerInt = 1;
967 			}
968 		}
969 
970 		if (timerInt)
971 		{
972 			count = Timer_IRQ();	/* Handle Timer IRQ */
973 			i8039_ICount -= count;
974 		}
975 
976 	} while (i8039_ICount>0);
977 
978 	i8039_ICount -= R.irq_extra_cycles;
979 	R.total_cycles += cycles - i8039_ICount;
980 	R.irq_extra_cycles = 0;
981 
982 	cycles = cycles - i8039_ICount;
983 	i8039_ICount_cycles = i8039_ICount = 0;
984 
985 	return cycles;
986 }
987 
I8039TotalCycles()988 INT32 I8039TotalCycles()
989 {
990 	return (INT32)R.total_cycles + (i8039_ICount_cycles - i8039_ICount);
991 }
992 
I8039NewFrame()993 void I8039NewFrame()
994 {
995 	i8039_ICount_cycles = 0;
996 	i8039_ICount = 0;
997 
998 	for (INT32 i = 0; i < I8039_NUM; i++)
999 	{
1000 		I8039_Regs *ptr = &RegStore[i];
1001 
1002 		ptr->total_cycles = 0;
1003 	}
1004 }
1005 
I8039Reset(void)1006 void I8039Reset (void)
1007 {
1008 #if defined FBA_DEBUG
1009 	if (!DebugCPU_I8039Initted) bprintf(PRINT_ERROR, _T("I8039Reset called without init\n"));
1010 #endif
1011 
1012 	R.PC.w.l = 0;
1013 	R.SP  = 0;
1014 	R.A   = 0;
1015 	R.PSW = 0x08;		/* Start with No Carry, Bit 4 is always SET */
1016 	//R.PSW = C_FLAG | 0x08;
1017 	R.P1  = 0xff;
1018 	R.P2  = 0xff;
1019 	R.bus = 0;
1020 	R.irq_executing = I8039_NO_INT;
1021 	R.pending_irq	= I8039_NO_INT;
1022 
1023 	R.A11     = 0;
1024 	R.tirq_en = R.xirq_en = 0;
1025 	R.timerON = R.countON = 0;
1026 
1027 	if (R.cpu_feature & FEATURE_M58715)
1028 	{
1029 		//R.timerON = 1;  /* Mario Bros. doesn't work without this */
1030 		//R.PSW |= C_FLAG; //MB will play startup sound, but wrong # */
1031 	}
1032 	R.irq_extra_cycles = 0;
1033 	R.masterClock = 0;
1034 }
1035 
I8039SetIrqState(int state)1036 void I8039SetIrqState(int state)
1037 {
1038 #if defined FBA_DEBUG
1039 	if (!DebugCPU_I8039Initted) bprintf(PRINT_ERROR, _T("I8039SetIrqState called without init\n"));
1040 #endif
1041 
1042 	if (state != 0) {
1043 		R.irq_state = I8039_EXTERNAL_INT;
1044 		R.irq_extra_cycles += Ext_IRQ();		/* Handle External IRQ */
1045 	}
1046 	else {
1047 		R.irq_state = I8039_NO_INT;
1048 	}
1049 }
1050 
I8039Scan(int nAction,int * pnMin)1051 int I8039Scan(int nAction, int *pnMin)
1052 {
1053 #if defined FBA_DEBUG
1054 	if (!DebugCPU_I8039Initted) bprintf(PRINT_ERROR, _T("I8039Scan called without init\n"));
1055 #endif
1056 
1057 	struct BurnArea ba;
1058 	char szName[16];
1059 
1060 	if (pnMin != NULL) {
1061 		*pnMin = 0x029719;
1062 	}
1063 
1064 	if (nAction & ACB_DRIVER_DATA) {
1065 
1066 		for (INT32 i = 0; i < I8039_NUM; i++)
1067 			if (RAMStore[i]) {
1068 				ScanVar(&RegStore[i], sizeof(I8039_Regs), "I8039Regs");
1069 
1070 				sprintf(szName, "I8039RAM %d", i);
1071 				memset(&ba, 0, sizeof(ba));
1072 				ba.Data	  = RAMStore[i];
1073 				ba.nLen	  = 128;
1074 				ba.szName = szName;
1075 				BurnAcb(&ba);
1076 			}
1077 	}
1078 
1079 	return 0;
1080 }
1081 
1082 /****************************************************************************
1083  * Get all registers in given buffer
1084  ****************************************************************************/
i8039_get_context(void * dst)1085 static void i8039_get_context (void *dst)
1086 {
1087 	if( dst )
1088 		*(I8039_Regs*)dst = R;
1089 }
1090 
1091 
1092 /****************************************************************************
1093  * Set all registers to given values
1094  ****************************************************************************/
i8039_set_context(void * src)1095 static void i8039_set_context (void *src)
1096 {
1097 	if( src )
1098 	{
1099 		R = *(I8039_Regs*)src;
1100 	}
1101 }
1102 
1103 #if 0
1104 
1105 /****************************************************************************
1106  * Initialize emulation
1107  ****************************************************************************/
1108 
1109 
1110 #if (HAS_I8035||HAS_I8048||HAS_MB8884)
1111 static void i8035_init (int index, int clock, const void *config, int (*irqcallback)(int))
1112 {
1113 	i8039_init(index, clock, config, irqcallback);
1114 	R.ram_mask = 0x3F;
1115 	R.int_rom_size = 0x400;
1116 }
1117 #endif
1118 
1119 #if (HAS_I8749)
1120 static void i8749_init (int index, int clock, const void *config, int (*irqcallback)(int))
1121 {
1122 	i8039_init(index, clock, config, irqcallback);
1123 
1124 	R.ram_mask = 0x7f;
1125 	R.int_rom_size = 0x800;
1126 }
1127 #endif
1128 
1129 #if (HAS_M58715)
1130 static void m58715_init (int index, int clock, const void *config, int (*irqcallback)(int))
1131 {
1132 	i8039_init(index, clock, config, irqcallback);
1133 	R.cpu_feature = FEATURE_M58715;
1134 }
1135 #endif /* HAS_M58715 */
1136 
1137 /****************************************************************************
1138  * Reset registers to their initial values
1139  ****************************************************************************/
1140 
1141 /****************************************************************************
1142  * Shut down CPU emulation
1143  ****************************************************************************/
1144 static void i8039_exit (void)
1145 {
1146 	/* nothing to do ? */
1147 }
1148 
1149 /****************************************************************************
1150  * Issue an interrupt if necessary
1151  ****************************************************************************/
1152 
1153 
1154 /****************************************************************************
1155  * Execute cycles CPU cycles. Return number of cycles really executed
1156  ****************************************************************************/
1157 
1158 
1159 /****************************************************************************
1160  * Set IRQ line state
1161  ****************************************************************************/
1162 
1163 
1164 /**************************************************************************
1165  * Generic set_info
1166  **************************************************************************/
1167 
1168 static void i8039_set_info(UINT32 state, cpuinfo *info)
1169 {
1170 	switch (state)
1171 	{
1172 		/* --- the following bits of info are set as 64-bit signed integers --- */
1173 		case CPUINFO_INT_INPUT_STATE + 0:				set_irq_line(0, info->i);				break;
1174 
1175 		case CPUINFO_INT_PC:
1176 		case CPUINFO_INT_REGISTER + I8039_PC:			R.PC.w.l = info->i;						break;
1177 		case CPUINFO_INT_SP:
1178 		case CPUINFO_INT_REGISTER + I8039_SP:			R.SP = info->i;							break;
1179 		case CPUINFO_INT_REGISTER + I8039_PSW:			R.PSW = info->i;						break;
1180 		case CPUINFO_INT_REGISTER + I8039_A:			R.A = info->i;							break;
1181 		case CPUINFO_INT_REGISTER + I8039_TC:			R.timer = info->i;						break;
1182 		case CPUINFO_INT_REGISTER + I8039_P1:			R.P1 = info->i;							break;
1183 		case CPUINFO_INT_REGISTER + I8039_P2:			R.P2 = info->i;							break;
1184 		case CPUINFO_INT_REGISTER + I8039_R0:			R0 = info->i;							break;
1185 		case CPUINFO_INT_REGISTER + I8039_R1:			R1 = info->i;							break;
1186 		case CPUINFO_INT_REGISTER + I8039_R2:			R2 = info->i;							break;
1187 		case CPUINFO_INT_REGISTER + I8039_R3:			R3 = info->i;							break;
1188 		case CPUINFO_INT_REGISTER + I8039_R4:			R4 = info->i;							break;
1189 		case CPUINFO_INT_REGISTER + I8039_R5:			R5 = info->i;							break;
1190 		case CPUINFO_INT_REGISTER + I8039_R6:			R6 = info->i;							break;
1191 		case CPUINFO_INT_REGISTER + I8039_R7:			R7 = info->i;							break;
1192 		case CPUINFO_INT_REGISTER + I8039_EA:			R.EA = info->i;							break;
1193 	}
1194 }
1195 
1196 
1197 
1198 /**************************************************************************
1199  * Generic get_info
1200  **************************************************************************/
1201 
1202 void i8039_get_info(UINT32 state, cpuinfo *info)
1203 {
1204 	switch (state)
1205 	{
1206 		/* --- the following bits of info are returned as 64-bit signed integers --- */
1207 		case CPUINFO_INT_CONTEXT_SIZE:					info->i = sizeof(R);					break;
1208 		case CPUINFO_INT_INPUT_LINES:					info->i = 1;							break;
1209 		case CPUINFO_INT_DEFAULT_IRQ_VECTOR:			info->i = 0;							break;
1210 		case CPUINFO_INT_ENDIANNESS:					info->i = CPU_IS_LE;					break;
1211 		case CPUINFO_INT_CLOCK_MULTIPLIER:				info->i = 1;							break;
1212 		case CPUINFO_INT_CLOCK_DIVIDER:					info->i = 3*5;							break;
1213 		case CPUINFO_INT_MIN_INSTRUCTION_BYTES:			info->i = 1;							break;
1214 		case CPUINFO_INT_MAX_INSTRUCTION_BYTES:			info->i = 2;							break;
1215 		case CPUINFO_INT_MIN_CYCLES:					info->i = 1;							break;
1216 		case CPUINFO_INT_MAX_CYCLES:					info->i = 3;							break;
1217 
1218 		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_PROGRAM:	info->i = 8;					break;
1219 		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_PROGRAM: info->i = 12;					break;
1220 		case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_PROGRAM: info->i = 0;					break;
1221 		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_DATA:	info->i = 0;					break;
1222 		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_DATA: 	info->i = 0;					break;
1223 		case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_DATA: 	info->i = 0;					break;
1224 		case CPUINFO_INT_DATABUS_WIDTH + ADDRESS_SPACE_IO:		info->i = 8;					break;
1225 		case CPUINFO_INT_ADDRBUS_WIDTH + ADDRESS_SPACE_IO: 		info->i = 9;					break;
1226 		case CPUINFO_INT_ADDRBUS_SHIFT + ADDRESS_SPACE_IO: 		info->i = 0;					break;
1227 
1228 		case CPUINFO_INT_INPUT_STATE + 0:				info->i = (R.irq_state == I8039_EXTERNAL_INT) ? ASSERT_LINE : CLEAR_LINE; break;
1229 
1230 		case CPUINFO_INT_PREVIOUSPC:					info->i = R.PREVPC.w.l;					break;
1231 
1232 		case CPUINFO_INT_PC:
1233 		case CPUINFO_INT_REGISTER + I8039_PC:			info->i = R.PC.w.l;						break;
1234 		case CPUINFO_INT_SP:
1235 		case CPUINFO_INT_REGISTER + I8039_SP:			info->i = R.SP;							break;
1236 		case CPUINFO_INT_REGISTER + I8039_PSW:			info->i = R.PSW;						break;
1237 		case CPUINFO_INT_REGISTER + I8039_A:			info->i = R.A;							break;
1238 		case CPUINFO_INT_REGISTER + I8039_TC:			info->i = R.timer;						break;
1239 		case CPUINFO_INT_REGISTER + I8039_P1:			info->i = R.P1;							break;
1240 		case CPUINFO_INT_REGISTER + I8039_P2:			info->i = R.P2;							break;
1241 		case CPUINFO_INT_REGISTER + I8039_R0:			info->i = R0;							break;
1242 		case CPUINFO_INT_REGISTER + I8039_R1:			info->i = R1;							break;
1243 		case CPUINFO_INT_REGISTER + I8039_R2:			info->i = R2;							break;
1244 		case CPUINFO_INT_REGISTER + I8039_R3:			info->i = R3;							break;
1245 		case CPUINFO_INT_REGISTER + I8039_R4:			info->i = R4;							break;
1246 		case CPUINFO_INT_REGISTER + I8039_R5:			info->i = R5;							break;
1247 		case CPUINFO_INT_REGISTER + I8039_R6:			info->i = R6;							break;
1248 		case CPUINFO_INT_REGISTER + I8039_R7:			info->i = R7;							break;
1249 		case CPUINFO_INT_REGISTER + I8039_EA:			info->i = R.EA;							break;
1250 
1251 		/* --- the following bits of info are returned as pointers to data or functions --- */
1252 		case CPUINFO_PTR_SET_INFO:						info->setinfo = i8039_set_info;			break;
1253 		case CPUINFO_PTR_GET_CONTEXT:					info->getcontext = i8039_get_context;	break;
1254 		case CPUINFO_PTR_SET_CONTEXT:					info->setcontext = i8039_set_context;	break;
1255 		case CPUINFO_PTR_INIT:							info->init = i8039_init;				break;
1256 		case CPUINFO_PTR_RESET:							info->reset = i8039_reset;				break;
1257 		case CPUINFO_PTR_EXIT:							info->exit = i8039_exit;				break;
1258 		case CPUINFO_PTR_EXECUTE:						info->execute = i8039_execute;			break;
1259 		case CPUINFO_PTR_BURN:							info->burn = NULL;						break;
1260 #ifdef ENABLE_DEBUGGER
1261 		case CPUINFO_PTR_DISASSEMBLE:					info->disassemble = i8039_dasm;			break;
1262 #endif /* ENABLE_DEBUGGER */
1263 		case CPUINFO_PTR_INSTRUCTION_COUNTER:			info->icount = &i8039_ICount;			break;
1264 
1265 		/* --- the following bits of info are returned as NULL-terminated strings --- */
1266 		case CPUINFO_STR_NAME:							strcpy(info->s, "I8039");				break;
1267 		case CPUINFO_STR_CORE_FAMILY:					strcpy(info->s, "Intel 8039");			break;
1268 		case CPUINFO_STR_CORE_VERSION:					strcpy(info->s, "1.2");					break;
1269 		case CPUINFO_STR_CORE_FILE:						strcpy(info->s, __FILE__);				break;
1270 		case CPUINFO_STR_CORE_CREDITS:					strcpy(info->s, "Copyright Mirko Buffoni\nBased on the original work Copyright Dan Boris"); break;
1271 
1272 		case CPUINFO_STR_FLAGS:
1273 			sprintf(info->s, "%c %c%c%c%c%c%c%c%c",
1274 				R.A11        ? 'M':'.',
1275 				R.PSW & 0x80 ? 'C':'.',
1276 				R.PSW & 0x40 ? 'A':'.',
1277 				R.PSW & 0x20 ? 'F':'.',
1278 				R.PSW & 0x10 ? 'B':'.',
1279 				R.PSW & 0x08 ? '?':'.',
1280 				R.PSW & 0x04 ? '4':'.',
1281 				R.PSW & 0x02 ? '2':'.',
1282 				R.PSW & 0x01 ? '1':'.');
1283 			break;
1284 
1285 		case CPUINFO_STR_REGISTER + I8039_PC:			sprintf(info->s, "PC:%04X", R.PC.w.l); break;
1286 		case CPUINFO_STR_REGISTER + I8039_SP:			sprintf(info->s, "SP:%02X", R.SP); break;
1287 		case CPUINFO_STR_REGISTER + I8039_PSW:			sprintf(info->s, "PSW:%02X", R.PSW); break;
1288 		case CPUINFO_STR_REGISTER + I8039_A:			sprintf(info->s, "A:%02X", R.A); break;
1289 		case CPUINFO_STR_REGISTER + I8039_TC:			sprintf(info->s, "TC:%02X", R.timer); break;
1290 		case CPUINFO_STR_REGISTER + I8039_P1:			sprintf(info->s, "P1:%02X", R.P1); break;
1291 		case CPUINFO_STR_REGISTER + I8039_P2:			sprintf(info->s, "P2:%02X", R.P2); break;
1292 		case CPUINFO_STR_REGISTER + I8039_R0:			sprintf(info->s, "R0:%02X", R.RAM[R.regPtr+0]); break;
1293 		case CPUINFO_STR_REGISTER + I8039_R1:			sprintf(info->s, "R1:%02X", R.RAM[R.regPtr+1]); break;
1294 		case CPUINFO_STR_REGISTER + I8039_R2:			sprintf(info->s, "R2:%02X", R.RAM[R.regPtr+2]); break;
1295 		case CPUINFO_STR_REGISTER + I8039_R3:			sprintf(info->s, "R3:%02X", R.RAM[R.regPtr+3]); break;
1296 		case CPUINFO_STR_REGISTER + I8039_R4:			sprintf(info->s, "R4:%02X", R.RAM[R.regPtr+4]); break;
1297 		case CPUINFO_STR_REGISTER + I8039_R5:			sprintf(info->s, "R5:%02X", R.RAM[R.regPtr+5]); break;
1298 		case CPUINFO_STR_REGISTER + I8039_R6:			sprintf(info->s, "R6:%02X", R.RAM[R.regPtr+6]); break;
1299 		case CPUINFO_STR_REGISTER + I8039_R7:			sprintf(info->s, "R7:%02X", R.RAM[R.regPtr+7]); break;
1300 		case CPUINFO_STR_REGISTER + I8039_EA:			sprintf(info->s, "EA:%02X", R.EA); break;
1301 	}
1302 }
1303 
1304 
1305 #if 0 //(HAS_I8035)
1306 /**************************************************************************
1307  * CPU-specific get_info/set_info
1308  **************************************************************************/
1309 void i8035_get_info(UINT32 state, cpuinfo *info)
1310 {
1311 	switch (state)
1312 	{
1313 		/* --- the following bits of info are returned as NULL-terminated strings --- */
1314 		case CPUINFO_STR_NAME:							strcpy(info->s, "I8035");				break;
1315 		case CPUINFO_PTR_INIT:							info->init = i8035_init;				break;
1316 
1317 		default:										i8039_get_info(state, info);			break;
1318 	}
1319 }
1320 #endif
1321 
1322 
1323 #if (HAS_I8048)
1324 /**************************************************************************
1325  * CPU-specific get_info/set_info
1326  **************************************************************************/
1327 void i8048_get_info(UINT32 state, cpuinfo *info)
1328 {
1329 	switch (state)
1330 	{
1331 		/* --- the following bits of info are returned as NULL-terminated strings --- */
1332 		case CPUINFO_STR_NAME:							strcpy(info->s, "I8048");				break;
1333 		case CPUINFO_PTR_INIT:							info->init = i8035_init;				break;
1334 
1335 		default:										i8039_get_info(state, info);			break;
1336 	}
1337 }
1338 #endif
1339 
1340 #if (HAS_I8749)
1341 /**************************************************************************
1342  * CPU-specific get_info/set_info
1343  **************************************************************************/
1344 void i8749_get_info(UINT32 state, cpuinfo *info)
1345 {
1346 	switch (state)
1347 	{
1348 		/* --- the following bits of info are returned as NULL-terminated strings --- */
1349 		case CPUINFO_STR_NAME:							strcpy(info->s, "I8749");				break;
1350 		case CPUINFO_PTR_INIT:							info->init = i8749_init;				break;
1351 
1352 		default:										i8039_get_info(state, info);			break;
1353 	}
1354 }
1355 #endif
1356 
1357 #if (HAS_N7751)
1358 /**************************************************************************
1359  * CPU-specific get_info/set_info
1360  **************************************************************************/
1361 void n7751_get_info(UINT32 state, cpuinfo *info)
1362 {
1363 	switch (state)
1364 	{
1365 		/* --- the following bits of info are returned as NULL-terminated strings --- */
1366 		case CPUINFO_STR_NAME:							strcpy(info->s, "N7751");				break;
1367 		case CPUINFO_PTR_INIT:							info->init = i8039_init;				break;
1368 
1369 		default:										i8039_get_info(state, info);			break;
1370 	}
1371 }
1372 #endif
1373 
1374 #if (HAS_MB8884)
1375 /**************************************************************************
1376  * CPU-specific get_info/set_info
1377  **************************************************************************/
1378 void mb8884_get_info(UINT32 state, cpuinfo *info)
1379 {
1380 	switch (state)
1381 	{
1382 		/* --- the following bits of info are returned as NULL-terminated strings --- */
1383 		case CPUINFO_STR_NAME:							strcpy(info->s, "MB8884");				break;
1384 		case CPUINFO_PTR_INIT:							info->init = i8035_init;				break;
1385 
1386 		default:										i8039_get_info(state, info);			break;
1387 	}
1388 }
1389 #endif
1390 
1391 #if (HAS_M58715)
1392 /**************************************************************************
1393  * CPU-specific get_info/set_info
1394  **************************************************************************/
1395 void m58715_get_info(UINT32 state, cpuinfo *info)
1396 {
1397 	switch (state)
1398 	{
1399 		/* --- the following bits of info are returned as NULL-terminated strings --- */
1400 		case CPUINFO_STR_NAME:							strcpy(info->s, "M58715");				break;
1401 		case CPUINFO_PTR_INIT:							info->init = m58715_init;				break;
1402 
1403 		default:										i8039_get_info(state, info);			break;
1404 	}
1405 }
1406 #endif
1407 #endif
1408