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