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