PIC16 - Applied patch from Vangelis Rokas. Many fixes for the PIC16 port.
[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, "\tradix dec");
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 /*
280   sym_link *test = NULL;
281   value *val;
282 */
283
284   fprintf(stderr,"checking for native mult\n");
285
286   if ( ic->op != '*')
287     {
288       return FALSE;
289     }
290
291   return TRUE;
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 /** $1 is always the basename.
323     $2 is always the output file.
324     $3 varies
325     $l is the list of extra options that should be there somewhere...
326     MUST be terminated with a NULL.
327 */
328 static const char *_linkCmd[] =
329 {
330   "gplink", "", "\"$1.o\"", NULL
331 };
332
333 static const char *_asmCmd[] =
334 {
335   "gpasm", "-c", "\"$1.asm\"", NULL
336
337 };
338
339 /* Globals */
340 PORT pic_port =
341 {
342   TARGET_ID_PIC,
343   "pic14",
344   "MCU pic",                    /* Target name */
345   "",                    /* Processor */
346   {
347     TRUE,                       /* Emit glue around main */
348     MODEL_SMALL | MODEL_LARGE | MODEL_FLAT24,
349     MODEL_SMALL
350   },
351   {
352     _asmCmd,
353     NULL,
354     NULL,
355     NULL,
356         //"-plosgffc",          /* Options with debug */
357         //"-plosgff",           /* Options without debug */
358     0,
359     ".asm",
360     NULL                        /* no do_assemble function */
361   },
362   {
363     _linkCmd,
364     NULL,
365     NULL,
366     ".o"
367   },
368   {
369     _defaultRules
370   },
371   {
372         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
373     1, 2, 2, 4, 2, 2, 2, 1, 4, 4
374         /* TSD - I changed the size of gptr from 3 to 1. However, it should be
375            2 so that we can accomodate the PIC's with 4 register banks (like the
376            16f877)
377          */
378   },
379   {
380     "XSEG    (XDATA)",
381     "STACK   (DATA)",
382     "code",
383     "DSEG    (DATA)",
384     "ISEG    (DATA)",
385     "XSEG    (XDATA)",
386     "BSEG    (BIT)",
387     "RSEG    (DATA)",
388     "GSINIT  (CODE)",
389     "udata_ovr",
390     "GSFINAL (CODE)",
391     "HOME        (CODE)",
392     NULL, // xidata
393     NULL, // xinit
394     NULL,
395     NULL,
396     1        // code is read only
397   },
398   {
399     +1, 1, 4, 1, 1, 0
400   },
401     /* pic14 has an 8 bit mul */
402   {
403     1, -1
404   },
405   "_",
406   _pic14_init,
407   _pic14_parseOptions,
408   NULL,
409   _pic14_finaliseOptions,
410   _pic14_setDefaultOptions,
411   pic14_assignRegisters,
412   _pic14_getRegName,
413   _pic14_keywords,
414   _pic14_genAssemblerPreamble,
415   NULL,                         /* no genAssemblerEnd */
416   _pic14_genIVT,
417   NULL, // _pic14_genXINIT
418   _pic14_reset_regparm,
419   _pic14_regparm,
420   _process_pragma,                              /* process a pragma */
421   NULL,
422   _hasNativeMulFor,
423   FALSE,
424   0,                            /* leave lt */
425   0,                            /* leave gt */
426   1,                            /* transform <= to ! > */
427   1,                            /* transform >= to ! < */
428   1,                            /* transform != to !(a == b) */
429   0,                            /* leave == */
430   FALSE,                        /* No array initializer support. */
431   0,                            /* no CSE cost estimation yet */
432   NULL,                         /* no builtin functions */
433   GPOINTER,                     /* treat unqualified pointers as "generic" pointers */
434   1,                            /* reset labelKey to 1 */
435   1,                            /* globals & local static allowed */
436   PORT_MAGIC
437 };