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
32 #if defined(__BORLANDC__) || defined(_MSC_VER)
33 #define STRCASECMP stricmp
35 #define STRCASECMP strcasecmp
38 extern int Gstack_base_addr;
39 extern int Gstack_size;
41 static PIC_device Pics[] = {
43 {"p16f627", "16f627", "pic16f627", "f627"}, /* processor name */
46 0, /* max ram address (calculated) */
47 0x1ff, /* default max ram address */
52 {"p16f628", "16f628", "pic16f628", "f628"},
61 {"p16f84", "16f84", "pic16f84", "f84"},
65 0x4f, /* 68 register available 0x0C to 0x4F (0x8C to 0xCF mapped to bank 0) */
70 {"p16f873", "16f873", "pic16f873", "f873"},
79 {"p16f877", "16f877", "pic16f877", "f877"},
88 {"p16f819", "16f819", "pic16f819", "f819"},
98 static int num_of_supported_PICS = sizeof(Pics)/sizeof(PIC_device);
100 static PIC_device *pic=NULL;
102 AssignedMemory *finalMapping=NULL;
104 #define CONFIG_WORD_ADDRESS 0x2007
105 #define DEFAULT_CONFIG_WORD 0x3fff
107 static unsigned int config_word = DEFAULT_CONFIG_WORD;
109 extern int is_shared (regs *reg);
110 extern void emitSymbolToFile (FILE *of, const char *name, const char *section_type, int size, int addr, int useEQU, int globalize);
112 void addMemRange(memRange *r, int type)
115 int alias = r->alias;
117 if (pic->maxRAMaddress < 0) {
118 fprintf(stderr, "missing \"#pragma maxram\" setting\n");
123 for (i=r->start_address; i<= r->end_address; i++) {
124 if ((i|alias) <= pic->maxRAMaddress) {
125 finalMapping[i | alias].isValid = 1;
126 finalMapping[i | alias].alias = r->alias;
127 finalMapping[i | alias].bank = r->bank;
130 finalMapping[i | alias].isSFR = 1;
132 finalMapping[i | alias].isSFR = 0;
135 fprintf(stderr, "WARNING: %s:%s memory at 0x%x is beyond max ram = 0x%x\n",
136 __FILE__,__FUNCTION__,(i|alias), pic->maxRAMaddress);
140 /* Decrement alias */
142 alias -= ((alias & (alias - 1)) ^ alias);
147 } while (alias >= 0);
150 void setMaxRAM(int size)
153 pic->maxRAMaddress = size;
155 if (pic->maxRAMaddress < 0) {
156 fprintf(stderr, "invalid \"#pragma maxram 0x%x\" setting\n",
161 finalMapping = Safe_calloc(1+pic->maxRAMaddress,
162 sizeof(AssignedMemory));
164 /* Now initialize the finalMapping array */
166 for(i=0; i<=pic->maxRAMaddress; i++) {
167 finalMapping[i].reg = NULL;
168 finalMapping[i].isValid = 0;
169 finalMapping[i].bank = (i>>7);
173 /*-----------------------------------------------------------------*
174 *-----------------------------------------------------------------*/
176 int isREGinBank(regs *reg, int bank)
182 if((int)((reg->address | reg->alias) & pic->bankMask & bank) == bank)
188 /*-----------------------------------------------------------------*
189 *-----------------------------------------------------------------*/
190 int REGallBanks(regs *reg)
196 return ((reg->address | reg->alias) & pic->bankMask);
200 /*-----------------------------------------------------------------*
201 *-----------------------------------------------------------------*/
203 int isSFR(int address)
206 if( (address > pic->maxRAMaddress) || !finalMapping[address].isSFR)
214 * dump_map -- debug stuff
221 for(i=0; i<=pic->maxRAMaddress; i++) {
222 //fprintf(stdout , "addr 0x%02x is %s\n", i, ((finalMapping[i].isValid) ? "valid":"invalid"));
224 if(finalMapping[i].isValid) {
225 fprintf(stderr,"addr: 0x%02x",i);
226 if(finalMapping[i].isSFR)
227 fprintf(stderr," isSFR");
228 if(finalMapping[i].reg)
229 fprintf( stderr, " reg %s", finalMapping[i].reg->name);
230 fprintf(stderr, "\n");
236 void dump_sfr(FILE *of)
241 static int udata_flag=0;
245 //dump_map(); /* display the register map */
246 //fprintf(stdout,";dump_sfr \n");
247 if (pic->maxRAMaddress < 0) {
248 fprintf(stderr, "missing \"#pragma maxram\" setting\n");
252 for (addr = 0; addr <= pic->maxRAMaddress; addr++)
254 regs *reg = finalMapping[addr].reg;
256 if (reg && !reg->isEmitted)
258 if (pic14_options.isLibrarySource && is_shared (reg))
260 /* rely on external declarations for the non-fixed stack */
261 fprintf (of, "\textern\t%s\n", reg->name);
263 emitSymbolToFile (of, reg->name, "udata", reg->size, reg->isFixed ? reg->address : -1, 0, is_shared (reg));
273 if(finalMapping[addr].reg && !finalMapping[addr].reg->isEmitted) {
280 /* clear the lower 7-bits of the start address of the first
281 * variable declared in this bank. The upper bits for the mid
282 * range pics are the bank select bits.
285 bank_base = start & 0xfff8;
287 /* The bank number printed in the cblock comment tacitly
288 * assumes that the first register in the contiguous group
289 * of registers represents the bank for the whole group */
291 if ( (start != addr) && (!udata_flag) ) {
293 //fprintf(of,"\tudata\n");
296 for( ; start < addr; start++) {
297 if((finalMapping[start].reg) &&
298 (!finalMapping[start].reg->isEmitted) &&
299 (!finalMapping[start].instance) &&
300 (!finalMapping[start].isSFR)) {
302 if (finalMapping[start].reg->isFixed) {
304 for (i=0; i<finalMapping[start].reg->size; i++) {
305 fprintf(of,"%s\tEQU\t0x%04x\n",
306 finalMapping[start].reg->name,
307 finalMapping[start].reg->address+i);
310 emitSymbolToFile (of, finalMapping[start].reg->name, finalMapping[start].reg->size);
312 fprintf(of,"%s\tres\t%i\n",
313 finalMapping[start].reg->name,
314 finalMapping[start].reg->size);
317 finalMapping[start].reg->isEmitted = 1;
328 } while(addr <= pic->maxRAMaddress);
334 /*-----------------------------------------------------------------*
335 * void list_valid_pics(int ncols, int list_alias)
337 * Print out a formatted list of valid PIC devices
339 * ncols - number of columns in the list.
341 * list_alias - if non-zero, print all of the supported aliases
342 * for a device (e.g. F84, 16F84, etc...)
343 *-----------------------------------------------------------------*/
344 void list_valid_pics(int ncols, int list_alias)
350 list_alias = sizeof(Pics[0].name) / sizeof(Pics[0].name[0]);
352 /* decrement the column number if it's greater than zero */
353 ncols = (ncols > 1) ? ncols-1 : 4;
355 /* Find the device with the longest name */
356 for(i=0,longest=0; i<num_of_supported_PICS; i++) {
357 for(j=0; j<=list_alias; j++) {
358 k = strlen(Pics[i].name[j]);
366 for(i=0; i < num_of_supported_PICS; i++) {
370 fprintf(stderr,"%s", Pics[i].name[j]);
372 l = longest + 2 - strlen(Pics[i].name[j]);
383 } while(++j<list_alias);
391 /*-----------------------------------------------------------------*
393 *-----------------------------------------------------------------*/
394 PIC_device *find_device(char *name)
402 for(i = 0; i<num_of_supported_PICS; i++) {
404 for(j=0; j<PROCESSOR_NAMES; j++)
405 if(!STRCASECMP(Pics[i].name[j], name) )
413 /*-----------------------------------------------------------------*
415 *-----------------------------------------------------------------*/
416 void init_pic(char *pic_type)
418 pic = find_device(pic_type);
422 fprintf(stderr, "'%s' was not found.\n", pic_type);
424 fprintf(stderr, "No processor has been specified (use -pPROCESSOR_NAME)\n");
426 fprintf(stderr,"Valid devices are:\n");
428 list_valid_pics(4,0);
432 pic->maxRAMaddress = -1;
435 /*-----------------------------------------------------------------*
437 *-----------------------------------------------------------------*/
438 int picIsInitialized(void)
440 if(pic && pic->maxRAMaddress > 0)
447 /*-----------------------------------------------------------------*
448 * char *processor_base_name(void) - Include file is derived from this.
449 *-----------------------------------------------------------------*/
450 char *processor_base_name(void)
459 /*-----------------------------------------------------------------*
460 *-----------------------------------------------------------------*/
461 int validAddress(int address, int reg_size)
465 if (pic->maxRAMaddress < 0) {
466 fprintf(stderr, "missing \"#pragma maxram\" setting\n");
469 // fprintf(stderr, "validAddress: Checking 0x%04x\n",address);
470 assert (reg_size > 0);
471 if(address + (reg_size - 1) > pic->maxRAMaddress)
474 for (i=0; i<reg_size; i++)
475 if(!finalMapping[address + i].isValid ||
476 finalMapping[address+i].reg ||
477 finalMapping[address+i].isSFR )
483 /*-----------------------------------------------------------------*
484 *-----------------------------------------------------------------*/
485 void mapRegister(regs *reg)
491 if(!reg || !reg->size) {
492 fprintf(stderr,"WARNING: %s:%s:%d Bad register\n",__FILE__,__FUNCTION__,__LINE__);
496 if (pic->maxRAMaddress < 0) {
497 fprintf(stderr, "missing \"#pragma maxram\" setting\n");
501 for(i=0; i<reg->size; i++) {
503 alias = finalMapping[reg->address].alias;
508 //fprintf(stdout,"mapping %s to address 0x%02x, reg size = %d\n",reg->name, (reg->address+alias+i),reg->size);
510 finalMapping[reg->address + alias + i].reg = reg;
511 finalMapping[reg->address + alias + i].instance = i;
513 /* Decrement alias */
515 alias -= ((alias & (alias - 1)) ^ alias);
522 //fprintf(stderr,"%s - %s addr = 0x%03x, size %d\n",__FUNCTION__,reg->name, reg->address,reg->size);
528 /*-----------------------------------------------------------------*
529 *-----------------------------------------------------------------*/
530 int assignRegister(regs *reg, int start_address)
534 //fprintf(stderr,"%s - %s start_address = 0x%03x\n",__FUNCTION__,reg->name, start_address);
537 if (validAddress(reg->address,reg->size)) {
538 //fprintf(stderr,"%s - %s address = 0x%03x\n",__FUNCTION__,reg->name, reg->address);
543 if( isSFR(reg->address)) {
548 fprintf(stderr, "WARNING: Ignoring Out of Range register assignment at fixed address %d, %s\n",
549 reg->address, reg->name);
553 /* This register does not have a fixed address requirement
554 * so we'll search through all availble ram address and
555 * assign the first one */
557 for (i=start_address; i<=pic->maxRAMaddress; i++) {
559 if (validAddress(i,reg->size)) {
566 fprintf(stderr, "WARNING: No more RAM available for %s\n",reg->name);
573 /*-----------------------------------------------------------------*
574 *-----------------------------------------------------------------*/
575 void assignFixedRegisters(set *regset)
579 for (reg = setFirstItem(regset) ; reg ;
580 reg = setNextItem(regset)) {
583 assignRegister(reg,0);
588 /*-----------------------------------------------------------------*
589 *-----------------------------------------------------------------*/
590 void assignRelocatableRegisters(set *regset, int used)
596 for (reg = setFirstItem(regset) ; reg ;
597 reg = setNextItem(regset)) {
599 //fprintf(stdout,"assigning %s (%d) isFixed=%d, wasUsed=%d\n",reg->name,reg->size,reg->isFixed,reg->wasUsed);
601 if((!reg->isExtern) && (!reg->isFixed) && ( used || reg->wasUsed)) {
602 /* If register have been reused then shall not print it a second time. */
605 for (s = regset; s; s = s->next) {
610 if((!r->isFixed) && ( used || r->wasUsed)) {
611 if (r->rIdx == reg->rIdx) {
612 reg->address = r->address;
619 address = assignRegister(reg,address);
626 /*-----------------------------------------------------------------*
627 * void assignConfigWordValue(int address, int value)
629 * All midrange PICs have one config word at address 0x2007.
630 * This routine will assign a value to that address.
632 *-----------------------------------------------------------------*/
634 void assignConfigWordValue(int address, int value)
636 if(CONFIG_WORD_ADDRESS == address)
639 //fprintf(stderr,"setting config word to 0x%x\n",value);
642 /*-----------------------------------------------------------------*
643 * int getConfigWord(int address)
645 * Get the current value of the config word.
647 *-----------------------------------------------------------------*/
649 int getConfigWord(int address)
651 if(CONFIG_WORD_ADDRESS == address)
659 /*-----------------------------------------------------------------*
661 *-----------------------------------------------------------------*/
662 void setDefMaxRam(void)
665 setMaxRAM(pic->defMaxRAMaddrs); /* Max RAM has not been included, so use default setting */
666 /* Validate full memory range for use by general purpose RAM */
667 for (i=0; i <= pic->defMaxRAMaddrs; i++) {
668 finalMapping[i].bank = (i>>7);
669 finalMapping[i].isValid = 1;
673 /*-----------------------------------------------------------------*
675 *-----------------------------------------------------------------*/
676 unsigned getMaxRam(void)
678 return pic->defMaxRAMaddrs;