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