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