* src/pic16/device.c (pic16_dump_section): fixed a bug that allowed
[fw/sdcc] / src / pic16 / device.c
1 /*-------------------------------------------------------------------------
2
3   device.c - Accomodates subtle variations in PIC16 devices
4
5    Written By -  Scott Dattalo scott@dattalo.com
6    Ported to PIC16 By -  Martin Dubuc m.dubuc@rogers.com
7
8    This program is free software; you can redistribute it and/or modify it
9    under the terms of the GNU General Public License as published by the
10    Free Software Foundation; either version 2, or (at your option) any
11    later version.
12    
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17    
18    You should have received a copy of the GNU General Public License
19    along with this program; if not, write to the Free Software
20    Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21 -------------------------------------------------------------------------*/
22
23
24 /*
25         VR - Began writing code to make PIC16 C source files independent from
26         the header file (created by the inc2h.pl)
27
28         - adding maximum RAM memory into PIC_Device structure
29
30 */
31
32 #include <stdio.h>
33
34 #include "common.h"   // Include everything in the SDCC src directory
35 #include "newalloc.h"
36
37
38 #include "pcode.h"
39 #include "ralloc.h"
40 #include "device.h"
41
42
43 static PIC16_device Pics16[] = {
44   {
45     {"p18f242", "18f242", "pic18f242", "f242"},         // aliases
46     0,
47     0x300,                                              // bank mask
48     0x300,                                              // RAMsize
49     0
50   },
51
52   {
53     {"p18f252", "18f252", "pic18f252", "f252"},         // aliases
54     0,
55     0x600,                                              // bank mask
56     0x600,                                              // RAMsize
57     0
58   },
59
60   {
61     {"p18f442", "18f442", "pic18f442", "f442"},         // aliases
62     0,
63     0x300,                                              // bank mask
64     0x300,                                              // RAMsize
65     0
66   },
67
68   {
69     {"p18f452", "18f452", "pic18f452", "f452"},         // aliases
70     0,
71     0x600,                                              // bank mask
72     0x600,                                              // RAMsize
73     0
74   },
75
76   {
77     {"p18f248", "18f248", "pic18f248", "f248"},         // aliases
78     0,
79     0x300,                                              // bank mask
80     0x300,                                              // RAMsize
81     0
82   },
83
84   {
85     {"p18f258", "18f258", "pic18f258", "f258"},         // aliases
86     0,
87     0x600,                                              // bank mask
88     0x600,                                              // RAMsize
89     0
90   },
91
92   {
93     {"p18f448", "18f448", "pic18f448", "f448"},         // aliases
94     0,
95     0x300,                                              // bank mask
96     0x300,                                              // RAMsize
97     0
98   },
99
100   {
101     {"p18f458", "18f458", "pic18f458", "f458"},         // aliases
102     0,
103     0x600,                                              // bank mask
104     0x600,                                              // RAMsize
105     0
106   },
107
108   {
109     {"p18f6520", "18f6520", "pic18f6520", "f6520"},     // aliases
110     0,
111     0x800,                                              // bank mask
112     0x800,                                              // RAMsize
113     1
114   },
115
116   {
117     {"p18f6620", "18f6620", "pic18f6620", "f6620"},     // aliases
118     0,
119     0xf00,                                              // bank mask
120     0xf00,                                              // RAMsize
121     1
122   },
123   {
124     {"p18f6680", "18f6680", "pic18f6680", "f6680"},     // aliases
125     0,
126     0xc00,                                              // bank mask
127     0xc00,                                              // RAMsize
128     1
129   },
130   {
131     {"p18f6720", "18f6720", "pic18f6720", "f6720"},     // aliases
132     0,
133     0xf00,                                              // bank mask
134     0xf00,                                              // RAMsize
135     1
136   },
137   {
138     {"p18f8520", "18f8520", "pic18f8520", "f8520"},     // aliases
139     0,
140     0x800,                                              // bank mask
141     0x800,                                              // RAMsize
142     1
143   },
144   {
145     {"p18f8620", "18f8620", "pic18f8620", "f8620"},     // aliases
146     0,
147     0xf00,                                              // bank mask
148     0xf00,                                              // RAMsize
149     1
150   },
151   {
152     {"p18f8680", "18f8680", "pic18f8680", "f8680"},     // aliases
153     0,
154     0xc00,                                              // bank mask
155     0x800,                                              // RAMsize
156     1
157   },
158   {
159     {"p18f8720", "18f8720", "pic18f8720", "f8720"},     // aliases
160     0,
161     0xf00,                                              // bank mask
162     0xf00,                                              // RAMsize
163     1
164   },
165
166 };
167
168 static int num_of_supported_PICS = sizeof(Pics16)/sizeof(PIC16_device);
169
170 #define DEFAULT_PIC "452"
171
172 PIC16_device *pic16=NULL;
173
174 #define DEFAULT_CONFIG_BYTE 0xff
175
176 #define CONFIG1H_WORD_ADDRESS 0x300001
177 #define DEFAULT_CONFIG1H_WORD DEFAULT_CONFIG_BYTE
178
179 #define CONFIG2L_WORD_ADDRESS 0x300002
180 #define DEFAULT_CONFIG2L_WORD DEFAULT_CONFIG_BYTE
181
182 #define CONFIG2H_WORD_ADDRESS 0x300003
183 #define DEFAULT_CONFIG2H_WORD DEFAULT_CONFIG_BYTE
184
185 #define CONFIG3H_WORD_ADDRESS 0x300005
186 #define DEFAULT_CONFIG3H_WORD DEFAULT_CONFIG_BYTE
187
188 #define CONFIG4L_WORD_ADDRESS 0x300006
189 #define DEFAULT_CONFIG4L_WORD DEFAULT_CONFIG_BYTE
190
191 #define CONFIG5L_WORD_ADDRESS 0x300008
192 #define DEFAULT_CONFIG5L_WORD DEFAULT_CONFIG_BYTE
193
194 #define CONFIG5H_WORD_ADDRESS 0x300009
195 #define DEFAULT_CONFIG5H_WORD DEFAULT_CONFIG_BYTE
196
197 #define CONFIG6L_WORD_ADDRESS 0x30000a
198 #define DEFAULT_CONFIG6L_WORD DEFAULT_CONFIG_BYTE
199
200 #define CONFIG6H_WORD_ADDRESS 0x30000b
201 #define DEFAULT_CONFIG6H_WORD DEFAULT_CONFIG_BYTE
202
203 #define CONFIG7L_WORD_ADDRESS 0x30000c
204 #define DEFAULT_CONFIG7L_WORD DEFAULT_CONFIG_BYTE
205
206 #define CONFIG7H_WORD_ADDRESS 0x30000d
207 #define DEFAULT_CONFIG7H_WORD DEFAULT_CONFIG_BYTE
208
209 static unsigned int config1h_word = DEFAULT_CONFIG1H_WORD;
210 static unsigned int config2l_word = DEFAULT_CONFIG2L_WORD;
211 static unsigned int config2h_word = DEFAULT_CONFIG2H_WORD;
212 static unsigned int config3h_word = DEFAULT_CONFIG3H_WORD;
213 static unsigned int config4l_word = DEFAULT_CONFIG4L_WORD;
214 static unsigned int config5l_word = DEFAULT_CONFIG5L_WORD;
215 static unsigned int config5h_word = DEFAULT_CONFIG5H_WORD;
216 static unsigned int config6l_word = DEFAULT_CONFIG6L_WORD;
217 static unsigned int config6h_word = DEFAULT_CONFIG6H_WORD;
218 static unsigned int config7l_word = DEFAULT_CONFIG7L_WORD;
219 static unsigned int config7h_word = DEFAULT_CONFIG7H_WORD;
220
221 unsigned int stackPos = 0;
222
223 extern regs* newReg(short type, short pc_type, int rIdx, char *name, int size, int alias, operand *refop);
224
225 void pic16_setMaxRAM(int size)
226 {
227         pic16->maxRAMaddress = size;
228         stackPos = pic16->RAMsize-1;
229
230         if (pic16->maxRAMaddress < 0) {
231                 fprintf(stderr, "invalid \"#pragma maxram 0x%x\" setting\n",
232                         pic16->maxRAMaddress);
233           return;
234         }
235 }
236
237 extern char *iComments2;
238
239 void pic16_dump_equates(FILE *of, set *equs)
240 {
241   regs *r;
242
243         r = setFirstItem(equs);
244         if(!r)return;
245         
246         fprintf(of, "%s", iComments2);
247         fprintf(of, ";\tEquates to used internal registers\n");
248         fprintf(of, "%s", iComments2);
249         
250         for(; r; r = setNextItem(equs)) {
251                 fprintf(of, "%s\tequ\t0x%02x\n", r->name, r->address);
252         }
253 }
254
255
256 int regCompare(const void *a, const void *b)
257 {
258   const regs *const *i = a;
259   const regs *const *j = b;
260
261         /* sort primarily by the address */
262         if( (*i)->address > (*j)->address)return 1;
263         if( (*i)->address < (*j)->address)return -1;
264         
265         /* and secondarily by size */
266         if( (*i)->size > (*j)->size)return 1;
267         if( (*i)->size < (*j)->size)return -1;
268
269
270   return 0;
271 }
272
273 void pic16_dump_section(FILE *of, set *section, int fix)
274 {
275   static int abs_section_no=0;
276   regs *r, *rprev;
277   int init_addr, i;
278   regs **rlist;
279
280         /* put all symbols in an array */
281         rlist = Safe_calloc(elementsInSet(section), sizeof(regs *));
282         r = rlist[0]; i = 0;
283         for(rprev = setFirstItem(section); rprev; rprev = setNextItem(section)) {
284                 rlist[i] = rprev; i++;
285         }
286         
287         if(!i) {
288                 if(rlist)free(rlist);
289           return;
290         }
291
292         /* sort symbols according to their address */
293         qsort(rlist, i  /*elementsInSet(section)*/, sizeof(regs *), regCompare);
294         
295         if(!fix) {
296                 fprintf(of, "\n\n\tudata\n");
297                 for(r = setFirstItem(section); r; r = setNextItem(section)) {
298                         fprintf(of, "%s\tres\t%d\n", r->name, r->size);
299                 }
300         } else {
301           int j=0;
302                   
303                 rprev = NULL;
304                 init_addr = rlist[j]->address;
305                 fprintf(of, "\n\nstatic_%s_%02d\tudata\t0X%04X\n", moduleName, abs_section_no++, init_addr);
306         
307                 for(j=0;j<i;j++) {
308                         r = rlist[j];
309                         init_addr = r->address;
310                         if(rprev && (init_addr != (rprev->address + rprev->size))) {
311                                 fprintf(of, "\nstatic_%s_%02d\tudata\t0X%04X\n", moduleName, abs_section_no++, init_addr);
312                         }
313
314                         fprintf(of, "%s\tres\t%d\n", r->name, r->size);
315                         rprev = r;
316                 }
317         }
318         free(rlist);
319 }
320
321 void pic16_dump_int_registers(FILE *of, set *section)
322 {
323   regs *r, *rprev;
324   int i;
325   regs **rlist;
326
327         /* put all symbols in an array */
328         rlist = Safe_calloc(elementsInSet(section), sizeof(regs *));
329         r = rlist[0]; i = 0;
330         for(rprev = setFirstItem(section); rprev; rprev = setNextItem(section)) {
331                 rlist[i] = rprev; i++;
332         }
333
334         /* sort symbols according to their address */
335         qsort(rlist, elementsInSet(section), sizeof(regs *), regCompare);
336         
337         if(!i) {
338                 if(rlist)free(rlist);
339           return;
340         }
341         
342         fprintf(of, "\n\n; Internal registers\n");
343         
344         fprintf(of, "%s\tudata_ovr\t0x0000\n", ".registers");
345         for(r = setFirstItem(section); r; r = setNextItem(section))
346                 fprintf(of, "%s\tres\t%d\n", r->name, r->size);
347
348         free(rlist);
349 }
350
351
352 #ifdef WORDS_BIGENDIAN
353   #define _ENDIAN(x)  (3-x)
354 #else
355   #define _ENDIAN(x)  (x)
356 #endif
357
358 #define BYTE_IN_LONG(x,b) ((x>>(8*_ENDIAN(b)))&0xff)
359
360 /*-----------------------------------------------------------------*/
361 /* printIvalType - generates ival for int/char                     */
362 /*-----------------------------------------------------------------*/
363 void print_idataType (FILE *of, symbol *sym, sym_link * type, initList * ilist)
364 {
365   value *val;
366   unsigned long ulval;
367
368   //fprintf(stderr, "%s\n",__FUNCTION__);
369
370   /* if initList is deep */
371   if (ilist->type == INIT_DEEP)
372     ilist = ilist->init.deep;
373
374   if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
375     werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
376   }
377
378   if (!(val = list2val (ilist))) {
379     // assuming a warning has been thrown
380     val=constVal("0");
381   }
382
383   if (val->type != type) {
384     val = valCastLiteral(type, floatFromVal(val));
385   }
386
387   if(val) 
388     ulval = (unsigned long) floatFromVal (val);
389   else
390     ulval =0;
391
392   switch (getSize (type)) {
393     case 1:
394         fprintf(of, "%s\tdata\t0x%02x\n", sym->name, (unsigned char)BYTE_IN_LONG(ulval, 0));
395 //      pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
396         break;
397
398     case 2:
399 //      fprintf(of, "%s\tdw\t0x%04x\n", sym->name, (unsigned int)(BYTE_IN_LONG(ulval, 0)
400 //                                      + (BYTE_IN_LONG(ulval, 1) << 8)));
401         fprintf(of, "%s\tdata\t0x%02x,0x%02x\n", sym->name, (unsigned char)BYTE_IN_LONG(ulval, 0),
402                                         (unsigned char)(BYTE_IN_LONG(ulval, 1) << 8));
403 //      pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
404 //      pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
405         break;
406
407     case 4:
408         fprintf(of, "%s\tdw\t0x%04x,0x%04x\n", sym->name, (unsigned int)(BYTE_IN_LONG(ulval, 0)
409                                         + (BYTE_IN_LONG(ulval, 1) << 8)),
410                                         (unsigned)(BYTE_IN_LONG(ulval, 2)
411                                         + (BYTE_IN_LONG(ulval, 3) << 8)));
412 //      pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
413 //      pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
414 //      pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
415 //      pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETLW,pic16_newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
416         break;
417   }
418 }
419
420
421
422 /*-----------------------------------------------------------------*/
423 /* printIval - generates code for initial value                    */
424 /*-----------------------------------------------------------------*/
425 void print_idata(FILE *of, symbol * sym, sym_link * type, initList * ilist)
426 {
427   if (!ilist)
428     return;
429
430   /* if structure then    */
431   if (IS_STRUCT (type))
432     {
433       //fprintf(stderr,"%s struct\n",__FUNCTION__);
434       //printIvalStruct (sym, type, ilist, oFile);
435       return;
436     }
437
438   /* if this is a pointer */
439   if (IS_PTR (type))
440     {
441       //fprintf(stderr,"%s pointer\n",__FUNCTION__);
442       //printIvalPtr (sym, type, ilist, oFile);
443       return;
444     }
445
446   /* if this is an array   */
447   if (IS_ARRAY (type))
448     {
449       //fprintf(stderr,"%s array\n",__FUNCTION__);
450 //      printIvalArray (sym, type, ilist, pb);
451       return;
452     }
453
454   /* if type is SPECIFIER */
455   if (IS_SPEC (type))
456     {
457 //      fprintf(stderr,"%s spec\n",__FUNCTION__);
458       print_idataType(of, sym, type, ilist);
459       return;
460     }
461 }
462
463
464 void pic16_dump_idata(FILE *of, set *idataSymSet)
465 {
466   int i;
467   symbol *ids;
468   
469
470         i = elementsInSet(idataSymSet);
471         if(!i)return;
472         
473         fprintf(of, "\n\n; Initialised data (idata)\n");
474         fprintf(of, "\tidata\n");
475         for(ids = setFirstItem(idataSymSet); ids; ids = setNextItem(idataSymSet))
476               print_idata(of, ids, ids->type, ids->ival);
477
478 }
479
480
481 /*-----------------------------------------------------------------*
482  *  void pic16_list_valid_pics(int ncols, int list_alias)
483  *
484  * Print out a formatted list of valid PIC devices
485  *
486  * ncols - number of columns in the list.
487  *
488  * list_alias - if non-zero, print all of the supported aliases
489  *              for a device (e.g. F84, 16F84, etc...)
490  *-----------------------------------------------------------------*/
491 void pic16_list_valid_pics(int ncols, int list_alias)
492 {
493   int col,longest;
494   int i,j,k,l;
495
496   if(list_alias)
497     list_alias = sizeof(Pics16[0].name) / sizeof(Pics16[0].name[0]);
498
499   /* decrement the column number if it's greater than zero */
500   ncols = (ncols > 1) ? ncols-1 : 4;
501
502   /* Find the device with the longest name */
503   for(i=0,longest=0; i<num_of_supported_PICS; i++) {
504     for(j=0; j<=list_alias; j++) {
505       k = strlen(Pics16[i].name[j]);
506       if(k>longest)
507         longest = k;
508     }
509   }
510
511   col = 0;
512
513   for(i=0;  i < num_of_supported_PICS; i++) {
514     j = 0;
515     do {
516
517       fprintf(stderr,"%s", Pics16[i].name[j]);
518       if(col<ncols) {
519         l = longest + 2 - strlen(Pics16[i].name[j]);
520         for(k=0; k<l; k++)
521           fputc(' ',stderr);
522
523         col++;
524
525       } else {
526         fputc('\n',stderr);
527         col = 0;
528       }
529
530     } while(++j<list_alias);
531
532   }
533   if(col != ncols)
534     fputc('\n',stderr);
535
536 }
537
538 /*-----------------------------------------------------------------*
539  *  
540  *-----------------------------------------------------------------*/
541 PIC16_device *pic16_find_device(char *name)
542 {
543
544   int i,j;
545
546   if(!name)
547     return NULL;
548
549   for(i = 0; i<num_of_supported_PICS; i++) {
550
551     for(j=0; j<PROCESSOR_NAMES; j++)
552       if(!STRCASECMP(Pics16[i].name[j], name) )
553         return &Pics16[i];
554   }
555
556   /* not found */
557   return NULL; 
558 }
559
560 /*-----------------------------------------------------------------*
561  *  
562  *-----------------------------------------------------------------*/
563 void pic16_init_pic(char *pic_type)
564 {
565         pic16 = pic16_find_device(pic_type);
566
567         if(!pic16) {
568                 if(pic_type)
569                         fprintf(stderr, "'%s' was not found.\n", pic_type);
570                 else
571                         fprintf(stderr, "No processor has been specified (use -pPROCESSOR_NAME)\n");
572
573                 fprintf(stderr,"Valid devices are:\n");
574
575                 pic16_list_valid_pics(4,0);
576                 exit(1);
577         }
578
579 //      printf("PIC processor found and initialized: %s\n", pic_type);
580         pic16_setMaxRAM( 0xfff  );
581 }
582
583 /*-----------------------------------------------------------------*
584  *  
585  *-----------------------------------------------------------------*/
586 int pic16_picIsInitialized(void)
587 {
588   if(pic16 && pic16->maxRAMaddress > 0)
589     return 1;
590
591   return 0;
592
593 }
594
595 /*-----------------------------------------------------------------*
596  *  char *pic16_processor_base_name(void) - Include file is derived from this.
597  *-----------------------------------------------------------------*/
598 char *pic16_processor_base_name(void)
599 {
600
601   if(!pic16)
602     return NULL;
603
604   return pic16->name[0];
605 }
606
607
608 /*
609  * return 1 if register wasn't found and added, 0 otherwise
610  */
611 int checkAddReg(set **set, regs *reg)
612 {
613   regs *tmp;
614
615
616         for(tmp = setFirstItem(*set); tmp; tmp = setNextItem(*set)) {
617                 if(!strcmp(tmp->name, reg->name))break;
618         }
619         
620         if(!tmp) {
621                 addSet(set, reg);
622                 return 1;
623         }
624
625   return 0;
626 }
627
628 /*-----------------------------------------------------------------*
629  * void pic16_groupRegistersInSection - add each register to its   *
630  *      corresponding section                                      *
631  *-----------------------------------------------------------------*/
632 void pic16_groupRegistersInSection(set *regset)
633 {
634   regs *reg;
635
636         for(reg=setFirstItem(regset); reg; reg = setNextItem(regset)) {
637                 if(reg->wasUsed
638                         && !(reg->regop && SPEC_EXTR(OP_SYM_ETYPE(reg->regop)))) {
639
640 //                      fprintf(stderr, "%s:%d register %s\n", __FILE__, __LINE__, reg->name);
641
642                         if(reg->alias) {
643                                 checkAddReg(&pic16_equ_data, reg);
644                         } else
645                         if(reg->isFixed) {
646                                 checkAddReg(&pic16_fix_udata, reg);
647                         } else
648                         if(!reg->isFixed) {
649                                 if(reg->pc_type == PO_GPR_TEMP)
650                                         checkAddReg(&pic16_int_regs, reg);
651                                 else
652                                         checkAddReg(&pic16_rel_udata, reg);
653                         }
654                 }
655         }
656 }
657
658
659
660
661
662 /*-----------------------------------------------------------------*
663  *  void pic16_assignConfigWordValue(int address, int value)
664  *
665  * All high performance RISC CPU PICs have seven config word starting
666  * at address 0x300000.
667  * This routine will assign a value to that address.
668  *
669  *-----------------------------------------------------------------*/
670
671 void pic16_assignConfigWordValue(int address, int value)
672 {
673   switch(address) {
674   case CONFIG1H_WORD_ADDRESS:
675     config1h_word = value;
676     break;
677   case CONFIG2L_WORD_ADDRESS:
678     config2l_word = value;
679     break;
680   case CONFIG2H_WORD_ADDRESS:
681     config2h_word = value;
682     break;
683   case CONFIG3H_WORD_ADDRESS:
684     config3h_word = value;
685     break;
686   case CONFIG4L_WORD_ADDRESS:
687     config4l_word = value;
688     break;
689   case CONFIG5L_WORD_ADDRESS:
690     config5l_word = value;
691     break;
692   case CONFIG5H_WORD_ADDRESS:
693     config5h_word = value;
694     break;
695   case CONFIG6L_WORD_ADDRESS:
696     config6l_word = value;
697     break;
698   case CONFIG6H_WORD_ADDRESS:
699     config6h_word = value;
700     break;
701   case CONFIG7L_WORD_ADDRESS:
702     config7l_word = value;
703     break;
704   case CONFIG7H_WORD_ADDRESS:
705     config7h_word = value;
706     break;
707   }
708
709         fprintf(stderr,"setting config word to 0x%x\n",value);
710
711 }
712 /*-----------------------------------------------------------------*
713  * int pic16_getConfigWord(int address)
714  *
715  * Get the current value of the config word.
716  *
717  *-----------------------------------------------------------------*/
718
719 int pic16_getConfigWord(int address)
720 {
721   switch(address) {
722   case CONFIG1H_WORD_ADDRESS:
723     return config1h_word;
724   case CONFIG2L_WORD_ADDRESS:
725     return config2l_word;
726   case CONFIG2H_WORD_ADDRESS:
727     return config2h_word;
728   case CONFIG3H_WORD_ADDRESS:
729     return config3h_word;
730   case CONFIG4L_WORD_ADDRESS:
731     return config4l_word;
732   case CONFIG5L_WORD_ADDRESS:
733     return config5l_word;
734   case CONFIG5H_WORD_ADDRESS:
735     return config5h_word;
736   case CONFIG6L_WORD_ADDRESS:
737     return config6l_word;
738   case CONFIG6H_WORD_ADDRESS:
739     return config6h_word;
740   case CONFIG7L_WORD_ADDRESS:
741     return config7l_word;
742   case CONFIG7H_WORD_ADDRESS:
743     return config7h_word;
744   default:
745     return 0;
746   }
747 }
748