1 /*-------------------------------------------------------------------------
3 SDCCglue.c - glues everything we have done together into one file.
4 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1998)
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
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.
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.
20 In other words, you are welcome to use, share and improve this program.
21 You are forbidden to forbid anyone else to use, share and improve
22 what you give them. Help stamp out software-hoarding!
23 -------------------------------------------------------------------------*/
25 #include "../common.h"
35 #ifdef WORDS_BIGENDIAN
36 #define _ENDIAN(x) (3-x)
38 #define _ENDIAN(x) (x)
41 #define BYTE_IN_LONG(x,b) ((x>>(8*_ENDIAN(b)))&0xff)
43 extern symbol *interrupts[256];
44 static void printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb);
48 extern unsigned maxInterrupts;
49 extern int maxRegBank;
51 extern char *VersionString;
52 extern FILE *codeOutFile;
53 extern set *tmpfileSet;
54 extern set *tmpfileNameSet;
55 extern char *iComments1;
56 extern char *iComments2;
57 //extern void emitStaticSeg (memmap * map);
59 extern DEFSETFUNC (closeTmpFiles);
60 extern DEFSETFUNC (rmTmpFiles);
62 extern void AnalyzeBanking (void);
63 extern void copyFile (FILE * dest, FILE * src);
64 extern void ReuseReg(void);
65 extern void InlinepCode(void);
66 extern void writeUsedRegs(FILE *);
68 extern void initialComments (FILE * afile);
69 extern void printPublics (FILE * afile);
71 extern void printChar (FILE * ofile, char *s, int plen);
72 void pCodeInitRegisters(void);
73 int getConfigWord(int address);
74 int getHasSecondConfigReg(void);
75 int pic14_getSharebankSize(void);
76 int pic14_getSharebankAddress(void);
78 char *udata_section_name=0; // FIXME Temporary fix to change udata section name -- VR
80 /*-----------------------------------------------------------------*/
81 /* aopLiteral - string from a literal value */
82 /*-----------------------------------------------------------------*/
83 int pic14aopLiteral (value *val, int offset)
90 /* if it is a float then it gets tricky */
91 /* otherwise it is fairly simple */
92 if (!IS_FLOAT(val->type)) {
93 unsigned long v = (unsigned long) floatFromVal(val);
95 return ( (v >> (offset * 8)) & 0xff);
98 /* it is type float */
99 fl.f = (float) floatFromVal(val);
100 #ifdef WORDS_BIGENDIAN
101 return fl.c[3-offset];
108 /* Check whether the given reg is shared amongst all .o files of a project.
109 * This is true for the pseudo stack and WSAVE, SSAVE and PSAVE. */
111 is_shared_address (int addr)
113 return ((addr > Gstack_base_addr - 18)
114 && (addr <= Gstack_base_addr));
118 pic14_is_shared (regs *reg)
121 return is_shared_address (reg->address);
125 is_valid_identifier( const char *name )
131 /* only accept [a-zA-Z_][a-zA-Z0-9_] */
132 if (!((a >= 'a' && a <= 'z')
133 || (a >= 'A' && a <= 'z')
138 while ((a = *name++))
140 if (!((a >= 'a' && a <= 'z')
141 || (a >= 'A' && a <= 'Z')
142 || (a >= '0' && a <= '9')
147 /* valid identifier */
151 /* set of already emitted symbols; we store only pointers to the emitted
152 * symbol names so these MUST NO BE CHANGED afterwards... */
153 static set *symbolsEmitted = NULL;
155 /*-------------------------------------------------------------------*/
156 /* emitSymbolToFile - write a symbol definition only if it is not */
157 /* already present */
158 /*-------------------------------------------------------------------*/
160 emitSymbolToFile (FILE *of, const char *name, const char *section_type, int size, int addr, int useEQU, int globalize)
163 static unsigned int sec_idx = 0;
165 /* workaround: variables declared via `sbit' result in a numeric
166 * identifier (0xHH), EQU'ing them is invalid, so just ignore it.
167 * sbit is heavily used in the inc2h-generated header files!
169 if (!is_valid_identifier(name))
171 //fprintf( stderr, "%s:%s:%u: ignored symbol: %s\n", __FILE__, __FUNCTION__, __LINE__, name );
175 /* check whether the symbol is already defined */
176 for (sym = (const char *) setFirstItem (symbolsEmitted);
178 sym = (const char *) setNextItem (symbolsEmitted))
180 if (!strcmp (sym, name))
182 //fprintf (stderr, "%s: already emitted: %s\n", __FUNCTION__, name);
187 /* new symbol -- define it */
188 //fprintf (stderr, "%s: emitting %s (%d)\n", __FUNCTION__, name, size);
190 fprintf (of, "%s\tEQU\t0x%04x\n", name, addr);
193 /* we place each symbol into a section of its own to allow the linker
194 * to distribute the data into all available memory banks */
195 if (!section_type) section_type = "udata";
198 /* absolute symbols are handled in pic14_constructAbsMap */
201 /* workaround gpasm bug with symbols being EQUated and placed in absolute sections */
202 if (1 || !is_shared_address (addr))
204 if (globalize) fprintf (of, "\tglobal\t%s\n", name);
205 fprintf (of, "udata_%s_%u\t%s\t0x%04x\n", moduleName,
206 sec_idx++, "udata_ovr", addr);
207 fprintf (of, "%s\tres\t%d\n", name, size);
211 /* EQUs cannot be exported... */
212 fprintf (of, "%s\tEQU\t0x%04x\n", name, addr);
216 if (globalize) fprintf (of, "\tglobal\t%s\n", name);
217 fprintf (of, "udata_%s_%u\t%s\n", moduleName,
218 sec_idx++, section_type);
219 fprintf (of, "%s\tres\t%d\n", name, size);
223 //if (options.verbose) fprintf (stderr, "%s: emitted %s\n", __FUNCTION__, name);
224 addSet (&symbolsEmitted, (void *) name);
227 #define IS_DEFINED_HERE(sym) (!IS_EXTERN(sym->etype))
228 extern int IS_CONFIG_ADDRESS( int addr );
230 pic14_constructAbsMap (FILE *ofile)
232 memmap *maps[] = { data, sfr, NULL };
237 int addr, min=-1, max=-1;
240 for (i=0; maps[i] != NULL; i++)
242 for (sym = (symbol *)setFirstItem (maps[i]->syms);
243 sym; sym = setNextItem (maps[i]->syms))
245 if (IS_DEFINED_HERE(sym) && SPEC_ABSA(sym->etype))
247 addr = SPEC_ADDR(sym->etype);
249 /* handle CONFIG words here */
250 if (IS_CONFIG_ADDRESS( addr ))
252 //fprintf( stderr, "%s: assignment to CONFIG@0x%x found\n", __FUNCTION__, addr );
253 //fprintf( stderr, "ival: %p (0x%x)\n", sym->ival, (int)list2int( sym->ival ) );
255 pic14_assignConfigWordValue( addr, (int)list2int( sym->ival ) );
257 fprintf( stderr, "ERROR: Symbol %s, which is covering a __CONFIG word must be initialized!\n", sym->name );
262 if (max == -1 || addr > max) max = addr;
263 if (min == -1 || addr < min) min = addr;
264 //fprintf (stderr, "%s: sym %s @ 0x%x\n", __FUNCTION__, sym->name, addr);
265 aliases = hTabItemWithKey (ht, addr);
267 /* May not use addSetHead, as we cannot update the
268 * list's head in the hastable `ht'. */
269 addSet (&aliases, sym);
271 fprintf( stderr, "%s: now %d aliases for %s @ 0x%x\n",
272 __FUNCTION__, elementsInSet(aliases), sym->name, addr);
275 addSet (&aliases, sym);
276 hTabAddItem (&ht, addr, aliases);
282 /* now emit definitions for all absolute symbols */
283 fprintf (ofile, "%s", iComments2);
284 fprintf (ofile, "; absolute symbol definitions\n");
285 fprintf (ofile, "%s", iComments2);
286 for (addr=min; addr <= max; addr++)
289 aliases = hTabItemWithKey (ht, addr);
290 if (aliases && elementsInSet(aliases)) {
291 fprintf (ofile, "udata_abs_%s_%x\tudata_ovr\t0x%04x",
292 moduleName, addr, addr);
293 for (sym = setFirstItem (aliases); sym;
294 sym = setNextItem (aliases))
296 /* emit STATUS as well as _STATUS, required for SFRs only */
297 fprintf (ofile, "\n%s", sym->name);
298 fprintf (ofile, "\n%s", sym->rname);
299 if (getSize(sym->type) > size) {
300 size = getSize(sym->type);
303 fprintf (ofile, "\tres\t%d\n", size);
307 /* also emit STK symbols
308 * XXX: This is ugly and fails as soon as devices start to get
309 * differently sized sharebanks, since STK12 will be
310 * required by larger devices but only up to STK03 might
311 * be defined using smaller devices. */
312 fprintf (ofile, "\n");
313 if (!pic14_options.isLibrarySource)
315 fprintf (ofile, "\tglobal PSAVE\n");
316 fprintf (ofile, "\tglobal SSAVE\n");
317 fprintf (ofile, "\tglobal WSAVE\n");
318 for (i=pic14_getSharebankSize()-4; i >= 0; i--) {
319 fprintf (ofile, "\tglobal STK%02d\n", i);
321 fprintf (ofile, "sharebank udata_ovr 0x%04x\n",
322 pic14_getSharebankAddress() - pic14_getSharebankSize() + 1);
323 fprintf (ofile, "PSAVE\tres 1\n");
324 fprintf (ofile, "SSAVE\tres 1\n");
325 fprintf (ofile, "WSAVE\tres 1\n");
326 /* fill rest of sharebank with stack STKxx .. STK00 */
327 for (i=pic14_getSharebankSize()-4; i >= 0; i--) {
328 fprintf (ofile, "STK%02d\tres 1\n", i);
331 /* declare STKxx as extern for all files
332 * except the one containing main() */
333 fprintf (ofile, "\textern PSAVE\n");
334 fprintf (ofile, "\textern SSAVE\n");
335 fprintf (ofile, "\textern WSAVE\n");
336 for (i=pic14_getSharebankSize()-4; i >= 0; i--) {
337 fprintf (ofile, "\textern STK%02d\n", i);
342 /*-----------------------------------------------------------------*/
343 /* emitRegularMap - emit code for maps with no special cases */
344 /*-----------------------------------------------------------------*/
346 pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag)
351 /* print the area name */
353 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
355 for (sym = setFirstItem (map->syms); sym;
356 sym = setNextItem (map->syms)) {
358 //printf("%s\n",sym->name);
360 /* ignore if config word */
361 if (SPEC_ABSA(sym->etype)
362 && IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype)))
365 /* if extern then add it into the extern list */
366 if (IS_EXTERN (sym->etype)) {
367 addSetHead (&externs, sym);
371 /* if allocation required check is needed
372 then check if the symbol really requires
373 allocation only for local variables */
374 if (arFlag && !IS_AGGREGATE (sym->type) &&
375 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
376 !sym->allocreq && sym->level)
379 /* if global variable & not static or extern
380 and addPublics allowed then add it to the public set */
381 if ((sym->level == 0 ||
382 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
384 !IS_STATIC (sym->etype))
386 //fprintf( stderr, "%s: made public %s\n", __FUNCTION__, sym->name );
387 addSetHead (&publics, sym);
390 // PIC code allocates its own registers - so ignore parameter variable generated by processFuncArgs()
393 /* if extern then do nothing or is a function
395 if (IS_FUNC (sym->type))
398 /* print extra debug info if required */
399 if (options.debug || sym->level == 0)
401 if (!sym->level) /* global */
402 if (IS_STATIC (sym->etype))
403 fprintf (map->oFile, "F%s_", moduleName); /* scope is file */
405 fprintf (map->oFile, "G_"); /* scope is global */
407 /* symbol is local */
408 fprintf (map->oFile, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
409 fprintf (map->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
412 /* absolute symbols are handled in pic14_constructAbsMap */
413 if (SPEC_ABSA(sym->etype) && IS_DEFINED_HERE(sym))
416 /* if it has an absolute address then generate
417 an equate for this no need to allocate space */
418 if (0 && SPEC_ABSA (sym->etype))
420 //if (options.debug || sym->level == 0)
421 //fprintf (map->oFile,"; == 0x%04x\n",SPEC_ADDR (sym->etype));
423 fprintf (map->oFile, "%s\tEQU\t0x%04x\n",
425 SPEC_ADDR (sym->etype));
431 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
432 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
433 /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
434 if (IS_BITVAR (sym->etype))
440 emitSymbolToFile (map->oFile,
443 getSize (sym->type) & 0xffff,
444 SPEC_ABSA(sym->etype)
445 ? SPEC_ADDR(sym->etype)
453 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1)
455 for (i = 1; i < size; i++)
456 fprintf (map->oFile, "\t%s_%d\n", sym->rname, i);
461 //fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
464 /* if it has a initial value then do it only if
465 it is a global variable */
466 if (sym->ival && sym->level == 0) {
469 if (IS_AGGREGATE (sym->type))
470 ival = initAggregates (sym, sym->ival, NULL);
472 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
473 decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
474 codeOutFile = statsg->oFile;
476 eBBlockFromiCode (iCodeFromAst (ival));
483 /*-----------------------------------------------------------------*/
484 /* printIvalType - generates ival for int/char */
485 /*-----------------------------------------------------------------*/
487 printIvalType (symbol *sym, sym_link * type, initList * ilist, pBlock *pb)
492 //fprintf(stderr, "%s\n",__FUNCTION__);
494 /* if initList is deep */
495 if (ilist->type == INIT_DEEP)
496 ilist = ilist->init.deep;
498 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
499 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
502 if (!(val = list2val (ilist))) {
503 // assuming a warning has been thrown
507 if (val->type != type) {
508 val = valCastLiteral(type, floatFromVal(val));
512 ulval = (unsigned long) floatFromVal (val);
516 switch (getSize (type)) {
518 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
522 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
523 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
527 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
528 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
529 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
530 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
535 /*-----------------------------------------------------------------*/
536 /* printIvalBitFields - generate initializer for bitfields */
537 /*-----------------------------------------------------------------*/
538 static void printIvalBitFields(symbol **sym, initList **ilist, pBlock *pb )
542 initList *lilist = *ilist ;
543 unsigned long ival = 0;
549 val = list2val(lilist);
551 if (SPEC_BLEN(lsym->etype) > 8) {
552 size += ((SPEC_BLEN (lsym->etype) / 8) +
553 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
556 size = ((SPEC_BLEN (lsym->etype) / 8) +
557 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
559 i = (unsigned long)floatFromVal(val);
560 i <<= SPEC_BSTR (lsym->etype);
562 if (! ( lsym->next &&
563 (IS_BITFIELD(lsym->next->type)) &&
564 (SPEC_BSTR(lsym->next->etype)))) break;
566 lilist = lilist->next;
570 //tfprintf (oFile, "\t!db !constbyte\n",ival);
571 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
575 //tfprintf (oFile, "\t!dw !constword\n",ival);
576 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
577 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
580 //tfprintf (oFile, "\t!db !constword,!constword\n",(ival >> 8) & 0xffff, (ival & 0xffff));
581 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>24)));
582 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>16)));
583 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
584 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
591 /*-----------------------------------------------------------------*/
592 /* printIvalStruct - generates initial value for structures */
593 /*-----------------------------------------------------------------*/
594 static void printIvalStruct (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
597 initList *iloop = NULL;
599 sflds = SPEC_STRUCT (type)->fields;
602 if (ilist->type != INIT_DEEP) {
603 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
607 iloop = ilist->init.deep;
610 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
611 if (IS_BITFIELD(sflds->type)) {
612 printIvalBitFields(&sflds,&iloop,pb);
614 printIval (sym, sflds->type, iloop, pb);
618 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
623 /*-----------------------------------------------------------------*/
624 /* printIvalChar - generates initital value for character array */
625 /*-----------------------------------------------------------------*/
627 printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
635 //fprintf(stderr, "%s\n",__FUNCTION__);
639 val = list2val (ilist);
641 /* if the value is a character string */
642 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
644 ilen = DCL_ELEM(val->type);
646 if (!DCL_ELEM (type))
647 DCL_ELEM (type) = ilen;
649 /* emit string constant */
650 for (remain = 0; remain < ilen; remain++) {
651 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(SPEC_CVAL(val->etype).v_char[remain])));
654 /* fill array up to desired size */
655 if ((remain = (DCL_ELEM (type) - ilen)) > 0)
657 //tfprintf (oFile, "\t!db !constbyte\n", 0);
658 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
665 //printChar (oFile, s, strlen (s) + 1);
667 for(remain=0; remain<(int)strlen(s); remain++) {
668 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(s[remain])));
669 //fprintf(stderr,"0x%02x ",s[remain]);
671 //fprintf(stderr,"\n");
676 /*-----------------------------------------------------------------*/
677 /* printIvalArray - generates code for array initialization */
678 /*-----------------------------------------------------------------*/
680 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
689 /* take care of the special case */
690 /* array of characters can be init */
692 if (IS_CHAR (type->next)) {
693 //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
694 if (!IS_LITERAL(list2val(ilist)->etype)) {
695 werror (W_INIT_WRONG);
698 if (printIvalChar (type,
699 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
700 pb, SPEC_CVAL (sym->etype).v_char))
703 /* not the special case */
704 if (ilist->type != INIT_DEEP) {
705 werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
709 for (iloop=ilist->init.deep; iloop; iloop=iloop->next) {
710 if ((++size > DCL_ELEM(type)) && DCL_ELEM(type)) {
711 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
714 printIval (sym, type->next, iloop, pb);
718 if (DCL_ELEM(type)) {
719 // pad with zeros if needed
720 if (size<DCL_ELEM(type)) {
721 size = (DCL_ELEM(type) - size) * getSize(type->next);
723 //tfprintf (oFile, "\t!db !constbyte\n", 0);
724 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
728 // we have not been given a size, but we now know it
729 DCL_ELEM (type) = size;
735 /*-----------------------------------------------------------------*/
736 /* printIvalPtr - generates code for initial value of pointers */
737 /*-----------------------------------------------------------------*/
738 extern value *initPointer (initList *, sym_link *toType);
741 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
748 fprintf (stderr, "FIXME: initializers for pointers...\n");
749 printTypeChain (type, stderr);
751 fprintf (stderr, "symbol: %s, DCL_TYPE():%d, DCL_ELEM():%d, IS_ARRAY():%d", sym->rname, DCL_TYPE(type), DCL_ELEM(type), IS_ARRAY(type));
752 fprintf (stderr, "ilist: type=%d (INIT_DEEP=%d, INIT_NODE=%d)\n", ilist->type, INIT_DEEP, INIT_NODE);
754 if (ilist && (ilist->type == INIT_DEEP))
755 ilist = ilist->init.deep;
757 /* function pointers */
758 if (IS_FUNC (type->next))
760 assert ( !"function pointers not yet handled" );
761 //printIvalFuncPtr (type, ilist, pb);
764 if (!(val = initPointer (ilist, type)))
767 if (IS_CHAR (type->next))
769 if (printIvalChar (type, ilist, pb, NULL)) return;
773 if (compareType (type, val->type) == 0)
775 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
776 printFromToType (val->type, type);
779 if (IS_LITERAL (val->etype))
781 switch (getSize (type))
784 fprintf (stderr, "BYTE: %i\n", (unsigned char)floatFromVal (val) & 0x00FF);
787 fprintf (stderr, "WORD: %i\n", (unsigned int)floatFromVal (val) & 0x00FFFF);
789 case 3: /* gneric pointers */
790 assert ( !"generic pointers not yet handled" );
792 fprintf (stderr, "LONG: %i\n", (unsigned int)floatFromVal (val) & 0x0000FFFFFFFF);
795 assert ( !"invaild size of value -- aborting" );
801 /* now handle symbolic values */
802 switch (getSize (type))
805 fprintf (stderr, "BYTE: %s", val->name);
808 fprintf (stderr, "WORD: %s", val->name);
811 fprintf (stderr, "LONG: %s", val->name);
814 assert ( !"invalid size of (symbolic) value -- aborting" );
818 /*-----------------------------------------------------------------*/
819 /* printIval - generates code for initial value */
820 /*-----------------------------------------------------------------*/
822 printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
827 /* if structure then */
828 if (IS_STRUCT (type))
830 //fprintf(stderr,"%s struct: %s\n",__FUNCTION__, sym->rname);
831 printIvalStruct (sym, type, ilist, pb);
835 /* if this is an array */
838 //fprintf(stderr,"%s array: %s\n",__FUNCTION__, sym->rname);
839 printIvalArray (sym, type, ilist, pb);
843 /* if this is a pointer */
846 //fprintf(stderr,"%s pointer: %s\n",__FUNCTION__, sym->rname);
847 printIvalPtr (sym, type, ilist, pb);
851 /* if type is SPECIFIER */
854 //fprintf(stderr,"%s spec %s\n",__FUNCTION__, sym->rname);
855 printIvalType (sym, type, ilist, pb);
860 extern void pCodeConstString(char *name, char *value);
861 /*-----------------------------------------------------------------*/
862 /* emitStaticSeg - emitcode for the static segment */
863 /*-----------------------------------------------------------------*/
865 pic14emitStaticSeg (memmap * map)
869 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
871 //fprintf(stderr, "%s\n",__FUNCTION__);
873 /* for all variables in this segment do */
874 for (sym = setFirstItem (map->syms); sym;
875 sym = setNextItem (map->syms))
877 /* if extern then add it into the extern list */
878 if (IS_EXTERN (sym->etype)) {
879 addSetHead (&externs, sym);
883 /* if it is not static add it to the public
885 if (!IS_STATIC (sym->etype))
886 addSetHead (&publics, sym);
888 /* print extra debug info if required */
889 if (options.debug || sym->level == 0)
893 if (IS_STATIC (sym->etype))
894 fprintf (code->oFile, "F%s_", moduleName); /* scope is file */
896 fprintf (code->oFile, "G_"); /* scope is global */
899 /* symbol is local */
900 fprintf (code->oFile, "L%s_",
901 (sym->localof ? sym->localof->name : "-null-"));
902 fprintf (code->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
906 /* if it has an absolute address */
907 if (SPEC_ABSA (sym->etype))
909 if (options.debug || sym->level == 0)
910 fprintf (code->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
912 fprintf (code->oFile, "%s\t=\t0x%04x\n",
914 SPEC_ADDR (sym->etype));
918 if (options.debug || sym->level == 0)
919 fprintf (code->oFile, " == .\n");
921 /* if it has an initial value */
926 fprintf (code->oFile, "%s:\n", sym->rname);
928 resolveIvalSym (sym->ival, sym->type);
929 //printIval (sym, sym->type, sym->ival, code->oFile);
930 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block for Ival"));
932 addpCode2pBlock(pb,newpCodeLabel(sym->rname,-1));
934 printIval (sym, sym->type, sym->ival, pb);
941 fprintf (code->oFile, "%s:\n", sym->rname);
942 /* special case for character strings */
943 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
944 SPEC_CVAL (sym->etype).v_char)
945 pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
946 /*printChar (code->oFile,
947 SPEC_CVAL (sym->etype).v_char,
948 strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
950 fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
958 /*-----------------------------------------------------------------*/
959 /* emitMaps - emits the code for the data portion the code */
960 /*-----------------------------------------------------------------*/
964 pic14_constructAbsMap (sfr->oFile);
965 /* no special considerations for the following
966 data, idata & bit & xdata */
967 pic14emitRegularMap (data, TRUE, TRUE);
968 pic14emitRegularMap (idata, TRUE, TRUE);
969 pic14emitRegularMap (bit, TRUE, FALSE);
970 pic14emitRegularMap (xdata, TRUE, TRUE);
971 pic14emitRegularMap (sfr, TRUE, FALSE);
972 pic14emitRegularMap (sfrbit, FALSE, FALSE);
973 pic14emitRegularMap (code, TRUE, FALSE);
974 pic14emitStaticSeg (statsg);
977 /*-----------------------------------------------------------------*/
978 /* createInterruptVect - creates the interrupt vector */
979 /*-----------------------------------------------------------------*/
981 pic14createInterruptVect (FILE * vFile)
983 mainf = newSymbol ("main", 0);
986 /* only if the main function exists */
987 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
989 struct options *op = &options;
990 if (!(op->cc_only || noAssemble))
991 // werror (E_NO_MAIN);
992 fprintf(stderr,"WARNING: function 'main' undefined\n");
996 /* if the main is only a prototype ie. no body then do nothing */
997 if (!IFFUNC_HASBODY(mainf->type))
999 /* if ! compile only then main function should be present */
1000 if (!(options.cc_only || noAssemble))
1001 // werror (E_NO_MAIN);
1002 fprintf(stderr,"WARNING: function 'main' undefined\n");
1006 fprintf (vFile, "%s", iComments2);
1007 fprintf (vFile, "; reset vector \n");
1008 fprintf (vFile, "%s", iComments2);
1009 fprintf (vFile, "STARTUP\t%s\n", CODE_NAME); // Lkr file should place section STARTUP at address 0x0
1010 fprintf (vFile, "\tnop\n"); /* first location for used by incircuit debugger */
1011 fprintf (vFile, "\tgoto\t__sdcc_gsinit_startup\n");
1015 /*-----------------------------------------------------------------*/
1016 /* initialComments - puts in some initial comments */
1017 /*-----------------------------------------------------------------*/
1019 pic14initialComments (FILE * afile)
1021 initialComments (afile);
1022 fprintf (afile, "; PIC port for the 14-bit core\n");
1023 fprintf (afile, iComments2);
1027 /*-----------------------------------------------------------------*/
1028 /* printExterns - generates extern for external variables */
1029 /*-----------------------------------------------------------------*/
1031 pic14printExterns (FILE * afile)
1035 fprintf (afile, "%s", iComments2);
1036 fprintf (afile, "; extern variables in this module\n");
1037 fprintf (afile, "%s", iComments2);
1039 for (sym = setFirstItem (externs); sym;
1040 sym = setNextItem (externs))
1041 fprintf (afile, "\textern %s\n", sym->rname);
1044 /*-----------------------------------------------------------------*/
1045 /* printPublics - generates .global for publics */
1046 /*-----------------------------------------------------------------*/
1048 pic14printPublics (FILE * afile)
1052 fprintf (afile, "%s", iComments2);
1053 fprintf (afile, "; publics variables in this module\n");
1054 fprintf (afile, "%s", iComments2);
1056 for (sym = setFirstItem (publics); sym;
1057 sym = setNextItem (publics)) {
1059 if(!IS_BITFIELD(sym->type) && ((IS_FUNC(sym->type) || sym->allocreq))) {
1060 if (!IS_BITVAR(sym->type))
1061 fprintf (afile, "\tglobal %s\n", sym->rname);
1063 /* Absolute variables are defines in the asm file as equates and thus can not be made global. */
1064 /* Not any longer! */
1065 //if (!SPEC_ABSA (sym->etype))
1066 fprintf (afile, "\tglobal %s\n", sym->rname);
1071 /*-----------------------------------------------------------------*/
1072 /* emitOverlay - will emit code for the overlay stuff */
1073 /*-----------------------------------------------------------------*/
1075 pic14emitOverlay (FILE * afile)
1079 /* if (!elementsInSet (ovrSetSets))*/
1081 /* the hack below, fixes translates for devices which
1082 * only have udata_shr memory */
1083 fprintf (afile, "%s\t%s\n",
1084 (elementsInSet(ovrSetSets)?"":";"),
1085 port->mem.overlay_name);
1087 /* for each of the sets in the overlay segment do */
1088 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1089 ovrset = setNextItem (ovrSetSets))
1094 if (elementsInSet (ovrset))
1096 /* this dummy area is used to fool the assembler
1097 otherwise the assembler will append each of these
1098 declarations into one chunk and will not overlay
1101 /* I don't think this applies to us. We are using gpasm. CRF */
1103 fprintf (afile, ";\t.area _DUMMY\n");
1104 /* output the area informtion */
1105 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1108 for (sym = setFirstItem (ovrset); sym;
1109 sym = setNextItem (ovrset))
1112 /* if extern then do nothing */
1113 if (IS_EXTERN (sym->etype))
1116 /* if allocation required check is needed
1117 then check if the symbol really requires
1118 allocation only for local variables */
1119 if (!IS_AGGREGATE (sym->type) &&
1120 !(sym->_isparm && !IS_REGPARM (sym->etype))
1121 && !sym->allocreq && sym->level)
1124 /* if global variable & not static or extern
1125 and addPublics allowed then add it to the public set */
1126 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1127 && !IS_STATIC (sym->etype))
1128 addSetHead (&publics, sym);
1130 /* if extern then do nothing or is a function
1132 if (IS_FUNC (sym->type))
1135 /* print extra debug info if required */
1136 if (options.debug || sym->level == 0)
1140 if (IS_STATIC (sym->etype))
1141 fprintf (afile, "F%s_", moduleName); /* scope is file */
1143 fprintf (afile, "G_"); /* scope is global */
1146 /* symbol is local */
1147 fprintf (afile, "L%s_",
1148 (sym->localof ? sym->localof->name : "-null-"));
1149 fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
1152 /* if is has an absolute address then generate
1153 an equate for this no need to allocate space */
1154 if (SPEC_ABSA (sym->etype))
1157 if (options.debug || sym->level == 0)
1158 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1160 fprintf (afile, "%s\t=\t0x%04x\n",
1162 SPEC_ADDR (sym->etype));
1166 if (options.debug || sym->level == 0)
1167 fprintf (afile, "==.\n");
1169 /* allocate space */
1170 fprintf (afile, "%s:\n", sym->rname);
1171 fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1179 /*-----------------------------------------------------------------*/
1180 /* glue - the final glue that hold the whole thing together */
1181 /*-----------------------------------------------------------------*/
1185 char udata_name[80];
1188 FILE *ovrFile = tempfile();
1190 addSetHead(&tmpfileSet,ovrFile);
1191 pCodeInitRegisters();
1193 /* check for main() */
1194 mainf = newSymbol ("main", 0);
1196 mainf = findSymWithLevel (SymbolTab, mainf);
1198 if (!mainf || !IFFUNC_HASBODY(mainf->type))
1200 /* main missing -- import stack from main module */
1201 //fprintf (stderr, "main() missing -- assuming we are NOT the main module\n");
1202 pic14_options.isLibrarySource = 1;
1206 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1208 pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
1211 /* entry point @ start of CSEG */
1212 addpCode2pBlock(pb,newpCodeLabel("__sdcc_program_startup",-1));
1213 /* put in the call to main */
1214 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp("_main",PO_STR)));
1216 if (options.mainreturn) {
1218 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will return to caller\n"));
1219 addpCode2pBlock(pb,newpCode(POC_RETURN,NULL));
1223 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will lock up\n"));
1224 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("$",PO_STR)));
1230 /* At this point we've got all the code in the form of pCode structures */
1231 /* Now it needs to be rearranged into the order it should be placed in the */
1234 movepBlock2Head('P'); // Last
1235 movepBlock2Head(code->dbName);
1236 movepBlock2Head('X');
1237 movepBlock2Head(statsg->dbName); // First
1240 /* print the global struct definitions */
1246 addSetHead(&tmpfileSet,vFile);
1248 /* emit code for the all the variables declared */
1250 /* do the overlay segments */
1251 pic14emitOverlay(ovrFile);
1253 /* PENDING: this isnt the best place but it will do */
1254 if (port->general.glue_up_main) {
1255 /* create the interrupt vector table */
1256 pic14createInterruptVect (vFile);
1261 ReuseReg(); // ReuseReg where call tree permits
1270 /* now put it all together into the assembler file */
1271 /* create the assembler file name */
1273 if ((noAssemble || options.c1mode) && fullDstFileName)
1275 sprintf (buffer, fullDstFileName);
1279 sprintf (buffer, dstFileName);
1280 strcat (buffer, ".asm");
1283 if (!(asmFile = fopen (buffer, "w"))) {
1284 werror (E_FILE_OPEN_ERR, buffer);
1288 /* prepare statistics */
1289 resetpCodeStatistics ();
1291 /* initial comments */
1292 pic14initialComments (asmFile);
1294 /* print module name */
1295 fprintf (asmFile, ";\t.module %s\n", moduleName);
1297 /* Let the port generate any global directives, etc. */
1298 if (port->genAssemblerPreamble)
1300 port->genAssemblerPreamble(asmFile);
1303 /* Emit the __config directive */
1304 pic14_emitConfigWord (asmFile);
1306 /* print the extern variables in this module */
1307 pic14printExterns (asmFile);
1309 /* print the global variables in this module */
1310 pic14printPublics (asmFile);
1312 /* copy the sfr segment */
1313 fprintf (asmFile, "%s", iComments2);
1314 fprintf (asmFile, "; special function registers\n");
1315 fprintf (asmFile, "%s", iComments2);
1316 copyFile (asmFile, sfr->oFile);
1319 if (udata_section_name) {
1320 sprintf(udata_name,"%s",udata_section_name);
1322 sprintf(udata_name,"data_%s",moduleName);
1324 fprintf (asmFile, "%s", iComments2);
1325 fprintf (asmFile, "; udata\n");
1326 fprintf (asmFile, "%s", iComments2);
1327 fprintf (asmFile, "%s\tudata\n", udata_name);
1328 copyFile (asmFile, data->oFile);
1330 /* Put all variables into a cblock */
1332 writeUsedRegs(asmFile);
1334 /* create the overlay segments */
1335 fprintf (asmFile, "%s", iComments2);
1336 fprintf (asmFile, "; overlayable items in internal ram \n");
1337 fprintf (asmFile, "%s", iComments2);
1338 copyFile (asmFile, ovrFile);
1342 /* create the stack segment MOF */
1343 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1344 fprintf (asmFile, "%s", iComments2);
1345 fprintf (asmFile, "; Stack segment in internal ram \n");
1346 fprintf (asmFile, "%s", iComments2);
1347 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1348 ";__start__stack:\n;\t.ds\t1\n\n");
1351 /* create the idata segment */
1352 fprintf (asmFile, "%s", iComments2);
1353 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1354 fprintf (asmFile, "%s", iComments2);
1355 copyFile (asmFile, idata->oFile);
1357 /* if external stack then reserve space of it */
1358 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1359 fprintf (asmFile, "%s", iComments2);
1360 fprintf (asmFile, "; external stack \n");
1361 fprintf (asmFile, "%s", iComments2);
1362 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1363 fprintf (asmFile,";\t.ds 256\n");
1366 /* copy xtern ram data */
1367 fprintf (asmFile, "%s", iComments2);
1368 fprintf (asmFile, "; external ram data\n");
1369 fprintf (asmFile, "%s", iComments2);
1370 copyFile (asmFile, xdata->oFile);
1374 /* copy the bit segment */
1375 fprintf (asmFile, "%s", iComments2);
1376 fprintf (asmFile, "; bit data\n");
1377 fprintf (asmFile, "%s", iComments2);
1378 copyFile (asmFile, bit->oFile);
1380 /* copy the interrupt vector table */
1381 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1382 copyFile (asmFile, vFile);
1384 fprintf (asmFile, "%s", iComments2);
1385 fprintf (asmFile, "; interrupt and initialization code\n");
1386 fprintf (asmFile, "%s", iComments2);
1387 fprintf (asmFile, "code_interrupt\t%s\t0x4\n", CODE_NAME); // Note - for mplink may have to enlarge section vectors in .lnk file
1389 /* interrupt service routine */
1390 fprintf (asmFile, "__sdcc_interrupt\n");
1391 copypCode(asmFile, 'I');
1393 /* initialize data memory */
1394 fprintf (asmFile, "code_init\t%s\n", CODE_NAME); // Note - for mplink may have to enlarge section vectors in .lnk file
1395 fprintf (asmFile,"__sdcc_gsinit_startup\n");
1396 /* FIXME: This is temporary. The idata section should be used. If
1397 not, we could add a special feature to the linker. This will
1398 work in the mean time. Put all initalized data in main.c */
1399 copypCode(asmFile, statsg->dbName);
1400 fprintf (asmFile,"\tpagesel _main\n");
1401 fprintf (asmFile,"\tgoto _main\n");
1406 /* copy global & static initialisations */
1407 fprintf (asmFile, "%s", iComments2);
1408 fprintf (asmFile, "; global & static initialisations\n");
1409 fprintf (asmFile, "%s", iComments2);
1410 copypCode(asmFile, statsg->dbName);
1414 /* copy over code */
1415 fprintf (asmFile, "%s", iComments2);
1416 fprintf (asmFile, "; code\n");
1417 fprintf (asmFile, "%s", iComments2);
1418 fprintf (asmFile, "code_%s\t%s\n", moduleName, port->mem.code_name);
1421 copypCode(asmFile, 'X');
1423 /* _main function */
1424 copypCode(asmFile, 'M');
1426 /* other functions */
1427 copypCode(asmFile, code->dbName);
1430 copypCode(asmFile, 'P');
1432 dumppCodeStatistics (asmFile);
1434 fprintf (asmFile,"\tend\n");