OpenCores
URL https://opencores.org/ocsvn/t48/t48/trunk

Subversion Repositories t48

[/] [t48/] [tags/] [rel_1_0/] [sw/] [i8039emu/] [i8039.c] - Blame information for rev 88

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 49 arniml
/****************************************************************************
2
 *                      Intel 8039 Portable Emulator                        *
3
 *                                                                          *
4
 *                   Copyright (C) 1997 by Mirko Buffoni                    *
5
 *  Based on the original work (C) 1997 by Dan Boris, an 8048 emulator      *
6
 *      You are not allowed to distribute this software commercially        *
7
 *        Please, notify me, if you make any changes to this file           *
8
 *                                                                          *
9
 *    Adapted for the T48 uController project, 2004 by Arnim Laeuger        *
10
 *      See http://www.opencores.org/projects.cgi/web/t48/overview          *
11
 *                                                                          *
12 88 arniml
 * $Id: i8039.c,v 1.5 2004-05-01 17:20:42 arniml Exp $
13 49 arniml
 *                                                                          *
14
 *  **** Change Log ****                                                    *
15
 *                                                                          *
16
 *  TLP (19-Jun-2001)                                                       *
17
 *   - Changed Ports 1 and 2 to quasi bidirectional output latched ports    *
18
 *   - Added the Port 1 & 2 output latch data to the debugger window        *
19
 *  TLP (02-Jan-2002)                                                       *
20
 *   - External IRQs no longer go pending (sampled as a level state)        *
21
 *   - Timer IRQs do not go pending if Timer interrupts are disabled        *
22
 *   - Timer IRQs made pending, were incorrectly being cleared if the       *
23
 *      external interrupt was being serviced                               *
24
 *   - External interrupts now take precedence when simultaneous            *
25
 *      internal and external interrupt requests occur                      *
26
 *   - 'DIS TCNTI' now removes pending timer IRQs                           *
27
 *   - Nested IRQs of any sort are no longer allowed                        *
28
 *   - T_flag was not being set in the right place of execution, which      *
29
 *      could have lead to it being incorrectly set after being cleared     *
30
 *   - Counter overflows now also set the T_flag                            *
31
 *   - Added the Timer/Counter register to the debugger window              *
32
 *  TLP (09-Jan-2002)                                                       *
33
 *   - Changed Interrupt system to instant servicing                        *
34
 *   - The Timer and Counter can no longer be 'on' simultaneously           *
35
 *   - Added Save State                                                     *
36
 *  TLP (15-Feb-2002)                                                       *
37
 *   - Corrected Positive signal edge sensing (used on the T1 input)        *
38
 ****************************************************************************/
39
 
40
 
41
#include <stdio.h>
42
#include <string.h>
43
#include <stdlib.h>
44
 
45
#include "i8039.h"
46
 
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
 
61
 
62
/* HJB 01/05/99 changed to positive values to use pending_irq as a flag */
63
#define I8039_NO_INT        0   /* No Interrupts pending or executing   */
64
#define I8039_EXTERNAL_INT  1   /* Execute a normal external interrupt  */
65
#define I8039_TIMCNT_INT    2   /* Execute a Timer/Counter interrupt    */
66
 
67
 
68
/* Layout of the registers in the debugger */
69
static UINT8 i8039_reg_layout[] = {
70
    I8039_PC, I8039_SP, I8039_PSW, I8039_A, I8039_TC, I8039_P1, I8039_P2, -1,
71
    I8039_R0, I8039_R1, I8039_R2, I8039_R3, I8039_R4, I8039_R5, I8039_R6, I8039_R7, 0
72
};
73
 
74
/* Layout of the debugger windows x,y,w,h */
75
static UINT8 i8039_win_layout[] = {
76
     0, 0,80, 2,    /* register window (top rows) */
77
     0, 3,24,19,    /* disassembler window (left colums) */
78
    25, 3,55, 9,    /* memory #1 window (right, upper middle) */
79
    25,13,55, 9,    /* memory #2 window (right, lower middle) */
80
     0,23,80, 1,    /* command line window (bottom rows) */
81
};
82
 
83
 
84
static int Ext_IRQ(void);
85
static int Timer_IRQ(void);
86
 
87
#define M_RDMEM(A)      I8039_RDMEM(A)
88
#define M_RDOP(A)       I8039_RDOP(A)
89
#define M_RDOP_ARG(A)   I8039_RDOP_ARG(A)
90
#define M_IN(A)         I8039_In(A)
91
#define M_OUT(A,V)      I8039_Out(A,V)
92
 
93
#define port_r(A)       I8039_In(I8039_p0 + A)
94
#define port_w(A,V)     I8039_Out(I8039_p0 + A,V)
95
#define test_r(A)       I8039_In(I8039_t0 + A)
96
#define test_w(A,V)     I8039_Out(I8039_t0 + A,V)
97
#define bus_r()         I8039_In(I8039_bus)
98
#define bus_w(V)        I8039_Out(I8039_bus,V)
99
 
100
#define C_FLAG          0x80
101
#define A_FLAG          0x40
102
#define F_FLAG          0x20
103
#define B_FLAG          0x10
104
 
105
typedef struct
106
{
107
    PAIR    PREVPC;         /* previous program counter */
108
    PAIR    PC;             /* program counter */
109
    UINT8   A, SP, PSW;
110
    UINT8   RAM[256];
111
    UINT8   bus, f1;        /* Bus data, and flag1 */
112
    UINT8   P1, P2;         /* Internal Port 1 and 2 latched outputs */
113
 
114
    UINT8   pending_irq, irq_executing, masterClock, regPtr;
115
    UINT8   t_flag, timer, timerON, countON, xirq_en, tirq_en;
116
    UINT16  A11, A11ff;
117
    UINT8   irq_state, irq_extra_cycles;
118
    int     (*irq_callback)(int irqline);
119
} I8039_Regs;
120
 
