* src/pic/pcode.c (register_reassign): do not crash on recursive code
[fw/sdcc] / src / pic / device.c
1 /*-------------------------------------------------------------------------
2
3    device.c - Accomodates subtle variations in PIC devices
4    Written By -  Scott Dattalo scott@dattalo.com
5
6    This program is free software; you can redistribute it and/or modify it
7    under the terms of the GNU General Public License as published by the
8    Free Software Foundation; either version 2, or (at your option) any
9    later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 -------------------------------------------------------------------------*/
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <ctype.h>
24
25 #include "common.h"   // Include everything in the SDCC src directory
26 #include "newalloc.h"
27
28
29 #include "main.h"
30 #include "pcode.h"
31 #include "ralloc.h"
32 #include "device.h"
33
34 #if defined(__BORLANDC__) || defined(_MSC_VER)
35 #define STRCASECMP stricmp
36 #define STRNCASECMP strnicmp
37 #else
38 #define STRCASECMP strcasecmp
39 #define STRNCASECMP strncasecmp
40 #endif
41
42 extern int Gstack_base_addr;
43 extern int Gstack_size;
44
45 #define MAX_PICLIST 200
46 static PIC_device *Pics[MAX_PICLIST];
47 static int num_of_supported_PICS = 0;
48
49 static PIC_device *pic=NULL;
50
51 int maxRAMaddress = 0;
52 AssignedMemory *finalMapping=NULL;
53
54 #define CONFIG_WORD_ADDRESS 0x2007
55 #define CONFIG2_WORD_ADDRESS 0x2008
56 #define DEFAULT_CONFIG_WORD 0x3fff
57 #define DEFAULT_CONFIG2_WORD 0x3ffc
58
59 #define DEVICE_FILE_NAME "pic14devices.txt"
60 #define PIC14_STRING_LEN 256
61 #define SPLIT_WORDS_MAX 16
62
63 static unsigned int config_word = DEFAULT_CONFIG_WORD;
64 static unsigned int config2_word = DEFAULT_CONFIG2_WORD;
65 static memRange *rangeRAM = NULL;
66
67 extern void emitSymbolToFile (FILE *of, const char *name, const char *section_type, int size, int addr, int useEQU, int globalize);
68
69
70 /* parse a value from the configuration file */
71 static int parse_config_value(char *str)
72 {
73         if (str[strlen(str) - 1] == 'K')
74                 return atoi(str) * 1024;        /* like "1K" */
75                 
76         else if (STRNCASECMP(str, "0x", 2) == 0)
77                 return strtol(str+2, NULL, 16); /* like "0x400" */
78         
79         else
80                 return atoi(str);               /* like "1024" */
81 }
82
83
84 /* split a line into words */
85 static int split_words(char result_word[SPLIT_WORDS_MAX][PIC14_STRING_LEN], char *str)
86 {
87         char *pos = str;
88         int num_words = 0;
89         int ccount;
90         
91         while (*pos != '\0' && num_words < SPLIT_WORDS_MAX) {
92                 /* remove leading spaces */
93                 while (isspace(*pos) || *pos == ',')
94                         pos++;
95         
96                 /* copy everything up until the first space or comma */
97                 for (ccount = 0; *pos != '\0' && !isspace(*pos) && *pos != ',' && ccount < PIC14_STRING_LEN-1; ccount++, pos++)
98                         result_word[num_words][ccount] = *pos;
99                 result_word[num_words][ccount] = '\0';
100                 
101                 num_words++;
102         }
103         
104         return num_words;
105 }
106
107
108 /* remove annoying prefixes from the processor name */
109 static char *sanitise_processor_name(char *name)
110 {
111         char *proc_pos = name;
112
113         if (name == NULL)
114                 return NULL;
115         
116         if (STRNCASECMP(proc_pos, "pic", 3) == 0)
117                 proc_pos += 3;
118
119         else if (tolower(*proc_pos) == 'p')
120                 proc_pos += 1;
121                                 
122         return proc_pos;
123 }
124
125
126 /* create a structure for a pic processor */
127 static PIC_device *create_pic(char *pic_name, int maxram, int bankmsk, int confsiz, int program, int data, int eeprom, int io)
128 {
129         PIC_device *new_pic;
130         char *simple_pic_name = sanitise_processor_name(pic_name);
131         
132         new_pic = Safe_calloc(1, sizeof(PIC_device));
133         new_pic->name = Safe_calloc(strlen(simple_pic_name)+1, sizeof(char));
134         strcpy(new_pic->name, simple_pic_name);
135                         
136         new_pic->defMaxRAMaddrs = maxram;
137         new_pic->bankMask = bankmsk;
138         new_pic->hasSecondConfigReg = confsiz > 1;
139         
140         new_pic->programMemSize = program;
141         new_pic->dataMemSize = data;
142         new_pic->eepromMemSize = eeprom;
143         new_pic->ioPins = io;
144
145         new_pic->ram = rangeRAM;
146         
147         Pics[num_of_supported_PICS] = new_pic;
148         num_of_supported_PICS++;
149                         
150         return new_pic;
151 }
152
153
154 /* mark some registers as being duplicated across banks */
155 static void register_map(int num_words, char word[SPLIT_WORDS_MAX][PIC14_STRING_LEN])
156 {
157         memRange r;
158         int pcount;
159         
160         if (num_words < 3) {
161                 fprintf(stderr, "WARNING: not enough values in %s regmap directive\n", DEVICE_FILE_NAME);
162                 return;
163         }
164         
165         r.alias = parse_config_value(word[1]);
166
167         for (pcount = 2; pcount < num_words; pcount++) {
168             
169                 r.start_address = parse_config_value(word[pcount]);
170                 r.end_address = parse_config_value(word[pcount]);
171                 r.bank = (r.start_address >> 7) & 3;
172                 
173                 addMemRange(&r, 1);
174         }
175 }
176
177
178 /* define ram areas - may be duplicated across banks */
179 static void ram_map(int num_words, char word[SPLIT_WORDS_MAX][PIC14_STRING_LEN])
180 {
181         memRange *r;
182         
183         if (num_words < 4) {
184                 fprintf(stderr, "WARNING: not enough values in %s memmap directive\n", DEVICE_FILE_NAME);
185                 return;
186         }
187
188         r = Safe_calloc(1, sizeof(memRange));
189         //fprintf (stderr, "%s: %s %s %s\n", __FUNCTION__, word[1], word[2], word[3]);
190         
191         r->start_address = parse_config_value(word[1]);
192         r->end_address = parse_config_value(word[2]);
193         r->alias = parse_config_value(word[3]);
194         r->bank = (r->start_address >> 7) & 3;
195                 
196         addMemRange(r, 0);
197
198         // add memRange to device entry for future lookup (sharebanks)
199         r->next = rangeRAM;
200         rangeRAM = r;
201 }
202
203 extern set *includeDirsSet;
204 extern set *userIncDirsSet;
205 extern set *libDirsSet;
206 extern set *libPathsSet;
207
208 /* read the file with all the pic14 definitions and pick out the definition for a processor
209  * if specified. if pic_name is NULL reads everything */
210 static PIC_device *find_device(char *pic_name)
211 {
212         FILE *pic_file;
213         char pic_buf[PIC14_STRING_LEN];
214         char *pic_buf_pos;
215         int found_processor = FALSE;
216         int done = FALSE;
217         char processor_name[SPLIT_WORDS_MAX][PIC14_STRING_LEN];
218         int num_processor_names = 0;
219         int pic_maxram = 0;
220         int pic_bankmsk = 0;
221         int pic_confsiz = 0;
222         int pic_program = 0;
223         int pic_data = 0;
224         int pic_eeprom = 0;
225         int pic_io = 0;
226         char *simple_pic_name;
227         char *dir;
228         char filename[512];
229         int len = 512;
230         
231         /* allow abbreviations of the form "f877" - convert to "16f877" */
232         simple_pic_name = sanitise_processor_name(pic_name);
233         num_of_supported_PICS = 0;
234         
235         /* open the piclist file */
236         /* first scan all include directories */
237         pic_file = NULL;
238         //fprintf( stderr, "%s: searching %s\n", __FUNCTION__, DEVICE_FILE_NAME );
239         for (dir = setFirstItem(includeDirsSet);
240                 !pic_file && dir;
241                 dir = setNextItem(includeDirsSet))
242         {
243           //fprintf( stderr, "searching1 %s\n", dir );
244           SNPRINTF(&filename[0], len, "%s%s%s", dir, DIR_SEPARATOR_STRING, DEVICE_FILE_NAME);
245           pic_file = fopen( filename, "rt" );
246           if (pic_file) break;
247         } // for
248         for (dir = setFirstItem(userIncDirsSet);
249                 !pic_file && dir;
250                 dir = setNextItem(userIncDirsSet))
251         {
252           //fprintf( stderr, "searching2 %s\n", dir );
253           SNPRINTF(&filename[0], len, "%s%s%s", dir, DIR_SEPARATOR_STRING, DEVICE_FILE_NAME);
254           pic_file = fopen( filename, "rt" );
255           if (pic_file) break;
256         } // for
257         for (dir = setFirstItem(libDirsSet);
258                 !pic_file && dir;
259                 dir = setNextItem(libDirsSet))
260         {
261           //fprintf( stderr, "searching3 %s\n", dir );
262           SNPRINTF(&filename[0], len, "%s%s%s", dir, DIR_SEPARATOR_STRING, DEVICE_FILE_NAME);
263           pic_file = fopen( filename, "rt" );
264           if (pic_file) break;
265         } // for
266         for (dir = setFirstItem(libPathsSet);
267                 !pic_file && dir;
268                 dir = setNextItem(libPathsSet))
269         {
270           //fprintf( stderr, "searching4 %s\n", dir );
271           SNPRINTF(&filename[0], len, "%s%s%s", dir, DIR_SEPARATOR_STRING, DEVICE_FILE_NAME);
272           pic_file = fopen( filename, "rt" );
273           if (pic_file) break;
274         } // for
275         if (!pic_file) {
276           pic_file = fopen(DATADIR LIB_DIR_SUFFIX DIR_SEPARATOR_STRING "pic" DIR_SEPARATOR_STRING DEVICE_FILE_NAME, "rt");
277         }
278         if (pic_file == NULL) {
279                 /* this second attempt is used when initially building the libraries */
280                 pic_file = fopen(".." DIR_SEPARATOR_STRING ".." DIR_SEPARATOR_STRING ".." DIR_SEPARATOR_STRING ".." 
281                                 DIR_SEPARATOR_STRING "src" DIR_SEPARATOR_STRING "pic" DIR_SEPARATOR_STRING 
282                                 DEVICE_FILE_NAME, "rt");
283                 if (pic_file == NULL) {
284                         fprintf(stderr, "can't find %s\n", DATADIR LIB_DIR_SUFFIX DIR_SEPARATOR_STRING "pic" 
285                                         DIR_SEPARATOR_STRING DEVICE_FILE_NAME);
286                         return NULL;
287                 }
288         }
289         
290         /* read line by line */
291         pic_buf[sizeof(pic_buf)-1] = '\0';
292         while (fgets(pic_buf, sizeof(pic_buf)-1, pic_file) != NULL && !done) {
293                 
294                 /* remove trailing spaces */
295                 while (isspace(pic_buf[strlen(pic_buf)-1]))
296                         pic_buf[strlen(pic_buf)-1] = '\0';
297                 
298                 /* remove leading spaces */
299                 for (pic_buf_pos = pic_buf; isspace(*pic_buf_pos); pic_buf_pos++)
300                 {}
301                 
302                 /* ignore comment / empty lines */
303                 if (*pic_buf_pos != '\0' && *pic_buf_pos != '#') {
304                         
305                         /* split into fields */
306                         char pic_word[SPLIT_WORDS_MAX][PIC14_STRING_LEN];
307                         int num_pic_words;
308                         int wcount;
309                         
310                         num_pic_words = split_words(pic_word, pic_buf_pos);
311                         
312                         if (STRCASECMP(pic_word[0], "processor") == 0) {
313                         
314                                 if (pic_name == NULL) {
315                                         /* this is the mode where we read all the processors in - store the names for now */
316                                         if (num_processor_names > 0) {
317                                                 /* store away all the previous processor definitions */
318                                                 int dcount;
319                                                 
320                                                 for (dcount = 1; dcount < num_processor_names; dcount++)
321                                                         create_pic(processor_name[dcount], pic_maxram, pic_bankmsk,
322                                                                    pic_confsiz, pic_program, pic_data, pic_eeprom, pic_io);
323                                         }
324                                         
325                                         num_processor_names = split_words(processor_name, pic_buf_pos);
326                                 }
327                                 else {
328                                         /* if we've just completed reading a processor definition stop now */
329                                         if (found_processor)
330                                                 done = TRUE;
331                                         else {
332                                                 /* check if this processor name is a match */
333                                                 for (wcount = 1; wcount < num_pic_words; wcount++) {
334                                                         
335                                                         /* skip uninteresting prefixes */
336                                                         char *found_name = sanitise_processor_name(pic_word[wcount]);
337
338                                                         if (STRCASECMP(found_name, simple_pic_name) == 0)
339                                                                 found_processor = TRUE;
340                                                 }
341                                         }
342                                 }
343                         }
344                         
345                         else {
346                                 if (found_processor || pic_name == NULL) {
347                                         /* only parse a processor section if we've found the one we want */
348                                         if (STRCASECMP(pic_word[0], "maxram") == 0 && num_pic_words > 1) {
349                                                 pic_maxram = parse_config_value(pic_word[1]);
350                                                 setMaxRAM(pic_maxram);
351                                         }
352                                         else if (STRCASECMP(pic_word[0], "bankmsk") == 0 && num_pic_words > 1)
353                                                 pic_bankmsk = parse_config_value(pic_word[1]);
354                         
355                                         else if (STRCASECMP(pic_word[0], "confsiz") == 0 && num_pic_words > 1)
356                                                 pic_confsiz = parse_config_value(pic_word[1]);
357                         
358                                         else if (STRCASECMP(pic_word[0], "program") == 0 && num_pic_words > 1)
359                                                 pic_program = parse_config_value(pic_word[1]);
360                         
361                                         else if (STRCASECMP(pic_word[0], "data") == 0 && num_pic_words > 1)
362                                                 pic_data = parse_config_value(pic_word[1]);
363                         
364                                         else if (STRCASECMP(pic_word[0], "eeprom") == 0 && num_pic_words > 1)
365                                                 pic_eeprom = parse_config_value(pic_word[1]);
366                         
367                                         else if (STRCASECMP(pic_word[0], "io") == 0 && num_pic_words > 1)
368                                                 pic_io = parse_config_value(pic_word[1]);
369                         
370                                         else if (STRCASECMP(pic_word[0], "regmap") == 0 && num_pic_words > 2) {
371                                                 if (found_processor)
372                                                         register_map(num_pic_words, pic_word);
373                                         }
374                                         else if (STRCASECMP(pic_word[0], "memmap") == 0 && num_pic_words > 2) {
375                                                 if (found_processor)
376                                                         ram_map(num_pic_words, pic_word);
377                                         }
378                                         else {
379                                                 fprintf(stderr, "WARNING: %s: bad syntax `%s'\n", DEVICE_FILE_NAME, pic_word[0]);
380                                         }
381                                 }
382                         }
383                 }
384         }
385         
386         fclose(pic_file);
387
388         /* if we're in read-the-lot mode then create the final processor definition */
389         if (pic_name == NULL) {
390             
391                 if (num_processor_names > 0) {
392                         /* store away all the previous processor definitions */
393                         int dcount;
394                 
395                         for (dcount = 1; dcount < num_processor_names; dcount++)
396                                 create_pic(processor_name[dcount], pic_maxram, pic_bankmsk,
397                                            pic_confsiz, pic_program, pic_data, pic_eeprom, pic_io);
398                 }
399         }
400         else {
401                 /* in search mode */
402                 if (found_processor) {
403                         /* create a new pic entry */
404                         return create_pic(pic_name, pic_maxram, pic_bankmsk,
405                                           pic_confsiz, pic_program, pic_data, pic_eeprom, pic_io);
406                 }
407         }
408         
409         return NULL;
410 }
411
412 void addMemRange(memRange *r, int type)
413 {
414         int i;
415         int alias = r->alias;
416
417         //fprintf (stderr, "%s: range %x..%x, alias %x, bank %x\n", __FUNCTION__, r->start_address, r->end_address, r->alias, r->bank);
418         
419         if (maxRAMaddress < 0) {
420                 fprintf(stderr, "missing maxram setting in %s\n", DEVICE_FILE_NAME);
421                 return;
422         }
423         
424         do {
425                 for (i=r->start_address; i<= r->end_address; i++) {
426                         if ((i|alias) <= maxRAMaddress) {
427                                 /* if we haven't seen this address before, enter it */
428                                 if (!finalMapping[i | alias].isValid) {
429                                 finalMapping[i | alias].isValid = 1;
430                                 finalMapping[i | alias].alias = r->alias;
431                                 finalMapping[i | alias].bank  = r->bank;
432                                 if(type) {
433                                         /* hack for now */
434                                         finalMapping[i | alias].isSFR  = 1;
435                                 } else {
436                                         finalMapping[i | alias].isSFR  = 0;
437                                 }
438                                 }
439                         } else {
440                                 if (getenv("SDCCPICDEBUG")) {
441                                         fprintf(stderr, "WARNING: %s:%s memory at 0x%x is beyond max ram = 0x%x\n",
442                                                 __FILE__,__FUNCTION__,(i|alias), maxRAMaddress);
443                                 }
444                         }
445                 }
446                 
447                 /* Decrement alias */
448                 if (alias) {
449                         alias -= ((alias & (alias - 1)) ^ alias);
450                 } else {
451                         alias--;
452                 }
453                 
454         } while (alias >= 0);
455 }
456
457 void setMaxRAM(int size)
458 {
459         int i;
460         maxRAMaddress = size;
461         
462         if (maxRAMaddress < 0) {
463                 fprintf(stderr, "invalid maxram 0x%x setting in %s\n",
464                         maxRAMaddress, DEVICE_FILE_NAME);
465                 return;
466         }
467         
468         finalMapping = Safe_calloc(1+maxRAMaddress,
469                 sizeof(AssignedMemory));
470         
471         /* Now initialize the finalMapping array */
472         
473         for(i=0; i<=maxRAMaddress; i++) {
474                 finalMapping[i].reg = NULL;
475                 finalMapping[i].isValid = 0;
476                 finalMapping[i].bank = (i>>7);
477         }
478 }
479
480 /*-----------------------------------------------------------------*
481 *-----------------------------------------------------------------*/
482
483 int isREGinBank(regs *reg, int bank)
484 {
485         
486         if(!reg || !pic)
487                 return 0;
488         
489         if((int)((reg->address | reg->alias) & pic->bankMask & bank) == bank)
490                 return 1;
491         
492         return 0;
493 }
494
495 /*-----------------------------------------------------------------*
496 *-----------------------------------------------------------------*/
497 int REGallBanks(regs *reg)
498 {
499         
500         if(!reg || !pic)
501                 return 0;
502         
503         return ((reg->address | reg->alias) & pic->bankMask);
504         
505 }
506
507 /*-----------------------------------------------------------------*
508 *-----------------------------------------------------------------*/
509
510 int isSFR(int address)
511 {
512         
513         if( (address > maxRAMaddress) || !finalMapping[address].isSFR)
514                 return 0;
515         
516         return 1;
517         
518 }
519
520 /*
521 *  dump_map -- debug stuff
522 */
523
524 void dump_map(void)
525 {
526         int i;
527         
528         for(i=0; i<=maxRAMaddress; i++) {
529                 //fprintf(stdout , "addr 0x%02x is %s\n", i, ((finalMapping[i].isValid) ? "valid":"invalid"));
530                 
531                 if(finalMapping[i].isValid) {
532                         fprintf(stderr,"addr: 0x%02x",i);
533                         if(finalMapping[i].isSFR)
534                                 fprintf(stderr," isSFR");
535                         if(finalMapping[i].reg) 
536                                 fprintf( stderr, "  reg %s", finalMapping[i].reg->name);
537                         fprintf(stderr, "\n");
538                 }
539         }
540         
541 }
542
543 void dump_sfr(FILE *of)
544 {
545 #if 0
546         int start=-1;
547         int bank_base;
548         static int udata_flag=0;
549 #endif
550         int addr=0;
551         
552         //dump_map();   /* display the register map */
553         //fprintf(stdout,";dump_sfr  \n");
554         if (maxRAMaddress < 0) {
555                 fprintf(stderr, "missing maxram setting in %s\n", DEVICE_FILE_NAME);
556                 return;
557         }
558         
559         for (addr = 0; addr <= maxRAMaddress; addr++)
560         {
561                 regs *reg = finalMapping[addr].reg;
562                 
563                 if (reg && !reg->isEmitted)
564                 {
565                   emitSymbolToFile (of, reg->name, "udata", reg->size, reg->isFixed ? reg->address : -1, 0, 0);
566                   
567                   reg->isEmitted = 1;
568                 }
569         } // for
570
571 #if 0
572         do {
573
574                 if(finalMapping[addr].reg && !finalMapping[addr].reg->isEmitted) {
575                         
576                         if(start<0)
577                                 start = addr;
578                 } else {
579                         if(start>=0) {
580                                 
581                                 /* clear the lower 7-bits of the start address of the first
582                                 * variable declared in this bank. The upper bits for the mid
583                                 * range pics are the bank select bits.
584                                 */
585                                 
586                                 bank_base = start & 0xfff8;
587                                 
588                                 /* The bank number printed in the cblock comment tacitly
589                                 * assumes that the first register in the contiguous group
590                                 * of registers represents the bank for the whole group */
591                                 
592                                 if ( (start != addr) && (!udata_flag) ) {
593                                         udata_flag = 1;
594                                         //fprintf(of,"\tudata\n");
595                                 }
596                                 
597                                 for( ; start < addr; start++) {
598                                         if((finalMapping[start].reg) && 
599                                                 (!finalMapping[start].reg->isEmitted) &&
600                                                 (!finalMapping[start].instance) && 
601                                                 (!finalMapping[start].isSFR)) {
602                                                 
603                                                 if (finalMapping[start].reg->isFixed) {
604                                                         unsigned i;
605                                                         for (i=0; i<finalMapping[start].reg->size; i++) {
606                                                                 fprintf(of,"%s\tEQU\t0x%04x\n",
607                                                                         finalMapping[start].reg->name, 
608                                                                         finalMapping[start].reg->address+i);
609                                                         }
610                                                 } else {
611                                                         emitSymbolToFile (of, finalMapping[start].reg->name, finalMapping[start].reg->size);
612 #if 0
613                                                         fprintf(of,"%s\tres\t%i\n",
614                                                                 finalMapping[start].reg->name, 
615                                                                 finalMapping[start].reg->size);
616 #endif
617                                                 }
618                                                 finalMapping[start].reg->isEmitted = 1;
619                                         }
620                                 }
621                                 
622                                 start = -1;
623                         }
624                         
625                 }
626                 
627                 addr++;
628                 
629         } while(addr <= maxRAMaddress);
630
631
632 #endif
633 }
634
635 /*-----------------------------------------------------------------*
636 *  void list_valid_pics(int ncols, int list_alias)
637 *
638 * Print out a formatted list of valid PIC devices
639 *
640 * ncols - number of columns in the list.
641 *
642 * list_alias - if non-zero, print all of the supported aliases
643 *              for a device (e.g. F84, 16F84, etc...)
644 *-----------------------------------------------------------------*/
645 void list_valid_pics(int ncols)
646 {
647         int col=0,longest;
648         int i,k,l;
649         
650         if (num_of_supported_PICS == 0)
651                 find_device(NULL);          /* load all the definitions */
652         
653         /* decrement the column number if it's greater than zero */
654         ncols = (ncols > 1) ? ncols-1 : 4;
655         
656         /* Find the device with the longest name */
657         for(i=0,longest=0; i<num_of_supported_PICS; i++) {
658                 k = strlen(Pics[i]->name);
659                 if(k>longest)
660                         longest = k;
661         }
662         
663 #if 1
664         /* heading */
665         fprintf(stderr, "\nPIC14 processors and their characteristics:\n\n");
666         fprintf(stderr, " processor");
667         for(k=0; k<longest-1; k++)
668                 fputc(' ',stderr);
669         fprintf(stderr, "program     RAM      EEPROM    I/O\n");
670         fprintf(stderr, "-----------------------------------------------------\n");
671         
672         for(i=0;  i < num_of_supported_PICS; i++) {
673                 fprintf(stderr,"  %s", Pics[i]->name);
674                 l = longest + 2 - strlen(Pics[i]->name);
675                 for(k=0; k<l; k++)
676                         fputc(' ',stderr);
677         
678                 fprintf(stderr, "     ");
679                 if (Pics[i]->programMemSize % 1024 == 0)
680                         fprintf(stderr, "%4dK", Pics[i]->programMemSize / 1024);
681                 else
682                         fprintf(stderr, "%5d", Pics[i]->programMemSize);
683         
684                 fprintf(stderr, "     %5d     %5d     %4d\n", 
685                         Pics[i]->dataMemSize, Pics[i]->eepromMemSize, Pics[i]->ioPins);
686         }
687
688         col = 0;
689         
690         fprintf(stderr, "\nPIC14 processors supported:\n");
691         for(i=0;  i < num_of_supported_PICS; i++) {
692                         
693                 fprintf(stderr,"%s", Pics[i]->name);
694                 if(col<ncols) {
695                         l = longest + 2 - strlen(Pics[i]->name);
696                         for(k=0; k<l; k++)
697                                 fputc(' ',stderr);
698                                 
699                         col++;
700                                 
701                 } else {
702                         fputc('\n',stderr);
703                         col = 0;
704                 }
705                 
706         }
707 #endif
708         if(col != 0)
709                 fputc('\n',stderr);
710 }
711
712 /*-----------------------------------------------------------------*
713 *  
714 *-----------------------------------------------------------------*/
715 PIC_device *init_pic(char *pic_type)
716 {
717         char long_name[PIC14_STRING_LEN];
718         
719         pic = find_device(pic_type);
720         
721         if (pic == NULL) {
722                 /* check for shortened "16xxx" form */
723                 sprintf(long_name, "16%s", pic_type);
724                 pic = find_device(long_name);
725                 if (pic == NULL) {
726                         if(pic_type != NULL && pic_type[0] != '\0')
727                                 fprintf(stderr, "'%s' was not found.\n", pic_type);
728                         else
729                                 fprintf(stderr, "No processor has been specified (use -pPROCESSOR_NAME)\n");
730                 
731                         list_valid_pics(7);
732                         exit(1);
733                 }
734         }
735         return pic;
736 }
737
738 /*-----------------------------------------------------------------*
739 *  
740 *-----------------------------------------------------------------*/
741 int picIsInitialized(void)
742 {
743         if(pic && maxRAMaddress > 0)
744                 return 1;
745         
746         return 0;
747         
748 }
749
750 /*-----------------------------------------------------------------*
751 *  char *processor_base_name(void) - Include file is derived from this.
752 *-----------------------------------------------------------------*/
753 char *processor_base_name(void)
754 {
755         
756         if(!pic)
757                 return NULL;
758         
759         return pic->name;
760 }
761
762 /*-----------------------------------------------------------------*
763 *-----------------------------------------------------------------*/
764 int validAddress(int address, int reg_size)
765 {
766         int i;
767         
768         if (maxRAMaddress < 0) {
769                 fprintf(stderr, "missing maxram setting in %s\n", DEVICE_FILE_NAME);
770                 return 0;
771         }
772         //  fprintf(stderr, "validAddress: Checking 0x%04x\n",address);
773         assert (reg_size > 0);
774         if(address + (reg_size - 1) > maxRAMaddress)
775                 return 0;
776         
777         for (i=0; i<reg_size; i++)
778                 if(!finalMapping[address + i].isValid || 
779                         finalMapping[address+i].reg ||
780                         finalMapping[address+i].isSFR )
781                         return 0;
782                 
783                 return 1;
784 }
785
786 /*-----------------------------------------------------------------*
787 *-----------------------------------------------------------------*/
788 void mapRegister(regs *reg)
789 {
790         
791         unsigned i;
792         int alias;
793         
794         if(!reg || !reg->size) {
795                 fprintf(stderr,"WARNING: %s:%s:%d Bad register\n",__FILE__,__FUNCTION__,__LINE__);
796                 return;
797         }
798         
799         if (maxRAMaddress < 0) {
800                 fprintf(stderr, "missing maxram setting in %s\n", DEVICE_FILE_NAME);
801                 return;
802         }
803         
804         for(i=0; i<reg->size; i++) {
805                 
806                 assert(reg->address >= 0 && reg->address < maxRAMaddress);
807                 
808                 alias = finalMapping[reg->address].alias;
809                 reg->alias = alias;
810                 
811                 do {
812                         
813                         //fprintf(stdout,"mapping %s to address 0x%02x, reg size = %d\n",reg->name, (reg->address+alias+i),reg->size);
814                         
815                         finalMapping[reg->address + alias + i].reg = reg;
816                         finalMapping[reg->address + alias + i].instance = i;
817                         
818                         /* Decrement alias */
819                         if(alias)
820                                 alias -= ((alias & (alias - 1)) ^ alias);
821                         else
822                                 alias--;
823                         
824                 } while (alias>=0);
825         }
826         
827         //fprintf(stderr,"%s - %s addr = 0x%03x, size %d\n",__FUNCTION__,reg->name, reg->address,reg->size);
828         
829         reg->isMapped = 1;
830         
831 }
832
833 /*-----------------------------------------------------------------*
834 *-----------------------------------------------------------------*/
835 int assignRegister(regs *reg, int start_address)
836 {
837         int i;
838         
839         //fprintf(stderr,"%s -  %s start_address = 0x%03x\n",__FUNCTION__,reg->name, start_address);
840         if(reg->isFixed) {
841                 
842                 if (validAddress(reg->address,reg->size)) {
843                         //fprintf(stderr,"%s -  %s address = 0x%03x\n",__FUNCTION__,reg->name, reg->address);
844                         mapRegister(reg);
845                         return reg->address;
846                 }
847                 
848                 if( isSFR(reg->address)) {
849                         mapRegister(reg);
850                         return reg->address;
851                 }
852                 
853                 if (getenv("SDCCPICDEBUG")) {
854                         fprintf(stderr, "WARNING: Ignoring Out of Range register assignment at fixed address %d, %s\n",
855                             reg->address, reg->name);
856                 }
857                 
858         } else {
859                 
860         /* This register does not have a fixed address requirement
861         * so we'll search through all availble ram address and
862                 * assign the first one */
863                 
864                 for (i=start_address; i<=maxRAMaddress; i++) {
865                         
866                         if (validAddress(i,reg->size)) {
867                                 reg->address = i;
868                                 mapRegister(reg);
869                                 return i;
870                         }
871                 }
872                 
873                 fprintf(stderr, "WARNING: No more RAM available for %s\n",reg->name);
874                 
875         }
876         
877         return -1;
878 }
879
880 /*-----------------------------------------------------------------*
881 *-----------------------------------------------------------------*/
882 void assignFixedRegisters(set *regset)
883 {
884         regs *reg;
885         
886         for (reg = setFirstItem(regset) ; reg ; 
887         reg = setNextItem(regset)) {
888                 
889                 if(reg->isFixed) 
890                         assignRegister(reg,0);
891         }
892         
893 }
894
895 /*-----------------------------------------------------------------*
896 *-----------------------------------------------------------------*/
897 void assignRelocatableRegisters(set *regset, int used)
898 {
899         
900         regs *reg;
901         int address = 0;
902         
903         for (reg = setFirstItem(regset) ; reg ; 
904         reg = setNextItem(regset)) {
905                 
906                 //fprintf(stdout,"assigning %s (%d) isFixed=%d, wasUsed=%d\n",reg->name,reg->size,reg->isFixed,reg->wasUsed);
907                 
908                 if((!reg->isExtern) && (!reg->isFixed) && ( used || reg->wasUsed)) {
909                         /* If register have been reused then shall not print it a second time. */
910                         set *s;
911                         int done = 0;
912                         for (s = regset; s; s = s->next) {
913                                 regs *r;
914                                 r = s->item;
915                                 if (r == reg)
916                                         break;
917                                 if((!r->isFixed) && ( used || r->wasUsed)) {
918                                         if (r->rIdx == reg->rIdx) {
919                                                 reg->address = r->address;
920                                                 done = 1;
921                                                 break;
922                                         }
923                                 }
924                         }
925                         if (!done)
926                                 address = assignRegister(reg,address);
927                 }
928         }
929         
930 }
931
932 /* Keep track of whether we found an assignment to the __config words. */
933 static int pic14_hasSetConfigWord = 0;
934
935 /*-----------------------------------------------------------------*
936  *  void assignConfigWordValue(int address, int value)
937  *
938  * Most midrange PICs have one config word at address 0x2007.
939  * Newer PIC14s have a second config word at address 0x2008.
940  * This routine will assign values to those addresses.
941  *
942  *-----------------------------------------------------------------*/
943
944 void pic14_assignConfigWordValue(int address, int value)
945 {
946         if (CONFIG_WORD_ADDRESS == address)
947                 config_word = value;
948         
949         else if (CONFIG2_WORD_ADDRESS == address)
950                 config2_word = value;
951         
952         //fprintf(stderr,"setting config word 0x%x to 0x%x\n", address, value);
953         pic14_hasSetConfigWord = 1;
954 }
955
956 /*-----------------------------------------------------------------*
957  * int pic14_emitConfigWord (FILE * vFile)
958  * 
959  * Emit the __config directives iff we found a previous assignment
960  * to the config word.
961  *-----------------------------------------------------------------*/
962 extern char *iComments2;
963 int pic14_emitConfigWord (FILE * vFile)
964 {
965   if (pic14_hasSetConfigWord)
966   {
967     fprintf (vFile, "%s", iComments2);
968     fprintf (vFile, "; config word \n");
969     fprintf (vFile, "%s", iComments2);
970     if (pic14_getHasSecondConfigReg())
971     {
972       fprintf (vFile, "\t__config _CONFIG1, 0x%x\n", pic14_getConfigWord(0x2007));
973       fprintf (vFile, "\t__config _CONFIG2, 0x%x\n", pic14_getConfigWord(0x2008));
974     }
975     else
976       fprintf (vFile, "\t__config 0x%x\n", pic14_getConfigWord(0x2007));
977
978     return 1;
979   }
980   return 0;
981 }
982
983 /*-----------------------------------------------------------------*
984  * int pic14_getConfigWord(int address)
985  *
986  * Get the current value of a config word.
987  *
988  *-----------------------------------------------------------------*/
989
990 int pic14_getConfigWord(int address)
991 {
992         switch (address)
993         {
994         case CONFIG_WORD_ADDRESS:
995                 return config_word;
996         
997         case CONFIG2_WORD_ADDRESS:
998                 return config2_word;
999         
1000         default:
1001                 return 0;
1002         }
1003 }
1004
1005 /*-----------------------------------------------------------------*
1006 *  
1007 *-----------------------------------------------------------------*/
1008 unsigned pic14_getMaxRam(void)
1009 {
1010         return pic->defMaxRAMaddrs;
1011 }
1012
1013
1014 /*-----------------------------------------------------------------*
1015 *  int getHasSecondConfigReg(void) - check if the device has a 
1016 *  second config register, rather than just one.
1017 *-----------------------------------------------------------------*/
1018 int pic14_getHasSecondConfigReg(void)
1019 {
1020         if(!pic)
1021                 return 0;
1022         else
1023                 return pic->hasSecondConfigReg;
1024 }
1025
1026 /*-----------------------------------------------------------------*
1027  * True iff the device has memory aliased in every bank.
1028  * If true, low and high will be set to the low and high address
1029  * occupied by the (last) sharebank found.
1030  *-----------------------------------------------------------------*/
1031 int pic14_hasSharebank(int *low, int *high, int *size)
1032 {
1033         memRange *r;
1034
1035         assert(pic);
1036         r = pic->ram;
1037
1038         while (r) {
1039             //fprintf (stderr, "%s: region %x..%x, bank %x, alias %x, pic->bankmask %x\n",  __FUNCTION__, r->start_address, r->end_address, r->bank, r->alias, pic->bankMask);
1040             if (r->alias == pic->bankMask) {
1041                 if (low) *low = r->start_address;
1042                 if (high) *high = r->end_address;
1043                 if (size) *size = r->end_address - r->start_address + 1;
1044                 return 1;
1045             } // if
1046             r = r->next;
1047         } // while
1048
1049         if (low) *low = 0x0;
1050         if (high) *high = 0x0;
1051         if (size) *size = 0x0;
1052         //fprintf (stderr, "%s: no shared bank found\n", __FUNCTION__);
1053         return 0;
1054 }
1055
1056 /*
1057  * True iff the memory region [low, high] is aliased in all banks.
1058  */
1059 int pic14_isShared(int low, int high)
1060 {
1061         memRange *r;
1062
1063         assert(pic);
1064         r = pic->ram;
1065
1066         while (r) {
1067             //fprintf (stderr, "%s: region %x..%x, bank %x, alias %x, pic->bankmask %x\n", __FUNCTION__, r->start_address, r->end_address, r->bank, r->alias, pic->bankMask);
1068             if ((r->alias == pic->bankMask) && (r->start_address <= low) && (r->end_address >= high)) {
1069                 return 1;
1070             } // if
1071             r = r->next;
1072         } // while
1073
1074         return 0;
1075 }
1076
1077 /*
1078  * True iff all RAM is aliased in all banks (no BANKSELs required except for
1079  * SFRs).
1080  */
1081 int pic14_allRAMShared(void)
1082 {
1083         memRange *r;
1084
1085         assert(pic);
1086         r = pic->ram;
1087
1088         while (r) {
1089             if (r->alias != pic->bankMask) return 0;
1090             r = r->next;
1091         } // while
1092         
1093         return 1;
1094 }
1095
1096 /*
1097  * True iff the pseudo stack is a sharebank --> let linker place it.
1098  * [low, high] denotes a size byte long block of (shared or banked)
1099  * memory to be used.
1100  */
1101 int pic14_getSharedStack(int *low, int *high, int *size)
1102 {
1103     int haveShared;
1104     int l, h, s;
1105
1106     haveShared = pic14_hasSharebank(&l, &h, &s);
1107     if ((options.stack_loc != 0) || !haveShared)
1108     {
1109         // sharebank not available or not to be used
1110         s = options.stack_size ? options.stack_size : 0x10;
1111         l = options.stack_loc ? options.stack_loc : 0x20;
1112         h = (options.stack_loc ? options.stack_loc : 0x20) + s  - 1;
1113         if (low) *low = l;
1114         if (high) *high = h;
1115         if (size) *size = s;
1116         // return 1 iff [low, high] is present in all banks
1117         //fprintf(stderr, "%s: low %x, high %x, size %x, shared %d\n", __FUNCTION__, l, h, s, pic14_isShared(l, h));
1118         return (pic14_isShared(l, h));
1119     } else {
1120         // sharebanks available for use by the stack
1121         if (options.stack_size) s = options.stack_size;
1122         else if (!s || s > 16) s = 16; // limit stack to 16 bytes in SHAREBANK
1123
1124         // provide addresses for sharebank
1125         if (low) *low = l;
1126         if (high) *high = l + s - 1;
1127         if (size) *size = s;
1128         //fprintf(stderr, "%s: low %x, high %x, size %x, shared 1\n", __FUNCTION__, l, h, s);
1129         return 1;
1130     }
1131 }
1132
1133 PIC_device * pic14_getPIC(void)
1134 {
1135     return pic;
1136 }