b20b01d5a62a89a52c409e604bf72aa8af849f24
[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
53 #define CONFIG_WORD_ADDRESS 0x2007
54 #define CONFIG2_WORD_ADDRESS 0x2008
55 #define DEFAULT_CONFIG_WORD 0x3fff
56 #define DEFAULT_CONFIG2_WORD 0x3ffc
57
58 #define DEVICE_FILE_NAME "pic14devices.txt"
59 #define PIC14_STRING_LEN 256
60 #define SPLIT_WORDS_MAX 16
61
62 static unsigned int config_word = DEFAULT_CONFIG_WORD;
63 static unsigned int config2_word = DEFAULT_CONFIG2_WORD;
64 static memRange *rangeRAM = NULL;
65
66
67 /* parse a value from the configuration file */
68 static int parse_config_value(char *str)
69 {
70         if (str[strlen(str) - 1] == 'K')
71                 return atoi(str) * 1024;        /* like "1K" */
72                 
73         else if (STRNCASECMP(str, "0x", 2) == 0)
74                 return strtol(str+2, NULL, 16); /* like "0x400" */
75         
76         else
77                 return atoi(str);               /* like "1024" */
78 }
79
80
81 /* split a line into words */
82 static int split_words(char result_word[SPLIT_WORDS_MAX][PIC14_STRING_LEN], char *str)
83 {
84         char *pos = str;
85         int num_words = 0;
86         int ccount;
87         
88         while (*pos != '\0' && num_words < SPLIT_WORDS_MAX) {
89                 /* remove leading spaces */
90                 while (isspace(*pos) || *pos == ',')
91                         pos++;
92         
93                 /* copy everything up until the first space or comma */
94                 for (ccount = 0; *pos != '\0' && !isspace(*pos) && *pos != ',' && ccount < PIC14_STRING_LEN-1; ccount++, pos++)
95                         result_word[num_words][ccount] = *pos;
96                 result_word[num_words][ccount] = '\0';
97                 
98                 num_words++;
99         }
100         
101         return num_words;
102 }
103
104
105 /* remove annoying prefixes from the processor name */
106 static char *sanitise_processor_name(char *name)
107 {
108         char *proc_pos = name;
109
110         if (name == NULL)
111                 return NULL;
112         
113         if (STRNCASECMP(proc_pos, "pic", 3) == 0)
114                 proc_pos += 3;
115
116         else if (tolower(*proc_pos) == 'p')
117                 proc_pos += 1;
118                                 
119         return proc_pos;
120 }
121
122
123 /* create a structure for a pic processor */
124 static PIC_device *create_pic(char *pic_name, int maxram, int bankmsk, int confsiz, int program, int data, int eeprom, int io)
125 {
126         PIC_device *new_pic;
127         char *simple_pic_name = sanitise_processor_name(pic_name);
128         
129         new_pic = Safe_calloc(1, sizeof(PIC_device));
130         new_pic->name = Safe_calloc(strlen(simple_pic_name)+1, sizeof(char));
131         strcpy(new_pic->name, simple_pic_name);
132                         
133         new_pic->defMaxRAMaddrs = maxram;
134         new_pic->bankMask = bankmsk;
135         new_pic->hasSecondConfigReg = confsiz > 1;
136         
137         new_pic->programMemSize = program;
138         new_pic->dataMemSize = data;
139         new_pic->eepromMemSize = eeprom;
140         new_pic->ioPins = io;
141
142         new_pic->ram = rangeRAM;
143         
144         Pics[num_of_supported_PICS] = new_pic;
145         num_of_supported_PICS++;
146                         
147         return new_pic;
148 }
149
150
151 /* mark some registers as being duplicated across banks */
152 static void register_map(int num_words, char word[SPLIT_WORDS_MAX][PIC14_STRING_LEN])
153 {
154         memRange *r;
155         int pcount;
156         
157         if (num_words < 3) {
158                 fprintf(stderr, "WARNING: not enough values in %s regmap directive\n", DEVICE_FILE_NAME);
159                 return;
160         }
161
162         for (pcount = 2; pcount < num_words; pcount++) {
163                 r = Safe_calloc(1, sizeof(memRange));
164                 
165                 r->start_address = parse_config_value(word[pcount]);
166                 r->end_address = parse_config_value(word[pcount]);
167                 r->alias = parse_config_value(word[1]);
168                 r->bank = (r->start_address >> 7) & 3;
169                 // add memRange to device entry for future lookup (sharebanks)
170                 r->next = rangeRAM;
171                 rangeRAM = r;
172         }
173 }
174
175
176 /* define ram areas - may be duplicated across banks */
177 static void ram_map(int num_words, char word[SPLIT_WORDS_MAX][PIC14_STRING_LEN])
178 {
179         memRange *r;
180         
181         if (num_words < 4) {
182                 fprintf(stderr, "WARNING: not enough values in %s memmap directive\n", DEVICE_FILE_NAME);
183                 return;
184         }
185
186         r = Safe_calloc(1, sizeof(memRange));
187         //fprintf (stderr, "%s: %s %s %s\n", __FUNCTION__, word[1], word[2], word[3]);
188         
189         r->start_address = parse_config_value(word[1]);
190         r->end_address = parse_config_value(word[2]);
191         r->alias = parse_config_value(word[3]);
192         r->bank = (r->start_address >> 7) & 3;
193                 
194         // add memRange to device entry for future lookup (sharebanks)
195         r->next = rangeRAM;
196         rangeRAM = r;
197 }
198
199 extern set *includeDirsSet;
200 extern set *userIncDirsSet;
201 extern set *libDirsSet;
202 extern set *libPathsSet;
203
204 /* read the file with all the pic14 definitions and pick out the definition for a processor
205  * if specified. if pic_name is NULL reads everything */
206 static PIC_device *find_device(char *pic_name)
207 {
208         FILE *pic_file;
209         char pic_buf[PIC14_STRING_LEN];
210         char *pic_buf_pos;
211         int found_processor = FALSE;
212         int done = FALSE;
213         char processor_name[SPLIT_WORDS_MAX][PIC14_STRING_LEN];
214         int num_processor_names = 0;
215         int pic_maxram = 0;
216         int pic_bankmsk = 0;
217         int pic_confsiz = 0;
218         int pic_program = 0;
219         int pic_data = 0;
220         int pic_eeprom = 0;
221         int pic_io = 0;
222         char *simple_pic_name;
223         char *dir;
224         char filename[512];
225         int len = 512;
226         
227         /* allow abbreviations of the form "f877" - convert to "16f877" */
228         simple_pic_name = sanitise_processor_name(pic_name);
229         num_of_supported_PICS = 0;
230         
231         /* open the piclist file */
232         /* first scan all include directories */
233         pic_file = NULL;
234         //fprintf( stderr, "%s: searching %s\n", __FUNCTION__, DEVICE_FILE_NAME );
235         for (dir = setFirstItem(includeDirsSet);
236                 !pic_file && dir;
237                 dir = setNextItem(includeDirsSet))
238         {
239           //fprintf( stderr, "searching1 %s\n", dir );
240           SNPRINTF(&filename[0], len, "%s%s%s", dir, DIR_SEPARATOR_STRING, DEVICE_FILE_NAME);
241           pic_file = fopen( filename, "rt" );
242           if (pic_file) break;
243         } // for
244         for (dir = setFirstItem(userIncDirsSet);
245                 !pic_file && dir;
246                 dir = setNextItem(userIncDirsSet))
247         {
248           //fprintf( stderr, "searching2 %s\n", dir );
249           SNPRINTF(&filename[0], len, "%s%s%s", dir, DIR_SEPARATOR_STRING, DEVICE_FILE_NAME);
250           pic_file = fopen( filename, "rt" );
251           if (pic_file) break;
252         } // for
253         for (dir = setFirstItem(libDirsSet);
254                 !pic_file && dir;
255                 dir = setNextItem(libDirsSet))
256         {
257           //fprintf( stderr, "searching3 %s\n", dir );
258           SNPRINTF(&filename[0], len, "%s%s%s", dir, DIR_SEPARATOR_STRING, DEVICE_FILE_NAME);
259           pic_file = fopen( filename, "rt" );
260           if (pic_file) break;
261         } // for
262         for (dir = setFirstItem(libPathsSet);
263                 !pic_file && dir;
264                 dir = setNextItem(libPathsSet))
265         {
266           //fprintf( stderr, "searching4 %s\n", dir );
267           SNPRINTF(&filename[0], len, "%s%s%s", dir, DIR_SEPARATOR_STRING, DEVICE_FILE_NAME);
268           pic_file = fopen( filename, "rt" );
269           if (pic_file) break;
270         } // for
271         if (!pic_file) {
272           pic_file = fopen(DATADIR LIB_DIR_SUFFIX DIR_SEPARATOR_STRING "pic" DIR_SEPARATOR_STRING DEVICE_FILE_NAME, "rt");
273         }
274         if (pic_file == NULL) {
275                 /* this second attempt is used when initially building the libraries */
276                 pic_file = fopen(".." DIR_SEPARATOR_STRING ".." DIR_SEPARATOR_STRING ".." DIR_SEPARATOR_STRING ".." 
277                                 DIR_SEPARATOR_STRING "src" DIR_SEPARATOR_STRING "pic" DIR_SEPARATOR_STRING 
278                                 DEVICE_FILE_NAME, "rt");
279                 if (pic_file == NULL) {
280                         fprintf(stderr, "can't find %s\n", DATADIR LIB_DIR_SUFFIX DIR_SEPARATOR_STRING "pic" 
281                                         DIR_SEPARATOR_STRING DEVICE_FILE_NAME);
282                         return NULL;
283                 }
284         }
285         
286         /* read line by line */
287         pic_buf[sizeof(pic_buf)-1] = '\0';
288         while (fgets(pic_buf, sizeof(pic_buf)-1, pic_file) != NULL && !done) {
289                 
290                 /* remove trailing spaces */
291                 while (isspace(pic_buf[strlen(pic_buf)-1]))
292                         pic_buf[strlen(pic_buf)-1] = '\0';
293                 
294                 /* remove leading spaces */
295                 for (pic_buf_pos = pic_buf; isspace(*pic_buf_pos); pic_buf_pos++)
296                 {}
297                 
298                 /* ignore comment / empty lines */
299                 if (*pic_buf_pos != '\0' && *pic_buf_pos != '#') {
300                         
301                         /* split into fields */
302                         char pic_word[SPLIT_WORDS_MAX][PIC14_STRING_LEN];
303                         int num_pic_words;
304                         int wcount;
305                         
306                         num_pic_words = split_words(pic_word, pic_buf_pos);
307                         
308                         if (STRCASECMP(pic_word[0], "processor") == 0) {
309                         
310                                 if (pic_name == NULL) {
311                                         /* this is the mode where we read all the processors in - store the names for now */
312                                         if (num_processor_names > 0) {
313                                                 /* store away all the previous processor definitions */
314                                                 int dcount;
315                                                 
316                                                 for (dcount = 1; dcount < num_processor_names; dcount++)
317                                                         create_pic(processor_name[dcount], pic_maxram, pic_bankmsk,
318                                                                    pic_confsiz, pic_program, pic_data, pic_eeprom, pic_io);
319                                         }
320                                         
321                                         num_processor_names = split_words(processor_name, pic_buf_pos);
322                                 }
323                                 else {
324                                         /* if we've just completed reading a processor definition stop now */
325                                         if (found_processor)
326                                                 done = TRUE;
327                                         else {
328                                                 /* check if this processor name is a match */
329                                                 for (wcount = 1; wcount < num_pic_words; wcount++) {
330                                                         
331                                                         /* skip uninteresting prefixes */
332                                                         char *found_name = sanitise_processor_name(pic_word[wcount]);
333
334                                                         if (STRCASECMP(found_name, simple_pic_name) == 0)
335                                                                 found_processor = TRUE;
336                                                 }
337                                         }
338                                 }
339                         }
340                         
341                         else {
342                                 if (found_processor || pic_name == NULL) {
343                                         /* only parse a processor section if we've found the one we want */
344                                         if (STRCASECMP(pic_word[0], "maxram") == 0 && num_pic_words > 1) {
345                                                 pic_maxram = parse_config_value(pic_word[1]);
346                                                 setMaxRAM(pic_maxram);
347                                         }
348                                         else if (STRCASECMP(pic_word[0], "bankmsk") == 0 && num_pic_words > 1)
349                                                 pic_bankmsk = parse_config_value(pic_word[1]);
350                         
351                                         else if (STRCASECMP(pic_word[0], "confsiz") == 0 && num_pic_words > 1)
352                                                 pic_confsiz = parse_config_value(pic_word[1]);
353                         
354                                         else if (STRCASECMP(pic_word[0], "program") == 0 && num_pic_words > 1)
355                                                 pic_program = parse_config_value(pic_word[1]);
356                         
357                                         else if (STRCASECMP(pic_word[0], "data") == 0 && num_pic_words > 1)
358                                                 pic_data = parse_config_value(pic_word[1]);
359                         
360                                         else if (STRCASECMP(pic_word[0], "eeprom") == 0 && num_pic_words > 1)
361                                                 pic_eeprom = parse_config_value(pic_word[1]);
362                         
363                                         else if (STRCASECMP(pic_word[0], "io") == 0 && num_pic_words > 1)
364                                                 pic_io = parse_config_value(pic_word[1]);
365                         
366                                         else if (STRCASECMP(pic_word[0], "regmap") == 0 && num_pic_words > 2) {
367                                                 if (found_processor)
368                                                         register_map(num_pic_words, pic_word);
369                                         }
370                                         else if (STRCASECMP(pic_word[0], "memmap") == 0 && num_pic_words > 2) {
371                                                 if (found_processor)
372                                                         ram_map(num_pic_words, pic_word);
373                                         }
374                                         else {
375                                                 fprintf(stderr, "WARNING: %s: bad syntax `%s'\n", DEVICE_FILE_NAME, pic_word[0]);
376                                         }
377                                 }
378                         }
379                 }
380         }
381         
382         fclose(pic_file);
383
384         /* if we're in read-the-lot mode then create the final processor definition */
385         if (pic_name == NULL) {
386             
387                 if (num_processor_names > 0) {
388                         /* store away all the previous processor definitions */
389                         int dcount;
390                 
391                         for (dcount = 1; dcount < num_processor_names; dcount++)
392                                 create_pic(processor_name[dcount], pic_maxram, pic_bankmsk,
393                                            pic_confsiz, pic_program, pic_data, pic_eeprom, pic_io);
394                 }
395         }
396         else {
397                 /* in search mode */
398                 if (found_processor) {
399                         /* create a new pic entry */
400                         return create_pic(pic_name, pic_maxram, pic_bankmsk,
401                                           pic_confsiz, pic_program, pic_data, pic_eeprom, pic_io);
402                 }
403         }
404         
405         return NULL;
406 }
407
408 void setMaxRAM(int size)
409 {
410         maxRAMaddress = size;
411         
412         if (maxRAMaddress < 0) {
413                 fprintf(stderr, "invalid maxram 0x%x setting in %s\n",
414                         maxRAMaddress, DEVICE_FILE_NAME);
415                 return;
416         }
417 }
418
419 /*-----------------------------------------------------------------*
420 *-----------------------------------------------------------------*/
421
422 int isREGinBank(regs *reg, int bank)
423 {
424         
425         if(!reg || !pic)
426                 return 0;
427         
428         if((int)((reg->address | reg->alias) & pic->bankMask & bank) == bank)
429                 return 1;
430         
431         return 0;
432 }
433
434 /*-----------------------------------------------------------------*
435 *-----------------------------------------------------------------*/
436 int REGallBanks(regs *reg)
437 {
438         
439         if(!reg || !pic)
440                 return 0;
441         
442         return ((reg->address | reg->alias) & pic->bankMask);
443         
444 }
445
446 /*-----------------------------------------------------------------*
447  *  void list_valid_pics(int ncols, int list_alias)
448  *
449  * Print out a formatted list of valid PIC devices
450  *
451  * ncols - number of columns in the list.
452  *
453  * list_alias - if non-zero, print all of the supported aliases
454  *              for a device (e.g. F84, 16F84, etc...)
455  *-----------------------------------------------------------------*/
456 void list_valid_pics(int ncols)
457 {
458         int col=0,longest;
459         int i,k,l;
460         
461         if (num_of_supported_PICS == 0)
462                 find_device(NULL);          /* load all the definitions */
463         
464         /* decrement the column number if it's greater than zero */
465         ncols = (ncols > 1) ? ncols-1 : 4;
466         
467         /* Find the device with the longest name */
468         for(i=0,longest=0; i<num_of_supported_PICS; i++) {
469                 k = strlen(Pics[i]->name);
470                 if(k>longest)
471                         longest = k;
472         }
473         
474 #if 1
475         /* heading */
476         fprintf(stderr, "\nPIC14 processors and their characteristics:\n\n");
477         fprintf(stderr, " processor");
478         for(k=0; k<longest-1; k++)
479                 fputc(' ',stderr);
480         fprintf(stderr, "program     RAM      EEPROM    I/O\n");
481         fprintf(stderr, "-----------------------------------------------------\n");
482         
483         for(i=0;  i < num_of_supported_PICS; i++) {
484                 fprintf(stderr,"  %s", Pics[i]->name);
485                 l = longest + 2 - strlen(Pics[i]->name);
486                 for(k=0; k<l; k++)
487                         fputc(' ',stderr);
488         
489                 fprintf(stderr, "     ");
490                 if (Pics[i]->programMemSize % 1024 == 0)
491                         fprintf(stderr, "%4dK", Pics[i]->programMemSize / 1024);
492                 else
493                         fprintf(stderr, "%5d", Pics[i]->programMemSize);
494         
495                 fprintf(stderr, "     %5d     %5d     %4d\n", 
496                         Pics[i]->dataMemSize, Pics[i]->eepromMemSize, Pics[i]->ioPins);
497         }
498
499         col = 0;
500         
501         fprintf(stderr, "\nPIC14 processors supported:\n");
502         for(i=0;  i < num_of_supported_PICS; i++) {
503                         
504                 fprintf(stderr,"%s", Pics[i]->name);
505                 if(col<ncols) {
506                         l = longest + 2 - strlen(Pics[i]->name);
507                         for(k=0; k<l; k++)
508                                 fputc(' ',stderr);
509                                 
510                         col++;
511                                 
512                 } else {
513                         fputc('\n',stderr);
514                         col = 0;
515                 }
516                 
517         }
518 #endif
519         if(col != 0)
520                 fputc('\n',stderr);
521 }
522
523 /*-----------------------------------------------------------------*
524 *  
525 *-----------------------------------------------------------------*/
526 PIC_device *init_pic(char *pic_type)
527 {
528         char long_name[PIC14_STRING_LEN];
529         
530         pic = find_device(pic_type);
531         
532         if (pic == NULL) {
533                 /* check for shortened "16xxx" form */
534                 sprintf(long_name, "16%s", pic_type);
535                 pic = find_device(long_name);
536                 if (pic == NULL) {
537                         if(pic_type != NULL && pic_type[0] != '\0')
538                                 fprintf(stderr, "'%s' was not found.\n", pic_type);
539                         else
540                                 fprintf(stderr, "No processor has been specified (use -pPROCESSOR_NAME)\n");
541                 
542                         list_valid_pics(7);
543                         exit(1);
544                 }
545         }
546         return pic;
547 }
548
549 /*-----------------------------------------------------------------*
550 *  
551 *-----------------------------------------------------------------*/
552 int picIsInitialized(void)
553 {
554         if(pic && maxRAMaddress > 0)
555                 return 1;
556         
557         return 0;
558         
559 }
560
561 /*-----------------------------------------------------------------*
562 *  char *processor_base_name(void) - Include file is derived from this.
563 *-----------------------------------------------------------------*/
564 char *processor_base_name(void)
565 {
566         
567         if(!pic)
568                 return NULL;
569         
570         return pic->name;
571 }
572
573 /*-----------------------------------------------------------------*
574 *-----------------------------------------------------------------*/
575 int validAddress(int address, int reg_size)
576 {
577         if (maxRAMaddress < 0) {
578                 fprintf(stderr, "missing maxram setting in %s\n", DEVICE_FILE_NAME);
579                 return 0;
580         }
581         //  fprintf(stderr, "validAddress: Checking 0x%04x\n",address);
582         assert (reg_size > 0);
583         if(address + (reg_size - 1) > maxRAMaddress)
584                 return 0;
585         
586         return 1;
587 }
588
589 #if 0
590 /* The following code should be (and is) implemented in the linker. */
591
592 /*-----------------------------------------------------------------*
593 *-----------------------------------------------------------------*/
594 void mapRegister(regs *reg)
595 {
596         
597         unsigned i;
598         int alias;
599         
600         if(!reg || !reg->size) {
601                 fprintf(stderr,"WARNING: %s:%s:%d Bad register\n",__FILE__,__FUNCTION__,__LINE__);
602                 return;
603         }
604         
605         if (maxRAMaddress < 0) {
606                 fprintf(stderr, "missing maxram setting in %s\n", DEVICE_FILE_NAME);
607                 return;
608         }
609         
610         for(i=0; i<reg->size; i++) {
611                 
612                 assert(reg->address >= 0 && reg->address < maxRAMaddress);
613                 
614                 alias = finalMapping[reg->address].alias;
615                 reg->alias = alias;
616                 
617                 do {
618                         
619                         //fprintf(stdout,"mapping %s to address 0x%02x, reg size = %d\n",reg->name, (reg->address+alias+i),reg->size);
620                         
621                         finalMapping[reg->address + alias + i].reg = reg;
622                         finalMapping[reg->address + alias + i].instance = i;
623                         
624                         /* Decrement alias */
625                         if(alias)
626                                 alias -= ((alias & (alias - 1)) ^ alias);
627                         else
628                                 alias--;
629                         
630                 } while (alias>=0);
631         }
632         
633         //fprintf(stderr,"%s - %s addr = 0x%03x, size %d\n",__FUNCTION__,reg->name, reg->address,reg->size);
634         
635         reg->isMapped = 1;
636         
637 }
638
639 /*-----------------------------------------------------------------*
640 *-----------------------------------------------------------------*/
641 int assignRegister(regs *reg, int start_address)
642 {
643         int i;
644         
645         //fprintf(stderr,"%s -  %s start_address = 0x%03x\n",__FUNCTION__,reg->name, start_address);
646         if(reg->isFixed) {
647                 
648                 if (validAddress(reg->address,reg->size)) {
649                         //fprintf(stderr,"%s -  %s address = 0x%03x\n",__FUNCTION__,reg->name, reg->address);
650                         mapRegister(reg);
651                         return reg->address;
652                 }
653                 
654                 if (getenv("SDCCPICDEBUG")) {
655                         fprintf(stderr, "WARNING: Ignoring Out of Range register assignment at fixed address %d, %s\n",
656                             reg->address, reg->name);
657                 }
658                 
659         } else {
660                 
661         /* This register does not have a fixed address requirement
662         * so we'll search through all availble ram address and
663                 * assign the first one */
664                 
665                 for (i=start_address; i<=maxRAMaddress; i++) {
666                         
667                         if (validAddress(i,reg->size)) {
668                                 reg->address = i;
669                                 mapRegister(reg);
670                                 return i;
671                         }
672                 }
673                 
674                 fprintf(stderr, "WARNING: No more RAM available for %s\n",reg->name);
675                 
676         }
677         
678         return -1;
679 }
680
681 /*-----------------------------------------------------------------*
682 *-----------------------------------------------------------------*/
683 void assignFixedRegisters(set *regset)
684 {
685         regs *reg;
686         
687         for (reg = setFirstItem(regset) ; reg ; 
688         reg = setNextItem(regset)) {
689                 
690                 if(reg->isFixed) 
691                         assignRegister(reg,0);
692         }
693         
694 }
695
696 /*-----------------------------------------------------------------*
697 *-----------------------------------------------------------------*/
698 void assignRelocatableRegisters(set *regset, int used)
699 {
700         
701         regs *reg;
702         int address = 0;
703         
704         for (reg = setFirstItem(regset) ; reg ; 
705         reg = setNextItem(regset)) {
706                 
707                 //fprintf(stdout,"assigning %s (%d) isFixed=%d, wasUsed=%d\n",reg->name,reg->size,reg->isFixed,reg->wasUsed);
708                 
709                 if((!reg->isExtern) && (!reg->isFixed) && ( used || reg->wasUsed)) {
710                         /* If register have been reused then shall not print it a second time. */
711                         set *s;
712                         int done = 0;
713                         for (s = regset; s; s = s->next) {
714                                 regs *r;
715                                 r = s->item;
716                                 if (r == reg)
717                                         break;
718                                 if((!r->isFixed) && ( used || r->wasUsed)) {
719                                         if (r->rIdx == reg->rIdx) {
720                                                 reg->address = r->address;
721                                                 done = 1;
722                                                 break;
723                                         }
724                                 }
725                         }
726                         if (!done)
727                                 address = assignRegister(reg,address);
728                 }
729         }
730         
731 }
732 #endif
733
734 /* Keep track of whether we found an assignment to the __config words. */
735 static int pic14_hasSetConfigWord = 0;
736
737 /*-----------------------------------------------------------------*
738  *  void assignConfigWordValue(int address, int value)
739  *
740  * Most midrange PICs have one config word at address 0x2007.
741  * Newer PIC14s have a second config word at address 0x2008.
742  * This routine will assign values to those addresses.
743  *
744  *-----------------------------------------------------------------*/
745
746 void pic14_assignConfigWordValue(int address, int value)
747 {
748         if (CONFIG_WORD_ADDRESS == address)
749                 config_word = value;
750         
751         else if (CONFIG2_WORD_ADDRESS == address)
752                 config2_word = value;
753         
754         //fprintf(stderr,"setting config word 0x%x to 0x%x\n", address, value);
755         pic14_hasSetConfigWord = 1;
756 }
757
758 /*-----------------------------------------------------------------*
759  * int pic14_emitConfigWord (FILE * vFile)
760  * 
761  * Emit the __config directives iff we found a previous assignment
762  * to the config word.
763  *-----------------------------------------------------------------*/
764 extern char *iComments2;
765 int pic14_emitConfigWord (FILE * vFile)
766 {
767   if (pic14_hasSetConfigWord)
768   {
769     fprintf (vFile, "%s", iComments2);
770     fprintf (vFile, "; config word \n");
771     fprintf (vFile, "%s", iComments2);
772     if (pic14_getHasSecondConfigReg())
773     {
774       fprintf (vFile, "\t__config _CONFIG1, 0x%x\n", pic14_getConfigWord(0x2007));
775       fprintf (vFile, "\t__config _CONFIG2, 0x%x\n", pic14_getConfigWord(0x2008));
776     }
777     else
778       fprintf (vFile, "\t__config 0x%x\n", pic14_getConfigWord(0x2007));
779
780     return 1;
781   }
782   return 0;
783 }
784
785 /*-----------------------------------------------------------------*
786  * int pic14_getConfigWord(int address)
787  *
788  * Get the current value of a config word.
789  *
790  *-----------------------------------------------------------------*/
791
792 int pic14_getConfigWord(int address)
793 {
794         switch (address)
795         {
796         case CONFIG_WORD_ADDRESS:
797                 return config_word;
798         
799         case CONFIG2_WORD_ADDRESS:
800                 return config2_word;
801         
802         default:
803                 return 0;
804         }
805 }
806
807 /*-----------------------------------------------------------------*
808 *  
809 *-----------------------------------------------------------------*/
810 unsigned pic14_getMaxRam(void)
811 {
812         return pic->defMaxRAMaddrs;
813 }
814
815
816 /*-----------------------------------------------------------------*
817 *  int getHasSecondConfigReg(void) - check if the device has a 
818 *  second config register, rather than just one.
819 *-----------------------------------------------------------------*/
820 int pic14_getHasSecondConfigReg(void)
821 {
822         if(!pic)
823                 return 0;
824         else
825                 return pic->hasSecondConfigReg;
826 }
827
828 /*-----------------------------------------------------------------*
829  * True iff the device has memory aliased in every bank.
830  * If true, low and high will be set to the low and high address
831  * occupied by the (last) sharebank found.
832  *-----------------------------------------------------------------*/
833 int pic14_hasSharebank(int *low, int *high, int *size)
834 {
835         memRange *r;
836
837         assert(pic);
838         r = pic->ram;
839
840         while (r) {
841             //fprintf (stderr, "%s: region %x..%x, bank %x, alias %x, pic->bankmask %x, min_size %d\n",  __FUNCTION__, r->start_address, r->end_address, r->bank, r->alias, pic->bankMask, size ? *size : 0);
842             // find sufficiently large shared region
843             if ((r->alias == pic->bankMask)
844                     && (r->end_address != r->start_address) // ignore SFRs
845                     && (!size || (*size <= (r->end_address - r->start_address + 1))))
846             {
847                 if (low) *low = r->start_address;
848                 if (high) *high = r->end_address;
849                 if (size) *size = r->end_address - r->start_address + 1;
850                 return 1;
851             } // if
852             r = r->next;
853         } // while
854
855         if (low) *low = 0x0;
856         if (high) *high = 0x0;
857         if (size) *size = 0x0;
858         //fprintf (stderr, "%s: no shared bank found\n", __FUNCTION__);
859         return 0;
860 }
861
862 /*
863  * True iff the memory region [low, high] is aliased in all banks.
864  */
865 int pic14_isShared(int low, int high)
866 {
867         memRange *r;
868
869         assert(pic);
870         r = pic->ram;
871
872         while (r) {
873             //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);
874             if ((r->alias == pic->bankMask) && (r->start_address <= low) && (r->end_address >= high)) {
875                 return 1;
876             } // if
877             r = r->next;
878         } // while
879
880         return 0;
881 }
882
883 /*
884  * True iff all RAM is aliased in all banks (no BANKSELs required except for
885  * SFRs).
886  */
887 int pic14_allRAMShared(void)
888 {
889         memRange *r;
890
891         assert(pic);
892         r = pic->ram;
893
894         while (r) {
895             if (r->alias != pic->bankMask) return 0;
896             r = r->next;
897         } // while
898         
899         return 1;
900 }
901
902 /*
903  * True iff the pseudo stack is a sharebank --> let linker place it.
904  * [low, high] denotes a size byte long block of (shared or banked)
905  * memory to be used.
906  */
907 int pic14_getSharedStack(int *low, int *high, int *size)
908 {
909     int haveShared;
910     int l, h, s;
911
912     s = options.stack_size ? options.stack_size : 0x10;
913     haveShared = pic14_hasSharebank(&l, &h, &s);
914     if ((options.stack_loc != 0) || !haveShared)
915     {
916         // sharebank not available or not to be used
917         s = options.stack_size ? options.stack_size : 0x10;
918         l = options.stack_loc ? options.stack_loc : 0x20;
919         h = l + s - 1;
920         if (low) *low = l;
921         if (high) *high = h;
922         if (size) *size = s;
923         // return 1 iff [low, high] is present in all banks
924         //fprintf(stderr, "%s: low %x, high %x, size %x, shared %d\n", __FUNCTION__, l, h, s, pic14_isShared(l, h));
925         return (pic14_isShared(l, h));
926     } else {
927         // sharebanks available for use by the stack
928         if (options.stack_size) s = options.stack_size;
929         else if (!s || s > 16) s = 16; // limit stack to 16 bytes in SHAREBANK
930
931         // provide addresses for sharebank
932         if (low) *low = l;
933         if (high) *high = l + s - 1;
934         if (size) *size = s;
935         //fprintf(stderr, "%s: low %x, high %x, size %x, shared 1\n", __FUNCTION__, l, h, s);
936         return 1;
937     }
938 }
939
940 PIC_device * pic14_getPIC(void)
941 {
942     return pic;
943 }