786af607083aae743c42dafd5cca2c675f72b3ac
[fceu.git] / x6502.c
1 /* FCE Ultra - NES/Famicom Emulator
2  *
3  * Copyright notice for this file:
4  *  Copyright (C) 2002 Ben Parnell
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include <string.h>
22
23 #include "types.h"
24 #include "x6502.h"
25 #include "fce.h"
26 #include "sound.h"
27 #include "sound098.h"
28 #include "cart.h"
29
30 #include "dprintf.h"
31
32 #ifdef DEBUG_ASM_6502
33 #include <stdio.h>
34 #include <stdlib.h>
35 extern uint32 PC_prev, OP_prev;
36 extern uint8  dreads[4];
37 extern uint32 dwrites_c[2];
38 extern int dread_count_c, dwrite_count_c;
39 extern int mapirq_cyc_c;
40 extern void (*MapIRQHook)(int a);
41 #define DummyRdMem(...)
42 #else
43 #define DummyRdMem RdMem
44 void FP_FASTAPASS(1) (*MapIRQHook)(int a);
45 #endif
46
47 X6502 X;
48 uint32 timestamp;
49
50 #define _PC              X.PC
51 #define _A               X.A
52 #define _X               X.X
53 #define _Y               X.Y
54 #define _S               X.S
55 #define _P               X.P
56 #define _PI              X.mooPI
57 //#define _PZ              X.PZ         // unused?
58 #define _DB              X.DB
59 #define _count           X.count
60 #define _tcount          X.tcount
61 #define _IRQlow          X.IRQlow
62 #define _jammed          X.jammed
63
64
65 static INLINE uint8 RdMem(unsigned int A)
66 {
67  int _DB1=ARead[A](A);
68 #ifdef DEBUG_ASM_6502
69  //_DB=_DB1;
70  //printf("a == %x, pc == %x\n", A, _PC);
71  if (A >= 0x2000) {
72   if (A == _PC || A == _PC - 1 || A == _PC + 1) {
73    //printf("fr: %02x\n", _DB1);
74   }
75   _DB=_DB1;
76  }
77  if (A >= 0x2000 && A != _PC - 1) {
78   dreads[dread_count_c++] = _DB1;
79   if (dread_count_c > 4) { printf("dread_count out of range\n"); exit(1); }
80  }
81 #else
82  _DB=_DB1;
83 #endif
84  return _DB1;
85 }
86
87 static INLINE void WrMem(unsigned int A, uint8 V)
88 {
89  //printf("w [%04x] %02x\n", A, V);
90  if ((A&0xe000) == 0) { // RAM area (always 0-0x1fff)
91   RAM[A&0x7FF] = V;
92   return;
93  }
94  BWrite[A](A,V);
95 #ifdef DEBUG_ASM_6502
96  dwrites_c[dwrite_count_c++] = (A<<8)|V;
97  if (dwrite_count_c > 2) { printf("dwrite_count_c out of range\n"); exit(1); }
98 #endif
99 }
100
101 static INLINE uint8 RdRAM(unsigned int A)
102 {
103  //return((_DB=RAM[A]));
104  int _DB1=RAM[A];
105 #ifndef DEBUG_ASM_6502
106  _DB=_DB1;
107 #endif
108  return _DB1;
109 }
110
111 static INLINE void WrRAM(unsigned int A, uint8 V)
112 {
113  RAM[A]=V;
114 }
115
116 static INLINE void ADDCYC(int x)
117 {
118  _tcount+=x;
119  _count-=x*48;
120  timestamp+=x;
121 }
122
123 void FASTAPASS(1) X6502_AddCycles_c(int x)
124 {
125  ADDCYC(x);
126 }
127
128 static INLINE void PUSH(uint8 V)
129 {
130  WrRAM(0x100+_S,V);
131  _S--;
132 }
133
134 static INLINE uint8 POP(void)
135 {
136  _S++;
137  return(RdRAM(0x100+_S));
138 }
139
140 #if 0
141 static uint8 ZNTable[256] = {
142         Z_FLAG,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
143         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
144         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
145         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
146         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
147         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
148         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
149         0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
150         N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
151         N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
152         N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
153         N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
154         N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
155         N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
156         N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,
157         N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG,N_FLAG
158 };
159 #endif
160 /* Some of these operations will only make sense if you know what the flag
161    constants are. */
162 //#define X_ZN(zort)         _P&=~(Z_FLAG|N_FLAG);_P|=ZNTable[zort]
163 //#define X_ZNT(zort)   _P|=ZNTable[zort]
164 #define X_ZN(zort)         _P&=~(Z_FLAG|N_FLAG);if(!zort) _P|=Z_FLAG;else _P|=zort&N_FLAG
165 #define X_ZNT(zort)     if(!zort) _P|=Z_FLAG;else _P|=(zort&N_FLAG)
166
167 /* Care must be taken if you want to turn this into a macro.  Use { and }. */
168 #define JR();   \
169 {               \
170  uint32 tmp;    \
171  int8 disp;     \
172  disp=RdMem(_PC++);     \
173  ADDCYC(1);     \
174  tmp=_PC;       \
175  _PC+=disp;     \
176  if((tmp^_PC)&0x100)    \
177   ADDCYC(1);    \
178 }
179
180 #define LDA        _A=x;X_ZN(_A)
181 #define LDX        _X=x;X_ZN(_X)
182 #define LDY        _Y=x;X_ZN(_Y)
183
184 /*  All of the freaky arithmetic operations. */
185 #define AND        _A&=x;X_ZN(_A)
186 //#define BIT        _P&=~(Z_FLAG|V_FLAG|N_FLAG);_P|=ZNTable[x&_A]&Z_FLAG;_P|=x&(V_FLAG|N_FLAG)
187 #define BIT        _P&=~(Z_FLAG|V_FLAG|N_FLAG);if(!(x&_A)) _P|=Z_FLAG;_P|=x&(V_FLAG|N_FLAG)
188 #define EOR        _A^=x;X_ZN(_A)
189 #define ORA        _A|=x;X_ZN(_A)
190
191 #define ADC  {  \
192               uint32 l=_A+x+(_P&1);     \
193               _P&=~(Z_FLAG|C_FLAG|N_FLAG|V_FLAG);       \
194               _P|=((((_A^x)&0x80)^0x80) & ((_A^l)&0x80))>>1;    \
195               _P|=(l>>8)&C_FLAG;        \
196               _A=l;     \
197               X_ZNT(_A);        \
198              }
199 #define SBC  {  \
200               uint32 l=_A-x-((_P&1)^1); \
201               _P&=~(Z_FLAG|C_FLAG|N_FLAG|V_FLAG);       \
202               _P|=((_A^l)&(_A^x)&0x80)>>1;      \
203               _P|=((l>>8)&C_FLAG)^C_FLAG;       \
204               _A=l;     \
205               X_ZNT(_A);        \
206              }
207
208 #define CMPL(a1,a2) {   \
209                      uint32 t=a1-a2;    \
210                      X_ZN(t&0xFF);      \
211                      _P&=~C_FLAG;       \
212                      _P|=((t>>8)&C_FLAG)^C_FLAG;        \
213                     }
214
215 /* Special undocumented operation.  Very similar to CMP. */
216 #define AXS         {   \
217                      uint32 t=(_A&_X)-x;    \
218                      X_ZN(t&0xFF);      \
219                      _P&=~C_FLAG;       \
220                      _P|=((t>>8)&C_FLAG)^C_FLAG;        \
221                      _X=t;      \
222                     }
223
224 #define CMP             CMPL(_A,x)
225 #define CPX             CMPL(_X,x)
226 #define CPY             CMPL(_Y,x)
227
228 /* The following operations modify the byte being worked on. */
229 #define DEC             x--;X_ZN(x)
230 #define INC             x++;X_ZN(x)
231
232 #define ASL        _P&=~C_FLAG;_P|=x>>7;x<<=1;X_ZN(x)
233 #define LSR     _P&=~(C_FLAG|N_FLAG|Z_FLAG);_P|=x&1;x>>=1;X_ZNT(x)
234
235 /* For undocumented instructions, maybe for other things later... */
236 #define LSRA    _P&=~(C_FLAG|N_FLAG|Z_FLAG);_P|=_A&1;_A>>=1;X_ZNT(_A)
237
238 #define ROL     {       \
239                  uint8 l=x>>7;  \
240                  x<<=1; \
241                  x|=_P&C_FLAG;  \
242                  _P&=~(Z_FLAG|N_FLAG|C_FLAG);   \
243                  _P|=l; \
244                  X_ZNT(x);      \
245                 }
246 #define ROR     {       \
247                  uint8 l=x&1;   \
248                  x>>=1; \
249                  x|=(_P&C_FLAG)<<7;     \
250                  _P&=~(Z_FLAG|N_FLAG|C_FLAG);   \
251                  _P|=l; \
252                  X_ZNT(x);      \
253                 }
254
255 /* Icky icky thing for some undocumented instructions.  Can easily be
256    broken if names of local variables are changed.
257 */
258
259 /* Absolute */
260 #define GetAB(target)   \
261 {       \
262  target=RdMem(_PC++);   \
263  target|=RdMem(_PC++)<<8;       \
264 }
265
266 /* Absolute Indexed(for reads) */
267 #define GetABIRD(target, i)     \
268 {       \
269  unsigned int tmp;      \
270  GetAB(tmp);    \
271  target=tmp;    \
272  target+=i;     \
273  if((target^tmp)&0x100) \
274  {      \
275   target&=0xFFFF;       \
276   DummyRdMem(target^0x100);     \
277   ADDCYC(1);    \
278  }      \
279 }
280
281 /* Absolute Indexed(for writes and rmws) */
282 #define GetABIWR(target, i)     \
283 {       \
284  unsigned int rt;       \
285  GetAB(rt);     \
286  target=rt;     \
287  target+=i;     \
288  target&=0xFFFF;        \
289  DummyRdMem((target&0x00FF)|(rt&0xFF00));       \
290 }
291
292 /* Zero Page */
293 #define GetZP(target)   \
294 {       \
295  target=RdMem(_PC++);   \
296 }
297
298 /* Zero Page Indexed */
299 #define GetZPI(target,i)        \
300 {       \
301  target=i+RdMem(_PC++); \
302 }
303
304 /* Indexed Indirect */
305 #define GetIX(target)   \
306 {       \
307  uint8 tmp;     \
308  tmp=RdMem(_PC++);      \
309  tmp+=_X;       \
310  target=RdRAM(tmp++);   \
311  target|=RdRAM(tmp)<<8; \
312 }
313
314 /* Indirect Indexed(for reads) */
315 #define GetIYRD(target) \
316 {       \
317  unsigned int rt;       \
318  uint8 tmp;     \
319  tmp=RdMem(_PC++);      \
320  rt=RdRAM(tmp++);       \
321  rt|=RdRAM(tmp)<<8;     \
322  target=rt;     \
323  target+=_Y;    \
324  if((target^rt)&0x100)  \
325  {      \
326   target&=0xFFFF;       \
327   DummyRdMem(target^0x100);     \
328   ADDCYC(1);    \
329  }      \
330 }
331
332 /* Indirect Indexed(for writes and rmws) */
333 #define GetIYWR(target) \
334 {       \
335  unsigned int rt;       \
336  uint8 tmp;     \
337  tmp=RdMem(_PC++);      \
338  rt=RdRAM(tmp++);       \
339  rt|=RdRAM(tmp)<<8;     \
340  target=rt;     \
341  target+=_Y;    \
342  DummyRdMem((target&0x00FF)|(rt&0xFF00));       \
343 }
344
345 /* Now come the macros to wrap up all of the above stuff addressing mode functions
346    and operation macros.  Note that operation macros will always operate(redundant
347    redundant) on the variable "x".
348 */
349
350 #define RMW_A(op) {uint8 x=_A; op; _A=x; break; } /* Meh... */
351 #define RMW_AB(op) {unsigned int A; uint8 x; GetAB(A); x=RdMem(A); WrMem(A,x); op; WrMem(A,x); break; }
352 #define RMW_ABI(reg,op) {unsigned int A; uint8 x; GetABIWR(A,reg); x=RdMem(A); WrMem(A,x); op; WrMem(A,x); break; }
353 #define RMW_ABX(op)     RMW_ABI(_X,op)
354 #define RMW_ABY(op)     RMW_ABI(_Y,op)
355 #define RMW_IX(op)  {unsigned int A; uint8 x; GetIX(A); x=RdMem(A); WrMem(A,x); op; WrMem(A,x); break; }
356 #define RMW_IY(op)  {unsigned int A; uint8 x; GetIYWR(A); x=RdMem(A); WrMem(A,x); op; WrMem(A,x); break; }
357 #define RMW_ZP(op)  {uint8 A; uint8 x; GetZP(A); x=RdRAM(A); op; WrRAM(A,x); break; }
358 #define RMW_ZPX(op) {uint8 A; uint8 x; GetZPI(A,_X); x=RdRAM(A); op; WrRAM(A,x); break;}
359
360 #define LD_IM(op)       {uint8 x; x=RdMem(_PC++); op; break;}
361 #define LD_ZP(op)       {uint8 A; uint8 x; GetZP(A); x=RdRAM(A); op; break;}
362 #define LD_ZPX(op)  {uint8 A; uint8 x; GetZPI(A,_X); x=RdRAM(A); op; break;}
363 #define LD_ZPY(op)  {uint8 A; uint8 x; GetZPI(A,_Y); x=RdRAM(A); op; break;}
364 #define LD_AB(op)       {unsigned int A; uint8 x; GetAB(A); x=RdMem(A); op; break; }
365 #define LD_ABI(reg,op)  {unsigned int A; uint8 x; GetABIRD(A,reg); x=RdMem(A); op; break;}
366 #define LD_ABX(op)      LD_ABI(_X,op)
367 #define LD_ABY(op)      LD_ABI(_Y,op)
368 #define LD_IX(op)       {unsigned int A; uint8 x; GetIX(A); x=RdMem(A); op; break;}
369 #define LD_IY(op)       {unsigned int A; uint8 x; GetIYRD(A); x=RdMem(A); op; break;}
370
371 #define ST_ZP(r)        {uint8 A; GetZP(A); WrRAM(A,r); break;}
372 #define ST_ZPX(r)       {uint8 A; GetZPI(A,_X); WrRAM(A,r); break;}
373 #define ST_ZPY(r)       {uint8 A; GetZPI(A,_Y); WrRAM(A,r); break;}
374 #define ST_AB(r)        {unsigned int A; GetAB(A); WrMem(A,r); break;}
375 #define ST_ABI(reg,r)   {unsigned int A; GetABIWR(A,reg); WrMem(A,r); break; }
376 #define ST_ABX(r)       ST_ABI(_X,r)
377 #define ST_ABY(r)       ST_ABI(_Y,r)
378 #define ST_IX(r)        {unsigned int A; GetIX(A); WrMem(A,r); break; }
379 #define ST_IY(r)        {unsigned int A; GetIYWR(A); WrMem(A,r); break; }
380
381 static uint8 CycTable[256] =
382 {
383 /*       0 1 2 3 4 5 6 7 8 9 a b c d e f */
384 /*0x00*/ 7,6,2,8,3,3,5,5,3,2,2,2,4,4,6,6,
385 /*0x10*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,
386 /*0x20*/ 6,6,2,8,3,3,5,5,4,2,2,2,4,4,6,6,
387 /*0x30*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,
388 /*0x40*/ 6,6,2,8,3,3,5,5,3,2,2,2,3,4,6,6,
389 /*0x50*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,
390 /*0x60*/ 6,6,2,8,3,3,5,5,4,2,2,2,5,4,6,6,
391 /*0x70*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,
392 /*0x80*/ 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,
393 /*0x90*/ 2,6,2,6,4,4,4,4,2,5,2,5,5,5,5,5,
394 /*0xA0*/ 2,6,2,6,3,3,3,3,2,2,2,2,4,4,4,4,
395 /*0xB0*/ 2,5,2,5,4,4,4,4,2,4,2,4,4,4,4,4,
396 /*0xC0*/ 2,6,2,8,3,3,5,5,2,2,2,2,4,4,6,6,
397 /*0xD0*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,
398 /*0xE0*/ 2,6,3,8,3,3,5,5,2,2,2,2,4,4,6,6,
399 /*0xF0*/ 2,5,2,8,4,4,6,6,2,4,2,7,4,4,7,7,
400 };
401
402 void FASTAPASS(1) X6502_IRQBegin_c(int w)
403 {
404  dprintf("IRQB %02x",w);
405  _IRQlow|=w;
406 }
407
408 void FASTAPASS(1) X6502_IRQEnd_c(int w)
409 {
410  dprintf("IRQE %02x",w);
411  _IRQlow&=~w;
412 }
413
414 void TriggerIRQ_c(void) /* This function should probably be phased out. */
415 {
416  _IRQlow|=FCEU_IQTEMP;
417 }
418
419 void TriggerNMI_c(void)
420 {
421  _IRQlow|=FCEU_IQNMI;
422 }
423
424 static void TriggerNMIReal(void)
425 {
426  if(!_jammed)
427  {
428   dprintf("NMI");
429   ADDCYC(7);
430   PUSH(_PC>>8);
431   PUSH(_PC);
432   _P&=~B_FLAG;
433   PUSH(_P|U_FLAG);
434   _PC=RdMem(0xFFFA);
435   _PC|=RdMem(0xFFFB)<<8;
436 #ifdef DEBUG_ASM_6502
437   PC_prev = _PC;
438   OP_prev = 0x100;
439 #endif
440  }
441 }
442
443 void TriggerIRQReal(void)
444 {
445  if(!(_PI&I_FLAG) && !_jammed)
446  {
447   dprintf("IRQ");
448   ADDCYC(7);
449   PUSH(_PC>>8);
450   PUSH(_PC);
451   _P&=~B_FLAG;
452   PUSH(_P|U_FLAG);
453   _P|=I_FLAG;
454   _PC=RdMem(0xFFFE);
455   _PC|=RdMem(0xFFFF)<<8;
456 #ifdef DEBUG_ASM_6502
457   PC_prev = _PC;
458   OP_prev = 0x101;
459 #endif
460  }
461 }
462
463 void X6502_Reset_c(void)
464 {
465   _PC=RdMem(0xFFFC);
466   _PC|=RdMem(0xFFFD)<<8;
467   _jammed=0;
468   _PI=_P=I_FLAG;
469 }
470
471 void X6502_Power_c(void)
472 {
473  memset((void *)&X,0,sizeof(X));
474  timestamp=0;
475  X6502_Reset_c();
476 }
477
478
479 //int asdc = 0;
480 void X6502_Run_c(void/*int32 cycles*/)
481 {
482 /*
483         if(PAL)
484          cycles*=15;          // 15*4=60
485         else
486          cycles*=16;          // 16*4=64
487
488         _count+=cycles;
489 */
490 //      if (_count <= 0) asdc++;
491
492         while(_count>0)
493         {
494          int32 temp;
495          uint8 b1;
496
497          if(_IRQlow)
498          {
499           if(_IRQlow&FCEU_IQNMI)
500            TriggerNMIReal();
501           else
502            TriggerIRQReal();
503
504           _IRQlow&=~(FCEU_IQTEMP|FCEU_IQNMI);
505           if(_count<=0)
506           {
507 #ifdef DEBUG_ASM_6502
508            if(MapIRQHook) mapirq_cyc_c = _tcount;
509            _tcount=0;
510 #endif
511            _PI=_P;
512            return; /* Should increase accuracy without a major speed hit. */
513           }
514          }
515          _PI=_P;
516 #ifdef DEBUG_ASM_6502
517          b1=RdMem(_PC++); _PC--;
518 #else
519          b1=RdMem(_PC);
520 #endif
521          ADDCYC(CycTable[b1]);
522          temp=_tcount;
523
524          if (use098code)
525           FCEU_SoundCPUHook098(temp);
526          else
527          {
528          temp*=48;
529
530          fhcnt-=temp;
531          if(fhcnt<=0)
532          {
533           FrameSoundUpdate();
534           fhcnt+=fhinc;
535          }
536
537          if(PCMIRQCount>0)
538          {
539           PCMIRQCount-=temp;
540           if(PCMIRQCount<=0)
541           {
542            vdis=1;
543            if((PSG[0x10]&0x80) && !(PSG[0x10]&0x40))
544            {
545             extern uint8 SIRQStat;
546             SIRQStat|=0x80;
547             X6502_IRQBegin(FCEU_IQDPCM);
548            }
549           }
550          }
551          }
552
553 #ifdef DEBUG_ASM_6502
554          PC_prev = _PC;
555          OP_prev = b1;
556 #endif
557           //printf("$%04x:$%02x\n",_PC,b1);
558          //_PC++;
559          //printf("$%02x\n",b1);
560          _PC++;
561          switch(b1)
562          {
563           #include "ops.h"
564          }
565
566          temp=_tcount; /* Gradius II (J) glitches if _tcount is not used */
567          _tcount=0;
568
569          if(MapIRQHook) {
570 #ifdef DEBUG_ASM_6502
571           mapirq_cyc_c = temp;
572 #endif
573           MapIRQHook(temp);
574          }
575
576 #ifdef DEBUG_ASM_6502
577          _PI=_P;
578 #endif
579         }
580 }
581
582