1 /*-------------------------------------------------------------------------
2 main.h - hc08 specific general function
3
4 Copyright (C) 2003, Erik Petrich
5
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 -------------------------------------------------------------------------*/
20 /*
21 Note that mlh prepended _hc08_ on the static functions. Makes
22 it easier to set a breakpoint using the debugger.
23 */
24 #include "common.h"
25 #include "hc08.h"
26 #include "main.h"
27 #include "ralloc.h"
28 #include "gen.h"
29 #include "dbuf_string.h"
30
31 extern char * iComments2;
32 extern DEBUGFILE dwarf2DebugFile;
33 extern int dwarf2FinalizeFile(FILE *);
34
35 static char _hc08_defaultRules[] =
36 {
37 #include "peeph.rul"
38 };
39
40 static char _s08_defaultRules[] =
41 {
42 #include "peeph.rul"
43 };
44
45 HC08_OPTS hc08_opts;
46
47 /* list of key words used by msc51 */
48 static char *_hc08_keywords[] =
49 {
50 "at",
51 //"bit",
52 "code",
53 "critical",
54 "data",
55 "far",
56 //"idata",
57 "interrupt",
58 "near",
59 //"pdata",
60 "reentrant",
61 //"sfr",
62 //"sbit",
63 //"using",
64 "xdata",
65 "_data",
66 "_code",
67 "_generic",
68 "_near",
69 "_xdata",
70 //"_pdata",
71 //"_idata",
72 "_naked",
73 "_overlay",
74 NULL
75 };
76
77
78 void hc08_assignRegisters (ebbIndex *);
79
80 static int regParmFlg = 0; /* determine if we can register a parameter */
81
82 static void
_hc08_init(void)83 _hc08_init (void)
84 {
85 hc08_opts.sub = SUB_HC08;
86 asm_addTree (&asm_asxxxx_mapping);
87 }
88
89 static void
_s08_init(void)90 _s08_init (void)
91 {
92 hc08_opts.sub = SUB_S08;
93 asm_addTree (&asm_asxxxx_mapping);
94 }
95
96 static void
_hc08_reset_regparm(struct sym_link * funcType)97 _hc08_reset_regparm (struct sym_link *funcType)
98 {
99 regParmFlg = 0;
100 }
101
102 static int
_hc08_regparm(sym_link * l,bool reentrant)103 _hc08_regparm (sym_link * l, bool reentrant)
104 {
105 int size = getSize(l);
106
107 /* If they fit completely, the first two bytes of parameters can go */
108 /* into A and X, otherwise, they go on the stack. Examples: */
109 /* foo(char p1) A <- p1 */
110 /* foo(char p1, char p2) A <- p1, X <- p2 */
111 /* foo(char p1, char p2, char p3) A <- p1, X <- p2, stack <- p3 */
112 /* foo(int p1) XA <- p1 */
113 /* foo(long p1) stack <- p1 */
114 /* foo(char p1, int p2) A <- p1, stack <- p2 */
115 /* foo(int p1, char p2) XA <- p1, stack <- p2 */
116
117 if (regParmFlg>=2)
118 return 0;
119
120 if ((regParmFlg+size)>2)
121 {
122 regParmFlg = 2;
123 return 0;
124 }
125
126 regParmFlg += size;
127 return 1+regParmFlg-size;
128 }
129
130 static bool
_hc08_parseOptions(int * pargc,char ** argv,int * i)131 _hc08_parseOptions (int *pargc, char **argv, int *i)
132 {
133 if (!strcmp (argv[*i], "--out-fmt-elf"))
134 {
135 options.out_fmt = 'E';
136 debugFile = &dwarf2DebugFile;
137 return TRUE;
138 }
139
140 if (!strcmp (argv[*i], "--oldralloc"))
141 {
142 options.oldralloc = TRUE;
143 return TRUE;
144 }
145
146 return FALSE;
147 }
148
149 #define OPTION_SMALL_MODEL "--model-small"
150 #define OPTION_LARGE_MODEL "--model-large"
151
152 static OPTION _hc08_options[] =
153 {
154 {0, OPTION_SMALL_MODEL, NULL, "8-bit address space for data"},
155 {0, OPTION_LARGE_MODEL, NULL, "16-bit address space for data (default)"},
156 {0, "--out-fmt-elf", NULL, "Output executable in ELF format" },
157 {0, "--oldralloc", NULL, "Use old register allocator"},
158 {0, NULL }
159 };
160
161 static void
_hc08_finaliseOptions(void)162 _hc08_finaliseOptions (void)
163 {
164 if (options.noXinitOpt)
165 port->genXINIT = 0;
166
167 if (options.model == MODEL_LARGE) {
168 port->mem.default_local_map = xdata;
169 port->mem.default_globl_map = xdata;
170 }
171 else
172 {
173 port->mem.default_local_map = data;
174 port->mem.default_globl_map = data;
175 }
176
177 istack->ptrType = FPOINTER;
178 }
179
180 static void
_hc08_setDefaultOptions(void)181 _hc08_setDefaultOptions (void)
182 {
183 options.code_loc = 0x8000;
184 options.data_loc = 0x80;
185 options.xdata_loc = 0; /* 0 means immediately following data */
186 options.stack_loc = 0x7fff;
187 options.out_fmt = 's'; /* use motorola S19 output */
188
189 options.omitFramePtr = 1; /* no frame pointer (we use SP */
190 /* offsets instead) */
191 }
192
193 static const char *
_hc08_getRegName(const struct reg_info * reg)194 _hc08_getRegName (const struct reg_info *reg)
195 {
196 if (reg)
197 return reg->name;
198 return "err";
199 }
200
201 static void
_hc08_genAssemblerPreamble(FILE * of)202 _hc08_genAssemblerPreamble (FILE * of)
203 {
204 int i;
205 int needOrg = 1;
206 symbol *mainExists=newSymbol("main", 0);
207 mainExists->block=0;
208
209 fprintf (of, "\t.area %s\n",HOME_NAME);
210 fprintf (of, "\t.area GSINIT0 (CODE)\n");
211 fprintf (of, "\t.area %s\n",port->mem.static_name);
212 fprintf (of, "\t.area %s\n",port->mem.post_static_name);
213 fprintf (of, "\t.area %s\n",CODE_NAME);
214 fprintf (of, "\t.area %s\n",port->mem.xinit_name);
215 fprintf (of, "\t.area %s\n",port->mem.const_name);
216 fprintf (of, "\t.area %s\n",port->mem.data_name);
217 fprintf (of, "\t.area %s\n",port->mem.overlay_name);
218 fprintf (of, "\t.area %s\n",port->mem.xdata_name);
219 fprintf (of, "\t.area %s\n",port->mem.xidata_name);
220
221 if ((mainExists=findSymWithLevel(SymbolTab, mainExists)))
222 {
223 // generate interrupt vector table
224 fprintf (of, "\t.area\tCODEIVT (ABS)\n");
225
226 for (i=maxInterrupts;i>0;i--)
227 {
228 if (interrupts[i])
229 {
230 if (needOrg)
231 {
232 fprintf (of, "\t.org\t0x%04x\n", (0xfffe - (i * 2)));
233 needOrg = 0;
234 }
235 fprintf (of, "\t.dw\t%s\n", interrupts[i]->rname);
236 }
237 else
238 needOrg = 1;
239 }
240 if (needOrg)
241 fprintf (of, "\t.org\t0xfffe\n");
242 fprintf (of, "\t.dw\t%s", "__sdcc_gs_init_startup\n\n");
243
244 fprintf (of, "\t.area GSINIT0\n");
245 fprintf (of, "__sdcc_gs_init_startup:\n");
246 if (options.stack_loc)
247 {
248 fprintf (of, "\tldhx\t#0x%04x\n", options.stack_loc+1);
249 fprintf (of, "\ttxs\n");
250 }
251 else
252 fprintf (of, "\trsp\n");
253 fprintf (of, "\tjsr\t__sdcc_external_startup\n");
254 fprintf (of, "\tbeq\t__sdcc_init_data\n");
255 fprintf (of, "\tjmp\t__sdcc_program_startup\n");
256 fprintf (of, "__sdcc_init_data:\n");
257
258 fprintf (of, "; _hc08_genXINIT() start\n");
259 fprintf (of, " ldhx #0\n");
260 fprintf (of, "00001$:\n");
261 fprintf (of, " cphx #l_XINIT\n");
262 fprintf (of, " beq 00002$\n");
263 fprintf (of, " lda s_XINIT,x\n");
264 fprintf (of, " sta s_XISEG,x\n");
265 fprintf (of, " aix #1\n");
266 fprintf (of, " bra 00001$\n");
267 fprintf (of, "00002$:\n");
268 fprintf (of, "; _hc08_genXINIT() end\n");
269
270 fprintf (of, "\t.area GSFINAL\n");
271 fprintf (of, "\tjmp\t__sdcc_program_startup\n\n");
272
273 fprintf (of, "\t.area CSEG\n");
274 fprintf (of, "__sdcc_program_startup:\n");
275 fprintf (of, "\tjsr\t_main\n");
276 fprintf (of, "\tbra\t.\n");
277
278 }
279 }
280
281 static void
_hc08_genAssemblerEnd(FILE * of)282 _hc08_genAssemblerEnd (FILE * of)
283 {
284 if (options.out_fmt == 'E' && options.debug)
285 {
286 dwarf2FinalizeFile (of);
287 }
288 }
289
290 static void
_hc08_genExtraAreas(FILE * asmFile,bool mainExists)291 _hc08_genExtraAreas (FILE * asmFile, bool mainExists)
292 {
293 fprintf (asmFile, "%s", iComments2);
294 fprintf (asmFile, "; extended address mode data\n");
295 fprintf (asmFile, "%s", iComments2);
296 dbuf_write_and_destroy (&xdata->oBuf, asmFile);
297 }
298
299 /* Generate interrupt vector table. */
300 static int
_hc08_genIVT(struct dbuf_s * oBuf,symbol ** interrupts,int maxInterrupts)301 _hc08_genIVT (struct dbuf_s * oBuf, symbol ** interrupts, int maxInterrupts)
302 {
303 int i;
304
305 dbuf_printf (oBuf, "\t.area\tCODEIVT (ABS)\n");
306 dbuf_printf (oBuf, "\t.org\t0x%04x\n",
307 (0xfffe - (maxInterrupts * 2)));
308
309 for (i=maxInterrupts;i>0;i--)
310 {
311 if (interrupts[i])
312 dbuf_printf (oBuf, "\t.dw\t%s\n", interrupts[i]->rname);
313 else
314 dbuf_printf (oBuf, "\t.dw\t0xffff\n");
315 }
316 dbuf_printf (oBuf, "\t.dw\t%s", "__sdcc_gs_init_startup\n");
317
318 return TRUE;
319 }
320
321 /* Generate code to copy XINIT to XISEG */
_hc08_genXINIT(FILE * of)322 static void _hc08_genXINIT (FILE * of) {
323 fprintf (of, "; _hc08_genXINIT() start\n");
324 fprintf (of, "; _hc08_genXINIT() end\n");
325 }
326
327
328 /* Do CSE estimation */
cseCostEstimation(iCode * ic,iCode * pdic)329 static bool cseCostEstimation (iCode *ic, iCode *pdic)
330 {
331 operand *result = IC_RESULT(ic);
332 sym_link *result_type = operandType(result);
333
334 /* if it is a pointer then return ok for now */
335 if (IC_RESULT(ic) && IS_PTR(result_type)) return 1;
336
337 if (ic->op == ADDRESS_OF)
338 return 0;
339
340 /* if bitwise | add & subtract then no since hc08 is pretty good at it
341 so we will cse only if they are local (i.e. both ic & pdic belong to
342 the same basic block */
343 if (IS_BITWISE_OP(ic) || ic->op == '+' || ic->op == '-') {
344 /* then if they are the same Basic block then ok */
345 if (ic->eBBlockNum == pdic->eBBlockNum) return 1;
346 else return 0;
347 }
348
349 /* for others it is cheaper to do the cse */
350 return 1;
351 }
352
353 /* Indicate which extended bit operations this port supports */
354 static bool
hasExtBitOp(int op,int size)355 hasExtBitOp (int op, int size)
356 {
357 if (op == RRC
358 || op == RLC
359 || (op == SWAP && size <= 2)
360 || op == GETABIT
361 || op == GETBYTE
362 || op == GETWORD
363 )
364 return TRUE;
365 else
366 return FALSE;
367 }
368
369 /* Indicate the expense of an access to an output storage class */
370 static int
oclsExpense(struct memmap * oclass)371 oclsExpense (struct memmap *oclass)
372 {
373 /* The hc08's addressing modes allow access to all storage classes */
374 /* inexpensively (<=0) */
375
376 if (IN_DIRSPACE (oclass)) /* direct addressing mode is fastest */
377 return -2;
378 if (IN_FARSPACE (oclass)) /* extended addressing mode is almost at fast */
379 return -1;
380 if (oclass == istack) /* stack is the slowest, but still faster than */
381 return 0; /* trying to copy to a temp location elsewhere */
382
383 return 0; /* anything we missed */
384 }
385
386 /*----------------------------------------------------------------------*/
387 /* hc08_dwarfRegNum - return the DWARF register number for a register. */
388 /* These are defined for the HC08 in "Motorola 8- and 16-bit Embedded */
389 /* Application Binary Interface (M8/16EABI)" */
390 /*----------------------------------------------------------------------*/
391 static int
hc08_dwarfRegNum(const struct reg_info * reg)392 hc08_dwarfRegNum (const struct reg_info *reg)
393 {
394 switch (reg->rIdx)
395 {
396 case A_IDX: return 0;
397 case H_IDX: return 1;
398 case X_IDX: return 2;
399 case CND_IDX: return 17;
400 case SP_IDX: return 15;
401 }
402 return -1;
403 }
404
405 static bool
_hasNativeMulFor(iCode * ic,sym_link * left,sym_link * right)406 _hasNativeMulFor (iCode *ic, sym_link *left, sym_link *right)
407 {
408 return getSize (left) == 1 && getSize (right) == 1;
409 }
410
411 typedef struct asmLineNode
412 {
413 int size;
414 }
415 asmLineNode;
416
417 static asmLineNode *
newAsmLineNode(void)418 newAsmLineNode (void)
419 {
420 asmLineNode *aln;
421
422 aln = Safe_alloc ( sizeof (asmLineNode));
423 aln->size = 0;
424
425 return aln;
426 }
427
428 typedef struct hc08opcodedata
429 {
430 char name[6];
431 char adrmode;
432 /* info for registers used and/or modified by an instruction will be added here */
433 }
434 hc08opcodedata;
435
436 #define HC08OP_STD 1
437 #define HC08OP_RMW 2
438 #define HC08OP_INH 3
439 #define HC08OP_IM1 4
440 #define HC08OP_BR 5
441 #define HC08OP_BTB 6
442 #define HC08OP_BSC 7
443 #define HC08OP_MOV 8
444 #define HC08OP_CBEQ 9
445 #define HC08OP_CPHX 10
446 #define HC08OP_LDHX 11
447 #define HC08OP_STHX 12
448 #define HC08OP_DBNZ 13
449
450 /* These must be kept sorted by opcode name */
451 static hc08opcodedata hc08opcodeDataTable[] =
452 {
453 {".db", HC08OP_INH}, /* used by the code generator only in the jump table */
454 {"adc", HC08OP_STD},
455 {"add", HC08OP_STD},
456 {"ais", HC08OP_IM1},
457 {"aix", HC08OP_IM1},
458 {"and", HC08OP_STD},
459 {"asl", HC08OP_RMW},
460 {"asla", HC08OP_INH},
461 {"aslx", HC08OP_INH},
462 {"asr", HC08OP_RMW},
463 {"asra", HC08OP_INH},
464 {"asrx", HC08OP_INH},
465 {"bcc", HC08OP_BR,},
466 {"bclr", HC08OP_BSC},
467 {"bcs", HC08OP_BR},
468 {"beq", HC08OP_BR},
469 {"bge", HC08OP_BR},
470 {"bgnd", HC08OP_INH},
471 {"bgt", HC08OP_BR},
472 {"bhcc", HC08OP_BR},
473 {"bhcs", HC08OP_BR},
474 {"bhi", HC08OP_BR},
475 {"bhs", HC08OP_BR},
476 {"bih", HC08OP_BR},
477 {"bil", HC08OP_BR},
478 {"bit", HC08OP_STD},
479 {"ble", HC08OP_BR},
480 {"blo", HC08OP_BR},
481 {"bls", HC08OP_BR},
482 {"blt", HC08OP_BR},
483 {"bmc", HC08OP_BR},
484 {"bmi", HC08OP_BR},
485 {"bms", HC08OP_BR},
486 {"bne", HC08OP_BR},
487 {"bpl", HC08OP_BR},
488 {"bra", HC08OP_BR},
489 {"brclr", HC08OP_BTB},
490 {"brn", HC08OP_BR},
491 {"brset", HC08OP_BTB},
492 {"bset", HC08OP_BSC},
493 {"bsr", HC08OP_BR},
494 {"cbeq", HC08OP_CBEQ},
495 {"cbeqa", HC08OP_CBEQ},
496 {"cbeqx", HC08OP_CBEQ},
497 {"clc", HC08OP_INH},
498 {"cli", HC08OP_INH},
499 {"clr", HC08OP_RMW},
500 {"clra", HC08OP_INH},
501 {"clrh", HC08OP_INH},
502 {"clrx", HC08OP_INH},
503 {"cmp", HC08OP_STD},
504 {"com", HC08OP_RMW},
505 {"coma", HC08OP_INH},
506 {"comx", HC08OP_INH},
507 {"cphx", HC08OP_CPHX},
508 {"cpx", HC08OP_STD},
509 {"daa", HC08OP_INH},
510 {"dbnz", HC08OP_DBNZ},
511 {"dbnza", HC08OP_BR},
512 {"dbnzx", HC08OP_BR},
513 {"dec", HC08OP_RMW},
514 {"deca", HC08OP_INH},
515 {"decx", HC08OP_INH},
516 {"div", HC08OP_INH},
517 {"eor", HC08OP_STD},
518 {"inc", HC08OP_RMW},
519 {"inca", HC08OP_INH},
520 {"incx", HC08OP_INH},
521 {"jmp", HC08OP_STD},
522 {"jsr", HC08OP_STD},
523 {"lda", HC08OP_STD},
524 {"ldhx", HC08OP_LDHX},
525 {"ldx", HC08OP_STD},
526 {"lsl", HC08OP_RMW},
527 {"lsla", HC08OP_INH},
528 {"lslx", HC08OP_INH},
529 {"lsr", HC08OP_RMW},
530 {"lsra", HC08OP_INH},
531 {"lsrx", HC08OP_INH},
532 {"mov", HC08OP_MOV},
533 {"mul", HC08OP_INH},
534 {"neg", HC08OP_RMW},
535 {"nega", HC08OP_INH},
536 {"negx", HC08OP_INH},
537 {"nop", HC08OP_INH},
538 {"nsa", HC08OP_INH},
539 {"ora", HC08OP_STD},
540 {"psha", HC08OP_INH},
541 {"pshh", HC08OP_INH},
542 {"pshx", HC08OP_INH},
543 {"pula", HC08OP_INH},
544 {"pulh", HC08OP_INH},
545 {"pulx", HC08OP_INH},
546 {"rol", HC08OP_RMW},
547 {"rola", HC08OP_INH},
548 {"rolx", HC08OP_INH},
549 {"ror", HC08OP_RMW},
550 {"rora", HC08OP_INH},
551 {"rorx", HC08OP_INH},
552 {"rsp", HC08OP_INH},
553 {"rti", HC08OP_INH},
554 {"rts", HC08OP_INH},
555 {"sbc", HC08OP_STD},
556 {"sec", HC08OP_INH},
557 {"sei", HC08OP_INH},
558 {"sta", HC08OP_STD},
559 {"sthx", HC08OP_STHX},
560 {"stop", HC08OP_INH},
561 {"stx", HC08OP_STD},
562 {"sub", HC08OP_STD},
563 {"swi", HC08OP_INH},
564 {"tap", HC08OP_INH},
565 {"tax", HC08OP_INH},
566 {"tpa", HC08OP_INH},
567 {"tst", HC08OP_RMW},
568 {"tsta", HC08OP_INH},
569 {"tstx", HC08OP_INH},
570 {"tsx", HC08OP_INH},
571 {"txa", HC08OP_INH},
572 {"txs", HC08OP_INH},
573 {"wait", HC08OP_INH}
574 };
575
576 static int
hc08_opcodeCompare(const void * key,const void * member)577 hc08_opcodeCompare (const void *key, const void *member)
578 {
579 return strcmp((const char *)key, ((hc08opcodedata *)member)->name);
580 }
581
582 /*--------------------------------------------------------------------*/
583 /* Given an instruction and its first two operands, compute the */
584 /* instruction size. There are a few cases where it's too complicated */
585 /* to distinguish between an 8-bit offset and 16-bit offset; in these */
586 /* cases we conservatively assume the 16-bit offset size. */
587 /*--------------------------------------------------------------------*/
588 static int
hc08_instructionSize(const char * inst,const char * op1,const char * op2)589 hc08_instructionSize(const char *inst, const char *op1, const char *op2)
590 {
591 hc08opcodedata *opcode;
592 int size;
593 long offset;
594 char * endnum = NULL;
595
596 opcode = bsearch (inst, hc08opcodeDataTable,
597 sizeof(hc08opcodeDataTable)/sizeof(hc08opcodedata),
598 sizeof(hc08opcodedata), hc08_opcodeCompare);
599
600 if (!opcode)
601 return 999;
602 switch (opcode->adrmode)
603 {
604 case HC08OP_INH: /* Inherent addressing mode */
605 return 1;
606
607 case HC08OP_BSC: /* Bit set/clear direct addressing mode */
608 case HC08OP_BR: /* Branch (1 byte signed offset) */
609 case HC08OP_IM1: /* 1 byte immediate addressing mode */
610 return 2;
611
612 case HC08OP_BTB: /* Bit test direct addressing mode and branch */
613 return 3;
614
615 case HC08OP_RMW: /* read/modify/write instructions */
616 if (!op2[0]) /* if not ,x or ,sp must be direct addressing mode */
617 return 2;
618 if (!op1[0]) /* if ,x with no offset */
619 return 1;
620 if (op2[0] == 'x') /* if ,x with offset */
621 return 2;
622 return 3; /* Otherwise, must be ,sp with offset */
623
624 case HC08OP_STD: /* standard instruction */
625 if (!op2[0])
626 {
627 if (op1[0] == '#') /* Immediate addressing mode */
628 return 2;
629 if (op1[0] == '*') /* Direct addressing mode */
630 return 2;
631 return 3; /* Otherwise, must be extended addressing mode */
632 }
633 else
634 {
635 if (!op1[0]) /* if ,x with no offset */
636 return 1;
637 size = 2;
638 if (op2[0] == 's')
639 size++;
640 offset = strtol (op1, &endnum, 0) & 0xffff;
641 if (endnum && *endnum)
642 size++;
643 else if (offset > 0xff)
644 size++;
645 return size;
646 }
647 case HC08OP_MOV:
648 if (op2[0] == 'x')
649 return 2;
650 return 3;
651 case HC08OP_CBEQ:
652 if (op2[0] == 'x' && !op1[0])
653 return 2; /* cbeq ,x+,rel */
654 if (op2[0] == 's')
655 return 4; /* cbeq oprx8,sp,rel */
656 return 3;
657 case HC08OP_CPHX:
658 if (op1[0] == '*')
659 return 2;
660 return 3;
661 case HC08OP_DBNZ:
662 if (!op2[0])
663 return 2;
664 if (!op1[0] && op2[0] == 'x')
665 return 2;
666 if (op2[0] == 's')
667 return 4;
668 return 3;
669 case HC08OP_LDHX:
670 case HC08OP_STHX:
671 if (op1[0] == '*')
672 return 2;
673 if (!op1[0] && op2[0] == 'x')
674 return 2;
675 if (op2[0] == 's' || op1[0] == '#' || !op2[0])
676 return 3;
677 size = 3;
678 offset = strtol (op1, &endnum, 0) & 0xffff;
679 if (endnum && *endnum)
680 size++;
681 else if (offset > 0xff)
682 size++;
683 return size;
684 default:
685 return 4;
686 }
687 }
688
689
690 static asmLineNode *
hc08_asmLineNodeFromLineNode(lineNode * ln)691 hc08_asmLineNodeFromLineNode (lineNode *ln)
692 {
693 asmLineNode *aln = newAsmLineNode();
694 char *op, op1[256], op2[256];
695 int opsize;
696 const char *p;
697 char inst[8];
698
699 p = ln->line;
700
701 while (*p && isspace(*p)) p++;
702 for (op = inst, opsize=1; *p; p++)
703 {
704 if (isspace(*p) || *p == ';' || *p == ':' || *p == '=')
705 break;
706 else
707 if (opsize < sizeof(inst))
708 *op++ = tolower(*p), opsize++;
709 }
710 *op = '\0';
711
712 if (*p == ';' || *p == ':' || *p == '=')
713 return aln;
714
715 while (*p && isspace(*p)) p++;
716 if (*p == '=')
717 return aln;
718
719 for (op = op1, opsize=1; *p && *p != ','; p++)
720 {
721 if (!isspace(*p) && opsize < sizeof(op1))
722 *op++ = tolower(*p), opsize++;
723 }
724 *op = '\0';
725
726 if (*p == ',') p++;
727 for (op = op2, opsize=1; *p && *p != ','; p++)
728 {
729 if (!isspace(*p) && opsize < sizeof(op2))
730 *op++ = tolower(*p), opsize++;
731 }
732 *op = '\0';
733
734 aln->size = hc08_instructionSize(inst, op1, op2);
735
736 return aln;
737 }
738
739 static int
hc08_getInstructionSize(lineNode * line)740 hc08_getInstructionSize (lineNode *line)
741 {
742 if (!line->aln)
743 line->aln = (asmLineNodeBase *) hc08_asmLineNodeFromLineNode (line);
744
745 return line->aln->size;
746 }
747
748 /** $1 is always the basename.
749 $2 is always the output file.
750 $3 varies
751 $l is the list of extra options that should be there somewhere...
752 MUST be terminated with a NULL.
753 */
754 static const char *_linkCmd[] =
755 {
756 "sdld6808", "-nf", "$1", NULL
757 };
758
759 /* $3 is replaced by assembler.debug_opts resp. port->assembler.plain_opts */
760 static const char *_asmCmd[] =
761 {
762 "sdas6808", "$l", "$3", "$2", "$1.asm", NULL
763 };
764
765 static const char * const _libs_hc08[] = { "hc08", NULL, };
766 static const char * const _libs_s08[] = { "s08", NULL, };
767
768 /* Globals */
769 PORT hc08_port =
770 {
771 TARGET_ID_HC08,
772 "hc08",
773 "HC08", /* Target name */
774 NULL, /* Processor name */
775 {
776 glue,
777 FALSE, /* Emit glue around main */
778 MODEL_SMALL | MODEL_LARGE,
779 MODEL_LARGE,
780 NULL, /* model == target */
781 },
782 {
783 _asmCmd,
784 NULL,
785 "-plosgffwy", /* Options with debug */
786 "-plosgffw", /* Options without debug */
787 0,
788 ".asm",
789 NULL /* no do_assemble function */
790 },
791 { /* Linker */
792 _linkCmd,
793 NULL,
794 NULL,
795 ".rel",
796 1,
797 NULL, /* crt */
798 _libs_hc08, /* libs */
799 },
800 { /* Peephole optimizer */
801 _hc08_defaultRules,
802 hc08_getInstructionSize,
803 },
804 {
805 /* Sizes: char, short, int, long, long long, near ptr, far ptr, gptr, func ptr, banked func ptr, bit, float */
806 1, 2, 2, 4, 8, 2, 2, 2, 2, 0, 1, 4
807 },
808 /* tags for generic pointers */
809 { 0x00, 0x00, 0x00, 0x00 }, /* far, near, xstack, code */
810 {
811 "XSEG",
812 "STACK",
813 "CSEG (CODE)",
814 "DSEG (PAG)",
815 NULL, /* "ISEG" */
816 NULL, /* "PSEG" */
817 "XSEG",
818 NULL, /* "BSEG" */
819 "RSEG (ABS)",
820 "GSINIT (CODE)",
821 "OSEG (PAG, OVR)",
822 "GSFINAL (CODE)",
823 "HOME (CODE)",
824 "XISEG", // initialized xdata
825 "XINIT (CODE)", // a code copy of xiseg
826 "CONST (CODE)", // const_name - const data (code or not)
827 "CABS (ABS,CODE)", // cabs_name - const absolute data (code or not)
828 "XABS (ABS)", // xabs_name - absolute xdata
829 "IABS (ABS)", // iabs_name - absolute data
830 NULL, // name of segment for initialized variables
831 NULL, // name of segment for copies of initialized variables in code space
832 NULL,
833 NULL,
834 1,
835 1 // No fancy alignments supported.
836 },
837 { _hc08_genExtraAreas,
838 NULL },
839 {
840 -1, /* direction (-1 = stack grows down) */
841 0, /* bank_overhead (switch between register banks) */
842 4, /* isr_overhead */
843 2, /* call_overhead */
844 0, /* reent_overhead */
845 0, /* banked_overhead (switch between code banks) */
846 1 /* sp is offset by 1 from last item pushed */
847 },
848 {
849 5, FALSE
850 },
851 {
852 hc08_emitDebuggerSymbol,
853 {
854 hc08_dwarfRegNum,
855 NULL,
856 NULL,
857 4, /* addressSize */
858 14, /* regNumRet */
859 15, /* regNumSP */
860 -1, /* regNumBP */
861 1, /* offsetSP */
862 },
863 },
864 {
865 256, /* maxCount */
866 2, /* sizeofElement */
867 {8,16,32}, /* sizeofMatchJump[] */
868 {8,16,32}, /* sizeofRangeCompare[] */
869 5, /* sizeofSubtract */
870 10, /* sizeofDispatch */
871 },
872 "_",
873 _hc08_init,
874 _hc08_parseOptions,
875 _hc08_options,
876 NULL,
877 _hc08_finaliseOptions,
878 _hc08_setDefaultOptions,
879 hc08_assignRegisters,
880 _hc08_getRegName,
881 0,
882 NULL,
883 _hc08_keywords,
884 _hc08_genAssemblerPreamble,
885 _hc08_genAssemblerEnd, /* no genAssemblerEnd */
886 _hc08_genIVT,
887 _hc08_genXINIT,
888 NULL, /* genInitStartup */
889 _hc08_reset_regparm,
890 _hc08_regparm,
891 NULL, /* process_pragma */
892 NULL, /* getMangledFunctionName */
893 _hasNativeMulFor, /* hasNativeMulFor */
894 hasExtBitOp, /* hasExtBitOp */
895 oclsExpense, /* oclsExpense */
896 TRUE, /* use_dw_for_init */
897 FALSE, /* little_endian */
898 0, /* leave lt */
899 0, /* leave gt */
900 1, /* transform <= to ! > */
901 1, /* transform >= to ! < */
902 1, /* transform != to !(a == b) */
903 0, /* leave == */
904 FALSE, /* No array initializer support. */
905 cseCostEstimation,
906 NULL, /* no builtin functions */
907 GPOINTER, /* treat unqualified pointers as "generic" pointers */
908 1, /* reset labelKey to 1 */
909 1, /* globals & local statics allowed */
910 3, /* Number of registers handled in the tree-decomposition-based register allocator in SDCCralloc.hpp */
911 PORT_MAGIC
912 };
913
914 PORT s08_port =
915 {
916 TARGET_ID_S08,
917 "s08",
918 "S08", /* Target name */
919 NULL, /* Processor name */
920 {
921 glue,
922 FALSE, /* Emit glue around main */
923 MODEL_SMALL | MODEL_LARGE,
924 MODEL_LARGE,
925 NULL, /* model == target */
926 },
927 {
928 _asmCmd,
929 NULL,
930 "-plosgffwy", /* Options with debug */
931 "-plosgffw", /* Options without debug */
932 0,
933 ".asm",
934 NULL /* no do_assemble function */
935 },
936 { /* Linker */
937 _linkCmd,
938 NULL,
939 NULL,
940 ".rel",
941 1,
942 NULL, /* crt */
943 _libs_s08, /* libs */
944 },
945 { /* Peephole optimizer */
946 _s08_defaultRules,
947 hc08_getInstructionSize,
948 },
949 {
950 /* Sizes: char, short, int, long, long long, near ptr, far ptr, gptr, func ptr, banked func ptr, bit, float */
951 1, 2, 2, 4, 8, 2, 2, 2, 2, 0, 1, 4
952 },
953 /* tags for generic pointers */
954 { 0x00, 0x00, 0x00, 0x00 }, /* far, near, xstack, code */
955 {
956 "XSEG",
957 "STACK",
958 "CSEG (CODE)",
959 "DSEG (PAG)",
960 NULL, /* "ISEG" */
961 NULL, /* "PSEG" */
962 "XSEG",
963 NULL, /* "BSEG" */
964 "RSEG (ABS)",
965 "GSINIT (CODE)",
966 "OSEG (PAG, OVR)",
967 "GSFINAL (CODE)",
968 "HOME (CODE)",
969 "XISEG", // initialized xdata
970 "XINIT (CODE)", // a code copy of xiseg
971 "CONST (CODE)", // const_name - const data (code or not)
972 "CABS (ABS,CODE)", // cabs_name - const absolute data (code or not)
973 "XABS (ABS)", // xabs_name - absolute xdata
974 "IABS (ABS)", // iabs_name - absolute data
975 NULL, // name of segment for initialized variables
976 NULL, // name of segment for copies of initialized variables in code space
977 NULL,
978 NULL,
979 1,
980 1 // No fancy alignments supported.
981 },
982 { _hc08_genExtraAreas,
983 NULL },
984 {
985 -1, /* direction (-1 = stack grows down) */
986 0, /* bank_overhead (switch between register banks) */
987 4, /* isr_overhead */
988 2, /* call_overhead */
989 0, /* reent_overhead */
990 0, /* banked_overhead (switch between code banks) */
991 1 /* sp is offset by 1 from last item pushed */
992 },
993 {
994 5, FALSE
995 },
996 {
997 hc08_emitDebuggerSymbol,
998 {
999 hc08_dwarfRegNum,
1000 NULL,
1001 NULL,
1002 4, /* addressSize */
1003 14, /* regNumRet */
1004 15, /* regNumSP */
1005 -1, /* regNumBP */
1006 1, /* offsetSP */
1007 },
1008 },
1009 {
1010 256, /* maxCount */
1011 2, /* sizeofElement */
1012 {8,16,32}, /* sizeofMatchJump[] */
1013 {8,16,32}, /* sizeofRangeCompare[] */
1014 5, /* sizeofSubtract */
1015 10, /* sizeofDispatch */
1016 },
1017 "_",
1018 _s08_init,
1019 _hc08_parseOptions,
1020 _hc08_options,
1021 NULL,
1022 _hc08_finaliseOptions,
1023 _hc08_setDefaultOptions,
1024 hc08_assignRegisters,
1025 _hc08_getRegName,
1026 0,
1027 NULL,
1028 _hc08_keywords,
1029 _hc08_genAssemblerPreamble,
1030 _hc08_genAssemblerEnd, /* no genAssemblerEnd */
1031 _hc08_genIVT,
1032 _hc08_genXINIT,
1033 NULL, /* genInitStartup */
1034 _hc08_reset_regparm,
1035 _hc08_regparm,
1036 NULL, /* process_pragma */
1037 NULL, /* getMangledFunctionName */
1038 _hasNativeMulFor, /* hasNativeMulFor */
1039 hasExtBitOp, /* hasExtBitOp */
1040 oclsExpense, /* oclsExpense */
1041 TRUE, /* use_dw_for_init */
1042 FALSE, /* little_endian */
1043 0, /* leave lt */
1044 0, /* leave gt */
1045 1, /* transform <= to ! > */
1046 1, /* transform >= to ! < */
1047 1, /* transform != to !(a == b) */
1048 0, /* leave == */
1049 FALSE, /* No array initializer support. */
1050 cseCostEstimation,
1051 NULL, /* no builtin functions */
1052 GPOINTER, /* treat unqualified pointers as "generic" pointers */
1053 1, /* reset labelKey to 1 */
1054 1, /* globals & local statics allowed */
1055 3, /* Number of registers handled in the tree-decomposition-based register allocator in SDCCralloc.hpp */
1056 PORT_MAGIC
1057 };
1058
1059