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[] =
69 void pic16_pCodeInitRegisters(void);
71 void pic16_assignRegisters (eBBlock ** ebbs, int count);
73 static int regParmFlg = 0; /* determine if we can register a parameter */
78 asm_addTree (&asm_asxxxx_mapping);
79 pic16_pCodeInitRegisters();
84 _pic16_reset_regparm ()
90 _pic16_regparm (sym_link * l)
92 /* for this processor it is simple
93 can pass only the first parameter in a register */
102 _process_pragma(const char *sz)
104 static const char *WHITE = " \t";
105 char *ptr = strtok((char *)sz, WHITE);
107 if (startsWith (ptr, "memmap"))
114 start = strtok((char *)NULL, WHITE);
115 end = strtok((char *)NULL, WHITE);
116 type = strtok((char *)NULL, WHITE);
117 alias = strtok((char *)NULL, WHITE);
119 if (start != (char *)NULL
120 && end != (char *)NULL
121 && type != (char *)NULL) {
122 value *startVal = constVal(start);
123 value *endVal = constVal(end);
127 if (alias == (char *)NULL) {
128 aliasVal = constVal(0);
130 aliasVal = constVal(alias);
133 r.start_address = (int)floatFromVal(startVal);
134 r.end_address = (int)floatFromVal(endVal);
135 r.alias = (int)floatFromVal(aliasVal);
136 r.bank = (r.start_address >> 7) & 0xf;
138 if (strcmp(type, "RAM") == 0) {
139 pic16_addMemRange(&r, 0);
140 } else if (strcmp(type, "SFR") == 0) {
141 pic16_addMemRange(&r, 1);
148 } else if (startsWith (ptr, "maxram")) {
149 char *maxRAM = strtok((char *)NULL, WHITE);
151 if (maxRAM != (char *)NULL) {
155 maxRAMVal = constVal(maxRAM);
156 maxRAMaddress = (int)floatFromVal(maxRAMVal);
157 pic16_setMaxRAM(maxRAMaddress);
166 _pic16_parseOptions (int *pargc, char **argv, int *i)
168 /* TODO: allow port-specific command line options to specify
169 * segment names here.
175 _pic16_finaliseOptions (void)
178 port->mem.default_local_map = data;
179 port->mem.default_globl_map = data;
181 /* Hack-o-matic: if we are using the flat24 model,
182 * adjust pointer sizes.
184 if (options.model == MODEL_FLAT24)
187 fprintf (stderr, "*** WARNING: you should use the '-mds390' option "
188 "for DS80C390 support. This code generator is "
189 "badly out of date and probably broken.\n");
191 port->s.fptr_size = 3;
192 port->s.gptr_size = 4;
193 port->stack.isr_overhead++; /* Will save dpx on ISR entry. */
195 port->stack.call_overhead++; /* This acounts for the extra byte
196 * of return addres on the stack.
197 * but is ugly. There must be a
201 fReturn = fReturn390;
205 if (options.model == MODEL_LARGE)
207 port->mem.default_local_map = xdata;
208 port->mem.default_globl_map = xdata;
212 port->mem.default_local_map = data;
213 port->mem.default_globl_map = data;
216 if (options.stack10bit)
218 if (options.model != MODEL_FLAT24)
221 "*** warning: 10 bit stack mode is only supported in flat24 model.\n");
222 fprintf (stderr, "\t10 bit stack mode disabled.\n");
223 options.stack10bit = 0;
227 /* Fixup the memory map for the stack; it is now in
228 * far space and requires a FPOINTER to access it.
231 istack->ptrType = FPOINTER;
238 _pic16_setDefaultOptions (void)
243 _pic16_getRegName (struct regs *reg)
250 extern char *pic16_processor_base_name(void);
253 _pic16_genAssemblerPreamble (FILE * of)
255 char * name = pic16_processor_base_name();
260 fprintf(stderr,"WARNING: No Pic has been selected, defaulting to %s\n",name);
263 fprintf (of, "\tlist\tp=%s\n",&name[1]);
264 fprintf (of, "\tinclude \"%s.inc\"\n",name);
267 fprintf (of, "\t__config _CONFIG1H,0x%x\n",pic16_getConfigWord(0x300001));
268 fprintf (of, "\t__config _CONFIG2L,0x%x\n",pic16_getConfigWord(0x300002));
269 fprintf (of, "\t__config _CONFIG2H,0x%x\n",pic16_getConfigWord(0x300003));
270 fprintf (of, "\t__config _CONFIG3H,0x%x\n",pic16_getConfigWord(0x300005));
271 fprintf (of, "\t__config _CONFIG4L,0x%x\n",pic16_getConfigWord(0x300006));
272 fprintf (of, "\t__config _CONFIG5L,0x%x\n",pic16_getConfigWord(0x300008));
273 fprintf (of, "\t__config _CONFIG5H,0x%x\n",pic16_getConfigWord(0x300009));
274 fprintf (of, "\t__config _CONFIG6L,0x%x\n",pic16_getConfigWord(0x30000a));
275 fprintf (of, "\t__config _CONFIG6H,0x%x\n",pic16_getConfigWord(0x30000b));
276 fprintf (of, "\t__config _CONFIG7L,0x%x\n",pic16_getConfigWord(0x30000c));
277 fprintf (of, "\t__config _CONFIG7H,0x%x\n",pic16_getConfigWord(0x30000d));
280 fprintf (of, "\tradix dec\n");
283 /* Generate interrupt vector table. */
285 _pic16_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts)
292 if (options.model != MODEL_FLAT24) {
293 /* Let the default code handle it. */
298 /* PIC18F family has only two interrupts, the high and the low
299 * priority interrupts, which reside at 0x0008 and 0x0018 respectively - VR */
301 fprintf(of, "; RESET vector\n");
302 fprintf(of, "\tgoto\t__sdcc_gsinit_startup\n");
303 fprintf(of, "\tres 6\n");
306 fprintf(of, "; High priority interrupt vector 0x0008\n");
308 fprintf(of, "\tgoto\t%s\n", interrupts[1]->rname);
309 fprintf(of, "\tres\t8\n");
311 fprintf(of, "\tretfie\n");
312 fprintf(of, "\tres\t8\n");
315 fprintf(of, "; Low priority interrupt vector 0x0018\n");
317 fprintf(of, "\tgoto\t%s\n", interrupts[2]->rname);
319 fprintf(of, "\tretfie\n");
322 /* now for the other interrupts */
323 for (i = 0; i < maxInterrupts; i++)
325 fprintf(of, "; %s priority interrupt vector 0x%s\n", (i==0)?"high":"low", (i==0)?"0008":"0018");
328 fprintf (of, "\tgoto\t%s\n\tres\t4\n", interrupts[i]->rname);
332 fprintf (of, "\tretfie\n\tres\t7\n");
341 _hasNativeMulFor (iCode *ic, sym_link *left, sym_link *right)
343 // sym_link *test = NULL;
346 fprintf(stderr,"checking for native mult\n");
355 if ( IS_LITERAL (left))
357 fprintf(stderr,"left is lit\n");
359 val = OP_VALUE (IC_LEFT (ic));
361 else if ( IS_LITERAL (right))
363 fprintf(stderr,"right is lit\n");
365 val = OP_VALUE (IC_RIGHT (ic));
369 fprintf(stderr,"oops, neither is lit so no\n");
373 if ( getSize (test) <= 2)
375 fprintf(stderr,"yep\n");
378 fprintf(stderr,"nope\n");
384 /** $1 is always the basename.
385 $2 is always the output file.
387 $l is the list of extra options that should be there somewhere...
388 MUST be terminated with a NULL.
390 static const char *_linkCmd[] =
392 "gplink", "\"$1.o\"", "-o $1", "$l", NULL
395 /* Sigh. This really is not good. For now, I recommend:
396 * sdcc -S -mpic16 file.c
397 * the -S option does not compile or link
399 static const char *_asmCmd[] =
401 "gpasm", "-c -I/usr/local/share/gputils/header", "\"$1.asm\"", NULL
410 "MCU PIC16", /* Target name */
411 "p18f442", /* Processor */
414 TRUE, /* Emit glue around main */
415 MODEL_SMALL | MODEL_LARGE | MODEL_FLAT24,
423 //"-plosgffc", /* Options with debug */
424 //"-plosgff", /* Options without debug */
427 NULL /* no do_assemble function */
439 /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
440 1, 2, 2, 4, 2, 2, 2, 1, 4, 4
441 /* TSD - I changed the size of gptr from 3 to 1. However, it should be
442 2 so that we can accomodate the PIC's with 4 register banks (like the
447 "XSEG (XDATA)", // xstack
448 "STACK (DATA)", // istack
449 "CSEG (CODE)", // code
450 "DSEG (DATA)", // data
451 "ISEG (DATA)", // idata
452 "XSEG (XDATA)", // xdata
454 "RSEG (DATA)", // reg
455 "GSINIT (CODE)", // static
456 "OSEG (OVR,DATA)", // overlay
457 "GSFINAL (CODE)", // post static
458 "HOME (CODE)", // home
461 NULL, // default location for auto vars
462 NULL, // default location for global vars
463 1 // code is read only
469 /* pic16 has an 8 bit mul */
477 _pic16_finaliseOptions,
478 _pic16_setDefaultOptions,
479 pic16_assignRegisters,
482 _pic16_genAssemblerPreamble,
483 NULL, /* no genAssemblerEnd */
485 NULL, // _pic16_genXINIT
486 _pic16_reset_regparm,
488 _process_pragma, /* process a pragma */
492 TRUE, /* little endian */
495 1, /* transform <= to ! > */
496 1, /* transform >= to ! < */
497 1, /* transform != to !(a == b) */
499 FALSE, /* No array initializer support. */
500 0, /* no CSE cost estimation yet */
501 NULL, /* no builtin functions */
502 GPOINTER, /* treat unqualified pointers as "generic" pointers */
503 1, /* reset labelKey to 1 */
504 1, /* globals & local static allowed */