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"
33 #include "dbuf_string.h"
36 #ifdef WORDS_BIGENDIAN
37 #define _ENDIAN(x) (3-x)
39 #define _ENDIAN(x) (x)
42 #define BYTE_IN_LONG(x,b) ((x>>(8*_ENDIAN(b)))&0xff)
44 extern symbol *interrupts[256];
45 static void printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb);
49 extern unsigned maxInterrupts;
50 extern int maxRegBank;
52 extern char *VersionString;
53 extern struct dbuf_s *codeOutBuf;
54 extern char *iComments1;
55 extern char *iComments2;
56 //extern void emitStaticSeg (memmap * map);
57 set *pic14_localFunctions = NULL;
59 extern DEFSETFUNC (closeTmpFiles);
60 extern DEFSETFUNC (rmTmpFiles);
62 extern void AnalyzeBanking (void);
63 extern void ReuseReg(void);
64 extern void InlinepCode(void);
65 extern void writeUsedRegs(FILE *);
67 extern void initialComments (FILE * afile);
68 extern void printPublics (FILE * afile);
70 extern void printChar (FILE * ofile, char *s, int plen);
71 void pCodeInitRegisters(void);
72 int getConfigWord(int address);
73 int getHasSecondConfigReg(void);
75 char *udata_section_name=0; // FIXME Temporary fix to change udata section name -- VR
76 int pic14_hasInterrupt = 0; // Indicates whether to emit interrupt handler or not
78 static set *emitted = NULL;
79 int pic14_stringInSet(const char *str, set **world, int autoAdd);
80 static void emitSymbol (struct dbuf_s *oBuf, const char *name, const char *section_type, int size, int addr, int useEQU, int globalize);
82 /*-----------------------------------------------------------------*/
83 /* aopLiteral - string from a literal value */
84 /*-----------------------------------------------------------------*/
85 unsigned int pic14aopLiteral (value *val, int offset)
92 /* if it is a float then it gets tricky */
93 /* otherwise it is fairly simple */
94 if (!IS_FLOAT(val->type)) {
95 unsigned long v = (unsigned long) floatFromVal(val);
97 return ( (v >> (offset * 8)) & 0xff);
100 /* it is type float */
101 fl.f = (float) floatFromVal(val);
102 #ifdef WORDS_BIGENDIAN
103 return fl.c[3-offset];
111 is_valid_identifier( const char *name )
117 /* only accept [a-zA-Z_][a-zA-Z0-9_] */
118 if (!((a >= 'a' && a <= 'z')
119 || (a >= 'A' && a <= 'z')
124 while ((a = *name++))
126 if (!((a >= 'a' && a <= 'z')
127 || (a >= 'A' && a <= 'Z')
128 || (a >= '0' && a <= '9')
133 /* valid identifier */
137 #define IS_DEFINED_HERE(sym) (!IS_EXTERN(sym->etype))
138 extern int IS_CONFIG_ADDRESS( int addr );
140 pic14_constructAbsMap (struct dbuf_s *oBuf)
142 memmap *maps[] = { data, sfr, NULL };
147 int addr, min=-1, max=-1;
150 int low, high, shared;
152 for (i=0; maps[i] != NULL; i++)
154 for (sym = (symbol *)setFirstItem (maps[i]->syms);
155 sym; sym = setNextItem (maps[i]->syms))
157 if (IS_DEFINED_HERE(sym) && SPEC_ABSA(sym->etype))
159 addr = SPEC_ADDR(sym->etype);
161 /* handle CONFIG words here */
162 if (IS_CONFIG_ADDRESS( addr ))
164 //fprintf( stderr, "%s: assignment to CONFIG@0x%x found\n", __FUNCTION__, addr );
165 //fprintf( stderr, "ival: %p (0x%x)\n", sym->ival, (int)list2int( sym->ival ) );
167 pic14_assignConfigWordValue( addr, (int)list2int( sym->ival ) );
169 fprintf( stderr, "ERROR: Symbol %s, which is covering a __CONFIG word must be initialized!\n", sym->name );
174 if (max == -1 || addr > max) max = addr;
175 if (min == -1 || addr < min) min = addr;
176 //fprintf (stderr, "%s: sym %s @ 0x%x\n", __FUNCTION__, sym->name, addr);
177 aliases = hTabItemWithKey (ht, addr);
179 /* May not use addSetHead, as we cannot update the
180 * list's head in the hastable `ht'. */
181 addSet (&aliases, sym);
183 fprintf( stderr, "%s: now %d aliases for %s @ 0x%x\n",
184 __FUNCTION__, elementsInSet(aliases), sym->name, addr);
187 addSet (&aliases, sym);
188 hTabAddItem (&ht, addr, aliases);
194 /* now emit definitions for all absolute symbols */
195 dbuf_printf (oBuf, "%s", iComments2);
196 dbuf_printf (oBuf, "; absolute symbol definitions\n");
197 dbuf_printf (oBuf, "%s", iComments2);
198 for (addr=min; addr <= max; addr++)
201 aliases = hTabItemWithKey (ht, addr);
202 if (aliases && elementsInSet(aliases)) {
203 dbuf_printf (oBuf, "udata_abs_%s_%x\tudata_ovr\t0x%04x",
204 moduleName, addr, addr);
205 for (sym = setFirstItem (aliases); sym;
206 sym = setNextItem (aliases))
208 /* emit STATUS as well as _STATUS, required for SFRs only */
209 dbuf_printf (oBuf, "\n%s", sym->name);
210 dbuf_printf (oBuf, "\n%s", sym->rname);
211 if (getSize(sym->type) > size) {
212 size = getSize(sym->type);
215 // global symbols must be emitted again as 'global sym->name'
216 pic14_stringInSet(sym->name, &emitted, 1);
217 pic14_stringInSet(sym->rname, &emitted, 1);
220 dbuf_printf (oBuf, "\tres\t%d\n", size);
224 /* also emit STK symbols
225 * XXX: This is ugly and fails as soon as devices start to get
226 * differently sized sharebanks, since STK12 will be
227 * required by larger devices but only up to STK03 might
228 * be defined using smaller devices. */
229 dbuf_printf (oBuf, "\n");
230 shared = pic14_getSharedStack(&low, &high, &size);
231 if (!pic14_options.isLibrarySource)
233 pic = pic14_getPIC();
235 dbuf_printf (oBuf, "\tglobal PSAVE\n");
236 dbuf_printf (oBuf, "\tglobal SSAVE\n");
237 dbuf_printf (oBuf, "\tglobal WSAVE\n");
238 for (i = size - 4; i >= 0; i--) {
239 dbuf_printf (oBuf, "\tglobal STK%02d\n", i);
242 // 16f84 has no SHAREBANK (in linkerscript) but memory aliased in two
245 // for single banked devices: use normal, "banked" RAM
246 dbuf_printf (oBuf, "sharebank udata_ovr 0x%04X\n", low);
248 // for devices with at least two banks, require a sharebank section
249 dbuf_printf (oBuf, "sharebank udata_shr\n");
251 dbuf_printf (oBuf, "PSAVE\tres 1\n");
252 dbuf_printf (oBuf, "SSAVE\tres 1\n");
253 dbuf_printf (oBuf, "WSAVE\tres 1\n"); // WSAVE *must* be in sharebank (IRQ handlers)
254 /* fill rest of sharebank with stack STKxx .. STK00 */
255 for (i = size - 4; i >= 0; i--) {
256 dbuf_printf (oBuf, "STK%02d\tres 1\n", i);
259 /* declare STKxx as extern for all files
260 * except the one containing main() */
261 dbuf_printf (oBuf, "\textern PSAVE\n");
262 dbuf_printf (oBuf, "\textern SSAVE\n");
263 dbuf_printf (oBuf, "\textern WSAVE\n");
264 for (i = size - 4; i >= 0; i--) {
266 SNPRINTF(&buffer[0], 127, "STK%02d", i);
267 dbuf_printf (oBuf, "\textern %s\n", &buffer[0]);
268 pic14_stringInSet(&buffer[0], &emitted, 1);
273 /*-----------------------------------------------------------------*/
274 /* emitRegularMap - emit code for maps with no special cases */
275 /*-----------------------------------------------------------------*/
277 pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag)
282 /* print the area name */
284 dbuf_printf (&map->oBuf, ";\t.area\t%s\n", map->sname);
286 for (sym = setFirstItem (map->syms); sym;
287 sym = setNextItem (map->syms)) {
289 //printf("%s\n",sym->name);
291 /* ignore if config word */
292 if (SPEC_ABSA(sym->etype)
293 && IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype)))
296 /* if extern then add it into the extern list */
297 if (IS_EXTERN (sym->etype)) {
298 addSetHead (&externs, sym);
302 /* if allocation required check is needed
303 then check if the symbol really requires
304 allocation only for local variables */
305 if (arFlag && !IS_AGGREGATE (sym->type) &&
306 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
307 !sym->allocreq && sym->level)
310 /* if global variable & not static or extern
311 and addPublics allowed then add it to the public set */
312 if ((sym->level == 0 ||
313 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
315 !IS_STATIC (sym->etype))
317 //fprintf( stderr, "%s: made public %s\n", __FUNCTION__, sym->name );
318 addSetHead (&publics, sym);
321 // PIC code allocates its own registers - so ignore parameter variable generated by processFuncArgs()
324 /* if extern then do nothing or is a function
326 if (IS_FUNC (sym->type))
329 /* print extra debug info if required */
330 if (options.debug || sym->level == 0)
332 if (!sym->level) /* global */
333 if (IS_STATIC (sym->etype))
334 dbuf_printf (&map->oBuf, "F%s_", moduleName); /* scope is file */
336 dbuf_printf (&map->oBuf, "G_"); /* scope is global */
338 /* symbol is local */
339 dbuf_printf (&map->oBuf, "L%s_", (sym->localof ? sym->localof->name : "-null-"));
340 dbuf_printf (&map->oBuf, "%s_%d_%d", sym->name, sym->level, sym->block);
343 /* absolute symbols are handled in pic14_constructAbsMap */
344 if (SPEC_ABSA(sym->etype) && IS_DEFINED_HERE(sym))
347 /* if it has an absolute address then generate
348 an equate for this no need to allocate space */
349 if (0 && SPEC_ABSA (sym->etype))
351 //if (options.debug || sym->level == 0)
352 //dbuf_printf (&map->oBuf,"; == 0x%04x\n",SPEC_ADDR (sym->etype));
354 dbuf_printf (&map->oBuf, "%s\tEQU\t0x%04x\n",
356 SPEC_ADDR (sym->etype));
362 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
363 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
364 /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
365 if (IS_BITVAR (sym->etype))
371 emitSymbol (&map->oBuf,
374 getSize (sym->type) & 0xffff,
375 SPEC_ABSA(sym->etype)
376 ? SPEC_ADDR(sym->etype)
384 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1)
386 for (i = 1; i < size; i++)
387 dbuf_printf (&map->oBuf, "\t%s_%d\n", sym->rname, i);
392 //dbuf_printf (&map->oBuf, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
395 /* if it has a initial value then do it only if
396 it is a global variable */
397 if (sym->ival && sym->level == 0) {
400 if (IS_AGGREGATE (sym->type))
401 ival = initAggregates (sym, sym->ival, NULL);
403 ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
404 decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
405 codeOutBuf = &statsg->oBuf;
407 eBBlockFromiCode (iCodeFromAst (ival));
414 /*-----------------------------------------------------------------*/
415 /* printIvalType - generates ival for int/char */
416 /*-----------------------------------------------------------------*/
418 printIvalType (symbol *sym, sym_link * type, initList * ilist, pBlock *pb)
423 //fprintf(stderr, "%s\n",__FUNCTION__);
425 /* if initList is deep */
426 if (ilist->type == INIT_DEEP)
427 ilist = ilist->init.deep;
429 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
430 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
433 if (!(val = list2val (ilist))) {
434 // assuming a warning has been thrown
438 if (val->type != type) {
439 val = valCastLiteral(type, floatFromVal(val));
443 ulval = (unsigned long) floatFromVal (val);
447 switch (getSize (type)) {
449 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
453 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
454 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
458 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,0))));
459 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,1))));
460 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,2))));
461 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(BYTE_IN_LONG(ulval,3))));
466 /*-----------------------------------------------------------------*/
467 /* printIvalBitFields - generate initializer for bitfields */
468 /*-----------------------------------------------------------------*/
469 static void printIvalBitFields(symbol **sym, initList **ilist, pBlock *pb )
473 initList *lilist = *ilist ;
474 unsigned long ival = 0;
480 val = list2val(lilist);
482 if (SPEC_BLEN(lsym->etype) > 8) {
483 size += ((SPEC_BLEN (lsym->etype) / 8) +
484 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
487 size = ((SPEC_BLEN (lsym->etype) / 8) +
488 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
490 i = (unsigned long)floatFromVal(val);
491 i <<= SPEC_BSTR (lsym->etype);
493 if (! ( lsym->next &&
494 (IS_BITFIELD(lsym->next->type)) &&
495 (SPEC_BSTR(lsym->next->etype)))) break;
497 lilist = lilist->next;
501 //tfprintf (oFile, "\t!db !constbyte\n",ival);
502 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
506 //tfprintf (oFile, "\t!dw !constword\n",ival);
507 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
508 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
511 //tfprintf (oFile, "\t!db !constword,!constword\n",(ival >> 8) & 0xffff, (ival & 0xffff));
512 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>24)));
513 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>16)));
514 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival>>8)));
515 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(ival)));
522 /*-----------------------------------------------------------------*/
523 /* printIvalStruct - generates initial value for structures */
524 /*-----------------------------------------------------------------*/
525 static void printIvalStruct (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
528 initList *iloop = NULL;
530 sflds = SPEC_STRUCT (type)->fields;
533 if (ilist->type != INIT_DEEP) {
534 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
538 iloop = ilist->init.deep;
541 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
542 if (IS_BITFIELD(sflds->type)) {
543 printIvalBitFields(&sflds,&iloop,pb);
545 printIval (sym, sflds->type, iloop, pb);
549 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
554 /*-----------------------------------------------------------------*/
555 /* printIvalChar - generates initital value for character array */
556 /*-----------------------------------------------------------------*/
558 printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s)
566 //fprintf(stderr, "%s\n",__FUNCTION__);
570 val = list2val (ilist);
572 /* if the value is a character string */
573 if (IS_ARRAY (val->type) && IS_CHAR (val->etype))
575 ilen = DCL_ELEM(val->type);
577 if (!DCL_ELEM (type))
578 DCL_ELEM (type) = ilen;
580 /* emit string constant */
581 for (remain = 0; remain < ilen; remain++) {
582 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(SPEC_CVAL(val->etype).v_char[remain])));
585 /* fill array up to desired size */
586 if ((remain = (DCL_ELEM (type) - ilen)) > 0)
588 //tfprintf (oFile, "\t!db !constbyte\n", 0);
589 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
596 //printChar (oFile, s, strlen (s) + 1);
598 for(remain=0; remain<(int)strlen(s); remain++) {
599 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(s[remain])));
600 //fprintf(stderr,"0x%02x ",s[remain]);
602 //fprintf(stderr,"\n");
607 /*-----------------------------------------------------------------*/
608 /* printIvalArray - generates code for array initialization */
609 /*-----------------------------------------------------------------*/
611 printIvalArray (symbol * sym, sym_link * type, initList * ilist,
620 /* take care of the special case */
621 /* array of characters can be init */
623 if (IS_CHAR (type->next)) {
624 //fprintf(stderr,"%s:%d - is_char\n",__FUNCTION__,__LINE__);
625 if (!IS_LITERAL(list2val(ilist)->etype)) {
626 werror (W_INIT_WRONG);
629 if (printIvalChar (type,
630 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
631 pb, SPEC_CVAL (sym->etype).v_char))
634 /* not the special case */
635 if (ilist->type != INIT_DEEP) {
636 werrorfl (ilist->filename, ilist->lineno, E_INIT_STRUCT, sym->name);
640 for (iloop=ilist->init.deep; iloop; iloop=iloop->next) {
641 if ((++size > DCL_ELEM(type)) && DCL_ELEM(type)) {
642 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "array", sym->name);
645 printIval (sym, type->next, iloop, pb);
649 if (DCL_ELEM(type)) {
650 // pad with zeros if needed
651 if (size<DCL_ELEM(type)) {
652 size = (DCL_ELEM(type) - size) * getSize(type->next);
654 //tfprintf (oFile, "\t!db !constbyte\n", 0);
655 addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(0)));
659 // we have not been given a size, but we now know it
660 DCL_ELEM (type) = size;
666 /*-----------------------------------------------------------------*/
667 /* printIvalPtr - generates code for initial value of pointers */
668 /*-----------------------------------------------------------------*/
669 extern value *initPointer (initList *, sym_link *toType);
672 printIvalPtr (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
679 fprintf (stderr, "FIXME: initializers for pointers...\n");
680 printTypeChain (type, stderr);
682 fprintf (stderr, "symbol: %s, DCL_TYPE():%d, DCL_ELEM():%d, IS_ARRAY():%d", sym->rname, DCL_TYPE(type), DCL_ELEM(type), IS_ARRAY(type));
683 fprintf (stderr, "ilist: type=%d (INIT_DEEP=%d, INIT_NODE=%d)\n", ilist->type, INIT_DEEP, INIT_NODE);
685 if (ilist && (ilist->type == INIT_DEEP))
686 ilist = ilist->init.deep;
688 /* function pointers */
689 if (IS_FUNC (type->next))
691 assert ( !"function pointers not yet handled" );
692 //printIvalFuncPtr (type, ilist, pb);
695 if (!(val = initPointer (ilist, type)))
698 if (IS_CHAR (type->next))
700 if (printIvalChar (type, ilist, pb, NULL)) return;
704 if (compareType (type, val->type) == 0)
706 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
707 printFromToType (val->type, type);
710 if (IS_LITERAL (val->etype))
712 switch (getSize (type))
715 fprintf (stderr, "BYTE: %i\n", (unsigned char)floatFromVal (val) & 0x00FF);
718 fprintf (stderr, "WORD: %i\n", (unsigned int)floatFromVal (val) & 0x00FFFF);
720 case 3: /* gneric pointers */
721 assert ( !"generic pointers not yet handled" );
723 fprintf (stderr, "LONG: %i\n", (unsigned int)floatFromVal (val) & 0x0000FFFFFFFF);
726 assert ( !"invaild size of value -- aborting" );
732 /* now handle symbolic values */
733 switch (getSize (type))
736 fprintf (stderr, "BYTE: %s", val->name);
739 fprintf (stderr, "WORD: %s", val->name);
742 fprintf (stderr, "LONG: %s", val->name);
745 assert ( !"invalid size of (symbolic) value -- aborting" );
749 /*-----------------------------------------------------------------*/
750 /* printIval - generates code for initial value */
751 /*-----------------------------------------------------------------*/
753 printIval (symbol * sym, sym_link * type, initList * ilist, pBlock *pb)
758 /* if structure then */
759 if (IS_STRUCT (type))
761 //fprintf(stderr,"%s struct: %s\n",__FUNCTION__, sym->rname);
762 printIvalStruct (sym, type, ilist, pb);
766 /* if this is an array */
769 //fprintf(stderr,"%s array: %s\n",__FUNCTION__, sym->rname);
770 printIvalArray (sym, type, ilist, pb);
774 /* if this is a pointer */
777 //fprintf(stderr,"%s pointer: %s\n",__FUNCTION__, sym->rname);
778 printIvalPtr (sym, type, ilist, pb);
782 /* if type is SPECIFIER */
785 //fprintf(stderr,"%s spec %s\n",__FUNCTION__, sym->rname);
786 printIvalType (sym, type, ilist, pb);
791 extern void pCodeConstString(char *name, char *value);
792 /*-----------------------------------------------------------------*/
793 /* emitStaticSeg - emitcode for the static segment */
794 /*-----------------------------------------------------------------*/
796 pic14emitStaticSeg (memmap * map)
800 dbuf_printf (&map->oBuf, ";\t.area\t%s\n", map->sname);
802 //fprintf(stderr, "%s\n",__FUNCTION__);
804 /* for all variables in this segment do */
805 for (sym = setFirstItem (map->syms); sym;
806 sym = setNextItem (map->syms))
808 /* if extern then add it into the extern list */
809 if (IS_EXTERN (sym->etype)) {
810 addSetHead (&externs, sym);
814 /* if it is not static add it to the public
816 if (!IS_STATIC (sym->etype))
817 addSetHead (&publics, sym);
819 /* print extra debug info if required */
820 if (options.debug || sym->level == 0)
824 if (IS_STATIC (sym->etype))
825 dbuf_printf (&code->oBuf, "F%s_", moduleName); /* scope is file */
827 dbuf_printf (&code->oBuf, "G_"); /* scope is global */
830 /* symbol is local */
831 dbuf_printf (&code->oBuf, "L%s_",
832 (sym->localof ? sym->localof->name : "-null-"));
833 dbuf_printf (&code->oBuf, "%s_%d_%d", sym->name, sym->level, sym->block);
837 /* if it has an absolute address */
838 if (SPEC_ABSA (sym->etype))
840 if (options.debug || sym->level == 0)
841 dbuf_printf (&code->oBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
843 dbuf_printf (&code->oBuf, "%s\t=\t0x%04x\n",
845 SPEC_ADDR (sym->etype));
849 if (options.debug || sym->level == 0)
850 dbuf_printf (&code->oBuf, " == .\n");
852 /* if it has an initial value */
857 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
859 resolveIvalSym (sym->ival, sym->type);
860 //printIval (sym, sym->type, sym->ival, &code->oBuf);
861 pb = newpCodeChain(NULL, 'P',newpCodeCharP("; Starting pCode block for Ival"));
863 addpCode2pBlock(pb,newpCodeLabel(sym->rname,-1));
865 printIval (sym, sym->type, sym->ival, pb);
872 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
873 /* special case for character strings */
874 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
875 SPEC_CVAL (sym->etype).v_char)
876 pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
877 /*printChar (code->oFile,
878 SPEC_CVAL (sym->etype).v_char,
879 strlen (SPEC_CVAL (sym->etype).v_char) + 1);*/
881 dbuf_printf (&code->oBuf, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
889 /*-----------------------------------------------------------------*/
890 /* emitMaps - emits the code for the data portion the code */
891 /*-----------------------------------------------------------------*/
895 pic14_constructAbsMap (&sfr->oBuf);
896 /* no special considerations for the following
897 data, idata & bit & xdata */
898 pic14emitRegularMap (data, TRUE, TRUE);
899 pic14emitRegularMap (idata, TRUE, TRUE);
900 pic14emitRegularMap (bit, TRUE, FALSE);
901 pic14emitRegularMap (xdata, TRUE, TRUE);
902 pic14emitRegularMap (sfr, TRUE, FALSE);
903 pic14emitRegularMap (sfrbit, FALSE, FALSE);
904 pic14emitRegularMap (code, TRUE, FALSE);
905 pic14emitStaticSeg (statsg);
906 pic14emitStaticSeg (c_abs);
909 /*-----------------------------------------------------------------*/
910 /* createInterruptVect - creates the interrupt vector */
911 /*-----------------------------------------------------------------*/
913 pic14createInterruptVect (struct dbuf_s * vBuf)
915 mainf = newSymbol ("main", 0);
918 /* only if the main function exists */
919 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
921 struct options *op = &options;
922 if (!(op->cc_only || noAssemble))
923 // werror (E_NO_MAIN);
924 fprintf(stderr,"WARNING: function 'main' undefined\n");
928 /* if the main is only a prototype ie. no body then do nothing */
929 if (!IFFUNC_HASBODY(mainf->type))
931 /* if ! compile only then main function should be present */
932 if (!(options.cc_only || noAssemble))
933 // werror (E_NO_MAIN);
934 fprintf(stderr,"WARNING: function 'main' undefined\n");
938 dbuf_printf (vBuf, "%s", iComments2);
939 dbuf_printf (vBuf, "; reset vector \n");
940 dbuf_printf (vBuf, "%s", iComments2);
941 dbuf_printf (vBuf, "STARTUP\t%s\n", CODE_NAME); // Lkr file should place section STARTUP at address 0x0
942 dbuf_printf (vBuf, "\tnop\n"); /* first location for used by incircuit debugger */
943 dbuf_printf (vBuf, "\tpagesel __sdcc_gsinit_startup\n");
944 dbuf_printf (vBuf, "\tgoto\t__sdcc_gsinit_startup\n");
948 /*-----------------------------------------------------------------*/
949 /* initialComments - puts in some initial comments */
950 /*-----------------------------------------------------------------*/
952 pic14initialComments (FILE * afile)
954 initialComments (afile);
955 fprintf (afile, "; PIC port for the 14-bit core\n");
956 fprintf (afile, iComments2);
961 pic14_stringInSet(const char *str, set **world, int autoAdd)
968 for (s = setFirstItem(*world); s; s = setNextItem(*world))
971 if (0 == strcmp(s, str)) return 1;
975 if (autoAdd) addSet(world, Safe_strdup(str));
980 pic14_emitSymbolIfNew(FILE *file, const char *fmt, const char *sym, int checkLocals)
982 if (!pic14_stringInSet(sym, &emitted, 1)) {
983 /* sym was not in emittedSymbols */
984 if (!checkLocals || !pic14_stringInSet(sym, &pic14_localFunctions, 0)) {
985 /* sym is not a locally defined function---avoid bug #1443651 */
986 fprintf( file, fmt, sym );
993 /*-------------------------------------------------------------------*/
994 /* emitSymbol - write a symbol definition only if it is not */
995 /* already present */
996 /*-------------------------------------------------------------------*/
999 emitSymbol (struct dbuf_s *oBuf, const char *name, const char *section_type, int size, int addr, int useEQU, int globalize)
1001 static unsigned int sec_idx = 0;
1003 /* workaround: variables declared via `sbit' result in a numeric
1004 * identifier (0xHH), EQU'ing them is invalid, so just ignore it.
1005 * sbit is heavily used in the inc2h-generated header files!
1007 if (!is_valid_identifier(name))
1009 //fprintf( stderr, "%s:%s:%u: ignored symbol: %s\n", __FILE__, __FUNCTION__, __LINE__, name );
1013 /* check whether the symbol is already defined */
1014 if (pic14_stringInSet(name, &emitted, 1)) return;
1016 /* new symbol -- define it */
1017 //fprintf (stderr, "%s: emitting %s (%d)\n", __FUNCTION__, name, size);
1019 dbuf_printf (oBuf, "%s\tEQU\t0x%04x\n", name, addr);
1021 /* we place each symbol into a section of its own to allow the linker
1022 * to distribute the data into all available memory banks */
1023 if (!section_type) section_type = "udata";
1026 /* absolute symbols are handled in pic14_constructAbsMap */
1029 if (globalize) dbuf_printf (oBuf, "\tglobal\t%s\n", name);
1030 dbuf_printf (oBuf, "udata_%s_%u\t%s\n", moduleName,
1031 sec_idx++, section_type);
1032 dbuf_printf (oBuf, "%s\tres\t%d\n", name, size);
1037 /*-----------------------------------------------------------------*/
1038 /* printExterns - generates extern for external variables */
1039 /*-----------------------------------------------------------------*/
1041 pic14printExterns (FILE * afile)
1045 fprintf (afile, "%s", iComments2);
1046 fprintf (afile, "; extern variables in this module\n");
1047 fprintf (afile, "%s", iComments2);
1049 for (sym = setFirstItem (externs); sym; sym = setNextItem (externs))
1050 pic14_emitSymbolIfNew(afile, "\textern %s\n", sym->rname, 1);
1053 /*-----------------------------------------------------------------*/
1054 /* printPublics - generates .global for publics */
1055 /*-----------------------------------------------------------------*/
1057 pic14printPublics (FILE * afile)
1061 fprintf (afile, "%s", iComments2);
1062 fprintf (afile, "; public variables in this module\n");
1063 fprintf (afile, "%s", iComments2);
1065 for (sym = setFirstItem (publics); sym;
1066 sym = setNextItem (publics)) {
1068 if(!IS_BITFIELD(sym->type) && ((IS_FUNC(sym->type) || sym->allocreq))) {
1069 if (!IS_BITVAR(sym->type))
1070 pic14_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1072 /* Absolute variables are defines in the asm file as equates and thus can not be made global. */
1073 /* Not any longer! */
1074 //if (!SPEC_ABSA (sym->etype))
1075 pic14_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1081 pic14printLocals (FILE * afile)
1083 set *allregs[6] = { dynAllocRegs, dynStackRegs, dynProcessorRegs, dynDirectRegs, dynDirectBitRegs, dynInternalRegs };
1088 dbuf_init(&dbuf, 1024);
1089 /* emit all registers from all possible sets */
1090 for (i = 0; i < 6; i++) {
1091 if (allregs[i] == NULL) continue;
1093 for (reg = setFirstItem(allregs[i]); reg; reg = setNextItem(allregs[i])) {
1094 if (reg->isEmitted) continue;
1096 if (reg->wasUsed && !reg->isExtern) {
1097 emitSymbol(&dbuf, reg->name, "udata", reg->size, reg->isFixed ? reg->address : -1, 0, reg->isPublic);
1102 dbuf_write_and_destroy(&dbuf, afile);
1105 /*-----------------------------------------------------------------*/
1106 /* emitOverlay - will emit code for the overlay stuff */
1107 /*-----------------------------------------------------------------*/
1109 pic14emitOverlay (struct dbuf_s * aBuf)
1113 /* if (!elementsInSet (ovrSetSets))*/
1115 /* the hack below, fixes translates for devices which
1116 * only have udata_shr memory */
1117 dbuf_printf (aBuf, "%s\t%s\n",
1118 (elementsInSet(ovrSetSets)?"":";"),
1119 port->mem.overlay_name);
1121 /* for each of the sets in the overlay segment do */
1122 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1123 ovrset = setNextItem (ovrSetSets))
1128 if (elementsInSet (ovrset))
1130 /* this dummy area is used to fool the assembler
1131 otherwise the assembler will append each of these
1132 declarations into one chunk and will not overlay
1135 /* I don't think this applies to us. We are using gpasm. CRF */
1137 dbuf_printf (aBuf, ";\t.area _DUMMY\n");
1138 /* output the area informtion */
1139 dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1142 for (sym = setFirstItem (ovrset); sym;
1143 sym = setNextItem (ovrset))
1146 /* if extern then do nothing */
1147 if (IS_EXTERN (sym->etype))
1150 /* if allocation required check is needed
1151 then check if the symbol really requires
1152 allocation only for local variables */
1153 if (!IS_AGGREGATE (sym->type) &&
1154 !(sym->_isparm && !IS_REGPARM (sym->etype))
1155 && !sym->allocreq && sym->level)
1158 /* if global variable & not static or extern
1159 and addPublics allowed then add it to the public set */
1160 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1161 && !IS_STATIC (sym->etype))
1162 addSetHead (&publics, sym);
1164 /* if extern then do nothing or is a function
1166 if (IS_FUNC (sym->type))
1169 /* print extra debug info if required */
1170 if (options.debug || sym->level == 0)
1174 if (IS_STATIC (sym->etype))
1175 dbuf_printf (aBuf, "F%s_", moduleName); /* scope is file */
1177 dbuf_printf (aBuf, "G_"); /* scope is global */
1180 /* symbol is local */
1181 dbuf_printf (aBuf, "L%s_",
1182 (sym->localof ? sym->localof->name : "-null-"));
1183 dbuf_printf (aBuf, "%s_%d_%d", sym->name, sym->level, sym->block);
1186 /* if is has an absolute address then generate
1187 an equate for this no need to allocate space */
1188 if (SPEC_ABSA (sym->etype))
1191 if (options.debug || sym->level == 0)
1192 dbuf_printf (aBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1194 dbuf_printf (aBuf, "%s\t=\t0x%04x\n",
1196 SPEC_ADDR (sym->etype));
1200 if (options.debug || sym->level == 0)
1201 dbuf_printf (aBuf, "==.\n");
1203 /* allocate space */
1204 dbuf_printf (aBuf, "%s:\n", sym->rname);
1205 dbuf_printf (aBuf, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1214 pic14_emitInterruptHandler (FILE * asmFile)
1216 if (pic14_hasInterrupt)
1219 fprintf (asmFile, "%s", iComments2);
1220 fprintf (asmFile, "; interrupt and initialization code\n");
1221 fprintf (asmFile, "%s", iComments2);
1222 // Note - for mplink may have to enlarge section vectors in .lnk file
1223 // Note: Do NOT name this code_interrupt to avoid nameclashes with
1224 // source files's code segment (interrupt.c -> code_interrupt)
1225 fprintf (asmFile, "c_interrupt\t%s\t0x4\n", CODE_NAME);
1227 /* interrupt service routine */
1228 fprintf (asmFile, "__sdcc_interrupt\n");
1229 copypCode(asmFile, 'I');
1233 /*-----------------------------------------------------------------*/
1234 /* glue - the final glue that hold the whole thing together */
1235 /*-----------------------------------------------------------------*/
1239 char udata_name[80];
1241 struct dbuf_s ovrBuf;
1244 dbuf_init(&ovrBuf, 4096);
1245 dbuf_init(&vBuf, 4096);
1247 pCodeInitRegisters();
1249 /* check for main() */
1250 mainf = newSymbol ("main", 0);
1252 mainf = findSymWithLevel (SymbolTab, mainf);
1254 if (!mainf || !IFFUNC_HASBODY(mainf->type))
1256 /* main missing -- import stack from main module */
1257 //fprintf (stderr, "main() missing -- assuming we are NOT the main module\n");
1258 pic14_options.isLibrarySource = 1;
1262 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1264 pBlock *pb = newpCodeChain(NULL,'X',newpCodeCharP("; Starting pCode block"));
1267 /* entry point @ start of CSEG */
1268 addpCode2pBlock(pb,newpCodeLabel("__sdcc_program_startup",-1));
1269 /* put in the call to main */
1270 addpCode2pBlock(pb,newpCode(POC_CALL,newpCodeOp("_main",PO_STR)));
1272 if (options.mainreturn) {
1274 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will return to caller\n"));
1275 addpCode2pBlock(pb,newpCode(POC_RETURN,NULL));
1279 addpCode2pBlock(pb,newpCodeCharP(";\treturn from main will lock up\n"));
1280 addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("$",PO_STR)));
1286 /* At this point we've got all the code in the form of pCode structures */
1287 /* Now it needs to be rearranged into the order it should be placed in the */
1290 movepBlock2Head('P'); // Last
1291 movepBlock2Head(code->dbName);
1292 movepBlock2Head('X');
1293 movepBlock2Head(statsg->dbName); // First
1296 /* print the global struct definitions */
1300 /* emit code for the all the variables declared */
1302 /* do the overlay segments */
1303 pic14emitOverlay(&ovrBuf);
1305 /* PENDING: this isnt the best place but it will do */
1306 if (port->general.glue_up_main) {
1307 /* create the interrupt vector table */
1308 pic14createInterruptVect (&vBuf);
1313 ReuseReg(); // ReuseReg where call tree permits
1322 /* now put it all together into the assembler file */
1323 /* create the assembler file name */
1325 if ((noAssemble || options.c1mode) && fullDstFileName)
1327 sprintf (buffer, fullDstFileName);
1331 sprintf (buffer, dstFileName);
1332 strcat (buffer, ".asm");
1335 if (!(asmFile = fopen (buffer, "w"))) {
1336 werror (E_FILE_OPEN_ERR, buffer);
1340 /* prepare statistics */
1341 resetpCodeStatistics ();
1343 /* initial comments */
1344 pic14initialComments (asmFile);
1346 /* print module name */
1347 fprintf (asmFile, ";\t.module %s\n", moduleName);
1349 /* Let the port generate any global directives, etc. */
1350 if (port->genAssemblerPreamble)
1352 port->genAssemblerPreamble(asmFile);
1355 /* Emit the __config directive */
1356 pic14_emitConfigWord (asmFile);
1358 /* print the global variables in this module */
1359 pic14printPublics (asmFile);
1361 /* print the extern variables in this module */
1362 pic14printExterns (asmFile);
1364 /* copy the sfr segment */
1365 fprintf (asmFile, "%s", iComments2);
1366 fprintf (asmFile, "; special function registers\n");
1367 fprintf (asmFile, "%s", iComments2);
1368 dbuf_write_and_destroy (&sfr->oBuf, asmFile);
1371 if (udata_section_name) {
1372 sprintf(udata_name,"%s",udata_section_name);
1374 sprintf(udata_name,"data_%s",moduleName);
1376 fprintf (asmFile, "%s", iComments2);
1377 fprintf (asmFile, "; udata\n");
1378 fprintf (asmFile, "%s", iComments2);
1379 fprintf (asmFile, "%s\tudata\n", udata_name);
1380 dbuf_write_and_destroy(&data->oBuf, asmFile);
1382 /* Put all variables into a cblock */
1385 /* print the locally defined variables in this module */
1386 writeUsedRegs(asmFile);
1387 pic14printLocals (asmFile);
1389 /* create the overlay segments */
1390 fprintf (asmFile, "%s", iComments2);
1391 fprintf (asmFile, "; overlayable items in internal ram \n");
1392 fprintf (asmFile, "%s", iComments2);
1393 dbuf_write_and_destroy (&ovrBuf, asmFile);
1397 /* create the stack segment MOF */
1398 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1399 fprintf (asmFile, "%s", iComments2);
1400 fprintf (asmFile, "; Stack segment in internal ram \n");
1401 fprintf (asmFile, "%s", iComments2);
1402 fprintf (asmFile, ";\t.area\tSSEG\t(DATA)\n"
1403 ";__start__stack:\n;\t.ds\t1\n\n");
1406 /* create the idata segment */
1407 fprintf (asmFile, "%s", iComments2);
1408 fprintf (asmFile, "; indirectly addressable internal ram data\n");
1409 fprintf (asmFile, "%s", iComments2);
1410 dbuf_write_and_destroy (&idata->oBuf, asmFile);
1412 /* if external stack then reserve space of it */
1413 if (mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1414 fprintf (asmFile, "%s", iComments2);
1415 fprintf (asmFile, "; external stack \n");
1416 fprintf (asmFile, "%s", iComments2);
1417 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1418 fprintf (asmFile,";\t.ds 256\n");
1421 /* copy xtern ram data */
1422 fprintf (asmFile, "%s", iComments2);
1423 fprintf (asmFile, "; external ram data\n");
1424 fprintf (asmFile, "%s", iComments2);
1425 dbuf_write_and_destroy (&xdata->oBuf, asmFile);
1429 /* copy the bit segment */
1430 fprintf (asmFile, "%s", iComments2);
1431 fprintf (asmFile, "; bit data\n");
1432 fprintf (asmFile, "%s", iComments2);
1433 dbuf_write_and_destroy (&bit->oBuf, asmFile);
1435 /* copy the interrupt vector table */
1436 if (mainf && IFFUNC_HASBODY(mainf->type))
1437 dbuf_write_and_destroy (&vBuf, asmFile);
1439 dbuf_destroy(&vBuf);
1441 /* create interupt ventor handler */
1442 pic14_emitInterruptHandler (asmFile);
1444 if (mainf && IFFUNC_HASBODY(mainf->type)) {
1445 /* initialize data memory */
1446 fprintf (asmFile, "code_init\t%s\n", CODE_NAME); // Note - for mplink may have to enlarge section vectors in .lnk file
1447 fprintf (asmFile,"__sdcc_gsinit_startup\n");
1448 /* FIXME: This is temporary. The idata section should be used. If
1449 not, we could add a special feature to the linker. This will
1450 work in the mean time. Put all initalized data in main.c */
1451 copypCode(asmFile, statsg->dbName);
1452 fprintf (asmFile,"\tpagesel _main\n");
1453 fprintf (asmFile,"\tgoto _main\n");
1458 /* copy global & static initialisations */
1459 fprintf (asmFile, "%s", iComments2);
1460 fprintf (asmFile, "; global & static initialisations\n");
1461 fprintf (asmFile, "%s", iComments2);
1462 copypCode(asmFile, statsg->dbName);
1466 /* copy over code */
1467 fprintf (asmFile, "%s", iComments2);
1468 fprintf (asmFile, "; code\n");
1469 fprintf (asmFile, "%s", iComments2);
1470 fprintf (asmFile, "code_%s\t%s\n", moduleName, port->mem.code_name);
1473 copypCode(asmFile, 'X');
1475 /* _main function */
1476 copypCode(asmFile, 'M');
1478 /* other functions */
1479 copypCode(asmFile, code->dbName);
1482 copypCode(asmFile, 'P');
1484 dumppCodeStatistics (asmFile);
1486 fprintf (asmFile,"\tend\n");