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