1 /*-------------------------------------------------------------------------
3 glue.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"
37 extern symbol *interrupts[256];
38 void pic16_printIval (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p);
42 extern unsigned maxInterrupts;
44 extern char *VersionString;
45 extern struct dbuf_s *codeOutBuf;
46 extern char *iComments1;
47 extern char *iComments2;
50 extern unsigned long pFile_isize;
52 extern unsigned long pic16_countInstructions();
53 set *pic16_localFunctions = NULL;
54 set *rel_idataSymSet=NULL;
55 set *fix_idataSymSet=NULL;
57 extern DEFSETFUNC (closeTmpFiles);
58 extern DEFSETFUNC (rmTmpFiles);
60 extern void pic16_AnalyzeBanking (void);
61 extern void pic16_OptimizeJumps ();
62 extern void pic16_OptimizeBanksel ();
63 extern void pic16_InlinepCode(void);
64 extern void pic16_writeUsedRegs(FILE *);
66 extern void initialComments (FILE * afile);
67 extern void printPublics (FILE * afile);
69 void pic16_pCodeInitRegisters(void);
70 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
71 extern void pic16_pCodeConstString(char *name, char *value, unsigned length);
74 /*-----------------------------------------------------------------*/
75 /* aopLiteral - string from a literal value */
76 /*-----------------------------------------------------------------*/
77 unsigned int pic16aopLiteral (value *val, int offset)
84 /* if it is a float then it gets tricky */
85 /* otherwise it is fairly simple */
86 if (!(IS_FLOAT(val->type) || IS_FIXED(val->type))) {
87 unsigned long v = ulFromVal (val);
89 return ( (v >> (offset * 8)) & 0xff);
92 if(IS_FIXED16X16(val->type)) {
93 unsigned long v = (unsigned long)fixed16x16FromDouble( 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];
110 char tbuffer[512], *tbuf=tbuffer;;
113 /*-----------------------------------------------------------------*/
114 /* emitRegularMap - emit code for maps with no special cases */
115 /*-----------------------------------------------------------------*/
117 pic16emitRegularMap (memmap * map, bool addPublics, bool arFlag)
120 // int i, size, bitvars = 0;;
122 // fprintf(stderr, "%s:%d map name= %s\n", __FUNCTION__, __LINE__, map->sname);
125 dbuf_printf (&map->oBuf, ";\t.area\t%s\n", map->sname);
126 /* print the area name */
128 for (sym = setFirstItem (map->syms); sym; sym = setNextItem (map->syms)) {
131 fprintf(stderr, "%s\t%s: sym: %s\tused: %d\textern: %d\tstatic: %d\taggregate: %d\tregister: 0x%x\tfunction: %d\n",
133 map->sname, sym->name, sym->used, IS_EXTERN(sym->etype), IS_STATIC(sym->etype),
134 IS_AGGREGATE(sym->type), (SPEC_SCLS(sym->etype) == S_REGISTER), IS_FUNC(sym->type));
135 printTypeChain( sym->type, stderr );
136 fprintf(stderr, "\n");
139 /* if extern then add to externs */
140 if (IS_EXTERN (sym->etype)) {
141 /* reduce overhead while linking by not declaring
142 * extern unused external functions (usually declared
143 * in header files) */
144 if(IS_FUNC(sym->type) && !sym->used)continue;
146 /* make sure symbol is not in publics section */
147 if(!checkSym(publics, sym))
148 checkAddSym(&externs, sym);
152 /* if allocation required check is needed
153 * then check if the symbol really requires
154 * allocation only for local variables */
155 if (arFlag && !IS_AGGREGATE (sym->type) &&
156 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
157 !sym->allocreq && sym->level) {
159 // fprintf(stderr, "%s:%d special case, continuing...\n", __FILE__, __LINE__);
164 /* if global variable & not static or extern
165 * and addPublics allowed then add it to the public set */
166 if ((sym->used) && (sym->level == 0 ||
167 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
169 !IS_STATIC (sym->etype) && !IS_FUNC(sym->type)) {
171 checkAddSym(&publics, sym);
174 if(IS_STATIC(sym->etype)
175 && !sym->ival) /* && !sym->level*/ {
180 // debugf("adding symbol %s\n", sym->name);
181 #define SET_IMPLICIT 1
184 if(IS_STRUCT(sym->type))
188 reg = pic16_allocDirReg( operandFromSymbol( sym ));
191 for(ssym=setFirstItem(sectSyms); ssym; ssym=setNextItem(sectSyms)) {
192 if(!strcmp(ssym->name, reg->name))found=1;
196 checkAddReg(&pic16_rel_udata, reg);
199 debugf("Did find %s in pic16_rel_udata already. Check!\n", reg->name);
200 // checkAddSym(&publics, sym);
206 /* if extern then do nothing or is a function
208 if (IS_FUNC (sym->type) && !IS_STATIC(sym->etype)) {
209 if(SPEC_OCLS(sym->etype) == code) {
210 // fprintf(stderr, "%s:%d: symbol added: %s\n", __FILE__, __LINE__, sym->rname);
211 checkAddSym(&publics, sym);
216 /* if is has an absolute address then generate
217 an equate for this no need to allocate space */
218 if (SPEC_ABSA (sym->etype)) {
219 // fprintf (stderr,"; %s == 0x%04x\t\treqv= %p nRegs= %d\n",
220 // sym->name, SPEC_ADDR (sym->etype), sym->reqv, sym->regType);
222 dbuf_printf (&map->oBuf, "%s\tEQU\t0x%04x\n",
224 SPEC_ADDR (sym->etype));
226 /* emit only if it is global */
227 if(sym->level == 0) {
230 reg = pic16_dirregWithName( sym->name );
233 // fprintf(stderr, "%s:%d: implicit add of symbol = %s\n",
234 // __FUNCTION__, __LINE__, sym->name);
236 /* if IS_STRUCT is omitted the following
237 * fixes structures but break char/int etc */
239 if(IS_STRUCT(sym->type))
240 sym->implicit = 1; // mark as implicit
243 reg = pic16_allocDirReg( operandFromSymbol(sym) );
245 if(checkAddReg(&pic16_fix_udata, reg)) {
246 /* and add to globals list if not exist */
247 addSet(&publics, sym);
251 addSet(&publics, sym);
255 if(!sym->used && (sym->level == 0)) {
258 /* symbol not used, just declared probably, but its in
259 * level 0, so we must declare it fine as global */
261 // fprintf(stderr, "EXTRA symbol declaration sym= %s\n", sym->name);
264 if(IS_STRUCT(sym->type))
265 sym->implicit = 1; // mark as implicit
268 if(IS_AGGREGATE(sym->type)) {
269 reg=pic16_allocRegByName(sym->rname, getSize( sym->type ), NULL);
271 reg = pic16_allocDirReg( operandFromSymbol( sym ) );
279 fprintf(stderr, "%s:%d sym->rname: %s reg: %p reg->name: %s\n", __FILE__, __LINE__,
280 sym->rname, reg, (reg?reg->name:"<<NULL>>"));
284 for(ssym=setFirstItem(sectSyms); ssym; ssym=setNextItem(sectSyms)) {
285 if(!strcmp(ssym->name, reg->name))found=1;
289 if(checkAddReg(&pic16_rel_udata, reg)) {
290 addSetHead(&publics, sym);
299 addSetHead(&publics, sym);
304 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
305 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
306 /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
307 if (IS_BITVAR (sym->etype)) {
310 dbuf_printf (map->oBuf, "\t%s\n", sym->rname);
311 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1) {
312 for (i = 1; i < size; i++)
313 dbuf_printf (map->oBuf, "\t%s_%d\n", sym->rname, i);
316 dbuf_printf (map->oBuf, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
320 /* FIXME -- VR Fix the following, so that syms to be placed
321 * in the idata section and let linker decide about their fate */
323 /* if it has an initial value then do it only if
324 it is a global variable */
327 && ((sym->level == 0)
328 || IS_STATIC(sym->etype)) ) {
332 if(SPEC_OCLS(sym->etype)==data) {
333 fprintf(stderr, "%s: sym %s placed in data segment\n", map->sname, sym->name);
336 if(SPEC_OCLS(sym->etype)==code) {
337 fprintf(stderr, "%s: sym %s placed in code segment\n", map->sname, sym->name);
342 fprintf(stderr, "'%s': sym '%s' has initial value SPEC_ABSA: %d, IS_AGGREGATE: %d\n",
343 map->sname, sym->name, SPEC_ABSA(sym->etype), IS_AGGREGATE(sym->type));
346 if (IS_AGGREGATE (sym->type)) {
347 if(SPEC_ABSA(sym->etype))
348 addSet(&fix_idataSymSet, copySymbol(sym));
350 addSet(&rel_idataSymSet, copySymbol(sym));
351 // ival = initAggregates (sym, sym->ival, NULL);
353 if(SPEC_ABSA(sym->etype))
354 addSet(&fix_idataSymSet, copySymbol(sym));
356 addSet(&rel_idataSymSet, copySymbol(sym));
358 // ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
359 // decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
363 setAstFileLine (ival, sym->fileDef, sym->lineDef);
364 codeOutBuf = &statsg->oBuf;
366 eBBlockFromiCode (iCodeFromAst (ival));
374 /*-----------------------------------------------------------------*/
375 /* pic16_initPointer - pointer initialization code massaging */
376 /*-----------------------------------------------------------------*/
378 pic16_initPointer (initList * ilist, sym_link *toType)
384 return valCastLiteral(toType, 0.0);
387 expr = decorateType(resolveSymbols( list2expr (ilist) ), FALSE);
388 // expr = list2expr( ilist );
393 /* try it the old way first */
394 if (expr->etype && (val = constExprValue (expr, FALSE)))
397 /* ( ptr + constant ) */
398 if (IS_AST_OP (expr) &&
399 (expr->opval.op == '+' || expr->opval.op == '-') &&
400 IS_AST_SYM_VALUE (expr->left) &&
401 (IS_ARRAY(expr->left->ftype) || IS_PTR(expr->left->ftype)) &&
402 compareType(toType, expr->left->ftype) &&
403 IS_AST_LIT_VALUE (expr->right)) {
404 return valForCastAggr (expr->left, expr->left->ftype,
410 if (IS_AST_OP(expr) && expr->opval.op==CAST &&
411 IS_AST_OP(expr->right) && expr->right->opval.op=='&') {
412 if (compareType(toType, expr->left->ftype)!=1) {
413 werror (W_INIT_WRONG);
414 printFromToType(expr->left->ftype, toType);
420 /* no then we have to do these cludgy checks */
421 /* pointers can be initialized with address of
422 a variable or address of an array element */
423 if (IS_AST_OP (expr) && expr->opval.op == '&') {
424 /* address of symbol */
425 if (IS_AST_SYM_VALUE (expr->left) && expr->left->etype) {
426 val = AST_VALUE (expr->left);
427 val->type = newLink (DECLARATOR);
428 if(SPEC_SCLS (expr->left->etype) == S_CODE) {
429 DCL_TYPE (val->type) = CPOINTER;
430 DCL_PTR_CONST (val->type) = port->mem.code_ro;
432 else if (SPEC_SCLS (expr->left->etype) == S_XDATA)
433 DCL_TYPE (val->type) = FPOINTER;
434 else if (SPEC_SCLS (expr->left->etype) == S_XSTACK)
435 DCL_TYPE (val->type) = PPOINTER;
436 else if (SPEC_SCLS (expr->left->etype) == S_IDATA)
437 DCL_TYPE (val->type) = IPOINTER;
438 else if (SPEC_SCLS (expr->left->etype) == S_EEPROM)
439 DCL_TYPE (val->type) = EEPPOINTER;
441 DCL_TYPE (val->type) = POINTER;
443 val->type->next = expr->left->ftype;
444 val->etype = getSpec (val->type);
448 /* if address of indexed array */
449 if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
450 return valForArray (expr->left);
452 /* if address of structure element then
454 if (IS_AST_OP (expr->left) &&
455 expr->left->opval.op == '.') {
456 return valForStructElem (expr->left->left,
461 (&some_struct)->element */
462 if (IS_AST_OP (expr->left) &&
463 expr->left->opval.op == PTR_OP &&
464 IS_ADDRESS_OF_OP (expr->left->left)) {
465 return valForStructElem (expr->left->left->left,
469 /* case 3. (((char *) &a) +/- constant) */
470 if (IS_AST_OP (expr) &&
471 (expr->opval.op == '+' || expr->opval.op == '-') &&
472 IS_AST_OP (expr->left) && expr->left->opval.op == CAST &&
473 IS_AST_OP (expr->left->right) &&
474 expr->left->right->opval.op == '&' &&
475 IS_AST_LIT_VALUE (expr->right)) {
477 return valForCastAggr (expr->left->right->left,
478 expr->left->left->opval.lnk,
479 expr->right, expr->opval.op);
482 /* case 4. (char *)(array type) */
483 if (IS_CAST_OP(expr) && IS_AST_SYM_VALUE (expr->right) &&
484 IS_ARRAY(expr->right->ftype)) {
486 val = copyValue (AST_VALUE (expr->right));
487 val->type = newLink (DECLARATOR);
488 if (SPEC_SCLS (expr->right->etype) == S_CODE) {
489 DCL_TYPE (val->type) = CPOINTER;
490 DCL_PTR_CONST (val->type) = port->mem.code_ro;
492 else if (SPEC_SCLS (expr->right->etype) == S_XDATA)
493 DCL_TYPE (val->type) = FPOINTER;
494 else if (SPEC_SCLS (expr->right->etype) == S_XSTACK)
495 DCL_TYPE (val->type) = PPOINTER;
496 else if (SPEC_SCLS (expr->right->etype) == S_IDATA)
497 DCL_TYPE (val->type) = IPOINTER;
498 else if (SPEC_SCLS (expr->right->etype) == S_EEPROM)
499 DCL_TYPE (val->type) = EEPPOINTER;
501 DCL_TYPE (val->type) = POINTER;
502 val->type->next = expr->right->ftype->next;
503 val->etype = getSpec (val->type);
509 werrorfl (expr->filename, expr->lineno, E_INCOMPAT_PTYPES);
511 werror (E_INCOMPAT_PTYPES);
517 /*-----------------------------------------------------------------*/
518 /* printPointerType - generates ival for pointer type */
519 /*-----------------------------------------------------------------*/
521 _pic16_printPointerType (const char *name, char ptype, void *p)
525 sprintf (buf, "LOW(%s)", name);
526 pic16_emitDS (buf, ptype, p);
527 sprintf (buf, "HIGH(%s)", name);
528 pic16_emitDS (buf, ptype, p);
531 /*-----------------------------------------------------------------*/
532 /* printPointerType - generates ival for pointer type */
533 /*-----------------------------------------------------------------*/
535 pic16_printPointerType (const char *name, char ptype, void *p)
537 _pic16_printPointerType (name, ptype, p);
538 //pic16_flushDB(ptype, p); /* breaks char* const arr[] = {&c, &c, &c}; */
541 /*-----------------------------------------------------------------*/
542 /* printGPointerType - generates ival for generic pointer type */
543 /*-----------------------------------------------------------------*/
545 pic16_printGPointerType (const char *iname, const unsigned int itype,
550 _pic16_printPointerType (iname, ptype, p);
554 case CPOINTER: /* fall through */
555 case FUNCTION: /* fall through */
557 /* GPTRs pointing to __data space should be reported as POINTERs */
558 sprintf (buf, "UPPER(%s)", iname);
559 pic16_emitDS (buf, ptype, p);
562 case POINTER: /* fall through */
563 case FPOINTER: /* fall through */
564 case IPOINTER: /* fall through */
565 case PPOINTER: /* __data space */
566 sprintf (buf, "0x%02x", GPTR_TAG_DATA);
567 pic16_emitDS (buf, ptype, p);
571 debugf ("itype = %d\n", itype );
575 if (itype == GPOINTER) {
576 fprintf(stderr, "%s: initialized generic pointer with unknown storage class assumes object in code space\n", __func__);
579 //pic16_flushDB(ptype, p); /* might break char* const arr[] = {...}; */
583 /* set to 0 to disable debug messages */
584 #define DEBUG_PRINTIVAL 0
586 /*-----------------------------------------------------------------*/
587 /* pic16_printIvalType - generates ival for int/char */
588 /*-----------------------------------------------------------------*/
590 pic16_printIvalType (symbol *sym, sym_link * type, initList * ilist, char ptype, void *p)
595 // fprintf(stderr, "%s for symbol %s\n",__FUNCTION__, sym->rname);
598 fprintf(stderr, "%s\n",__FUNCTION__);
602 /* if initList is deep */
603 if (ilist && ilist->type == INIT_DEEP)
604 ilist = ilist->init.deep;
606 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
607 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
610 if (!(val = list2val (ilist))) {
611 // assuming a warning has been thrown
612 val = constCharVal (0);
615 if (val->type != type) {
616 val = valCastLiteral(type, floatFromVal(val));
619 for (i = 0; i < getSize (type); i++) {
620 pic16_emitDB(pic16aopLiteral(val, i), ptype, p);
624 /*--------------------------------------------------------------------*/
625 /* pic16_printIvalChar - generates initital value for character array */
626 /*--------------------------------------------------------------------*/
628 pic16_printIvalChar (symbol *sym, sym_link * type, initList * ilist, char *s, char ptype, void *p)
631 int remain, len, ilen;
637 fprintf(stderr, "%s\n",__FUNCTION__);
641 val = list2val (ilist);
643 /* if the value is a character string */
644 if(IS_ARRAY (val->type) && IS_CHAR (val->etype)) {
645 /* length of initializer string (might contain \0, so do not use strlen) */
646 ilen = DCL_ELEM(val->type);
649 /* This causes structflexarray.c to fail. */
651 DCL_ELEM (type) = ilen;
654 /* len is 0 if declartion equals initializer,
655 * >0 if declaration greater than initializer
656 * <0 if declaration less than initializer
657 * Strategy: if >0 emit 0x00 for the rest of the length,
658 * if <0 then emit only the length of declaration elements
661 len = DCL_ELEM (type) - ilen;
663 // fprintf(stderr, "%s:%d ilen = %i len = %i DCL_ELEM(type) = %i SPEC_CVAL-len = %i\n", __FILE__, __LINE__,
664 // ilen, len, DCL_ELEM(type), strlen(SPEC_CVAL(val->etype).v_char));
667 /* emit initializer */
668 for(remain=0; remain<ilen; remain++) {
669 pic16_emitDB(SPEC_CVAL(val->etype).v_char[ remain ], ptype, p);
672 /* fill array with 0x00 */
674 pic16_emitDB(0x00, ptype, p);
676 } else if (!DCL_ELEM (type)) {
677 // flexible arrays: char str[] = "something"; */
678 for(remain=0; remain<ilen; remain++) {
679 pic16_emitDB(SPEC_CVAL(val->etype).v_char[ remain ], ptype, p);
682 werror (W_EXCESS_INITIALIZERS, "array of chars", sym->name, sym->lineDef);
683 for(remain=0; remain<DCL_ELEM (type); remain++) {
684 pic16_emitDB(SPEC_CVAL(val->etype).v_char[ remain ], ptype, p);
689 // if((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0) {
694 for(remain=0; remain<strlen(s); remain++) {
695 pic16_emitDB(s[remain], ptype, p);
701 /*-----------------------------------------------------------------*/
702 /* pic16_printIvalArray - generates code for array initialization */
703 /*-----------------------------------------------------------------*/
705 pic16_printIvalArray (symbol * sym, sym_link * type, initList * ilist,
709 int lcnt = 0, size = 0;
716 fprintf(stderr, "%s\n",__FUNCTION__);
718 /* take care of the special case */
719 /* array of characters can be init */
721 if (IS_CHAR (type->next) && ilist) {
722 if (!IS_LITERAL(list2val(ilist)->etype)) {
723 werror (W_INIT_WRONG);
727 if(pic16_printIvalChar (sym, type,
728 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
729 SPEC_CVAL (sym->etype).v_char, ptype, p))
732 /* not the special case */
733 if (ilist && ilist->type != INIT_DEEP)
735 werror (E_INIT_STRUCT, sym->name);
739 iloop = (ilist ? ilist->init.deep : NULL);
740 lcnt = DCL_ELEM (type);
745 pic16_printIval (sym, type->next, iloop, ptype, p);
746 iloop = (iloop ? iloop->next : NULL);
749 /* if not array limits given & we */
750 /* are out of initialisers then */
751 if (!DCL_ELEM (type) && !iloop)
754 /* no of elements given and we */
755 /* have generated for all of them */
757 /* if initializers left */
759 werror (W_EXCESS_INITIALIZERS, "array", sym->name, sym->lineDef);
766 /* This causes bug #1843745. */
767 /* if we have not been given a size */
768 if (!DCL_ELEM (type))
769 DCL_ELEM (type) = size;
775 /*-----------------------------------------------------------------*/
776 /* pic16_printIvalBitFields - generate initializer for bitfields */
777 /*-----------------------------------------------------------------*/
779 pic16_printIvalBitFields(symbol **sym, initList **ilist, char ptype, void *p)
783 initList *lilist = *ilist ;
784 unsigned long ival = 0;
790 fprintf(stderr, "%s\n",__FUNCTION__);
795 val = list2val(lilist);
797 if (SPEC_BLEN(lsym->etype) > 8) {
798 size += ((SPEC_BLEN (lsym->etype) / 8) +
799 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
802 size = ((SPEC_BLEN (lsym->etype) / 8) +
803 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
806 i <<= SPEC_BSTR (lsym->etype);
808 if (! ( lsym->next &&
809 (lilist && lilist->next) &&
810 (IS_BITFIELD(lsym->next->type)) &&
811 (SPEC_BSTR(lsym->next->etype)))) break;
813 lilist = lilist->next;
816 for (i = 0; i < size; i++) {
817 pic16_emitDB(BYTE_IN_LONG(ival, i), ptype, p);
825 /*-----------------------------------------------------------------*/
826 /* printIvalStruct - generates initial value for structures */
827 /*-----------------------------------------------------------------*/
829 pic16_printIvalStruct (symbol * sym, sym_link * type,
830 initList * ilist, char ptype, void *p)
833 initList *iloop = NULL;
837 fprintf(stderr, "%s\n",__FUNCTION__);
840 sflds = SPEC_STRUCT (type)->fields;
843 if (ilist->type != INIT_DEEP) {
844 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
848 iloop = ilist->init.deep;
851 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
852 // fprintf(stderr, "%s:%d sflds: %p\tiloop = %p\n", __FILE__, __LINE__, sflds, iloop);
853 if (IS_BITFIELD(sflds->type)) {
854 pic16_printIvalBitFields(&sflds, &iloop, ptype, p);
856 pic16_printIval (sym, sflds->type, iloop, ptype, p);
860 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
865 /*-----------------------------------------------------------------*/
866 /* printIvalUnion - generates initial value for unions */
867 /*-----------------------------------------------------------------*/
869 pic16_printIvalUnion (symbol * sym, sym_link * type,
870 initList * ilist, char ptype, void *p)
873 initList *iloop = NULL;
875 symbol *sflds = NULL;
878 fprintf(stderr, "%s\n",__FUNCTION__);
883 sflds = SPEC_STRUCT (type)->fields;
886 if (ilist->type != INIT_DEEP) {
887 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
891 iloop = ilist->init.deep;
894 size = SPEC_STRUCT(type)->size;
895 sflds = SPEC_STRUCT(type)->fields;
896 pic16_printIval (sym, sflds->type, iloop, ptype, p);
898 /* if the first field is not the longest, fill with 0s */
899 while (size > getSize (sflds->type)) {
900 pic16_emitDB(0, ptype, p);
906 pic16_isUnion( symbol *sym, sym_link *type )
908 if (type && SPEC_STRUCT(type)->type == UNION) return 1;
912 /*--------------------------------------------------------------------------*/
913 /* pic16_printIvalCharPtr - generates initial values for character pointers */
914 /*--------------------------------------------------------------------------*/
916 pic16_printIvalCharPtr (symbol * sym, sym_link * type, value * val, char ptype, void *p)
920 /* PENDING: this is _very_ mcs51 specific, including a magic
922 It's also endin specific.
924 VR - Attempting to port this function to pic16 port - 8-Jun-2004
929 fprintf(stderr, "%s\n",__FUNCTION__);
932 size = getSize (type);
934 if (val->name && strlen (val->name))
936 if (size == 1) /* This appears to be Z80 specific?? */
938 pic16_emitDS(val->name, ptype, p);
942 pic16_printPointerType (val->name, ptype, p);
947 type = PTR_TYPE (SPEC_OCLS (val->etype));
948 if (val->sym && val->sym->isstrlit) {
949 // this is a literal string
952 pic16_printGPointerType(val->name, type, ptype, p);
956 fprintf (stderr, "*** internal error: unknown size in "
957 "printIvalCharPtr.\n");
963 // these are literals assigned to pointers
967 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
970 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
971 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
974 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
975 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
976 pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
984 if (val->sym && val->sym->isstrlit) { // && !isinSet(statsg->syms, val->sym)) {
985 if(ptype == 'p' && !isinSet(statsg->syms, val->sym))addSet (&statsg->syms, val->sym);
986 else if(ptype == 'f' /*&& !isinSet(rel_idataSymSet, val->sym)*/)addSet(&rel_idataSymSet, val->sym);
992 /*-----------------------------------------------------------------------*/
993 /* pic16_printIvalFuncPtr - generate initial value for function pointers */
994 /*-----------------------------------------------------------------------*/
996 pic16_printIvalFuncPtr (sym_link * type, initList * ilist, char ptype, void *p)
1003 fprintf(stderr, "%s\n",__FUNCTION__);
1007 val = list2val (ilist);
1009 val = valCastLiteral(type, 0.0);
1012 // an error has been thrown already
1013 val = constCharVal (0);
1016 if (IS_LITERAL(val->etype)) {
1017 if (0 && compareType(type, val->etype) == 0) {
1018 werrorfl (ilist->filename, ilist->lineno, E_INCOMPAT_TYPES);
1019 printFromToType (val->type, type);
1021 pic16_printIvalCharPtr (NULL, type, val, ptype, p);
1025 /* check the types */
1026 if ((dLvl = compareType (val->type, type->next)) <= 0)
1028 pic16_emitDB(0x00, ptype, p);
1032 /* now generate the name */
1034 pic16_printGPointerType (val->name, CPOINTER /*DCL_TYPE(val->type)*/, ptype, p);
1036 pic16_printGPointerType (val->sym->rname, CPOINTER /*DCL_TYPE(val->type)*/, ptype, p);
1038 if(IS_FUNC(val->sym->type) && !val->sym->used && !IS_STATIC(val->sym->etype)) {
1040 if(!checkSym(publics, val->sym))
1041 if(checkAddSym(&externs, val->sym) && (ptype == 'f')) {
1042 /* this has not been declared as extern
1043 * so declare it as a 'late extern' just after the symbol */
1044 fprintf((FILE *)p, ";\tdeclare symbol as extern\n");
1045 fprintf((FILE *)p, "\textern\t%s\n", val->sym->rname);
1046 fprintf((FILE *)p, ";\tcontinue variable declaration\n");
1055 /*-----------------------------------------------------------------*/
1056 /* pic16_printIvalPtr - generates initial value for pointers */
1057 /*-----------------------------------------------------------------*/
1059 pic16_printIvalPtr (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p)
1065 fprintf(stderr, "%s:%d initialising pointer: %s size: %d\n", __FILE__, __LINE__,
1066 sym->rname, getSize(sym->type));
1070 if (ilist && (ilist->type == INIT_DEEP))
1071 ilist = ilist->init.deep;
1073 /* function pointer */
1074 if (IS_FUNC (type->next))
1076 pic16_printIvalFuncPtr (type, ilist, ptype, p);
1080 if (!(val = pic16_initPointer (ilist, type)))
1083 /* if character pointer */
1084 if (IS_CHAR (type->next))
1085 if (pic16_printIvalCharPtr (sym, type, val, ptype, p))
1088 /* check the type */
1089 if (compareType (type, val->type) == 0) {
1090 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
1091 printFromToType (val->type, type);
1094 /* if val is literal */
1095 if (IS_LITERAL (val->etype))
1097 switch (getSize (type))
1100 pic16_emitDB((unsigned int) ulFromVal (val) & 0xff, ptype, p);
1103 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
1104 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
1107 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
1108 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
1109 pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
1112 fprintf(stderr, "%s:%d size = %d\n", __FILE__, __LINE__, getSize(type));
1119 size = getSize (type);
1121 if (size == 1) /* Z80 specific?? */
1123 pic16_emitDS(val->name, ptype, p);
1127 pic16_printPointerType (val->name, ptype, p);
1132 itype = PTR_TYPE (SPEC_OCLS (val->etype));
1133 pic16_printGPointerType (val->name, itype, ptype, p);
1141 /*-----------------------------------------------------------------*/
1142 /* pic16_printIval - generates code for initial value */
1143 /*-----------------------------------------------------------------*/
1144 void pic16_printIval (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p)
1152 fprintf(stderr, "%s:%d generating init for %s\n", __FILE__, __LINE__, sym->name);
1153 fprintf(stderr, "%s: IS_STRUCT: %d IS_ARRAY: %d IS_PTR: %d IS_SPEC: %d\n", sym->name,
1154 IS_STRUCT(type), IS_ARRAY(type), IS_PTR(type), IS_SPEC(type));
1157 /* if structure then */
1158 if (IS_STRUCT (type))
1160 if (pic16_isUnion(sym, type))
1162 //fprintf(stderr,"%s union\n",__FUNCTION__);
1163 pic16_printIvalUnion (sym, type, ilist, ptype, p);
1165 //fprintf(stderr,"%s struct\n",__FUNCTION__);
1166 pic16_printIvalStruct (sym, type, ilist, ptype, p);
1171 /* if this is an array */
1172 if (IS_ARRAY (type))
1174 // fprintf(stderr,"%s array\n",__FUNCTION__);
1175 pic16_printIvalArray (sym, type, ilist, ptype, p);
1182 // not an aggregate, ilist must be a node
1183 if (ilist->type!=INIT_NODE) {
1184 // or a 1-element list
1185 if (ilist->init.deep->next) {
1186 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar",
1189 ilist=ilist->init.deep;
1194 // and the type must match
1195 itype=ilist->init.node->ftype;
1197 if (compareType(type, itype)==0) {
1198 // special case for literal strings
1199 if (IS_ARRAY (itype) && IS_CHAR (getSpec(itype)) &&
1200 // which are really code pointers
1201 IS_PTR(type) && DCL_TYPE(type)==CPOINTER) {
1204 // werrorfl (ilist->filename, ilist->lineno, E_TYPE_MISMATCH, "assignment", " ");
1205 // printFromToType(itype, type);
1212 /* if this is a pointer */
1215 // fprintf(stderr,"%s pointer\n",__FUNCTION__);
1216 pic16_printIvalPtr (sym, type, ilist, ptype, p);
1221 /* if type is SPECIFIER */
1224 // fprintf(stderr,"%s spec\n",__FUNCTION__);
1225 pic16_printIvalType (sym, type, ilist, ptype, p);
1231 PIC16_IS_CONFIG_ADDRESS(int address)
1233 return ((address >= pic16->cwInfo.confAddrStart && address <= pic16->cwInfo.confAddrEnd));
1237 PIC16_IS_IDLOC_ADDRESS(int address)
1239 return ((address >= pic16->idInfo.idAddrStart && address <= pic16->idInfo.idAddrEnd));
1242 /*-----------------------------------------------------------------*/
1243 /* emitStaticSeg - emitcode for the static segment */
1244 /*-----------------------------------------------------------------*/
1246 pic16emitStaticSeg (memmap * map)
1249 static int didcode=0;
1251 //fprintf(stderr, "%s\n",__FUNCTION__);
1255 /* for all variables in this segment do */
1256 for (sym = setFirstItem (map->syms); sym;
1257 sym = setNextItem (map->syms))
1261 fprintf(stderr, "%s\t%s: sym: %s\tused: %d\tSPEC_ABSA: %d\tSPEC_AGGREGATE: %d\tCODE: %d\n\
1262 CODESPACE: %d\tCONST: %d\tPTRCONST: %d\tSPEC_CONST: %d\n", __FUNCTION__,
1263 map->sname, sym->name, sym->used, SPEC_ABSA(sym->etype), IS_AGGREGATE(sym->type),
1264 IS_CODE(sym->etype), IN_CODESPACE( SPEC_OCLS(sym->etype)), IS_CONSTANT(sym->etype),
1265 IS_PTR_CONST(sym->etype), SPEC_CONST(sym->etype));
1266 printTypeChain( sym->type, stderr );
1267 fprintf(stderr, "\n");
1270 if(SPEC_ABSA(sym->etype) && PIC16_IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype))) {
1271 pic16_assignConfigWordValue(SPEC_ADDR(sym->etype),
1272 (int) ulFromVal (list2val(sym->ival)));
1277 if(SPEC_ABSA(sym->etype) && PIC16_IS_IDLOC_ADDRESS(SPEC_ADDR(sym->etype))) {
1278 pic16_assignIdByteValue(SPEC_ADDR(sym->etype),
1279 (char) ulFromVal (list2val(sym->ival)));
1284 /* if it is "extern" then do nothing */
1285 if (IS_EXTERN (sym->etype)/* && !SPEC_ABSA(sym->etype)*/) {
1286 checkAddSym(&externs, sym);
1290 /* if it is not static add it to the public
1292 if (!IS_STATIC (sym->etype)) {
1293 /* do not emit if it is a config word declaration */
1294 checkAddSym(&publics, sym);
1297 /* print extra debug info if required */
1298 if (options.debug || sym->level == 0) {
1299 /* NOTE to me - cdbFile may be null in which case,
1300 * the sym name will be printed to stdout. oh well */
1301 debugFile->writeSymbol(sym);
1304 /* if it has an absolute address */
1305 if (SPEC_ABSA (sym->etype)) {
1306 // fprintf(stderr, "%s:%d spec_absa is true for symbol: %s\n",
1307 // __FILE__, __LINE__, sym->name);
1309 /* if it has an initial value */
1317 /* symbol has absolute address and initial value */
1319 resolveIvalSym (sym->ival, sym->type);
1320 asym = newSymbol(sym->rname, 0);
1321 abSym = Safe_calloc(1, sizeof(absSym));
1322 strcpy(abSym->name, sym->rname);
1323 abSym->address = SPEC_ADDR( sym->etype );
1324 addSet(&absSymSet, abSym);
1326 pb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute Ival"));
1327 pic16_addpBlock(pb);
1329 pcf = pic16_newpCodeFunction(moduleName, asym->name);
1330 PCF(pcf)->absblock = 1;
1332 pic16_addpCode2pBlock(pb,pcf);
1333 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
1334 //fprintf(stderr, "%s:%d [1] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1335 pic16_printIval(sym, sym->type, sym->ival, 'p', (void *)pb);
1336 pic16_flushDB('p', (void *)pb);
1338 pic16_addpCode2pBlock(pb, pic16_newpCodeFunction(NULL, NULL));
1344 /* symbol has absolute address but no initial value */
1346 /* allocate space */
1347 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
1349 /* special case for character strings */
1350 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1351 SPEC_CVAL (sym->etype).v_char) {
1353 // fprintf(stderr, "%s:%d printing code string from %s\n", __FILE__, __LINE__, sym->rname);
1355 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char, getSize(sym->type));
1357 fprintf (stderr, "%s:%u(%s): do not know how to intialize symbol %s\n", __FILE__, __LINE__, __FUNCTION__, sym->rname);
1363 // fprintf(stderr, "%s:%d spec_absa is false for symbol: %s\n",
1364 // __FILE__, __LINE__, sym->name);
1367 /* if it has an initial value */
1371 /* symbol doesn't have absolute address but has initial value */
1372 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
1374 resolveIvalSym (sym->ival, sym->type);
1376 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block for Ival"));
1377 pic16_addpBlock(pb);
1380 /* make sure that 'code' directive is emitted before, once */
1381 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir("code", NULL));
1386 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
1387 //fprintf(stderr, "%s:%d [2] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1388 pic16_printIval(sym, sym->type, sym->ival, 'p', (void *)pb);
1389 pic16_flushDB('p', (void *)pb);
1393 /* symbol doesn't have absolute address and no initial value */
1394 /* allocate space */
1395 // fprintf(stderr, "%s:%d [3] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1396 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
1397 /* special case for character strings */
1398 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1399 SPEC_CVAL (sym->etype).v_char) {
1401 // fprintf(stderr, "%s:%d printing code string for %s\n", __FILE__, __LINE__, sym->rname);
1403 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char, getSize(sym->type));
1414 /*-----------------------------------------------------------------*/
1415 /* pic16_emitConfigRegs - emits the configuration registers */
1416 /*-----------------------------------------------------------------*/
1417 void pic16_emitConfigRegs(FILE *of)
1421 for(i=0;i<=(pic16->cwInfo.confAddrEnd-pic16->cwInfo.confAddrStart);i++)
1422 if(pic16->cwInfo.crInfo[i].emit) //mask != -1)
1423 fprintf (of, "\t__config 0x%x, 0x%hhx\n",
1424 pic16->cwInfo.confAddrStart+i,
1425 pic16->cwInfo.crInfo[i].value);
1428 void pic16_emitIDRegs(FILE *of)
1432 for(i=0;i<=(pic16->idInfo.idAddrEnd-pic16->idInfo.idAddrStart);i++)
1433 if(pic16->idInfo.irInfo[i].emit)
1434 fprintf (of, "\t__idlocs 0x%06x, 0x%hhx\n",
1435 pic16->idInfo.idAddrStart+i,
1436 pic16->idInfo.irInfo[i].value);
1443 /* no special considerations for the following
1444 data, idata & bit & xdata */
1445 pic16emitRegularMap (data, TRUE, TRUE);
1446 pic16emitRegularMap (idata, TRUE, TRUE);
1447 pic16emitRegularMap (bit, TRUE, FALSE);
1448 pic16emitRegularMap (xdata, TRUE, TRUE);
1449 pic16emitRegularMap (sfr, FALSE, FALSE);
1450 pic16emitRegularMap (sfrbit, FALSE, FALSE);
1451 pic16emitRegularMap (code, TRUE, FALSE);
1452 pic16emitStaticSeg (statsg);
1453 pic16emitStaticSeg (c_abs);
1456 /*-----------------------------------------------------------------*/
1457 /* createInterruptVect - creates the interrupt vector */
1458 /*-----------------------------------------------------------------*/
1460 pic16createInterruptVect (struct dbuf_s * vBuf)
1462 /* if the main is only a prototype ie. no body then do nothing */
1464 if (!IFFUNC_HASBODY(mainf->type)) {
1465 /* if ! compile only then main function should be present */
1466 if (!options.cc_only)
1472 if((!pic16_options.omit_ivt) || (pic16_options.omit_ivt && pic16_options.leave_reset)) {
1473 dbuf_printf (vBuf, ";\t.area\t%s\n", CODE_NAME);
1474 dbuf_printf (vBuf, ".intvecs\tcode\t0x%06x\n", pic16_options.ivt_loc);
1476 /* this is an overkill since WE are the port,
1477 * and we know if we have a genIVT function! */
1479 port->genIVT(vFile, interrupts, maxInterrupts);
1487 /*-----------------------------------------------------------------*/
1488 /* pic16initialComments - puts in some initial comments */
1489 /*-----------------------------------------------------------------*/
1491 pic16initialComments (FILE * afile)
1493 initialComments (afile);
1494 fprintf (afile, "; PIC16 port for the Microchip 16-bit core micros\n");
1495 if (pic16_options.xinst) {
1496 fprintf (afile, "; * Extended Instruction Set\n");
1499 if (pic16_mplab_comp) {
1500 fprintf(afile, "; * MPLAB/MPASM/MPASMWIN/MPLINK compatibility mode enabled\n");
1502 fprintf (afile, iComments2);
1504 if (options.debug) {
1505 fprintf (afile, "\n\t.ident \"SDCC version %s #%s [pic16 port]%s\"\n",
1506 SDCC_VERSION_STR, getBuildNumber(), (!pic16_options.xinst?"":" {extended}") );
1511 pic16_stringInSet(const char *str, set **world, int autoAdd)
1518 for (s = setFirstItem(*world); s; s = setNextItem(*world))
1521 if (0 == strcmp(s, str)) return 1;
1525 if (autoAdd) addSet(world, Safe_strdup(str));
1530 pic16_emitSymbolIfNew(FILE *file, const char *fmt, const char *sym, int checkLocals)
1532 static set *emitted = NULL;
1534 if (!pic16_stringInSet(sym, &emitted, 1)) {
1535 /* sym was not in emittedSymbols */
1536 if (!checkLocals || !pic16_stringInSet(sym, &pic16_localFunctions, 0)) {
1537 /* sym is not a locally defined function---avoid bug #1443651 */
1538 fprintf( file, fmt, sym );
1545 /*-----------------------------------------------------------------*/
1546 /* printPublics - generates global declarations for publics */
1547 /*-----------------------------------------------------------------*/
1549 pic16printPublics (FILE *afile)
1553 fprintf (afile, "\n%s", iComments2);
1554 fprintf (afile, "; public variables in this module\n");
1555 fprintf (afile, "%s", iComments2);
1557 for(sym = setFirstItem (publics); sym; sym = setNextItem (publics))
1559 if(!IS_STATIC(sym->etype))
1560 pic16_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1563 /*-----------------------------------------------------------------*/
1564 /* printExterns - generates extern declarations for externs */
1565 /*-----------------------------------------------------------------*/
1567 pic16_printExterns(FILE *afile)
1571 /* print nothing if no externs to declare */
1572 if(!elementsInSet(externs) && !elementsInSet(pic16_builtin_functions))
1575 fprintf(afile, "\n%s", iComments2);
1576 fprintf(afile, "; extern variables in this module\n");
1577 fprintf(afile, "%s", iComments2);
1579 for(sym = setFirstItem(externs); sym; sym = setNextItem(externs))
1580 pic16_emitSymbolIfNew(afile, "\textern %s\n", sym->rname, 1);
1582 for(sym = setFirstItem(pic16_builtin_functions); sym; sym = setNextItem(pic16_builtin_functions))
1583 pic16_emitSymbolIfNew(afile, "\textern _%s\n", sym->name, 1);
1586 /*-----------------------------------------------------------------*/
1587 /* emitOverlay - will emit code for the overlay stuff */
1588 /*-----------------------------------------------------------------*/
1590 pic16emitOverlay (struct dbuf_s *aBuf)
1594 if (!elementsInSet (ovrSetSets))
1595 dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name);
1597 /* for each of the sets in the overlay segment do */
1598 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1599 ovrset = setNextItem (ovrSetSets))
1604 if (elementsInSet (ovrset))
1606 /* this dummy area is used to fool the assembler
1607 otherwise the assembler will append each of these
1608 declarations into one chunk and will not overlay
1610 dbuf_printf (aBuf, ";\t.area _DUMMY\n");
1611 /* output the area informtion */
1612 dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1615 for (sym = setFirstItem (ovrset); sym;
1616 sym = setNextItem (ovrset))
1619 /* if extern then do nothing */
1620 if (IS_EXTERN (sym->etype))
1623 /* if allocation required check is needed
1624 then check if the symbol really requires
1625 allocation only for local variables */
1626 if (!IS_AGGREGATE (sym->type) &&
1627 !(sym->_isparm && !IS_REGPARM (sym->etype))
1628 && !sym->allocreq && sym->level)
1631 /* if global variable & not static or extern
1632 and addPublics allowed then add it to the public set */
1633 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1634 && !IS_STATIC (sym->etype)) {
1635 // fprintf(stderr, "%s:%d %s accessed\n", __FILE__, __LINE__, __FUNCTION__);
1636 checkAddSym(&publics, sym);
1637 // addSetHead (&publics, sym);
1640 /* if extern then do nothing or is a function
1642 if (IS_FUNC (sym->type))
1646 /* if is has an absolute address then generate
1647 an equate for this no need to allocate space */
1648 if (SPEC_ABSA (sym->etype))
1651 if (options.debug || sym->level == 0)
1652 dbuf_printf (aBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1654 dbuf_printf (aBuf, "%s\t=\t0x%04x\n",
1656 SPEC_ADDR (sym->etype));
1660 if (options.debug || sym->level == 0)
1661 dbuf_printf (aBuf, "==.\n");
1663 /* allocate space */
1664 dbuf_printf (aBuf, "%s:\n", sym->rname);
1665 dbuf_printf (aBuf, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1673 emitStatistics(FILE *asmFile)
1675 unsigned long isize, udsize, ramsize;
1676 statistics.isize = pic16_countInstructions();
1677 isize = (statistics.isize >= 0) ? statistics.isize : 0;
1678 udsize = (statistics.udsize >= 0) ? statistics.udsize : 0;
1679 ramsize = pic16 ? pic16->RAMsize : 0x200;
1680 ramsize -= 256; /* ignore access bank and SFRs */
1681 if (ramsize == 0) ramsize = 64; /* prevent division by zero (below) */
1683 fprintf (asmFile, "\n\n; Statistics:\n");
1684 fprintf (asmFile, "; code size:\t%5ld (0x%04lx) bytes (%5.2f%%)\n; \t%5ld (0x%04lx) words\n",
1685 isize, isize, (isize*100.0)/(128UL << 10),
1686 isize>>1, isize>>1);
1687 fprintf (asmFile, "; udata size:\t%5ld (0x%04lx) bytes (%5.2f%%)\n",
1688 udsize, udsize, (udsize*100.0) / (1.0 * ramsize));
1689 fprintf (asmFile, "; access size:\t%5ld (0x%04lx) bytes\n",
1690 statistics.intsize, statistics.intsize);
1692 fprintf (asmFile, "\n\n");
1697 /*-----------------------------------------------------------------*/
1698 /* glue - the final glue that hold the whole thing together */
1699 /*-----------------------------------------------------------------*/
1704 struct dbuf_s ovrBuf;
1707 dbuf_init(&ovrBuf, 4096);
1708 dbuf_init(&vBuf, 4096);
1710 mainf = newSymbol ("main", 0);
1713 mainf = findSymWithLevel(SymbolTab, mainf);
1715 pic16_pCodeInitRegisters();
1717 if(pic16_options.no_crt && mainf && IFFUNC_HASBODY(mainf->type)) {
1718 pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
1720 pic16_addpBlock(pb);
1722 /* entry point @ start of CSEG */
1723 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup",-1));
1726 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1727 pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("_stack_end"))));
1728 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1729 pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("_stack_end"))));
1732 /* put in the call to main */
1733 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
1735 if (options.mainreturn) {
1736 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
1737 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
1739 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
1740 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
1744 /* At this point we've got all the code in the form of pCode structures */
1745 /* Now it needs to be rearranged into the order it should be placed in the */
1748 pic16_movepBlock2Head('P'); // Last
1749 pic16_movepBlock2Head(code->dbName);
1750 pic16_movepBlock2Head('X');
1751 pic16_movepBlock2Head(statsg->dbName); // First
1753 /* print the global struct definitions */
1755 /* PENDING: this isnt the best place but it will do */
1756 if (port->general.glue_up_main) {
1757 /* create the interrupt vector table */
1758 pic16createInterruptVect (&vBuf);
1761 /* emit code for the all the variables declared */
1764 /* do the overlay segments */
1765 pic16emitOverlay(&ovrBuf);
1766 pic16_AnalyzepCode('*');
1769 if(pic16_options.dumpcalltree) {
1772 sprintf(buffer, dstFileName);
1773 strcat(buffer, ".calltree");
1774 cFile = fopen(buffer, "w");
1775 pic16_printCallTree( cFile );
1780 pic16_InlinepCode();
1781 pic16_AnalyzepCode('*');
1784 if(pic16_debug_verbose)
1787 /* now put it all together into the assembler file */
1788 /* create the assembler file name */
1789 if((noAssemble || options.c1mode) && fullDstFileName) {
1790 sprintf (buffer, fullDstFileName);
1792 sprintf (buffer, dstFileName);
1793 strcat (buffer, ".asm");
1796 if(!(asmFile = fopen (buffer, "w"))) {
1797 werror (E_FILE_OPEN_ERR, buffer);
1801 /* initial comments */
1802 pic16initialComments (asmFile);
1804 /* print module name */
1806 fprintf(asmFile, "\t.file\t\"%s\"\n", fullSrcFileName);
1808 /* Let the port generate any global directives, etc. */
1809 if(port->genAssemblerPreamble) {
1810 port->genAssemblerPreamble(asmFile);
1813 /* Put all variables into a cblock */
1814 pic16_AnalyzeBanking();
1817 if(pic16_options.opt_flags & OF_LR_SUPPORT) {
1818 pic16_OptimizeLocalRegs();
1822 /* remove redundant BANKSELs -- added by RN 2005-01-17 */
1823 if(pic16_options.opt_banksel > 1) {
1824 pic16_OptimizeBanksel();
1827 /* turn GOTOs into BRAs -- added by RN 2004-11-16 */
1828 if(!(pic16_options.opt_flags & OF_NO_OPTIMIZE_GOTO)) {
1829 pic16_OptimizeJumps();
1832 /* print the global variables in this module */
1833 pic16printPublics (asmFile);
1835 /* print the extern variables to this module */
1836 pic16_printExterns(asmFile);
1838 pic16_writeUsedRegs(asmFile);
1841 /* no xdata in pic */
1842 /* if external stack then reserve space of it */
1843 if(mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1844 fprintf (asmFile, "%s", iComments2);
1845 fprintf (asmFile, "; external stack \n");
1846 fprintf (asmFile, "%s", iComments2);
1847 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1848 fprintf (asmFile,";\t.ds 256\n");
1853 /* no xdata in pic */
1854 /* copy xtern ram data */
1855 fprintf (asmFile, "%s", iComments2);
1856 fprintf (asmFile, "; external ram data\n");
1857 fprintf (asmFile, "%s", iComments2);
1858 dbuf_write_and_destroy (&xdata->oBuf, asmFile);
1862 /* copy the bit segment */
1863 fprintf (asmFile, "%s", iComments2);
1864 fprintf (asmFile, "; bit data\n");
1865 fprintf (asmFile, "%s", iComments2);
1866 dbuf_write_and_destroy (&bit->oBuf, asmFile);
1869 /* copy the interrupt vector table */
1870 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1871 fprintf (asmFile, "\n%s", iComments2);
1872 fprintf (asmFile, "; interrupt vector \n");
1873 fprintf (asmFile, "%s", iComments2);
1874 dbuf_write_and_destroy (&vBuf, asmFile);
1877 /* copy global & static initialisations */
1878 fprintf (asmFile, "\n%s", iComments2);
1879 fprintf (asmFile, "; global & static initialisations\n");
1880 fprintf (asmFile, "%s", iComments2);
1882 if(pic16_debug_verbose)
1883 fprintf(asmFile, "; A code from now on!\n");
1885 pic16_copypCode(asmFile, 'A');
1887 if(pic16_options.no_crt) {
1888 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1889 fprintf(asmFile, "\tcode\n");
1890 fprintf(asmFile,"__sdcc_gsinit_startup:\n");
1894 // dbuf_write_and_destroy (&code->oBuf, stderr);
1896 fprintf(asmFile, "; I code from now on!\n");
1897 pic16_copypCode(asmFile, 'I');
1899 if(pic16_debug_verbose)
1900 fprintf(asmFile, "; dbName from now on!\n");
1902 pic16_copypCode(asmFile, statsg->dbName);
1904 if(pic16_options.no_crt) {
1905 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
1906 fprintf (asmFile,"\tgoto\t__sdcc_program_startup\n");
1910 if(pic16_debug_verbose)
1911 fprintf(asmFile, "; X code from now on!\n");
1913 pic16_copypCode(asmFile, 'X');
1915 if(pic16_debug_verbose)
1916 fprintf(asmFile, "; M code from now on!\n");
1918 pic16_copypCode(asmFile, 'M');
1920 pic16_copypCode(asmFile, code->dbName);
1922 pic16_copypCode(asmFile, 'P');
1924 emitStatistics(asmFile);
1926 fprintf (asmFile,"\tend\n");