1 /*-------------------------------------------------------------------------
3 device.c - Accomodates subtle variations in PIC devices
4 Written By - Scott Dattalo scott@dattalo.com
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
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.
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 -------------------------------------------------------------------------*/
23 #include "common.h" // Include everything in the SDCC src directory
31 #if defined(__BORLANDC__) || defined(_MSC_VER)
32 #define STRCASECMP stricmp
34 #define STRCASECMP strcasecmp
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 */
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 {0x81, 0x81, 0x100, 1},
52 {0x85, 0x85, 0x000, 1},
53 {0x86, 0x86, 0x100, 1},
54 {0x0a, 0x0b, 0x180, 0},
55 {0x0c, 0x0c, 0x000, 0},
56 {0x0e, 0x12, 0x000, 0},
57 {0x15, 0x1a, 0x000, 0},
58 {0x1f, 0x1f, 0x000, 0},
59 {0x8e, 0x8e, 0x000, 1},
60 {0x92, 0x92, 0x000, 1},
61 {0x98, 0x9d, 0x000, 1},
62 {0x9f, 0x9f, 0x000, 1},
64 {-1, -1, -1, -1} /* end indicator */
68 memRange p16f84_mem[] = {
69 {0x0c, 0x4f, 0x80, 0},
70 {-1, -1, -1, -1} /* end indicator */
72 memRange p16f84_sfr[] = {
73 {0x01, 0x01, 0x00, 0},
74 {0x02, 0x04, 0x80, 0},
75 {0x05, 0x06, 0x00, 0},
76 {0x81, 0x81, 0x00, 1},
77 {0x85, 0x86, 0x00, 1},
78 {0x08, 0x09, 0x00, 0},
79 {0x88, 0x89, 0x00, 1},
80 {0x0a, 0x0b, 0x80, 0},
81 {-1, -1, -1, -1} /* end indicator */
85 memRange p16f877_mem[] = {
86 {0x20, 0x6f, 0x00, 0},
87 {0xa0, 0xef, 0x00, 1},
88 {0x110, 0x16f, 0x00, 2},
89 {0x190, 0x1ef, 0x00, 3},
90 {0x70, 0x7f, 0x180, 0},
91 {-1, -1, -1, -1} /* end indicator */
93 memRange p16f877_sfr[] = {
94 {0x00, 0x00, 0x180, 0},
95 {0x01, 0x01, 0x100, 0},
96 {0x02, 0x04, 0x180, 0},
97 {0x05, 0x05, 0x000, 0},
98 {0x85, 0x85, 0x000, 1},
99 {0x81, 0x81, 0x100, 1},
100 {0x06, 0x06, 0x100, 0},
101 {0x86, 0x86, 0x100, 1},
102 {0x07, 0x09, 0x000, 0},
103 {0x87, 0x89, 0x000, 1},
104 {0x0a, 0x0b, 0x180, 0},
105 {0x0c, 0x1f, 0x000, 0},
106 {0x8c, 0x8e, 0x000, 1},
107 {0x91, 0x94, 0x000, 1},
108 {0x98, 0x99, 0x000, 1},
109 {0x9e, 0x9f, 0x000, 1},
110 {0x10c, 0x10f, 0x000, 2},
111 {0x18c, 0x18f, 0x000, 3},
113 {-1, -1, -1, -1} /* end indicator */
117 memRange p16f873_mem[] = {
118 {0x20, 0x7f, 0x100, 0},
119 {0xa0, 0xff, 0x100, 1},
120 {-1, -1, -1, -1} /* end indicator */
122 memRange p16f873_sfr[] = {
123 {0x00, 0x00, 0x180, 0},
124 {0x01, 0x01, 0x100, 0},
125 {0x02, 0x04, 0x180, 0},
126 {0x05, 0x05, 0x000, 0},
127 {0x85, 0x85, 0x000, 1},
128 {0x81, 0x81, 0x100, 1},
129 {0x06, 0x06, 0x100, 0},
130 {0x86, 0x86, 0x100, 1},
131 {0x07, 0x09, 0x000, 0},
132 {0x87, 0x89, 0x000, 1},
133 {0x0a, 0x0b, 0x180, 0},
134 {0x0c, 0x1f, 0x000, 0},
135 {0x8c, 0x8e, 0x000, 1},
136 {0x91, 0x94, 0x000, 1},
137 {0x98, 0x99, 0x000, 1},
138 {0x9e, 0x9f, 0x000, 1},
139 {0x10c, 0x10f, 0x000, 2},
140 {0x18c, 0x18f, 0x000, 3},
142 {-1, -1, -1, -1} /* end indicator */
145 static PIC_device Pics[] = {
147 {"p16f627", "16f627", "pic16f627", "f627"}, /* processor name */
148 p16f627_mem, /* ram mem map */
149 p16f627_sfr, /* sfr mem map */
150 0, /* max ram address (calculated) */
151 0x80, /* Bank Mask */
155 {"p16f628", "16f628", "pic16f628", "f628"},
163 {"p16f84", "16f84", "pic16f84", "f84"},
171 {"p16f873", "16f873", "pic16f873", "f873"},
179 {"p16f877", "16f877", "pic16f877", "f877"},
188 static int num_of_supported_PICS = sizeof(Pics)/sizeof(PIC_device);
190 #define DEFAULT_PIC "f877"
192 static PIC_device *pic=NULL;
194 AssignedMemory *finalMapping=NULL;
196 #define CONFIG_WORD_ADDRESS 0x2007
197 #define DEFAULT_CONFIG_WORD 0x3fff
199 static unsigned int config_word = DEFAULT_CONFIG_WORD;
201 /*-----------------------------------------------------------------*
203 * void addMem(memRange *ranges,int type)
206 *-----------------------------------------------------------------*/
208 static void addMem(memRange *ranges,int type)
210 memRange *r = ranges;
215 int alias = r->alias;
219 for(i=r->start_address; i<= r->end_address; i++) {
220 if(i <= pic->maxRAMaddress) {
221 finalMapping[i | alias].isValid = 1;
222 finalMapping[i | alias].alias = r->alias;
223 finalMapping[i | alias].bank = r->bank;
226 finalMapping[i | alias].isSFR = 1;
228 finalMapping[i | alias].isSFR = 0;
232 /* Decrement alias */
234 alias -= ((alias & (alias - 1)) ^ alias);
242 } while (r->start_address >= 0);
247 /*-----------------------------------------------------------------*
248 *-----------------------------------------------------------------*/
250 int isREGinBank(regs *reg, int bank)
256 if(((reg->address | reg->alias) & pic->bankMask & bank) == bank)
262 /*-----------------------------------------------------------------*
263 *-----------------------------------------------------------------*/
264 int REGallBanks(regs *reg)
270 return ((reg->address | reg->alias) & pic->bankMask);
274 /*-----------------------------------------------------------------*
275 *-----------------------------------------------------------------*/
277 static void addMaps(PIC_device *pPic)
286 /* First, find the maximum address */
289 pPic->maxRAMaddress = 0;
293 if((r->end_address | r->alias) > pPic->maxRAMaddress)
294 pPic->maxRAMaddress = r->end_address | r->alias;
298 } while (r->start_address >= 0);
302 finalMapping = Safe_calloc(1+pPic->maxRAMaddress, sizeof(AssignedMemory));
304 /* Now initialize the finalMapping array */
306 for(i=0; i<=pPic->maxRAMaddress; i++) {
307 finalMapping[i].reg = NULL;
308 finalMapping[i].isValid = 0;
311 addMem(pPic->ram,0); /* add general purpose regs to the map */
312 addMem(pPic->sfr,1); /* Add SFR's to the memmap */
317 * dump_map -- debug stuff
324 for(i=0; i<=pic->maxRAMaddress; i++) {
325 //fprintf(stdout , "addr 0x%02x is %s\n", i, ((finalMapping[i].isValid) ? "valid":"invalid"));
327 if(finalMapping[i].isValid) {
328 fprintf(stderr,"addr: 0x%02x",i);
329 if(finalMapping[i].isSFR)
330 fprintf(stderr," isSFR");
331 if(finalMapping[i].reg)
332 fprintf( stderr, " reg %s", finalMapping[i].reg->name);
333 fprintf(stderr, "\n");
339 void dump_cblock(FILE *of)
345 //dump_map(); /* display the register map */
349 if(finalMapping[addr].reg && !finalMapping[addr].reg->isEmitted) {
356 /* clear the lower 7-bits of the start address of the first
357 * variable declared in this bank. The upper bits for the mid
358 * range pics are the bank select bits.
361 bank_base = start & 0xfff8;
363 /* The bank number printed in the cblock comment tacitly
364 * assumes that the first register in the contiguous group
365 * of registers represents the bank for the whole group */
367 fprintf(of," cblock 0X%04X\t; Bank %d\n",start,finalMapping[start].bank);
369 for( ; start < addr; start++) {
370 if((finalMapping[start].reg) && !finalMapping[start].reg->isEmitted ) {
371 fprintf(of,"\t%s",finalMapping[start].reg->name);
373 /* If this register is aliased in multiple banks, then
374 * mangle the variable name with the alias address: */
375 if(finalMapping[start].alias & start)
376 fprintf(of,"_%x",bank_base);
378 if(finalMapping[start].instance)
379 fprintf(of,"_%d",finalMapping[start].instance);
384 //finalMapping[start].reg->isEmitted = 1;
388 fprintf(of," endc\n");
397 } while(addr <= pic->maxRAMaddress);
402 /*-----------------------------------------------------------------*
403 * void list_valid_pics(int ncols, int list_alias)
405 * Print out a formatted list of valid PIC devices
407 * ncols - number of columns in the list.
409 * list_alias - if non-zero, print all of the supported aliases
410 * for a device (e.g. F84, 16F84, etc...)
411 *-----------------------------------------------------------------*/
412 void list_valid_pics(int ncols, int list_alias)
418 list_alias = sizeof(Pics[0].name) / sizeof(Pics[0].name[0]);
420 /* decrement the column number if it's greater than zero */
421 ncols = (ncols > 1) ? ncols-1 : 4;
423 /* Find the device with the longest name */
424 for(i=0,longest=0; i<num_of_supported_PICS; i++) {
425 for(j=0; j<=list_alias; j++) {
426 k = strlen(Pics[i].name[j]);
434 for(i=0; i < num_of_supported_PICS; i++) {
438 fprintf(stderr,"%s", Pics[i].name[j]);
440 l = longest + 2 - strlen(Pics[i].name[j]);
451 } while(++j<list_alias);
459 /*-----------------------------------------------------------------*
461 *-----------------------------------------------------------------*/
462 PIC_device *find_device(char *name)
470 for(i = 0; i<num_of_supported_PICS; i++) {
472 for(j=0; j<PROCESSOR_NAMES; j++)
473 if(!STRCASECMP(Pics[i].name[j], name) )
481 /*-----------------------------------------------------------------*
483 *-----------------------------------------------------------------*/
484 void init_pic(char *pic_type)
486 pic = find_device(pic_type);
490 fprintf(stderr, "'%s' was not found.\n", pic_type);
492 fprintf(stderr, "No processor has been specified (use -pPROCESSOR_NAME)\n");
494 fprintf(stderr,"Valid devices are:\n");
496 list_valid_pics(4,0);
506 /*-----------------------------------------------------------------*
507 * char *processor_base_name(void) - Include file is derived from this.
508 *-----------------------------------------------------------------*/
509 char *processor_base_name(void)
518 int isSFR(int address)
521 if( (address > pic->maxRAMaddress) || !finalMapping[address].isSFR)
528 int validAddress(int address, int reg_size)
532 if(address > pic->maxRAMaddress)
535 for (i=0; i<reg_size; i++)
536 if(!finalMapping[address + i].isValid ||
537 finalMapping[address+i].reg ||
538 finalMapping[address+i].isSFR )
544 void mapRegister(regs *reg)
550 if(!reg || !reg->size) {
551 fprintf(stderr,"WARNING: %s:%s:%d Bad register\n",__FILE__,__FUNCTION__,__LINE__);
555 for(i=0; i<reg->size; i++) {
557 alias = finalMapping[reg->address].alias;
562 // fprintf(stdout,"mapping %s to address 0x%02x, reg size = %d\n",reg->name, (reg->address+alias+i),reg->size);
564 finalMapping[reg->address + alias + i].reg = reg;
565 finalMapping[reg->address + alias + i].instance = i;
567 /* Decrement alias */
569 alias -= ((alias & (alias - 1)) ^ alias);
576 // fprintf(stderr,"%s - %s addr = 0x%03x, size %d\n",__FUNCTION__,reg->name, reg->address,reg->size);
582 int assignRegister(regs *reg, int start_address)
586 //fprintf(stderr,"%s - %s start_address = 0x%03x\n",__FUNCTION__,reg->name, start_address);
589 if (validAddress(reg->address,reg->size)) {
595 if( isSFR(reg->address)) {
599 fprintf(stderr, "WARNING: Ignoring Out of Range register assignment at fixed address %d, %s\n",
600 reg->address, reg->name);
604 /* This register does not have a fixed address requirement
605 * so we'll search through all availble ram address and
606 * assign the first one */
608 for (i=start_address; i<=pic->maxRAMaddress; i++) {
610 if (validAddress(i,reg->size)) {
617 fprintf(stderr, "WARNING: No more RAM available\n");
624 void assignFixedRegisters(set *regset)
628 for (reg = setFirstItem(regset) ; reg ;
629 reg = setNextItem(regset)) {
632 assignRegister(reg,0);
637 void assignRelocatableRegisters(set *regset, int used)
643 for (reg = setFirstItem(regset) ; reg ;
644 reg = setNextItem(regset)) {
646 //fprintf(stdout,"assigning %s isFixed=%d, wasUsed=%d\n",reg->name,reg->isFixed,reg->wasUsed);
648 if((!reg->isFixed) && ( used || reg->wasUsed))
649 address = assignRegister(reg,address);
656 /*-----------------------------------------------------------------*
657 * void assignConfigWordValue(int address, int value)
659 * All midrange PICs have one config word at address 0x2007.
660 * This routine will assign a value to that address.
662 *-----------------------------------------------------------------*/
664 void assignConfigWordValue(int address, int value)
666 if(CONFIG_WORD_ADDRESS == address)
669 //fprintf(stderr,"setting config word to 0x%x\n",value);
672 /*-----------------------------------------------------------------*
673 * int getConfigWord(int address)
675 * Get the current value of the config word.
677 *-----------------------------------------------------------------*/
679 int getConfigWord(int address)
681 if(CONFIG_WORD_ADDRESS == address)