a84d1bc8050122c8419d470bd3226677f16db153
[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         NULL,                           /* genInitStartup */
470         _pic14_reset_regparm,
471         _pic14_regparm,
472         _process_pragma,                                /* process a pragma */
473         NULL,
474         _hasNativeMulFor,
475         hasExtBitOp,                    /* hasExtBitOp */
476         oclsExpense,                    /* oclsExpense */
477         FALSE,
478 //      TRUE,                           /* little endian */
479         FALSE,                          /* little endian - PIC code enumlates big endian */
480         0,                              /* leave lt */
481         0,                              /* leave gt */
482         1,                              /* transform <= to ! > */
483         1,                              /* transform >= to ! < */
484         1,                              /* transform != to !(a == b) */
485         0,                              /* leave == */
486         FALSE,                        /* No array initializer support. */
487         0,                            /* no CSE cost estimation yet */
488         NULL,                   /* no builtin functions */
489         GPOINTER,                       /* treat unqualified pointers as "generic" pointers */
490         1,                              /* reset labelKey to 1 */
491         1,                              /* globals & local static allowed */
492         PORT_MAGIC
493 };