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