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