2004-02-06 Vangelis Rokas <vrokas AT 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 PIC16_device Pics16[] = {
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(Pics16)/sizeof(PIC16_device);
206
207 #define DEFAULT_PIC "452"
208
209 PIC16_device *pic16=NULL;
210
211 #define DEFAULT_CONFIG_BYTE 0xff
212
213 #define CONFIG1H_WORD_ADDRESS 0x300001
214 #define DEFAULT_CONFIG1H_WORD DEFAULT_CONFIG_BYTE
215
216 #define CONFIG2L_WORD_ADDRESS 0x300002
217 #define DEFAULT_CONFIG2L_WORD DEFAULT_CONFIG_BYTE
218
219 #define CONFIG2H_WORD_ADDRESS 0x300003
220 #define DEFAULT_CONFIG2H_WORD DEFAULT_CONFIG_BYTE
221
222 #define CONFIG3H_WORD_ADDRESS 0x300005
223 #define DEFAULT_CONFIG3H_WORD DEFAULT_CONFIG_BYTE
224
225 #define CONFIG4L_WORD_ADDRESS 0x300006
226 #define DEFAULT_CONFIG4L_WORD DEFAULT_CONFIG_BYTE
227
228 #define CONFIG5L_WORD_ADDRESS 0x300008
229 #define DEFAULT_CONFIG5L_WORD DEFAULT_CONFIG_BYTE
230
231 #define CONFIG5H_WORD_ADDRESS 0x300009
232 #define DEFAULT_CONFIG5H_WORD DEFAULT_CONFIG_BYTE
233
234 #define CONFIG6L_WORD_ADDRESS 0x30000a
235 #define DEFAULT_CONFIG6L_WORD DEFAULT_CONFIG_BYTE
236
237 #define CONFIG6H_WORD_ADDRESS 0x30000b
238 #define DEFAULT_CONFIG6H_WORD DEFAULT_CONFIG_BYTE
239
240 #define CONFIG7L_WORD_ADDRESS 0x30000c
241 #define DEFAULT_CONFIG7L_WORD DEFAULT_CONFIG_BYTE
242
243 #define CONFIG7H_WORD_ADDRESS 0x30000d
244 #define DEFAULT_CONFIG7H_WORD DEFAULT_CONFIG_BYTE
245
246 static unsigned int config1h_word = DEFAULT_CONFIG1H_WORD;
247 static unsigned int config2l_word = DEFAULT_CONFIG2L_WORD;
248 static unsigned int config2h_word = DEFAULT_CONFIG2H_WORD;
249 static unsigned int config3h_word = DEFAULT_CONFIG3H_WORD;
250 static unsigned int config4l_word = DEFAULT_CONFIG4L_WORD;
251 static unsigned int config5l_word = DEFAULT_CONFIG5L_WORD;
252 static unsigned int config5h_word = DEFAULT_CONFIG5H_WORD;
253 static unsigned int config6l_word = DEFAULT_CONFIG6L_WORD;
254 static unsigned int config6h_word = DEFAULT_CONFIG6H_WORD;
255 static unsigned int config7l_word = DEFAULT_CONFIG7L_WORD;
256 static unsigned int config7h_word = DEFAULT_CONFIG7H_WORD;
257
258 unsigned int stackPos = 0;
259
260 extern regs* newReg(short type, short pc_type, int rIdx, char *name, int size, int alias, operand *refop);
261
262 void pic16_setMaxRAM(int size)
263 {
264   regs * reg;
265   pic16->maxRAMaddress = size;
266   stackPos = pic16->RAMsize-1;
267
268
269         if(USE_STACK) {
270                 reg=newReg(REG_SFR, PO_SFR_REGISTER, stackPos, "stack", 1, 0, NULL);
271                 addSet(&pic16_fix_udata, reg);
272         }
273
274         if (pic16->maxRAMaddress < 0) {
275                 fprintf(stderr, "invalid \"#pragma maxram 0x%x\" setting\n",
276                         pic16->maxRAMaddress);
277           return;
278         }
279 }
280
281 extern char *iComments2;
282
283 void pic16_dump_equates(FILE *of, set *equs)
284 {
285   regs *r;
286
287         r = setFirstItem(equs);
288         if(!r)return;
289         
290         fprintf(of, "%s", iComments2);
291         fprintf(of, ";\tEquates to used internal registers\n");
292         fprintf(of, "%s", iComments2);
293         
294         for(; r; r = setNextItem(equs)) {
295                 fprintf(of, "%s\tequ\t0x%02x\n", r->name, r->address);
296         }
297 }
298
299
300 int regCompare(const void *a, const void *b)
301 {
302   const regs *const *i = a;
303   const regs *const *j = b;
304
305         /* sort primarily by the address */
306         if( (*i)->address > (*j)->address)return 1;
307         if( (*i)->address < (*j)->address)return -1;
308         
309         /* and secondarily by size */
310         if( (*i)->size > (*j)->size)return 1;
311         if( (*i)->size < (*j)->size)return -1;
312
313
314   return 0;
315 }
316
317 void pic16_dump_section(FILE *of, set *section, int fix)
318 {
319   static int abs_section_no=0;
320   regs *r, *rprev;
321   int init_addr, i;
322   regs **rlist;
323
324         /* put all symbols in an array */
325         rlist = Safe_calloc(elementsInSet(section), sizeof(regs *));
326         r = rlist[0]; i = 0;
327         for(rprev = setFirstItem(section); rprev; rprev = setNextItem(section)) {
328                 rlist[i] = rprev; i++;
329         }
330
331         /* sort symbols according to their address */
332         qsort(rlist, elementsInSet(section), sizeof(regs *), regCompare);
333         
334         if(!i)return;
335         
336         if(!fix) {
337                 fprintf(of, "\n\n\tudata\n");
338                 for(r = setFirstItem(section); r; r = setNextItem(section)) {
339                         fprintf(of, "%s\tres\t%d\n", r->name, r->size);
340                 }
341         } else {
342           int j=0;
343                   
344                 rprev = NULL;
345                 init_addr = rlist[j]->address;
346                 fprintf(of, "\n\nstatic_%s_%02d\tudata\t0X%04X\n", moduleName, abs_section_no++, init_addr);
347         
348                 for(j=0;j<i;j++) {
349                         r = rlist[j];
350                         init_addr = r->address;
351                         if(rprev && (init_addr != (rprev->address + rprev->size))) {
352                                 fprintf(of, "\nstatic_%s_%02d\tudata\t0X%04X\n", moduleName, abs_section_no++, init_addr);
353                         }
354
355                         fprintf(of, "%s\tres\t%d\n", r->name, r->size);
356                         rprev = r;
357                 }
358         }
359         free(rlist);
360 }
361
362
363
364
365 /*-----------------------------------------------------------------*
366  *  void pic16_list_valid_pics(int ncols, int list_alias)
367  *
368  * Print out a formatted list of valid PIC devices
369  *
370  * ncols - number of columns in the list.
371  *
372  * list_alias - if non-zero, print all of the supported aliases
373  *              for a device (e.g. F84, 16F84, etc...)
374  *-----------------------------------------------------------------*/
375 void pic16_list_valid_pics(int ncols, int list_alias)
376 {
377   int col,longest;
378   int i,j,k,l;
379
380   if(list_alias)
381     list_alias = sizeof(Pics16[0].name) / sizeof(Pics16[0].name[0]);
382
383   /* decrement the column number if it's greater than zero */
384   ncols = (ncols > 1) ? ncols-1 : 4;
385
386   /* Find the device with the longest name */
387   for(i=0,longest=0; i<num_of_supported_PICS; i++) {
388     for(j=0; j<=list_alias; j++) {
389       k = strlen(Pics16[i].name[j]);
390       if(k>longest)
391         longest = k;
392     }
393   }
394
395   col = 0;
396
397   for(i=0;  i < num_of_supported_PICS; i++) {
398     j = 0;
399     do {
400
401       fprintf(stderr,"%s", Pics16[i].name[j]);
402       if(col<ncols) {
403         l = longest + 2 - strlen(Pics16[i].name[j]);
404         for(k=0; k<l; k++)
405           fputc(' ',stderr);
406
407         col++;
408
409       } else {
410         fputc('\n',stderr);
411         col = 0;
412       }
413
414     } while(++j<list_alias);
415
416   }
417   if(col != ncols)
418     fputc('\n',stderr);
419
420 }
421
422 /*-----------------------------------------------------------------*
423  *  
424  *-----------------------------------------------------------------*/
425 PIC16_device *pic16_find_device(char *name)
426 {
427
428   int i,j;
429
430   if(!name)
431     return NULL;
432
433   for(i = 0; i<num_of_supported_PICS; i++) {
434
435     for(j=0; j<PROCESSOR_NAMES; j++)
436       if(!STRCASECMP(Pics16[i].name[j], name) )
437         return &Pics16[i];
438   }
439
440   /* not found */
441   return NULL; 
442 }
443
444 /*-----------------------------------------------------------------*
445  *  
446  *-----------------------------------------------------------------*/
447 void pic16_init_pic(char *pic_type)
448 {
449         pic16 = pic16_find_device(pic_type);
450
451         if(!pic16) {
452                 if(pic_type)
453                         fprintf(stderr, "'%s' was not found.\n", pic_type);
454                 else
455                         fprintf(stderr, "No processor has been specified (use -pPROCESSOR_NAME)\n");
456
457                 fprintf(stderr,"Valid devices are:\n");
458
459                 pic16_list_valid_pics(4,0);
460                 exit(1);
461         }
462
463 //      printf("PIC processor found and initialized: %s\n", pic_type);
464         pic16_setMaxRAM( 0xfff  );
465 }
466
467 /*-----------------------------------------------------------------*
468  *  
469  *-----------------------------------------------------------------*/
470 int pic16_picIsInitialized(void)
471 {
472   if(pic16 && pic16->maxRAMaddress > 0)
473     return 1;
474
475   return 0;
476
477 }
478
479 /*-----------------------------------------------------------------*
480  *  char *pic16_processor_base_name(void) - Include file is derived from this.
481  *-----------------------------------------------------------------*/
482 char *pic16_processor_base_name(void)
483 {
484
485   if(!pic16)
486     return NULL;
487
488   return pic16->name[0];
489 }
490
491
492 void checkAddReg(set **set, regs *reg)
493 {
494   regs *tmp;
495
496
497         for(tmp = setFirstItem(*set); tmp; tmp = setNextItem(*set)) {
498                 if(!strcmp(tmp->name, reg->name))break;
499         }
500         
501         if(!tmp)
502                 addSet(set, reg);
503 }
504
505 /*-----------------------------------------------------------------*
506  * void pic16_groupRegistersInSection - add each register to its   *
507  *      corresponding section                                      *
508  *-----------------------------------------------------------------*/
509 void pic16_groupRegistersInSection(set *regset)
510 {
511   regs *reg;
512
513         for(reg=setFirstItem(regset); reg; reg = setNextItem(regset)) {
514                 if(reg->wasUsed
515                         && !(reg->regop && SPEC_EXTR(OP_SYM_ETYPE(reg->regop)))) {
516
517 //                      fprintf(stderr, "%s:%d register %s\n", __FILE__, __LINE__, reg->name);
518
519                         if(reg->alias) {
520                                 checkAddReg(&pic16_equ_data, reg);
521                         } else
522                         if(reg->isFixed) {
523                                 checkAddReg(&pic16_fix_udata, reg);
524                         } else
525                         if(!reg->isFixed) {
526 //                              fprintf(stderr, "%s:%d adding symbol %s in relocatable udata section\n",
527 //                                      __FILE__, __LINE__, reg->name);
528                                 checkAddReg(&pic16_rel_udata, reg);
529                         }
530                 }
531         }
532 }
533
534
535
536
537
538 /*-----------------------------------------------------------------*
539  *  void pic16_assignConfigWordValue(int address, int value)
540  *
541  * All high performance RISC CPU PICs have seven config word starting
542  * at address 0x300000.
543  * This routine will assign a value to that address.
544  *
545  *-----------------------------------------------------------------*/
546
547 void pic16_assignConfigWordValue(int address, int value)
548 {
549   switch(address) {
550   case CONFIG1H_WORD_ADDRESS:
551     config1h_word = value;
552     break;
553   case CONFIG2L_WORD_ADDRESS:
554     config2l_word = value;
555     break;
556   case CONFIG2H_WORD_ADDRESS:
557     config2h_word = value;
558     break;
559   case CONFIG3H_WORD_ADDRESS:
560     config3h_word = value;
561     break;
562   case CONFIG4L_WORD_ADDRESS:
563     config4l_word = value;
564     break;
565   case CONFIG5L_WORD_ADDRESS:
566     config5l_word = value;
567     break;
568   case CONFIG5H_WORD_ADDRESS:
569     config5h_word = value;
570     break;
571   case CONFIG6L_WORD_ADDRESS:
572     config6l_word = value;
573     break;
574   case CONFIG6H_WORD_ADDRESS:
575     config6h_word = value;
576     break;
577   case CONFIG7L_WORD_ADDRESS:
578     config7l_word = value;
579     break;
580   case CONFIG7H_WORD_ADDRESS:
581     config7h_word = value;
582     break;
583   }
584
585         fprintf(stderr,"setting config word to 0x%x\n",value);
586
587 }
588 /*-----------------------------------------------------------------*
589  * int pic16_getConfigWord(int address)
590  *
591  * Get the current value of the config word.
592  *
593  *-----------------------------------------------------------------*/
594
595 int pic16_getConfigWord(int address)
596 {
597   switch(address) {
598   case CONFIG1H_WORD_ADDRESS:
599     return config1h_word;
600   case CONFIG2L_WORD_ADDRESS:
601     return config2l_word;
602   case CONFIG2H_WORD_ADDRESS:
603     return config2h_word;
604   case CONFIG3H_WORD_ADDRESS:
605     return config3h_word;
606   case CONFIG4L_WORD_ADDRESS:
607     return config4l_word;
608   case CONFIG5L_WORD_ADDRESS:
609     return config5l_word;
610   case CONFIG5H_WORD_ADDRESS:
611     return config5h_word;
612   case CONFIG6L_WORD_ADDRESS:
613     return config6l_word;
614   case CONFIG6H_WORD_ADDRESS:
615     return config6h_word;
616   case CONFIG7L_WORD_ADDRESS:
617     return config7l_word;
618   case CONFIG7H_WORD_ADDRESS:
619     return config7h_word;
620   default:
621     return 0;
622   }
623 }