2004-01-06 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
343 void pic16_dump_section(FILE *of, char *sname, set *section, int fix)
344 {
345   static int abs_section_no=0;
346   regs *r, *rprev;
347   int init_addr;
348
349         if(!fix) {
350                 fprintf(of, "\n\n\tudata\n");
351                 for(r = setFirstItem(section); r; r = setNextItem(section)) {
352                         fprintf(of, "%s\tres\t%d\n", r->name, r->size);
353                 }
354         } else {
355                 r = setFirstItem(section);
356                 if(!r)return;
357                 init_addr = r->address;
358                 fprintf(of, "\n\nstatic_%s_%02d\tudata\t0X%04X\n", moduleName, abs_section_no++, init_addr);
359                 
360                 rprev = NULL;
361                 for(; r; r = setNextItem(section)) {
362                         init_addr = r->address;
363
364                         if(rprev && (init_addr != (rprev->address + rprev->size))) {
365                                 fprintf(of, "\nstatic_%s_%02d\tudata\t0X%04X\n", moduleName, abs_section_no++, init_addr);
366                         }
367
368                         fprintf(of, "%s\tres\t%d\n", r->name, r->size);
369                         rprev = r;
370                 }
371         }
372 }
373
374
375
376
377 /*-----------------------------------------------------------------*
378  *  void pic16_list_valid_pics(int ncols, int list_alias)
379  *
380  * Print out a formatted list of valid PIC devices
381  *
382  * ncols - number of columns in the list.
383  *
384  * list_alias - if non-zero, print all of the supported aliases
385  *              for a device (e.g. F84, 16F84, etc...)
386  *-----------------------------------------------------------------*/
387 void pic16_list_valid_pics(int ncols, int list_alias)
388 {
389   int col,longest;
390   int i,j,k,l;
391
392   if(list_alias)
393     list_alias = sizeof(Pics[0].name) / sizeof(Pics[0].name[0]);
394
395   /* decrement the column number if it's greater than zero */
396   ncols = (ncols > 1) ? ncols-1 : 4;
397
398   /* Find the device with the longest name */
399   for(i=0,longest=0; i<num_of_supported_PICS; i++) {
400     for(j=0; j<=list_alias; j++) {
401       k = strlen(Pics[i].name[j]);
402       if(k>longest)
403         longest = k;
404     }
405   }
406
407   col = 0;
408
409   for(i=0;  i < num_of_supported_PICS; i++) {
410     j = 0;
411     do {
412
413       fprintf(stderr,"%s", Pics[i].name[j]);
414       if(col<ncols) {
415         l = longest + 2 - strlen(Pics[i].name[j]);
416         for(k=0; k<l; k++)
417           fputc(' ',stderr);
418
419         col++;
420
421       } else {
422         fputc('\n',stderr);
423         col = 0;
424       }
425
426     } while(++j<list_alias);
427
428   }
429   if(col != ncols)
430     fputc('\n',stderr);
431
432 }
433
434 /*-----------------------------------------------------------------*
435  *  
436  *-----------------------------------------------------------------*/
437 PIC_device *pic16_find_device(char *name)
438 {
439
440   int i,j;
441
442   if(!name)
443     return NULL;
444
445   for(i = 0; i<num_of_supported_PICS; i++) {
446
447     for(j=0; j<PROCESSOR_NAMES; j++)
448       if(!STRCASECMP(Pics[i].name[j], name) )
449         return &Pics[i];
450   }
451
452   /* not found */
453   return NULL; 
454 }
455
456 /*-----------------------------------------------------------------*
457  *  
458  *-----------------------------------------------------------------*/
459 void pic16_init_pic(char *pic_type)
460 {
461         pic = pic16_find_device(pic_type);
462
463         if(!pic) {
464                 if(pic_type)
465                         fprintf(stderr, "'%s' was not found.\n", pic_type);
466                 else
467                         fprintf(stderr, "No processor has been specified (use -pPROCESSOR_NAME)\n");
468
469                 fprintf(stderr,"Valid devices are:\n");
470
471                 pic16_list_valid_pics(4,0);
472                 exit(1);
473         }
474
475 //      printf("PIC processor found and initialized: %s\n", pic_type);
476         pic16_setMaxRAM( 0xfff  );
477 }
478
479 /*-----------------------------------------------------------------*
480  *  
481  *-----------------------------------------------------------------*/
482 int pic16_picIsInitialized(void)
483 {
484   if(pic && pic->maxRAMaddress > 0)
485     return 1;
486
487   return 0;
488
489 }
490
491 /*-----------------------------------------------------------------*
492  *  char *pic16_processor_base_name(void) - Include file is derived from this.
493  *-----------------------------------------------------------------*/
494 char *pic16_processor_base_name(void)
495 {
496
497   if(!pic)
498     return NULL;
499
500   return pic->name[0];
501 }
502
503
504 #if 0
505 /*-----------------------------------------------------------------*
506  *-----------------------------------------------------------------*/
507 static int validAddress(int address, int reg_size)
508 {
509   int i;
510
511 #if 0
512   if (pic->maxRAMaddress < 0) {
513     fprintf(stderr, "missing \"#pragma maxram\" setting\n");
514     return 0;
515   }
516 //  fprintf(stderr, "validAddress: Checking 0x%04x (max=0x%04x) (reg_size = %d)\n",address, pic->maxRAMaddress, reg_size);
517   if(address > pic->maxRAMaddress)
518     return 0;
519
520   for (i=0; i<reg_size; i++)
521     if(!pic16_finalMapping[address + i].isValid || 
522        pic16_finalMapping[address+i].reg ||
523        pic16_finalMapping[address+i].isSFR )
524       return 0;
525 #endif
526
527   return 1;
528 }
529 #endif
530
531 void checkAddReg(set **set, regs *reg)
532 {
533   regs *tmp;
534
535
536         for(tmp = setFirstItem(*set); tmp; tmp = setNextItem(*set)) {
537                 if(!strcmp(tmp->name, reg->name))break;
538         }
539         
540         if(!tmp)
541                 addSet(set, reg);
542 }
543
544 /*-----------------------------------------------------------------*
545  * void pic16_groupRegistersInSection - add each register to its   *
546  *      corresponding section                                      *
547  *-----------------------------------------------------------------*/
548 void pic16_groupRegistersInSection(set *regset)
549 {
550   regs *reg;
551
552         for(reg=setFirstItem(regset); reg; reg = setNextItem(regset)) {
553                 if(reg->wasUsed
554                         && !(reg->regop && SPEC_EXTR(OP_SYM_ETYPE(reg->regop)))) {
555                         if(reg->isFixed)
556                                 checkAddReg(&pic16_fix_udata, reg);
557                 
558                         if(!reg->isFixed)
559                                 checkAddReg(&pic16_rel_udata, reg);
560                 }
561         }
562 }
563
564
565
566
567
568 /*-----------------------------------------------------------------*
569  *  void pic16_assignConfigWordValue(int address, int value)
570  *
571  * All high performance RISC CPU PICs have seven config word starting
572  * at address 0x300000.
573  * This routine will assign a value to that address.
574  *
575  *-----------------------------------------------------------------*/
576
577 void pic16_assignConfigWordValue(int address, int value)
578 {
579   switch(address) {
580   case CONFIG1H_WORD_ADDRESS:
581     config1h_word = value;
582     break;
583   case CONFIG2L_WORD_ADDRESS:
584     config2l_word = value;
585     break;
586   case CONFIG2H_WORD_ADDRESS:
587     config2h_word = value;
588     break;
589   case CONFIG3H_WORD_ADDRESS:
590     config3h_word = value;
591     break;
592   case CONFIG4L_WORD_ADDRESS:
593     config4l_word = value;
594     break;
595   case CONFIG5L_WORD_ADDRESS:
596     config5l_word = value;
597     break;
598   case CONFIG5H_WORD_ADDRESS:
599     config5h_word = value;
600     break;
601   case CONFIG6L_WORD_ADDRESS:
602     config6l_word = value;
603     break;
604   case CONFIG6H_WORD_ADDRESS:
605     config6h_word = value;
606     break;
607   case CONFIG7L_WORD_ADDRESS:
608     config7l_word = value;
609     break;
610   case CONFIG7H_WORD_ADDRESS:
611     config7h_word = value;
612     break;
613   }
614
615         fprintf(stderr,"setting config word to 0x%x\n",value);
616
617 }
618 /*-----------------------------------------------------------------*
619  * int pic16_getConfigWord(int address)
620  *
621  * Get the current value of the config word.
622  *
623  *-----------------------------------------------------------------*/
624
625 int pic16_getConfigWord(int address)
626 {
627   switch(address) {
628   case CONFIG1H_WORD_ADDRESS:
629     return config1h_word;
630   case CONFIG2L_WORD_ADDRESS:
631     return config2l_word;
632   case CONFIG2H_WORD_ADDRESS:
633     return config2h_word;
634   case CONFIG3H_WORD_ADDRESS:
635     return config3h_word;
636   case CONFIG4L_WORD_ADDRESS:
637     return config4l_word;
638   case CONFIG5L_WORD_ADDRESS:
639     return config5l_word;
640   case CONFIG5H_WORD_ADDRESS:
641     return config5h_word;
642   case CONFIG6L_WORD_ADDRESS:
643     return config6l_word;
644   case CONFIG6H_WORD_ADDRESS:
645     return config6h_word;
646   case CONFIG7L_WORD_ADDRESS:
647     return config7l_word;
648   case CONFIG7H_WORD_ADDRESS:
649     return config7h_word;
650   default:
651     return 0;
652   }
653 }