* src/hc08/gen.c (hc08_emitDebuggerSymbol),
[fw/sdcc] / src / hc08 / main.c
1 /** @file main.c
2     hc08 specific general functions.
3
4     Note that mlh prepended _hc08_ on the static functions.  Makes
5     it easier to set a breakpoint using the debugger.
6 */
7 #include "common.h"
8 #include "main.h"
9 #include "ralloc.h"
10 #include "gen.h"
11 #include "../SDCCutil.h"
12
13 void copyFile(FILE *dest, FILE *src);
14 extern char * iComments2;
15 extern FILE * dwarf2FilePtr;
16 extern DEBUGFILE dwarf2DebugFile;
17 extern int dwarf2FinalizeFile(void);
18
19 static char _defaultRules[] =
20 {
21 #include "peeph.rul"
22 };
23
24 /* list of key words used by msc51 */
25 static char *_hc08_keywords[] =
26 {
27   "at",
28   //"bit",
29   "code",
30   "critical",
31   "data",
32   "far",
33   //"idata",
34   "interrupt",
35   "near",
36   //"pdata",
37   "reentrant",
38   //"sfr",
39   //"sbit",
40   //"using",
41   "xdata",
42   "_data",
43   "_code",
44   "_generic",
45   "_near",
46   "_xdata",
47   //"_pdata",
48   //"_idata",
49   "_naked",
50   "_overlay",
51   NULL
52 };
53
54
55 void hc08_assignRegisters (eBBlock ** ebbs, int count);
56
57 static int regParmFlg = 0;      /* determine if we can register a parameter */
58
59 static void
60 _hc08_init (void)
61 {
62   asm_addTree (&asm_asxxxx_mapping);
63 }
64
65 static void
66 _hc08_reset_regparm ()
67 {
68   regParmFlg = 0;
69 }
70
71 static int
72 _hc08_regparm (sym_link * l)
73 {
74   int size = getSize(l);
75     
76   /* If they fit completely, the first two bytes of parameters can go */
77   /* into A and X, otherwise, they go on the stack. Examples:         */
78   /*   foo(char p1)                    A <- p1                        */
79   /*   foo(char p1, char p2)           A <- p1, X <- p2               */
80   /*   foo(char p1, char p2, char p3)  A <- p1, X <- p2, stack <- p3  */
81   /*   foo(int p1)                     XA <- p1                       */
82   /*   foo(long p1)                    stack <- p1                    */
83   /*   foo(char p1, int p2)            A <- p1, stack <- p2           */
84   /*   foo(int p1, char p2)            XA <- p1, stack <- p2          */
85
86   if (regParmFlg>=2)
87     return 0;
88
89   if ((regParmFlg+size)>2) 
90     {
91       regParmFlg = 2;
92       return 0;
93     }
94
95   regParmFlg += size;
96   return 1+regParmFlg-size;
97 }
98
99 static bool
100 _hc08_parseOptions (int *pargc, char **argv, int *i)
101 {
102   if (!strcmp (argv[*i], "--out-fmt-elf"))
103     {
104       options.out_fmt = 2;
105       debugFile = &dwarf2DebugFile;
106       return TRUE;
107     }
108     
109   return FALSE;
110 }
111
112 static OPTION _hc08_options[] = 
113   {
114     {  0,   "--out-fmt-elf", NULL, "Output executable in ELF format" },
115     {  0, NULL }
116   };
117
118 static void
119 _hc08_finaliseOptions (void)
120 {
121   if (options.noXinitOpt) {
122     port->genXINIT=0;
123   }
124
125   if (options.model == MODEL_LARGE) {
126       port->mem.default_local_map = xdata;
127       port->mem.default_globl_map = xdata;
128     }
129   else
130     {
131       port->mem.default_local_map = data;
132       port->mem.default_globl_map = data;
133     }
134
135   istack->ptrType = FPOINTER;
136 }
137
138 static void
139 _hc08_setDefaultOptions (void)
140 {
141   options.code_loc = 0x8000;
142   options.data_loc = 0x80;
143   options.xdata_loc = 0x100;
144   options.stack_loc = 0x7fff;
145   options.out_fmt = 1;          /* use motorola S19 output */
146
147   options.ommitFramePtr = 1;    /* no frame pointer (we use SP */
148                                 /* offsets instead)            */
149   
150 }
151
152 static const char *
153 _hc08_getRegName (struct regs *reg)
154 {
155   if (reg)
156     return reg->name;
157   return "err";
158 }
159
160 static void
161 _hc08_genAssemblerPreamble (FILE * of)
162 {
163   int i;
164   int needOrg = 1;
165   symbol *mainExists=newSymbol("main", 0);
166   mainExists->block=0;
167
168   fprintf (of, "\t.area %s\n",port->mem.code_name);
169   fprintf (of, "\t.area %s\n",port->mem.static_name);
170   fprintf (of, "\t.area %s\n",port->mem.post_static_name);
171   fprintf (of, "\t.area %s\n",port->mem.xinit_name);
172   fprintf (of, "\t.area %s\n",port->mem.data_name);
173   fprintf (of, "\t.area %s\n",port->mem.overlay_name);
174   fprintf (of, "\t.area %s\n",port->mem.bit_name);
175   fprintf (of, "\t.area %s\n",port->mem.xdata_name);
176   fprintf (of, "\t.area %s\n",port->mem.xidata_name);
177
178   if ((mainExists=findSymWithLevel(SymbolTab, mainExists)))
179     {
180       // generate interrupt vector table
181       fprintf (of, "\t.area\tCODEIVT (ABS)\n");
182       
183       for (i=maxInterrupts;i>0;i--)
184         {
185           if (interrupts[i])
186             {
187               if (needOrg)
188                 {
189                   fprintf (of, "\t.org\t0x%04x\n", (0xfffe - (i * 2)));
190                   needOrg = 0;
191                 }
192               fprintf (of, "\t.dw\t%s\n", interrupts[i]->rname);
193             }
194           else
195             needOrg = 1;
196         }
197       if (needOrg)
198         fprintf (of, "\t.org\t0xfffe\n");
199       fprintf (of, "\t.dw\t%s", "__sdcc_gs_init_startup\n\n");
200         
201       fprintf (of, "\t.area GSINIT\n");
202       fprintf (of, "__sdcc_gs_init_startup:\n");
203       if (options.stack_loc)
204         {
205           fprintf (of, "\tldhx\t#0x%04x\n", options.stack_loc+1);
206           fprintf (of, "\ttxs\n");
207         }
208       else
209         fprintf (of, "\trsp\n");
210       fprintf (of, "\tjsr\t__sdcc_external_startup\n");
211       fprintf (of, "\tbeq\t__sdcc_init_data\n");
212       fprintf (of, "\tjmp\t__sdcc_program_startup\n");
213       fprintf (of, "__sdcc_init_data:\n");
214
215       fprintf (of, "; _hc08_genXINIT() start\n");
216       fprintf (of, "        ldhx #0\n");
217       fprintf (of, "00001$:\n");
218       fprintf (of, "        cphx #l_XINIT\n");
219       fprintf (of, "        beq  00002$\n");
220       fprintf (of, "        lda  s_XINIT,x\n");
221       fprintf (of, "        sta  s_XISEG,x\n");
222       fprintf (of, "        aix  #1\n");
223       fprintf (of, "        bra  00001$\n");
224       fprintf (of, "00002$:\n");
225       fprintf (of, "; _hc08_genXINIT() end\n");
226
227       fprintf (of, "\t.area GSFINAL\n");
228       fprintf (of, "\tjmp\t__sdcc_program_startup\n\n");
229
230       fprintf (of, "\t.area CSEG\n");
231       fprintf (of, "__sdcc_program_startup:\n");
232       fprintf (of, "\tjsr\t_main\n");
233       fprintf (of, "\tbra\t.\n");
234       
235     }
236 }
237
238 static void
239 _hc08_genAssemblerEnd (FILE * of)
240 {
241   if (options.out_fmt == 2 && options.debug)
242     {
243       dwarf2FinalizeFile();
244       copyFile(of, dwarf2FilePtr);
245     }
246 }
247
248 static void
249 _hc08_genExtraAreas (FILE * asmFile, bool mainExists)
250 {
251     fprintf (asmFile, "%s", iComments2);
252     fprintf (asmFile, "; extended address mode data\n");
253     fprintf (asmFile, "%s", iComments2);
254     copyFile (asmFile, xdata->oFile);
255 }
256
257
258 /* Generate interrupt vector table. */
259 static int
260 _hc08_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts)
261 {
262   int i;
263   
264   fprintf (of, "\t.area\tCODEIVT (ABS)\n");
265   fprintf (of, "\t.org\t0x%04x\n",
266     (0xfffe - (maxInterrupts * 2)));
267   
268   for (i=maxInterrupts;i>0;i--)
269     {
270       if (interrupts[i])
271         fprintf (of, "\t.dw\t%s\n", interrupts[i]->rname);
272       else
273         fprintf (of, "\t.dw\t0xffff\n");
274     }
275   fprintf (of, "\t.dw\t%s", "__sdcc_gs_init_startup\n");
276         
277   return TRUE;
278 }
279
280 /* Generate code to copy XINIT to XISEG */
281 static void _hc08_genXINIT (FILE * of) {
282   fprintf (of, ";       _hc08_genXINIT() start\n");
283   fprintf (of, ";       _hc08_genXINIT() end\n");
284 }
285
286
287 /* Do CSE estimation */
288 static bool cseCostEstimation (iCode *ic, iCode *pdic)
289 {
290     operand *result = IC_RESULT(ic);
291     sym_link *result_type = operandType(result);
292
293     return 0; /* disable CSE */
294     
295     /* if it is a pointer then return ok for now */
296     if (IC_RESULT(ic) && IS_PTR(result_type)) return 1;
297     
298     if (ic->op == ADDRESS_OF)
299       return 0;
300     
301     /* if bitwise | add & subtract then no since hc08 is pretty good at it 
302        so we will cse only if they are local (i.e. both ic & pdic belong to
303        the same basic block */
304     if (IS_BITWISE_OP(ic) || ic->op == '+' || ic->op == '-') {
305         /* then if they are the same Basic block then ok */
306         if (ic->eBBlockNum == pdic->eBBlockNum) return 1;
307         else return 0;
308     }
309         
310     /* for others it is cheaper to do the cse */
311     return 1;
312 }
313
314
315 /* Indicate which extended bit operations this port supports */
316 static bool
317 hasExtBitOp (int op, int size)
318 {
319   if (op == RRC
320       || op == RLC
321       || op == GETHBIT
322       || (op == SWAP && size <= 2)
323      )
324     return TRUE;
325   else
326     return FALSE;
327 }
328
329 /* Indicate the expense of an access to an output storage class */
330 static int
331 oclsExpense (struct memmap *oclass)
332 {
333   /* The hc08's addressing modes allow access to all storage classes */
334   /* inexpensively (<=0) */
335   
336   if (IN_DIRSPACE (oclass))     /* direct addressing mode is fastest */
337     return -2;
338   if (IN_FARSPACE (oclass))     /* extended addressing mode is almost at fast */
339     return -1;
340   if (oclass == istack) /* stack is the slowest, but still faster than */
341     return 0;           /* trying to copy to a temp location elsewhere */
342   
343   return 0; /* anything we missed */
344 }
345
346
347 /*----------------------------------------------------------------------*/
348 /* hc08_dwarfRegNum - return the DWARF register number for a register.  */
349 /*   These are defined for the HC08 in "Motorola 8- and 16-bit Embedded */
350 /*   Application Binary Interface (M8/16EABI)"                          */
351 /*----------------------------------------------------------------------*/
352 static int
353 hc08_dwarfRegNum (regs * reg)
354 {
355   switch (reg->rIdx)
356     {
357     case A_IDX: return 0;
358     case H_IDX: return 1;
359     case X_IDX: return 2;
360     case CND_IDX: return 17;
361     case SP_IDX: return 15;
362     }
363   return -1;
364 }
365
366
367
368 /** $1 is always the basename.
369     $2 is always the output file.
370     $3 varies
371     $l is the list of extra options that should be there somewhere...
372     MUST be terminated with a NULL.
373 */
374 static const char *_linkCmd[] =
375 {
376   "link-hc08", "-nf", "\"$1\"", NULL
377 };
378
379 /* $3 is replaced by assembler.debug_opts resp. port->assembler.plain_opts */
380 static const char *_asmCmd[] =
381 {
382   "as-hc08", "$l", "$3", "\"$1.asm\"", NULL
383 };
384
385 /* Globals */
386 PORT hc08_port =
387 {
388   TARGET_ID_HC08,
389   "hc08",
390   "HC08",                       /* Target name */
391   NULL,                         /* Processor name */
392   {
393     glue,
394     FALSE,                      /* Emit glue around main */
395     MODEL_SMALL | MODEL_LARGE,
396     MODEL_LARGE
397   },
398   {
399     _asmCmd,
400     NULL,
401     "-plosgffc",                /* Options with debug */
402     "-plosgff",                 /* Options without debug */
403     0,
404     ".asm",
405     NULL                        /* no do_assemble function */
406   },
407   {
408     _linkCmd,
409     NULL,
410     NULL,
411     ".rel",
412     1
413   },
414   {
415     _defaultRules
416   },
417   {
418         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
419     1, 2, 2, 4, 2, 2, 2, 1, 4, 4
420   },
421   {
422     "XSEG",
423     "STACK",
424     "CSEG (CODE)",
425     "DSEG",
426     NULL, /* "ISEG" */
427     "XSEG",
428     "BSEG",
429     "RSEG",
430     "GSINIT (CODE)",
431     "OSEG    (OVR)",
432     "GSFINAL (CODE)",
433     "HOME (CODE)",
434     "XISEG", // initialized xdata
435     "XINIT", // a code copy of xiseg
436     NULL,
437     NULL,
438     1
439   },
440   { _hc08_genExtraAreas,
441     NULL },
442   {
443     -1,         /* direction (-1 = stack grows down) */
444     0,          /* bank_overhead (switch between register banks) */
445     4,          /* isr_overhead */
446     2,          /* call_overhead */
447     0,          /* reent_overhead */
448     0           /* banked_overhead (switch between code banks) */
449   },
450     /* hc08 has an 8 bit mul */
451   {
452     1, -1
453   },
454   {
455     hc08_emitDebuggerSymbol,
456     {
457       hc08_dwarfRegNum,
458       NULL,
459       NULL,
460       4,                                /* addressSize */
461       14,                       /* regNumRet */
462       15,                       /* regNumSP */
463       -1,                       /* regNumBP */
464       1,                        /* offsetSP */
465     },
466   },
467   "_",
468   _hc08_init,
469   _hc08_parseOptions,
470   _hc08_options,
471   _hc08_finaliseOptions,
472   _hc08_setDefaultOptions,
473   hc08_assignRegisters,
474   _hc08_getRegName,
475   _hc08_keywords,
476   _hc08_genAssemblerPreamble,
477   _hc08_genAssemblerEnd,        /* no genAssemblerEnd */
478   _hc08_genIVT,
479   _hc08_genXINIT,
480   NULL,                         /* genInitStartup */
481   _hc08_reset_regparm,
482   _hc08_regparm,
483   NULL,                         /* process_pragma */
484   NULL,                         /* getMangledFunctionName */
485   NULL,                         /* hasNativeMulFor */
486   hasExtBitOp,                  /* hasExtBitOp */
487   oclsExpense,                  /* oclsExpense */
488   TRUE,                         /* use_dw_for_init */
489   FALSE,                        /* little endian */
490   0,                            /* leave lt */
491   0,                            /* leave gt */
492   1,                            /* transform <= to ! > */
493   1,                            /* transform >= to ! < */
494   1,                            /* transform != to !(a == b) */
495   0,                            /* leave == */
496   FALSE,                        /* No array initializer support. */
497   cseCostEstimation,
498   NULL,                         /* no builtin functions */
499   GPOINTER,                     /* treat unqualified pointers as "generic" pointers */
500   1,                            /* reset labelKey to 1 */
501   1,                            /* globals & local static allowed */
502   PORT_MAGIC
503 };