1 /*-------------------------------------------------------------------------
3 main.c - pic16 specific general functions.
5 Written by - Scott Dattalo scott@dattalo.com
6 Ported to PIC16 by - Martin Dubuc m.debuc@rogers.com
8 Note that mlh prepended _pic16_ on the static functions. Makes
9 it easier to set a breakpoint using the debugger.
12 This program is free software; you can redistribute it and/or modify it
13 under the terms of the GNU General Public License as published by the
14 Free Software Foundation; either version 2, or (at your option) any
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License for more details.
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 -------------------------------------------------------------------------*/
36 static char _defaultRules[] =
41 /* list of key words used by pic16 */
42 static char *_pic16_keywords[] =
70 extern char *pic16_processor_base_name(void);
72 void pic16_pCodeInitRegisters(void);
74 void pic16_assignRegisters (eBBlock ** ebbs, int count);
76 static int regParmFlg = 0; /* determine if we can register a parameter */
81 asm_addTree (&asm_asxxxx_mapping);
82 pic16_pCodeInitRegisters();
87 _pic16_reset_regparm ()
93 _pic16_regparm (sym_link * l)
95 /* for this processor it is simple
96 can pass only the first parameter in a register */
105 _process_pragma(const char *sz)
107 static const char *WHITE = " \t";
108 char *ptr = strtok((char *)sz, WHITE);
110 if (startsWith (ptr, "memmap"))
117 start = strtok((char *)NULL, WHITE);
118 end = strtok((char *)NULL, WHITE);
119 type = strtok((char *)NULL, WHITE);
120 alias = strtok((char *)NULL, WHITE);
122 if (start != (char *)NULL
123 && end != (char *)NULL
124 && type != (char *)NULL) {
125 value *startVal = constVal(start);
126 value *endVal = constVal(end);
130 if (alias == (char *)NULL) {
131 aliasVal = constVal(0);
133 aliasVal = constVal(alias);
136 r.start_address = (int)floatFromVal(startVal);
137 r.end_address = (int)floatFromVal(endVal);
138 r.alias = (int)floatFromVal(aliasVal);
139 r.bank = (r.start_address >> 7) & 0xf;
141 if (strcmp(type, "RAM") == 0) {
142 pic16_addMemRange(&r, 0);
143 } else if (strcmp(type, "SFR") == 0) {
144 pic16_addMemRange(&r, 1);
151 } else if (startsWith (ptr, "maxram")) {
152 char *maxRAM = strtok((char *)NULL, WHITE);
154 if (maxRAM != (char *)NULL) {
158 maxRAMVal = constVal(maxRAM);
159 maxRAMaddress = (int)floatFromVal(maxRAMVal);
160 pic16_setMaxRAM(maxRAMaddress);
169 _pic16_parseOptions (int *pargc, char **argv, int *i)
171 /* TODO: allow port-specific command line options to specify
172 * segment names here.
178 _pic16_finaliseOptions (void)
180 port->mem.default_local_map = data;
181 port->mem.default_globl_map = data;
183 setMainValue("mcu", pic16_processor_base_name() );
184 addSet(&preArgvSet, Safe_strdup("-DMCU={mcu}"));
188 /* all the rest is commented ifdef'd out */
190 /* Hack-o-matic: if we are using the flat24 model,
191 * adjust pointer sizes.
193 if (options.model == MODEL_FLAT24)
196 fprintf (stderr, "*** WARNING: you should use the '-mds390' option "
197 "for DS80C390 support. This code generator is "
198 "badly out of date and probably broken.\n");
200 port->s.fptr_size = 3;
201 port->s.gptr_size = 4;
202 port->stack.isr_overhead++; /* Will save dpx on ISR entry. */
204 port->stack.call_overhead++; /* This acounts for the extra byte
205 * of return addres on the stack.
206 * but is ugly. There must be a
210 fReturn = fReturn390;
214 if (options.model == MODEL_LARGE)
216 port->mem.default_local_map = xdata;
217 port->mem.default_globl_map = xdata;
221 port->mem.default_local_map = data;
222 port->mem.default_globl_map = data;
225 if (options.stack10bit)
227 if (options.model != MODEL_FLAT24)
230 "*** warning: 10 bit stack mode is only supported in flat24 model.\n");
231 fprintf (stderr, "\t10 bit stack mode disabled.\n");
232 options.stack10bit = 0;
236 /* Fixup the memory map for the stack; it is now in
237 * far space and requires a FPOINTER to access it.
240 istack->ptrType = FPOINTER;
247 _pic16_setDefaultOptions (void)
252 _pic16_getRegName (struct regs *reg)
261 _pic16_genAssemblerPreamble (FILE * of)
263 char * name = pic16_processor_base_name();
268 fprintf(stderr,"WARNING: No Pic has been selected, defaulting to %s\n",name);
271 fprintf (of, "\tlist\tp=%s\n",&name[1]);
272 fprintf (of, "\tinclude \"%s.inc\"\n",name);
274 fprintf (of, "\t__config _CONFIG1H,0x%x\n",pic16_getConfigWord(0x300001));
275 fprintf (of, "\t__config _CONFIG2L,0x%x\n",pic16_getConfigWord(0x300002));
276 fprintf (of, "\t__config _CONFIG2H,0x%x\n",pic16_getConfigWord(0x300003));
277 fprintf (of, "\t__config _CONFIG3H,0x%x\n",pic16_getConfigWord(0x300005));
278 fprintf (of, "\t__config _CONFIG4L,0x%x\n",pic16_getConfigWord(0x300006));
279 fprintf (of, "\t__config _CONFIG5L,0x%x\n",pic16_getConfigWord(0x300008));
280 fprintf (of, "\t__config _CONFIG5H,0x%x\n",pic16_getConfigWord(0x300009));
281 fprintf (of, "\t__config _CONFIG6L,0x%x\n",pic16_getConfigWord(0x30000a));
282 fprintf (of, "\t__config _CONFIG6H,0x%x\n",pic16_getConfigWord(0x30000b));
283 fprintf (of, "\t__config _CONFIG7L,0x%x\n",pic16_getConfigWord(0x30000c));
284 fprintf (of, "\t__config _CONFIG7H,0x%x\n",pic16_getConfigWord(0x30000d));
286 fprintf (of, "\tradix dec\n");
289 /* Generate interrupt vector table. */
291 _pic16_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts)
298 if (options.model != MODEL_FLAT24) {
299 /* Let the default code handle it. */
304 /* PIC18F family has only two interrupts, the high and the low
305 * priority interrupts, which reside at 0x0008 and 0x0018 respectively - VR */
307 fprintf(of, "; RESET vector\n");
308 fprintf(of, "\tgoto\t__sdcc_gsinit_startup\n");
309 fprintf(of, "\tres 4\n");
312 fprintf(of, "; High priority interrupt vector 0x0008\n");
314 fprintf(of, "\tgoto\t%s\n", interrupts[1]->rname);
315 fprintf(of, "\tres\t12\n");
317 fprintf(of, "\tretfie\n");
318 fprintf(of, "\tres\t14\n");
321 fprintf(of, "; Low priority interrupt vector 0x0018\n");
323 fprintf(of, "\tgoto\t%s\n", interrupts[2]->rname);
325 fprintf(of, "\tretfie\n");
328 /* now for the other interrupts */
329 for (i = 0; i < maxInterrupts; i++)
331 fprintf(of, "; %s priority interrupt vector 0x%s\n", (i==0)?"high":"low", (i==0)?"0008":"0018");
334 fprintf (of, "\tgoto\t%s\n\tres\t4\n", interrupts[i]->rname);
338 fprintf (of, "\tretfie\n\tres\t7\n");
347 _hasNativeMulFor (iCode *ic, sym_link *left, sym_link *right)
349 // sym_link *test = NULL;
352 fprintf(stderr,"checking for native mult\n");
361 if ( IS_LITERAL (left))
363 fprintf(stderr,"left is lit\n");
365 val = OP_VALUE (IC_LEFT (ic));
367 else if ( IS_LITERAL (right))
369 fprintf(stderr,"right is lit\n");
371 val = OP_VALUE (IC_RIGHT (ic));
375 fprintf(stderr,"oops, neither is lit so no\n");
379 if ( getSize (test) <= 2)
381 fprintf(stderr,"yep\n");
384 fprintf(stderr,"nope\n");
390 /* Indicate which extended bit operations this port supports */
392 hasExtBitOp (int op, int size)
396 /* || op == GETHBIT */ /* GETHBIT doesn't look complete for PIC */
403 /* Indicate the expense of an access to an output storage class */
405 oclsExpense (struct memmap *oclass)
407 /* The IN_FARSPACE test is compatible with historical behaviour, */
408 /* but I don't think it is applicable to PIC. If so, please feel */
409 /* free to remove this test -- EEP */
410 if (IN_FARSPACE(oclass))
416 /** $1 is always the basename.
417 $2 is always the output file.
419 $l is the list of extra options that should be there somewhere...
420 MUST be terminated with a NULL.
422 static const char *_linkCmd[] =
424 "gplink", "\"$1.o\"", "-o $1", "$l", NULL
427 /* Sigh. This really is not good. For now, I recommend:
428 * sdcc -S -mpic16 file.c
429 * the -S option does not compile or link
431 static const char *_asmCmd[] =
433 "gpasm", "-c -I/usr/local/share/gputils/header", "\"$1.asm\"", NULL
442 "MCU PIC16", /* Target name */
443 "p18f442", /* Processor */
446 TRUE, /* Emit glue around main */
447 MODEL_SMALL | MODEL_LARGE | MODEL_FLAT24,
455 //"-plosgffc", /* Options with debug */
456 //"-plosgff", /* Options without debug */
459 NULL /* no do_assemble function */
471 /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
472 1, 2, 2, 4, 2, 2, 2, 1, 4, 4
473 /* TSD - I changed the size of gptr from 3 to 1. However, it should be
474 2 so that we can accomodate the PIC's with 4 register banks (like the
479 "XSEG (XDATA)", // xstack
480 "STACK (DATA)", // istack
481 "CSEG (CODE)", // code
482 "DSEG (DATA)", // data
483 "ISEG (DATA)", // idata
484 "XSEG (XDATA)", // xdata
486 "RSEG (DATA)", // reg
487 "GSINIT (CODE)", // static
488 "OSEG (OVR,DATA)", // overlay
489 "GSFINAL (CODE)", // post static
490 "HOME (CODE)", // home
493 NULL, // default location for auto vars
494 NULL, // default location for global vars
495 1 // code is read only
501 /* pic16 has an 8 bit mul */
509 _pic16_finaliseOptions,
510 _pic16_setDefaultOptions,
511 pic16_assignRegisters,
514 _pic16_genAssemblerPreamble,
515 NULL, /* no genAssemblerEnd */
517 NULL, // _pic16_genXINIT
518 _pic16_reset_regparm,
520 _process_pragma, /* process a pragma */
523 hasExtBitOp, /* hasExtBitOp */
524 oclsExpense, /* oclsExpense */
526 TRUE, /* little endian */
529 1, /* transform <= to ! > */
530 1, /* transform >= to ! < */
531 1, /* transform != to !(a == b) */
533 FALSE, /* No array initializer support. */
534 0, /* no CSE cost estimation yet */
535 NULL, /* no builtin functions */
536 GPOINTER, /* treat unqualified pointers as "generic" pointers */
537 1, /* reset labelKey to 1 */
538 1, /* globals & local static allowed */