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
43 static PIC16_device Pics16[] = {
45 {"p18f242", "18f242", "pic18f242", "f242"}, // aliases
53 {"p18f252", "18f252", "pic18f252", "f252"}, // aliases
61 {"p18f442", "18f442", "pic18f442", "f442"}, // aliases
69 {"p18f452", "18f452", "pic18f452", "f452"}, // aliases
77 {"p18f248", "18f248", "pic18f248", "f248"}, // aliases
85 {"p18f258", "18f258", "pic18f258", "f258"}, // aliases
93 {"p18f448", "18f448", "pic18f448", "f448"}, // aliases
101 {"p18f458", "18f458", "pic18f458", "f458"}, // aliases
109 {"p18f6520", "18f6520", "pic18f6520", "f6520"}, // aliases
117 {"p18f6620", "18f6620", "pic18f6620", "f6620"}, // aliases
124 {"p18f6680", "18f6680", "pic18f6680", "f6680"}, // aliases
131 {"p18f6720", "18f6720", "pic18f6720", "f6720"}, // aliases
138 {"p18f8520", "18f8520", "pic18f8520", "f8520"}, // aliases
145 {"p18f8620", "18f8620", "pic18f8620", "f8620"}, // aliases
152 {"p18f8680", "18f8680", "pic18f8680", "f8680"}, // aliases
159 {"p18f8720", "18f8720", "pic18f8720", "f8720"}, // aliases
168 static int num_of_supported_PICS = sizeof(Pics16)/sizeof(PIC16_device);
170 #define DEFAULT_PIC "452"
172 PIC16_device *pic16=NULL;
174 #define DEFAULT_CONFIG_BYTE 0xff
176 #define CONFIG1H_WORD_ADDRESS 0x300001
177 #define DEFAULT_CONFIG1H_WORD DEFAULT_CONFIG_BYTE
179 #define CONFIG2L_WORD_ADDRESS 0x300002
180 #define DEFAULT_CONFIG2L_WORD DEFAULT_CONFIG_BYTE
182 #define CONFIG2H_WORD_ADDRESS 0x300003
183 #define DEFAULT_CONFIG2H_WORD DEFAULT_CONFIG_BYTE
185 #define CONFIG3H_WORD_ADDRESS 0x300005
186 #define DEFAULT_CONFIG3H_WORD DEFAULT_CONFIG_BYTE
188 #define CONFIG4L_WORD_ADDRESS 0x300006
189 #define DEFAULT_CONFIG4L_WORD DEFAULT_CONFIG_BYTE
191 #define CONFIG5L_WORD_ADDRESS 0x300008
192 #define DEFAULT_CONFIG5L_WORD DEFAULT_CONFIG_BYTE
194 #define CONFIG5H_WORD_ADDRESS 0x300009
195 #define DEFAULT_CONFIG5H_WORD DEFAULT_CONFIG_BYTE
197 #define CONFIG6L_WORD_ADDRESS 0x30000a
198 #define DEFAULT_CONFIG6L_WORD DEFAULT_CONFIG_BYTE
200 #define CONFIG6H_WORD_ADDRESS 0x30000b
201 #define DEFAULT_CONFIG6H_WORD DEFAULT_CONFIG_BYTE
203 #define CONFIG7L_WORD_ADDRESS 0x30000c
204 #define DEFAULT_CONFIG7L_WORD DEFAULT_CONFIG_BYTE
206 #define CONFIG7H_WORD_ADDRESS 0x30000d
207 #define DEFAULT_CONFIG7H_WORD DEFAULT_CONFIG_BYTE
209 static unsigned int config1h_word = DEFAULT_CONFIG1H_WORD;
210 static unsigned int config2l_word = DEFAULT_CONFIG2L_WORD;
211 static unsigned int config2h_word = DEFAULT_CONFIG2H_WORD;
212 static unsigned int config3h_word = DEFAULT_CONFIG3H_WORD;
213 static unsigned int config4l_word = DEFAULT_CONFIG4L_WORD;
214 static unsigned int config5l_word = DEFAULT_CONFIG5L_WORD;
215 static unsigned int config5h_word = DEFAULT_CONFIG5H_WORD;
216 static unsigned int config6l_word = DEFAULT_CONFIG6L_WORD;
217 static unsigned int config6h_word = DEFAULT_CONFIG6H_WORD;
218 static unsigned int config7l_word = DEFAULT_CONFIG7L_WORD;
219 static unsigned int config7h_word = DEFAULT_CONFIG7H_WORD;
221 unsigned int stackPos = 0;
223 extern regs* newReg(short type, short pc_type, int rIdx, char *name, int size, int alias, operand *refop);
225 void pic16_setMaxRAM(int size)
227 pic16->maxRAMaddress = size;
228 stackPos = pic16->RAMsize-1;
230 if (pic16->maxRAMaddress < 0) {
231 fprintf(stderr, "invalid \"#pragma maxram 0x%x\" setting\n",
232 pic16->maxRAMaddress);
237 extern char *iComments2;
239 void pic16_dump_equates(FILE *of, set *equs)
243 r = setFirstItem(equs);
246 fprintf(of, "%s", iComments2);
247 fprintf(of, ";\tEquates to used internal registers\n");
248 fprintf(of, "%s", iComments2);
250 for(; r; r = setNextItem(equs)) {
251 fprintf(of, "%s\tequ\t0x%02x\n", r->name, r->address);
256 int regCompare(const void *a, const void *b)
258 const regs *const *i = a;
259 const regs *const *j = b;
261 /* sort primarily by the address */
262 if( (*i)->address > (*j)->address)return 1;
263 if( (*i)->address < (*j)->address)return -1;
265 /* and secondarily by size */
266 if( (*i)->size > (*j)->size)return 1;
267 if( (*i)->size < (*j)->size)return -1;
269 /* register size sorting may have strange results use with care */
271 /* finally if in same address and same size sort by name */
272 return (strcmp( (*i)->name, (*j)->name));
277 void pic16_dump_section(FILE *of, set *section, int fix)
279 static int abs_section_no=0;
284 /* put all symbols in an array */
285 rlist = Safe_calloc(elementsInSet(section), sizeof(regs *));
287 for(rprev = setFirstItem(section); rprev; rprev = setNextItem(section)) {
288 rlist[i] = rprev; i++;
292 if(rlist)free(rlist);
296 /* sort symbols according to their address */
297 qsort(rlist, i /*elementsInSet(section)*/, sizeof(regs *), regCompare);
300 fprintf(of, "\n\n\tudata\n");
301 for(r = setFirstItem(section); r; r = setNextItem(section)) {
302 fprintf(of, "%s\tres\t%d\n", r->name, r->size);
309 init_addr = rlist[j]->address;
310 fprintf(of, "\n\nstatic_%s_%02d\tudata\t0X%04X\n", moduleName, abs_section_no++, init_addr);
314 if(j < i-1)r1 = rlist[j+1]; else r1 = NULL;
316 init_addr = r->address;
318 if(rprev && (init_addr != (rprev->address + rprev->size))
319 && !(r1 && (init_addr != r1->address))) {
320 fprintf(of, "\nstatic_%s_%02d\tudata\t0X%04X\n", moduleName, abs_section_no++, init_addr);
324 if(r1 && (init_addr == r1->address)) {
325 fprintf(of, "%s\tres\t0\n\n", r->name);
327 fprintf(of, "%s\tres\t%d\n", r->name, r->size);
336 void pic16_dump_int_registers(FILE *of, set *section)
342 /* put all symbols in an array */
343 rlist = Safe_calloc(elementsInSet(section), sizeof(regs *));
345 for(rprev = setFirstItem(section); rprev; rprev = setNextItem(section)) {
346 rlist[i] = rprev; i++;
349 /* sort symbols according to their address */
350 qsort(rlist, elementsInSet(section), sizeof(regs *), regCompare);
353 if(rlist)free(rlist);
357 fprintf(of, "\n\n; Internal registers\n");
359 fprintf(of, "%s\tudata_ovr\t0x0000\n", ".registers");
360 for(r = setFirstItem(section); r; r = setNextItem(section))
361 fprintf(of, "%s\tres\t%d\n", r->name, r->size);
367 #ifdef WORDS_BIGENDIAN
368 #define _ENDIAN(x) (3-x)
370 #define _ENDIAN(x) (x)
373 #define BYTE_IN_LONG(x,b) ((x>>(8*_ENDIAN(b)))&0xff)
375 /*-----------------------------------------------------------------*/
376 /* printIvalType - generates ival for int/char */
377 /*-----------------------------------------------------------------*/
378 void print_idataType (FILE *of, symbol *sym, sym_link * type, initList * ilist)
383 //fprintf(stderr, "%s\n",__FUNCTION__);
385 /* if initList is deep */
386 if (ilist->type == INIT_DEEP)
387 ilist = ilist->init.deep;
389 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
390 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
393 if (!(val = list2val (ilist))) {
394 // assuming a warning has been thrown
398 if (val->type != type) {
399 val = valCastLiteral(type, floatFromVal(val));
403 ulval = (unsigned long) floatFromVal (val);
407 switch (getSize (type)) {
409 fprintf(of, "%s\tdata\t0x%02x\n", sym->name, (unsigned char)BYTE_IN_LONG(ulval, 0));
410 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
414 // fprintf(of, "%s\tdw\t0x%04x\n", sym->name, (unsigned int)(BYTE_IN_LONG(ulval, 0)
415 // + (BYTE_IN_LONG(ulval, 1) << 8)));
416 fprintf(of, "%s\tdata\t0x%02x,0x%02x\n", sym->name, (unsigned char)BYTE_IN_LONG(ulval, 0),
417 (unsigned char)(BYTE_IN_LONG(ulval, 1) << 8));
418 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
419 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
423 fprintf(of, "%s\tdw\t0x%04x,0x%04x\n", sym->name, (unsigned int)(BYTE_IN_LONG(ulval, 0)
424 + (BYTE_IN_LONG(ulval, 1) << 8)),
425 (unsigned)(BYTE_IN_LONG(ulval, 2)
426 + (BYTE_IN_LONG(ulval, 3) << 8)));
427 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
428 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
429 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
430 // pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
437 /*-----------------------------------------------------------------*/
438 /* printIval - generates code for initial value */
439 /*-----------------------------------------------------------------*/
440 void print_idata(FILE *of, symbol * sym, sym_link * type, initList * ilist)
445 /* if structure then */
446 if (IS_STRUCT (type))
448 //fprintf(stderr,"%s struct\n",__FUNCTION__);
449 //printIvalStruct (sym, type, ilist, oFile);
453 /* if this is a pointer */
456 //fprintf(stderr,"%s pointer\n",__FUNCTION__);
457 //printIvalPtr (sym, type, ilist, oFile);
461 /* if this is an array */
464 //fprintf(stderr,"%s array\n",__FUNCTION__);
465 // printIvalArray (sym, type, ilist, pb);
469 /* if type is SPECIFIER */
472 // fprintf(stderr,"%s spec\n",__FUNCTION__);
473 print_idataType(of, sym, type, ilist);
479 void pic16_dump_idata(FILE *of, set *idataSymSet)
485 i = elementsInSet(idataSymSet);
488 fprintf(of, "\n\n; Initialised data (idata)\n");
489 fprintf(of, "\tidata\n");
490 for(ids = setFirstItem(idataSymSet); ids; ids = setNextItem(idataSymSet))
491 print_idata(of, ids, ids->type, ids->ival);
496 /*-----------------------------------------------------------------*
497 * void pic16_list_valid_pics(int ncols, int list_alias)
499 * Print out a formatted list of valid PIC devices
501 * ncols - number of columns in the list.
503 * list_alias - if non-zero, print all of the supported aliases
504 * for a device (e.g. F84, 16F84, etc...)
505 *-----------------------------------------------------------------*/
506 void pic16_list_valid_pics(int ncols, int list_alias)
512 list_alias = sizeof(Pics16[0].name) / sizeof(Pics16[0].name[0]);
514 /* decrement the column number if it's greater than zero */
515 ncols = (ncols > 1) ? ncols-1 : 4;
517 /* Find the device with the longest name */
518 for(i=0,longest=0; i<num_of_supported_PICS; i++) {
519 for(j=0; j<=list_alias; j++) {
520 k = strlen(Pics16[i].name[j]);
528 for(i=0; i < num_of_supported_PICS; i++) {
532 fprintf(stderr,"%s", Pics16[i].name[j]);
534 l = longest + 2 - strlen(Pics16[i].name[j]);
545 } while(++j<list_alias);
553 /*-----------------------------------------------------------------*
555 *-----------------------------------------------------------------*/
556 PIC16_device *pic16_find_device(char *name)
564 for(i = 0; i<num_of_supported_PICS; i++) {
566 for(j=0; j<PROCESSOR_NAMES; j++)
567 if(!STRCASECMP(Pics16[i].name[j], name) )
575 /*-----------------------------------------------------------------*
577 *-----------------------------------------------------------------*/
578 void pic16_init_pic(char *pic_type)
580 pic16 = pic16_find_device(pic_type);
584 fprintf(stderr, "'%s' was not found.\n", pic_type);
586 fprintf(stderr, "No processor has been specified (use -pPROCESSOR_NAME)\n");
588 fprintf(stderr,"Valid devices are:\n");
590 pic16_list_valid_pics(4,0);
594 // printf("PIC processor found and initialized: %s\n", pic_type);
595 pic16_setMaxRAM( 0xfff );
598 /*-----------------------------------------------------------------*
600 *-----------------------------------------------------------------*/
601 int pic16_picIsInitialized(void)
603 if(pic16 && pic16->maxRAMaddress > 0)
610 /*-----------------------------------------------------------------*
611 * char *pic16_processor_base_name(void) - Include file is derived from this.
612 *-----------------------------------------------------------------*/
613 char *pic16_processor_base_name(void)
619 return pic16->name[0];
622 #define DEBUG_CHECK 0
625 * return 1 if register wasn't found and added, 0 otherwise
627 int checkAddReg(set **set, regs *reg)
632 fprintf(stderr, "%s: about to insert REGister: %s ... ", __FUNCTION__, reg->name);
635 for(tmp = setFirstItem(*set); tmp; tmp = setNextItem(*set)) {
636 if(!strcmp(tmp->name, reg->name))break;
642 fprintf(stderr, "added\n");
648 fprintf(stderr, "already added\n");
653 int checkAddSym(set **set, symbol *sym)
658 fprintf(stderr, "%s: about to add SYMbol: %s ... ", __FUNCTION__, sym->name);
661 for(tmp = setFirstItem( *set ); tmp; tmp = setNextItem(*set)) {
662 if(!strcmp(tmp->name, sym->name))break;
668 fprintf(stderr, "added\n");
674 fprintf(stderr, "already added\n");
681 /*-----------------------------------------------------------------*
682 * void pic16_groupRegistersInSection - add each register to its *
683 * corresponding section *
684 *-----------------------------------------------------------------*/
685 void pic16_groupRegistersInSection(set *regset)
689 for(reg=setFirstItem(regset); reg; reg = setNextItem(regset)) {
691 // fprintf(stderr, "%s:%d group registers in section, reg: %s\n", __FILE__, __LINE__, reg->name);
694 && !(reg->regop && SPEC_EXTR(OP_SYM_ETYPE(reg->regop)))) {
696 // fprintf(stderr, "%s:%d register %s alias:%d fix:%d\n",
697 // __FILE__, __LINE__, reg->name, reg->alias, reg->isFixed);
700 checkAddReg(&pic16_equ_data, reg);
703 checkAddReg(&pic16_fix_udata, reg);
706 if(reg->pc_type == PO_GPR_TEMP)
707 checkAddReg(&pic16_int_regs, reg);
709 checkAddReg(&pic16_rel_udata, reg);
719 /*-----------------------------------------------------------------*
720 * void pic16_assignConfigWordValue(int address, int value)
722 * All high performance RISC CPU PICs have seven config word starting
723 * at address 0x300000.
724 * This routine will assign a value to that address.
726 *-----------------------------------------------------------------*/
728 void pic16_assignConfigWordValue(int address, int value)
731 case CONFIG1H_WORD_ADDRESS:
732 config1h_word = value;
734 case CONFIG2L_WORD_ADDRESS:
735 config2l_word = value;
737 case CONFIG2H_WORD_ADDRESS:
738 config2h_word = value;
740 case CONFIG3H_WORD_ADDRESS:
741 config3h_word = value;
743 case CONFIG4L_WORD_ADDRESS:
744 config4l_word = value;
746 case CONFIG5L_WORD_ADDRESS:
747 config5l_word = value;
749 case CONFIG5H_WORD_ADDRESS:
750 config5h_word = value;
752 case CONFIG6L_WORD_ADDRESS:
753 config6l_word = value;
755 case CONFIG6H_WORD_ADDRESS:
756 config6h_word = value;
758 case CONFIG7L_WORD_ADDRESS:
759 config7l_word = value;
761 case CONFIG7H_WORD_ADDRESS:
762 config7h_word = value;
766 fprintf(stderr,"setting config word to 0x%x\n",value);
769 /*-----------------------------------------------------------------*
770 * int pic16_getConfigWord(int address)
772 * Get the current value of the config word.
774 *-----------------------------------------------------------------*/
776 int pic16_getConfigWord(int address)
779 case CONFIG1H_WORD_ADDRESS:
780 return config1h_word;
781 case CONFIG2L_WORD_ADDRESS:
782 return config2l_word;
783 case CONFIG2H_WORD_ADDRESS:
784 return config2h_word;
785 case CONFIG3H_WORD_ADDRESS:
786 return config3h_word;
787 case CONFIG4L_WORD_ADDRESS:
788 return config4l_word;
789 case CONFIG5L_WORD_ADDRESS:
790 return config5l_word;
791 case CONFIG5H_WORD_ADDRESS:
792 return config5h_word;
793 case CONFIG6L_WORD_ADDRESS:
794 return config6l_word;
795 case CONFIG6H_WORD_ADDRESS:
796 return config6h_word;
797 case CONFIG7L_WORD_ADDRESS:
798 return config7l_word;
799 case CONFIG7H_WORD_ADDRESS:
800 return config7h_word;