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