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];
108 /* Check whether the given reg is shared amongst all .o files of a project.
109 * This is true for the pseudo stack and WSAVE, SSAVE and PSAVE. */
111 is_shared_address (int addr)
113 return ((addr > Gstack_base_addr - 18)
114 && (addr <= Gstack_base_addr));
118 pic14_is_shared (regs *reg)
121 return is_shared_address (reg->address);
125 is_valid_identifier( const char *name )
131 /* only accept [a-zA-Z_][a-zA-Z0-9_] */
132 if (!((a >= 'a' && a <= 'z')
133 || (a >= 'A' && a <= 'z')
138 while ((a = *name++))
140 if (!((a >= 'a' && a <= 'z')
141 || (a >= 'A' && a <= 'Z')
142 || (a >= '0' && a <= '9')
147 /* valid identifier */
151 /* set of already emitted symbols; we store only pointers to the emitted
152 * symbol names so these MUST NO BE CHANGED afterwards... */
153 static set *symbolsEmitted = NULL;
155 /*-------------------------------------------------------------------*/
156 /* emitSymbolToFile - write a symbol definition only if it is not */
157 /* already present */
158 /*-------------------------------------------------------------------*/
160 emitSymbolToFile (FILE *of, const char *name, const char *section_type, int size, int addr, int useEQU, int globalize)
163 static unsigned int sec_idx = 0;
165 /* workaround: variables declared via `sbit' result in a numeric
166 * identifier (0xHH), EQU'ing them is invalid, so just ignore it.
167 * sbit is heavily used in the inc2h-generated header files!
169 if (!is_valid_identifier(name))
171 //fprintf( stderr, "%s:%s:%u: ignored symbol: %s\n", __FILE__, __FUNCTION__, __LINE__, name );
175 /* check whether the symbol is already defined */
176 for (sym = (const char *) setFirstItem (symbolsEmitted);
178 sym = (const char *) setNextItem (symbolsEmitted))
180 if (!strcmp (sym, name))
182 //fprintf (stderr, "%s: already emitted: %s\n", __FUNCTION__, name);
187 /* new symbol -- define it */
188 //fprintf (stderr, "%s: emitting %s (%d)\n", __FUNCTION__, name, size);
190 fprintf (of, "%s\tEQU\t0x%04x\n", name, addr);
193 /* we place each symbol into a section of its own to allow the linker
194 * to distribute the data into all available memory banks */
195 if (!section_type) section_type = "udata";
198 /* absolute symbols are handled in pic14_constructAbsMap */
201 /* workaround gpasm bug with symbols being EQUated and placed in absolute sections */
202 if (1 || !is_shared_address (addr))
204 if (globalize) fprintf (of, "\tglobal\t%s\n", name);
205 fprintf (of, "udata_%s_%u\t%s\t0x%04x\n", moduleName,
206 sec_idx++, "udata_ovr", addr);
207 fprintf (of, "%s\tres\t%d\n", name, size);
211 /* EQUs cannot be exported... */
212 fprintf (of, "%s\tEQU\t0x%04x\n", name, addr);
216 if (globalize) fprintf (of, "\tglobal\t%s\n", name);
217 fprintf (of, "udata_%s_%u\t%s\n", moduleName,
218 sec_idx++, section_type);
219 fprintf (of, "%s\tres\t%d\n", name, size);
223 //if (options.verbose) fprintf (stderr, "%s: emitted %s\n", __FUNCTION__, name);
224 addSet (&symbolsEmitted, (void *) name);
227 #define IS_DEFINED_HERE(sym) (!IS_EXTERN(sym->etype))
228 extern int IS_CONFIG_ADDRESS( int addr );
230 pic14_constructAbsMap (FILE *ofile)
232 memmap *maps[] = { data, sfr, NULL };
237 int addr, min=-1, max=-1;
240 int low, high, shared;
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 shared = pic14_getSharedStack(&low, &high, &size);
318 if (!pic14_options.isLibrarySource)
320 pic = pic14_getPIC();
322 fprintf (ofile, "\tglobal PSAVE\n");
323 fprintf (ofile, "\tglobal SSAVE\n");
324 fprintf (ofile, "\tglobal WSAVE\n");
325 for (i = size - 4; i >= 0; i--) {
326 fprintf (ofile, "\tglobal STK%02d\n", i);
329 // 16f84 has no SHAREBANK (in linkerscript) but memory aliased in two
332 // for single banked devices: use normal, "banked" RAM
333 fprintf (ofile, "sharebank udata_ovr 0x%04X\n", low);
335 // for devices with at least two banks, require a sharebank section
336 fprintf (ofile, "sharebank udata_shr\n");
338 fprintf (ofile, "PSAVE\tres 1\n");
339 fprintf (ofile, "SSAVE\tres 1\n");
340 fprintf (ofile, "WSAVE\tres 1\n"); // WSAVE *must* be in sharebank (IRQ handlers)
341 /* fill rest of sharebank with stack STKxx .. STK00 */
342 for (i = size - 4; i >= 0; i--) {
343 fprintf (ofile, "STK%02d\tres 1\n", i);
346 /* declare STKxx as extern for all files
347 * except the one containing main() */
348 fprintf (ofile, "\textern PSAVE\n");
349 fprintf (ofile, "\textern SSAVE\n");
350 fprintf (ofile, "\textern WSAVE\n");
351 for (i = size - 4; i >= 0; i--) {
353 SNPRINTF(&buffer[0], 127, "STK%02d", i);
354 fprintf (ofile, "\textern %s\n", &buffer[0]);
355 addSet (&symbolsEmitted, (void *) &buffer[0]);
360 /*-----------------------------------------------------------------*/
361 /* emitRegularMap - emit code for maps with no special cases */
362 /*-----------------------------------------------------------------*/
364 pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag)
369 /* print the area name */
371 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
373 for (sym = setFirstItem (map->syms); sym;
374 sym = setNextItem (map->syms)) {
376 //printf("%s\n",sym->name);
378 /* ignore if config word */
379 if (SPEC_ABSA(sym->etype)
380 && IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype)))
383 /* if extern then add it into the extern list */
384 if (IS_EXTERN (sym->etype)) {
385 addSetHead (&externs, sym);
389 /* if allocation required check is needed
390 then check if the symbol really requires
391 allocation only for local variables */
392 if (arFlag && !IS_AGGREGATE (sym->type) &&
393 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
394 !sym->allocreq && sym->level)
397 /* if global variable & not static or extern
398 and addPublics allowed then add it to the public set */
399 if ((sym->level == 0 ||
400 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
402 !IS_STATIC (sym->etype))
404 //fprintf( stderr, "%s: made public %s\n", __FUNCTION__, sym->name );
405 addSetHead (&publics, sym);
408 // PIC code allocates its own registers - so ignore parameter variable generated by processFuncArgs()
411 /* if extern then do nothing or is a function
413 if (IS_FUNC (sym->type))
416 /* print extra debug info if required */
417 if (options.debug || sym->level == 0)
419 if (!sym->level) /* global */
420 if (IS_STATIC (sym->etype))
421 fprintf (map->oFile, "F%s_", moduleName); /* scope is file */
423 fprintf (map->oFile, "G_"); /* scope is global */
425 /* symbol is local */
426 fprintf (map->oFile, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
427 fprintf (map->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
430 /* absolute symbols are handled in pic14_constructAbsMap */
431 if (SPEC_ABSA(sym->etype) && IS_DEFINED_HERE(sym))
434 /* if it has an absolute address then generate
435 an equate for this no need to allocate space */
436 if (0 && SPEC_ABSA (sym->etype))
438 //if (options.debug || sym->level == 0)
439 //fprintf (map->oFile,"; == 0x%04x\n",SPEC_ADDR (sym->etype));
441 fprintf (map->oFile, "%s\tEQU\t0x%04x\n",
443 SPEC_ADDR (sym->etype));
449 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
450 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
451 /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
452 if (IS_BITVAR (sym->etype))
458 emitSymbolToFile (map->oFile,
461 getSize (sym->type) & 0xffff,
462 SPEC_ABSA(sym->etype)
463 ? SPEC_ADDR(sym->etype)
471 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1)
473 for (i = 1; i < size; i++)
474 fprintf (map->oFile, "\t%s_%d\n", sym->rname, i);
479 //fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
482 /* if it has a initial value then do it only if
483 it is a global variable */
484 if (sym->ival && sym->level == 0) {
487 if (IS_AGGREGATE (sym->type))
488 ival = initAggregates (sym, sym->ival, NULL);
490 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
491 decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
492 codeOutFile = statsg->oFile;
494 eBBlockFromiCode (iCodeFromAst (ival));
501 /*-----------------------------------------------------------------*/
502 /* printIvalType - generates ival for int/char */
503 /*-----------------------------------------------------------------*/
505 printIvalType (symbol *sym, sym_link * type, initList * ilist, pBlock *pb)
510 //fprintf(stderr, "%s\n",__FUNCTION__);
512 /* if initList is deep */
513 if (ilist->type == INIT_DEEP)
514 ilist = ilist->init.deep;
516 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
517 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
520 if (!(val = list2val (ilist))) {
521 // assuming a warning has been thrown
525 if (val->type != type) {
526 val = valCastLiteral(type, floatFromVal(val));
530 ulval = (unsigned long) floatFromVal (val);
534 switch (getSize (type)) {
536 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
540 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
541 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
545 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
546 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
547 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
548 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
553 /*-----------------------------------------------------------------*/
554 /* printIvalBitFields - generate initializer for bitfields */
555 /*-----------------------------------------------------------------*/
556 static void printIvalBitFields(symbol **sym, initList **ilist, pBlock *pb )
560 initList *lilist = *ilist ;
561 unsigned long ival = 0;
567 val = list2val(lilist);
569 if (SPEC_BLEN(lsym->etype) > 8) {
570 size += ((SPEC_BLEN (lsym->etype) / 8) +
571 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
574 size = ((SPEC_BLEN (lsym->etype) / 8) +
575 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
577 i = (unsigned long)floatFromVal(val);
578 i <<= SPEC_BSTR (lsym->etype);
580 if (! ( lsym->next &&
581 (IS_BITFIELD(lsym->next->type)) &&
582 (SPEC_BSTR(lsym->next->etype)))) break;
584 lilist = lilist->next;
588 //tfprintf (oFile, "\t!db !constbyte\n",ival);
589 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
593 //tfprintf (oFile, "\t!dw !constword\n",ival);
594 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
595 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
598 //tfprintf (oFile, "\t!db !constword,!constword\n",(ival >> 8) & 0xffff, (ival & 0xffff));
599 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>24)));
600 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>16)));
601 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
602 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
609 /*-----------------------------------------------------------------*/
610 /* printIvalStruct - generates initial value for structures */
611 /*-----------------------------------------------------------------*/
612 static void printIvalStruct (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
615 initList *iloop = NULL;
617 sflds = SPEC_STRUCT (type)->fields;
620 if (ilist->type != INIT_DEEP) {
621 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
625 iloop = ilist->init.deep;
628 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
629 if (IS_BITFIELD(sflds->type)) {
630 printIvalBitFields(&sflds,&iloop,pb);
632 printIval (sym, sflds->type, iloop, pb);
636 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
641 /*-----------------------------------------------------------------*/
642 /* printIvalChar - generates initital value for character array */
643 /*-----------------------------------------------------------------*/
645 printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
653 //fprintf(stderr, "%s\n",__FUNCTION__);
657 val = list2val (ilist);
659 /* if the value is a character string */
660 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
662 ilen = DCL_ELEM(val->type);
664 if (!DCL_ELEM (type))
665 DCL_ELEM (type) = ilen;
667 /* emit string constant */
668 for (remain = 0; remain < ilen; remain++) {
669 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(SPEC_CVAL(val->etype).v_char[remain])));
672 /* fill array up to desired size */
673 if ((remain = (DCL_ELEM (type) - ilen)) > 0)
675 //tfprintf (oFile, "\t!db !constbyte\n", 0);
676 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
683 //printChar (oFile, s, strlen (s) + 1);
685 for(remain=0; remain<(int)strlen(s); remain++) {
686 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(s[remain])));
687 //fprintf(stderr,"0x%02x ",s[remain]);
689 //fprintf(stderr,"\n");
694 /*-----------------------------------------------------------------*/
695 /* printIvalArray - generates code for array initialization */
696 /*-----------------------------------------------------------------*/
698 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
707 /* take care of the special case */
708 /* array of characters can be init */
710 if (IS_CHAR (type->next)) {
711 //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
712 if (!IS_LITERAL(list2val(ilist)->etype)) {
713 werror (W_INIT_WRONG);
716 if (printIvalChar (type,
717 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
718 pb, SPEC_CVAL (sym->etype).v_char))
721 /* not the special case */
722 if (ilist->type != INIT_DEEP) {
723 werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
727 for (iloop=ilist->init.deep; iloop; iloop=iloop->next) {
728 if ((++size > DCL_ELEM(type)) && DCL_ELEM(type)) {
729 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
732 printIval (sym, type->next, iloop, pb);
736 if (DCL_ELEM(type)) {
737 // pad with zeros if needed
738 if (size<DCL_ELEM(type)) {
739 size = (DCL_ELEM(type) - size) * getSize(type->next);
741 //tfprintf (oFile, "\t!db !constbyte\n", 0);
742 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
746 // we have not been given a size, but we now know it
747 DCL_ELEM (type) = size;
753 /*-----------------------------------------------------------------*/
754 /* printIvalPtr - generates code for initial value of pointers */
755 /*-----------------------------------------------------------------*/
756 extern value *initPointer (initList *, sym_link *toType);
759 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
766 fprintf (stderr, "FIXME: initializers for pointers...\n");
767 printTypeChain (type, stderr);
769 fprintf (stderr, "symbol: %s, DCL_TYPE():%d, DCL_ELEM():%d, IS_ARRAY():%d", sym->rname, DCL_TYPE(type), DCL_ELEM(type), IS_ARRAY(type));
770 fprintf (stderr, "ilist: type=%d (INIT_DEEP=%d, INIT_NODE=%d)\n", ilist->type, INIT_DEEP, INIT_NODE);
772 if (ilist && (ilist->type == INIT_DEEP))
773 ilist = ilist->init.deep;
775 /* function pointers */
776 if (IS_FUNC (type->next))
778 assert ( !"function pointers not yet handled" );
779 //printIvalFuncPtr (type, ilist, pb);
782 if (!(val = initPointer (ilist, type)))
785 if (IS_CHAR (type->next))
787 if (printIvalChar (type, ilist, pb, NULL)) return;
791 if (compareType (type, val->type) == 0)
793 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
794 printFromToType (val->type, type);
797 if (IS_LITERAL (val->etype))
799 switch (getSize (type))
802 fprintf (stderr, "BYTE: %i\n", (unsigned char)floatFromVal (val) & 0x00FF);
805 fprintf (stderr, "WORD: %i\n", (unsigned int)floatFromVal (val) & 0x00FFFF);
807 case 3: /* gneric pointers */
808 assert ( !"generic pointers not yet handled" );
810 fprintf (stderr, "LONG: %i\n", (unsigned int)floatFromVal (val) & 0x0000FFFFFFFF);
813 assert ( !"invaild size of value -- aborting" );
819 /* now handle symbolic values */
820 switch (getSize (type))
823 fprintf (stderr, "BYTE: %s", val->name);
826 fprintf (stderr, "WORD: %s", val->name);
829 fprintf (stderr, "LONG: %s", val->name);
832 assert ( !"invalid size of (symbolic) value -- aborting" );
836 /*-----------------------------------------------------------------*/
837 /* printIval - generates code for initial value */
838 /*-----------------------------------------------------------------*/
840 printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
845 /* if structure then */
846 if (IS_STRUCT (type))
848 //fprintf(stderr,"%s struct: %s\n",__FUNCTION__, sym->rname);
849 printIvalStruct (sym, type, ilist, pb);
853 /* if this is an array */
856 //fprintf(stderr,"%s array: %s\n",__FUNCTION__, sym->rname);
857 printIvalArray (sym, type, ilist, pb);
861 /* if this is a pointer */
864 //fprintf(stderr,"%s pointer: %s\n",__FUNCTION__, sym->rname);
865 printIvalPtr (sym, type, ilist, pb);
869 /* if type is SPECIFIER */
872 //fprintf(stderr,"%s spec %s\n",__FUNCTION__, sym->rname);
873 printIvalType (sym, type, ilist, pb);
878 extern void pCodeConstString(char *name, char *value);
879 /*-----------------------------------------------------------------*/
880 /* emitStaticSeg - emitcode for the static segment */
881 /*-----------------------------------------------------------------*/
883 pic14emitStaticSeg (memmap * map)
887 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
889 //fprintf(stderr, "%s\n",__FUNCTION__);
891 /* for all variables in this segment do */
892 for (sym = setFirstItem (map->syms); sym;
893 sym = setNextItem (map->syms))
895 /* if extern then add it into the extern list */
896 if (IS_EXTERN (sym->etype)) {
897 addSetHead (&externs, sym);
901 /* if it is not static add it to the public
903 if (!IS_STATIC (sym->etype))
904 addSetHead (&publics, sym);
906 /* print extra debug info if required */
907 if (options.debug || sym->level == 0)
911 if (IS_STATIC (sym->etype))
912 fprintf (code->oFile, "F%s_", moduleName); /* scope is file */
914 fprintf (code->oFile, "G_"); /* scope is global */
917 /* symbol is local */
918 fprintf (code->oFile, "L%s_",
919 (sym->localof ? sym->localof->name : "-null-"));
920 fprintf (code->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
924 /* if it has an absolute address */
925 if (SPEC_ABSA (sym->etype))
927 if (options.debug || sym->level == 0)
928 fprintf (code->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
930 fprintf (code->oFile, "%s\t=\t0x%04x\n",
932 SPEC_ADDR (sym->etype));
936 if (options.debug || sym->level == 0)
937 fprintf (code->oFile, " == .\n");
939 /* if it has an initial value */
944 fprintf (code->oFile, "%s:\n", sym->rname);
946 resolveIvalSym (sym->ival, sym->type);
947 //printIval (sym, sym->type, sym->ival, code->oFile);
948 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block for Ival"));
950 addpCode2pBlock(pb,newpCodeLabel(sym->rname,-1));
952 printIval (sym, sym->type, sym->ival, pb);
959 fprintf (code->oFile, "%s:\n", sym->rname);
960 /* special case for character strings */
961 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
962 SPEC_CVAL (sym->etype).v_char)
963 pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
964 /*printChar (code->oFile,
965 SPEC_CVAL (sym->etype).v_char,
966 strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
968 fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
976 /*-----------------------------------------------------------------*/
977 /* emitMaps - emits the code for the data portion the code */
978 /*-----------------------------------------------------------------*/
982 pic14_constructAbsMap (sfr->oFile);
983 /* no special considerations for the following
984 data, idata & bit & xdata */
985 pic14emitRegularMap (data, TRUE, TRUE);
986 pic14emitRegularMap (idata, TRUE, TRUE);
987 pic14emitRegularMap (bit, TRUE, FALSE);
988 pic14emitRegularMap (xdata, TRUE, TRUE);
989 pic14emitRegularMap (sfr, TRUE, FALSE);
990 pic14emitRegularMap (sfrbit, FALSE, FALSE);
991 pic14emitRegularMap (code, TRUE, FALSE);
992 pic14emitStaticSeg (statsg);
993 pic14emitStaticSeg (c_abs);
996 /*-----------------------------------------------------------------*/
997 /* createInterruptVect - creates the interrupt vector */
998 /*-----------------------------------------------------------------*/
1000 pic14createInterruptVect (FILE * vFile)
1002 mainf = newSymbol ("main", 0);
1005 /* only if the main function exists */
1006 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
1008 struct options *op = &options;
1009 if (!(op->cc_only || noAssemble))
1010 // werror (E_NO_MAIN);
1011 fprintf(stderr,"WARNING: function 'main' undefined\n");
1015 /* if the main is only a prototype ie. no body then do nothing */
1016 if (!IFFUNC_HASBODY(mainf->type))
1018 /* if ! compile only then main function should be present */
1019 if (!(options.cc_only || noAssemble))
1020 // werror (E_NO_MAIN);
1021 fprintf(stderr,"WARNING: function 'main' undefined\n");
1025 fprintf (vFile, "%s", iComments2);
1026 fprintf (vFile, "; reset vector \n");
1027 fprintf (vFile, "%s", iComments2);
1028 fprintf (vFile, "STARTUP\t%s\n", CODE_NAME); // Lkr file should place section STARTUP at address 0x0
1029 fprintf (vFile, "\tnop\n"); /* first location for used by incircuit debugger */
1030 fprintf( vFile, "\tpagesel __sdcc_gsinit_startup\n");
1031 fprintf (vFile, "\tgoto\t__sdcc_gsinit_startup\n");
1035 /*-----------------------------------------------------------------*/
1036 /* initialComments - puts in some initial comments */
1037 /*-----------------------------------------------------------------*/
1039 pic14initialComments (FILE * afile)
1041 initialComments (afile);
1042 fprintf (afile, "; PIC port for the 14-bit core\n");
1043 fprintf (afile, iComments2);
1048 pic14_stringInSet(const char *str, set **world, int autoAdd)
1055 for (s = setFirstItem(*world); s; s = setNextItem(*world))
1058 if (0 == strcmp(s, str)) return 1;
1062 if (autoAdd) addSet(world, Safe_strdup(str));
1067 pic14_emitSymbolIfNew(FILE *file, const char *fmt, const char *sym, int checkLocals)
1069 static set *emitted = NULL;
1071 if (!pic14_stringInSet(sym, &emitted, 1)) {
1072 /* sym was not in emittedSymbols */
1073 if (!checkLocals || !pic14_stringInSet(sym, &pic14_localFunctions, 0)) {
1074 /* sym is not a locally defined function---avoid bug #1443651 */
1075 fprintf( file, fmt, sym );
1082 /*-----------------------------------------------------------------*/
1083 /* printExterns - generates extern for external variables */
1084 /*-----------------------------------------------------------------*/
1086 pic14printExterns (FILE * afile)
1090 fprintf (afile, "%s", iComments2);
1091 fprintf (afile, "; extern variables in this module\n");
1092 fprintf (afile, "%s", iComments2);
1094 for (sym = setFirstItem (externs); sym; sym = setNextItem (externs))
1095 pic14_emitSymbolIfNew(afile, "\textern %s\n", sym->rname, 1);
1098 /*-----------------------------------------------------------------*/
1099 /* printPublics - generates .global for publics */
1100 /*-----------------------------------------------------------------*/
1102 pic14printPublics (FILE * afile)
1106 fprintf (afile, "%s", iComments2);
1107 fprintf (afile, "; publics variables in this module\n");
1108 fprintf (afile, "%s", iComments2);
1110 for (sym = setFirstItem (publics); sym;
1111 sym = setNextItem (publics)) {
1113 if(!IS_BITFIELD(sym->type) && ((IS_FUNC(sym->type) || sym->allocreq))) {
1114 if (!IS_BITVAR(sym->type))
1115 pic14_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1117 /* Absolute variables are defines in the asm file as equates and thus can not be made global. */
1118 /* Not any longer! */
1119 //if (!SPEC_ABSA (sym->etype))
1120 pic14_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1125 /*-----------------------------------------------------------------*/
1126 /* emitOverlay - will emit code for the overlay stuff */
1127 /*-----------------------------------------------------------------*/
1129 pic14emitOverlay (FILE * afile)
1133 /* if (!elementsInSet (ovrSetSets))*/
1135 /* the hack below, fixes translates for devices which
1136 * only have udata_shr memory */
1137 fprintf (afile, "%s\t%s\n",
1138 (elementsInSet(ovrSetSets)?"":";"),
1139 port->mem.overlay_name);
1141 /* for each of the sets in the overlay segment do */
1142 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1143 ovrset = setNextItem (ovrSetSets))
1148 if (elementsInSet (ovrset))
1150 /* this dummy area is used to fool the assembler
1151 otherwise the assembler will append each of these
1152 declarations into one chunk and will not overlay
1155 /* I don't think this applies to us. We are using gpasm. CRF */
1157 fprintf (afile, ";\t.area _DUMMY\n");
1158 /* output the area informtion */
1159 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1162 for (sym = setFirstItem (ovrset); sym;
1163 sym = setNextItem (ovrset))
1166 /* if extern then do nothing */
1167 if (IS_EXTERN (sym->etype))
1170 /* if allocation required check is needed
1171 then check if the symbol really requires
1172 allocation only for local variables */
1173 if (!IS_AGGREGATE (sym->type) &&
1174 !(sym->_isparm && !IS_REGPARM (sym->etype))
1175 && !sym->allocreq && sym->level)
1178 /* if global variable & not static or extern
1179 and addPublics allowed then add it to the public set */
1180 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1181 && !IS_STATIC (sym->etype))
1182 addSetHead (&publics, sym);
1184 /* if extern then do nothing or is a function
1186 if (IS_FUNC (sym->type))
1189 /* print extra debug info if required */
1190 if (options.debug || sym->level == 0)
1194 if (IS_STATIC (sym->etype))
1195 fprintf (afile, "F%s_", moduleName); /* scope is file */
1197 fprintf (afile, "G_"); /* scope is global */
1200 /* symbol is local */
1201 fprintf (afile, "L%s_",
1202 (sym->localof ? sym->localof->name : "-null-"));
1203 fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
1206 /* if is has an absolute address then generate
1207 an equate for this no need to allocate space */
1208 if (SPEC_ABSA (sym->etype))
1211 if (options.debug || sym->level == 0)
1212 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1214 fprintf (afile, "%s\t=\t0x%04x\n",
1216 SPEC_ADDR (sym->etype));
1220 if (options.debug || sym->level == 0)
1221 fprintf (afile, "==.\n");
1223 /* allocate space */
1224 fprintf (afile, "%s:\n", sym->rname);
1225 fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1234 pic14_emitInterruptHandler (FILE * asmFile)
1236 if (pic14_hasInterrupt)
1239 fprintf (asmFile, "%s", iComments2);
1240 fprintf (asmFile, "; interrupt and initialization code\n");
1241 fprintf (asmFile, "%s", iComments2);
1242 // Note - for mplink may have to enlarge section vectors in .lnk file
1243 // Note: Do NOT name this code_interrupt to avoid nameclashes with
1244 // source files's code segment (interrupt.c -> code_interrupt)
1245 fprintf (asmFile, "c_interrupt\t%s\t0x4\n", CODE_NAME);
1247 /* interrupt service routine */
1248 fprintf (asmFile, "__sdcc_interrupt\n");
1249 copypCode(asmFile, 'I');
1253 /*-----------------------------------------------------------------*/
1254 /* glue - the final glue that hold the whole thing together */
1255 /*-----------------------------------------------------------------*/
1259 char udata_name[80];
1262 FILE *ovrFile = tempfile();
1264 addSetHead(&tmpfileSet,ovrFile);
1265 pCodeInitRegisters();
1267 /* check for main() */
1268 mainf = newSymbol ("main", 0);
1270 mainf = findSymWithLevel (SymbolTab, mainf);
1272 if (!mainf || !IFFUNC_HASBODY(mainf->type))
1274 /* main missing -- import stack from main module */
1275 //fprintf (stderr, "main() missing -- assuming we are NOT the main module\n");
1276 pic14_options.isLibrarySource = 1;
1280 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1282 pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
1285 /* entry point @ start of CSEG */
1286 addpCode2pBlock(pb,newpCodeLabel("__sdcc_program_startup",-1));
1287 /* put in the call to main */
1288 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp("_main",PO_STR)));
1290 if (options.mainreturn) {
1292 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will return to caller\n"));
1293 addpCode2pBlock(pb,newpCode(POC_RETURN,NULL));
1297 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will lock up\n"));
1298 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("$",PO_STR)));
1304 /* At this point we've got all the code in the form of pCode structures */
1305 /* Now it needs to be rearranged into the order it should be placed in the */
1308 movepBlock2Head('P'); // Last
1309 movepBlock2Head(code->dbName);
1310 movepBlock2Head('X');
1311 movepBlock2Head(statsg->dbName); // First
1314 /* print the global struct definitions */
1320 addSetHead(&tmpfileSet,vFile);
1322 /* emit code for the all the variables declared */
1324 /* do the overlay segments */
1325 pic14emitOverlay(ovrFile);
1327 /* PENDING: this isnt the best place but it will do */
1328 if (port->general.glue_up_main) {
1329 /* create the interrupt vector table */
1330 pic14createInterruptVect (vFile);
1335 ReuseReg(); // ReuseReg where call tree permits
1344 /* now put it all together into the assembler file */
1345 /* create the assembler file name */
1347 if ((noAssemble || options.c1mode) && fullDstFileName)
1349 sprintf (buffer, fullDstFileName);
1353 sprintf (buffer, dstFileName);
1354 strcat (buffer, ".asm");
1357 if (!(asmFile = fopen (buffer, "w"))) {
1358 werror (E_FILE_OPEN_ERR, buffer);
1362 /* prepare statistics */
1363 resetpCodeStatistics ();
1365 /* initial comments */
1366 pic14initialComments (asmFile);
1368 /* print module name */
1369 fprintf (asmFile, ";\t.module %s\n", moduleName);
1371 /* Let the port generate any global directives, etc. */
1372 if (port->genAssemblerPreamble)
1374 port->genAssemblerPreamble(asmFile);
1377 /* Emit the __config directive */
1378 pic14_emitConfigWord (asmFile);
1380 /* print the global variables in this module */
1381 pic14printPublics (asmFile);
1383 /* print the extern variables in this module */
1384 pic14printExterns (asmFile);
1386 /* copy the sfr segment */
1387 fprintf (asmFile, "%s", iComments2);
1388 fprintf (asmFile, "; special function registers\n");
1389 fprintf (asmFile, "%s", iComments2);
1390 copyFile (asmFile, sfr->oFile);
1393 if (udata_section_name) {
1394 sprintf(udata_name,"%s",udata_section_name);
1396 sprintf(udata_name,"data_%s",moduleName);
1398 fprintf (asmFile, "%s", iComments2);
1399 fprintf (asmFile, "; udata\n");
1400 fprintf (asmFile, "%s", iComments2);
1401 fprintf (asmFile, "%s\tudata\n", udata_name);
1402 copyFile (asmFile, data->oFile);
1404 /* Put all variables into a cblock */
1406 writeUsedRegs(asmFile);
1408 /* create the overlay segments */
1409 fprintf (asmFile, "%s", iComments2);
1410 fprintf (asmFile, "; overlayable items in internal ram \n");
1411 fprintf (asmFile, "%s", iComments2);
1412 copyFile (asmFile, ovrFile);
1416 /* create the stack segment MOF */
1417 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1418 fprintf (asmFile, "%s", iComments2);
1419 fprintf (asmFile, "; Stack segment in internal ram \n");
1420 fprintf (asmFile, "%s", iComments2);
1421 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1422 ";__start__stack:\n;\t.ds\t1\n\n");
1425 /* create the idata segment */
1426 fprintf (asmFile, "%s", iComments2);
1427 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1428 fprintf (asmFile, "%s", iComments2);
1429 copyFile (asmFile, idata->oFile);
1431 /* if external stack then reserve space of it */
1432 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1433 fprintf (asmFile, "%s", iComments2);
1434 fprintf (asmFile, "; external stack \n");
1435 fprintf (asmFile, "%s", iComments2);
1436 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1437 fprintf (asmFile,";\t.ds 256\n");
1440 /* copy xtern ram data */
1441 fprintf (asmFile, "%s", iComments2);
1442 fprintf (asmFile, "; external ram data\n");
1443 fprintf (asmFile, "%s", iComments2);
1444 copyFile (asmFile, xdata->oFile);
1448 /* copy the bit segment */
1449 fprintf (asmFile, "%s", iComments2);
1450 fprintf (asmFile, "; bit data\n");
1451 fprintf (asmFile, "%s", iComments2);
1452 copyFile (asmFile, bit->oFile);
1454 /* copy the interrupt vector table */
1455 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1456 copyFile (asmFile, vFile);
1459 /* create interupt ventor handler */
1460 pic14_emitInterruptHandler (asmFile);
1462 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1463 /* initialize data memory */
1464 fprintf (asmFile, "code_init\t%s\n", CODE_NAME); // Note - for mplink may have to enlarge section vectors in .lnk file
1465 fprintf (asmFile,"__sdcc_gsinit_startup\n");
1466 /* FIXME: This is temporary. The idata section should be used. If
1467 not, we could add a special feature to the linker. This will
1468 work in the mean time. Put all initalized data in main.c */
1469 copypCode(asmFile, statsg->dbName);
1470 fprintf (asmFile,"\tpagesel _main\n");
1471 fprintf (asmFile,"\tgoto _main\n");
1476 /* copy global & static initialisations */
1477 fprintf (asmFile, "%s", iComments2);
1478 fprintf (asmFile, "; global & static initialisations\n");
1479 fprintf (asmFile, "%s", iComments2);
1480 copypCode(asmFile, statsg->dbName);
1484 /* copy over code */
1485 fprintf (asmFile, "%s", iComments2);
1486 fprintf (asmFile, "; code\n");
1487 fprintf (asmFile, "%s", iComments2);
1488 fprintf (asmFile, "code_%s\t%s\n", moduleName, port->mem.code_name);
1491 copypCode(asmFile, 'X');
1493 /* _main function */
1494 copypCode(asmFile, 'M');
1496 /* other functions */
1497 copypCode(asmFile, code->dbName);
1500 copypCode(asmFile, 'P');
1502 dumppCodeStatistics (asmFile);
1504 fprintf (asmFile,"\tend\n");