121
static I8039_Regs R;
122
int    i8039_ICount;
123
int    inst_cycles;
124
static UINT8 Old_T1;
125
 
126
/* The opcode table now is a combination of cycle counts and function pointers */
127
typedef struct {
128
    unsigned cycles;
129
    void (*function) (void);
130
}   s_opcode;
131
 
132
#define POSITIVE_EDGE_T1  (( (int)(T1-Old_T1) > 0) ? 1 : 0)
133
#define NEGATIVE_EDGE_T1  (( (int)(Old_T1-T1) > 0) ? 1 : 0)
134
 
135
#define M_Cy    ((R.PSW & C_FLAG) >> 7)
136
#define M_Cn    (!M_Cy)
137
#define M_Ay    ((R.PSW & A_FLAG))
138
#define M_An    (!M_Ay)
139
#define M_F0y   ((R.PSW & F_FLAG))
140
#define M_F0n   (!M_F0y)
141
#define M_By    ((R.PSW & B_FLAG))
142
#define M_Bn    (!M_By)
143
 
144
#define intRAM  R.RAM
145
#define regPTR  R.regPtr
146
 
147
#define R0  intRAM[regPTR  ]
148
#define R1  intRAM[regPTR+1]
149
#define R2  intRAM[regPTR+2]
150
#define R3  intRAM[regPTR+3]
151
#define R4  intRAM[regPTR+4]
152
#define R5  intRAM[regPTR+5]
153
#define R6  intRAM[regPTR+6]
154
#define R7  intRAM[regPTR+7]
155
 
156
 
157
INLINE void CLR (UINT8 flag) { R.PSW &= ~flag; }
158
INLINE void SET (UINT8 flag) { R.PSW |= flag;  }
159
 
160
 
161
/* Get next opcode argument and increment program counter */
162
INLINE unsigned M_RDMEM_OPCODE (void)
163
{
164
    unsigned retval;
165
    retval=M_RDOP_ARG(R.PC.w.l);
166
    R.PC.w.l++;
167
    return retval;
168
}
169
 
170
INLINE void push(UINT8 d)
171
{
172
    intRAM[8+R.SP++] = d;
173
    R.SP  = R.SP & 0x0f;
174
    R.PSW = R.PSW & 0xf8;
175
    R.PSW = R.PSW | (R.SP >> 1);
176
}
177
 
178
INLINE UINT8 pull(void) {
179
    R.SP  = (R.SP + 15) & 0x0f;     /*  if (--R.SP < 0) R.SP = 15;  */
180
    R.PSW = R.PSW & 0xf8;
181
    R.PSW = R.PSW | (R.SP >> 1);
182
    /* regPTR = ((M_By) ? 24 : 0);  regPTR should not change */
183
    return intRAM[8+R.SP];
184
}
185
 
186
INLINE void daa_a(void)
187
{
188
    if ((R.A & 0x0f) > 0x09 || (R.PSW & A_FLAG))
189
        R.A += 0x06;
190
    if ((R.A & 0xf0) > 0x90 || (R.PSW & C_FLAG))
191
    {
192
        R.A += 0x60;
193
        SET(C_FLAG);
194
    } else CLR(C_FLAG);
195
}
196
 
197
INLINE void M_ADD(UINT8 dat)
198
{
199
    UINT16 temp;
200
 
201
    CLR(C_FLAG | A_FLAG);
202
    if ((R.A & 0xf) + (dat & 0xf) > 0xf) SET(A_FLAG);
203
    temp = R.A + dat;
204
    if (temp > 0xff) SET(C_FLAG);
205
    R.A  = temp & 0xff;
206
}
207
 
208
INLINE void M_ADDC(UINT8 dat)
209
{
210
    UINT16 temp;
211
 
212
    CLR(A_FLAG);
213
    if ((R.A & 0xf) + (dat & 0xf) + M_Cy > 0xf) SET(A_FLAG);
214
    temp = R.A + dat + M_Cy;
215
    CLR(C_FLAG);
216
    if (temp > 0xff) SET(C_FLAG);
217
    R.A  = temp & 0xff;
218
}
219
 
220
INLINE void M_CALL(UINT16 addr)
221
{
222
    push(R.PC.b.l);
223
    push((R.PC.b.h & 0x0f) | (R.PSW & 0xf0));
224
    R.PC.w.l = addr;
225
 
226
}
227
 
228
INLINE void M_XCHD(UINT8 addr)
229
{
230
    UINT8 dat = R.A & 0x0f;
231
    R.A &= 0xf0;
232
    R.A |= intRAM[addr] & 0x0f;
233
    intRAM[addr] &= 0xf0;
234
    intRAM[addr] |= dat;
235
}
236
 
237
 
238
INLINE void M_ILLEGAL(void)
239
{
240
    logerror("I8039:  PC = %04x,  Illegal opcode = %02x\n", R.PC.w.l-1, M_RDMEM(R.PC.w.l-1));
241
}
242
 
243
INLINE void M_UNDEFINED(void)
244
{
245
    logerror("I8039:  PC = %04x,  Unimplemented opcode = %02x\n", R.PC.w.l-1, M_RDMEM(R.PC.w.l-1));
246
}
247
 
248
#define INT_RAM_MASK 0xff
249
 
250
static void illegal(void)    { M_ILLEGAL(); }
251
 
