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