* src/port.h (PORT structure): added hook initPaths, now each
[fw/sdcc] / src / pic16 / main.c
1 /*-------------------------------------------------------------------------
2
3   main.c - pic16 specific general functions.
4
5    Written by - Scott Dattalo scott@dattalo.com
6    Ported to PIC16 by - Martin Dubuc m.debuc@rogers.com
7     
8    Note that mlh prepended _pic16_ on the static functions.  Makes
9    it easier to set a breakpoint using the debugger.
10
11
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
15    later version.
16    
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.
21    
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 -------------------------------------------------------------------------*/
26
27 #include "common.h"
28 #include "main.h"
29 #include "ralloc.h"
30 #include "device.h"
31 #include "SDCCutil.h"
32 #include "glue.h"
33 #include "pcode.h"
34 //#include "gen.h"
35
36
37 static char _defaultRules[] =
38 {
39 #include "peeph.rul"
40 };
41
42 /* list of key words used by pic16 */
43 static char *_pic16_keywords[] =
44 {
45   "at",
46   "bit",
47   "code",
48   "critical",
49   "data",
50   "far",
51   "idata",
52   "interrupt",
53   "near",
54   "pdata",
55   "reentrant",
56   "sfr",
57   "sbit",
58   "using",
59   "xdata",
60   "_data",
61   "_code",
62   "_generic",
63   "_near",
64   "_xdata",
65   "_pdata",
66   "_idata",
67   "_naked",
68   NULL
69 };
70
71
72 pic16_sectioninfo_t pic16_sectioninfo;
73
74
75 extern char *pic16_processor_base_name(void);
76
77 void  pic16_pCodeInitRegisters(void);
78
79 void pic16_assignRegisters (eBBlock ** ebbs, int count);
80
81 static int regParmFlg = 0;      /* determine if we can register a parameter */
82
83 pic16_options_t pic16_options;
84
85 extern set *includeDirsSet;
86 extern set *dataDirsSet;
87 extern set *libFilesSet;
88
89 /* Also defined in gen.h, but the #include is commented out */
90 /* for an unknowned reason. - EEP */
91 void pic16_emitDebuggerSymbol (char *);
92  
93
94 static void
95 _pic16_init (void)
96 {
97 #if 0
98   char pic16incDir[512];
99   char pic16libDir[512];
100   set *pic16incDirsSet;
101   set *pic16libDirsSet;
102   char devlib[512];
103 #endif
104
105         asm_addTree (&asm_asxxxx_mapping);
106         pic16_pCodeInitRegisters();
107         maxInterrupts = 2;
108
109         /* set pic16 port options to defaults */
110         pic16_options.no_banksel = 0;
111         pic16_options.opt_banksel = 0;
112         pic16_options.omit_configw = 0;
113         pic16_options.omit_ivt = 0;
114         pic16_options.leave_reset = 0;
115         pic16_options.stack_model = 0;                  /* 0 for 'small', 1 for 'large' */
116
117
118 #if 0
119         setMainValue("mcu", pic16->name[2] );
120         addSet(&preArgvSet, Safe_strdup("-D{mcu}"));
121
122         sprintf(pic16incDir, "%s/pic16", INCLUDE_DIR_SUFFIX);
123         sprintf(pic16libDir, "%s/pic16", LIB_DIR_SUFFIX);
124
125         if(!options.nostdinc) {
126                 /* setup pic16 include directory */
127                 pic16incDirsSet = appendStrSet(dataDirsSet, NULL, pic16incDir);
128                 mergeSets(&includeDirsSet, pic16incDirsSet);
129         }
130         
131         if(!options.nostdlib) {
132                 /* setup pic16 library directory */
133                 pic16libDirsSet = appendStrSet(dataDirsSet, NULL, pic16libDir);
134                 mergeSets(&libDirsSet, pic16libDirsSet);
135         
136                 /* now add the library for the device */
137                 sprintf(devlib, "%s.lib", pic16->name[2]);
138                 addSet(&libFilesSet, Safe_strdup(devlib));
139         }
140 #endif
141 }
142
143 static void
144 _pic16_reset_regparm ()
145 {
146   regParmFlg = 0;
147 }
148
149 static int
150 _pic16_regparm (sym_link * l)
151 {
152   /* for this processor it is simple
153      can pass only the first parameter in a register */
154   //if (regParmFlg)
155   //  return 0;
156
157   regParmFlg++;// = 1;
158   return 1;
159 }
160
161
162 int initsfpnt=0;                /* set to 1 if source provides a pragma for stack
163                                  * so glue() later emits code to initialize stack/frame pointers */
164 set *absSymSet;
165
166 static int
167 _process_pragma(const char *sz)
168 {
169   static const char *WHITE = " \t";
170   
171   char  *ptr = strtok((char *)sz, WHITE);
172
173         if (startsWith (ptr, "maxram")) {
174           char *maxRAM = strtok((char *)NULL, WHITE);
175
176                 if (maxRAM != (char *)NULL) {
177                   int maxRAMaddress;
178                   value *maxRAMVal;
179
180                         maxRAMVal = constVal(maxRAM);
181                         maxRAMaddress = (int)floatFromVal(maxRAMVal);
182                         pic16_setMaxRAM(maxRAMaddress);
183                 }
184         }
185         
186         if(startsWith(ptr, "stack")) {
187           char *stackPosS = strtok((char *)NULL, WHITE);
188           value *stackPosVal;
189           regs *reg;
190
191 //              fprintf(stderr, "Initializing stack pointer to 0x%x\n", (int)floatFromVal(constVal(stackPos)));
192                 stackPosVal = constVal( stackPosS );
193                 stackPos = (unsigned int)floatFromVal( stackPosVal );
194
195                 reg=newReg(REG_SFR, PO_SFR_REGISTER, stackPos, "stack", 1, 0, NULL);
196                 addSet(&pic16_fix_udata, reg);
197                 
198                 initsfpnt = 1;          // force glue() to initialize stack/frame pointers */
199
200           return 0;
201         }
202         
203         if(startsWith(ptr, "code")) {
204           char *symname = strtok((char *)NULL, WHITE);
205           char *location = strtok((char *)NULL, WHITE);
206           absSym *absS;
207           value *addr;
208
209                 absS = Safe_calloc(1, sizeof(absSym));
210                 absS->name = Safe_strdup( symname );
211                 addr = constVal( location );
212                 absS->address = (unsigned int)floatFromVal( addr );
213
214                 addSet(&absSymSet, absS);
215                 fprintf(stderr, "%s:%d symbol %s will be placed in location 0x%06x in code memory\n",
216                         __FILE__, __LINE__, symname, absS->address);
217
218           return 0;
219         }         
220
221   return 1;
222 }
223
224 #define REP_UDATA       "--preplace-udata-with="
225
226 #define STACK_MODEL     "--pstack-model="
227 #define OPT_BANKSEL     "--obanksel="
228
229
230 extern int pic16_debug_verbose;
231 extern int pic16_ralloc_debug;
232 extern int pic16_pcode_verbose;
233
234 OPTION pic16_optionsTable[]= {
235         { 0,    "--pno-banksel",        &pic16_options.no_banksel,      "do not generate BANKSEL assembler directives"},
236         { 0,    OPT_BANKSEL,            NULL,                           "set banksel optimization level (default=0 no)"},
237         { 0,    "--pomit-config-words", &pic16_options.omit_configw,    "omit the generation of configuration words"},
238         { 0,    "--pomit-ivt",          &pic16_options.omit_ivt,        "omit the generation of the Interrupt Vector Table"},
239         { 0,    "--pleave-reset-vector",&pic16_options.leave_reset,     "when omitting IVT leave RESET vector"},
240         { 0,    STACK_MODEL,    NULL,   "use stack model 'small' (default) or 'large'"},
241
242         { 0,    "--debug-xtra",         &pic16_debug_verbose,   "show more debug info in assembly output"},
243         { 0,    "--debug-ralloc",       &pic16_ralloc_debug,    "dump register allocator debug file *.d"},
244         { 0,    "--pcode-verbose",      &pic16_pcode_verbose,   "dump pcode related info"},
245                 
246         { 0,    REP_UDATA,      NULL,   "Place udata variables at another section: udata_acs, udata_ovr, udata_shr"},
247
248         { 0,    NULL,           NULL,   NULL}
249         };
250
251
252 #define ISOPT(str)      !strncmp(argv[ *i ], str, strlen(str) )
253
254 extern char *getStringArg(const char *,  char **, int *, int);
255 extern int getIntArg(const char *, char **, int *, int);
256
257 static bool
258 _pic16_parseOptions (int *pargc, char **argv, int *i)
259 {
260   int j=0;
261   char *stkmodel;
262   
263   /* TODO: allow port-specific command line options to specify
264    * segment names here.
265    */
266         /* check for arguments that have associated an integer variable */
267         while(pic16_optionsTable[j].pparameter) {
268                 if(ISOPT( pic16_optionsTable[j].longOpt )) {
269                         (*pic16_optionsTable[j].pparameter)++;
270                         return TRUE;
271                 }
272                 j++;
273         }
274
275
276         if(ISOPT(STACK_MODEL)) {
277                 stkmodel = getStringArg(STACK_MODEL, argv, i, *pargc);
278                 if(STRCASECMP(stkmodel, "small"))pic16_options.stack_model = 0;
279                 else if(STRCASECMP(stkmodel, "large"))pic16_options.stack_model = 1;
280                 else {
281                         fprintf(stderr, "Unknown stack model: %s", stkmodel);
282                         exit(-1);
283                 }
284                 return TRUE;
285         }
286
287         if(ISOPT(OPT_BANKSEL)) {
288                 pic16_options.opt_banksel = getIntArg(OPT_BANKSEL, argv, i, *pargc);
289                 return TRUE;
290         }
291
292         if(ISOPT(REP_UDATA)) {
293                 pic16_sectioninfo.at_udata = Safe_strdup(getStringArg(REP_UDATA, argv, i, *pargc));
294                 return TRUE;
295         }
296         
297   return FALSE;
298 }
299
300 static void _pic16_initPaths(void)
301 {
302 #if 1
303   char pic16incDir[512];
304   char pic16libDir[512];
305   set *pic16incDirsSet;
306   set *pic16libDirsSet;
307   char devlib[512];
308 #endif
309
310 #if 1
311         setMainValue("mcu", pic16->name[2] );
312         addSet(&preArgvSet, Safe_strdup("-D{mcu}"));
313
314         sprintf(pic16incDir, "%s/pic16", INCLUDE_DIR_SUFFIX);
315         sprintf(pic16libDir, "%s/pic16", LIB_DIR_SUFFIX);
316
317         if(!options.nostdinc) {
318                 /* setup pic16 include directory */
319                 pic16incDirsSet = appendStrSet(dataDirsSet, NULL, pic16incDir);
320                 mergeSets(&includeDirsSet, pic16incDirsSet);
321         }
322         
323         if(!options.nostdlib) {
324                 /* setup pic16 library directory */
325                 pic16libDirsSet = appendStrSet(dataDirsSet, NULL, pic16libDir);
326                 mergeSets(&libDirsSet, pic16libDirsSet);
327         
328                 /* now add the library for the device */
329                 sprintf(devlib, "%s.lib", pic16->name[2]);
330                 addSet(&libFilesSet, Safe_strdup(devlib));
331         }
332 #endif
333 }
334
335
336 static void
337 _pic16_finaliseOptions (void)
338 {
339 #if 0
340   char pic16incDir[512];
341   char pic16libDir[512];
342   set *pic16incDirsSet;
343   set *pic16libDirsSet;
344   char devlib[512];
345 #endif
346         port->mem.default_local_map = data;
347         port->mem.default_globl_map = data;
348
349         options.all_callee_saves = 1;           // always callee saves
350 //      options.float_rent = 1;
351 //      options.intlong_rent = 1;
352         
353 #if 0
354         setMainValue("mcu", pic16->name[2] );
355         addSet(&preArgvSet, Safe_strdup("-D{mcu}"));
356
357         sprintf(pic16incDir, "%s/pic16", INCLUDE_DIR_SUFFIX);
358         sprintf(pic16libDir, "%s/pic16", LIB_DIR_SUFFIX);
359
360         if(!options.nostdinc) {
361                 /* setup pic16 include directory */
362                 pic16incDirsSet = appendStrSet(dataDirsSet, NULL, pic16incDir);
363                 mergeSets(&includeDirsSet, pic16incDirsSet);
364         }
365         
366         if(!options.nostdlib) {
367                 /* setup pic16 library directory */
368                 pic16libDirsSet = appendStrSet(dataDirsSet, NULL, pic16libDir);
369                 mergeSets(&libDirsSet, pic16libDirsSet);
370         
371                 /* now add the library for the device */
372                 sprintf(devlib, "%s.lib", pic16->name[2]);
373                 addSet(&libFilesSet, Safe_strdup(devlib));
374         }
375 #endif
376 }
377
378
379 /* all the rest is commented ifdef'd out */
380 #if 0
381   /* Hack-o-matic: if we are using the flat24 model,
382    * adjust pointer sizes.
383    */
384   if (options.model == MODEL_FLAT24)
385     {
386
387       fprintf (stderr, "*** WARNING: you should use the '-mds390' option "
388                "for DS80C390 support. This code generator is "
389                "badly out of date and probably broken.\n");
390
391       port->s.fptr_size = 3;
392       port->s.gptr_size = 4;
393       port->stack.isr_overhead++;       /* Will save dpx on ISR entry. */
394 #if 1
395       port->stack.call_overhead++;      /* This acounts for the extra byte 
396                                          * of return addres on the stack.
397                                          * but is ugly. There must be a 
398                                          * better way.
399                                          */
400 #endif
401       fReturn = fReturn390;
402       fReturnSize = 5;
403     }
404
405   if (options.model == MODEL_LARGE)
406     {
407       port->mem.default_local_map = xdata;
408       port->mem.default_globl_map = xdata;
409     }
410   else
411     {
412       port->mem.default_local_map = data;
413       port->mem.default_globl_map = data;
414     }
415
416   if (options.stack10bit)
417     {
418       if (options.model != MODEL_FLAT24)
419         {
420           fprintf (stderr,
421                    "*** warning: 10 bit stack mode is only supported in flat24 model.\n");
422           fprintf (stderr, "\t10 bit stack mode disabled.\n");
423           options.stack10bit = 0;
424         }
425       else
426         {
427           /* Fixup the memory map for the stack; it is now in
428            * far space and requires a FPOINTER to access it.
429            */
430           istack->fmap = 1;
431           istack->ptrType = FPOINTER;
432         }
433     }
434 #endif
435
436
437 static void
438 _pic16_setDefaultOptions (void)
439 {
440         /* initialize to defaults section locations, names and addresses */
441         pic16_sectioninfo.at_udata      = "udata";
442         pic16_sectioninfo.at_udataacs   = "udata_acs";
443         pic16_sectioninfo.at_udataovr   = "udata_ovr";
444         pic16_sectioninfo.at_udatashr   = "udata_shr";
445
446         /* initialize to nothing, so let linker decide about their names */
447         pic16_sectioninfo.name_code     =
448         pic16_sectioninfo.name_idata    =
449         pic16_sectioninfo.name_udata    =
450         pic16_sectioninfo.name_udataacs =
451         pic16_sectioninfo.name_udataovr =
452         pic16_sectioninfo.name_udatashr = "";
453
454         /* initialize to -1, so let linker decide about their address */
455         pic16_sectioninfo.addr_code     =
456         pic16_sectioninfo.addr_idata    =
457         pic16_sectioninfo.addr_udata    =
458         pic16_sectioninfo.addr_udataacs =
459         pic16_sectioninfo.addr_udataovr =
460         pic16_sectioninfo.addr_udatashr = -1;
461
462
463
464         /* set pic16 port options to defaults */
465         pic16_options.no_banksel = 0;
466         pic16_options.opt_banksel = 0;
467         pic16_options.omit_configw = 0;
468         pic16_options.omit_ivt = 0;
469         pic16_options.leave_reset = 0;
470         pic16_options.stack_model = 0;                  /* 0 for 'small', 1 for 'large' */
471 }
472
473 static const char *
474 _pic16_getRegName (struct regs *reg)
475 {
476   if (reg)
477     return reg->name;
478   return "err";
479 }
480
481
482 #if 1
483 static  char *_pic16_mangleFunctionName(char *sz)
484 {
485 //      fprintf(stderr, "mangled function name: %s\n", sz);
486
487   return sz;
488 }
489 #endif
490
491
492 static void
493 _pic16_genAssemblerPreamble (FILE * of)
494 {
495   char *name = pic16_processor_base_name();
496
497         if(!name) {
498                 name = "p18f452";
499                 fprintf(stderr,"WARNING: No Pic has been selected, defaulting to %s\n",name);
500         }
501
502         fprintf (of, "\tlist\tp=%s\n",&name[1]);
503
504         if(!pic16_options.omit_configw) {
505                 fprintf (of, "\t__config 0x%x,0x%hhx\n", 0x300001, pic16_getConfigWord(0x300001));
506                 fprintf (of, "\t__config 0x%x,0x%hhx\n", 0x300002, pic16_getConfigWord(0x300002));
507                 fprintf (of, "\t__config 0x%x,0x%hhx\n", 0x300003, pic16_getConfigWord(0x300003));
508                 fprintf (of, "\t__config 0x%x,0x%hhx\n", 0x300005, pic16_getConfigWord(0x300005));
509                 fprintf (of, "\t__config 0x%x,0x%hhx\n", 0x300006, pic16_getConfigWord(0x300006));
510                 fprintf (of, "\t__config 0x%x,0x%hhx\n", 0x300008, pic16_getConfigWord(0x300008));
511                 fprintf (of, "\t__config 0x%x,0x%hhx\n", 0x300009, pic16_getConfigWord(0x300009));
512                 fprintf (of, "\t__config 0x%x,0x%hhx\n", 0x30000a, pic16_getConfigWord(0x30000a));
513                 fprintf (of, "\t__config 0x%x,0x%hhx\n", 0x30000b, pic16_getConfigWord(0x30000b));
514                 fprintf (of, "\t__config 0x%x,0x%hhx\n", 0x30000c, pic16_getConfigWord(0x30000c));
515                 fprintf (of, "\t__config 0x%x,0x%hhx\n", 0x30000d, pic16_getConfigWord(0x30000d));
516         }
517         
518   fprintf (of, "\tradix dec\n");
519 }
520
521 /* Generate interrupt vector table. */
522 static int
523 _pic16_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts)
524 {
525 #if 1
526         /* PIC18F family has only two interrupts, the high and the low
527          * priority interrupts, which reside at 0x0008 and 0x0018 respectively - VR */
528
529         if((!pic16_options.omit_ivt) || (pic16_options.omit_ivt && pic16_options.leave_reset)) {
530                 fprintf(of, "; RESET vector\n");
531                 fprintf(of, "\tgoto\t__sdcc_gsinit_startup\n");
532         }
533         
534         if(!pic16_options.omit_ivt) {
535                 fprintf(of, "\tres 4\n");
536
537
538                 fprintf(of, "; High priority interrupt vector 0x0008\n");
539                 if(interrupts[1]) {
540                         fprintf(of, "\tgoto\t%s\n", interrupts[1]->rname);
541                         fprintf(of, "\tres\t12\n"); 
542                 } else {
543                         fprintf(of, "\tretfie\n");
544                         fprintf(of, "\tres\t14\n");
545                 }
546
547                 fprintf(of, "; Low priority interrupt vector 0x0018\n");
548                 if(interrupts[2]) {
549                         fprintf(of, "\tgoto\t%s\n", interrupts[2]->rname);
550                 } else {
551                         fprintf(of, "\tretfie\n");
552                 }
553         }
554 #endif
555   return TRUE;
556 }
557
558 /* return True if the port can handle the type,
559  * False to convert it to function call */
560 static bool _hasNativeMulFor (iCode *ic, sym_link *left, sym_link *right)
561 {
562 //      fprintf(stderr,"checking for native mult for %c (size: %d)\n", ic->op, getSize(OP_SYMBOL(IC_RESULT(ic))->type));
563
564         /* support mul for char/int {/long} */
565         if((getSize(OP_SYMBOL(IC_LEFT(ic))->type ) < 2)
566                 && (ic->op == '*'))return TRUE;
567         
568         /* support div for char/int/long */
569         if((getSize(OP_SYMBOL(IC_LEFT(ic))->type ) < 0)
570                 && (ic->op == '/'))return TRUE;
571         
572   return FALSE;
573 }
574
575
576 #if 0
577 /* Do CSE estimation */
578 static bool cseCostEstimation (iCode *ic, iCode *pdic)
579 {
580 //    operand *result = IC_RESULT(ic);
581 //    sym_link *result_type = operandType(result);
582
583
584         /* VR -- this is an adhoc. Put here after conversation
585          * with Erik Epetrich */
586
587         if(ic->op == '<'
588                 || ic->op == '>'
589                 || ic->op == EQ_OP) {
590
591                 fprintf(stderr, "%d %s\n", __LINE__, __FUNCTION__);
592           return 0;
593         }
594
595 #if 0
596     /* if it is a pointer then return ok for now */
597     if (IC_RESULT(ic) && IS_PTR(result_type)) return 1;
598
599     /* if bitwise | add & subtract then no since mcs51 is pretty good at it
600        so we will cse only if they are local (i.e. both ic & pdic belong to
601        the same basic block */
602     if (IS_BITWISE_OP(ic) || ic->op == '+' || ic->op == '-') {
603         /* then if they are the same Basic block then ok */
604         if (ic->eBBlockNum == pdic->eBBlockNum) return 1;
605         else return 0;
606     }
607 #endif
608
609     /* for others it is cheaper to do the cse */
610     return 1;
611 }
612 #endif
613
614
615 /* Indicate which extended bit operations this port supports */
616 static bool
617 hasExtBitOp (int op, int size)
618 {
619   if (op == RRC
620       || op == RLC
621       /* || op == GETHBIT */ /* GETHBIT doesn't look complete for PIC */
622      )
623     return TRUE;
624   else
625     return FALSE;
626 }
627
628 /* Indicate the expense of an access to an output storage class */
629 static int
630 oclsExpense (struct memmap *oclass)
631 {
632   /* The IN_FARSPACE test is compatible with historical behaviour, */
633   /* but I don't think it is applicable to PIC. If so, please feel */
634   /* free to remove this test -- EEP */
635   if (IN_FARSPACE(oclass))
636     return 1;
637     
638   return 0;
639 }
640
641 /** $1 is always the basename.
642     $2 is always the output file.
643     $3 -L path and -l libraries
644     $l is the list of extra options that should be there somewhere...
645     MUST be terminated with a NULL.
646 */
647 static const char *_linkCmd[] =
648 {
649   "gplink", "$3", "\"$1.o\"", "-o $1", "$l", NULL
650 };
651
652
653
654 /** $1 is always the basename.
655     $2 is always the output file.
656     $3 varies (nothing currently)
657     $l is the list of extra options that should be there somewhere...
658     MUST be terminated with a NULL.
659 */
660 static const char *_asmCmd[] =
661 {
662   "gpasm", "$l", "$3", "-c", "\"$1.asm\"", NULL
663
664 };
665
666 /* Globals */
667 PORT pic16_port =
668 {
669   TARGET_ID_PIC16,
670   "pic16",
671   "MCU PIC16",                  /* Target name */
672   "p18f452",                    /* Processor */
673   {
674     pic16glue,
675     TRUE,                       /* Emit glue around main */
676     MODEL_SMALL | MODEL_LARGE | MODEL_FLAT24,
677     MODEL_SMALL
678   },
679   {
680     _asmCmd,                    /* assembler command and arguments */
681     NULL,                       /* alternate macro based form */
682     NULL,                       /* arguments for debug mode */
683     NULL,                       /* arguments for normal mode */
684     0,                          /* print externs as global */
685     ".asm",                     /* assembler file extension */
686     NULL                        /* no do_assemble function */
687   },
688   {
689     _linkCmd,                   /* linker command and arguments */
690     NULL,                       /* alternate macro based form */
691     NULL,                       /* no do_link function */
692     ".o",                       /* extension for object files */
693     0                           /* no need for linker file */
694   },
695   {
696     _defaultRules
697   },
698   {
699         /* Sizes */
700     1,          /* char */
701     2,          /* short */
702     2,          /* int */
703     4,          /* long */
704     2,          /* ptr */
705     3,          /* fptr, far pointers (see Microchip) */
706     2,          /* gptr */
707     1,          /* bit */
708     4,          /* float */
709     4           /* max */
710   },
711   {
712     "XSEG    (XDATA)",          // xstack
713     "STACK   (DATA)",           // istack
714     "CSEG    (CODE)",           // code
715     "DSEG    (DATA)",           // data
716     "ISEG    (DATA)",           // idata
717     "XSEG    (XDATA)",          // xdata
718     "BSEG    (BIT)",            // bit
719     "RSEG    (DATA)",           // reg
720     "GSINIT  (CODE)",           // static
721     "OSEG    (OVR,DATA)",       // overlay
722     "GSFINAL (CODE)",           // post static
723     "HOME        (CODE)",       // home
724     NULL,                       // xidata
725     NULL,                       // xinit
726     NULL,                       // default location for auto vars
727     NULL,                       // default location for global vars
728     1                           // code is read only 1=yes
729   },
730   {
731     NULL,               /* genExtraAreaDeclaration */
732     NULL                /* genExatrAreaLinkOptions */
733   },
734   {
735         /* stack related information */
736     -1,                 /* -1 stack grows downwards, +1 upwards */
737     1,                  /* extra overhead when calling between banks */
738     4,                  /* extra overhead when the function is an ISR */
739     1,                  /* extra overhead for a function call */
740     1,                  /* re-entrant space */
741     0                   /* 'banked' call overhead, mild overlap with bank_overhead */
742   },
743     /* pic16 has an 8 bit mul */
744   {
745      0, -1
746   },
747   {
748     pic16_emitDebuggerSymbol
749   },
750   "_",
751   _pic16_init,
752   _pic16_parseOptions,
753   pic16_optionsTable,
754   _pic16_initPaths,
755   _pic16_finaliseOptions,
756   _pic16_setDefaultOptions,
757   pic16_assignRegisters,
758   _pic16_getRegName,
759   _pic16_keywords,
760   _pic16_genAssemblerPreamble,
761   NULL,                         /* no genAssemblerEnd */
762   _pic16_genIVT,
763   NULL, // _pic16_genXINIT
764   NULL,                         /* genInitStartup */
765   _pic16_reset_regparm,
766   _pic16_regparm,
767   _process_pragma,                              /* process a pragma */
768   _pic16_mangleFunctionName,                            /* mangles function name */
769   _hasNativeMulFor,
770   hasExtBitOp,                  /* hasExtBitOp */
771   oclsExpense,                  /* oclsExpense */
772   FALSE,                        
773   TRUE,                         /* little endian */
774   0,                            /* leave lt */
775   0,                            /* leave gt */
776   1,                            /* transform <= to ! > */
777   1,                            /* transform >= to ! < */
778   1,                            /* transform != to !(a == b) */
779   0,                            /* leave == */
780   FALSE,                        /* No array initializer support. */
781   0,    //cseCostEstimation,            /* !!!no CSE cost estimation yet */
782   NULL,                         /* no builtin functions */
783   GPOINTER,                     /* treat unqualified pointers as "generic" pointers */
784   1,                            /* reset labelKey to 1 */
785   1,                            /* globals & local static allowed */
786   PORT_MAGIC
787 };