dattalo - Major commit! re-wrote register allocation and flow analysis.
[fw/sdcc] / src / pic / device.c
1 /*-------------------------------------------------------------------------
2
3    device.c - Accomodates subtle variations in PIC devices
4    Written By -  Scott Dattalo scott@dattalo.com
5
6    This program is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 2, or (at your option) any
9    later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 -------------------------------------------------------------------------*/
20
21 #include <stdio.h>
22
23 #include "common.h"   // Include everything in the SDCC src directory
24 #include "newalloc.h"
25
26
27 #include "pcode.h"
28 #include "ralloc.h"
29 #include "device.h"
30
31 #if defined(__BORLANDC__) || defined(_MSC_VER)
32 #define STRCASECMP stricmp
33 #else
34 #define STRCASECMP strcasecmp
35 #endif
36
37 /* 16F627 */
38 memRange p16f627_mem[] = {
39   {0x20,  0x6f,  0x00,  0},
40   {0xa0,  0xef,  0x00,  1},
41   {0x120, 0x14f, 0x00,  2},
42   {0x70,  0x7f,  0x180, 0},
43   {-1,    -1,    -1,   -1}     /* end indicator */
44 };
45 memRange p16f627_sfr[] = {
46   {0x00,  0x00,  0x180, 0},
47   {0x01,  0x01,  0x100, 0},
48   {0x02,  0x04,  0x180, 0},
49   {0x05,  0x05,  0x000, 0},
50   {0x06,  0x06,  0x100, 0},
51   {0x85,  0x85,  0x000, 1},
52   {0x86,  0x86,  0x100, 1},
53   {0x0a,  0x0b,  0x180, 0},
54   {0x0c,  0x0c,  0x000, 0},
55   {0x0e,  0x12,  0x000, 0},
56   {0x15,  0x1a,  0x000, 0},
57   {0x1f,  0x1f,  0x000, 0},
58   {0x8e,  0x8e,  0x000, 1},
59   {0x92,  0x92,  0x000, 1},
60   {0x98,  0x9d,  0x000, 1},
61   {0x9f,  0x9f,  0x000, 1},
62
63   {-1,    -1,    -1,   -1}     /* end indicator */
64 };
65
66 /* 16F84 */
67 memRange p16f84_mem[] = {
68   {0x0c,  0x4f,  0x80,  0},
69   {-1,    -1,    -1,   -1}     /* end indicator */
70 };
71 memRange p16f84_sfr[] = {
72   {0x01,  0x01,  0x00, 0},
73   {0x02,  0x04,  0x80, 0},
74   {0x05,  0x06,  0x00, 0},
75   {0x85,  0x86,  0x80, 1},
76   {0x08,  0x09,  0x00, 0},
77   {0x88,  0x89,  0x00, 1},
78   {0x0a,  0x0b,  0x80, 0},
79   {-1,    -1,    -1,   -1}     /* end indicator */
80 };
81
82 /* 16F877 */
83 memRange p16f877_mem[] = {
84   {0x20,  0x6f,  0x00,  0},
85   {0xa0,  0xef,  0x00,  1},
86   {0x110, 0x16f, 0x00,  2},
87   {0x190, 0x1ef, 0x00,  3},
88   {0x70,  0x7f,  0x180, 0},
89   {-1,    -1,    -1,   -1}     /* end indicator */
90 };
91 memRange p16f877_sfr[] = {
92   {0x00,  0x00,  0x180, 0},
93   {0x01,  0x01,  0x100, 0},
94   {0x02,  0x04,  0x180, 0},
95   {0x05,  0x05,  0x000, 0},
96   {0x85,  0x85,  0x000, 1},
97   {0x06,  0x06,  0x100, 0},
98   {0x86,  0x86,  0x100, 1},
99   {0x07,  0x09,  0x000, 0},
100   {0x87,  0x89,  0x000, 1},
101   {0x0a,  0x0b,  0x180, 0},
102   {0x0c,  0x1f,  0x000, 0},
103   {0x8c,  0x8e,  0x000, 1},
104   {0x91,  0x94,  0x000, 1},
105   {0x98,  0x99,  0x000, 1},
106   {0x9e,  0x9f,  0x000, 1},
107   {0x10c, 0x10f, 0x000, 2},
108   {0x18c, 0x18f, 0x000, 3},
109
110   {-1,    -1,    -1,   -1}     /* end indicator */
111 };
112
113
114 static PIC_device Pics[] = {
115   {
116     {"p16f627", "16f627", "pic16f627", "f627"}, /* processor name */
117     p16f627_mem,                     /* ram mem map */
118     p16f627_sfr,                     /* sfr mem map */
119     0,                               /* max ram address (calculated) */
120   },
121
122   {
123     {"p16f628", "16f628", "pic16f628", "f628"},
124     p16f627_mem,
125     p16f627_sfr,
126     0,
127   },
128
129   {
130     {"p16f84", "16f84", "pic16f84", "f84"},
131     p16f84_mem,
132     p16f84_sfr,
133     0,
134   },
135
136   {
137     {"p16f877", "16f877", "pic16f877", "f877"},
138     p16f877_mem,
139     p16f877_sfr,
140     0,
141   },
142
143 };
144
145 static int num_of_supported_PICS = sizeof(Pics)/sizeof(PIC_device);
146 static int default_pic = 0;
147 #define DEFAULT_PIC "f84"
148
149 static PIC_device *pic=NULL;
150
151 AssignedMemory *finalMapping=NULL;
152 /*-----------------------------------------------------------------*
153  *
154  * void addMem(memRange *ranges,int type)
155  *
156  *
157  *-----------------------------------------------------------------*/
158
159 static void addMem(memRange *ranges,int type)
160 {
161   memRange *r = ranges;
162   int i;
163
164   do {
165
166     int alias = r->alias;
167
168     do {
169
170       for(i=r->start_address; i<= r->end_address; i++) {
171         if(i <= pic->max_address) {
172           finalMapping[i | alias].isValid = 1;
173           finalMapping[i | alias].alias = r->alias;
174           finalMapping[i | alias].bank  = r->bank;
175           if(type) {
176             /* hack for now */
177             finalMapping[i | alias].isSFR  = 1;
178           } else
179             finalMapping[i | alias].isSFR  = 0;
180         }
181       }
182
183       /* Decrement alias */
184       if(alias)
185         alias -= ((alias & (alias - 1)) ^ alias);
186         else
187           alias--;
188         
189     } while(alias >= 0);
190
191     r++;
192
193   } while (r->start_address >= 0);
194
195
196 }
197
198 static void addMaps(PIC_device *pPic)
199 {
200   int i;
201   memRange *r;
202
203   if(!pPic)
204     return;
205
206
207   /* First, find the maximum address */
208
209   r = pPic->ram;
210   pPic->max_address = 0;
211
212   do {
213
214     if((r->end_address | r->alias) > pPic->max_address)
215       pPic->max_address = r->end_address | r->alias;
216
217     r++;
218
219   } while (r->start_address >= 0);
220
221
222
223   finalMapping = Safe_calloc(1+pPic->max_address, sizeof(AssignedMemory));
224
225   /* Now initialize the finalMapping array */
226
227   for(i=0; i<=pPic->max_address; i++) {
228     finalMapping[i].reg = NULL;
229     finalMapping[i].isValid = 0;
230   }
231
232   addMem(pPic->ram,0); /* add general purpose regs to the map */
233   addMem(pPic->sfr,1); /* Add SFR's to the memmap */
234
235 }
236
237 /*
238  *  dump_map -- debug stuff
239  */
240
241 void dump_map(void)
242 {
243   int i;
244
245   for(i=0; i<=pic->max_address; i++) {
246     //fprintf(stdout , "addr 0x%02x is %s\n", i, ((finalMapping[i].isValid) ? "valid":"invalid"));
247
248     if(finalMapping[i].isValid) {
249       fprintf(stderr,"addr: 0x%02x",i);
250       if(finalMapping[i].isSFR)
251         fprintf(stderr," isSFR");
252       if(finalMapping[i].reg) 
253         fprintf( stderr, "  reg %s", finalMapping[i].reg->name);
254       fprintf(stderr, "\n");
255     }
256   }
257
258 }
259
260 void dump_cblock(FILE *of)
261 {
262   int start=-1;
263   int addr=0;
264
265   //dump_map();   /* display the register map */
266
267   do {
268
269     if(finalMapping[addr].reg && !finalMapping[addr].reg->isEmitted) {
270
271       if(start<0)
272         start = addr;
273     } else {
274       if(start>=0) {
275
276         /* The bank number printed in the cblock comment tacitly
277          * assumes that the first register in the contiguous group
278          * of registers represents the bank for the whole group */
279         fprintf(of,"  cblock  0X%04X\t; Bank %d\n",start,finalMapping[start].bank);
280
281         for( ; start < addr; start++) {
282           if((finalMapping[start].reg) && !finalMapping[start].reg->isEmitted ) {
283             fprintf(of,"\t%s",finalMapping[start].reg->name);
284
285             /* If this register is aliased in multiple banks, then
286              * mangle the variable name with the alias address: */
287             if(finalMapping[start].alias & start)
288               fprintf(of,"_%x",finalMapping[start].alias);
289
290             if(finalMapping[start].instance)
291               fprintf(of,"_%d",finalMapping[start].instance);
292
293             
294             fputc('\n',of);
295
296             //finalMapping[start].reg->isEmitted = 1;
297           }
298         }
299
300         fprintf(of,"  endc\n");
301
302         start = -1;
303       }
304
305     }
306
307     addr++;
308
309   } while(addr <= pic->max_address);
310   
311
312 }
313
314 /*-----------------------------------------------------------------*
315  *  void list_valid_pics(int ncols, int list_alias)
316  *
317  * Print out a formatted list of valid PIC devices
318  *
319  * ncols - number of columns in the list.
320  *
321  * list_alias - if non-zero, print all of the supported aliases
322  *              for a device (e.g. F84, 16F84, etc...)
323  *-----------------------------------------------------------------*/
324 void list_valid_pics(int ncols, int list_alias)
325 {
326   int col,longest;
327   int i,j,k,l;
328
329   if(list_alias)
330     list_alias = sizeof(Pics[0].name) / sizeof(Pics[0].name[0]);
331
332   fprintf(stderr,"list_alias size = %d\n",list_alias);
333   /* decrement the column number if it's greater than zero */
334   ncols = (ncols > 1) ? ncols-1 : 4;
335
336   /* Find the device with the longest name */
337   for(i=0,longest=0; i<num_of_supported_PICS; i++) {
338     for(j=0; j<=list_alias; j++) {
339       k = strlen(Pics[i].name[j]);
340       if(k>longest)
341         longest = k;
342     }
343   }
344
345   col = 0;
346
347   for(i=0;  i < num_of_supported_PICS; i++) {
348     j = 0;
349     do {
350
351       fprintf(stderr,"%s", Pics[i].name[j]);
352       if(col<ncols) {
353         l = longest + 2 - strlen(Pics[i].name[j]);
354         for(k=0; k<l; k++)
355           fputc(' ',stderr);
356
357         col++;
358
359       } else {
360         fputc('\n',stderr);
361         col = 0;
362       }
363
364     } while(++j<list_alias);
365
366   }
367   if(col != ncols)
368     fputc('\n',stderr);
369
370 }
371
372 /*-----------------------------------------------------------------*
373  *  
374  *-----------------------------------------------------------------*/
375 PIC_device *find_device(char *name)
376 {
377
378   int i,j;
379
380   if(!name)
381     return NULL;
382
383   for(i = 0; i<num_of_supported_PICS; i++) {
384
385     for(j=0; j<PROCESSOR_NAMES; j++)
386       if(!STRCASECMP(Pics[i].name[j], name) )
387         return &Pics[i];
388   }
389
390   /* not found */
391   return NULL; 
392 }
393
394 /*-----------------------------------------------------------------*
395  *  
396  *-----------------------------------------------------------------*/
397 void init_pic(void)
398 {
399   pic = find_device(DEFAULT_PIC);
400
401   if(!pic) {
402     fprintf(stderr, "%s was not found.\nValid devices are:\n",DEFAULT_PIC);
403     list_valid_pics(4,0);
404     exit(1);
405   }
406
407   
408   addMaps(pic);
409
410
411 }
412
413 /*-----------------------------------------------------------------*
414  *  char *processor_base_name(void) - Include file is derived from this.
415  *-----------------------------------------------------------------*/
416 char *processor_base_name(void)
417 {
418
419   if(!pic)
420     return NULL;
421
422   return pic->name[0];
423 }
424
425 int isSFR(int address)
426 {
427
428   if( (address > pic->max_address) || !finalMapping[address].isSFR)
429     return 0;
430
431   return 1;
432
433 }
434
435 int validAddress(int address, int reg_size)
436 {
437   int i;
438
439   if(address > pic->max_address)
440     return 0;
441
442   for (i=0; i<reg_size; i++)
443     if(!finalMapping[address + i].isValid || 
444        finalMapping[address+i].reg ||
445        finalMapping[address+i].isSFR )
446       return 0;
447
448   return 1;
449 }
450
451 void mapRegister(regs *reg)
452 {
453
454   int i;
455   int alias;
456
457
458
459   for(i=0; i<reg->size; i++) {
460
461     alias = finalMapping[reg->address].alias;
462     reg->alias = alias;
463
464     do {
465
466       fprintf(stdout,"mapping %s to address 0x%02x\n",reg->name, (reg->address+alias+i));
467
468       finalMapping[reg->address + alias + i].reg = reg;
469       finalMapping[reg->address + alias + i].instance = i;
470
471       /* Decrement alias */
472       if(alias)
473         alias -= ((alias & (alias - 1)) ^ alias);
474       else
475         alias--;
476
477     } while (alias>=0);
478   }
479
480   reg->isMapped = 1;
481
482 }
483
484 int assignRegister(regs *reg, int start_address)
485 {
486   int i;
487
488   if(reg->isFixed) {
489
490     if (validAddress(reg->address,reg->size)) {
491
492       mapRegister(reg);
493       return reg->address;
494     }
495
496     if( isSFR(reg->address)) {
497       mapRegister(reg);
498       return reg->address;
499     }
500     fprintf(stderr, "WARNING: Ignoring Out of Range register assignment at fixed address %d, %s\n",
501             reg->address, reg->name);
502
503   } else {
504
505     /* This register does not have a fixed address requirement
506      * so we'll search through all availble ram address and
507      * assign the first one */
508
509     for (i=start_address; i<=pic->max_address; i++) {
510
511       if (validAddress(i,reg->size)) {
512         reg->address = i;
513         mapRegister(reg);
514         return i;
515       }
516     }
517
518     fprintf(stderr, "WARNING: No more RAM available\n");
519
520   }
521
522   return -1;
523 }
524
525 void assignFixedRegisters(set *regset)
526 {
527   regs *reg;
528
529   for (reg = setFirstItem(regset) ; reg ; 
530        reg = setNextItem(regset)) {
531
532     if(reg->isFixed) 
533       assignRegister(reg,0);
534   }
535
536 }
537
538 void assignRelocatableRegisters(set *regset)
539 {
540
541   regs *reg;
542   int address = 0;
543
544   for (reg = setFirstItem(regset) ; reg ; 
545        reg = setNextItem(regset)) {
546
547     //fprintf(stdout,"assigning %s\n",reg->name);
548
549     if(!reg->isFixed) 
550       address = assignRegister(reg,address);
551
552   }
553
554 }
555