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);
77 char *udata_section_name=0; // FIXME Temporary fix to change udata section name -- VR
78 int pic14_hasInterrupt = 0; // Indicates whether to emit interrupt handler or not
80 /*-----------------------------------------------------------------*/
81 /* aopLiteral - string from a literal value */
82 /*-----------------------------------------------------------------*/
83 unsigned int pic14aopLiteral (value *val, int offset)
90 /* if it is a float then it gets tricky */
91 /* otherwise it is fairly simple */
92 if (!IS_FLOAT(val->type)) {
93 unsigned long v = (unsigned long) floatFromVal(val);
95 return ( (v >> (offset * 8)) & 0xff);
98 /* it is type float */
99 fl.f = (float) floatFromVal(val);
100 #ifdef WORDS_BIGENDIAN
101 return fl.c[3-offset];
109 is_valid_identifier( const char *name )
115 /* only accept [a-zA-Z_][a-zA-Z0-9_] */
116 if (!((a >= 'a' && a <= 'z')
117 || (a >= 'A' && a <= 'z')
122 while ((a = *name++))
124 if (!((a >= 'a' && a <= 'z')
125 || (a >= 'A' && a <= 'Z')
126 || (a >= '0' && a <= '9')
131 /* valid identifier */
135 /* set of already emitted symbols; we store only pointers to the emitted
136 * symbol names so these MUST NO BE CHANGED afterwards... */
137 static set *symbolsEmitted = NULL;
139 /*-------------------------------------------------------------------*/
140 /* emitSymbolToFile - write a symbol definition only if it is not */
141 /* already present */
142 /*-------------------------------------------------------------------*/
144 emitSymbolToFile (FILE *of, const char *name, const char *section_type, int size, int addr, int useEQU, int globalize)
147 static unsigned int sec_idx = 0;
149 /* workaround: variables declared via `sbit' result in a numeric
150 * identifier (0xHH), EQU'ing them is invalid, so just ignore it.
151 * sbit is heavily used in the inc2h-generated header files!
153 if (!is_valid_identifier(name))
155 //fprintf( stderr, "%s:%s:%u: ignored symbol: %s\n", __FILE__, __FUNCTION__, __LINE__, name );
159 /* check whether the symbol is already defined */
160 for (sym = (const char *) setFirstItem (symbolsEmitted);
162 sym = (const char *) setNextItem (symbolsEmitted))
164 if (!strcmp (sym, name))
166 //fprintf (stderr, "%s: already emitted: %s\n", __FUNCTION__, name);
171 /* new symbol -- define it */
172 //fprintf (stderr, "%s: emitting %s (%d)\n", __FUNCTION__, name, size);
174 fprintf (of, "%s\tEQU\t0x%04x\n", name, addr);
177 /* we place each symbol into a section of its own to allow the linker
178 * to distribute the data into all available memory banks */
179 if (!section_type) section_type = "udata";
182 /* absolute symbols are handled in pic14_constructAbsMap */
185 /* workaround gpasm bug with symbols being EQUated and placed in absolute sections */
186 if (1 || !is_shared_address (addr))
188 if (globalize) fprintf (of, "\tglobal\t%s\n", name);
189 fprintf (of, "udata_%s_%u\t%s\t0x%04x\n", moduleName,
190 sec_idx++, "udata_ovr", addr);
191 fprintf (of, "%s\tres\t%d\n", name, size);
195 /* EQUs cannot be exported... */
196 fprintf (of, "%s\tEQU\t0x%04x\n", name, addr);
200 if (globalize) fprintf (of, "\tglobal\t%s\n", name);
201 fprintf (of, "udata_%s_%u\t%s\n", moduleName,
202 sec_idx++, section_type);
203 fprintf (of, "%s\tres\t%d\n", name, size);
207 //if (options.verbose) fprintf (stderr, "%s: emitted %s\n", __FUNCTION__, name);
208 addSet (&symbolsEmitted, (void *) name);
211 #define IS_DEFINED_HERE(sym) (!IS_EXTERN(sym->etype))
212 extern int IS_CONFIG_ADDRESS( int addr );
214 pic14_constructAbsMap (FILE *ofile)
216 memmap *maps[] = { data, sfr, NULL };
221 int addr, min=-1, max=-1;
224 int low, high, shared;
226 for (i=0; maps[i] != NULL; i++)
228 for (sym = (symbol *)setFirstItem (maps[i]->syms);
229 sym; sym = setNextItem (maps[i]->syms))
231 if (IS_DEFINED_HERE(sym) && SPEC_ABSA(sym->etype))
233 addr = SPEC_ADDR(sym->etype);
235 /* handle CONFIG words here */
236 if (IS_CONFIG_ADDRESS( addr ))
238 //fprintf( stderr, "%s: assignment to CONFIG@0x%x found\n", __FUNCTION__, addr );
239 //fprintf( stderr, "ival: %p (0x%x)\n", sym->ival, (int)list2int( sym->ival ) );
241 pic14_assignConfigWordValue( addr, (int)list2int( sym->ival ) );
243 fprintf( stderr, "ERROR: Symbol %s, which is covering a __CONFIG word must be initialized!\n", sym->name );
248 if (max == -1 || addr > max) max = addr;
249 if (min == -1 || addr < min) min = addr;
250 //fprintf (stderr, "%s: sym %s @ 0x%x\n", __FUNCTION__, sym->name, addr);
251 aliases = hTabItemWithKey (ht, addr);
253 /* May not use addSetHead, as we cannot update the
254 * list's head in the hastable `ht'. */
255 addSet (&aliases, sym);
257 fprintf( stderr, "%s: now %d aliases for %s @ 0x%x\n",
258 __FUNCTION__, elementsInSet(aliases), sym->name, addr);
261 addSet (&aliases, sym);
262 hTabAddItem (&ht, addr, aliases);
268 /* now emit definitions for all absolute symbols */
269 fprintf (ofile, "%s", iComments2);
270 fprintf (ofile, "; absolute symbol definitions\n");
271 fprintf (ofile, "%s", iComments2);
272 for (addr=min; addr <= max; addr++)
275 aliases = hTabItemWithKey (ht, addr);
276 if (aliases && elementsInSet(aliases)) {
277 fprintf (ofile, "udata_abs_%s_%x\tudata_ovr\t0x%04x",
278 moduleName, addr, addr);
279 for (sym = setFirstItem (aliases); sym;
280 sym = setNextItem (aliases))
282 /* emit STATUS as well as _STATUS, required for SFRs only */
283 fprintf (ofile, "\n%s", sym->name);
284 fprintf (ofile, "\n%s", sym->rname);
285 if (getSize(sym->type) > size) {
286 size = getSize(sym->type);
288 addSet (&symbolsEmitted, (void *) sym->name);
289 addSet (&symbolsEmitted, (void *) sym->rname);
291 fprintf (ofile, "\tres\t%d\n", size);
295 /* also emit STK symbols
296 * XXX: This is ugly and fails as soon as devices start to get
297 * differently sized sharebanks, since STK12 will be
298 * required by larger devices but only up to STK03 might
299 * be defined using smaller devices. */
300 fprintf (ofile, "\n");
301 shared = pic14_getSharedStack(&low, &high, &size);
302 if (!pic14_options.isLibrarySource)
304 pic = pic14_getPIC();
306 fprintf (ofile, "\tglobal PSAVE\n");
307 fprintf (ofile, "\tglobal SSAVE\n");
308 fprintf (ofile, "\tglobal WSAVE\n");
309 for (i = size - 4; i >= 0; i--) {
310 fprintf (ofile, "\tglobal STK%02d\n", i);
313 // 16f84 has no SHAREBANK (in linkerscript) but memory aliased in two
316 // for single banked devices: use normal, "banked" RAM
317 fprintf (ofile, "sharebank udata_ovr 0x%04X\n", low);
319 // for devices with at least two banks, require a sharebank section
320 fprintf (ofile, "sharebank udata_shr\n");
322 fprintf (ofile, "PSAVE\tres 1\n");
323 fprintf (ofile, "SSAVE\tres 1\n");
324 fprintf (ofile, "WSAVE\tres 1\n"); // WSAVE *must* be in sharebank (IRQ handlers)
325 /* fill rest of sharebank with stack STKxx .. STK00 */
326 for (i = size - 4; i >= 0; i--) {
327 fprintf (ofile, "STK%02d\tres 1\n", i);
330 /* declare STKxx as extern for all files
331 * except the one containing main() */
332 fprintf (ofile, "\textern PSAVE\n");
333 fprintf (ofile, "\textern SSAVE\n");
334 fprintf (ofile, "\textern WSAVE\n");
335 for (i = size - 4; i >= 0; i--) {
337 SNPRINTF(&buffer[0], 127, "STK%02d", i);
338 fprintf (ofile, "\textern %s\n", &buffer[0]);
339 addSet (&symbolsEmitted, (void *) &buffer[0]);
344 /*-----------------------------------------------------------------*/
345 /* emitRegularMap - emit code for maps with no special cases */
346 /*-----------------------------------------------------------------*/
348 pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag)
353 /* print the area name */
355 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
357 for (sym = setFirstItem (map->syms); sym;
358 sym = setNextItem (map->syms)) {
360 //printf("%s\n",sym->name);
362 /* ignore if config word */
363 if (SPEC_ABSA(sym->etype)
364 && IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype)))
367 /* if extern then add it into the extern list */
368 if (IS_EXTERN (sym->etype)) {
369 addSetHead (&externs, sym);
373 /* if allocation required check is needed
374 then check if the symbol really requires
375 allocation only for local variables */
376 if (arFlag && !IS_AGGREGATE (sym->type) &&
377 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
378 !sym->allocreq && sym->level)
381 /* if global variable & not static or extern
382 and addPublics allowed then add it to the public set */
383 if ((sym->level == 0 ||
384 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
386 !IS_STATIC (sym->etype))
388 //fprintf( stderr, "%s: made public %s\n", __FUNCTION__, sym->name );
389 addSetHead (&publics, sym);
392 // PIC code allocates its own registers - so ignore parameter variable generated by processFuncArgs()
395 /* if extern then do nothing or is a function
397 if (IS_FUNC (sym->type))
400 /* print extra debug info if required */
401 if (options.debug || sym->level == 0)
403 if (!sym->level) /* global */
404 if (IS_STATIC (sym->etype))
405 fprintf (map->oFile, "F%s_", moduleName); /* scope is file */
407 fprintf (map->oFile, "G_"); /* scope is global */
409 /* symbol is local */
410 fprintf (map->oFile, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
411 fprintf (map->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
414 /* absolute symbols are handled in pic14_constructAbsMap */
415 if (SPEC_ABSA(sym->etype) && IS_DEFINED_HERE(sym))
418 /* if it has an absolute address then generate
419 an equate for this no need to allocate space */
420 if (0 && SPEC_ABSA (sym->etype))
422 //if (options.debug || sym->level == 0)
423 //fprintf (map->oFile,"; == 0x%04x\n",SPEC_ADDR (sym->etype));
425 fprintf (map->oFile, "%s\tEQU\t0x%04x\n",
427 SPEC_ADDR (sym->etype));
433 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
434 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
435 /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
436 if (IS_BITVAR (sym->etype))
442 emitSymbolToFile (map->oFile,
445 getSize (sym->type) & 0xffff,
446 SPEC_ABSA(sym->etype)
447 ? SPEC_ADDR(sym->etype)
455 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1)
457 for (i = 1; i < size; i++)
458 fprintf (map->oFile, "\t%s_%d\n", sym->rname, i);
463 //fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
466 /* if it has a initial value then do it only if
467 it is a global variable */
468 if (sym->ival && sym->level == 0) {
471 if (IS_AGGREGATE (sym->type))
472 ival = initAggregates (sym, sym->ival, NULL);
474 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
475 decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
476 codeOutFile = statsg->oFile;
478 eBBlockFromiCode (iCodeFromAst (ival));
485 /*-----------------------------------------------------------------*/
486 /* printIvalType - generates ival for int/char */
487 /*-----------------------------------------------------------------*/
489 printIvalType (symbol *sym, sym_link * type, initList * ilist, pBlock *pb)
494 //fprintf(stderr, "%s\n",__FUNCTION__);
496 /* if initList is deep */
497 if (ilist->type == INIT_DEEP)
498 ilist = ilist->init.deep;
500 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
501 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
504 if (!(val = list2val (ilist))) {
505 // assuming a warning has been thrown
509 if (val->type != type) {
510 val = valCastLiteral(type, floatFromVal(val));
514 ulval = (unsigned long) floatFromVal (val);
518 switch (getSize (type)) {
520 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
524 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
525 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
529 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
530 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
531 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
532 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
537 /*-----------------------------------------------------------------*/
538 /* printIvalBitFields - generate initializer for bitfields */
539 /*-----------------------------------------------------------------*/
540 static void printIvalBitFields(symbol **sym, initList **ilist, pBlock *pb )
544 initList *lilist = *ilist ;
545 unsigned long ival = 0;
551 val = list2val(lilist);
553 if (SPEC_BLEN(lsym->etype) > 8) {
554 size += ((SPEC_BLEN (lsym->etype) / 8) +
555 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
558 size = ((SPEC_BLEN (lsym->etype) / 8) +
559 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
561 i = (unsigned long)floatFromVal(val);
562 i <<= SPEC_BSTR (lsym->etype);
564 if (! ( lsym->next &&
565 (IS_BITFIELD(lsym->next->type)) &&
566 (SPEC_BSTR(lsym->next->etype)))) break;
568 lilist = lilist->next;
572 //tfprintf (oFile, "\t!db !constbyte\n",ival);
573 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
577 //tfprintf (oFile, "\t!dw !constword\n",ival);
578 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
579 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
582 //tfprintf (oFile, "\t!db !constword,!constword\n",(ival >> 8) & 0xffff, (ival & 0xffff));
583 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>24)));
584 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>16)));
585 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
586 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
593 /*-----------------------------------------------------------------*/
594 /* printIvalStruct - generates initial value for structures */
595 /*-----------------------------------------------------------------*/
596 static void printIvalStruct (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
599 initList *iloop = NULL;
601 sflds = SPEC_STRUCT (type)->fields;
604 if (ilist->type != INIT_DEEP) {
605 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
609 iloop = ilist->init.deep;
612 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
613 if (IS_BITFIELD(sflds->type)) {
614 printIvalBitFields(&sflds,&iloop,pb);
616 printIval (sym, sflds->type, iloop, pb);
620 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
625 /*-----------------------------------------------------------------*/
626 /* printIvalChar - generates initital value for character array */
627 /*-----------------------------------------------------------------*/
629 printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
637 //fprintf(stderr, "%s\n",__FUNCTION__);
641 val = list2val (ilist);
643 /* if the value is a character string */
644 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
646 ilen = DCL_ELEM(val->type);
648 if (!DCL_ELEM (type))
649 DCL_ELEM (type) = ilen;
651 /* emit string constant */
652 for (remain = 0; remain < ilen; remain++) {
653 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(SPEC_CVAL(val->etype).v_char[remain])));
656 /* fill array up to desired size */
657 if ((remain = (DCL_ELEM (type) - ilen)) > 0)
659 //tfprintf (oFile, "\t!db !constbyte\n", 0);
660 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
667 //printChar (oFile, s, strlen (s) + 1);
669 for(remain=0; remain<(int)strlen(s); remain++) {
670 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(s[remain])));
671 //fprintf(stderr,"0x%02x ",s[remain]);
673 //fprintf(stderr,"\n");
678 /*-----------------------------------------------------------------*/
679 /* printIvalArray - generates code for array initialization */
680 /*-----------------------------------------------------------------*/
682 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
691 /* take care of the special case */
692 /* array of characters can be init */
694 if (IS_CHAR (type->next)) {
695 //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
696 if (!IS_LITERAL(list2val(ilist)->etype)) {
697 werror (W_INIT_WRONG);
700 if (printIvalChar (type,
701 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
702 pb, SPEC_CVAL (sym->etype).v_char))
705 /* not the special case */
706 if (ilist->type != INIT_DEEP) {
707 werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
711 for (iloop=ilist->init.deep; iloop; iloop=iloop->next) {
712 if ((++size > DCL_ELEM(type)) && DCL_ELEM(type)) {
713 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
716 printIval (sym, type->next, iloop, pb);
720 if (DCL_ELEM(type)) {
721 // pad with zeros if needed
722 if (size<DCL_ELEM(type)) {
723 size = (DCL_ELEM(type) - size) * getSize(type->next);
725 //tfprintf (oFile, "\t!db !constbyte\n", 0);
726 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
730 // we have not been given a size, but we now know it
731 DCL_ELEM (type) = size;
737 /*-----------------------------------------------------------------*/
738 /* printIvalPtr - generates code for initial value of pointers */
739 /*-----------------------------------------------------------------*/
740 extern value *initPointer (initList *, sym_link *toType);
743 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
750 fprintf (stderr, "FIXME: initializers for pointers...\n");
751 printTypeChain (type, stderr);
753 fprintf (stderr, "symbol: %s, DCL_TYPE():%d, DCL_ELEM():%d, IS_ARRAY():%d", sym->rname, DCL_TYPE(type), DCL_ELEM(type), IS_ARRAY(type));
754 fprintf (stderr, "ilist: type=%d (INIT_DEEP=%d, INIT_NODE=%d)\n", ilist->type, INIT_DEEP, INIT_NODE);
756 if (ilist && (ilist->type == INIT_DEEP))
757 ilist = ilist->init.deep;
759 /* function pointers */
760 if (IS_FUNC (type->next))
762 assert ( !"function pointers not yet handled" );
763 //printIvalFuncPtr (type, ilist, pb);
766 if (!(val = initPointer (ilist, type)))
769 if (IS_CHAR (type->next))
771 if (printIvalChar (type, ilist, pb, NULL)) return;
775 if (compareType (type, val->type) == 0)
777 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
778 printFromToType (val->type, type);
781 if (IS_LITERAL (val->etype))
783 switch (getSize (type))
786 fprintf (stderr, "BYTE: %i\n", (unsigned char)floatFromVal (val) & 0x00FF);
789 fprintf (stderr, "WORD: %i\n", (unsigned int)floatFromVal (val) & 0x00FFFF);
791 case 3: /* gneric pointers */
792 assert ( !"generic pointers not yet handled" );
794 fprintf (stderr, "LONG: %i\n", (unsigned int)floatFromVal (val) & 0x0000FFFFFFFF);
797 assert ( !"invaild size of value -- aborting" );
803 /* now handle symbolic values */
804 switch (getSize (type))
807 fprintf (stderr, "BYTE: %s", val->name);
810 fprintf (stderr, "WORD: %s", val->name);
813 fprintf (stderr, "LONG: %s", val->name);
816 assert ( !"invalid size of (symbolic) value -- aborting" );
820 /*-----------------------------------------------------------------*/
821 /* printIval - generates code for initial value */
822 /*-----------------------------------------------------------------*/
824 printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
829 /* if structure then */
830 if (IS_STRUCT (type))
832 //fprintf(stderr,"%s struct: %s\n",__FUNCTION__, sym->rname);
833 printIvalStruct (sym, type, ilist, pb);
837 /* if this is an array */
840 //fprintf(stderr,"%s array: %s\n",__FUNCTION__, sym->rname);
841 printIvalArray (sym, type, ilist, pb);
845 /* if this is a pointer */
848 //fprintf(stderr,"%s pointer: %s\n",__FUNCTION__, sym->rname);
849 printIvalPtr (sym, type, ilist, pb);
853 /* if type is SPECIFIER */
856 //fprintf(stderr,"%s spec %s\n",__FUNCTION__, sym->rname);
857 printIvalType (sym, type, ilist, pb);
862 extern void pCodeConstString(char *name, char *value);
863 /*-----------------------------------------------------------------*/
864 /* emitStaticSeg - emitcode for the static segment */
865 /*-----------------------------------------------------------------*/
867 pic14emitStaticSeg (memmap * map)
871 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
873 //fprintf(stderr, "%s\n",__FUNCTION__);
875 /* for all variables in this segment do */
876 for (sym = setFirstItem (map->syms); sym;
877 sym = setNextItem (map->syms))
879 /* if extern then add it into the extern list */
880 if (IS_EXTERN (sym->etype)) {
881 addSetHead (&externs, sym);
885 /* if it is not static add it to the public
887 if (!IS_STATIC (sym->etype))
888 addSetHead (&publics, sym);
890 /* print extra debug info if required */
891 if (options.debug || sym->level == 0)
895 if (IS_STATIC (sym->etype))
896 fprintf (code->oFile, "F%s_", moduleName); /* scope is file */
898 fprintf (code->oFile, "G_"); /* scope is global */
901 /* symbol is local */
902 fprintf (code->oFile, "L%s_",
903 (sym->localof ? sym->localof->name : "-null-"));
904 fprintf (code->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
908 /* if it has an absolute address */
909 if (SPEC_ABSA (sym->etype))
911 if (options.debug || sym->level == 0)
912 fprintf (code->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
914 fprintf (code->oFile, "%s\t=\t0x%04x\n",
916 SPEC_ADDR (sym->etype));
920 if (options.debug || sym->level == 0)
921 fprintf (code->oFile, " == .\n");
923 /* if it has an initial value */
928 fprintf (code->oFile, "%s:\n", sym->rname);
930 resolveIvalSym (sym->ival, sym->type);
931 //printIval (sym, sym->type, sym->ival, code->oFile);
932 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block for Ival"));
934 addpCode2pBlock(pb,newpCodeLabel(sym->rname,-1));
936 printIval (sym, sym->type, sym->ival, pb);
943 fprintf (code->oFile, "%s:\n", sym->rname);
944 /* special case for character strings */
945 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
946 SPEC_CVAL (sym->etype).v_char)
947 pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
948 /*printChar (code->oFile,
949 SPEC_CVAL (sym->etype).v_char,
950 strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
952 fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
960 /*-----------------------------------------------------------------*/
961 /* emitMaps - emits the code for the data portion the code */
962 /*-----------------------------------------------------------------*/
966 pic14_constructAbsMap (sfr->oFile);
967 /* no special considerations for the following
968 data, idata & bit & xdata */
969 pic14emitRegularMap (data, TRUE, TRUE);
970 pic14emitRegularMap (idata, TRUE, TRUE);
971 pic14emitRegularMap (bit, TRUE, FALSE);
972 pic14emitRegularMap (xdata, TRUE, TRUE);
973 pic14emitRegularMap (sfr, TRUE, FALSE);
974 pic14emitRegularMap (sfrbit, FALSE, FALSE);
975 pic14emitRegularMap (code, TRUE, FALSE);
976 pic14emitStaticSeg (statsg);
977 pic14emitStaticSeg (c_abs);
980 /*-----------------------------------------------------------------*/
981 /* createInterruptVect - creates the interrupt vector */
982 /*-----------------------------------------------------------------*/
984 pic14createInterruptVect (FILE * vFile)
986 mainf = newSymbol ("main", 0);
989 /* only if the main function exists */
990 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
992 struct options *op = &options;
993 if (!(op->cc_only || noAssemble))
994 // werror (E_NO_MAIN);
995 fprintf(stderr,"WARNING: function 'main' undefined\n");
999 /* if the main is only a prototype ie. no body then do nothing */
1000 if (!IFFUNC_HASBODY(mainf->type))
1002 /* if ! compile only then main function should be present */
1003 if (!(options.cc_only || noAssemble))
1004 // werror (E_NO_MAIN);
1005 fprintf(stderr,"WARNING: function 'main' undefined\n");
1009 fprintf (vFile, "%s", iComments2);
1010 fprintf (vFile, "; reset vector \n");
1011 fprintf (vFile, "%s", iComments2);
1012 fprintf (vFile, "STARTUP\t%s\n", CODE_NAME); // Lkr file should place section STARTUP at address 0x0
1013 fprintf (vFile, "\tnop\n"); /* first location for used by incircuit debugger */
1014 fprintf( vFile, "\tpagesel __sdcc_gsinit_startup\n");
1015 fprintf (vFile, "\tgoto\t__sdcc_gsinit_startup\n");
1019 /*-----------------------------------------------------------------*/
1020 /* initialComments - puts in some initial comments */
1021 /*-----------------------------------------------------------------*/
1023 pic14initialComments (FILE * afile)
1025 initialComments (afile);
1026 fprintf (afile, "; PIC port for the 14-bit core\n");
1027 fprintf (afile, iComments2);
1032 pic14_stringInSet(const char *str, set **world, int autoAdd)
1039 for (s = setFirstItem(*world); s; s = setNextItem(*world))
1042 if (0 == strcmp(s, str)) return 1;
1046 if (autoAdd) addSet(world, Safe_strdup(str));
1051 pic14_emitSymbolIfNew(FILE *file, const char *fmt, const char *sym, int checkLocals)
1053 static set *emitted = NULL;
1055 if (!pic14_stringInSet(sym, &emitted, 1)) {
1056 /* sym was not in emittedSymbols */
1057 if (!checkLocals || !pic14_stringInSet(sym, &pic14_localFunctions, 0)) {
1058 /* sym is not a locally defined function---avoid bug #1443651 */
1059 fprintf( file, fmt, sym );
1066 /*-----------------------------------------------------------------*/
1067 /* printExterns - generates extern for external variables */
1068 /*-----------------------------------------------------------------*/
1070 pic14printExterns (FILE * afile)
1074 fprintf (afile, "%s", iComments2);
1075 fprintf (afile, "; extern variables in this module\n");
1076 fprintf (afile, "%s", iComments2);
1078 for (sym = setFirstItem (externs); sym; sym = setNextItem (externs))
1079 pic14_emitSymbolIfNew(afile, "\textern %s\n", sym->rname, 1);
1082 /*-----------------------------------------------------------------*/
1083 /* printPublics - generates .global for publics */
1084 /*-----------------------------------------------------------------*/
1086 pic14printPublics (FILE * afile)
1090 fprintf (afile, "%s", iComments2);
1091 fprintf (afile, "; public variables in this module\n");
1092 fprintf (afile, "%s", iComments2);
1094 for (sym = setFirstItem (publics); sym;
1095 sym = setNextItem (publics)) {
1097 if(!IS_BITFIELD(sym->type) && ((IS_FUNC(sym->type) || sym->allocreq))) {
1098 if (!IS_BITVAR(sym->type))
1099 pic14_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1101 /* Absolute variables are defines in the asm file as equates and thus can not be made global. */
1102 /* Not any longer! */
1103 //if (!SPEC_ABSA (sym->etype))
1104 pic14_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1109 /*-----------------------------------------------------------------*/
1110 /* emitOverlay - will emit code for the overlay stuff */
1111 /*-----------------------------------------------------------------*/
1113 pic14emitOverlay (FILE * afile)
1117 /* if (!elementsInSet (ovrSetSets))*/
1119 /* the hack below, fixes translates for devices which
1120 * only have udata_shr memory */
1121 fprintf (afile, "%s\t%s\n",
1122 (elementsInSet(ovrSetSets)?"":";"),
1123 port->mem.overlay_name);
1125 /* for each of the sets in the overlay segment do */
1126 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1127 ovrset = setNextItem (ovrSetSets))
1132 if (elementsInSet (ovrset))
1134 /* this dummy area is used to fool the assembler
1135 otherwise the assembler will append each of these
1136 declarations into one chunk and will not overlay
1139 /* I don't think this applies to us. We are using gpasm. CRF */
1141 fprintf (afile, ";\t.area _DUMMY\n");
1142 /* output the area informtion */
1143 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1146 for (sym = setFirstItem (ovrset); sym;
1147 sym = setNextItem (ovrset))
1150 /* if extern then do nothing */
1151 if (IS_EXTERN (sym->etype))
1154 /* if allocation required check is needed
1155 then check if the symbol really requires
1156 allocation only for local variables */
1157 if (!IS_AGGREGATE (sym->type) &&
1158 !(sym->_isparm && !IS_REGPARM (sym->etype))
1159 && !sym->allocreq && sym->level)
1162 /* if global variable & not static or extern
1163 and addPublics allowed then add it to the public set */
1164 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1165 && !IS_STATIC (sym->etype))
1166 addSetHead (&publics, sym);
1168 /* if extern then do nothing or is a function
1170 if (IS_FUNC (sym->type))
1173 /* print extra debug info if required */
1174 if (options.debug || sym->level == 0)
1178 if (IS_STATIC (sym->etype))
1179 fprintf (afile, "F%s_", moduleName); /* scope is file */
1181 fprintf (afile, "G_"); /* scope is global */
1184 /* symbol is local */
1185 fprintf (afile, "L%s_",
1186 (sym->localof ? sym->localof->name : "-null-"));
1187 fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
1190 /* if is has an absolute address then generate
1191 an equate for this no need to allocate space */
1192 if (SPEC_ABSA (sym->etype))
1195 if (options.debug || sym->level == 0)
1196 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1198 fprintf (afile, "%s\t=\t0x%04x\n",
1200 SPEC_ADDR (sym->etype));
1204 if (options.debug || sym->level == 0)
1205 fprintf (afile, "==.\n");
1207 /* allocate space */
1208 fprintf (afile, "%s:\n", sym->rname);
1209 fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1218 pic14_emitInterruptHandler (FILE * asmFile)
1220 if (pic14_hasInterrupt)
1223 fprintf (asmFile, "%s", iComments2);
1224 fprintf (asmFile, "; interrupt and initialization code\n");
1225 fprintf (asmFile, "%s", iComments2);
1226 // Note - for mplink may have to enlarge section vectors in .lnk file
1227 // Note: Do NOT name this code_interrupt to avoid nameclashes with
1228 // source files's code segment (interrupt.c -> code_interrupt)
1229 fprintf (asmFile, "c_interrupt\t%s\t0x4\n", CODE_NAME);
1231 /* interrupt service routine */
1232 fprintf (asmFile, "__sdcc_interrupt\n");
1233 copypCode(asmFile, 'I');
1237 /*-----------------------------------------------------------------*/
1238 /* glue - the final glue that hold the whole thing together */
1239 /*-----------------------------------------------------------------*/
1243 char udata_name[80];
1246 FILE *ovrFile = tempfile();
1248 addSetHead(&tmpfileSet,ovrFile);
1249 pCodeInitRegisters();
1251 /* check for main() */
1252 mainf = newSymbol ("main", 0);
1254 mainf = findSymWithLevel (SymbolTab, mainf);
1256 if (!mainf || !IFFUNC_HASBODY(mainf->type))
1258 /* main missing -- import stack from main module */
1259 //fprintf (stderr, "main() missing -- assuming we are NOT the main module\n");
1260 pic14_options.isLibrarySource = 1;
1264 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1266 pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
1269 /* entry point @ start of CSEG */
1270 addpCode2pBlock(pb,newpCodeLabel("__sdcc_program_startup",-1));
1271 /* put in the call to main */
1272 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp("_main",PO_STR)));
1274 if (options.mainreturn) {
1276 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will return to caller\n"));
1277 addpCode2pBlock(pb,newpCode(POC_RETURN,NULL));
1281 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will lock up\n"));
1282 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("$",PO_STR)));
1288 /* At this point we've got all the code in the form of pCode structures */
1289 /* Now it needs to be rearranged into the order it should be placed in the */
1292 movepBlock2Head('P'); // Last
1293 movepBlock2Head(code->dbName);
1294 movepBlock2Head('X');
1295 movepBlock2Head(statsg->dbName); // First
1298 /* print the global struct definitions */
1304 addSetHead(&tmpfileSet,vFile);
1306 /* emit code for the all the variables declared */
1308 /* do the overlay segments */
1309 pic14emitOverlay(ovrFile);
1311 /* PENDING: this isnt the best place but it will do */
1312 if (port->general.glue_up_main) {
1313 /* create the interrupt vector table */
1314 pic14createInterruptVect (vFile);
1319 ReuseReg(); // ReuseReg where call tree permits
1328 /* now put it all together into the assembler file */
1329 /* create the assembler file name */
1331 if ((noAssemble || options.c1mode) && fullDstFileName)
1333 sprintf (buffer, fullDstFileName);
1337 sprintf (buffer, dstFileName);
1338 strcat (buffer, ".asm");
1341 if (!(asmFile = fopen (buffer, "w"))) {
1342 werror (E_FILE_OPEN_ERR, buffer);
1346 /* prepare statistics */
1347 resetpCodeStatistics ();
1349 /* initial comments */
1350 pic14initialComments (asmFile);
1352 /* print module name */
1353 fprintf (asmFile, ";\t.module %s\n", moduleName);
1355 /* Let the port generate any global directives, etc. */
1356 if (port->genAssemblerPreamble)
1358 port->genAssemblerPreamble(asmFile);
1361 /* Emit the __config directive */
1362 pic14_emitConfigWord (asmFile);
1364 /* print the global variables in this module */
1365 pic14printPublics (asmFile);
1367 /* print the extern variables in this module */
1368 pic14printExterns (asmFile);
1370 /* copy the sfr segment */
1371 fprintf (asmFile, "%s", iComments2);
1372 fprintf (asmFile, "; special function registers\n");
1373 fprintf (asmFile, "%s", iComments2);
1374 copyFile (asmFile, sfr->oFile);
1377 if (udata_section_name) {
1378 sprintf(udata_name,"%s",udata_section_name);
1380 sprintf(udata_name,"data_%s",moduleName);
1382 fprintf (asmFile, "%s", iComments2);
1383 fprintf (asmFile, "; udata\n");
1384 fprintf (asmFile, "%s", iComments2);
1385 fprintf (asmFile, "%s\tudata\n", udata_name);
1386 copyFile (asmFile, data->oFile);
1388 /* Put all variables into a cblock */
1390 writeUsedRegs(asmFile);
1392 /* create the overlay segments */
1393 fprintf (asmFile, "%s", iComments2);
1394 fprintf (asmFile, "; overlayable items in internal ram \n");
1395 fprintf (asmFile, "%s", iComments2);
1396 copyFile (asmFile, ovrFile);
1400 /* create the stack segment MOF */
1401 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1402 fprintf (asmFile, "%s", iComments2);
1403 fprintf (asmFile, "; Stack segment in internal ram \n");
1404 fprintf (asmFile, "%s", iComments2);
1405 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1406 ";__start__stack:\n;\t.ds\t1\n\n");
1409 /* create the idata segment */
1410 fprintf (asmFile, "%s", iComments2);
1411 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1412 fprintf (asmFile, "%s", iComments2);
1413 copyFile (asmFile, idata->oFile);
1415 /* if external stack then reserve space of it */
1416 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1417 fprintf (asmFile, "%s", iComments2);
1418 fprintf (asmFile, "; external stack \n");
1419 fprintf (asmFile, "%s", iComments2);
1420 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1421 fprintf (asmFile,";\t.ds 256\n");
1424 /* copy xtern ram data */
1425 fprintf (asmFile, "%s", iComments2);
1426 fprintf (asmFile, "; external ram data\n");
1427 fprintf (asmFile, "%s", iComments2);
1428 copyFile (asmFile, xdata->oFile);
1432 /* copy the bit segment */
1433 fprintf (asmFile, "%s", iComments2);
1434 fprintf (asmFile, "; bit data\n");
1435 fprintf (asmFile, "%s", iComments2);
1436 copyFile (asmFile, bit->oFile);
1438 /* copy the interrupt vector table */
1439 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1440 copyFile (asmFile, vFile);
1443 /* create interupt ventor handler */
1444 pic14_emitInterruptHandler (asmFile);
1446 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1447 /* initialize data memory */
1448 fprintf (asmFile, "code_init\t%s\n", CODE_NAME); // Note - for mplink may have to enlarge section vectors in .lnk file
1449 fprintf (asmFile,"__sdcc_gsinit_startup\n");
1450 /* FIXME: This is temporary. The idata section should be used. If
1451 not, we could add a special feature to the linker. This will
1452 work in the mean time. Put all initalized data in main.c */
1453 copypCode(asmFile, statsg->dbName);
1454 fprintf (asmFile,"\tpagesel _main\n");
1455 fprintf (asmFile,"\tgoto _main\n");
1460 /* copy global & static initialisations */
1461 fprintf (asmFile, "%s", iComments2);
1462 fprintf (asmFile, "; global & static initialisations\n");
1463 fprintf (asmFile, "%s", iComments2);
1464 copypCode(asmFile, statsg->dbName);
1468 /* copy over code */
1469 fprintf (asmFile, "%s", iComments2);
1470 fprintf (asmFile, "; code\n");
1471 fprintf (asmFile, "%s", iComments2);
1472 fprintf (asmFile, "code_%s\t%s\n", moduleName, port->mem.code_name);
1475 copypCode(asmFile, 'X');
1477 /* _main function */
1478 copypCode(asmFile, 'M');
1480 /* other functions */
1481 copypCode(asmFile, code->dbName);
1484 copypCode(asmFile, 'P');
1486 dumppCodeStatistics (asmFile);
1488 fprintf (asmFile,"\tend\n");