252
static void add_a_n(void)    { M_ADD(M_RDMEM_OPCODE()); }
253
static void add_a_r0(void)   { M_ADD(R0); }
254
static void add_a_r1(void)   { M_ADD(R1); }
255
static void add_a_r2(void)   { M_ADD(R2); }
256
static void add_a_r3(void)   { M_ADD(R3); }
257
static void add_a_r4(void)   { M_ADD(R4); }
258
static void add_a_r5(void)   { M_ADD(R5); }
259
static void add_a_r6(void)   { M_ADD(R6); }
260
static void add_a_r7(void)   { M_ADD(R7); }
261
static void add_a_xr0(void)  { M_ADD(intRAM[R0 & INT_RAM_MASK]); }
262
static void add_a_xr1(void)  { M_ADD(intRAM[R1 & INT_RAM_MASK]); }
263
static void adc_a_n(void)    { M_ADDC(M_RDMEM_OPCODE()); }
264
static void adc_a_r0(void)   { M_ADDC(R0); }
265
static void adc_a_r1(void)   { M_ADDC(R1); }
266
static void adc_a_r2(void)   { M_ADDC(R2); }
267
static void adc_a_r3(void)   { M_ADDC(R3); }
268
static void adc_a_r4(void)   { M_ADDC(R4); }
269
static void adc_a_r5(void)   { M_ADDC(R5); }
270
static void adc_a_r6(void)   { M_ADDC(R6); }
271
static void adc_a_r7(void)   { M_ADDC(R7); }
272
static void adc_a_xr0(void)  { M_ADDC(intRAM[R0 & INT_RAM_MASK]); }
273
static void adc_a_xr1(void)  { M_ADDC(intRAM[R1 & INT_RAM_MASK]); }
274
static void anl_a_n(void)    { R.A &= M_RDMEM_OPCODE(); }
275
static void anl_a_r0(void)   { R.A &= R0; }
276
static void anl_a_r1(void)   { R.A &= R1; }
277
static void anl_a_r2(void)   { R.A &= R2; }
278
static void anl_a_r3(void)   { R.A &= R3; }
279
static void anl_a_r4(void)   { R.A &= R4; }
280
static void anl_a_r5(void)   { R.A &= R5; }
281
static void anl_a_r6(void)   { R.A &= R6; }
282
static void anl_a_r7(void)   { R.A &= R7; }
283
static void anl_a_xr0(void)  { R.A &= intRAM[R0 & INT_RAM_MASK]; }
284
static void anl_a_xr1(void)  { R.A &= intRAM[R1 & INT_RAM_MASK]; }
285
static void anl_bus_n(void)  { bus_w( bus_r() & M_RDMEM_OPCODE() ); }
286
static void anl_p1_n(void)   { R.P1 &= M_RDMEM_OPCODE(); port_w( 1, R.P1 ); }
287
static void anl_p2_n(void)   { R.P2 &= M_RDMEM_OPCODE(); port_w( 2, R.P2 ); }
288
static void anld_p4_a(void)  { port_w( 4, port_r(4) & M_RDMEM_OPCODE() ); }
289
static void anld_p5_a(void)  { port_w( 5, port_r(5) & M_RDMEM_OPCODE() ); }
290
static void anld_p6_a(void)  { port_w( 6, port_r(6) & M_RDMEM_OPCODE() ); }
291
static void anld_p7_a(void)  { port_w( 7, port_r(7) & M_RDMEM_OPCODE() ); }
292
static void call(void)       { UINT8 i=M_RDMEM_OPCODE(); M_CALL(i | R.A11); }
293
static void call_1(void)     { UINT8 i=M_RDMEM_OPCODE(); M_CALL(i | 0x100 | R.A11); }
294
static void call_2(void)     { UINT8 i=M_RDMEM_OPCODE(); M_CALL(i | 0x200 | R.A11); }
295
static void call_3(void)     { UINT8 i=M_RDMEM_OPCODE(); M_CALL(i | 0x300 | R.A11); }
296
static void call_4(void)     { UINT8 i=M_RDMEM_OPCODE(); M_CALL(i | 0x400 | R.A11); }
297
static void call_5(void)     { UINT8 i=M_RDMEM_OPCODE(); M_CALL(i | 0x500 | R.A11); }
298
static void call_6(void)     { UINT8 i=M_RDMEM_OPCODE(); M_CALL(i | 0x600 | R.A11); }
299
static void call_7(void)     { UINT8 i=M_RDMEM_OPCODE(); M_CALL(i | 0x700 | R.A11); }
300
static void clr_a(void)      { R.A=0; }
301
static void clr_c(void)      { CLR(C_FLAG); }
302
static void clr_f0(void)     { CLR(F_FLAG); }
303
static void clr_f1(void)     { R.f1 = 0; }
304
static void cpl_a(void)      { R.A ^= 0xff; }
305
static void cpl_c(void)      { R.PSW ^= C_FLAG; }
306
static void cpl_f0(void)     { R.PSW ^= F_FLAG; }
307
static void cpl_f1(void)     { R.f1 ^= 1; }
308
static void dec_a(void)      { R.A--; }
309
static void dec_r0(void)     { R0--; }
310
static void dec_r1(void)     { R1--; }
311
static void dec_r2(void)     { R2--; }
312
static void dec_r3(void)     { R3--; }
313
static void dec_r4(void)     { R4--; }
314
static void dec_r5(void)     { R5--; }
315
static void dec_r6(void)     { R6--; }
316
static void dec_r7(void)     { R7--; }
317
static void dis_i(void)      { R.xirq_en = 0; }
318
static void dis_tcnti(void)  { R.tirq_en = 0; R.pending_irq &= ~I8039_TIMCNT_INT; }
319
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; } else ADJUST_CYCLES }
320
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; } else ADJUST_CYCLES }
321
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; } else ADJUST_CYCLES }
322
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; } else ADJUST_CYCLES }
323
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; } else ADJUST_CYCLES }
324
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; } else ADJUST_CYCLES }
325
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; } else ADJUST_CYCLES }
326
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; } else ADJUST_CYCLES }
327
static void en_i(void)       { R.xirq_en = 1; if (R.irq_state == I8039_EXTERNAL_INT) { R.irq_extra_cycles += Ext_IRQ(); } }
328
static void en_tcnti(void)   { R.tirq_en = 1; }
329
static void ento_clk(void)   { M_UNDEFINED(); }
330
static void in_a_p1(void)    { R.A = port_r(1) & R.P1; }
331
static void in_a_p2(void)    { R.A = port_r(2) & R.P2; }
332
static void ins_a_bus(void)  { R.A = bus_r(); }
333
static void inc_a(void)      { R.A++; }
334
static void inc_r0(void)     { R0++; }
335
static void inc_r1(void)     { R1++; }
336
static void inc_r2(void)     { R2++; }
337
static void inc_r3(void)     { R3++; }
338
static void inc_r4(void)     { R4++; }
339
static void inc_r5(void)     { R5++; }
340
static void inc_r6(void)     { R6++; }
341
static void inc_r7(void)     { R7++; }
342
static void inc_xr0(void)    { intRAM[R0 & INT_RAM_MASK]++; }
343
static void inc_xr1(void)    { intRAM[R1 & INT_RAM_MASK]++; }
344
 
