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
37 static PIC_device Pics[] = {
39 {"p16f627", "16f627", "pic16f627", "f627"}, /* processor name */
42 0, /* max ram address (calculated) */
47 {"p16f628", "16f628", "pic16f628", "f628"},
55 {"p16f84", "16f84", "pic16f84", "f84"},
63 {"p16f873", "16f873", "pic16f873", "f873"},
71 {"p16f877", "16f877", "pic16f877", "f877"},
80 static int num_of_supported_PICS = sizeof(Pics)/sizeof(PIC_device);
82 #define DEFAULT_PIC "f877"
84 static PIC_device *pic=NULL;
86 AssignedMemory *finalMapping=NULL;
88 #define CONFIG_WORD_ADDRESS 0x2007
89 #define DEFAULT_CONFIG_WORD 0x3fff
91 static unsigned int config_word = DEFAULT_CONFIG_WORD;
93 void addMemRange(memRange *r, int type)
98 if (pic->maxRAMaddress < 0) {
99 fprintf(stderr, "missing \"#pragma maxram\" setting\n");
104 for (i=r->start_address; i<= r->end_address; i++) {
105 if ((i|alias) <= pic->maxRAMaddress) {
106 finalMapping[i | alias].isValid = 1;
107 finalMapping[i | alias].alias = r->alias;
108 finalMapping[i | alias].bank = r->bank;
111 finalMapping[i | alias].isSFR = 1;
113 finalMapping[i | alias].isSFR = 0;
116 fprintf(stderr, "WARNING: %s:%s memory at 0x%x is beyond max ram = 0x%x\n",
117 __FILE__,__FUNCTION__,(i|alias), pic->maxRAMaddress);
121 /* Decrement alias */
123 alias -= ((alias & (alias - 1)) ^ alias);
128 } while (alias >= 0);
131 void setMaxRAM(int size)
134 pic->maxRAMaddress = size;
136 if (pic->maxRAMaddress < 0) {
137 fprintf(stderr, "invalid \"#pragma maxram 0x%x\" setting\n",
142 finalMapping = Safe_calloc(1+pic->maxRAMaddress,
143 sizeof(AssignedMemory));
145 /* Now initialize the finalMapping array */
147 for(i=0; i<=pic->maxRAMaddress; i++) {
148 finalMapping[i].reg = NULL;
149 finalMapping[i].isValid = 0;
153 /*-----------------------------------------------------------------*
154 *-----------------------------------------------------------------*/
156 int isREGinBank(regs *reg, int bank)
162 if(((reg->address | reg->alias) & pic->bankMask & bank) == bank)
168 /*-----------------------------------------------------------------*
169 *-----------------------------------------------------------------*/
170 int REGallBanks(regs *reg)
176 return ((reg->address | reg->alias) & pic->bankMask);
180 /*-----------------------------------------------------------------*
181 *-----------------------------------------------------------------*/
184 * dump_map -- debug stuff
191 for(i=0; i<=pic->maxRAMaddress; i++) {
192 //fprintf(stdout , "addr 0x%02x is %s\n", i, ((finalMapping[i].isValid) ? "valid":"invalid"));
194 if(finalMapping[i].isValid) {
195 fprintf(stderr,"addr: 0x%02x",i);
196 if(finalMapping[i].isSFR)
197 fprintf(stderr," isSFR");
198 if(finalMapping[i].reg)
199 fprintf( stderr, " reg %s", finalMapping[i].reg->name);
200 fprintf(stderr, "\n");
206 void dump_cblock(FILE *of)
212 //dump_map(); /* display the register map */
214 if (pic->maxRAMaddress < 0) {
215 fprintf(stderr, "missing \"#pragma maxram\" setting\n");
221 if(finalMapping[addr].reg && !finalMapping[addr].reg->isEmitted) {
228 /* clear the lower 7-bits of the start address of the first
229 * variable declared in this bank. The upper bits for the mid
230 * range pics are the bank select bits.
233 bank_base = start & 0xfff8;
235 /* The bank number printed in the cblock comment tacitly
236 * assumes that the first register in the contiguous group
237 * of registers represents the bank for the whole group */
239 fprintf(of," cblock 0X%04X\t; Bank %d\n",start,finalMapping[start].bank);
241 for( ; start < addr; start++) {
242 if((finalMapping[start].reg) && !finalMapping[start].reg->isEmitted ) {
243 fprintf(of,"\t%s",finalMapping[start].reg->name);
245 /* If this register is aliased in multiple banks, then
246 * mangle the variable name with the alias address: */
247 if(finalMapping[start].alias & start)
248 fprintf(of,"_%x",bank_base);
250 if(finalMapping[start].instance)
251 fprintf(of,"_%d",finalMapping[start].instance);
256 //finalMapping[start].reg->isEmitted = 1;
260 fprintf(of," endc\n");
269 } while(addr <= pic->maxRAMaddress);
274 /*-----------------------------------------------------------------*
275 * void list_valid_pics(int ncols, int list_alias)
277 * Print out a formatted list of valid PIC devices
279 * ncols - number of columns in the list.
281 * list_alias - if non-zero, print all of the supported aliases
282 * for a device (e.g. F84, 16F84, etc...)
283 *-----------------------------------------------------------------*/
284 void list_valid_pics(int ncols, int list_alias)
290 list_alias = sizeof(Pics[0].name) / sizeof(Pics[0].name[0]);
292 /* decrement the column number if it's greater than zero */
293 ncols = (ncols > 1) ? ncols-1 : 4;
295 /* Find the device with the longest name */
296 for(i=0,longest=0; i<num_of_supported_PICS; i++) {
297 for(j=0; j<=list_alias; j++) {
298 k = strlen(Pics[i].name[j]);
306 for(i=0; i < num_of_supported_PICS; i++) {
310 fprintf(stderr,"%s", Pics[i].name[j]);
312 l = longest + 2 - strlen(Pics[i].name[j]);
323 } while(++j<list_alias);
331 /*-----------------------------------------------------------------*
333 *-----------------------------------------------------------------*/
334 PIC_device *find_device(char *name)
342 for(i = 0; i<num_of_supported_PICS; i++) {
344 for(j=0; j<PROCESSOR_NAMES; j++)
345 if(!STRCASECMP(Pics[i].name[j], name) )
353 /*-----------------------------------------------------------------*
355 *-----------------------------------------------------------------*/
356 void init_pic(char *pic_type)
358 pic = find_device(pic_type);
362 fprintf(stderr, "'%s' was not found.\n", pic_type);
364 fprintf(stderr, "No processor has been specified (use -pPROCESSOR_NAME)\n");
366 fprintf(stderr,"Valid devices are:\n");
368 list_valid_pics(4,0);
372 pic->maxRAMaddress = -1;
375 /*-----------------------------------------------------------------*
377 *-----------------------------------------------------------------*/
378 int picIsInitialized(void)
380 if(pic && pic->maxRAMaddress > 0)
387 /*-----------------------------------------------------------------*
388 * char *processor_base_name(void) - Include file is derived from this.
389 *-----------------------------------------------------------------*/
390 char *processor_base_name(void)
399 int isSFR(int address)
402 if( (address > pic->maxRAMaddress) || !finalMapping[address].isSFR)
409 /*-----------------------------------------------------------------*
410 *-----------------------------------------------------------------*/
411 int validAddress(int address, int reg_size)
415 if (pic->maxRAMaddress < 0) {
416 fprintf(stderr, "missing \"#pragma maxram\" setting\n");
420 if(address > pic->maxRAMaddress)
423 for (i=0; i<reg_size; i++)
424 if(!finalMapping[address + i].isValid ||
425 finalMapping[address+i].reg ||
426 finalMapping[address+i].isSFR )
432 /*-----------------------------------------------------------------*
433 *-----------------------------------------------------------------*/
434 void mapRegister(regs *reg)
440 if(!reg || !reg->size) {
441 fprintf(stderr,"WARNING: %s:%s:%d Bad register\n",__FILE__,__FUNCTION__,__LINE__);
445 if (pic->maxRAMaddress < 0) {
446 fprintf(stderr, "missing \"#pragma maxram\" setting\n");
450 for(i=0; i<reg->size; i++) {
452 alias = finalMapping[reg->address].alias;
457 //fprintf(stdout,"mapping %s to address 0x%02x, reg size = %d\n",reg->name, (reg->address+alias+i),reg->size);
459 finalMapping[reg->address + alias + i].reg = reg;
460 finalMapping[reg->address + alias + i].instance = i;
462 /* Decrement alias */
464 alias -= ((alias & (alias - 1)) ^ alias);
471 // fprintf(stderr,"%s - %s addr = 0x%03x, size %d\n",__FUNCTION__,reg->name, reg->address,reg->size);
477 /*-----------------------------------------------------------------*
478 *-----------------------------------------------------------------*/
479 int assignRegister(regs *reg, int start_address)
483 //fprintf(stderr,"%s - %s start_address = 0x%03x\n",__FUNCTION__,reg->name, start_address);
486 if (validAddress(reg->address,reg->size)) {
487 fprintf(stderr,"%s - %s address = 0x%03x\n",__FUNCTION__,reg->name, reg->address);
492 if( isSFR(reg->address)) {
496 fprintf(stderr, "WARNING: Ignoring Out of Range register assignment at fixed address %d, %s\n",
497 reg->address, reg->name);
501 /* This register does not have a fixed address requirement
502 * so we'll search through all availble ram address and
503 * assign the first one */
505 for (i=start_address; i<=pic->maxRAMaddress; i++) {
507 if (validAddress(i,reg->size)) {
514 fprintf(stderr, "WARNING: No more RAM available\n");
521 /*-----------------------------------------------------------------*
522 *-----------------------------------------------------------------*/
523 void assignFixedRegisters(set *regset)
527 for (reg = setFirstItem(regset) ; reg ;
528 reg = setNextItem(regset)) {
531 assignRegister(reg,0);
536 /*-----------------------------------------------------------------*
537 *-----------------------------------------------------------------*/
538 void assignRelocatableRegisters(set *regset, int used)
544 for (reg = setFirstItem(regset) ; reg ;
545 reg = setNextItem(regset)) {
547 //fprintf(stdout,"assigning %s isFixed=%d, wasUsed=%d\n",reg->name,reg->isFixed,reg->wasUsed);
549 if((!reg->isFixed) && ( used || reg->wasUsed))
550 address = assignRegister(reg,address);
557 /*-----------------------------------------------------------------*
558 * void assignConfigWordValue(int address, int value)
560 * All midrange PICs have one config word at address 0x2007.
561 * This routine will assign a value to that address.
563 *-----------------------------------------------------------------*/
565 void assignConfigWordValue(int address, int value)
567 if(CONFIG_WORD_ADDRESS == address)
570 //fprintf(stderr,"setting config word to 0x%x\n",value);
573 /*-----------------------------------------------------------------*
574 * int getConfigWord(int address)
576 * Get the current value of the config word.
578 *-----------------------------------------------------------------*/
580 int getConfigWord(int address)
582 if(CONFIG_WORD_ADDRESS == address)