fix warning
[fw/sdcc] / src / pic16 / main.c
1 /** @file main.c
2     pic16 specific general functions.
3
4     Note that mlh prepended _pic16_ 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 pic16 */
22 static char *_pic16_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  pic16_pCodeInitRegisters(void);
50
51 void pic16_assignRegisters (eBBlock ** ebbs, int count);
52
53 static int regParmFlg = 0;      /* determine if we can register a parameter */
54
55 static void
56 _pic16_init (void)
57 {
58   asm_addTree (&asm_asxxxx_mapping);
59   pic16_pCodeInitRegisters();
60   maxInterrupts = 2;
61 }
62
63 static void
64 _pic16_reset_regparm ()
65 {
66   regParmFlg = 0;
67 }
68
69 static int
70 _pic16_regparm (sym_link * l)
71 {
72   /* for this processor it is simple
73      can pass only the first parameter in a register */
74   //if (regParmFlg)
75   //  return 0;
76
77   regParmFlg++;// = 1;
78   return 1;
79 }
80
81 static int
82 _process_pragma(const char *sz)
83 {
84   static const char *WHITE = " \t";
85   char  *ptr = strtok((char *)sz, WHITE);
86
87   if (startsWith (ptr, "memmap"))
88     {
89       char      *start;
90       char      *end;
91       char      *type;
92       char      *alias;
93
94       start = strtok((char *)NULL, WHITE);
95       end = strtok((char *)NULL, WHITE);
96       type = strtok((char *)NULL, WHITE);
97       alias = strtok((char *)NULL, WHITE);
98
99       if (start != (char *)NULL
100           && end != (char *)NULL
101           && type != (char *)NULL) {
102         value           *startVal = constVal(start);
103         value           *endVal = constVal(end);
104         value           *aliasVal;
105         memRange        r;
106
107         if (alias == (char *)NULL) {
108           aliasVal = constVal(0);
109         } else {
110           aliasVal = constVal(alias);
111         }
112
113         r.start_address = (int)floatFromVal(startVal);
114         r.end_address = (int)floatFromVal(endVal);
115         r.alias = (int)floatFromVal(aliasVal);
116         r.bank = (r.start_address >> 7) & 0xf;
117
118         if (strcmp(type, "RAM") == 0) {
119           pic16_addMemRange(&r, 0);
120         } else if (strcmp(type, "SFR") == 0) {
121           pic16_addMemRange(&r, 1);
122         } else {
123           return 1;
124         }
125       }
126
127       return 0;
128     } else if (startsWith (ptr, "maxram")) {
129       char *maxRAM = strtok((char *)NULL, WHITE);
130
131       if (maxRAM != (char *)NULL) {
132         int     maxRAMaddress;
133         value   *maxRAMVal;
134
135         maxRAMVal = constVal(maxRAM);
136         maxRAMaddress = (int)floatFromVal(maxRAMVal);
137         pic16_setMaxRAM(maxRAMaddress);
138       }
139         
140       return 0;
141     }
142   return 1;
143 }
144
145 static bool
146 _pic16_parseOptions (int *pargc, char **argv, int *i)
147 {
148   /* TODO: allow port-specific command line options to specify
149    * segment names here.
150    */
151   return FALSE;
152 }
153
154 static void
155 _pic16_finaliseOptions (void)
156 {
157
158       port->mem.default_local_map = data;
159       port->mem.default_globl_map = data;
160 #if 0
161   /* Hack-o-matic: if we are using the flat24 model,
162    * adjust pointer sizes.
163    */
164   if (options.model == MODEL_FLAT24)
165     {
166
167       fprintf (stderr, "*** WARNING: you should use the '-mds390' option "
168                "for DS80C390 support. This code generator is "
169                "badly out of date and probably broken.\n");
170
171       port->s.fptr_size = 3;
172       port->s.gptr_size = 4;
173       port->stack.isr_overhead++;       /* Will save dpx on ISR entry. */
174 #if 1
175       port->stack.call_overhead++;      /* This acounts for the extra byte 
176                                          * of return addres on the stack.
177                                          * but is ugly. There must be a 
178                                          * better way.
179                                          */
180 #endif
181       fReturn = fReturn390;
182       fReturnSize = 5;
183     }
184
185   if (options.model == MODEL_LARGE)
186     {
187       port->mem.default_local_map = xdata;
188       port->mem.default_globl_map = xdata;
189     }
190   else
191     {
192       port->mem.default_local_map = data;
193       port->mem.default_globl_map = data;
194     }
195
196   if (options.stack10bit)
197     {
198       if (options.model != MODEL_FLAT24)
199         {
200           fprintf (stderr,
201                    "*** warning: 10 bit stack mode is only supported in flat24 model.\n");
202           fprintf (stderr, "\t10 bit stack mode disabled.\n");
203           options.stack10bit = 0;
204         }
205       else
206         {
207           /* Fixup the memory map for the stack; it is now in
208            * far space and requires a FPOINTER to access it.
209            */
210           istack->fmap = 1;
211           istack->ptrType = FPOINTER;
212         }
213     }
214 #endif
215 }
216
217 static void
218 _pic16_setDefaultOptions (void)
219 {
220 }
221
222 static const char *
223 _pic16_getRegName (struct regs *reg)
224 {
225   if (reg)
226     return reg->name;
227   return "err";
228 }
229
230 extern char *pic16_processor_base_name(void);
231
232 static void
233 _pic16_genAssemblerPreamble (FILE * of)
234 {
235   char * name = pic16_processor_base_name();
236
237   if(!name) {
238
239     name = "p18f452";
240     fprintf(stderr,"WARNING: No Pic has been selected, defaulting to %s\n",name);
241   }
242
243   fprintf (of, "\tlist\tp=%s\n",&name[1]);
244   fprintf (of, "\tinclude \"%s.inc\"\n",name);
245
246 #if 0
247   fprintf (of, "\t__config _CONFIG1H,0x%x\n",pic16_getConfigWord(0x300001));
248   fprintf (of, "\t__config _CONFIG2L,0x%x\n",pic16_getConfigWord(0x300002));
249   fprintf (of, "\t__config _CONFIG2H,0x%x\n",pic16_getConfigWord(0x300003));
250   fprintf (of, "\t__config _CONFIG3H,0x%x\n",pic16_getConfigWord(0x300005));
251   fprintf (of, "\t__config _CONFIG4L,0x%x\n",pic16_getConfigWord(0x300006));
252   fprintf (of, "\t__config _CONFIG5L,0x%x\n",pic16_getConfigWord(0x300008));
253   fprintf (of, "\t__config _CONFIG5H,0x%x\n",pic16_getConfigWord(0x300009));
254   fprintf (of, "\t__config _CONFIG6L,0x%x\n",pic16_getConfigWord(0x30000a));
255   fprintf (of, "\t__config _CONFIG6H,0x%x\n",pic16_getConfigWord(0x30000b));
256   fprintf (of, "\t__config _CONFIG7L,0x%x\n",pic16_getConfigWord(0x30000c));
257   fprintf (of, "\t__config _CONFIG7H,0x%x\n",pic16_getConfigWord(0x30000d));
258 #endif
259
260   fprintf (of, "\tradix dec\n");
261 }
262
263 /* Generate interrupt vector table. */
264 static int
265 _pic16_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts)
266 {
267 #if 0
268   int i;
269 #endif
270
271 #if 0
272   if (options.model != MODEL_FLAT24)
273     {
274       /* Let the default code handle it. */
275       return FALSE;
276     }
277 #endif
278
279         /* PIC18F family has only two interrupts, the high and the low
280          * priority interrupts, which reside in 0x0008 and 0x0018 respectively */
281
282         fprintf(of, "; RESET vector\n");
283         fprintf(of, "\tgoto\t__sdcc_gsinit_startup\n");
284         fprintf(of, "\tres 2\n");
285
286
287         fprintf(of, "; High priority interrupt vector 0x0008\n");
288         
289         if(interrupts[1]) {
290                 fprintf(of, "\tgoto\t%s\n", interrupts[1]->rname);
291                 fprintf(of, "\tres\t6\n");
292         } else {
293                 fprintf(of, "\tretfie\n");
294                 fprintf(of, "\tres\t14\n");
295         }
296
297         fprintf(of, "; Low priority interrupt vector 0x0018\n");
298         if(interrupts[2]) {
299                 fprintf(of, "\tgoto\t%s\n", interrupts[2]->rname);
300         } else {
301                 fprintf(of, "\tretfie\n");
302         }
303 #if 0
304   /* now for the other interrupts */
305   for (i = 0; i < maxInterrupts; i++)
306     {
307         fprintf(of, "; %s priority interrupt vector 0x%s\n", (i==0)?"high":"low", (i==0)?"0008":"0018");
308       if (interrupts[i])
309         {
310           fprintf (of, "\tgoto\t%s\n\tres\t4\n", interrupts[i]->rname);
311         }
312       else
313         {
314           fprintf (of, "\tretfie\n\tres\t7\n");
315         }
316     }
317 #endif
318
319   return TRUE;
320 }
321
322 static bool
323 _hasNativeMulFor (iCode *ic, sym_link *left, sym_link *right)
324 {
325   //  sym_link *test = NULL;
326   //  value *val;
327
328   fprintf(stderr,"checking for native mult\n");
329
330   if ( ic->op != '*')
331     {
332       return FALSE;
333     }
334
335   return TRUE;
336 /*
337   if ( IS_LITERAL (left))
338     {
339       fprintf(stderr,"left is lit\n");
340       test = left;
341       val = OP_VALUE (IC_LEFT (ic));
342     }
343   else if ( IS_LITERAL (right))
344     {
345       fprintf(stderr,"right is lit\n");
346       test = left;
347       val = OP_VALUE (IC_RIGHT (ic));
348     }
349   else
350     {
351       fprintf(stderr,"oops, neither is lit so no\n");
352       return FALSE;
353     }
354
355   if ( getSize (test) <= 2)
356     {
357       fprintf(stderr,"yep\n");
358       return TRUE;
359     }
360   fprintf(stderr,"nope\n");
361
362   return FALSE;
363 */
364 }
365
366 /** $1 is always the basename.
367     $2 is always the output file.
368     $3 varies
369     $l is the list of extra options that should be there somewhere...
370     MUST be terminated with a NULL.
371 */
372 static const char *_linkCmd[] =
373 {
374   "gplink", "\"$1.o\"", "-o $1", "$l", NULL
375 };
376
377 /* Sigh. This really is not good. For now, I recommend:
378  * sdcc -S -mpic16 file.c
379  * the -S option does not compile or link
380  */
381 static const char *_asmCmd[] =
382 {
383   "gpasm", "-c  -I/usr/local/share/gputils/header", "\"$1.asm\"", NULL
384
385 };
386
387 /* Globals */
388 PORT pic16_port =
389 {
390   TARGET_ID_PIC16,
391   "pic16",
392   "MCU PIC16",                  /* Target name */
393   "p18f442",                    /* Processor */
394   {
395     pic16glue,
396     TRUE,                       /* Emit glue around main */
397     MODEL_SMALL | MODEL_LARGE | MODEL_FLAT24,
398     MODEL_SMALL
399   },
400   {
401     _asmCmd,
402     NULL,
403     NULL,
404     NULL,
405         //"-plosgffc",          /* Options with debug */
406         //"-plosgff",           /* Options without debug */
407     0,
408     ".asm",
409     NULL                        /* no do_assemble function */
410   },
411   {
412     _linkCmd,
413     NULL,
414     NULL,
415     ".rel"
416   },
417   {
418     _defaultRules
419   },
420   {
421         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
422     1, 2, 2, 4, 2, 2, 2, 1, 4, 4
423         /* TSD - I changed the size of gptr from 3 to 1. However, it should be
424            2 so that we can accomodate the PIC's with 4 register banks (like the
425            16f877)
426          */
427   },
428   {
429     "XSEG    (XDATA)",          // xstack
430     "STACK   (DATA)",           // istack
431     "CSEG    (CODE)",           // code
432     "DSEG    (DATA)",           // data
433     "ISEG    (DATA)",           // idata
434     "XSEG    (XDATA)",          // xdata
435     "BSEG    (BIT)",            // bit
436     "RSEG    (DATA)",           // reg
437     "GSINIT  (CODE)",           // static
438     "OSEG    (OVR,DATA)",       // overlay
439     "GSFINAL (CODE)",           // post static
440     "HOME        (CODE)",       // home
441     NULL,                       // xidata
442     NULL,                       // xinit
443     NULL,                       // default location for auto vars
444     NULL,                       // default location for global vars
445     1                           // code is read only
446   },
447   { NULL, NULL },
448   {
449     +1, 1, 4, 1, 1, 0
450   },
451     /* pic16 has an 8 bit mul */
452   {
453     1, -1
454   },
455   "_",
456   _pic16_init,
457   _pic16_parseOptions,
458   NULL,
459   _pic16_finaliseOptions,
460   _pic16_setDefaultOptions,
461   pic16_assignRegisters,
462   _pic16_getRegName,
463   _pic16_keywords,
464   _pic16_genAssemblerPreamble,
465   NULL,                         /* no genAssemblerEnd */
466   _pic16_genIVT,
467   NULL, // _pic16_genXINIT
468   _pic16_reset_regparm,
469   _pic16_regparm,
470   _process_pragma,                              /* process a pragma */
471   NULL,
472   _hasNativeMulFor,
473   FALSE,
474   0,                            /* leave lt */
475   0,                            /* leave gt */
476   1,                            /* transform <= to ! > */
477   1,                            /* transform >= to ! < */
478   1,                            /* transform != to !(a == b) */
479   0,                            /* leave == */
480   FALSE,                        /* No array initializer support. */
481   0,                            /* no CSE cost estimation yet */
482   NULL,                         /* no builtin functions */
483   GPOINTER,                     /* treat unqualified pointers as "generic" pointers */
484   1,                            /* reset labelKey to 1 */
485   1,                            /* globals & local static allowed */
486   PORT_MAGIC
487 };