OSDN Git Service

[DOC] For release 2017-01-24.
[csp-qt/common_source_project-fm7.git] / source / src / vm / mcs48.cpp
1 /*
2         Skelton for retropc emulator
3
4         Origin : MAME 0.148
5         Author : Takeda.Toshiya
6         Date   : 2013.05.01-
7
8         [ MCS48 ]
9 */
10
11 #include "mcs48.h"
12 #ifdef USE_DEBUGGER
13 #include "debugger.h"
14 #endif
15
16 /***************************************************************************
17
18     mcs48.c
19
20     Intel MCS-48/UPI-41 Portable Emulator
21
22     Copyright Mirko Buffoni
23     Based on the original work Copyright Dan Boris, an 8048 emulator
24     You are not allowed to distribute this software commercially
25
26 ****************************************************************************
27
28     Note that the default internal divisor for this chip is by 3 and
29     then again by 5, or by 15 total.
30
31 ***************************************************************************/
32
33 #if defined(_MSC_VER) && (_MSC_VER >= 1400)
34 #pragma warning( disable : 4244 )
35 #endif
36
37 #define INLINE inline
38
39 /***************************************************************************
40     CONSTANTS
41 ***************************************************************************/
42
43 /* timer/counter enable bits */
44 #define TIMER_ENABLED   0x01
45 #define COUNTER_ENABLED 0x02
46
47 /* flag bits */
48 #define C_FLAG          0x80
49 #define A_FLAG          0x40
50 #define F_FLAG          0x20
51 #define B_FLAG          0x10
52
53 /* status bits (UPI-41) */
54 #define STS_F1          0x08
55 #define STS_F0          0x04
56
57 /* 8243 expander operations */
58 enum
59 {
60         MCS48_EXPANDER_OP_READ = 0,
61         MCS48_EXPANDER_OP_WRITE = 1,
62         MCS48_EXPANDER_OP_OR = 2,
63         MCS48_EXPANDER_OP_AND = 3
64 };
65
66 /***************************************************************************
67     TYPE DEFINITIONS
68 ***************************************************************************/
69
70 /* live processor state */
71 struct mcs48_state
72 {
73         UINT16      prevpc;             /* 16-bit previous program counter */
74         UINT16      pc;                 /* 16-bit program counter */
75
76         UINT8       a;                  /* 8-bit accumulator */
77         int         regptr;             /* offset of r0-r7 */
78         UINT8       psw;                /* 8-bit cpustate->psw */
79         UINT8       p1;                 /* 8-bit latched port 1 */
80         UINT8       p2;                 /* 8-bit latched port 2 */
81         UINT8       timer;              /* 8-bit timer */
82         UINT8       prescaler;          /* 5-bit timer prescaler */
83         UINT8       t1_history;         /* 8-bit history of the T1 input */
84         UINT8       sts;                /* 8-bit status register */
85
86         UINT8       int_state;          /* INT signal status */
87         UINT8       irq_state;          /* TRUE if an IRQ is pending */
88         UINT8       irq_in_progress;    /* TRUE if an IRQ is in progress */
89         UINT8       timer_overflow;     /* TRUE on a timer overflow; cleared by taking interrupt */
90         UINT8       timer_flag;         /* TRUE on a timer overflow; cleared on JTF */
91         UINT8       tirq_enabled;       /* TRUE if the timer IRQ is enabled */
92         UINT8       xirq_enabled;       /* TRUE if the external IRQ is enabled */
93         UINT8       t0_clk_enabled;     /* TRUE if ent0_clk is called */
94         UINT8       timecount_enabled;  /* bitmask of timer/counter enabled */
95
96         UINT16      a11;                /* A11 value, either 0x000 or 0x800 */
97
98         DEVICE *    mem;
99         DEVICE *    io;
100         DEVICE *    intr;
101
102         int         icount;
103
104         UINT8       rom[0x1000];
105 //      UINT8       ram[0x100];
106 };
107
108 /* opcode table entry */
109 typedef int (*mcs48_ophandler)(mcs48_state *state);
110
111 /***************************************************************************
112     MACROS
113 ***************************************************************************/
114
115 #define program_r(a)    cpustate->rom[(a) & 0xfff]
116
117 #define ram_r(a)        cpustate->mem->read_data8(a)
118 #define ram_w(a,V)      cpustate->mem->write_data8(a, V)
119 #define reg_r(a)        cpustate->mem->read_data8(cpustate->regptr + a)
120 #define reg_w(a,V)      cpustate->mem->write_data8(cpustate->regptr + a, V)
121
122 #define ext_r(a)        cpustate->io->read_io8(a)
123 #define ext_w(a,V)      cpustate->io->write_io8(a, V)
124 #define port_r(a)       cpustate->io->read_io8(MCS48_PORT_P0 + a)
125 #define port_w(a,V)     cpustate->io->write_io8(MCS48_PORT_P0 + a, V)
126 #define test_r(a)       cpustate->io->read_io8(MCS48_PORT_T0 + a)
127 #define test_w(a,V)     cpustate->io->write_io8(MCS48_PORT_T0 + a, V)
128 #define bus_r()         cpustate->io->read_io8(MCS48_PORT_BUS)
129 #define bus_w(V)        cpustate->io->write_io8(MCS48_PORT_BUS, V)
130 #define prog_w(V)       cpustate->io->write_io8(MCS48_PORT_PROG, V)
131
132 /***************************************************************************
133     FUNCTION PROTOTYPES
134 ***************************************************************************/
135
136 static int check_irqs(mcs48_state *cpustate);
137
138 /***************************************************************************
139     INLINE FUNCTIONS
140 ***************************************************************************/
141
142 /*-------------------------------------------------
143     opcode_fetch - fetch an opcode byte
144 -------------------------------------------------*/
145
146 INLINE UINT8 opcode_fetch(mcs48_state *cpustate)
147 {
148         return cpustate->rom[cpustate->pc++ & 0xfff];
149 }
150
151 /*-------------------------------------------------
152     argument_fetch - fetch an opcode argument
153     byte
154 -------------------------------------------------*/
155
156 INLINE UINT8 argument_fetch(mcs48_state *cpustate)
157 {
158         return cpustate->rom[cpustate->pc++ & 0xfff];
159 }
160
161 /*-------------------------------------------------
162     update_regptr - update the regptr member to
163     point to the appropriate register bank
164 -------------------------------------------------*/
165
166 INLINE void update_regptr(mcs48_state *cpustate)
167 {
168         cpustate->regptr = ((cpustate->psw & B_FLAG) ? 24 : 0);
169 }
170
171 /*-------------------------------------------------
172     push_pc_psw - push the cpustate->pc and cpustate->psw values onto
173     the stack
174 -------------------------------------------------*/
175
176 INLINE void push_pc_psw(mcs48_state *cpustate)
177 {
178         UINT8 sp = cpustate->psw & 0x07;
179         ram_w(8 + 2*sp, cpustate->pc);
180         ram_w(9 + 2*sp, ((cpustate->pc >> 8) & 0x0f) | (cpustate->psw & 0xf0));
181         cpustate->psw = (cpustate->psw & 0xf8) | ((sp + 1) & 0x07);
182 }
183
184 /*-------------------------------------------------
185     pull_pc_psw - pull the PC and PSW values from
186     the stack
187 -------------------------------------------------*/
188
189 INLINE void pull_pc_psw(mcs48_state *cpustate)
190 {
191         UINT8 sp = (cpustate->psw - 1) & 0x07;
192         cpustate->pc = ram_r(8 + 2*sp);
193         cpustate->pc |= ram_r(9 + 2*sp) << 8;
194         cpustate->psw = ((cpustate->pc >> 8) & 0xf0) | 0x08 | sp;
195         cpustate->pc &= 0xfff;
196         update_regptr(cpustate);
197 }
198
199 /*-------------------------------------------------
200     pull_pc - pull the PC value from the stack,
201     leaving the upper part of PSW intact
202 -------------------------------------------------*/
203
204 INLINE void pull_pc(mcs48_state *cpustate)
205 {
206         UINT8 sp = (cpustate->psw - 1) & 0x07;
207         cpustate->pc = ram_r(8 + 2*sp);
208         cpustate->pc |= ram_r(9 + 2*sp) << 8;
209         cpustate->pc &= 0xfff;
210         cpustate->psw = (cpustate->psw & 0xf0) | 0x08 | sp;
211 }
212
213 /*-------------------------------------------------
214     execute_add - perform the logic of an ADD
215     instruction
216 -------------------------------------------------*/
217
218 INLINE void execute_add(mcs48_state *cpustate, UINT8 dat)
219 {
220         UINT16 temp = cpustate->a + dat;
221         UINT16 temp4 = (cpustate->a & 0x0f) + (dat & 0x0f);
222
223         cpustate->psw &= ~(C_FLAG | A_FLAG);
224         cpustate->psw |= (temp4 << 2) & A_FLAG;
225         cpustate->psw |= (temp >> 1) & C_FLAG;
226         cpustate->a = temp;
227 }
228
229 /*-------------------------------------------------
230     execute_addc - perform the logic of an ADDC
231     instruction
232 -------------------------------------------------*/
233
234 INLINE void execute_addc(mcs48_state *cpustate, UINT8 dat)
235 {
236         UINT8 carryin = (cpustate->psw & C_FLAG) >> 7;
237         UINT16 temp = cpustate->a + dat + carryin;
238         UINT16 temp4 = (cpustate->a & 0x0f) + (dat & 0x0f) + carryin;
239
240         cpustate->psw &= ~(C_FLAG | A_FLAG);
241         cpustate->psw |= (temp4 << 2) & A_FLAG;
242         cpustate->psw |= (temp >> 1) & C_FLAG;
243         cpustate->a = temp;
244 }
245
246 /*-------------------------------------------------
247     execute_jmp - perform the logic of a JMP
248     instruction
249 -------------------------------------------------*/
250
251 INLINE void execute_jmp(mcs48_state *cpustate, UINT16 address)
252 {
253         UINT16 a11 = (cpustate->irq_in_progress) ? 0 : cpustate->a11;
254         cpustate->pc = address | a11;
255 }
256
257 /*-------------------------------------------------
258     execute_call - perform the logic of a CALL
259     instruction
260 -------------------------------------------------*/
261
262 INLINE void execute_call(mcs48_state *cpustate, UINT16 address)
263 {
264         push_pc_psw(cpustate);
265         execute_jmp(cpustate, address);
266 }
267
268 /*-------------------------------------------------
269     execute_jcc - perform the logic of a
270     conditional jump instruction
271 -------------------------------------------------*/
272
273 INLINE void execute_jcc(mcs48_state *cpustate, UINT8 result)
274 {
275         UINT8 offset = argument_fetch(cpustate);
276         if (result != 0)
277                 cpustate->pc = ((cpustate->pc - 1) & 0xf00) | offset;
278 }
279
280 /*-------------------------------------------------
281     expander_operation - perform an operation via
282     the 8243 expander chip
283 -------------------------------------------------*/
284
285 INLINE void expander_operation(mcs48_state *cpustate, UINT8 operation, UINT8 port)
286 {
287         /* put opcode/data on low 4 bits of P2 */
288         port_w(2, cpustate->p2 = (cpustate->p2 & 0xf0) | (operation << 2) | (port & 3));
289
290         /* generate high-to-low transition on PROG line */
291         prog_w(0);
292
293         /* put data on low 4 bits of P2 */
294         if (operation != 0)
295                 port_w(2, cpustate->p2 = (cpustate->p2 & 0xf0) | (cpustate->a & 0x0f));
296         else
297                 cpustate->a = port_r(2) | 0x0f;
298
299         /* generate low-to-high transition on PROG line */
300         prog_w(1);
301 }
302
303 /***************************************************************************
304     OPCODE HANDLERS
305 ***************************************************************************/
306
307 #define OPHANDLER(_name) static int _name(mcs48_state *cpustate)
308
309 OPHANDLER( illegal )
310 {
311 //      logerror("MCS-48 PC:%04X - Illegal opcode = %02x\n", cpustate->pc - 1, program_r(cpustate->pc - 1));
312         return 1;
313 }
314
315 OPHANDLER( add_a_r0 )       { execute_add(cpustate, reg_r(0)); return 1; }
316 OPHANDLER( add_a_r1 )       { execute_add(cpustate, reg_r(1)); return 1; }
317 OPHANDLER( add_a_r2 )       { execute_add(cpustate, reg_r(2)); return 1; }
318 OPHANDLER( add_a_r3 )       { execute_add(cpustate, reg_r(3)); return 1; }
319 OPHANDLER( add_a_r4 )       { execute_add(cpustate, reg_r(4)); return 1; }
320 OPHANDLER( add_a_r5 )       { execute_add(cpustate, reg_r(5)); return 1; }
321 OPHANDLER( add_a_r6 )       { execute_add(cpustate, reg_r(6)); return 1; }
322 OPHANDLER( add_a_r7 )       { execute_add(cpustate, reg_r(7)); return 1; }
323 OPHANDLER( add_a_xr0 )      { execute_add(cpustate, ram_r(reg_r(0))); return 1; }
324 OPHANDLER( add_a_xr1 )      { execute_add(cpustate, ram_r(reg_r(1))); return 1; }
325 OPHANDLER( add_a_n )        { execute_add(cpustate, argument_fetch(cpustate)); return 2; }
326
327 OPHANDLER( adc_a_r0 )       { execute_addc(cpustate, reg_r(0)); return 1; }
328 OPHANDLER( adc_a_r1 )       { execute_addc(cpustate, reg_r(1)); return 1; }
329 OPHANDLER( adc_a_r2 )       { execute_addc(cpustate, reg_r(2)); return 1; }
330 OPHANDLER( adc_a_r3 )       { execute_addc(cpustate, reg_r(3)); return 1; }
331 OPHANDLER( adc_a_r4 )       { execute_addc(cpustate, reg_r(4)); return 1; }
332 OPHANDLER( adc_a_r5 )       { execute_addc(cpustate, reg_r(5)); return 1; }
333 OPHANDLER( adc_a_r6 )       { execute_addc(cpustate, reg_r(6)); return 1; }
334 OPHANDLER( adc_a_r7 )       { execute_addc(cpustate, reg_r(7)); return 1; }
335 OPHANDLER( adc_a_xr0 )      { execute_addc(cpustate, ram_r(reg_r(0))); return 1; }
336 OPHANDLER( adc_a_xr1 )      { execute_addc(cpustate, ram_r(reg_r(1))); return 1; }
337 OPHANDLER( adc_a_n )        { execute_addc(cpustate, argument_fetch(cpustate)); return 2; }
338
339 OPHANDLER( anl_a_r0 )       { cpustate->a &= reg_r(0); return 1; }
340 OPHANDLER( anl_a_r1 )       { cpustate->a &= reg_r(1); return 1; }
341 OPHANDLER( anl_a_r2 )       { cpustate->a &= reg_r(2); return 1; }
342 OPHANDLER( anl_a_r3 )       { cpustate->a &= reg_r(3); return 1; }
343 OPHANDLER( anl_a_r4 )       { cpustate->a &= reg_r(4); return 1; }
344 OPHANDLER( anl_a_r5 )       { cpustate->a &= reg_r(5); return 1; }
345 OPHANDLER( anl_a_r6 )       { cpustate->a &= reg_r(6); return 1; }
346 OPHANDLER( anl_a_r7 )       { cpustate->a &= reg_r(7); return 1; }
347 OPHANDLER( anl_a_xr0 )      { cpustate->a &= ram_r(reg_r(0)); return 1; }
348 OPHANDLER( anl_a_xr1 )      { cpustate->a &= ram_r(reg_r(1)); return 1; }
349 OPHANDLER( anl_a_n )        { cpustate->a &= argument_fetch(cpustate); return 2; }
350
351 OPHANDLER( anl_bus_n )      { bus_w(bus_r() & argument_fetch(cpustate)); return 2; }
352 OPHANDLER( anl_p1_n )       { port_w(1, cpustate->p1 &= argument_fetch(cpustate)); return 2; }
353 OPHANDLER( anl_p2_n )       { port_w(2, cpustate->p2 &= argument_fetch(cpustate)); return 2; }
354 OPHANDLER( anld_p4_a )      { expander_operation(cpustate, MCS48_EXPANDER_OP_AND, 4); return 2; }
355 OPHANDLER( anld_p5_a )      { expander_operation(cpustate, MCS48_EXPANDER_OP_AND, 5); return 2; }
356 OPHANDLER( anld_p6_a )      { expander_operation(cpustate, MCS48_EXPANDER_OP_AND, 6); return 2; }
357 OPHANDLER( anld_p7_a )      { expander_operation(cpustate, MCS48_EXPANDER_OP_AND, 7); return 2; }
358
359 OPHANDLER( call_0 )         { execute_call(cpustate, argument_fetch(cpustate) | 0x000); return 2; }
360 OPHANDLER( call_1 )         { execute_call(cpustate, argument_fetch(cpustate) | 0x100); return 2; }
361 OPHANDLER( call_2 )         { execute_call(cpustate, argument_fetch(cpustate) | 0x200); return 2; }
362 OPHANDLER( call_3 )         { execute_call(cpustate, argument_fetch(cpustate) | 0x300); return 2; }
363 OPHANDLER( call_4 )         { execute_call(cpustate, argument_fetch(cpustate) | 0x400); return 2; }
364 OPHANDLER( call_5 )         { execute_call(cpustate, argument_fetch(cpustate) | 0x500); return 2; }
365 OPHANDLER( call_6 )         { execute_call(cpustate, argument_fetch(cpustate) | 0x600); return 2; }
366 OPHANDLER( call_7 )         { execute_call(cpustate, argument_fetch(cpustate) | 0x700); return 2; }
367
368 OPHANDLER( clr_a )          { cpustate->a = 0; return 1; }
369 OPHANDLER( clr_c )          { cpustate->psw &= ~C_FLAG; return 1; }
370 OPHANDLER( clr_f0 )         { cpustate->psw &= ~F_FLAG; cpustate->sts &= ~STS_F0; return 1; }
371 OPHANDLER( clr_f1 )         { cpustate->sts &= ~STS_F1; return 1; }
372
373 OPHANDLER( cpl_a )          { cpustate->a ^= 0xff; return 1; }
374 OPHANDLER( cpl_c )          { cpustate->psw ^= C_FLAG; return 1; }
375 OPHANDLER( cpl_f0 )         { cpustate->psw ^= F_FLAG; cpustate->sts ^= STS_F0; return 1; }
376 OPHANDLER( cpl_f1 )         { cpustate->sts ^= STS_F1; return 1; }
377
378 OPHANDLER( da_a )
379 {
380         if ((cpustate->a & 0x0f) > 0x09 || (cpustate->psw & A_FLAG))
381         {
382                 cpustate->a += 0x06;
383                 if ((cpustate->a & 0xf0) == 0x00)
384                         cpustate->psw |= C_FLAG;
385         }
386         if ((cpustate->a & 0xf0) > 0x90 || (cpustate->psw & C_FLAG))
387         {
388                 cpustate->a += 0x60;
389                 cpustate->psw |= C_FLAG;
390         }
391         else
392                 cpustate->psw &= ~C_FLAG;
393         return 1;
394 }
395
396 OPHANDLER( dec_a )          { cpustate->a--; return 1; }
397 OPHANDLER( dec_r0 )         { reg_w(0, reg_r(0) - 1); return 1; }
398 OPHANDLER( dec_r1 )         { reg_w(1, reg_r(1) - 1); return 1; }
399 OPHANDLER( dec_r2 )         { reg_w(2, reg_r(2) - 1); return 1; }
400 OPHANDLER( dec_r3 )         { reg_w(3, reg_r(3) - 1); return 1; }
401 OPHANDLER( dec_r4 )         { reg_w(4, reg_r(4) - 1); return 1; }
402 OPHANDLER( dec_r5 )         { reg_w(5, reg_r(5) - 1); return 1; }
403 OPHANDLER( dec_r6 )         { reg_w(6, reg_r(6) - 1); return 1; }
404 OPHANDLER( dec_r7 )         { reg_w(7, reg_r(7) - 1); return 1; }
405
406 OPHANDLER( dis_i )          { cpustate->xirq_enabled = FALSE; return 1; }
407 OPHANDLER( dis_tcnti )      { cpustate->tirq_enabled = FALSE; cpustate->timer_overflow = FALSE; return 1; }
408
409 OPHANDLER( djnz_r0 )        { UINT8 r0 = reg_r(0); reg_w(0, --r0); execute_jcc(cpustate, r0 != 0); return 2; }
410 OPHANDLER( djnz_r1 )        { UINT8 r1 = reg_r(1); reg_w(1, --r1); execute_jcc(cpustate, r1 != 0); return 2; }
411 OPHANDLER( djnz_r2 )        { UINT8 r2 = reg_r(2); reg_w(2, --r2); execute_jcc(cpustate, r2 != 0); return 2; }
412 OPHANDLER( djnz_r3 )        { UINT8 r3 = reg_r(3); reg_w(3, --r3); execute_jcc(cpustate, r3 != 0); return 2; }
413 OPHANDLER( djnz_r4 )        { UINT8 r4 = reg_r(4); reg_w(4, --r4); execute_jcc(cpustate, r4 != 0); return 2; }
414 OPHANDLER( djnz_r5 )        { UINT8 r5 = reg_r(5); reg_w(5, --r5); execute_jcc(cpustate, r5 != 0); return 2; }
415 OPHANDLER( djnz_r6 )        { UINT8 r6 = reg_r(6); reg_w(6, --r6); execute_jcc(cpustate, r6 != 0); return 2; }
416 OPHANDLER( djnz_r7 )        { UINT8 r7 = reg_r(7); reg_w(7, --r7); execute_jcc(cpustate, r7 != 0); return 2; }
417
418 OPHANDLER( en_i )           { cpustate->xirq_enabled = TRUE; return 1 + check_irqs(cpustate); }
419 OPHANDLER( en_tcnti )       { cpustate->tirq_enabled = TRUE; return 1 + check_irqs(cpustate); }
420 OPHANDLER( ent0_clk )       { cpustate->t0_clk_enabled = TRUE; return 1; }
421
422 OPHANDLER( in_a_p1 )        { cpustate->a = port_r(1) & cpustate->p1; return 2; }
423 OPHANDLER( in_a_p2 )        { cpustate->a = port_r(2) & cpustate->p2; return 2; }
424 OPHANDLER( ins_a_bus )      { cpustate->a = bus_r(); return 2; }
425
426 OPHANDLER( inc_a )          { cpustate->a++; return 1; }
427 OPHANDLER( inc_r0 )         { reg_w(0, reg_r(0) + 1); return 1; }
428 OPHANDLER( inc_r1 )         { reg_w(1, reg_r(1) + 1); return 1; }
429 OPHANDLER( inc_r2 )         { reg_w(2, reg_r(2) + 1); return 1; }
430 OPHANDLER( inc_r3 )         { reg_w(3, reg_r(3) + 1); return 1; }
431 OPHANDLER( inc_r4 )         { reg_w(4, reg_r(4) + 1); return 1; }
432 OPHANDLER( inc_r5 )         { reg_w(5, reg_r(5) + 1); return 1; }
433 OPHANDLER( inc_r6 )         { reg_w(6, reg_r(6) + 1); return 1; }
434 OPHANDLER( inc_r7 )         { reg_w(7, reg_r(7) + 1); return 1; }
435 OPHANDLER( inc_xr0 )        { UINT8 r0 = reg_r(0); ram_w(r0, ram_r(r0) + 1); return 1; }
436 OPHANDLER( inc_xr1 )        { UINT8 r1 = reg_r(1); ram_w(r1, ram_r(r1) + 1); return 1; }
437
438 OPHANDLER( jb_0 )           { execute_jcc(cpustate, (cpustate->a & 0x01) != 0); return 2; }
439 OPHANDLER( jb_1 )           { execute_jcc(cpustate, (cpustate->a & 0x02) != 0); return 2; }
440 OPHANDLER( jb_2 )           { execute_jcc(cpustate, (cpustate->a & 0x04) != 0); return 2; }
441 OPHANDLER( jb_3 )           { execute_jcc(cpustate, (cpustate->a & 0x08) != 0); return 2; }
442 OPHANDLER( jb_4 )           { execute_jcc(cpustate, (cpustate->a & 0x10) != 0); return 2; }
443 OPHANDLER( jb_5 )           { execute_jcc(cpustate, (cpustate->a & 0x20) != 0); return 2; }
444 OPHANDLER( jb_6 )           { execute_jcc(cpustate, (cpustate->a & 0x40) != 0); return 2; }
445 OPHANDLER( jb_7 )           { execute_jcc(cpustate, (cpustate->a & 0x80) != 0); return 2; }
446 OPHANDLER( jc )             { execute_jcc(cpustate, (cpustate->psw & C_FLAG) != 0); return 2; }
447 OPHANDLER( jf0 )            { execute_jcc(cpustate, (cpustate->psw & F_FLAG) != 0); return 2; }
448 OPHANDLER( jf1 )            { execute_jcc(cpustate, (cpustate->sts & STS_F1) != 0); return 2; }
449 OPHANDLER( jnc )            { execute_jcc(cpustate, (cpustate->psw & C_FLAG) == 0); return 2; }
450 OPHANDLER( jni )            { execute_jcc(cpustate, cpustate->int_state == 0); return 2; }
451 OPHANDLER( jnt_0 )          { execute_jcc(cpustate, test_r(0) == 0); return 2; }
452 OPHANDLER( jnt_1 )          { execute_jcc(cpustate, test_r(1) == 0); return 2; }
453 OPHANDLER( jnz )            { execute_jcc(cpustate, cpustate->a != 0); return 2; }
454 OPHANDLER( jtf )            { execute_jcc(cpustate, cpustate->timer_flag); cpustate->timer_flag = FALSE; return 2; }
455 OPHANDLER( jt_0 )           { execute_jcc(cpustate, test_r(0) != 0); return 2; }
456 OPHANDLER( jt_1 )           { execute_jcc(cpustate, test_r(1) != 0); return 2; }
457 OPHANDLER( jz )             { execute_jcc(cpustate, cpustate->a == 0); return 2; }
458
459 OPHANDLER( jmp_0 )          { execute_jmp(cpustate, argument_fetch(cpustate) | 0x000); return 2; }
460 OPHANDLER( jmp_1 )          { execute_jmp(cpustate, argument_fetch(cpustate) | 0x100); return 2; }
461 OPHANDLER( jmp_2 )          { execute_jmp(cpustate, argument_fetch(cpustate) | 0x200); return 2; }
462 OPHANDLER( jmp_3 )          { execute_jmp(cpustate, argument_fetch(cpustate) | 0x300); return 2; }
463 OPHANDLER( jmp_4 )          { execute_jmp(cpustate, argument_fetch(cpustate) | 0x400); return 2; }
464 OPHANDLER( jmp_5 )          { execute_jmp(cpustate, argument_fetch(cpustate) | 0x500); return 2; }
465 OPHANDLER( jmp_6 )          { execute_jmp(cpustate, argument_fetch(cpustate) | 0x600); return 2; }
466 OPHANDLER( jmp_7 )          { execute_jmp(cpustate, argument_fetch(cpustate) | 0x700); return 2; }
467 OPHANDLER( jmpp_xa )        { cpustate->pc &= 0xf00; cpustate->pc |= program_r(cpustate->pc | cpustate->a); return 2; }
468
469 OPHANDLER( mov_a_n )        { cpustate->a = argument_fetch(cpustate); return 2; }
470 OPHANDLER( mov_a_psw )      { cpustate->a = cpustate->psw; return 1; }
471 OPHANDLER( mov_a_r0 )       { cpustate->a = reg_r(0); return 1; }
472 OPHANDLER( mov_a_r1 )       { cpustate->a = reg_r(1); return 1; }
473 OPHANDLER( mov_a_r2 )       { cpustate->a = reg_r(2); return 1; }
474 OPHANDLER( mov_a_r3 )       { cpustate->a = reg_r(3); return 1; }
475 OPHANDLER( mov_a_r4 )       { cpustate->a = reg_r(4); return 1; }
476 OPHANDLER( mov_a_r5 )       { cpustate->a = reg_r(5); return 1; }
477 OPHANDLER( mov_a_r6 )       { cpustate->a = reg_r(6); return 1; }
478 OPHANDLER( mov_a_r7 )       { cpustate->a = reg_r(7); return 1; }
479 OPHANDLER( mov_a_xr0 )      { cpustate->a = ram_r(reg_r(0)); return 1; }
480 OPHANDLER( mov_a_xr1 )      { cpustate->a = ram_r(reg_r(1)); return 1; }
481 OPHANDLER( mov_a_t )        { cpustate->a = cpustate->timer; return 1; }
482
483 OPHANDLER( mov_psw_a )      { cpustate->psw = cpustate->a; update_regptr(cpustate); return 1; }
484 OPHANDLER( mov_r0_a )       { reg_w(0, cpustate->a); return 1; }
485 OPHANDLER( mov_r1_a )       { reg_w(1, cpustate->a); return 1; }
486 OPHANDLER( mov_r2_a )       { reg_w(2, cpustate->a); return 1; }
487 OPHANDLER( mov_r3_a )       { reg_w(3, cpustate->a); return 1; }
488 OPHANDLER( mov_r4_a )       { reg_w(4, cpustate->a); return 1; }
489 OPHANDLER( mov_r5_a )       { reg_w(5, cpustate->a); return 1; }
490 OPHANDLER( mov_r6_a )       { reg_w(6, cpustate->a); return 1; }
491 OPHANDLER( mov_r7_a )       { reg_w(7, cpustate->a); return 1; }
492 OPHANDLER( mov_r0_n )       { reg_w(0, argument_fetch(cpustate)); return 2; }
493 OPHANDLER( mov_r1_n )       { reg_w(1, argument_fetch(cpustate)); return 2; }
494 OPHANDLER( mov_r2_n )       { reg_w(2, argument_fetch(cpustate)); return 2; }
495 OPHANDLER( mov_r3_n )       { reg_w(3, argument_fetch(cpustate)); return 2; }
496 OPHANDLER( mov_r4_n )       { reg_w(4, argument_fetch(cpustate)); return 2; }
497 OPHANDLER( mov_r5_n )       { reg_w(5, argument_fetch(cpustate)); return 2; }
498 OPHANDLER( mov_r6_n )       { reg_w(6, argument_fetch(cpustate)); return 2; }
499 OPHANDLER( mov_r7_n )       { reg_w(7, argument_fetch(cpustate)); return 2; }
500 OPHANDLER( mov_t_a )        { cpustate->timer = cpustate->a; return 1; }
501 OPHANDLER( mov_xr0_a )      { ram_w(reg_r(0), cpustate->a); return 1; }
502 OPHANDLER( mov_xr1_a )      { ram_w(reg_r(1), cpustate->a); return 1; }
503 OPHANDLER( mov_xr0_n )      { ram_w(reg_r(0), argument_fetch(cpustate)); return 2; }
504 OPHANDLER( mov_xr1_n )      { ram_w(reg_r(1), argument_fetch(cpustate)); return 2; }
505
506 OPHANDLER( movd_a_p4 )      { expander_operation(cpustate, MCS48_EXPANDER_OP_READ, 4); return 2; }
507 OPHANDLER( movd_a_p5 )      { expander_operation(cpustate, MCS48_EXPANDER_OP_READ, 5); return 2; }
508 OPHANDLER( movd_a_p6 )      { expander_operation(cpustate, MCS48_EXPANDER_OP_READ, 6); return 2; }
509 OPHANDLER( movd_a_p7 )      { expander_operation(cpustate, MCS48_EXPANDER_OP_READ, 7); return 2; }
510 OPHANDLER( movd_p4_a )      { expander_operation(cpustate, MCS48_EXPANDER_OP_WRITE, 4); return 2; }
511 OPHANDLER( movd_p5_a )      { expander_operation(cpustate, MCS48_EXPANDER_OP_WRITE, 5); return 2; }
512 OPHANDLER( movd_p6_a )      { expander_operation(cpustate, MCS48_EXPANDER_OP_WRITE, 6); return 2; }
513 OPHANDLER( movd_p7_a )      { expander_operation(cpustate, MCS48_EXPANDER_OP_WRITE, 7); return 2; }
514
515 OPHANDLER( movp_a_xa )      { cpustate->a = program_r((cpustate->pc & 0xf00) | cpustate->a); return 2; }
516 OPHANDLER( movp3_a_xa )     { cpustate->a = program_r(0x300 | cpustate->a); return 2; }
517
518 OPHANDLER( movx_a_xr0 )     { cpustate->a = ext_r(reg_r(0)); return 2; }
519 OPHANDLER( movx_a_xr1 )     { cpustate->a = ext_r(reg_r(1)); return 2; }
520 OPHANDLER( movx_xr0_a )     { ext_w(reg_r(0), cpustate->a); return 2; }
521 OPHANDLER( movx_xr1_a )     { ext_w(reg_r(1), cpustate->a); return 2; }
522
523 OPHANDLER( nop )            { return 1; }
524
525 OPHANDLER( orl_a_r0 )       { cpustate->a |= reg_r(0); return 1; }
526 OPHANDLER( orl_a_r1 )       { cpustate->a |= reg_r(1); return 1; }
527 OPHANDLER( orl_a_r2 )       { cpustate->a |= reg_r(2); return 1; }
528 OPHANDLER( orl_a_r3 )       { cpustate->a |= reg_r(3); return 1; }
529 OPHANDLER( orl_a_r4 )       { cpustate->a |= reg_r(4); return 1; }
530 OPHANDLER( orl_a_r5 )       { cpustate->a |= reg_r(5); return 1; }
531 OPHANDLER( orl_a_r6 )       { cpustate->a |= reg_r(6); return 1; }
532 OPHANDLER( orl_a_r7 )       { cpustate->a |= reg_r(7); return 1; }
533 OPHANDLER( orl_a_xr0 )      { cpustate->a |= ram_r(reg_r(0)); return 1; }
534 OPHANDLER( orl_a_xr1 )      { cpustate->a |= ram_r(reg_r(1)); return 1; }
535 OPHANDLER( orl_a_n )        { cpustate->a |= argument_fetch(cpustate); return 2; }
536
537 OPHANDLER( orl_bus_n )      { bus_w(bus_r() | argument_fetch(cpustate)); return 2; }
538 OPHANDLER( orl_p1_n )       { port_w(1, cpustate->p1 |= argument_fetch(cpustate)); return 2; }
539 OPHANDLER( orl_p2_n )       { port_w(2, cpustate->p2 |= argument_fetch(cpustate)); return 2; }
540 OPHANDLER( orld_p4_a )      { expander_operation(cpustate, MCS48_EXPANDER_OP_OR, 4); return 2; }
541 OPHANDLER( orld_p5_a )      { expander_operation(cpustate, MCS48_EXPANDER_OP_OR, 5); return 2; }
542 OPHANDLER( orld_p6_a )      { expander_operation(cpustate, MCS48_EXPANDER_OP_OR, 6); return 2; }
543 OPHANDLER( orld_p7_a )      { expander_operation(cpustate, MCS48_EXPANDER_OP_OR, 7); return 2; }
544
545 OPHANDLER( outl_bus_a )     { bus_w(cpustate->a); return 2; }
546 OPHANDLER( outl_p1_a )      { port_w(1, cpustate->p1 = cpustate->a); return 2; }
547 OPHANDLER( outl_p2_a )      { port_w(2, cpustate->p2 = cpustate->a); return 2; }
548
549 OPHANDLER( ret )            { pull_pc(cpustate); return 2; }
550 OPHANDLER( retr )
551 {
552         pull_pc_psw(cpustate);
553
554         /* implicitly clear the IRQ in progress flip flop and re-check interrupts */
555         cpustate->irq_in_progress = FALSE;
556         return 2 + check_irqs(cpustate);
557 }
558
559 OPHANDLER( rl_a )           { cpustate->a = (cpustate->a << 1) | (cpustate->a >> 7); return 1; }
560 OPHANDLER( rlc_a )          { UINT8 newc = cpustate->a & C_FLAG; cpustate->a = (cpustate->a << 1) | (cpustate->psw >> 7); cpustate->psw = (cpustate->psw & ~C_FLAG) | newc; return 1; }
561
562 OPHANDLER( rr_a )           { cpustate->a = (cpustate->a >> 1) | (cpustate->a << 7); return 1; }
563 OPHANDLER( rrc_a )          { UINT8 newc = (cpustate->a << 7) & C_FLAG; cpustate->a = (cpustate->a >> 1) | (cpustate->psw & C_FLAG); cpustate->psw = (cpustate->psw & ~C_FLAG) | newc; return 1; }
564
565 OPHANDLER( sel_mb0 )        { cpustate->a11 = 0x000; return 1; }
566 OPHANDLER( sel_mb1 )        { cpustate->a11 = 0x800; return 1; }
567
568 OPHANDLER( sel_rb0 )        { cpustate->psw &= ~B_FLAG; update_regptr(cpustate); return 1; }
569 OPHANDLER( sel_rb1 )        { cpustate->psw |=  B_FLAG; update_regptr(cpustate); return 1; }
570
571 OPHANDLER( stop_tcnt )      { cpustate->timecount_enabled = 0; return 1; }
572
573 OPHANDLER( strt_cnt )       { cpustate->timecount_enabled = COUNTER_ENABLED; cpustate->t1_history = test_r(1); return 1; }
574 OPHANDLER( strt_t )         { cpustate->timecount_enabled = TIMER_ENABLED; cpustate->prescaler = 0; return 1; }
575
576 OPHANDLER( swap_a )         { cpustate->a = (cpustate->a << 4) | (cpustate->a >> 4); return 1; }
577
578 OPHANDLER( xch_a_r0 )       { UINT8 tmp = cpustate->a; cpustate->a = reg_r(0); reg_w(0, tmp); return 1; }
579 OPHANDLER( xch_a_r1 )       { UINT8 tmp = cpustate->a; cpustate->a = reg_r(1); reg_w(1, tmp); return 1; }
580 OPHANDLER( xch_a_r2 )       { UINT8 tmp = cpustate->a; cpustate->a = reg_r(2); reg_w(2, tmp); return 1; }
581 OPHANDLER( xch_a_r3 )       { UINT8 tmp = cpustate->a; cpustate->a = reg_r(3); reg_w(3, tmp); return 1; }
582 OPHANDLER( xch_a_r4 )       { UINT8 tmp = cpustate->a; cpustate->a = reg_r(4); reg_w(4, tmp); return 1; }
583 OPHANDLER( xch_a_r5 )       { UINT8 tmp = cpustate->a; cpustate->a = reg_r(5); reg_w(5, tmp); return 1; }
584 OPHANDLER( xch_a_r6 )       { UINT8 tmp = cpustate->a; cpustate->a = reg_r(6); reg_w(6, tmp); return 1; }
585 OPHANDLER( xch_a_r7 )       { UINT8 tmp = cpustate->a; cpustate->a = reg_r(7); reg_w(7, tmp); return 1; }
586 OPHANDLER( xch_a_xr0 )      { UINT8 r0 = reg_r(0); UINT8 tmp = cpustate->a; cpustate->a = ram_r(r0); ram_w(r0, tmp); return 1; }
587 OPHANDLER( xch_a_xr1 )      { UINT8 r1 = reg_r(1); UINT8 tmp = cpustate->a; cpustate->a = ram_r(r1); ram_w(r1, tmp); return 1; }
588
589 OPHANDLER( xchd_a_xr0 )     { UINT8 r0 = reg_r(0); UINT8 oldram = ram_r(r0); ram_w(r0, (oldram & 0xf0) | (cpustate->a & 0x0f)); cpustate->a = (cpustate->a & 0xf0) | (oldram & 0x0f); return 1; }
590 OPHANDLER( xchd_a_xr1 )     { UINT8 r1 = reg_r(1); UINT8 oldram = ram_r(r1); ram_w(r1, (oldram & 0xf0) | (cpustate->a & 0x0f)); cpustate->a = (cpustate->a & 0xf0) | (oldram & 0x0f); return 1; }
591
592 OPHANDLER( xrl_a_r0 )       { cpustate->a ^= reg_r(0); return 1; }
593 OPHANDLER( xrl_a_r1 )       { cpustate->a ^= reg_r(1); return 1; }
594 OPHANDLER( xrl_a_r2 )       { cpustate->a ^= reg_r(2); return 1; }
595 OPHANDLER( xrl_a_r3 )       { cpustate->a ^= reg_r(3); return 1; }
596 OPHANDLER( xrl_a_r4 )       { cpustate->a ^= reg_r(4); return 1; }
597 OPHANDLER( xrl_a_r5 )       { cpustate->a ^= reg_r(5); return 1; }
598 OPHANDLER( xrl_a_r6 )       { cpustate->a ^= reg_r(6); return 1; }
599 OPHANDLER( xrl_a_r7 )       { cpustate->a ^= reg_r(7); return 1; }
600 OPHANDLER( xrl_a_xr0 )      { cpustate->a ^= ram_r(reg_r(0)); return 1; }
601 OPHANDLER( xrl_a_xr1 )      { cpustate->a ^= ram_r(reg_r(1)); return 1; }
602 OPHANDLER( xrl_a_n )        { cpustate->a ^= argument_fetch(cpustate); return 2; }
603
604 /***************************************************************************
605     OPCODE TABLES
606 ***************************************************************************/
607
608 static const mcs48_ophandler opcode_table[256]=
609 {
610         nop,        illegal,    outl_bus_a,add_a_n,   jmp_0,     en_i,       illegal,   dec_a,         /* 00 */
611         ins_a_bus,  in_a_p1,    in_a_p2,   illegal,   movd_a_p4, movd_a_p5,  movd_a_p6, movd_a_p7,
612         inc_xr0,    inc_xr1,    jb_0,      adc_a_n,   call_0,    dis_i,      jtf,       inc_a,         /* 10 */
613         inc_r0,     inc_r1,     inc_r2,    inc_r3,    inc_r4,    inc_r5,     inc_r6,    inc_r7,
614         xch_a_xr0,  xch_a_xr1,  illegal,   mov_a_n,   jmp_1,     en_tcnti,   jnt_0,     clr_a,         /* 20 */
615         xch_a_r0,   xch_a_r1,   xch_a_r2,  xch_a_r3,  xch_a_r4,  xch_a_r5,   xch_a_r6,  xch_a_r7,
616         xchd_a_xr0, xchd_a_xr1, jb_1,      illegal,   call_1,    dis_tcnti,  jt_0,      cpl_a,         /* 30 */
617         illegal,    outl_p1_a,  outl_p2_a, illegal,   movd_p4_a, movd_p5_a,  movd_p6_a, movd_p7_a,
618         orl_a_xr0,  orl_a_xr1,  mov_a_t,   orl_a_n,   jmp_2,     strt_cnt,   jnt_1,     swap_a,        /* 40 */
619         orl_a_r0,   orl_a_r1,   orl_a_r2,  orl_a_r3,  orl_a_r4,  orl_a_r5,   orl_a_r6,  orl_a_r7,
620         anl_a_xr0,  anl_a_xr1,  jb_2,      anl_a_n,   call_2,    strt_t,     jt_1,      da_a,          /* 50 */
621         anl_a_r0,   anl_a_r1,   anl_a_r2,  anl_a_r3,  anl_a_r4,  anl_a_r5,   anl_a_r6,  anl_a_r7,
622         add_a_xr0,  add_a_xr1,  mov_t_a,   illegal,   jmp_3,     stop_tcnt,  illegal,   rrc_a,         /* 60 */
623         add_a_r0,   add_a_r1,   add_a_r2,  add_a_r3,  add_a_r4,  add_a_r5,   add_a_r6,  add_a_r7,
624         adc_a_xr0,  adc_a_xr1,  jb_3,      illegal,   call_3,    ent0_clk,   jf1,       rr_a,          /* 70 */
625         adc_a_r0,   adc_a_r1,   adc_a_r2,  adc_a_r3,  adc_a_r4,  adc_a_r5,   adc_a_r6,  adc_a_r7,
626         movx_a_xr0, movx_a_xr1, illegal,   ret,       jmp_4,     clr_f0,     jni,       illegal,       /* 80 */
627         orl_bus_n,  orl_p1_n,   orl_p2_n,  illegal,   orld_p4_a, orld_p5_a,  orld_p6_a, orld_p7_a,
628         movx_xr0_a, movx_xr1_a, jb_4,      retr,      call_4,    cpl_f0,     jnz,       clr_c,         /* 90 */
629         anl_bus_n,  anl_p1_n,   anl_p2_n,  illegal,   anld_p4_a, anld_p5_a,  anld_p6_a, anld_p7_a,
630         mov_xr0_a,  mov_xr1_a,  illegal,   movp_a_xa, jmp_5,     clr_f1,     illegal,   cpl_c,         /* A0 */
631         mov_r0_a,   mov_r1_a,   mov_r2_a,  mov_r3_a,  mov_r4_a,  mov_r5_a,   mov_r6_a,  mov_r7_a,
632         mov_xr0_n,  mov_xr1_n,  jb_5,      jmpp_xa,   call_5,    cpl_f1,     jf0,       illegal,       /* B0 */
633         mov_r0_n,   mov_r1_n,   mov_r2_n,  mov_r3_n,  mov_r4_n,  mov_r5_n,   mov_r6_n,  mov_r7_n,
634         illegal,    illegal,    illegal,   illegal,   jmp_6,     sel_rb0,    jz,        mov_a_psw,     /* C0 */
635         dec_r0,     dec_r1,     dec_r2,    dec_r3,    dec_r4,    dec_r5,     dec_r6,    dec_r7,
636         xrl_a_xr0,  xrl_a_xr1,  jb_6,      xrl_a_n,   call_6,    sel_rb1,    illegal,   mov_psw_a,     /* D0 */
637         xrl_a_r0,   xrl_a_r1,   xrl_a_r2,  xrl_a_r3,  xrl_a_r4,  xrl_a_r5,   xrl_a_r6,  xrl_a_r7,
638         illegal,    illegal,    illegal,   movp3_a_xa,jmp_7,     sel_mb0,    jnc,       rl_a,          /* E0 */
639         djnz_r0,    djnz_r1,    djnz_r2,   djnz_r3,   djnz_r4,   djnz_r5,    djnz_r6,   djnz_r7,
640         mov_a_xr0,  mov_a_xr1,  jb_7,      illegal,   call_7,    sel_mb1,    jc,        rlc_a,         /* F0 */
641         mov_a_r0,   mov_a_r1,   mov_a_r2,  mov_a_r3,  mov_a_r4,  mov_a_r5,   mov_a_r6,  mov_a_r7
642 };
643
644 /***************************************************************************
645     INITIALIZATION/RESET
646 ***************************************************************************/
647
648 void MCS48::initialize()
649 {
650         opaque = calloc(1, sizeof(mcs48_state));
651         
652         mcs48_state *cpustate = (mcs48_state *)opaque;
653         
654         cpustate->mem = d_mem;
655         cpustate->io = d_io;
656         cpustate->intr = d_intr;
657 #ifdef USE_DEBUGGER
658         d_mem_stored = d_mem;
659         d_io_stored = d_io;
660         d_debugger->set_context_mem(d_mem);
661         d_debugger->set_context_io(d_io);
662 #endif
663 }
664
665 void MCS48::release()
666 {
667         free(opaque);
668 }
669
670 void MCS48::reset()
671 {
672         mcs48_state *cpustate = (mcs48_state *)opaque;
673         
674         /* confirmed from reset description */
675         cpustate->pc = 0;
676         cpustate->psw = (cpustate->psw & (C_FLAG | A_FLAG)) | 0x08;
677         cpustate->a11 = 0x000;
678 //      bus_w(0xff);
679         cpustate->p1 = 0xff;
680         cpustate->p2 = 0xff;
681 //      port_w(1, cpustate->p1);
682 //      port_w(2, cpustate->p2);
683         cpustate->tirq_enabled = FALSE;
684         cpustate->xirq_enabled = FALSE;
685         cpustate->t0_clk_enabled = FALSE;
686         cpustate->timecount_enabled = 0;
687         cpustate->timer_flag = FALSE;
688         cpustate->sts = 0;
689         
690         cpustate->icount = 0;
691         
692         /* confirmed from interrupt logic description */
693         cpustate->int_state = TRUE;
694         cpustate->irq_state = cpustate->irq_in_progress = FALSE;
695         cpustate->timer_overflow = FALSE;
696 }
697
698 void MCS48::load_rom_image(const _TCHAR *file_path)
699 {
700         mcs48_state *cpustate = (mcs48_state *)opaque;
701         
702         memset(cpustate->rom, 0, sizeof(cpustate->rom));
703         
704         FILEIO* fio = new FILEIO();
705         if(fio->Fopen(file_path, FILEIO_READ_BINARY)) {
706                 fio->Fread(cpustate->rom, sizeof(cpustate->rom), 1);
707                 fio->Fclose();
708         }
709         delete fio;
710 }
711
712 uint8_t *MCS48::get_rom_ptr()
713 {
714         mcs48_state *cpustate = (mcs48_state *)opaque;
715         return cpustate->rom;
716 }
717
718 /***************************************************************************
719     EXECUTION
720 ***************************************************************************/
721
722 /*-------------------------------------------------
723     check_irqs - check for and process IRQs
724 -------------------------------------------------*/
725
726 static int check_irqs(mcs48_state *cpustate)
727 {
728         /* if something is in progress, we do nothing */
729         if (cpustate->irq_in_progress)
730                 return 0;
731
732         /* external interrupts take priority */
733         if (cpustate->irq_state && cpustate->xirq_enabled)
734         {
735                 cpustate->irq_state = FALSE;
736                 cpustate->irq_in_progress = TRUE;
737
738                 /* transfer to location 0x03 */
739                 push_pc_psw(cpustate);
740                 cpustate->pc = 0x03;
741
742                 /* indicate we took the external IRQ */
743                 if (cpustate->intr != NULL)
744                         cpustate->intr->get_intr_ack();
745                 return 2;
746         }
747
748         /* timer overflow interrupts follow */
749         if (cpustate->timer_overflow && cpustate->tirq_enabled)
750         {
751                 cpustate->irq_in_progress = TRUE;
752
753                 /* transfer to location 0x07 */
754                 push_pc_psw(cpustate);
755                 cpustate->pc = 0x07;
756
757                 /* timer overflow flip-flop is reset once taken */
758                 cpustate->timer_overflow = FALSE;
759                 return 2;
760         }
761         return 0;
762 }
763
764 /*-------------------------------------------------
765     burn_cycles - burn cycles, processing timers
766     and counters
767 -------------------------------------------------*/
768
769 static void burn_cycles(mcs48_state *cpustate, int count)
770 {
771         int timerover = FALSE;
772
773         /* output (clock*15/3) hz to t0 */
774         if (cpustate->t0_clk_enabled)
775         {
776                 for(int i = 0; i < count * 5; i++)
777                 {
778                         test_w(0, 1);
779                         test_w(0, 0);
780                 }
781         }
782
783         /* if the timer is enabled, accumulate prescaler cycles */
784         if (cpustate->timecount_enabled & TIMER_ENABLED)
785         {
786                 UINT8 oldtimer = cpustate->timer;
787                 cpustate->prescaler += count;
788                 cpustate->timer += cpustate->prescaler >> 5;
789                 cpustate->prescaler &= 0x1f;
790                 timerover = (oldtimer != 0 && cpustate->timer == 0);
791         }
792
793         /* if the counter is enabled, poll the T1 test input once for each cycle */
794         else if (cpustate->timecount_enabled & COUNTER_ENABLED)
795                 for ( ; count > 0; count--)
796                 {
797                         cpustate->t1_history = (cpustate->t1_history << 1) | (test_r(1) & 1);
798                         if ((cpustate->t1_history & 3) == 2)
799                                 timerover = (++cpustate->timer == 0);
800                 }
801
802         /* if either source caused a timer overflow, set the flags and check IRQs */
803         if (timerover)
804         {
805                 cpustate->timer_flag = TRUE;
806
807                 /* according to the docs, if an overflow occurs with interrupts disabled, the overflow is not stored */
808                 if (cpustate->tirq_enabled)
809                 {
810                         cpustate->timer_overflow = TRUE;
811                         check_irqs(cpustate);
812                 }
813         }
814 }
815
816 int MCS48::run(int icount)
817 {
818         mcs48_state *cpustate = (mcs48_state *)opaque;
819         int curcycles;
820         
821         if (icount == -1) {
822                 cpustate->icount = 1;
823         } else {
824                 cpustate->icount += icount;
825                 if (cpustate->icount < 0) {
826                         return 0;
827                 }
828         }
829         
830         int base_icount = cpustate->icount;
831         
832         update_regptr(cpustate);
833         
834         /* external interrupts may have been set since we last checked */
835         curcycles = check_irqs(cpustate);
836         cpustate->icount -= curcycles * 15;
837         if (cpustate->timecount_enabled != 0)
838                 burn_cycles(cpustate, curcycles);
839
840         /* iterate over remaining cycles, guaranteeing at least one instruction */
841         do
842         {
843 #ifdef USE_DEBUGGER
844                 bool now_debugging = d_debugger->now_debugging;
845                 if(now_debugging) {
846                         d_debugger->check_break_points(cpustate->pc);
847                         if(d_debugger->now_suspended) {
848                                 emu->mute_sound();
849                                 while(d_debugger->now_debugging && d_debugger->now_suspended) {
850                                         emu->sleep(10);
851                                 }
852                         }
853                         if(d_debugger->now_debugging) {
854                                 d_mem = d_io = d_debugger;
855                         } else {
856                                 now_debugging = false;
857                         }
858                         
859                         /* fetch next opcode */
860                         cpustate->prevpc = cpustate->pc;
861                         unsigned opcode = opcode_fetch(cpustate);
862
863                         /* process opcode and count cycles */
864                         curcycles = (*opcode_table[opcode])(cpustate);
865
866                         /* burn the cycles */
867                         cpustate->icount -= curcycles * 15;
868                         if (cpustate->timecount_enabled != 0)
869                                 burn_cycles(cpustate, curcycles);
870                         
871                         if(now_debugging) {
872                                 if(!d_debugger->now_going) {
873                                         d_debugger->now_suspended = true;
874                                 }
875                                 d_mem = d_mem_stored;
876                                 d_io = d_io_stored;
877                         }
878                 } else {
879 #endif
880                         /* fetch next opcode */
881                         cpustate->prevpc = cpustate->pc;
882                         unsigned opcode = opcode_fetch(cpustate);
883
884                         /* process opcode and count cycles */
885                         curcycles = (*opcode_table[opcode])(cpustate);
886
887                         /* burn the cycles */
888                         cpustate->icount -= curcycles * 15;
889                         if (cpustate->timecount_enabled != 0)
890                                 burn_cycles(cpustate, curcycles);
891 #ifdef USE_DEBUGGER
892                 }
893 #endif
894         } while (cpustate->icount > 0);
895         
896         return base_icount - cpustate->icount;
897 }
898
899 uint32_t MCS48::get_pc()
900 {
901         mcs48_state *cpustate = (mcs48_state *)opaque;
902         return cpustate->prevpc;
903 }
904
905 uint32_t MCS48::get_next_pc()
906 {
907         mcs48_state *cpustate = (mcs48_state *)opaque;
908         return cpustate->pc;
909 }
910
911 /***************************************************************************
912     GENERAL CONTEXT ACCESS
913 ***************************************************************************/
914
915 void MCS48::write_signal(int id, uint32_t data, uint32_t mask)
916 {
917         mcs48_state *cpustate = (mcs48_state *)opaque;
918         
919         if(id == SIG_CPU_IRQ) {
920                 UINT8 prev = cpustate->int_state;
921                 cpustate->int_state = ((data & mask) != 0);
922                 // INT H->L
923                 if(prev && !cpustate->int_state) {
924                         cpustate->irq_state = TRUE;
925                 }
926         }
927 }
928
929 #ifdef USE_DEBUGGER
930 void MCS48::write_debug_data8(uint32_t addr, uint32_t data)
931 {
932         d_mem_stored->write_data8(addr, data);
933 }
934
935 uint32_t MCS48::read_debug_data8(uint32_t addr)
936 {
937         return d_mem_stored->read_data8(addr);
938 }
939
940 void MCS48::write_debug_io8(uint32_t addr, uint32_t data)
941 {
942         d_io_stored->write_io8(addr, data);
943 }
944
945 uint32_t MCS48::read_debug_io8(uint32_t addr)
946 {
947         return d_io_stored->read_io8(addr);
948 }
949
950 bool MCS48::write_debug_reg(const _TCHAR *reg, uint32_t data)
951 {
952         mcs48_state *cpustate = (mcs48_state *)opaque;
953         
954         if(_tcsicmp(reg, _T("R0")) == 0) {
955                 reg_w(0, data);
956         } else if(_tcsicmp(reg, _T("R1")) == 0) {
957                 reg_w(1, data);
958         } else if(_tcsicmp(reg, _T("R2")) == 0) {
959                 reg_w(2, data);
960         } else if(_tcsicmp(reg, _T("R3")) == 0) {
961                 reg_w(3, data);
962         } else if(_tcsicmp(reg, _T("R4")) == 0) {
963                 reg_w(4, data);
964         } else if(_tcsicmp(reg, _T("R5")) == 0) {
965                 reg_w(5, data);
966         } else if(_tcsicmp(reg, _T("R6")) == 0) {
967                 reg_w(6, data);
968         } else if(_tcsicmp(reg, _T("R7")) == 0) {
969                 reg_w(7, data);
970         } else {
971                 return false;
972         }
973         return true;
974 }
975
976 void MCS48::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
977 {
978 /*
979 R0 = 00  R1 = 00  R2 = 00  R3 = 00 (R0)= 00 (R1)= 00 (SP-1)= 0000  PC = 0000
980 R4 = 00  R5 = 00  R6 = 00  R7 = 00  AC = 00  SP = 00 [MB F1 C AC F0 BS]
981 */
982         mcs48_state *cpustate = (mcs48_state *)opaque;
983         UINT8 sp = 8 + 2 * (cpustate->psw & 7);
984         UINT8 prev_sp = 8 + 2 * ((cpustate->psw - 1) & 7);
985         
986         my_stprintf_s(buffer, buffer_len,
987         _T("R0 = %02X  R1 = %02X  R2 = %02X  R3 = %02X (R0)= %02X (R1)= %02X (SP-1)= %04X  PC = %04X\nR4 = %02X  R5 = %02X  R6 = %02X  R7 = %02X  AC = %02X  SP = %02X [%s %s %s %s %s %s]"),
988         reg_r(0), reg_r(1), reg_r(2), reg_r(3), d_mem_stored->read_data8(reg_r(0)), d_mem_stored->read_data8(reg_r(1)),
989         d_mem_stored->read_data8(prev_sp) | (d_mem_stored->read_data8(prev_sp + 1) << 8), cpustate->pc,
990         reg_r(4), reg_r(5), reg_r(6), reg_r(7), cpustate->a, sp,
991         (cpustate->a11 == 0x800) ? _T("MB") : _T("--"), (cpustate->sts & STS_F1) ? _T("F1") : _T("--"),
992         (cpustate->psw & C_FLAG) ? _T("C" ) : _T("-" ), (cpustate->psw & A_FLAG) ? _T("AC") : _T("--"),
993         (cpustate->psw & F_FLAG) ? _T("F0") : _T("--"), (cpustate->psw & B_FLAG) ? _T("BS") : _T("--"));
994 }
995
996 // license:BSD-3-Clause
997 // copyright-holders:Aaron Giles
998 /***************************************************************************
999
1000     mcs48dsm.c
1001
1002     Simple MCS-48/UPI-41 disassembler.
1003     Written by Aaron Giles
1004
1005 ***************************************************************************/
1006
1007 int MCS48::debug_dasm(uint32_t pc, _TCHAR *buffer, size_t buffer_len)
1008 {
1009         mcs48_state *cpustate = (mcs48_state *)opaque;
1010         uint32_t ptr = pc;
1011         
1012         #define upi41 false
1013         
1014         switch (program_r(ptr++))
1015         {
1016                 case 0x00:      my_stprintf_s(buffer, buffer_len, _T("nop"));                                                 break;
1017                 case 0x02:  if (!upi41)
1018                                 my_stprintf_s(buffer, buffer_len, _T("out  bus,a"));
1019                             else
1020                                 my_stprintf_s(buffer, buffer_len, _T("out  dbb,a"));                                          break;
1021                 case 0x03:      my_stprintf_s(buffer, buffer_len, _T("add  a,#$%02X"), program_r(ptr++));                     break;
1022                 case 0x04:      my_stprintf_s(buffer, buffer_len, _T("jmp  $0%02X"), program_r(ptr++));                       break;
1023                 case 0x05:      my_stprintf_s(buffer, buffer_len, _T("en   i"));                                              break;
1024                 case 0x07:      my_stprintf_s(buffer, buffer_len, _T("dec  a"));                                              break;
1025                 case 0x08:  if (!upi41)
1026                                 my_stprintf_s(buffer, buffer_len, _T("in   a,bus"));
1027                             else
1028                                 my_stprintf_s(buffer, buffer_len, _T("illegal"));                                             break;
1029                 case 0x09:      my_stprintf_s(buffer, buffer_len, _T("in   a,p1"));                                           break;
1030                 case 0x0a:      my_stprintf_s(buffer, buffer_len, _T("in   a,p2"));                                           break;
1031                 case 0x0c:      my_stprintf_s(buffer, buffer_len, _T("movd a,p4"));                                           break;
1032                 case 0x0d:      my_stprintf_s(buffer, buffer_len, _T("movd a,p5"));                                           break;
1033                 case 0x0e:      my_stprintf_s(buffer, buffer_len, _T("movd a,p6"));                                           break;
1034                 case 0x0f:      my_stprintf_s(buffer, buffer_len, _T("movd a,p7"));                                           break;
1035                 case 0x10:      my_stprintf_s(buffer, buffer_len, _T("inc  @r0"));                                            break;
1036                 case 0x11:      my_stprintf_s(buffer, buffer_len, _T("inc  @r1"));                                            break;
1037                 case 0x12:      my_stprintf_s(buffer, buffer_len, _T("jb0  $%03X"), (pc & 0xf00) | program_r(ptr++));         break;
1038                 case 0x13:      my_stprintf_s(buffer, buffer_len, _T("addc a,#$%02X"), program_r(ptr++));                     break;
1039                 case 0x14:      my_stprintf_s(buffer, buffer_len, _T("call $0%02X"), program_r(ptr++));                       break;
1040                 case 0x15:      my_stprintf_s(buffer, buffer_len, _T("dis  i"));                                              break;
1041                 case 0x16:      my_stprintf_s(buffer, buffer_len, _T("jtf  $%03X"), (pc & 0xf00) | program_r(ptr++));         break;
1042                 case 0x17:      my_stprintf_s(buffer, buffer_len, _T("inc  a"));                                              break;
1043                 case 0x18:      my_stprintf_s(buffer, buffer_len, _T("inc  r0"));                                             break;
1044                 case 0x19:      my_stprintf_s(buffer, buffer_len, _T("inc  r1"));                                             break;
1045                 case 0x1a:      my_stprintf_s(buffer, buffer_len, _T("inc  r2"));                                             break;
1046                 case 0x1b:      my_stprintf_s(buffer, buffer_len, _T("inc  r3"));                                             break;
1047                 case 0x1c:      my_stprintf_s(buffer, buffer_len, _T("inc  r4"));                                             break;
1048                 case 0x1d:      my_stprintf_s(buffer, buffer_len, _T("inc  r5"));                                             break;
1049                 case 0x1e:      my_stprintf_s(buffer, buffer_len, _T("inc  r6"));                                             break;
1050                 case 0x1f:      my_stprintf_s(buffer, buffer_len, _T("inc  r7"));                                             break;
1051                 case 0x20:      my_stprintf_s(buffer, buffer_len, _T("xch  a,@r0"));                                          break;
1052                 case 0x21:      my_stprintf_s(buffer, buffer_len, _T("xch  a,@r1"));                                          break;
1053                 case 0x22:  if (!upi41)
1054                                 my_stprintf_s(buffer, buffer_len, _T("illegal"));
1055                             else
1056                                 my_stprintf_s(buffer, buffer_len, _T("in   a,dbb"));                                          break;
1057                 case 0x23:      my_stprintf_s(buffer, buffer_len, _T("mov  a,#$%02X"), program_r(ptr++));                     break;
1058                 case 0x24:      my_stprintf_s(buffer, buffer_len, _T("jmp  $1%02X"), program_r(ptr++));                       break;
1059                 case 0x25:      my_stprintf_s(buffer, buffer_len, _T("en   tcnti"));                                          break;
1060                 case 0x26:      my_stprintf_s(buffer, buffer_len, _T("jnt0 $%03X"), (pc & 0xf00) | program_r(ptr++));         break;
1061                 case 0x27:      my_stprintf_s(buffer, buffer_len, _T("clr  a"));                                              break;
1062                 case 0x28:      my_stprintf_s(buffer, buffer_len, _T("xch  a,r0"));                                           break;
1063                 case 0x29:      my_stprintf_s(buffer, buffer_len, _T("xch  a,r1"));                                           break;
1064                 case 0x2a:      my_stprintf_s(buffer, buffer_len, _T("xch  a,r2"));                                           break;
1065                 case 0x2b:      my_stprintf_s(buffer, buffer_len, _T("xch  a,r3"));                                           break;
1066                 case 0x2c:      my_stprintf_s(buffer, buffer_len, _T("xch  a,r4"));                                           break;
1067                 case 0x2d:      my_stprintf_s(buffer, buffer_len, _T("xch  a,r5"));                                           break;
1068                 case 0x2e:      my_stprintf_s(buffer, buffer_len, _T("xch  a,r6"));                                           break;
1069                 case 0x2f:      my_stprintf_s(buffer, buffer_len, _T("xch  a,r7"));                                           break;
1070                 case 0x30:      my_stprintf_s(buffer, buffer_len, _T("xchd a,@r0"));                                          break;
1071                 case 0x31:      my_stprintf_s(buffer, buffer_len, _T("xchd a,@r1"));                                          break;
1072                 case 0x32:      my_stprintf_s(buffer, buffer_len, _T("jb1  $%03X"), (pc & 0xf00) | program_r(ptr++));         break;
1073                 case 0x34:      my_stprintf_s(buffer, buffer_len, _T("call $1%02X"), program_r(ptr++));                       break;
1074                 case 0x35:      my_stprintf_s(buffer, buffer_len, _T("dis  tcnti"));                                          break;
1075                 case 0x36:      my_stprintf_s(buffer, buffer_len, _T("jt0  $%03X"), (pc & 0xf00) | program_r(ptr++));         break;
1076                 case 0x37:      my_stprintf_s(buffer, buffer_len, _T("cpl  a"));                                              break;
1077                 case 0x39:      my_stprintf_s(buffer, buffer_len, _T("outl p1,a"));                                           break;
1078                 case 0x3a:      my_stprintf_s(buffer, buffer_len, _T("outl p2,a"));                                           break;
1079                 case 0x3c:      my_stprintf_s(buffer, buffer_len, _T("movd p4,a"));                                           break;
1080                 case 0x3d:      my_stprintf_s(buffer, buffer_len, _T("movd p5,a"));                                           break;
1081                 case 0x3e:      my_stprintf_s(buffer, buffer_len, _T("movd p6,a"));                                           break;
1082                 case 0x3f:      my_stprintf_s(buffer, buffer_len, _T("movd p7,a"));                                           break;
1083                 case 0x40:      my_stprintf_s(buffer, buffer_len, _T("orl  a,@r0"));                                          break;
1084                 case 0x41:      my_stprintf_s(buffer, buffer_len, _T("orl  a,@r1"));                                          break;
1085                 case 0x42:      my_stprintf_s(buffer, buffer_len, _T("mov  a,t"));                                            break;
1086                 case 0x43:      my_stprintf_s(buffer, buffer_len, _T("orl  a,#$%02X"), program_r(ptr++));                     break;
1087                 case 0x44:      my_stprintf_s(buffer, buffer_len, _T("jmp  $2%02X"), program_r(ptr++));                       break;
1088                 case 0x45:      my_stprintf_s(buffer, buffer_len, _T("strt cnt"));                                            break;
1089                 case 0x46:      my_stprintf_s(buffer, buffer_len, _T("jnt1 $%03X"), (pc & 0xf00) | program_r(ptr++));         break;
1090                 case 0x47:      my_stprintf_s(buffer, buffer_len, _T("swap a"));                                              break;
1091                 case 0x48:      my_stprintf_s(buffer, buffer_len, _T("orl  a,r0"));                                           break;
1092                 case 0x49:      my_stprintf_s(buffer, buffer_len, _T("orl  a,r1"));                                           break;
1093                 case 0x4a:      my_stprintf_s(buffer, buffer_len, _T("orl  a,r2"));                                           break;
1094                 case 0x4b:      my_stprintf_s(buffer, buffer_len, _T("orl  a,r3"));                                           break;
1095                 case 0x4c:      my_stprintf_s(buffer, buffer_len, _T("orl  a,r4"));                                           break;
1096                 case 0x4d:      my_stprintf_s(buffer, buffer_len, _T("orl  a,r5"));                                           break;
1097                 case 0x4e:      my_stprintf_s(buffer, buffer_len, _T("orl  a,r6"));                                           break;
1098                 case 0x4f:      my_stprintf_s(buffer, buffer_len, _T("orl  a,r7"));                                           break;
1099                 case 0x50:      my_stprintf_s(buffer, buffer_len, _T("anl  a,@r0"));                                          break;
1100                 case 0x51:      my_stprintf_s(buffer, buffer_len, _T("anl  a,@r1"));                                          break;
1101                 case 0x52:      my_stprintf_s(buffer, buffer_len, _T("jb2  $%03X"), (pc & 0xf00) | program_r(ptr++));         break;
1102                 case 0x53:      my_stprintf_s(buffer, buffer_len, _T("anl  a,#$%02X"), program_r(ptr++));                     break;
1103                 case 0x54:      my_stprintf_s(buffer, buffer_len, _T("call $2%02X"), program_r(ptr++));                       break;
1104                 case 0x55:      my_stprintf_s(buffer, buffer_len, _T("strt t"));                                              break;
1105                 case 0x56:      my_stprintf_s(buffer, buffer_len, _T("jt1  $%03X"), (pc & 0xf00) | program_r(ptr++));         break;
1106                 case 0x57:      my_stprintf_s(buffer, buffer_len, _T("da   a"));                                              break;
1107                 case 0x58:      my_stprintf_s(buffer, buffer_len, _T("anl  a,r0"));                                           break;
1108                 case 0x59:      my_stprintf_s(buffer, buffer_len, _T("anl  a,r1"));                                           break;
1109                 case 0x5a:      my_stprintf_s(buffer, buffer_len, _T("anl  a,r2"));                                           break;
1110                 case 0x5b:      my_stprintf_s(buffer, buffer_len, _T("anl  a,r3"));                                           break;
1111                 case 0x5c:      my_stprintf_s(buffer, buffer_len, _T("anl  a,r4"));                                           break;
1112                 case 0x5d:      my_stprintf_s(buffer, buffer_len, _T("anl  a,r5"));                                           break;
1113                 case 0x5e:      my_stprintf_s(buffer, buffer_len, _T("anl  a,r6"));                                           break;
1114                 case 0x5f:      my_stprintf_s(buffer, buffer_len, _T("anl  a,r7"));                                           break;
1115                 case 0x60:      my_stprintf_s(buffer, buffer_len, _T("add  a,@r0"));                                          break;
1116                 case 0x61:      my_stprintf_s(buffer, buffer_len, _T("add  a,@r1"));                                          break;
1117                 case 0x62:      my_stprintf_s(buffer, buffer_len, _T("mov  t,a"));                                            break;
1118                 case 0x64:      my_stprintf_s(buffer, buffer_len, _T("jmp  $3%02X"), program_r(ptr++));                       break;
1119                 case 0x65:      my_stprintf_s(buffer, buffer_len, _T("stop tcnt"));                                           break;
1120                 case 0x67:      my_stprintf_s(buffer, buffer_len, _T("rrc  a"));                                              break;
1121                 case 0x68:      my_stprintf_s(buffer, buffer_len, _T("add  a,r0"));                                           break;
1122                 case 0x69:      my_stprintf_s(buffer, buffer_len, _T("add  a,r1"));                                           break;
1123                 case 0x6a:      my_stprintf_s(buffer, buffer_len, _T("add  a,r2"));                                           break;
1124                 case 0x6b:      my_stprintf_s(buffer, buffer_len, _T("add  a,r3"));                                           break;
1125                 case 0x6c:      my_stprintf_s(buffer, buffer_len, _T("add  a,r4"));                                           break;
1126                 case 0x6d:      my_stprintf_s(buffer, buffer_len, _T("add  a,r5"));                                           break;
1127                 case 0x6e:      my_stprintf_s(buffer, buffer_len, _T("add  a,r6"));                                           break;
1128                 case 0x6f:      my_stprintf_s(buffer, buffer_len, _T("add  a,r7"));                                           break;
1129                 case 0x70:      my_stprintf_s(buffer, buffer_len, _T("addc a,@r0"));                                          break;
1130                 case 0x71:      my_stprintf_s(buffer, buffer_len, _T("addc a,@r1"));                                          break;
1131                 case 0x72:      my_stprintf_s(buffer, buffer_len, _T("jb3  $%03X"), (pc & 0xf00) | program_r(ptr++));         break;
1132                 case 0x74:      my_stprintf_s(buffer, buffer_len, _T("call $3%02X"), program_r(ptr++));                       break;
1133                 case 0x75:  if (!upi41)
1134                                 my_stprintf_s(buffer, buffer_len, _T("ent0 clk"));
1135                             else
1136                                 my_stprintf_s(buffer, buffer_len, _T("illegal"));                                             break;
1137                 case 0x76:      my_stprintf_s(buffer, buffer_len, _T("jf1  $%03X"), (pc & 0xf00) | program_r(ptr++));         break;
1138                 case 0x77:      my_stprintf_s(buffer, buffer_len, _T("rr   a"));                                              break;
1139                 case 0x78:      my_stprintf_s(buffer, buffer_len, _T("addc a,r0"));                                           break;
1140                 case 0x79:      my_stprintf_s(buffer, buffer_len, _T("addc a,r1"));                                           break;
1141                 case 0x7a:      my_stprintf_s(buffer, buffer_len, _T("addc a,r2"));                                           break;
1142                 case 0x7b:      my_stprintf_s(buffer, buffer_len, _T("addc a,r3"));                                           break;
1143                 case 0x7c:      my_stprintf_s(buffer, buffer_len, _T("addc a,r4"));                                           break;
1144                 case 0x7d:      my_stprintf_s(buffer, buffer_len, _T("addc a,r5"));                                           break;
1145                 case 0x7e:      my_stprintf_s(buffer, buffer_len, _T("addc a,r6"));                                           break;
1146                 case 0x7f:      my_stprintf_s(buffer, buffer_len, _T("addc a,r7"));                                           break;
1147                 case 0x80:  if (!upi41)
1148                                 my_stprintf_s(buffer, buffer_len, _T("movx a,@r0"));
1149                             else
1150                                 my_stprintf_s(buffer, buffer_len, _T("illegal"));                                             break;
1151                 case 0x81:  if (!upi41)
1152                                 my_stprintf_s(buffer, buffer_len, _T("movx a,@r1"));
1153                             else
1154                                 my_stprintf_s(buffer, buffer_len, _T("illegal"));                                             break;
1155                 case 0x83:      my_stprintf_s(buffer, buffer_len, _T("ret"));                                                 break;
1156                 case 0x84:      my_stprintf_s(buffer, buffer_len, _T("jmp  $4%02X"), program_r(ptr++));                       break;
1157                 case 0x85:      my_stprintf_s(buffer, buffer_len, _T("clr  f0"));                                             break;
1158                 case 0x86:  if (!upi41)
1159                                 my_stprintf_s(buffer, buffer_len, _T("jni  $%03X"), (pc & 0xf00) | program_r(ptr++));
1160                             else
1161                                 my_stprintf_s(buffer, buffer_len, _T("jobf $%03X"), (pc & 0xf00) | program_r(ptr++));         break;
1162                 case 0x88:  if (!upi41)
1163                                 my_stprintf_s(buffer, buffer_len, _T("orl  bus,#$%02X"), program_r(ptr++));
1164                             else
1165                                 my_stprintf_s(buffer, buffer_len, _T("illegal"));                                             break;
1166                 case 0x89:      my_stprintf_s(buffer, buffer_len, _T("orl  p1,#$%02X"), program_r(ptr++));                    break;
1167                 case 0x8a:      my_stprintf_s(buffer, buffer_len, _T("orl  p2,#$%02X"), program_r(ptr++));                    break;
1168                 case 0x8c:      my_stprintf_s(buffer, buffer_len, _T("orld p4,a"));                                           break;
1169                 case 0x8d:      my_stprintf_s(buffer, buffer_len, _T("orld p5,a"));                                           break;
1170                 case 0x8e:      my_stprintf_s(buffer, buffer_len, _T("orld p6,a"));                                           break;
1171                 case 0x8f:      my_stprintf_s(buffer, buffer_len, _T("orld p7,a"));                                           break;
1172                 case 0x90:  if (!upi41)
1173                                 my_stprintf_s(buffer, buffer_len, _T("movx @r0,a"));
1174                             else
1175                                 my_stprintf_s(buffer, buffer_len, _T("mov  sts,a"));                                          break;
1176                 case 0x91:  if (!upi41)
1177                                 my_stprintf_s(buffer, buffer_len, _T("movx @r1,a"));
1178                             else
1179                                 my_stprintf_s(buffer, buffer_len, _T("illegal"));                                             break;
1180                 case 0x92:      my_stprintf_s(buffer, buffer_len, _T("jb4  $%03X"), (pc & 0xf00) | program_r(ptr++));         break;
1181                 case 0x93:      my_stprintf_s(buffer, buffer_len, _T("retr"));                                                break;
1182                 case 0x94:      my_stprintf_s(buffer, buffer_len, _T("call $4%02X"), program_r(ptr++));                       break;
1183                 case 0x95:      my_stprintf_s(buffer, buffer_len, _T("cpl  f0"));                                             break;
1184                 case 0x96:      my_stprintf_s(buffer, buffer_len, _T("jnz  $%03X"), (pc & 0xf00) | program_r(ptr++));         break;
1185                 case 0x97:      my_stprintf_s(buffer, buffer_len, _T("clr  c"));                                              break;
1186                 case 0x98:  if (!upi41)
1187                                 my_stprintf_s(buffer, buffer_len, _T("anl  bus,#$%02X"), program_r(ptr++));
1188                             else
1189                                 my_stprintf_s(buffer, buffer_len, _T("illegal"));                                             break;
1190                 case 0x99:      my_stprintf_s(buffer, buffer_len, _T("anl  p1,#$%02X"), program_r(ptr++));                    break;
1191                 case 0x9a:      my_stprintf_s(buffer, buffer_len, _T("anl  p2,#$%02X"), program_r(ptr++));                    break;
1192                 case 0x9c:      my_stprintf_s(buffer, buffer_len, _T("anld p4,a"));                                           break;
1193                 case 0x9d:      my_stprintf_s(buffer, buffer_len, _T("anld p5,a"));                                           break;
1194                 case 0x9e:      my_stprintf_s(buffer, buffer_len, _T("anld p6,a"));                                           break;
1195                 case 0x9f:      my_stprintf_s(buffer, buffer_len, _T("anld p7,a"));                                           break;
1196                 case 0xa0:      my_stprintf_s(buffer, buffer_len, _T("mov  @r0,a"));                                          break;
1197                 case 0xa1:      my_stprintf_s(buffer, buffer_len, _T("mov  @r1,a"));                                          break;
1198                 case 0xa3:      my_stprintf_s(buffer, buffer_len, _T("movp a,@a"));                                           break;
1199                 case 0xa4:      my_stprintf_s(buffer, buffer_len, _T("jmp  $5%02X"), program_r(ptr++));                       break;
1200                 case 0xa5:      my_stprintf_s(buffer, buffer_len, _T("clr  f1"));                                             break;
1201                 case 0xa7:      my_stprintf_s(buffer, buffer_len, _T("cpl  c"));                                              break;
1202                 case 0xa8:      my_stprintf_s(buffer, buffer_len, _T("mov  r0,a"));                                           break;
1203                 case 0xa9:      my_stprintf_s(buffer, buffer_len, _T("mov  r1,a"));                                           break;
1204                 case 0xaa:      my_stprintf_s(buffer, buffer_len, _T("mov  r2,a"));                                           break;
1205                 case 0xab:      my_stprintf_s(buffer, buffer_len, _T("mov  r3,a"));                                           break;
1206                 case 0xac:      my_stprintf_s(buffer, buffer_len, _T("mov  r4,a"));                                           break;
1207                 case 0xad:      my_stprintf_s(buffer, buffer_len, _T("mov  r5,a"));                                           break;
1208                 case 0xae:      my_stprintf_s(buffer, buffer_len, _T("mov  r6,a"));                                           break;
1209                 case 0xaf:      my_stprintf_s(buffer, buffer_len, _T("mov  r7,a"));                                           break;
1210                 case 0xb0:      my_stprintf_s(buffer, buffer_len, _T("mov  @r0,#$%02X"), program_r(ptr++));                   break;
1211                 case 0xb1:      my_stprintf_s(buffer, buffer_len, _T("mov  @r1,#$%02X"), program_r(ptr++));                   break;
1212                 case 0xb2:      my_stprintf_s(buffer, buffer_len, _T("jb5  $%03X"), (pc & 0xf00) | program_r(ptr++));         break;
1213                 case 0xb3:      my_stprintf_s(buffer, buffer_len, _T("jmpp @a"));                                             break;
1214                 case 0xb4:      my_stprintf_s(buffer, buffer_len, _T("call $5%02X"), program_r(ptr++));                       break;
1215                 case 0xb5:      my_stprintf_s(buffer, buffer_len, _T("cpl  f1"));                                             break;
1216                 case 0xb6:      my_stprintf_s(buffer, buffer_len, _T("jf0  $%03X"), (pc & 0xf00) | program_r(ptr++));         break;
1217                 case 0xb8:      my_stprintf_s(buffer, buffer_len, _T("mov  r0,#$%02X"), program_r(ptr++));                    break;
1218                 case 0xb9:      my_stprintf_s(buffer, buffer_len, _T("mov  r1,#$%02X"), program_r(ptr++));                    break;
1219                 case 0xba:      my_stprintf_s(buffer, buffer_len, _T("mov  r2,#$%02X"), program_r(ptr++));                    break;
1220                 case 0xbb:      my_stprintf_s(buffer, buffer_len, _T("mov  r3,#$%02X"), program_r(ptr++));                    break;
1221                 case 0xbc:      my_stprintf_s(buffer, buffer_len, _T("mov  r4,#$%02X"), program_r(ptr++));                    break;
1222                 case 0xbd:      my_stprintf_s(buffer, buffer_len, _T("mov  r5,#$%02X"), program_r(ptr++));                    break;
1223                 case 0xbe:      my_stprintf_s(buffer, buffer_len, _T("mov  r6,#$%02X"), program_r(ptr++));                    break;
1224                 case 0xbf:      my_stprintf_s(buffer, buffer_len, _T("mov  r7,#$%02X"), program_r(ptr++));                    break;
1225                 case 0xc4:      my_stprintf_s(buffer, buffer_len, _T("jmp  $6%02X"), program_r(ptr++));                       break;
1226                 case 0xc5:      my_stprintf_s(buffer, buffer_len, _T("sel  rb0"));                                            break;
1227                 case 0xc6:      my_stprintf_s(buffer, buffer_len, _T("jz   $%03X"), (pc & 0xf00) | program_r(ptr++));         break;
1228                 case 0xc7:      my_stprintf_s(buffer, buffer_len, _T("mov  a,psw"));                                          break;
1229                 case 0xc8:      my_stprintf_s(buffer, buffer_len, _T("dec  r0"));                                             break;
1230                 case 0xc9:      my_stprintf_s(buffer, buffer_len, _T("dec  r1"));                                             break;
1231                 case 0xca:      my_stprintf_s(buffer, buffer_len, _T("dec  r2"));                                             break;
1232                 case 0xcb:      my_stprintf_s(buffer, buffer_len, _T("dec  r3"));                                             break;
1233                 case 0xcc:      my_stprintf_s(buffer, buffer_len, _T("dec  r4"));                                             break;
1234                 case 0xcd:      my_stprintf_s(buffer, buffer_len, _T("dec  r5"));                                             break;
1235                 case 0xce:      my_stprintf_s(buffer, buffer_len, _T("dec  r6"));                                             break;
1236                 case 0xcf:      my_stprintf_s(buffer, buffer_len, _T("dec  r7"));                                             break;
1237                 case 0xd0:      my_stprintf_s(buffer, buffer_len, _T("xrl  a,@r0"));                                          break;
1238                 case 0xd1:      my_stprintf_s(buffer, buffer_len, _T("xrl  a,@r1"));                                          break;
1239                 case 0xd2:      my_stprintf_s(buffer, buffer_len, _T("jb6  $%03X"), (pc & 0xf00) | program_r(ptr++));         break;
1240                 case 0xd3:      my_stprintf_s(buffer, buffer_len, _T("xrl  a,#$%02X"), program_r(ptr++));                     break;
1241                 case 0xd4:      my_stprintf_s(buffer, buffer_len, _T("call $6%02X"), program_r(ptr++));                       break;
1242                 case 0xd5:      my_stprintf_s(buffer, buffer_len, _T("sel  rb1"));                                            break;
1243                 case 0xd6:  if (!upi41)
1244                                 my_stprintf_s(buffer, buffer_len, _T("illegal"));
1245                             else
1246                                 my_stprintf_s(buffer, buffer_len, _T("jnibf $%03X"), (pc & 0xf00) | program_r(ptr++));        break;
1247                 case 0xd7:      my_stprintf_s(buffer, buffer_len, _T("mov  psw,a"));                                          break;
1248                 case 0xd8:      my_stprintf_s(buffer, buffer_len, _T("xrl  a,r0"));                                           break;
1249                 case 0xd9:      my_stprintf_s(buffer, buffer_len, _T("xrl  a,r1"));                                           break;
1250                 case 0xda:      my_stprintf_s(buffer, buffer_len, _T("xrl  a,r2"));                                           break;
1251                 case 0xdb:      my_stprintf_s(buffer, buffer_len, _T("xrl  a,r3"));                                           break;
1252                 case 0xdc:      my_stprintf_s(buffer, buffer_len, _T("xrl  a,r4"));                                           break;
1253                 case 0xdd:      my_stprintf_s(buffer, buffer_len, _T("xrl  a,r5"));                                           break;
1254                 case 0xde:      my_stprintf_s(buffer, buffer_len, _T("xrl  a,r6"));                                           break;
1255                 case 0xdf:      my_stprintf_s(buffer, buffer_len, _T("xrl  a,r7"));                                           break;
1256                 case 0xe3:      my_stprintf_s(buffer, buffer_len, _T("movp3 a,@a"));                                          break;
1257                 case 0xe4:      my_stprintf_s(buffer, buffer_len, _T("jmp  $7%02X"), program_r(ptr++));                       break;
1258                 case 0xe5:  if (!upi41)
1259                                 my_stprintf_s(buffer, buffer_len, _T("sel  mb0"));
1260                             else
1261                                 my_stprintf_s(buffer, buffer_len, _T("en   dma"));                                            break;
1262                 case 0xe6:      my_stprintf_s(buffer, buffer_len, _T("jnc  $%03X"), (pc & 0xf00) | program_r(ptr++));         break;
1263                 case 0xe7:      my_stprintf_s(buffer, buffer_len, _T("rl   a"));                                              break;
1264                 case 0xe8:      my_stprintf_s(buffer, buffer_len, _T("djnz r0,$%03X"), (pc & 0xf00) | program_r(ptr++));      break;
1265                 case 0xe9:      my_stprintf_s(buffer, buffer_len, _T("djnz r1,$%03X"), (pc & 0xf00) | program_r(ptr++));      break;
1266                 case 0xea:      my_stprintf_s(buffer, buffer_len, _T("djnz r2,$%03X"), (pc & 0xf00) | program_r(ptr++));      break;
1267                 case 0xeb:      my_stprintf_s(buffer, buffer_len, _T("djnz r3,$%03X"), (pc & 0xf00) | program_r(ptr++));      break;
1268                 case 0xec:      my_stprintf_s(buffer, buffer_len, _T("djnz r4,$%03X"), (pc & 0xf00) | program_r(ptr++));      break;
1269                 case 0xed:      my_stprintf_s(buffer, buffer_len, _T("djnz r5,$%03X"), (pc & 0xf00) | program_r(ptr++));      break;
1270                 case 0xee:      my_stprintf_s(buffer, buffer_len, _T("djnz r6,$%03X"), (pc & 0xf00) | program_r(ptr++));      break;
1271                 case 0xef:      my_stprintf_s(buffer, buffer_len, _T("djnz r7,$%03X"), (pc & 0xf00) | program_r(ptr++));      break;
1272                 case 0xf0:      my_stprintf_s(buffer, buffer_len, _T("mov  a,@r0"));                                          break;
1273                 case 0xf1:      my_stprintf_s(buffer, buffer_len, _T("mov  a,@r1"));                                          break;
1274                 case 0xf2:      my_stprintf_s(buffer, buffer_len, _T("jb7  $%03X"), (pc & 0xf00) | program_r(ptr++));         break;
1275                 case 0xf4:      my_stprintf_s(buffer, buffer_len, _T("call $7%02X"), program_r(ptr++));                       break;
1276                 case 0xf5:  if (!upi41)
1277                                 my_stprintf_s(buffer, buffer_len, _T("sel  mb1"));
1278                             else
1279                                 my_stprintf_s(buffer, buffer_len, _T("en   flags"));                                          break;
1280                 case 0xf6:      my_stprintf_s(buffer, buffer_len, _T("jc   $%03X"), (pc & 0xf00) | program_r(ptr++));         break;
1281                 case 0xf7:      my_stprintf_s(buffer, buffer_len, _T("rlc  a"));                                              break;
1282                 case 0xf8:      my_stprintf_s(buffer, buffer_len, _T("mov  a,r0"));                                           break;
1283                 case 0xf9:      my_stprintf_s(buffer, buffer_len, _T("mov  a,r1"));                                           break;
1284                 case 0xfa:      my_stprintf_s(buffer, buffer_len, _T("mov  a,r2"));                                           break;
1285                 case 0xfb:      my_stprintf_s(buffer, buffer_len, _T("mov  a,r3"));                                           break;
1286                 case 0xfc:      my_stprintf_s(buffer, buffer_len, _T("mov  a,r4"));                                           break;
1287                 case 0xfd:      my_stprintf_s(buffer, buffer_len, _T("mov  a,r5"));                                           break;
1288                 case 0xfe:      my_stprintf_s(buffer, buffer_len, _T("mov  a,r6"));                                           break;
1289                 case 0xff:      my_stprintf_s(buffer, buffer_len, _T("mov  a,r7"));                                           break;
1290                 default:        my_stprintf_s(buffer, buffer_len, _T("illegal"));                                             break;
1291         }
1292         return ptr - pc;
1293 }
1294 #endif
1295
1296 #define STATE_VERSION   1
1297
1298 void MCS48MEM::save_state(FILEIO* state_fio)
1299 {
1300         state_fio->FputUint32(STATE_VERSION);
1301         state_fio->FputInt32(this_device_id);
1302         
1303         state_fio->Fwrite(ram, sizeof(ram), 1);
1304 }
1305
1306 bool MCS48MEM::load_state(FILEIO* state_fio)
1307 {
1308         if(state_fio->FgetUint32() != STATE_VERSION) {
1309                 return false;
1310         }
1311         if(state_fio->FgetInt32() != this_device_id) {
1312                 return false;
1313         }
1314         state_fio->Fread(ram, sizeof(ram), 1);
1315         return true;
1316 }
1317
1318 void MCS48::save_state(FILEIO* state_fio)
1319 {
1320         state_fio->FputUint32(STATE_VERSION);
1321         state_fio->FputInt32(this_device_id);
1322         
1323         state_fio->Fwrite(opaque, sizeof(mcs48_state), 1);
1324 }
1325
1326 bool MCS48::load_state(FILEIO* state_fio)
1327 {
1328         if(state_fio->FgetUint32() != STATE_VERSION) {
1329                 return false;
1330         }
1331         if(state_fio->FgetInt32() != this_device_id) {
1332                 return false;
1333         }
1334         state_fio->Fread(opaque, sizeof(mcs48_state), 1);
1335         
1336         // post process
1337         mcs48_state *cpustate = (mcs48_state *)opaque;
1338         cpustate->mem = d_mem;
1339         cpustate->io = d_io;
1340         cpustate->intr = d_intr;
1341         return true;
1342 }
1343