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