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