Changes to support big endian targets:
[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 "glue.h"
13 //#include "gen.h"
14
15
16 static char _defaultRules[] =
17 {
18 #include "peeph.rul"
19 };
20
21 /* list of key words used by msc51 */
22 static char *_pic14_keywords[] =
23 {
24   "at",
25   "bit",
26   "code",
27   "critical",
28   "data",
29   "far",
30   "idata",
31   "interrupt",
32   "near",
33   "pdata",
34   "reentrant",
35   "sfr",
36   "sbit",
37   "using",
38   "xdata",
39   "_data",
40   "_code",
41   "_generic",
42   "_near",
43   "_xdata",
44   "_pdata",
45   "_idata",
46   NULL
47 };
48
49 void  pCodeInitRegisters(void);
50
51 void pic14_assignRegisters (eBBlock ** ebbs, int count);
52
53 static int regParmFlg = 0;      /* determine if we can register a parameter */
54
55 static void
56 _pic14_init (void)
57 {
58   asm_addTree (&asm_asxxxx_mapping);
59   pCodeInitRegisters();
60 }
61
62 static void
63 _pic14_reset_regparm ()
64 {
65   regParmFlg = 0;
66 }
67
68 static int
69 _pic14_regparm (sym_link * l)
70 {
71   /* for this processor it is simple
72      can pass only the first parameter in a register */
73   //if (regParmFlg)
74   //  return 0;
75
76   regParmFlg++;// = 1;
77   return 1;
78 }
79
80 static int
81 _process_pragma(const char *sz)
82 {
83   static const char *WHITE = " \t";
84   char  *ptr = strtok((char *)sz, WHITE);
85
86   if (startsWith (ptr, "memmap"))
87     {
88       char      *start;
89       char      *end;
90       char      *type;
91       char      *alias;
92
93       start = strtok((char *)NULL, WHITE);
94       end = strtok((char *)NULL, WHITE);
95       type = strtok((char *)NULL, WHITE);
96       alias = strtok((char *)NULL, WHITE);
97
98       if (start != (char *)NULL
99           && end != (char *)NULL
100           && type != (char *)NULL) {
101         value           *startVal = constVal(start);
102         value           *endVal = constVal(end);
103         value           *aliasVal;
104         memRange        r;
105
106         if (alias == (char *)NULL) {
107           aliasVal = constVal(0);
108         } else {
109           aliasVal = constVal(alias);
110         }
111
112         r.start_address = (int)floatFromVal(startVal);
113         r.end_address = (int)floatFromVal(endVal);
114         r.alias = (int)floatFromVal(aliasVal);
115         r.bank = (r.start_address >> 7) & 3;
116
117         if (strcmp(type, "RAM") == 0) {
118           addMemRange(&r, 0);
119         } else if (strcmp(type, "SFR") == 0) {
120           addMemRange(&r, 1);
121         } else {
122           return 1;
123         }
124       }
125
126       return 0;
127     } else if (startsWith (ptr, "maxram")) {
128       char *maxRAM = strtok((char *)NULL, WHITE);
129
130       if (maxRAM != (char *)NULL) {
131         int     maxRAMaddress;
132         value   *maxRAMVal;
133
134         maxRAMVal = constVal(maxRAM);
135         maxRAMaddress = (int)floatFromVal(maxRAMVal);
136         setMaxRAM(maxRAMaddress);
137       }
138         
139       return 0;
140     }
141   return 1;
142 }
143
144 static bool
145 _pic14_parseOptions (int *pargc, char **argv, int *i)
146 {
147   /* TODO: allow port-specific command line options to specify
148    * segment names here.
149    */
150   return FALSE;
151 }
152
153 static void
154 _pic14_finaliseOptions (void)
155 {
156
157       port->mem.default_local_map = data;
158       port->mem.default_globl_map = data;
159 #if 0
160   /* Hack-o-matic: if we are using the flat24 model,
161    * adjust pointer sizes.
162    */
163   if (options.model == MODEL_FLAT24)
164     {
165
166       fprintf (stderr, "*** WARNING: you should use the '-mds390' option "
167                "for DS80C390 support. This code generator is "
168                "badly out of date and probably broken.\n");
169
170       port->s.fptr_size = 3;
171       port->s.gptr_size = 4;
172       port->stack.isr_overhead++;       /* Will save dpx on ISR entry. */
173 #if 1
174       port->stack.call_overhead++;      /* This acounts for the extra byte 
175                                          * of return addres on the stack.
176                                          * but is ugly. There must be a 
177                                          * better way.
178                                          */
179 #endif
180       fReturn = fReturn390;
181       fReturnSize = 5;
182     }
183
184   if (options.model == MODEL_LARGE)
185     {
186       port->mem.default_local_map = xdata;
187       port->mem.default_globl_map = xdata;
188     }
189   else
190     {
191       port->mem.default_local_map = data;
192       port->mem.default_globl_map = data;
193     }
194
195   if (options.stack10bit)
196     {
197       if (options.model != MODEL_FLAT24)
198         {
199           fprintf (stderr,
200                    "*** warning: 10 bit stack mode is only supported in flat24 model.\n");
201           fprintf (stderr, "\t10 bit stack mode disabled.\n");
202           options.stack10bit = 0;
203         }
204       else
205         {
206           /* Fixup the memory map for the stack; it is now in
207            * far space and requires a FPOINTER to access it.
208            */
209           istack->fmap = 1;
210           istack->ptrType = FPOINTER;
211         }
212     }
213 #endif
214 }
215
216 static void
217 _pic14_setDefaultOptions (void)
218 {
219 }
220
221 static const char *
222 _pic14_getRegName (struct regs *reg)
223 {
224   if (reg)
225     return reg->name;
226   return "err";
227 }
228
229 extern char *processor_base_name(void);
230
231 static void
232 _pic14_genAssemblerPreamble (FILE * of)
233 {
234   char * name = processor_base_name();
235
236   if(!name) {
237
238     name = "p16f877";
239     fprintf(stderr,"WARNING: No Pic has been selected, defaulting to %s\n",name);
240   }
241
242   fprintf (of, "\tlist\tp=%s\n",&name[1]);
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   "gplink", "", "\"$1.o\"", NULL
332 };
333
334 static const char *_asmCmd[] =
335 {
336   "gpasm", "-c", "\"$1.asm\"", NULL
337
338 };
339
340 /* Globals */
341 PORT pic_port =
342 {
343   TARGET_ID_PIC,
344   "pic14",
345   "MCU pic",                    /* Target name */
346   "",                    /* Processor */
347   {
348     picglue,
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     ".o"
369   },
370   {
371     _defaultRules
372   },
373   {
374         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
375     1, 2, 2, 4, 2, 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     "code",
385     "DSEG    (DATA)",
386     "ISEG    (DATA)",
387     "XSEG    (XDATA)",
388     "BSEG    (BIT)",
389     "RSEG    (DATA)",
390     "GSINIT  (CODE)",
391     "udata_ovr",
392     "GSFINAL (CODE)",
393     "HOME        (CODE)",
394     NULL, // xidata
395     NULL, // xinit
396     NULL,
397     NULL,
398     1        // code is read only
399   },
400   { NULL, NULL },
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   TRUE,                         /* little endian */
428   0,                            /* leave lt */
429   0,                            /* leave gt */
430   1,                            /* transform <= to ! > */
431   1,                            /* transform >= to ! < */
432   1,                            /* transform != to !(a == b) */
433   0,                            /* leave == */
434   FALSE,                        /* No array initializer support. */
435   0,                            /* no CSE cost estimation yet */
436   NULL,                         /* no builtin functions */
437   GPOINTER,                     /* treat unqualified pointers as "generic" pointers */
438   1,                            /* reset labelKey to 1 */
439   1,                            /* globals & local static allowed */
440   PORT_MAGIC
441 };