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