]> Shamusworld >> Repos - apple2/blob - src/dis65c02.cpp
Add documentation of the process for emulating an A2 hard drive.
[apple2] / src / dis65c02.cpp
1 //
2 // 65C02 disassembler
3 //
4 // by James Hammons
5 // (c) 2005-2018 Underground Software
6 //
7
8 #include "dis65c02.h"
9
10 #include <stdio.h>
11 #include <string.h>
12 #include "log.h"
13
14
15 // Private global variables
16
17 static uint8_t op_mat[256] = {
18         14, 6,  0,  0,  2,  2,  2,  2,  14, 1,  14, 0,  8,  8,  8,  13,
19         13, 7,  5,  0,  2,  3,  3,  2,  14, 10, 14, 0,  8,  9,  9,  13,
20         8,  6,  0,  0,  2,  2,  2,  2,  14, 1,  14, 0,  8,  8,  8,  13,
21         13, 7,  5,  0,  3,  3,  3,  2,  14, 10, 14, 0,  9,  9,  9,  13,
22         14, 6,  0,  0,  0,  2,  2,  2,  14, 1,  14, 0,  8,  8,  8,  13,
23         13, 7,  5,  0,  0,  3,  3,  2,  14, 10, 14, 0,  0,  9,  9,  13,
24         14, 6,  0,  0,  2,  2,  2,  2,  14, 1,  14, 0,  11, 8,  8,  13,
25         13, 7,  5,  0,  3,  3,  3,  2,  14, 10, 14, 0,  12, 9,  9,  13,
26         13, 6,  0,  0,  2,  2,  2,  2,  14, 1,  14, 0,  8,  8,  8,  13,
27         13, 7,  5,  0,  3,  3,  4,  2,  14, 10, 14, 0,  8,  9,  9,  13,
28         1,  6,  1,  0,  2,  2,  2,  2,  14, 1,  14, 0,  8,  8,  8,  13,
29         13, 7,  5,  0,  3,  3,  4,  2,  14, 10, 14, 0,  9,  9,  10, 13,
30         1,  6,  0,  0,  2,  2,  2,  2,  14, 1,  14, 0,  8,  8,  8,  13,
31         13, 7,  5,  0,  0,  3,  3,  2,  14, 10, 14, 0,  0,  9,  9,  13,
32         1,  6,  0,  0,  2,  2,  2,  2,  14, 1,  14, 0,  8,  8,  8,  13,
33         13, 7,  5,  0,  0,  3,  3,  2,  14, 10, 14, 0,  0,  9,  9,  13
34 };
35
36 static uint8_t mnemonics[256][5] = {
37         "BRK ","ORA ","??? ","??? ","TSB ","ORA ","ASL ","RMB0",
38         "PHP ","ORA ","ASL ","??? ","TSB ","ORA ","ASL ","BBR0",
39         "BPL ","ORA ","ORA ","??? ","TRB ","ORA ","ASL ","RMB1",
40         "CLC ","ORA ","INC ","??? ","TRB ","ORA ","ASL ","BBR1",
41         "JSR ","AND ","??? ","??? ","BIT ","AND ","ROL ","RMB2",
42         "PLP ","AND ","ROL ","??? ","BIT ","AND ","ROL ","BBR2",
43         "BMI ","AND ","AND ","??? ","BIT ","AND ","ROL ","RMB3",
44         "SEC ","AND ","DEC ","??? ","BIT ","AND ","ROL ","BBR3",
45         "RTI ","EOR ","??? ","??? ","??? ","EOR ","LSR ","RMB4",
46         "PHA ","EOR ","LSR ","??? ","JMP ","EOR ","LSR ","BBR4",
47         "BVC ","EOR ","EOR ","??? ","??? ","EOR ","LSR ","RMB5",
48         "CLI ","EOR ","PHY ","??? ","??? ","EOR ","LSR ","BBR5",
49         "RTS ","ADC ","??? ","??? ","STZ ","ADC ","ROR ","RMB6",
50         "PLA ","ADC ","ROR ","??? ","JMP ","ADC ","ROR ","BBR6",
51         "BVS ","ADC ","ADC ","??? ","STZ ","ADC ","ROR ","RMB7",
52         "SEI ","ADC ","PLY ","??? ","JMP ","ADC ","ROR ","BBR7",
53         "BRA ","STA ","??? ","??? ","STY ","STA ","STX ","SMB0",
54         "DEY ","BIT ","TXA ","??? ","STY ","STA ","STX ","BBS0",
55         "BCC ","STA ","STA ","??? ","STY ","STA ","STX ","SMB1",
56         "TYA ","STA ","TXS ","??? ","STZ ","STA ","STZ ","BBS1",
57         "LDY ","LDA ","LDX ","??? ","LDY ","LDA ","LDX ","SMB2",
58         "TAY ","LDA ","TAX ","??? ","LDY ","LDA ","LDX ","BBS2",
59         "BCS ","LDA ","LDA ","??? ","LDY ","LDA ","LDX ","SMB3",
60         "CLV ","LDA ","TSX ","??? ","LDY ","LDA ","LDX ","BBS3",
61         "CPY ","CMP ","??? ","??? ","CPY ","CMP ","DEC ","SMB4",
62         "INY ","CMP ","DEX ","??? ","CPY ","CMP ","DEC ","BBS4",
63         "BNE ","CMP ","CMP ","??? ","??? ","CMP ","DEC ","SMB5",
64         "CLD ","CMP ","PHX ","??? ","??? ","CMP ","DEC ","BBS5",
65         "CPX ","SBC ","??? ","??? ","CPX ","SBC ","INC ","SMB6",
66         "INX ","SBC ","NOP ","??? ","CPX ","SBC ","INC ","BBS6",
67         "BEQ ","SBC ","SBC ","??? ","??? ","SBC ","INC ","SMB7",
68         "SED ","SBC ","PLX ","??? ","??? ","SBC ","INC ","BBS7"
69 };
70
71
72 //
73 // Display bytes in mem in hex
74 //
75 static void DisplayBytes(V65C02REGS * regs, char * outbuf, uint16_t src, uint32_t dst)
76 {
77         char buf[32];
78         sprintf(outbuf, "%04X: ", src);
79         uint8_t cnt = 0;
80
81         // That should fix the $FFFF bug...
82         if (src > dst)
83                 dst += 0x10000;
84
85         for(uint32_t i=src; i<dst; i++)
86         {
87                 sprintf(buf, "%02X ", regs->RdMem(i));
88                 strcat(outbuf, buf);
89                 cnt++;
90         }
91
92         // Pad the leftover spaces...
93         for(int i=cnt; i<3; i++)
94         {
95                 sprintf(buf, "   ");
96                 strcat(outbuf, buf);
97         }
98 }
99
100
101 //
102 // Decode a 65C02 instruction
103 //
104 int Decode65C02(V65C02REGS * regs, char * outbuf, uint16_t pc)
105 {
106         char buf[32], buf2[32];
107
108         uint16_t addr = pc;
109         uint16_t w;
110         uint8_t opcode = regs->RdMem(addr++);   // Get the opcode
111
112         switch (op_mat[opcode])                                 // Decode the addressing mode...
113         {
114         case 0:                                                                 // Illegal
115                 sprintf(buf, "???");
116                 break;
117         case 1:                                                                 // Immediate
118                 sprintf(buf, "%s #$%02X", mnemonics[opcode], regs->RdMem(addr++));
119                 break;
120         case 2:                                                                 // Zero page
121                 sprintf(buf, "%s $%02X", mnemonics[opcode], regs->RdMem(addr++));
122                 break;
123         case 3:                                                                 // Zero page, X
124                 sprintf(buf, "%s $%02X,X", mnemonics[opcode], regs->RdMem(addr++));
125                 break;
126         case 4:                                                                 // Zero page, Y
127                 sprintf(buf, "%s $%02X,Y", mnemonics[opcode], regs->RdMem(addr++));
128                 break;
129         case 5:                                                                 // Zero page indirect
130                 sprintf(buf, "%s ($%02X)", mnemonics[opcode], regs->RdMem(addr++));
131                 break;
132         case 6:                                                                 // Zero page, X indirect
133                 sprintf(buf, "%s ($%02X,X)", mnemonics[opcode], regs->RdMem(addr++));
134                 break;
135         case 7:                                                                 // Zero page, Y indirect
136                 sprintf(buf, "%s ($%02X),Y", mnemonics[opcode], regs->RdMem(addr++));
137                 break;
138         case 8:                                                                 // Absolute
139                 w = regs->RdMem(addr++);
140                 w |= regs->RdMem(addr++) << 8;
141                 sprintf(buf, "%s $%04X", mnemonics[opcode], w);
142                 break;
143         case 9:                                                                 // Absolute, X
144                 w = regs->RdMem(addr++);
145                 w |= regs->RdMem(addr++) << 8;
146                 sprintf(buf, "%s $%04X,X", mnemonics[opcode], w);
147                 break;
148         case 10:                                                                // Absolute, Y
149                 w = regs->RdMem(addr++);
150                 w |= regs->RdMem(addr++) << 8;
151                 sprintf(buf, "%s $%04X,Y", mnemonics[opcode], w);
152                 break;
153         case 11:                                                                // Indirect
154                 w = regs->RdMem(addr++);
155                 w |= regs->RdMem(addr++) << 8;
156                 sprintf(buf, "%s ($%04X)", mnemonics[opcode], w);
157                 break;
158         case 12:                                                                // Indirect, X
159                 w = regs->RdMem(addr++);
160                 w |= regs->RdMem(addr++) << 8;
161                 sprintf(buf, "%s ($%04X,X)", mnemonics[opcode], w);
162                 break;
163         case 13:                                                                // Relative
164                 sprintf(buf, "%s $%04X", mnemonics[opcode], addr + (int16_t)((int8_t)regs->RdMem(addr)) + 1);
165                 addr++;
166                 break;
167         case 14:                                                                // Inherent
168                 sprintf(buf, "%s ", mnemonics[opcode]);
169                 break;
170         }
171
172         DisplayBytes(regs, buf2, pc, addr);             // Show bytes
173         sprintf(outbuf, "%s %-14s", buf2, buf); // Display opcode & addressing, etc.
174
175         return addr - pc;
176 }
177