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"
32 #ifdef WORDS_BIGENDIAN
33 #define _ENDIAN(x) (3-x)
35 #define _ENDIAN(x) (x)
38 #define BYTE_IN_LONG(x,b) ((x>>(8*_ENDIAN(b)))&0xff)
40 extern symbol *interrupts[256];
41 static void printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb);
45 extern unsigned maxInterrupts;
46 extern int maxRegBank;
48 extern char *VersionString;
49 extern FILE *codeOutFile;
50 extern set *tmpfileSet;
51 extern set *tmpfileNameSet;
52 extern char *iComments1;
53 extern char *iComments2;
54 //extern void emitStaticSeg (memmap * map);
56 extern DEFSETFUNC (closeTmpFiles);
57 extern DEFSETFUNC (rmTmpFiles);
59 extern void AnalyzeBanking (void);
60 extern void copyFile (FILE * dest, FILE * src);
61 extern void ReuseReg(void);
62 extern void InlinepCode(void);
63 extern void writeUsedRegs(FILE *);
65 extern void initialComments (FILE * afile);
66 extern void printPublics (FILE * afile);
68 extern void printChar (FILE * ofile, char *s, int plen);
69 void pCodeInitRegisters(void);
70 int getConfigWord(int address);
72 char *udata_section_name=0; // FIXME Temporary fix to change udata section name -- VR
74 /*-----------------------------------------------------------------*/
75 /* aopLiteral - string from a literal value */
76 /*-----------------------------------------------------------------*/
77 int pic14aopLiteral (value *val, int offset)
84 /* if it is a float then it gets tricky */
85 /* otherwise it is fairly simple */
86 if (!IS_FLOAT(val->type)) {
87 unsigned long v = (unsigned long) floatFromVal(val);
89 return ( (v >> (offset * 8)) & 0xff);
92 /* it is type float */
93 fl.f = (float) floatFromVal(val);
94 #ifdef WORDS_BIGENDIAN
95 return fl.c[3-offset];
103 /*-----------------------------------------------------------------*/
104 /* emitRegularMap - emit code for maps with no special cases */
105 /*-----------------------------------------------------------------*/
107 pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag)
112 /* print the area name */
114 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
116 for (sym = setFirstItem (map->syms); sym;
117 sym = setNextItem (map->syms)) {
119 //printf("%s\n",sym->name);
121 /* if extern then add it into the extern list */
122 if (IS_EXTERN (sym->etype)) {
123 addSetHead (&externs, sym);
127 /* if allocation required check is needed
128 then check if the symbol really requires
129 allocation only for local variables */
130 if (arFlag && !IS_AGGREGATE (sym->type) &&
131 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
132 !sym->allocreq && sym->level)
135 /* if global variable & not static or extern
136 and addPublics allowed then add it to the public set */
137 if ((sym->level == 0 ||
138 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
140 !IS_STATIC (sym->etype))
141 addSetHead (&publics, sym);
143 // PIC code allocates its own registers - so ignore parameter variable generated by processFuncArgs()
146 /* if extern then do nothing or is a function
148 if (IS_FUNC (sym->type))
151 /* print extra debug info if required */
152 if (options.debug || sym->level == 0)
154 if (!sym->level) /* global */
155 if (IS_STATIC (sym->etype))
156 fprintf (map->oFile, "F%s_", moduleName); /* scope is file */
158 fprintf (map->oFile, "G_"); /* scope is global */
160 /* symbol is local */
161 fprintf (map->oFile, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
162 fprintf (map->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
166 /* if it has an absolute address then generate
167 an equate for this no need to allocate space */
168 if (SPEC_ABSA (sym->etype))
170 //if (options.debug || sym->level == 0)
171 //fprintf (map->oFile,"; == 0x%04x\n",SPEC_ADDR (sym->etype));
173 fprintf (map->oFile, "%s\tEQU\t0x%04x\n",
175 SPEC_ADDR (sym->etype));
181 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
182 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
183 /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
184 if (IS_BITVAR (sym->etype))
190 fprintf (map->oFile, "%s\tres\t%d\n", sym->rname,getSize (sym->type) & 0xffff);
195 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1)
197 for (i = 1; i < size; i++)
198 fprintf (map->oFile, "\t%s_%d\n", sym->rname, i);
203 //fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
206 /* if it has a initial value then do it only if
207 it is a global variable */
208 if (sym->ival && sym->level == 0) {
211 if (IS_AGGREGATE (sym->type))
212 ival = initAggregates (sym, sym->ival, NULL);
214 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
215 decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
216 codeOutFile = statsg->oFile;
218 eBBlockFromiCode (iCodeFromAst (ival));
225 /*-----------------------------------------------------------------*/
226 /* printIvalType - generates ival for int/char */
227 /*-----------------------------------------------------------------*/
229 printIvalType (symbol *sym, sym_link * type, initList * ilist, pBlock *pb)
234 //fprintf(stderr, "%s\n",__FUNCTION__);
236 /* if initList is deep */
237 if (ilist->type == INIT_DEEP)
238 ilist = ilist->init.deep;
240 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
241 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
244 if (!(val = list2val (ilist))) {
245 // assuming a warning has been thrown
249 if (val->type != type) {
250 val = valCastLiteral(type, floatFromVal(val));
254 ulval = (unsigned long) floatFromVal (val);
258 switch (getSize (type)) {
260 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
264 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
265 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
269 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
270 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
271 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
272 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
277 /*-----------------------------------------------------------------*/
278 /* printIvalBitFields - generate initializer for bitfields */
279 /*-----------------------------------------------------------------*/
280 static void printIvalBitFields(symbol **sym, initList **ilist, pBlock *pb )
284 initList *lilist = *ilist ;
285 unsigned long ival = 0;
291 val = list2val(lilist);
293 if (SPEC_BLEN(lsym->etype) > 8) {
294 size += ((SPEC_BLEN (lsym->etype) / 8) +
295 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
298 size = ((SPEC_BLEN (lsym->etype) / 8) +
299 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
301 i = (unsigned long)floatFromVal(val);
302 i <<= SPEC_BSTR (lsym->etype);
304 if (! ( lsym->next &&
305 (IS_BITFIELD(lsym->next->type)) &&
306 (SPEC_BSTR(lsym->next->etype)))) break;
308 lilist = lilist->next;
312 //tfprintf (oFile, "\t!db !constbyte\n",ival);
313 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
317 //tfprintf (oFile, "\t!dw !constword\n",ival);
318 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
319 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
322 //tfprintf (oFile, "\t!db !constword,!constword\n",(ival >> 8) & 0xffff, (ival & 0xffff));
323 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>24)));
324 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>16)));
325 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
326 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
333 /*-----------------------------------------------------------------*/
334 /* printIvalStruct - generates initial value for structures */
335 /*-----------------------------------------------------------------*/
336 static void printIvalStruct (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
339 initList *iloop = NULL;
341 sflds = SPEC_STRUCT (type)->fields;
344 if (ilist->type != INIT_DEEP) {
345 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
349 iloop = ilist->init.deep;
352 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
353 if (IS_BITFIELD(sflds->type)) {
354 printIvalBitFields(&sflds,&iloop,pb);
356 printIval (sym, sflds->type, iloop, pb);
360 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
365 /*-----------------------------------------------------------------*/
366 /* printIvalChar - generates initital value for character array */
367 /*-----------------------------------------------------------------*/
369 printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
377 //fprintf(stderr, "%s\n",__FUNCTION__);
381 val = list2val (ilist);
382 /* if the value is a character string */
383 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
385 if (!DCL_ELEM (type))
386 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
388 //printChar (oFile, SPEC_CVAL (val->etype).v_char, DCL_ELEM (type));
389 //fprintf(stderr, "%s omitting call to printChar\n",__FUNCTION__);
390 addpCode2pBlock(pb,newpCodeCharP(";omitting call to printChar"));
392 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0)
394 //tfprintf (oFile, "\t!db !constbyte\n", 0);
395 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
402 //printChar (oFile, s, strlen (s) + 1);
404 for(remain=0; remain<(int)strlen(s); remain++) {
405 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(s[remain])));
406 //fprintf(stderr,"0x%02x ",s[remain]);
408 //fprintf(stderr,"\n");
413 /*-----------------------------------------------------------------*/
414 /* printIvalArray - generates code for array initialization */
415 /*-----------------------------------------------------------------*/
417 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
426 /* take care of the special case */
427 /* array of characters can be init */
429 if (IS_CHAR (type->next)) {
430 //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
431 if (!IS_LITERAL(list2val(ilist)->etype)) {
432 werror (W_INIT_WRONG);
435 if (printIvalChar (type,
436 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
437 pb, SPEC_CVAL (sym->etype).v_char))
440 /* not the special case */
441 if (ilist->type != INIT_DEEP) {
442 werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
446 for (iloop=ilist->init.deep; iloop; iloop=iloop->next) {
447 if ((++size > DCL_ELEM(type)) && DCL_ELEM(type)) {
448 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
451 printIval (sym, type->next, iloop, pb);
455 if (DCL_ELEM(type)) {
456 // pad with zeros if needed
457 if (size<DCL_ELEM(type)) {
458 size = (DCL_ELEM(type) - size) * getSize(type->next);
460 //tfprintf (oFile, "\t!db !constbyte\n", 0);
461 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
465 // we have not been given a size, but we now know it
466 DCL_ELEM (type) = size;
472 /*-----------------------------------------------------------------*/
473 /* printIval - generates code for initial value */
474 /*-----------------------------------------------------------------*/
476 printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
481 /* if structure then */
482 if (IS_STRUCT (type))
484 //fprintf(stderr,"%s struct\n",__FUNCTION__);
485 printIvalStruct (sym, type, ilist, pb);
489 /* if this is a pointer */
492 //fprintf(stderr,"%s pointer\n",__FUNCTION__);
493 //printIvalPtr (sym, type, ilist, oFile);
497 /* if this is an array */
500 //fprintf(stderr,"%s array\n",__FUNCTION__);
501 printIvalArray (sym, type, ilist, pb);
505 /* if type is SPECIFIER */
508 //fprintf(stderr,"%s spec\n",__FUNCTION__);
509 printIvalType (sym, type, ilist, pb);
514 extern void pCodeConstString(char *name, char *value);
515 /*-----------------------------------------------------------------*/
516 /* emitStaticSeg - emitcode for the static segment */
517 /*-----------------------------------------------------------------*/
519 pic14emitStaticSeg (memmap * map)
523 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
525 //fprintf(stderr, "%s\n",__FUNCTION__);
527 /* for all variables in this segment do */
528 for (sym = setFirstItem (map->syms); sym;
529 sym = setNextItem (map->syms))
531 /* if extern then add it into the extern list */
532 if (IS_EXTERN (sym->etype)) {
533 addSetHead (&externs, sym);
537 /* if it is not static add it to the public
539 if (!IS_STATIC (sym->etype))
540 addSetHead (&publics, sym);
542 /* print extra debug info if required */
543 if (options.debug || sym->level == 0)
547 if (IS_STATIC (sym->etype))
548 fprintf (code->oFile, "F%s_", moduleName); /* scope is file */
550 fprintf (code->oFile, "G_"); /* scope is global */
553 /* symbol is local */
554 fprintf (code->oFile, "L%s_",
555 (sym->localof ? sym->localof->name : "-null-"));
556 fprintf (code->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
560 /* if it has an absolute address */
561 if (SPEC_ABSA (sym->etype))
563 if (options.debug || sym->level == 0)
564 fprintf (code->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
566 fprintf (code->oFile, "%s\t=\t0x%04x\n",
568 SPEC_ADDR (sym->etype));
572 if (options.debug || sym->level == 0)
573 fprintf (code->oFile, " == .\n");
575 /* if it has an initial value */
580 fprintf (code->oFile, "%s:\n", sym->rname);
582 resolveIvalSym (sym->ival, sym->type);
583 //printIval (sym, sym->type, sym->ival, code->oFile);
584 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block for Ival"));
586 addpCode2pBlock(pb,newpCodeLabel(sym->rname,-1));
588 printIval (sym, sym->type, sym->ival, pb);
595 fprintf (code->oFile, "%s:\n", sym->rname);
596 /* special case for character strings */
597 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
598 SPEC_CVAL (sym->etype).v_char)
599 pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
600 /*printChar (code->oFile,
601 SPEC_CVAL (sym->etype).v_char,
602 strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
604 fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
612 /*-----------------------------------------------------------------*/
613 /* emitMaps - emits the code for the data portion the code */
614 /*-----------------------------------------------------------------*/
618 /* no special considerations for the following
619 data, idata & bit & xdata */
620 pic14emitRegularMap (data, TRUE, TRUE);
621 pic14emitRegularMap (idata, TRUE, TRUE);
622 pic14emitRegularMap (bit, TRUE, FALSE);
623 pic14emitRegularMap (xdata, TRUE, TRUE);
624 pic14emitRegularMap (sfr, FALSE, FALSE);
625 pic14emitRegularMap (sfrbit, FALSE, FALSE);
626 pic14emitRegularMap (code, TRUE, FALSE);
627 pic14emitStaticSeg (statsg);
630 /*-----------------------------------------------------------------*/
631 /* createInterruptVect - creates the interrupt vector */
632 /*-----------------------------------------------------------------*/
634 pic14createInterruptVect (FILE * vFile)
636 mainf = newSymbol ("main", 0);
639 /* only if the main function exists */
640 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
642 struct options *op = &options;
643 if (!(op->cc_only || noAssemble))
644 // werror (E_NO_MAIN);
645 fprintf(stderr,"WARNING: function 'main' undefined\n");
649 /* if the main is only a prototype ie. no body then do nothing */
650 if (!IFFUNC_HASBODY(mainf->type))
652 /* if ! compile only then main function should be present */
653 if (!(options.cc_only || noAssemble))
654 // werror (E_NO_MAIN);
655 fprintf(stderr,"WARNING: function 'main' undefined\n");
659 fprintf (vFile, "%s", iComments2);
660 fprintf (vFile, "; config word \n");
661 fprintf (vFile, "%s", iComments2);
662 fprintf (vFile, "\t__config 0x%x\n", getConfigWord(0x2007));
664 fprintf (vFile, "%s", iComments2);
665 fprintf (vFile, "; reset vector \n");
666 fprintf (vFile, "%s", iComments2);
667 fprintf (vFile, "STARTUP\t%s\n", CODE_NAME); // Lkr file should place section STARTUP at address 0x0
668 fprintf (vFile, "\tnop\n"); /* first location for used by incircuit debugger */
669 fprintf (vFile, "\tgoto\t__sdcc_gsinit_startup\n");
673 /*-----------------------------------------------------------------*/
674 /* initialComments - puts in some initial comments */
675 /*-----------------------------------------------------------------*/
677 pic14initialComments (FILE * afile)
679 initialComments (afile);
680 fprintf (afile, "; PIC port for the 14-bit core\n");
681 fprintf (afile, iComments2);
685 /*-----------------------------------------------------------------*/
686 /* printExterns - generates extern for external variables */
687 /*-----------------------------------------------------------------*/
689 pic14printExterns (FILE * afile)
693 fprintf (afile, "%s", iComments2);
694 fprintf (afile, "; extern variables in this module\n");
695 fprintf (afile, "%s", iComments2);
697 for (sym = setFirstItem (externs); sym;
698 sym = setNextItem (externs))
699 fprintf (afile, "\textern %s\n", sym->rname);
702 /*-----------------------------------------------------------------*/
703 /* printPublics - generates .global for publics */
704 /*-----------------------------------------------------------------*/
706 pic14printPublics (FILE * afile)
710 fprintf (afile, "%s", iComments2);
711 fprintf (afile, "; publics variables in this module\n");
712 fprintf (afile, "%s", iComments2);
714 for (sym = setFirstItem (publics); sym;
715 sym = setNextItem (publics)) {
717 if(!IS_BITFIELD(sym->type) && ((IS_FUNC(sym->type) || sym->allocreq))) {
718 if (!IS_BITVAR(sym->type))
719 fprintf (afile, "\tglobal %s\n", sym->rname);
721 /* Absolute variables are defines in the asm file as equates and thus can not be made global. */
722 if (!SPEC_ABSA (sym->etype))
723 fprintf (afile, "\tglobal %s\n", sym->rname);
728 /*-----------------------------------------------------------------*/
729 /* emitOverlay - will emit code for the overlay stuff */
730 /*-----------------------------------------------------------------*/
732 pic14emitOverlay (FILE * afile)
736 /* if (!elementsInSet (ovrSetSets))*/
738 /* the hack below, fixes translates for devices which
739 * only have udata_shr memory */
740 fprintf (afile, "%s\t%s\n",
741 (elementsInSet(ovrSetSets)?"":";"),
742 port->mem.overlay_name);
744 /* for each of the sets in the overlay segment do */
745 for (ovrset = setFirstItem (ovrSetSets); ovrset;
746 ovrset = setNextItem (ovrSetSets))
751 if (elementsInSet (ovrset))
753 /* this dummy area is used to fool the assembler
754 otherwise the assembler will append each of these
755 declarations into one chunk and will not overlay
758 /* I don't think this applies to us. We are using gpasm. CRF */
760 fprintf (afile, ";\t.area _DUMMY\n");
761 /* output the area informtion */
762 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
765 for (sym = setFirstItem (ovrset); sym;
766 sym = setNextItem (ovrset))
769 /* if extern then do nothing */
770 if (IS_EXTERN (sym->etype))
773 /* if allocation required check is needed
774 then check if the symbol really requires
775 allocation only for local variables */
776 if (!IS_AGGREGATE (sym->type) &&
777 !(sym->_isparm && !IS_REGPARM (sym->etype))
778 && !sym->allocreq && sym->level)
781 /* if global variable & not static or extern
782 and addPublics allowed then add it to the public set */
783 if ((sym->_isparm && !IS_REGPARM (sym->etype))
784 && !IS_STATIC (sym->etype))
785 addSetHead (&publics, sym);
787 /* if extern then do nothing or is a function
789 if (IS_FUNC (sym->type))
792 /* print extra debug info if required */
793 if (options.debug || sym->level == 0)
797 if (IS_STATIC (sym->etype))
798 fprintf (afile, "F%s_", moduleName); /* scope is file */
800 fprintf (afile, "G_"); /* scope is global */
803 /* symbol is local */
804 fprintf (afile, "L%s_",
805 (sym->localof ? sym->localof->name : "-null-"));
806 fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
809 /* if is has an absolute address then generate
810 an equate for this no need to allocate space */
811 if (SPEC_ABSA (sym->etype))
814 if (options.debug || sym->level == 0)
815 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
817 fprintf (afile, "%s\t=\t0x%04x\n",
819 SPEC_ADDR (sym->etype));
823 if (options.debug || sym->level == 0)
824 fprintf (afile, "==.\n");
827 fprintf (afile, "%s:\n", sym->rname);
828 fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
836 /*-----------------------------------------------------------------*/
837 /* glue - the final glue that hold the whole thing together */
838 /*-----------------------------------------------------------------*/
845 FILE *ovrFile = tempfile();
847 addSetHead(&tmpfileSet,ovrFile);
848 pCodeInitRegisters();
850 if (mainf && IFFUNC_HASBODY(mainf->type)) {
852 pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
855 /* entry point @ start of CSEG */
856 addpCode2pBlock(pb,newpCodeLabel("__sdcc_program_startup",-1));
857 /* put in the call to main */
858 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp("_main",PO_STR)));
860 if (options.mainreturn) {
862 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will return to caller\n"));
863 addpCode2pBlock(pb,newpCode(POC_RETURN,NULL));
867 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will lock up\n"));
868 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("$",PO_STR)));
874 /* At this point we've got all the code in the form of pCode structures */
875 /* Now it needs to be rearranged into the order it should be placed in the */
878 movepBlock2Head('P'); // Last
879 movepBlock2Head(code->dbName);
880 movepBlock2Head('X');
881 movepBlock2Head(statsg->dbName); // First
884 /* print the global struct definitions */
890 addSetHead(&tmpfileSet,vFile);
892 /* emit code for the all the variables declared */
894 /* do the overlay segments */
895 pic14emitOverlay(ovrFile);
897 /* PENDING: this isnt the best place but it will do */
898 if (port->general.glue_up_main) {
899 /* create the interrupt vector table */
900 pic14createInterruptVect (vFile);
905 ReuseReg(); // ReuseReg where call tree permits
914 /* now put it all together into the assembler file */
915 /* create the assembler file name */
917 if ((noAssemble || options.c1mode) && fullDstFileName)
919 sprintf (buffer, fullDstFileName);
923 sprintf (buffer, dstFileName);
924 strcat (buffer, ".asm");
927 if (!(asmFile = fopen (buffer, "w"))) {
928 werror (E_FILE_OPEN_ERR, buffer);
932 /* initial comments */
933 pic14initialComments (asmFile);
935 /* print module name */
936 fprintf (asmFile, ";\t.module %s\n", moduleName);
938 /* Let the port generate any global directives, etc. */
939 if (port->genAssemblerPreamble)
941 port->genAssemblerPreamble(asmFile);
944 /* print the extern variables in this module */
945 pic14printExterns (asmFile);
947 /* print the global variables in this module */
948 pic14printPublics (asmFile);
950 /* copy the sfr segment */
951 fprintf (asmFile, "%s", iComments2);
952 fprintf (asmFile, "; special function registers\n");
953 fprintf (asmFile, "%s", iComments2);
954 copyFile (asmFile, sfr->oFile);
957 if (udata_section_name) {
958 sprintf(udata_name,"%s",udata_section_name);
960 sprintf(udata_name,"data_%s",moduleName);
962 fprintf (asmFile, "%s", iComments2);
963 fprintf (asmFile, "; udata\n");
964 fprintf (asmFile, "%s", iComments2);
965 fprintf (asmFile, "%s\tudata\n", udata_name);
966 copyFile (asmFile, data->oFile);
968 /* Put all variables into a cblock */
970 writeUsedRegs(asmFile);
972 /* create the overlay segments */
973 fprintf (asmFile, "%s", iComments2);
974 fprintf (asmFile, "; overlayable items in internal ram \n");
975 fprintf (asmFile, "%s", iComments2);
976 copyFile (asmFile, ovrFile);
980 /* create the stack segment MOF */
981 if (mainf && IFFUNC_HASBODY(mainf->type)) {
982 fprintf (asmFile, "%s", iComments2);
983 fprintf (asmFile, "; Stack segment in internal ram \n");
984 fprintf (asmFile, "%s", iComments2);
985 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
986 ";__start__stack:\n;\t.ds\t1\n\n");
989 /* create the idata segment */
990 fprintf (asmFile, "%s", iComments2);
991 fprintf (asmFile, "; indirectly addressable internal ram data\n");
992 fprintf (asmFile, "%s", iComments2);
993 copyFile (asmFile, idata->oFile);
995 /* if external stack then reserve space of it */
996 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
997 fprintf (asmFile, "%s", iComments2);
998 fprintf (asmFile, "; external stack \n");
999 fprintf (asmFile, "%s", iComments2);
1000 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1001 fprintf (asmFile,";\t.ds 256\n");
1004 /* copy xtern ram data */
1005 fprintf (asmFile, "%s", iComments2);
1006 fprintf (asmFile, "; external ram data\n");
1007 fprintf (asmFile, "%s", iComments2);
1008 copyFile (asmFile, xdata->oFile);
1012 /* copy the bit segment */
1013 fprintf (asmFile, "%s", iComments2);
1014 fprintf (asmFile, "; bit data\n");
1015 fprintf (asmFile, "%s", iComments2);
1016 copyFile (asmFile, bit->oFile);
1018 /* copy the interrupt vector table */
1019 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1020 copyFile (asmFile, vFile);
1022 fprintf (asmFile, "%s", iComments2);
1023 fprintf (asmFile, "; interrupt and initialization code\n");
1024 fprintf (asmFile, "%s", iComments2);
1025 fprintf (asmFile, "code_init\t%s\t0x4\n", CODE_NAME); // Note - for mplink may have to enlarge section vectors in .lnk file
1027 /* interrupt service routine */
1028 fprintf (asmFile, "__sdcc_interrupt:\n");
1029 copypCode(asmFile, 'I');
1031 /* initialize data memory */
1032 fprintf (asmFile,"__sdcc_gsinit_startup:\n");
1033 /* FIXME: This is temporary. The idata section should be used. If
1034 not, we could add a special feature to the linker. This will
1035 work in the mean time. Put all initalized data in main.c */
1036 copypCode(asmFile, statsg->dbName);
1037 fprintf (asmFile,"\tpagesel _main\n");
1038 fprintf (asmFile,"\tgoto _main\n");
1043 /* copy global & static initialisations */
1044 fprintf (asmFile, "%s", iComments2);
1045 fprintf (asmFile, "; global & static initialisations\n");
1046 fprintf (asmFile, "%s", iComments2);
1047 copypCode(asmFile, statsg->dbName);
1051 /* copy over code */
1052 fprintf (asmFile, "%s", iComments2);
1053 fprintf (asmFile, "; code\n");
1054 fprintf (asmFile, "%s", iComments2);
1055 fprintf (asmFile, "code_%s\t%s\n", moduleName, port->mem.code_name);
1058 copypCode(asmFile, 'X');
1060 /* _main function */
1061 copypCode(asmFile, 'M');
1063 /* other functions */
1064 copypCode(asmFile, code->dbName);
1067 copypCode(asmFile, 'P');
1069 fprintf (asmFile,"\tend\n");