]> git.sur5r.net Git - cc65/blob - src/da65/handler.c
The absolute X indirect addressing mode for the 65C02 CPU was missing.
[cc65] / src / da65 / handler.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                 handler.c                                 */
4 /*                                                                           */
5 /*               Opcode handler functions for the disassembler               */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2000-2004 Ullrich von Bassewitz                                       */
10 /*               Römerstrasse 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 "xsprintf.h"
40
41 /* da65 */
42 #include "attrtab.h"
43 #include "code.h"
44 #include "error.h"
45 #include "global.h"
46 #include "handler.h"
47 #include "opctable.h"
48 #include "output.h"
49
50
51
52 /*****************************************************************************/
53 /*                             Helper functions                              */
54 /*****************************************************************************/
55
56
57
58 static void Mnemonic (const char* M)
59 /* Indent and output a mnemonic */
60 {
61     Indent (MIndent);
62     Output ("%s", M);
63 }
64
65
66
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 */
70 {
71     char Buf [256];
72     va_list ap;
73
74     /* Mnemonic */
75     Mnemonic (D->Mnemo);
76
77     /* Argument */
78     va_start (ap, Arg);
79     xvsprintf (Buf, sizeof (Buf), Arg, ap);
80     va_end (ap);
81     Indent (AIndent);
82     Output (Buf);
83
84     /* Add the code stuff as comment */
85     LineComment (PC, D->Size);
86
87     /* End the line */
88     LineFeed ();
89 }
90
91
92
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.
96  */
97 {
98     if ((Flags & flAbsOverride) != 0 && Addr < 0x100) {
99         return "a:";
100     } else {
101         return "";
102     }
103 }
104
105
106
107 static const char* GetAddrArg (unsigned Flags, unsigned Addr)
108 /* Return an address argument - a label if we have one, or the address itself */
109 {
110     const char* Label = 0;
111     if (Flags & flUseLabel) {
112         Label = GetLabel (Addr);
113     }
114     if (Label) {
115         return Label;
116     } else {
117         static char Buf [32];
118         if (Addr < 0x100) {
119             xsprintf (Buf, sizeof (Buf), "$%02X", Addr);
120         } else {
121             xsprintf (Buf, sizeof (Buf), "$%04X", Addr);
122         }
123         return Buf;
124     }
125 }
126
127
128
129 static void GenerateLabel (unsigned Flags, unsigned Addr)
130 /* Generate a label in pass one if requested */
131 {
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))) {
137
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.
142          */
143         attr_t Style         = GetStyleAttr (Addr);
144         unsigned Granularity = GetGranularity (Style);
145
146         if (Granularity == 1) {
147             /* Just add the label */
148             AddLabel (Addr, atIntLabel, MakeLabelName (Addr));
149         } else {
150             /* Search for the start of the range or the last non dependent
151              * label in the range.
152              */
153             unsigned Offs;
154             attr_t LabelAttr;
155             unsigned LabelAddr = Addr;
156             while (LabelAddr > CodeStart) {
157
158                 if (Style != GetStyleAttr (LabelAddr-1)) {
159                     /* End of range reached */
160                     break;
161                 }
162                 --LabelAddr;
163                 LabelAttr = GetLabelAttr (LabelAddr);
164                 if ((LabelAttr & (atIntLabel|atExtLabel)) != 0 &&
165                     (LabelAttr & atDepLabel) == 0) {
166                     /* The address has an internal or external label */
167                     break;
168                 }
169             }
170
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));
174             }
175
176             /* Create the label */
177             Offs = Addr - LabelAddr;
178             if (Offs == 0) {
179                 AddLabel (Addr, atIntLabel, MakeLabelName (Addr));
180             } else {
181                 AddDepLabel (Addr, atIntLabel, GetLabel (LabelAddr), Offs);
182             }
183         }
184     }
185 }
186
187
188
189 /*****************************************************************************/
190 /*                                   Code                                    */
191 /*****************************************************************************/
192
193
194
195 void OH_Illegal (const OpcDesc* D attribute ((unused)))
196 {
197     DataByteLine (1);
198 }
199
200
201
202 void OH_Accumulator (const OpcDesc* D)
203 {
204     OneLine (D, "a");
205 }
206
207
208
209 void OH_Implicit (const OpcDesc* D)
210 {
211     Mnemonic (D->Mnemo);
212     LineComment (PC, D->Size);
213     LineFeed ();
214 }
215
216
217
218 void OH_Immidiate (const OpcDesc* D)
219 {
220     OneLine (D, "#$%02X", GetCodeByte (PC+1));
221 }
222
223
224
225 void OH_Direct (const OpcDesc* D)
226 {
227     /* Get the operand */
228     unsigned Addr = GetCodeByte (PC+1);
229
230     /* Generate a label in pass 1 */
231     GenerateLabel (D->Flags, Addr);
232
233     /* Output the line */
234     OneLine (D, "%s", GetAddrArg (D->Flags, Addr));
235 }
236
237
238
239 void OH_DirectX (const OpcDesc* D)
240 {
241     /* Get the operand */
242     unsigned Addr = GetCodeByte (PC+1);
243
244     /* Generate a label in pass 1 */
245     GenerateLabel (D->Flags, Addr);
246
247     /* Output the line */
248     OneLine (D, "%s,x", GetAddrArg (D->Flags, Addr));
249 }
250
251
252
253 void OH_DirectY (const OpcDesc* D)
254 {
255     /* Get the operand */
256     unsigned Addr = GetCodeByte (PC+1);
257
258     /* Generate a label in pass 1 */
259     GenerateLabel (D->Flags, Addr);
260
261     /* Output the line */
262     OneLine (D, "%s,y", GetAddrArg (D->Flags, Addr));
263 }
264
265
266
267 void OH_Absolute (const OpcDesc* D)
268 {
269     /* Get the operand */
270     unsigned Addr = GetCodeWord (PC+1);
271
272     /* Generate a label in pass 1 */
273     GenerateLabel (D->Flags, Addr);
274
275     /* Output the line */
276     OneLine (D, "%s%s", GetAbsOverride (D->Flags, Addr), GetAddrArg (D->Flags, Addr));
277 }
278
279
280
281 void OH_AbsoluteX (const OpcDesc* D)
282 {
283     /* Get the operand */
284     unsigned Addr = GetCodeWord (PC+1);
285
286     /* Generate a label in pass 1 */
287     GenerateLabel (D->Flags, Addr);
288
289     /* Output the line */
290     OneLine (D, "%s%s,x", GetAbsOverride (D->Flags, Addr), GetAddrArg (D->Flags, Addr));
291 }
292
293
294
295 void OH_AbsoluteY (const OpcDesc* D)
296 {
297     /* Get the operand */
298     unsigned Addr = GetCodeWord (PC+1);
299
300     /* Generate a label in pass 1 */
301     GenerateLabel (D->Flags, Addr);
302
303     /* Output the line */
304     OneLine (D, "%s%s,y", GetAbsOverride (D->Flags, Addr), GetAddrArg (D->Flags, Addr));
305 }
306
307
308
309 void OH_AbsoluteLong (const OpcDesc* D attribute ((unused)))
310 {
311     Error ("Not implemented");
312 }
313
314
315
316 void OH_AbsoluteLongX (const OpcDesc* D attribute ((unused)))
317 {
318     Error ("Not implemented");
319 }
320
321
322
323 void OH_Relative (const OpcDesc* D)
324 {
325     /* Get the operand */
326     signed char Offs = GetCodeByte (PC+1);
327
328     /* Calculate the target address */
329     unsigned Addr = (((int) PC+2) + Offs) & 0xFFFF;
330
331     /* Generate a label in pass 1 */
332     GenerateLabel (D->Flags, Addr);
333
334     /* Output the line */
335     OneLine (D, "%s", GetAddrArg (D->Flags, Addr));
336 }
337
338
339
340 void OH_RelativeLong (const OpcDesc* D attribute ((unused)))
341 {
342     Error ("Not implemented");
343 }
344
345
346
347 void OH_DirectIndirect (const OpcDesc* D)
348 {
349     /* Get the operand */
350     unsigned Addr = GetCodeByte (PC+1);
351
352     /* Generate a label in pass 1 */
353     GenerateLabel (D->Flags, Addr);
354
355     /* Output the line */
356     OneLine (D, "(%s)", GetAddrArg (D->Flags, Addr));
357 }
358
359
360
361 void OH_DirectIndirectY (const OpcDesc* D)
362 {
363     /* Get the operand */
364     unsigned Addr = GetCodeByte (PC+1);
365
366     /* Generate a label in pass 1 */
367     GenerateLabel (D->Flags, Addr);
368
369     /* Output the line */
370     OneLine (D, "(%s),y", GetAddrArg (D->Flags, Addr));
371 }
372
373
374
375 void OH_DirectXIndirect (const OpcDesc* D)
376 {
377     /* Get the operand */
378     unsigned Addr = GetCodeByte (PC+1);
379
380     /* Generate a label in pass 1 */
381     GenerateLabel (D->Flags, Addr);
382
383     /* Output the line */
384     OneLine (D, "(%s,x)", GetAddrArg (D->Flags, Addr));
385 }
386
387
388
389 void OH_AbsoluteIndirect (const OpcDesc* D)
390 {
391     /* Get the operand */
392     unsigned Addr = GetCodeWord (PC+1);
393
394     /* Generate a label in pass 1 */
395     GenerateLabel (D->Flags, Addr);
396
397     /* Output the line */
398     OneLine (D, "(%s)", GetAddrArg (D->Flags, Addr));
399 }
400
401
402
403 void OH_BitBranch (const OpcDesc* D)
404 {
405     /* Get the operands */
406     unsigned char TestAddr   = GetCodeByte (PC+1);
407     signed char   BranchOffs = GetCodeByte (PC+2);
408
409     /* Calculate the target address for the branch */
410     unsigned BranchAddr = (((int) PC+3) + BranchOffs) & 0xFFFF;
411
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.
416      */
417     GenerateLabel (D->Flags, TestAddr);
418     GenerateLabel (flLabel, BranchAddr);
419
420     /* Output the line */
421     OneLine (D, "%s,%s", GetAddrArg (D->Flags, TestAddr), GetAddrArg (flLabel, BranchAddr));
422 }
423
424
425
426 void OH_StackRelative (const OpcDesc* D attribute ((unused)))
427 {
428     Error ("Not implemented");
429 }
430
431
432
433 void OH_DirectIndirectLongX (const OpcDesc* D attribute ((unused)))
434 {
435     Error ("Not implemented");
436 }
437
438
439
440 void OH_StackRelativeIndirectY (const OpcDesc* D attribute ((unused)))
441 {
442     Error ("Not implemented");
443 }
444
445
446
447 void OH_DirectIndirectLong (const OpcDesc* D attribute ((unused)))
448 {
449     Error ("Not implemented");
450 }
451
452
453
454 void OH_DirectIndirectLongY (const OpcDesc* D attribute ((unused)))
455 {
456     Error ("Not implemented");
457 }
458
459
460
461 void OH_BlockMove (const OpcDesc* D attribute ((unused)))
462 {
463     Error ("Not implemented");
464 }
465
466
467
468 void OH_AbsoluteXIndirect (const OpcDesc* D attribute ((unused)))
469 {
470     /* Get the operand */
471     unsigned Addr = GetCodeWord (PC+1);
472
473     /* Generate a label in pass 1 */
474     GenerateLabel (D->Flags, Addr);
475
476     /* Output the line */
477     OneLine (D, "(%s,x)", GetAddrArg (D->Flags, Addr));
478 }
479
480
481
482 void OH_Rts (const OpcDesc* D)
483 {
484     OH_Implicit (D);
485     SeparatorLine();
486 }
487
488
489
490 void OH_JmpAbsolute (const OpcDesc* D)
491 {
492     OH_Absolute (D);
493     SeparatorLine ();
494 }
495
496
497
498 void OH_JmpAbsoluteIndirect (const OpcDesc* D)
499 {
500     OH_AbsoluteIndirect (D);
501     SeparatorLine ();
502 }
503
504
505