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) */
126 {"p16f628", "16f628", "pic16f628", "f628"},
133 {"p16f84", "16f84", "pic16f84", "f84"},
140 {"p16f877", "16f877", "pic16f877", "f877"},
148 static int num_of_supported_PICS = sizeof(Pics)/sizeof(PIC_device);
150 #define DEFAULT_PIC "f877"
152 static PIC_device *pic=NULL;
154 AssignedMemory *finalMapping=NULL;
156 #define CONFIG_WORD_ADDRESS 0x2007
157 #define DEFAULT_CONFIG_WORD 0x3fff
159 static unsigned int config_word = DEFAULT_CONFIG_WORD;
161 /*-----------------------------------------------------------------*
163 * void addMem(memRange *ranges,int type)
166 *-----------------------------------------------------------------*/
168 static void addMem(memRange *ranges,int type)
170 memRange *r = ranges;
175 int alias = r->alias;
179 for(i=r->start_address; i<= r->end_address; i++) {
180 if(i <= pic->maxRAMaddress) {
181 finalMapping[i | alias].isValid = 1;
182 finalMapping[i | alias].alias = r->alias;
183 finalMapping[i | alias].bank = r->bank;
186 finalMapping[i | alias].isSFR = 1;
188 finalMapping[i | alias].isSFR = 0;
192 /* Decrement alias */
194 alias -= ((alias & (alias - 1)) ^ alias);
202 } while (r->start_address >= 0);
207 static void addMaps(PIC_device *pPic)
216 /* First, find the maximum address */
219 pPic->maxRAMaddress = 0;
223 if((r->end_address | r->alias) > pPic->maxRAMaddress)
224 pPic->maxRAMaddress = r->end_address | r->alias;
228 } while (r->start_address >= 0);
232 finalMapping = Safe_calloc(1+pPic->maxRAMaddress, sizeof(AssignedMemory));
234 /* Now initialize the finalMapping array */
236 for(i=0; i<=pPic->maxRAMaddress; i++) {
237 finalMapping[i].reg = NULL;
238 finalMapping[i].isValid = 0;
241 addMem(pPic->ram,0); /* add general purpose regs to the map */
242 addMem(pPic->sfr,1); /* Add SFR's to the memmap */
247 * dump_map -- debug stuff
254 for(i=0; i<=pic->maxRAMaddress; i++) {
255 //fprintf(stdout , "addr 0x%02x is %s\n", i, ((finalMapping[i].isValid) ? "valid":"invalid"));
257 if(finalMapping[i].isValid) {
258 fprintf(stderr,"addr: 0x%02x",i);
259 if(finalMapping[i].isSFR)
260 fprintf(stderr," isSFR");
261 if(finalMapping[i].reg)
262 fprintf( stderr, " reg %s", finalMapping[i].reg->name);
263 fprintf(stderr, "\n");
269 void dump_cblock(FILE *of)
275 //dump_map(); /* display the register map */
279 if(finalMapping[addr].reg && !finalMapping[addr].reg->isEmitted) {
286 /* clear the lower 7-bits of the start address of the first
287 * variable declared in this bank. The upper bits for the mid
288 * range pics are the bank select bits.
291 bank_base = start & 0xfff8;
293 /* The bank number printed in the cblock comment tacitly
294 * assumes that the first register in the contiguous group
295 * of registers represents the bank for the whole group */
297 fprintf(of," cblock 0X%04X\t; Bank %d\n",start,finalMapping[start].bank);
299 for( ; start < addr; start++) {
300 if((finalMapping[start].reg) && !finalMapping[start].reg->isEmitted ) {
301 fprintf(of,"\t%s",finalMapping[start].reg->name);
303 /* If this register is aliased in multiple banks, then
304 * mangle the variable name with the alias address: */
305 if(finalMapping[start].alias & start)
306 fprintf(of,"_%x",bank_base);
308 if(finalMapping[start].instance)
309 fprintf(of,"_%d",finalMapping[start].instance);
314 //finalMapping[start].reg->isEmitted = 1;
318 fprintf(of," endc\n");
327 } while(addr <= pic->maxRAMaddress);
332 /*-----------------------------------------------------------------*
333 * void list_valid_pics(int ncols, int list_alias)
335 * Print out a formatted list of valid PIC devices
337 * ncols - number of columns in the list.
339 * list_alias - if non-zero, print all of the supported aliases
340 * for a device (e.g. F84, 16F84, etc...)
341 *-----------------------------------------------------------------*/
342 void list_valid_pics(int ncols, int list_alias)
348 list_alias = sizeof(Pics[0].name) / sizeof(Pics[0].name[0]);
350 /* decrement the column number if it's greater than zero */
351 ncols = (ncols > 1) ? ncols-1 : 4;
353 /* Find the device with the longest name */
354 for(i=0,longest=0; i<num_of_supported_PICS; i++) {
355 for(j=0; j<=list_alias; j++) {
356 k = strlen(Pics[i].name[j]);
364 for(i=0; i < num_of_supported_PICS; i++) {
368 fprintf(stderr,"%s", Pics[i].name[j]);
370 l = longest + 2 - strlen(Pics[i].name[j]);
381 } while(++j<list_alias);
389 /*-----------------------------------------------------------------*
391 *-----------------------------------------------------------------*/
392 PIC_device *find_device(char *name)
400 for(i = 0; i<num_of_supported_PICS; i++) {
402 for(j=0; j<PROCESSOR_NAMES; j++)
403 if(!STRCASECMP(Pics[i].name[j], name) )
411 /*-----------------------------------------------------------------*
413 *-----------------------------------------------------------------*/
414 void init_pic(char *pic_type)
416 pic = find_device(pic_type);
420 fprintf(stderr, "'%s' was not found.\n", pic_type);
422 fprintf(stderr, "No processor has been specified (use -pPROCESSOR_NAME)\n");
424 fprintf(stderr,"Valid devices are:\n");
426 list_valid_pics(4,0);
436 /*-----------------------------------------------------------------*
437 * char *processor_base_name(void) - Include file is derived from this.
438 *-----------------------------------------------------------------*/
439 char *processor_base_name(void)
448 int isSFR(int address)
451 if( (address > pic->maxRAMaddress) || !finalMapping[address].isSFR)
458 int validAddress(int address, int reg_size)
462 if(address > pic->maxRAMaddress)
465 for (i=0; i<reg_size; i++)
466 if(!finalMapping[address + i].isValid ||
467 finalMapping[address+i].reg ||
468 finalMapping[address+i].isSFR )
474 void mapRegister(regs *reg)
480 if(!reg || !reg->size) {
481 fprintf(stderr,"WARNING: %s:%s:%d Bad register\n",__FILE__,__FUNCTION__,__LINE__);
485 for(i=0; i<reg->size; i++) {
487 alias = finalMapping[reg->address].alias;
492 // fprintf(stdout,"mapping %s to address 0x%02x, reg size = %d\n",reg->name, (reg->address+alias+i),reg->size);
494 finalMapping[reg->address + alias + i].reg = reg;
495 finalMapping[reg->address + alias + i].instance = i;
497 /* Decrement alias */
499 alias -= ((alias & (alias - 1)) ^ alias);
506 // fprintf(stderr,"%s - %s addr = 0x%03x, size %d\n",__FUNCTION__,reg->name, reg->address,reg->size);
512 int assignRegister(regs *reg, int start_address)
516 //fprintf(stderr,"%s - %s start_address = 0x%03x\n",__FUNCTION__,reg->name, start_address);
519 if (validAddress(reg->address,reg->size)) {
525 if( isSFR(reg->address)) {
529 fprintf(stderr, "WARNING: Ignoring Out of Range register assignment at fixed address %d, %s\n",
530 reg->address, reg->name);
534 /* This register does not have a fixed address requirement
535 * so we'll search through all availble ram address and
536 * assign the first one */
538 for (i=start_address; i<=pic->maxRAMaddress; i++) {
540 if (validAddress(i,reg->size)) {
547 fprintf(stderr, "WARNING: No more RAM available\n");
554 void assignFixedRegisters(set *regset)
558 for (reg = setFirstItem(regset) ; reg ;
559 reg = setNextItem(regset)) {
562 assignRegister(reg,0);
567 void assignRelocatableRegisters(set *regset, int used)
573 for (reg = setFirstItem(regset) ; reg ;
574 reg = setNextItem(regset)) {
576 // fprintf(stdout,"assigning %s\n",reg->name);
578 if((!reg->isFixed) && ( (used==0) || reg->wasUsed))
579 address = assignRegister(reg,address);
586 /*-----------------------------------------------------------------*
587 * void assignConfigWordValue(int address, int value)
589 * All midrange PICs have one config word at address 0x2007.
590 * This routine will assign a value to that address.
592 *-----------------------------------------------------------------*/
594 void assignConfigWordValue(int address, int value)
596 if(CONFIG_WORD_ADDRESS == address)
599 fprintf(stderr,"setting config word to 0x%x\n",value);
602 /*-----------------------------------------------------------------*
603 * int getConfigWord(int address)
605 * Get the current value of the config word.
607 *-----------------------------------------------------------------*/
609 int getConfigWord(int address)
611 if(CONFIG_WORD_ADDRESS == address)