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