345
/* static void jmp(void)     { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | R.A11; }
346
 */
347
 
348
static void jmp(void)
349
{
350
    UINT8 i=M_RDOP(R.PC.w.l);
351
    UINT16 oldpc,newpc;
352
 
353
    oldpc = R.PC.w.l-1;
354
    R.PC.w.l = i | R.A11;
355
    newpc = R.PC.w.l;
356
    if (newpc == oldpc) { if (i8039_ICount > 0) i8039_ICount = 0; } /* speed up busy loop */
357
    else if (newpc == oldpc-1 && M_RDOP(newpc) == 0x00) /* NOP - Gyruss */
358
        { if (i8039_ICount > 0) i8039_ICount = 0; }
359
}
360
 
361
static void jmp_1(void)      { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x100 | R.A11; }
362
static void jmp_2(void)      { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x200 | R.A11; }
363
static void jmp_3(void)      { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x300 | R.A11; }
364
static void jmp_4(void)      { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x400 | R.A11; }
365
static void jmp_5(void)      { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x500 | R.A11; }
366
static void jmp_6(void)      { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x600 | R.A11; }
367
static void jmp_7(void)      { UINT8 i=M_RDOP(R.PC.w.l); R.PC.w.l = i | 0x700 | R.A11; }
368
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); }
369
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; } else ADJUST_CYCLES }
370
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; } else ADJUST_CYCLES }
371
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; } else ADJUST_CYCLES }
372
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; } else ADJUST_CYCLES }
373
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; } else ADJUST_CYCLES }
374
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; } else ADJUST_CYCLES }
375
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; } else ADJUST_CYCLES }
376
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; } else ADJUST_CYCLES }
377
static void jf0(void)        { UINT8 i=M_RDMEM_OPCODE(); if (M_F0y) { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; } else ADJUST_CYCLES }
378
static void jf1(void)        { UINT8 i=M_RDMEM_OPCODE(); if (R.f1)  { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; } else ADJUST_CYCLES }
379
static void jnc(void)        { UINT8 i=M_RDMEM_OPCODE(); if (M_Cn)  { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; } else ADJUST_CYCLES }
380
static void jc(void)         { UINT8 i=M_RDMEM_OPCODE(); if (M_Cy)  { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; } else ADJUST_CYCLES }
381
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; } else ADJUST_CYCLES }
382
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; } else ADJUST_CYCLES }
383
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; } else ADJUST_CYCLES }
384
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; } else ADJUST_CYCLES }
385
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; } else ADJUST_CYCLES }
386
static void jnz(void)        { UINT8 i=M_RDMEM_OPCODE(); if (R.A != 0)   { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; } else ADJUST_CYCLES }
387
static void jz(void)         { UINT8 i=M_RDMEM_OPCODE(); if (R.A == 0)   { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; } else ADJUST_CYCLES }
388
static void jtf(void)        { UINT8 i=M_RDMEM_OPCODE(); if (R.t_flag)   { R.PC.w.l = ((R.PC.w.l-1) & 0xf00) | i; R.t_flag = 0; } else ADJUST_CYCLES }
389
 
