2004-01-13 Vangelis Rokas <vrokas@otenet.gr>
[fw/sdcc] / src / pic16 / device.c
1 /*-------------------------------------------------------------------------
2
3   device.c - Accomodates subtle variations in PIC16 devices
4
5    Written By -  Scott Dattalo scott@dattalo.com
6    Ported to PIC16 By -  Martin Dubuc m.dubuc@rogers.com
7
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
11    later version.
12    
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.
17    
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 -------------------------------------------------------------------------*/
22
23
24 /*
25         VR - Began writing code to make PIC16 C source files independent from
26         the header file (created by the inc2h.pl)
27
28         - adding maximum RAM memory into PIC_Device structure
29
30 */
31
32 #include <stdio.h>
33
34 #include "common.h"   // Include everything in the SDCC src directory
35 #include "newalloc.h"
36
37
38 #include "pcode.h"
39 #include "ralloc.h"
40 #include "device.h"
41
42 #if defined(__BORLANDC__) || defined(_MSC_VER)
43 #define STRCASECMP stricmp
44 #else
45 #define STRCASECMP strcasecmp
46 #endif
47
48 static PIC_device Pics[] = {
49   {
50     {"p18f242", "18f242", "pic18f242", "f242"},         // aliases
51     (memRange *)NULL,                                   // ram memory map
52     (memRange *)NULL,                                   // sfr memory map
53     0,
54     0x300,                                              // bank mask
55     0x300,                                              // RAMsize
56     0
57   },
58
59   {
60     {"p18f252", "18f252", "pic18f252", "f252"},         // aliases
61     (memRange *)NULL,                                   // ram memory map
62     (memRange *)NULL,                                   // sfr memory map
63     0,
64     0x600,                                              // bank mask
65     0x600,                                              // RAMsize
66     0
67   },
68
69   {
70     {"p18f442", "18f442", "pic18f442", "f442"},         // aliases
71     (memRange *)NULL,                                   // ram memory map
72     (memRange *)NULL,                                   // sfr memory map
73     0,
74     0x300,                                              // bank mask
75     0x300,                                              // RAMsize
76     0
77   },
78
79   {
80     {"p18f452", "18f452", "pic18f452", "f452"},         // aliases
81     (memRange *)NULL,                                   // ram memory map
82     (memRange *)NULL,                                   // sfr memory map
83     0,
84     0x600,                                              // bank mask
85     0x600,                                              // RAMsize
86     0
87   },
88
89   {
90     {"p18f248", "18f248", "pic18f248", "f248"},         // aliases
91     (memRange *)NULL,                                   // ram memory map
92     (memRange *)NULL,                                   // sfr memory map
93     0,
94     0x300,                                              // bank mask
95     0x300,                                              // RAMsize
96     0
97   },
98
99   {
100     {"p18f258", "18f258", "pic18f258", "f258"},         // aliases
101     (memRange *)NULL,                                   // ram memory map
102     (memRange *)NULL,                                   // sfr memory map
103     0,
104     0x600,                                              // bank mask
105     0x600,                                              // RAMsize
106     0
107   },
108
109   {
110     {"p18f448", "18f448", "pic18f448", "f448"},         // aliases
111     (memRange *)NULL,                                   // ram memory map
112     (memRange *)NULL,                                   // sfr memory map
113     0,
114     0x300,                                              // bank mask
115     0x300,                                              // RAMsize
116     0
117   },
118
119   {
120     {"p18f458", "18f458", "pic18f458", "f458"},         // aliases
121     (memRange *)NULL,                                   // ram memory map
122     (memRange *)NULL,                                   // sfr memory map
123     0,
124     0x600,                                              // bank mask
125     0x600,                                              // RAMsize
126     0
127   },
128
129   {
130     {"p18f6520", "18f6520", "pic18f6520", "f6520"},     // aliases
131     (memRange *)NULL,                                   // ram memory map
132     (memRange *)NULL,                                   // sfr memory map
133     0,
134     0x800,                                              // bank mask
135     0x800,                                              // RAMsize
136     1
137   },
138
139   {
140     {"p18f6620", "18f6620", "pic18f6620", "f6620"},     // aliases
141     (memRange *)NULL,                                   // ram memory map
142     (memRange *)NULL,                                   // sfr memory map
143     0,
144     0xf00,                                              // bank mask
145     0xf00,                                              // RAMsize
146     1
147   },
148   {
149     {"p18f6680", "18f6680", "pic18f6680", "f6680"},     // aliases
150     (memRange *)NULL,                                   // ram memory map
151     (memRange *)NULL,                                   // sfr memory map
152     0,
153     0xc00,                                              // bank mask
154     0xc00,                                              // RAMsize
155     1
156   },
157   {
158     {"p18f6720", "18f6720", "pic18f6720", "f6720"},     // aliases
159     (memRange *)NULL,                                   // ram memory map
160     (memRange *)NULL,                                   // sfr memory map
161     0,
162     0xf00,                                              // bank mask
163     0xf00,                                              // RAMsize
164     1
165   },
166   {
167     {"p18f8520", "18f8520", "pic18f8520", "f8520"},     // aliases
168     (memRange *)NULL,                                   // ram memory map
169     (memRange *)NULL,                                   // sfr memory map
170     0,
171     0x800,                                              // bank mask
172     0x800,                                              // RAMsize
173     1
174   },
175   {
176     {"p18f8620", "18f8620", "pic18f8620", "f8620"},     // aliases
177     (memRange *)NULL,                                   // ram memory map
178     (memRange *)NULL,                                   // sfr memory map
179     0,
180     0xf00,                                              // bank mask
181     0xf00,                                              // RAMsize
182     1
183   },
184   {
185     {"p18f8680", "18f8680", "pic18f8680", "f8680"},     // aliases
186     (memRange *)NULL,                                   // ram memory map
187     (memRange *)NULL,                                   // sfr memory map
188     0,
189     0xc00,                                              // bank mask
190     0x800,                                              // RAMsize
191     1
192   },
193   {
194     {"p18f8720", "18f8720", "pic18f8720", "f8720"},     // aliases
195     (memRange *)NULL,                                   // ram memory map
196     (memRange *)NULL,                                   // sfr memory map
197     0,
198     0xf00,                                              // bank mask
199     0xf00,                                              // RAMsize
200     1
201   },
202
203 };
204
205 static int num_of_supported_PICS = sizeof(Pics)/sizeof(PIC_device);
206
207 #define DEFAULT_PIC "452"
208
209 static PIC_device *pic=NULL;
210
211 //AssignedMemory *pic16_finalMapping=NULL;
212 //int pic16_finalMappingSize=0;
213
214 #define DEFAULT_CONFIG_BYTE 0xff
215
216 #define CONFIG1H_WORD_ADDRESS 0x300001
217 #define DEFAULT_CONFIG1H_WORD DEFAULT_CONFIG_BYTE
218
219 #define CONFIG2L_WORD_ADDRESS 0x300002
220 #define DEFAULT_CONFIG2L_WORD DEFAULT_CONFIG_BYTE
221
222 #define CONFIG2H_WORD_ADDRESS 0x300003
223 #define DEFAULT_CONFIG2H_WORD DEFAULT_CONFIG_BYTE
224
225 #define CONFIG3H_WORD_ADDRESS 0x300005
226 #define DEFAULT_CONFIG3H_WORD DEFAULT_CONFIG_BYTE
227
228 #define CONFIG4L_WORD_ADDRESS 0x300006
229 #define DEFAULT_CONFIG4L_WORD DEFAULT_CONFIG_BYTE
230
231 #define CONFIG5L_WORD_ADDRESS 0x300008
232 #define DEFAULT_CONFIG5L_WORD DEFAULT_CONFIG_BYTE
233
234 #define CONFIG5H_WORD_ADDRESS 0x300009
235 #define DEFAULT_CONFIG5H_WORD DEFAULT_CONFIG_BYTE
236
237 #define CONFIG6L_WORD_ADDRESS 0x30000a
238 #define DEFAULT_CONFIG6L_WORD DEFAULT_CONFIG_BYTE
239
240 #define CONFIG6H_WORD_ADDRESS 0x30000b
241 #define DEFAULT_CONFIG6H_WORD DEFAULT_CONFIG_BYTE
242
243 #define CONFIG7L_WORD_ADDRESS 0x30000c
244 #define DEFAULT_CONFIG7L_WORD DEFAULT_CONFIG_BYTE
245
246 #define CONFIG7H_WORD_ADDRESS 0x30000d
247 #define DEFAULT_CONFIG7H_WORD DEFAULT_CONFIG_BYTE
248
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;
260
261 unsigned int stackPos = 0;
262
263 extern regs* newReg(short type, short pc_type, int rIdx, char *name, int size, int alias, operand *refop);
264
265 void pic16_setMaxRAM(int size)
266 {
267   pic->maxRAMaddress = size;
268   stackPos = pic->RAMsize-1;
269   regs * reg;
270
271         reg=newReg(REG_SFR, PO_SFR_REGISTER, stackPos, "stack", 1, 0, NULL);
272         addSet(&pic16_fix_udata, reg);
273
274   if (pic->maxRAMaddress < 0) {
275     fprintf(stderr, "invalid \"#pragma maxram 0x%x\" setting\n",
276             pic->maxRAMaddress);
277     return;
278   }
279
280 //  pic16_finalMapping = Safe_calloc(1+pic->maxRAMaddress,
281 //                           sizeof(AssignedMemory));
282
283   /* Now initialize the pic16_finalMapping array */
284
285 //  for(i=0; i<=pic->maxRAMaddress; i++) {
286 //    pic16_finalMapping[i].reg = NULL;
287 //    pic16_finalMapping[i].isValid = 0;
288 //  }
289 }
290
291 /*-----------------------------------------------------------------*
292  *-----------------------------------------------------------------*/
293 #if 0
294 int pic16_isREGinBank(regs *reg, int bank)
295 {
296
297   if(!reg || !pic)
298     return 0;
299
300   if(pic16_finalMapping[reg->address].bank == bank)
301     return 1;
302
303   return 0;
304 }
305 #endif
306 /*-----------------------------------------------------------------*
307  *-----------------------------------------------------------------*/
308 int pic16_REGallBanks(regs *reg)
309 {
310
311   if(!reg || !pic)
312     return 0;
313
314   if ((int)reg->address > pic->maxRAMaddress)
315     return 0;
316
317   return 1;
318
319 }
320
321 /*-----------------------------------------------------------------*
322  *-----------------------------------------------------------------*/
323
324 /*
325  *  pic16_dump_map -- debug stuff
326  */
327 #if 0
328 void pic16_dump_map(void)
329 {
330   int i;
331
332   for(i=0; i<=pic->maxRAMaddress; i++) {
333     //fprintf(stdout , "addr 0x%02x is %s\n", i, ((pic16_finalMapping[i].isValid) ? "valid":"invalid"));
334
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");
342     }
343   }
344
345 }
346 #endif
347
348 extern char *iComments2;
349
350 void pic16_dump_equates(FILE *of, set *equs)
351 {
352   regs *r;
353
354         r = setFirstItem(equs);
355         if(!r)return;
356         
357         fprintf(of, "%s", iComments2);
358         fprintf(of, ";\tEquates to used internal registers\n");
359         fprintf(of, "%s", iComments2);
360         
361         for(; r; r = setNextItem(equs)) {
362                 fprintf(of, "%s\tequ\t0x%02x\n", r->name, r->address);
363         }
364 }
365
366
367 int regCompare(const void *a, const void *b)
368 {
369   const regs *const *i = a;
370   const regs *const *j = b;
371
372         if( (*i)->address > (*j)->address)return 1;
373         if( (*i)->address < (*j)->address)return -1;
374
375   return 0;
376 }
377
378 void pic16_dump_section(FILE *of, set *section, int fix)
379 {
380   static int abs_section_no=0;
381   regs *r, *rprev;
382   int init_addr, i;
383   regs **rlist;
384
385         /* put all symbols in an array */
386         rlist = Safe_calloc(elementsInSet(section), sizeof(regs *));
387         r = rlist[0]; i = 0;
388         for(rprev = setFirstItem(section); rprev; rprev = setNextItem(section)) {
389                 rlist[i] = rprev; i++;
390         }
391
392         /* sort symbols according to their address */
393         qsort(rlist, elementsInSet(section), sizeof(regs *), regCompare);
394         
395         if(!i)return;
396         
397         if(!fix) {
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);
401                 }
402         } else {
403           int j=0;
404                   
405                 rprev = NULL;
406                 init_addr = rlist[j]->address;
407                 fprintf(of, "\n\nstatic_%s_%02d\tudata\t0X%04X\n", moduleName, abs_section_no++, init_addr);
408         
409                 for(j=0;j<i;j++) {
410                         r = rlist[j];
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);
414                         }
415
416                         fprintf(of, "%s\tres\t%d\n", r->name, r->size);
417                         rprev = r;
418                 }
419         }
420         free(rlist);
421 }
422
423
424
425
426 /*-----------------------------------------------------------------*
427  *  void pic16_list_valid_pics(int ncols, int list_alias)
428  *
429  * Print out a formatted list of valid PIC devices
430  *
431  * ncols - number of columns in the list.
432  *
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)
437 {
438   int col,longest;
439   int i,j,k,l;
440
441   if(list_alias)
442     list_alias = sizeof(Pics[0].name) / sizeof(Pics[0].name[0]);
443
444   /* decrement the column number if it's greater than zero */
445   ncols = (ncols > 1) ? ncols-1 : 4;
446
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]);
451       if(k>longest)
452         longest = k;
453     }
454   }
455
456   col = 0;
457
458   for(i=0;  i < num_of_supported_PICS; i++) {
459     j = 0;
460     do {
461
462       fprintf(stderr,"%s", Pics[i].name[j]);
463       if(col<ncols) {
464         l = longest + 2 - strlen(Pics[i].name[j]);
465         for(k=0; k<l; k++)
466           fputc(' ',stderr);
467
468         col++;
469
470       } else {
471         fputc('\n',stderr);
472         col = 0;
473       }
474
475     } while(++j<list_alias);
476
477   }
478   if(col != ncols)
479     fputc('\n',stderr);
480
481 }
482
483 /*-----------------------------------------------------------------*
484  *  
485  *-----------------------------------------------------------------*/
486 PIC_device *pic16_find_device(char *name)
487 {
488
489   int i,j;
490
491   if(!name)
492     return NULL;
493
494   for(i = 0; i<num_of_supported_PICS; i++) {
495
496     for(j=0; j<PROCESSOR_NAMES; j++)
497       if(!STRCASECMP(Pics[i].name[j], name) )
498         return &Pics[i];
499   }
500
501   /* not found */
502   return NULL; 
503 }
504
505 /*-----------------------------------------------------------------*
506  *  
507  *-----------------------------------------------------------------*/
508 void pic16_init_pic(char *pic_type)
509 {
510         pic = pic16_find_device(pic_type);
511
512         if(!pic) {
513                 if(pic_type)
514                         fprintf(stderr, "'%s' was not found.\n", pic_type);
515                 else
516                         fprintf(stderr, "No processor has been specified (use -pPROCESSOR_NAME)\n");
517
518                 fprintf(stderr,"Valid devices are:\n");
519
520                 pic16_list_valid_pics(4,0);
521                 exit(1);
522         }
523
524 //      printf("PIC processor found and initialized: %s\n", pic_type);
525         pic16_setMaxRAM( 0xfff  );
526 }
527
528 /*-----------------------------------------------------------------*
529  *  
530  *-----------------------------------------------------------------*/
531 int pic16_picIsInitialized(void)
532 {
533   if(pic && pic->maxRAMaddress > 0)
534     return 1;
535
536   return 0;
537
538 }
539
540 /*-----------------------------------------------------------------*
541  *  char *pic16_processor_base_name(void) - Include file is derived from this.
542  *-----------------------------------------------------------------*/
543 char *pic16_processor_base_name(void)
544 {
545
546   if(!pic)
547     return NULL;
548
549   return pic->name[0];
550 }
551
552
553 #if 0
554 /*-----------------------------------------------------------------*
555  *-----------------------------------------------------------------*/
556 static int validAddress(int address, int reg_size)
557 {
558   int i;
559
560 #if 0
561   if (pic->maxRAMaddress < 0) {
562     fprintf(stderr, "missing \"#pragma maxram\" setting\n");
563     return 0;
564   }
565 //  fprintf(stderr, "validAddress: Checking 0x%04x (max=0x%04x) (reg_size = %d)\n",address, pic->maxRAMaddress, reg_size);
566   if(address > pic->maxRAMaddress)
567     return 0;
568
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 )
573       return 0;
574 #endif
575
576   return 1;
577 }
578 #endif
579
580 void checkAddReg(set **set, regs *reg)
581 {
582   regs *tmp;
583
584
585         for(tmp = setFirstItem(*set); tmp; tmp = setNextItem(*set)) {
586                 if(!strcmp(tmp->name, reg->name))break;
587         }
588         
589         if(!tmp)
590                 addSet(set, reg);
591 }
592
593 /*-----------------------------------------------------------------*
594  * void pic16_groupRegistersInSection - add each register to its   *
595  *      corresponding section                                      *
596  *-----------------------------------------------------------------*/
597 void pic16_groupRegistersInSection(set *regset)
598 {
599   regs *reg;
600
601         for(reg=setFirstItem(regset); reg; reg = setNextItem(regset)) {
602                 if(reg->wasUsed
603                         && !(reg->regop && SPEC_EXTR(OP_SYM_ETYPE(reg->regop)))) {
604
605 //                      fprintf(stderr, "%s:%d register %s\n", __FILE__, __LINE__, reg->name);
606
607                         if(reg->alias) {
608                                 checkAddReg(&pic16_equ_data, reg);
609                         } else
610                         if(reg->isFixed) {
611                                 checkAddReg(&pic16_fix_udata, reg);
612                         } else
613                         if(!reg->isFixed) {
614 //                              fprintf(stderr, "%s:%d adding symbol %s in relocatable udata section\n",
615 //                                      __FILE__, __LINE__, reg->name);
616                                 checkAddReg(&pic16_rel_udata, reg);
617                         }
618                 }
619         }
620 }
621
622
623
624
625
626 /*-----------------------------------------------------------------*
627  *  void pic16_assignConfigWordValue(int address, int value)
628  *
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.
632  *
633  *-----------------------------------------------------------------*/
634
635 void pic16_assignConfigWordValue(int address, int value)
636 {
637   switch(address) {
638   case CONFIG1H_WORD_ADDRESS:
639     config1h_word = value;
640     break;
641   case CONFIG2L_WORD_ADDRESS:
642     config2l_word = value;
643     break;
644   case CONFIG2H_WORD_ADDRESS:
645     config2h_word = value;
646     break;
647   case CONFIG3H_WORD_ADDRESS:
648     config3h_word = value;
649     break;
650   case CONFIG4L_WORD_ADDRESS:
651     config4l_word = value;
652     break;
653   case CONFIG5L_WORD_ADDRESS:
654     config5l_word = value;
655     break;
656   case CONFIG5H_WORD_ADDRESS:
657     config5h_word = value;
658     break;
659   case CONFIG6L_WORD_ADDRESS:
660     config6l_word = value;
661     break;
662   case CONFIG6H_WORD_ADDRESS:
663     config6h_word = value;
664     break;
665   case CONFIG7L_WORD_ADDRESS:
666     config7l_word = value;
667     break;
668   case CONFIG7H_WORD_ADDRESS:
669     config7h_word = value;
670     break;
671   }
672
673         fprintf(stderr,"setting config word to 0x%x\n",value);
674
675 }
676 /*-----------------------------------------------------------------*
677  * int pic16_getConfigWord(int address)
678  *
679  * Get the current value of the config word.
680  *
681  *-----------------------------------------------------------------*/
682
683 int pic16_getConfigWord(int address)
684 {
685   switch(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;
708   default:
709     return 0;
710   }
711 }