2004-01-11 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 void pic16_setMaxRAM(int size)
264 {
265   pic->maxRAMaddress = size;
266   stackPos = pic->RAMsize-1;
267
268   if (pic->maxRAMaddress < 0) {
269     fprintf(stderr, "invalid \"#pragma maxram 0x%x\" setting\n",
270             pic->maxRAMaddress);
271     return;
272   }
273
274 //  pic16_finalMapping = Safe_calloc(1+pic->maxRAMaddress,
275 //                           sizeof(AssignedMemory));
276
277   /* Now initialize the pic16_finalMapping array */
278
279 //  for(i=0; i<=pic->maxRAMaddress; i++) {
280 //    pic16_finalMapping[i].reg = NULL;
281 //    pic16_finalMapping[i].isValid = 0;
282 //  }
283 }
284
285 /*-----------------------------------------------------------------*
286  *-----------------------------------------------------------------*/
287 #if 0
288 int pic16_isREGinBank(regs *reg, int bank)
289 {
290
291   if(!reg || !pic)
292     return 0;
293
294   if(pic16_finalMapping[reg->address].bank == bank)
295     return 1;
296
297   return 0;
298 }
299 #endif
300 /*-----------------------------------------------------------------*
301  *-----------------------------------------------------------------*/
302 int pic16_REGallBanks(regs *reg)
303 {
304
305   if(!reg || !pic)
306     return 0;
307
308   if ((int)reg->address > pic->maxRAMaddress)
309     return 0;
310
311   return 1;
312
313 }
314
315 /*-----------------------------------------------------------------*
316  *-----------------------------------------------------------------*/
317
318 /*
319  *  pic16_dump_map -- debug stuff
320  */
321 #if 0
322 void pic16_dump_map(void)
323 {
324   int i;
325
326   for(i=0; i<=pic->maxRAMaddress; i++) {
327     //fprintf(stdout , "addr 0x%02x is %s\n", i, ((pic16_finalMapping[i].isValid) ? "valid":"invalid"));
328
329     if(pic16_finalMapping[i].isValid) {
330       fprintf(stderr,"addr: 0x%02x",i);
331       if(pic16_finalMapping[i].isSFR)
332         fprintf(stderr," isSFR");
333       if(pic16_finalMapping[i].reg) 
334         fprintf( stderr, "  reg %s", pic16_finalMapping[i].reg->name);
335       fprintf(stderr, "\n");
336     }
337   }
338
339 }
340 #endif
341
342 extern char *iComments2;
343
344 void pic16_dump_equates(FILE *of, set *equs)
345 {
346   regs *r;
347
348         r = setFirstItem(equs);
349         if(!r)return;
350         
351         fprintf(of, "%s", iComments2);
352         fprintf(of, ";\tEquates to used internal registers\n");
353         fprintf(of, "%s", iComments2);
354         
355         for(; r; r = setNextItem(equs)) {
356                 fprintf(of, "%s\tequ\t0x%02x\n", r->name, r->address);
357         }
358 }
359
360
361 void pic16_dump_section(FILE *of, set *section, int fix)
362 {
363   static int abs_section_no=0;
364   regs *r, *rprev;
365   int init_addr;
366
367         if(!fix) {
368                 fprintf(of, "\n\n\tudata\n");
369                 for(r = setFirstItem(section); r; r = setNextItem(section)) {
370                         fprintf(of, "%s\tres\t%d\n", r->name, r->size);
371                 }
372         } else {
373                 r = setFirstItem(section);
374                 if(!r)return;
375                 init_addr = r->address;
376                 fprintf(of, "\n\nstatic_%s_%02d\tudata\t0X%04X\n", moduleName, abs_section_no++, init_addr);
377                 
378                 rprev = NULL;
379                 for(; r; r = setNextItem(section)) {
380                         init_addr = r->address;
381
382                         if(rprev && (init_addr != (rprev->address + rprev->size))) {
383                                 fprintf(of, "\nstatic_%s_%02d\tudata\t0X%04X\n", moduleName, abs_section_no++, init_addr);
384                         }
385
386                         fprintf(of, "%s\tres\t%d\n", r->name, r->size);
387                         rprev = r;
388                 }
389         }
390 }
391
392
393
394
395 /*-----------------------------------------------------------------*
396  *  void pic16_list_valid_pics(int ncols, int list_alias)
397  *
398  * Print out a formatted list of valid PIC devices
399  *
400  * ncols - number of columns in the list.
401  *
402  * list_alias - if non-zero, print all of the supported aliases
403  *              for a device (e.g. F84, 16F84, etc...)
404  *-----------------------------------------------------------------*/
405 void pic16_list_valid_pics(int ncols, int list_alias)
406 {
407   int col,longest;
408   int i,j,k,l;
409
410   if(list_alias)
411     list_alias = sizeof(Pics[0].name) / sizeof(Pics[0].name[0]);
412
413   /* decrement the column number if it's greater than zero */
414   ncols = (ncols > 1) ? ncols-1 : 4;
415
416   /* Find the device with the longest name */
417   for(i=0,longest=0; i<num_of_supported_PICS; i++) {
418     for(j=0; j<=list_alias; j++) {
419       k = strlen(Pics[i].name[j]);
420       if(k>longest)
421         longest = k;
422     }
423   }
424
425   col = 0;
426
427   for(i=0;  i < num_of_supported_PICS; i++) {
428     j = 0;
429     do {
430
431       fprintf(stderr,"%s", Pics[i].name[j]);
432       if(col<ncols) {
433         l = longest + 2 - strlen(Pics[i].name[j]);
434         for(k=0; k<l; k++)
435           fputc(' ',stderr);
436
437         col++;
438
439       } else {
440         fputc('\n',stderr);
441         col = 0;
442       }
443
444     } while(++j<list_alias);
445
446   }
447   if(col != ncols)
448     fputc('\n',stderr);
449
450 }
451
452 /*-----------------------------------------------------------------*
453  *  
454  *-----------------------------------------------------------------*/
455 PIC_device *pic16_find_device(char *name)
456 {
457
458   int i,j;
459
460   if(!name)
461     return NULL;
462
463   for(i = 0; i<num_of_supported_PICS; i++) {
464
465     for(j=0; j<PROCESSOR_NAMES; j++)
466       if(!STRCASECMP(Pics[i].name[j], name) )
467         return &Pics[i];
468   }
469
470   /* not found */
471   return NULL; 
472 }
473
474 /*-----------------------------------------------------------------*
475  *  
476  *-----------------------------------------------------------------*/
477 void pic16_init_pic(char *pic_type)
478 {
479         pic = pic16_find_device(pic_type);
480
481         if(!pic) {
482                 if(pic_type)
483                         fprintf(stderr, "'%s' was not found.\n", pic_type);
484                 else
485                         fprintf(stderr, "No processor has been specified (use -pPROCESSOR_NAME)\n");
486
487                 fprintf(stderr,"Valid devices are:\n");
488
489                 pic16_list_valid_pics(4,0);
490                 exit(1);
491         }
492
493 //      printf("PIC processor found and initialized: %s\n", pic_type);
494         pic16_setMaxRAM( 0xfff  );
495 }
496
497 /*-----------------------------------------------------------------*
498  *  
499  *-----------------------------------------------------------------*/
500 int pic16_picIsInitialized(void)
501 {
502   if(pic && pic->maxRAMaddress > 0)
503     return 1;
504
505   return 0;
506
507 }
508
509 /*-----------------------------------------------------------------*
510  *  char *pic16_processor_base_name(void) - Include file is derived from this.
511  *-----------------------------------------------------------------*/
512 char *pic16_processor_base_name(void)
513 {
514
515   if(!pic)
516     return NULL;
517
518   return pic->name[0];
519 }
520
521
522 #if 0
523 /*-----------------------------------------------------------------*
524  *-----------------------------------------------------------------*/
525 static int validAddress(int address, int reg_size)
526 {
527   int i;
528
529 #if 0
530   if (pic->maxRAMaddress < 0) {
531     fprintf(stderr, "missing \"#pragma maxram\" setting\n");
532     return 0;
533   }
534 //  fprintf(stderr, "validAddress: Checking 0x%04x (max=0x%04x) (reg_size = %d)\n",address, pic->maxRAMaddress, reg_size);
535   if(address > pic->maxRAMaddress)
536     return 0;
537
538   for (i=0; i<reg_size; i++)
539     if(!pic16_finalMapping[address + i].isValid || 
540        pic16_finalMapping[address+i].reg ||
541        pic16_finalMapping[address+i].isSFR )
542       return 0;
543 #endif
544
545   return 1;
546 }
547 #endif
548
549 void checkAddReg(set **set, regs *reg)
550 {
551   regs *tmp;
552
553
554         for(tmp = setFirstItem(*set); tmp; tmp = setNextItem(*set)) {
555                 if(!strcmp(tmp->name, reg->name))break;
556         }
557         
558         if(!tmp)
559                 addSet(set, reg);
560 }
561
562 /*-----------------------------------------------------------------*
563  * void pic16_groupRegistersInSection - add each register to its   *
564  *      corresponding section                                      *
565  *-----------------------------------------------------------------*/
566 void pic16_groupRegistersInSection(set *regset)
567 {
568   regs *reg;
569
570         for(reg=setFirstItem(regset); reg; reg = setNextItem(regset)) {
571                 if(reg->wasUsed
572                         && !(reg->regop && SPEC_EXTR(OP_SYM_ETYPE(reg->regop)))) {
573
574                         if(reg->alias) {
575                                 checkAddReg(&pic16_equ_data, reg);
576                         } else
577                         if(reg->isFixed) {
578                                 checkAddReg(&pic16_fix_udata, reg);
579                         } else
580                         if(!reg->isFixed) {
581 //                              fprintf(stderr, "%s:%d adding symbol %s in relocatable udata section\n",
582 //                                      __FILE__, __LINE__, reg->name);
583                                 checkAddReg(&pic16_rel_udata, reg);
584                         }
585                 }
586         }
587 }
588
589
590
591
592
593 /*-----------------------------------------------------------------*
594  *  void pic16_assignConfigWordValue(int address, int value)
595  *
596  * All high performance RISC CPU PICs have seven config word starting
597  * at address 0x300000.
598  * This routine will assign a value to that address.
599  *
600  *-----------------------------------------------------------------*/
601
602 void pic16_assignConfigWordValue(int address, int value)
603 {
604   switch(address) {
605   case CONFIG1H_WORD_ADDRESS:
606     config1h_word = value;
607     break;
608   case CONFIG2L_WORD_ADDRESS:
609     config2l_word = value;
610     break;
611   case CONFIG2H_WORD_ADDRESS:
612     config2h_word = value;
613     break;
614   case CONFIG3H_WORD_ADDRESS:
615     config3h_word = value;
616     break;
617   case CONFIG4L_WORD_ADDRESS:
618     config4l_word = value;
619     break;
620   case CONFIG5L_WORD_ADDRESS:
621     config5l_word = value;
622     break;
623   case CONFIG5H_WORD_ADDRESS:
624     config5h_word = value;
625     break;
626   case CONFIG6L_WORD_ADDRESS:
627     config6l_word = value;
628     break;
629   case CONFIG6H_WORD_ADDRESS:
630     config6h_word = value;
631     break;
632   case CONFIG7L_WORD_ADDRESS:
633     config7l_word = value;
634     break;
635   case CONFIG7H_WORD_ADDRESS:
636     config7h_word = value;
637     break;
638   }
639
640         fprintf(stderr,"setting config word to 0x%x\n",value);
641
642 }
643 /*-----------------------------------------------------------------*
644  * int pic16_getConfigWord(int address)
645  *
646  * Get the current value of the config word.
647  *
648  *-----------------------------------------------------------------*/
649
650 int pic16_getConfigWord(int address)
651 {
652   switch(address) {
653   case CONFIG1H_WORD_ADDRESS:
654     return config1h_word;
655   case CONFIG2L_WORD_ADDRESS:
656     return config2l_word;
657   case CONFIG2H_WORD_ADDRESS:
658     return config2h_word;
659   case CONFIG3H_WORD_ADDRESS:
660     return config3h_word;
661   case CONFIG4L_WORD_ADDRESS:
662     return config4l_word;
663   case CONFIG5L_WORD_ADDRESS:
664     return config5l_word;
665   case CONFIG5H_WORD_ADDRESS:
666     return config5h_word;
667   case CONFIG6L_WORD_ADDRESS:
668     return config6l_word;
669   case CONFIG6H_WORD_ADDRESS:
670     return config6h_word;
671   case CONFIG7L_WORD_ADDRESS:
672     return config7l_word;
673   case CONFIG7H_WORD_ADDRESS:
674     return config7h_word;
675   default:
676     return 0;
677   }
678 }