390
static void mov_a_n(void)    { R.A = M_RDMEM_OPCODE(); }
391
static void mov_a_r0(void)   { R.A = R0; }
392
static void mov_a_r1(void)   { R.A = R1; }
393
static void mov_a_r2(void)   { R.A = R2; }
394
static void mov_a_r3(void)   { R.A = R3; }
395
static void mov_a_r4(void)   { R.A = R4; }
396
static void mov_a_r5(void)   { R.A = R5; }
397
static void mov_a_r6(void)   { R.A = R6; }
398
static void mov_a_r7(void)   { R.A = R7; }
399 52 arniml
static void mov_a_psw(void)  { R.A = R.PSW | 0x08; }
400 49 arniml
static void mov_a_xr0(void)  { R.A = intRAM[R0 & INT_RAM_MASK]; }
401
static void mov_a_xr1(void)  { R.A = intRAM[R1 & INT_RAM_MASK]; }
402
static void mov_r0_a(void)   { R0 = R.A; }
403
static void mov_r1_a(void)   { R1 = R.A; }
404
static void mov_r2_a(void)   { R2 = R.A; }
405
static void mov_r3_a(void)   { R3 = R.A; }
406
static void mov_r4_a(void)   { R4 = R.A; }
407
static void mov_r5_a(void)   { R5 = R.A; }
408
static void mov_r6_a(void)   { R6 = R.A; }
409
static void mov_r7_a(void)   { R7 = R.A; }
410 52 arniml
static void mov_psw_a(void)  { R.PSW = R.A | 0x08; regPTR = ((M_By) ? 24 : 0); R.SP = (R.PSW & 7) << 1; }
411 49 arniml
static void mov_r0_n(void)   { R0 = M_RDMEM_OPCODE(); }
412
static void mov_r1_n(void)   { R1 = M_RDMEM_OPCODE(); }
413
static void mov_r2_n(void)   { R2 = M_RDMEM_OPCODE(); }
414
static void mov_r3_n(void)   { R3 = M_RDMEM_OPCODE(); }
415
static void mov_r4_n(void)   { R4 = M_RDMEM_OPCODE(); }
416
static void mov_r5_n(void)   { R5 = M_RDMEM_OPCODE(); }
417
static void mov_r6_n(void)   { R6 = M_RDMEM_OPCODE(); }
418
static void mov_r7_n(void)   { R7 = M_RDMEM_OPCODE(); }
419
static void mov_a_t(void)    { R.A = R.timer; }
420
static void mov_t_a(void)    { R.timer = R.A; }
421
static void mov_xr0_a(void)  { intRAM[R0 & INT_RAM_MASK] = R.A; }
422
static void mov_xr1_a(void)  { intRAM[R1 & INT_RAM_MASK] = R.A; }
423
static void mov_xr0_n(void)  { intRAM[R0 & INT_RAM_MASK] = M_RDMEM_OPCODE(); }
424
static void mov_xr1_n(void)  { intRAM[R1 & INT_RAM_MASK] = M_RDMEM_OPCODE(); }
425
static void movd_a_p4(void)  { R.A = port_r(4); }
426
static void movd_a_p5(void)  { R.A = port_r(5); }
427
static void movd_a_p6(void)  { R.A = port_r(6); }
428
static void movd_a_p7(void)  { R.A = port_r(7); }
429
static void movd_p4_a(void)  { port_w(4, R.A); }
430
static void movd_p5_a(void)  { port_w(5, R.A); }
431
static void movd_p6_a(void)  { port_w(6, R.A); }
432
static void movd_p7_a(void)  { port_w(7, R.A); }
433
static void movp_a_xa(void)  { R.A = M_RDMEM((R.PC.w.l & 0x0f00) | R.A); }
434
static void movp3_a_xa(void) { R.A = M_RDMEM(0x300 | R.A); }
435
static void movx_a_xr0(void) { R.A = M_IN(R0); }
436
static void movx_a_xr1(void) { R.A = M_IN(R1); }
437
static void movx_xr0_a(void) { M_OUT(R0, R.A); }
438
static void movx_xr1_a(void) { M_OUT(R1, R.A); }
439
static void nop(void) { }
440
static void orl_a_n(void)    { R.A |= M_RDMEM_OPCODE(); }
441
static void orl_a_r0(void)   { R.A |= R0; }
442
static void orl_a_r1(void)   { R.A |= R1; }
443
static void orl_a_r2(void)   { R.A |= R2; }
444
static void orl_a_r3(void)   { R.A |= R3; }
445
static void orl_a_r4(void)   { R.A |= R4; }
446
static void orl_a_r5(void)   { R.A |= R5; }
447
static void orl_a_r6(void)   { R.A |= R6; }
448
static void orl_a_r7(void)   { R.A |= R7; }
449
static void orl_a_xr0(void)  { R.A |= intRAM[R0 & INT_RAM_MASK]; }
450
static void orl_a_xr1(void)  { R.A |= intRAM[R1 & INT_RAM_MASK]; }
451
static void orl_bus_n(void)  { bus_w( bus_r() | M_RDMEM_OPCODE() ); }
452
static void orl_p1_n(void)   { R.P1 |= M_RDMEM_OPCODE(); port_w(1, R.P1); }
453
static void orl_p2_n(void)   { R.P2 |= M_RDMEM_OPCODE(); port_w(2, R.P2); }
454
static void orld_p4_a(void)  { port_w(4, port_r(4) | R.A ); }
455
static void orld_p5_a(void)  { port_w(5, port_r(5) | R.A ); }
456
static void orld_p6_a(void)  { port_w(6, port_r(6) | R.A ); }
457
static void orld_p7_a(void)  { port_w(7, port_r(7) | R.A ); }
458
static void outl_bus_a(void) { bus_w(R.A); }
459
static void outl_p1_a(void)  { port_w(1, R.A); R.P1 = R.A; }
460
static void outl_p2_a(void)  { port_w(2, R.A); R.P2 = R.A; }
461
static void ret(void)    { R.PC.w.l = ((pull() & 0x0f) << 8); R.PC.w.l |= pull(); }
462
 
