]> git.sur5r.net Git - cc65/blob - src/da65/handler.c
Fixed some bugs in da65's HuC6280 section.
[cc65] / src / da65 / handler.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                 handler.c                                 */
4 /*                                                                           */
5 /*               Opcode handler functions for the disassembler               */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2000-2011, Ullrich von Bassewitz                                      */
10 /*                Roemerstrasse 52                                           */
11 /*                D-70794 Filderstadt                                        */
12 /* EMail:         uz@cc65.org                                                */
13 /*                                                                           */
14 /*                                                                           */
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.                                    */
18 /*                                                                           */
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:                            */
22 /*                                                                           */
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              */
30 /*    distribution.                                                          */
31 /*                                                                           */
32 /*****************************************************************************/
33
34
35
36 #include <stdarg.h>
37
38 /* common */
39 #include "xmalloc.h"
40 #include "xsprintf.h"
41
42 /* da65 */
43 #include "attrtab.h"
44 #include "code.h"
45 #include "error.h"
46 #include "global.h"
47 #include "handler.h"
48 #include "labels.h"
49 #include "opctable.h"
50 #include "output.h"
51
52
53
54 /*****************************************************************************/
55 /*                             Helper functions                              */
56 /*****************************************************************************/
57
58
59
60 static void Mnemonic (const char* M)
61 /* Indent and output a mnemonic */
62 {
63     Indent (MCol);
64     Output ("%s", M);
65 }
66
67
68
69 static void OneLine (const OpcDesc* D, const char* Arg, ...) attribute ((format(printf, 2, 3)));
70 static void OneLine (const OpcDesc* D, const char* Arg, ...)
71 /* Output one line with the given mnemonic and argument */
72 {
73     char Buf [256];
74     va_list ap;
75
76     /* Mnemonic */
77     Mnemonic (D->Mnemo);
78
79     /* Argument */
80     va_start (ap, Arg);
81     xvsprintf (Buf, sizeof (Buf), Arg, ap);
82     va_end (ap);
83     Indent (ACol);
84     Output ("%s", Buf);
85
86     /* Add the code stuff as comment */
87     LineComment (PC, D->Size);
88
89     /* End the line */
90     LineFeed ();
91 }
92
93
94
95 static const char* GetAbsOverride (unsigned Flags, unsigned Addr)
96 /* If the instruction requires an abs override modifier, return the necessary
97 ** string, otherwise return the empty string.
98 */
99 {
100     if ((Flags & flAbsOverride) != 0 && Addr < 0x100) {
101         return "a:";
102     } else {
103         return "";
104     }
105 }
106
107
108
109 static const char* GetAddrArg (unsigned Flags, unsigned Addr)
110 /* Return an address argument - a label if we have one, or the address itself */
111 {
112     const char* Label = 0;
113     if (Flags & flUseLabel) {
114         Label = GetLabel (Addr, PC);
115     }
116     if (Label) {
117         return Label;
118     } else {
119         static char Buf [32];
120         if (Addr < 0x100) {
121             xsprintf (Buf, sizeof (Buf), "$%02X", Addr);
122         } else {
123             xsprintf (Buf, sizeof (Buf), "$%04X", Addr);
124         }
125         return Buf;
126     }
127 }
128
129
130
131 static void GenerateLabel (unsigned Flags, unsigned Addr)
132 /* Generate a label in pass one if requested */
133 {
134     /* Generate labels in pass #1, and only if we don't have a label already */
135     if (Pass == 1 && !HaveLabel (Addr) &&
136         /* Check if we must create a label */
137         ((Flags & flGenLabel) != 0 ||
138          ((Flags & flUseLabel) != 0 && Addr >= CodeStart && Addr <= CodeEnd))) {
139
140         /* As a special case, handle ranges with tables or similar. Within
141         ** such a range with a granularity > 1, do only generate dependent
142         ** labels for all addresses but the first one. Be sure to generate
143         ** a label for the start of the range, however.
144         */
145         attr_t Style         = GetStyleAttr (Addr);
146         unsigned Granularity = GetGranularity (Style);
147
148         if (Granularity == 1) {
149             /* Just add the label */
150             AddIntLabel (Addr);
151         } else {
152
153             /* THIS CODE IS A MESS AND WILL FAIL ON SEVERAL CONDITIONS! ### */
154
155
156             /* Search for the start of the range or the last non dependent
157             ** label in the range.
158             */
159             unsigned Offs;
160             attr_t LabelAttr;
161             unsigned LabelAddr = Addr;
162             while (LabelAddr > CodeStart) {
163
164                 if (Style != GetStyleAttr (LabelAddr-1)) {
165                     /* End of range reached */
166                     break;
167                 }
168                 --LabelAddr;
169                 LabelAttr = GetLabelAttr (LabelAddr);
170                 if ((LabelAttr & (atIntLabel|atExtLabel)) != 0) {
171                     /* The address has an internal or external label */
172                     break;
173                 }
174             }
175
176             /* If the proposed label address doesn't have a label, define one */
177             if ((GetLabelAttr (LabelAddr) & (atIntLabel|atExtLabel)) == 0) {
178                 AddIntLabel (LabelAddr);
179             }
180
181             /* Create the label */
182             Offs = Addr - LabelAddr;
183             if (Offs == 0) {
184                 AddIntLabel (Addr);
185             } else {
186                 AddDepLabel (Addr, atIntLabel, GetLabelName (LabelAddr), Offs);
187             }
188         }
189     }
190 }
191
192
193
194 /*****************************************************************************/
195 /*                                   Code                                    */
196 /*****************************************************************************/
197
198
199
200 void OH_Illegal (const OpcDesc* D attribute ((unused)))
201 {
202     DataByteLine (1);
203 }
204
205
206
207 void OH_Accumulator (const OpcDesc* D)
208 {
209     OneLine (D, "a");
210 }
211
212
213
214 void OH_Implicit (const OpcDesc* D)
215 {
216     Mnemonic (D->Mnemo);
217     LineComment (PC, D->Size);
218     LineFeed ();
219 }
220
221
222
223 void OH_Immediate (const OpcDesc* D)
224 {
225     OneLine (D, "#$%02X", GetCodeByte (PC+1));
226 }
227
228
229
230 void OH_Direct (const OpcDesc* D)
231 {
232     /* Get the operand */
233     unsigned Addr = GetCodeByte (PC+1);
234
235     /* Generate a label in pass 1 */
236     GenerateLabel (D->Flags, Addr);
237
238     /* Output the line */
239     OneLine (D, "%s", GetAddrArg (D->Flags, Addr));
240 }
241
242
243
244 void OH_DirectX (const OpcDesc* D)
245 {
246     /* Get the operand */
247     unsigned Addr = GetCodeByte (PC+1);
248
249     /* Generate a label in pass 1 */
250     GenerateLabel (D->Flags, Addr);
251
252     /* Output the line */
253     OneLine (D, "%s,x", GetAddrArg (D->Flags, Addr));
254 }
255
256
257
258 void OH_DirectY (const OpcDesc* D)
259 {
260     /* Get the operand */
261     unsigned Addr = GetCodeByte (PC+1);
262
263     /* Generate a label in pass 1 */
264     GenerateLabel (D->Flags, Addr);
265
266     /* Output the line */
267     OneLine (D, "%s,y", GetAddrArg (D->Flags, Addr));
268 }
269
270
271
272 void OH_Absolute (const OpcDesc* D)
273 {
274     /* Get the operand */
275     unsigned Addr = GetCodeWord (PC+1);
276
277     /* Generate a label in pass 1 */
278     GenerateLabel (D->Flags, Addr);
279
280     /* Output the line */
281     OneLine (D, "%s%s", GetAbsOverride (D->Flags, Addr), GetAddrArg (D->Flags, Addr));
282 }
283
284
285
286 void OH_AbsoluteX (const OpcDesc* D)
287 {
288     /* Get the operand */
289     unsigned Addr = GetCodeWord (PC+1);
290
291     /* Generate a label in pass 1 */
292     GenerateLabel (D->Flags, Addr);
293
294     /* Output the line */
295     OneLine (D, "%s%s,x", GetAbsOverride (D->Flags, Addr), GetAddrArg (D->Flags, Addr));
296 }
297
298
299
300 void OH_AbsoluteY (const OpcDesc* D)
301 {
302     /* Get the operand */
303     unsigned Addr = GetCodeWord (PC+1);
304
305     /* Generate a label in pass 1 */
306     GenerateLabel (D->Flags, Addr);
307
308     /* Output the line */
309     OneLine (D, "%s%s,y", GetAbsOverride (D->Flags, Addr), GetAddrArg (D->Flags, Addr));
310 }
311
312
313
314 void OH_AbsoluteLong (const OpcDesc* D attribute ((unused)))
315 {
316     Error ("Not implemented");
317 }
318
319
320
321 void OH_AbsoluteLongX (const OpcDesc* D attribute ((unused)))
322 {
323     Error ("Not implemented");
324 }
325
326
327
328 void OH_Relative (const OpcDesc* D)
329 {
330     /* Get the operand */
331     signed char Offs = GetCodeByte (PC+1);
332
333     /* Calculate the target address */
334     unsigned Addr = (((int) PC+2) + Offs) & 0xFFFF;
335
336     /* Generate a label in pass 1 */
337     GenerateLabel (D->Flags, Addr);
338
339     /* Output the line */
340     OneLine (D, "%s", GetAddrArg (D->Flags, Addr));
341 }
342
343
344
345 void OH_RelativeLong (const OpcDesc* D attribute ((unused)))
346 {
347     Error ("Not implemented");
348 }
349
350
351
352 void OH_DirectIndirect (const OpcDesc* D)
353 {
354     /* Get the operand */
355     unsigned Addr = GetCodeByte (PC+1);
356
357     /* Generate a label in pass 1 */
358     GenerateLabel (D->Flags, Addr);
359
360     /* Output the line */
361     OneLine (D, "(%s)", GetAddrArg (D->Flags, Addr));
362 }
363
364
365
366 void OH_DirectIndirectY (const OpcDesc* D)
367 {
368     /* Get the operand */
369     unsigned Addr = GetCodeByte (PC+1);
370
371     /* Generate a label in pass 1 */
372     GenerateLabel (D->Flags, Addr);
373
374     /* Output the line */
375     OneLine (D, "(%s),y", GetAddrArg (D->Flags, Addr));
376 }
377
378
379
380 void OH_DirectXIndirect (const OpcDesc* D)
381 {
382     /* Get the operand */
383     unsigned Addr = GetCodeByte (PC+1);
384
385     /* Generate a label in pass 1 */
386     GenerateLabel (D->Flags, Addr);
387
388     /* Output the line */
389     OneLine (D, "(%s,x)", GetAddrArg (D->Flags, Addr));
390 }
391
392
393
394 void OH_AbsoluteIndirect (const OpcDesc* D)
395 {
396     /* Get the operand */
397     unsigned Addr = GetCodeWord (PC+1);
398
399     /* Generate a label in pass 1 */
400     GenerateLabel (D->Flags, Addr);
401
402     /* Output the line */
403     OneLine (D, "(%s)", GetAddrArg (D->Flags, Addr));
404 }
405
406
407
408 void OH_BitBranch (const OpcDesc* D)
409 {
410     char* BranchLabel;
411
412     /* Get the operands */
413     unsigned char TestAddr   = GetCodeByte (PC+1);
414     signed char   BranchOffs = GetCodeByte (PC+2);
415
416     /* Calculate the target address for the branch */
417     unsigned BranchAddr = (((int) PC+3) + BranchOffs) & 0xFFFF;
418
419     /* Generate labels in pass 1. The bit branch codes are special in that
420     ** they don't really match the remainder of the 6502 instruction set (they
421     ** are a Rockwell addon), so we must pass additional flags as direct
422     ** value to the second GenerateLabel call.
423     */
424     GenerateLabel (D->Flags, TestAddr);
425     GenerateLabel (flLabel, BranchAddr);
426
427     /* Make a copy of an operand, so that
428     ** the other operand can't overwrite it.
429     ** [GetAddrArg() uses a statically-stored buffer.]
430     */
431     BranchLabel = xstrdup (GetAddrArg (flLabel, BranchAddr));
432
433     /* Output the line */
434     OneLine (D, "%s,%s", GetAddrArg (D->Flags, TestAddr), BranchLabel);
435
436     xfree (BranchLabel);
437 }
438
439
440
441 void OH_ImmediateDirect (const OpcDesc* D)
442 {
443     /* Get the operand */
444     unsigned Addr = GetCodeByte (PC+2);
445
446     /* Generate a label in pass 1 */
447     GenerateLabel (D->Flags, Addr);
448
449     /* Output the line */
450     OneLine (D, "#$%02X,%s", GetCodeByte (PC+1), GetAddrArg (D->Flags, Addr));
451 }
452
453
454
455 void OH_ImmediateDirectX (const OpcDesc* D)
456 {
457     /* Get the operand */
458     unsigned Addr = GetCodeByte (PC+2);
459
460     /* Generate a label in pass 1 */
461     GenerateLabel (D->Flags, Addr);
462
463     /* Output the line */
464     OneLine (D, "#$%02X,%s,x", GetCodeByte (PC+1), GetAddrArg (D->Flags, Addr));
465 }
466
467
468
469 void OH_ImmediateAbsolute (const OpcDesc* D)
470 {
471     /* Get the operand */
472     unsigned Addr = GetCodeWord (PC+2);
473
474     /* Generate a label in pass 1 */
475     GenerateLabel (D->Flags, Addr);
476
477     /* Output the line */
478     OneLine (D, "#$%02X,%s%s", GetCodeByte (PC+1), GetAbsOverride (D->Flags, Addr), GetAddrArg (D->Flags, Addr));
479 }
480
481
482
483 void OH_ImmediateAbsoluteX (const OpcDesc* D)
484 {
485     /* Get the operand */
486     unsigned Addr = GetCodeWord (PC+2);
487
488     /* Generate a label in pass 1 */
489     GenerateLabel (D->Flags, Addr);
490
491     /* Output the line */
492     OneLine (D, "#$%02X,%s%s,x", GetCodeByte (PC+1), GetAbsOverride (D->Flags, Addr), GetAddrArg (D->Flags, Addr));
493 }
494
495
496
497 void OH_StackRelative (const OpcDesc* D attribute ((unused)))
498 {
499     Error ("Not implemented");
500 }
501
502
503
504 void OH_DirectIndirectLongX (const OpcDesc* D attribute ((unused)))
505 {
506     Error ("Not implemented");
507 }
508
509
510
511 void OH_StackRelativeIndirectY (const OpcDesc* D attribute ((unused)))
512 {
513     Error ("Not implemented");
514 }
515
516
517
518 void OH_DirectIndirectLong (const OpcDesc* D attribute ((unused)))
519 {
520     Error ("Not implemented");
521 }
522
523
524
525 void OH_DirectIndirectLongY (const OpcDesc* D attribute ((unused)))
526 {
527     Error ("Not implemented");
528 }
529
530
531
532 void OH_BlockMove (const OpcDesc* D)
533 {
534     char* DstLabel;
535
536     /* Get source operand */
537     unsigned Src = GetCodeWord (PC+1);
538     /* Get destination operand */
539     unsigned Dst = GetCodeWord (PC+3);
540
541     /* Generate a label in pass 1 */
542     GenerateLabel (D->Flags, Src);
543     GenerateLabel (D->Flags, Dst);
544
545     /* Make a copy of an operand, so that
546     ** the other operand can't overwrite it.
547     ** [GetAddrArg() uses a statically-stored buffer.]
548     */
549     DstLabel = xstrdup (GetAddrArg (D->Flags, Dst));
550
551     /* Output the line */
552     OneLine (D, "%s%s,%s%s,$%04X",
553              GetAbsOverride (D->Flags, Src), GetAddrArg (D->Flags, Src),
554              GetAbsOverride (D->Flags, Dst), DstLabel,
555              GetCodeWord (PC+5));
556
557     xfree (DstLabel);
558 }
559
560
561
562 void OH_AbsoluteXIndirect (const OpcDesc* D attribute ((unused)))
563 {
564     /* Get the operand */
565     unsigned Addr = GetCodeWord (PC+1);
566
567     /* Generate a label in pass 1 */
568     GenerateLabel (D->Flags, Addr);
569
570     /* Output the line */
571     OneLine (D, "(%s,x)", GetAddrArg (D->Flags, Addr));
572 }
573
574
575
576 void OH_DirectImmediate (const OpcDesc* D)
577 {
578     /* Get the operand */
579     unsigned Addr = GetCodeByte (PC+1);
580
581     /* Generate a label in pass 1 */
582     GenerateLabel (D->Flags, Addr);
583
584     /* Output the line */
585     OneLine (D, "%s, #$%02X", GetAddrArg (D->Flags, Addr), GetCodeByte (PC+2));
586 }
587
588
589
590 void OH_ZeroPageBit (const OpcDesc* D)
591 {
592     unsigned Bit = GetCodeByte (PC) >> 5;
593     unsigned Addr = GetCodeByte (PC+1);
594
595     /* Generate a label in pass 1 */
596     GenerateLabel (D->Flags, Addr);
597
598     /* Output the line */
599     OneLine (D, "%01X,%s", Bit, GetAddrArg (D->Flags, Addr));
600 }
601
602
603
604 void OH_AccumulatorBit (const OpcDesc* D)
605 {
606     unsigned Bit = GetCodeByte (PC) >> 5;
607
608     /* Output the line */
609     OneLine (D, "%01X,a", Bit);
610 }
611
612
613
614 void OH_AccumulatorBitBranch (const OpcDesc* D)
615 {
616     unsigned Bit = GetCodeByte (PC) >> 5;
617     signed char BranchOffs = GetCodeByte (PC+1);
618
619     /* Calculate the target address for the branch */
620     unsigned BranchAddr = (((int) PC+3) + BranchOffs) & 0xFFFF;
621
622     /* Generate labels in pass 1 */
623     GenerateLabel (flLabel, BranchAddr);
624
625     /* Output the line */
626     OneLine (D, "%01X,a,%s", Bit, GetAddrArg (flLabel, BranchAddr));
627 }
628
629
630
631 void OH_JmpDirectIndirect (const OpcDesc* D)
632 {
633     OH_DirectIndirect (D);
634     if (NewlineAfterJMP) {
635         LineFeed ();
636     }
637     SeparatorLine ();
638 }
639
640
641
642 void OH_SpecialPage (const OpcDesc* D)
643 {
644   /* Get the operand */
645   unsigned Addr = 0xFF00 + GetCodeByte (PC+1);
646
647   /* Generate a label in pass 1 */
648   GenerateLabel (D->Flags, Addr);
649
650   /* OneLine (D, "$FF%02X", (CodeByte (PC+1)); */
651   OneLine (D, "%s", GetAddrArg (D->Flags, Addr));
652 }
653
654
655
656 void OH_Rts (const OpcDesc* D)
657 {
658     OH_Implicit (D);
659     if (NewlineAfterRTS) {
660         LineFeed ();
661     }
662     SeparatorLine();
663 }
664
665
666
667 void OH_JmpAbsolute (const OpcDesc* D)
668 {
669     OH_Absolute (D);
670     if (NewlineAfterJMP) {
671         LineFeed ();
672     }
673     SeparatorLine ();
674 }
675
676
677
678 void OH_JmpAbsoluteIndirect (const OpcDesc* D)
679 {
680     OH_AbsoluteIndirect (D);
681     if (NewlineAfterJMP) {
682         LineFeed ();
683     }
684     SeparatorLine ();
685 }
686
687
688
689 void OH_JmpAbsoluteXIndirect (const OpcDesc* D)
690 {
691     OH_AbsoluteXIndirect (D);
692     if (NewlineAfterJMP) {
693         LineFeed ();
694     }
695     SeparatorLine ();
696 }