1 /*-------------------------------------------------------------------------
3 device.c - Accomodates subtle variations in PIC16 devices
5 Written By - Scott Dattalo scott@dattalo.com
6 Ported to PIC16 By - Martin Dubuc m.dubuc@rogers.com
8 This program is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 2, or (at your option) any
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 -------------------------------------------------------------------------*/
25 VR - Began writing code to make PIC16 C source files independent from
26 the header file (created by the inc2h.pl)
28 - adding maximum RAM memory into PIC_Device structure
34 #include "common.h" // Include everything in the SDCC src directory
42 #if defined(__BORLANDC__) || defined(_MSC_VER)
43 #define STRCASECMP stricmp
45 #define STRCASECMP strcasecmp
48 static PIC_device Pics[] = {
50 {"p18f242", "18f242", "pic18f242", "f242"}, // aliases
51 (memRange *)NULL, // ram memory map
52 (memRange *)NULL, // sfr memory map
60 {"p18f252", "18f252", "pic18f252", "f252"}, // aliases
61 (memRange *)NULL, // ram memory map
62 (memRange *)NULL, // sfr memory map
70 {"p18f442", "18f442", "pic18f442", "f442"}, // aliases
71 (memRange *)NULL, // ram memory map
72 (memRange *)NULL, // sfr memory map
80 {"p18f452", "18f452", "pic18f452", "f452"}, // aliases
81 (memRange *)NULL, // ram memory map
82 (memRange *)NULL, // sfr memory map
90 {"p18f248", "18f248", "pic18f248", "f248"}, // aliases
91 (memRange *)NULL, // ram memory map
92 (memRange *)NULL, // sfr memory map
100 {"p18f258", "18f258", "pic18f258", "f258"}, // aliases
101 (memRange *)NULL, // ram memory map
102 (memRange *)NULL, // sfr memory map
110 {"p18f448", "18f448", "pic18f448", "f448"}, // aliases
111 (memRange *)NULL, // ram memory map
112 (memRange *)NULL, // sfr memory map
120 {"p18f458", "18f458", "pic18f458", "f458"}, // aliases
121 (memRange *)NULL, // ram memory map
122 (memRange *)NULL, // sfr memory map
130 {"p18f6520", "18f6520", "pic18f6520", "f6520"}, // aliases
131 (memRange *)NULL, // ram memory map
132 (memRange *)NULL, // sfr memory map
140 {"p18f6620", "18f6620", "pic18f6620", "f6620"}, // aliases
141 (memRange *)NULL, // ram memory map
142 (memRange *)NULL, // sfr memory map
149 {"p18f6680", "18f6680", "pic18f6680", "f6680"}, // aliases
150 (memRange *)NULL, // ram memory map
151 (memRange *)NULL, // sfr memory map
158 {"p18f6720", "18f6720", "pic18f6720", "f6720"}, // aliases
159 (memRange *)NULL, // ram memory map
160 (memRange *)NULL, // sfr memory map
167 {"p18f8520", "18f8520", "pic18f8520", "f8520"}, // aliases
168 (memRange *)NULL, // ram memory map
169 (memRange *)NULL, // sfr memory map
176 {"p18f8620", "18f8620", "pic18f8620", "f8620"}, // aliases
177 (memRange *)NULL, // ram memory map
178 (memRange *)NULL, // sfr memory map
185 {"p18f8680", "18f8680", "pic18f8680", "f8680"}, // aliases
186 (memRange *)NULL, // ram memory map
187 (memRange *)NULL, // sfr memory map
194 {"p18f8720", "18f8720", "pic18f8720", "f8720"}, // aliases
195 (memRange *)NULL, // ram memory map
196 (memRange *)NULL, // sfr memory map
205 static int num_of_supported_PICS = sizeof(Pics)/sizeof(PIC_device);
207 #define DEFAULT_PIC "452"
209 static PIC_device *pic=NULL;
211 //AssignedMemory *pic16_finalMapping=NULL;
212 //int pic16_finalMappingSize=0;
214 #define DEFAULT_CONFIG_BYTE 0xff
216 #define CONFIG1H_WORD_ADDRESS 0x300001
217 #define DEFAULT_CONFIG1H_WORD DEFAULT_CONFIG_BYTE
219 #define CONFIG2L_WORD_ADDRESS 0x300002
220 #define DEFAULT_CONFIG2L_WORD DEFAULT_CONFIG_BYTE
222 #define CONFIG2H_WORD_ADDRESS 0x300003
223 #define DEFAULT_CONFIG2H_WORD DEFAULT_CONFIG_BYTE
225 #define CONFIG3H_WORD_ADDRESS 0x300005
226 #define DEFAULT_CONFIG3H_WORD DEFAULT_CONFIG_BYTE
228 #define CONFIG4L_WORD_ADDRESS 0x300006
229 #define DEFAULT_CONFIG4L_WORD DEFAULT_CONFIG_BYTE
231 #define CONFIG5L_WORD_ADDRESS 0x300008
232 #define DEFAULT_CONFIG5L_WORD DEFAULT_CONFIG_BYTE
234 #define CONFIG5H_WORD_ADDRESS 0x300009
235 #define DEFAULT_CONFIG5H_WORD DEFAULT_CONFIG_BYTE
237 #define CONFIG6L_WORD_ADDRESS 0x30000a
238 #define DEFAULT_CONFIG6L_WORD DEFAULT_CONFIG_BYTE
240 #define CONFIG6H_WORD_ADDRESS 0x30000b
241 #define DEFAULT_CONFIG6H_WORD DEFAULT_CONFIG_BYTE
243 #define CONFIG7L_WORD_ADDRESS 0x30000c
244 #define DEFAULT_CONFIG7L_WORD DEFAULT_CONFIG_BYTE
246 #define CONFIG7H_WORD_ADDRESS 0x30000d
247 #define DEFAULT_CONFIG7H_WORD DEFAULT_CONFIG_BYTE
249 static unsigned int config1h_word = DEFAULT_CONFIG1H_WORD;
250 static unsigned int config2l_word = DEFAULT_CONFIG2L_WORD;
251 static unsigned int config2h_word = DEFAULT_CONFIG2H_WORD;
252 static unsigned int config3h_word = DEFAULT_CONFIG3H_WORD;
253 static unsigned int config4l_word = DEFAULT_CONFIG4L_WORD;
254 static unsigned int config5l_word = DEFAULT_CONFIG5L_WORD;
255 static unsigned int config5h_word = DEFAULT_CONFIG5H_WORD;
256 static unsigned int config6l_word = DEFAULT_CONFIG6L_WORD;
257 static unsigned int config6h_word = DEFAULT_CONFIG6H_WORD;
258 static unsigned int config7l_word = DEFAULT_CONFIG7L_WORD;
259 static unsigned int config7h_word = DEFAULT_CONFIG7H_WORD;
261 unsigned int stackPos = 0;
263 extern regs* newReg(short type, short pc_type, int rIdx, char *name, int size, int alias, operand *refop);
265 void pic16_setMaxRAM(int size)
267 pic->maxRAMaddress = size;
268 stackPos = pic->RAMsize-1;
271 reg=newReg(REG_SFR, PO_SFR_REGISTER, stackPos, "stack", 1, 0, NULL);
272 addSet(&pic16_fix_udata, reg);
274 if (pic->maxRAMaddress < 0) {
275 fprintf(stderr, "invalid \"#pragma maxram 0x%x\" setting\n",
280 // pic16_finalMapping = Safe_calloc(1+pic->maxRAMaddress,
281 // sizeof(AssignedMemory));
283 /* Now initialize the pic16_finalMapping array */
285 // for(i=0; i<=pic->maxRAMaddress; i++) {
286 // pic16_finalMapping[i].reg = NULL;
287 // pic16_finalMapping[i].isValid = 0;
291 /*-----------------------------------------------------------------*
292 *-----------------------------------------------------------------*/
294 int pic16_isREGinBank(regs *reg, int bank)
300 if(pic16_finalMapping[reg->address].bank == bank)
306 /*-----------------------------------------------------------------*
307 *-----------------------------------------------------------------*/
308 int pic16_REGallBanks(regs *reg)
314 if ((int)reg->address > pic->maxRAMaddress)
321 /*-----------------------------------------------------------------*
322 *-----------------------------------------------------------------*/
325 * pic16_dump_map -- debug stuff
328 void pic16_dump_map(void)
332 for(i=0; i<=pic->maxRAMaddress; i++) {
333 //fprintf(stdout , "addr 0x%02x is %s\n", i, ((pic16_finalMapping[i].isValid) ? "valid":"invalid"));
335 if(pic16_finalMapping[i].isValid) {
336 fprintf(stderr,"addr: 0x%02x",i);
337 if(pic16_finalMapping[i].isSFR)
338 fprintf(stderr," isSFR");
339 if(pic16_finalMapping[i].reg)
340 fprintf( stderr, " reg %s", pic16_finalMapping[i].reg->name);
341 fprintf(stderr, "\n");
348 extern char *iComments2;
350 void pic16_dump_equates(FILE *of, set *equs)
354 r = setFirstItem(equs);
357 fprintf(of, "%s", iComments2);
358 fprintf(of, ";\tEquates to used internal registers\n");
359 fprintf(of, "%s", iComments2);
361 for(; r; r = setNextItem(equs)) {
362 fprintf(of, "%s\tequ\t0x%02x\n", r->name, r->address);
367 int regCompare(const void *a, const void *b)
369 const regs *const *i = a;
370 const regs *const *j = b;
372 if( (*i)->address > (*j)->address)return 1;
373 if( (*i)->address < (*j)->address)return -1;
378 void pic16_dump_section(FILE *of, set *section, int fix)
380 static int abs_section_no=0;
385 /* put all symbols in an array */
386 rlist = Safe_calloc(elementsInSet(section), sizeof(regs *));
388 for(rprev = setFirstItem(section); rprev; rprev = setNextItem(section)) {
389 rlist[i] = rprev; i++;
392 /* sort symbols according to their address */
393 qsort(rlist, elementsInSet(section), sizeof(regs *), regCompare);
398 fprintf(of, "\n\n\tudata\n");
399 for(r = setFirstItem(section); r; r = setNextItem(section)) {
400 fprintf(of, "%s\tres\t%d\n", r->name, r->size);
406 init_addr = rlist[j]->address;
407 fprintf(of, "\n\nstatic_%s_%02d\tudata\t0X%04X\n", moduleName, abs_section_no++, init_addr);
411 init_addr = r->address;
412 if(rprev && (init_addr != (rprev->address + rprev->size))) {
413 fprintf(of, "\nstatic_%s_%02d\tudata\t0X%04X\n", moduleName, abs_section_no++, init_addr);
416 fprintf(of, "%s\tres\t%d\n", r->name, r->size);
426 /*-----------------------------------------------------------------*
427 * void pic16_list_valid_pics(int ncols, int list_alias)
429 * Print out a formatted list of valid PIC devices
431 * ncols - number of columns in the list.
433 * list_alias - if non-zero, print all of the supported aliases
434 * for a device (e.g. F84, 16F84, etc...)
435 *-----------------------------------------------------------------*/
436 void pic16_list_valid_pics(int ncols, int list_alias)
442 list_alias = sizeof(Pics[0].name) / sizeof(Pics[0].name[0]);
444 /* decrement the column number if it's greater than zero */
445 ncols = (ncols > 1) ? ncols-1 : 4;
447 /* Find the device with the longest name */
448 for(i=0,longest=0; i<num_of_supported_PICS; i++) {
449 for(j=0; j<=list_alias; j++) {
450 k = strlen(Pics[i].name[j]);
458 for(i=0; i < num_of_supported_PICS; i++) {
462 fprintf(stderr,"%s", Pics[i].name[j]);
464 l = longest + 2 - strlen(Pics[i].name[j]);
475 } while(++j<list_alias);
483 /*-----------------------------------------------------------------*
485 *-----------------------------------------------------------------*/
486 PIC_device *pic16_find_device(char *name)
494 for(i = 0; i<num_of_supported_PICS; i++) {
496 for(j=0; j<PROCESSOR_NAMES; j++)
497 if(!STRCASECMP(Pics[i].name[j], name) )
505 /*-----------------------------------------------------------------*
507 *-----------------------------------------------------------------*/
508 void pic16_init_pic(char *pic_type)
510 pic = pic16_find_device(pic_type);
514 fprintf(stderr, "'%s' was not found.\n", pic_type);
516 fprintf(stderr, "No processor has been specified (use -pPROCESSOR_NAME)\n");
518 fprintf(stderr,"Valid devices are:\n");
520 pic16_list_valid_pics(4,0);
524 // printf("PIC processor found and initialized: %s\n", pic_type);
525 pic16_setMaxRAM( 0xfff );
528 /*-----------------------------------------------------------------*
530 *-----------------------------------------------------------------*/
531 int pic16_picIsInitialized(void)
533 if(pic && pic->maxRAMaddress > 0)
540 /*-----------------------------------------------------------------*
541 * char *pic16_processor_base_name(void) - Include file is derived from this.
542 *-----------------------------------------------------------------*/
543 char *pic16_processor_base_name(void)
554 /*-----------------------------------------------------------------*
555 *-----------------------------------------------------------------*/
556 static int validAddress(int address, int reg_size)
561 if (pic->maxRAMaddress < 0) {
562 fprintf(stderr, "missing \"#pragma maxram\" setting\n");
565 // fprintf(stderr, "validAddress: Checking 0x%04x (max=0x%04x) (reg_size = %d)\n",address, pic->maxRAMaddress, reg_size);
566 if(address > pic->maxRAMaddress)
569 for (i=0; i<reg_size; i++)
570 if(!pic16_finalMapping[address + i].isValid ||
571 pic16_finalMapping[address+i].reg ||
572 pic16_finalMapping[address+i].isSFR )
580 void checkAddReg(set **set, regs *reg)
585 for(tmp = setFirstItem(*set); tmp; tmp = setNextItem(*set)) {
586 if(!strcmp(tmp->name, reg->name))break;
593 /*-----------------------------------------------------------------*
594 * void pic16_groupRegistersInSection - add each register to its *
595 * corresponding section *
596 *-----------------------------------------------------------------*/
597 void pic16_groupRegistersInSection(set *regset)
601 for(reg=setFirstItem(regset); reg; reg = setNextItem(regset)) {
603 && !(reg->regop && SPEC_EXTR(OP_SYM_ETYPE(reg->regop)))) {
605 // fprintf(stderr, "%s:%d register %s\n", __FILE__, __LINE__, reg->name);
608 checkAddReg(&pic16_equ_data, reg);
611 checkAddReg(&pic16_fix_udata, reg);
614 // fprintf(stderr, "%s:%d adding symbol %s in relocatable udata section\n",
615 // __FILE__, __LINE__, reg->name);
616 checkAddReg(&pic16_rel_udata, reg);
626 /*-----------------------------------------------------------------*
627 * void pic16_assignConfigWordValue(int address, int value)
629 * All high performance RISC CPU PICs have seven config word starting
630 * at address 0x300000.
631 * This routine will assign a value to that address.
633 *-----------------------------------------------------------------*/
635 void pic16_assignConfigWordValue(int address, int value)
638 case CONFIG1H_WORD_ADDRESS:
639 config1h_word = value;
641 case CONFIG2L_WORD_ADDRESS:
642 config2l_word = value;
644 case CONFIG2H_WORD_ADDRESS:
645 config2h_word = value;
647 case CONFIG3H_WORD_ADDRESS:
648 config3h_word = value;
650 case CONFIG4L_WORD_ADDRESS:
651 config4l_word = value;
653 case CONFIG5L_WORD_ADDRESS:
654 config5l_word = value;
656 case CONFIG5H_WORD_ADDRESS:
657 config5h_word = value;
659 case CONFIG6L_WORD_ADDRESS:
660 config6l_word = value;
662 case CONFIG6H_WORD_ADDRESS:
663 config6h_word = value;
665 case CONFIG7L_WORD_ADDRESS:
666 config7l_word = value;
668 case CONFIG7H_WORD_ADDRESS:
669 config7h_word = value;
673 fprintf(stderr,"setting config word to 0x%x\n",value);
676 /*-----------------------------------------------------------------*
677 * int pic16_getConfigWord(int address)
679 * Get the current value of the config word.
681 *-----------------------------------------------------------------*/
683 int pic16_getConfigWord(int address)
686 case CONFIG1H_WORD_ADDRESS:
687 return config1h_word;
688 case CONFIG2L_WORD_ADDRESS:
689 return config2l_word;
690 case CONFIG2H_WORD_ADDRESS:
691 return config2h_word;
692 case CONFIG3H_WORD_ADDRESS:
693 return config3h_word;
694 case CONFIG4L_WORD_ADDRESS:
695 return config4l_word;
696 case CONFIG5L_WORD_ADDRESS:
697 return config5l_word;
698 case CONFIG5H_WORD_ADDRESS:
699 return config5h_word;
700 case CONFIG6L_WORD_ADDRESS:
701 return config6l_word;
702 case CONFIG6H_WORD_ADDRESS:
703 return config6h_word;
704 case CONFIG7L_WORD_ADDRESS:
705 return config7l_word;
706 case CONFIG7H_WORD_ADDRESS:
707 return config7h_word;