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);
149 static int default_pic = 0;
150 #define DEFAULT_PIC "f877"
152 static PIC_device *pic=NULL;
154 AssignedMemory *finalMapping=NULL;
155 /*-----------------------------------------------------------------*
157 * void addMem(memRange *ranges,int type)
160 *-----------------------------------------------------------------*/
162 static void addMem(memRange *ranges,int type)
164 memRange *r = ranges;
169 int alias = r->alias;
173 for(i=r->start_address; i<= r->end_address; i++) {
174 if(i <= pic->max_address) {
175 finalMapping[i | alias].isValid = 1;
176 finalMapping[i | alias].alias = r->alias;
177 finalMapping[i | alias].bank = r->bank;
180 finalMapping[i | alias].isSFR = 1;
182 finalMapping[i | alias].isSFR = 0;
186 /* Decrement alias */
188 alias -= ((alias & (alias - 1)) ^ alias);
196 } while (r->start_address >= 0);
201 static void addMaps(PIC_device *pPic)
210 /* First, find the maximum address */
213 pPic->max_address = 0;
217 if((r->end_address | r->alias) > pPic->max_address)
218 pPic->max_address = r->end_address | r->alias;
222 } while (r->start_address >= 0);
226 finalMapping = Safe_calloc(1+pPic->max_address, sizeof(AssignedMemory));
228 /* Now initialize the finalMapping array */
230 for(i=0; i<=pPic->max_address; i++) {
231 finalMapping[i].reg = NULL;
232 finalMapping[i].isValid = 0;
235 addMem(pPic->ram,0); /* add general purpose regs to the map */
236 addMem(pPic->sfr,1); /* Add SFR's to the memmap */
241 * dump_map -- debug stuff
248 for(i=0; i<=pic->max_address; i++) {
249 //fprintf(stdout , "addr 0x%02x is %s\n", i, ((finalMapping[i].isValid) ? "valid":"invalid"));
251 if(finalMapping[i].isValid) {
252 fprintf(stderr,"addr: 0x%02x",i);
253 if(finalMapping[i].isSFR)
254 fprintf(stderr," isSFR");
255 if(finalMapping[i].reg)
256 fprintf( stderr, " reg %s", finalMapping[i].reg->name);
257 fprintf(stderr, "\n");
263 void dump_cblock(FILE *of)
268 //dump_map(); /* display the register map */
272 if(finalMapping[addr].reg && !finalMapping[addr].reg->isEmitted) {
279 /* The bank number printed in the cblock comment tacitly
280 * assumes that the first register in the contiguous group
281 * of registers represents the bank for the whole group */
282 fprintf(of," cblock 0X%04X\t; Bank %d\n",start,finalMapping[start].bank);
284 for( ; start < addr; start++) {
285 if((finalMapping[start].reg) && !finalMapping[start].reg->isEmitted ) {
286 fprintf(of,"\t%s",finalMapping[start].reg->name);
288 /* If this register is aliased in multiple banks, then
289 * mangle the variable name with the alias address: */
290 if(finalMapping[start].alias & start)
291 fprintf(of,"_%x",finalMapping[start].alias);
293 if(finalMapping[start].instance)
294 fprintf(of,"_%d",finalMapping[start].instance);
299 //finalMapping[start].reg->isEmitted = 1;
303 fprintf(of," endc\n");
312 } while(addr <= pic->max_address);
317 /*-----------------------------------------------------------------*
318 * void list_valid_pics(int ncols, int list_alias)
320 * Print out a formatted list of valid PIC devices
322 * ncols - number of columns in the list.
324 * list_alias - if non-zero, print all of the supported aliases
325 * for a device (e.g. F84, 16F84, etc...)
326 *-----------------------------------------------------------------*/
327 void list_valid_pics(int ncols, int list_alias)
333 list_alias = sizeof(Pics[0].name) / sizeof(Pics[0].name[0]);
335 fprintf(stderr,"list_alias size = %d\n",list_alias);
336 /* decrement the column number if it's greater than zero */
337 ncols = (ncols > 1) ? ncols-1 : 4;
339 /* Find the device with the longest name */
340 for(i=0,longest=0; i<num_of_supported_PICS; i++) {
341 for(j=0; j<=list_alias; j++) {
342 k = strlen(Pics[i].name[j]);
350 for(i=0; i < num_of_supported_PICS; i++) {
354 fprintf(stderr,"%s", Pics[i].name[j]);
356 l = longest + 2 - strlen(Pics[i].name[j]);
367 } while(++j<list_alias);
375 /*-----------------------------------------------------------------*
377 *-----------------------------------------------------------------*/
378 PIC_device *find_device(char *name)
386 for(i = 0; i<num_of_supported_PICS; i++) {
388 for(j=0; j<PROCESSOR_NAMES; j++)
389 if(!STRCASECMP(Pics[i].name[j], name) )
397 /*-----------------------------------------------------------------*
399 *-----------------------------------------------------------------*/
402 pic = find_device(DEFAULT_PIC);
405 fprintf(stderr, "%s was not found.\nValid devices are:\n",DEFAULT_PIC);
406 list_valid_pics(4,0);
416 /*-----------------------------------------------------------------*
417 * char *processor_base_name(void) - Include file is derived from this.
418 *-----------------------------------------------------------------*/
419 char *processor_base_name(void)
428 int isSFR(int address)
431 if( (address > pic->max_address) || !finalMapping[address].isSFR)
438 int validAddress(int address, int reg_size)
442 if(address > pic->max_address)
445 for (i=0; i<reg_size; i++)
446 if(!finalMapping[address + i].isValid ||
447 finalMapping[address+i].reg ||
448 finalMapping[address+i].isSFR )
454 void mapRegister(regs *reg)
462 for(i=0; i<reg->size; i++) {
464 alias = finalMapping[reg->address].alias;
469 //fprintf(stdout,"mapping %s to address 0x%02x\n",reg->name, (reg->address+alias+i));
471 finalMapping[reg->address + alias + i].reg = reg;
472 finalMapping[reg->address + alias + i].instance = i;
474 /* Decrement alias */
476 alias -= ((alias & (alias - 1)) ^ alias);
487 int assignRegister(regs *reg, int start_address)
493 if (validAddress(reg->address,reg->size)) {
499 if( isSFR(reg->address)) {
503 fprintf(stderr, "WARNING: Ignoring Out of Range register assignment at fixed address %d, %s\n",
504 reg->address, reg->name);
508 /* This register does not have a fixed address requirement
509 * so we'll search through all availble ram address and
510 * assign the first one */
512 for (i=start_address; i<=pic->max_address; i++) {
514 if (validAddress(i,reg->size)) {
521 fprintf(stderr, "WARNING: No more RAM available\n");
528 void assignFixedRegisters(set *regset)
532 for (reg = setFirstItem(regset) ; reg ;
533 reg = setNextItem(regset)) {
536 assignRegister(reg,0);
541 void assignRelocatableRegisters(set *regset, int used)
547 for (reg = setFirstItem(regset) ; reg ;
548 reg = setNextItem(regset)) {
550 //fprintf(stdout,"assigning %s\n",reg->name);
552 if((!reg->isFixed) && ( (used==0) || reg->wasUsed))
553 address = assignRegister(reg,address);