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_ovr 0x%04x\n",
326 pic14_getSharebankAddress() - pic14_getSharebankSize() + 1);
327 fprintf (ofile, "PSAVE\tres 1\n");
328 fprintf (ofile, "SSAVE\tres 1\n");
329 fprintf (ofile, "WSAVE\tres 1\n");
330 /* fill rest of sharebank with stack STKxx .. STK00 */
331 for (i=pic14_getSharebankSize()-4; i >= 0; i--) {
332 fprintf (ofile, "STK%02d\tres 1\n", i);
335 /* declare STKxx as extern for all files
336 * except the one containing main() */
337 fprintf (ofile, "\textern PSAVE\n");
338 fprintf (ofile, "\textern SSAVE\n");
339 fprintf (ofile, "\textern WSAVE\n");
340 for (i=pic14_getSharebankSize()-4; i >= 0; i--) {
341 fprintf (ofile, "\textern STK%02d\n", i);
346 /*-----------------------------------------------------------------*/
347 /* emitRegularMap - emit code for maps with no special cases */
348 /*-----------------------------------------------------------------*/
350 pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag)
355 /* print the area name */
357 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
359 for (sym = setFirstItem (map->syms); sym;
360 sym = setNextItem (map->syms)) {
362 //printf("%s\n",sym->name);
364 /* ignore if config word */
365 if (SPEC_ABSA(sym->etype)
366 && IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype)))
369 /* if extern then add it into the extern list */
370 if (IS_EXTERN (sym->etype)) {
371 addSetHead (&externs, sym);
375 /* if allocation required check is needed
376 then check if the symbol really requires
377 allocation only for local variables */
378 if (arFlag && !IS_AGGREGATE (sym->type) &&
379 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
380 !sym->allocreq && sym->level)
383 /* if global variable & not static or extern
384 and addPublics allowed then add it to the public set */
385 if ((sym->level == 0 ||
386 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
388 !IS_STATIC (sym->etype))
390 //fprintf( stderr, "%s: made public %s\n", __FUNCTION__, sym->name );
391 addSetHead (&publics, sym);
394 // PIC code allocates its own registers - so ignore parameter variable generated by processFuncArgs()
397 /* if extern then do nothing or is a function
399 if (IS_FUNC (sym->type))
402 /* print extra debug info if required */
403 if (options.debug || sym->level == 0)
405 if (!sym->level) /* global */
406 if (IS_STATIC (sym->etype))
407 fprintf (map->oFile, "F%s_", moduleName); /* scope is file */
409 fprintf (map->oFile, "G_"); /* scope is global */
411 /* symbol is local */
412 fprintf (map->oFile, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
413 fprintf (map->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
416 /* absolute symbols are handled in pic14_constructAbsMap */
417 if (SPEC_ABSA(sym->etype) && IS_DEFINED_HERE(sym))
420 /* if it has an absolute address then generate
421 an equate for this no need to allocate space */
422 if (0 && SPEC_ABSA (sym->etype))
424 //if (options.debug || sym->level == 0)
425 //fprintf (map->oFile,"; == 0x%04x\n",SPEC_ADDR (sym->etype));
427 fprintf (map->oFile, "%s\tEQU\t0x%04x\n",
429 SPEC_ADDR (sym->etype));
435 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
436 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
437 /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
438 if (IS_BITVAR (sym->etype))
444 emitSymbolToFile (map->oFile,
447 getSize (sym->type) & 0xffff,
448 SPEC_ABSA(sym->etype)
449 ? SPEC_ADDR(sym->etype)
457 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1)
459 for (i = 1; i < size; i++)
460 fprintf (map->oFile, "\t%s_%d\n", sym->rname, i);
465 //fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
468 /* if it has a initial value then do it only if
469 it is a global variable */
470 if (sym->ival && sym->level == 0) {
473 if (IS_AGGREGATE (sym->type))
474 ival = initAggregates (sym, sym->ival, NULL);
476 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
477 decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
478 codeOutFile = statsg->oFile;
480 eBBlockFromiCode (iCodeFromAst (ival));
487 /*-----------------------------------------------------------------*/
488 /* printIvalType - generates ival for int/char */
489 /*-----------------------------------------------------------------*/
491 printIvalType (symbol *sym, sym_link * type, initList * ilist, pBlock *pb)
496 //fprintf(stderr, "%s\n",__FUNCTION__);
498 /* if initList is deep */
499 if (ilist->type == INIT_DEEP)
500 ilist = ilist->init.deep;
502 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
503 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
506 if (!(val = list2val (ilist))) {
507 // assuming a warning has been thrown
511 if (val->type != type) {
512 val = valCastLiteral(type, floatFromVal(val));
516 ulval = (unsigned long) floatFromVal (val);
520 switch (getSize (type)) {
522 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
526 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
527 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
531 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
532 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
533 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
534 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
539 /*-----------------------------------------------------------------*/
540 /* printIvalBitFields - generate initializer for bitfields */
541 /*-----------------------------------------------------------------*/
542 static void printIvalBitFields(symbol **sym, initList **ilist, pBlock *pb )
546 initList *lilist = *ilist ;
547 unsigned long ival = 0;
553 val = list2val(lilist);
555 if (SPEC_BLEN(lsym->etype) > 8) {
556 size += ((SPEC_BLEN (lsym->etype) / 8) +
557 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
560 size = ((SPEC_BLEN (lsym->etype) / 8) +
561 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
563 i = (unsigned long)floatFromVal(val);
564 i <<= SPEC_BSTR (lsym->etype);
566 if (! ( lsym->next &&
567 (IS_BITFIELD(lsym->next->type)) &&
568 (SPEC_BSTR(lsym->next->etype)))) break;
570 lilist = lilist->next;
574 //tfprintf (oFile, "\t!db !constbyte\n",ival);
575 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
579 //tfprintf (oFile, "\t!dw !constword\n",ival);
580 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
581 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
584 //tfprintf (oFile, "\t!db !constword,!constword\n",(ival >> 8) & 0xffff, (ival & 0xffff));
585 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>24)));
586 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>16)));
587 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
588 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
595 /*-----------------------------------------------------------------*/
596 /* printIvalStruct - generates initial value for structures */
597 /*-----------------------------------------------------------------*/
598 static void printIvalStruct (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
601 initList *iloop = NULL;
603 sflds = SPEC_STRUCT (type)->fields;
606 if (ilist->type != INIT_DEEP) {
607 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
611 iloop = ilist->init.deep;
614 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
615 if (IS_BITFIELD(sflds->type)) {
616 printIvalBitFields(&sflds,&iloop,pb);
618 printIval (sym, sflds->type, iloop, pb);
622 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
627 /*-----------------------------------------------------------------*/
628 /* printIvalChar - generates initital value for character array */
629 /*-----------------------------------------------------------------*/
631 printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
639 //fprintf(stderr, "%s\n",__FUNCTION__);
643 val = list2val (ilist);
645 /* if the value is a character string */
646 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
648 ilen = DCL_ELEM(val->type);
650 if (!DCL_ELEM (type))
651 DCL_ELEM (type) = ilen;
653 /* emit string constant */
654 for (remain = 0; remain < ilen; remain++) {
655 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(SPEC_CVAL(val->etype).v_char[remain])));
658 /* fill array up to desired size */
659 if ((remain = (DCL_ELEM (type) - ilen)) > 0)
661 //tfprintf (oFile, "\t!db !constbyte\n", 0);
662 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
669 //printChar (oFile, s, strlen (s) + 1);
671 for(remain=0; remain<(int)strlen(s); remain++) {
672 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(s[remain])));
673 //fprintf(stderr,"0x%02x ",s[remain]);
675 //fprintf(stderr,"\n");
680 /*-----------------------------------------------------------------*/
681 /* printIvalArray - generates code for array initialization */
682 /*-----------------------------------------------------------------*/
684 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
693 /* take care of the special case */
694 /* array of characters can be init */
696 if (IS_CHAR (type->next)) {
697 //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
698 if (!IS_LITERAL(list2val(ilist)->etype)) {
699 werror (W_INIT_WRONG);
702 if (printIvalChar (type,
703 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
704 pb, SPEC_CVAL (sym->etype).v_char))
707 /* not the special case */
708 if (ilist->type != INIT_DEEP) {
709 werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
713 for (iloop=ilist->init.deep; iloop; iloop=iloop->next) {
714 if ((++size > DCL_ELEM(type)) && DCL_ELEM(type)) {
715 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
718 printIval (sym, type->next, iloop, pb);
722 if (DCL_ELEM(type)) {
723 // pad with zeros if needed
724 if (size<DCL_ELEM(type)) {
725 size = (DCL_ELEM(type) - size) * getSize(type->next);
727 //tfprintf (oFile, "\t!db !constbyte\n", 0);
728 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
732 // we have not been given a size, but we now know it
733 DCL_ELEM (type) = size;
739 /*-----------------------------------------------------------------*/
740 /* printIvalPtr - generates code for initial value of pointers */
741 /*-----------------------------------------------------------------*/
742 extern value *initPointer (initList *, sym_link *toType);
745 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
752 fprintf (stderr, "FIXME: initializers for pointers...\n");
753 printTypeChain (type, stderr);
755 fprintf (stderr, "symbol: %s, DCL_TYPE():%d, DCL_ELEM():%d, IS_ARRAY():%d", sym->rname, DCL_TYPE(type), DCL_ELEM(type), IS_ARRAY(type));
756 fprintf (stderr, "ilist: type=%d (INIT_DEEP=%d, INIT_NODE=%d)\n", ilist->type, INIT_DEEP, INIT_NODE);
758 if (ilist && (ilist->type == INIT_DEEP))
759 ilist = ilist->init.deep;
761 /* function pointers */
762 if (IS_FUNC (type->next))
764 assert ( !"function pointers not yet handled" );
765 //printIvalFuncPtr (type, ilist, pb);
768 if (!(val = initPointer (ilist, type)))
771 if (IS_CHAR (type->next))
773 if (printIvalChar (type, ilist, pb, NULL)) return;
777 if (compareType (type, val->type) == 0)
779 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
780 printFromToType (val->type, type);
783 if (IS_LITERAL (val->etype))
785 switch (getSize (type))
788 fprintf (stderr, "BYTE: %i\n", (unsigned char)floatFromVal (val) & 0x00FF);
791 fprintf (stderr, "WORD: %i\n", (unsigned int)floatFromVal (val) & 0x00FFFF);
793 case 3: /* gneric pointers */
794 assert ( !"generic pointers not yet handled" );
796 fprintf (stderr, "LONG: %i\n", (unsigned int)floatFromVal (val) & 0x0000FFFFFFFF);
799 assert ( !"invaild size of value -- aborting" );
805 /* now handle symbolic values */
806 switch (getSize (type))
809 fprintf (stderr, "BYTE: %s", val->name);
812 fprintf (stderr, "WORD: %s", val->name);
815 fprintf (stderr, "LONG: %s", val->name);
818 assert ( !"invalid size of (symbolic) value -- aborting" );
822 /*-----------------------------------------------------------------*/
823 /* printIval - generates code for initial value */
824 /*-----------------------------------------------------------------*/
826 printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
831 /* if structure then */
832 if (IS_STRUCT (type))
834 //fprintf(stderr,"%s struct: %s\n",__FUNCTION__, sym->rname);
835 printIvalStruct (sym, type, ilist, pb);
839 /* if this is an array */
842 //fprintf(stderr,"%s array: %s\n",__FUNCTION__, sym->rname);
843 printIvalArray (sym, type, ilist, pb);
847 /* if this is a pointer */
850 //fprintf(stderr,"%s pointer: %s\n",__FUNCTION__, sym->rname);
851 printIvalPtr (sym, type, ilist, pb);
855 /* if type is SPECIFIER */
858 //fprintf(stderr,"%s spec %s\n",__FUNCTION__, sym->rname);
859 printIvalType (sym, type, ilist, pb);
864 extern void pCodeConstString(char *name, char *value);
865 /*-----------------------------------------------------------------*/
866 /* emitStaticSeg - emitcode for the static segment */
867 /*-----------------------------------------------------------------*/
869 pic14emitStaticSeg (memmap * map)
873 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
875 //fprintf(stderr, "%s\n",__FUNCTION__);
877 /* for all variables in this segment do */
878 for (sym = setFirstItem (map->syms); sym;
879 sym = setNextItem (map->syms))
881 /* if extern then add it into the extern list */
882 if (IS_EXTERN (sym->etype)) {
883 addSetHead (&externs, sym);
887 /* if it is not static add it to the public
889 if (!IS_STATIC (sym->etype))
890 addSetHead (&publics, sym);
892 /* print extra debug info if required */
893 if (options.debug || sym->level == 0)
897 if (IS_STATIC (sym->etype))
898 fprintf (code->oFile, "F%s_", moduleName); /* scope is file */
900 fprintf (code->oFile, "G_"); /* scope is global */
903 /* symbol is local */
904 fprintf (code->oFile, "L%s_",
905 (sym->localof ? sym->localof->name : "-null-"));
906 fprintf (code->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
910 /* if it has an absolute address */
911 if (SPEC_ABSA (sym->etype))
913 if (options.debug || sym->level == 0)
914 fprintf (code->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
916 fprintf (code->oFile, "%s\t=\t0x%04x\n",
918 SPEC_ADDR (sym->etype));
922 if (options.debug || sym->level == 0)
923 fprintf (code->oFile, " == .\n");
925 /* if it has an initial value */
930 fprintf (code->oFile, "%s:\n", sym->rname);
932 resolveIvalSym (sym->ival, sym->type);
933 //printIval (sym, sym->type, sym->ival, code->oFile);
934 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block for Ival"));
936 addpCode2pBlock(pb,newpCodeLabel(sym->rname,-1));
938 printIval (sym, sym->type, sym->ival, pb);
945 fprintf (code->oFile, "%s:\n", sym->rname);
946 /* special case for character strings */
947 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
948 SPEC_CVAL (sym->etype).v_char)
949 pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
950 /*printChar (code->oFile,
951 SPEC_CVAL (sym->etype).v_char,
952 strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
954 fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
962 /*-----------------------------------------------------------------*/
963 /* emitMaps - emits the code for the data portion the code */
964 /*-----------------------------------------------------------------*/
968 pic14_constructAbsMap (sfr->oFile);
969 /* no special considerations for the following
970 data, idata & bit & xdata */
971 pic14emitRegularMap (data, TRUE, TRUE);
972 pic14emitRegularMap (idata, TRUE, TRUE);
973 pic14emitRegularMap (bit, TRUE, FALSE);
974 pic14emitRegularMap (xdata, TRUE, TRUE);
975 pic14emitRegularMap (sfr, TRUE, FALSE);
976 pic14emitRegularMap (sfrbit, FALSE, FALSE);
977 pic14emitRegularMap (code, TRUE, FALSE);
978 pic14emitStaticSeg (statsg);
979 pic14emitStaticSeg (c_abs);
982 /*-----------------------------------------------------------------*/
983 /* createInterruptVect - creates the interrupt vector */
984 /*-----------------------------------------------------------------*/
986 pic14createInterruptVect (FILE * vFile)
988 mainf = newSymbol ("main", 0);
991 /* only if the main function exists */
992 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
994 struct options *op = &options;
995 if (!(op->cc_only || noAssemble))
996 // werror (E_NO_MAIN);
997 fprintf(stderr,"WARNING: function 'main' undefined\n");
1001 /* if the main is only a prototype ie. no body then do nothing */
1002 if (!IFFUNC_HASBODY(mainf->type))
1004 /* if ! compile only then main function should be present */
1005 if (!(options.cc_only || noAssemble))
1006 // werror (E_NO_MAIN);
1007 fprintf(stderr,"WARNING: function 'main' undefined\n");
1011 fprintf (vFile, "%s", iComments2);
1012 fprintf (vFile, "; reset vector \n");
1013 fprintf (vFile, "%s", iComments2);
1014 fprintf (vFile, "STARTUP\t%s\n", CODE_NAME); // Lkr file should place section STARTUP at address 0x0
1015 fprintf (vFile, "\tnop\n"); /* first location for used by incircuit debugger */
1016 fprintf( vFile, "\tpagesel __sdcc_gsinit_startup\n");
1017 fprintf (vFile, "\tgoto\t__sdcc_gsinit_startup\n");
1021 /*-----------------------------------------------------------------*/
1022 /* initialComments - puts in some initial comments */
1023 /*-----------------------------------------------------------------*/
1025 pic14initialComments (FILE * afile)
1027 initialComments (afile);
1028 fprintf (afile, "; PIC port for the 14-bit core\n");
1029 fprintf (afile, iComments2);
1034 pic14_stringInSet(const char *str, set **world, int autoAdd)
1041 for (s = setFirstItem(*world); s; s = setNextItem(*world))
1044 if (0 == strcmp(s, str)) return 1;
1048 if (autoAdd) addSet(world, Safe_strdup(str));
1053 pic14_emitSymbolIfNew(FILE *file, const char *fmt, const char *sym, int checkLocals)
1055 static set *emitted = NULL;
1057 if (!pic14_stringInSet(sym, &emitted, 1)) {
1058 /* sym was not in emittedSymbols */
1059 if (!checkLocals || !pic14_stringInSet(sym, &pic14_localFunctions, 0)) {
1060 /* sym is not a locally defined function---avoid bug #1443651 */
1061 fprintf( file, fmt, sym );
1068 /*-----------------------------------------------------------------*/
1069 /* printExterns - generates extern for external variables */
1070 /*-----------------------------------------------------------------*/
1072 pic14printExterns (FILE * afile)
1076 fprintf (afile, "%s", iComments2);
1077 fprintf (afile, "; extern variables in this module\n");
1078 fprintf (afile, "%s", iComments2);
1080 for (sym = setFirstItem (externs); sym; sym = setNextItem (externs))
1081 pic14_emitSymbolIfNew(afile, "\textern %s\n", sym->rname, 1);
1084 /*-----------------------------------------------------------------*/
1085 /* printPublics - generates .global for publics */
1086 /*-----------------------------------------------------------------*/
1088 pic14printPublics (FILE * afile)
1092 fprintf (afile, "%s", iComments2);
1093 fprintf (afile, "; publics variables in this module\n");
1094 fprintf (afile, "%s", iComments2);
1096 for (sym = setFirstItem (publics); sym;
1097 sym = setNextItem (publics)) {
1099 if(!IS_BITFIELD(sym->type) && ((IS_FUNC(sym->type) || sym->allocreq))) {
1100 if (!IS_BITVAR(sym->type))
1101 pic14_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1103 /* Absolute variables are defines in the asm file as equates and thus can not be made global. */
1104 /* Not any longer! */
1105 //if (!SPEC_ABSA (sym->etype))
1106 pic14_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1111 /*-----------------------------------------------------------------*/
1112 /* emitOverlay - will emit code for the overlay stuff */
1113 /*-----------------------------------------------------------------*/
1115 pic14emitOverlay (FILE * afile)
1119 /* if (!elementsInSet (ovrSetSets))*/
1121 /* the hack below, fixes translates for devices which
1122 * only have udata_shr memory */
1123 fprintf (afile, "%s\t%s\n",
1124 (elementsInSet(ovrSetSets)?"":";"),
1125 port->mem.overlay_name);
1127 /* for each of the sets in the overlay segment do */
1128 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1129 ovrset = setNextItem (ovrSetSets))
1134 if (elementsInSet (ovrset))
1136 /* this dummy area is used to fool the assembler
1137 otherwise the assembler will append each of these
1138 declarations into one chunk and will not overlay
1141 /* I don't think this applies to us. We are using gpasm. CRF */
1143 fprintf (afile, ";\t.area _DUMMY\n");
1144 /* output the area informtion */
1145 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1148 for (sym = setFirstItem (ovrset); sym;
1149 sym = setNextItem (ovrset))
1152 /* if extern then do nothing */
1153 if (IS_EXTERN (sym->etype))
1156 /* if allocation required check is needed
1157 then check if the symbol really requires
1158 allocation only for local variables */
1159 if (!IS_AGGREGATE (sym->type) &&
1160 !(sym->_isparm && !IS_REGPARM (sym->etype))
1161 && !sym->allocreq && sym->level)
1164 /* if global variable & not static or extern
1165 and addPublics allowed then add it to the public set */
1166 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1167 && !IS_STATIC (sym->etype))
1168 addSetHead (&publics, sym);
1170 /* if extern then do nothing or is a function
1172 if (IS_FUNC (sym->type))
1175 /* print extra debug info if required */
1176 if (options.debug || sym->level == 0)
1180 if (IS_STATIC (sym->etype))
1181 fprintf (afile, "F%s_", moduleName); /* scope is file */
1183 fprintf (afile, "G_"); /* scope is global */
1186 /* symbol is local */
1187 fprintf (afile, "L%s_",
1188 (sym->localof ? sym->localof->name : "-null-"));
1189 fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
1192 /* if is has an absolute address then generate
1193 an equate for this no need to allocate space */
1194 if (SPEC_ABSA (sym->etype))
1197 if (options.debug || sym->level == 0)
1198 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1200 fprintf (afile, "%s\t=\t0x%04x\n",
1202 SPEC_ADDR (sym->etype));
1206 if (options.debug || sym->level == 0)
1207 fprintf (afile, "==.\n");
1209 /* allocate space */
1210 fprintf (afile, "%s:\n", sym->rname);
1211 fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1220 pic14_emitInterruptHandler (FILE * asmFile)
1222 if (pic14_hasInterrupt)
1225 fprintf (asmFile, "%s", iComments2);
1226 fprintf (asmFile, "; interrupt and initialization code\n");
1227 fprintf (asmFile, "%s", iComments2);
1228 // Note - for mplink may have to enlarge section vectors in .lnk file
1229 // Note: Do NOT name this code_interrupt to avoid nameclashes with
1230 // source files's code segment (interrupt.c -> code_interrupt)
1231 fprintf (asmFile, "c_interrupt\t%s\t0x4\n", CODE_NAME);
1233 /* interrupt service routine */
1234 fprintf (asmFile, "__sdcc_interrupt\n");
1235 copypCode(asmFile, 'I');
1239 /*-----------------------------------------------------------------*/
1240 /* glue - the final glue that hold the whole thing together */
1241 /*-----------------------------------------------------------------*/
1245 char udata_name[80];
1248 FILE *ovrFile = tempfile();
1250 addSetHead(&tmpfileSet,ovrFile);
1251 pCodeInitRegisters();
1253 /* check for main() */
1254 mainf = newSymbol ("main", 0);
1256 mainf = findSymWithLevel (SymbolTab, mainf);
1258 if (!mainf || !IFFUNC_HASBODY(mainf->type))
1260 /* main missing -- import stack from main module */
1261 //fprintf (stderr, "main() missing -- assuming we are NOT the main module\n");
1262 pic14_options.isLibrarySource = 1;
1266 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1268 pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
1271 /* entry point @ start of CSEG */
1272 addpCode2pBlock(pb,newpCodeLabel("__sdcc_program_startup",-1));
1273 /* put in the call to main */
1274 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp("_main",PO_STR)));
1276 if (options.mainreturn) {
1278 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will return to caller\n"));
1279 addpCode2pBlock(pb,newpCode(POC_RETURN,NULL));
1283 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will lock up\n"));
1284 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("$",PO_STR)));
1290 /* At this point we've got all the code in the form of pCode structures */
1291 /* Now it needs to be rearranged into the order it should be placed in the */
1294 movepBlock2Head('P'); // Last
1295 movepBlock2Head(code->dbName);
1296 movepBlock2Head('X');
1297 movepBlock2Head(statsg->dbName); // First
1300 /* print the global struct definitions */
1306 addSetHead(&tmpfileSet,vFile);
1308 /* emit code for the all the variables declared */
1310 /* do the overlay segments */
1311 pic14emitOverlay(ovrFile);
1313 /* PENDING: this isnt the best place but it will do */
1314 if (port->general.glue_up_main) {
1315 /* create the interrupt vector table */
1316 pic14createInterruptVect (vFile);
1321 ReuseReg(); // ReuseReg where call tree permits
1330 /* now put it all together into the assembler file */
1331 /* create the assembler file name */
1333 if ((noAssemble || options.c1mode) && fullDstFileName)
1335 sprintf (buffer, fullDstFileName);
1339 sprintf (buffer, dstFileName);
1340 strcat (buffer, ".asm");
1343 if (!(asmFile = fopen (buffer, "w"))) {
1344 werror (E_FILE_OPEN_ERR, buffer);
1348 /* prepare statistics */
1349 resetpCodeStatistics ();
1351 /* initial comments */
1352 pic14initialComments (asmFile);
1354 /* print module name */
1355 fprintf (asmFile, ";\t.module %s\n", moduleName);
1357 /* Let the port generate any global directives, etc. */
1358 if (port->genAssemblerPreamble)
1360 port->genAssemblerPreamble(asmFile);
1363 /* Emit the __config directive */
1364 pic14_emitConfigWord (asmFile);
1366 /* print the global variables in this module */
1367 pic14printPublics (asmFile);
1369 /* print the extern variables in this module */
1370 pic14printExterns (asmFile);
1372 /* copy the sfr segment */
1373 fprintf (asmFile, "%s", iComments2);
1374 fprintf (asmFile, "; special function registers\n");
1375 fprintf (asmFile, "%s", iComments2);
1376 copyFile (asmFile, sfr->oFile);
1379 if (udata_section_name) {
1380 sprintf(udata_name,"%s",udata_section_name);
1382 sprintf(udata_name,"data_%s",moduleName);
1384 fprintf (asmFile, "%s", iComments2);
1385 fprintf (asmFile, "; udata\n");
1386 fprintf (asmFile, "%s", iComments2);
1387 fprintf (asmFile, "%s\tudata\n", udata_name);
1388 copyFile (asmFile, data->oFile);
1390 /* Put all variables into a cblock */
1392 writeUsedRegs(asmFile);
1394 /* create the overlay segments */
1395 fprintf (asmFile, "%s", iComments2);
1396 fprintf (asmFile, "; overlayable items in internal ram \n");
1397 fprintf (asmFile, "%s", iComments2);
1398 copyFile (asmFile, ovrFile);
1402 /* create the stack segment MOF */
1403 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1404 fprintf (asmFile, "%s", iComments2);
1405 fprintf (asmFile, "; Stack segment in internal ram \n");
1406 fprintf (asmFile, "%s", iComments2);
1407 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1408 ";__start__stack:\n;\t.ds\t1\n\n");
1411 /* create the idata segment */
1412 fprintf (asmFile, "%s", iComments2);
1413 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1414 fprintf (asmFile, "%s", iComments2);
1415 copyFile (asmFile, idata->oFile);
1417 /* if external stack then reserve space of it */
1418 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1419 fprintf (asmFile, "%s", iComments2);
1420 fprintf (asmFile, "; external stack \n");
1421 fprintf (asmFile, "%s", iComments2);
1422 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1423 fprintf (asmFile,";\t.ds 256\n");
1426 /* copy xtern ram data */
1427 fprintf (asmFile, "%s", iComments2);
1428 fprintf (asmFile, "; external ram data\n");
1429 fprintf (asmFile, "%s", iComments2);
1430 copyFile (asmFile, xdata->oFile);
1434 /* copy the bit segment */
1435 fprintf (asmFile, "%s", iComments2);
1436 fprintf (asmFile, "; bit data\n");
1437 fprintf (asmFile, "%s", iComments2);
1438 copyFile (asmFile, bit->oFile);
1440 /* copy the interrupt vector table */
1441 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1442 copyFile (asmFile, vFile);
1445 /* create interupt ventor handler */
1446 pic14_emitInterruptHandler (asmFile);
1448 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1449 /* initialize data memory */
1450 fprintf (asmFile, "code_init\t%s\n", CODE_NAME); // Note - for mplink may have to enlarge section vectors in .lnk file
1451 fprintf (asmFile,"__sdcc_gsinit_startup\n");
1452 /* FIXME: This is temporary. The idata section should be used. If
1453 not, we could add a special feature to the linker. This will
1454 work in the mean time. Put all initalized data in main.c */
1455 copypCode(asmFile, statsg->dbName);
1456 fprintf (asmFile,"\tpagesel _main\n");
1457 fprintf (asmFile,"\tgoto _main\n");
1462 /* copy global & static initialisations */
1463 fprintf (asmFile, "%s", iComments2);
1464 fprintf (asmFile, "; global & static initialisations\n");
1465 fprintf (asmFile, "%s", iComments2);
1466 copypCode(asmFile, statsg->dbName);
1470 /* copy over code */
1471 fprintf (asmFile, "%s", iComments2);
1472 fprintf (asmFile, "; code\n");
1473 fprintf (asmFile, "%s", iComments2);
1474 fprintf (asmFile, "code_%s\t%s\n", moduleName, port->mem.code_name);
1477 copypCode(asmFile, 'X');
1479 /* _main function */
1480 copypCode(asmFile, 'M');
1482 /* other functions */
1483 copypCode(asmFile, code->dbName);
1486 copypCode(asmFile, 'P');
1488 dumppCodeStatistics (asmFile);
1490 fprintf (asmFile,"\tend\n");