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 static PIC_device Pics[] = {
119 {"p16f627", "16f627", "pic16f627", "f627"}, /* processor name */
120 p16f627_mem, /* ram mem map */
121 p16f627_sfr, /* sfr mem map */
122 0, /* max ram address (calculated) */
123 0x80, /* Bank Mask */
127 {"p16f628", "16f628", "pic16f628", "f628"},
135 {"p16f84", "16f84", "pic16f84", "f84"},
143 {"p16f877", "16f877", "pic16f877", "f877"},
152 static int num_of_supported_PICS = sizeof(Pics)/sizeof(PIC_device);
154 #define DEFAULT_PIC "f877"
156 static PIC_device *pic=NULL;
158 AssignedMemory *finalMapping=NULL;
160 #define CONFIG_WORD_ADDRESS 0x2007
161 #define DEFAULT_CONFIG_WORD 0x3fff
163 static unsigned int config_word = DEFAULT_CONFIG_WORD;
165 /*-----------------------------------------------------------------*
167 * void addMem(memRange *ranges,int type)
170 *-----------------------------------------------------------------*/
172 static void addMem(memRange *ranges,int type)
174 memRange *r = ranges;
179 int alias = r->alias;
183 for(i=r->start_address; i<= r->end_address; i++) {
184 if(i <= pic->maxRAMaddress) {
185 finalMapping[i | alias].isValid = 1;
186 finalMapping[i | alias].alias = r->alias;
187 finalMapping[i | alias].bank = r->bank;
190 finalMapping[i | alias].isSFR = 1;
192 finalMapping[i | alias].isSFR = 0;
196 /* Decrement alias */
198 alias -= ((alias & (alias - 1)) ^ alias);
206 } while (r->start_address >= 0);
211 /*-----------------------------------------------------------------*
212 *-----------------------------------------------------------------*/
214 int isREGinBank(regs *reg, int bank)
220 if(((reg->address | reg->alias) & pic->bankMask & bank) == bank)
226 /*-----------------------------------------------------------------*
227 *-----------------------------------------------------------------*/
228 int REGallBanks(regs *reg)
234 return ((reg->address | reg->alias) & pic->bankMask);
238 /*-----------------------------------------------------------------*
239 *-----------------------------------------------------------------*/
241 static void addMaps(PIC_device *pPic)
250 /* First, find the maximum address */
253 pPic->maxRAMaddress = 0;
257 if((r->end_address | r->alias) > pPic->maxRAMaddress)
258 pPic->maxRAMaddress = r->end_address | r->alias;
262 } while (r->start_address >= 0);
266 finalMapping = Safe_calloc(1+pPic->maxRAMaddress, sizeof(AssignedMemory));
268 /* Now initialize the finalMapping array */
270 for(i=0; i<=pPic->maxRAMaddress; i++) {
271 finalMapping[i].reg = NULL;
272 finalMapping[i].isValid = 0;
275 addMem(pPic->ram,0); /* add general purpose regs to the map */
276 addMem(pPic->sfr,1); /* Add SFR's to the memmap */
281 * dump_map -- debug stuff
288 for(i=0; i<=pic->maxRAMaddress; i++) {
289 //fprintf(stdout , "addr 0x%02x is %s\n", i, ((finalMapping[i].isValid) ? "valid":"invalid"));
291 if(finalMapping[i].isValid) {
292 fprintf(stderr,"addr: 0x%02x",i);
293 if(finalMapping[i].isSFR)
294 fprintf(stderr," isSFR");
295 if(finalMapping[i].reg)
296 fprintf( stderr, " reg %s", finalMapping[i].reg->name);
297 fprintf(stderr, "\n");
303 void dump_cblock(FILE *of)
309 //dump_map(); /* display the register map */
313 if(finalMapping[addr].reg && !finalMapping[addr].reg->isEmitted) {
320 /* clear the lower 7-bits of the start address of the first
321 * variable declared in this bank. The upper bits for the mid
322 * range pics are the bank select bits.
325 bank_base = start & 0xfff8;
327 /* The bank number printed in the cblock comment tacitly
328 * assumes that the first register in the contiguous group
329 * of registers represents the bank for the whole group */
331 fprintf(of," cblock 0X%04X\t; Bank %d\n",start,finalMapping[start].bank);
333 for( ; start < addr; start++) {
334 if((finalMapping[start].reg) && !finalMapping[start].reg->isEmitted ) {
335 fprintf(of,"\t%s",finalMapping[start].reg->name);
337 /* If this register is aliased in multiple banks, then
338 * mangle the variable name with the alias address: */
339 if(finalMapping[start].alias & start)
340 fprintf(of,"_%x",bank_base);
342 if(finalMapping[start].instance)
343 fprintf(of,"_%d",finalMapping[start].instance);
348 //finalMapping[start].reg->isEmitted = 1;
352 fprintf(of," endc\n");
361 } while(addr <= pic->maxRAMaddress);
366 /*-----------------------------------------------------------------*
367 * void list_valid_pics(int ncols, int list_alias)
369 * Print out a formatted list of valid PIC devices
371 * ncols - number of columns in the list.
373 * list_alias - if non-zero, print all of the supported aliases
374 * for a device (e.g. F84, 16F84, etc...)
375 *-----------------------------------------------------------------*/
376 void list_valid_pics(int ncols, int list_alias)
382 list_alias = sizeof(Pics[0].name) / sizeof(Pics[0].name[0]);
384 /* decrement the column number if it's greater than zero */
385 ncols = (ncols > 1) ? ncols-1 : 4;
387 /* Find the device with the longest name */
388 for(i=0,longest=0; i<num_of_supported_PICS; i++) {
389 for(j=0; j<=list_alias; j++) {
390 k = strlen(Pics[i].name[j]);
398 for(i=0; i < num_of_supported_PICS; i++) {
402 fprintf(stderr,"%s", Pics[i].name[j]);
404 l = longest + 2 - strlen(Pics[i].name[j]);
415 } while(++j<list_alias);
423 /*-----------------------------------------------------------------*
425 *-----------------------------------------------------------------*/
426 PIC_device *find_device(char *name)
434 for(i = 0; i<num_of_supported_PICS; i++) {
436 for(j=0; j<PROCESSOR_NAMES; j++)
437 if(!STRCASECMP(Pics[i].name[j], name) )
445 /*-----------------------------------------------------------------*
447 *-----------------------------------------------------------------*/
448 void init_pic(char *pic_type)
450 pic = find_device(pic_type);
454 fprintf(stderr, "'%s' was not found.\n", pic_type);
456 fprintf(stderr, "No processor has been specified (use -pPROCESSOR_NAME)\n");
458 fprintf(stderr,"Valid devices are:\n");
460 list_valid_pics(4,0);
470 /*-----------------------------------------------------------------*
471 * char *processor_base_name(void) - Include file is derived from this.
472 *-----------------------------------------------------------------*/
473 char *processor_base_name(void)
482 int isSFR(int address)
485 if( (address > pic->maxRAMaddress) || !finalMapping[address].isSFR)
492 int validAddress(int address, int reg_size)
496 if(address > pic->maxRAMaddress)
499 for (i=0; i<reg_size; i++)
500 if(!finalMapping[address + i].isValid ||
501 finalMapping[address+i].reg ||
502 finalMapping[address+i].isSFR )
508 void mapRegister(regs *reg)
514 if(!reg || !reg->size) {
515 fprintf(stderr,"WARNING: %s:%s:%d Bad register\n",__FILE__,__FUNCTION__,__LINE__);
519 for(i=0; i<reg->size; i++) {
521 alias = finalMapping[reg->address].alias;
526 // fprintf(stdout,"mapping %s to address 0x%02x, reg size = %d\n",reg->name, (reg->address+alias+i),reg->size);
528 finalMapping[reg->address + alias + i].reg = reg;
529 finalMapping[reg->address + alias + i].instance = i;
531 /* Decrement alias */
533 alias -= ((alias & (alias - 1)) ^ alias);
540 // fprintf(stderr,"%s - %s addr = 0x%03x, size %d\n",__FUNCTION__,reg->name, reg->address,reg->size);
546 int assignRegister(regs *reg, int start_address)
550 //fprintf(stderr,"%s - %s start_address = 0x%03x\n",__FUNCTION__,reg->name, start_address);
553 if (validAddress(reg->address,reg->size)) {
559 if( isSFR(reg->address)) {
563 fprintf(stderr, "WARNING: Ignoring Out of Range register assignment at fixed address %d, %s\n",
564 reg->address, reg->name);
568 /* This register does not have a fixed address requirement
569 * so we'll search through all availble ram address and
570 * assign the first one */
572 for (i=start_address; i<=pic->maxRAMaddress; i++) {
574 if (validAddress(i,reg->size)) {
581 fprintf(stderr, "WARNING: No more RAM available\n");
588 void assignFixedRegisters(set *regset)
592 for (reg = setFirstItem(regset) ; reg ;
593 reg = setNextItem(regset)) {
596 assignRegister(reg,0);
601 void assignRelocatableRegisters(set *regset, int used)
607 for (reg = setFirstItem(regset) ; reg ;
608 reg = setNextItem(regset)) {
610 //fprintf(stdout,"assigning %s isFixed=%d, wasUsed=%d\n",reg->name,reg->isFixed,reg->wasUsed);
612 if((!reg->isFixed) && ( used || reg->wasUsed))
613 address = assignRegister(reg,address);
620 /*-----------------------------------------------------------------*
621 * void assignConfigWordValue(int address, int value)
623 * All midrange PICs have one config word at address 0x2007.
624 * This routine will assign a value to that address.
626 *-----------------------------------------------------------------*/
628 void assignConfigWordValue(int address, int value)
630 if(CONFIG_WORD_ADDRESS == address)
633 //fprintf(stderr,"setting config word to 0x%x\n",value);
636 /*-----------------------------------------------------------------*
637 * int getConfigWord(int address)
639 * Get the current value of the config word.
641 *-----------------------------------------------------------------*/
643 int getConfigWord(int address)
645 if(CONFIG_WORD_ADDRESS == address)