463
static void retr(void)
464
{
465
    UINT8 i=pull();
466
    R.PC.w.l = ((i & 0x0f) << 8) | pull();
467
    R.PSW = (R.PSW & 0x0f) | (i & 0xf0);    /* Stack is already changed by pull */
468
    regPTR = ((M_By) ? 24 : 0);
469
 
470
    R.irq_executing = I8039_NO_INT;
471
 
472
    /* Take an interrupt if a request is still being made */
473
    if (R.irq_state == I8039_EXTERNAL_INT) {
474
        R.irq_extra_cycles += Ext_IRQ();            /* Service External IRQ */
475
    }
476
    else if (R.pending_irq == I8039_TIMCNT_INT) {
477
        R.irq_extra_cycles += Timer_IRQ();          /* Service pending Timer/Counter IRQ */
478
    }
479
}
480
static void rl_a(void)       { UINT8 i=R.A & 0x80; R.A <<= 1; if (i) R.A |= 0x01; else R.A &= 0xfe; }
481
/* NS990113 */
482
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; }
483
static void rr_a(void)       { UINT8 i=R.A & 1; R.A >>= 1; if (i) R.A |= 0x80; else R.A &= 0x7f; }
484
/* NS990113 */
485
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; }
486
static void sel_mb0(void)   { R.A11 = 0; R.A11ff = 0; }
487 88 arniml
static void sel_mb1(void)    { R.A11ff = 0x800; R.A11 = 0x800; }
488 49 arniml
static void sel_rb0(void)    { CLR(B_FLAG); regPTR = 0;  }
489
static void sel_rb1(void)    { SET(B_FLAG); regPTR = 24; }
490
static void stop_tcnt(void)  { R.timerON = R.countON = 0; }
491
static void strt_cnt(void)   { R.countON = 1; R.timerON = 0; Old_T1 = test_r(1); }  /* NS990113 */
492
static void strt_t(void)     { R.timerON = 1; R.countON = 0; R.masterClock = 0; }   /* NS990113 */
493
static void swap_a(void)     { UINT8 i=R.A >> 4; R.A <<= 4; R.A |= i; }
494
static void xch_a_r0(void)   { UINT8 i=R.A; R.A=R0; R0=i; }
495
static void xch_a_r1(void)   { UINT8 i=R.A; R.A=R1; R1=i; }
496
static void xch_a_r2(void)   { UINT8 i=R.A; R.A=R2; R2=i; }
497
static void xch_a_r3(void)   { UINT8 i=R.A; R.A=R3; R3=i; }
498
static void xch_a_r4(void)   { UINT8 i=R.A; R.A=R4; R4=i; }
499
static void xch_a_r5(void)   { UINT8 i=R.A; R.A=R5; R5=i; }
500
static void xch_a_r6(void)   { UINT8 i=R.A; R.A=R6; R6=i; }
501
static void xch_a_r7(void)   { UINT8 i=R.A; R.A=R7; R7=i; }
502
static void xch_a_xr0(void)  { UINT8 i=R.A; R.A=intRAM[R0 & INT_RAM_MASK]; intRAM[R0 & INT_RAM_MASK]=i; }
503
static void xch_a_xr1(void)  { UINT8 i=R.A; R.A=intRAM[R1 & INT_RAM_MASK]; intRAM[R1 & INT_RAM_MASK]=i; }
504
static void xchd_a_xr0(void) { M_XCHD(R0 & INT_RAM_MASK); }
505
static void xchd_a_xr1(void) { M_XCHD(R1 & INT_RAM_MASK); }
506
static void xrl_a_n(void)    { R.A ^= M_RDMEM_OPCODE(); }
507
static void xrl_a_r0(void)   { R.A ^= R0; }
508
static void xrl_a_r1(void)   { R.A ^= R1; }
509
static void xrl_a_r2(void)   { R.A ^= R2; }
510
static void xrl_a_r3(void)   { R.A ^= R3; }
511
static void xrl_a_r4(void)   { R.A ^= R4; }
512
static void xrl_a_r5(void)   { R.A ^= R5; }
513
static void xrl_a_r6(void)   { R.A ^= R6; }
514
static void xrl_a_r7(void)   { R.A ^= R7; }
515
static void xrl_a_xr0(void)  { R.A ^= intRAM[R0 & INT_RAM_MASK]; }
516
static void xrl_a_xr1(void)  { R.A ^= intRAM[R1 & INT_RAM_MASK]; }
517
 
518
static s_opcode opcode_main[256]=
519
{
520
    {1, nop        },{0, illegal    },{2, outl_bus_a },{2, add_a_n    },{2, jmp        },{1, en_i       },{0, illegal    },{1, dec_a      },
521
    {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  },
522
    {1, inc_xr0    },{1, inc_xr1    },{2, jb_0       },{2, adc_a_n    },{2, call       },{1, dis_i      },{2, jtf        },{1, inc_a      },
523
    {1, inc_r0     },{1, inc_r1     },{1, inc_r2     },{1, inc_r3     },{1, inc_r4     },{1, inc_r5     },{1, inc_r6     },{1, inc_r7     },
524
    {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      },
525
    {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   },
526
    {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      },
527
    {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  },
528
    {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     },
529
    {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   },
530
    {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      },
531
    {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   },
532
    {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      },
533
    {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   },
534
    {1, adc_a_xr0  },{1, adc_a_xr1  },{2, jb_3       },{0, illegal    },{2, call_3     },{1, ento_clk   },{2, jf1        },{1, rr_a       },
535
    {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   },
536
    {2, movx_a_xr0 },{2, movx_a_xr1 },{0, illegal    },{2, ret        },{2, jmp_4      },{1, clr_f0     },{2, jni        },{0, illegal    },
537
    {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  },
538
    {2, movx_xr0_a },{2, movx_xr1_a },{2, jb_4       },{2, retr       },{2, call_4     },{1, cpl_f0     },{2, jnz        },{1, clr_c      },
539
    {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  },
540
    {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      },
541
    {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   },
542
    {2, mov_xr0_n  },{2, mov_xr1_n  },{2, jb_5       },{2, jmpp_xa    },{2, call_5     },{1, cpl_f1     },{2, jf0        },{0, illegal    },
543
    {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   },
544
    {0, illegal    },{0, illegal    },{0, illegal    },{0, illegal    },{2, jmp_6      },{1, sel_rb0    },{2, jz         },{1, mov_a_psw  },
545
    {1, dec_r0     },{1, dec_r1     },{1, dec_r2     },{1, dec_r3     },{1, dec_r4     },{1, dec_r5     },{1, dec_r6     },{1, dec_r7     },
546
    {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  },
547
    {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   },
548
    {0, illegal    },{0, illegal    },{0, illegal    },{2, movp3_a_xa },{2, jmp_7      },{1, sel_mb0    },{2, jnc        },{1, rl_a       },
549
    {2, djnz_r0    },{2, djnz_r1    },{2, djnz_r2    },{2, djnz_r3    },{2, djnz_r4    },{2, djnz_r5    },{2, djnz_r6    },{2, djnz_r7    },
550
    {1, mov_a_xr0  },{1, mov_a_xr1  },{2, jb_7       },{0, illegal    },{2, call_7     },{1, sel_mb1    },{2, jc         },{1, rlc_a      },
551
    {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   }
552
};
553
 
