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