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);
59 extern DEFSETFUNC (closeTmpFiles);
60 extern DEFSETFUNC (rmTmpFiles);
62 extern void AnalyzeBanking (void);
63 extern void copyFile (FILE * dest, FILE * src);
64 extern void ReuseReg(void);
65 extern void InlinepCode(void);
66 extern void writeUsedRegs(FILE *);
68 extern void initialComments (FILE * afile);
69 extern void printPublics (FILE * afile);
71 extern void printChar (FILE * ofile, char *s, int plen);
72 void pCodeInitRegisters(void);
73 int getConfigWord(int address);
74 int getHasSecondConfigReg(void);
75 int pic14_getSharebankSize(void);
76 int pic14_getSharebankAddress(void);
78 char *udata_section_name=0; // FIXME Temporary fix to change udata section name -- VR
79 int pic14_hasInterrupt = 0; // Indicates whether to emit interrupt handler or not
81 /*-----------------------------------------------------------------*/
82 /* aopLiteral - string from a literal value */
83 /*-----------------------------------------------------------------*/
84 int pic14aopLiteral (value *val, int offset)
91 /* if it is a float then it gets tricky */
92 /* otherwise it is fairly simple */
93 if (!IS_FLOAT(val->type)) {
94 unsigned long v = (unsigned long) floatFromVal(val);
96 return ( (v >> (offset * 8)) & 0xff);
99 /* it is type float */
100 fl.f = (float) floatFromVal(val);
101 #ifdef WORDS_BIGENDIAN
102 return fl.c[3-offset];
109 /* Check whether the given reg is shared amongst all .o files of a project.
110 * This is true for the pseudo stack and WSAVE, SSAVE and PSAVE. */
112 is_shared_address (int addr)
114 return ((addr > Gstack_base_addr - 18)
115 && (addr <= Gstack_base_addr));
119 pic14_is_shared (regs *reg)
122 return is_shared_address (reg->address);
126 is_valid_identifier( const char *name )
132 /* only accept [a-zA-Z_][a-zA-Z0-9_] */
133 if (!((a >= 'a' && a <= 'z')
134 || (a >= 'A' && a <= 'z')
139 while ((a = *name++))
141 if (!((a >= 'a' && a <= 'z')
142 || (a >= 'A' && a <= 'Z')
143 || (a >= '0' && a <= '9')
148 /* valid identifier */
152 /* set of already emitted symbols; we store only pointers to the emitted
153 * symbol names so these MUST NO BE CHANGED afterwards... */
154 static set *symbolsEmitted = NULL;
156 /*-------------------------------------------------------------------*/
157 /* emitSymbolToFile - write a symbol definition only if it is not */
158 /* already present */
159 /*-------------------------------------------------------------------*/
161 emitSymbolToFile (FILE *of, const char *name, const char *section_type, int size, int addr, int useEQU, int globalize)
164 static unsigned int sec_idx = 0;
166 /* workaround: variables declared via `sbit' result in a numeric
167 * identifier (0xHH), EQU'ing them is invalid, so just ignore it.
168 * sbit is heavily used in the inc2h-generated header files!
170 if (!is_valid_identifier(name))
172 //fprintf( stderr, "%s:%s:%u: ignored symbol: %s\n", __FILE__, __FUNCTION__, __LINE__, name );
176 /* check whether the symbol is already defined */
177 for (sym = (const char *) setFirstItem (symbolsEmitted);
179 sym = (const char *) setNextItem (symbolsEmitted))
181 if (!strcmp (sym, name))
183 //fprintf (stderr, "%s: already emitted: %s\n", __FUNCTION__, name);
188 /* new symbol -- define it */
189 //fprintf (stderr, "%s: emitting %s (%d)\n", __FUNCTION__, name, size);
191 fprintf (of, "%s\tEQU\t0x%04x\n", name, addr);
194 /* we place each symbol into a section of its own to allow the linker
195 * to distribute the data into all available memory banks */
196 if (!section_type) section_type = "udata";
199 /* absolute symbols are handled in pic14_constructAbsMap */
202 /* workaround gpasm bug with symbols being EQUated and placed in absolute sections */
203 if (1 || !is_shared_address (addr))
205 if (globalize) fprintf (of, "\tglobal\t%s\n", name);
206 fprintf (of, "udata_%s_%u\t%s\t0x%04x\n", moduleName,
207 sec_idx++, "udata_ovr", addr);
208 fprintf (of, "%s\tres\t%d\n", name, size);
212 /* EQUs cannot be exported... */
213 fprintf (of, "%s\tEQU\t0x%04x\n", name, addr);
217 if (globalize) fprintf (of, "\tglobal\t%s\n", name);
218 fprintf (of, "udata_%s_%u\t%s\n", moduleName,
219 sec_idx++, section_type);
220 fprintf (of, "%s\tres\t%d\n", name, size);
224 //if (options.verbose) fprintf (stderr, "%s: emitted %s\n", __FUNCTION__, name);
225 addSet (&symbolsEmitted, (void *) name);
228 #define IS_DEFINED_HERE(sym) (!IS_EXTERN(sym->etype))
229 extern int IS_CONFIG_ADDRESS( int addr );
231 pic14_constructAbsMap (FILE *ofile)
233 memmap *maps[] = { data, sfr, NULL };
238 int addr, min=-1, max=-1;
241 for (i=0; maps[i] != NULL; i++)
243 for (sym = (symbol *)setFirstItem (maps[i]->syms);
244 sym; sym = setNextItem (maps[i]->syms))
246 if (IS_DEFINED_HERE(sym) && SPEC_ABSA(sym->etype))
248 addr = SPEC_ADDR(sym->etype);
250 /* handle CONFIG words here */
251 if (IS_CONFIG_ADDRESS( addr ))
253 //fprintf( stderr, "%s: assignment to CONFIG@0x%x found\n", __FUNCTION__, addr );
254 //fprintf( stderr, "ival: %p (0x%x)\n", sym->ival, (int)list2int( sym->ival ) );
256 pic14_assignConfigWordValue( addr, (int)list2int( sym->ival ) );
258 fprintf( stderr, "ERROR: Symbol %s, which is covering a __CONFIG word must be initialized!\n", sym->name );
263 if (max == -1 || addr > max) max = addr;
264 if (min == -1 || addr < min) min = addr;
265 //fprintf (stderr, "%s: sym %s @ 0x%x\n", __FUNCTION__, sym->name, addr);
266 aliases = hTabItemWithKey (ht, addr);
268 /* May not use addSetHead, as we cannot update the
269 * list's head in the hastable `ht'. */
270 addSet (&aliases, sym);
272 fprintf( stderr, "%s: now %d aliases for %s @ 0x%x\n",
273 __FUNCTION__, elementsInSet(aliases), sym->name, addr);
276 addSet (&aliases, sym);
277 hTabAddItem (&ht, addr, aliases);
283 /* now emit definitions for all absolute symbols */
284 fprintf (ofile, "%s", iComments2);
285 fprintf (ofile, "; absolute symbol definitions\n");
286 fprintf (ofile, "%s", iComments2);
287 for (addr=min; addr <= max; addr++)
290 aliases = hTabItemWithKey (ht, addr);
291 if (aliases && elementsInSet(aliases)) {
292 fprintf (ofile, "udata_abs_%s_%x\tudata_ovr\t0x%04x",
293 moduleName, addr, addr);
294 for (sym = setFirstItem (aliases); sym;
295 sym = setNextItem (aliases))
297 /* emit STATUS as well as _STATUS, required for SFRs only */
298 fprintf (ofile, "\n%s", sym->name);
299 fprintf (ofile, "\n%s", sym->rname);
300 if (getSize(sym->type) > size) {
301 size = getSize(sym->type);
304 fprintf (ofile, "\tres\t%d\n", size);
308 /* also emit STK symbols
309 * XXX: This is ugly and fails as soon as devices start to get
310 * differently sized sharebanks, since STK12 will be
311 * required by larger devices but only up to STK03 might
312 * be defined using smaller devices. */
313 fprintf (ofile, "\n");
314 if (!pic14_options.isLibrarySource)
316 fprintf (ofile, "\tglobal PSAVE\n");
317 fprintf (ofile, "\tglobal SSAVE\n");
318 fprintf (ofile, "\tglobal WSAVE\n");
319 for (i=pic14_getSharebankSize()-4; i >= 0; i--) {
320 fprintf (ofile, "\tglobal STK%02d\n", i);
322 fprintf (ofile, "sharebank udata_ovr 0x%04x\n",
323 pic14_getSharebankAddress() - pic14_getSharebankSize() + 1);
324 fprintf (ofile, "PSAVE\tres 1\n");
325 fprintf (ofile, "SSAVE\tres 1\n");
326 fprintf (ofile, "WSAVE\tres 1\n");
327 /* fill rest of sharebank with stack STKxx .. STK00 */
328 for (i=pic14_getSharebankSize()-4; i >= 0; i--) {
329 fprintf (ofile, "STK%02d\tres 1\n", i);
332 /* declare STKxx as extern for all files
333 * except the one containing main() */
334 fprintf (ofile, "\textern PSAVE\n");
335 fprintf (ofile, "\textern SSAVE\n");
336 fprintf (ofile, "\textern WSAVE\n");
337 for (i=pic14_getSharebankSize()-4; i >= 0; i--) {
338 fprintf (ofile, "\textern STK%02d\n", i);
343 /*-----------------------------------------------------------------*/
344 /* emitRegularMap - emit code for maps with no special cases */
345 /*-----------------------------------------------------------------*/
347 pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag)
352 /* print the area name */
354 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
356 for (sym = setFirstItem (map->syms); sym;
357 sym = setNextItem (map->syms)) {
359 //printf("%s\n",sym->name);
361 /* ignore if config word */
362 if (SPEC_ABSA(sym->etype)
363 && IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype)))
366 /* if extern then add it into the extern list */
367 if (IS_EXTERN (sym->etype)) {
368 addSetHead (&externs, sym);
372 /* if allocation required check is needed
373 then check if the symbol really requires
374 allocation only for local variables */
375 if (arFlag && !IS_AGGREGATE (sym->type) &&
376 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
377 !sym->allocreq && sym->level)
380 /* if global variable & not static or extern
381 and addPublics allowed then add it to the public set */
382 if ((sym->level == 0 ||
383 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
385 !IS_STATIC (sym->etype))
387 //fprintf( stderr, "%s: made public %s\n", __FUNCTION__, sym->name );
388 addSetHead (&publics, sym);
391 // PIC code allocates its own registers - so ignore parameter variable generated by processFuncArgs()
394 /* if extern then do nothing or is a function
396 if (IS_FUNC (sym->type))
399 /* print extra debug info if required */
400 if (options.debug || sym->level == 0)
402 if (!sym->level) /* global */
403 if (IS_STATIC (sym->etype))
404 fprintf (map->oFile, "F%s_", moduleName); /* scope is file */
406 fprintf (map->oFile, "G_"); /* scope is global */
408 /* symbol is local */
409 fprintf (map->oFile, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
410 fprintf (map->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
413 /* absolute symbols are handled in pic14_constructAbsMap */
414 if (SPEC_ABSA(sym->etype) && IS_DEFINED_HERE(sym))
417 /* if it has an absolute address then generate
418 an equate for this no need to allocate space */
419 if (0 && SPEC_ABSA (sym->etype))
421 //if (options.debug || sym->level == 0)
422 //fprintf (map->oFile,"; == 0x%04x\n",SPEC_ADDR (sym->etype));
424 fprintf (map->oFile, "%s\tEQU\t0x%04x\n",
426 SPEC_ADDR (sym->etype));
432 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
433 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
434 /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
435 if (IS_BITVAR (sym->etype))
441 emitSymbolToFile (map->oFile,
444 getSize (sym->type) & 0xffff,
445 SPEC_ABSA(sym->etype)
446 ? SPEC_ADDR(sym->etype)
454 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1)
456 for (i = 1; i < size; i++)
457 fprintf (map->oFile, "\t%s_%d\n", sym->rname, i);
462 //fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
465 /* if it has a initial value then do it only if
466 it is a global variable */
467 if (sym->ival && sym->level == 0) {
470 if (IS_AGGREGATE (sym->type))
471 ival = initAggregates (sym, sym->ival, NULL);
473 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
474 decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
475 codeOutFile = statsg->oFile;
477 eBBlockFromiCode (iCodeFromAst (ival));
484 /*-----------------------------------------------------------------*/
485 /* printIvalType - generates ival for int/char */
486 /*-----------------------------------------------------------------*/
488 printIvalType (symbol *sym, sym_link * type, initList * ilist, pBlock *pb)
493 //fprintf(stderr, "%s\n",__FUNCTION__);
495 /* if initList is deep */
496 if (ilist->type == INIT_DEEP)
497 ilist = ilist->init.deep;
499 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
500 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
503 if (!(val = list2val (ilist))) {
504 // assuming a warning has been thrown
508 if (val->type != type) {
509 val = valCastLiteral(type, floatFromVal(val));
513 ulval = (unsigned long) floatFromVal (val);
517 switch (getSize (type)) {
519 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
523 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
524 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
528 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
529 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
530 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
531 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
536 /*-----------------------------------------------------------------*/
537 /* printIvalBitFields - generate initializer for bitfields */
538 /*-----------------------------------------------------------------*/
539 static void printIvalBitFields(symbol **sym, initList **ilist, pBlock *pb )
543 initList *lilist = *ilist ;
544 unsigned long ival = 0;
550 val = list2val(lilist);
552 if (SPEC_BLEN(lsym->etype) > 8) {
553 size += ((SPEC_BLEN (lsym->etype) / 8) +
554 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
557 size = ((SPEC_BLEN (lsym->etype) / 8) +
558 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
560 i = (unsigned long)floatFromVal(val);
561 i <<= SPEC_BSTR (lsym->etype);
563 if (! ( lsym->next &&
564 (IS_BITFIELD(lsym->next->type)) &&
565 (SPEC_BSTR(lsym->next->etype)))) break;
567 lilist = lilist->next;
571 //tfprintf (oFile, "\t!db !constbyte\n",ival);
572 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
576 //tfprintf (oFile, "\t!dw !constword\n",ival);
577 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
578 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
581 //tfprintf (oFile, "\t!db !constword,!constword\n",(ival >> 8) & 0xffff, (ival & 0xffff));
582 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>24)));
583 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>16)));
584 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
585 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
592 /*-----------------------------------------------------------------*/
593 /* printIvalStruct - generates initial value for structures */
594 /*-----------------------------------------------------------------*/
595 static void printIvalStruct (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
598 initList *iloop = NULL;
600 sflds = SPEC_STRUCT (type)->fields;
603 if (ilist->type != INIT_DEEP) {
604 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
608 iloop = ilist->init.deep;
611 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
612 if (IS_BITFIELD(sflds->type)) {
613 printIvalBitFields(&sflds,&iloop,pb);
615 printIval (sym, sflds->type, iloop, pb);
619 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
624 /*-----------------------------------------------------------------*/
625 /* printIvalChar - generates initital value for character array */
626 /*-----------------------------------------------------------------*/
628 printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
636 //fprintf(stderr, "%s\n",__FUNCTION__);
640 val = list2val (ilist);
642 /* if the value is a character string */
643 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
645 ilen = DCL_ELEM(val->type);
647 if (!DCL_ELEM (type))
648 DCL_ELEM (type) = ilen;
650 /* emit string constant */
651 for (remain = 0; remain < ilen; remain++) {
652 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(SPEC_CVAL(val->etype).v_char[remain])));
655 /* fill array up to desired size */
656 if ((remain = (DCL_ELEM (type) - ilen)) > 0)
658 //tfprintf (oFile, "\t!db !constbyte\n", 0);
659 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
666 //printChar (oFile, s, strlen (s) + 1);
668 for(remain=0; remain<(int)strlen(s); remain++) {
669 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(s[remain])));
670 //fprintf(stderr,"0x%02x ",s[remain]);
672 //fprintf(stderr,"\n");
677 /*-----------------------------------------------------------------*/
678 /* printIvalArray - generates code for array initialization */
679 /*-----------------------------------------------------------------*/
681 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
690 /* take care of the special case */
691 /* array of characters can be init */
693 if (IS_CHAR (type->next)) {
694 //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
695 if (!IS_LITERAL(list2val(ilist)->etype)) {
696 werror (W_INIT_WRONG);
699 if (printIvalChar (type,
700 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
701 pb, SPEC_CVAL (sym->etype).v_char))
704 /* not the special case */
705 if (ilist->type != INIT_DEEP) {
706 werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
710 for (iloop=ilist->init.deep; iloop; iloop=iloop->next) {
711 if ((++size > DCL_ELEM(type)) && DCL_ELEM(type)) {
712 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
715 printIval (sym, type->next, iloop, pb);
719 if (DCL_ELEM(type)) {
720 // pad with zeros if needed
721 if (size<DCL_ELEM(type)) {
722 size = (DCL_ELEM(type) - size) * getSize(type->next);
724 //tfprintf (oFile, "\t!db !constbyte\n", 0);
725 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
729 // we have not been given a size, but we now know it
730 DCL_ELEM (type) = size;
736 /*-----------------------------------------------------------------*/
737 /* printIvalPtr - generates code for initial value of pointers */
738 /*-----------------------------------------------------------------*/
739 extern value *initPointer (initList *, sym_link *toType);
742 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
749 fprintf (stderr, "FIXME: initializers for pointers...\n");
750 printTypeChain (type, stderr);
752 fprintf (stderr, "symbol: %s, DCL_TYPE():%d, DCL_ELEM():%d, IS_ARRAY():%d", sym->rname, DCL_TYPE(type), DCL_ELEM(type), IS_ARRAY(type));
753 fprintf (stderr, "ilist: type=%d (INIT_DEEP=%d, INIT_NODE=%d)\n", ilist->type, INIT_DEEP, INIT_NODE);
755 if (ilist && (ilist->type == INIT_DEEP))
756 ilist = ilist->init.deep;
758 /* function pointers */
759 if (IS_FUNC (type->next))
761 assert ( !"function pointers not yet handled" );
762 //printIvalFuncPtr (type, ilist, pb);
765 if (!(val = initPointer (ilist, type)))
768 if (IS_CHAR (type->next))
770 if (printIvalChar (type, ilist, pb, NULL)) return;
774 if (compareType (type, val->type) == 0)
776 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
777 printFromToType (val->type, type);
780 if (IS_LITERAL (val->etype))
782 switch (getSize (type))
785 fprintf (stderr, "BYTE: %i\n", (unsigned char)floatFromVal (val) & 0x00FF);
788 fprintf (stderr, "WORD: %i\n", (unsigned int)floatFromVal (val) & 0x00FFFF);
790 case 3: /* gneric pointers */
791 assert ( !"generic pointers not yet handled" );
793 fprintf (stderr, "LONG: %i\n", (unsigned int)floatFromVal (val) & 0x0000FFFFFFFF);
796 assert ( !"invaild size of value -- aborting" );
802 /* now handle symbolic values */
803 switch (getSize (type))
806 fprintf (stderr, "BYTE: %s", val->name);
809 fprintf (stderr, "WORD: %s", val->name);
812 fprintf (stderr, "LONG: %s", val->name);
815 assert ( !"invalid size of (symbolic) value -- aborting" );
819 /*-----------------------------------------------------------------*/
820 /* printIval - generates code for initial value */
821 /*-----------------------------------------------------------------*/
823 printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
828 /* if structure then */
829 if (IS_STRUCT (type))
831 //fprintf(stderr,"%s struct: %s\n",__FUNCTION__, sym->rname);
832 printIvalStruct (sym, type, ilist, pb);
836 /* if this is an array */
839 //fprintf(stderr,"%s array: %s\n",__FUNCTION__, sym->rname);
840 printIvalArray (sym, type, ilist, pb);
844 /* if this is a pointer */
847 //fprintf(stderr,"%s pointer: %s\n",__FUNCTION__, sym->rname);
848 printIvalPtr (sym, type, ilist, pb);
852 /* if type is SPECIFIER */
855 //fprintf(stderr,"%s spec %s\n",__FUNCTION__, sym->rname);
856 printIvalType (sym, type, ilist, pb);
861 extern void pCodeConstString(char *name, char *value);
862 /*-----------------------------------------------------------------*/
863 /* emitStaticSeg - emitcode for the static segment */
864 /*-----------------------------------------------------------------*/
866 pic14emitStaticSeg (memmap * map)
870 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
872 //fprintf(stderr, "%s\n",__FUNCTION__);
874 /* for all variables in this segment do */
875 for (sym = setFirstItem (map->syms); sym;
876 sym = setNextItem (map->syms))
878 /* if extern then add it into the extern list */
879 if (IS_EXTERN (sym->etype)) {
880 addSetHead (&externs, sym);
884 /* if it is not static add it to the public
886 if (!IS_STATIC (sym->etype))
887 addSetHead (&publics, sym);
889 /* print extra debug info if required */
890 if (options.debug || sym->level == 0)
894 if (IS_STATIC (sym->etype))
895 fprintf (code->oFile, "F%s_", moduleName); /* scope is file */
897 fprintf (code->oFile, "G_"); /* scope is global */
900 /* symbol is local */
901 fprintf (code->oFile, "L%s_",
902 (sym->localof ? sym->localof->name : "-null-"));
903 fprintf (code->oFile, "%s_%d_%d", sym->name, sym->level, sym->block);
907 /* if it has an absolute address */
908 if (SPEC_ABSA (sym->etype))
910 if (options.debug || sym->level == 0)
911 fprintf (code->oFile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
913 fprintf (code->oFile, "%s\t=\t0x%04x\n",
915 SPEC_ADDR (sym->etype));
919 if (options.debug || sym->level == 0)
920 fprintf (code->oFile, " == .\n");
922 /* if it has an initial value */
927 fprintf (code->oFile, "%s:\n", sym->rname);
929 resolveIvalSym (sym->ival, sym->type);
930 //printIval (sym, sym->type, sym->ival, code->oFile);
931 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block for Ival"));
933 addpCode2pBlock(pb,newpCodeLabel(sym->rname,-1));
935 printIval (sym, sym->type, sym->ival, pb);
942 fprintf (code->oFile, "%s:\n", sym->rname);
943 /* special case for character strings */
944 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
945 SPEC_CVAL (sym->etype).v_char)
946 pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
947 /*printChar (code->oFile,
948 SPEC_CVAL (sym->etype).v_char,
949 strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
951 fprintf (code->oFile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
959 /*-----------------------------------------------------------------*/
960 /* emitMaps - emits the code for the data portion the code */
961 /*-----------------------------------------------------------------*/
965 pic14_constructAbsMap (sfr->oFile);
966 /* no special considerations for the following
967 data, idata & bit & xdata */
968 pic14emitRegularMap (data, TRUE, TRUE);
969 pic14emitRegularMap (idata, TRUE, TRUE);
970 pic14emitRegularMap (bit, TRUE, FALSE);
971 pic14emitRegularMap (xdata, TRUE, TRUE);
972 pic14emitRegularMap (sfr, TRUE, FALSE);
973 pic14emitRegularMap (sfrbit, FALSE, FALSE);
974 pic14emitRegularMap (code, TRUE, FALSE);
975 pic14emitStaticSeg (statsg);
978 /*-----------------------------------------------------------------*/
979 /* createInterruptVect - creates the interrupt vector */
980 /*-----------------------------------------------------------------*/
982 pic14createInterruptVect (FILE * vFile)
984 mainf = newSymbol ("main", 0);
987 /* only if the main function exists */
988 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
990 struct options *op = &options;
991 if (!(op->cc_only || noAssemble))
992 // werror (E_NO_MAIN);
993 fprintf(stderr,"WARNING: function 'main' undefined\n");
997 /* if the main is only a prototype ie. no body then do nothing */
998 if (!IFFUNC_HASBODY(mainf->type))
1000 /* if ! compile only then main function should be present */
1001 if (!(options.cc_only || noAssemble))
1002 // werror (E_NO_MAIN);
1003 fprintf(stderr,"WARNING: function 'main' undefined\n");
1007 fprintf (vFile, "%s", iComments2);
1008 fprintf (vFile, "; reset vector \n");
1009 fprintf (vFile, "%s", iComments2);
1010 fprintf (vFile, "STARTUP\t%s\n", CODE_NAME); // Lkr file should place section STARTUP at address 0x0
1011 fprintf (vFile, "\tnop\n"); /* first location for used by incircuit debugger */
1012 fprintf (vFile, "\tgoto\t__sdcc_gsinit_startup\n");
1016 /*-----------------------------------------------------------------*/
1017 /* initialComments - puts in some initial comments */
1018 /*-----------------------------------------------------------------*/
1020 pic14initialComments (FILE * afile)
1022 initialComments (afile);
1023 fprintf (afile, "; PIC port for the 14-bit core\n");
1024 fprintf (afile, iComments2);
1028 /*-----------------------------------------------------------------*/
1029 /* printExterns - generates extern for external variables */
1030 /*-----------------------------------------------------------------*/
1032 pic14printExterns (FILE * afile)
1036 fprintf (afile, "%s", iComments2);
1037 fprintf (afile, "; extern variables in this module\n");
1038 fprintf (afile, "%s", iComments2);
1040 for (sym = setFirstItem (externs); sym;
1041 sym = setNextItem (externs))
1042 fprintf (afile, "\textern %s\n", sym->rname);
1045 /*-----------------------------------------------------------------*/
1046 /* printPublics - generates .global for publics */
1047 /*-----------------------------------------------------------------*/
1049 pic14printPublics (FILE * afile)
1053 fprintf (afile, "%s", iComments2);
1054 fprintf (afile, "; publics variables in this module\n");
1055 fprintf (afile, "%s", iComments2);
1057 for (sym = setFirstItem (publics); sym;
1058 sym = setNextItem (publics)) {
1060 if(!IS_BITFIELD(sym->type) && ((IS_FUNC(sym->type) || sym->allocreq))) {
1061 if (!IS_BITVAR(sym->type))
1062 fprintf (afile, "\tglobal %s\n", sym->rname);
1064 /* Absolute variables are defines in the asm file as equates and thus can not be made global. */
1065 /* Not any longer! */
1066 //if (!SPEC_ABSA (sym->etype))
1067 fprintf (afile, "\tglobal %s\n", sym->rname);
1072 /*-----------------------------------------------------------------*/
1073 /* emitOverlay - will emit code for the overlay stuff */
1074 /*-----------------------------------------------------------------*/
1076 pic14emitOverlay (FILE * afile)
1080 /* if (!elementsInSet (ovrSetSets))*/
1082 /* the hack below, fixes translates for devices which
1083 * only have udata_shr memory */
1084 fprintf (afile, "%s\t%s\n",
1085 (elementsInSet(ovrSetSets)?"":";"),
1086 port->mem.overlay_name);
1088 /* for each of the sets in the overlay segment do */
1089 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1090 ovrset = setNextItem (ovrSetSets))
1095 if (elementsInSet (ovrset))
1097 /* this dummy area is used to fool the assembler
1098 otherwise the assembler will append each of these
1099 declarations into one chunk and will not overlay
1102 /* I don't think this applies to us. We are using gpasm. CRF */
1104 fprintf (afile, ";\t.area _DUMMY\n");
1105 /* output the area informtion */
1106 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1109 for (sym = setFirstItem (ovrset); sym;
1110 sym = setNextItem (ovrset))
1113 /* if extern then do nothing */
1114 if (IS_EXTERN (sym->etype))
1117 /* if allocation required check is needed
1118 then check if the symbol really requires
1119 allocation only for local variables */
1120 if (!IS_AGGREGATE (sym->type) &&
1121 !(sym->_isparm && !IS_REGPARM (sym->etype))
1122 && !sym->allocreq && sym->level)
1125 /* if global variable & not static or extern
1126 and addPublics allowed then add it to the public set */
1127 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1128 && !IS_STATIC (sym->etype))
1129 addSetHead (&publics, sym);
1131 /* if extern then do nothing or is a function
1133 if (IS_FUNC (sym->type))
1136 /* print extra debug info if required */
1137 if (options.debug || sym->level == 0)
1141 if (IS_STATIC (sym->etype))
1142 fprintf (afile, "F%s_", moduleName); /* scope is file */
1144 fprintf (afile, "G_"); /* scope is global */
1147 /* symbol is local */
1148 fprintf (afile, "L%s_",
1149 (sym->localof ? sym->localof->name : "-null-"));
1150 fprintf (afile, "%s_%d_%d", sym->name, sym->level, sym->block);
1153 /* if is has an absolute address then generate
1154 an equate for this no need to allocate space */
1155 if (SPEC_ABSA (sym->etype))
1158 if (options.debug || sym->level == 0)
1159 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1161 fprintf (afile, "%s\t=\t0x%04x\n",
1163 SPEC_ADDR (sym->etype));
1167 if (options.debug || sym->level == 0)
1168 fprintf (afile, "==.\n");
1170 /* allocate space */
1171 fprintf (afile, "%s:\n", sym->rname);
1172 fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1181 pic14_emitInterruptHandler (FILE * asmFile)
1183 if (pic14_hasInterrupt)
1186 fprintf (asmFile, "%s", iComments2);
1187 fprintf (asmFile, "; interrupt and initialization code\n");
1188 fprintf (asmFile, "%s", iComments2);
1189 // Note - for mplink may have to enlarge section vectors in .lnk file
1190 // Note: Do NOT name this code_interrupt to avoid nameclashes with
1191 // source files's code segment (interrupt.c -> code_interrupt)
1192 fprintf (asmFile, "c_interrupt\t%s\t0x4\n", CODE_NAME);
1194 /* interrupt service routine */
1195 fprintf (asmFile, "__sdcc_interrupt\n");
1196 copypCode(asmFile, 'I');
1200 /*-----------------------------------------------------------------*/
1201 /* glue - the final glue that hold the whole thing together */
1202 /*-----------------------------------------------------------------*/
1206 char udata_name[80];
1209 FILE *ovrFile = tempfile();
1211 addSetHead(&tmpfileSet,ovrFile);
1212 pCodeInitRegisters();
1214 /* check for main() */
1215 mainf = newSymbol ("main", 0);
1217 mainf = findSymWithLevel (SymbolTab, mainf);
1219 if (!mainf || !IFFUNC_HASBODY(mainf->type))
1221 /* main missing -- import stack from main module */
1222 //fprintf (stderr, "main() missing -- assuming we are NOT the main module\n");
1223 pic14_options.isLibrarySource = 1;
1227 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1229 pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
1232 /* entry point @ start of CSEG */
1233 addpCode2pBlock(pb,newpCodeLabel("__sdcc_program_startup",-1));
1234 /* put in the call to main */
1235 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp("_main",PO_STR)));
1237 if (options.mainreturn) {
1239 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will return to caller\n"));
1240 addpCode2pBlock(pb,newpCode(POC_RETURN,NULL));
1244 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will lock up\n"));
1245 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("$",PO_STR)));
1251 /* At this point we've got all the code in the form of pCode structures */
1252 /* Now it needs to be rearranged into the order it should be placed in the */
1255 movepBlock2Head('P'); // Last
1256 movepBlock2Head(code->dbName);
1257 movepBlock2Head('X');
1258 movepBlock2Head(statsg->dbName); // First
1261 /* print the global struct definitions */
1267 addSetHead(&tmpfileSet,vFile);
1269 /* emit code for the all the variables declared */
1271 /* do the overlay segments */
1272 pic14emitOverlay(ovrFile);
1274 /* PENDING: this isnt the best place but it will do */
1275 if (port->general.glue_up_main) {
1276 /* create the interrupt vector table */
1277 pic14createInterruptVect (vFile);
1282 ReuseReg(); // ReuseReg where call tree permits
1291 /* now put it all together into the assembler file */
1292 /* create the assembler file name */
1294 if ((noAssemble || options.c1mode) && fullDstFileName)
1296 sprintf (buffer, fullDstFileName);
1300 sprintf (buffer, dstFileName);
1301 strcat (buffer, ".asm");
1304 if (!(asmFile = fopen (buffer, "w"))) {
1305 werror (E_FILE_OPEN_ERR, buffer);
1309 /* prepare statistics */
1310 resetpCodeStatistics ();
1312 /* initial comments */
1313 pic14initialComments (asmFile);
1315 /* print module name */
1316 fprintf (asmFile, ";\t.module %s\n", moduleName);
1318 /* Let the port generate any global directives, etc. */
1319 if (port->genAssemblerPreamble)
1321 port->genAssemblerPreamble(asmFile);
1324 /* Emit the __config directive */
1325 pic14_emitConfigWord (asmFile);
1327 /* print the extern variables in this module */
1328 pic14printExterns (asmFile);
1330 /* print the global variables in this module */
1331 pic14printPublics (asmFile);
1333 /* copy the sfr segment */
1334 fprintf (asmFile, "%s", iComments2);
1335 fprintf (asmFile, "; special function registers\n");
1336 fprintf (asmFile, "%s", iComments2);
1337 copyFile (asmFile, sfr->oFile);
1340 if (udata_section_name) {
1341 sprintf(udata_name,"%s",udata_section_name);
1343 sprintf(udata_name,"data_%s",moduleName);
1345 fprintf (asmFile, "%s", iComments2);
1346 fprintf (asmFile, "; udata\n");
1347 fprintf (asmFile, "%s", iComments2);
1348 fprintf (asmFile, "%s\tudata\n", udata_name);
1349 copyFile (asmFile, data->oFile);
1351 /* Put all variables into a cblock */
1353 writeUsedRegs(asmFile);
1355 /* create the overlay segments */
1356 fprintf (asmFile, "%s", iComments2);
1357 fprintf (asmFile, "; overlayable items in internal ram \n");
1358 fprintf (asmFile, "%s", iComments2);
1359 copyFile (asmFile, ovrFile);
1363 /* create the stack segment MOF */
1364 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1365 fprintf (asmFile, "%s", iComments2);
1366 fprintf (asmFile, "; Stack segment in internal ram \n");
1367 fprintf (asmFile, "%s", iComments2);
1368 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1369 ";__start__stack:\n;\t.ds\t1\n\n");
1372 /* create the idata segment */
1373 fprintf (asmFile, "%s", iComments2);
1374 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1375 fprintf (asmFile, "%s", iComments2);
1376 copyFile (asmFile, idata->oFile);
1378 /* if external stack then reserve space of it */
1379 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1380 fprintf (asmFile, "%s", iComments2);
1381 fprintf (asmFile, "; external stack \n");
1382 fprintf (asmFile, "%s", iComments2);
1383 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1384 fprintf (asmFile,";\t.ds 256\n");
1387 /* copy xtern ram data */
1388 fprintf (asmFile, "%s", iComments2);
1389 fprintf (asmFile, "; external ram data\n");
1390 fprintf (asmFile, "%s", iComments2);
1391 copyFile (asmFile, xdata->oFile);
1395 /* copy the bit segment */
1396 fprintf (asmFile, "%s", iComments2);
1397 fprintf (asmFile, "; bit data\n");
1398 fprintf (asmFile, "%s", iComments2);
1399 copyFile (asmFile, bit->oFile);
1401 /* copy the interrupt vector table */
1402 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1403 copyFile (asmFile, vFile);
1406 /* create interupt ventor handler */
1407 pic14_emitInterruptHandler (asmFile);
1409 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1410 /* initialize data memory */
1411 fprintf (asmFile, "code_init\t%s\n", CODE_NAME); // Note - for mplink may have to enlarge section vectors in .lnk file
1412 fprintf (asmFile,"__sdcc_gsinit_startup\n");
1413 /* FIXME: This is temporary. The idata section should be used. If
1414 not, we could add a special feature to the linker. This will
1415 work in the mean time. Put all initalized data in main.c */
1416 copypCode(asmFile, statsg->dbName);
1417 fprintf (asmFile,"\tpagesel _main\n");
1418 fprintf (asmFile,"\tgoto _main\n");
1423 /* copy global & static initialisations */
1424 fprintf (asmFile, "%s", iComments2);
1425 fprintf (asmFile, "; global & static initialisations\n");
1426 fprintf (asmFile, "%s", iComments2);
1427 copypCode(asmFile, statsg->dbName);
1431 /* copy over code */
1432 fprintf (asmFile, "%s", iComments2);
1433 fprintf (asmFile, "; code\n");
1434 fprintf (asmFile, "%s", iComments2);
1435 fprintf (asmFile, "code_%s\t%s\n", moduleName, port->mem.code_name);
1438 copypCode(asmFile, 'X');
1440 /* _main function */
1441 copypCode(asmFile, 'M');
1443 /* other functions */
1444 copypCode(asmFile, code->dbName);
1447 copypCode(asmFile, 'P');
1449 dumppCodeStatistics (asmFile);
1451 fprintf (asmFile,"\tend\n");