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