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