yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
disassembler_65816.cc
Go to the documentation of this file.
2
3namespace yaze {
4namespace cli {
5namespace agent {
6
8 // Initialize the opcode table with 65816 instruction information
9 // Format: opcode -> {mnemonic, addressing mode, base size, cycles}
10
11 // 0x00 - 0x0F
12 opcode_table_[0x00] = {"BRK", AddressingMode::Immediate8, 2, 7};
13 opcode_table_[0x01] = {"ORA", AddressingMode::IndirectX, 2, 6};
14 opcode_table_[0x02] = {"COP", AddressingMode::Immediate8, 2, 8};
15 opcode_table_[0x03] = {"ORA", AddressingMode::StackRel, 2, 8};
16 opcode_table_[0x04] = {"TSB", AddressingMode::Direct, 2, 3};
17 opcode_table_[0x05] = {"ORA", AddressingMode::Direct, 2, 3};
18 opcode_table_[0x06] = {"ASL", AddressingMode::Direct, 2, 5};
19 opcode_table_[0x07] = {"ORA", AddressingMode::IndirectLong, 2, 5};
20 opcode_table_[0x08] = {"PHP", AddressingMode::Implied, 1, 3};
21 opcode_table_[0x09] = {"ORA", AddressingMode::Immediate8, 2, 2}; // Size depends on M flag
22 opcode_table_[0x0A] = {"ASL", AddressingMode::Accumulator, 1, 2};
23 opcode_table_[0x0B] = {"PHD", AddressingMode::Implied, 1, 4};
24 opcode_table_[0x0C] = {"TSB", AddressingMode::Absolute, 3, 4};
25 opcode_table_[0x0D] = {"ORA", AddressingMode::Absolute, 3, 4};
26 opcode_table_[0x0E] = {"ASL", AddressingMode::Absolute, 3, 6};
27 opcode_table_[0x0F] = {"ORA", AddressingMode::AbsoluteLong, 4, 6};
28
29 // 0x10 - 0x1F
30 opcode_table_[0x10] = {"BPL", AddressingMode::Relative8, 2, 2};
31 opcode_table_[0x11] = {"ORA", AddressingMode::IndirectY, 2, 5};
32 opcode_table_[0x12] = {"ORA", AddressingMode::Indirect, 2, 6};
33 opcode_table_[0x13] = {"ORA", AddressingMode::StackRelY, 2, 8};
34 opcode_table_[0x14] = {"TRB", AddressingMode::Direct, 2, 4};
35 opcode_table_[0x15] = {"ORA", AddressingMode::DirectX, 2, 4};
36 opcode_table_[0x16] = {"ASL", AddressingMode::DirectX, 2, 6};
37 opcode_table_[0x17] = {"ORA", AddressingMode::IndirectLongY, 2, 6};
38 opcode_table_[0x18] = {"CLC", AddressingMode::Implied, 1, 2};
39 opcode_table_[0x19] = {"ORA", AddressingMode::AbsoluteY, 3, 4};
40 opcode_table_[0x1A] = {"INC", AddressingMode::Accumulator, 1, 2};
41 opcode_table_[0x1B] = {"TCS", AddressingMode::Implied, 1, 4};
42 opcode_table_[0x1C] = {"TRB", AddressingMode::Absolute, 3, 4};
43 opcode_table_[0x1D] = {"ORA", AddressingMode::AbsoluteX, 3, 4};
44 opcode_table_[0x1E] = {"ASL", AddressingMode::AbsoluteX, 3, 7};
45 opcode_table_[0x1F] = {"ORA", AddressingMode::AbsoluteXLong, 4, 7};
46
47 // 0x20 - 0x2F
48 opcode_table_[0x20] = {"JSR", AddressingMode::Absolute, 3, 6};
49 opcode_table_[0x21] = {"AND", AddressingMode::IndirectX, 2, 6};
50 opcode_table_[0x22] = {"JSL", AddressingMode::AbsoluteLong, 4, 8};
51 opcode_table_[0x23] = {"AND", AddressingMode::StackRel, 2, 8};
52 opcode_table_[0x24] = {"BIT", AddressingMode::Direct, 2, 3};
53 opcode_table_[0x25] = {"AND", AddressingMode::Direct, 2, 3};
54 opcode_table_[0x26] = {"ROL", AddressingMode::Direct, 2, 5};
55 opcode_table_[0x27] = {"AND", AddressingMode::IndirectLong, 2, 5};
56 opcode_table_[0x28] = {"PLP", AddressingMode::Implied, 1, 4};
57 opcode_table_[0x29] = {"AND", AddressingMode::Immediate8, 2, 2}; // Size depends on M flag
58 opcode_table_[0x2A] = {"ROL", AddressingMode::Accumulator, 1, 2};
59 opcode_table_[0x2B] = {"PLD", AddressingMode::Implied, 1, 4};
60 opcode_table_[0x2C] = {"BIT", AddressingMode::Absolute, 3, 4};
61 opcode_table_[0x2D] = {"AND", AddressingMode::Absolute, 3, 4};
62 opcode_table_[0x2E] = {"ROL", AddressingMode::Absolute, 3, 6};
63 opcode_table_[0x2F] = {"AND", AddressingMode::AbsoluteLong, 4, 6};
64
65 // 0x30 - 0x3F
66 opcode_table_[0x30] = {"BMI", AddressingMode::Relative8, 2, 2};
67 opcode_table_[0x31] = {"AND", AddressingMode::IndirectY, 2, 5};
68 opcode_table_[0x32] = {"AND", AddressingMode::Indirect, 2, 6};
69 opcode_table_[0x33] = {"AND", AddressingMode::StackRelY, 2, 8};
70 opcode_table_[0x34] = {"BIT", AddressingMode::DirectX, 2, 4};
71 opcode_table_[0x35] = {"AND", AddressingMode::DirectX, 2, 4};
72 opcode_table_[0x36] = {"ROL", AddressingMode::DirectX, 2, 6};
73 opcode_table_[0x37] = {"AND", AddressingMode::IndirectLongY, 2, 6};
74 opcode_table_[0x38] = {"SEC", AddressingMode::Implied, 1, 2};
75 opcode_table_[0x39] = {"AND", AddressingMode::AbsoluteY, 3, 4};
76 opcode_table_[0x3A] = {"DEC", AddressingMode::Accumulator, 1, 2};
77 opcode_table_[0x3B] = {"TSC", AddressingMode::Implied, 1, 4};
78 opcode_table_[0x3C] = {"BIT", AddressingMode::AbsoluteX, 3, 4};
79 opcode_table_[0x3D] = {"AND", AddressingMode::AbsoluteX, 3, 4};
80 opcode_table_[0x3E] = {"ROL", AddressingMode::AbsoluteX, 3, 7};
81 opcode_table_[0x3F] = {"AND", AddressingMode::AbsoluteXLong, 4, 7};
82
83 // 0x40 - 0x4F
84 opcode_table_[0x40] = {"RTI", AddressingMode::Implied, 1, 6};
85 opcode_table_[0x41] = {"EOR", AddressingMode::IndirectX, 2, 6};
86 opcode_table_[0x42] = {"WDM", AddressingMode::Immediate8, 2, 8};
87 opcode_table_[0x43] = {"EOR", AddressingMode::StackRel, 2, 8};
88 opcode_table_[0x44] = {"MVP", AddressingMode::BlockMove, 3, 3};
89 opcode_table_[0x45] = {"EOR", AddressingMode::Direct, 2, 3};
90 opcode_table_[0x46] = {"LSR", AddressingMode::Direct, 2, 5};
91 opcode_table_[0x47] = {"EOR", AddressingMode::IndirectLong, 2, 5};
92 opcode_table_[0x48] = {"PHA", AddressingMode::Implied, 1, 3};
93 opcode_table_[0x49] = {"EOR", AddressingMode::Immediate8, 2, 2}; // Size depends on M flag
94 opcode_table_[0x4A] = {"LSR", AddressingMode::Accumulator, 1, 2};
95 opcode_table_[0x4B] = {"PHK", AddressingMode::Implied, 1, 4};
96 opcode_table_[0x4C] = {"JMP", AddressingMode::Absolute, 3, 3};
97 opcode_table_[0x4D] = {"EOR", AddressingMode::Absolute, 3, 4};
98 opcode_table_[0x4E] = {"LSR", AddressingMode::Absolute, 3, 6};
99 opcode_table_[0x4F] = {"EOR", AddressingMode::AbsoluteLong, 4, 6};
100
101 // 0x50 - 0x5F
102 opcode_table_[0x50] = {"BVC", AddressingMode::Relative8, 2, 2};
103 opcode_table_[0x51] = {"EOR", AddressingMode::IndirectY, 2, 5};
104 opcode_table_[0x52] = {"EOR", AddressingMode::Indirect, 2, 6};
105 opcode_table_[0x53] = {"EOR", AddressingMode::StackRelY, 2, 8};
106 opcode_table_[0x54] = {"MVN", AddressingMode::BlockMove, 3, 4};
107 opcode_table_[0x55] = {"EOR", AddressingMode::DirectX, 2, 4};
108 opcode_table_[0x56] = {"LSR", AddressingMode::DirectX, 2, 6};
109 opcode_table_[0x57] = {"EOR", AddressingMode::IndirectLongY, 2, 6};
110 opcode_table_[0x58] = {"CLI", AddressingMode::Implied, 1, 2};
111 opcode_table_[0x59] = {"EOR", AddressingMode::AbsoluteY, 3, 4};
112 opcode_table_[0x5A] = {"PHY", AddressingMode::Implied, 1, 2};
113 opcode_table_[0x5B] = {"TCD", AddressingMode::Implied, 1, 4};
114 opcode_table_[0x5C] = {"JMP", AddressingMode::AbsoluteLong, 4, 4};
115 opcode_table_[0x5D] = {"EOR", AddressingMode::AbsoluteX, 3, 4};
116 opcode_table_[0x5E] = {"LSR", AddressingMode::AbsoluteX, 3, 7};
117 opcode_table_[0x5F] = {"EOR", AddressingMode::AbsoluteXLong, 4, 7};
118
119 // 0x60 - 0x6F
120 opcode_table_[0x60] = {"RTS", AddressingMode::Implied, 1, 6};
121 opcode_table_[0x61] = {"ADC", AddressingMode::IndirectX, 2, 6};
122 opcode_table_[0x62] = {"PER", AddressingMode::Relative16, 3, 8};
123 opcode_table_[0x63] = {"ADC", AddressingMode::StackRel, 2, 8};
124 opcode_table_[0x64] = {"STZ", AddressingMode::Direct, 2, 3};
125 opcode_table_[0x65] = {"ADC", AddressingMode::Direct, 2, 3};
126 opcode_table_[0x66] = {"ROR", AddressingMode::Direct, 2, 5};
127 opcode_table_[0x67] = {"ADC", AddressingMode::IndirectLong, 2, 5};
128 opcode_table_[0x68] = {"PLA", AddressingMode::Implied, 1, 4};
129 opcode_table_[0x69] = {"ADC", AddressingMode::Immediate8, 2, 2}; // Size depends on M flag
130 opcode_table_[0x6A] = {"ROR", AddressingMode::Accumulator, 1, 2};
131 opcode_table_[0x6B] = {"RTL", AddressingMode::Implied, 1, 4};
132 opcode_table_[0x6C] = {"JMP", AddressingMode::Indirect, 3, 5};
133 opcode_table_[0x6D] = {"ADC", AddressingMode::Absolute, 3, 4};
134 opcode_table_[0x6E] = {"ROR", AddressingMode::Absolute, 3, 6};
135 opcode_table_[0x6F] = {"ADC", AddressingMode::AbsoluteLong, 4, 6};
136
137 // 0x70 - 0x7F
138 opcode_table_[0x70] = {"BVS", AddressingMode::Relative8, 2, 2};
139 opcode_table_[0x71] = {"ADC", AddressingMode::IndirectY, 2, 5};
140 opcode_table_[0x72] = {"ADC", AddressingMode::Indirect, 2, 6};
141 opcode_table_[0x73] = {"ADC", AddressingMode::StackRelY, 2, 8};
142 opcode_table_[0x74] = {"STZ", AddressingMode::DirectX, 2, 4};
143 opcode_table_[0x75] = {"ADC", AddressingMode::DirectX, 2, 4};
144 opcode_table_[0x76] = {"ROR", AddressingMode::DirectX, 2, 6};
145 opcode_table_[0x77] = {"ADC", AddressingMode::IndirectLongY, 2, 6};
146 opcode_table_[0x78] = {"SEI", AddressingMode::Implied, 1, 2};
147 opcode_table_[0x79] = {"ADC", AddressingMode::AbsoluteY, 3, 4};
148 opcode_table_[0x7A] = {"PLY", AddressingMode::Implied, 1, 2};
149 opcode_table_[0x7B] = {"TDC", AddressingMode::Implied, 1, 4};
150 opcode_table_[0x7C] = {"JMP", AddressingMode::AbsoluteX, 3, 6};
151 opcode_table_[0x7D] = {"ADC", AddressingMode::AbsoluteX, 3, 4};
152 opcode_table_[0x7E] = {"ROR", AddressingMode::AbsoluteX, 3, 7};
153 opcode_table_[0x7F] = {"ADC", AddressingMode::AbsoluteXLong, 4, 7};
154
155 // 0x80 - 0x8F
156 opcode_table_[0x80] = {"BRA", AddressingMode::Relative8, 2, 2};
157 opcode_table_[0x81] = {"STA", AddressingMode::IndirectX, 2, 6};
158 opcode_table_[0x82] = {"BRL", AddressingMode::Relative16, 3, 5};
159 opcode_table_[0x83] = {"STA", AddressingMode::StackRel, 2, 8};
160 opcode_table_[0x84] = {"STY", AddressingMode::Direct, 2, 3};
161 opcode_table_[0x85] = {"STA", AddressingMode::Direct, 2, 3};
162 opcode_table_[0x86] = {"STX", AddressingMode::Direct, 2, 3};
163 opcode_table_[0x87] = {"STA", AddressingMode::IndirectLong, 2, 5};
164 opcode_table_[0x88] = {"DEY", AddressingMode::Implied, 1, 2};
165 opcode_table_[0x89] = {"BIT", AddressingMode::Immediate8, 2, 2}; // Size depends on M flag
166 opcode_table_[0x8A] = {"TXA", AddressingMode::Implied, 1, 2};
167 opcode_table_[0x8B] = {"PHB", AddressingMode::Implied, 1, 4};
168 opcode_table_[0x8C] = {"STY", AddressingMode::Absolute, 3, 4};
169 opcode_table_[0x8D] = {"STA", AddressingMode::Absolute, 3, 4};
170 opcode_table_[0x8E] = {"STX", AddressingMode::Absolute, 3, 4};
171 opcode_table_[0x8F] = {"STA", AddressingMode::AbsoluteLong, 4, 6};
172
173 // 0x90 - 0x9F
174 opcode_table_[0x90] = {"BCC", AddressingMode::Relative8, 2, 2};
175 opcode_table_[0x91] = {"STA", AddressingMode::IndirectY, 2, 6};
176 opcode_table_[0x92] = {"STA", AddressingMode::Indirect, 2, 5};
177 opcode_table_[0x93] = {"STA", AddressingMode::StackRelY, 2, 8};
178 opcode_table_[0x94] = {"STY", AddressingMode::DirectX, 2, 4};
179 opcode_table_[0x95] = {"STA", AddressingMode::DirectX, 2, 4};
180 opcode_table_[0x96] = {"STX", AddressingMode::DirectY, 2, 4};
181 opcode_table_[0x97] = {"STA", AddressingMode::IndirectLongY, 2, 6};
182 opcode_table_[0x98] = {"TYA", AddressingMode::Implied, 1, 2};
183 opcode_table_[0x99] = {"STA", AddressingMode::AbsoluteY, 3, 5};
184 opcode_table_[0x9A] = {"TXS", AddressingMode::Implied, 1, 2};
185 opcode_table_[0x9B] = {"TXY", AddressingMode::Implied, 1, 4};
186 opcode_table_[0x9C] = {"STZ", AddressingMode::Absolute, 3, 4};
187 opcode_table_[0x9D] = {"STA", AddressingMode::AbsoluteX, 3, 4};
188 opcode_table_[0x9E] = {"STZ", AddressingMode::AbsoluteX, 3, 4};
189 opcode_table_[0x9F] = {"STA", AddressingMode::AbsoluteXLong, 4, 5};
190
191 // 0xA0 - 0xAF
192 opcode_table_[0xA0] = {"LDY", AddressingMode::ImmediateX, 2, 2}; // Size depends on X flag
193 opcode_table_[0xA1] = {"LDA", AddressingMode::IndirectX, 2, 6};
194 opcode_table_[0xA2] = {"LDX", AddressingMode::ImmediateX, 2, 2}; // Size depends on X flag
195 opcode_table_[0xA3] = {"LDA", AddressingMode::StackRel, 2, 8};
196 opcode_table_[0xA4] = {"LDY", AddressingMode::Direct, 2, 3};
197 opcode_table_[0xA5] = {"LDA", AddressingMode::Direct, 2, 3};
198 opcode_table_[0xA6] = {"LDX", AddressingMode::Direct, 2, 3};
199 opcode_table_[0xA7] = {"LDA", AddressingMode::IndirectLong, 2, 5};
200 opcode_table_[0xA8] = {"TAY", AddressingMode::Implied, 1, 2};
201 opcode_table_[0xA9] = {"LDA", AddressingMode::Immediate8, 2, 2}; // Size depends on M flag
202 opcode_table_[0xAA] = {"TAX", AddressingMode::Implied, 1, 2};
203 opcode_table_[0xAB] = {"PLB", AddressingMode::Implied, 1, 4};
204 opcode_table_[0xAC] = {"LDY", AddressingMode::Absolute, 3, 4};
205 opcode_table_[0xAD] = {"LDA", AddressingMode::Absolute, 3, 4};
206 opcode_table_[0xAE] = {"LDX", AddressingMode::Absolute, 3, 4};
207 opcode_table_[0xAF] = {"LDA", AddressingMode::AbsoluteLong, 4, 6};
208
209 // 0xB0 - 0xBF
210 opcode_table_[0xB0] = {"BCS", AddressingMode::Relative8, 2, 2};
211 opcode_table_[0xB1] = {"LDA", AddressingMode::IndirectY, 2, 5};
212 opcode_table_[0xB2] = {"LDA", AddressingMode::Indirect, 2, 5};
213 opcode_table_[0xB3] = {"LDA", AddressingMode::StackRelY, 2, 8};
214 opcode_table_[0xB4] = {"LDY", AddressingMode::DirectX, 2, 4};
215 opcode_table_[0xB5] = {"LDA", AddressingMode::DirectX, 2, 4};
216 opcode_table_[0xB6] = {"LDX", AddressingMode::DirectY, 2, 4};
217 opcode_table_[0xB7] = {"LDA", AddressingMode::IndirectLongY, 2, 6};
218 opcode_table_[0xB8] = {"CLV", AddressingMode::Implied, 1, 2};
219 opcode_table_[0xB9] = {"LDA", AddressingMode::AbsoluteY, 3, 4};
220 opcode_table_[0xBA] = {"TSX", AddressingMode::Implied, 1, 2};
221 opcode_table_[0xBB] = {"TYX", AddressingMode::Implied, 1, 4};
222 opcode_table_[0xBC] = {"LDY", AddressingMode::AbsoluteX, 3, 4};
223 opcode_table_[0xBD] = {"LDA", AddressingMode::AbsoluteX, 3, 4};
224 opcode_table_[0xBE] = {"LDX", AddressingMode::AbsoluteY, 3, 4};
225 opcode_table_[0xBF] = {"LDA", AddressingMode::AbsoluteXLong, 4, 5};
226
227 // 0xC0 - 0xCF
228 opcode_table_[0xC0] = {"CPY", AddressingMode::ImmediateX, 2, 2}; // Size depends on X flag
229 opcode_table_[0xC1] = {"CMP", AddressingMode::IndirectX, 2, 6};
230 opcode_table_[0xC2] = {"REP", AddressingMode::Immediate8, 2, 2};
231 opcode_table_[0xC3] = {"CMP", AddressingMode::StackRel, 2, 8};
232 opcode_table_[0xC4] = {"CPY", AddressingMode::Direct, 2, 3};
233 opcode_table_[0xC5] = {"CMP", AddressingMode::Direct, 2, 3};
234 opcode_table_[0xC6] = {"DEC", AddressingMode::Direct, 2, 5};
235 opcode_table_[0xC7] = {"CMP", AddressingMode::IndirectLong, 2, 5};
236 opcode_table_[0xC8] = {"INY", AddressingMode::Implied, 1, 2};
237 opcode_table_[0xC9] = {"CMP", AddressingMode::Immediate8, 2, 2}; // Size depends on M flag
238 opcode_table_[0xCA] = {"DEX", AddressingMode::Implied, 1, 2};
239 opcode_table_[0xCB] = {"WAI", AddressingMode::Implied, 1, 4};
240 opcode_table_[0xCC] = {"CPY", AddressingMode::Absolute, 3, 4};
241 opcode_table_[0xCD] = {"CMP", AddressingMode::Absolute, 3, 4};
242 opcode_table_[0xCE] = {"DEC", AddressingMode::Absolute, 3, 6};
243 opcode_table_[0xCF] = {"CMP", AddressingMode::AbsoluteLong, 4, 6};
244
245 // 0xD0 - 0xDF
246 opcode_table_[0xD0] = {"BNE", AddressingMode::Relative8, 2, 2};
247 opcode_table_[0xD1] = {"CMP", AddressingMode::IndirectY, 2, 5};
248 opcode_table_[0xD2] = {"CMP", AddressingMode::Indirect, 2, 5};
249 opcode_table_[0xD3] = {"CMP", AddressingMode::StackRelY, 2, 8};
250 opcode_table_[0xD4] = {"PEI", AddressingMode::Indirect, 2, 4};
251 opcode_table_[0xD5] = {"CMP", AddressingMode::DirectX, 2, 4};
252 opcode_table_[0xD6] = {"DEC", AddressingMode::DirectX, 2, 6};
253 opcode_table_[0xD7] = {"CMP", AddressingMode::IndirectLongY, 2, 6};
254 opcode_table_[0xD8] = {"CLD", AddressingMode::Implied, 1, 2};
255 opcode_table_[0xD9] = {"CMP", AddressingMode::AbsoluteY, 3, 4};
256 opcode_table_[0xDA] = {"PHX", AddressingMode::Implied, 1, 2};
257 opcode_table_[0xDB] = {"STP", AddressingMode::Implied, 1, 4};
258 opcode_table_[0xDC] = {"JMP", AddressingMode::IndirectLong, 3, 3};
259 opcode_table_[0xDD] = {"CMP", AddressingMode::AbsoluteX, 3, 4};
260 opcode_table_[0xDE] = {"DEC", AddressingMode::AbsoluteX, 3, 7};
261 opcode_table_[0xDF] = {"CMP", AddressingMode::AbsoluteXLong, 4, 7};
262
263 // 0xE0 - 0xEF
264 opcode_table_[0xE0] = {"CPX", AddressingMode::ImmediateX, 2, 2}; // Size depends on X flag
265 opcode_table_[0xE1] = {"SBC", AddressingMode::IndirectX, 2, 6};
266 opcode_table_[0xE2] = {"SEP", AddressingMode::Immediate8, 2, 2};
267 opcode_table_[0xE3] = {"SBC", AddressingMode::StackRel, 2, 8};
268 opcode_table_[0xE4] = {"CPX", AddressingMode::Direct, 2, 3};
269 opcode_table_[0xE5] = {"SBC", AddressingMode::Direct, 2, 3};
270 opcode_table_[0xE6] = {"INC", AddressingMode::Direct, 2, 5};
271 opcode_table_[0xE7] = {"SBC", AddressingMode::IndirectLong, 2, 5};
272 opcode_table_[0xE8] = {"INX", AddressingMode::Implied, 1, 2};
273 opcode_table_[0xE9] = {"SBC", AddressingMode::Immediate8, 2, 2}; // Size depends on M flag
274 opcode_table_[0xEA] = {"NOP", AddressingMode::Implied, 1, 2};
275 opcode_table_[0xEB] = {"XBA", AddressingMode::Implied, 1, 2};
276 opcode_table_[0xEC] = {"CPX", AddressingMode::Absolute, 3, 4};
277 opcode_table_[0xED] = {"SBC", AddressingMode::Absolute, 3, 4};
278 opcode_table_[0xEE] = {"INC", AddressingMode::Absolute, 3, 6};
279 opcode_table_[0xEF] = {"SBC", AddressingMode::AbsoluteLong, 4, 6};
280
281 // 0xF0 - 0xFF
282 opcode_table_[0xF0] = {"BEQ", AddressingMode::Relative8, 2, 2};
283 opcode_table_[0xF1] = {"SBC", AddressingMode::IndirectY, 2, 5};
284 opcode_table_[0xF2] = {"SBC", AddressingMode::Indirect, 2, 5};
285 opcode_table_[0xF3] = {"SBC", AddressingMode::StackRelY, 2, 8};
286 opcode_table_[0xF4] = {"PEA", AddressingMode::Absolute, 3, 4};
287 opcode_table_[0xF5] = {"SBC", AddressingMode::DirectX, 2, 4};
288 opcode_table_[0xF6] = {"INC", AddressingMode::DirectX, 2, 6};
289 opcode_table_[0xF7] = {"SBC", AddressingMode::IndirectLongY, 2, 6};
290 opcode_table_[0xF8] = {"SED", AddressingMode::Implied, 1, 2};
291 opcode_table_[0xF9] = {"SBC", AddressingMode::AbsoluteY, 3, 4};
292 opcode_table_[0xFA] = {"PLX", AddressingMode::Implied, 1, 2};
293 opcode_table_[0xFB] = {"XCE", AddressingMode::Implied, 1, 2};
294 opcode_table_[0xFC] = {"JSR", AddressingMode::AbsoluteX, 3, 3};
295 opcode_table_[0xFD] = {"SBC", AddressingMode::AbsoluteX, 3, 4};
296 opcode_table_[0xFE] = {"INC", AddressingMode::AbsoluteX, 3, 7};
297 opcode_table_[0xFF] = {"SBC", AddressingMode::AbsoluteXLong, 4, 7};
298}
299
301 uint32_t address, const uint8_t* data, std::string& mnemonic,
302 std::string& operand_str, std::vector<uint8_t>& operands) {
303 uint8_t opcode = data[0];
304
305 auto it = opcode_table_.find(opcode);
306 if (it == opcode_table_.end()) {
307 // Unknown opcode
308 mnemonic = absl::StrFormat("DB $%02X", opcode);
309 operand_str = "";
310 operands.clear();
311 return 1;
312 }
313
314 const InstructionInfo& info = it->second;
315 mnemonic = info.mnemonic;
316
317 // Get the effective size based on M/X flags
318 uint8_t size = GetEffectiveSize(opcode, info.mode);
319
320 // Extract operand bytes
321 operands.clear();
322 for (uint8_t i = 1; i < size; ++i) {
323 operands.push_back(data[i]);
324 }
325
326 // Format the operand string
327 operand_str = FormatOperand(info.mode, address, operands);
328
329 return size;
330}
331
332uint8_t Disassembler65816::GetInstructionSize(uint8_t opcode) const {
333 auto it = opcode_table_.find(opcode);
334 if (it == opcode_table_.end()) {
335 return 1; // Unknown opcode
336 }
337
338 return GetEffectiveSize(opcode, it->second.mode);
339}
340
342 AddressingMode mode) const {
343 auto it = opcode_table_.find(opcode);
344 if (it == opcode_table_.end()) {
345 return 1;
346 }
347
348 uint8_t base_size = it->second.base_size;
349
350 // Adjust size based on M and X flags for immediate mode instructions
351 switch (mode) {
353 // Instructions affected by M flag (accumulator/memory operations)
354 if (opcode == 0x09 || opcode == 0x29 || opcode == 0x49 || // ORA, AND, EOR
355 opcode == 0x69 || opcode == 0x89 || opcode == 0xA9 || // ADC, BIT, LDA
356 opcode == 0xC9 || opcode == 0xE9) { // CMP, SBC
357 return m_flag_ ? 2 : 3; // 8-bit when M=1, 16-bit when M=0
358 }
359 return base_size;
360
362 // Instructions affected by X flag (index register operations)
363 if (opcode == 0xA0 || opcode == 0xA2 || // LDY, LDX
364 opcode == 0xC0 || opcode == 0xE0) { // CPY, CPX
365 return x_flag_ ? 2 : 3; // 8-bit when X=1, 16-bit when X=0
366 }
367 return base_size;
368
369 default:
370 return base_size;
371 }
372}
373
375 AddressingMode mode, uint32_t address,
376 const std::vector<uint8_t>& operands) const {
377 switch (mode) {
380 return "";
381
383 if (operands.size() == 1) {
384 return absl::StrFormat("#$%02X", operands[0]);
385 } else if (operands.size() == 2) {
386 return absl::StrFormat("#$%04X", operands[0] | (operands[1] << 8));
387 }
388 break;
389
392 if (operands.size() == 1) {
393 return absl::StrFormat("#$%02X", operands[0]);
394 } else if (operands.size() == 2) {
395 return absl::StrFormat("#$%04X", operands[0] | (operands[1] << 8));
396 }
397 break;
398
400 if (operands.size() == 2) {
401 return absl::StrFormat("$%04X", operands[0] | (operands[1] << 8));
402 }
403 break;
404
406 if (operands.size() == 3) {
407 return absl::StrFormat("$%02X%04X", operands[2],
408 operands[0] | (operands[1] << 8));
409 }
410 break;
411
413 if (operands.size() == 2) {
414 return absl::StrFormat("$%04X,X", operands[0] | (operands[1] << 8));
415 }
416 break;
417
419 if (operands.size() == 3) {
420 return absl::StrFormat("$%02X%04X,X", operands[2],
421 operands[0] | (operands[1] << 8));
422 }
423 break;
424
426 if (operands.size() == 2) {
427 return absl::StrFormat("$%04X,Y", operands[0] | (operands[1] << 8));
428 }
429 break;
430
432 if (operands.size() == 1) {
433 return absl::StrFormat("$%02X", operands[0]);
434 }
435 break;
436
438 if (operands.size() == 1) {
439 return absl::StrFormat("$%02X,X", operands[0]);
440 }
441 break;
442
444 if (operands.size() == 1) {
445 return absl::StrFormat("$%02X,Y", operands[0]);
446 }
447 break;
448
450 if (operands.size() == 1) {
451 return absl::StrFormat("($%02X)", operands[0]);
452 } else if (operands.size() == 2) {
453 return absl::StrFormat("($%04X)", operands[0] | (operands[1] << 8));
454 }
455 break;
456
458 if (operands.size() == 1) {
459 return absl::StrFormat("($%02X,X)", operands[0]);
460 }
461 break;
462
464 if (operands.size() == 1) {
465 return absl::StrFormat("($%02X),Y", operands[0]);
466 }
467 break;
468
470 if (operands.size() == 1) {
471 return absl::StrFormat("[$%02X]", operands[0]);
472 }
473 break;
474
476 if (operands.size() == 1) {
477 return absl::StrFormat("[$%02X],Y", operands[0]);
478 }
479 break;
480
482 if (operands.size() == 1) {
483 return absl::StrFormat("$%02X,S", operands[0]);
484 }
485 break;
486
488 if (operands.size() == 1) {
489 return absl::StrFormat("($%02X,S),Y", operands[0]);
490 }
491 break;
492
494 if (operands.size() == 1) {
495 int8_t offset = static_cast<int8_t>(operands[0]);
496 uint32_t target = address + 2 + offset; // +2 for instruction size
497 return absl::StrFormat("$%04X", target & 0xFFFF);
498 }
499 break;
500
502 if (operands.size() == 2) {
503 int16_t offset = static_cast<int16_t>(operands[0] | (operands[1] << 8));
504 uint32_t target = address + 3 + offset; // +3 for instruction size
505 return absl::StrFormat("$%04X", target & 0xFFFF);
506 }
507 break;
508
510 if (operands.size() == 2) {
511 return absl::StrFormat("$%02X,$%02X", operands[1], operands[0]);
512 }
513 break;
514 }
515
516 return "???";
517}
518
519// ExecutionTraceBuffer implementation
520
522 if (buffer_.size() < max_size_) {
523 buffer_.push_back(entry);
524 } else {
525 // Circular buffer behavior
526 buffer_[write_index_] = entry;
528 }
529}
530
531std::vector<ExecutionTraceBuffer::TraceEntry>
533 std::vector<TraceEntry> result;
534
535 if (buffer_.empty()) {
536 return result;
537 }
538
539 size_t start_idx;
540 size_t entries_to_copy = std::min(count, buffer_.size());
541
542 if (buffer_.size() < max_size_) {
543 // Buffer not full yet
544 start_idx = buffer_.size() >= entries_to_copy
545 ? buffer_.size() - entries_to_copy
546 : 0;
547 for (size_t i = start_idx; i < buffer_.size(); ++i) {
548 result.push_back(buffer_[i]);
549 }
550 } else {
551 // Circular buffer is full
552 start_idx = write_index_ >= entries_to_copy
553 ? write_index_ - entries_to_copy
554 : max_size_ - (entries_to_copy - write_index_);
555
556 for (size_t i = 0; i < entries_to_copy; ++i) {
557 result.push_back(buffer_[(start_idx + i) % max_size_]);
558 }
559 }
560
561 return result;
562}
563
564std::vector<ExecutionTraceBuffer::TraceEntry>
566 uint32_t end_addr) const {
567 std::vector<TraceEntry> result;
568
569 for (const auto& entry : buffer_) {
570 if (entry.address >= start_addr && entry.address <= end_addr) {
571 result.push_back(entry);
572 }
573 }
574
575 return result;
576}
577
578} // namespace agent
579} // namespace cli
580} // namespace yaze
uint8_t DisassembleInstruction(uint32_t address, const uint8_t *data, std::string &mnemonic, std::string &operand_str, std::vector< uint8_t > &operands)
std::unordered_map< uint8_t, InstructionInfo > opcode_table_
uint8_t GetInstructionSize(uint8_t opcode) const
std::string FormatOperand(AddressingMode mode, uint32_t address, const std::vector< uint8_t > &operands) const
uint8_t GetEffectiveSize(uint8_t opcode, AddressingMode mode) const
void RecordExecution(const TraceEntry &entry)
std::vector< TraceEntry > GetRecentEntries(size_t count) const
std::vector< TraceEntry > GetEntriesInRange(uint32_t start_addr, uint32_t end_addr) const