Interrupt context registers WSAVE and SSAVE were not getting allocated.
[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   sym_link *test = NULL;
281   value *val;
282
283   fprintf(stderr,"checking for native mult\n");
284
285   if ( ic->op != '*')
286     {
287       return FALSE;
288     }
289
290   return TRUE;
291 /*
292   if ( IS_LITERAL (left))
293     {
294       fprintf(stderr,"left is lit\n");
295       test = left;
296       val = OP_VALUE (IC_LEFT (ic));
297     }
298   else if ( IS_LITERAL (right))
299     {
300       fprintf(stderr,"right is lit\n");
301       test = left;
302       val = OP_VALUE (IC_RIGHT (ic));
303     }
304   else
305     {
306       fprintf(stderr,"oops, neither is lit so no\n");
307       return FALSE;
308     }
309
310   if ( getSize (test) <= 2)
311     {
312       fprintf(stderr,"yep\n");
313       return TRUE;
314     }
315   fprintf(stderr,"nope\n");
316
317   return FALSE;
318 */
319 }
320
321 /** $1 is always the basename.
322     $2 is always the output file.
323     $3 varies
324     $l is the list of extra options that should be there somewhere...
325     MUST be terminated with a NULL.
326 */
327 static const char *_linkCmd[] =
328 {
329   "aslink", "-nf", "$1", NULL
330 };
331
332 /* Sigh. This really is not good. For now, I recommend:
333  * sdcc -S -mpic14 file.c
334  * the -S option does not compile or link
335  */
336 static const char *_asmCmd[] =
337 {
338   "gpasm", "-c  -I /usr/local/share/gpasm/header", "$1.asm", NULL
339
340 };
341
342 /* Globals */
343 PORT pic_port =
344 {
345   TARGET_ID_PIC,
346   "pic14",
347   "MCU pic",                    /* Target name */
348   "p16f877",                    /* Processor */
349   {
350     TRUE,                       /* Emit glue around main */
351     MODEL_SMALL | MODEL_LARGE | MODEL_FLAT24,
352     MODEL_SMALL
353   },
354   {
355     _asmCmd,
356     NULL,
357     NULL,
358     NULL,
359         //"-plosgffc",          /* Options with debug */
360         //"-plosgff",           /* Options without debug */
361     0,
362     ".asm",
363     NULL                        /* no do_assemble function */
364   },
365   {
366     _linkCmd,
367     NULL,
368     NULL,
369     ".rel"
370   },
371   {
372     _defaultRules
373   },
374   {
375         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
376     1, 2, 2, 4, 1, 2, 2, 1, 4, 4
377         /* TSD - I changed the size of gptr from 3 to 1. However, it should be
378            2 so that we can accomodate the PIC's with 4 register banks (like the
379            16f877)
380          */
381   },
382   {
383     "XSEG    (XDATA)",
384     "STACK   (DATA)",
385     "CSEG    (CODE)",
386     "DSEG    (DATA)",
387     "ISEG    (DATA)",
388     "XSEG    (XDATA)",
389     "BSEG    (BIT)",
390     "RSEG    (DATA)",
391     "GSINIT  (CODE)",
392     "OSEG    (OVR,DATA)",
393     "GSFINAL (CODE)",
394     "HOME        (CODE)",
395     NULL, // xidata
396     NULL, // xinit
397     NULL,
398     NULL,
399     1        // code is read only
400   },
401   {
402     +1, 1, 4, 1, 1, 0
403   },
404     /* pic14 has an 8 bit mul */
405   {
406     1, -1
407   },
408   "_",
409   _pic14_init,
410   _pic14_parseOptions,
411   NULL,
412   _pic14_finaliseOptions,
413   _pic14_setDefaultOptions,
414   pic14_assignRegisters,
415   _pic14_getRegName,
416   _pic14_keywords,
417   _pic14_genAssemblerPreamble,
418   NULL,                         /* no genAssemblerEnd */
419   _pic14_genIVT,
420   NULL, // _pic14_genXINIT
421   _pic14_reset_regparm,
422   _pic14_regparm,
423   _process_pragma,                              /* process a pragma */
424   NULL,
425   _hasNativeMulFor,
426   FALSE,
427   0,                            /* leave lt */
428   0,                            /* leave gt */
429   1,                            /* transform <= to ! > */
430   1,                            /* transform >= to ! < */
431   1,                            /* transform != to !(a == b) */
432   0,                            /* leave == */
433   FALSE,                        /* No array initializer support. */
434   0,                            /* no CSE cost estimation yet */
435   NULL,                         /* no builtin functions */
436   GPOINTER,                     /* treat unqualified pointers as "generic" pointers */
437   1,                            /* reset labelKey to 1 */
438   1,                            /* globals & local static allowed */
439   PORT_MAGIC
440 };