554
 
555
/****************************************************************************
556
 * Reset registers to their initial values
557
 ****************************************************************************/
558
void i8039_reset (void *param)
559
{
560
    R.PC.w.l = 0;
561
    R.SP  = 0;
562
    R.A   = 0;
563
    R.PSW = 0x08;       /* Start with Carry SET, Bit 4 is always SET */
564
    memset(R.RAM, 0x0, 128);
565
    R.P1  = 0xff;
566
    R.P2  = 0xff;
567
    R.bus = 0;
568
    R.irq_executing = I8039_NO_INT;
569
    R.pending_irq   = I8039_NO_INT;
570
 
571
    R.A11ff   = R.A11     = 0;
572
    R.tirq_en = R.xirq_en = 0;
573
    R.timerON = R.countON = 0;
574
    R.timerON = 1;  /* Mario Bros. doesn't work without this */
575
    R.irq_extra_cycles = 0;
576
    R.masterClock = 0;
577
 
578
    /* print dump header */
579
    printf("  Addr | Instruction        |  PC  Accu SP PSW BUS F1 P1 P2 A11 RAM\n");
580
    printf(" ------+--------------------+---------------------------------------\n");
581
}
582
 
583
 
584
/****************************************************************************
585
 * Shut down CPU emulation
586
 ****************************************************************************/
587
static void i8039_exit (void)
588
{
589
    /* nothing to do ? */
590
}
591
 
592
/****************************************************************************
593
 * Issue an interrupt if necessary
594
 ****************************************************************************/
595
static int Ext_IRQ(void)
596
{
597
    int extra_cycles = 0;
598
 
599
    if (R.xirq_en) {
600
        if (R.irq_executing == I8039_NO_INT) {
601
/*          logerror("I8039:  EXT INTERRUPT being serviced\n"); */
602
            R.irq_executing = I8039_EXTERNAL_INT;
603
            push(R.PC.b.l);
604
            push((R.PC.b.h & 0x0f) | (R.PSW & 0xf0));
605
            R.PC.w.l = 0x03;
606
            R.A11ff = R.A11;
607
            R.A11   = 0;
608
 
609
            extra_cycles = 2;       /* 2 clock cycles used */
610
 
611
            if (R.timerON)  /* NS990113 */
612
                R.masterClock += extra_cycles;
613
            if (R.irq_callback) (*R.irq_callback)(0);
614
        }
615
    }
616
 
617
    return extra_cycles;
618
}
619
 
620
static int Timer_IRQ(void)
621
{
622
    int extra_cycles = 0;
623
 
624
    if (R.tirq_en) {
625
        if (R.irq_executing == I8039_NO_INT) {
626
/*          logerror("I8039:  TIMER/COUNTER INTERRUPT\n"); */
627
            R.irq_executing = I8039_TIMCNT_INT;
628
            R.pending_irq &= ~I8039_TIMCNT_INT;
629
            push(R.PC.b.l);
630
            push((R.PC.b.h & 0x0f) | (R.PSW & 0xf0));
631
            R.PC.w.l = 0x07;
632
            R.A11ff = R.A11;
633
            R.A11   = 0;
634
 
635
            extra_cycles = 2;       /* 2 clock cycles used */
636
 
637
            if (R.timerON)  /* NS990113 */
638
                R.masterClock += extra_cycles;
639
        }
640
        else {
641
            if (R.irq_executing == I8039_EXTERNAL_INT) {
642
                R.pending_irq |= I8039_TIMCNT_INT;
643
            }
644
        }
645
    }
646
 
647
    R.t_flag = 1;
648
 
649
    return extra_cycles;
650
}
651
 
652
 
653
static void dump_machine_state(void)
654
{
655
  int i;
656
 
657 52 arniml
  printf("  | %04X  %02X  %02X %02X", (UINT32)R.PC.w.l, (UINT32)R.A, (UINT32)(R.SP >> 1), (UINT32)R.PSW);
658 49 arniml
  printf("  %02X  %X  %02X %02X",     (UINT32)R.bus, (UINT32)R.f1, (UINT32)R.P1, (UINT32)R.P2);
659
  printf(" %X  ",                     (UINT32)(R.A11 >> 11));
660
 
661
  for (i = 0; i < 256; i++)
662
    printf(" %02X", R.RAM[i]);
663
 
664
  printf("\n");
665
}
666
 
667
 
668
enum {ACCU_IDLE, ACCU_HAS_AA, ACCU_HAS_55, ACCU_PASS, ACCU_FAIL};
669
 
