* src/SDCCmain.c, src/ds390/main.c, src/mcs51/main.c, src/pic/main.c,
[fw/sdcc] / src / pic / main.c
1 /** @file main.c
2     pic14 specific general functions.
3
4     Note that mlh prepended _pic14_ on the static functions.  Makes
5     it easier to set a breakpoint using the debugger.
6 */
7 #include "common.h"
8 #include "main.h"
9 #include "ralloc.h"
10 #include "device.h"
11 #include "SDCCutil.h"
12 #include "SDCCmacro.h"
13 #include "MySystem.h"
14 #include "glue.h"
15 #include "dbuf_string.h"
16 #include <errno.h>
17 //#include "gen.h"
18
19 #define OPTION_STACK_SIZE         "--stack-size"
20 #define OPTION_UDATA_SECTION_NAME "--udata-section-name"
21
22
23 static char _defaultRules[] =
24 {
25 #include "peeph.rul"
26 };
27
28 pic14_options_t pic14_options;
29 extern int debug_verbose; /* from pcode.c */
30
31 static OPTION _pic14_poptions[] =
32   {
33     { 0, "--debug-xtra",   &debug_verbose, "show more debug info in assembly output" },
34     { 0, "--no-pcode-opt", &pic14_options.disable_df, "disable (slightly faulty) optimization on pCode" },
35     { 0, OPTION_STACK_SIZE, NULL, "sets the size if the argument passing stack (default: 16, minimum: 4)" },
36     { 0, OPTION_UDATA_SECTION_NAME, NULL, "set udata section name" },
37     { 0, NULL, NULL, NULL }
38   };
39
40 /* list of key words used by pic14 */
41 static char *_pic14_keywords[] =
42 {
43   "at",
44   //"bit",
45   "code",
46   "critical",
47   "data",
48   "far",
49   "idata",
50   "interrupt",
51   "near",
52   "pdata",
53   "reentrant",
54   "sfr",
55   //"sbit",
56   "using",
57   "xdata",
58   "_data",
59   "_code",
60   "_generic",
61   "_near",
62   "_xdata",
63   "_pdata",
64   "_idata",
65   NULL
66 };
67
68 void  pCodeInitRegisters(void);
69
70 void pic14_assignRegisters (ebbIndex *);
71
72 /* Also defined in gen.h, but the #include is commented out */
73 /* for an unknowned reason. - EEP */
74 void pic14_emitDebuggerSymbol (char *);
75
76 static int regParmFlg = 0;  /* determine if we can register a parameter */
77
78 static void
79 _pic14_init (void)
80 {
81   asm_addTree (&asm_asxxxx_mapping);
82   memset (&pic14_options, 0, sizeof (pic14_options));
83 }
84
85 static void
86 _pic14_reset_regparm (void)
87 {
88   regParmFlg = 0;
89 }
90
91 static int
92 _pic14_regparm (sym_link * l, bool reentrant)
93 {
94 /* for this processor it is simple
95   can pass only the first parameter in a register */
96   //if (regParmFlg)
97   //  return 0;
98   
99   regParmFlg++;// = 1;
100   return 1;
101 }
102
103 extern char *udata_section_name;
104
105 static bool
106 _pic14_parseOptions (int *pargc, char **argv, int *i)
107 {
108     /* TODO: allow port-specific command line options to specify
109     * segment names here.
110     */
111     
112     /* This is a temporary hack, to solve problems with some processors
113      * that do not have udata section. It will be changed when a more
114      * robust solution is figured out -- VR 27-11-2003 FIXME
115      */
116   if (!strcmp (argv[*i], OPTION_UDATA_SECTION_NAME))
117     {
118       if (udata_section_name) Safe_free(udata_section_name);
119       udata_section_name = Safe_strdup(getStringArg (OPTION_UDATA_SECTION_NAME, argv, i, *pargc));
120       return TRUE;
121     }
122   else if (!strcmp (argv[*i], OPTION_STACK_SIZE))
123     {
124       options.stack_size = getIntArg (OPTION_STACK_SIZE, argv, i, *pargc);
125       return TRUE;
126     }
127     return FALSE;
128 }
129
130 extern set *dataDirsSet;
131 extern set *includeDirsSet;
132 /* pic14 port uses include/pic and lib/pic instead of
133  * include/pic14 and lib/pic14 as indicated by SDCCmain.c's
134  * setIncludePaths routine. */
135 static void
136 _pic14_initPaths (void)
137 {
138   char *p;
139   char *p2=NULL;
140   set *tempSet=NULL;
141
142   if (options.nostdinc)
143       return;
144
145   tempSet = appendStrSet(dataDirsSet, NULL, INCLUDE_DIR_SUFFIX DIR_SEPARATOR_STRING "pic");
146   mergeSets(&includeDirsSet, tempSet);
147
148   if ((p = getenv(SDCC_INCLUDE_NAME)) != NULL)
149   {
150     addSetHead(&includeDirsSet, p);
151     p2=Safe_alloc(strlen(p)+strlen(DIR_SEPARATOR_STRING)+strlen("pic")+1);
152     if(p2!=NULL)
153     {
154         strcpy(p2, p);
155         strcat(p2, DIR_SEPARATOR_STRING);
156         strcat(p2, "pic");
157         addSetHead(&includeDirsSet, p2);
158     }
159   }
160 }
161
162 static void
163 _pic14_finaliseOptions (void)
164 {
165   pCodeInitRegisters();
166   
167   port->mem.default_local_map = data;
168   port->mem.default_globl_map = data;
169 #if 0
170   /* Hack-o-matic: if we are using the flat24 model,
171   * adjust pointer sizes.
172   */
173   if (options.model == MODEL_FLAT24)
174   {
175     
176     fprintf (stderr, "*** WARNING: you should use the '-mds390' option "
177       "for DS80C390 support. This code generator is "
178       "badly out of date and probably broken.\n");
179     
180     port->s.fptr_size = 3;
181     port->s.gptr_size = 4;
182     port->stack.isr_overhead++; /* Will save dpx on ISR entry. */
183 #if 1
184     port->stack.call_overhead++;  /* This acounts for the extra byte 
185                                      * of return addres on the stack.
186                                      * but is ugly. There must be a 
187                                      * better way.
188                                      */
189 #endif
190     fReturn = fReturn390;
191     fReturnSize = 5;
192   }
193   
194   if (options.model == MODEL_LARGE)
195   {
196     port->mem.default_local_map = xdata;
197     port->mem.default_globl_map = xdata;
198   }
199   else
200   {
201     port->mem.default_local_map = data;
202     port->mem.default_globl_map = data;
203   }
204   
205   if (options.stack10bit)
206   {
207     if (options.model != MODEL_FLAT24)
208     {
209       fprintf (stderr,
210         "*** warning: 10 bit stack mode is only supported in flat24 model.\n");
211       fprintf (stderr, "\t10 bit stack mode disabled.\n");
212       options.stack10bit = 0;
213     }
214     else
215     {
216     /* Fixup the memory map for the stack; it is now in
217     * far space and requires a FPOINTER to access it.
218     */
219       istack->fmap = 1;
220       istack->ptrType = FPOINTER;
221     }
222   }
223 #endif
224 }
225
226 static void
227 _pic14_setDefaultOptions (void)
228 {
229 }
230
231 static const char *
232 _pic14_getRegName (struct regs *reg)
233 {
234   if (reg)
235     return reg->name;
236   return "err";
237 }
238
239 extern char *processor_base_name(void);
240
241 static void
242 _pic14_genAssemblerPreamble (FILE * of)
243 {
244   char * name = processor_base_name();
245   
246   if(!name) {
247     
248     name = "16f877";
249     fprintf(stderr,"WARNING: No Pic has been selected, defaulting to %s\n",name);
250   }
251   
252   fprintf (of, "\tlist\tp=%s\n",name);
253   fprintf (of, "\tradix dec\n");
254   fprintf (of, "\tinclude \"p%s.inc\"\n",name);
255 }
256
257 /* Generate interrupt vector table. */
258 static int
259 _pic14_genIVT (struct dbuf_s * oBuf, symbol ** interrupts, int maxInterrupts)
260 {
261   int i;
262   
263   if (options.model != MODEL_FLAT24)
264   {
265     /* Let the default code handle it. */
266     return FALSE;
267   }
268   
269   dbuf_printf (oBuf, "\t;ajmp\t__sdcc_gsinit_startup\n");
270   
271   /* now for the other interrupts */
272   for (i = 0; i < maxInterrupts; i++)
273   {
274     if (interrupts[i])
275     {
276       dbuf_printf (oBuf, "\t;ljmp\t%s\n\t.ds\t4\n", interrupts[i]->rname);
277     }
278     else
279     {
280       dbuf_printf (oBuf, "\t;reti\n\t.ds\t7\n");
281     }
282   }
283   
284   return TRUE;
285 }
286
287 static bool
288 _hasNativeMulFor (iCode *ic, sym_link *left, sym_link *right)
289 {
290 /*
291 sym_link *test = NULL;
292 value *val;
293   */
294   
295   //fprintf(stderr,"checking for native mult\n");
296   
297   if ( ic->op != '*')
298   {
299     return FALSE;
300   }
301   
302   /* multiply chars in-place */
303   if (getSize(left) == 1 && getSize(right) == 1)
304     return TRUE;
305   
306   /* use library functions for more complex maths */
307   return FALSE;
308
309   /*
310   if ( IS_LITERAL (left))
311   {
312   fprintf(stderr,"left is lit\n");
313   test = left;
314   val = OP_VALUE (IC_LEFT (ic));
315   }
316   else if ( IS_LITERAL (right))
317   {
318   fprintf(stderr,"right is lit\n");
319   test = left;
320   val = OP_VALUE (IC_RIGHT (ic));
321   }
322   else
323   {
324   fprintf(stderr,"oops, neither is lit so no\n");
325   return FALSE;
326   }
327   
328     if ( getSize (test) <= 2)
329     {
330     fprintf(stderr,"yep\n");
331     return TRUE;
332     }
333     fprintf(stderr,"nope\n");
334     
335     return FALSE;
336   */
337 }
338
339 /* Indicate which extended bit operations this port supports */
340 static bool
341 hasExtBitOp (int op, int size)
342 {
343   if (op == RRC
344     || op == RLC
345     /* || op == GETHBIT */ /* GETHBIT doesn't look complete for PIC */
346     )
347     return TRUE;
348   else
349     return FALSE;
350 }
351
352 /* Indicate the expense of an access to an output storage class */
353 static int
354 oclsExpense (struct memmap *oclass)
355 {
356   /* The IN_FARSPACE test is compatible with historical behaviour, */
357   /* but I don't think it is applicable to PIC. If so, please feel */
358   /* free to remove this test -- EEP */
359   if (IN_FARSPACE(oclass))
360     return 1;
361
362   return 0;
363 }
364
365 /** $1 is always the basename.
366     $2 is always the output file.
367     $3 varies
368     $l is the list of extra options that should be there somewhere...
369     MUST be terminated with a NULL.
370 */
371 static const char *_linkCmd[] =
372 {
373   "gplink", "$l", "-w", "-r", "-o \"$2\"", "\"$1\"", "$3", NULL
374 };
375
376 static const char *_asmCmd[] =
377 {
378   "gpasm", "$l", "-c", "\"$1.asm\"", NULL
379     
380 };
381
382 extern set *libFilesSet;
383 extern set *libDirsSet;
384 extern set *libPathsSet;
385 extern set *includeDirsSet;
386 extern set *userIncDirsSet;
387 extern set *dataDirsSetSet;
388 extern set *relFilesSet;
389 extern set *linkOptionsSet;
390
391 static void _pic14_do_link (void)
392 {
393   hTab *linkValues=NULL;
394   char lfrm[256];
395   char *lcmd;
396   char temp[128];
397   set *tSet=NULL;
398   int ret;
399   char * procName;
400   
401   /*
402    * link command format:
403    * {linker} {incdirs} {lflags} -o {outfile} {spec_ofiles} {ofiles} {libs}
404    *
405    */
406
407   sprintf(lfrm, "{linker} {incdirs} {sysincdirs} {lflags} -w -r -o {outfile} {user_ofile} {spec_ofiles} {ofiles} {libs}");
408
409   shash_add(&linkValues, "linker", "gplink");
410
411   /* LIBRARY SEARCH DIRS */
412   mergeSets(&tSet, libPathsSet);
413   mergeSets(&tSet, libDirsSet);
414   shash_add(&linkValues, "incdirs", joinStrSet(appendStrSet(tSet, "-I\"", "\"")));
415
416   SNPRINTF (&temp[0], 128, "%cpic\"", DIR_SEPARATOR_CHAR);
417   joinStrSet(appendStrSet(libDirsSet, "-I\"", &temp[0]));
418   shash_add(&linkValues, "sysincdirs", joinStrSet(appendStrSet(libDirsSet, "-I\"", &temp[0])));
419   
420   shash_add(&linkValues, "lflags", joinStrSet(linkOptionsSet));
421
422   shash_add(&linkValues, "outfile", fullDstFileName ? fullDstFileName : dstFileName);
423
424   if(fullSrcFileName) {
425     sprintf(temp, "%s.o", fullDstFileName ? fullDstFileName : dstFileName );
426     shash_add(&linkValues, "user_ofile", temp);
427   }
428
429   shash_add(&linkValues, "ofiles", joinStrSet(relFilesSet));
430
431   /* LIBRARIES */
432   procName = processor_base_name();
433   if (!procName) {
434      procName = "16f877";
435   }
436
437   addSet(&libFilesSet, "libsdcc.lib");
438   SNPRINTF(&temp[0], 128, "pic%s.lib", procName);
439   addSet(&libFilesSet, temp);
440   shash_add(&linkValues, "libs", joinStrSet(libFilesSet));
441
442   lcmd = msprintf(linkValues, lfrm);
443
444   ret = my_system( lcmd );
445
446   Safe_free( lcmd );
447
448   if(ret)
449     exit(1);
450 }
451
452 /* Globals */
453 PORT pic_port =
454 {
455   TARGET_ID_PIC,
456   "pic14",
457   "MCU pic",        /* Target name */
458   "",               /* Processor */
459   {
460     picglue,
461     TRUE,     /* Emit glue around main */
462     MODEL_SMALL | MODEL_LARGE | MODEL_FLAT24,
463     MODEL_SMALL
464   },
465   {
466     _asmCmd,
467     NULL,
468     NULL,
469     NULL,
470     //"-plosgffc",  /* Options with debug */
471     //"-plosgff",   /* Options without debug */
472     0,
473     ".asm",
474     NULL            /* no do_assemble function */
475   },
476   {
477     _linkCmd,
478     NULL,
479     _pic14_do_link, /* own do link function */
480     ".o",
481     0
482   },
483   {
484     _defaultRules
485   },
486   {
487     /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
488     1, 2, 2, 4, 2, 2, 3, 1, 4, 4
489     /* TSD - I changed the size of gptr from 3 to 1. However, it should be
490        2 so that we can accomodate the PIC's with 4 register banks (like the
491        16f877)
492      */
493   },
494   /* tags for generic pointers */
495   { 0x00, 0x00, 0x00, 0x80 },   /* far, near, xstack, code */
496   {
497     "XSEG    (XDATA)",
498     "STACK   (DATA)",
499     "code",
500     "DSEG    (DATA)",
501     "ISEG    (DATA)",
502     NULL, /* pdata */
503     "XSEG    (XDATA)",
504     "BSEG    (BIT)",
505     "RSEG    (DATA)",
506     "GSINIT  (CODE)",
507     "udata_ovr",
508     "GSFINAL (CODE)",
509     "HOME        (CODE)",
510     NULL, // xidata
511     NULL, // xinit
512     "CONST   (CODE)",   // const_name - const data (code or not)
513     "CABS    (ABS,CODE)", // cabs_name - const absolute data (code or not)
514     "XABS    (ABS,XDATA)",  // xabs_name - absolute xdata
515     "IABS    (ABS,DATA)", // iabs_name - absolute data
516     NULL,
517     NULL,
518     1        // code is read only
519   },
520   { NULL, NULL },
521   {
522     +1, 1, 4, 1, 1, 0
523   },
524     /* pic14 has an 8 bit mul */
525   {
526     1, -1
527   },
528   {
529     pic14_emitDebuggerSymbol
530   },
531   {
532     255/3,      /* maxCount */
533     3,          /* sizeofElement */
534     /* The rest of these costs are bogus. They approximate */
535     /* the behavior of src/SDCCicode.c 1.207 and earlier.  */
536     {4,4,4},    /* sizeofMatchJump[] */
537     {0,0,0},    /* sizeofRangeCompare[] */
538     0,          /* sizeofSubtract */
539     3,          /* sizeofDispatch */
540   },
541   "_",
542   _pic14_init,
543   _pic14_parseOptions,
544   _pic14_poptions,
545   _pic14_initPaths,
546   _pic14_finaliseOptions,
547   _pic14_setDefaultOptions,
548   pic14_assignRegisters,
549   _pic14_getRegName,
550   _pic14_keywords,
551   _pic14_genAssemblerPreamble,
552   NULL,         /* no genAssemblerEnd */
553   _pic14_genIVT,
554   NULL, // _pic14_genXINIT
555   NULL,         /* genInitStartup */
556   _pic14_reset_regparm,
557   _pic14_regparm,
558   NULL,         /* process a pragma */
559   NULL,
560   _hasNativeMulFor,
561   hasExtBitOp,  /* hasExtBitOp */
562   oclsExpense,  /* oclsExpense */
563   FALSE,
564 //  TRUE,       /* little endian */
565   FALSE,        /* little endian - PIC code enumlates big endian */
566   0,            /* leave lt */
567   0,            /* leave gt */
568   1,            /* transform <= to ! > */
569   1,            /* transform >= to ! < */
570   1,            /* transform != to !(a == b) */
571   0,            /* leave == */
572   FALSE,        /* No array initializer support. */
573   0,            /* no CSE cost estimation yet */
574   NULL,         /* no builtin functions */
575   GPOINTER,     /* treat unqualified pointers as "generic" pointers */
576   1,            /* reset labelKey to 1 */
577   1,            /* globals & local static allowed */
578   PORT_MAGIC
579 };