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"
30 extern symbol *interrupts[256];
31 void printIval (symbol *, sym_link *, initList *, FILE *);
34 extern int maxInterrupts;
35 extern int maxRegBank ;
37 extern char *VersionString;
38 extern FILE *codeOutFile;
39 extern set *tmpfileSet;
40 extern set *tmpfileNameSet;
41 extern char *iComments1;
42 extern char *iComments2;
43 //extern void emitStaticSeg (memmap * map);
45 extern DEFSETFUNC(closeTmpFiles);
46 extern DEFSETFUNC(rmTmpFiles);
48 extern void copyFile (FILE * dest, FILE * src);
51 //extern void emitMaps ();
52 //extern void createInterruptVect (FILE * vFile);
53 extern void initialComments (FILE * afile);
54 extern void printPublics (FILE * afile);
56 extern void printChar (FILE * ofile, char *s, int plen);
59 char *aopLiteral (value *val, int offset)
60 static void emitRegularMap (memmap * map, bool addPublics, bool arFlag)
61 value *initPointer (initList *ilist)
62 void printIvalType (sym_link * type, initList * ilist, FILE * oFile)
63 void printIvalStruct (symbol * sym,sym_link * type,
64 initList * ilist, FILE * oFile)
65 int printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s)
66 void printIvalArray (symbol * sym, sym_link * type, initList * ilist,
68 void printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
69 int printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
70 void printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
74 /*-----------------------------------------------------------------*/
75 /* aopLiteral - string from a literal value */
76 /*-----------------------------------------------------------------*/
77 char *pic14aopLiteral (value *val, int offset)
85 /* if it is a float then it gets tricky */
86 /* otherwise it is fairly simple */
87 if (!IS_FLOAT(val->type)) {
88 unsigned long v = floatFromVal(val);
91 sprintf(buffer,"0x%02x",((char) v) & 0xff);
92 rs = Safe_calloc(strlen(buffer)+1);
93 return strcpy (rs,buffer);
96 /* it is type float */
97 fl.f = (float) floatFromVal(val);
99 sprintf(buffer,"0x%02x",fl.c[3-offset]);
101 sprintf(buffer,"0x%02x",fl.c[offset]);
103 rs = Safe_calloc(strlen(buffer)+1);
104 return strcpy (rs,buffer);
108 /*-----------------------------------------------------------------*/
109 /* emitRegularMap - emit code for maps with no special cases */
110 /*-----------------------------------------------------------------*/
111 static void pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag)
114 int i,size,bitvars=0;;
117 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
119 /* print the area name */
120 for (sym = setFirstItem (map->syms); sym;
121 sym = setNextItem (map->syms)) {
123 /* if extern then do nothing */
124 if (IS_EXTERN (sym->etype))
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 /* if extern then do nothing or is a function
145 if (IS_FUNC (sym->type))
148 /* print extra debug info if required */
149 if (options.debug || sym->level == 0) {
151 cdbSymbol(sym,cdbFile,FALSE,FALSE);
153 if (!sym->level) /* global */
154 if (IS_STATIC(sym->etype))
155 fprintf(map->oFile,"F%s_",moduleName); /* scope is file */
157 fprintf(map->oFile,"G_"); /* scope is global */
159 /* symbol is local */
160 fprintf(map->oFile,"L%s_",(sym->localof ? sym->localof->name : "-null-"));
161 fprintf(map->oFile,"%s_%d_%d",sym->name,sym->level,sym->block);
165 /* if is has an absolute address then generate
166 an equate for this no need to allocate space */
167 if (SPEC_ABSA (sym->etype)) {
168 //if (options.debug || sym->level == 0)
169 //fprintf (map->oFile,"; == 0x%04x\n",SPEC_ADDR (sym->etype));
171 fprintf (map->oFile, "%s\tEQU\t0x%04x\n",
173 SPEC_ADDR (sym->etype));
178 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
179 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
180 /* by grouping the bits together into groups of 8 and storing them in the normal ram.*/
181 if(IS_BITVAR(sym->etype)) {
182 if((bitvars % 8) == 0) {
183 fprintf (map->oFile, " cblock\n");
184 fprintf (map->oFile, "\tbitfield%d\n", bitvars);
185 fprintf (map->oFile, " endc\n");
188 fprintf (map->oFile, "%s\tEQU\t( (bitfield%d<<3)+%d)\n",
195 fprintf (map->oFile, "\t%s\n", sym->rname);
196 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);
201 //fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
204 /* if it has a initial value then do it only if
205 it is a global variable */
206 if (sym->ival && sym->level == 0) {
209 if (IS_AGGREGATE (sym->type))
210 ival = initAggregates (sym, sym->ival, NULL);
212 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
213 decorateType (resolveSymbols (list2expr (sym->ival))));
214 codeOutFile = statsg->oFile;
215 eBBlockFromiCode (iCodeFromAst (ival));
223 /*-----------------------------------------------------------------*/
224 /* initPointer - pointer initialization code massaging */
225 /*-----------------------------------------------------------------*/
226 value *initPointer (initList *ilist)
229 ast *expr = list2expr(ilist);
234 /* try it the oldway first */
235 if ((val = constExprValue(expr,FALSE)))
238 /* no then we have to do these cludgy checks */
239 /* pointers can be initialized with address of
240 a variable or address of an array element */
241 if (IS_AST_OP(expr) && expr->opval.op == '&') {
242 /* address of symbol */
243 if (IS_AST_SYM_VALUE(expr->left)) {
244 val = copyValue(AST_VALUE(expr->left));
245 val->type = newLink();
246 if (SPEC_SCLS(expr->left->etype) == S_CODE) {
247 DCL_TYPE(val->type) = CPOINTER ;
248 DCL_PTR_CONST(val->type) = port->mem.code_ro;
251 if (SPEC_SCLS(expr->left->etype) == S_XDATA)
252 DCL_TYPE(val->type) = FPOINTER;
254 if (SPEC_SCLS(expr->left->etype) == S_XSTACK )
255 DCL_TYPE(val->type) = PPOINTER ;
257 if (SPEC_SCLS(expr->left->etype) == S_IDATA)
258 DCL_TYPE(val->type) = IPOINTER ;
260 if (SPEC_SCLS(expr->left->etype) == S_EEPROM)
261 DCL_TYPE(val->type) = EEPPOINTER ;
263 DCL_TYPE(val->type) = POINTER ;
264 val->type->next = expr->left->ftype;
265 val->etype = getSpec(val->type);
269 /* if address of indexed array */
270 if (IS_AST_OP(expr->left) && expr->left->opval.op == '[')
271 return valForArray(expr->left);
273 /* if address of structure element then
275 if (IS_AST_OP(expr->left) &&
276 expr->left->opval.op == '.' ) {
277 return valForStructElem(expr->left->left,
282 (&some_struct)->element */
283 if (IS_AST_OP(expr->left) &&
284 expr->left->opval.op == PTR_OP &&
285 IS_ADDRESS_OF_OP(expr->left->left))
286 return valForStructElem(expr->left->left->left,
291 werror(E_INIT_WRONG);
296 /*-----------------------------------------------------------------*/
297 /* printChar - formats and prints a characater string with DB */
298 /*-----------------------------------------------------------------*/
299 void printChar (FILE * ofile, char *s, int plen)
302 int len = strlen (s);
305 while (len && pplen < plen) {
307 fprintf (ofile, "\t.ascii /");
309 while (i && *s && pplen < plen) {
310 if (*s < ' ' || *s == '/') {
311 fprintf (ofile, "/\n\t.byte 0x%02x\n\t.ascii /", *s++);
314 fprintf (ofile, "%c", *s++);
318 fprintf (ofile, "/\n");
326 fprintf(ofile,"\t.byte\t0\n");
329 /*-----------------------------------------------------------------*/
330 /* printIvalType - generates ival for int/char */
331 /*-----------------------------------------------------------------*/
332 void printIvalType (sym_link * type, initList * ilist, FILE * oFile)
336 /* if initList is deep */
337 if (ilist->type == INIT_DEEP)
338 ilist = ilist->init.deep;
340 val = list2val (ilist);
341 switch (getSize (type)) {
344 fprintf (oFile, "\t.byte 0\n");
346 fprintf (oFile, "\t.byte %s\n",
347 aopLiteral (val, 0));
352 fprintf (oFile, "\t.word 0\n");
354 fprintf (oFile, "\t.byte %s,%s\n",
355 aopLiteral (val, 0), aopLiteral (val, 1));
360 fprintf (oFile, "\t.word 0,0\n");
362 fprintf (oFile, "\t.byte %s,%s,%s,%s\n",
363 aopLiteral (val, 0), aopLiteral (val, 1),
364 aopLiteral (val, 2), aopLiteral (val, 3));
371 /*-----------------------------------------------------------------*/
372 /* printIvalStruct - generates initial value for structures */
373 /*-----------------------------------------------------------------*/
374 void printIvalStruct (symbol * sym,sym_link * type,
375 initList * ilist, FILE * oFile)
380 sflds = SPEC_STRUCT (type)->fields;
381 if (ilist->type != INIT_DEEP) {
382 werror (E_INIT_STRUCT, sym->name);
386 iloop = ilist->init.deep;
388 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL))
389 printIval (sflds, sflds->type, iloop, oFile);
394 /*-----------------------------------------------------------------*/
395 /* printIvalChar - generates initital value for character array */
396 /*-----------------------------------------------------------------*/
397 int printIvalChar (sym_link * type, initList * ilist, FILE * oFile, char *s)
404 val = list2val (ilist);
405 /* if the value is a character string */
406 if (IS_ARRAY (val->type) && IS_CHAR (val->etype)) {
407 if (!DCL_ELEM (type))
408 DCL_ELEM (type) = strlen (SPEC_CVAL (val->etype).v_char) + 1;
410 /* if size mismatch */
411 /* if (DCL_ELEM (type) < ((int) strlen (SPEC_CVAL (val->etype).v_char) + 1)) */
412 /* werror (E_ARRAY_BOUND); */
414 printChar (oFile, SPEC_CVAL (val->etype).v_char,DCL_ELEM(type));
416 if ((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) -1))>0)
418 fprintf (oFile, "\t.byte 0\n");
426 printChar (oFile, s,strlen(s)+1);
430 /*-----------------------------------------------------------------*/
431 /* printIvalArray - generates code for array initialization */
432 /*-----------------------------------------------------------------*/
433 void printIvalArray (symbol * sym, sym_link * type, initList * ilist,
437 int lcnt = 0, size = 0;
439 /* take care of the special case */
440 /* array of characters can be init */
442 if (IS_CHAR (type->next))
443 if (printIvalChar (type,
444 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
445 oFile, SPEC_CVAL (sym->etype).v_char))
448 /* not the special case */
449 if (ilist->type != INIT_DEEP) {
450 werror (E_INIT_STRUCT, sym->name);
454 iloop = ilist->init.deep;
455 lcnt = DCL_ELEM (type);
459 printIval (sym, type->next, iloop, oFile);
460 iloop = (iloop ? iloop->next : NULL);
463 /* if not array limits given & we */
464 /* are out of initialisers then */
465 if (!DCL_ELEM (type) && !iloop)
468 /* no of elements given and we */
469 /* have generated for all of them */
474 /* if we have not been given a size */
475 if (!DCL_ELEM (type))
476 DCL_ELEM (type) = size;
481 /*-----------------------------------------------------------------*/
482 /* printIvalFuncPtr - generate initial value for function pointers */
483 /*-----------------------------------------------------------------*/
484 void printIvalFuncPtr (sym_link * type, initList * ilist, FILE * oFile)
489 val = list2val (ilist);
490 /* check the types */
491 if ((dLvl = checkType (val->type, type->next)) <= 0) {
493 fprintf (oFile, "\t.word 0\n");
497 /* now generate the name */
499 if (IS_LITERAL (val->etype))
500 fprintf (oFile, "\t.byte %s,%s\n",
501 aopLiteral (val, 0), aopLiteral (val, 1));
503 fprintf (oFile, "\t.byte %s,(%s >> 8)\n",
504 val->name, val->name);
507 fprintf (oFile, "\t.byte %s,(%s >> 8)\n",
508 val->sym->rname, val->sym->rname);
513 /*-----------------------------------------------------------------*/
514 /* printIvalCharPtr - generates initial values for character pointers */
515 /*-----------------------------------------------------------------*/
516 int printIvalCharPtr (symbol * sym, sym_link * type, value * val, FILE * oFile)
520 size = getSize (type);
524 "\t.byte %s", val->name) ;
527 "\t.byte %s,(%s >> 8)",
528 val->name, val->name);
531 fprintf (oFile, ",#0x02\n");
533 fprintf (oFile, "\n");
535 if (val->sym && val->sym->isstrlit)
536 addSet (&statsg->syms, val->sym);
541 /*-----------------------------------------------------------------*/
542 /* printIvalPtr - generates initial value for pointers */
543 /*-----------------------------------------------------------------*/
544 void printIvalPtr (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
549 if (ilist->type == INIT_DEEP)
550 ilist = ilist->init.deep;
552 /* function pointer */
553 if (IS_FUNC (type->next)) {
554 printIvalFuncPtr (type, ilist, oFile);
558 if (!(val = initPointer (ilist)))
561 /* if character pointer */
562 if (IS_CHAR (type->next))
563 if (printIvalCharPtr (sym, type, val, oFile))
567 if (checkType (type, val->type) != 1)
568 werror (E_INIT_WRONG);
570 /* if val is literal */
571 if (IS_LITERAL (val->etype)) {
572 switch (getSize (type)) {
574 fprintf (oFile, "\t.byte 0x%02x\n", ((char) floatFromVal (val)) & 0xff);
577 fprintf (oFile, "\t.byte %s,%s\n",
578 aopLiteral (val, 0), aopLiteral (val, 1));
582 fprintf (oFile, "\t.byte %s,%s,0x%02x\n",
583 aopLiteral (val, 0), aopLiteral (val, 1), CPOINTER);
589 switch (getSize (type)) {
591 fprintf (oFile, "\t.byte %s\n", val->name);
594 fprintf (oFile, "\t.byte %s,(%s >> 8)\n", val->name, val->name);
598 fprintf (oFile, "\t.byte %s,(%s >> 8),0x%02x\n",
599 val->name, val->name, DCL_TYPE(val->type));
604 /*-----------------------------------------------------------------*/
605 /* printIval - generates code for initial value */
606 /*-----------------------------------------------------------------*/
607 void printIval (symbol * sym, sym_link * type, initList * ilist, FILE * oFile)
612 /* if structure then */
613 if (IS_STRUCT (type)) {
614 printIvalStruct (sym, type, ilist, oFile);
618 /* if this is a pointer */
620 printIvalPtr (sym, type, ilist, oFile);
624 /* if this is an array */
625 if (IS_ARRAY (type)) {
626 printIvalArray (sym, type, ilist, oFile);
630 /* if type is SPECIFIER */
631 if (IS_SPEC (type)) {
632 printIvalType (type, ilist, oFile);
638 /*-----------------------------------------------------------------*/
639 /* emitStaticSeg - emitcode for the static segment */
640 /*-----------------------------------------------------------------*/
641 static void pic14emitStaticSeg (memmap * map)
645 fprintf(map->oFile,";\t.area\t%s\n",map->sname);
648 /* for all variables in this segment do */
649 for (sym = setFirstItem (map->syms); sym;
650 sym = setNextItem (map->syms)) {
652 /* if it is "extern" then do nothing */
653 if (IS_EXTERN (sym->etype))
656 /* if it is not static add it to the public
658 if (!IS_STATIC (sym->etype))
659 addSetHead (&publics, sym);
661 /* print extra debug info if required */
662 if (options.debug || sym->level == 0) {
664 cdbSymbol(sym,cdbFile,FALSE,FALSE);
666 if (!sym->level) { /* global */
667 if (IS_STATIC(sym->etype))
668 fprintf(code->oFile,"F%s_",moduleName); /* scope is file */
670 fprintf(code->oFile,"G_"); /* scope is global */
673 /* symbol is local */
674 fprintf(code->oFile,"L%s_",
675 (sym->localof ? sym->localof->name : "-null-"));
676 fprintf(code->oFile,"%s_%d_%d",sym->name,sym->level,sym->block);
679 /* if it has an absolute address */
680 if (SPEC_ABSA (sym->etype)) {
681 if (options.debug || sym->level == 0)
682 fprintf(code->oFile," == 0x%04x\n", SPEC_ADDR (sym->etype));
684 fprintf (code->oFile, "%s\t=\t0x%04x\n",
686 SPEC_ADDR (sym->etype));
689 if (options.debug || sym->level == 0)
690 fprintf(code->oFile," == .\n");
692 /* if it has an initial value */
694 fprintf (code->oFile, "%s:\n", sym->rname);
696 resolveIvalSym (sym->ival);
697 printIval (sym, sym->type, sym->ival, code->oFile);
702 fprintf (code->oFile, "%s:\n", sym->rname);
703 /* special case for character strings */
704 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
705 SPEC_CVAL (sym->etype).v_char)
706 printChar (code->oFile,
707 SPEC_CVAL (sym->etype).v_char,
708 strlen(SPEC_CVAL (sym->etype).v_char)+1);
710 fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type)& 0xffff);
717 /*-----------------------------------------------------------------*/
718 /* emitMaps - emits the code for the data portion the code */
719 /*-----------------------------------------------------------------*/
720 static void pic14emitMaps ()
722 /* no special considerations for the following
723 data, idata & bit & xdata */
724 pic14emitRegularMap (data, TRUE, TRUE);
725 pic14emitRegularMap (idata, TRUE,TRUE);
726 pic14emitRegularMap (bit, TRUE,FALSE);
727 pic14emitRegularMap (xdata, TRUE,TRUE);
728 pic14emitRegularMap (sfr, FALSE,FALSE);
729 pic14emitRegularMap (sfrbit, FALSE,FALSE);
730 pic14emitRegularMap (code, TRUE,FALSE);
731 pic14emitStaticSeg (statsg);
734 /*-----------------------------------------------------------------*/
735 /* createInterruptVect - creates the interrupt vector */
736 /*-----------------------------------------------------------------*/
737 static void pic14createInterruptVect (FILE * vFile)
740 mainf = newSymbol ("main", 0);
743 /* only if the main function exists */
744 if (!(mainf = findSymWithLevel (SymbolTab, mainf))) {
745 if (!options.cc_only)
750 /* if the main is only a prototype ie. no body then do nothing */
752 /* if ! compile only then main function should be present */
753 if (!options.cc_only)
758 fprintf (vFile, ";\t.area\t%s\n", CODE_NAME);
759 fprintf (vFile, ";__interrupt_vect:\n");
762 if (!port->genIVT || ! (port->genIVT(vFile, interrupts, maxInterrupts)))
764 /* "generic" interrupt table header (if port doesn't specify one).
766 * Look suspiciously like 8051 code to me...
769 fprintf (vFile, ";\tljmp\t__sdcc_gsinit_startup\n");
772 /* now for the other interrupts */
773 for (; i < maxInterrupts; i++) {
775 fprintf (vFile, ";\tljmp\t%s\n\t.ds\t5\n", interrupts[i]->rname);
777 fprintf (vFile, ";\treti\n;\t.ds\t7\n");
783 /*-----------------------------------------------------------------*/
784 /* initialComments - puts in some initial comments */
785 /*-----------------------------------------------------------------*/
786 static void pic14initialComments (FILE * afile)
788 initialComments(afile);
789 fprintf (afile, "; PIC port for the 14-bit core\n" );
790 fprintf (afile, iComments2);
794 /*-----------------------------------------------------------------*/
795 /* printPublics - generates .global for publics */
796 /*-----------------------------------------------------------------*/
797 static void pic14printPublics (FILE * afile)
801 fprintf (afile, "%s", iComments2);
802 fprintf (afile, "; publics variables in this module\n");
803 fprintf (afile, "%s", iComments2);
805 for (sym = setFirstItem (publics); sym;
806 sym = setNextItem (publics))
807 fprintf (afile, ";\t.globl %s\n", sym->rname);
812 /*-----------------------------------------------------------------*/
813 /* emitOverlay - will emit code for the overlay stuff */
814 /*-----------------------------------------------------------------*/
815 static void pic14emitOverlay(FILE *afile)
819 if (!elementsInSet(ovrSetSets))
820 fprintf(afile,";\t.area\t%s\n", port->mem.overlay_name);
822 /* for each of the sets in the overlay segment do */
823 for (ovrset = setFirstItem(ovrSetSets); ovrset;
824 ovrset = setNextItem(ovrSetSets)) {
828 if (elementsInSet(ovrset)) {
829 /* this dummy area is used to fool the assembler
830 otherwise the assembler will append each of these
831 declarations into one chunk and will not overlay
833 fprintf(afile,";\t.area _DUMMY\n");
834 /* output the area informtion */
835 fprintf(afile,";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
838 for (sym = setFirstItem(ovrset); sym;
839 sym = setNextItem(ovrset)) {
841 /* if extern then do nothing */
842 if (IS_EXTERN (sym->etype))
845 /* if allocation required check is needed
846 then check if the symbol really requires
847 allocation only for local variables */
848 if (!IS_AGGREGATE(sym->type) &&
849 !(sym->_isparm && !IS_REGPARM(sym->etype))
850 && !sym->allocreq && sym->level)
853 /* if global variable & not static or extern
854 and addPublics allowed then add it to the public set */
855 if ((sym->_isparm && !IS_REGPARM(sym->etype))
856 && !IS_STATIC (sym->etype))
857 addSetHead (&publics, sym);
859 /* if extern then do nothing or is a function
861 if (IS_FUNC (sym->type))
864 /* print extra debug info if required */
865 if (options.debug || sym->level == 0) {
867 cdbSymbol(sym,cdbFile,FALSE,FALSE);
869 if (!sym->level) { /* global */
870 if (IS_STATIC(sym->etype))
871 fprintf(afile,"F%s_",moduleName); /* scope is file */
873 fprintf(afile,"G_"); /* scope is global */
876 /* symbol is local */
877 fprintf(afile,"L%s_",
878 (sym->localof ? sym->localof->name : "-null-"));
879 fprintf(afile,"%s_%d_%d",sym->name,sym->level,sym->block);
882 /* if is has an absolute address then generate
883 an equate for this no need to allocate space */
884 if (SPEC_ABSA (sym->etype)) {
886 if (options.debug || sym->level == 0)
887 fprintf (afile," == 0x%04x\n",SPEC_ADDR (sym->etype));
889 fprintf (afile, "%s\t=\t0x%04x\n",
891 SPEC_ADDR (sym->etype));
894 if (options.debug || sym->level == 0)
895 fprintf(afile,"==.\n");
898 fprintf (afile, "%s:\n", sym->rname);
899 fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
908 /*-----------------------------------------------------------------*/
909 /* glue - the final glue that hold the whole thing together */
910 /*-----------------------------------------------------------------*/
915 FILE *ovrFile = tempfile();
918 addSetHead(&tmpfileSet,ovrFile);
919 /* print the global struct definitions */
921 cdbStructBlock (0,cdbFile);
924 /* PENDING: this isnt the best place but it will do */
925 if (port->general.glue_up_main) {
926 /* create the interrupt vector table */
927 pic14createInterruptVect (vFile);
930 addSetHead(&tmpfileSet,vFile);
932 /* emit code for the all the variables declared */
934 /* do the overlay segments */
935 pic14emitOverlay(ovrFile);
937 /* now put it all together into the assembler file */
938 /* create the assembler file name */
940 if (!options.c1mode) {
941 sprintf (buffer, srcFileName);
942 strcat (buffer, ".asm");
945 strcpy(buffer, options.out_name);
948 if (!(asmFile = fopen (buffer, "w"))) {
949 werror (E_FILE_OPEN_ERR, buffer);
953 /* initial comments */
954 pic14initialComments (asmFile);
956 /* print module name */
957 fprintf (asmFile, ";\t.module %s\n", moduleName);
959 /* Let the port generate any global directives, etc. */
960 if (port->genAssemblerPreamble)
962 port->genAssemblerPreamble(asmFile);
965 /* print the global variables in this module */
966 pic14printPublics (asmFile);
969 /* copy the sfr segment */
970 fprintf (asmFile, "%s", iComments2);
971 fprintf (asmFile, "; special function registers\n");
972 fprintf (asmFile, "%s", iComments2);
973 copyFile (asmFile, sfr->oFile);
976 /* Put all variables into a cblock */
977 fprintf (asmFile, "\n\n\tcblock 0x13\n\n");
979 for(i=0; i<pic14_nRegs; i++) {
980 if(regspic14[i].wasUsed && (regspic14[i].offset>=0x0c) )
981 fprintf (asmFile, "\t%s\n",regspic14[i].name);
983 //fprintf (asmFile, "\tr0x0C\n");
984 //fprintf (asmFile, "\tr0x0D\n");
986 /* For now, create a "dpl" and a "dph" in the register space */
987 /* of the pic so that we can use the same calling mechanism */
988 /* as the 8051 port */
989 fprintf (asmFile, "%s", iComments2);
990 fprintf (asmFile, "; dpl and dph to emulate the 8051 calling mechanism \n");
991 fprintf (asmFile, "%s", iComments2);
993 fprintf (asmFile, "\tdph\n");
997 /* copy the sbit segment */
998 fprintf (asmFile, "%s", iComments2);
999 fprintf (asmFile, "; special function bits \n");
1000 fprintf (asmFile, "%s", iComments2);
1001 copyFile (asmFile, sfrbit->oFile);
1003 /* copy the data segment */
1004 fprintf (asmFile, "%s", iComments2);
1005 fprintf (asmFile, "; internal ram data\n");
1006 fprintf (asmFile, "%s", iComments2);
1007 copyFile (asmFile, data->oFile);
1010 /* create the overlay segments */
1011 fprintf (asmFile, "%s", iComments2);
1012 fprintf (asmFile, "; overlayable items in internal ram \n");
1013 fprintf (asmFile, "%s", iComments2);
1014 copyFile (asmFile, ovrFile);
1016 /* create the stack segment MOF */
1017 if (mainf && mainf->fbody) {
1018 fprintf (asmFile, "%s", iComments2);
1019 fprintf (asmFile, "; Stack segment in internal ram \n");
1020 fprintf (asmFile, "%s", iComments2);
1021 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1022 ";__start__stack:\n;\t.ds\t1\n\n");
1025 /* create the idata segment */
1026 fprintf (asmFile, "%s", iComments2);
1027 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1028 fprintf (asmFile, "%s", iComments2);
1029 copyFile (asmFile, idata->oFile);
1031 /* if external stack then reserve space of it */
1032 if (mainf && mainf->fbody && options.useXstack ) {
1033 fprintf (asmFile, "%s", iComments2);
1034 fprintf (asmFile, "; external stack \n");
1035 fprintf (asmFile, "%s", iComments2);
1036 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1037 fprintf (asmFile,";\t.ds 256\n");
1041 /* copy xtern ram data */
1042 fprintf (asmFile, "%s", iComments2);
1043 fprintf (asmFile, "; external ram data\n");
1044 fprintf (asmFile, "%s", iComments2);
1045 copyFile (asmFile, xdata->oFile);
1048 fprintf (asmFile, "\tendc\n");
1051 /* copy the bit segment */
1052 fprintf (asmFile, "%s", iComments2);
1053 fprintf (asmFile, "; bit data\n");
1054 fprintf (asmFile, "%s", iComments2);
1055 copyFile (asmFile, bit->oFile);
1058 fprintf (asmFile, "\tORG 0\n");
1060 /* copy the interrupt vector table */
1061 if (mainf && mainf->fbody) {
1062 fprintf (asmFile, "%s", iComments2);
1063 fprintf (asmFile, "; interrupt vector \n");
1064 fprintf (asmFile, "%s", iComments2);
1065 copyFile (asmFile, vFile);
1068 /* copy global & static initialisations */
1069 fprintf (asmFile, "%s", iComments2);
1070 fprintf (asmFile, "; global & static initialisations\n");
1071 fprintf (asmFile, "%s", iComments2);
1073 /* Everywhere we generate a reference to the static_name area,
1074 * (which is currently only here), we immediately follow it with a
1075 * definition of the post_static_name area. This guarantees that
1076 * the post_static_name area will immediately follow the static_name
1079 fprintf (asmFile, ";\t.area %s\n", port->mem.static_name); /* MOF */
1080 fprintf (asmFile, ";\t.area %s\n", port->mem.post_static_name);
1081 fprintf (asmFile, ";\t.area %s\n", port->mem.static_name);
1083 if (mainf && mainf->fbody) {
1084 fprintf (asmFile,"__sdcc_gsinit_startup:\n");
1085 /* if external stack is specified then the
1086 higher order byte of the xdatalocation is
1087 going into P2 and the lower order going into
1089 if (options.useXstack) {
1090 fprintf(asmFile,";\tmov\tP2,#0x%02x\n",
1091 (((unsigned int)options.xdata_loc) >> 8) & 0xff);
1092 fprintf(asmFile,";\tmov\t_spx,#0x%02x\n",
1093 (unsigned int)options.xdata_loc & 0xff);
1096 /* initialise the stack pointer */
1097 /* if the user specified a value then use it */
1098 if (options.stack_loc)
1099 fprintf(asmFile,";\tmov\tsp,#%d\n",options.stack_loc);
1101 /* no: we have to compute it */
1102 if (!options.stackOnData && maxRegBank <= 3)
1103 fprintf(asmFile,";\tmov\tsp,#%d\n",((maxRegBank + 1) * 8) -1);
1105 fprintf(asmFile,";\tmov\tsp,#__start__stack\n"); /* MOF */
1107 fprintf (asmFile,";\tlcall\t__sdcc_external_startup\n");
1108 fprintf (asmFile,";\tmov\ta,dpl\n");
1109 fprintf (asmFile,";\tjz\t__sdcc_init_data\n");
1110 fprintf (asmFile,";\tljmp\t__sdcc_program_startup\n");
1111 fprintf (asmFile,";__sdcc_init_data:\n");
1114 copyFile (asmFile, statsg->oFile);
1116 if (port->general.glue_up_main && mainf && mainf->fbody)
1118 /* This code is generated in the post-static area.
1119 * This area is guaranteed to follow the static area
1120 * by the ugly shucking and jiving about 20 lines ago.
1122 fprintf(asmFile, ";\t.area %s\n", port->mem.post_static_name);
1123 fprintf (asmFile,";\tljmp\t__sdcc_program_startup\n");
1126 /* copy over code */
1127 fprintf (asmFile, "%s", iComments2);
1128 fprintf (asmFile, "; code\n");
1129 fprintf (asmFile, "%s", iComments2);
1130 fprintf (asmFile, ";\t.area %s\n", port->mem.code_name);
1131 if (mainf && mainf->fbody) {
1133 /* entry point @ start of CSEG */
1134 fprintf (asmFile,"__sdcc_program_startup:\n");
1136 /* put in the call to main */
1137 fprintf(asmFile,"\tcall\t_main\n");
1138 if (options.mainreturn) {
1140 fprintf(asmFile,";\treturn from main ; will return to caller\n");
1141 fprintf(asmFile,"\treturn\n");
1145 fprintf(asmFile,";\treturn from main will lock up\n");
1146 fprintf(asmFile,"\tgoto\t$\n");
1149 copyFile (asmFile, code->oFile);
1151 fprintf (asmFile,"\tend\n");
1154 applyToSet(tmpfileSet,closeTmpFiles);
1155 applyToSet(tmpfileNameSet, rmTmpFiles);