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