Imported Upstream version 2.9.0
[debian/cc1111] / 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 "dbuf_string.h"
12 #include "../SDCCutil.h"
13
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 (ebbIndex *);
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 (void)
66 {
67   regParmFlg = 0;
68 }
69
70 static int
71 _hc08_regparm (sym_link * l, bool reentrant)
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 = 0;        /* 0 means immediately following data */
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",HOME_NAME);
168   fprintf (of, "\t.area GSINIT0 (CODE)\n");
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",CODE_NAME);
172   fprintf (of, "\t.area %s\n",port->mem.xinit_name);
173   fprintf (of, "\t.area %s\n",port->mem.const_name);
174   fprintf (of, "\t.area %s\n",port->mem.data_name);
175   fprintf (of, "\t.area %s\n",port->mem.overlay_name);
176   fprintf (of, "\t.area %s\n",port->mem.bit_name);
177   fprintf (of, "\t.area %s\n",port->mem.xdata_name);
178   fprintf (of, "\t.area %s\n",port->mem.xidata_name);
179
180   if ((mainExists=findSymWithLevel(SymbolTab, mainExists)))
181     {
182       // generate interrupt vector table
183       fprintf (of, "\t.area\tCODEIVT (ABS)\n");
184       
185       for (i=maxInterrupts;i>0;i--)
186         {
187           if (interrupts[i])
188             {
189               if (needOrg)
190                 {
191                   fprintf (of, "\t.org\t0x%04x\n", (0xfffe - (i * 2)));
192                   needOrg = 0;
193                 }
194               fprintf (of, "\t.dw\t%s\n", interrupts[i]->rname);
195             }
196           else
197             needOrg = 1;
198         }
199       if (needOrg)
200         fprintf (of, "\t.org\t0xfffe\n");
201       fprintf (of, "\t.dw\t%s", "__sdcc_gs_init_startup\n\n");
202         
203       fprintf (of, "\t.area GSINIT0\n");
204       fprintf (of, "__sdcc_gs_init_startup:\n");
205       if (options.stack_loc)
206         {
207           fprintf (of, "\tldhx\t#0x%04x\n", options.stack_loc+1);
208           fprintf (of, "\ttxs\n");
209         }
210       else
211         fprintf (of, "\trsp\n");
212       fprintf (of, "\tjsr\t__sdcc_external_startup\n");
213       fprintf (of, "\tbeq\t__sdcc_init_data\n");
214       fprintf (of, "\tjmp\t__sdcc_program_startup\n");
215       fprintf (of, "__sdcc_init_data:\n");
216
217       fprintf (of, "; _hc08_genXINIT() start\n");
218       fprintf (of, "        ldhx #0\n");
219       fprintf (of, "00001$:\n");
220       fprintf (of, "        cphx #l_XINIT\n");
221       fprintf (of, "        beq  00002$\n");
222       fprintf (of, "        lda  s_XINIT,x\n");
223       fprintf (of, "        sta  s_XISEG,x\n");
224       fprintf (of, "        aix  #1\n");
225       fprintf (of, "        bra  00001$\n");
226       fprintf (of, "00002$:\n");
227       fprintf (of, "; _hc08_genXINIT() end\n");
228
229       fprintf (of, "\t.area GSFINAL\n");
230       fprintf (of, "\tjmp\t__sdcc_program_startup\n\n");
231
232       fprintf (of, "\t.area CSEG\n");
233       fprintf (of, "__sdcc_program_startup:\n");
234       fprintf (of, "\tjsr\t_main\n");
235       fprintf (of, "\tbra\t.\n");
236       
237     }
238 }
239
240 static void
241 _hc08_genAssemblerEnd (FILE * of)
242 {
243   if (options.out_fmt == 2 && options.debug)
244     {
245       dwarf2FinalizeFile (of);
246     }
247 }
248
249 static void
250 _hc08_genExtraAreas (FILE * asmFile, bool mainExists)
251 {
252     fprintf (asmFile, "%s", iComments2);
253     fprintf (asmFile, "; extended address mode data\n");
254     fprintf (asmFile, "%s", iComments2);
255     dbuf_write_and_destroy (&xdata->oBuf, asmFile);
256 }
257
258
259 /* Generate interrupt vector table. */
260 static int
261 _hc08_genIVT (struct dbuf_s * oBuf, symbol ** interrupts, int maxInterrupts)
262 {
263   int i;
264   
265   dbuf_printf (oBuf, "\t.area\tCODEIVT (ABS)\n");
266   dbuf_printf (oBuf, "\t.org\t0x%04x\n",
267     (0xfffe - (maxInterrupts * 2)));
268   
269   for (i=maxInterrupts;i>0;i--)
270     {
271       if (interrupts[i])
272         dbuf_printf (oBuf, "\t.dw\t%s\n", interrupts[i]->rname);
273       else
274         dbuf_printf (oBuf, "\t.dw\t0xffff\n");
275     }
276   dbuf_printf (oBuf, "\t.dw\t%s", "__sdcc_gs_init_startup\n");
277         
278   return TRUE;
279 }
280
281 /* Generate code to copy XINIT to XISEG */
282 static void _hc08_genXINIT (FILE * of) {
283   fprintf (of, ";       _hc08_genXINIT() start\n");
284   fprintf (of, ";       _hc08_genXINIT() end\n");
285 }
286
287
288 /* Do CSE estimation */
289 static bool cseCostEstimation (iCode *ic, iCode *pdic)
290 {
291     operand *result = IC_RESULT(ic);
292     sym_link *result_type = operandType(result);
293
294     return 0; /* disable CSE */
295     
296     /* if it is a pointer then return ok for now */
297     if (IC_RESULT(ic) && IS_PTR(result_type)) return 1;
298     
299     if (ic->op == ADDRESS_OF)
300       return 0;
301     
302     /* if bitwise | add & subtract then no since hc08 is pretty good at it 
303        so we will cse only if they are local (i.e. both ic & pdic belong to
304        the same basic block */
305     if (IS_BITWISE_OP(ic) || ic->op == '+' || ic->op == '-') {
306         /* then if they are the same Basic block then ok */
307         if (ic->eBBlockNum == pdic->eBBlockNum) return 1;
308         else return 0;
309     }
310         
311     /* for others it is cheaper to do the cse */
312     return 1;
313 }
314
315
316 /* Indicate which extended bit operations this port supports */
317 static bool
318 hasExtBitOp (int op, int size)
319 {
320   if (op == RRC
321       || op == RLC
322       || op == GETHBIT
323       || (op == SWAP && size <= 2)
324      )
325     return TRUE;
326   else
327     return FALSE;
328 }
329
330 /* Indicate the expense of an access to an output storage class */
331 static int
332 oclsExpense (struct memmap *oclass)
333 {
334   /* The hc08's addressing modes allow access to all storage classes */
335   /* inexpensively (<=0) */
336   
337   if (IN_DIRSPACE (oclass))     /* direct addressing mode is fastest */
338     return -2;
339   if (IN_FARSPACE (oclass))     /* extended addressing mode is almost at fast */
340     return -1;
341   if (oclass == istack) /* stack is the slowest, but still faster than */
342     return 0;           /* trying to copy to a temp location elsewhere */
343   
344   return 0; /* anything we missed */
345 }
346
347
348 /*----------------------------------------------------------------------*/
349 /* hc08_dwarfRegNum - return the DWARF register number for a register.  */
350 /*   These are defined for the HC08 in "Motorola 8- and 16-bit Embedded */
351 /*   Application Binary Interface (M8/16EABI)"                          */
352 /*----------------------------------------------------------------------*/
353 static int
354 hc08_dwarfRegNum (regs * reg)
355 {
356   switch (reg->rIdx)
357     {
358     case A_IDX: return 0;
359     case H_IDX: return 1;
360     case X_IDX: return 2;
361     case CND_IDX: return 17;
362     case SP_IDX: return 15;
363     }
364   return -1;
365 }
366
367
368
369 /** $1 is always the basename.
370     $2 is always the output file.
371     $3 varies
372     $l is the list of extra options that should be there somewhere...
373     MUST be terminated with a NULL.
374 */
375 static const char *_linkCmd[] =
376 {
377   "link-hc08", "-nf", "\"$1\"", NULL
378 };
379
380 /* $3 is replaced by assembler.debug_opts resp. port->assembler.plain_opts */
381 static const char *_asmCmd[] =
382 {
383   "as-hc08", "$l", "$3", "\"$1.asm\"", NULL
384 };
385
386 /* Globals */
387 PORT hc08_port =
388 {
389   TARGET_ID_HC08,
390   "hc08",
391   "HC08",                       /* Target name */
392   NULL,                         /* Processor name */
393   {
394     glue,
395     FALSE,                      /* Emit glue around main */
396     MODEL_SMALL | MODEL_LARGE,
397     MODEL_LARGE
398   },
399   {
400     _asmCmd,
401     NULL,
402     "-plosgffc",                /* Options with debug */
403     "-plosgff",                 /* Options without debug */
404     0,
405     ".asm",
406     NULL                        /* no do_assemble function */
407   },
408   {
409     _linkCmd,
410     NULL,
411     NULL,
412     ".rel",
413     1
414   },
415   {
416     _defaultRules
417   },
418   {
419         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
420     1, 2, 2, 4, 2, 2, 2, 1, 4, 4
421   },
422   /* tags for generic pointers */
423   { 0x00, 0x40, 0x60, 0x80 },           /* far, near, xstack, code */
424   
425   {
426     "XSEG",
427     "STACK",
428     "CSEG (CODE)",
429     "DSEG",
430     NULL, /* "ISEG" */
431     NULL, /* "PSEG" */
432     "XSEG",
433     "BSEG",
434     "RSEG",
435     "GSINIT (CODE)",
436     "OSEG    (OVR)",
437     "GSFINAL (CODE)",
438     "HOME (CODE)",
439     "XISEG", // initialized xdata
440     "XINIT", // a code copy of xiseg
441     "CONST   (CODE)",     // const_name - const data (code or not)
442     "CABS    (ABS,CODE)", // cabs_name - const absolute data (code or not)
443     "XABS    (ABS)",      // xabs_name - absolute xdata
444     "IABS    (ABS)",      // iabs_name - absolute data
445     NULL,
446     NULL,
447     1
448   },
449   { _hc08_genExtraAreas,
450     NULL },
451   {
452     -1,         /* direction (-1 = stack grows down) */
453     0,          /* bank_overhead (switch between register banks) */
454     4,          /* isr_overhead */
455     2,          /* call_overhead */
456     0,          /* reent_overhead */
457     0           /* banked_overhead (switch between code banks) */
458   },
459     /* hc08 has an 8 bit mul */
460   {
461     1, -1
462   },
463   {
464     hc08_emitDebuggerSymbol,
465     {
466       hc08_dwarfRegNum,
467       NULL,
468       NULL,
469       4,                                /* addressSize */
470       14,                       /* regNumRet */
471       15,                       /* regNumSP */
472       -1,                       /* regNumBP */
473       1,                        /* offsetSP */
474     },
475   },
476   {
477     256,        /* maxCount */
478     2,          /* sizeofElement */
479     {8,16,32},  /* sizeofMatchJump[] */
480     {8,16,32},  /* sizeofRangeCompare[] */
481     5,          /* sizeofSubtract */
482     10,         /* sizeofDispatch */
483   },
484   "_",
485   _hc08_init,
486   _hc08_parseOptions,
487   _hc08_options,
488   NULL,
489   _hc08_finaliseOptions,
490   _hc08_setDefaultOptions,
491   hc08_assignRegisters,
492   _hc08_getRegName,
493   _hc08_keywords,
494   _hc08_genAssemblerPreamble,
495   _hc08_genAssemblerEnd,        /* no genAssemblerEnd */
496   _hc08_genIVT,
497   _hc08_genXINIT,
498   NULL,                         /* genInitStartup */
499   _hc08_reset_regparm,
500   _hc08_regparm,
501   NULL,                         /* process_pragma */
502   NULL,                         /* getMangledFunctionName */
503   NULL,                         /* hasNativeMulFor */
504   hasExtBitOp,                  /* hasExtBitOp */
505   oclsExpense,                  /* oclsExpense */
506   TRUE,                         /* use_dw_for_init */
507   FALSE,                        /* little endian */
508   0,                            /* leave lt */
509   0,                            /* leave gt */
510   1,                            /* transform <= to ! > */
511   1,                            /* transform >= to ! < */
512   1,                            /* transform != to !(a == b) */
513   0,                            /* leave == */
514   FALSE,                        /* No array initializer support. */
515   cseCostEstimation,
516   NULL,                         /* no builtin functions */
517   GPOINTER,                     /* treat unqualified pointers as "generic" pointers */
518   1,                            /* reset labelKey to 1 */
519   1,                            /* globals & local static allowed */
520   PORT_MAGIC
521 };