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"
29 extern symbol *interrupts[256];
30 void printIval (symbol *, sym_link *, initList *, FILE *);
33 extern int maxInterrupts;
34 extern int maxRegBank ;
36 extern char *VersionString;
37 extern FILE *codeOutFile;
38 extern set *tmpfileSet;
39 extern set *tmpfileNameSet;
40 extern char *iComments1;
41 extern char *iComments2;
42 //extern void emitStaticSeg (memmap * map);
44 extern DEFSETFUNC(closeTmpFiles);
45 extern DEFSETFUNC(rmTmpFiles);
47 extern void copyFile (FILE * dest, FILE * src);
50 //extern void emitMaps ();
51 //extern void createInterruptVect (FILE * vFile);
52 extern void initialComments (FILE * afile);
53 extern void printPublics (FILE * afile);
55 extern void printChar (FILE * ofile, char *s, int plen);
58 char *aopLiteral (value *val, int offset)
59 static void emitRegularMap (memmap * map, bool addPublics, bool arFlag)
60 value *initPointer (initList *ilist)
61 void printIvalType (sym_link * type, initList * ilist, FILE * oFile)
62 void printIvalStruct (symbol * sym,sym_link * type,
63 initList * ilist, FILE * oFile)
64 int printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s)
65 void printIvalArray (symbol * sym, sym_link * type, initList * ilist,
67 void printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
68 int printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
69 void printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
73 /*-----------------------------------------------------------------*/
74 /* aopLiteral - string from a literal value */
75 /*-----------------------------------------------------------------*/
76 char *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 = floatFromVal(val);
90 sprintf(buffer,"0x%02x",((char) v) & 0xff);
91 ALLOC_ATOMIC(rs,strlen(buffer)+1);
92 return strcpy (rs,buffer);
95 /* it is type float */
96 fl.f = (float) floatFromVal(val);
98 sprintf(buffer,"0x%02x",fl.c[3-offset]);
100 sprintf(buffer,"0x%02x",fl.c[offset]);
102 ALLOC_ATOMIC(rs,strlen(buffer)+1);
103 return strcpy (rs,buffer);
107 /*-----------------------------------------------------------------*/
108 /* emitRegularMap - emit code for maps with no special cases */
109 /*-----------------------------------------------------------------*/
110 static void pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag)
113 int i,size,bitvars=0;;
116 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
118 /* print the area name */
119 for (sym = setFirstItem (map->syms); sym;
120 sym = setNextItem (map->syms)) {
122 /* if extern then do nothing */
123 if (IS_EXTERN (sym->etype))
126 /* if allocation required check is needed
127 then check if the symbol really requires
128 allocation only for local variables */
129 if (arFlag && !IS_AGGREGATE(sym->type) &&
130 !(sym->_isparm && !IS_REGPARM(sym->etype)) &&
131 !sym->allocreq && sym->level)
134 /* if global variable & not static or extern
135 and addPublics allowed then add it to the public set */
136 if ((sym->level == 0 ||
137 (sym->_isparm && !IS_REGPARM(sym->etype))) &&
139 !IS_STATIC (sym->etype))
140 addSetHead (&publics, sym);
142 /* if extern then do nothing or is a function
144 if (IS_FUNC (sym->type))
147 /* print extra debug info if required */
148 if (options.debug || sym->level == 0) {
150 cdbSymbol(sym,cdbFile,FALSE,FALSE);
152 if (!sym->level) /* global */
153 if (IS_STATIC(sym->etype))
154 fprintf(map->oFile,"F%s_",moduleName); /* scope is file */
156 fprintf(map->oFile,"G_"); /* scope is global */
158 /* symbol is local */
159 fprintf(map->oFile,"L%s_",(sym->localof ? sym->localof->name : "-null-"));
160 fprintf(map->oFile,"%s_%d_%d",sym->name,sym->level,sym->block);
164 /* if is has an absolute address then generate
165 an equate for this no need to allocate space */
166 if (SPEC_ABSA (sym->etype)) {
167 //if (options.debug || sym->level == 0)
168 //fprintf (map->oFile,"; == 0x%04x\n",SPEC_ADDR (sym->etype));
170 fprintf (map->oFile, "%s\tEQU\t0x%04x\n",
172 SPEC_ADDR (sym->etype));
177 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
178 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
179 /* by grouping the bits together into groups of 8 and storing them in the normal ram.*/
180 if(IS_BITVAR(sym->etype)) {
181 if((bitvars % 8) == 0) {
182 fprintf (map->oFile, " cblock\n");
183 fprintf (map->oFile, "\tbitfield%d\n", bitvars);
184 fprintf (map->oFile, " endc\n");
187 fprintf (map->oFile, "%s\tEQU\t( (bitfield%d<<3)+%d)\n",
194 fprintf (map->oFile, "\t%s\n", sym->rname);
195 if( (size = (unsigned int)getSize (sym->type) & 0xffff)>1) {
196 for(i=1; i<size; i++)
197 fprintf (map->oFile, "\t%s_%d\n", sym->rname,i);
200 //fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
203 /* if it has a initial value then do it only if
204 it is a global variable */
205 if (sym->ival && sym->level == 0) {
208 if (IS_AGGREGATE (sym->type))
209 ival = initAggregates (sym, sym->ival, NULL);
211 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
212 decorateType (resolveSymbols (list2expr (sym->ival))));
213 codeOutFile = statsg->oFile;
214 eBBlockFromiCode (iCodeFromAst (ival));
222 /*-----------------------------------------------------------------*/
223 /* initPointer - pointer initialization code massaging */
224 /*-----------------------------------------------------------------*/
225 value *initPointer (initList *ilist)
228 ast *expr = list2expr(ilist);
233 /* try it the oldway first */
234 if ((val = constExprValue(expr,FALSE)))
237 /* no then we have to do these cludgy checks */
238 /* pointers can be initialized with address of
239 a variable or address of an array element */
240 if (IS_AST_OP(expr) && expr->opval.op == '&') {
241 /* address of symbol */
242 if (IS_AST_SYM_VALUE(expr->left)) {
243 val = copyValue(AST_VALUE(expr->left));
244 val->type = newLink();
245 if (SPEC_SCLS(expr->left->etype) == S_CODE) {
246 DCL_TYPE(val->type) = CPOINTER ;
247 DCL_PTR_CONST(val->type) = port->mem.code_ro;
250 if (SPEC_SCLS(expr->left->etype) == S_XDATA)
251 DCL_TYPE(val->type) = FPOINTER;
253 if (SPEC_SCLS(expr->left->etype) == S_XSTACK )
254 DCL_TYPE(val->type) = PPOINTER ;
256 if (SPEC_SCLS(expr->left->etype) == S_IDATA)
257 DCL_TYPE(val->type) = IPOINTER ;
259 if (SPEC_SCLS(expr->left->etype) == S_EEPROM)
260 DCL_TYPE(val->type) = EEPPOINTER ;
262 DCL_TYPE(val->type) = POINTER ;
263 val->type->next = expr->left->ftype;
264 val->etype = getSpec(val->type);
268 /* if address of indexed array */
269 if (IS_AST_OP(expr->left) && expr->left->opval.op == '[')
270 return valForArray(expr->left);
272 /* if address of structure element then
274 if (IS_AST_OP(expr->left) &&
275 expr->left->opval.op == '.' ) {
276 return valForStructElem(expr->left->left,
281 (&some_struct)->element */
282 if (IS_AST_OP(expr->left) &&
283 expr->left->opval.op == PTR_OP &&
284 IS_ADDRESS_OF_OP(expr->left->left))
285 return valForStructElem(expr->left->left->left,
290 werror(E_INIT_WRONG);
295 /*-----------------------------------------------------------------*/
296 /* printChar - formats and prints a characater string with DB */
297 /*-----------------------------------------------------------------*/
298 void printChar (FILE * ofile, char *s, int plen)
301 int len = strlen (s);
304 while (len && pplen < plen) {
306 fprintf (ofile, "\t.ascii /");
308 while (i && *s && pplen < plen) {
309 if (*s < ' ' || *s == '/') {
310 fprintf (ofile, "/\n\t.byte 0x%02x\n\t.ascii /", *s++);
313 fprintf (ofile, "%c", *s++);
317 fprintf (ofile, "/\n");
325 fprintf(ofile,"\t.byte\t0\n");
328 /*-----------------------------------------------------------------*/
329 /* printIvalType - generates ival for int/char */
330 /*-----------------------------------------------------------------*/
331 void printIvalType (sym_link * type, initList * ilist, FILE * oFile)
335 /* if initList is deep */
336 if (ilist->type == INIT_DEEP)
337 ilist = ilist->init.deep;
339 val = list2val (ilist);
340 switch (getSize (type)) {
343 fprintf (oFile, "\t.byte 0\n");
345 fprintf (oFile, "\t.byte %s\n",
346 aopLiteral (val, 0));
351 fprintf (oFile, "\t.word 0\n");
353 fprintf (oFile, "\t.byte %s,%s\n",
354 aopLiteral (val, 0), aopLiteral (val, 1));
359 fprintf (oFile, "\t.word 0,0\n");
361 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
362 aopLiteral (val, 0), aopLiteral (val, 1),
363 aopLiteral (val, 2), aopLiteral (val, 3));
370 /*-----------------------------------------------------------------*/
371 /* printIvalStruct - generates initial value for structures */
372 /*-----------------------------------------------------------------*/
373 void printIvalStruct (symbol * sym,sym_link * type,
374 initList * ilist, FILE * oFile)
379 sflds = SPEC_STRUCT (type)->fields;
380 if (ilist->type != INIT_DEEP) {
381 werror (E_INIT_STRUCT, sym->name);
385 iloop = ilist->init.deep;
387 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
388 printIval (sflds, sflds->type, iloop, oFile);
393 /*-----------------------------------------------------------------*/
394 /* printIvalChar - generates initital value for character array */
395 /*-----------------------------------------------------------------*/
396 int printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s)
403 val = list2val (ilist);
404 /* if the value is a character string */
405 if (IS_ARRAY (val->type) && IS_CHAR (val->etype)) {
406 if (!DCL_ELEM (type))
407 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
409 /* if size mismatch */
410 /* if (DCL_ELEM (type) < ((int) strlen (SPEC_CVAL (val->etype).v_char) + 1)) */
411 /* werror (E_ARRAY_BOUND); */
413 printChar (oFile, SPEC_CVAL (val->etype).v_char,DCL_ELEM(type));
415 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) -1))>0)
417 fprintf (oFile, "\t.byte 0\n");
425 printChar (oFile, s,strlen(s)+1);
429 /*-----------------------------------------------------------------*/
430 /* printIvalArray - generates code for array initialization */
431 /*-----------------------------------------------------------------*/
432 void printIvalArray (symbol * sym, sym_link * type, initList * ilist,
436 int lcnt = 0, size = 0;
438 /* take care of the special case */
439 /* array of characters can be init */
441 if (IS_CHAR (type->next))
442 if (printIvalChar (type,
443 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
444 oFile, SPEC_CVAL (sym->etype).v_char))
447 /* not the special case */
448 if (ilist->type != INIT_DEEP) {
449 werror (E_INIT_STRUCT, sym->name);
453 iloop = ilist->init.deep;
454 lcnt = DCL_ELEM (type);
458 printIval (sym, type->next, iloop, oFile);
459 iloop = (iloop ? iloop->next : NULL);
462 /* if not array limits given & we */
463 /* are out of initialisers then */
464 if (!DCL_ELEM (type) && !iloop)
467 /* no of elements given and we */
468 /* have generated for all of them */
473 /* if we have not been given a size */
474 if (!DCL_ELEM (type))
475 DCL_ELEM (type) = size;
480 /*-----------------------------------------------------------------*/
481 /* printIvalFuncPtr - generate initial value for function pointers */
482 /*-----------------------------------------------------------------*/
483 void printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
488 val = list2val (ilist);
489 /* check the types */
490 if ((dLvl = checkType (val->type, type->next)) <= 0) {
492 fprintf (oFile, "\t.word 0\n");
496 /* now generate the name */
498 if (IS_LITERAL (val->etype))
499 fprintf (oFile, "\t.byte %s,%s\n",
500 aopLiteral (val, 0), aopLiteral (val, 1));
502 fprintf (oFile, "\t.byte %s,(%s >> 8)\n",
503 val->name, val->name);
506 fprintf (oFile, "\t.byte %s,(%s >> 8)\n",
507 val->sym->rname, val->sym->rname);
512 /*-----------------------------------------------------------------*/
513 /* printIvalCharPtr - generates initial values for character pointers */
514 /*-----------------------------------------------------------------*/
515 int printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
519 size = getSize (type);
523 "\t.byte %s", val->name) ;
526 "\t.byte %s,(%s >> 8)",
527 val->name, val->name);
530 fprintf (oFile, ",#0x02\n");
532 fprintf (oFile, "\n");
534 if (val->sym && val->sym->isstrlit)
535 addSet (&statsg->syms, val->sym);
540 /*-----------------------------------------------------------------*/
541 /* printIvalPtr - generates initial value for pointers */
542 /*-----------------------------------------------------------------*/
543 void printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
548 if (ilist->type == INIT_DEEP)
549 ilist = ilist->init.deep;
551 /* function pointer */
552 if (IS_FUNC (type->next)) {
553 printIvalFuncPtr (type, ilist, oFile);
557 if (!(val = initPointer (ilist)))
560 /* if character pointer */
561 if (IS_CHAR (type->next))
562 if (printIvalCharPtr (sym, type, val, oFile))
566 if (checkType (type, val->type) != 1)
567 werror (E_INIT_WRONG);
569 /* if val is literal */
570 if (IS_LITERAL (val->etype)) {
571 switch (getSize (type)) {
573 fprintf (oFile, "\t.byte 0x%02x\n", ((char) floatFromVal (val)) & 0xff);
576 fprintf (oFile, "\t.byte %s,%s\n",
577 aopLiteral (val, 0), aopLiteral (val, 1));
581 fprintf (oFile, "\t.byte %s,%s,0x%02x\n",
582 aopLiteral (val, 0), aopLiteral (val, 1), CPOINTER);
588 switch (getSize (type)) {
590 fprintf (oFile, "\t.byte %s\n", val->name);
593 fprintf (oFile, "\t.byte %s,(%s >> 8)\n", val->name, val->name);
597 fprintf (oFile, "\t.byte %s,(%s >> 8),0x%02x\n",
598 val->name, val->name, DCL_TYPE(val->type));
603 /*-----------------------------------------------------------------*/
604 /* printIval - generates code for initial value */
605 /*-----------------------------------------------------------------*/
606 void printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
611 /* if structure then */
612 if (IS_STRUCT (type)) {
613 printIvalStruct (sym, type, ilist, oFile);
617 /* if this is a pointer */
619 printIvalPtr (sym, type, ilist, oFile);
623 /* if this is an array */
624 if (IS_ARRAY (type)) {
625 printIvalArray (sym, type, ilist, oFile);
629 /* if type is SPECIFIER */
630 if (IS_SPEC (type)) {
631 printIvalType (type, ilist, oFile);
637 /*-----------------------------------------------------------------*/
638 /* emitStaticSeg - emitcode for the static segment */
639 /*-----------------------------------------------------------------*/
640 static void pic14emitStaticSeg (memmap * map)
644 fprintf(map->oFile,";\t.area\t%s\n",map->sname);
647 /* for all variables in this segment do */
648 for (sym = setFirstItem (map->syms); sym;
649 sym = setNextItem (map->syms)) {
651 /* if it is "extern" then do nothing */
652 if (IS_EXTERN (sym->etype))
655 /* if it is not static add it to the public
657 if (!IS_STATIC (sym->etype))
658 addSetHead (&publics, sym);
660 /* print extra debug info if required */
661 if (options.debug || sym->level == 0) {
663 cdbSymbol(sym,cdbFile,FALSE,FALSE);
665 if (!sym->level) { /* global */
666 if (IS_STATIC(sym->etype))
667 fprintf(code->oFile,"F%s_",moduleName); /* scope is file */
669 fprintf(code->oFile,"G_"); /* scope is global */
672 /* symbol is local */
673 fprintf(code->oFile,"L%s_",
674 (sym->localof ? sym->localof->name : "-null-"));
675 fprintf(code->oFile,"%s_%d_%d",sym->name,sym->level,sym->block);
678 /* if it has an absolute address */
679 if (SPEC_ABSA (sym->etype)) {
680 if (options.debug || sym->level == 0)
681 fprintf(code->oFile," == 0x%04x\n", SPEC_ADDR (sym->etype));
683 fprintf (code->oFile, "%s\t=\t0x%04x\n",
685 SPEC_ADDR (sym->etype));
688 if (options.debug || sym->level == 0)
689 fprintf(code->oFile," == .\n");
691 /* if it has an initial value */
693 fprintf (code->oFile, "%s:\n", sym->rname);
695 resolveIvalSym (sym->ival);
696 printIval (sym, sym->type, sym->ival, code->oFile);
701 fprintf (code->oFile, "%s:\n", sym->rname);
702 /* special case for character strings */
703 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
704 SPEC_CVAL (sym->etype).v_char)
705 printChar (code->oFile,
706 SPEC_CVAL (sym->etype).v_char,
707 strlen(SPEC_CVAL (sym->etype).v_char)+1);
709 fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type)& 0xffff);
716 /*-----------------------------------------------------------------*/
717 /* emitMaps - emits the code for the data portion the code */
718 /*-----------------------------------------------------------------*/
719 static void pic14emitMaps ()
721 /* no special considerations for the following
722 data, idata & bit & xdata */
723 pic14emitRegularMap (data, TRUE, TRUE);
724 pic14emitRegularMap (idata, TRUE,TRUE);
725 pic14emitRegularMap (bit, TRUE,FALSE);
726 pic14emitRegularMap (xdata, TRUE,TRUE);
727 pic14emitRegularMap (sfr, FALSE,FALSE);
728 pic14emitRegularMap (sfrbit, FALSE,FALSE);
729 pic14emitRegularMap (code, TRUE,FALSE);
730 pic14emitStaticSeg (statsg);
733 /*-----------------------------------------------------------------*/
734 /* createInterruptVect - creates the interrupt vector */
735 /*-----------------------------------------------------------------*/
736 static void pic14createInterruptVect (FILE * vFile)
739 mainf = newSymbol ("main", 0);
742 /* only if the main function exists */
743 if (!(mainf = findSymWithLevel (SymbolTab, mainf))) {
744 if (!options.cc_only)
749 /* if the main is only a prototype ie. no body then do nothing */
751 /* if ! compile only then main function should be present */
752 if (!options.cc_only)
757 fprintf (vFile, ";\t.area\t%s\n", CODE_NAME);
758 fprintf (vFile, ";__interrupt_vect:\n");
761 if (!port->genIVT || ! (port->genIVT(vFile, interrupts, maxInterrupts)))
763 /* "generic" interrupt table header (if port doesn't specify one).
765 * Look suspiciously like 8051 code to me...
768 fprintf (vFile, ";\tljmp\t__sdcc_gsinit_startup\n");
771 /* now for the other interrupts */
772 for (; i < maxInterrupts; i++) {
774 fprintf (vFile, ";\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
776 fprintf (vFile, ";\treti\n;\t.ds\t7\n");
782 /*-----------------------------------------------------------------*/
783 /* initialComments - puts in some initial comments */
784 /*-----------------------------------------------------------------*/
785 static void pic14initialComments (FILE * afile)
787 initialComments(afile);
788 fprintf (afile, "; PIC port for the 14-bit core\n" );
789 fprintf (afile, iComments2);
793 /*-----------------------------------------------------------------*/
794 /* printPublics - generates .global for publics */
795 /*-----------------------------------------------------------------*/
796 static void pic14printPublics (FILE * afile)
800 fprintf (afile, "%s", iComments2);
801 fprintf (afile, "; publics variables in this module\n");
802 fprintf (afile, "%s", iComments2);
804 for (sym = setFirstItem (publics); sym;
805 sym = setNextItem (publics))
806 fprintf (afile, ";\t.globl %s\n", sym->rname);
811 /*-----------------------------------------------------------------*/
812 /* emitOverlay - will emit code for the overlay stuff */
813 /*-----------------------------------------------------------------*/
814 static void pic14emitOverlay(FILE *afile)
818 if (!elementsInSet(ovrSetSets))
819 fprintf(afile,";\t.area\t%s\n", port->mem.overlay_name);
821 /* for each of the sets in the overlay segment do */
822 for (ovrset = setFirstItem(ovrSetSets); ovrset;
823 ovrset = setNextItem(ovrSetSets)) {
827 if (elementsInSet(ovrset)) {
828 /* this dummy area is used to fool the assembler
829 otherwise the assembler will append each of these
830 declarations into one chunk and will not overlay
832 fprintf(afile,";\t.area _DUMMY\n");
833 /* output the area informtion */
834 fprintf(afile,";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
837 for (sym = setFirstItem(ovrset); sym;
838 sym = setNextItem(ovrset)) {
840 /* if extern then do nothing */
841 if (IS_EXTERN (sym->etype))
844 /* if allocation required check is needed
845 then check if the symbol really requires
846 allocation only for local variables */
847 if (!IS_AGGREGATE(sym->type) &&
848 !(sym->_isparm && !IS_REGPARM(sym->etype))
849 && !sym->allocreq && sym->level)
852 /* if global variable & not static or extern
853 and addPublics allowed then add it to the public set */
854 if ((sym->_isparm && !IS_REGPARM(sym->etype))
855 && !IS_STATIC (sym->etype))
856 addSetHead (&publics, sym);
858 /* if extern then do nothing or is a function
860 if (IS_FUNC (sym->type))
863 /* print extra debug info if required */
864 if (options.debug || sym->level == 0) {
866 cdbSymbol(sym,cdbFile,FALSE,FALSE);
868 if (!sym->level) { /* global */
869 if (IS_STATIC(sym->etype))
870 fprintf(afile,"F%s_",moduleName); /* scope is file */
872 fprintf(afile,"G_"); /* scope is global */
875 /* symbol is local */
876 fprintf(afile,"L%s_",
877 (sym->localof ? sym->localof->name : "-null-"));
878 fprintf(afile,"%s_%d_%d",sym->name,sym->level,sym->block);
881 /* if is has an absolute address then generate
882 an equate for this no need to allocate space */
883 if (SPEC_ABSA (sym->etype)) {
885 if (options.debug || sym->level == 0)
886 fprintf (afile," == 0x%04x\n",SPEC_ADDR (sym->etype));
888 fprintf (afile, "%s\t=\t0x%04x\n",
890 SPEC_ADDR (sym->etype));
893 if (options.debug || sym->level == 0)
894 fprintf(afile,"==.\n");
897 fprintf (afile, "%s:\n", sym->rname);
898 fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
907 /*-----------------------------------------------------------------*/
908 /* glue - the final glue that hold the whole thing together */
909 /*-----------------------------------------------------------------*/
914 FILE *ovrFile = tempfile();
917 addSetHead(&tmpfileSet,ovrFile);
918 /* print the global struct definitions */
920 cdbStructBlock (0,cdbFile);
923 /* PENDING: this isnt the best place but it will do */
924 if (port->general.glue_up_main) {
925 /* create the interrupt vector table */
926 pic14createInterruptVect (vFile);
929 addSetHead(&tmpfileSet,vFile);
931 /* emit code for the all the variables declared */
933 /* do the overlay segments */
934 pic14emitOverlay(ovrFile);
936 /* now put it all together into the assembler file */
937 /* create the assembler file name */
939 if (!options.c1mode) {
940 sprintf (buffer, srcFileName);
941 strcat (buffer, ".asm");
944 strcpy(buffer, options.out_name);
947 if (!(asmFile = fopen (buffer, "w"))) {
948 werror (E_FILE_OPEN_ERR, buffer);
952 /* initial comments */
953 pic14initialComments (asmFile);
955 /* print module name */
956 fprintf (asmFile, ";\t.module %s\n", moduleName);
958 /* Let the port generate any global directives, etc. */
959 if (port->genAssemblerPreamble)
961 port->genAssemblerPreamble(asmFile);
964 /* print the global variables in this module */
965 pic14printPublics (asmFile);
968 /* copy the sfr segment */
969 fprintf (asmFile, "%s", iComments2);
970 fprintf (asmFile, "; special function registers\n");
971 fprintf (asmFile, "%s", iComments2);
972 copyFile (asmFile, sfr->oFile);
975 /* Put all variables into a cblock */
976 fprintf (asmFile, "\n\n\tcblock 0x13\n\n");
978 for(i=0; i<pic14_nRegs; i++) {
979 if(regspic14[i].wasUsed && (regspic14[i].offset>=0x0c) )
980 fprintf (asmFile, "\t%s\n",regspic14[i].name);
982 //fprintf (asmFile, "\tr0x0C\n");
983 //fprintf (asmFile, "\tr0x0D\n");
985 /* For now, create a "dpl" and a "dph" in the register space */
986 /* of the pic so that we can use the same calling mechanism */
987 /* as the 8051 port */
988 fprintf (asmFile, "%s", iComments2);
989 fprintf (asmFile, "; dpl and dph to emulate the 8051 calling mechanism \n");
990 fprintf (asmFile, "%s", iComments2);
992 fprintf (asmFile, "\tdph\n");
996 /* copy the sbit segment */
997 fprintf (asmFile, "%s", iComments2);
998 fprintf (asmFile, "; special function bits \n");
999 fprintf (asmFile, "%s", iComments2);
1000 copyFile (asmFile, sfrbit->oFile);
1002 /* copy the data segment */
1003 fprintf (asmFile, "%s", iComments2);
1004 fprintf (asmFile, "; internal ram data\n");
1005 fprintf (asmFile, "%s", iComments2);
1006 copyFile (asmFile, data->oFile);
1009 /* create the overlay segments */
1010 fprintf (asmFile, "%s", iComments2);
1011 fprintf (asmFile, "; overlayable items in internal ram \n");
1012 fprintf (asmFile, "%s", iComments2);
1013 copyFile (asmFile, ovrFile);
1015 /* create the stack segment MOF */
1016 if (mainf && mainf->fbody) {
1017 fprintf (asmFile, "%s", iComments2);
1018 fprintf (asmFile, "; Stack segment in internal ram \n");
1019 fprintf (asmFile, "%s", iComments2);
1020 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1021 ";__start__stack:\n;\t.ds\t1\n\n");
1024 /* create the idata segment */
1025 fprintf (asmFile, "%s", iComments2);
1026 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1027 fprintf (asmFile, "%s", iComments2);
1028 copyFile (asmFile, idata->oFile);
1030 /* if external stack then reserve space of it */
1031 if (mainf && mainf->fbody && options.useXstack ) {
1032 fprintf (asmFile, "%s", iComments2);
1033 fprintf (asmFile, "; external stack \n");
1034 fprintf (asmFile, "%s", iComments2);
1035 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1036 fprintf (asmFile,";\t.ds 256\n");
1040 /* copy xtern ram data */
1041 fprintf (asmFile, "%s", iComments2);
1042 fprintf (asmFile, "; external ram data\n");
1043 fprintf (asmFile, "%s", iComments2);
1044 copyFile (asmFile, xdata->oFile);
1047 fprintf (asmFile, "\tendc\n");
1050 /* copy the bit segment */
1051 fprintf (asmFile, "%s", iComments2);
1052 fprintf (asmFile, "; bit data\n");
1053 fprintf (asmFile, "%s", iComments2);
1054 copyFile (asmFile, bit->oFile);
1057 fprintf (asmFile, "\tORG 0\n");
1059 /* copy the interrupt vector table */
1060 if (mainf && mainf->fbody) {
1061 fprintf (asmFile, "%s", iComments2);
1062 fprintf (asmFile, "; interrupt vector \n");
1063 fprintf (asmFile, "%s", iComments2);
1064 copyFile (asmFile, vFile);
1067 /* copy global & static initialisations */
1068 fprintf (asmFile, "%s", iComments2);
1069 fprintf (asmFile, "; global & static initialisations\n");
1070 fprintf (asmFile, "%s", iComments2);
1072 /* Everywhere we generate a reference to the static_name area,
1073 * (which is currently only here), we immediately follow it with a
1074 * definition of the post_static_name area. This guarantees that
1075 * the post_static_name area will immediately follow the static_name
1078 fprintf (asmFile, ";\t.area %s\n", port->mem.static_name); /* MOF */
1079 fprintf (asmFile, ";\t.area %s\n", port->mem.post_static_name);
1080 fprintf (asmFile, ";\t.area %s\n", port->mem.static_name);
1082 if (mainf && mainf->fbody) {
1083 fprintf (asmFile,"__sdcc_gsinit_startup:\n");
1084 /* if external stack is specified then the
1085 higher order byte of the xdatalocation is
1086 going into P2 and the lower order going into
1088 if (options.useXstack) {
1089 fprintf(asmFile,";\tmov\tP2,#0x%02x\n",
1090 (((unsigned int)options.xdata_loc) >> 8) & 0xff);
1091 fprintf(asmFile,";\tmov\t_spx,#0x%02x\n",
1092 (unsigned int)options.xdata_loc & 0xff);
1095 /* initialise the stack pointer */
1096 /* if the user specified a value then use it */
1097 if (options.stack_loc)
1098 fprintf(asmFile,";\tmov\tsp,#%d\n",options.stack_loc);
1100 /* no: we have to compute it */
1101 if (!options.stackOnData && maxRegBank <= 3)
1102 fprintf(asmFile,";\tmov\tsp,#%d\n",((maxRegBank + 1) * 8) -1);
1104 fprintf(asmFile,";\tmov\tsp,#__start__stack\n"); /* MOF */
1106 fprintf (asmFile,";\tlcall\t__sdcc_external_startup\n");
1107 fprintf (asmFile,";\tmov\ta,dpl\n");
1108 fprintf (asmFile,";\tjz\t__sdcc_init_data\n");
1109 fprintf (asmFile,";\tljmp\t__sdcc_program_startup\n");
1110 fprintf (asmFile,";__sdcc_init_data:\n");
1113 copyFile (asmFile, statsg->oFile);
1115 if (port->general.glue_up_main && mainf && mainf->fbody)
1117 /* This code is generated in the post-static area.
1118 * This area is guaranteed to follow the static area
1119 * by the ugly shucking and jiving about 20 lines ago.
1121 fprintf(asmFile, ";\t.area %s\n", port->mem.post_static_name);
1122 fprintf (asmFile,";\tljmp\t__sdcc_program_startup\n");
1125 /* copy over code */
1126 fprintf (asmFile, "%s", iComments2);
1127 fprintf (asmFile, "; code\n");
1128 fprintf (asmFile, "%s", iComments2);
1129 fprintf (asmFile, ";\t.area %s\n", port->mem.code_name);
1130 if (mainf && mainf->fbody) {
1132 /* entry point @ start of CSEG */
1133 fprintf (asmFile,"__sdcc_program_startup:\n");
1135 /* put in the call to main */
1136 fprintf(asmFile,"\tcall\t_main\n");
1137 if (options.mainreturn) {
1139 fprintf(asmFile,";\treturn from main ; will return to caller\n");
1140 fprintf(asmFile,"\treturn\n");
1144 fprintf(asmFile,";\treturn from main will lock up\n");
1145 fprintf(asmFile,"\tgoto\t$\n");
1148 copyFile (asmFile, code->oFile);
1150 fprintf (asmFile,"\tend\n");
1153 applyToSet(tmpfileSet,closeTmpFiles);
1154 applyToSet(tmpfileNameSet, rmTmpFiles);