1 /*****************************************************************************/
5 /* Opcode handler functions for the disassembler */
9 /* (C) 2000-2004 Ullrich von Bassewitz */
10 /* Römerstrasse 52 */
11 /* D-70794 Filderstadt */
12 /* EMail: uz@cc65.org */
15 /* This software is provided 'as-is', without any expressed or implied */
16 /* warranty. In no event will the authors be held liable for any damages */
17 /* arising from the use of this software. */
19 /* Permission is granted to anyone to use this software for any purpose, */
20 /* including commercial applications, and to alter it and redistribute it */
21 /* freely, subject to the following restrictions: */
23 /* 1. The origin of this software must not be misrepresented; you must not */
24 /* claim that you wrote the original software. If you use this software */
25 /* in a product, an acknowledgment in the product documentation would be */
26 /* appreciated but is not required. */
27 /* 2. Altered source versions must be plainly marked as such, and must not */
28 /* be misrepresented as being the original software. */
29 /* 3. This notice may not be removed or altered from any source */
32 /*****************************************************************************/
52 /*****************************************************************************/
53 /* Helper functions */
54 /*****************************************************************************/
58 static void Mnemonic (const char* M)
59 /* Indent and output a mnemonic */
67 static void OneLine (const OpcDesc* D, const char* Arg, ...) attribute ((format(printf, 2, 3)));
68 static void OneLine (const OpcDesc* D, const char* Arg, ...)
69 /* Output one line with the given mnemonic and argument */
79 xvsprintf (Buf, sizeof (Buf), Arg, ap);
84 /* Add the code stuff as comment */
85 LineComment (PC, D->Size);
93 static const char* GetAbsOverride (unsigned Flags, unsigned Addr)
94 /* If the instruction requires an abs override modifier, return the necessary
95 * string, otherwise return the empty string.
98 if ((Flags & flAbsOverride) != 0 && Addr < 0x100) {
107 static const char* GetAddrArg (unsigned Flags, unsigned Addr)
108 /* Return an address argument - a label if we have one, or the address itself */
110 const char* Label = 0;
111 if (Flags & flUseLabel) {
112 Label = GetLabel (Addr);
117 static char Buf [32];
119 xsprintf (Buf, sizeof (Buf), "$%02X", Addr);
121 xsprintf (Buf, sizeof (Buf), "$%04X", Addr);
129 static void GenerateLabel (unsigned Flags, unsigned Addr)
130 /* Generate a label in pass one if requested */
132 /* Generate labels in pass #1, and only if we don't have a label already */
133 if (Pass == 1 && !HaveLabel (Addr) &&
134 /* Check if we must create a label */
135 ((Flags & flGenLabel) != 0 ||
136 ((Flags & flUseLabel) != 0 && Addr >= CodeStart && Addr <= CodeEnd))) {
138 /* As a special case, handle ranges with tables or similar. Within
139 * such a range with a granularity > 1, do only generate dependent
140 * labels for all addresses but the first one. Be sure to generate
141 * a label for the start of the range, however.
143 attr_t Style = GetStyleAttr (Addr);
144 unsigned Granularity = GetGranularity (Style);
146 if (Granularity == 1) {
147 /* Just add the label */
148 AddLabel (Addr, atIntLabel, MakeLabelName (Addr));
150 /* Search for the start of the range or the last non dependent
151 * label in the range.
155 unsigned LabelAddr = Addr;
156 while (LabelAddr > CodeStart) {
158 if (Style != GetStyleAttr (LabelAddr-1)) {
159 /* End of range reached */
163 LabelAttr = GetLabelAttr (LabelAddr);
164 if ((LabelAttr & (atIntLabel|atExtLabel)) != 0 &&
165 (LabelAttr & atDepLabel) == 0) {
166 /* The address has an internal or external label */
171 /* If the proposed label address doesn't have a label, define one */
172 if ((GetLabelAttr (LabelAddr) & (atIntLabel|atExtLabel)) == 0) {
173 AddLabel (LabelAddr, atIntLabel, MakeLabelName (LabelAddr));
176 /* Create the label */
177 Offs = Addr - LabelAddr;
179 AddLabel (Addr, atIntLabel, MakeLabelName (Addr));
181 AddDepLabel (Addr, atIntLabel, GetLabel (LabelAddr), Offs);
189 /*****************************************************************************/
191 /*****************************************************************************/
195 void OH_Illegal (const OpcDesc* D attribute ((unused)))
202 void OH_Accumulator (const OpcDesc* D)
209 void OH_Implicit (const OpcDesc* D)
212 LineComment (PC, D->Size);
218 void OH_Immidiate (const OpcDesc* D)
220 OneLine (D, "#$%02X", GetCodeByte (PC+1));
225 void OH_Direct (const OpcDesc* D)
227 /* Get the operand */
228 unsigned Addr = GetCodeByte (PC+1);
230 /* Generate a label in pass 1 */
231 GenerateLabel (D->Flags, Addr);
233 /* Output the line */
234 OneLine (D, "%s", GetAddrArg (D->Flags, Addr));
239 void OH_DirectX (const OpcDesc* D)
241 /* Get the operand */
242 unsigned Addr = GetCodeByte (PC+1);
244 /* Generate a label in pass 1 */
245 GenerateLabel (D->Flags, Addr);
247 /* Output the line */
248 OneLine (D, "%s,x", GetAddrArg (D->Flags, Addr));
253 void OH_DirectY (const OpcDesc* D)
255 /* Get the operand */
256 unsigned Addr = GetCodeByte (PC+1);
258 /* Generate a label in pass 1 */
259 GenerateLabel (D->Flags, Addr);
261 /* Output the line */
262 OneLine (D, "%s,y", GetAddrArg (D->Flags, Addr));
267 void OH_Absolute (const OpcDesc* D)
269 /* Get the operand */
270 unsigned Addr = GetCodeWord (PC+1);
272 /* Generate a label in pass 1 */
273 GenerateLabel (D->Flags, Addr);
275 /* Output the line */
276 OneLine (D, "%s%s", GetAbsOverride (D->Flags, Addr), GetAddrArg (D->Flags, Addr));
281 void OH_AbsoluteX (const OpcDesc* D)
283 /* Get the operand */
284 unsigned Addr = GetCodeWord (PC+1);
286 /* Generate a label in pass 1 */
287 GenerateLabel (D->Flags, Addr);
289 /* Output the line */
290 OneLine (D, "%s%s,x", GetAbsOverride (D->Flags, Addr), GetAddrArg (D->Flags, Addr));
295 void OH_AbsoluteY (const OpcDesc* D)
297 /* Get the operand */
298 unsigned Addr = GetCodeWord (PC+1);
300 /* Generate a label in pass 1 */
301 GenerateLabel (D->Flags, Addr);
303 /* Output the line */
304 OneLine (D, "%s%s,y", GetAbsOverride (D->Flags, Addr), GetAddrArg (D->Flags, Addr));
309 void OH_AbsoluteLong (const OpcDesc* D attribute ((unused)))
311 Error ("Not implemented");
316 void OH_AbsoluteLongX (const OpcDesc* D attribute ((unused)))
318 Error ("Not implemented");
323 void OH_Relative (const OpcDesc* D)
325 /* Get the operand */
326 signed char Offs = GetCodeByte (PC+1);
328 /* Calculate the target address */
329 unsigned Addr = (((int) PC+2) + Offs) & 0xFFFF;
331 /* Generate a label in pass 1 */
332 GenerateLabel (D->Flags, Addr);
334 /* Output the line */
335 OneLine (D, "%s", GetAddrArg (D->Flags, Addr));
340 void OH_RelativeLong (const OpcDesc* D attribute ((unused)))
342 Error ("Not implemented");
347 void OH_DirectIndirect (const OpcDesc* D)
349 /* Get the operand */
350 unsigned Addr = GetCodeByte (PC+1);
352 /* Generate a label in pass 1 */
353 GenerateLabel (D->Flags, Addr);
355 /* Output the line */
356 OneLine (D, "(%s)", GetAddrArg (D->Flags, Addr));
361 void OH_DirectIndirectY (const OpcDesc* D)
363 /* Get the operand */
364 unsigned Addr = GetCodeByte (PC+1);
366 /* Generate a label in pass 1 */
367 GenerateLabel (D->Flags, Addr);
369 /* Output the line */
370 OneLine (D, "(%s),y", GetAddrArg (D->Flags, Addr));
375 void OH_DirectXIndirect (const OpcDesc* D)
377 /* Get the operand */
378 unsigned Addr = GetCodeByte (PC+1);
380 /* Generate a label in pass 1 */
381 GenerateLabel (D->Flags, Addr);
383 /* Output the line */
384 OneLine (D, "(%s,x)", GetAddrArg (D->Flags, Addr));
389 void OH_AbsoluteIndirect (const OpcDesc* D)
391 /* Get the operand */
392 unsigned Addr = GetCodeWord (PC+1);
394 /* Generate a label in pass 1 */
395 GenerateLabel (D->Flags, Addr);
397 /* Output the line */
398 OneLine (D, "(%s)", GetAddrArg (D->Flags, Addr));
403 void OH_BitBranch (const OpcDesc* D)
405 /* Get the operands */
406 unsigned char TestAddr = GetCodeByte (PC+1);
407 signed char BranchOffs = GetCodeByte (PC+2);
409 /* Calculate the target address for the branch */
410 unsigned BranchAddr = (((int) PC+3) + BranchOffs) & 0xFFFF;
412 /* Generate labels in pass 1. The bit branch codes are special in that
413 * they don't really match the remainder of the 6502 instruction set (they
414 * are a Rockwell addon), so we must pass additional flags as direct
415 * value to the second GenerateLabel call.
417 GenerateLabel (D->Flags, TestAddr);
418 GenerateLabel (flLabel, BranchAddr);
420 /* Output the line */
421 OneLine (D, "%s,%s", GetAddrArg (D->Flags, TestAddr), GetAddrArg (flLabel, BranchAddr));
426 void OH_StackRelative (const OpcDesc* D attribute ((unused)))
428 Error ("Not implemented");
433 void OH_DirectIndirectLongX (const OpcDesc* D attribute ((unused)))
435 Error ("Not implemented");
440 void OH_StackRelativeIndirectY (const OpcDesc* D attribute ((unused)))
442 Error ("Not implemented");
447 void OH_DirectIndirectLong (const OpcDesc* D attribute ((unused)))
449 Error ("Not implemented");
454 void OH_DirectIndirectLongY (const OpcDesc* D attribute ((unused)))
456 Error ("Not implemented");
461 void OH_BlockMove (const OpcDesc* D attribute ((unused)))
463 Error ("Not implemented");
468 void OH_AbsoluteXIndirect (const OpcDesc* D attribute ((unused)))
470 Error ("Not implemented");
475 void OH_Rts (const OpcDesc* D)
483 void OH_JmpAbsolute (const OpcDesc* D)
491 void OH_JmpAbsoluteIndirect (const OpcDesc* D)
493 OH_AbsoluteIndirect (D);