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