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