]> git.gag.com Git - fw/sdcc/blob - src/pic/main.c
* src/pic/device.c,
[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
22 /* list of key words used by msc51 */
23 static char *_pic14_keywords[] =
24 {
25   "at",
26   "bit",
27   "code",
28   "critical",
29   "data",
30   "far",
31   "idata",
32   "interrupt",
33   "near",
34   "pdata",
35   "reentrant",
36   "sfr",
37   "sbit",
38   "using",
39   "xdata",
40   "_data",
41   "_code",
42   "_generic",
43   "_near",
44   "_xdata",
45   "_pdata",
46   "_idata",
47   NULL
48 };
49
50 void  pCodeInitRegisters(void);
51
52 void pic14_assignRegisters (eBBlock ** ebbs, int count);
53
54 static int regParmFlg = 0;      /* determine if we can register a parameter */
55
56 static void
57 _pic14_init (void)
58 {
59   asm_addTree (&asm_asxxxx_mapping);
60   pCodeInitRegisters();
61 }
62
63 static void
64 _pic14_reset_regparm ()
65 {
66   regParmFlg = 0;
67 }
68
69 static int
70 _pic14_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) & 3;
117
118         if (strcmp(type, "RAM") == 0) {
119           addMemRange(&r, 0);
120         } else if (strcmp(type, "SFR") == 0) {
121           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         setMaxRAM(maxRAMaddress);
138       }
139         
140       return 0;
141     }
142   return 1;
143 }
144
145 extern char *udata_section_name;
146
147 static bool
148 _pic14_parseOptions (int *pargc, char **argv, int *i)
149 {
150   char buf[128];
151
152   /* TODO: allow port-specific command line options to specify
153    * segment names here.
154    */
155
156         /* This is a temporary hack, to solve problems with some processors
157          * that do not have udata section. It will be changed when a more
158          * robust solution is figured out -- VR 27-11-2003 FIXME
159          */
160         strcpy(buf, "--udata-section-name");
161         if(!strncmp(buf, argv[ *i ], strlen(buf))) {
162                 if(strlen(argv[ *i ]) <= strlen(buf)+1) {
163                         fprintf(stderr, "WARNING: no `%s' entered\n", buf+2);
164                         exit(-1);
165                 } else {
166                         udata_section_name = strdup( strchr(argv[*i], '=') + 1 );
167                 }
168                 return 1;
169         }
170    
171   return FALSE;
172 }
173
174 static void
175 _pic14_finaliseOptions (void)
176 {
177
178       port->mem.default_local_map = data;
179       port->mem.default_globl_map = data;
180 #if 0
181   /* Hack-o-matic: if we are using the flat24 model,
182    * adjust pointer sizes.
183    */
184   if (options.model == MODEL_FLAT24)
185     {
186
187       fprintf (stderr, "*** WARNING: you should use the '-mds390' option "
188                "for DS80C390 support. This code generator is "
189                "badly out of date and probably broken.\n");
190
191       port->s.fptr_size = 3;
192       port->s.gptr_size = 4;
193       port->stack.isr_overhead++;       /* Will save dpx on ISR entry. */
194 #if 1
195       port->stack.call_overhead++;      /* This acounts for the extra byte 
196                                          * of return addres on the stack.
197                                          * but is ugly. There must be a 
198                                          * better way.
199                                          */
200 #endif
201       fReturn = fReturn390;
202       fReturnSize = 5;
203     }
204
205   if (options.model == MODEL_LARGE)
206     {
207       port->mem.default_local_map = xdata;
208       port->mem.default_globl_map = xdata;
209     }
210   else
211     {
212       port->mem.default_local_map = data;
213       port->mem.default_globl_map = data;
214     }
215
216   if (options.stack10bit)
217     {
218       if (options.model != MODEL_FLAT24)
219         {
220           fprintf (stderr,
221                    "*** warning: 10 bit stack mode is only supported in flat24 model.\n");
222           fprintf (stderr, "\t10 bit stack mode disabled.\n");
223           options.stack10bit = 0;
224         }
225       else
226         {
227           /* Fixup the memory map for the stack; it is now in
228            * far space and requires a FPOINTER to access it.
229            */
230           istack->fmap = 1;
231           istack->ptrType = FPOINTER;
232         }
233     }
234 #endif
235 }
236
237 static void
238 _pic14_setDefaultOptions (void)
239 {
240 }
241
242 static const char *
243 _pic14_getRegName (struct regs *reg)
244 {
245   if (reg)
246     return reg->name;
247   return "err";
248 }
249
250 extern char *processor_base_name(void);
251
252 static void
253 _pic14_genAssemblerPreamble (FILE * of)
254 {
255   char * name = processor_base_name();
256
257   if(!name) {
258
259     name = "p16f877";
260     fprintf(stderr,"WARNING: No Pic has been selected, defaulting to %s\n",name);
261   }
262
263   fprintf (of, "\tlist\tp=%s\n",&name[1]);
264   fprintf (of, "\tradix dec\n");
265   fprintf (of, "\tinclude \"%s.inc\"\n",name);
266 }
267
268 /* Generate interrupt vector table. */
269 static int
270 _pic14_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts)
271 {
272   int i;
273
274   if (options.model != MODEL_FLAT24)
275     {
276       /* Let the default code handle it. */
277       return FALSE;
278     }
279
280   fprintf (of, "\t;ajmp\t__sdcc_gsinit_startup\n");
281
282   /* now for the other interrupts */
283   for (i = 0; i < maxInterrupts; i++)
284     {
285       if (interrupts[i])
286         {
287           fprintf (of, "\t;ljmp\t%s\n\t.ds\t4\n", interrupts[i]->rname);
288         }
289       else
290         {
291           fprintf (of, "\t;reti\n\t.ds\t7\n");
292         }
293     }
294
295   return TRUE;
296 }
297
298 static bool
299 _hasNativeMulFor (iCode *ic, sym_link *left, sym_link *right)
300 {
301 /*
302   sym_link *test = NULL;
303   value *val;
304 */
305
306   fprintf(stderr,"checking for native mult\n");
307
308   if ( ic->op != '*')
309     {
310       return FALSE;
311     }
312
313   return TRUE;
314 /*
315   if ( IS_LITERAL (left))
316     {
317       fprintf(stderr,"left is lit\n");
318       test = left;
319       val = OP_VALUE (IC_LEFT (ic));
320     }
321   else if ( IS_LITERAL (right))
322     {
323       fprintf(stderr,"right is lit\n");
324       test = left;
325       val = OP_VALUE (IC_RIGHT (ic));
326     }
327   else
328     {
329       fprintf(stderr,"oops, neither is lit so no\n");
330       return FALSE;
331     }
332
333   if ( getSize (test) <= 2)
334     {
335       fprintf(stderr,"yep\n");
336       return TRUE;
337     }
338   fprintf(stderr,"nope\n");
339
340   return FALSE;
341 */
342 }
343
344 /* Indicate which extended bit operations this port supports */
345 static bool
346 hasExtBitOp (int op, int size)
347 {
348   if (op == RRC
349       || op == RLC
350       /* || op == GETHBIT */ /* GETHBIT doesn't look complete for PIC */
351      )
352     return TRUE;
353   else
354     return FALSE;
355 }
356
357 /* Indicate the expense of an access to an output storage class */
358 static int
359 oclsExpense (struct memmap *oclass)
360 {
361   /* The IN_FARSPACE test is compatible with historical behaviour, */
362   /* but I don't think it is applicable to PIC. If so, please feel */
363   /* free to remove this test -- EEP */
364   if (IN_FARSPACE(oclass))
365     return 1;
366     
367   return 0;
368 }
369
370 /** $1 is always the basename.
371     $2 is always the output file.
372     $3 varies
373     $l is the list of extra options that should be there somewhere...
374     MUST be terminated with a NULL.
375 */
376 static const char *_linkCmd[] =
377 {
378   "gplink", "-o $2", "\"$1.o\"", "$l", NULL
379 };
380
381 static const char *_asmCmd[] =
382 {
383   "gpasm", "$l", "-c", "\"$1.asm\"", NULL
384
385 };
386
387 /* Globals */
388 PORT pic_port =
389 {
390   TARGET_ID_PIC,
391   "pic14",
392   "MCU pic",                    /* Target name */
393   "",                    /* Processor */
394   {
395     picglue,
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     ".o",
416     0
417   },
418   {
419     _defaultRules
420   },
421   {
422         /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
423     1, 2, 2, 4, 2, 2, 2, 1, 4, 4
424         /* TSD - I changed the size of gptr from 3 to 1. However, it should be
425            2 so that we can accomodate the PIC's with 4 register banks (like the
426            16f877)
427          */
428   },
429   {
430     "XSEG    (XDATA)",
431     "STACK   (DATA)",
432     "code",
433     "DSEG    (DATA)",
434     "ISEG    (DATA)",
435     "XSEG    (XDATA)",
436     "BSEG    (BIT)",
437     "RSEG    (DATA)",
438     "GSINIT  (CODE)",
439     "udata_ovr",
440     "GSFINAL (CODE)",
441     "HOME        (CODE)",
442     NULL, // xidata
443     NULL, // xinit
444     NULL,
445     NULL,
446     1        // code is read only
447   },
448   { NULL, NULL },
449   {
450     +1, 1, 4, 1, 1, 0
451   },
452     /* pic14 has an 8 bit mul */
453   {
454     1, -1
455   },
456   "_",
457   _pic14_init,
458   _pic14_parseOptions,
459   NULL,
460   _pic14_finaliseOptions,
461   _pic14_setDefaultOptions,
462   pic14_assignRegisters,
463   _pic14_getRegName,
464   _pic14_keywords,
465   _pic14_genAssemblerPreamble,
466   NULL,                         /* no genAssemblerEnd */
467   _pic14_genIVT,
468   NULL, // _pic14_genXINIT
469   _pic14_reset_regparm,
470   _pic14_regparm,
471   _process_pragma,                              /* process a pragma */
472   NULL,
473   _hasNativeMulFor,
474   hasExtBitOp,                  /* hasExtBitOp */
475   oclsExpense,                  /* oclsExpense */
476   FALSE,
477 //  TRUE,                               /* little endian */
478   FALSE,                                /* little endian - PIC code enumlates big endian */
479   0,                            /* leave lt */
480   0,                            /* leave gt */
481   1,                            /* transform <= to ! > */
482   1,                            /* transform >= to ! < */
483   1,                            /* transform != to !(a == b) */
484   0,                            /* leave == */
485   FALSE,                        /* No array initializer support. */
486   0,                            /* no CSE cost estimation yet */
487   NULL,                         /* no builtin functions */
488   GPOINTER,                     /* treat unqualified pointers as "generic" pointers */
489   1,                            /* reset labelKey to 1 */
490   1,                            /* globals & local static allowed */
491   PORT_MAGIC
492 };