handling space characters in file path
[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 "gen.h"
13
14
15 static char _defaultRules[] =
16 {
17 #include "peeph.rul"
18 };
19
20 /* list of key words used by msc51 */
21 static char *_pic14_keywords[] =
22 {
23   "at",
24   "bit",
25   "code",
26   "critical",
27   "data",
28   "far",
29   "idata",
30   "interrupt",
31   "near",
32   "pdata",
33   "reentrant",
34   "sfr",
35   "sbit",
36   "using",
37   "xdata",
38   "_data",
39   "_code",
40   "_generic",
41   "_near",
42   "_xdata",
43   "_pdata",
44   "_idata",
45   NULL
46 };
47
48 void  pCodeInitRegisters(void);
49
50 void pic14_assignRegisters (eBBlock ** ebbs, int count);
51
52 static int regParmFlg = 0;      /* determine if we can register a parameter */
53
54 static void
55 _pic14_init (void)
56 {
57   asm_addTree (&asm_asxxxx_mapping);
58   pCodeInitRegisters();
59 }
60
61 static void
62 _pic14_reset_regparm ()
63 {
64   regParmFlg = 0;
65 }
66
67 static int
68 _pic14_regparm (sym_link * l)
69 {
70   /* for this processor it is simple
71      can pass only the first parameter in a register */
72   //if (regParmFlg)
73   //  return 0;
74
75   regParmFlg++;// = 1;
76   return 1;
77 }
78
79 static int
80 _process_pragma(const char *sz)
81 {
82   static const char *WHITE = " \t";
83   char  *ptr = strtok((char *)sz, WHITE);
84
85   if (startsWith (ptr, "memmap"))
86     {
87       char      *start;
88       char      *end;
89       char      *type;
90       char      *alias;
91
92       start = strtok((char *)NULL, WHITE);
93       end = strtok((char *)NULL, WHITE);
94       type = strtok((char *)NULL, WHITE);
95       alias = strtok((char *)NULL, WHITE);
96
97       if (start != (char *)NULL
98           && end != (char *)NULL
99           && type != (char *)NULL) {
100         value           *startVal = constVal(start);
101         value           *endVal = constVal(end);
102         value           *aliasVal;
103         memRange        r;
104
105         if (alias == (char *)NULL) {
106           aliasVal = constVal(0);
107         } else {
108           aliasVal = constVal(alias);
109         }
110
111         r.start_address = (int)floatFromVal(startVal);
112         r.end_address = (int)floatFromVal(endVal);
113         r.alias = (int)floatFromVal(aliasVal);
114         r.bank = (r.start_address >> 7) & 3;
115
116         if (strcmp(type, "RAM") == 0) {
117           addMemRange(&r, 0);
118         } else if (strcmp(type, "SFR") == 0) {
119           addMemRange(&r, 1);
120         } else {
121           return 1;
122         }
123       }
124
125       return 0;
126     } else if (startsWith (ptr, "maxram")) {
127       char *maxRAM = strtok((char *)NULL, WHITE);
128
129       if (maxRAM != (char *)NULL) {
130         int     maxRAMaddress;
131         value   *maxRAMVal;
132
133         maxRAMVal = constVal(maxRAM);
134         maxRAMaddress = (int)floatFromVal(maxRAMVal);
135         setMaxRAM(maxRAMaddress);
136       }
137         
138       return 0;
139     }
140   return 1;
141 }
142
143 static bool
144 _pic14_parseOptions (int *pargc, char **argv, int *i)
145 {
146   /* TODO: allow port-specific command line options to specify
147    * segment names here.
148    */
149   return FALSE;
150 }
151
152 static void
153 _pic14_finaliseOptions (void)
154 {
155
156       port->mem.default_local_map = data;
157       port->mem.default_globl_map = data;
158 #if 0
159   /* Hack-o-matic: if we are using the flat24 model,
160    * adjust pointer sizes.
161    */
162   if (options.model == MODEL_FLAT24)
163     {
164
165       fprintf (stderr, "*** WARNING: you should use the '-mds390' option "
166                "for DS80C390 support. This code generator is "
167                "badly out of date and probably broken.\n");
168
169       port->s.fptr_size = 3;
170       port->s.gptr_size = 4;
171       port->stack.isr_overhead++;       /* Will save dpx on ISR entry. */
172 #if 1
173       port->stack.call_overhead++;      /* This acounts for the extra byte 
174                                          * of return addres on the stack.
175                                          * but is ugly. There must be a 
176                                          * better way.
177                                          */
178 #endif
179       fReturn = fReturn390;
180       fReturnSize = 5;
181     }
182
183   if (options.model == MODEL_LARGE)
184     {
185       port->mem.default_local_map = xdata;
186       port->mem.default_globl_map = xdata;
187     }
188   else
189     {
190       port->mem.default_local_map = data;
191       port->mem.default_globl_map = data;
192     }
193
194   if (options.stack10bit)
195     {
196       if (options.model != MODEL_FLAT24)
197         {
198           fprintf (stderr,
199                    "*** warning: 10 bit stack mode is only supported in flat24 model.\n");
200           fprintf (stderr, "\t10 bit stack mode disabled.\n");
201           options.stack10bit = 0;
202         }
203       else
204         {
205           /* Fixup the memory map for the stack; it is now in
206            * far space and requires a FPOINTER to access it.
207            */
208           istack->fmap = 1;
209           istack->ptrType = FPOINTER;
210         }
211     }
212 #endif
213 }
214
215 static void
216 _pic14_setDefaultOptions (void)
217 {
218 }
219
220 static const char *
221 _pic14_getRegName (struct regs *reg)
222 {
223   if (reg)
224     return reg->name;
225   return "err";
226 }
227
228 extern char *processor_base_name(void);
229
230 static void
231 _pic14_genAssemblerPreamble (FILE * of)
232 {
233   char * name = processor_base_name();
234
235   if(!name) {
236
237     name = "p16f877";
238     fprintf(stderr,"WARNING: No Pic has been selected, defaulting to %s\n",name);
239   }
240
241   fprintf (of, "\tlist\tp=%s\n",&name[1]);
242   fprintf (of, "\t__CONFIG 0x%x\n",getConfigWord(0x2007));
243   fprintf (of, "\tradix dec");
244   fprintf (of, "\ninclude \"%s.inc\"\n",name);
245 }
246
247 /* Generate interrupt vector table. */
248 static int
249 _pic14_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts)
250 {
251   int i;
252
253   if (options.model != MODEL_FLAT24)
254     {
255       /* Let the default code handle it. */
256       return FALSE;
257     }
258
259   fprintf (of, "\t;ajmp\t__sdcc_gsinit_startup\n");
260
261   /* now for the other interrupts */
262   for (i = 0; i < maxInterrupts; i++)
263     {
264       if (interrupts[i])
265         {
266           fprintf (of, "\t;ljmp\t%s\n\t.ds\t4\n", interrupts[i]->rname);
267         }
268       else
269         {
270           fprintf (of, "\t;reti\n\t.ds\t7\n");
271         }
272     }
273
274   return TRUE;
275 }
276
277 static bool
278 _hasNativeMulFor (iCode *ic, sym_link *left, sym_link *right)
279 {
280 /*
281   sym_link *test = NULL;
282   value *val;
283 */
284
285   fprintf(stderr,"checking for native mult\n");
286
287   if ( ic->op != '*')
288     {
289       return FALSE;
290     }
291
292   return TRUE;
293 /*
294   if ( IS_LITERAL (left))
295     {
296       fprintf(stderr,"left is lit\n");
297       test = left;
298       val = OP_VALUE (IC_LEFT (ic));
299     }
300   else if ( IS_LITERAL (right))
301     {
302       fprintf(stderr,"right is lit\n");
303       test = left;
304       val = OP_VALUE (IC_RIGHT (ic));
305     }
306   else
307     {
308       fprintf(stderr,"oops, neither is lit so no\n");
309       return FALSE;
310     }
311
312   if ( getSize (test) <= 2)
313     {
314       fprintf(stderr,"yep\n");
315       return TRUE;
316     }
317   fprintf(stderr,"nope\n");
318
319   return FALSE;
320 */
321 }
322
323 /** $1 is always the basename.
324     $2 is always the output file.
325     $3 varies
326     $l is the list of extra options that should be there somewhere...
327     MUST be terminated with a NULL.
328 */
329 static const char *_linkCmd[] =
330 {
331   "aslink", "-nf", "$1", NULL
332 };
333
334 /* Sigh. This really is not good. For now, I recommend:
335  * sdcc -S -mpic14 file.c
336  * the -S option does not compile or link
337  */
338 static const char *_asmCmd[] =
339 {
340   /* This should be:
341    * "gpasm", "-c  -I \"{datadir}\" -o \"$2\"", "\"$1.asm\"", NULL
342    * but unfortunately buildCmdLine() doesn't expand {xxx} macros.
343    */
344   "gpasm", "-c  -I \"/usr/local/share/gpasm/header\" -o \"$2\"", "\"$1.asm\"", NULL
345 };
346
347 /* Globals */
348 PORT pic_port =
349 {
350   TARGET_ID_PIC,
351   "pic14",
352   "MCU pic",                    /* Target name */
353   "p16f877",                    /* Processor */
354   {
355     TRUE,                       /* Emit glue around main */
356     MODEL_SMALL | MODEL_LARGE | MODEL_FLAT24,
357     MODEL_SMALL
358   },
359   {
360     _asmCmd,
361     NULL,
362     NULL,
363     NULL,
364         //"-plosgffc",          /* Options with debug */
365         //"-plosgff",           /* Options without debug */
366     0,
367     ".asm",
368     NULL                        /* no do_assemble function */
369   },
370   {
371     _linkCmd,
372     NULL,
373     NULL,
374     ".rel"
375   },
376   {
377     _defaultRules
378   },
379   {
380         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
381     1, 2, 2, 4, 2, 2, 2, 1, 4, 4
382         /* TSD - I changed the size of gptr from 3 to 1. However, it should be
383            2 so that we can accomodate the PIC's with 4 register banks (like the
384            16f877)
385          */
386   },
387   {
388     "XSEG    (XDATA)",
389     "STACK   (DATA)",
390     "CSEG    (CODE)",
391     "DSEG    (DATA)",
392     "ISEG    (DATA)",
393     "XSEG    (XDATA)",
394     "BSEG    (BIT)",
395     "RSEG    (DATA)",
396     "GSINIT  (CODE)",
397     "OSEG    (OVR,DATA)",
398     "GSFINAL (CODE)",
399     "HOME        (CODE)",
400     NULL, // xidata
401     NULL, // xinit
402     NULL,
403     NULL,
404     1        // code is read only
405   },
406   {
407     +1, 1, 4, 1, 1, 0
408   },
409     /* pic14 has an 8 bit mul */
410   {
411     1, -1
412   },
413   "_",
414   _pic14_init,
415   _pic14_parseOptions,
416   NULL,
417   _pic14_finaliseOptions,
418   _pic14_setDefaultOptions,
419   pic14_assignRegisters,
420   _pic14_getRegName,
421   _pic14_keywords,
422   _pic14_genAssemblerPreamble,
423   NULL,                         /* no genAssemblerEnd */
424   _pic14_genIVT,
425   NULL, // _pic14_genXINIT
426   _pic14_reset_regparm,
427   _pic14_regparm,
428   _process_pragma,                              /* process a pragma */
429   NULL,
430   _hasNativeMulFor,
431   FALSE,
432   0,                            /* leave lt */
433   0,                            /* leave gt */
434   1,                            /* transform <= to ! > */
435   1,                            /* transform >= to ! < */
436   1,                            /* transform != to !(a == b) */
437   0,                            /* leave == */
438   FALSE,                        /* No array initializer support. */
439   0,                            /* no CSE cost estimation yet */
440   NULL,                         /* no builtin functions */
441   GPOINTER,                     /* treat unqualified pointers as "generic" pointers */
442   1,                            /* reset labelKey to 1 */
443   1,                            /* globals & local static allowed */
444   PORT_MAGIC
445 };