1
//============================================================================
5
// SS tttttt eeee ll ll aaaa
6
// SSSS tt ee ee ll ll aa
7
// SS tt eeeeee ll ll aaaaa -- "An Atari 2600 VCS Emulator"
8
// SS SS tt ee ll ll aa aa
9
// SSSS ttt eeeee llll llll aaaaa
11
// Copyright (c) 1995-2010 by Bradford W. Mott, Stephen Anthony
12
// and the Stella Team
14
// See the file "License.txt" for information on usage and redistribution of
15
// this file, and for a DISCLAIMER OF ALL WARRANTIES.
17
// $Id: DiStella.cxx 2002 2010-04-10 21:57:49Z stephena $
18
//============================================================================
21
#include "Debugger.hxx"
22
#include "DiStella.hxx"
24
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
25
DiStella::DiStella(CartDebug::DisassemblyList& list, uInt16 start,
29
while(!myAddressQueue.empty())
32
myAppData.start = 0x0000;
33
myAppData.end = 0x0FFF;
34
myAppData.length = 4096;
36
memset(labels, 0, 0x1000);
38
/*============================================
39
The offset is the address where the code segment
40
starts. For a 4K game, it is usually 0xf000,
41
which would then have the code data end at 0xffff,
42
but that is not necessarily the case. Because the
43
Atari 2600 only has 13 address lines, it's possible
44
that the "code" can be considered to start in a lot
45
of different places. So, we use the start
46
address as a reference to determine where the
47
offset is, logically-anded to produce an offset
48
that is a multiple of 4K.
51
Start address = $D973, so therefore
52
Offset to code = $D000
53
Code range = $D000-$DFFF
54
=============================================*/
55
myOffset = (start - (start % 0x1000));
57
myAddressQueue.push(start);
61
while(!myAddressQueue.empty())
63
myPC = myAddressQueue.front();
67
for (uInt32 k = myPCBeg; k <= myPCEnd; k++)
71
for (int k = 0; k <= myAppData.end; k++)
73
if (!check_bit(labels[k], REACHABLE))
74
mark(k+myOffset, DATA);
85
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
90
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
91
void DiStella::disasm(uInt32 distart, int pass)
93
#define HEX4 uppercase << hex << setw(4) << setfill('0')
94
#define HEX2 uppercase << hex << setw(2) << setfill('0')
99
int bytes=0, labfound=0, addbranch=0;
100
stringstream nextline, nextlinebytes;
103
/* pc=myAppData.start; */
104
myPC = distart - myOffset;
105
while(myPC <= myAppData.end)
107
if(check_bit(labels[myPC], GFX))
108
/* && !check_bit(labels[myPC], REACHABLE))*/
111
mark(myPC+myOffset,VALID_ENTRY);
114
if (check_bit(labels[myPC],REFERENCED))
115
myDisasmBuf << HEX4 << myPC+myOffset << "'L'" << HEX4 << myPC+myOffset << "'";
117
myDisasmBuf << HEX4 << myPC+myOffset << "' '";
119
myDisasmBuf << ".byte $" << HEX2 << (int)Debugger::debugger().peek(myPC+myOffset) << " ; ";
120
showgfx(Debugger::debugger().peek(myPC+myOffset));
121
myDisasmBuf << " $" << HEX4 << myPC+myOffset;
126
else if (check_bit(labels[myPC], DATA) && !check_bit(labels[myPC], GFX))
127
/* && !check_bit(labels[myPC],REACHABLE)) { */
129
mark(myPC+myOffset, VALID_ENTRY);
133
myDisasmBuf << HEX4 << myPC+myOffset << "'L" << HEX4 << myPC+myOffset << "'.byte "
134
<< "$" << HEX2 << (int)Debugger::debugger().peek(myPC+myOffset);
138
while (check_bit(labels[myPC], DATA) && !check_bit(labels[myPC], REFERENCED)
139
&& !check_bit(labels[myPC], GFX) && pass == 3 && myPC <= myAppData.end)
147
myDisasmBuf << " ' '.byte $" << HEX2 << (int)Debugger::debugger().peek(myPC+myOffset);
151
myDisasmBuf << ",$" << HEX2 << (int)Debugger::debugger().peek(myPC+myOffset);
159
myDisasmBuf << " ' ' ";
165
op = Debugger::debugger().peek(myPC+myOffset);
166
/* version 2.1 bug fix */
168
mark(myPC+myOffset, VALID_ENTRY);
171
if (check_bit(labels[myPC], REFERENCED))
172
myDisasmBuf << HEX4 << myPC+myOffset << "'L" << HEX4 << myPC+myOffset << "'";
174
myDisasmBuf << HEX4 << myPC+myOffset << "' '";
177
amode = ourLookup[op].addr_mode;
180
if (ourLookup[op].mnemonic[0] == '.')
184
nextline << ".byte $" << HEX2 << (int)op << " ;";
189
opsrc = ourLookup[op].source;
190
/* M_REL covers BPL, BMI, BVC, BVS, BCC, BCS, BNE, BEQ
191
M_ADDR = JMP $NNNN, JSR $NNNN
192
M_AIND = JMP Abs, Indirect */
193
if ((opsrc == M_REL) || (opsrc == M_ADDR) || (opsrc == M_AIND))
200
nextline << ourLookup[op].mnemonic;
201
nextlinebytes << HEX2 << (int)op << " ";
204
if (myPC >= myAppData.end)
217
/* Line information is already printed; append .byte since last instruction will
218
put recompilable object larger that original binary file */
219
myDisasmBuf << ".byte $" << HEX2 << (int)op;
222
if (myPC == myAppData.end)
224
if (check_bit(labels[myPC],REFERENCED))
225
myDisasmBuf << HEX4 << myPC+myOffset << "'L" << HEX4 << myPC+myOffset << "'";
227
myDisasmBuf << HEX4 << myPC+myOffset << "' '";
229
op = Debugger::debugger().peek(myPC+myOffset); myPC++;
230
myDisasmBuf << ".byte $" << HEX2 << (int)op;
234
myPCEnd = myAppData.end + myOffset;
244
if (myPC > myAppData.end)
248
/* Line information is already printed, but we can remove the
249
Instruction (i.e. BMI) by simply clearing the buffer to print */
250
myDisasmBuf << ".byte $" << HEX2 << (int)op;
253
nextlinebytes.str("");
256
myPCEnd = myAppData.end + myOffset;
266
/* Version 2.1 added the extensions to mnemonics */
272
if (op == 0x40 || op == 0x60)
287
ad = Debugger::debugger().dpeek(myPC+myOffset); myPC+=2;
288
labfound = mark(ad, REFERENCED);
291
if ((addbranch) && !check_bit(labels[ad & myAppData.end], REACHABLE))
294
myAddressQueue.push((ad & myAppData.end) + myOffset);
308
nextline << "L" << HEX4 << ad;
309
nextlinebytes << HEX2 << (int)(ad&0xff) << " " << HEX2 << (int)(ad>>8);
311
else if (labfound == 3)
313
nextline << CartDebug::ourIOMnemonic[ad-0x280];
314
nextlinebytes << HEX2 << (int)(ad&0xff) << " " << HEX2 << (int)(ad>>8);
316
else if (labfound == 4)
318
int tmp = (ad & myAppData.end)+myOffset;
319
nextline << "L" << HEX4 << tmp;
320
nextlinebytes << HEX2 << (int)(tmp&0xff) << " " << HEX2 << (int)(tmp>>8);
324
nextline << "$" << HEX4 << ad;
325
nextlinebytes << HEX2 << (int)(ad&0xff) << " " << HEX2 << (int)(ad>>8);
333
d1 = Debugger::debugger().peek(myPC+myOffset); myPC++;
334
labfound = mark(d1, REFERENCED);
338
nextline << " " << (ourLookup[op].rw_mode == READ ?
339
CartDebug::ourTIAMnemonicR[d1&0x0f] : CartDebug::ourTIAMnemonicW[d1&0x3f]);
341
nextline << " $" << HEX2 << (int)d1;
343
nextlinebytes << HEX2 << (int)d1;
350
d1 = Debugger::debugger().peek(myPC+myOffset); myPC++;
353
nextline << " #$" << HEX2 << (int)d1 << " ";
354
nextlinebytes << HEX2 << (int)d1;
361
ad = Debugger::debugger().dpeek(myPC+myOffset); myPC+=2;
362
labfound = mark(ad, REFERENCED);
372
nextline << "L" << HEX4 << ad << ",X";
373
nextlinebytes << HEX2 << (int)(ad&0xff) << " " << HEX2 << (int)(ad>>8);
375
else if (labfound == 3)
377
nextline << CartDebug::ourIOMnemonic[ad-0x280] << ",X";
378
nextlinebytes << HEX2 << (int)(ad&0xff) << " " << HEX2 << (int)(ad>>8);
380
else if (labfound == 4)
382
int tmp = (ad & myAppData.end)+myOffset;
383
nextline << "L" << HEX4 << tmp << ",X";
384
nextlinebytes << HEX2 << (int)(tmp&0xff) << " " << HEX2 << (int)(tmp>>8);
388
nextline << "$" << HEX4 << ad << ",X";
389
nextlinebytes << HEX2 << (int)(ad&0xff) << " " << HEX2 << (int)(ad>>8);
397
ad = Debugger::debugger().dpeek(myPC+myOffset); myPC+=2;
398
labfound = mark(ad, REFERENCED);
408
nextline << "L" << HEX4 << ad << ",Y";
409
nextlinebytes << HEX2 << (int)(ad&0xff) << " " << HEX2 << (int)(ad>>8);
411
else if (labfound == 3)
413
nextline << CartDebug::ourIOMnemonic[ad-0x280] << ",Y";
414
nextlinebytes << HEX2 << (int)(ad&0xff) << " " << HEX2 << (int)(ad>>8);
416
else if (labfound == 4)
418
int tmp = (ad & myAppData.end)+myOffset;
419
nextline << "L" << HEX4 << tmp << ",Y";
420
nextlinebytes << HEX2 << (int)(tmp&0xff) << " " << HEX2 << (int)(tmp>>8);
424
nextline << "$" << HEX4 << ad << ",Y";
425
nextlinebytes << HEX2 << (int)(ad&0xff) << " " << HEX2 << (int)(ad>>8);
433
d1 = Debugger::debugger().peek(myPC+myOffset); myPC++;
436
nextline << " ($" << HEX2 << (int)d1 << ",X)";
437
nextlinebytes << HEX2 << (int)d1;
444
d1 = Debugger::debugger().peek(myPC+myOffset); myPC++;
447
nextline << " ($" << HEX2 << (int)d1 << "),Y";
448
nextlinebytes << HEX2 << (int)d1;
455
d1 = Debugger::debugger().peek(myPC+myOffset); myPC++;
456
labfound = mark(d1, REFERENCED);
460
nextline << " " << (ourLookup[op].rw_mode == READ ?
461
CartDebug::ourTIAMnemonicR[d1&0x0f] :
462
CartDebug::ourTIAMnemonicW[d1&0x3f]) << ",X";
464
nextline << " $" << HEX2 << (int)d1 << ",X";
466
nextlinebytes << HEX2 << (int)d1;
472
d1 = Debugger::debugger().peek(myPC+myOffset); myPC++;
473
labfound = mark(d1,REFERENCED);
477
nextline << " " << (ourLookup[op].rw_mode == READ ?
478
CartDebug::ourTIAMnemonicR[d1&0x0f] :
479
CartDebug::ourTIAMnemonicW[d1&0x3f]) << ",Y";
481
nextline << " $" << HEX2 << (int)d1 << ",Y";
483
nextlinebytes << HEX2 << (int)d1;
489
// SA - 04-06-2010: there seemed to be a bug in distella,
490
// where wraparound occurred on a 32-bit int, and subsequent
491
// indexing into the labels array caused a crash
492
d1 = Debugger::debugger().peek(myPC+myOffset); myPC++;
493
ad = ((myPC + (Int8)d1) & 0xfff) + myOffset;
495
labfound = mark(ad+myOffset, REFERENCED);
498
if ((addbranch) && !check_bit(labels[ad-myOffset], REACHABLE))
500
myAddressQueue.push(ad);
507
nextline << " L" << HEX4 << ad;
509
nextline << " $" << HEX4 << ad;
511
nextlinebytes << HEX2 << (int)(ad&0xff) << " " << HEX2 << (int)(ad>>8);
518
ad = Debugger::debugger().dpeek(myPC+myOffset); myPC+=2;
519
labfound = mark(ad, REFERENCED);
528
nextline << "(L" << HEX4 << ad << ")";
529
else if (labfound == 3)
530
nextline << "(" << CartDebug::ourIOMnemonic[ad-0x280] << ")";
532
nextline << "($" << HEX4 << ad << ")";
534
nextlinebytes << HEX2 << (int)(ad&0xff) << " " << HEX2 << (int)(ad>>8);
541
if (!strcmp(ourLookup[op].mnemonic,"RTS") ||
542
!strcmp(ourLookup[op].mnemonic,"JMP") ||
543
/* !strcmp(ourLookup[op].mnemonic,"BRK") || */
544
!strcmp(ourLookup[op].mnemonic,"RTI"))
546
myPCEnd = (myPC-1) + myOffset;
552
myDisasmBuf << nextline.str();;
553
uInt32 nextlinelen = nextline.str().length();
554
if (nextlinelen <= 15)
556
/* Print spaces to align cycle count data */
557
for (uInt32 charcnt=0;charcnt<15-nextlinelen;charcnt++)
560
myDisasmBuf << ";" << dec << (int)ourLookup[op].cycles << "'" << nextlinebytes.str();
562
if (op == 0x40 || op == 0x60)
564
myDisasmBuf << " ' ' ";
569
nextlinebytes.str("");
574
/* Just in case we are disassembling outside of the address range, force the myPCEnd to EOF */
575
myPCEnd = myAppData.end + myOffset;
578
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
579
int DiStella::mark(uInt32 address, MarkType bit)
581
/*-----------------------------------------------------------------------
582
For any given offset and code range...
584
If we're between the offset and the end of the code range, we mark
585
the bit in the labels array for that data. The labels array is an
586
array of label info for each code address. If this is the case,
589
We sweep for hardware/system equates, which are valid addresses,
590
outside the scope of the code/data range. For these, we mark its
591
corresponding hardware/system array element, and return "2" or "3"
592
(depending on which system/hardware element was accessed), or "5"
593
for zero-page RAM. If this was not the case...
595
Next we check if it is a code "mirror". For the 2600, address ranges
596
are limited with 13 bits, so other addresses can exist outside of the
597
standard code/data range. For these, we mark the element in the "labels"
598
array that corresponds to the mirrored address, and return "4"
600
If all else fails, it's not a valid address, so return 0.
602
A quick example breakdown for a 2600 4K cart:
603
===========================================================
604
$00-$3d = system equates (WSYNC, etc...); mark the array's element
605
with the appropriate bit; return 2.
606
$0080-$00FF = zero-page RAM; mark the array's element
607
with the appropriate bit; return 5.
608
$0280-$0297 = system equates (INPT0, etc...); mark the array's element
609
with the appropriate bit; return 3.
610
$1000-$1FFF = CODE/DATA, mark the code/data array for the mirrored address
611
with the appropriate bit; return 4.
612
$3000-$3FFF = CODE/DATA, mark the code/data array for the mirrored address
613
with the appropriate bit; return 4.
614
$5000-$5FFF = CODE/DATA, mark the code/data array for the mirrored address
615
with the appropriate bit; return 4.
616
$7000-$7FFF = CODE/DATA, mark the code/data array for the mirrored address
617
with the appropriate bit; return 4.
618
$9000-$9FFF = CODE/DATA, mark the code/data array for the mirrored address
619
with the appropriate bit; return 4.
620
$B000-$BFFF = CODE/DATA, mark the code/data array for the mirrored address
621
with the appropriate bit; return 4.
622
$D000-$DFFF = CODE/DATA, mark the code/data array for the mirrored address
623
with the appropriate bit; return 4.
624
$F000-$FFFF = CODE/DATA, mark the code/data array for the address
625
with the appropriate bit; return 1.
626
Anything else = invalid, return 0.
627
===========================================================
628
-----------------------------------------------------------------------*/
630
if (address >= myOffset && address <= myAppData.end + myOffset)
632
labels[address-myOffset] = labels[address-myOffset] | bit;
635
else if (address >= 0 && address <= 0x3f)
639
/* This isn't supported by the core code yet, so why waste time checking
640
else if (address >= 0x80 && address <= 0xff)
645
else if (address >= 0x280 && address <= 0x297)
649
else if (address > 0x1000)
652
labels[address & myAppData.end] = labels[address & myAppData.end] | bit;
659
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
660
void DiStella::showgfx(uInt8 c)
665
for(i = 0;i < 8; i++)
677
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
678
void DiStella::addEntry()
680
const string& line = myDisasmBuf.str();
681
CartDebug::DisassemblyTag tag;
686
myDisasmBuf >> setw(4) >> hex >> tag.address;
689
tag.label = line.substr(5, 5);
697
tag.disasm = line.substr(11);
700
tag.disasm = line.substr(11, 17);
701
tag.bytes = line.substr(29);
704
myList.push_back(tag);
709
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
710
const DiStella::Instruction_tag DiStella::ourLookup[256] = {
713
/* 00 */ { "BRK", IMPLIED, M_NONE, NONE, 7 }, /* Pseudo Absolute */
714
/* 01 */ { "ORA", INDIRECT_X, M_INDX, READ, 6 }, /* (Indirect,X) */
715
/* 02 */ { "jam", IMPLIED, M_NONE, NONE, 0 }, /* TILT */
716
/* 03 */ { "slo", INDIRECT_X, M_INDX, WRITE, 8 },
718
/* 04 */ { "nop", ZERO_PAGE, M_NONE, NONE, 3 },
719
/* 05 */ { "ORA", ZERO_PAGE, M_ZERO, READ, 3 }, /* Zeropage */
720
/* 06 */ { "ASL", ZERO_PAGE, M_ZERO, WRITE, 5 }, /* Zeropage */
721
/* 07 */ { "slo", ZERO_PAGE, M_ZERO, WRITE, 5 },
723
/* 08 */ { "PHP", IMPLIED, M_SR, NONE, 3 },
724
/* 09 */ { "ORA", IMMEDIATE, M_IMM, READ, 2 }, /* Immediate */
725
/* 0a */ { "ASL", ACCUMULATOR, M_AC, WRITE, 2 }, /* Accumulator */
726
/* 0b */ { "anc", IMMEDIATE, M_ACIM, READ, 2 },
728
/* 0c */ { "nop", ABSOLUTE, M_NONE, NONE, 4 },
729
/* 0d */ { "ORA", ABSOLUTE, M_ABS, READ, 4 }, /* Absolute */
730
/* 0e */ { "ASL", ABSOLUTE, M_ABS, WRITE, 6 }, /* Absolute */
731
/* 0f */ { "slo", ABSOLUTE, M_ABS, WRITE, 6 },
733
/* 10 */ { "BPL", RELATIVE, M_REL, READ, 2 },
734
/* 11 */ { "ORA", INDIRECT_Y, M_INDY, READ, 5 }, /* (Indirect),Y */
735
/* 12 */ { "jam", IMPLIED, M_NONE, NONE, 0 }, /* TILT */
736
/* 13 */ { "slo", INDIRECT_Y, M_INDY, WRITE, 8 },
738
/* 14 */ { "nop", ZERO_PAGE_X, M_NONE, NONE, 4 },
739
/* 15 */ { "ORA", ZERO_PAGE_X, M_ZERX, READ, 4 }, /* Zeropage,X */
740
/* 16 */ { "ASL", ZERO_PAGE_X, M_ZERX, WRITE, 6 }, /* Zeropage,X */
741
/* 17 */ { "slo", ZERO_PAGE_X, M_ZERX, WRITE, 6 },
743
/* 18 */ { "CLC", IMPLIED, M_NONE, NONE, 2 },
744
/* 19 */ { "ORA", ABSOLUTE_Y, M_ABSY, READ, 4 }, /* Absolute,Y */
745
/* 1a */ { "nop", IMPLIED, M_NONE, NONE, 2 },
746
/* 1b */ { "slo", ABSOLUTE_Y, M_ABSY, WRITE, 7 },
748
/* 1c */ { "nop", ABSOLUTE_X, M_NONE, NONE, 4 },
749
/* 1d */ { "ORA", ABSOLUTE_X, M_ABSX, READ, 4 }, /* Absolute,X */
750
/* 1e */ { "ASL", ABSOLUTE_X, M_ABSX, WRITE, 7 }, /* Absolute,X */
751
/* 1f */ { "slo", ABSOLUTE_X, M_ABSX, WRITE, 7 },
753
/* 20 */ { "JSR", ABSOLUTE, M_ADDR, READ, 6 },
754
/* 21 */ { "AND", INDIRECT_X, M_INDX, READ, 6 }, /* (Indirect ,X) */
755
/* 22 */ { "jam", IMPLIED, M_NONE, NONE, 0 }, /* TILT */
756
/* 23 */ { "rla", INDIRECT_X, M_INDX, WRITE, 8 },
758
/* 24 */ { "BIT", ZERO_PAGE, M_ZERO, READ, 3 }, /* Zeropage */
759
/* 25 */ { "AND", ZERO_PAGE, M_ZERO, READ, 3 }, /* Zeropage */
760
/* 26 */ { "ROL", ZERO_PAGE, M_ZERO, WRITE, 5 }, /* Zeropage */
761
/* 27 */ { "rla", ZERO_PAGE, M_ZERO, WRITE, 5 },
763
/* 28 */ { "PLP", IMPLIED, M_NONE, NONE, 4 },
764
/* 29 */ { "AND", IMMEDIATE, M_IMM, READ, 2 }, /* Immediate */
765
/* 2a */ { "ROL", ACCUMULATOR, M_AC, WRITE, 2 }, /* Accumulator */
766
/* 2b */ { "anc", IMMEDIATE, M_ACIM, READ, 2 },
768
/* 2c */ { "BIT", ABSOLUTE, M_ABS, READ, 4 }, /* Absolute */
769
/* 2d */ { "AND", ABSOLUTE, M_ABS, READ, 4 }, /* Absolute */
770
/* 2e */ { "ROL", ABSOLUTE, M_ABS, WRITE, 6 }, /* Absolute */
771
/* 2f */ { "rla", ABSOLUTE, M_ABS, WRITE, 6 },
773
/* 30 */ { "BMI", RELATIVE, M_REL, READ, 2 },
774
/* 31 */ { "AND", INDIRECT_Y, M_INDY, READ, 5 }, /* (Indirect),Y */
775
/* 32 */ { "jam", IMPLIED, M_NONE, NONE, 0 }, /* TILT */
776
/* 33 */ { "rla", INDIRECT_Y, M_INDY, WRITE, 8 },
778
/* 34 */ { "nop", ZERO_PAGE_X, M_NONE, NONE, 4 },
779
/* 35 */ { "AND", ZERO_PAGE_X, M_ZERX, READ, 4 }, /* Zeropage,X */
780
/* 36 */ { "ROL", ZERO_PAGE_X, M_ZERX, WRITE, 6 }, /* Zeropage,X */
781
/* 37 */ { "rla", ZERO_PAGE_X, M_ZERX, WRITE, 6 },
783
/* 38 */ { "SEC", IMPLIED, M_NONE, NONE, 2 },
784
/* 39 */ { "AND", ABSOLUTE_Y, M_ABSY, READ, 4 }, /* Absolute,Y */
785
/* 3a */ { "nop", IMPLIED, M_NONE, NONE, 2 },
786
/* 3b */ { "rla", ABSOLUTE_Y, M_ABSY, WRITE, 7 },
788
/* 3c */ { "nop", ABSOLUTE_X, M_NONE, NONE, 4 },
789
/* 3d */ { "AND", ABSOLUTE_X, M_ABSX, READ, 4 }, /* Absolute,X */
790
/* 3e */ { "ROL", ABSOLUTE_X, M_ABSX, WRITE, 7 }, /* Absolute,X */
791
/* 3f */ { "rla", ABSOLUTE_X, M_ABSX, WRITE, 7 },
793
/* 40 */ { "RTI", IMPLIED, M_NONE, NONE, 6 },
794
/* 41 */ { "EOR", INDIRECT_X, M_INDX, READ, 6 }, /* (Indirect,X) */
795
/* 42 */ { "jam", IMPLIED, M_NONE, NONE, 0 }, /* TILT */
796
/* 43 */ { "sre", INDIRECT_X, M_INDX, WRITE, 8 },
798
/* 44 */ { "nop", ZERO_PAGE, M_NONE, NONE, 3 },
799
/* 45 */ { "EOR", ZERO_PAGE, M_ZERO, READ, 3 }, /* Zeropage */
800
/* 46 */ { "LSR", ZERO_PAGE, M_ZERO, WRITE, 5 }, /* Zeropage */
801
/* 47 */ { "sre", ZERO_PAGE, M_ZERO, WRITE, 5 },
803
/* 48 */ { "PHA", IMPLIED, M_AC, NONE, 3 },
804
/* 49 */ { "EOR", IMMEDIATE, M_IMM, READ, 2 }, /* Immediate */
805
/* 4a */ { "LSR", ACCUMULATOR, M_AC, WRITE, 2 }, /* Accumulator */
806
/* 4b */ { "asr", IMMEDIATE, M_ACIM, READ, 2 }, /* (AC & IMM) >>1 */
808
/* 4c */ { "JMP", ABSOLUTE, M_ADDR, READ, 3 }, /* Absolute */
809
/* 4d */ { "EOR", ABSOLUTE, M_ABS, READ, 4 }, /* Absolute */
810
/* 4e */ { "LSR", ABSOLUTE, M_ABS, WRITE, 6 }, /* Absolute */
811
/* 4f */ { "sre", ABSOLUTE, M_ABS, WRITE, 6 },
813
/* 50 */ { "BVC", RELATIVE, M_REL, READ, 2 },
814
/* 51 */ { "EOR", INDIRECT_Y, M_INDY, READ, 5 }, /* (Indirect),Y */
815
/* 52 */ { "jam", IMPLIED, M_NONE, NONE, 0 }, /* TILT */
816
/* 53 */ { "sre", INDIRECT_Y, M_INDY, WRITE, 8 },
818
/* 54 */ { "nop", ZERO_PAGE_X, M_NONE, NONE, 4 },
819
/* 55 */ { "EOR", ZERO_PAGE_X, M_ZERX, READ, 4 }, /* Zeropage,X */
820
/* 56 */ { "LSR", ZERO_PAGE_X, M_ZERX, WRITE, 6 }, /* Zeropage,X */
821
/* 57 */ { "sre", ZERO_PAGE_X, M_ZERX, WRITE, 6 },
823
/* 58 */ { "CLI", IMPLIED, M_NONE, NONE, 2 },
824
/* 59 */ { "EOR", ABSOLUTE_Y, M_ABSY, READ, 4 }, /* Absolute,Y */
825
/* 5a */ { "nop", IMPLIED, M_NONE, NONE, 2 },
826
/* 5b */ { "sre", ABSOLUTE_Y, M_ABSY, WRITE, 7 },
828
/* 5c */ { "nop", ABSOLUTE_X, M_NONE, NONE, 4 },
829
/* 5d */ { "EOR", ABSOLUTE_X, M_ABSX, READ, 4 }, /* Absolute,X */
830
/* 5e */ { "LSR", ABSOLUTE_X, M_ABSX, WRITE, 7 }, /* Absolute,X */
831
/* 5f */ { "sre", ABSOLUTE_X, M_ABSX, WRITE, 7 },
833
/* 60 */ { "RTS", IMPLIED, M_NONE, NONE, 6 },
834
/* 61 */ { "ADC", INDIRECT_X, M_INDX, READ, 6 }, /* (Indirect,X) */
835
/* 62 */ { "jam", IMPLIED, M_NONE, NONE, 0 }, /* TILT */
836
/* 63 */ { "rra", INDIRECT_X, M_INDX, WRITE, 8 },
838
/* 64 */ { "nop", ZERO_PAGE, M_NONE, NONE, 3 },
839
/* 65 */ { "ADC", ZERO_PAGE, M_ZERO, READ, 3 }, /* Zeropage */
840
/* 66 */ { "ROR", ZERO_PAGE, M_ZERO, WRITE, 5 }, /* Zeropage */
841
/* 67 */ { "rra", ZERO_PAGE, M_ZERO, WRITE, 5 },
843
/* 68 */ { "PLA", IMPLIED, M_NONE, NONE, 4 },
844
/* 69 */ { "ADC", IMMEDIATE, M_IMM, READ, 2 }, /* Immediate */
845
/* 6a */ { "ROR", ACCUMULATOR, M_AC, WRITE, 2 }, /* Accumulator */
846
/* 6b */ { "arr", IMMEDIATE, M_ACIM, READ, 2 }, /* ARR isn't typo */
848
/* 6c */ { "JMP", ABS_INDIRECT,M_AIND, READ, 5 }, /* Indirect */
849
/* 6d */ { "ADC", ABSOLUTE, M_ABS, READ, 4 }, /* Absolute */
850
/* 6e */ { "ROR", ABSOLUTE, M_ABS, WRITE, 6 }, /* Absolute */
851
/* 6f */ { "rra", ABSOLUTE, M_ABS, WRITE, 6 },
853
/* 70 */ { "BVS", RELATIVE, M_REL, READ, 2 },
854
/* 71 */ { "ADC", INDIRECT_Y, M_INDY, READ, 5 }, /* (Indirect),Y */
855
/* 72 */ { "jam", IMPLIED, M_NONE, NONE, 0 }, /* TILT relative? */
856
/* 73 */ { "rra", INDIRECT_Y, M_INDY, WRITE, 8 },
858
/* 74 */ { "nop", ZERO_PAGE_X, M_NONE, NONE, 4 },
859
/* 75 */ { "ADC", ZERO_PAGE_X, M_ZERX, READ, 4 }, /* Zeropage,X */
860
/* 76 */ { "ROR", ZERO_PAGE_X, M_ZERX, WRITE, 6 }, /* Zeropage,X */
861
/* 77 */ { "rra", ZERO_PAGE_X, M_ZERX, WRITE, 6 },
863
/* 78 */ { "SEI", IMPLIED, M_NONE, NONE, 2 },
864
/* 79 */ { "ADC", ABSOLUTE_Y, M_ABSY, READ, 4 }, /* Absolute,Y */
865
/* 7a */ { "nop", IMPLIED, M_NONE, NONE, 2 },
866
/* 7b */ { "rra", ABSOLUTE_Y, M_ABSY, WRITE, 7 },
868
/* 7c */ { "nop", ABSOLUTE_X, M_NONE, NONE, 4 },
869
/* 7d */ { "ADC", ABSOLUTE_X, M_ABSX, READ, 4 }, /* Absolute,X */
870
/* 7e */ { "ROR", ABSOLUTE_X, M_ABSX, WRITE, 7 }, /* Absolute,X */
871
/* 7f */ { "rra", ABSOLUTE_X, M_ABSX, WRITE, 7 },
875
/* 80 */ { "nop", IMMEDIATE, M_NONE, NONE, 2 },
876
/* 81 */ { "STA", INDIRECT_X, M_AC, WRITE, 6 }, /* (Indirect,X) */
877
/* 82 */ { "nop", IMMEDIATE, M_NONE, NONE, 2 },
878
/* 83 */ { "sax", INDIRECT_X, M_ANXR, WRITE, 6 },
880
/* 84 */ { "STY", ZERO_PAGE, M_YR, WRITE, 3 }, /* Zeropage */
881
/* 85 */ { "STA", ZERO_PAGE, M_AC, WRITE, 3 }, /* Zeropage */
882
/* 86 */ { "STX", ZERO_PAGE, M_XR, WRITE, 3 }, /* Zeropage */
883
/* 87 */ { "sax", ZERO_PAGE, M_ANXR, WRITE, 3 },
885
/* 88 */ { "DEY", IMPLIED, M_YR, NONE, 2 },
886
/* 89 */ { "nop", IMMEDIATE, M_NONE, NONE, 2 },
887
/* 8a */ { "TXA", IMPLIED, M_XR, NONE, 2 },
888
/**** very abnormal: usually AC = AC | #$EE & XR & #$oper ****/
889
/* 8b */ { "ane", IMMEDIATE, M_AXIM, READ, 2 },
891
/* 8c */ { "STY", ABSOLUTE, M_YR, WRITE, 4 }, /* Absolute */
892
/* 8d */ { "STA", ABSOLUTE, M_AC, WRITE, 4 }, /* Absolute */
893
/* 8e */ { "STX", ABSOLUTE, M_XR, WRITE, 4 }, /* Absolute */
894
/* 8f */ { "sax", ABSOLUTE, M_ANXR, WRITE, 4 },
896
/* 90 */ { "BCC", RELATIVE, M_REL, READ, 2 },
897
/* 91 */ { "STA", INDIRECT_Y, M_AC, WRITE, 6 }, /* (Indirect),Y */
898
/* 92 */ { "jam", IMPLIED, M_NONE, NONE, 0 }, /* TILT relative? */
899
/* 93 */ { "sha", INDIRECT_Y, M_ANXR, WRITE, 6 },
901
/* 94 */ { "STY", ZERO_PAGE_X, M_YR, WRITE, 4 }, /* Zeropage,X */
902
/* 95 */ { "STA", ZERO_PAGE_X, M_AC, WRITE, 4 }, /* Zeropage,X */
903
/* 96 */ { "STX", ZERO_PAGE_Y, M_XR, WRITE, 4 }, /* Zeropage,Y */
904
/* 97 */ { "sax", ZERO_PAGE_Y, M_ANXR, WRITE, 4 },
906
/* 98 */ { "TYA", IMPLIED, M_YR, NONE, 2 },
907
/* 99 */ { "STA", ABSOLUTE_Y, M_AC, WRITE, 5 }, /* Absolute,Y */
908
/* 9a */ { "TXS", IMPLIED, M_XR, NONE, 2 },
909
/*** This is very mysterious comm AND ... */
910
/* 9b */ { "shs", ABSOLUTE_Y, M_ANXR, WRITE, 5 },
912
/* 9c */ { "shy", ABSOLUTE_X, M_YR, WRITE, 5 },
913
/* 9d */ { "STA", ABSOLUTE_X, M_AC, WRITE, 5 }, /* Absolute,X */
914
/* 9e */ { "shx", ABSOLUTE_Y, M_XR , WRITE, 5 },
915
/* 9f */ { "sha", ABSOLUTE_Y, M_ANXR, WRITE, 5 },
917
/* a0 */ { "LDY", IMMEDIATE, M_IMM, READ, 2 }, /* Immediate */
918
/* a1 */ { "LDA", INDIRECT_X, M_INDX, READ, 6 }, /* (indirect,X) */
919
/* a2 */ { "LDX", IMMEDIATE, M_IMM, READ, 2 }, /* Immediate */
920
/* a3 */ { "lax", INDIRECT_X, M_INDX, READ, 6 }, /* (indirect,X) */
922
/* a4 */ { "LDY", ZERO_PAGE, M_ZERO, READ, 3 }, /* Zeropage */
923
/* a5 */ { "LDA", ZERO_PAGE, M_ZERO, READ, 3 }, /* Zeropage */
924
/* a6 */ { "LDX", ZERO_PAGE, M_ZERO, READ, 3 }, /* Zeropage */
925
/* a7 */ { "lax", ZERO_PAGE, M_ZERO, READ, 3 },
927
/* a8 */ { "TAY", IMPLIED, M_AC, NONE, 2 },
928
/* a9 */ { "LDA", IMMEDIATE, M_IMM, READ, 2 }, /* Immediate */
929
/* aa */ { "TAX", IMPLIED, M_AC, NONE, 2 },
930
/* ab */ { "lxa", IMMEDIATE, M_ACIM, READ, 2 }, /* LXA isn't a typo */
932
/* ac */ { "LDY", ABSOLUTE, M_ABS, READ, 4 }, /* Absolute */
933
/* ad */ { "LDA", ABSOLUTE, M_ABS, READ, 4 }, /* Absolute */
934
/* ae */ { "LDX", ABSOLUTE, M_ABS, READ, 4 }, /* Absolute */
935
/* af */ { "lax", ABSOLUTE, M_ABS, READ, 4 },
937
/* b0 */ { "BCS", RELATIVE, M_REL, READ, 2 },
938
/* b1 */ { "LDA", INDIRECT_Y, M_INDY, READ, 5 }, /* (indirect),Y */
939
/* b2 */ { "jam", IMPLIED, M_NONE, NONE, 0 }, /* TILT */
940
/* b3 */ { "lax", INDIRECT_Y, M_INDY, READ, 5 },
942
/* b4 */ { "LDY", ZERO_PAGE_X, M_ZERX, READ, 4 }, /* Zeropage,X */
943
/* b5 */ { "LDA", ZERO_PAGE_X, M_ZERX, READ, 4 }, /* Zeropage,X */
944
/* b6 */ { "LDX", ZERO_PAGE_Y, M_ZERY, READ, 4 }, /* Zeropage,Y */
945
/* b7 */ { "lax", ZERO_PAGE_Y, M_ZERY, READ, 4 },
947
/* b8 */ { "CLV", IMPLIED, M_NONE, NONE, 2 },
948
/* b9 */ { "LDA", ABSOLUTE_Y, M_ABSY, READ, 4 }, /* Absolute,Y */
949
/* ba */ { "TSX", IMPLIED, M_SP, NONE, 2 },
950
/* bb */ { "las", ABSOLUTE_Y, M_SABY, READ, 4 },
952
/* bc */ { "LDY", ABSOLUTE_X, M_ABSX, READ, 4 }, /* Absolute,X */
953
/* bd */ { "LDA", ABSOLUTE_X, M_ABSX, READ, 4 }, /* Absolute,X */
954
/* be */ { "LDX", ABSOLUTE_Y, M_ABSY, READ, 4 }, /* Absolute,Y */
955
/* bf */ { "lax", ABSOLUTE_Y, M_ABSY, READ, 4 },
957
/* c0 */ { "CPY", IMMEDIATE, M_IMM, READ, 2 }, /* Immediate */
958
/* c1 */ { "CMP", INDIRECT_X, M_INDX, READ, 6 }, /* (Indirect,X) */
959
/* c2 */ { "nop", IMMEDIATE, M_NONE, NONE, 2 }, /* occasional TILT */
960
/* c3 */ { "dcp", INDIRECT_X, M_INDX, WRITE, 8 },
962
/* c4 */ { "CPY", ZERO_PAGE, M_ZERO, READ, 3 }, /* Zeropage */
963
/* c5 */ { "CMP", ZERO_PAGE, M_ZERO, READ, 3 }, /* Zeropage */
964
/* c6 */ { "DEC", ZERO_PAGE, M_ZERO, WRITE, 5 }, /* Zeropage */
965
/* c7 */ { "dcp", ZERO_PAGE, M_ZERO, WRITE, 5 },
967
/* c8 */ { "INY", IMPLIED, M_YR, NONE, 2 },
968
/* c9 */ { "CMP", IMMEDIATE, M_IMM, READ, 2 }, /* Immediate */
969
/* ca */ { "DEX", IMPLIED, M_XR, NONE, 2 },
970
/* cb */ { "sbx", IMMEDIATE, M_IMM, READ, 2 },
972
/* cc */ { "CPY", ABSOLUTE, M_ABS, READ, 4 }, /* Absolute */
973
/* cd */ { "CMP", ABSOLUTE, M_ABS, READ, 4 }, /* Absolute */
974
/* ce */ { "DEC", ABSOLUTE, M_ABS, WRITE, 6 }, /* Absolute */
975
/* cf */ { "dcp", ABSOLUTE, M_ABS, WRITE, 6 },
977
/* d0 */ { "BNE", RELATIVE, M_REL, READ, 2 },
978
/* d1 */ { "CMP", INDIRECT_Y, M_INDY, READ, 5 }, /* (Indirect),Y */
979
/* d2 */ { "jam", IMPLIED, M_NONE, NONE, 0 }, /* TILT */
980
/* d3 */ { "dcp", INDIRECT_Y, M_INDY, WRITE, 8 },
982
/* d4 */ { "nop", ZERO_PAGE_X, M_NONE, NONE, 4 },
983
/* d5 */ { "CMP", ZERO_PAGE_X, M_ZERX, READ, 4 }, /* Zeropage,X */
984
/* d6 */ { "DEC", ZERO_PAGE_X, M_ZERX, WRITE, 6 }, /* Zeropage,X */
985
/* d7 */ { "dcp", ZERO_PAGE_X, M_ZERX, WRITE, 6 },
987
/* d8 */ { "CLD", IMPLIED, M_NONE, NONE, 2 },
988
/* d9 */ { "CMP", ABSOLUTE_Y, M_ABSY, READ, 4 }, /* Absolute,Y */
989
/* da */ { "nop", IMPLIED, M_NONE, NONE, 2 },
990
/* db */ { "dcp", ABSOLUTE_Y, M_ABSY, WRITE, 7 },
992
/* dc */ { "nop", ABSOLUTE_X, M_NONE, NONE, 4 },
993
/* dd */ { "CMP", ABSOLUTE_X, M_ABSX, READ, 4 }, /* Absolute,X */
994
/* de */ { "DEC", ABSOLUTE_X, M_ABSX, WRITE, 7 }, /* Absolute,X */
995
/* df */ { "dcp", ABSOLUTE_X, M_ABSX, WRITE, 7 },
997
/* e0 */ { "CPX", IMMEDIATE, M_IMM, READ, 2 }, /* Immediate */
998
/* e1 */ { "SBC", INDIRECT_X, M_INDX, READ, 6 }, /* (Indirect,X) */
999
/* e2 */ { "nop", IMMEDIATE, M_NONE, NONE, 2 },
1000
/* e3 */ { "isb", INDIRECT_X, M_INDX, WRITE, 8 },
1002
/* e4 */ { "CPX", ZERO_PAGE, M_ZERO, READ, 3 }, /* Zeropage */
1003
/* e5 */ { "SBC", ZERO_PAGE, M_ZERO, READ, 3 }, /* Zeropage */
1004
/* e6 */ { "INC", ZERO_PAGE, M_ZERO, WRITE, 5 }, /* Zeropage */
1005
/* e7 */ { "isb", ZERO_PAGE, M_ZERO, WRITE, 5 },
1007
/* e8 */ { "INX", IMPLIED, M_XR, NONE, 2 },
1008
/* e9 */ { "SBC", IMMEDIATE, M_IMM, READ, 2 }, /* Immediate */
1009
/* ea */ { "NOP", IMPLIED, M_NONE, NONE, 2 },
1010
/* eb */ { "sbc", IMMEDIATE, M_IMM, READ, 2 }, /* same as e9 */
1012
/* ec */ { "CPX", ABSOLUTE, M_ABS, READ, 4 }, /* Absolute */
1013
/* ed */ { "SBC", ABSOLUTE, M_ABS, READ, 4 }, /* Absolute */
1014
/* ee */ { "INC", ABSOLUTE, M_ABS, WRITE, 6 }, /* Absolute */
1015
/* ef */ { "isb", ABSOLUTE, M_ABS, WRITE, 6 },
1017
/* f0 */ { "BEQ", RELATIVE, M_REL, READ, 2 },
1018
/* f1 */ { "SBC", INDIRECT_Y, M_INDY, READ, 5 }, /* (Indirect),Y */
1019
/* f2 */ { "jam", IMPLIED, M_NONE, NONE, 0 }, /* TILT */
1020
/* f3 */ { "isb", INDIRECT_Y, M_INDY, WRITE, 8 },
1022
/* f4 */ { "nop", ZERO_PAGE_X, M_NONE, NONE, 4 },
1023
/* f5 */ { "SBC", ZERO_PAGE_X, M_ZERX, READ, 4 }, /* Zeropage,X */
1024
/* f6 */ { "INC", ZERO_PAGE_X, M_ZERX, WRITE, 6 }, /* Zeropage,X */
1025
/* f7 */ { "isb", ZERO_PAGE_X, M_ZERX, WRITE, 6 },
1027
/* f8 */ { "SED", IMPLIED, M_NONE, NONE, 2 },
1028
/* f9 */ { "SBC", ABSOLUTE_Y, M_ABSY, READ, 4 }, /* Absolute,Y */
1029
/* fa */ { "nop", IMPLIED, M_NONE, NONE, 2 },
1030
/* fb */ { "isb", ABSOLUTE_Y, M_ABSY, WRITE, 7 },
1032
/* fc */ { "nop", ABSOLUTE_X, M_NONE, NONE, 4 },
1033
/* fd */ { "SBC", ABSOLUTE_X, M_ABSX, READ, 4 }, /* Absolute,X */
1034
/* fe */ { "INC", ABSOLUTE_X, M_ABSX, WRITE, 7 }, /* Absolute,X */
1035
/* ff */ { "isb", ABSOLUTE_X, M_ABSX, WRITE, 7 }