670
/****************************************************************************
671
 * Execute cycles CPU cycles. Return number of cycles really executed
672
 ****************************************************************************/
673
int i8039_execute(int cycles, int dump)
674
{
675
    unsigned opcode, T1;
676
    int count, i;
677
    char buffer[64];
678
    char string[32];
679
 
680
    static int accu        = 0;
681
    static int accu_state  = ACCU_IDLE;
682
 
683
    i8039_ICount = (cycles - R.irq_extra_cycles);
684
    R.irq_extra_cycles = 0;
685
 
686
    if ((accu_state == ACCU_PASS) || (accu_state == ACCU_FAIL)) {
687
      printf("End of simulation detected\n");
688
 
689
      return(accu_state == ACCU_PASS ? 0 : -1);
690
    }
691
 
692
    do
693
    {
694
        R.PREVPC = R.PC;
695
 
696
 
697
        opcode=M_RDOP(R.PC.w.l);
698
 
699
        buffer[0] = '\0';
700
        Dasm8039(buffer, R.PC.w.l);
701
        sprintf(string, "  %04X : %s", R.PC.w.l, buffer);
702
        for (i = strlen(string); i < 26; i++)
703
          string[i] = ' ';
704
        string[i <= 31 ? i : 31] = '\0';
705
        printf("%s", string);
706
 
707
/*      logerror("I8039:  PC = %04x,  opcode = %02x\n", R.PC.w.l, opcode); */
708
 
709
        R.PC.w.l++;
710
        inst_cycles = opcode_main[opcode].cycles;
711
        (*(opcode_main[opcode].function))();
712
        i8039_ICount -= inst_cycles; /*/ */
713
 
714
        if (dump == 1) {
715
          /* dump machine state information */
716
          dump_machine_state();
717
        } else
718
          printf("\n");
719
 
720
        /* end-of-simulation check */
721
        if (accu != R.A) {
722
          accu = R.A;
723
 
724
          switch (accu_state) {
725
            case ACCU_IDLE:
726
              accu_state = accu == 0xaa ? ACCU_HAS_AA : ACCU_IDLE;
727
              break;
728
 
729
            case ACCU_HAS_AA:
730
              accu_state = accu == 0x55 ? ACCU_HAS_55 : ACCU_IDLE;
731
              break;
732
 
733
            case ACCU_HAS_55:
734 74 arniml
              switch (accu) {
735
                case 0x01:
736
                  accu_state = ACCU_PASS;
737
                  break;
738
                case 0x00:
739
                  accu_state = ACCU_FAIL;
740
                  break;
741
                default:
742
                  accu_state = ACCU_IDLE;
743
                  break;
744
              }
745 49 arniml
              break;
746
 
747
            case ACCU_PASS:
748
            case ACCU_FAIL:
749
              break;
750
 
751
            default:
752
              accu_state = ACCU_IDLE;
753
              break;
754
          }
755
        }
756
 
757
 
758
 
759
 
760
        if (R.countON)  /* NS990113 */
761
        {
762
            for ( ; inst_cycles > 0; inst_cycles-- )
763
            {
764
                T1 = test_r(1);
765
                if (POSITIVE_EDGE_T1)
766
                {
767
                    R.timer++;
768
                    if (R.timer == 0) {
769
                        count = Timer_IRQ();    /* Handle Counter IRQ */
770
                        i8039_ICount -= count;
771
                    }
772
                }
773
                Old_T1 = T1;
774
            }
775
        }
776
 
777
        if (R.timerON) {
778
            R.masterClock += opcode_main[opcode].cycles;
779
            if (R.masterClock >= 32) {  /* NS990113 */
780
                R.masterClock -= 32;
781
                R.timer++;
782
                if (R.timer == 0) {
783
                    count = Timer_IRQ();    /* Handle Timer IRQ */
784
                    i8039_ICount -= count;
785
                }
786
            }
787
        }
788
    } while (i8039_ICount > 0 && accu_state != ACCU_PASS && accu_state != ACCU_FAIL);
789
 
790
    i8039_ICount -= R.irq_extra_cycles;
791
    R.irq_extra_cycles = 0;
792
 
793
    return cycles - i8039_ICount;
794
}
795
 
796
/****************************************************************************
797
 * Get all registers in given buffer
798
 ****************************************************************************/
799
static void i8039_get_context (void *dst)
800
{
801
    if( dst )
802
        *(I8039_Regs*)dst = R;
803
}
804
 
805
 
806
/****************************************************************************
807
 * Set all registers to given values
808
 ****************************************************************************/
809
static void i8039_set_context (void *src)
810
{
811
    if( src )
812
    {
813
        R = *(I8039_Regs*)src;
814
        regPTR = ((M_By) ? 24 : 0);
815
        R.SP = (R.PSW << 1) & 0x0f;
816
    }
817
    /* Handle forced Interrupts throught the Debugger */
818
    if (R.irq_state != I8039_NO_INT) {
819
        R.irq_extra_cycles += Ext_IRQ();        /* Handle External IRQ */
820
    }
821
    if (R.timer == 0) {
822
        R.irq_extra_cycles += Timer_IRQ();      /* Handle Timer IRQ */
823
    }
824
}
825
 
826
 
827
/****************************************************************************
828
 * Set IRQ line state
829
 ****************************************************************************/
830 58 arniml
void set_irq_line(int irqline, int state)
831 49 arniml
{
832
    if (state != CLEAR_LINE) {
833
        R.irq_state = I8039_EXTERNAL_INT;
834
        R.irq_extra_cycles += Ext_IRQ();        /* Handle External IRQ */
835
    }
836
    else {
837
        R.irq_state = I8039_NO_INT;
838
    }
839
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.