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 extern symbol *interrupts[256];
33 void printIval (symbol *, sym_link *, initList *, FILE *);
36 extern int maxInterrupts;
37 extern int maxRegBank;
39 extern char *VersionString;
40 extern FILE *codeOutFile;
41 extern set *tmpfileSet;
42 extern set *tmpfileNameSet;
43 extern char *iComments1;
44 extern char *iComments2;
45 //extern void emitStaticSeg (memmap * map);
47 extern DEFSETFUNC (closeTmpFiles);
48 extern DEFSETFUNC (rmTmpFiles);
50 extern void copyFile (FILE * dest, FILE * src);
53 //extern void emitMaps ();
54 //extern void createInterruptVect (FILE * vFile);
55 extern void initialComments (FILE * afile);
56 extern void printPublics (FILE * afile);
58 extern void printChar (FILE * ofile, char *s, int plen);
62 aopLiteral (value * val, int offset)
63 static void emitRegularMap (memmap * map, bool addPublics, bool arFlag)
64 value *initPointer (initList * ilist)
65 void printIvalType (sym_link * type, initList * ilist, FILE * oFile)
66 void printIvalStruct (symbol * sym, sym_link * type,
67 initList * ilist, FILE * oFile)
68 int printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s)
69 void printIvalArray (symbol * sym, sym_link * type, initList * ilist,
71 void printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
72 int printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
73 void printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
76 /*-----------------------------------------------------------------*/
77 /* Allocation macros that replace those in SDCCalloc.h */
78 /* Why? I dunno. I ran across a bug with those macros that */
79 /* I couldn't fix, but I could work around... */
80 /*-----------------------------------------------------------------*/
82 #define _ALLOC(x,sz) if (!(x = calloc((sz),1) )) \
84 werror(E_OUT_OF_MEM,__FILE__,(long) sz);\
88 #define _ALLOC_ATOMIC(x,y) if (!((x) = malloc(y))) \
90 werror(E_OUT_OF_MEM,__FILE__,(long) y); \
95 /*-----------------------------------------------------------------*/
96 /* aopLiteral - string from a literal value */
97 /*-----------------------------------------------------------------*/
98 int pic14aopLiteral (value *val, int offset)
105 /* if it is a float then it gets tricky */
106 /* otherwise it is fairly simple */
107 if (!IS_FLOAT(val->type)) {
108 unsigned long v = floatFromVal(val);
110 //v >>= (offset * 8);
111 return ( (v >> (offset * 8)) & 0xff);
112 //sprintf(buffer,"0x%02x",((char) v) & 0xff);
113 //_ALLOC_ATOMIC(rs,strlen(buffer)+1);
114 //return strcpy (rs,buffer);
117 /* it is type float */
118 fl.f = (float) floatFromVal(val);
120 return fl.c[3-offset];
128 /*-----------------------------------------------------------------*/
129 /* emitRegularMap - emit code for maps with no special cases */
130 /*-----------------------------------------------------------------*/
132 pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag)
135 int i, size, bitvars = 0;;
138 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
140 /* print the area name */
141 for (sym = setFirstItem (map->syms); sym;
142 sym = setNextItem (map->syms))
145 /* if extern then do nothing */
146 if (IS_EXTERN (sym->etype))
149 /* if allocation required check is needed
150 then check if the symbol really requires
151 allocation only for local variables */
152 if (arFlag && !IS_AGGREGATE (sym->type) &&
153 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
154 !sym->allocreq && sym->level)
157 /* if global variable & not static or extern
158 and addPublics allowed then add it to the public set */
159 if ((sym->level == 0 ||
160 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
162 !IS_STATIC (sym->etype))
163 addSetHead (&publics, sym);
165 /* if extern then do nothing or is a function
167 if (IS_FUNC (sym->type))
170 /* print extra debug info if required */
171 if (options.debug || sym->level == 0)
174 cdbSymbol (sym, cdbFile, FALSE, FALSE);
176 if (!sym->level) /* global */
177 if (IS_STATIC (sym->etype))
178 fprintf (map->oFile, "F%s_", moduleName); /* scope is file */
180 fprintf (map->oFile, "G_"); /* scope is global */
182 /* symbol is local */
183 fprintf (map->oFile, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
184 fprintf (map->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
188 /* if is has an absolute address then generate
189 an equate for this no need to allocate space */
190 if (SPEC_ABSA (sym->etype))
192 //if (options.debug || sym->level == 0)
193 //fprintf (map->oFile,"; == 0x%04x\n",SPEC_ADDR (sym->etype));
195 fprintf (map->oFile, "%s\tEQU\t0x%04x\n",
197 SPEC_ADDR (sym->etype));
203 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
204 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
205 /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
206 if (IS_BITVAR (sym->etype))
208 if ((bitvars % 8) == 0)
210 fprintf (map->oFile, " cblock\n");
211 fprintf (map->oFile, "\tbitfield%d\n", bitvars);
212 fprintf (map->oFile, " endc\n");
215 fprintf (map->oFile, "%s\tEQU\t( (bitfield%d<<3)+%d)\n",
224 fprintf (map->oFile, "\t%s\n", sym->rname);
225 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1)
227 for (i = 1; i < size; i++)
228 fprintf (map->oFile, "\t%s_%d\n", sym->rname, i);
231 //fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
234 /* if it has a initial value then do it only if
235 it is a global variable */
236 if (sym->ival && sym->level == 0) {
239 if (IS_AGGREGATE (sym->type))
240 ival = initAggregates (sym, sym->ival, NULL);
242 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
243 decorateType (resolveSymbols (list2expr (sym->ival))));
244 codeOutFile = statsg->oFile;
246 eBBlockFromiCode (iCodeFromAst (ival));
254 /*-----------------------------------------------------------------*/
255 /* initPointer - pointer initialization code massaging */
256 /*-----------------------------------------------------------------*/
258 initPointer (initList * ilist)
261 ast *expr = list2expr (ilist);
266 /* try it the oldway first */
267 if ((val = constExprValue (expr, FALSE)))
270 /* no then we have to do these cludgy checks */
271 /* pointers can be initialized with address of
272 a variable or address of an array element */
273 if (IS_AST_OP (expr) && expr->opval.op == '&')
275 /* address of symbol */
276 if (IS_AST_SYM_VALUE (expr->left))
278 val = copyValue (AST_VALUE (expr->left));
279 val->type = newLink ();
280 if (SPEC_SCLS (expr->left->etype) == S_CODE)
282 DCL_TYPE (val->type) = CPOINTER;
283 DCL_PTR_CONST (val->type) = port->mem.code_ro;
285 else if (SPEC_SCLS (expr->left->etype) == S_XDATA)
286 DCL_TYPE (val->type) = FPOINTER;
287 else if (SPEC_SCLS (expr->left->etype) == S_XSTACK)
288 DCL_TYPE (val->type) = PPOINTER;
289 else if (SPEC_SCLS (expr->left->etype) == S_IDATA)
290 DCL_TYPE (val->type) = IPOINTER;
291 else if (SPEC_SCLS (expr->left->etype) == S_EEPROM)
292 DCL_TYPE (val->type) = EEPPOINTER;
294 DCL_TYPE (val->type) = POINTER;
295 val->type->next = expr->left->ftype;
296 val->etype = getSpec (val->type);
300 /* if address of indexed array */
301 if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
302 return valForArray (expr->left);
304 /* if address of structure element then
306 if (IS_AST_OP (expr->left) &&
307 expr->left->opval.op == '.')
309 return valForStructElem (expr->left->left,
314 (&some_struct)->element */
315 if (IS_AST_OP (expr->left) &&
316 expr->left->opval.op == PTR_OP &&
317 IS_ADDRESS_OF_OP (expr->left->left))
318 return valForStructElem (expr->left->left->left,
323 werror (E_INIT_WRONG);
328 /*-----------------------------------------------------------------*/
329 /* printChar - formats and prints a characater string with DB */
330 /*-----------------------------------------------------------------*/
332 printChar (FILE * ofile, char *s, int plen)
335 int len = strlen (s);
338 while (len && pplen < plen)
341 fprintf (ofile, "\t.ascii /");
343 while (i && *s && pplen < plen)
345 if (*s < ' ' || *s == '/')
347 fprintf (ofile, "/\n\t.byte 0x%02x\n\t.ascii /", *s++);
350 fprintf (ofile, "%c", *s++);
354 fprintf (ofile, "/\n");
362 fprintf (ofile, "\t.byte\t0\n");
365 /*-----------------------------------------------------------------*/
366 /* printIvalType - generates ival for int/char */
367 /*-----------------------------------------------------------------*/
369 printIvalType (sym_link * type, initList * ilist, FILE * oFile)
373 /* if initList is deep */
374 if (ilist->type == INIT_DEEP)
375 ilist = ilist->init.deep;
377 val = list2val (ilist);
378 switch (getSize (type))
382 fprintf (oFile, "\t.byte 0\n");
384 fprintf (oFile, "\t.byte %s\n",
385 aopLiteral (val, 0));
390 fprintf (oFile, "\t.word 0\n");
392 fprintf (oFile, "\t.byte %s,%s\n",
393 aopLiteral (val, 0), aopLiteral (val, 1));
398 fprintf (oFile, "\t.word 0,0\n");
400 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
401 aopLiteral (val, 0), aopLiteral (val, 1),
402 aopLiteral (val, 2), aopLiteral (val, 3));
409 /*-----------------------------------------------------------------*/
410 /* printIvalStruct - generates initial value for structures */
411 /*-----------------------------------------------------------------*/
413 printIvalStruct (symbol * sym, sym_link * type,
414 initList * ilist, FILE * oFile)
419 sflds = SPEC_STRUCT (type)->fields;
420 if (ilist->type != INIT_DEEP)
422 werror (E_INIT_STRUCT, sym->name);
426 iloop = ilist->init.deep;
428 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
429 printIval (sflds, sflds->type, iloop, oFile);
434 /*-----------------------------------------------------------------*/
435 /* printIvalChar - generates initital value for character array */
436 /*-----------------------------------------------------------------*/
438 printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s)
446 val = list2val (ilist);
447 /* if the value is a character string */
448 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
450 if (!DCL_ELEM (type))
451 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
453 /* if size mismatch */
454 /* if (DCL_ELEM (type) < ((int) strlen (SPEC_CVAL (val->etype).v_char) + 1)) */
455 /* werror (E_ARRAY_BOUND); */
457 printChar (oFile, SPEC_CVAL (val->etype).v_char, DCL_ELEM (type));
459 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0)
461 fprintf (oFile, "\t.byte 0\n");
469 printChar (oFile, s, strlen (s) + 1);
473 /*-----------------------------------------------------------------*/
474 /* printIvalArray - generates code for array initialization */
475 /*-----------------------------------------------------------------*/
477 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
481 int lcnt = 0, size = 0;
483 /* take care of the special case */
484 /* array of characters can be init */
486 if (IS_CHAR (type->next))
487 if (printIvalChar (type,
488 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
489 oFile, SPEC_CVAL (sym->etype).v_char))
492 /* not the special case */
493 if (ilist->type != INIT_DEEP)
495 werror (E_INIT_STRUCT, sym->name);
499 iloop = ilist->init.deep;
500 lcnt = DCL_ELEM (type);
505 printIval (sym, type->next, iloop, oFile);
506 iloop = (iloop ? iloop->next : NULL);
509 /* if not array limits given & we */
510 /* are out of initialisers then */
511 if (!DCL_ELEM (type) && !iloop)
514 /* no of elements given and we */
515 /* have generated for all of them */
520 /* if we have not been given a size */
521 if (!DCL_ELEM (type))
522 DCL_ELEM (type) = size;
527 /*-----------------------------------------------------------------*/
528 /* printIvalFuncPtr - generate initial value for function pointers */
529 /*-----------------------------------------------------------------*/
531 printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
536 val = list2val (ilist);
537 /* check the types */
538 if ((dLvl = checkType (val->type, type->next)) <= 0)
541 fprintf (oFile, "\t.word 0\n");
545 /* now generate the name */
548 if (IS_LITERAL (val->etype))
549 fprintf (oFile, "\t.byte %s,%s\n",
550 aopLiteral (val, 0), aopLiteral (val, 1));
552 fprintf (oFile, "\t.byte %s,(%s >> 8)\n",
553 val->name, val->name);
556 fprintf (oFile, "\t.byte %s,(%s >> 8)\n",
557 val->sym->rname, val->sym->rname);
562 /*-----------------------------------------------------------------*/
563 /* printIvalCharPtr - generates initial values for character pointers */
564 /*-----------------------------------------------------------------*/
566 printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
570 size = getSize (type);
574 "\t.byte %s", val->name);
577 "\t.byte %s,(%s >> 8)",
578 val->name, val->name);
581 fprintf (oFile, ",#0x02\n");
583 fprintf (oFile, "\n");
585 if (val->sym && val->sym->isstrlit)
586 addSet (&statsg->syms, val->sym);
591 /*-----------------------------------------------------------------*/
592 /* printIvalPtr - generates initial value for pointers */
593 /*-----------------------------------------------------------------*/
595 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
600 if (ilist->type == INIT_DEEP)
601 ilist = ilist->init.deep;
603 /* function pointer */
604 if (IS_FUNC (type->next))
606 printIvalFuncPtr (type, ilist, oFile);
610 if (!(val = initPointer (ilist)))
613 /* if character pointer */
614 if (IS_CHAR (type->next))
615 if (printIvalCharPtr (sym, type, val, oFile))
619 if (checkType (type, val->type) != 1)
620 werror (E_INIT_WRONG);
622 /* if val is literal */
623 if (IS_LITERAL (val->etype))
625 switch (getSize (type))
628 fprintf (oFile, "\t.byte 0x%02x\n", ((char) floatFromVal (val)) & 0xff);
631 fprintf (oFile, "\t.byte %s,%s\n",
632 aopLiteral (val, 0), aopLiteral (val, 1));
636 fprintf (oFile, "\t.byte %s,%s,0x%02x\n",
637 aopLiteral (val, 0), aopLiteral (val, 1), CPOINTER);
643 switch (getSize (type))
646 fprintf (oFile, "\t.byte %s\n", val->name);
649 fprintf (oFile, "\t.byte %s,(%s >> 8)\n", val->name, val->name);
653 fprintf (oFile, "\t.byte %s,(%s >> 8),0x%02x\n",
654 val->name, val->name, DCL_TYPE (val->type));
659 /*-----------------------------------------------------------------*/
660 /* printIval - generates code for initial value */
661 /*-----------------------------------------------------------------*/
663 printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
668 /* if structure then */
669 if (IS_STRUCT (type))
671 printIvalStruct (sym, type, ilist, oFile);
675 /* if this is a pointer */
678 printIvalPtr (sym, type, ilist, oFile);
682 /* if this is an array */
685 printIvalArray (sym, type, ilist, oFile);
689 /* if type is SPECIFIER */
692 printIvalType (type, ilist, oFile);
698 /*-----------------------------------------------------------------*/
699 /* emitStaticSeg - emitcode for the static segment */
700 /*-----------------------------------------------------------------*/
702 pic14emitStaticSeg (memmap * map)
706 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
709 /* for all variables in this segment do */
710 for (sym = setFirstItem (map->syms); sym;
711 sym = setNextItem (map->syms))
714 /* if it is "extern" then do nothing */
715 if (IS_EXTERN (sym->etype))
718 /* if it is not static add it to the public
720 if (!IS_STATIC (sym->etype))
721 addSetHead (&publics, sym);
723 /* print extra debug info if required */
724 if (options.debug || sym->level == 0)
727 cdbSymbol (sym, cdbFile, FALSE, FALSE);
731 if (IS_STATIC (sym->etype))
732 fprintf (code->oFile, "F%s_", moduleName); /* scope is file */
734 fprintf (code->oFile, "G_"); /* scope is global */
737 /* symbol is local */
738 fprintf (code->oFile, "L%s_",
739 (sym->localof ? sym->localof->name : "-null-"));
740 fprintf (code->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
743 /* if it has an absolute address */
744 if (SPEC_ABSA (sym->etype))
746 if (options.debug || sym->level == 0)
747 fprintf (code->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
749 fprintf (code->oFile, "%s\t=\t0x%04x\n",
751 SPEC_ADDR (sym->etype));
755 if (options.debug || sym->level == 0)
756 fprintf (code->oFile, " == .\n");
758 /* if it has an initial value */
761 fprintf (code->oFile, "%s:\n", sym->rname);
763 resolveIvalSym (sym->ival);
764 printIval (sym, sym->type, sym->ival, code->oFile);
770 fprintf (code->oFile, "%s:\n", sym->rname);
771 /* special case for character strings */
772 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
773 SPEC_CVAL (sym->etype).v_char)
774 printChar (code->oFile,
775 SPEC_CVAL (sym->etype).v_char,
776 strlen (SPEC_CVAL (sym->etype).v_char) + 1);
778 fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
785 /*-----------------------------------------------------------------*/
786 /* emitMaps - emits the code for the data portion the code */
787 /*-----------------------------------------------------------------*/
791 /* no special considerations for the following
792 data, idata & bit & xdata */
793 pic14emitRegularMap (data, TRUE, TRUE);
794 pic14emitRegularMap (idata, TRUE, TRUE);
795 pic14emitRegularMap (bit, TRUE, FALSE);
796 pic14emitRegularMap (xdata, TRUE, TRUE);
797 pic14emitRegularMap (sfr, FALSE, FALSE);
798 pic14emitRegularMap (sfrbit, FALSE, FALSE);
799 pic14emitRegularMap (code, TRUE, FALSE);
800 pic14emitStaticSeg (statsg);
803 /*-----------------------------------------------------------------*/
804 /* createInterruptVect - creates the interrupt vector */
805 /*-----------------------------------------------------------------*/
807 pic14createInterruptVect (FILE * vFile)
810 mainf = newSymbol ("main", 0);
813 /* only if the main function exists */
814 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
816 if (!options.cc_only)
821 /* if the main is only a prototype ie. no body then do nothing */
824 /* if ! compile only then main function should be present */
825 if (!options.cc_only)
830 fprintf (vFile, ";\t.area\t%s\n", CODE_NAME);
831 fprintf (vFile, ";__interrupt_vect:\n");
834 if (!port->genIVT || !(port->genIVT (vFile, interrupts, maxInterrupts)))
836 /* "generic" interrupt table header (if port doesn't specify one).
838 * Look suspiciously like 8051 code to me...
841 fprintf (vFile, ";\tljmp\t__sdcc_gsinit_startup\n");
844 /* now for the other interrupts */
845 for (; i < maxInterrupts; i++)
848 fprintf (vFile, ";\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
850 fprintf (vFile, ";\treti\n;\t.ds\t7\n");
856 /*-----------------------------------------------------------------*/
857 /* initialComments - puts in some initial comments */
858 /*-----------------------------------------------------------------*/
860 pic14initialComments (FILE * afile)
862 initialComments (afile);
863 fprintf (afile, "; PIC port for the 14-bit core\n");
864 fprintf (afile, iComments2);
868 /*-----------------------------------------------------------------*/
869 /* printPublics - generates .global for publics */
870 /*-----------------------------------------------------------------*/
872 pic14printPublics (FILE * afile)
876 fprintf (afile, "%s", iComments2);
877 fprintf (afile, "; publics variables in this module\n");
878 fprintf (afile, "%s", iComments2);
880 for (sym = setFirstItem (publics); sym;
881 sym = setNextItem (publics))
882 fprintf (afile, ";\t.globl %s\n", sym->rname);
887 /*-----------------------------------------------------------------*/
888 /* emitOverlay - will emit code for the overlay stuff */
889 /*-----------------------------------------------------------------*/
891 pic14emitOverlay (FILE * afile)
895 if (!elementsInSet (ovrSetSets))
896 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);
898 /* for each of the sets in the overlay segment do */
899 for (ovrset = setFirstItem (ovrSetSets); ovrset;
900 ovrset = setNextItem (ovrSetSets))
905 if (elementsInSet (ovrset))
907 /* this dummy area is used to fool the assembler
908 otherwise the assembler will append each of these
909 declarations into one chunk and will not overlay
911 fprintf (afile, ";\t.area _DUMMY\n");
912 /* output the area informtion */
913 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
916 for (sym = setFirstItem (ovrset); sym;
917 sym = setNextItem (ovrset))
920 /* if extern then do nothing */
921 if (IS_EXTERN (sym->etype))
924 /* if allocation required check is needed
925 then check if the symbol really requires
926 allocation only for local variables */
927 if (!IS_AGGREGATE (sym->type) &&
928 !(sym->_isparm && !IS_REGPARM (sym->etype))
929 && !sym->allocreq && sym->level)
932 /* if global variable & not static or extern
933 and addPublics allowed then add it to the public set */
934 if ((sym->_isparm && !IS_REGPARM (sym->etype))
935 && !IS_STATIC (sym->etype))
936 addSetHead (&publics, sym);
938 /* if extern then do nothing or is a function
940 if (IS_FUNC (sym->type))
943 /* print extra debug info if required */
944 if (options.debug || sym->level == 0)
947 cdbSymbol (sym, cdbFile, FALSE, FALSE);
951 if (IS_STATIC (sym->etype))
952 fprintf (afile, "F%s_", moduleName); /* scope is file */
954 fprintf (afile, "G_"); /* scope is global */
957 /* symbol is local */
958 fprintf (afile, "L%s_",
959 (sym->localof ? sym->localof->name : "-null-"));
960 fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
963 /* if is has an absolute address then generate
964 an equate for this no need to allocate space */
965 if (SPEC_ABSA (sym->etype))
968 if (options.debug || sym->level == 0)
969 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
971 fprintf (afile, "%s\t=\t0x%04x\n",
973 SPEC_ADDR (sym->etype));
977 if (options.debug || sym->level == 0)
978 fprintf (afile, "==.\n");
981 fprintf (afile, "%s:\n", sym->rname);
982 fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
991 /*-----------------------------------------------------------------*/
992 /* glue - the final glue that hold the whole thing together */
993 /*-----------------------------------------------------------------*/
1000 FILE *ovrFile = tempfile();
1003 addSetHead(&tmpfileSet,ovrFile);
1004 /* print the global struct definitions */
1006 cdbStructBlock (0,cdbFile);
1009 /* PENDING: this isnt the best place but it will do */
1010 if (port->general.glue_up_main) {
1011 /* create the interrupt vector table */
1012 pic14createInterruptVect (vFile);
1015 addSetHead(&tmpfileSet,vFile);
1017 /* emit code for the all the variables declared */
1019 /* do the overlay segments */
1020 pic14emitOverlay(ovrFile);
1026 /* now put it all together into the assembler file */
1027 /* create the assembler file name */
1029 if (!options.c1mode) {
1030 sprintf (buffer, srcFileName);
1031 strcat (buffer, ".asm");
1034 strcpy(buffer, options.out_name);
1037 if (!(asmFile = fopen (buffer, "w"))) {
1038 werror (E_FILE_OPEN_ERR, buffer);
1042 /* initial comments */
1043 pic14initialComments (asmFile);
1045 /* print module name */
1046 fprintf (asmFile, ";\t.module %s\n", moduleName);
1048 /* Let the port generate any global directives, etc. */
1049 if (port->genAssemblerPreamble)
1051 port->genAssemblerPreamble(asmFile);
1054 /* print the global variables in this module */
1055 pic14printPublics (asmFile);
1058 /* copy the sfr segment */
1059 fprintf (asmFile, "%s", iComments2);
1060 fprintf (asmFile, "; special function registers\n");
1061 fprintf (asmFile, "%s", iComments2);
1062 copyFile (asmFile, sfr->oFile);
1065 /* Put all variables into a cblock */
1066 fprintf (asmFile, "\n\n\tcblock 0x13\n\n");
1068 for(i=0; i<pic14_nRegs; i++) {
1069 if(regspic14[i].wasUsed && (regspic14[i].offset>=0x0c) )
1070 fprintf (asmFile, "\t%s\n",regspic14[i].name);
1072 //fprintf (asmFile, "\tr0x0C\n");
1073 //fprintf (asmFile, "\tr0x0D\n");
1075 /* For now, create a "dpl" and a "dph" in the register space */
1076 /* of the pic so that we can use the same calling mechanism */
1077 /* as the 8051 port */
1078 fprintf (asmFile, "%s", iComments2);
1079 fprintf (asmFile, "; dpl and dph to emulate the 8051 calling mechanism \n");
1080 fprintf (asmFile, "%s", iComments2);
1082 fprintf (asmFile, "\tdph\n");
1086 /* copy the sbit segment */
1087 fprintf (asmFile, "%s", iComments2);
1088 fprintf (asmFile, "; special function bits \n");
1089 fprintf (asmFile, "%s", iComments2);
1090 copyFile (asmFile, sfrbit->oFile);
1092 /* copy the data segment */
1093 fprintf (asmFile, "%s", iComments2);
1094 fprintf (asmFile, "; internal ram data\n");
1095 fprintf (asmFile, "%s", iComments2);
1096 copyFile (asmFile, data->oFile);
1099 /* create the overlay segments */
1100 fprintf (asmFile, "%s", iComments2);
1101 fprintf (asmFile, "; overlayable items in internal ram \n");
1102 fprintf (asmFile, "%s", iComments2);
1103 copyFile (asmFile, ovrFile);
1105 /* create the stack segment MOF */
1106 if (mainf && mainf->fbody) {
1107 fprintf (asmFile, "%s", iComments2);
1108 fprintf (asmFile, "; Stack segment in internal ram \n");
1109 fprintf (asmFile, "%s", iComments2);
1110 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1111 ";__start__stack:\n;\t.ds\t1\n\n");
1114 /* create the idata segment */
1115 fprintf (asmFile, "%s", iComments2);
1116 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1117 fprintf (asmFile, "%s", iComments2);
1118 copyFile (asmFile, idata->oFile);
1120 /* if external stack then reserve space of it */
1121 if (mainf && mainf->fbody && options.useXstack ) {
1122 fprintf (asmFile, "%s", iComments2);
1123 fprintf (asmFile, "; external stack \n");
1124 fprintf (asmFile, "%s", iComments2);
1125 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1126 fprintf (asmFile,";\t.ds 256\n");
1130 /* copy xtern ram data */
1131 fprintf (asmFile, "%s", iComments2);
1132 fprintf (asmFile, "; external ram data\n");
1133 fprintf (asmFile, "%s", iComments2);
1134 copyFile (asmFile, xdata->oFile);
1137 fprintf (asmFile, "\tendc\n");
1140 /* copy the bit segment */
1141 fprintf (asmFile, "%s", iComments2);
1142 fprintf (asmFile, "; bit data\n");
1143 fprintf (asmFile, "%s", iComments2);
1144 copyFile (asmFile, bit->oFile);
1147 fprintf (asmFile, "\tORG 0\n");
1149 /* copy the interrupt vector table */
1150 if (mainf && mainf->fbody) {
1151 fprintf (asmFile, "%s", iComments2);
1152 fprintf (asmFile, "; interrupt vector \n");
1153 fprintf (asmFile, "%s", iComments2);
1154 copyFile (asmFile, vFile);
1157 /* copy global & static initialisations */
1158 fprintf (asmFile, "%s", iComments2);
1159 fprintf (asmFile, "; global & static initialisations\n");
1160 fprintf (asmFile, "%s", iComments2);
1162 /* Everywhere we generate a reference to the static_name area,
1163 * (which is currently only here), we immediately follow it with a
1164 * definition of the post_static_name area. This guarantees that
1165 * the post_static_name area will immediately follow the static_name
1168 fprintf (asmFile, ";\t.area %s\n", port->mem.static_name); /* MOF */
1169 fprintf (asmFile, ";\t.area %s\n", port->mem.post_static_name);
1170 fprintf (asmFile, ";\t.area %s\n", port->mem.static_name);
1172 if (mainf && mainf->fbody) {
1173 fprintf (asmFile,"__sdcc_gsinit_startup:\n");
1174 /* if external stack is specified then the
1175 higher order byte of the xdatalocation is
1176 going into P2 and the lower order going into
1178 if (options.useXstack) {
1179 fprintf(asmFile,";\tmov\tP2,#0x%02x\n",
1180 (((unsigned int)options.xdata_loc) >> 8) & 0xff);
1181 fprintf(asmFile,";\tmov\t_spx,#0x%02x\n",
1182 (unsigned int)options.xdata_loc & 0xff);
1185 /* initialise the stack pointer */
1186 /* if the user specified a value then use it */
1187 if (options.stack_loc)
1188 fprintf(asmFile,";\tmov\tsp,#%d\n",options.stack_loc);
1190 /* no: we have to compute it */
1191 if (!options.stackOnData && maxRegBank <= 3)
1192 fprintf(asmFile,";\tmov\tsp,#%d\n",((maxRegBank + 1) * 8) -1);
1194 fprintf(asmFile,";\tmov\tsp,#__start__stack\n"); /* MOF */
1196 fprintf (asmFile,";\tlcall\t__sdcc_external_startup\n");
1197 fprintf (asmFile,";\tmov\ta,dpl\n");
1198 fprintf (asmFile,";\tjz\t__sdcc_init_data\n");
1199 fprintf (asmFile,";\tljmp\t__sdcc_program_startup\n");
1200 fprintf (asmFile,";__sdcc_init_data:\n");
1203 //copyFile (asmFile, statsg->oFile);
1204 copypCode(asmFile, statsg->dbName);
1206 if (port->general.glue_up_main && mainf && mainf->fbody)
1208 /* This code is generated in the post-static area.
1209 * This area is guaranteed to follow the static area
1210 * by the ugly shucking and jiving about 20 lines ago.
1212 fprintf(asmFile, ";\t.area %s\n", port->mem.post_static_name);
1213 fprintf (asmFile,";\tljmp\t__sdcc_program_startup\n");
1216 /* copy over code */
1217 fprintf (asmFile, "%s", iComments2);
1218 fprintf (asmFile, "; code\n");
1219 fprintf (asmFile, "%s", iComments2);
1220 fprintf (asmFile, ";\t.area %s\n", port->mem.code_name);
1221 if (mainf && mainf->fbody) {
1223 /* entry point @ start of CSEG */
1224 fprintf (asmFile,"__sdcc_program_startup:\n");
1226 /* put in the call to main */
1227 fprintf(asmFile,"\tcall\t_main\n");
1228 if (options.mainreturn) {
1230 fprintf(asmFile,";\treturn from main ; will return to caller\n");
1231 fprintf(asmFile,"\treturn\n");
1235 fprintf(asmFile,";\treturn from main will lock up\n");
1236 fprintf(asmFile,"\tgoto\t$\n");
1240 AnalyzepCode(code->dbName);
1243 OptimizepCode(code->dbName);
1244 //copyFile (asmFile, code->oFile);
1245 copypCode(asmFile, code->dbName);
1247 printCallTree(stderr);
1249 fprintf (asmFile,"\tend\n");
1252 applyToSet(tmpfileSet,closeTmpFiles);
1253 applyToSet(tmpfileNameSet, rmTmpFiles);