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