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"
34 #ifdef WORDS_BIGENDIAN
35 #define _ENDIAN(x) (3-x)
37 #define _ENDIAN(x) (x)
40 #define BYTE_IN_LONG(x,b) ((x>>(8*_ENDIAN(b)))&0xff)
42 extern symbol *interrupts[256];
43 static void printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb);
47 extern unsigned maxInterrupts;
48 extern int maxRegBank;
50 extern char *VersionString;
51 extern FILE *codeOutFile;
52 extern set *tmpfileSet;
53 extern set *tmpfileNameSet;
54 extern char *iComments1;
55 extern char *iComments2;
56 //extern void emitStaticSeg (memmap * map);
58 extern DEFSETFUNC (closeTmpFiles);
59 extern DEFSETFUNC (rmTmpFiles);
61 extern void AnalyzeBanking (void);
62 extern void copyFile (FILE * dest, FILE * src);
63 extern void ReuseReg(void);
64 extern void InlinepCode(void);
65 extern void writeUsedRegs(FILE *);
67 extern void initialComments (FILE * afile);
68 extern void printPublics (FILE * afile);
70 extern void printChar (FILE * ofile, char *s, int plen);
71 void pCodeInitRegisters(void);
72 int getConfigWord(int address);
73 int getHasSecondConfigReg(void);
74 int pic14_getSharebankSize(void);
75 int pic14_getSharebankAddress(void);
77 char *udata_section_name=0; // FIXME Temporary fix to change udata section name -- VR
79 /*-----------------------------------------------------------------*/
80 /* aopLiteral - string from a literal value */
81 /*-----------------------------------------------------------------*/
82 int pic14aopLiteral (value *val, int offset)
89 /* if it is a float then it gets tricky */
90 /* otherwise it is fairly simple */
91 if (!IS_FLOAT(val->type)) {
92 unsigned long v = (unsigned long) floatFromVal(val);
94 return ( (v >> (offset * 8)) & 0xff);
97 /* it is type float */
98 fl.f = (float) floatFromVal(val);
99 #ifdef WORDS_BIGENDIAN
100 return fl.c[3-offset];
107 /* Check whether the given reg is shared amongst all .o files of a project.
108 * This is true for the pseudo stack and WSAVE, SSAVE and PSAVE. */
110 is_shared_address (int addr)
112 return ((addr > Gstack_base_addr - 18)
113 && (addr <= Gstack_base_addr));
117 pic14_is_shared (regs *reg)
120 return is_shared_address (reg->address);
124 is_valid_identifier( const char *name )
130 /* only accept [a-zA-Z_][a-zA-Z0-9_] */
131 if (!((a >= 'a' && a <= 'z')
132 || (a >= 'A' && a <= 'z')
137 while ((a = *name++))
139 if (!((a >= 'a' && a <= 'z')
140 || (a >= 'A' && a <= 'Z')
141 || (a >= '0' && a <= '9')
146 /* valid identifier */
150 /* set of already emitted symbols; we store only pointers to the emitted
151 * symbol names so these MUST NO BE CHANGED afterwards... */
152 static set *symbolsEmitted = NULL;
154 /*-------------------------------------------------------------------*/
155 /* emitSymbolToFile - write a symbol definition only if it is not */
156 /* already present */
157 /*-------------------------------------------------------------------*/
159 emitSymbolToFile (FILE *of, const char *name, const char *section_type, int size, int addr, int useEQU, int globalize)
162 static unsigned int sec_idx = 0;
164 /* workaround: variables declared via `sbit' result in a numeric
165 * identifier (0xHH), EQU'ing them is invalid, so just ignore it.
166 * sbit is heavily used in the inc2h-generated header files!
168 if (!is_valid_identifier(name))
170 //fprintf( stderr, "%s:%s:%u: ignored symbol: %s\n", __FILE__, __FUNCTION__, __LINE__, name );
174 /* check whether the symbol is already defined */
175 for (sym = (const char *) setFirstItem (symbolsEmitted);
177 sym = (const char *) setNextItem (symbolsEmitted))
179 if (!strcmp (sym, name))
181 //fprintf (stderr, "%s: already emitted: %s\n", __FUNCTION__, name);
186 /* new symbol -- define it */
187 //fprintf (stderr, "%s: emitting %s (%d)\n", __FUNCTION__, name, size);
189 fprintf (of, "%s\tEQU\t0x%04x\n", name, addr);
192 /* we place each symbol into a section of its own to allow the linker
193 * to distribute the data into all available memory banks */
194 if (!section_type) section_type = "udata";
197 /* absolute symbols are handled in pic14_constructAbsMap */
200 /* workaround gpasm bug with symbols being EQUated and placed in absolute sections */
201 if (1 || !is_shared_address (addr))
203 if (globalize) fprintf (of, "\tglobal\t%s\n", name);
204 fprintf (of, "udata_%s_%u\t%s\t0x%04x\n", moduleName,
205 sec_idx++, "udata_ovr", addr);
206 fprintf (of, "%s\tres\t%d\n", name, size);
210 /* EQUs cannot be exported... */
211 fprintf (of, "%s\tEQU\t0x%04x\n", name, addr);
215 if (globalize) fprintf (of, "\tglobal\t%s\n", name);
216 fprintf (of, "udata_%s_%u\t%s\n", moduleName,
217 sec_idx++, section_type);
218 fprintf (of, "%s\tres\t%d\n", name, size);
222 //if (options.verbose) fprintf (stderr, "%s: emitted %s\n", __FUNCTION__, name);
223 addSet (&symbolsEmitted, (void *) name);
226 #define IS_DEFINED_HERE(sym) (!IS_EXTERN(sym->etype))
228 pic14_constructAbsMap (FILE *ofile)
230 memmap *maps[] = { data, sfr, NULL };
235 int addr, min=-1, max=-1;
238 for (i=0; maps[i] != NULL; i++)
240 for (sym = (symbol *)setFirstItem (maps[i]->syms);
241 sym; sym = setNextItem (maps[i]->syms))
243 if (IS_DEFINED_HERE(sym) && SPEC_ABSA(sym->etype))
245 addr = SPEC_ADDR(sym->etype);
246 if (max == -1 || addr > max) max = addr;
247 if (min == -1 || addr < min) min = addr;
248 //fprintf (stderr, "%s: sym %s @ 0x%x\n", __FUNCTION__, sym->name, addr);
249 aliases = hTabItemWithKey (ht, addr);
251 /* May not use addSetHead, as we cannot update the
252 * list's head in the hastable `ht'. */
253 addSet (&aliases, sym);
255 fprintf( stderr, "%s: now %d aliases for %s @ 0x%x\n",
256 __FUNCTION__, elementsInSet(aliases), sym->name, addr);
259 addSet (&aliases, sym);
260 hTabAddItem (&ht, addr, aliases);
266 /* now emit definitions for all absolute symbols */
267 fprintf (ofile, "%s", iComments2);
268 fprintf (ofile, "; absolute symbol definitions\n");
269 fprintf (ofile, "%s", iComments2);
270 for (addr=min; addr <= max; addr++)
273 aliases = hTabItemWithKey (ht, addr);
274 if (aliases && elementsInSet(aliases)) {
275 fprintf (ofile, "udata_abs_%s_%x\tudata_ovr\t0x%04x",
276 moduleName, addr, addr);
277 for (sym = setFirstItem (aliases); sym;
278 sym = setNextItem (aliases))
280 /* emit STATUS as well as _STATUS, required for SFRs only */
281 fprintf (ofile, "\n%s", sym->name);
282 fprintf (ofile, "\n%s", sym->rname);
283 if (getSize(sym->type) > size) {
284 size = getSize(sym->type);
287 fprintf (ofile, "\tres\t%d\n", size);
291 /* also emit STK symbols
292 * XXX: This is ugly and fails as soon as devices start to get
293 * differently sized sharebanks, since STK12 will be
294 * required by larger devices but only up to STK03 might
295 * be defined using smaller devices. */
296 fprintf (ofile, "\n");
297 if (!pic14_options.isLibrarySource)
299 fprintf (ofile, "\tglobal PSAVE\n");
300 fprintf (ofile, "\tglobal SSAVE\n");
301 fprintf (ofile, "\tglobal WSAVE\n");
302 for (i=pic14_getSharebankSize()-4; i >= 0; i--) {
303 fprintf (ofile, "\tglobal STK%02d\n", i);
305 fprintf (ofile, "sharebank udata_ovr 0x%04x\n",
306 pic14_getSharebankAddress() - pic14_getSharebankSize() + 1);
307 fprintf (ofile, "PSAVE\tres 1\n");
308 fprintf (ofile, "SSAVE\tres 1\n");
309 fprintf (ofile, "WSAVE\tres 1\n");
310 /* fill rest of sharebank with stack STKxx .. STK00 */
311 for (i=pic14_getSharebankSize()-4; i >= 0; i--) {
312 fprintf (ofile, "STK%02d\tres 1\n", i);
315 /* declare STKxx as extern for all files
316 * except the one containing main() */
317 fprintf (ofile, "\textern PSAVE\n");
318 fprintf (ofile, "\textern SSAVE\n");
319 fprintf (ofile, "\textern WSAVE\n");
320 for (i=pic14_getSharebankSize()-4; i >= 0; i--) {
321 fprintf (ofile, "\textern STK%02d\n", i);
326 /*-----------------------------------------------------------------*/
327 /* emitRegularMap - emit code for maps with no special cases */
328 /*-----------------------------------------------------------------*/
330 pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag)
335 /* print the area name */
337 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
339 for (sym = setFirstItem (map->syms); sym;
340 sym = setNextItem (map->syms)) {
342 //printf("%s\n",sym->name);
344 /* if extern then add it into the extern list */
345 if (IS_EXTERN (sym->etype)) {
346 addSetHead (&externs, sym);
350 /* if allocation required check is needed
351 then check if the symbol really requires
352 allocation only for local variables */
353 if (arFlag && !IS_AGGREGATE (sym->type) &&
354 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
355 !sym->allocreq && sym->level)
358 /* if global variable & not static or extern
359 and addPublics allowed then add it to the public set */
360 if ((sym->level == 0 ||
361 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
363 !IS_STATIC (sym->etype))
365 //fprintf( stderr, "%s: made public %s\n", __FUNCTION__, sym->name );
366 addSetHead (&publics, sym);
369 // PIC code allocates its own registers - so ignore parameter variable generated by processFuncArgs()
372 /* if extern then do nothing or is a function
374 if (IS_FUNC (sym->type))
377 /* print extra debug info if required */
378 if (options.debug || sym->level == 0)
380 if (!sym->level) /* global */
381 if (IS_STATIC (sym->etype))
382 fprintf (map->oFile, "F%s_", moduleName); /* scope is file */
384 fprintf (map->oFile, "G_"); /* scope is global */
386 /* symbol is local */
387 fprintf (map->oFile, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
388 fprintf (map->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
391 /* absolute symbols are handled in pic14_constructAbsMap */
392 if (SPEC_ABSA(sym->etype) && IS_DEFINED_HERE(sym))
395 /* if it has an absolute address then generate
396 an equate for this no need to allocate space */
397 if (0 && SPEC_ABSA (sym->etype))
399 //if (options.debug || sym->level == 0)
400 //fprintf (map->oFile,"; == 0x%04x\n",SPEC_ADDR (sym->etype));
402 fprintf (map->oFile, "%s\tEQU\t0x%04x\n",
404 SPEC_ADDR (sym->etype));
410 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
411 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
412 /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
413 if (IS_BITVAR (sym->etype))
419 emitSymbolToFile (map->oFile,
422 getSize (sym->type) & 0xffff,
423 SPEC_ABSA(sym->etype)
424 ? SPEC_ADDR(sym->etype)
432 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1)
434 for (i = 1; i < size; i++)
435 fprintf (map->oFile, "\t%s_%d\n", sym->rname, i);
440 //fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
443 /* if it has a initial value then do it only if
444 it is a global variable */
445 if (sym->ival && sym->level == 0) {
448 if (IS_AGGREGATE (sym->type))
449 ival = initAggregates (sym, sym->ival, NULL);
451 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
452 decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
453 codeOutFile = statsg->oFile;
455 eBBlockFromiCode (iCodeFromAst (ival));
462 /*-----------------------------------------------------------------*/
463 /* printIvalType - generates ival for int/char */
464 /*-----------------------------------------------------------------*/
466 printIvalType (symbol *sym, sym_link * type, initList * ilist, pBlock *pb)
471 //fprintf(stderr, "%s\n",__FUNCTION__);
473 /* if initList is deep */
474 if (ilist->type == INIT_DEEP)
475 ilist = ilist->init.deep;
477 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
478 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
481 if (!(val = list2val (ilist))) {
482 // assuming a warning has been thrown
486 if (val->type != type) {
487 val = valCastLiteral(type, floatFromVal(val));
491 ulval = (unsigned long) floatFromVal (val);
495 switch (getSize (type)) {
497 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
501 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
502 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
506 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
507 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
508 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
509 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
514 /*-----------------------------------------------------------------*/
515 /* printIvalBitFields - generate initializer for bitfields */
516 /*-----------------------------------------------------------------*/
517 static void printIvalBitFields(symbol **sym, initList **ilist, pBlock *pb )
521 initList *lilist = *ilist ;
522 unsigned long ival = 0;
528 val = list2val(lilist);
530 if (SPEC_BLEN(lsym->etype) > 8) {
531 size += ((SPEC_BLEN (lsym->etype) / 8) +
532 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
535 size = ((SPEC_BLEN (lsym->etype) / 8) +
536 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
538 i = (unsigned long)floatFromVal(val);
539 i <<= SPEC_BSTR (lsym->etype);
541 if (! ( lsym->next &&
542 (IS_BITFIELD(lsym->next->type)) &&
543 (SPEC_BSTR(lsym->next->etype)))) break;
545 lilist = lilist->next;
549 //tfprintf (oFile, "\t!db !constbyte\n",ival);
550 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
554 //tfprintf (oFile, "\t!dw !constword\n",ival);
555 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
556 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
559 //tfprintf (oFile, "\t!db !constword,!constword\n",(ival >> 8) & 0xffff, (ival & 0xffff));
560 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>24)));
561 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>16)));
562 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
563 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
570 /*-----------------------------------------------------------------*/
571 /* printIvalStruct - generates initial value for structures */
572 /*-----------------------------------------------------------------*/
573 static void printIvalStruct (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
576 initList *iloop = NULL;
578 sflds = SPEC_STRUCT (type)->fields;
581 if (ilist->type != INIT_DEEP) {
582 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
586 iloop = ilist->init.deep;
589 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
590 if (IS_BITFIELD(sflds->type)) {
591 printIvalBitFields(&sflds,&iloop,pb);
593 printIval (sym, sflds->type, iloop, pb);
597 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
602 /*-----------------------------------------------------------------*/
603 /* printIvalChar - generates initital value for character array */
604 /*-----------------------------------------------------------------*/
606 printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
614 //fprintf(stderr, "%s\n",__FUNCTION__);
618 val = list2val (ilist);
620 /* if the value is a character string */
621 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
623 ilen = DCL_ELEM(val->type);
625 if (!DCL_ELEM (type))
626 DCL_ELEM (type) = ilen;
628 /* emit string constant */
629 for (remain = 0; remain < ilen; remain++) {
630 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(SPEC_CVAL(val->etype).v_char[remain])));
633 /* fill array up to desired size */
634 if ((remain = (DCL_ELEM (type) - ilen)) > 0)
636 //tfprintf (oFile, "\t!db !constbyte\n", 0);
637 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
644 //printChar (oFile, s, strlen (s) + 1);
646 for(remain=0; remain<(int)strlen(s); remain++) {
647 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(s[remain])));
648 //fprintf(stderr,"0x%02x ",s[remain]);
650 //fprintf(stderr,"\n");
655 /*-----------------------------------------------------------------*/
656 /* printIvalArray - generates code for array initialization */
657 /*-----------------------------------------------------------------*/
659 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
668 /* take care of the special case */
669 /* array of characters can be init */
671 if (IS_CHAR (type->next)) {
672 //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
673 if (!IS_LITERAL(list2val(ilist)->etype)) {
674 werror (W_INIT_WRONG);
677 if (printIvalChar (type,
678 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
679 pb, SPEC_CVAL (sym->etype).v_char))
682 /* not the special case */
683 if (ilist->type != INIT_DEEP) {
684 werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
688 for (iloop=ilist->init.deep; iloop; iloop=iloop->next) {
689 if ((++size > DCL_ELEM(type)) && DCL_ELEM(type)) {
690 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
693 printIval (sym, type->next, iloop, pb);
697 if (DCL_ELEM(type)) {
698 // pad with zeros if needed
699 if (size<DCL_ELEM(type)) {
700 size = (DCL_ELEM(type) - size) * getSize(type->next);
702 //tfprintf (oFile, "\t!db !constbyte\n", 0);
703 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
707 // we have not been given a size, but we now know it
708 DCL_ELEM (type) = size;
714 /*-----------------------------------------------------------------*/
715 /* printIvalPtr - generates code for initial value of pointers */
716 /*-----------------------------------------------------------------*/
717 extern value *initPointer (initList *, sym_link *toType);
720 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
727 fprintf (stderr, "FIXME: initializers for pointers...\n");
728 printTypeChain (type, stderr);
730 fprintf (stderr, "symbol: %s, DCL_TYPE():%d, DCL_ELEM():%d, IS_ARRAY():%d", sym->rname, DCL_TYPE(type), DCL_ELEM(type), IS_ARRAY(type));
731 fprintf (stderr, "ilist: type=%d (INIT_DEEP=%d, INIT_NODE=%d)\n", ilist->type, INIT_DEEP, INIT_NODE);
733 if (ilist && (ilist->type == INIT_DEEP))
734 ilist = ilist->init.deep;
736 /* function pointers */
737 if (IS_FUNC (type->next))
739 assert ( !"function pointers not yet handled" );
740 //printIvalFuncPtr (type, ilist, pb);
743 if (!(val = initPointer (ilist, type)))
746 if (IS_CHAR (type->next))
748 if (printIvalChar (type, ilist, pb, NULL)) return;
752 if (compareType (type, val->type) == 0)
754 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
755 printFromToType (val->type, type);
758 if (IS_LITERAL (val->etype))
760 switch (getSize (type))
763 fprintf (stderr, "BYTE: %i\n", (unsigned char)floatFromVal (val) & 0x00FF);
766 fprintf (stderr, "WORD: %i\n", (unsigned int)floatFromVal (val) & 0x00FFFF);
768 case 3: /* gneric pointers */
769 assert ( !"generic pointers not yet handled" );
771 fprintf (stderr, "LONG: %i\n", (unsigned int)floatFromVal (val) & 0x0000FFFFFFFF);
774 assert ( !"invaild size of value -- aborting" );
780 /* now handle symbolic values */
781 switch (getSize (type))
784 fprintf (stderr, "BYTE: %s", val->name);
787 fprintf (stderr, "WORD: %s", val->name);
790 fprintf (stderr, "LONG: %s", val->name);
793 assert ( !"invalid size of (symbolic) value -- aborting" );
797 /*-----------------------------------------------------------------*/
798 /* printIval - generates code for initial value */
799 /*-----------------------------------------------------------------*/
801 printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
806 /* if structure then */
807 if (IS_STRUCT (type))
809 //fprintf(stderr,"%s struct: %s\n",__FUNCTION__, sym->rname);
810 printIvalStruct (sym, type, ilist, pb);
814 /* if this is an array */
817 //fprintf(stderr,"%s array: %s\n",__FUNCTION__, sym->rname);
818 printIvalArray (sym, type, ilist, pb);
822 /* if this is a pointer */
825 //fprintf(stderr,"%s pointer: %s\n",__FUNCTION__, sym->rname);
826 printIvalPtr (sym, type, ilist, pb);
830 /* if type is SPECIFIER */
833 //fprintf(stderr,"%s spec %s\n",__FUNCTION__, sym->rname);
834 printIvalType (sym, type, ilist, pb);
839 extern void pCodeConstString(char *name, char *value);
840 /*-----------------------------------------------------------------*/
841 /* emitStaticSeg - emitcode for the static segment */
842 /*-----------------------------------------------------------------*/
844 pic14emitStaticSeg (memmap * map)
848 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
850 //fprintf(stderr, "%s\n",__FUNCTION__);
852 /* for all variables in this segment do */
853 for (sym = setFirstItem (map->syms); sym;
854 sym = setNextItem (map->syms))
856 /* if extern then add it into the extern list */
857 if (IS_EXTERN (sym->etype)) {
858 addSetHead (&externs, sym);
862 /* if it is not static add it to the public
864 if (!IS_STATIC (sym->etype))
865 addSetHead (&publics, sym);
867 /* print extra debug info if required */
868 if (options.debug || sym->level == 0)
872 if (IS_STATIC (sym->etype))
873 fprintf (code->oFile, "F%s_", moduleName); /* scope is file */
875 fprintf (code->oFile, "G_"); /* scope is global */
878 /* symbol is local */
879 fprintf (code->oFile, "L%s_",
880 (sym->localof ? sym->localof->name : "-null-"));
881 fprintf (code->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
885 /* if it has an absolute address */
886 if (SPEC_ABSA (sym->etype))
888 if (options.debug || sym->level == 0)
889 fprintf (code->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
891 fprintf (code->oFile, "%s\t=\t0x%04x\n",
893 SPEC_ADDR (sym->etype));
897 if (options.debug || sym->level == 0)
898 fprintf (code->oFile, " == .\n");
900 /* if it has an initial value */
905 fprintf (code->oFile, "%s:\n", sym->rname);
907 resolveIvalSym (sym->ival, sym->type);
908 //printIval (sym, sym->type, sym->ival, code->oFile);
909 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block for Ival"));
911 addpCode2pBlock(pb,newpCodeLabel(sym->rname,-1));
913 printIval (sym, sym->type, sym->ival, pb);
920 fprintf (code->oFile, "%s:\n", sym->rname);
921 /* special case for character strings */
922 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
923 SPEC_CVAL (sym->etype).v_char)
924 pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
925 /*printChar (code->oFile,
926 SPEC_CVAL (sym->etype).v_char,
927 strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
929 fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
937 /*-----------------------------------------------------------------*/
938 /* emitMaps - emits the code for the data portion the code */
939 /*-----------------------------------------------------------------*/
943 pic14_constructAbsMap (sfr->oFile);
944 /* no special considerations for the following
945 data, idata & bit & xdata */
946 pic14emitRegularMap (data, TRUE, TRUE);
947 pic14emitRegularMap (idata, TRUE, TRUE);
948 pic14emitRegularMap (bit, TRUE, FALSE);
949 pic14emitRegularMap (xdata, TRUE, TRUE);
950 pic14emitRegularMap (sfr, TRUE, FALSE);
951 pic14emitRegularMap (sfrbit, FALSE, FALSE);
952 pic14emitRegularMap (code, TRUE, FALSE);
953 pic14emitStaticSeg (statsg);
956 /*-----------------------------------------------------------------*/
957 /* createInterruptVect - creates the interrupt vector */
958 /*-----------------------------------------------------------------*/
960 pic14createInterruptVect (FILE * vFile)
962 mainf = newSymbol ("main", 0);
965 /* only if the main function exists */
966 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
968 struct options *op = &options;
969 if (!(op->cc_only || noAssemble))
970 // werror (E_NO_MAIN);
971 fprintf(stderr,"WARNING: function 'main' undefined\n");
975 /* if the main is only a prototype ie. no body then do nothing */
976 if (!IFFUNC_HASBODY(mainf->type))
978 /* if ! compile only then main function should be present */
979 if (!(options.cc_only || noAssemble))
980 // werror (E_NO_MAIN);
981 fprintf(stderr,"WARNING: function 'main' undefined\n");
985 fprintf (vFile, "%s", iComments2);
986 fprintf (vFile, "; config word \n");
987 fprintf (vFile, "%s", iComments2);
988 if (getHasSecondConfigReg())
990 fprintf (vFile, "\t__config _CONFIG1, 0x%x\n", getConfigWord(0x2007));
991 fprintf (vFile, "\t__config _CONFIG2, 0x%x\n", getConfigWord(0x2008));
994 fprintf (vFile, "\t__config 0x%x\n", getConfigWord(0x2007));
996 fprintf (vFile, "%s", iComments2);
997 fprintf (vFile, "; reset vector \n");
998 fprintf (vFile, "%s", iComments2);
999 fprintf (vFile, "STARTUP\t%s\n", CODE_NAME); // Lkr file should place section STARTUP at address 0x0
1000 fprintf (vFile, "\tnop\n"); /* first location for used by incircuit debugger */
1001 fprintf (vFile, "\tgoto\t__sdcc_gsinit_startup\n");
1005 /*-----------------------------------------------------------------*/
1006 /* initialComments - puts in some initial comments */
1007 /*-----------------------------------------------------------------*/
1009 pic14initialComments (FILE * afile)
1011 initialComments (afile);
1012 fprintf (afile, "; PIC port for the 14-bit core\n");
1013 fprintf (afile, iComments2);
1017 /*-----------------------------------------------------------------*/
1018 /* printExterns - generates extern for external variables */
1019 /*-----------------------------------------------------------------*/
1021 pic14printExterns (FILE * afile)
1025 fprintf (afile, "%s", iComments2);
1026 fprintf (afile, "; extern variables in this module\n");
1027 fprintf (afile, "%s", iComments2);
1029 for (sym = setFirstItem (externs); sym;
1030 sym = setNextItem (externs))
1031 fprintf (afile, "\textern %s\n", sym->rname);
1034 /*-----------------------------------------------------------------*/
1035 /* printPublics - generates .global for publics */
1036 /*-----------------------------------------------------------------*/
1038 pic14printPublics (FILE * afile)
1042 fprintf (afile, "%s", iComments2);
1043 fprintf (afile, "; publics variables in this module\n");
1044 fprintf (afile, "%s", iComments2);
1046 for (sym = setFirstItem (publics); sym;
1047 sym = setNextItem (publics)) {
1049 if(!IS_BITFIELD(sym->type) && ((IS_FUNC(sym->type) || sym->allocreq))) {
1050 if (!IS_BITVAR(sym->type))
1051 fprintf (afile, "\tglobal %s\n", sym->rname);
1053 /* Absolute variables are defines in the asm file as equates and thus can not be made global. */
1054 /* Not any longer! */
1055 //if (!SPEC_ABSA (sym->etype))
1056 fprintf (afile, "\tglobal %s\n", sym->rname);
1061 /*-----------------------------------------------------------------*/
1062 /* emitOverlay - will emit code for the overlay stuff */
1063 /*-----------------------------------------------------------------*/
1065 pic14emitOverlay (FILE * afile)
1069 /* if (!elementsInSet (ovrSetSets))*/
1071 /* the hack below, fixes translates for devices which
1072 * only have udata_shr memory */
1073 fprintf (afile, "%s\t%s\n",
1074 (elementsInSet(ovrSetSets)?"":";"),
1075 port->mem.overlay_name);
1077 /* for each of the sets in the overlay segment do */
1078 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1079 ovrset = setNextItem (ovrSetSets))
1084 if (elementsInSet (ovrset))
1086 /* this dummy area is used to fool the assembler
1087 otherwise the assembler will append each of these
1088 declarations into one chunk and will not overlay
1091 /* I don't think this applies to us. We are using gpasm. CRF */
1093 fprintf (afile, ";\t.area _DUMMY\n");
1094 /* output the area informtion */
1095 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1098 for (sym = setFirstItem (ovrset); sym;
1099 sym = setNextItem (ovrset))
1102 /* if extern then do nothing */
1103 if (IS_EXTERN (sym->etype))
1106 /* if allocation required check is needed
1107 then check if the symbol really requires
1108 allocation only for local variables */
1109 if (!IS_AGGREGATE (sym->type) &&
1110 !(sym->_isparm && !IS_REGPARM (sym->etype))
1111 && !sym->allocreq && sym->level)
1114 /* if global variable & not static or extern
1115 and addPublics allowed then add it to the public set */
1116 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1117 && !IS_STATIC (sym->etype))
1118 addSetHead (&publics, sym);
1120 /* if extern then do nothing or is a function
1122 if (IS_FUNC (sym->type))
1125 /* print extra debug info if required */
1126 if (options.debug || sym->level == 0)
1130 if (IS_STATIC (sym->etype))
1131 fprintf (afile, "F%s_", moduleName); /* scope is file */
1133 fprintf (afile, "G_"); /* scope is global */
1136 /* symbol is local */
1137 fprintf (afile, "L%s_",
1138 (sym->localof ? sym->localof->name : "-null-"));
1139 fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
1142 /* if is has an absolute address then generate
1143 an equate for this no need to allocate space */
1144 if (SPEC_ABSA (sym->etype))
1147 if (options.debug || sym->level == 0)
1148 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1150 fprintf (afile, "%s\t=\t0x%04x\n",
1152 SPEC_ADDR (sym->etype));
1156 if (options.debug || sym->level == 0)
1157 fprintf (afile, "==.\n");
1159 /* allocate space */
1160 fprintf (afile, "%s:\n", sym->rname);
1161 fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1169 /*-----------------------------------------------------------------*/
1170 /* glue - the final glue that hold the whole thing together */
1171 /*-----------------------------------------------------------------*/
1175 char udata_name[80];
1178 FILE *ovrFile = tempfile();
1180 addSetHead(&tmpfileSet,ovrFile);
1181 pCodeInitRegisters();
1183 /* check for main() */
1184 mainf = newSymbol ("main", 0);
1186 mainf = findSymWithLevel (SymbolTab, mainf);
1188 if (!mainf || !IFFUNC_HASBODY(mainf->type))
1190 /* main missing -- import stack from main module */
1191 //fprintf (stderr, "main() missing -- assuming we are NOT the main module\n");
1192 pic14_options.isLibrarySource = 1;
1196 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1198 pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
1201 /* entry point @ start of CSEG */
1202 addpCode2pBlock(pb,newpCodeLabel("__sdcc_program_startup",-1));
1203 /* put in the call to main */
1204 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp("_main",PO_STR)));
1206 if (options.mainreturn) {
1208 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will return to caller\n"));
1209 addpCode2pBlock(pb,newpCode(POC_RETURN,NULL));
1213 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will lock up\n"));
1214 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("$",PO_STR)));
1220 /* At this point we've got all the code in the form of pCode structures */
1221 /* Now it needs to be rearranged into the order it should be placed in the */
1224 movepBlock2Head('P'); // Last
1225 movepBlock2Head(code->dbName);
1226 movepBlock2Head('X');
1227 movepBlock2Head(statsg->dbName); // First
1230 /* print the global struct definitions */
1236 addSetHead(&tmpfileSet,vFile);
1238 /* emit code for the all the variables declared */
1240 /* do the overlay segments */
1241 pic14emitOverlay(ovrFile);
1243 /* PENDING: this isnt the best place but it will do */
1244 if (port->general.glue_up_main) {
1245 /* create the interrupt vector table */
1246 pic14createInterruptVect (vFile);
1251 ReuseReg(); // ReuseReg where call tree permits
1260 /* now put it all together into the assembler file */
1261 /* create the assembler file name */
1263 if ((noAssemble || options.c1mode) && fullDstFileName)
1265 sprintf (buffer, fullDstFileName);
1269 sprintf (buffer, dstFileName);
1270 strcat (buffer, ".asm");
1273 if (!(asmFile = fopen (buffer, "w"))) {
1274 werror (E_FILE_OPEN_ERR, buffer);
1278 /* prepare statistics */
1279 resetpCodeStatistics ();
1281 /* initial comments */
1282 pic14initialComments (asmFile);
1284 /* print module name */
1285 fprintf (asmFile, ";\t.module %s\n", moduleName);
1287 /* Let the port generate any global directives, etc. */
1288 if (port->genAssemblerPreamble)
1290 port->genAssemblerPreamble(asmFile);
1293 /* print the extern variables in this module */
1294 pic14printExterns (asmFile);
1296 /* print the global variables in this module */
1297 pic14printPublics (asmFile);
1299 /* copy the sfr segment */
1300 fprintf (asmFile, "%s", iComments2);
1301 fprintf (asmFile, "; special function registers\n");
1302 fprintf (asmFile, "%s", iComments2);
1303 copyFile (asmFile, sfr->oFile);
1306 if (udata_section_name) {
1307 sprintf(udata_name,"%s",udata_section_name);
1309 sprintf(udata_name,"data_%s",moduleName);
1311 fprintf (asmFile, "%s", iComments2);
1312 fprintf (asmFile, "; udata\n");
1313 fprintf (asmFile, "%s", iComments2);
1314 fprintf (asmFile, "%s\tudata\n", udata_name);
1315 copyFile (asmFile, data->oFile);
1317 /* Put all variables into a cblock */
1319 writeUsedRegs(asmFile);
1321 /* create the overlay segments */
1322 fprintf (asmFile, "%s", iComments2);
1323 fprintf (asmFile, "; overlayable items in internal ram \n");
1324 fprintf (asmFile, "%s", iComments2);
1325 copyFile (asmFile, ovrFile);
1329 /* create the stack segment MOF */
1330 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1331 fprintf (asmFile, "%s", iComments2);
1332 fprintf (asmFile, "; Stack segment in internal ram \n");
1333 fprintf (asmFile, "%s", iComments2);
1334 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1335 ";__start__stack:\n;\t.ds\t1\n\n");
1338 /* create the idata segment */
1339 fprintf (asmFile, "%s", iComments2);
1340 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1341 fprintf (asmFile, "%s", iComments2);
1342 copyFile (asmFile, idata->oFile);
1344 /* if external stack then reserve space of it */
1345 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1346 fprintf (asmFile, "%s", iComments2);
1347 fprintf (asmFile, "; external stack \n");
1348 fprintf (asmFile, "%s", iComments2);
1349 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1350 fprintf (asmFile,";\t.ds 256\n");
1353 /* copy xtern ram data */
1354 fprintf (asmFile, "%s", iComments2);
1355 fprintf (asmFile, "; external ram data\n");
1356 fprintf (asmFile, "%s", iComments2);
1357 copyFile (asmFile, xdata->oFile);
1361 /* copy the bit segment */
1362 fprintf (asmFile, "%s", iComments2);
1363 fprintf (asmFile, "; bit data\n");
1364 fprintf (asmFile, "%s", iComments2);
1365 copyFile (asmFile, bit->oFile);
1367 /* copy the interrupt vector table */
1368 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1369 copyFile (asmFile, vFile);
1371 fprintf (asmFile, "%s", iComments2);
1372 fprintf (asmFile, "; interrupt and initialization code\n");
1373 fprintf (asmFile, "%s", iComments2);
1374 fprintf (asmFile, "code_interrupt\t%s\t0x4\n", CODE_NAME); // Note - for mplink may have to enlarge section vectors in .lnk file
1376 /* interrupt service routine */
1377 fprintf (asmFile, "__sdcc_interrupt\n");
1378 copypCode(asmFile, 'I');
1380 /* initialize data memory */
1381 fprintf (asmFile, "code_init\t%s\n", CODE_NAME); // Note - for mplink may have to enlarge section vectors in .lnk file
1382 fprintf (asmFile,"__sdcc_gsinit_startup\n");
1383 /* FIXME: This is temporary. The idata section should be used. If
1384 not, we could add a special feature to the linker. This will
1385 work in the mean time. Put all initalized data in main.c */
1386 copypCode(asmFile, statsg->dbName);
1387 fprintf (asmFile,"\tpagesel _main\n");
1388 fprintf (asmFile,"\tgoto _main\n");
1393 /* copy global & static initialisations */
1394 fprintf (asmFile, "%s", iComments2);
1395 fprintf (asmFile, "; global & static initialisations\n");
1396 fprintf (asmFile, "%s", iComments2);
1397 copypCode(asmFile, statsg->dbName);
1401 /* copy over code */
1402 fprintf (asmFile, "%s", iComments2);
1403 fprintf (asmFile, "; code\n");
1404 fprintf (asmFile, "%s", iComments2);
1405 fprintf (asmFile, "code_%s\t%s\n", moduleName, port->mem.code_name);
1408 copypCode(asmFile, 'X');
1410 /* _main function */
1411 copypCode(asmFile, 'M');
1413 /* other functions */
1414 copypCode(asmFile, code->dbName);
1417 copypCode(asmFile, 'P');
1419 dumppCodeStatistics (asmFile);
1421 fprintf (asmFile,"\tend\n");