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