c25636b2f71957b7f4d6b5775371c829bbf47232
[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 }
132
133 static void
134 _hc08_setDefaultOptions (void)
135 {
136   options.code_loc = 0x8000;
137   options.data_loc = 0x80;
138   options.xdata_loc = 0x100;
139   options.stack_loc = 0x7fff;
140   options.out_fmt = 1;          /* use motorola S19 output */
141
142   options.ommitFramePtr = 1;    /* no frame pointer (we use SP */
143                                 /* offsets instead)            */
144   
145 }
146
147 static const char *
148 _hc08_getRegName (struct regs *reg)
149 {
150   if (reg)
151     return reg->name;
152   return "err";
153 }
154
155 static void
156 _hc08_genAssemblerPreamble (FILE * of)
157 {
158   int i;
159   int needOrg = 1;
160   symbol *mainExists=newSymbol("main", 0);
161   mainExists->block=0;
162
163   fprintf (of, "\t.area %s\n",port->mem.code_name);
164   fprintf (of, "\t.area %s\n",port->mem.static_name);
165   fprintf (of, "\t.area %s\n",port->mem.post_static_name);
166   fprintf (of, "\t.area %s\n",port->mem.xinit_name);
167   fprintf (of, "\t.area %s\n",port->mem.data_name);
168   fprintf (of, "\t.area %s\n",port->mem.overlay_name);
169   fprintf (of, "\t.area %s\n",port->mem.bit_name);
170   fprintf (of, "\t.area %s\n",port->mem.xdata_name);
171   fprintf (of, "\t.area %s\n",port->mem.xidata_name);
172
173   if ((mainExists=findSymWithLevel(SymbolTab, mainExists)))
174     {
175       // generate interrupt vector table
176       fprintf (of, "\t.area\tCODEIVT (ABS)\n");
177       
178       for (i=maxInterrupts;i>0;i--)
179         {
180           if (interrupts[i])
181             {
182               if (needOrg)
183                 {
184                   fprintf (of, "\t.org\t0x%04x\n", (0xfffe - (i * 2)));
185                   needOrg = 0;
186                 }
187               fprintf (of, "\t.dw\t%s\n", interrupts[i]->rname);
188             }
189           else
190             needOrg = 1;
191         }
192       if (needOrg)
193         fprintf (of, "\t.org\t0xfffe\n");
194       fprintf (of, "\t.dw\t%s", "__sdcc_gs_init_startup\n\n");
195         
196       fprintf (of, "\t.area GSINIT\n");
197       fprintf (of, "__sdcc_gs_init_startup:\n");
198       if (options.stack_loc)
199         {
200           fprintf (of, "\tldhx\t#0x%04x\n", options.stack_loc+1);
201           fprintf (of, "\ttxs\n");
202         }
203       else
204         fprintf (of, "\trsp\n");
205       fprintf (of, "\tjsr\t__sdcc_external_startup\n");
206       fprintf (of, "\tbeq\t__sdcc_init_data\n");
207       fprintf (of, "\tjmp\t__sdcc_program_startup\n");
208       fprintf (of, "__sdcc_init_data:\n");
209
210       fprintf (of, "; _hc08_genXINIT() start\n");
211       fprintf (of, "        ldhx #0\n");
212       fprintf (of, "00001$:\n");
213       fprintf (of, "        cphx #l_XINIT\n");
214       fprintf (of, "        beq  00002$\n");
215       fprintf (of, "        lda  s_XINIT,x\n");
216       fprintf (of, "        sta  s_XISEG,x\n");
217       fprintf (of, "        aix  #1\n");
218       fprintf (of, "        bra  00001$\n");
219       fprintf (of, "00002$:\n");
220       fprintf (of, "; _hc08_genXINIT() end\n");
221
222       fprintf (of, "\t.area GSFINAL\n");
223       fprintf (of, "\tjmp\t__sdcc_program_startup\n\n");
224
225       fprintf (of, "\t.area CSEG\n");
226       fprintf (of, "__sdcc_program_startup:\n");
227       fprintf (of, "\tjsr\t_main\n");
228       fprintf (of, "\tbra\t.\n");
229       
230     }
231 }
232
233 static void
234 _hc08_genExtraAreas (FILE * asmFile, bool mainExists)
235 {
236     fprintf (asmFile, "%s", iComments2);
237     fprintf (asmFile, "; extended address mode data\n");
238     fprintf (asmFile, "%s", iComments2);
239     copyFile (asmFile, xdata->oFile);
240 }
241
242
243 /* Generate interrupt vector table. */
244 static int
245 _hc08_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts)
246 {
247   int i;
248   
249   fprintf (of, "\t.area\tCODEIVT (ABS)\n");
250   fprintf (of, "\t.org\t0x%04x\n",
251     (0xfffe - (maxInterrupts * 2)));
252   
253   for (i=maxInterrupts;i>0;i--)
254     {
255       if (interrupts[i])
256         fprintf (of, "\t.dw\t%s\n", interrupts[i]->rname);
257       else
258         fprintf (of, "\t.dw\t0xffff\n");
259     }
260   fprintf (of, "\t.dw\t%s", "__sdcc_gs_init_startup\n");
261         
262   return TRUE;
263 }
264
265 /* Generate code to copy XINIT to XISEG */
266 static void _hc08_genXINIT (FILE * of) {
267   fprintf (of, ";       _hc08_genXINIT() start\n");
268   fprintf (of, ";       _hc08_genXINIT() end\n");
269 }
270
271
272 /* Do CSE estimation */
273 static bool cseCostEstimation (iCode *ic, iCode *pdic)
274 {
275     operand *result = IC_RESULT(ic);
276     sym_link *result_type = operandType(result);
277
278     return 0; /* disable CSE */
279     
280     /* if it is a pointer then return ok for now */
281     if (IC_RESULT(ic) && IS_PTR(result_type)) return 1;
282     
283     if (ic->op == ADDRESS_OF)
284       return 0;
285     
286     /* if bitwise | add & subtract then no since hc08 is pretty good at it 
287        so we will cse only if they are local (i.e. both ic & pdic belong to
288        the same basic block */
289     if (IS_BITWISE_OP(ic) || ic->op == '+' || ic->op == '-') {
290         /* then if they are the same Basic block then ok */
291         if (ic->eBBlockNum == pdic->eBBlockNum) return 1;
292         else return 0;
293     }
294         
295     /* for others it is cheaper to do the cse */
296     return 1;
297 }
298
299
300 /* Indicate which extended bit operations this port supports */
301 static bool
302 hasExtBitOp (int op, int size)
303 {
304   if (op == RRC
305       || op == RLC
306       || op == GETHBIT
307       || (op == SWAP && size <= 2)
308      )
309     return TRUE;
310   else
311     return FALSE;
312 }
313
314 /* Indicate the expense of an access to an output storage class */
315 static int
316 oclsExpense (struct memmap *oclass)
317 {
318   /* The hc08's addressing modes allow access to all storage classes */
319   /* inexpensively (<=0) */
320   
321   if (IN_DIRSPACE (oclass))     /* direct addressing mode is fastest */
322     return -2;
323   if (IN_FARSPACE (oclass))     /* extended addressing mode is almost at fast */
324     return -1;
325   if (oclass == istack) /* stack is the slowest, but still faster than */
326     return 0;           /* trying to copy to a temp location elsewhere */
327   
328   return 0; /* anything we missed */
329 }
330
331
332
333 /** $1 is always the basename.
334     $2 is always the output file.
335     $3 varies
336     $l is the list of extra options that should be there somewhere...
337     MUST be terminated with a NULL.
338 */
339 static const char *_linkCmd[] =
340 {
341   "link-hc08", "-nf", "\"$1\"", NULL
342 };
343
344 /* $3 is replaced by assembler.debug_opts resp. port->assembler.plain_opts */
345 static const char *_asmCmd[] =
346 {
347   "as-hc08", "$l", "$3", "\"$1.asm\"", NULL
348 };
349
350 /* Globals */
351 PORT hc08_port =
352 {
353   TARGET_ID_HC08,
354   "hc08",
355   "HC08",                       /* Target name */
356   NULL,                         /* Processor name */
357   {
358     glue,
359     FALSE,                      /* Emit glue around main */
360     MODEL_SMALL | MODEL_LARGE,
361     MODEL_LARGE
362   },
363   {
364     _asmCmd,
365     NULL,
366     "-plosgffc",                /* Options with debug */
367     "-plosgff",                 /* Options without debug */
368     0,
369     ".asm",
370     NULL                        /* no do_assemble function */
371   },
372   {
373     _linkCmd,
374     NULL,
375     NULL,
376     ".rel",
377     1
378   },
379   {
380     _defaultRules
381   },
382   {
383         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
384     1, 2, 2, 4, 2, 2, 2, 1, 4, 4
385   },
386   {
387     "XSEG",
388     "STACK",
389     "CSEG (CODE)",
390     "DSEG",
391     NULL, /* "ISEG" */
392     "XSEG",
393     "BSEG",
394     "RSEG",
395     "GSINIT (CODE)",
396     "OSEG    (OVR)",
397     "GSFINAL (CODE)",
398     "HOME (CODE)",
399     "XISEG", // initialized xdata
400     "XINIT", // a code copy of xiseg
401     NULL,
402     NULL,
403     1
404   },
405   { _hc08_genExtraAreas,
406     NULL },
407   {
408     -1, 0, 4, 2, 0, 0
409   },
410     /* hc08 has an 8 bit mul */
411   {
412     1, -1
413   },
414   "_",
415   _hc08_init,
416   _hc08_parseOptions,
417   _hc08_options,
418   _hc08_finaliseOptions,
419   _hc08_setDefaultOptions,
420   hc08_assignRegisters,
421   _hc08_getRegName,
422   _hc08_keywords,
423   _hc08_genAssemblerPreamble,
424   NULL,                         /* no genAssemblerEnd */
425   _hc08_genIVT,
426   _hc08_genXINIT,
427   NULL,                         /* genInitStartup */
428   _hc08_reset_regparm,
429   _hc08_regparm,
430   NULL,                         /* process_pragma */
431   NULL,                         /* getMangledFunctionName */
432   NULL,                         /* hasNativeMulFor */
433   hasExtBitOp,                  /* hasExtBitOp */
434   oclsExpense,                  /* oclsExpense */
435   TRUE,                         /* use_dw_for_init */
436   FALSE,                        /* little endian */
437   0,                            /* leave lt */
438   0,                            /* leave gt */
439   1,                            /* transform <= to ! > */
440   1,                            /* transform >= to ! < */
441   1,                            /* transform != to !(a == b) */
442   0,                            /* leave == */
443   FALSE,                        /* No array initializer support. */
444   cseCostEstimation,
445   NULL,                         /* no builtin functions */
446   GPOINTER,                     /* treat unqualified pointers as "generic" pointers */
447   1,                            /* reset labelKey to 1 */
448   1,                            /* globals & local static allowed */
449   PORT_MAGIC
450 };