OSDN Git Service

[VM][General] Merge Upstream 2017-03-30.
[csp-qt/common_source_project-fm7.git] / source / src / vm / m6502.cpp
1 /*
2         Skelton for retropc emulator
3
4         Origin : MAME
5         Author : Takeda.Toshiya
6         Date   : 2010.08.10-
7
8         [ M6502 ]
9 */
10
11 #include "m6502.h"
12 #ifdef USE_DEBUGGER
13 #include "debugger.h"
14 #endif
15
16 // vectors
17 #define NMI_VEC 0xfffa
18 #define RST_VEC 0xfffc
19 #define IRQ_VEC 0xfffe
20
21 // flags
22 #define F_C     0x01
23 #define F_Z     0x02
24 #define F_I     0x04
25 #define F_D     0x08
26 #define F_B     0x10
27 #define F_T     0x20
28 #define F_V     0x40
29 #define F_N     0x80
30
31 // some shortcuts for improved readability
32 #define A       a
33 #define X       x
34 #define Y       y
35 #define P       p
36 #define S       sp.b.l
37 #define SPD     sp.d
38
39 #define SET_NZ(n) \
40         if((n) == 0) \
41                 P = (P & ~F_N) | F_Z; \
42         else \
43                 P = (P & ~(F_N | F_Z)) | ((n) & F_N)
44
45 #define SET_Z(n) \
46         if((n) == 0) \
47                 P |= F_Z; \
48         else \
49                 P &= ~F_Z
50
51 #define EAL ea.b.l
52 #define EAH ea.b.h
53 #define EAW ea.w.l
54 #define EAD ea.d
55
56 #define ZPL zp.b.l
57 #define ZPH zp.b.h
58 #define ZPW zp.w.l
59 #define ZPD zp.d
60
61 #define PCL pc.b.l
62 #define PCH pc.b.h
63 #define PCW pc.w.l
64 #define PCD pc.d
65
66 // virtual machine interface
67
68 #define RDMEM_ID(addr) d_mem->read_data8(addr)
69 #define WRMEM_ID(addr, data) d_mem->write_data8(addr, data)
70
71 #define RDOP() d_mem->read_data8(PCW++)
72 #define PEEKOP() d_mem->read_data8(PCW)
73 #define RDOPARG() d_mem->read_data8(PCW++)
74
75 #define RDMEM(addr) d_mem->read_data8(addr)
76 #define WRMEM(addr, data) d_mem->write_data8(addr, data)
77
78 #define CYCLES(c) icount -= (c)
79
80 // branch relative
81
82 #define BRA(cond) { \
83         int8_t tmp2 = RDOPARG(); \
84         if(cond) { \
85                 RDMEM(PCW); \
86                 EAW = PCW + (int8_t)tmp2; \
87                 if(EAH != PCH) { \
88                         RDMEM((PCH << 8) | EAL) ; \
89                         CYCLES(1); \
90                 } \
91                 PCD = EAD; \
92                 CYCLES(1); \
93         } \
94 }
95
96 // Helper macros to build the effective address
97
98 #define EA_ZPG \
99         ZPL = RDOPARG(); \
100         EAD = ZPD
101
102 #define EA_ZPX \
103         ZPL = RDOPARG(); \
104         RDMEM(ZPD); \
105         ZPL = X + ZPL; \
106         EAD = ZPD
107
108 #define EA_ZPY \
109         ZPL = RDOPARG(); \
110         RDMEM(ZPD); \
111         ZPL = Y + ZPL; \
112         EAD = ZPD
113
114 #define EA_ABS \
115         EAL = RDOPARG(); \
116         EAH = RDOPARG()
117
118 #define EA_ABX_P \
119         EA_ABS; \
120         if(EAL + X > 0xff) { \
121                 RDMEM((EAH << 8) | ((EAL + X) & 0xff)); \
122                 CYCLES(1); \
123         } \
124         EAW += X;
125
126 #define EA_ABX_NP \
127         EA_ABS; \
128         RDMEM((EAH << 8) | ((EAL + X) & 0xff)); \
129         EAW += X
130
131 #define EA_ABY_P \
132         EA_ABS; \
133         if(EAL + Y > 0xff) { \
134                 RDMEM((EAH << 8) | ((EAL + Y) & 0xff)); \
135                 CYCLES(1); \
136         } \
137         EAW += Y;
138
139 #define EA_ABY_NP \
140         EA_ABS; \
141         RDMEM((EAH << 8) | ((EAL + Y) & 0xff)); \
142         EAW += Y
143
144 #define EA_IDX \
145         ZPL = RDOPARG(); \
146         RDMEM(ZPD); \
147         ZPL = ZPL + X; \
148         EAL = RDMEM(ZPD); \
149         ZPL++; \
150         EAH = RDMEM(ZPD)
151
152 #define EA_IDY_P \
153         ZPL = RDOPARG(); \
154         EAL = RDMEM(ZPD); \
155         ZPL++; \
156         EAH = RDMEM(ZPD); \
157         if(EAL + Y > 0xff) { \
158                 RDMEM((EAH << 8) | ((EAL + Y) & 0xff)); \
159                 CYCLES(1); \
160         } \
161         EAW += Y;
162
163 #define EA_IDY_NP \
164         ZPL = RDOPARG(); \
165         EAL = RDMEM(ZPD); \
166         ZPL++; \
167         EAH = RDMEM(ZPD); \
168         RDMEM((EAH << 8) | ((EAL + Y) & 0xff)); \
169         EAW += Y
170
171 #define EA_ZPI \
172         ZPL = RDOPARG(); \
173         EAL = RDMEM(ZPD); \
174         ZPL++; \
175         EAH = RDMEM(ZPD)
176
177 #define EA_IND \
178         EA_ABS; \
179         tmp = RDMEM(EAD); \
180         EAL++; \
181         EAH = RDMEM(EAD); \
182         EAL = tmp
183
184 // read a value into tmp
185
186 #define RD_IMM          tmp = RDOPARG()
187 #define RD_DUM          RDMEM(PCW)
188 #define RD_ACC          tmp = A
189 #define RD_ZPG          EA_ZPG; tmp = RDMEM(EAD)
190 #define RD_ZPX          EA_ZPX; tmp = RDMEM(EAD)
191 #define RD_ZPY          EA_ZPY; tmp = RDMEM(EAD)
192 #define RD_ABS          EA_ABS; tmp = RDMEM(EAD)
193 #define RD_ABX_P        EA_ABX_P; tmp = RDMEM(EAD)
194 #define RD_ABX_NP       EA_ABX_NP; tmp = RDMEM(EAD)
195 #define RD_ABY_P        EA_ABY_P; tmp = RDMEM(EAD)
196 #define RD_ABY_NP       EA_ABY_NP; tmp = RDMEM(EAD)
197 #define RD_IDX          EA_IDX; tmp = RDMEM_ID(EAD)
198 #define RD_IDY_P        EA_IDY_P; tmp = RDMEM_ID(EAD)
199 #define RD_IDY_NP       EA_IDY_NP; tmp = RDMEM_ID(EAD)
200 #define RD_ZPI          EA_ZPI; tmp = RDMEM(EAD)
201
202 // write a value from tmp
203
204 #define WR_ZPG          EA_ZPG; WRMEM(EAD, tmp)
205 #define WR_ZPX          EA_ZPX; WRMEM(EAD, tmp)
206 #define WR_ZPY          EA_ZPY; WRMEM(EAD, tmp)
207 #define WR_ABS          EA_ABS; WRMEM(EAD, tmp)
208 #define WR_ABX_NP       EA_ABX_NP; WRMEM(EAD, tmp)
209 #define WR_ABY_NP       EA_ABY_NP; WRMEM(EAD, tmp)
210 #define WR_IDX          EA_IDX; WRMEM_ID(EAD, tmp)
211 #define WR_IDY_NP       EA_IDY_NP; WRMEM_ID(EAD, tmp)
212 #define WR_ZPI          EA_ZPI; WRMEM(EAD, tmp)
213
214 // dummy read from the last EA
215
216 #define RD_EA   RDMEM(EAD)
217
218 // write back a value from tmp to the last EA
219
220 #define WB_ACC  A = (uint8_t)tmp;
221 #define WB_EA   WRMEM(EAD, tmp)
222
223 // opcodes
224
225 #define PUSH(Rg) WRMEM(SPD, Rg); S--
226 #define PULL(Rg) S++; Rg = RDMEM(SPD)
227
228 #ifdef HAS_N2A03
229 #define ADC \
230         { \
231                 int c = (P & F_C); \
232                 int sum = A + tmp + c; \
233                 P &= ~(F_V | F_C); \
234                 if(~(A ^ tmp) & (A ^ sum) & F_N) { \
235                         P |= F_V; \
236                 } \
237                 if(sum & 0xff00) { \
238                         P |= F_C; \
239                 } \
240                 A = (uint8_t)sum; \
241         } \
242         SET_NZ(A)
243 #else
244 #define ADC \
245         if(P & F_D) { \
246                 int c = (P & F_C); \
247                 int lo = (A & 0x0f) + (tmp & 0x0f) + c; \
248                 int hi = (A & 0xf0) + (tmp & 0xf0); \
249                 P &= ~(F_V | F_C | F_N | F_Z); \
250                 if(!((lo + hi) & 0xff)) { \
251                         P |= F_Z; \
252                 } \
253                 if(lo > 0x09) { \
254                         hi += 0x10; \
255                         lo += 0x06; \
256                 } \
257                 if(hi & 0x80) { \
258                         P |= F_N; \
259                 } \
260                 if(~(A ^ tmp) & (A ^ hi) & F_N) { \
261                         P |= F_V; \
262                 } \
263                 if(hi > 0x90) { \
264                         hi += 0x60; \
265                 } \
266                 if(hi & 0xff00) { \
267                         P |= F_C; \
268                 } \
269                 A = (lo & 0x0f) + (hi & 0xf0); \
270         } else { \
271                 int c = (P & F_C); \
272                 int sum = A + tmp + c; \
273                 P &= ~(F_V | F_C); \
274                 if(~(A ^ tmp) & (A ^ sum) & F_N) { \
275                         P |= F_V; \
276                 } \
277                 if(sum & 0xff00) { \
278                         P |= F_C; \
279                 } \
280                 A = (uint8_t)sum; \
281                 SET_NZ(A); \
282         }
283 #endif
284
285 #define AND \
286         A = (uint8_t)(A & tmp); \
287         SET_NZ(A)
288
289 #define ASL \
290         P = (P & ~F_C) | ((tmp >> 7) & F_C); \
291         tmp = (uint8_t)(tmp << 1); \
292         SET_NZ(tmp)
293
294 #define BCC BRA(!(P & F_C))
295 #define BCS BRA(P & F_C)
296 #define BEQ BRA(P & F_Z)
297
298 #define BIT \
299         P &= ~(F_N | F_V | F_Z); \
300         P |= tmp & (F_N | F_V); \
301         if((tmp & A) == 0) \
302                 P |= F_Z
303
304 #define BMI BRA(P & F_N)
305 #define BNE BRA(!(P & F_Z))
306 #define BPL BRA(!(P & F_N))
307
308 #define BRK \
309         RDOPARG(); \
310         PUSH(PCH); \
311         PUSH(PCL); \
312         PUSH(P | F_B); \
313         P = (P | F_I); \
314         PCL = RDMEM(IRQ_VEC); \
315         PCH = RDMEM(IRQ_VEC + 1)
316
317 #define BVC BRA(!(P & F_V))
318 #define BVS BRA(P & F_V)
319
320 #define CLC P &= ~F_C
321 #define CLD P &= ~F_D
322 #define CLI \
323         if(irq_state && (P & F_I)) { \
324                 if(PEEKOP() != 0x40) { \
325                         after_cli = true; \
326                 } \
327         } \
328         P &= ~F_I
329 #define CLV P &= ~F_V
330
331 #define CMP \
332         P &= ~F_C; \
333         if(A >= tmp) { \
334                 P |= F_C; \
335         } \
336         SET_NZ((uint8_t)(A - tmp))
337 #define CPX \
338         P &= ~F_C; \
339         if(X >= tmp) { \
340                 P |= F_C; \
341         } \
342         SET_NZ((uint8_t)(X - tmp))
343 #define CPY \
344         P &= ~F_C; \
345         if(Y >= tmp) { \
346                 P |= F_C; \
347         } \
348         SET_NZ((uint8_t)(Y - tmp))
349
350 #define DEC \
351         tmp = (uint8_t)(tmp - 1); \
352         SET_NZ(tmp)
353 #define DEX \
354         X = (uint8_t)(X - 1); \
355         SET_NZ(X)
356 #define DEY \
357         Y = (uint8_t)(Y - 1); \
358         SET_NZ(Y)
359
360 #define EOR \
361         A = (uint8_t)(A ^ tmp); \
362         SET_NZ(A)
363
364 #define INC \
365         tmp = (uint8_t)(tmp + 1); \
366         SET_NZ(tmp)
367 #define INX \
368         X = (uint8_t)(X + 1); \
369         SET_NZ(X)
370 #define INY \
371         Y = (uint8_t)(Y + 1); \
372         SET_NZ(Y)
373
374 #define JMP PCD = EAD
375 #define JSR \
376         EAL = RDOPARG(); \
377         RDMEM(SPD); \
378         PUSH(PCH); \
379         PUSH(PCL); \
380         EAH = RDOPARG(); \
381         PCD = EAD
382
383 #define LDA \
384         A = (uint8_t)tmp; \
385         SET_NZ(A)
386 #define LDX \
387         X = (uint8_t)tmp; \
388         SET_NZ(X)
389 #define LDY \
390         Y = (uint8_t)tmp; \
391         SET_NZ(Y)
392
393 #define LSR \
394         P = (P & ~F_C) | (tmp & F_C); \
395         tmp = (uint8_t)tmp >> 1; \
396         SET_NZ(tmp)
397
398 #define NOP
399
400 #define ORA \
401         A = (uint8_t)(A | tmp); \
402         SET_NZ(A)
403
404 #define PHA PUSH(A)
405 #define PHP PUSH(P)
406
407 #define PLA \
408         RDMEM(SPD); \
409         PULL(A); \
410         SET_NZ(A)
411 #define PLP \
412         RDMEM(SPD); \
413         if(P & F_I) { \
414                 PULL(P); \
415                 if(irq_state && !(P & F_I)) { \
416                         after_cli = true; \
417                 } \
418         } else { \
419                 PULL(P); \
420         } \
421         P |= (F_T | F_B);
422
423 #define ROL \
424         tmp = (tmp << 1) | (P & F_C); \
425         P = (P & ~F_C) | ((tmp >> 8) & F_C); \
426         tmp = (uint8_t)tmp; \
427         SET_NZ(tmp)
428 #define ROR \
429         tmp |= (P & F_C) << 8; \
430         P = (P & ~F_C) | (tmp & F_C); \
431         tmp = (uint8_t)(tmp >> 1); \
432         SET_NZ(tmp)
433
434 #define RTI \
435         RDOPARG(); \
436         RDMEM(SPD); \
437         PULL(P); \
438         PULL(PCL); \
439         PULL(PCH); \
440         P |= F_T | F_B; \
441         if(irq_state && !(P & F_I)) { \
442                 after_cli = true; \
443         }
444 #define RTS \
445         RDOPARG(); \
446         RDMEM(SPD); \
447         PULL(PCL); \
448         PULL(PCH); \
449         RDMEM(PCW); \
450         PCW++
451
452 #ifdef HAS_N2A03
453 #define SBC \
454         { \
455                 int c = (P & F_C) ^ F_C; \
456                 int sum = A - tmp - c; \
457                 P &= ~(F_V | F_C); \
458                 if((A ^ tmp) & (A ^ sum) & F_N) { \
459                         P |= F_V; \
460                 } \
461                 if((sum & 0xff00) == 0) { \
462                         P |= F_C; \
463                 } \
464                 A = (uint8_t)sum; \
465         } \
466         SET_NZ(A)
467 #else
468 #define SBC \
469         if(P & F_D) { \
470                 int c = (P & F_C) ^ F_C; \
471                 int sum = A - tmp - c; \
472                 int lo = (A & 0x0f) - (tmp & 0x0f) - c; \
473                 int hi = (A & 0xf0) - (tmp & 0xf0); \
474                 if(lo & 0x10) { \
475                         lo -= 6; \
476                         hi--; \
477                 } \
478                 P &= ~(F_V | F_C | F_Z | F_N); \
479                 if((A ^ tmp) & (A ^ sum) & F_N) { \
480                         P |= F_V; \
481                 } \
482                 if(hi & 0x0100) { \
483                         hi -= 0x60; \
484                 } \
485                 if((sum & 0xff00) == 0) { \
486                         P |= F_C; \
487                 } \
488                 if(!((A - tmp - c) & 0xff)) { \
489                         P |= F_Z; \
490                 }
491                 if((A - tmp - c) & 0x80) { \
492                         P |= F_N; \
493                 } \
494                 A = (lo & 0x0f) | (hi & 0xf0); \
495         } else { \
496                 int c = (P & F_C) ^ F_C; \
497                 int sum = A - tmp - c; \
498                 P &= ~(F_V | F_C); \
499                 if((A ^ tmp) & (A ^ sum) & F_N) { \
500                         P |= F_V; \
501                 } \
502                 if((sum & 0xff00) == 0) { \
503                         P |= F_C; \
504                 } \
505                 A = (uint8_t)sum; \
506                 SET_NZ(A); \
507         }
508 #endif
509
510 #define SEC P |= F_C
511 #define SED P |= F_D
512 #define SEI P |= F_I
513
514 #define STA tmp = A
515 #define STX tmp = X
516 #define STY tmp = Y
517
518 #define TAX \
519         X = A; \
520         SET_NZ(X)
521 #define TAY \
522         Y = A; \
523         SET_NZ(Y)
524 #define TSX \
525         X = S; \
526         SET_NZ(X)
527 #define TXA \
528         A = X; \
529         SET_NZ(A)
530 #define TXS S = X
531 #define TYA \
532         A = Y; \
533         SET_NZ(A)
534
535 #define ANC \
536         P &= ~F_C; \
537         A = (uint8_t)(A & tmp); \
538         if(A & 0x80) { \
539                 P |= F_C; \
540         } \
541         SET_NZ(A)
542
543 #define ASR \
544         tmp &= A; \
545         LSR
546
547 #define AST \
548         S &= tmp; \
549         A = X = S; \
550         SET_NZ(A)
551
552 #ifdef HAS_N2A03
553 #define ARR \
554         { \
555                 tmp &= A; \
556                 ROR; \
557                 P &=~(F_V| F_C); \
558                 if(tmp & 0x40) { \
559                         P |= F_C; \
560                 } \
561                 if((tmp & 0x60) == 0x20 || (tmp & 0x60) == 0x40) { \
562                         P |= F_V; \
563                 } \
564         }
565 #else
566 #define ARR \
567         if(P & F_D) { \
568                 tmp &= A; \
569                 int t = tmp; \
570                 int hi = tmp & 0xf0; \
571                 int lo = tmp & 0x0f; \
572                 if(P & F_C) { \
573                         tmp = (tmp >> 1) | 0x80; \
574                         P |= F_N; \
575                 } else { \
576                         tmp >>= 1; \
577                         P &= ~F_N; \
578                 } \
579                 if(tmp) { \
580                         P &= ~F_Z; \
581                 } else { \
582                         P |= F_Z; \
583                 } \
584                 if((t ^ tmp) & 0x40) { \
585                         P |= F_V; \
586                 } else { \
587                         P &= ~F_V; \
588                 } \
589                 if(lo + (lo & 0x01) > 0x05) { \
590                         tmp = (tmp & 0xf0) | ((tmp + 6) & 0x0f); \
591                 } \
592                 if(hi + (hi & 0x10) > 0x50) { \
593                         P |= F_C; \
594                         tmp = (tmp+0x60) & 0xff; \
595                 } else { \
596                         P &= ~F_C; \
597                 } \
598         } else { \
599                 tmp &= A; \
600                 ROR; \
601                 P &=~(F_V| F_C); \
602                 if(tmp & 0x40) { \
603                         P |= F_C; \
604                 } \
605                 if((tmp & 0x60) == 0x20 || (tmp & 0x60) == 0x40) { \
606                         P |= F_V; \
607                 } \
608         }
609 #endif
610
611 #define ASX \
612         P &= ~F_C; \
613         X &= A; \
614         if(X >= tmp) { \
615                 P |= F_C; \
616         } \
617         X = (uint8_t)(X - tmp); \
618         SET_NZ(X)
619
620 #define AXA \
621         A = (uint8_t)((A | 0xee) & X & tmp); \
622         SET_NZ(A)
623
624 #define DCP \
625         tmp = (uint8_t)(tmp - 1); \
626         P &= ~F_C; \
627         if(A >= tmp) { \
628                 P |= F_C; \
629         } \
630         SET_NZ((uint8_t)(A - tmp))
631
632 #define DOP RDOPARG()
633
634 #define ISB \
635         tmp = (uint8_t)(tmp + 1); \
636         SBC
637
638 #define LAX \
639         A = X = (uint8_t)tmp; \
640         SET_NZ(A)
641
642 #ifdef HAS_N2A03
643 #define OAL \
644         A = X = (uint8_t)((A | 0xff) & tmp); \
645         SET_NZ(A)
646 #else
647 #define OAL \
648         A = X = (uint8_t)((A | 0xee) & tmp); \
649         SET_NZ(A)
650 #endif
651
652 #define RLA \
653         tmp = (tmp << 1) | (P & F_C); \
654         P = (P & ~F_C) | ((tmp >> 8) & F_C); \
655         tmp = (uint8_t)tmp; \
656         A &= tmp; \
657         SET_NZ(A)
658 #define RRA \
659         tmp |= (P & F_C) << 8; \
660         P = (P & ~F_C) | (tmp & F_C); \
661         tmp = (uint8_t)(tmp >> 1); \
662         ADC
663
664 #define SAX tmp = A & X
665
666 #define SLO \
667         P = (P & ~F_C) | ((tmp >> 7) & F_C); \
668         tmp = (uint8_t)(tmp << 1); \
669         A |= tmp; \
670         SET_NZ(A)
671
672 #define SRE \
673         P = (P & ~F_C) | (tmp & F_C); \
674         tmp = (uint8_t)tmp >> 1; \
675         A ^= tmp; \
676         SET_NZ(A)
677
678 #define SAH tmp = A & X & (EAH + 1)
679
680 #define SSH \
681         S = A & X; \
682         tmp = S & (EAH + 1)
683
684 #ifdef HAS_N2A03
685 #define SXH \
686         if(Y && Y > EAL) { \
687                 EAH |= (Y << 1); \
688         } \
689         tmp = X & (EAH + 1)
690 #define SYH \
691         if(X && X > EAL) { \
692                 EAH |= (X << 1); \
693         } \
694         tmp = Y & (EAH + 1)
695 #else
696 #define SXH tmp = X & (EAH + 1)
697 #define SYH tmp = Y & (EAH + 1)
698 #endif
699
700 #define TOP PCW += 2
701 #define KIL PCW--
702
703 void M6502::OP(uint8_t code)
704 {
705         int tmp;
706         
707         switch(code) {
708         case 0x00: { CYCLES(7);                    BRK;            } break; /* 7 BRK */
709         case 0x01: { CYCLES(6); RD_IDX;            ORA;            } break; /* 6 ORA IDX */
710         case 0x02: { CYCLES(1);                    KIL;            } break; /* 1 KIL */
711         case 0x03: { CYCLES(7); RD_IDX;    RD_EA;  SLO; WB_EA;     } break; /* 7 SLO IDX */
712         case 0x04: { CYCLES(3); RD_ZPG;            NOP;            } break; /* 3 NOP ZPG */
713         case 0x05: { CYCLES(3); RD_ZPG;            ORA;            } break; /* 3 ORA ZPG */
714         case 0x06: { CYCLES(5); RD_ZPG;    RD_EA;  ASL; WB_EA;     } break; /* 5 ASL ZPG */
715         case 0x07: { CYCLES(5); RD_ZPG;    RD_EA;  SLO; WB_EA;     } break; /* 5 SLO ZPG */
716         case 0x08: { CYCLES(3); RD_DUM;            PHP;            } break; /* 3 PHP */
717         case 0x09: { CYCLES(2); RD_IMM;            ORA;            } break; /* 2 ORA IMM */
718         case 0x0a: { CYCLES(2); RD_DUM;    RD_ACC; ASL; WB_ACC;    } break; /* 2 ASL A */
719         case 0x0b: { CYCLES(2); RD_IMM;            ANC;            } break; /* 2 ANC IMM */
720         case 0x0c: { CYCLES(4); RD_ABS;            NOP;            } break; /* 4 NOP ABS */
721         case 0x0d: { CYCLES(4); RD_ABS;            ORA;            } break; /* 4 ORA ABS */
722         case 0x0e: { CYCLES(6); RD_ABS;    RD_EA;  ASL; WB_EA;     } break; /* 6 ASL ABS */
723         case 0x0f: { CYCLES(6); RD_ABS;    RD_EA;  SLO; WB_EA;     } break; /* 6 SLO ABS */
724         case 0x10: { CYCLES(2);                    BPL;            } break; /* 2-4 BPL REL */
725         case 0x11: { CYCLES(5); RD_IDY_P;          ORA;            } break; /* 5 ORA IDY page penalty */
726         case 0x12: { CYCLES(1);                    KIL;            } break; /* 1 KIL */
727         case 0x13: { CYCLES(7); RD_IDY_NP; RD_EA;  SLO; WB_EA;     } break; /* 7 SLO IDY */
728         case 0x14: { CYCLES(4); RD_ZPX;            NOP;            } break; /* 4 NOP ZPX */
729         case 0x15: { CYCLES(4); RD_ZPX;            ORA;            } break; /* 4 ORA ZPX */
730         case 0x16: { CYCLES(6); RD_ZPX;    RD_EA;  ASL; WB_EA;     } break; /* 6 ASL ZPX */
731         case 0x17: { CYCLES(6); RD_ZPX;    RD_EA;  SLO; WB_EA;     } break; /* 6 SLO ZPX */
732         case 0x18: { CYCLES(2); RD_DUM;            CLC;            } break; /* 2 CLC */
733         case 0x19: { CYCLES(4); RD_ABY_P;          ORA;            } break; /* 4 ORA ABY page penalty */
734         case 0x1a: { CYCLES(2); RD_DUM;            NOP;            } break; /* 2 NOP */
735         case 0x1b: { CYCLES(7); RD_ABY_NP; RD_EA;  SLO; WB_EA;     } break; /* 7 SLO ABY */
736         case 0x1c: { CYCLES(4); RD_ABX_P;          NOP;            } break; /* 4 NOP ABX page penalty */
737         case 0x1d: { CYCLES(4); RD_ABX_P;          ORA;            } break; /* 4 ORA ABX page penalty */
738         case 0x1e: { CYCLES(7); RD_ABX_NP; RD_EA;  ASL; WB_EA;     } break; /* 7 ASL ABX */
739         case 0x1f: { CYCLES(7); RD_ABX_NP; RD_EA;  SLO; WB_EA;     } break; /* 7 SLO ABX */
740         case 0x20: { CYCLES(6);                    JSR;            } break; /* 6 JSR */
741         case 0x21: { CYCLES(6); RD_IDX;            AND;            } break; /* 6 AND IDX */
742         case 0x22: { CYCLES(1);                    KIL;            } break; /* 1 KIL */
743         case 0x23: { CYCLES(7); RD_IDX;    RD_EA;  RLA; WB_EA;     } break; /* 7 RLA IDX */
744         case 0x24: { CYCLES(3); RD_ZPG;            BIT;            } break; /* 3 BIT ZPG */
745         case 0x25: { CYCLES(3); RD_ZPG;            AND;            } break; /* 3 AND ZPG */
746         case 0x26: { CYCLES(5); RD_ZPG;    RD_EA;  ROL; WB_EA;     } break; /* 5 ROL ZPG */
747         case 0x27: { CYCLES(5); RD_ZPG;    RD_EA;  RLA; WB_EA;     } break; /* 5 RLA ZPG */
748         case 0x28: { CYCLES(4); RD_DUM;            PLP;            } break; /* 4 PLP */
749         case 0x29: { CYCLES(2); RD_IMM;            AND;            } break; /* 2 AND IMM */
750         case 0x2a: { CYCLES(2); RD_DUM;    RD_ACC; ROL; WB_ACC;    } break; /* 2 ROL A */
751         case 0x2b: { CYCLES(2); RD_IMM;            ANC;            } break; /* 2 ANC IMM */
752         case 0x2c: { CYCLES(4); RD_ABS;            BIT;            } break; /* 4 BIT ABS */
753         case 0x2d: { CYCLES(4); RD_ABS;            AND;            } break; /* 4 AND ABS */
754         case 0x2e: { CYCLES(6); RD_ABS;    RD_EA;  ROL; WB_EA;     } break; /* 6 ROL ABS */
755         case 0x2f: { CYCLES(6); RD_ABS;    RD_EA;  RLA; WB_EA;     } break; /* 6 RLA ABS */
756         case 0x30: { CYCLES(2);                    BMI;            } break; /* 2-4 BMI REL */
757         case 0x31: { CYCLES(5); RD_IDY_P;          AND;            } break; /* 5 AND IDY page penalty */
758         case 0x32: { CYCLES(1);                    KIL;            } break; /* 1 KIL */
759         case 0x33: { CYCLES(7); RD_IDY_NP; RD_EA;  RLA; WB_EA;     } break; /* 7 RLA IDY */
760         case 0x34: { CYCLES(4); RD_ZPX;            NOP;            } break; /* 4 NOP ZPX */
761         case 0x35: { CYCLES(4); RD_ZPX;            AND;            } break; /* 4 AND ZPX */
762         case 0x36: { CYCLES(6); RD_ZPX;    RD_EA;  ROL; WB_EA;     } break; /* 6 ROL ZPX */
763         case 0x37: { CYCLES(6); RD_ZPX;    RD_EA;  RLA; WB_EA;     } break; /* 6 RLA ZPX */
764         case 0x38: { CYCLES(2); RD_DUM;            SEC;            } break; /* 2 SEC */
765         case 0x39: { CYCLES(4); RD_ABY_P;          AND;            } break; /* 4 AND ABY page penalty */
766         case 0x3a: { CYCLES(2); RD_DUM;            NOP;            } break; /* 2 NOP */
767         case 0x3b: { CYCLES(7); RD_ABY_NP; RD_EA;  RLA; WB_EA;     } break; /* 7 RLA ABY */
768         case 0x3c: { CYCLES(4); RD_ABX_P;          NOP;            } break; /* 4 NOP ABX page penalty */
769         case 0x3d: { CYCLES(4); RD_ABX_P;          AND;            } break; /* 4 AND ABX page penalty */
770         case 0x3e: { CYCLES(7); RD_ABX_NP; RD_EA;  ROL; WB_EA;     } break; /* 7 ROL ABX */
771         case 0x3f: { CYCLES(7); RD_ABX_NP; RD_EA;  RLA; WB_EA;     } break; /* 7 RLA ABX */
772         case 0x40: { CYCLES(6);                    RTI;            } break; /* 6 RTI */
773         case 0x41: { CYCLES(6); RD_IDX;            EOR;            } break; /* 6 EOR IDX */
774         case 0x42: { CYCLES(1);                    KIL;            } break; /* 1 KIL */
775         case 0x43: { CYCLES(7); RD_IDX;    RD_EA;  SRE; WB_EA;     } break; /* 7 SRE IDX */
776         case 0x44: { CYCLES(3); RD_ZPG;            NOP;            } break; /* 3 NOP ZPG */
777         case 0x45: { CYCLES(3); RD_ZPG;            EOR;            } break; /* 3 EOR ZPG */
778         case 0x46: { CYCLES(5); RD_ZPG;    RD_EA;  LSR; WB_EA;     } break; /* 5 LSR ZPG */
779         case 0x47: { CYCLES(5); RD_ZPG;    RD_EA;  SRE; WB_EA;     } break; /* 5 SRE ZPG */
780         case 0x48: { CYCLES(3); RD_DUM;            PHA;            } break; /* 3 PHA */
781         case 0x49: { CYCLES(2); RD_IMM;            EOR;            } break; /* 2 EOR IMM */
782         case 0x4a: { CYCLES(2); RD_DUM;    RD_ACC; LSR; WB_ACC;    } break; /* 2 LSR A */
783         case 0x4b: { CYCLES(2); RD_IMM;            ASR; WB_ACC;    } break; /* 2 ASR IMM */
784         case 0x4c: { CYCLES(3); EA_ABS;            JMP;            } break; /* 3 JMP ABS */
785         case 0x4d: { CYCLES(4); RD_ABS;            EOR;            } break; /* 4 EOR ABS */
786         case 0x4e: { CYCLES(6); RD_ABS;    RD_EA;  LSR; WB_EA;     } break; /* 6 LSR ABS */
787         case 0x4f: { CYCLES(6); RD_ABS;    RD_EA;  SRE; WB_EA;     } break; /* 6 SRE ABS */
788         case 0x50: { CYCLES(2);                    BVC;            } break; /* 2-4 BVC REL */
789         case 0x51: { CYCLES(5); RD_IDY_P;          EOR;            } break; /* 5 EOR IDY page penalty */
790         case 0x52: { CYCLES(1);                    KIL;            } break; /* 1 KIL */
791         case 0x53: { CYCLES(7); RD_IDY_NP; RD_EA;  SRE; WB_EA;     } break; /* 7 SRE IDY */
792         case 0x54: { CYCLES(4); RD_ZPX;            NOP;            } break; /* 4 NOP ZPX */
793         case 0x55: { CYCLES(4); RD_ZPX;            EOR;            } break; /* 4 EOR ZPX */
794         case 0x56: { CYCLES(6); RD_ZPX;    RD_EA;  LSR; WB_EA;     } break; /* 6 LSR ZPX */
795         case 0x57: { CYCLES(6); RD_ZPX;    RD_EA;  SRE; WB_EA;     } break; /* 6 SRE ZPX */
796         case 0x58: { CYCLES(2); RD_DUM;            CLI;            } break; /* 2 CLI */
797         case 0x59: { CYCLES(4); RD_ABY_P;          EOR;            } break; /* 4 EOR ABY page penalty */
798         case 0x5a: { CYCLES(2); RD_DUM;            NOP;            } break; /* 2 NOP */
799         case 0x5b: { CYCLES(7); RD_ABY_NP; RD_EA;  SRE; WB_EA;     } break; /* 7 SRE ABY */
800         case 0x5c: { CYCLES(4); RD_ABX_P;          NOP;            } break; /* 4 NOP ABX page penalty */
801         case 0x5d: { CYCLES(4); RD_ABX_P;          EOR;            } break; /* 4 EOR ABX page penalty */
802         case 0x5e: { CYCLES(7); RD_ABX_NP; RD_EA;  LSR; WB_EA;     } break; /* 7 LSR ABX */
803         case 0x5f: { CYCLES(7); RD_ABX_NP; RD_EA;  SRE; WB_EA;     } break; /* 7 SRE ABX */
804         case 0x60: { CYCLES(6);                    RTS;            } break; /* 6 RTS */
805         case 0x61: { CYCLES(6); RD_IDX;            ADC;            } break; /* 6 ADC IDX */
806         case 0x62: { CYCLES(1);                    KIL;            } break; /* 1 KIL */
807         case 0x63: { CYCLES(7); RD_IDX;    RD_EA;  RRA; WB_EA;     } break; /* 7 RRA IDX */
808         case 0x64: { CYCLES(3); RD_ZPG;            NOP;            } break; /* 3 NOP ZPG */
809         case 0x65: { CYCLES(3); RD_ZPG;            ADC;            } break; /* 3 ADC ZPG */
810         case 0x66: { CYCLES(5); RD_ZPG;    RD_EA;  ROR; WB_EA;     } break; /* 5 ROR ZPG */
811         case 0x67: { CYCLES(5); RD_ZPG;    RD_EA;  RRA; WB_EA;     } break; /* 5 RRA ZPG */
812         case 0x68: { CYCLES(4); RD_DUM;            PLA;            } break; /* 4 PLA */
813         case 0x69: { CYCLES(2); RD_IMM;            ADC;            } break; /* 2 ADC IMM */
814         case 0x6a: { CYCLES(2); RD_DUM;    RD_ACC; ROR; WB_ACC;    } break; /* 2 ROR A */
815         case 0x6b: { CYCLES(2); RD_IMM;            ARR; WB_ACC;    } break; /* 2 ARR IMM */
816         case 0x6c: { CYCLES(5); EA_IND;            JMP;            } break; /* 5 JMP IND */
817         case 0x6d: { CYCLES(4); RD_ABS;            ADC;            } break; /* 4 ADC ABS */
818         case 0x6e: { CYCLES(6); RD_ABS;    RD_EA;  ROR; WB_EA;     } break; /* 6 ROR ABS */
819         case 0x6f: { CYCLES(6); RD_ABS;    RD_EA;  RRA; WB_EA;     } break; /* 6 RRA ABS */
820         case 0x70: { CYCLES(2);                    BVS;            } break; /* 2-4 BVS REL */
821         case 0x71: { CYCLES(5); RD_IDY_P;          ADC;            } break; /* 5 ADC IDY page penalty */
822         case 0x72: { CYCLES(1);                    KIL;            } break; /* 1 KIL */
823         case 0x73: { CYCLES(7); RD_IDY_NP; RD_EA;  RRA; WB_EA;     } break; /* 7 RRA IDY */
824         case 0x74: { CYCLES(4); RD_ZPX;            NOP;            } break; /* 4 NOP ZPX */
825         case 0x75: { CYCLES(4); RD_ZPX;            ADC;            } break; /* 4 ADC ZPX */
826         case 0x76: { CYCLES(6); RD_ZPX;    RD_EA;  ROR; WB_EA;     } break; /* 6 ROR ZPX */
827         case 0x77: { CYCLES(6); RD_ZPX;    RD_EA;  RRA; WB_EA;     } break; /* 6 RRA ZPX */
828         case 0x78: { CYCLES(2); RD_DUM;            SEI;            } break; /* 2 SEI */
829         case 0x79: { CYCLES(4); RD_ABY_P;          ADC;            } break; /* 4 ADC ABY page penalty */
830         case 0x7a: { CYCLES(2); RD_DUM;            NOP;            } break; /* 2 NOP */
831         case 0x7b: { CYCLES(7); RD_ABY_NP; RD_EA;  RRA; WB_EA;     } break; /* 7 RRA ABY */
832         case 0x7c: { CYCLES(4); RD_ABX_P;          NOP;            } break; /* 4 NOP ABX page penalty */
833         case 0x7d: { CYCLES(4); RD_ABX_P;          ADC;            } break; /* 4 ADC ABX page penalty */
834         case 0x7e: { CYCLES(7); RD_ABX_NP; RD_EA;  ROR; WB_EA;     } break; /* 7 ROR ABX */
835         case 0x7f: { CYCLES(7); RD_ABX_NP; RD_EA;  RRA; WB_EA;     } break; /* 7 RRA ABX */
836         case 0x80: { CYCLES(2); RD_IMM;            NOP;            } break; /* 2 NOP IMM */
837         case 0x81: { CYCLES(6);                    STA; WR_IDX;    } break; /* 6 STA IDX */
838         case 0x82: { CYCLES(2); RD_IMM;            NOP;            } break; /* 2 NOP IMM */
839         case 0x83: { CYCLES(6);                    SAX; WR_IDX;    } break; /* 6 SAX IDX */
840         case 0x84: { CYCLES(3);                    STY; WR_ZPG;    } break; /* 3 STY ZPG */
841         case 0x85: { CYCLES(3);                    STA; WR_ZPG;    } break; /* 3 STA ZPG */
842         case 0x86: { CYCLES(3);                    STX; WR_ZPG;    } break; /* 3 STX ZPG */
843         case 0x87: { CYCLES(3);                    SAX; WR_ZPG;    } break; /* 3 SAX ZPG */
844         case 0x88: { CYCLES(2); RD_DUM;            DEY;            } break; /* 2 DEY */
845         case 0x89: { CYCLES(2); RD_IMM;            NOP;            } break; /* 2 NOP IMM */
846         case 0x8a: { CYCLES(2); RD_DUM;            TXA;            } break; /* 2 TXA */
847         case 0x8b: { CYCLES(2); RD_IMM;            AXA;            } break; /* 2 AXA IMM */
848         case 0x8c: { CYCLES(4);                    STY; WR_ABS;    } break; /* 4 STY ABS */
849         case 0x8d: { CYCLES(4);                    STA; WR_ABS;    } break; /* 4 STA ABS */
850         case 0x8e: { CYCLES(4);                    STX; WR_ABS;    } break; /* 4 STX ABS */
851         case 0x8f: { CYCLES(4);                    SAX; WR_ABS;    } break; /* 4 SAX ABS */
852         case 0x90: { CYCLES(2);                    BCC;            } break; /* 2-4 BCC REL */
853         case 0x91: { CYCLES(6);                    STA; WR_IDY_NP; } break; /* 6 STA IDY */
854         case 0x92: { CYCLES(1);                    KIL;            } break; /* 1 KIL */
855         case 0x93: { CYCLES(5); EA_IDY_NP;         SAH; WB_EA;     } break; /* 5 SAH IDY */
856         case 0x94: { CYCLES(4);                    STY; WR_ZPX;    } break; /* 4 STY ZPX */
857         case 0x95: { CYCLES(4);                    STA; WR_ZPX;    } break; /* 4 STA ZPX */
858         case 0x96: { CYCLES(4);                    STX; WR_ZPY;    } break; /* 4 STX ZPY */
859         case 0x97: { CYCLES(4);                    SAX; WR_ZPY;    } break; /* 4 SAX ZPY */
860         case 0x98: { CYCLES(2); RD_DUM;            TYA;            } break; /* 2 TYA */
861         case 0x99: { CYCLES(5);                    STA; WR_ABY_NP; } break; /* 5 STA ABY */
862         case 0x9a: { CYCLES(2); RD_DUM;            TXS;            } break; /* 2 TXS */
863         case 0x9b: { CYCLES(5); EA_ABY_NP;         SSH; WB_EA;     } break; /* 5 SSH ABY */
864         case 0x9c: { CYCLES(5); EA_ABX_NP;         SYH; WB_EA;     } break; /* 5 SYH ABX */
865         case 0x9d: { CYCLES(5);                    STA; WR_ABX_NP; } break; /* 5 STA ABX */
866         case 0x9e: { CYCLES(5); EA_ABY_NP;         SXH; WB_EA;     } break; /* 5 SXH ABY */
867         case 0x9f: { CYCLES(5); EA_ABY_NP;         SAH; WB_EA;     } break; /* 5 SAH ABY */
868         case 0xa0: { CYCLES(2); RD_IMM;            LDY;            } break; /* 2 LDY IMM */
869         case 0xa1: { CYCLES(6); RD_IDX;            LDA;            } break; /* 6 LDA IDX */
870         case 0xa2: { CYCLES(2); RD_IMM;            LDX;            } break; /* 2 LDX IMM */
871         case 0xa3: { CYCLES(6); RD_IDX;            LAX;            } break; /* 6 LAX IDX */
872         case 0xa4: { CYCLES(3); RD_ZPG;            LDY;            } break; /* 3 LDY ZPG */
873         case 0xa5: { CYCLES(3); RD_ZPG;            LDA;            } break; /* 3 LDA ZPG */
874         case 0xa6: { CYCLES(3); RD_ZPG;            LDX;            } break; /* 3 LDX ZPG */
875         case 0xa7: { CYCLES(3); RD_ZPG;            LAX;            } break; /* 3 LAX ZPG */
876         case 0xa8: { CYCLES(2); RD_DUM;            TAY;            } break; /* 2 TAY */
877         case 0xa9: { CYCLES(2); RD_IMM;            LDA;            } break; /* 2 LDA IMM */
878         case 0xaa: { CYCLES(2); RD_DUM;            TAX;            } break; /* 2 TAX */
879         case 0xab: { CYCLES(2); RD_IMM;            OAL;            } break; /* 2 OAL IMM */
880         case 0xac: { CYCLES(4); RD_ABS;            LDY;            } break; /* 4 LDY ABS */
881         case 0xad: { CYCLES(4); RD_ABS;            LDA;            } break; /* 4 LDA ABS */
882         case 0xae: { CYCLES(4); RD_ABS;            LDX;            } break; /* 4 LDX ABS */
883         case 0xaf: { CYCLES(4); RD_ABS;            LAX;            } break; /* 4 LAX ABS */
884         case 0xb0: { CYCLES(2);                    BCS;            } break; /* 2-4 BCS REL */
885         case 0xb1: { CYCLES(5); RD_IDY_P;          LDA;            } break; /* 5 LDA IDY page penalty */
886         case 0xb2: { CYCLES(1);                    KIL;            } break; /* 1 KIL */
887         case 0xb3: { CYCLES(5); RD_IDY_P;          LAX;            } break; /* 5 LAX IDY page penalty */
888         case 0xb4: { CYCLES(4); RD_ZPX;            LDY;            } break; /* 4 LDY ZPX */
889         case 0xb5: { CYCLES(4); RD_ZPX;            LDA;            } break; /* 4 LDA ZPX */
890         case 0xb6: { CYCLES(4); RD_ZPY;            LDX;            } break; /* 4 LDX ZPY */
891         case 0xb7: { CYCLES(4); RD_ZPY;            LAX;            } break; /* 4 LAX ZPY */
892         case 0xb8: { CYCLES(2); RD_DUM;            CLV;            } break; /* 2 CLV */
893         case 0xb9: { CYCLES(4); RD_ABY_P;          LDA;            } break; /* 4 LDA ABY page penalty */
894         case 0xba: { CYCLES(2); RD_DUM;            TSX;            } break; /* 2 TSX */
895         case 0xbb: { CYCLES(4); RD_ABY_P;          AST;            } break; /* 4 AST ABY page penalty */
896         case 0xbc: { CYCLES(4); RD_ABX_P;          LDY;            } break; /* 4 LDY ABX page penalty */
897         case 0xbd: { CYCLES(4); RD_ABX_P;          LDA;            } break; /* 4 LDA ABX page penalty */
898         case 0xbe: { CYCLES(4); RD_ABY_P;          LDX;            } break; /* 4 LDX ABY page penalty */
899         case 0xbf: { CYCLES(4); RD_ABY_P;          LAX;            } break; /* 4 LAX ABY page penalty */
900         case 0xc0: { CYCLES(2); RD_IMM;            CPY;            } break; /* 2 CPY IMM */
901         case 0xc1: { CYCLES(6); RD_IDX;            CMP;            } break; /* 6 CMP IDX */
902         case 0xc2: { CYCLES(2); RD_IMM;            NOP;            } break; /* 2 NOP IMM */
903         case 0xc3: { CYCLES(7); RD_IDX;    RD_EA;  DCP; WB_EA;     } break; /* 7 DCP IDX */
904         case 0xc4: { CYCLES(3); RD_ZPG;            CPY;            } break; /* 3 CPY ZPG */
905         case 0xc5: { CYCLES(3); RD_ZPG;            CMP;            } break; /* 3 CMP ZPG */
906         case 0xc6: { CYCLES(5); RD_ZPG;    RD_EA;  DEC; WB_EA;     } break; /* 5 DEC ZPG */
907         case 0xc7: { CYCLES(5); RD_ZPG;    RD_EA;  DCP; WB_EA;     } break; /* 5 DCP ZPG */
908         case 0xc8: { CYCLES(2); RD_DUM;            INY;            } break; /* 2 INY */
909         case 0xc9: { CYCLES(2); RD_IMM;            CMP;            } break; /* 2 CMP IMM */
910         case 0xca: { CYCLES(2); RD_DUM;            DEX;            } break; /* 2 DEX */
911         case 0xcb: { CYCLES(2); RD_IMM;            ASX;            } break; /* 2 ASX IMM */
912         case 0xcc: { CYCLES(4); RD_ABS;            CPY;            } break; /* 4 CPY ABS */
913         case 0xcd: { CYCLES(4); RD_ABS;            CMP;            } break; /* 4 CMP ABS */
914         case 0xce: { CYCLES(6); RD_ABS;    RD_EA;  DEC; WB_EA;     } break; /* 6 DEC ABS */
915         case 0xcf: { CYCLES(6); RD_ABS;    RD_EA;  DCP; WB_EA;     } break; /* 6 DCP ABS */
916         case 0xd0: { CYCLES(2);                    BNE;            } break; /* 2-4 BNE REL */
917         case 0xd1: { CYCLES(5); RD_IDY_P;          CMP;            } break; /* 5 CMP IDY page penalty */
918         case 0xd2: { CYCLES(1);                    KIL;            } break; /* 1 KIL */
919         case 0xd3: { CYCLES(7); RD_IDY_NP; RD_EA;  DCP; WB_EA;     } break; /* 7 DCP IDY */
920         case 0xd4: { CYCLES(4); RD_ZPX;            NOP;            } break; /* 4 NOP ZPX */
921         case 0xd5: { CYCLES(4); RD_ZPX;            CMP;            } break; /* 4 CMP ZPX */
922         case 0xd6: { CYCLES(6); RD_ZPX;    RD_EA;  DEC; WB_EA;     } break; /* 6 DEC ZPX */
923         case 0xd7: { CYCLES(6); RD_ZPX;    RD_EA;  DCP; WB_EA;     } break; /* 6 DCP ZPX */
924         case 0xd8: { CYCLES(2); RD_DUM;            CLD;            } break; /* 2 CLD */
925         case 0xd9: { CYCLES(4); RD_ABY_P;          CMP;            } break; /* 4 CMP ABY page penalty */
926         case 0xda: { CYCLES(2); RD_DUM;            NOP;            } break; /* 2 NOP */
927         case 0xdb: { CYCLES(7); RD_ABY_NP; RD_EA;  DCP; WB_EA;     } break; /* 7 DCP ABY */
928         case 0xdc: { CYCLES(4); RD_ABX_P;          NOP;            } break; /* 4 NOP ABX page penalty */
929         case 0xdd: { CYCLES(4); RD_ABX_P;          CMP;            } break; /* 4 CMP ABX page penalty */
930         case 0xde: { CYCLES(7); RD_ABX_NP; RD_EA;  DEC; WB_EA;     } break; /* 7 DEC ABX */
931         case 0xdf: { CYCLES(7); RD_ABX_NP; RD_EA;  DCP; WB_EA;     } break; /* 7 DCP ABX */
932         case 0xe0: { CYCLES(2); RD_IMM;            CPX;            } break; /* 2 CPX IMM */
933         case 0xe1: { CYCLES(6); RD_IDX;            SBC;            } break; /* 6 SBC IDX */
934         case 0xe2: { CYCLES(2); RD_IMM;            NOP;            } break; /* 2 NOP IMM */
935         case 0xe3: { CYCLES(7); RD_IDX;    RD_EA;  ISB; WB_EA;     } break; /* 7 ISB IDX */
936         case 0xe4: { CYCLES(3); RD_ZPG;            CPX;            } break; /* 3 CPX ZPG */
937         case 0xe5: { CYCLES(3); RD_ZPG;            SBC;            } break; /* 3 SBC ZPG */
938         case 0xe6: { CYCLES(5); RD_ZPG;    RD_EA;  INC; WB_EA;     } break; /* 5 INC ZPG */
939         case 0xe7: { CYCLES(5); RD_ZPG;    RD_EA;  ISB; WB_EA;     } break; /* 5 ISB ZPG */
940         case 0xe8: { CYCLES(2); RD_DUM;            INX;            } break; /* 2 INX */
941         case 0xe9: { CYCLES(2); RD_IMM;            SBC;            } break; /* 2 SBC IMM */
942         case 0xea: { CYCLES(2); RD_DUM;            NOP;            } break; /* 2 NOP */
943         case 0xeb: { CYCLES(2); RD_IMM;            SBC;            } break; /* 2 SBC IMM */
944         case 0xec: { CYCLES(4); RD_ABS;            CPX;            } break; /* 4 CPX ABS */
945         case 0xed: { CYCLES(4); RD_ABS;            SBC;            } break; /* 4 SBC ABS */
946         case 0xee: { CYCLES(6); RD_ABS;    RD_EA;  INC; WB_EA;     } break; /* 6 INC ABS */
947         case 0xef: { CYCLES(6); RD_ABS;    RD_EA;  ISB; WB_EA;     } break; /* 6 ISB ABS */
948         case 0xf0: { CYCLES(2);                    BEQ;            } break; /* 2-4 BEQ REL */
949         case 0xf1: { CYCLES(5); RD_IDY_P;          SBC;            } break; /* 5 SBC IDY page penalty */
950         case 0xf2: { CYCLES(1);                    KIL;            } break; /* 1 KIL */
951         case 0xf3: { CYCLES(7); RD_IDY_NP; RD_EA;  ISB; WB_EA;     } break; /* 7 ISB IDY */
952         case 0xf4: { CYCLES(4); RD_ZPX;            NOP;            } break; /* 4 NOP ZPX */
953         case 0xf5: { CYCLES(4); RD_ZPX;            SBC;            } break; /* 4 SBC ZPX */
954         case 0xf6: { CYCLES(6); RD_ZPX;    RD_EA;  INC; WB_EA;     } break; /* 6 INC ZPX */
955         case 0xf7: { CYCLES(6); RD_ZPX;    RD_EA;  ISB; WB_EA;     } break; /* 6 ISB ZPX */
956         case 0xf8: { CYCLES(2); RD_DUM;            SED;            } break; /* 2 SED */
957         case 0xf9: { CYCLES(4); RD_ABY_P;          SBC;            } break; /* 4 SBC ABY page penalty */
958         case 0xfa: { CYCLES(2); RD_DUM;            NOP;            } break; /* 2 NOP */
959         case 0xfb: { CYCLES(7); RD_ABY_NP; RD_EA;  ISB; WB_EA;     } break; /* 7 ISB ABY */
960         case 0xfc: { CYCLES(4); RD_ABX_P;          NOP;            } break; /* 4 NOP ABX page penalty */
961         case 0xfd: { CYCLES(4); RD_ABX_P;          SBC;            } break; /* 4 SBC ABX page penalty */
962         case 0xfe: { CYCLES(7); RD_ABX_NP; RD_EA;  INC; WB_EA;     } break; /* 7 INC ABX */
963         case 0xff: { CYCLES(7); RD_ABX_NP; RD_EA;  ISB; WB_EA;     } break; /* 7 ISB ABX */
964 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
965         default: __assume(0);
966 #endif
967         }
968 }
969
970 inline void M6502::update_irq()
971 {
972         if(!(P & F_I)) {
973                 EAD = IRQ_VEC;
974                 CYCLES(2);
975                 PUSH(PCH);
976                 PUSH(PCL);
977                 PUSH(P & ~F_B);
978                 P |= F_I;
979                 PCL = RDMEM(EAD);
980                 PCH = RDMEM(EAD + 1);
981                 // call back the cpuintrf to let it clear the line
982                 d_pic->notify_intr_reti();
983                 irq_state = false;
984         }
985         pending_irq = false;
986 }
987
988 // main
989
990 void M6502::initialize()
991 {
992         A = X = Y = P = 0;
993         SPD = EAD = ZPD = PCD = 0;
994 #ifdef USE_DEBUGGER
995         d_mem_stored = d_mem;
996         d_debugger->set_context_mem(d_mem);
997 #endif
998 }
999
1000 void M6502::reset()
1001 {
1002         PCL = RDMEM(RST_VEC);
1003         PCH = RDMEM(RST_VEC + 1);
1004         SPD = 0x01ff;
1005         P = F_T | F_I | F_Z | F_B | (P & F_D);
1006         
1007         icount = 0;
1008         pending_irq = after_cli = false;
1009         irq_state = nmi_state = so_state = false;
1010 }
1011
1012 int M6502::run(int clock)
1013 {
1014         if(clock == -1) {
1015                 if (busreq) {
1016                         // don't run cpu!
1017                         return 1;
1018                 } else {
1019                         // run only one opcode
1020                         icount = 0;
1021 #ifdef USE_DEBUGGER
1022                         bool now_debugging = d_debugger->now_debugging;
1023                         if(now_debugging) {
1024                                 d_debugger->check_break_points(PCW);
1025                                 if(d_debugger->now_suspended) {
1026                                         emu->mute_sound();
1027                                         while(d_debugger->now_debugging && d_debugger->now_suspended) {
1028                                                 emu->sleep(10);
1029                                         }
1030                                 }
1031                                 if(d_debugger->now_debugging) {
1032                                         d_mem = d_debugger;
1033                                 } else {
1034                                         now_debugging = false;
1035                                 }
1036                                 
1037                                 run_one_opecode();
1038                                 
1039                                 if(now_debugging) {
1040                                         if(!d_debugger->now_going) {
1041                                                 d_debugger->now_suspended = true;
1042                                         }
1043                                         d_mem = d_mem_stored;
1044                                 }
1045                         } else {
1046 #endif
1047                                 run_one_opecode();
1048 #ifdef USE_DEBUGGER
1049                         }
1050 #endif
1051                         return -icount;
1052                 }
1053         } else {
1054                 icount += clock;
1055                 int first_icount = icount;
1056                 
1057                 // run cpu while given clocks
1058                 while(icount > 0 && !busreq) {
1059 #ifdef USE_DEBUGGER
1060                         bool now_debugging = d_debugger->now_debugging;
1061                         if(now_debugging) {
1062                                 d_debugger->check_break_points(PCW);
1063                                 if(d_debugger->now_suspended) {
1064                                         emu->mute_sound();
1065                                         while(d_debugger->now_debugging && d_debugger->now_suspended) {
1066                                                 emu->sleep(10);
1067                                         }
1068                                 }
1069                                 if(d_debugger->now_debugging) {
1070                                         d_mem = d_debugger;
1071                                 } else {
1072                                         now_debugging = false;
1073                                 }
1074                                 
1075                                 run_one_opecode();
1076                                 
1077                                 if(now_debugging) {
1078                                         if(!d_debugger->now_going) {
1079                                                 d_debugger->now_suspended = true;
1080                                         }
1081                                         d_mem = d_mem_stored;
1082                                 }
1083                         } else {
1084 #endif
1085                                 run_one_opecode();
1086 #ifdef USE_DEBUGGER
1087                         }
1088 #endif
1089                 }
1090                 // if busreq is raised, spin cpu while remained clock
1091                 if(icount > 0 && busreq) {
1092                         icount = 0;
1093                 }
1094                 return first_icount - icount;
1095         }
1096 }
1097
1098 void M6502::run_one_opecode()
1099 {
1100         // if an irq is pending, take it now
1101         if(nmi_state) {
1102                 EAD = NMI_VEC;
1103                 CYCLES(2);
1104                 PUSH(PCH);
1105                 PUSH(PCL);
1106                 PUSH(P & ~F_B);
1107                 P |= F_I;       // set I flag
1108                 PCL = RDMEM(EAD);
1109                 PCH = RDMEM(EAD + 1);
1110                 nmi_state = false;
1111         } else if(pending_irq) {
1112                 update_irq();
1113         }
1114         prev_pc = PCW;
1115         uint8_t code = RDOP();
1116         OP(code);
1117         
1118         // check if the I flag was just reset (interrupts enabled)
1119         if(after_cli) {
1120                 after_cli = false;
1121                 if(irq_state) {
1122                         pending_irq = true;
1123                 }
1124         } else if(pending_irq) {
1125                 update_irq();
1126         }
1127 }
1128
1129 void M6502::write_signal(int id, uint32_t data, uint32_t mask)
1130 {
1131         bool state = ((data & mask) != 0);
1132         
1133         if(id == SIG_CPU_NMI) {
1134                 nmi_state = state;
1135         } else if(id == SIG_CPU_IRQ) {
1136                 irq_state = state;
1137                 if(state) {
1138                         pending_irq = true;
1139                 }
1140         } else if(id == SIG_M6502_OVERFLOW) {
1141                 if(so_state && !state) {
1142                         P |= F_V;
1143                 }
1144                 so_state = state;
1145         } else if(id == SIG_CPU_BUSREQ) {
1146                 busreq = ((data & mask) != 0);
1147         }
1148 }
1149
1150 #ifdef USE_DEBUGGER
1151 void M6502::write_debug_data8(uint32_t addr, uint32_t data)
1152 {
1153         int wait;
1154         d_mem_stored->write_data8w(addr, data, &wait);
1155 }
1156
1157 uint32_t M6502::read_debug_data8(uint32_t addr)
1158 {
1159         int wait;
1160         return d_mem_stored->read_data8w(addr, &wait);
1161 }
1162
1163 bool M6502::write_debug_reg(const _TCHAR *reg, uint32_t data)
1164 {
1165         if(_tcsicmp(reg, _T("PC")) == 0) {
1166                 PCW = data;
1167         } else if(_tcsicmp(reg, _T("A")) == 0) {
1168                 A = data;
1169         } else if(_tcsicmp(reg, _T("X")) == 0) {
1170                 X = data;
1171         } else if(_tcsicmp(reg, _T("Y")) == 0) {
1172                 Y = data;
1173         } else if(_tcsicmp(reg, _T("S")) == 0) {
1174                 S = data;
1175         } else if(_tcsicmp(reg, _T("P")) == 0) {
1176                 P = data;
1177         } else {
1178                 return false;
1179         }
1180         return true;
1181 }
1182
1183 void M6502::get_debug_regs_info(_TCHAR *buffer, size_t buffer_len)
1184 {
1185         my_stprintf_s(buffer, buffer_len,
1186         _T("PC = %04X  A = %02X  X = %02X  Y = %02X  S = %02X  P = %02X [%c%c%c%c%c%c%c%c]"),
1187         PCW, A, X, Y, S, P,
1188         (P & F_N) ? _T('N') : _T('-'), (P & F_V) ? _T('V') : _T('-'), (P & F_T) ? _T('T') : _T('-'), (P & F_B) ? _T('B') : _T('-'), 
1189         (P & F_D) ? _T('D') : _T('-'), (P & F_I) ? _T('I') : _T('-'), (P & F_Z) ? _T('Z') : _T('-'), (P & F_C) ? _T('C') : _T('-'));
1190 }
1191
1192 // disassembler
1193
1194 #define offs_t UINT16
1195
1196 /*****************************************************************************/
1197 /* src/emu/devcpu.h */
1198
1199 // CPU interface functions
1200 #define CPU_DISASSEMBLE_NAME(name)              cpu_disassemble_##name
1201 #define CPU_DISASSEMBLE(name)                   int CPU_DISASSEMBLE_NAME(name)(_TCHAR *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, symbol_t *first_symbol)
1202 #define CPU_DISASSEMBLE_CALL(name)              CPU_DISASSEMBLE_NAME(name)(buffer, pc, oprom, oprom, d_debugger->first_symbol)
1203
1204 /*****************************************************************************/
1205 /* src/emu/didisasm.h */
1206
1207 // Disassembler constants
1208 const UINT32 DASMFLAG_SUPPORTED     = 0x80000000;   // are disassembly flags supported?
1209 const UINT32 DASMFLAG_STEP_OUT      = 0x40000000;   // this instruction should be the end of a step out sequence
1210 const UINT32 DASMFLAG_STEP_OVER     = 0x20000000;   // this instruction should be stepped over by setting a breakpoint afterwards
1211 const UINT32 DASMFLAG_OVERINSTMASK  = 0x18000000;   // number of extra instructions to skip when stepping over
1212 const UINT32 DASMFLAG_OVERINSTSHIFT = 27;           // bits to shift after masking to get the value
1213 const UINT32 DASMFLAG_LENGTHMASK    = 0x0000ffff;   // the low 16-bits contain the actual length
1214
1215 #include "mame/emu/cpu/m6502/6502dasm.c"
1216
1217 int M6502::debug_dasm(uint32_t pc, _TCHAR *buffer, size_t buffer_len)
1218 {
1219         uint8_t oprom[4];
1220         uint8_t *opram = oprom;
1221         
1222         for(int i = 0; i < 4; i++) {
1223                 int wait;
1224                 oprom[i] = d_mem->read_data8w(pc + i, &wait);
1225         }
1226         return CPU_DISASSEMBLE_CALL(m6502) & DASMFLAG_LENGTHMASK;
1227 }
1228 #endif
1229
1230 #define STATE_VERSION   1
1231
1232 void M6502::save_state(FILEIO* state_fio)
1233 {
1234         state_fio->FputUint32(STATE_VERSION);
1235         state_fio->FputInt32(this_device_id);
1236         
1237         state_fio->FputUint32(pc.d);
1238         state_fio->FputUint32(sp.d);
1239         state_fio->FputUint32(zp.d);
1240         state_fio->FputUint32(ea.d);
1241         state_fio->FputUint16(prev_pc);
1242         state_fio->FputUint8(a);
1243         state_fio->FputUint8(x);
1244         state_fio->FputUint8(y);
1245         state_fio->FputUint8(p);
1246         state_fio->FputBool(pending_irq);
1247         state_fio->FputBool(after_cli);
1248         state_fio->FputBool(nmi_state);
1249         state_fio->FputBool(irq_state);
1250         state_fio->FputBool(so_state);
1251         state_fio->FputInt32(icount);
1252         state_fio->FputBool(busreq);
1253 }
1254
1255 bool M6502::load_state(FILEIO* state_fio)
1256 {
1257         if(state_fio->FgetUint32() != STATE_VERSION) {
1258                 return false;
1259         }
1260         if(state_fio->FgetInt32() != this_device_id) {
1261                 return false;
1262         }
1263         pc.d = state_fio->FgetUint32();
1264         sp.d = state_fio->FgetUint32();
1265         zp.d = state_fio->FgetUint32();
1266         ea.d = state_fio->FgetUint32();
1267         prev_pc = state_fio->FgetUint16();
1268         a = state_fio->FgetUint8();
1269         x = state_fio->FgetUint8();
1270         y = state_fio->FgetUint8();
1271         p = state_fio->FgetUint8();
1272         pending_irq = state_fio->FgetBool();
1273         after_cli = state_fio->FgetBool();
1274         nmi_state = state_fio->FgetBool();
1275         irq_state = state_fio->FgetBool();
1276         so_state = state_fio->FgetBool();
1277         icount = state_fio->FgetInt32();
1278         busreq = state_fio->FgetBool();
1279         return true;
1280 }
1281