Added a new peep rule to handle carry logic (optimizes src/regression/nestfor.c).
[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 static PIC_device Pics[] = {
38   {
39     {"p16f627", "16f627", "pic16f627", "f627"}, /* processor name */
40     (memRange *)NULL,
41     (memRange *)NULL,
42     0,                               /* max ram address (calculated) */
43     0x80,                            /* Bank Mask */
44   },
45
46   {
47     {"p16f628", "16f628", "pic16f628", "f628"},
48     (memRange *)NULL,
49     (memRange *)NULL,
50     0,
51     0x80,
52   },
53
54   {
55     {"p16f84", "16f84", "pic16f84", "f84"},
56     (memRange *)NULL,
57     (memRange *)NULL,
58     0,
59     0x80,
60   },
61
62   {
63     {"p16f873", "16f873", "pic16f873", "f873"},
64     (memRange *)NULL,
65     (memRange *)NULL,
66     0,
67     0x180,
68   },
69
70   {
71     {"p16f877", "16f877", "pic16f877", "f877"},
72     (memRange *)NULL,
73     (memRange *)NULL,
74     0,
75     0x180,
76   },
77
78 };
79
80 static int num_of_supported_PICS = sizeof(Pics)/sizeof(PIC_device);
81
82 #define DEFAULT_PIC "f877"
83
84 static PIC_device *pic=NULL;
85
86 AssignedMemory *finalMapping=NULL;
87
88 #define CONFIG_WORD_ADDRESS 0x2007
89 #define DEFAULT_CONFIG_WORD 0x3fff
90
91 static unsigned int config_word = DEFAULT_CONFIG_WORD;
92
93 void addMemRange(memRange *r, int type)
94 {
95   int i;
96   int alias = r->alias;
97
98   if (pic->maxRAMaddress < 0) {
99     fprintf(stderr, "missing \"#pragma maxram\" setting\n");
100     return;
101   }
102
103   do {
104     for (i=r->start_address; i<= r->end_address; i++) {
105       if ((i|alias) <= pic->maxRAMaddress) {
106         finalMapping[i | alias].isValid = 1;
107         finalMapping[i | alias].alias = r->alias;
108         finalMapping[i | alias].bank  = r->bank;
109         if(type) {
110           /* hack for now */
111           finalMapping[i | alias].isSFR  = 1;
112         } else {
113           finalMapping[i | alias].isSFR  = 0;
114         }
115       } else {
116         fprintf(stderr, "WARNING: %s:%s memory at 0x%x is beyond max ram = 0x%x\n",
117                 __FILE__,__FUNCTION__,(i|alias), pic->maxRAMaddress);
118       }
119     }
120
121     /* Decrement alias */
122     if (alias) {
123       alias -= ((alias & (alias - 1)) ^ alias);
124     } else {
125       alias--;
126     }
127
128   } while (alias >= 0);
129 }
130
131 void setMaxRAM(int size)
132 {
133   int i;
134   pic->maxRAMaddress = size;
135
136   if (pic->maxRAMaddress < 0) {
137     fprintf(stderr, "invalid \"#pragma maxram 0x%x\" setting\n",
138             pic->maxRAMaddress);
139     return;
140   }
141
142   finalMapping = Safe_calloc(1+pic->maxRAMaddress,
143                              sizeof(AssignedMemory));
144
145   /* Now initialize the finalMapping array */
146
147   for(i=0; i<=pic->maxRAMaddress; i++) {
148     finalMapping[i].reg = NULL;
149     finalMapping[i].isValid = 0;
150   }
151 }
152
153 /*-----------------------------------------------------------------*
154  *-----------------------------------------------------------------*/
155
156 int isREGinBank(regs *reg, int bank)
157 {
158
159   if(!reg || !pic)
160     return 0;
161
162   if(((reg->address | reg->alias) & pic->bankMask & bank) == bank)
163     return 1;
164
165   return 0;
166 }
167
168 /*-----------------------------------------------------------------*
169  *-----------------------------------------------------------------*/
170 int REGallBanks(regs *reg)
171 {
172
173   if(!reg || !pic)
174     return 0;
175
176   return ((reg->address | reg->alias) & pic->bankMask);
177
178 }
179
180 /*-----------------------------------------------------------------*
181  *-----------------------------------------------------------------*/
182
183 /*
184  *  dump_map -- debug stuff
185  */
186
187 void dump_map(void)
188 {
189   int i;
190
191   for(i=0; i<=pic->maxRAMaddress; i++) {
192     //fprintf(stdout , "addr 0x%02x is %s\n", i, ((finalMapping[i].isValid) ? "valid":"invalid"));
193
194     if(finalMapping[i].isValid) {
195       fprintf(stderr,"addr: 0x%02x",i);
196       if(finalMapping[i].isSFR)
197         fprintf(stderr," isSFR");
198       if(finalMapping[i].reg) 
199         fprintf( stderr, "  reg %s", finalMapping[i].reg->name);
200       fprintf(stderr, "\n");
201     }
202   }
203
204 }
205
206 void dump_sfr(FILE *of)
207 {
208
209   int start=-1;
210   int addr=0;
211   int bank_base;
212   static int udata_flag=0;
213
214   //dump_map();   /* display the register map */
215   //fprintf(stdout,";dump_sfr  \n");
216   if (pic->maxRAMaddress < 0) {
217     fprintf(stderr, "missing \"#pragma maxram\" setting\n");
218     return;
219   }
220
221   do {
222
223     if(finalMapping[addr].reg && !finalMapping[addr].reg->isEmitted) {
224
225       if(start<0)
226         start = addr;
227     } else {
228       if(start>=0) {
229
230         /* clear the lower 7-bits of the start address of the first
231          * variable declared in this bank. The upper bits for the mid
232          * range pics are the bank select bits.
233          */
234
235         bank_base = start & 0xfff8;
236
237         /* The bank number printed in the cblock comment tacitly
238          * assumes that the first register in the contiguous group
239          * of registers represents the bank for the whole group */
240
241         if ( (start != addr) && (!udata_flag) ) {
242           udata_flag = 1;
243           //fprintf(of,"\tudata\n");
244         }
245
246         for( ; start < addr; start++) {
247           if((finalMapping[start].reg) && 
248              (!finalMapping[start].reg->isEmitted) &&
249              (!finalMapping[start].instance) && 
250              (!finalMapping[start].isSFR)) {
251
252             fprintf(of,"%s\tres\t%i\n",
253                     finalMapping[start].reg->name, 
254                     finalMapping[start].reg->size);
255
256             finalMapping[start].reg->isEmitted = 1;
257           }
258         }
259
260         start = -1;
261       }
262
263     }
264
265     addr++;
266
267   } while(addr <= pic->maxRAMaddress);
268   
269
270 }
271
272 /*-----------------------------------------------------------------*
273  *  void list_valid_pics(int ncols, int list_alias)
274  *
275  * Print out a formatted list of valid PIC devices
276  *
277  * ncols - number of columns in the list.
278  *
279  * list_alias - if non-zero, print all of the supported aliases
280  *              for a device (e.g. F84, 16F84, etc...)
281  *-----------------------------------------------------------------*/
282 void list_valid_pics(int ncols, int list_alias)
283 {
284   int col,longest;
285   int i,j,k,l;
286
287   if(list_alias)
288     list_alias = sizeof(Pics[0].name) / sizeof(Pics[0].name[0]);
289
290   /* decrement the column number if it's greater than zero */
291   ncols = (ncols > 1) ? ncols-1 : 4;
292
293   /* Find the device with the longest name */
294   for(i=0,longest=0; i<num_of_supported_PICS; i++) {
295     for(j=0; j<=list_alias; j++) {
296       k = strlen(Pics[i].name[j]);
297       if(k>longest)
298         longest = k;
299     }
300   }
301
302   col = 0;
303
304   for(i=0;  i < num_of_supported_PICS; i++) {
305     j = 0;
306     do {
307
308       fprintf(stderr,"%s", Pics[i].name[j]);
309       if(col<ncols) {
310         l = longest + 2 - strlen(Pics[i].name[j]);
311         for(k=0; k<l; k++)
312           fputc(' ',stderr);
313
314         col++;
315
316       } else {
317         fputc('\n',stderr);
318         col = 0;
319       }
320
321     } while(++j<list_alias);
322
323   }
324   if(col != ncols)
325     fputc('\n',stderr);
326
327 }
328
329 /*-----------------------------------------------------------------*
330  *  
331  *-----------------------------------------------------------------*/
332 PIC_device *find_device(char *name)
333 {
334
335   int i,j;
336
337   if(!name)
338     return NULL;
339
340   for(i = 0; i<num_of_supported_PICS; i++) {
341
342     for(j=0; j<PROCESSOR_NAMES; j++)
343       if(!STRCASECMP(Pics[i].name[j], name) )
344         return &Pics[i];
345   }
346
347   /* not found */
348   return NULL; 
349 }
350
351 /*-----------------------------------------------------------------*
352  *  
353  *-----------------------------------------------------------------*/
354 void init_pic(char *pic_type)
355 {
356   pic = find_device(pic_type);
357
358   if(!pic) {
359     if(pic_type)
360       fprintf(stderr, "'%s' was not found.\n", pic_type);
361     else
362       fprintf(stderr, "No processor has been specified (use -pPROCESSOR_NAME)\n");
363
364     fprintf(stderr,"Valid devices are:\n");
365
366     list_valid_pics(4,0);
367     exit(1);
368   }
369
370   pic->maxRAMaddress = -1;
371 }
372
373 /*-----------------------------------------------------------------*
374  *  
375  *-----------------------------------------------------------------*/
376 int picIsInitialized(void)
377 {
378   if(pic && pic->maxRAMaddress > 0)
379     return 1;
380
381   return 0;
382
383 }
384
385 /*-----------------------------------------------------------------*
386  *  char *processor_base_name(void) - Include file is derived from this.
387  *-----------------------------------------------------------------*/
388 char *processor_base_name(void)
389 {
390
391   if(!pic)
392     return NULL;
393
394   return pic->name[0];
395 }
396
397 int isSFR(int address)
398 {
399
400   if( (address > pic->maxRAMaddress) || !finalMapping[address].isSFR)
401     return 0;
402
403   return 1;
404
405 }
406
407 /*-----------------------------------------------------------------*
408  *-----------------------------------------------------------------*/
409 int validAddress(int address, int reg_size)
410 {
411   int i;
412
413   if (pic->maxRAMaddress < 0) {
414     fprintf(stderr, "missing \"#pragma maxram\" setting\n");
415     return 0;
416   }
417   //  fprintf(stderr, "validAddress: Checking 0x%04x\n",address);
418   if(address > pic->maxRAMaddress)
419     return 0;
420
421   for (i=0; i<reg_size; i++)
422     if(!finalMapping[address + i].isValid || 
423        finalMapping[address+i].reg ||
424        finalMapping[address+i].isSFR )
425       return 0;
426
427   return 1;
428 }
429
430 /*-----------------------------------------------------------------*
431  *-----------------------------------------------------------------*/
432 void mapRegister(regs *reg)
433 {
434
435   int i;
436   int alias;
437
438   if(!reg || !reg->size) {
439     fprintf(stderr,"WARNING: %s:%s:%d Bad register\n",__FILE__,__FUNCTION__,__LINE__);
440     return;
441   }
442
443   if (pic->maxRAMaddress < 0) {
444     fprintf(stderr, "missing \"#pragma maxram\" setting\n");
445     return;
446   }
447
448   for(i=0; i<reg->size; i++) {
449
450     alias = finalMapping[reg->address].alias;
451     reg->alias = alias;
452
453     do {
454
455       //fprintf(stdout,"mapping %s to address 0x%02x, reg size = %d\n",reg->name, (reg->address+alias+i),reg->size);
456
457       finalMapping[reg->address + alias + i].reg = reg;
458       finalMapping[reg->address + alias + i].instance = i;
459
460       /* Decrement alias */
461       if(alias)
462         alias -= ((alias & (alias - 1)) ^ alias);
463       else
464         alias--;
465
466     } while (alias>=0);
467   }
468
469   //fprintf(stderr,"%s - %s addr = 0x%03x, size %d\n",__FUNCTION__,reg->name, reg->address,reg->size);
470
471   reg->isMapped = 1;
472
473 }
474
475 /*-----------------------------------------------------------------*
476  *-----------------------------------------------------------------*/
477 int assignRegister(regs *reg, int start_address)
478 {
479   int i;
480
481   //fprintf(stderr,"%s -  %s start_address = 0x%03x\n",__FUNCTION__,reg->name, start_address);
482   if(reg->isFixed) {
483
484     if (validAddress(reg->address,reg->size)) {
485       //fprintf(stderr,"%s -  %s address = 0x%03x\n",__FUNCTION__,reg->name, reg->address);
486       mapRegister(reg);
487       return reg->address;
488     }
489
490     if( isSFR(reg->address)) {
491       mapRegister(reg);
492       return reg->address;
493     }
494
495     //fprintf(stderr, "WARNING: Ignoring Out of Range register assignment at fixed address %d, %s\n",
496     //    reg->address, reg->name);
497
498   } else {
499
500     /* This register does not have a fixed address requirement
501      * so we'll search through all availble ram address and
502      * assign the first one */
503
504     for (i=start_address; i<=pic->maxRAMaddress; i++) {
505
506       if (validAddress(i,reg->size)) {
507         reg->address = i;
508         mapRegister(reg);
509         return i;
510       }
511     }
512
513     fprintf(stderr, "WARNING: No more RAM available for %s\n",reg->name);
514
515   }
516
517   return -1;
518 }
519
520 /*-----------------------------------------------------------------*
521  *-----------------------------------------------------------------*/
522 void assignFixedRegisters(set *regset)
523 {
524   regs *reg;
525
526   for (reg = setFirstItem(regset) ; reg ; 
527        reg = setNextItem(regset)) {
528
529     if(reg->isFixed) 
530       assignRegister(reg,0);
531   }
532
533 }
534
535 /*-----------------------------------------------------------------*
536  *-----------------------------------------------------------------*/
537 void assignRelocatableRegisters(set *regset, int used)
538 {
539
540   regs *reg;
541   int address = 0;
542
543   for (reg = setFirstItem(regset) ; reg ; 
544        reg = setNextItem(regset)) {
545
546     //fprintf(stdout,"assigning %s isFixed=%d, wasUsed=%d\n",reg->name,reg->isFixed,reg->wasUsed);
547
548     if((!reg->isFixed) && ( used || reg->wasUsed))
549       address = assignRegister(reg,address);
550
551   }
552
553 }
554
555
556 /*-----------------------------------------------------------------*
557  *  void assignConfigWordValue(int address, int value)
558  *
559  * All midrange PICs have one config word at address 0x2007.
560  * This routine will assign a value to that address.
561  *
562  *-----------------------------------------------------------------*/
563
564 void assignConfigWordValue(int address, int value)
565 {
566   if(CONFIG_WORD_ADDRESS == address)
567     config_word = value;
568
569   //fprintf(stderr,"setting config word to 0x%x\n",value);
570
571 }
572 /*-----------------------------------------------------------------*
573  * int getConfigWord(int address)
574  *
575  * Get the current value of the config word.
576  *
577  *-----------------------------------------------------------------*/
578
579 int getConfigWord(int address)
580 {
581   if(CONFIG_WORD_ADDRESS == address)
582     return config_word;
583
584   else
585     return 0;
586
587 }