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"
35 #ifdef WORDS_BIGENDIAN
36 #define _ENDIAN(x) (3-x)
38 #define _ENDIAN(x) (x)
41 #define BYTE_IN_LONG(x,b) ((x>>(8*_ENDIAN(b)))&0xff)
43 extern symbol *interrupts[256];
44 static void printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb);
48 extern unsigned maxInterrupts;
49 extern int maxRegBank;
51 extern char *VersionString;
52 extern FILE *codeOutFile;
53 extern set *tmpfileSet;
54 extern set *tmpfileNameSet;
55 extern char *iComments1;
56 extern char *iComments2;
57 //extern void emitStaticSeg (memmap * map);
58 set *pic14_localFunctions = NULL;
60 extern DEFSETFUNC (closeTmpFiles);
61 extern DEFSETFUNC (rmTmpFiles);
63 extern void AnalyzeBanking (void);
64 extern void copyFile (FILE * dest, FILE * src);
65 extern void ReuseReg(void);
66 extern void InlinepCode(void);
67 extern void writeUsedRegs(FILE *);
69 extern void initialComments (FILE * afile);
70 extern void printPublics (FILE * afile);
72 extern void printChar (FILE * ofile, char *s, int plen);
73 void pCodeInitRegisters(void);
74 int getConfigWord(int address);
75 int getHasSecondConfigReg(void);
76 int pic14_getSharebankSize(void);
77 int pic14_getSharebankAddress(void);
79 char *udata_section_name=0; // FIXME Temporary fix to change udata section name -- VR
80 int pic14_hasInterrupt = 0; // Indicates whether to emit interrupt handler or not
82 /*-----------------------------------------------------------------*/
83 /* aopLiteral - string from a literal value */
84 /*-----------------------------------------------------------------*/
85 unsigned int pic14aopLiteral (value *val, int offset)
92 /* if it is a float then it gets tricky */
93 /* otherwise it is fairly simple */
94 if (!IS_FLOAT(val->type)) {
95 unsigned long v = (unsigned long) floatFromVal(val);
97 return ( (v >> (offset * 8)) & 0xff);
100 /* it is type float */
101 fl.f = (float) floatFromVal(val);
102 #ifdef WORDS_BIGENDIAN
103 return fl.c[3-offset];
110 /* Check whether the given reg is shared amongst all .o files of a project.
111 * This is true for the pseudo stack and WSAVE, SSAVE and PSAVE. */
113 is_shared_address (int addr)
115 return ((addr > Gstack_base_addr - 18)
116 && (addr <= Gstack_base_addr));
120 pic14_is_shared (regs *reg)
123 return is_shared_address (reg->address);
127 is_valid_identifier( const char *name )
133 /* only accept [a-zA-Z_][a-zA-Z0-9_] */
134 if (!((a >= 'a' && a <= 'z')
135 || (a >= 'A' && a <= 'z')
140 while ((a = *name++))
142 if (!((a >= 'a' && a <= 'z')
143 || (a >= 'A' && a <= 'Z')
144 || (a >= '0' && a <= '9')
149 /* valid identifier */
153 /* set of already emitted symbols; we store only pointers to the emitted
154 * symbol names so these MUST NO BE CHANGED afterwards... */
155 static set *symbolsEmitted = NULL;
157 /*-------------------------------------------------------------------*/
158 /* emitSymbolToFile - write a symbol definition only if it is not */
159 /* already present */
160 /*-------------------------------------------------------------------*/
162 emitSymbolToFile (FILE *of, const char *name, const char *section_type, int size, int addr, int useEQU, int globalize)
165 static unsigned int sec_idx = 0;
167 /* workaround: variables declared via `sbit' result in a numeric
168 * identifier (0xHH), EQU'ing them is invalid, so just ignore it.
169 * sbit is heavily used in the inc2h-generated header files!
171 if (!is_valid_identifier(name))
173 //fprintf( stderr, "%s:%s:%u: ignored symbol: %s\n", __FILE__, __FUNCTION__, __LINE__, name );
177 /* check whether the symbol is already defined */
178 for (sym = (const char *) setFirstItem (symbolsEmitted);
180 sym = (const char *) setNextItem (symbolsEmitted))
182 if (!strcmp (sym, name))
184 //fprintf (stderr, "%s: already emitted: %s\n", __FUNCTION__, name);
189 /* new symbol -- define it */
190 //fprintf (stderr, "%s: emitting %s (%d)\n", __FUNCTION__, name, size);
192 fprintf (of, "%s\tEQU\t0x%04x\n", name, addr);
195 /* we place each symbol into a section of its own to allow the linker
196 * to distribute the data into all available memory banks */
197 if (!section_type) section_type = "udata";
200 /* absolute symbols are handled in pic14_constructAbsMap */
203 /* workaround gpasm bug with symbols being EQUated and placed in absolute sections */
204 if (1 || !is_shared_address (addr))
206 if (globalize) fprintf (of, "\tglobal\t%s\n", name);
207 fprintf (of, "udata_%s_%u\t%s\t0x%04x\n", moduleName,
208 sec_idx++, "udata_ovr", addr);
209 fprintf (of, "%s\tres\t%d\n", name, size);
213 /* EQUs cannot be exported... */
214 fprintf (of, "%s\tEQU\t0x%04x\n", name, addr);
218 if (globalize) fprintf (of, "\tglobal\t%s\n", name);
219 fprintf (of, "udata_%s_%u\t%s\n", moduleName,
220 sec_idx++, section_type);
221 fprintf (of, "%s\tres\t%d\n", name, size);
225 //if (options.verbose) fprintf (stderr, "%s: emitted %s\n", __FUNCTION__, name);
226 addSet (&symbolsEmitted, (void *) name);
229 #define IS_DEFINED_HERE(sym) (!IS_EXTERN(sym->etype))
230 extern int IS_CONFIG_ADDRESS( int addr );
232 pic14_constructAbsMap (FILE *ofile)
234 memmap *maps[] = { data, sfr, NULL };
239 int addr, min=-1, max=-1;
242 for (i=0; maps[i] != NULL; i++)
244 for (sym = (symbol *)setFirstItem (maps[i]->syms);
245 sym; sym = setNextItem (maps[i]->syms))
247 if (IS_DEFINED_HERE(sym) && SPEC_ABSA(sym->etype))
249 addr = SPEC_ADDR(sym->etype);
251 /* handle CONFIG words here */
252 if (IS_CONFIG_ADDRESS( addr ))
254 //fprintf( stderr, "%s: assignment to CONFIG@0x%x found\n", __FUNCTION__, addr );
255 //fprintf( stderr, "ival: %p (0x%x)\n", sym->ival, (int)list2int( sym->ival ) );
257 pic14_assignConfigWordValue( addr, (int)list2int( sym->ival ) );
259 fprintf( stderr, "ERROR: Symbol %s, which is covering a __CONFIG word must be initialized!\n", sym->name );
264 if (max == -1 || addr > max) max = addr;
265 if (min == -1 || addr < min) min = addr;
266 //fprintf (stderr, "%s: sym %s @ 0x%x\n", __FUNCTION__, sym->name, addr);
267 aliases = hTabItemWithKey (ht, addr);
269 /* May not use addSetHead, as we cannot update the
270 * list's head in the hastable `ht'. */
271 addSet (&aliases, sym);
273 fprintf( stderr, "%s: now %d aliases for %s @ 0x%x\n",
274 __FUNCTION__, elementsInSet(aliases), sym->name, addr);
277 addSet (&aliases, sym);
278 hTabAddItem (&ht, addr, aliases);
284 /* now emit definitions for all absolute symbols */
285 fprintf (ofile, "%s", iComments2);
286 fprintf (ofile, "; absolute symbol definitions\n");
287 fprintf (ofile, "%s", iComments2);
288 for (addr=min; addr <= max; addr++)
291 aliases = hTabItemWithKey (ht, addr);
292 if (aliases && elementsInSet(aliases)) {
293 fprintf (ofile, "udata_abs_%s_%x\tudata_ovr\t0x%04x",
294 moduleName, addr, addr);
295 for (sym = setFirstItem (aliases); sym;
296 sym = setNextItem (aliases))
298 /* emit STATUS as well as _STATUS, required for SFRs only */
299 fprintf (ofile, "\n%s", sym->name);
300 fprintf (ofile, "\n%s", sym->rname);
301 if (getSize(sym->type) > size) {
302 size = getSize(sym->type);
304 addSet (&symbolsEmitted, (void *) sym->name);
305 addSet (&symbolsEmitted, (void *) sym->rname);
307 fprintf (ofile, "\tres\t%d\n", size);
311 /* also emit STK symbols
312 * XXX: This is ugly and fails as soon as devices start to get
313 * differently sized sharebanks, since STK12 will be
314 * required by larger devices but only up to STK03 might
315 * be defined using smaller devices. */
316 fprintf (ofile, "\n");
317 if (!pic14_options.isLibrarySource)
319 fprintf (ofile, "\tglobal PSAVE\n");
320 fprintf (ofile, "\tglobal SSAVE\n");
321 fprintf (ofile, "\tglobal WSAVE\n");
322 for (i=pic14_getSharebankSize()-4; i >= 0; i--) {
323 fprintf (ofile, "\tglobal STK%02d\n", i);
325 fprintf (ofile, "sharebank udata_shr\n");//pic14_getSharebankAddress() - pic14_getSharebankSize());
326 fprintf (ofile, "PSAVE\tres 1\n");
327 fprintf (ofile, "SSAVE\tres 1\n");
328 fprintf (ofile, "WSAVE\tres 1\n"); // WSAVE *must* be in sharebank (IRQ handlers)
329 /* fill rest of sharebank with stack STKxx .. STK00 */
330 for (i=pic14_getSharebankSize()-4; i >= 0; i--) {
331 fprintf (ofile, "STK%02d\tres 1\n", i);
334 /* declare STKxx as extern for all files
335 * except the one containing main() */
336 fprintf (ofile, "\textern PSAVE\n");
337 fprintf (ofile, "\textern SSAVE\n");
338 fprintf (ofile, "\textern WSAVE\n");
339 for (i=pic14_getSharebankSize()-4; i >= 0; i--) {
341 SNPRINTF(&buffer[0], 127, "STK%02d", i);
342 fprintf (ofile, "\textern %s\n", &buffer[0]);
343 addSet (&symbolsEmitted, (void *) &buffer[0]);
348 /*-----------------------------------------------------------------*/
349 /* emitRegularMap - emit code for maps with no special cases */
350 /*-----------------------------------------------------------------*/
352 pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag)
357 /* print the area name */
359 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
361 for (sym = setFirstItem (map->syms); sym;
362 sym = setNextItem (map->syms)) {
364 //printf("%s\n",sym->name);
366 /* ignore if config word */
367 if (SPEC_ABSA(sym->etype)
368 && IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype)))
371 /* if extern then add it into the extern list */
372 if (IS_EXTERN (sym->etype)) {
373 addSetHead (&externs, sym);
377 /* if allocation required check is needed
378 then check if the symbol really requires
379 allocation only for local variables */
380 if (arFlag && !IS_AGGREGATE (sym->type) &&
381 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
382 !sym->allocreq && sym->level)
385 /* if global variable & not static or extern
386 and addPublics allowed then add it to the public set */
387 if ((sym->level == 0 ||
388 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
390 !IS_STATIC (sym->etype))
392 //fprintf( stderr, "%s: made public %s\n", __FUNCTION__, sym->name );
393 addSetHead (&publics, sym);
396 // PIC code allocates its own registers - so ignore parameter variable generated by processFuncArgs()
399 /* if extern then do nothing or is a function
401 if (IS_FUNC (sym->type))
404 /* print extra debug info if required */
405 if (options.debug || sym->level == 0)
407 if (!sym->level) /* global */
408 if (IS_STATIC (sym->etype))
409 fprintf (map->oFile, "F%s_", moduleName); /* scope is file */
411 fprintf (map->oFile, "G_"); /* scope is global */
413 /* symbol is local */
414 fprintf (map->oFile, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
415 fprintf (map->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
418 /* absolute symbols are handled in pic14_constructAbsMap */
419 if (SPEC_ABSA(sym->etype) && IS_DEFINED_HERE(sym))
422 /* if it has an absolute address then generate
423 an equate for this no need to allocate space */
424 if (0 && SPEC_ABSA (sym->etype))
426 //if (options.debug || sym->level == 0)
427 //fprintf (map->oFile,"; == 0x%04x\n",SPEC_ADDR (sym->etype));
429 fprintf (map->oFile, "%s\tEQU\t0x%04x\n",
431 SPEC_ADDR (sym->etype));
437 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
438 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
439 /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
440 if (IS_BITVAR (sym->etype))
446 emitSymbolToFile (map->oFile,
449 getSize (sym->type) & 0xffff,
450 SPEC_ABSA(sym->etype)
451 ? SPEC_ADDR(sym->etype)
459 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1)
461 for (i = 1; i < size; i++)
462 fprintf (map->oFile, "\t%s_%d\n", sym->rname, i);
467 //fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
470 /* if it has a initial value then do it only if
471 it is a global variable */
472 if (sym->ival && sym->level == 0) {
475 if (IS_AGGREGATE (sym->type))
476 ival = initAggregates (sym, sym->ival, NULL);
478 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
479 decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
480 codeOutFile = statsg->oFile;
482 eBBlockFromiCode (iCodeFromAst (ival));
489 /*-----------------------------------------------------------------*/
490 /* printIvalType - generates ival for int/char */
491 /*-----------------------------------------------------------------*/
493 printIvalType (symbol *sym, sym_link * type, initList * ilist, pBlock *pb)
498 //fprintf(stderr, "%s\n",__FUNCTION__);
500 /* if initList is deep */
501 if (ilist->type == INIT_DEEP)
502 ilist = ilist->init.deep;
504 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
505 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
508 if (!(val = list2val (ilist))) {
509 // assuming a warning has been thrown
513 if (val->type != type) {
514 val = valCastLiteral(type, floatFromVal(val));
518 ulval = (unsigned long) floatFromVal (val);
522 switch (getSize (type)) {
524 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
528 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
529 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
533 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
534 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
535 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
536 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
541 /*-----------------------------------------------------------------*/
542 /* printIvalBitFields - generate initializer for bitfields */
543 /*-----------------------------------------------------------------*/
544 static void printIvalBitFields(symbol **sym, initList **ilist, pBlock *pb )
548 initList *lilist = *ilist ;
549 unsigned long ival = 0;
555 val = list2val(lilist);
557 if (SPEC_BLEN(lsym->etype) > 8) {
558 size += ((SPEC_BLEN (lsym->etype) / 8) +
559 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
562 size = ((SPEC_BLEN (lsym->etype) / 8) +
563 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
565 i = (unsigned long)floatFromVal(val);
566 i <<= SPEC_BSTR (lsym->etype);
568 if (! ( lsym->next &&
569 (IS_BITFIELD(lsym->next->type)) &&
570 (SPEC_BSTR(lsym->next->etype)))) break;
572 lilist = lilist->next;
576 //tfprintf (oFile, "\t!db !constbyte\n",ival);
577 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
581 //tfprintf (oFile, "\t!dw !constword\n",ival);
582 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
583 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
586 //tfprintf (oFile, "\t!db !constword,!constword\n",(ival >> 8) & 0xffff, (ival & 0xffff));
587 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>24)));
588 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>16)));
589 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
590 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
597 /*-----------------------------------------------------------------*/
598 /* printIvalStruct - generates initial value for structures */
599 /*-----------------------------------------------------------------*/
600 static void printIvalStruct (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
603 initList *iloop = NULL;
605 sflds = SPEC_STRUCT (type)->fields;
608 if (ilist->type != INIT_DEEP) {
609 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
613 iloop = ilist->init.deep;
616 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
617 if (IS_BITFIELD(sflds->type)) {
618 printIvalBitFields(&sflds,&iloop,pb);
620 printIval (sym, sflds->type, iloop, pb);
624 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
629 /*-----------------------------------------------------------------*/
630 /* printIvalChar - generates initital value for character array */
631 /*-----------------------------------------------------------------*/
633 printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
641 //fprintf(stderr, "%s\n",__FUNCTION__);
645 val = list2val (ilist);
647 /* if the value is a character string */
648 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
650 ilen = DCL_ELEM(val->type);
652 if (!DCL_ELEM (type))
653 DCL_ELEM (type) = ilen;
655 /* emit string constant */
656 for (remain = 0; remain < ilen; remain++) {
657 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(SPEC_CVAL(val->etype).v_char[remain])));
660 /* fill array up to desired size */
661 if ((remain = (DCL_ELEM (type) - ilen)) > 0)
663 //tfprintf (oFile, "\t!db !constbyte\n", 0);
664 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
671 //printChar (oFile, s, strlen (s) + 1);
673 for(remain=0; remain<(int)strlen(s); remain++) {
674 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(s[remain])));
675 //fprintf(stderr,"0x%02x ",s[remain]);
677 //fprintf(stderr,"\n");
682 /*-----------------------------------------------------------------*/
683 /* printIvalArray - generates code for array initialization */
684 /*-----------------------------------------------------------------*/
686 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
695 /* take care of the special case */
696 /* array of characters can be init */
698 if (IS_CHAR (type->next)) {
699 //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
700 if (!IS_LITERAL(list2val(ilist)->etype)) {
701 werror (W_INIT_WRONG);
704 if (printIvalChar (type,
705 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
706 pb, SPEC_CVAL (sym->etype).v_char))
709 /* not the special case */
710 if (ilist->type != INIT_DEEP) {
711 werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
715 for (iloop=ilist->init.deep; iloop; iloop=iloop->next) {
716 if ((++size > DCL_ELEM(type)) && DCL_ELEM(type)) {
717 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
720 printIval (sym, type->next, iloop, pb);
724 if (DCL_ELEM(type)) {
725 // pad with zeros if needed
726 if (size<DCL_ELEM(type)) {
727 size = (DCL_ELEM(type) - size) * getSize(type->next);
729 //tfprintf (oFile, "\t!db !constbyte\n", 0);
730 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
734 // we have not been given a size, but we now know it
735 DCL_ELEM (type) = size;
741 /*-----------------------------------------------------------------*/
742 /* printIvalPtr - generates code for initial value of pointers */
743 /*-----------------------------------------------------------------*/
744 extern value *initPointer (initList *, sym_link *toType);
747 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
754 fprintf (stderr, "FIXME: initializers for pointers...\n");
755 printTypeChain (type, stderr);
757 fprintf (stderr, "symbol: %s, DCL_TYPE():%d, DCL_ELEM():%d, IS_ARRAY():%d", sym->rname, DCL_TYPE(type), DCL_ELEM(type), IS_ARRAY(type));
758 fprintf (stderr, "ilist: type=%d (INIT_DEEP=%d, INIT_NODE=%d)\n", ilist->type, INIT_DEEP, INIT_NODE);
760 if (ilist && (ilist->type == INIT_DEEP))
761 ilist = ilist->init.deep;
763 /* function pointers */
764 if (IS_FUNC (type->next))
766 assert ( !"function pointers not yet handled" );
767 //printIvalFuncPtr (type, ilist, pb);
770 if (!(val = initPointer (ilist, type)))
773 if (IS_CHAR (type->next))
775 if (printIvalChar (type, ilist, pb, NULL)) return;
779 if (compareType (type, val->type) == 0)
781 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
782 printFromToType (val->type, type);
785 if (IS_LITERAL (val->etype))
787 switch (getSize (type))
790 fprintf (stderr, "BYTE: %i\n", (unsigned char)floatFromVal (val) & 0x00FF);
793 fprintf (stderr, "WORD: %i\n", (unsigned int)floatFromVal (val) & 0x00FFFF);
795 case 3: /* gneric pointers */
796 assert ( !"generic pointers not yet handled" );
798 fprintf (stderr, "LONG: %i\n", (unsigned int)floatFromVal (val) & 0x0000FFFFFFFF);
801 assert ( !"invaild size of value -- aborting" );
807 /* now handle symbolic values */
808 switch (getSize (type))
811 fprintf (stderr, "BYTE: %s", val->name);
814 fprintf (stderr, "WORD: %s", val->name);
817 fprintf (stderr, "LONG: %s", val->name);
820 assert ( !"invalid size of (symbolic) value -- aborting" );
824 /*-----------------------------------------------------------------*/
825 /* printIval - generates code for initial value */
826 /*-----------------------------------------------------------------*/
828 printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
833 /* if structure then */
834 if (IS_STRUCT (type))
836 //fprintf(stderr,"%s struct: %s\n",__FUNCTION__, sym->rname);
837 printIvalStruct (sym, type, ilist, pb);
841 /* if this is an array */
844 //fprintf(stderr,"%s array: %s\n",__FUNCTION__, sym->rname);
845 printIvalArray (sym, type, ilist, pb);
849 /* if this is a pointer */
852 //fprintf(stderr,"%s pointer: %s\n",__FUNCTION__, sym->rname);
853 printIvalPtr (sym, type, ilist, pb);
857 /* if type is SPECIFIER */
860 //fprintf(stderr,"%s spec %s\n",__FUNCTION__, sym->rname);
861 printIvalType (sym, type, ilist, pb);
866 extern void pCodeConstString(char *name, char *value);
867 /*-----------------------------------------------------------------*/
868 /* emitStaticSeg - emitcode for the static segment */
869 /*-----------------------------------------------------------------*/
871 pic14emitStaticSeg (memmap * map)
875 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
877 //fprintf(stderr, "%s\n",__FUNCTION__);
879 /* for all variables in this segment do */
880 for (sym = setFirstItem (map->syms); sym;
881 sym = setNextItem (map->syms))
883 /* if extern then add it into the extern list */
884 if (IS_EXTERN (sym->etype)) {
885 addSetHead (&externs, sym);
889 /* if it is not static add it to the public
891 if (!IS_STATIC (sym->etype))
892 addSetHead (&publics, sym);
894 /* print extra debug info if required */
895 if (options.debug || sym->level == 0)
899 if (IS_STATIC (sym->etype))
900 fprintf (code->oFile, "F%s_", moduleName); /* scope is file */
902 fprintf (code->oFile, "G_"); /* scope is global */
905 /* symbol is local */
906 fprintf (code->oFile, "L%s_",
907 (sym->localof ? sym->localof->name : "-null-"));
908 fprintf (code->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
912 /* if it has an absolute address */
913 if (SPEC_ABSA (sym->etype))
915 if (options.debug || sym->level == 0)
916 fprintf (code->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
918 fprintf (code->oFile, "%s\t=\t0x%04x\n",
920 SPEC_ADDR (sym->etype));
924 if (options.debug || sym->level == 0)
925 fprintf (code->oFile, " == .\n");
927 /* if it has an initial value */
932 fprintf (code->oFile, "%s:\n", sym->rname);
934 resolveIvalSym (sym->ival, sym->type);
935 //printIval (sym, sym->type, sym->ival, code->oFile);
936 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block for Ival"));
938 addpCode2pBlock(pb,newpCodeLabel(sym->rname,-1));
940 printIval (sym, sym->type, sym->ival, pb);
947 fprintf (code->oFile, "%s:\n", sym->rname);
948 /* special case for character strings */
949 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
950 SPEC_CVAL (sym->etype).v_char)
951 pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
952 /*printChar (code->oFile,
953 SPEC_CVAL (sym->etype).v_char,
954 strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
956 fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
964 /*-----------------------------------------------------------------*/
965 /* emitMaps - emits the code for the data portion the code */
966 /*-----------------------------------------------------------------*/
970 pic14_constructAbsMap (sfr->oFile);
971 /* no special considerations for the following
972 data, idata & bit & xdata */
973 pic14emitRegularMap (data, TRUE, TRUE);
974 pic14emitRegularMap (idata, TRUE, TRUE);
975 pic14emitRegularMap (bit, TRUE, FALSE);
976 pic14emitRegularMap (xdata, TRUE, TRUE);
977 pic14emitRegularMap (sfr, TRUE, FALSE);
978 pic14emitRegularMap (sfrbit, FALSE, FALSE);
979 pic14emitRegularMap (code, TRUE, FALSE);
980 pic14emitStaticSeg (statsg);
981 pic14emitStaticSeg (c_abs);
984 /*-----------------------------------------------------------------*/
985 /* createInterruptVect - creates the interrupt vector */
986 /*-----------------------------------------------------------------*/
988 pic14createInterruptVect (FILE * vFile)
990 mainf = newSymbol ("main", 0);
993 /* only if the main function exists */
994 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
996 struct options *op = &options;
997 if (!(op->cc_only || noAssemble))
998 // werror (E_NO_MAIN);
999 fprintf(stderr,"WARNING: function 'main' undefined\n");
1003 /* if the main is only a prototype ie. no body then do nothing */
1004 if (!IFFUNC_HASBODY(mainf->type))
1006 /* if ! compile only then main function should be present */
1007 if (!(options.cc_only || noAssemble))
1008 // werror (E_NO_MAIN);
1009 fprintf(stderr,"WARNING: function 'main' undefined\n");
1013 fprintf (vFile, "%s", iComments2);
1014 fprintf (vFile, "; reset vector \n");
1015 fprintf (vFile, "%s", iComments2);
1016 fprintf (vFile, "STARTUP\t%s\n", CODE_NAME); // Lkr file should place section STARTUP at address 0x0
1017 fprintf (vFile, "\tnop\n"); /* first location for used by incircuit debugger */
1018 fprintf( vFile, "\tpagesel __sdcc_gsinit_startup\n");
1019 fprintf (vFile, "\tgoto\t__sdcc_gsinit_startup\n");
1023 /*-----------------------------------------------------------------*/
1024 /* initialComments - puts in some initial comments */
1025 /*-----------------------------------------------------------------*/
1027 pic14initialComments (FILE * afile)
1029 initialComments (afile);
1030 fprintf (afile, "; PIC port for the 14-bit core\n");
1031 fprintf (afile, iComments2);
1036 pic14_stringInSet(const char *str, set **world, int autoAdd)
1043 for (s = setFirstItem(*world); s; s = setNextItem(*world))
1046 if (0 == strcmp(s, str)) return 1;
1050 if (autoAdd) addSet(world, Safe_strdup(str));
1055 pic14_emitSymbolIfNew(FILE *file, const char *fmt, const char *sym, int checkLocals)
1057 static set *emitted = NULL;
1059 if (!pic14_stringInSet(sym, &emitted, 1)) {
1060 /* sym was not in emittedSymbols */
1061 if (!checkLocals || !pic14_stringInSet(sym, &pic14_localFunctions, 0)) {
1062 /* sym is not a locally defined function---avoid bug #1443651 */
1063 fprintf( file, fmt, sym );
1070 /*-----------------------------------------------------------------*/
1071 /* printExterns - generates extern for external variables */
1072 /*-----------------------------------------------------------------*/
1074 pic14printExterns (FILE * afile)
1078 fprintf (afile, "%s", iComments2);
1079 fprintf (afile, "; extern variables in this module\n");
1080 fprintf (afile, "%s", iComments2);
1082 for (sym = setFirstItem (externs); sym; sym = setNextItem (externs))
1083 pic14_emitSymbolIfNew(afile, "\textern %s\n", sym->rname, 1);
1086 /*-----------------------------------------------------------------*/
1087 /* printPublics - generates .global for publics */
1088 /*-----------------------------------------------------------------*/
1090 pic14printPublics (FILE * afile)
1094 fprintf (afile, "%s", iComments2);
1095 fprintf (afile, "; publics variables in this module\n");
1096 fprintf (afile, "%s", iComments2);
1098 for (sym = setFirstItem (publics); sym;
1099 sym = setNextItem (publics)) {
1101 if(!IS_BITFIELD(sym->type) && ((IS_FUNC(sym->type) || sym->allocreq))) {
1102 if (!IS_BITVAR(sym->type))
1103 pic14_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1105 /* Absolute variables are defines in the asm file as equates and thus can not be made global. */
1106 /* Not any longer! */
1107 //if (!SPEC_ABSA (sym->etype))
1108 pic14_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1113 /*-----------------------------------------------------------------*/
1114 /* emitOverlay - will emit code for the overlay stuff */
1115 /*-----------------------------------------------------------------*/
1117 pic14emitOverlay (FILE * afile)
1121 /* if (!elementsInSet (ovrSetSets))*/
1123 /* the hack below, fixes translates for devices which
1124 * only have udata_shr memory */
1125 fprintf (afile, "%s\t%s\n",
1126 (elementsInSet(ovrSetSets)?"":";"),
1127 port->mem.overlay_name);
1129 /* for each of the sets in the overlay segment do */
1130 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1131 ovrset = setNextItem (ovrSetSets))
1136 if (elementsInSet (ovrset))
1138 /* this dummy area is used to fool the assembler
1139 otherwise the assembler will append each of these
1140 declarations into one chunk and will not overlay
1143 /* I don't think this applies to us. We are using gpasm. CRF */
1145 fprintf (afile, ";\t.area _DUMMY\n");
1146 /* output the area informtion */
1147 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1150 for (sym = setFirstItem (ovrset); sym;
1151 sym = setNextItem (ovrset))
1154 /* if extern then do nothing */
1155 if (IS_EXTERN (sym->etype))
1158 /* if allocation required check is needed
1159 then check if the symbol really requires
1160 allocation only for local variables */
1161 if (!IS_AGGREGATE (sym->type) &&
1162 !(sym->_isparm && !IS_REGPARM (sym->etype))
1163 && !sym->allocreq && sym->level)
1166 /* if global variable & not static or extern
1167 and addPublics allowed then add it to the public set */
1168 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1169 && !IS_STATIC (sym->etype))
1170 addSetHead (&publics, sym);
1172 /* if extern then do nothing or is a function
1174 if (IS_FUNC (sym->type))
1177 /* print extra debug info if required */
1178 if (options.debug || sym->level == 0)
1182 if (IS_STATIC (sym->etype))
1183 fprintf (afile, "F%s_", moduleName); /* scope is file */
1185 fprintf (afile, "G_"); /* scope is global */
1188 /* symbol is local */
1189 fprintf (afile, "L%s_",
1190 (sym->localof ? sym->localof->name : "-null-"));
1191 fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
1194 /* if is has an absolute address then generate
1195 an equate for this no need to allocate space */
1196 if (SPEC_ABSA (sym->etype))
1199 if (options.debug || sym->level == 0)
1200 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1202 fprintf (afile, "%s\t=\t0x%04x\n",
1204 SPEC_ADDR (sym->etype));
1208 if (options.debug || sym->level == 0)
1209 fprintf (afile, "==.\n");
1211 /* allocate space */
1212 fprintf (afile, "%s:\n", sym->rname);
1213 fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1222 pic14_emitInterruptHandler (FILE * asmFile)
1224 if (pic14_hasInterrupt)
1227 fprintf (asmFile, "%s", iComments2);
1228 fprintf (asmFile, "; interrupt and initialization code\n");
1229 fprintf (asmFile, "%s", iComments2);
1230 // Note - for mplink may have to enlarge section vectors in .lnk file
1231 // Note: Do NOT name this code_interrupt to avoid nameclashes with
1232 // source files's code segment (interrupt.c -> code_interrupt)
1233 fprintf (asmFile, "c_interrupt\t%s\t0x4\n", CODE_NAME);
1235 /* interrupt service routine */
1236 fprintf (asmFile, "__sdcc_interrupt\n");
1237 copypCode(asmFile, 'I');
1241 /*-----------------------------------------------------------------*/
1242 /* glue - the final glue that hold the whole thing together */
1243 /*-----------------------------------------------------------------*/
1247 char udata_name[80];
1250 FILE *ovrFile = tempfile();
1252 addSetHead(&tmpfileSet,ovrFile);
1253 pCodeInitRegisters();
1255 /* check for main() */
1256 mainf = newSymbol ("main", 0);
1258 mainf = findSymWithLevel (SymbolTab, mainf);
1260 if (!mainf || !IFFUNC_HASBODY(mainf->type))
1262 /* main missing -- import stack from main module */
1263 //fprintf (stderr, "main() missing -- assuming we are NOT the main module\n");
1264 pic14_options.isLibrarySource = 1;
1268 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1270 pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
1273 /* entry point @ start of CSEG */
1274 addpCode2pBlock(pb,newpCodeLabel("__sdcc_program_startup",-1));
1275 /* put in the call to main */
1276 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp("_main",PO_STR)));
1278 if (options.mainreturn) {
1280 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will return to caller\n"));
1281 addpCode2pBlock(pb,newpCode(POC_RETURN,NULL));
1285 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will lock up\n"));
1286 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("$",PO_STR)));
1292 /* At this point we've got all the code in the form of pCode structures */
1293 /* Now it needs to be rearranged into the order it should be placed in the */
1296 movepBlock2Head('P'); // Last
1297 movepBlock2Head(code->dbName);
1298 movepBlock2Head('X');
1299 movepBlock2Head(statsg->dbName); // First
1302 /* print the global struct definitions */
1308 addSetHead(&tmpfileSet,vFile);
1310 /* emit code for the all the variables declared */
1312 /* do the overlay segments */
1313 pic14emitOverlay(ovrFile);
1315 /* PENDING: this isnt the best place but it will do */
1316 if (port->general.glue_up_main) {
1317 /* create the interrupt vector table */
1318 pic14createInterruptVect (vFile);
1323 ReuseReg(); // ReuseReg where call tree permits
1332 /* now put it all together into the assembler file */
1333 /* create the assembler file name */
1335 if ((noAssemble || options.c1mode) && fullDstFileName)
1337 sprintf (buffer, fullDstFileName);
1341 sprintf (buffer, dstFileName);
1342 strcat (buffer, ".asm");
1345 if (!(asmFile = fopen (buffer, "w"))) {
1346 werror (E_FILE_OPEN_ERR, buffer);
1350 /* prepare statistics */
1351 resetpCodeStatistics ();
1353 /* initial comments */
1354 pic14initialComments (asmFile);
1356 /* print module name */
1357 fprintf (asmFile, ";\t.module %s\n", moduleName);
1359 /* Let the port generate any global directives, etc. */
1360 if (port->genAssemblerPreamble)
1362 port->genAssemblerPreamble(asmFile);
1365 /* Emit the __config directive */
1366 pic14_emitConfigWord (asmFile);
1368 /* print the global variables in this module */
1369 pic14printPublics (asmFile);
1371 /* print the extern variables in this module */
1372 pic14printExterns (asmFile);
1374 /* copy the sfr segment */
1375 fprintf (asmFile, "%s", iComments2);
1376 fprintf (asmFile, "; special function registers\n");
1377 fprintf (asmFile, "%s", iComments2);
1378 copyFile (asmFile, sfr->oFile);
1381 if (udata_section_name) {
1382 sprintf(udata_name,"%s",udata_section_name);
1384 sprintf(udata_name,"data_%s",moduleName);
1386 fprintf (asmFile, "%s", iComments2);
1387 fprintf (asmFile, "; udata\n");
1388 fprintf (asmFile, "%s", iComments2);
1389 fprintf (asmFile, "%s\tudata\n", udata_name);
1390 copyFile (asmFile, data->oFile);
1392 /* Put all variables into a cblock */
1394 writeUsedRegs(asmFile);
1396 /* create the overlay segments */
1397 fprintf (asmFile, "%s", iComments2);
1398 fprintf (asmFile, "; overlayable items in internal ram \n");
1399 fprintf (asmFile, "%s", iComments2);
1400 copyFile (asmFile, ovrFile);
1404 /* create the stack segment MOF */
1405 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1406 fprintf (asmFile, "%s", iComments2);
1407 fprintf (asmFile, "; Stack segment in internal ram \n");
1408 fprintf (asmFile, "%s", iComments2);
1409 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1410 ";__start__stack:\n;\t.ds\t1\n\n");
1413 /* create the idata segment */
1414 fprintf (asmFile, "%s", iComments2);
1415 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1416 fprintf (asmFile, "%s", iComments2);
1417 copyFile (asmFile, idata->oFile);
1419 /* if external stack then reserve space of it */
1420 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1421 fprintf (asmFile, "%s", iComments2);
1422 fprintf (asmFile, "; external stack \n");
1423 fprintf (asmFile, "%s", iComments2);
1424 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1425 fprintf (asmFile,";\t.ds 256\n");
1428 /* copy xtern ram data */
1429 fprintf (asmFile, "%s", iComments2);
1430 fprintf (asmFile, "; external ram data\n");
1431 fprintf (asmFile, "%s", iComments2);
1432 copyFile (asmFile, xdata->oFile);
1436 /* copy the bit segment */
1437 fprintf (asmFile, "%s", iComments2);
1438 fprintf (asmFile, "; bit data\n");
1439 fprintf (asmFile, "%s", iComments2);
1440 copyFile (asmFile, bit->oFile);
1442 /* copy the interrupt vector table */
1443 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1444 copyFile (asmFile, vFile);
1447 /* create interupt ventor handler */
1448 pic14_emitInterruptHandler (asmFile);
1450 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1451 /* initialize data memory */
1452 fprintf (asmFile, "code_init\t%s\n", CODE_NAME); // Note - for mplink may have to enlarge section vectors in .lnk file
1453 fprintf (asmFile,"__sdcc_gsinit_startup\n");
1454 /* FIXME: This is temporary. The idata section should be used. If
1455 not, we could add a special feature to the linker. This will
1456 work in the mean time. Put all initalized data in main.c */
1457 copypCode(asmFile, statsg->dbName);
1458 fprintf (asmFile,"\tpagesel _main\n");
1459 fprintf (asmFile,"\tgoto _main\n");
1464 /* copy global & static initialisations */
1465 fprintf (asmFile, "%s", iComments2);
1466 fprintf (asmFile, "; global & static initialisations\n");
1467 fprintf (asmFile, "%s", iComments2);
1468 copypCode(asmFile, statsg->dbName);
1472 /* copy over code */
1473 fprintf (asmFile, "%s", iComments2);
1474 fprintf (asmFile, "; code\n");
1475 fprintf (asmFile, "%s", iComments2);
1476 fprintf (asmFile, "code_%s\t%s\n", moduleName, port->mem.code_name);
1479 copypCode(asmFile, 'X');
1481 /* _main function */
1482 copypCode(asmFile, 'M');
1484 /* other functions */
1485 copypCode(asmFile, code->dbName);
1488 copypCode(asmFile, 'P');
1490 dumppCodeStatistics (asmFile);
1492 fprintf (asmFile,"\tend\n");