* configure.in, configure: have device/lib/pic configured
[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 (ebbIndex *);
53
54 /* Also defined in gen.h, but the #include is commented out */
55 /* for an unknowned reason. - EEP */
56 void pic14_emitDebuggerSymbol (char *);
57
58 static int regParmFlg = 0;      /* determine if we can register a parameter */
59
60 static void
61 _pic14_init (void)
62 {
63         asm_addTree (&asm_asxxxx_mapping);
64         pCodeInitRegisters();
65 }
66
67 static void
68 _pic14_reset_regparm (void)
69 {
70         regParmFlg = 0;
71 }
72
73 static int
74 _pic14_regparm (sym_link * l, bool reentrant)
75 {
76 /* for this processor it is simple
77         can pass only the first parameter in a register */
78         //if (regParmFlg)
79         //  return 0;
80         
81         regParmFlg++;// = 1;
82         return 1;
83 }
84
85 static int
86 _process_pragma(const char *sz)
87 {
88         static const char *WHITE = " \t";
89         char    *ptr = strtok((char *)sz, WHITE);
90         
91         if (startsWith (ptr, "memmap"))
92         {
93                 char    *start;
94                 char    *end;
95                 char    *type;
96                 char    *alias;
97                 
98                 start = strtok((char *)NULL, WHITE);
99                 end = strtok((char *)NULL, WHITE);
100                 type = strtok((char *)NULL, WHITE);
101                 alias = strtok((char *)NULL, WHITE);
102                 
103                 if (start != (char *)NULL
104                         && end != (char *)NULL
105                         && type != (char *)NULL) {
106                         value           *startVal = constVal(start);
107                         value           *endVal = constVal(end);
108                         value           *aliasVal;
109                         memRange        r;
110                         
111                         if (alias == (char *)NULL) {
112                                 aliasVal = constVal(0);
113                         } else {
114                                 aliasVal = constVal(alias);
115                         }
116                         
117                         r.start_address = (int)floatFromVal(startVal);
118                         r.end_address = (int)floatFromVal(endVal);
119                         r.alias = (int)floatFromVal(aliasVal);
120                         r.bank = (r.start_address >> 7) & 3;
121                         
122                         if (strcmp(type, "RAM") == 0) {
123                                 addMemRange(&r, 0);
124                         } else if (strcmp(type, "SFR") == 0) {
125                                 addMemRange(&r, 1);
126                         } else {
127                                 return 1;
128                         }
129                 }
130                 
131                 return 0;
132         } else if (startsWith (ptr, "maxram")) {
133                 char *maxRAM = strtok((char *)NULL, WHITE);
134                 
135                 if (maxRAM != (char *)NULL) {
136                         int     maxRAMaddress;
137                         value   *maxRAMVal;
138                         
139                         maxRAMVal = constVal(maxRAM);
140                         maxRAMaddress = (int)floatFromVal(maxRAMVal);
141                         setMaxRAM(maxRAMaddress);
142                 }
143                 
144                 return 0;
145         }
146         return 1;
147 }
148
149 extern char *udata_section_name;
150
151 static bool
152 _pic14_parseOptions (int *pargc, char **argv, int *i)
153 {
154         char buf[128];
155         
156         /* TODO: allow port-specific command line options to specify
157         * segment names here.
158         */
159         
160         /* This is a temporary hack, to solve problems with some processors
161         * that do not have udata section. It will be changed when a more
162         * robust solution is figured out -- VR 27-11-2003 FIXME
163         */
164         strcpy(buf, "--udata-section-name");
165         if(!strncmp(buf, argv[ *i ], strlen(buf))) {
166                 if(strlen(argv[ *i ]) <= strlen(buf)+1) {
167                         fprintf(stderr, "WARNING: no `%s' entered\n", buf+2);
168                         exit(-1);
169                 } else {
170                         udata_section_name = strdup( strchr(argv[*i], '=') + 1 );
171                 }
172                 return 1;
173         }
174         
175         return FALSE;
176 }
177
178 static void
179 _pic14_finaliseOptions (void)
180 {
181         
182         port->mem.default_local_map = data;
183         port->mem.default_globl_map = data;
184 #if 0
185         /* Hack-o-matic: if we are using the flat24 model,
186         * adjust pointer sizes.
187         */
188         if (options.model == MODEL_FLAT24)
189         {
190                 
191                 fprintf (stderr, "*** WARNING: you should use the '-mds390' option "
192                         "for DS80C390 support. This code generator is "
193                         "badly out of date and probably broken.\n");
194                 
195                 port->s.fptr_size = 3;
196                 port->s.gptr_size = 4;
197                 port->stack.isr_overhead++;     /* Will save dpx on ISR entry. */
198 #if 1
199                 port->stack.call_overhead++;    /* This acounts for the extra byte 
200                                                  * of return addres on the stack.
201                                                  * but is ugly. There must be a 
202                                                  * better way.
203                                                  */
204 #endif
205                 fReturn = fReturn390;
206                 fReturnSize = 5;
207         }
208         
209         if (options.model == MODEL_LARGE)
210         {
211                 port->mem.default_local_map = xdata;
212                 port->mem.default_globl_map = xdata;
213         }
214         else
215         {
216                 port->mem.default_local_map = data;
217                 port->mem.default_globl_map = data;
218         }
219         
220         if (options.stack10bit)
221         {
222                 if (options.model != MODEL_FLAT24)
223                 {
224                         fprintf (stderr,
225                                 "*** warning: 10 bit stack mode is only supported in flat24 model.\n");
226                         fprintf (stderr, "\t10 bit stack mode disabled.\n");
227                         options.stack10bit = 0;
228                 }
229                 else
230                 {
231                 /* Fixup the memory map for the stack; it is now in
232                 * far space and requires a FPOINTER to access it.
233                 */
234                         istack->fmap = 1;
235                         istack->ptrType = FPOINTER;
236                 }
237         }
238 #endif
239 }
240
241 static void
242 _pic14_setDefaultOptions (void)
243 {
244 }
245
246 static const char *
247 _pic14_getRegName (struct regs *reg)
248 {
249         if (reg)
250                 return reg->name;
251         return "err";
252 }
253
254 extern char *processor_base_name(void);
255
256 static void
257 _pic14_genAssemblerPreamble (FILE * of)
258 {
259         char * name = processor_base_name();
260         
261         if(!name) {
262                 
263                 name = "p16f877";
264                 fprintf(stderr,"WARNING: No Pic has been selected, defaulting to %s\n",name);
265         }
266         
267         fprintf (of, "\tlist\tp=%s\n",&name[1]);
268         fprintf (of, "\tradix dec\n");
269         fprintf (of, "\tinclude \"%s.inc\"\n",name);
270 }
271
272 /* Generate interrupt vector table. */
273 static int
274 _pic14_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts)
275 {
276         int i;
277         
278         if (options.model != MODEL_FLAT24)
279         {
280                 /* Let the default code handle it. */
281                 return FALSE;
282         }
283         
284         fprintf (of, "\t;ajmp\t__sdcc_gsinit_startup\n");
285         
286         /* now for the other interrupts */
287         for (i = 0; i < maxInterrupts; i++)
288         {
289                 if (interrupts[i])
290                 {
291                         fprintf (of, "\t;ljmp\t%s\n\t.ds\t4\n", interrupts[i]->rname);
292                 }
293                 else
294                 {
295                         fprintf (of, "\t;reti\n\t.ds\t7\n");
296                 }
297         }
298         
299         return TRUE;
300 }
301
302 static bool
303 _hasNativeMulFor (iCode *ic, sym_link *left, sym_link *right)
304 {
305 /*
306 sym_link *test = NULL;
307 value *val;
308         */
309         
310         fprintf(stderr,"checking for native mult\n");
311         
312         if ( ic->op != '*')
313         {
314                 return FALSE;
315         }
316         
317         /* multiply chars in-place */
318         if (getSize(left) == 1 && getSize(right) == 1)
319                 return TRUE;
320         
321         /* use library functions for more complex maths */
322         return FALSE;
323
324         /*
325         if ( IS_LITERAL (left))
326         {
327         fprintf(stderr,"left is lit\n");
328         test = left;
329         val = OP_VALUE (IC_LEFT (ic));
330         }
331         else if ( IS_LITERAL (right))
332         {
333         fprintf(stderr,"right is lit\n");
334         test = left;
335         val = OP_VALUE (IC_RIGHT (ic));
336         }
337         else
338         {
339         fprintf(stderr,"oops, neither is lit so no\n");
340         return FALSE;
341         }
342         
343           if ( getSize (test) <= 2)
344           {
345           fprintf(stderr,"yep\n");
346           return TRUE;
347           }
348           fprintf(stderr,"nope\n");
349           
350                 return FALSE;
351         */
352 }
353
354 /* Indicate which extended bit operations this port supports */
355 static bool
356 hasExtBitOp (int op, int size)
357 {
358         if (op == RRC
359                 || op == RLC
360                 /* || op == GETHBIT */ /* GETHBIT doesn't look complete for PIC */
361                 )
362                 return TRUE;
363         else
364                 return FALSE;
365 }
366
367 /* Indicate the expense of an access to an output storage class */
368 static int
369 oclsExpense (struct memmap *oclass)
370 {
371         /* The IN_FARSPACE test is compatible with historical behaviour, */
372         /* but I don't think it is applicable to PIC. If so, please feel */
373         /* free to remove this test -- EEP */
374         if (IN_FARSPACE(oclass))
375                 return 1;
376
377         return 0;
378 }
379
380 /** $1 is always the basename.
381 $2 is always the output file.
382 $3 varies
383 $l is the list of extra options that should be there somewhere...
384 MUST be terminated with a NULL.
385 */
386 static const char *_linkCmd[] =
387 {
388         "gplink", "$l", "-o \"$2\"", "\"$1\"", "$3", NULL
389 };
390
391 static const char *_asmCmd[] =
392 {
393         "gpasm", "$l", "-c", "\"$1.asm\"", NULL
394                 
395 };
396
397 /* Globals */
398 PORT pic_port =
399 {
400         TARGET_ID_PIC,
401         "pic14",
402         "MCU pic",                      /* Target name */
403         "",                    /* Processor */
404         {
405                 picglue,
406                 TRUE,                   /* Emit glue around main */
407                 MODEL_SMALL | MODEL_LARGE | MODEL_FLAT24,
408                 MODEL_SMALL
409         },
410         {
411                 _asmCmd,
412                 NULL,
413                 NULL,
414                 NULL,
415                 //"-plosgffc",          /* Options with debug */
416                 //"-plosgff",           /* Options without debug */
417                 0,
418                 ".asm",
419                 NULL                    /* no do_assemble function */
420         },
421         {
422                 _linkCmd,
423                 NULL,
424                 NULL,
425                 ".o",
426                 0
427         },
428         {
429                 _defaultRules
430         },
431         {
432                 /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
433                 1, 2, 2, 4, 2, 2, 2, 1, 4, 4
434                 /* TSD - I changed the size of gptr from 3 to 1. However, it should be
435                    2 so that we can accomodate the PIC's with 4 register banks (like the
436                    16f877)
437                  */
438         },
439         {
440                 "XSEG    (XDATA)",
441                 "STACK   (DATA)",
442                 "code",
443                 "DSEG    (DATA)",
444                 "ISEG    (DATA)",
445                 NULL, /* pdata */
446                 "XSEG    (XDATA)",
447                 "BSEG    (BIT)",
448                 "RSEG    (DATA)",
449                 "GSINIT  (CODE)",
450                 "udata_ovr",
451                 "GSFINAL (CODE)",
452                 "HOME    (CODE)",
453                 NULL, // xidata
454                 NULL, // xinit
455                 "CONST   (CODE)",               // const_name - const data (code or not)
456                 NULL,
457                 NULL,
458                 1        // code is read only
459         },
460         { NULL, NULL },
461         {
462                 +1, 1, 4, 1, 1, 0
463         },
464                 /* pic14 has an 8 bit mul */
465         {
466                 1, -1
467         },
468         {
469                 pic14_emitDebuggerSymbol
470         },
471         {
472                 255/3,      /* maxCount */
473                 3,          /* sizeofElement */
474                 /* The rest of these costs are bogus. They approximate */
475                 /* the behavior of src/SDCCicode.c 1.207 and earlier.  */
476                 {4,4,4},    /* sizeofMatchJump[] */
477                 {0,0,0},    /* sizeofRangeCompare[] */
478                 0,          /* sizeofSubtract */
479                 3,          /* sizeofDispatch */
480         },
481         "_",
482         _pic14_init,
483         _pic14_parseOptions,
484         NULL,
485         NULL,
486         _pic14_finaliseOptions,
487         _pic14_setDefaultOptions,
488         pic14_assignRegisters,
489         _pic14_getRegName,
490         _pic14_keywords,
491         _pic14_genAssemblerPreamble,
492         NULL,                           /* no genAssemblerEnd */
493         _pic14_genIVT,
494         NULL, // _pic14_genXINIT
495         NULL,                           /* genInitStartup */
496         _pic14_reset_regparm,
497         _pic14_regparm,
498         _process_pragma,                                /* process a pragma */
499         NULL,
500         _hasNativeMulFor,
501         hasExtBitOp,                    /* hasExtBitOp */
502         oclsExpense,                    /* oclsExpense */
503         FALSE,
504 //      TRUE,                           /* little endian */
505         FALSE,                          /* little endian - PIC code enumlates big endian */
506         0,                              /* leave lt */
507         0,                              /* leave gt */
508         1,                              /* transform <= to ! > */
509         1,                              /* transform >= to ! < */
510         1,                              /* transform != to !(a == b) */
511         0,                              /* leave == */
512         FALSE,                        /* No array initializer support. */
513         0,                            /* no CSE cost estimation yet */
514         NULL,                   /* no builtin functions */
515         GPOINTER,                       /* treat unqualified pointers as "generic" pointers */
516         1,                              /* reset labelKey to 1 */
517         1,                              /* globals & local static allowed */
518         PORT_MAGIC
519 };