1 /**************************************************************************
2  *                      Intel 8039 Portable Emulator                      *
3  *                                                                        *
4  *					 Copyright (C) 1997 by Mirko Buffoni				  *
5  *	Based on the original work (C) 1997 by 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 #include <stdio.h>
11 #include <string.h>
12 #include <stdlib.h>
13 #include "cpuintrf.h"
14 #include "i8039.h"
15 
16 #include <retro_inline.h>
17 
18 #define M_RDMEM(A)      I8039_RDMEM(A)
19 #define M_RDOP(A)       I8039_RDOP(A)
20 #define M_RDOP_ARG(A)   I8039_RDOP_ARG(A)
21 #define M_IN(A)		I8039_In(A)
22 #define M_OUT(A,V)	I8039_Out(A,V)
23 
24 #if OLDPORTHANDLING
25         #define port_r(A)	I8039_port_r(A)
26         #define port_w(A,V)	I8039_port_w(A,V)
27         #define test_r(A)	I8039_test_r(A)
28         #define test_w(A,V)	I8039_test_w(A,V)
29         #define bus_r		I8039_bus_r
30         #define bus_w(V)	I8039_bus_w(V)
31 #else
32         #define port_r(A)	I8039_In(I8039_p0 + A)
33         #define port_w(A,V)	I8039_Out(I8039_p0 + A,V)
34         #define test_r(A)	I8039_In(I8039_t0 + A)
35         #define test_w(A,V)	I8039_Out(I8039_t0 + A,V)
36         #define bus_r()		I8039_In(I8039_bus)
37         #define bus_w(V)	I8039_Out(I8039_bus,V)
38 #endif
39 
40 #define C_FLAG          0x80
41 #define A_FLAG          0x40
42 #define F_FLAG          0x20
43 #define B_FLAG          0x10
44 
45 typedef struct
46 {
47 	PAIR	PREPC;			/* previous program counter */
48     PAIR    PC;             /* program counter */
49     UINT8   A, SP, PSW;
50     UINT8   RAM[128];
51     UINT8   bus, f1;        /* Bus data, and flag1 */
52 
53     int     pending_irq,irq_executing, masterClock, regPtr;
54     UINT8   t_flag, timer, timerON, countON, xirq_en, tirq_en;
55     UINT16  A11, A11ff;
56     int     irq_state;
57     int     (*irq_callback)(int irqline);
58 } I8039_Regs;
59 
60 static I8039_Regs R;
61 int    i8039_ICount;
62 static UINT8 Old_T1;
63 
64 /* The opcode table now is a combination of cycle counts and function pointers */
65 typedef struct {
66 	unsigned cycles;
67 	void (*function) (void);
68 }	s_opcode;
69 
70 #define POSITIVE_EDGE_T1  (((T1-Old_T1) > 0) ? 1 : 0)
71 #define NEGATIVE_EDGE_T1  (((Old_T1-T1) > 0) ? 1 : 0)
72 
73 #define M_Cy    ((R.PSW & C_FLAG) >> 7)
74 #define M_Cn    (!M_Cy)
75 #define M_Ay    ((R.PSW & A_FLAG))
76 #define M_An    (!M_Ay)
77 #define M_F0y   ((R.PSW & F_FLAG))
78 #define M_F0n   (!M_F0y)
79 #define M_By    ((R.PSW & B_FLAG))
80 #define M_Bn    (!M_By)
81 
82 #define intRAM	R.RAM
83 #define regPTR	R.regPtr
84 
85 #define R0	intRAM[regPTR  ]
86 #define R1	intRAM[regPTR+1]
87 #define R2	intRAM[regPTR+2]
88 #define R3	intRAM[regPTR+3]
89 #define R4	intRAM[regPTR+4]
90 #define R5	intRAM[regPTR+5]
91 #define R6	intRAM[regPTR+6]
92 #define R7	intRAM[regPTR+7]
93 
94 
CLR(UINT8 flag)95 static INLINE void CLR (UINT8 flag) { R.PSW &= ~flag; }
SET(UINT8 flag)96 static INLINE void SET (UINT8 flag) { R.PSW |= flag;  }
97 
98 
99 /* Get next opcode argument and increment program counter */
M_RDMEM_OPCODE(void)100 static INLINE unsigned M_RDMEM_OPCODE (void)
101 {
102         unsigned retval;
103 		retval=M_RDOP_ARG(R.PC.w.l);
104 		R.PC.w.l++;
105         return retval;
106 }
107 
push(UINT8 d)108 static INLINE void push(UINT8 d)
109 {
110 	intRAM[8+R.SP++] = d;
111     R.SP  = R.SP & 0x0f;
112     R.PSW = R.PSW & 0xf8;
113     R.PSW = R.PSW | (R.SP >> 1);
114 }
115 
pull(void)116 static INLINE UINT8 pull(void) {
117 	R.SP  = (R.SP + 15) & 0x0f;		/*  if (--R.SP < 0) R.SP = 15;  */
118     R.PSW = R.PSW & 0xf8;
119     R.PSW = R.PSW | (R.SP >> 1);
120 	/* regPTR = ((M_By) ? 24 : 0);  regPTR should not change */
121 	return intRAM[8+R.SP];
122 }
123 
daa_a(void)124 static INLINE void daa_a(void)
125 {
126 	if ((R.A & 0x0f) > 0x09 || (R.PSW & A_FLAG))
127 		R.A += 0x06;
128 	if ((R.A & 0xf0) > 0x90 || (R.PSW & C_FLAG))
129 	{
130 		R.A += 0x60;
131 		SET(C_FLAG);
132 	} else CLR(C_FLAG);
133 }
134 
M_ADD(UINT8 dat)135 static INLINE void M_ADD(UINT8 dat)
136 {
137 	UINT16 temp;
138 
139 	CLR(C_FLAG | A_FLAG);
140 	if ((R.A & 0xf) + (dat & 0xf) > 0xf) SET(A_FLAG);
141 	temp = R.A + dat;
142 	if (temp > 0xff) SET(C_FLAG);
143 	R.A  = temp & 0xff;
144 }
145 
M_ADDC(UINT8 dat)146 static INLINE void M_ADDC(UINT8 dat)
147 {
148 	UINT16 temp;
149 
150 	CLR(A_FLAG);
151 	if ((R.A & 0xf) + (dat & 0xf) + M_Cy > 0xf) SET(A_FLAG);
152 	temp = R.A + dat + M_Cy;
153 	CLR(C_FLAG);
154 	if (temp > 0xff) SET(C_FLAG);
155 	R.A  = temp & 0xff;
156 }
157 
M_CALL(UINT16 addr)158 static INLINE void M_CALL(UINT16 addr)
159 {
160 	push(R.PC.b.l);
161 	push((R.PC.b.h & 0x0f) | (R.PSW & 0xf0));
162 	R.PC.w.l = addr;
163 	#ifdef MESS
164 		change_pc(addr);
165 	#endif
166 
167 }
168 
M_XCHD(UINT8 addr)169 static INLINE void M_XCHD(UINT8 addr)
170 {
171 	UINT8 dat = R.A & 0x0f;
172 	R.A &= 0xf0;
173 	R.A |= intRAM[addr] & 0x0f;
174 	intRAM[addr] &= 0xf0;
175 	intRAM[addr] |= dat;
176 }
177 
178 
M_ILLEGAL(void)179 static INLINE void M_ILLEGAL(void)
180 {
181 	/*logerror("I8039:  PC = %04x,  Illegal opcode = %02x\n", R.PC.w.l-1, M_RDMEM(R.PC.w.l-1));*/
182 }
183 
M_UNDEFINED(void)184 static INLINE void M_UNDEFINED(void)
185 {
186 	/*logerror("I8039:  PC = %04x,  Unimplemented opcode = %02x\n", R.PC.w.l-1, M_RDMEM(R.PC.w.l-1));*/
187 }
188 
189 
190 #if OLDPORTHANDLING
I8039_port_r(UINT8 port)191 	UINT8 I8039_port_r(UINT8 port)			  { return R.p[port & 7]; }
I8039_port_w(UINT8 port,UINT8 data)192 	void I8039_port_w(UINT8 port, UINT8 data) { R.p[port & 7] = data; }
193 
I8039_test_r(UINT8 port)194 	UINT8 I8039_test_r(UINT8 port)			  { return R.t[port & 1]; }
I8039_test_w(UINT8 port,UINT8 data)195 	void I8039_test_w(UINT8 port, UINT8 data) { R.t[port & 1] = data; }
196 
I8039_bus_r(void)197 	UINT8 I8039_bus_r(void) 	 { return R.bus; }
I8039_bus_w(UINT8 data)198 	void I8039_bus_w(UINT8 data) { R.bus = data; }
199 #endif
200 
illegal(void)201 static void illegal(void)    { M_ILLEGAL(); }
202 
add_a_n(void)203 static void add_a_n(void)    { M_ADD(M_RDMEM_OPCODE()); }
add_a_r0(void)204 static void add_a_r0(void)   { M_ADD(R0); }
add_a_r1(void)205 static void add_a_r1(void)   { M_ADD(R1); }
add_a_r2(void)206 static void add_a_r2(void)   { M_ADD(R2); }
add_a_r3(void)207 static void add_a_r3(void)   { M_ADD(R3); }
add_a_r4(void)208 static void add_a_r4(void)   { M_ADD(R4); }
add_a_r5(void)209 static void add_a_r5(void)   { M_ADD(R5); }
add_a_r6(void)210 static void add_a_r6(void)   { M_ADD(R6); }
add_a_r7(void)211 static void add_a_r7(void)   { M_ADD(R7); }
add_a_xr0(void)212 static void add_a_xr0(void)  { M_ADD(intRAM[R0 & 0x7f]); }
add_a_xr1(void)213 static void add_a_xr1(void)  { M_ADD(intRAM[R1 & 0x7f]); }
adc_a_n(void)214 static void adc_a_n(void)    { M_ADDC(M_RDMEM_OPCODE()); }
adc_a_r0(void)215 static void adc_a_r0(void)   { M_ADDC(R0); }
adc_a_r1(void)216 static void adc_a_r1(void)   { M_ADDC(R1); }
adc_a_r2(void)217 static void adc_a_r2(void)   { M_ADDC(R2); }
adc_a_r3(void)218 static void adc_a_r3(void)   { M_ADDC(R3); }
adc_a_r4(void)219 static void adc_a_r4(void)   { M_ADDC(R4); }
adc_a_r5(void)220 static void adc_a_r5(void)   { M_ADDC(R5); }
adc_a_r6(void)221 static void adc_a_r6(void)   { M_ADDC(R6); }
adc_a_r7(void)222 static void adc_a_r7(void)   { M_ADDC(R7); }
adc_a_xr0(void)223 static void adc_a_xr0(void)  { M_ADDC(intRAM[R0 & 0x7f]); }
adc_a_xr1(void)224 static void adc_a_xr1(void)  { M_ADDC(intRAM[R1 & 0x7f]); }
anl_a_n(void)225 static void anl_a_n(void)    { R.A &= M_RDMEM_OPCODE(); }
anl_a_r0(void)226 static void anl_a_r0(void)   { R.A &= R0; }
anl_a_r1(void)227 static void anl_a_r1(void)   { R.A &= R1; }
anl_a_r2(void)228 static void anl_a_r2(void)   { R.A &= R2; }
anl_a_r3(void)229 static void anl_a_r3(void)   { R.A &= R3; }
anl_a_r4(void)230 static void anl_a_r4(void)   { R.A &= R4; }
anl_a_r5(void)231 static void anl_a_r5(void)   { R.A &= R5; }
anl_a_r6(void)232 static void anl_a_r6(void)   { R.A &= R6; }
anl_a_r7(void)233 static void anl_a_r7(void)   { R.A &= R7; }
anl_a_xr0(void)234 static void anl_a_xr0(void)  { R.A &= intRAM[R0 & 0x7f]; }
anl_a_xr1(void)235 static void anl_a_xr1(void)  { R.A &= intRAM[R1 & 0x7f]; }
anl_bus_n(void)236 static void anl_bus_n(void)  { bus_w( bus_r() & M_RDMEM_OPCODE() ); }
anl_p1_n(void)237 static void anl_p1_n(void)   { port_w( 1, port_r(1) & M_RDMEM_OPCODE() ); }
anl_p2_n(void)238 static void anl_p2_n(void)   { port_w( 2, port_r(2) & M_RDMEM_OPCODE() ); }
anld_p4_a(void)239 static void anld_p4_a(void)  { port_w( 4, port_r(4) & M_RDMEM_OPCODE() ); }
anld_p5_a(void)240 static void anld_p5_a(void)  { port_w( 5, port_r(5) & M_RDMEM_OPCODE() ); }
anld_p6_a(void)241 static void anld_p6_a(void)  { port_w( 6, port_r(6) & M_RDMEM_OPCODE() ); }
anld_p7_a(void)242 static void anld_p7_a(void)  { port_w( 7, port_r(7) & M_RDMEM_OPCODE() ); }
call(void)243 static void call(void)		 { UINT8 i=M_RDMEM_OPCODE(); M_CALL(i | R.A11); }
call_1(void)244 static void call_1(void)	 { UINT8 i=M_RDMEM_OPCODE(); M_CALL(i | 0x100 | R.A11); }
call_2(void)245 static void call_2(void)	 { UINT8 i=M_RDMEM_OPCODE(); M_CALL(i | 0x200 | R.A11); }
call_3(void)246 static void call_3(void)	 { UINT8 i=M_RDMEM_OPCODE(); M_CALL(i | 0x300 | R.A11); }
call_4(void)247 static void call_4(void)	 { UINT8 i=M_RDMEM_OPCODE(); M_CALL(i | 0x400 | R.A11); }
call_5(void)248 static void call_5(void)	 { UINT8 i=M_RDMEM_OPCODE(); M_CALL(i | 0x500 | R.A11); }
call_6(void)249 static void call_6(void)	 { UINT8 i=M_RDMEM_OPCODE(); M_CALL(i | 0x600 | R.A11); }
call_7(void)250 static void call_7(void)	 { UINT8 i=M_RDMEM_OPCODE(); M_CALL(i | 0x700 | R.A11); }
clr_a(void)251 static void clr_a(void)      { R.A=0; }
clr_c(void)252 static void clr_c(void)      { CLR(C_FLAG); }
clr_f0(void)253 static void clr_f0(void)     { CLR(F_FLAG); }
clr_f1(void)254 static void clr_f1(void)     { R.f1 = 0; }
cpl_a(void)255 static void cpl_a(void)      { R.A ^= 0xff; }
cpl_c(void)256 static void cpl_c(void)      { R.PSW ^= C_FLAG; }
cpl_f0(void)257 static void cpl_f0(void)     { R.PSW ^= F_FLAG; }
cpl_f1(void)258 static void cpl_f1(void)     { R.f1 ^= 1; }
dec_a(void)259 static void dec_a(void)      { R.A--; }
dec_r0(void)260 static void dec_r0(void)     { R0--; }
dec_r1(void)261 static void dec_r1(void)     { R1--; }
dec_r2(void)262 static void dec_r2(void)     { R2--; }
dec_r3(void)263 static void dec_r3(void)     { R3--; }
dec_r4(void)264 static void dec_r4(void)     { R4--; }
dec_r5(void)265 static void dec_r5(void)     { R5--; }
dec_r6(void)266 static void dec_r6(void)     { R6--; }
dec_r7(void)267 static void dec_r7(void)     { R7--; }
dis_i(void)268 static void dis_i(void)      { R.xirq_en = 0; }
dis_tcnti(void)269 static void dis_tcnti(void)  { R.tirq_en = 0; }
270 #ifdef MESS
djnz_r0(void)271 	static void djnz_r0(void)	 { UINT8 i=M_RDMEM_OPCODE(); R0--; if (R0 != 0) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); }}
djnz_r1(void)272 	static void djnz_r1(void)	 { UINT8 i=M_RDMEM_OPCODE(); R1--; if (R1 != 0) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
djnz_r2(void)273 	static void djnz_r2(void)	 { UINT8 i=M_RDMEM_OPCODE(); R2--; if (R2 != 0) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
djnz_r3(void)274 	static void djnz_r3(void)	 { UINT8 i=M_RDMEM_OPCODE(); R3--; if (R3 != 0) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
djnz_r4(void)275 	static void djnz_r4(void)	 { UINT8 i=M_RDMEM_OPCODE(); R4--; if (R4 != 0) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
djnz_r5(void)276 	static void djnz_r5(void)	 { UINT8 i=M_RDMEM_OPCODE(); R5--; if (R5 != 0) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
djnz_r6(void)277 	static void djnz_r6(void)	 { UINT8 i=M_RDMEM_OPCODE(); R6--; if (R6 != 0) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
djnz_r7(void)278 	static void djnz_r7(void)	 { UINT8 i=M_RDMEM_OPCODE(); R7--; if (R7 != 0) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
279 #else
djnz_r0(void)280 	static void djnz_r0(void)	 { UINT8 i=M_RDMEM_OPCODE(); R0--; if (R0 != 0) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  }}
djnz_r1(void)281 	static void djnz_r1(void)	 { UINT8 i=M_RDMEM_OPCODE(); R1--; if (R1 != 0) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
djnz_r2(void)282 	static void djnz_r2(void)	 { UINT8 i=M_RDMEM_OPCODE(); R2--; if (R2 != 0) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
djnz_r3(void)283 	static void djnz_r3(void)	 { UINT8 i=M_RDMEM_OPCODE(); R3--; if (R3 != 0) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
djnz_r4(void)284 	static void djnz_r4(void)	 { UINT8 i=M_RDMEM_OPCODE(); R4--; if (R4 != 0) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
djnz_r5(void)285 	static void djnz_r5(void)	 { UINT8 i=M_RDMEM_OPCODE(); R5--; if (R5 != 0) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
djnz_r6(void)286 	static void djnz_r6(void)	 { UINT8 i=M_RDMEM_OPCODE(); R6--; if (R6 != 0) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
djnz_r7(void)287 	static void djnz_r7(void)	 { UINT8 i=M_RDMEM_OPCODE(); R7--; if (R7 != 0) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
288 #endif
en_i(void)289 static void en_i(void)       { R.xirq_en = 1; if (R.irq_state != CLEAR_LINE) R.pending_irq |= I8039_EXT_INT; }
en_tcnti(void)290 static void en_tcnti(void)   { R.tirq_en = 1; }
ento_clk(void)291 static void ento_clk(void)   { M_UNDEFINED(); }
in_a_p1(void)292 static void in_a_p1(void)    { R.A = port_r(1); }
in_a_p2(void)293 static void in_a_p2(void)    { R.A = port_r(2); }
ins_a_bus(void)294 static void ins_a_bus(void)  { R.A = bus_r(); }
inc_a(void)295 static void inc_a(void)      { R.A++; }
inc_r0(void)296 static void inc_r0(void)     { R0++; }
inc_r1(void)297 static void inc_r1(void)     { R1++; }
inc_r2(void)298 static void inc_r2(void)     { R2++; }
inc_r3(void)299 static void inc_r3(void)     { R3++; }
inc_r4(void)300 static void inc_r4(void)     { R4++; }
inc_r5(void)301 static void inc_r5(void)     { R5++; }
inc_r6(void)302 static void inc_r6(void)     { R6++; }
inc_r7(void)303 static void inc_r7(void)     { R7++; }
inc_xr0(void)304 static void inc_xr0(void)    { intRAM[R0 & 0x7f]++; }
inc_xr1(void)305 static void inc_xr1(void)    { intRAM[R1 & 0x7f]++; }
306 
307 /* static void jmp(void)		{ UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | R.A11; }
308  */
309 
jmp(void)310 static void jmp(void)
311 {
312   UINT8 i=M_RDOP(R.PC.w.l);
313   UINT16 oldpc,newpc;
314 
315   oldpc = R.PC.w.l-1;
316   R.PC.w.l = i | R.A11;
317   #ifdef MESS
318 	  change_pc(R.PC.w.l);
319   #endif
320   newpc = R.PC.w.l;
321   if (newpc == oldpc) { if (i8039_ICount > 0) i8039_ICount = 0; } /* speed up busy loop */
322   else if (newpc == oldpc-1 && M_RDOP(newpc) == 0x00)	/* NOP - Gyruss */
323 	  { if (i8039_ICount > 0) i8039_ICount = 0; }
324 }
325 
326 #ifdef MESS
jmp_1(void)327 	static void jmp_1(void) 	 { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x100 | R.A11; change_pc(R.PC.w.l); }
jmp_2(void)328 	static void jmp_2(void) 	 { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x200 | R.A11; change_pc(R.PC.w.l); }
jmp_3(void)329 	static void jmp_3(void) 	 { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x300 | R.A11; change_pc(R.PC.w.l); }
jmp_4(void)330 	static void jmp_4(void) 	 { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x400 | R.A11; change_pc(R.PC.w.l); }
jmp_5(void)331 	static void jmp_5(void) 	 { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x500 | R.A11; change_pc(R.PC.w.l); }
jmp_6(void)332 	static void jmp_6(void) 	 { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x600 | R.A11; change_pc(R.PC.w.l); }
jmp_7(void)333 	static void jmp_7(void) 	 { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x700 | R.A11; change_pc(R.PC.w.l); }
jmpp_xa(void)334 	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)335 	static void jb_0(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x01) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
jb_1(void)336 	static void jb_1(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x02) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
jb_2(void)337 	static void jb_2(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x04) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
jb_3(void)338 	static void jb_3(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x08) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
jb_4(void)339 	static void jb_4(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x10) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
jb_5(void)340 	static void jb_5(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x20) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
jb_6(void)341 	static void jb_6(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x40) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
jb_7(void)342 	static void jb_7(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x80) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
jf0(void)343 	static void jf0(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (M_F0y) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
jf_1(void)344 	static void jf_1(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (R.f1)	{ R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
jnc(void)345 	static void jnc(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (M_Cn)	{ R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
jc(void)346 	static void jc(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (M_Cy)	{ R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
jni(void)347 	static void jni(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (R.irq_state != CLEAR_LINE) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
jnt_0(void)348 	static void jnt_0(void) 	 { UINT8 i=M_RDMEM_OPCODE(); if (!test_r(0)) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
jt_0(void)349 	static void jt_0(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (test_r(0))  { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
jnt_1(void)350 	static void jnt_1(void) 	 { UINT8 i=M_RDMEM_OPCODE(); if (!test_r(1)) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
jt_1(void)351 	static void jt_1(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (test_r(1))  { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
jnz(void)352 	static void jnz(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (R.A != 0)	 { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
jz(void)353 	static void jz(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (R.A == 0)	 { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); } }
jtf(void)354 	static void jtf(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (R.t_flag)	 { R.PC.w.l = (R.PC.w.l & 0xf00) | i; change_pc(R.PC.w.l); R.t_flag = 0; } }
355 #else
jmp_1(void)356 	static void jmp_1(void) 	 { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x100 | R.A11;  }
jmp_2(void)357 	static void jmp_2(void) 	 { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x200 | R.A11;  }
jmp_3(void)358 	static void jmp_3(void) 	 { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x300 | R.A11;  }
jmp_4(void)359 	static void jmp_4(void) 	 { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x400 | R.A11;  }
jmp_5(void)360 	static void jmp_5(void) 	 { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x500 | R.A11;  }
jmp_6(void)361 	static void jmp_6(void) 	 { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x600 | R.A11;  }
jmp_7(void)362 	static void jmp_7(void) 	 { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x700 | R.A11;  }
jmpp_xa(void)363 	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);  }
jb_0(void)364 	static void jb_0(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x01) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
jb_1(void)365 	static void jb_1(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x02) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
jb_2(void)366 	static void jb_2(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x04) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
jb_3(void)367 	static void jb_3(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x08) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
jb_4(void)368 	static void jb_4(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x10) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
jb_5(void)369 	static void jb_5(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x20) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
jb_6(void)370 	static void jb_6(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x40) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
jb_7(void)371 	static void jb_7(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (R.A & 0x80) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
jf0(void)372 	static void jf0(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (M_F0y) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; } }
jf_1(void)373 	static void jf_1(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (R.f1)	{ R.PC.w.l = (R.PC.w.l & 0xf00) | i; } }
jnc(void)374 	static void jnc(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (M_Cn)	{ R.PC.w.l = (R.PC.w.l & 0xf00) | i; } }
jc(void)375 	static void jc(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (M_Cy)	{ R.PC.w.l = (R.PC.w.l & 0xf00) | i; } }
jni(void)376 	static void jni(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (R.irq_state != CLEAR_LINE) { R.PC.w.l = (R.PC.w.l & 0xf00) | i; } }
jnt_0(void)377 	static void jnt_0(void) 	 { UINT8 i=M_RDMEM_OPCODE(); if (!test_r(0)) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
jt_0(void)378 	static void jt_0(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (test_r(0))  { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
jnt_1(void)379 	static void jnt_1(void) 	 { UINT8 i=M_RDMEM_OPCODE(); if (!test_r(1)) { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
jt_1(void)380 	static void jt_1(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (test_r(1))  { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
jnz(void)381 	static void jnz(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (R.A != 0)	 { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
jz(void)382 	static void jz(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (R.A == 0)	 { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  } }
jtf(void)383 	static void jtf(void)		 { UINT8 i=M_RDMEM_OPCODE(); if (R.t_flag)	 { R.PC.w.l = (R.PC.w.l & 0xf00) | i;  R.t_flag = 0; } }
384 #endif
385 
mov_a_n(void)386 static void mov_a_n(void)    { R.A = M_RDMEM_OPCODE(); }
mov_a_r0(void)387 static void mov_a_r0(void)   { R.A = R0; }
mov_a_r1(void)388 static void mov_a_r1(void)   { R.A = R1; }
mov_a_r2(void)389 static void mov_a_r2(void)   { R.A = R2; }
mov_a_r3(void)390 static void mov_a_r3(void)   { R.A = R3; }
mov_a_r4(void)391 static void mov_a_r4(void)   { R.A = R4; }
mov_a_r5(void)392 static void mov_a_r5(void)   { R.A = R5; }
mov_a_r6(void)393 static void mov_a_r6(void)   { R.A = R6; }
mov_a_r7(void)394 static void mov_a_r7(void)   { R.A = R7; }
mov_a_psw(void)395 static void mov_a_psw(void)  { R.A = R.PSW; }
mov_a_xr0(void)396 static void mov_a_xr0(void)  { R.A = intRAM[R0 & 0x7f]; }
mov_a_xr1(void)397 static void mov_a_xr1(void)  { R.A = intRAM[R1 & 0x7f]; }
mov_r0_a(void)398 static void mov_r0_a(void)   { R0 = R.A; }
mov_r1_a(void)399 static void mov_r1_a(void)   { R1 = R.A; }
mov_r2_a(void)400 static void mov_r2_a(void)   { R2 = R.A; }
mov_r3_a(void)401 static void mov_r3_a(void)   { R3 = R.A; }
mov_r4_a(void)402 static void mov_r4_a(void)   { R4 = R.A; }
mov_r5_a(void)403 static void mov_r5_a(void)   { R5 = R.A; }
mov_r6_a(void)404 static void mov_r6_a(void)   { R6 = R.A; }
mov_r7_a(void)405 static void mov_r7_a(void)   { R7 = R.A; }
mov_psw_a(void)406 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)407 static void mov_r0_n(void)   { R0 = M_RDMEM_OPCODE(); }
mov_r1_n(void)408 static void mov_r1_n(void)   { R1 = M_RDMEM_OPCODE(); }
mov_r2_n(void)409 static void mov_r2_n(void)   { R2 = M_RDMEM_OPCODE(); }
mov_r3_n(void)410 static void mov_r3_n(void)   { R3 = M_RDMEM_OPCODE(); }
mov_r4_n(void)411 static void mov_r4_n(void)   { R4 = M_RDMEM_OPCODE(); }
mov_r5_n(void)412 static void mov_r5_n(void)   { R5 = M_RDMEM_OPCODE(); }
mov_r6_n(void)413 static void mov_r6_n(void)   { R6 = M_RDMEM_OPCODE(); }
mov_r7_n(void)414 static void mov_r7_n(void)   { R7 = M_RDMEM_OPCODE(); }
mov_a_t(void)415 static void mov_a_t(void)    { R.A = R.timer; }
mov_t_a(void)416 static void mov_t_a(void)    { R.timer = R.A; }
mov_xr0_a(void)417 static void mov_xr0_a(void)  { intRAM[R0 & 0x7f] = R.A; }
mov_xr1_a(void)418 static void mov_xr1_a(void)  { intRAM[R1 & 0x7f] = R.A; }
mov_xr0_n(void)419 static void mov_xr0_n(void)  { intRAM[R0 & 0x7f] = M_RDMEM_OPCODE(); }
mov_xr1_n(void)420 static void mov_xr1_n(void)  { intRAM[R1 & 0x7f] = M_RDMEM_OPCODE(); }
movd_a_p4(void)421 static void movd_a_p4(void)  { R.A = port_r(4); }
movd_a_p5(void)422 static void movd_a_p5(void)  { R.A = port_r(5); }
movd_a_p6(void)423 static void movd_a_p6(void)  { R.A = port_r(6); }
movd_a_p7(void)424 static void movd_a_p7(void)  { R.A = port_r(7); }
movd_p4_a(void)425 static void movd_p4_a(void)  { port_w(4, R.A); }
movd_p5_a(void)426 static void movd_p5_a(void)  { port_w(5, R.A); }
movd_p6_a(void)427 static void movd_p6_a(void)  { port_w(6, R.A); }
movd_p7_a(void)428 static void movd_p7_a(void)  { port_w(7, R.A); }
movp_a_xa(void)429 static void movp_a_xa(void)  { R.A = M_RDMEM((R.PC.w.l & 0x0f00) | R.A); }
movp3_a_xa(void)430 static void movp3_a_xa(void) { R.A = M_RDMEM(0x300 | R.A); }
movx_a_xr0(void)431 static void movx_a_xr0(void) { R.A = M_IN(R0); }
movx_a_xr1(void)432 static void movx_a_xr1(void) { R.A = M_IN(R1); }
movx_xr0_a(void)433 static void movx_xr0_a(void) { M_OUT(R0, R.A); }
movx_xr1_a(void)434 static void movx_xr1_a(void) { M_OUT(R1, R.A); }
nop(void)435 static void nop(void) { }
orl_a_n(void)436 static void orl_a_n(void)    { R.A |= M_RDMEM_OPCODE(); }
orl_a_r0(void)437 static void orl_a_r0(void)   { R.A |= R0; }
orl_a_r1(void)438 static void orl_a_r1(void)   { R.A |= R1; }
orl_a_r2(void)439 static void orl_a_r2(void)   { R.A |= R2; }
orl_a_r3(void)440 static void orl_a_r3(void)   { R.A |= R3; }
orl_a_r4(void)441 static void orl_a_r4(void)   { R.A |= R4; }
orl_a_r5(void)442 static void orl_a_r5(void)   { R.A |= R5; }
orl_a_r6(void)443 static void orl_a_r6(void)   { R.A |= R6; }
orl_a_r7(void)444 static void orl_a_r7(void)   { R.A |= R7; }
orl_a_xr0(void)445 static void orl_a_xr0(void)  { R.A |= intRAM[R0 & 0x7f]; }
orl_a_xr1(void)446 static void orl_a_xr1(void)  { R.A |= intRAM[R1 & 0x7f]; }
orl_bus_n(void)447 static void orl_bus_n(void)  { bus_w( bus_r() | M_RDMEM_OPCODE() ); }
orl_p1_n(void)448 static void orl_p1_n(void)   { port_w(1, port_r(1) | M_RDMEM_OPCODE() ); }
orl_p2_n(void)449 static void orl_p2_n(void)   { port_w(2, port_r(2) | M_RDMEM_OPCODE() ); }
orld_p4_a(void)450 static void orld_p4_a(void)  { port_w(4, port_r(4) | R.A ); }
orld_p5_a(void)451 static void orld_p5_a(void)  { port_w(5, port_r(5) | R.A ); }
orld_p6_a(void)452 static void orld_p6_a(void)  { port_w(6, port_r(6) | R.A ); }
orld_p7_a(void)453 static void orld_p7_a(void)  { port_w(7, port_r(7) | R.A ); }
outl_bus_a(void)454 static void outl_bus_a(void) { bus_w(R.A); }
outl_p1_a(void)455 static void outl_p1_a(void)  { port_w(1, R.A ); }
outl_p2_a(void)456 static void outl_p2_a(void)  { port_w(2, R.A ); }
457 #ifdef MESS
ret(void)458 	static void ret(void)		 { R.PC.w.l = ((pull() & 0x0f) << 8); R.PC.w.l |= pull(); change_pc(R.PC.w.l); }
459 #else
ret(void)460 	static void ret(void)		 { R.PC.w.l = ((pull() & 0x0f) << 8); R.PC.w.l |= pull();  }
461 #endif
462 
retr(void)463 static void retr(void)
464 {
465 	UINT8 i=pull();
466 	R.PC.w.l = ((i & 0x0f) << 8) | pull();
467 	#ifdef MESS
468 		change_pc(R.PC.w.l);
469 	#endif
470 	R.irq_executing = I8039_IGNORE_INT;
471 //	R.A11 = R.A11ff;	/* NS990113 */
472 	R.PSW = (R.PSW & 0x0f) | (i & 0xf0);   /* Stack is already changed by pull */
473 	regPTR = ((M_By) ? 24 : 0);
474 }
rl_a(void)475 static void rl_a(void)		 { UINT8 i=R.A & 0x80; R.A <<= 1; if (i) R.A |= 0x01; else R.A &= 0xfe; }
476 /* NS990113 */
rlc_a(void)477 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)478 static void rr_a(void)		 { UINT8 i=R.A & 1; R.A >>= 1; if (i) R.A |= 0x80; else R.A &= 0x7f; }
479 /* NS990113 */
rrc_a(void)480 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)481 static void sel_mb0(void)    { R.A11 = 0; R.A11ff = 0; }
sel_mb1(void)482 static void sel_mb1(void)    { R.A11ff = 0x800; if (R.irq_executing == I8039_IGNORE_INT) R.A11 = 0x800; }
sel_rb0(void)483 static void sel_rb0(void)    { CLR(B_FLAG); regPTR = 0;  }
sel_rb1(void)484 static void sel_rb1(void)    { SET(B_FLAG); regPTR = 24; }
stop_tcnt(void)485 static void stop_tcnt(void)  { R.timerON = R.countON = 0; }
strt_cnt(void)486 static void strt_cnt(void)   { R.countON = 1; Old_T1 = test_r(1); }	/* NS990113 */
strt_t(void)487 static void strt_t(void)     { R.timerON = 1; R.masterClock = 0; }	/* NS990113 */
swap_a(void)488 static void swap_a(void)	 { UINT8 i=R.A >> 4; R.A <<= 4; R.A |= i; }
xch_a_r0(void)489 static void xch_a_r0(void)	 { UINT8 i=R.A; R.A=R0; R0=i; }
xch_a_r1(void)490 static void xch_a_r1(void)	 { UINT8 i=R.A; R.A=R1; R1=i; }
xch_a_r2(void)491 static void xch_a_r2(void)	 { UINT8 i=R.A; R.A=R2; R2=i; }
xch_a_r3(void)492 static void xch_a_r3(void)	 { UINT8 i=R.A; R.A=R3; R3=i; }
xch_a_r4(void)493 static void xch_a_r4(void)	 { UINT8 i=R.A; R.A=R4; R4=i; }
xch_a_r5(void)494 static void xch_a_r5(void)	 { UINT8 i=R.A; R.A=R5; R5=i; }
xch_a_r6(void)495 static void xch_a_r6(void)	 { UINT8 i=R.A; R.A=R6; R6=i; }
xch_a_r7(void)496 static void xch_a_r7(void)	 { UINT8 i=R.A; R.A=R7; R7=i; }
xch_a_xr0(void)497 static void xch_a_xr0(void)  { UINT8 i=R.A; R.A=intRAM[R0 & 0x7f]; intRAM[R0 & 0x7f]=i; }
xch_a_xr1(void)498 static void xch_a_xr1(void)  { UINT8 i=R.A; R.A=intRAM[R1 & 0x7f]; intRAM[R1 & 0x7f]=i; }
xchd_a_xr0(void)499 static void xchd_a_xr0(void) { M_XCHD(R0 & 0x7f); }
xchd_a_xr1(void)500 static void xchd_a_xr1(void) { M_XCHD(R1 & 0x7f); }
xrl_a_n(void)501 static void xrl_a_n(void)    { R.A ^= M_RDMEM_OPCODE(); }
xrl_a_r0(void)502 static void xrl_a_r0(void)   { R.A ^= R0; }
xrl_a_r1(void)503 static void xrl_a_r1(void)   { R.A ^= R1; }
xrl_a_r2(void)504 static void xrl_a_r2(void)   { R.A ^= R2; }
xrl_a_r3(void)505 static void xrl_a_r3(void)   { R.A ^= R3; }
xrl_a_r4(void)506 static void xrl_a_r4(void)   { R.A ^= R4; }
xrl_a_r5(void)507 static void xrl_a_r5(void)   { R.A ^= R5; }
xrl_a_r6(void)508 static void xrl_a_r6(void)   { R.A ^= R6; }
xrl_a_r7(void)509 static void xrl_a_r7(void)   { R.A ^= R7; }
xrl_a_xr0(void)510 static void xrl_a_xr0(void)  { R.A ^= intRAM[R0 & 0x7f]; }
xrl_a_xr1(void)511 static void xrl_a_xr1(void)  { R.A ^= intRAM[R1 & 0x7f]; }
512 
513 static s_opcode opcode_main[256]=
514 {
515 	{1, nop 	   },{0, illegal	},{2, outl_bus_a },{2, add_a_n	  },{2, jmp 	   },{1, en_i		},{0, illegal	 },{1, dec_a	  },
516 	{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  },
517 	{1, inc_xr0    },{1, inc_xr1	},{2, jb_0		 },{2, adc_a_n	  },{2, call	   },{1, dis_i		},{2, jtf		 },{1, inc_a	  },
518 	{1, inc_r0	   },{1, inc_r1 	},{1, inc_r2	 },{1, inc_r3	  },{1, inc_r4	   },{1, inc_r5 	},{1, inc_r6	 },{1, inc_r7	  },
519 	{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	  },
520 	{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   },
521 	{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	  },
522 	{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  },
523 	{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	  },
524 	{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   },
525 	{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	  },
526 	{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   },
527 	{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	  },
528 	{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   },
529 	{1, adc_a_xr0  },{1, adc_a_xr1	},{2, jb_3		 },{0, illegal	  },{2, call_3	   },{1, ento_clk	},{2, jf_1		 },{1, rr_a 	  },
530 	{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   },
531 	{2, movx_a_xr0 },{2, movx_a_xr1 },{0, illegal	 },{2, ret		  },{2, jmp_4	   },{1, clr_f0 	},{2, jni		 },{0, illegal	  },
532 	{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  },
533 	{2, movx_xr0_a },{2, movx_xr1_a },{2, jb_4		 },{2, retr 	  },{2, call_4	   },{1, cpl_f0 	},{2, jnz		 },{1, clr_c	  },
534 	{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  },
535 	{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	  },
536 	{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   },
537 	{2, mov_xr0_n  },{2, mov_xr1_n	},{2, jb_5		 },{2, jmpp_xa	  },{2, call_5	   },{1, cpl_f1 	},{2, jf0		 },{0, illegal	  },
538 	{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   },
539 	{0, illegal    },{0, illegal	},{0, illegal	 },{0, illegal	  },{2, jmp_6	   },{1, sel_rb0	},{2, jz		 },{1, mov_a_psw  },
540 	{1, dec_r0	   },{1, dec_r1 	},{1, dec_r2	 },{1, dec_r3	  },{1, dec_r4	   },{1, dec_r5 	},{1, dec_r6	 },{1, dec_r7	  },
541 	{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  },
542 	{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   },
543 	{0, illegal    },{0, illegal	},{0, illegal	 },{2, movp3_a_xa },{2, jmp_7	   },{1, sel_mb0	},{2, jnc		 },{1, rl_a 	  },
544 	{2, djnz_r0    },{2, djnz_r1	},{2, djnz_r2	 },{2, djnz_r3	  },{2, djnz_r4    },{2, djnz_r5	},{2, djnz_r6	 },{2, djnz_r7	  },
545 	{1, mov_a_xr0  },{1, mov_a_xr1	},{2, jb_7		 },{0, illegal	  },{2, call_7	   },{1, sel_mb1	},{2, jc		 },{1, rlc_a	  },
546 	{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   }
547 };
548 
549 
550 /****************************************************************************
551  * Issue an interrupt if necessary
552  ****************************************************************************/
Timer_IRQ(void)553 static int Timer_IRQ(void)
554 {
555 	if (R.tirq_en && !R.irq_executing)
556 	{
557 		/*logerror("I8039:  TIMER INTERRUPT\n");*/
558 		R.irq_executing = I8039_TIMER_INT;
559 		push(R.PC.b.l);
560 		push((R.PC.b.h & 0x0f) | (R.PSW & 0xf0));
561 		R.PC.w.l = 0x07;
562 		#ifdef MESS
563 			change_pc(0x07);
564 		#endif
565 		R.A11ff = R.A11;
566 		R.A11	= 0;
567 		return 2;		/* 2 clock cycles used */
568 	}
569 	return 0;
570 }
571 
Ext_IRQ(void)572 static int Ext_IRQ(void)
573 {
574 	if (R.xirq_en) {
575 //logerror("I8039:  EXT INTERRUPT\n");
576 		R.irq_executing = I8039_EXT_INT;
577 		push(R.PC.b.l);
578 		push((R.PC.b.h & 0x0f) | (R.PSW & 0xf0));
579 		R.PC.w.l = 0x03;
580 		R.A11ff = R.A11;
581         R.A11   = 0;
582         return 2;       /* 2 clock cycles used */
583 	}
584     return 0;
585 }
586 
587 
588 
589 /****************************************************************************
590  * Reset registers to their initial values
591  ****************************************************************************/
i8039_reset(void * param)592 void i8039_reset (void *param)
593 {
594 	R.PC.w.l  = 0;
595 	R.SP  = 0;
596 	R.A   = 0;
597 	R.PSW = 0x08;		/* Start with Carry SET, Bit 4 is always SET */
598 	memset(R.RAM, 0x0, 128);
599 	R.bus = 0;
600 	R.irq_executing = I8039_IGNORE_INT;
601 	R.pending_irq	= I8039_IGNORE_INT;
602 
603 	R.A11ff   = R.A11     = 0;
604 	R.timerON = R.countON = 0;
605 	R.tirq_en = R.xirq_en = 0;
606 	R.xirq_en = 0;	/* NS990113 */
607 	R.timerON = 1;	/* Mario Bros. doesn't work without this */
608 	R.masterClock = 0;
609 }
610 
611 
612 /****************************************************************************
613  * Shut down CPU emulation
614  ****************************************************************************/
i8039_exit(void)615 void i8039_exit (void)
616 {
617 	/* nothing to do ? */
618 }
619 
620 /****************************************************************************
621  * Execute cycles CPU cycles. Return number of cycles really executed
622  ****************************************************************************/
i8039_execute(int cycles)623 int i8039_execute(int cycles)
624 {
625     unsigned opcode, T1;
626     int count;
627 
628 	i8039_ICount=cycles;
629 
630     do {
631         switch (R.pending_irq)
632         {
633             case I8039_COUNT_INT:
634             case I8039_TIMER_INT:
635                 count = Timer_IRQ();
636 				i8039_ICount -= count;
637                 if (R.timerON)  /* NS990113 */
638                     R.masterClock += count;
639                 R.t_flag = 1;
640                 break;
641             case I8039_EXT_INT:
642                 if (R.irq_callback) (*R.irq_callback)(0);
643                 count = Ext_IRQ();
644 				i8039_ICount -= count;
645                 if (R.timerON)  /* NS990113 */
646                     R.masterClock += count;
647                 break;
648 		}
649         R.pending_irq = I8039_IGNORE_INT;
650 
651         R.PREPC = R.PC;
652 
653 		opcode=M_RDOP(R.PC.w.l);
654 
655 /*      logerror("I8039:  PC = %04x,  opcode = %02x\n", R.PC.w.l, opcode); */
656 
657         R.PC.w.l++;
658 		i8039_ICount -= opcode_main[opcode].cycles;
659 		(*(opcode_main[opcode].function))();
660 
661         if (R.countON)  /* NS990113 */
662         {
663             T1 = test_r(1);
664             if (POSITIVE_EDGE_T1)
665             {   /* Handle COUNTER IRQs */
666                 R.timer++;
667                 if (R.timer == 0) R.pending_irq = I8039_COUNT_INT;
668 
669                 Old_T1 = T1;
670 			}
671 		}
672 
673         if (R.timerON) {                        /* Handle TIMER IRQs */
674 			R.masterClock += opcode_main[opcode].cycles;
675             if (R.masterClock >= 32) {  /* NS990113 */
676                 R.masterClock -= 32;
677                 R.timer++;
678                 if (R.timer == 0) R.pending_irq = I8039_TIMER_INT;
679 			}
680 		}
681    } while (i8039_ICount>0);
682 
683    return cycles - i8039_ICount;
684 }
685 
686 /****************************************************************************
687  * Get all registers in given buffer
688  ****************************************************************************/
i8039_get_context(void * dst)689 unsigned i8039_get_context (void *dst)
690 {
691 	if( dst )
692 		*(I8039_Regs*)dst = R;
693 	return sizeof(I8039_Regs);
694 }
695 
696 
697 /****************************************************************************
698  * Set all registers to given values
699  ****************************************************************************/
i8039_set_context(void * src)700 void i8039_set_context (void *src)
701 {
702 	if( src )
703 	{
704 		R = *(I8039_Regs*)src;
705 		regPTR = ((M_By) ? 24 : 0);
706 		R.SP = (R.PSW << 1) & 0x0f;
707 		#ifdef MESS
708 			change_pc(R.PC.w.l);
709 		#endif
710 	}
711 }
712 
713 
714 /****************************************************************************
715  * Return program counter
716  ****************************************************************************/
i8039_get_pc(void)717 unsigned i8039_get_pc (void)
718 {
719 	return R.PC.d;
720 }
721 
722 
723 /****************************************************************************
724  * Return program counter
725  ****************************************************************************/
i8039_set_pc(unsigned val)726 void i8039_set_pc (unsigned val)
727 {
728 	R.PC.w.l = val;
729 }
730 
731 
732 /****************************************************************************
733  * Return stack pointer
734  ****************************************************************************/
i8039_get_sp(void)735 unsigned i8039_get_sp (void)
736 {
737 	return R.SP;
738 }
739 
740 
741 /****************************************************************************
742  * Set stack pointer
743  ****************************************************************************/
i8039_set_sp(unsigned val)744 void i8039_set_sp (unsigned val)
745 {
746 	R.SP = val;
747 }
748 
749 
750 /****************************************************************************/
751 /* Get a specific register                                                  */
752 /****************************************************************************/
i8039_get_reg(int regnum)753 unsigned i8039_get_reg (int regnum)
754 {
755 	switch( regnum )
756 	{
757 		case I8039_PC: return R.PC.w.l;
758 		case I8039_SP: return R.SP;
759 		case I8039_PSW: return R.PSW;
760         case I8039_A: return R.A;
761 		case I8039_IRQ_STATE: return R.irq_state;
762 		case I8039_R0: return R0;
763 		case I8039_R1: return R1;
764 		case I8039_R2: return R2;
765 		case I8039_R3: return R3;
766 		case I8039_R4: return R4;
767 		case I8039_R5: return R5;
768 		case I8039_R6: return R6;
769 		case I8039_R7: return R7;
770 		case REG_PREVIOUSPC: return R.PREPC.w.l;
771 		default:
772 			if( regnum <= REG_SP_CONTENTS )
773 			{
774 				unsigned offset = 8 + 2 * ((R.SP + REG_SP_CONTENTS - regnum) & 7);
775 				return R.RAM[offset] + 256 * R.RAM[offset+1];
776 			}
777 	}
778 	return 0;
779 }
780 
781 
782 /****************************************************************************/
783 /* Set a specific register                                                  */
784 /****************************************************************************/
i8039_set_reg(int regnum,unsigned val)785 void i8039_set_reg (int regnum, unsigned val)
786 {
787 	switch( regnum )
788 	{
789 		case I8039_PC: R.PC.w.l = val; break;
790 		case I8039_SP: R.SP = val; break;
791 		case I8039_PSW: R.PSW = val; break;
792 		case I8039_A: R.A = val; break;
793 		case I8039_IRQ_STATE: i8039_set_irq_line( 0, val ); break;
794 		case I8039_R0: R0 = val; break;
795 		case I8039_R1: R1 = val; break;
796 		case I8039_R2: R2 = val; break;
797 		case I8039_R3: R3 = val; break;
798 		case I8039_R4: R4 = val; break;
799 		case I8039_R5: R5 = val; break;
800 		case I8039_R6: R6 = val; break;
801 		case I8039_R7: R7 = val; break;
802 		default:
803 			if( regnum <= REG_SP_CONTENTS )
804 			{
805 				unsigned offset = 8 + 2 * ((R.SP + REG_SP_CONTENTS - regnum) & 7);
806 				R.RAM[offset] = val & 0xff;
807 				R.RAM[offset+1] = val >> 8;
808             }
809 	}
810 }
811 
812 
813 /****************************************************************************/
814 /* Set NMI line state														*/
815 /****************************************************************************/
i8039_set_nmi_line(int state)816 void i8039_set_nmi_line(int state)
817 {
818 	/* I8039 does not have a NMI line */
819 }
820 
821 /****************************************************************************/
822 /* Set IRQ line state														*/
823 /****************************************************************************/
i8039_set_irq_line(int irqline,int state)824 void i8039_set_irq_line(int irqline, int state)
825 {
826 	R.irq_state = state;
827 	if (state == CLEAR_LINE)
828 		R.pending_irq &= ~I8039_EXT_INT;
829 	else
830 		R.pending_irq |= I8039_EXT_INT;
831 }
832 
833 /****************************************************************************/
834 /* Set IRQ callback (interrupt acknowledge) 								*/
835 /****************************************************************************/
i8039_set_irq_callback(int (* callback)(int irqline))836 void i8039_set_irq_callback(int (*callback)(int irqline))
837 {
838 	R.irq_callback = callback;
839 }
840 
841 /****************************************************************************
842  * Return a formatted string for a register
843  ****************************************************************************/
i8039_info(void * context,int regnum)844 const char *i8039_info(void *context, int regnum)
845 {
846     switch( regnum )
847     {
848 		case CPU_INFO_NAME: return "I8039";
849 		case CPU_INFO_FAMILY: return "Intel 8039";
850 		case CPU_INFO_VERSION: return "1.1";
851 		case CPU_INFO_FILE: return __FILE__;
852 		case CPU_INFO_CREDITS: return "Copyright (C) 1997 by Mirko Buffoni\nBased on the original work (C) 1997 by Dan Boris";
853 	}
854     return "";
855 }
856 
i8039_dasm(char * buffer,unsigned pc)857 unsigned i8039_dasm(char *buffer, unsigned pc)
858 {
859 	sprintf( buffer, "$%02X", cpu_readop(pc) );
860 	return 1;
861 }
862 
863 /**************************************************************************
864  * I8035 section
865  **************************************************************************/
866 #if (HAS_I8035)
i8035_reset(void * param)867 void i8035_reset(void *param) { i8039_reset(param); }
i8035_exit(void)868 void i8035_exit(void) { i8039_exit(); }
i8035_execute(int cycles)869 int i8035_execute(int cycles) { return i8039_execute(cycles); }
i8035_get_context(void * dst)870 unsigned i8035_get_context(void *dst) { return i8039_get_context(dst); }
i8035_set_context(void * src)871 void i8035_set_context(void *src)  { i8039_set_context(src); }
i8035_get_pc(void)872 unsigned i8035_get_pc(void) { return i8039_get_pc(); }
i8035_set_pc(unsigned val)873 void i8035_set_pc(unsigned val) { i8039_set_pc(val); }
i8035_get_sp(void)874 unsigned i8035_get_sp(void) { return i8039_get_sp(); }
i8035_set_sp(unsigned val)875 void i8035_set_sp(unsigned val) { i8039_set_sp(val); }
i8035_get_reg(int regnum)876 unsigned i8035_get_reg(int regnum) { return i8039_get_reg(regnum); }
i8035_set_reg(int regnum,unsigned val)877 void i8035_set_reg(int regnum, unsigned val) { i8039_set_reg(regnum,val); }
i8035_set_nmi_line(int state)878 void i8035_set_nmi_line(int state) { i8039_set_nmi_line(state); }
i8035_set_irq_line(int irqline,int state)879 void i8035_set_irq_line(int irqline, int state) { i8039_set_irq_line(irqline,state); }
i8035_set_irq_callback(int (* callback)(int irqline))880 void i8035_set_irq_callback(int (*callback)(int irqline)) { i8039_set_irq_callback(callback); }
i8035_info(void * context,int regnum)881 const char *i8035_info(void *context, int regnum)
882 {
883 	switch( regnum )
884     {
885 		case CPU_INFO_NAME: return "I8035";
886 		case CPU_INFO_VERSION: return "1.1";
887 	}
888 	return i8039_info(context,regnum);
889 }
890 
i8035_dasm(char * buffer,unsigned pc)891 unsigned i8035_dasm(char *buffer, unsigned pc)
892 {
893 	sprintf( buffer, "$%02X", cpu_readop(pc) );
894 	return 1;
895 }
896 
897 #endif
898 
899 /**************************************************************************
900  * I8048 section
901  **************************************************************************/
902 #if (HAS_I8048)
i8048_reset(void * param)903 void i8048_reset(void *param) { i8039_reset(param); }
i8048_exit(void)904 void i8048_exit(void) { i8039_exit(); }
i8048_execute(int cycles)905 int i8048_execute(int cycles) { return i8039_execute(cycles); }
i8048_get_context(void * dst)906 unsigned i8048_get_context(void *dst) { return i8039_get_context(dst); }
i8048_set_context(void * src)907 void i8048_set_context(void *src)  { i8039_set_context(src); }
i8048_get_pc(void)908 unsigned i8048_get_pc(void) { return i8039_get_pc(); }
i8048_set_pc(unsigned val)909 void i8048_set_pc(unsigned val) { i8039_set_pc(val); }
i8048_get_sp(void)910 unsigned i8048_get_sp(void) { return i8039_get_sp(); }
i8048_set_sp(unsigned val)911 void i8048_set_sp(unsigned val) { i8039_set_sp(val); }
i8048_get_reg(int regnum)912 unsigned i8048_get_reg(int regnum) { return i8039_get_reg(regnum); }
i8048_set_reg(int regnum,unsigned val)913 void i8048_set_reg(int regnum, unsigned val) { i8039_set_reg(regnum,val); }
i8048_set_nmi_line(int state)914 void i8048_set_nmi_line(int state) { i8039_set_nmi_line(state); }
i8048_set_irq_line(int irqline,int state)915 void i8048_set_irq_line(int irqline, int state) { i8039_set_irq_line(irqline,state); }
i8048_set_irq_callback(int (* callback)(int irqline))916 void i8048_set_irq_callback(int (*callback)(int irqline)) { i8039_set_irq_callback(callback); }
i8048_info(void * context,int regnum)917 const char *i8048_info(void *context, int regnum)
918 {
919 	switch( regnum )
920     {
921 		case CPU_INFO_NAME: return "I8048";
922 		case CPU_INFO_VERSION: return "1.1";
923 	}
924 	return i8039_info(context,regnum);
925 }
926 
i8048_dasm(char * buffer,unsigned pc)927 unsigned i8048_dasm(char *buffer, unsigned pc)
928 {
929 	sprintf( buffer, "$%02X", cpu_readop(pc) );
930 	return 1;
931 }
932 #endif
933 /**************************************************************************
934  * N7751 section
935  **************************************************************************/
936 #if (HAS_N7751)
n7751_reset(void * param)937 void n7751_reset(void *param) { i8039_reset(param); }
n7751_exit(void)938 void n7751_exit(void) { i8039_exit(); }
n7751_execute(int cycles)939 int n7751_execute(int cycles) { return i8039_execute(cycles); }
n7751_get_context(void * dst)940 unsigned n7751_get_context(void *dst) { return i8039_get_context(dst); }
n7751_set_context(void * src)941 void n7751_set_context(void *src)  { i8039_set_context(src); }
n7751_get_pc(void)942 unsigned n7751_get_pc(void) { return i8039_get_pc(); }
n7751_set_pc(unsigned val)943 void n7751_set_pc(unsigned val) { i8039_set_pc(val); }
n7751_get_sp(void)944 unsigned n7751_get_sp(void) { return i8039_get_sp(); }
n7751_set_sp(unsigned val)945 void n7751_set_sp(unsigned val) { i8039_set_sp(val); }
n7751_get_reg(int regnum)946 unsigned n7751_get_reg(int regnum) { return i8039_get_reg(regnum); }
n7751_set_reg(int regnum,unsigned val)947 void n7751_set_reg(int regnum, unsigned val) { i8039_set_reg(regnum,val); }
n7751_set_nmi_line(int state)948 void n7751_set_nmi_line(int state) { i8039_set_nmi_line(state); }
n7751_set_irq_line(int irqline,int state)949 void n7751_set_irq_line(int irqline, int state) { i8039_set_irq_line(irqline,state); }
n7751_set_irq_callback(int (* callback)(int irqline))950 void n7751_set_irq_callback(int (*callback)(int irqline)) { i8039_set_irq_callback(callback); }
n7751_info(void * context,int regnum)951 const char *n7751_info(void *context, int regnum)
952 {
953 	switch( regnum )
954     {
955 		case CPU_INFO_NAME: return "N7751";
956 		case CPU_INFO_VERSION: return "1.1";
957 	}
958 	return i8039_info(context,regnum);
959 }
960 
n7751_dasm(char * buffer,unsigned pc)961 unsigned n7751_dasm(char *buffer, unsigned pc)
962 {
963 	sprintf( buffer, "$%02X", cpu_readop(pc) );
964 	return 1;
965 }
966 #endif
967 
968