2 hc08 specific general functions.
4 Note that mlh prepended _hc08_ on the static functions. Makes
5 it easier to set a breakpoint using the debugger.
11 #include "../SDCCutil.h"
13 void copyFile(FILE *dest, FILE *src);
14 extern char * iComments2;
15 extern DEBUGFILE dwarf2DebugFile;
16 extern int dwarf2FinalizeFile(FILE *);
18 static char _defaultRules[] =
23 /* list of key words used by msc51 */
24 static char *_hc08_keywords[] =
54 void hc08_assignRegisters (ebbIndex *);
56 static int regParmFlg = 0; /* determine if we can register a parameter */
61 asm_addTree (&asm_asxxxx_mapping);
65 _hc08_reset_regparm (void)
71 _hc08_regparm (sym_link * l, bool reentrant)
73 int size = getSize(l);
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 */
88 if ((regParmFlg+size)>2)
95 return 1+regParmFlg-size;
99 _hc08_parseOptions (int *pargc, char **argv, int *i)
101 if (!strcmp (argv[*i], "--out-fmt-elf"))
104 debugFile = &dwarf2DebugFile;
111 static OPTION _hc08_options[] =
113 { 0, "--out-fmt-elf", NULL, "Output executable in ELF format" },
118 _hc08_finaliseOptions (void)
120 if (options.noXinitOpt) {
124 if (options.model == MODEL_LARGE) {
125 port->mem.default_local_map = xdata;
126 port->mem.default_globl_map = xdata;
130 port->mem.default_local_map = data;
131 port->mem.default_globl_map = data;
134 istack->ptrType = FPOINTER;
138 _hc08_setDefaultOptions (void)
140 options.code_loc = 0x8000;
141 options.data_loc = 0x80;
142 options.xdata_loc = 0; /* 0 means immediately following data */
143 options.stack_loc = 0x7fff;
144 options.out_fmt = 1; /* use motorola S19 output */
146 options.ommitFramePtr = 1; /* no frame pointer (we use SP */
147 /* offsets instead) */
152 _hc08_getRegName (struct regs *reg)
160 _hc08_genAssemblerPreamble (FILE * of)
164 symbol *mainExists=newSymbol("main", 0);
167 fprintf (of, "\t.area %s\n",HOME_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",CODE_NAME);
172 fprintf (of, "\t.area %s\n",port->mem.xinit_name);
173 fprintf (of, "\t.area %s\n",port->mem.const_name);
174 fprintf (of, "\t.area %s\n",port->mem.data_name);
175 fprintf (of, "\t.area %s\n",port->mem.overlay_name);
176 fprintf (of, "\t.area %s\n",port->mem.bit_name);
177 fprintf (of, "\t.area %s\n",port->mem.xdata_name);
178 fprintf (of, "\t.area %s\n",port->mem.xidata_name);
180 if ((mainExists=findSymWithLevel(SymbolTab, mainExists)))
182 // generate interrupt vector table
183 fprintf (of, "\t.area\tCODEIVT (ABS)\n");
185 for (i=maxInterrupts;i>0;i--)
191 fprintf (of, "\t.org\t0x%04x\n", (0xfffe - (i * 2)));
194 fprintf (of, "\t.dw\t%s\n", interrupts[i]->rname);
200 fprintf (of, "\t.org\t0xfffe\n");
201 fprintf (of, "\t.dw\t%s", "__sdcc_gs_init_startup\n\n");
203 fprintf (of, "\t.area GSINIT0\n");
204 fprintf (of, "__sdcc_gs_init_startup:\n");
205 if (options.stack_loc)
207 fprintf (of, "\tldhx\t#0x%04x\n", options.stack_loc+1);
208 fprintf (of, "\ttxs\n");
211 fprintf (of, "\trsp\n");
212 fprintf (of, "\tjsr\t__sdcc_external_startup\n");
213 fprintf (of, "\tbeq\t__sdcc_init_data\n");
214 fprintf (of, "\tjmp\t__sdcc_program_startup\n");
215 fprintf (of, "__sdcc_init_data:\n");
217 fprintf (of, "; _hc08_genXINIT() start\n");
218 fprintf (of, " ldhx #0\n");
219 fprintf (of, "00001$:\n");
220 fprintf (of, " cphx #l_XINIT\n");
221 fprintf (of, " beq 00002$\n");
222 fprintf (of, " lda s_XINIT,x\n");
223 fprintf (of, " sta s_XISEG,x\n");
224 fprintf (of, " aix #1\n");
225 fprintf (of, " bra 00001$\n");
226 fprintf (of, "00002$:\n");
227 fprintf (of, "; _hc08_genXINIT() end\n");
229 fprintf (of, "\t.area GSFINAL\n");
230 fprintf (of, "\tjmp\t__sdcc_program_startup\n\n");
232 fprintf (of, "\t.area CSEG\n");
233 fprintf (of, "__sdcc_program_startup:\n");
234 fprintf (of, "\tjsr\t_main\n");
235 fprintf (of, "\tbra\t.\n");
241 _hc08_genAssemblerEnd (FILE * of)
243 if (options.out_fmt == 2 && options.debug)
245 dwarf2FinalizeFile (of);
250 _hc08_genExtraAreas (FILE * asmFile, bool mainExists)
252 fprintf (asmFile, "%s", iComments2);
253 fprintf (asmFile, "; extended address mode data\n");
254 fprintf (asmFile, "%s", iComments2);
255 copyFile (asmFile, xdata->oFile);
259 /* Generate interrupt vector table. */
261 _hc08_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts)
265 fprintf (of, "\t.area\tCODEIVT (ABS)\n");
266 fprintf (of, "\t.org\t0x%04x\n",
267 (0xfffe - (maxInterrupts * 2)));
269 for (i=maxInterrupts;i>0;i--)
272 fprintf (of, "\t.dw\t%s\n", interrupts[i]->rname);
274 fprintf (of, "\t.dw\t0xffff\n");
276 fprintf (of, "\t.dw\t%s", "__sdcc_gs_init_startup\n");
281 /* Generate code to copy XINIT to XISEG */
282 static void _hc08_genXINIT (FILE * of) {
283 fprintf (of, "; _hc08_genXINIT() start\n");
284 fprintf (of, "; _hc08_genXINIT() end\n");
288 /* Do CSE estimation */
289 static bool cseCostEstimation (iCode *ic, iCode *pdic)
291 operand *result = IC_RESULT(ic);
292 sym_link *result_type = operandType(result);
294 return 0; /* disable CSE */
296 /* if it is a pointer then return ok for now */
297 if (IC_RESULT(ic) && IS_PTR(result_type)) return 1;
299 if (ic->op == ADDRESS_OF)
302 /* if bitwise | add & subtract then no since hc08 is pretty good at it
303 so we will cse only if they are local (i.e. both ic & pdic belong to
304 the same basic block */
305 if (IS_BITWISE_OP(ic) || ic->op == '+' || ic->op == '-') {
306 /* then if they are the same Basic block then ok */
307 if (ic->eBBlockNum == pdic->eBBlockNum) return 1;
311 /* for others it is cheaper to do the cse */
316 /* Indicate which extended bit operations this port supports */
318 hasExtBitOp (int op, int size)
323 || (op == SWAP && size <= 2)
330 /* Indicate the expense of an access to an output storage class */
332 oclsExpense (struct memmap *oclass)
334 /* The hc08's addressing modes allow access to all storage classes */
335 /* inexpensively (<=0) */
337 if (IN_DIRSPACE (oclass)) /* direct addressing mode is fastest */
339 if (IN_FARSPACE (oclass)) /* extended addressing mode is almost at fast */
341 if (oclass == istack) /* stack is the slowest, but still faster than */
342 return 0; /* trying to copy to a temp location elsewhere */
344 return 0; /* anything we missed */
348 /*----------------------------------------------------------------------*/
349 /* hc08_dwarfRegNum - return the DWARF register number for a register. */
350 /* These are defined for the HC08 in "Motorola 8- and 16-bit Embedded */
351 /* Application Binary Interface (M8/16EABI)" */
352 /*----------------------------------------------------------------------*/
354 hc08_dwarfRegNum (regs * reg)
358 case A_IDX: return 0;
359 case H_IDX: return 1;
360 case X_IDX: return 2;
361 case CND_IDX: return 17;
362 case SP_IDX: return 15;
369 /** $1 is always the basename.
370 $2 is always the output file.
372 $l is the list of extra options that should be there somewhere...
373 MUST be terminated with a NULL.
375 static const char *_linkCmd[] =
377 "link-hc08", "-nf", "\"$1\"", NULL
380 /* $3 is replaced by assembler.debug_opts resp. port->assembler.plain_opts */
381 static const char *_asmCmd[] =
383 "as-hc08", "$l", "$3", "\"$1.asm\"", NULL
391 "HC08", /* Target name */
392 NULL, /* Processor name */
395 FALSE, /* Emit glue around main */
396 MODEL_SMALL | MODEL_LARGE,
402 "-plosgffc", /* Options with debug */
403 "-plosgff", /* Options without debug */
406 NULL /* no do_assemble function */
419 /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
420 1, 2, 2, 4, 2, 2, 2, 1, 4, 4
422 /* tags for generic pointers */
423 { 0x00, 0x40, 0x60, 0x80 }, /* far, near, xstack, code */
439 "XISEG", // initialized xdata
440 "XINIT", // a code copy of xiseg
441 "CONST (CODE)", // const_name - const data (code or not)
446 { _hc08_genExtraAreas,
449 -1, /* direction (-1 = stack grows down) */
450 0, /* bank_overhead (switch between register banks) */
451 4, /* isr_overhead */
452 2, /* call_overhead */
453 0, /* reent_overhead */
454 0 /* banked_overhead (switch between code banks) */
456 /* hc08 has an 8 bit mul */
461 hc08_emitDebuggerSymbol,
475 2, /* sizeofElement */
476 {8,16,32}, /* sizeofMatchJump[] */
477 {8,16,32}, /* sizeofRangeCompare[] */
478 5, /* sizeofSubtract */
479 10, /* sizeofDispatch */
486 _hc08_finaliseOptions,
487 _hc08_setDefaultOptions,
488 hc08_assignRegisters,
491 _hc08_genAssemblerPreamble,
492 _hc08_genAssemblerEnd, /* no genAssemblerEnd */
495 NULL, /* genInitStartup */
498 NULL, /* process_pragma */
499 NULL, /* getMangledFunctionName */
500 NULL, /* hasNativeMulFor */
501 hasExtBitOp, /* hasExtBitOp */
502 oclsExpense, /* oclsExpense */
503 TRUE, /* use_dw_for_init */
504 FALSE, /* little endian */
507 1, /* transform <= to ! > */
508 1, /* transform >= to ! < */
509 1, /* transform != to !(a == b) */
511 FALSE, /* No array initializer support. */
513 NULL, /* no builtin functions */
514 GPOINTER, /* treat unqualified pointers as "generic" pointers */
515 1, /* reset labelKey to 1 */
516 1, /* globals & local static allowed */