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