1 /*****************************************************************************/
5 /* Opcode handler functions for the disassembler */
9 /* (C) 2000-2009, Ullrich von Bassewitz */
10 /* Roemerstrasse 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 /*****************************************************************************/
53 /*****************************************************************************/
54 /* Helper functions */
55 /*****************************************************************************/
59 static void Mnemonic (const char* M)
60 /* Indent and output a mnemonic */
68 static void OneLine (const OpcDesc* D, const char* Arg, ...) attribute ((format(printf, 2, 3)));
69 static void OneLine (const OpcDesc* D, const char* Arg, ...)
70 /* Output one line with the given mnemonic and argument */
80 xvsprintf (Buf, sizeof (Buf), Arg, ap);
85 /* Add the code stuff as comment */
86 LineComment (PC, D->Size);
94 static const char* GetAbsOverride (unsigned Flags, unsigned Addr)
95 /* If the instruction requires an abs override modifier, return the necessary
96 * string, otherwise return the empty string.
99 if ((Flags & flAbsOverride) != 0 && Addr < 0x100) {
108 static const char* GetAddrArg (unsigned Flags, unsigned Addr)
109 /* Return an address argument - a label if we have one, or the address itself */
111 const char* Label = 0;
112 if (Flags & flUseLabel) {
113 Label = GetLabel (Addr, PC);
118 static char Buf [32];
120 xsprintf (Buf, sizeof (Buf), "$%02X", Addr);
122 xsprintf (Buf, sizeof (Buf), "$%04X", Addr);
130 static void GenerateLabel (unsigned Flags, unsigned Addr)
131 /* Generate a label in pass one if requested */
133 /* Generate labels in pass #1, and only if we don't have a label already */
134 if (Pass == 1 && !HaveLabel (Addr) &&
135 /* Check if we must create a label */
136 ((Flags & flGenLabel) != 0 ||
137 ((Flags & flUseLabel) != 0 && Addr >= CodeStart && Addr <= CodeEnd))) {
139 /* As a special case, handle ranges with tables or similar. Within
140 * such a range with a granularity > 1, do only generate dependent
141 * labels for all addresses but the first one. Be sure to generate
142 * a label for the start of the range, however.
144 attr_t Style = GetStyleAttr (Addr);
145 unsigned Granularity = GetGranularity (Style);
147 if (Granularity == 1) {
148 /* Just add the label */
152 /* THIS CODE IS A MESS AND WILL FAIL ON SEVERAL CONDITIONS! ### */
155 /* Search for the start of the range or the last non dependent
156 * label in the range.
160 unsigned LabelAddr = Addr;
161 while (LabelAddr > CodeStart) {
163 if (Style != GetStyleAttr (LabelAddr-1)) {
164 /* End of range reached */
168 LabelAttr = GetLabelAttr (LabelAddr);
169 if ((LabelAttr & (atIntLabel|atExtLabel)) != 0) {
170 /* The address has an internal or external label */
175 /* If the proposed label address doesn't have a label, define one */
176 if ((GetLabelAttr (LabelAddr) & (atIntLabel|atExtLabel)) == 0) {
177 AddIntLabel (LabelAddr);
180 /* Create the label */
181 Offs = Addr - LabelAddr;
185 AddDepLabel (Addr, atIntLabel, GetLabelName (LabelAddr), Offs);
193 /*****************************************************************************/
195 /*****************************************************************************/
199 void OH_Illegal (const OpcDesc* D attribute ((unused)))
206 void OH_Accumulator (const OpcDesc* D)
213 void OH_Implicit (const OpcDesc* D)
216 LineComment (PC, D->Size);
222 void OH_Immidiate (const OpcDesc* D)
224 OneLine (D, "#$%02X", GetCodeByte (PC+1));
229 void OH_Direct (const OpcDesc* D)
231 /* Get the operand */
232 unsigned Addr = GetCodeByte (PC+1);
234 /* Generate a label in pass 1 */
235 GenerateLabel (D->Flags, Addr);
237 /* Output the line */
238 OneLine (D, "%s", GetAddrArg (D->Flags, Addr));
243 void OH_DirectX (const OpcDesc* D)
245 /* Get the operand */
246 unsigned Addr = GetCodeByte (PC+1);
248 /* Generate a label in pass 1 */
249 GenerateLabel (D->Flags, Addr);
251 /* Output the line */
252 OneLine (D, "%s,x", GetAddrArg (D->Flags, Addr));
257 void OH_DirectY (const OpcDesc* D)
259 /* Get the operand */
260 unsigned Addr = GetCodeByte (PC+1);
262 /* Generate a label in pass 1 */
263 GenerateLabel (D->Flags, Addr);
265 /* Output the line */
266 OneLine (D, "%s,y", GetAddrArg (D->Flags, Addr));
271 void OH_Absolute (const OpcDesc* D)
273 /* Get the operand */
274 unsigned Addr = GetCodeWord (PC+1);
276 /* Generate a label in pass 1 */
277 GenerateLabel (D->Flags, Addr);
279 /* Output the line */
280 OneLine (D, "%s%s", GetAbsOverride (D->Flags, Addr), GetAddrArg (D->Flags, Addr));
285 void OH_AbsoluteX (const OpcDesc* D)
287 /* Get the operand */
288 unsigned Addr = GetCodeWord (PC+1);
290 /* Generate a label in pass 1 */
291 GenerateLabel (D->Flags, Addr);
293 /* Output the line */
294 OneLine (D, "%s%s,x", GetAbsOverride (D->Flags, Addr), GetAddrArg (D->Flags, Addr));
299 void OH_AbsoluteY (const OpcDesc* D)
301 /* Get the operand */
302 unsigned Addr = GetCodeWord (PC+1);
304 /* Generate a label in pass 1 */
305 GenerateLabel (D->Flags, Addr);
307 /* Output the line */
308 OneLine (D, "%s%s,y", GetAbsOverride (D->Flags, Addr), GetAddrArg (D->Flags, Addr));
313 void OH_AbsoluteLong (const OpcDesc* D attribute ((unused)))
315 Error ("Not implemented");
320 void OH_AbsoluteLongX (const OpcDesc* D attribute ((unused)))
322 Error ("Not implemented");
327 void OH_Relative (const OpcDesc* D)
329 /* Get the operand */
330 signed char Offs = GetCodeByte (PC+1);
332 /* Calculate the target address */
333 unsigned Addr = (((int) PC+2) + Offs) & 0xFFFF;
335 /* Generate a label in pass 1 */
336 GenerateLabel (D->Flags, Addr);
338 /* Output the line */
339 OneLine (D, "%s", GetAddrArg (D->Flags, Addr));
344 void OH_RelativeLong (const OpcDesc* D attribute ((unused)))
346 Error ("Not implemented");
351 void OH_DirectIndirect (const OpcDesc* D)
353 /* Get the operand */
354 unsigned Addr = GetCodeByte (PC+1);
356 /* Generate a label in pass 1 */
357 GenerateLabel (D->Flags, Addr);
359 /* Output the line */
360 OneLine (D, "(%s)", GetAddrArg (D->Flags, Addr));
365 void OH_DirectIndirectY (const OpcDesc* D)
367 /* Get the operand */
368 unsigned Addr = GetCodeByte (PC+1);
370 /* Generate a label in pass 1 */
371 GenerateLabel (D->Flags, Addr);
373 /* Output the line */
374 OneLine (D, "(%s),y", GetAddrArg (D->Flags, Addr));
379 void OH_DirectXIndirect (const OpcDesc* D)
381 /* Get the operand */
382 unsigned Addr = GetCodeByte (PC+1);
384 /* Generate a label in pass 1 */
385 GenerateLabel (D->Flags, Addr);
387 /* Output the line */
388 OneLine (D, "(%s,x)", GetAddrArg (D->Flags, Addr));
393 void OH_AbsoluteIndirect (const OpcDesc* D)
395 /* Get the operand */
396 unsigned Addr = GetCodeWord (PC+1);
398 /* Generate a label in pass 1 */
399 GenerateLabel (D->Flags, Addr);
401 /* Output the line */
402 OneLine (D, "(%s)", GetAddrArg (D->Flags, Addr));
407 void OH_BitBranch (const OpcDesc* D)
409 /* Get the operands */
410 unsigned char TestAddr = GetCodeByte (PC+1);
411 signed char BranchOffs = GetCodeByte (PC+2);
413 /* Calculate the target address for the branch */
414 unsigned BranchAddr = (((int) PC+3) + BranchOffs) & 0xFFFF;
416 /* Generate labels in pass 1. The bit branch codes are special in that
417 * they don't really match the remainder of the 6502 instruction set (they
418 * are a Rockwell addon), so we must pass additional flags as direct
419 * value to the second GenerateLabel call.
421 GenerateLabel (D->Flags, TestAddr);
422 GenerateLabel (flLabel, BranchAddr);
424 /* Output the line */
425 OneLine (D, "%s,%s", GetAddrArg (D->Flags, TestAddr), GetAddrArg (flLabel, BranchAddr));
430 void OH_ImmidiateDirect (const OpcDesc* D)
432 /* Get the operand */
433 unsigned Addr = GetCodeByte (PC+2);
435 /* Generate a label in pass 1 */
436 GenerateLabel (D->Flags, Addr);
438 /* Output the line */
439 OneLine (D, "#$%02X,%s", GetCodeByte (PC+1), GetAddrArg (D->Flags, Addr));
444 void OH_ImmidiateDirectX (const OpcDesc* D)
446 /* Get the operand */
447 unsigned Addr = GetCodeByte (PC+2);
449 /* Generate a label in pass 1 */
450 GenerateLabel (D->Flags, Addr);
452 /* Output the line */
453 OneLine (D, "#$%02X,%s,x", GetCodeByte (PC+1), GetAddrArg (D->Flags, Addr));
458 void OH_ImmidiateAbsolute (const OpcDesc* D)
460 /* Get the operand */
461 unsigned Addr = GetCodeWord (PC+2);
463 /* Generate a label in pass 1 */
464 GenerateLabel (D->Flags, Addr);
466 /* Output the line */
467 OneLine (D, "#$%02X,%s%s", GetCodeByte (PC+1), GetAbsOverride (D->Flags, Addr), GetAddrArg (D->Flags, Addr));
472 void OH_ImmidiateAbsoluteX (const OpcDesc* D)
474 /* Get the operand */
475 unsigned Addr = GetCodeWord (PC+2);
477 /* Generate a label in pass 1 */
478 GenerateLabel (D->Flags, Addr);
480 /* Output the line */
481 OneLine (D, "#$%02X,%s%s,x", GetCodeByte (PC+1), GetAbsOverride (D->Flags, Addr), GetAddrArg (D->Flags, Addr));
486 void OH_StackRelative (const OpcDesc* D attribute ((unused)))
488 Error ("Not implemented");
493 void OH_DirectIndirectLongX (const OpcDesc* D attribute ((unused)))
495 Error ("Not implemented");
500 void OH_StackRelativeIndirectY (const OpcDesc* D attribute ((unused)))
502 Error ("Not implemented");
507 void OH_DirectIndirectLong (const OpcDesc* D attribute ((unused)))
509 Error ("Not implemented");
514 void OH_DirectIndirectLongY (const OpcDesc* D attribute ((unused)))
516 Error ("Not implemented");
521 void OH_BlockMove (const OpcDesc* D attribute ((unused)))
523 /* Get source operand */
524 unsigned Src = GetCodeWord (PC+1);
525 /* Get destination operand */
526 unsigned Dst = GetCodeWord (PC+3);
528 /* Generate a label in pass 1 */
529 GenerateLabel (D->Flags, Src);
530 GenerateLabel (D->Flags, Dst);
532 /* Output the line */
533 OneLine (D, "%s%s,%s%s,#$%02X",
534 GetAbsOverride (D->Flags, Src), GetAddrArg (D->Flags, Src),
535 GetAbsOverride (D->Flags, Dst), GetAddrArg (D->Flags, Dst),
541 void OH_AbsoluteXIndirect (const OpcDesc* D attribute ((unused)))
543 /* Get the operand */
544 unsigned Addr = GetCodeWord (PC+1);
546 /* Generate a label in pass 1 */
547 GenerateLabel (D->Flags, Addr);
549 /* Output the line */
550 OneLine (D, "(%s,x)", GetAddrArg (D->Flags, Addr));
555 void OH_Rts (const OpcDesc* D)
563 void OH_JmpAbsolute (const OpcDesc* D)
571 void OH_JmpAbsoluteIndirect (const OpcDesc* D)
573 OH_AbsoluteIndirect (D);