Initial import
[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 /** $1 is always the basename.
280     $2 is always the output file.
281     $3 varies
282     $l is the list of extra options that should be there somewhere...
283     MUST be terminated with a NULL.
284 */
285 static const char *_linkCmd[] =
286 {
287   "link-hc08", "-nf", "\"$1\"", NULL
288 };
289
290 /* $3 is replaced by assembler.debug_opts resp. port->assembler.plain_opts */
291 static const char *_asmCmd[] =
292 {
293   "as-hc08", "$l", "$3", "\"$1.asm\"", NULL
294 };
295
296 /* Globals */
297 PORT hc08_port =
298 {
299   TARGET_ID_HC08,
300   "hc08",
301   "HC08",                       /* Target name */
302   NULL,                         /* Processor name */
303   {
304     glue,
305     FALSE,                      /* Emit glue around main */
306     MODEL_SMALL | MODEL_LARGE,
307     MODEL_LARGE
308   },
309   {
310     _asmCmd,
311     NULL,
312     "-plosgffc",                /* Options with debug */
313     "-plosgff",                 /* Options without debug */
314     0,
315     ".asm",
316     NULL                        /* no do_assemble function */
317   },
318   {
319     _linkCmd,
320     NULL,
321     NULL,
322     ".rel"
323   },
324   {
325     _defaultRules
326   },
327   {
328         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
329     1, 2, 2, 4, 2, 2, 2, 1, 4, 4
330   },
331   {
332     "XSEG",
333     "STACK",
334     "CSEG",
335     "DSEG",
336     NULL, /* "ISEG" */
337     "XSEG",
338     "BSEG",
339     "RSEG",
340     "GSINIT",
341     "OSEG    (OVR)",
342     "GSFINAL",
343     "HOME",
344     "XISEG", // initialized xdata
345     "XINIT", // a code copy of xiseg
346     NULL,
347     NULL,
348     1
349   },
350   { _hc08_genExtraAreas,
351     NULL },
352   {
353     -1, 0, 4, 2, 0, 0
354   },
355     /* hc08 has an 8 bit mul */
356   {
357     1, -1
358   },
359   "_",
360   _hc08_init,
361   _hc08_parseOptions,
362   NULL,
363   _hc08_finaliseOptions,
364   _hc08_setDefaultOptions,
365   hc08_assignRegisters,
366   _hc08_getRegName,
367   _hc08_keywords,
368   _hc08_genAssemblerPreamble,
369   NULL,                         /* no genAssemblerEnd */
370   _hc08_genIVT,
371   _hc08_genXINIT,
372   _hc08_reset_regparm,
373   _hc08_regparm,
374   NULL,                         /* process_pragma */
375   NULL,                         /* getMangledFunctionName */
376   NULL,                         /* hasNativeMulFor */
377   TRUE,                         /* use_dw_for_init */
378   FALSE,                        /* little endian */
379   0,                            /* leave lt */
380   0,                            /* leave gt */
381   1,                            /* transform <= to ! > */
382   1,                            /* transform >= to ! < */
383   1,                            /* transform != to !(a == b) */
384   0,                            /* leave == */
385   FALSE,                        /* No array initializer support. */
386   cseCostEstimation,
387   NULL,                         /* no builtin functions */
388   GPOINTER,                     /* treat unqualified pointers as "generic" pointers */
389   1,                            /* reset labelKey to 1 */
390   1,                            /* globals & local static allowed */
391   PORT_MAGIC
392 };