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;
43 extern int maxRegBank;
45 extern char *VersionString;
46 extern struct dbuf_s *codeOutBuf;
47 extern char *iComments1;
48 extern char *iComments2;
51 extern unsigned long pFile_isize;
53 extern unsigned long pic16_countInstructions();
54 set *pic16_localFunctions = NULL;
55 set *rel_idataSymSet=NULL;
56 set *fix_idataSymSet=NULL;
58 extern DEFSETFUNC (closeTmpFiles);
59 extern DEFSETFUNC (rmTmpFiles);
61 extern void pic16_AnalyzeBanking (void);
62 extern void pic16_OptimizeJumps ();
63 extern void pic16_OptimizeBanksel ();
64 extern void pic16_InlinepCode(void);
65 extern void pic16_writeUsedRegs(FILE *);
67 extern void initialComments (FILE * afile);
68 extern void printPublics (FILE * afile);
70 void pic16_pCodeInitRegisters(void);
71 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
72 extern void pic16_pCodeConstString(char *name, char *value);
75 /*-----------------------------------------------------------------*/
76 /* aopLiteral - string from a literal value */
77 /*-----------------------------------------------------------------*/
78 unsigned int pic16aopLiteral (value *val, int offset)
85 /* if it is a float then it gets tricky */
86 /* otherwise it is fairly simple */
87 if (!(IS_FLOAT(val->type) || IS_FIXED(val->type))) {
88 unsigned long v = (unsigned long) floatFromVal(val);
90 return ( (v >> (offset * 8)) & 0xff);
93 if(IS_FIXED16X16(val->type)) {
94 unsigned long v = (unsigned long)fixed16x16FromDouble( 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];
111 char tbuffer[512], *tbuf=tbuffer;;
114 /*-----------------------------------------------------------------*/
115 /* emitRegularMap - emit code for maps with no special cases */
116 /*-----------------------------------------------------------------*/
118 pic16emitRegularMap (memmap * map, bool addPublics, bool arFlag)
121 // int i, size, bitvars = 0;;
123 // fprintf(stderr, "%s:%d map name= %s\n", __FUNCTION__, __LINE__, map->sname);
126 dbuf_printf (&map->oBuf, ";\t.area\t%s\n", map->sname);
127 /* print the area name */
129 for (sym = setFirstItem (map->syms); sym; sym = setNextItem (map->syms)) {
132 fprintf(stderr, "%s\t%s: sym: %s\tused: %d\textern: %d\tstatic: %d\taggregate: %d\tregister: 0x%x\tfunction: %d\n",
134 map->sname, sym->name, sym->used, IS_EXTERN(sym->etype), IS_STATIC(sym->etype),
135 IS_AGGREGATE(sym->type), (SPEC_SCLS(sym->etype) == S_REGISTER), IS_FUNC(sym->type));
136 printTypeChain( sym->type, stderr );
137 fprintf(stderr, "\n");
140 /* if extern then add to externs */
141 if (IS_EXTERN (sym->etype)) {
142 /* reduce overhead while linking by not declaring
143 * extern unused external functions (usually declared
144 * in header files) */
145 if(IS_FUNC(sym->type) && !sym->used)continue;
147 /* make sure symbol is not in publics section */
148 if(!checkSym(publics, sym))
149 checkAddSym(&externs, sym);
153 /* if allocation required check is needed
154 * then check if the symbol really requires
155 * allocation only for local variables */
156 if (arFlag && !IS_AGGREGATE (sym->type) &&
157 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
158 !sym->allocreq && sym->level) {
160 // fprintf(stderr, "%s:%d special case, continuing...\n", __FILE__, __LINE__);
165 /* if global variable & not static or extern
166 * and addPublics allowed then add it to the public set */
167 if ((sym->used) && (sym->level == 0 ||
168 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
170 !IS_STATIC (sym->etype) && !IS_FUNC(sym->type)) {
172 checkAddSym(&publics, sym);
175 if(IS_STATIC(sym->etype)
176 && !sym->ival) /* && !sym->level*/ {
181 // debugf("adding symbol %s\n", sym->name);
182 #define SET_IMPLICIT 1
185 if(IS_STRUCT(sym->type))
189 reg = pic16_allocDirReg( operandFromSymbol( sym ));
192 for(ssym=setFirstItem(sectSyms); ssym; ssym=setNextItem(sectSyms)) {
193 if(!strcmp(ssym->name, reg->name))found=1;
197 checkAddReg(&pic16_rel_udata, reg);
200 debugf("Did find %s in pic16_rel_udata already. Check!\n", reg->name);
201 // checkAddSym(&publics, sym);
207 /* if extern then do nothing or is a function
209 if (IS_FUNC (sym->type) && !IS_STATIC(sym->etype)) {
210 if(SPEC_OCLS(sym->etype) == code) {
211 // fprintf(stderr, "%s:%d: symbol added: %s\n", __FILE__, __LINE__, sym->rname);
212 checkAddSym(&publics, sym);
217 /* if is has an absolute address then generate
218 an equate for this no need to allocate space */
219 if (SPEC_ABSA (sym->etype)) {
220 // fprintf (stderr,"; %s == 0x%04x\t\treqv= %p nRegs= %d\n",
221 // sym->name, SPEC_ADDR (sym->etype), sym->reqv, sym->regType);
223 dbuf_printf (&map->oBuf, "%s\tEQU\t0x%04x\n",
225 SPEC_ADDR (sym->etype));
227 /* emit only if it is global */
228 if(sym->level == 0) {
231 reg = pic16_dirregWithName( sym->name );
234 // fprintf(stderr, "%s:%d: implicit add of symbol = %s\n",
235 // __FUNCTION__, __LINE__, sym->name);
237 /* if IS_STRUCT is omitted the following
238 * fixes structures but break char/int etc */
240 if(IS_STRUCT(sym->type))
241 sym->implicit = 1; // mark as implicit
244 reg = pic16_allocDirReg( operandFromSymbol(sym) );
246 if(checkAddReg(&pic16_fix_udata, reg)) {
247 /* and add to globals list if not exist */
248 addSet(&publics, sym);
252 addSet(&publics, sym);
256 if(!sym->used && (sym->level == 0)) {
259 /* symbol not used, just declared probably, but its in
260 * level 0, so we must declare it fine as global */
262 // fprintf(stderr, "EXTRA symbol declaration sym= %s\n", sym->name);
265 if(IS_STRUCT(sym->type))
266 sym->implicit = 1; // mark as implicit
269 if(IS_AGGREGATE(sym->type)) {
270 reg=pic16_allocRegByName(sym->rname, getSize( sym->type ), NULL);
272 reg = pic16_allocDirReg( operandFromSymbol( sym ) );
280 fprintf(stderr, "%s:%d sym->rname: %s reg: %p reg->name: %s\n", __FILE__, __LINE__,
281 sym->rname, reg, (reg?reg->name:"<<NULL>>"));
285 for(ssym=setFirstItem(sectSyms); ssym; ssym=setNextItem(sectSyms)) {
286 if(!strcmp(ssym->name, reg->name))found=1;
290 if(checkAddReg(&pic16_rel_udata, reg)) {
291 addSetHead(&publics, sym);
300 addSetHead(&publics, sym);
305 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
306 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
307 /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
308 if (IS_BITVAR (sym->etype)) {
311 dbuf_printf (map->oBuf, "\t%s\n", sym->rname);
312 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1) {
313 for (i = 1; i < size; i++)
314 dbuf_printf (map->oBuf, "\t%s_%d\n", sym->rname, i);
317 dbuf_printf (map->oBuf, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
321 /* FIXME -- VR Fix the following, so that syms to be placed
322 * in the idata section and let linker decide about their fate */
324 /* if it has an initial value then do it only if
325 it is a global variable */
328 && ((sym->level == 0)
329 || IS_STATIC(sym->etype)) ) {
333 if(SPEC_OCLS(sym->etype)==data) {
334 fprintf(stderr, "%s: sym %s placed in data segment\n", map->sname, sym->name);
337 if(SPEC_OCLS(sym->etype)==code) {
338 fprintf(stderr, "%s: sym %s placed in code segment\n", map->sname, sym->name);
343 fprintf(stderr, "'%s': sym '%s' has initial value SPEC_ABSA: %d, IS_AGGREGATE: %d\n",
344 map->sname, sym->name, SPEC_ABSA(sym->etype), IS_AGGREGATE(sym->type));
347 if (IS_AGGREGATE (sym->type)) {
348 if(SPEC_ABSA(sym->etype))
349 addSet(&fix_idataSymSet, copySymbol(sym));
351 addSet(&rel_idataSymSet, copySymbol(sym));
352 // ival = initAggregates (sym, sym->ival, NULL);
354 if(SPEC_ABSA(sym->etype))
355 addSet(&fix_idataSymSet, copySymbol(sym));
357 addSet(&rel_idataSymSet, copySymbol(sym));
359 // ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
360 // decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
364 setAstLineno(ival, sym->lineDef);
365 codeOutBuf = &statsg->oBuf;
367 eBBlockFromiCode (iCodeFromAst (ival));
375 /*-----------------------------------------------------------------*/
376 /* pic16_initPointer - pointer initialization code massaging */
377 /*-----------------------------------------------------------------*/
378 value *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 /*-----------------------------------------------------------------*/
520 void _pic16_printPointerType (const char *name, char ptype, void *p)
524 sprintf(buf, "LOW(%s)", name);
525 pic16_emitDS(buf, ptype, p);
526 sprintf(buf, "HIGH(%s)", name);
527 pic16_emitDS(buf, ptype, p);
530 /*-----------------------------------------------------------------*/
531 /* printPointerType - generates ival for pointer type */
532 /*-----------------------------------------------------------------*/
533 void pic16_printPointerType (const char *name, char ptype, void *p)
535 _pic16_printPointerType (name, ptype, p);
536 //pic16_flushDB(ptype, p); /* breaks char* const arr[] = {&c, &c, &c}; */
539 /*-----------------------------------------------------------------*/
540 /* printGPointerType - generates ival for generic pointer type */
541 /*-----------------------------------------------------------------*/
542 void pic16_printGPointerType (const char *iname, const unsigned int itype,
547 _pic16_printPointerType (iname, ptype, p);
555 sprintf(buf, "UPPER(%s)", iname);
556 pic16_emitDS(buf, ptype, p);
560 sprintf(buf, "0x80");
561 pic16_emitDS(buf, ptype, p);
564 debugf("itype = %d\n", itype );
568 //pic16_flushDB(ptype, p); /* might break char* const arr[] = {...}; */
572 /* set to 0 to disable debug messages */
573 #define DEBUG_PRINTIVAL 0
575 /*-----------------------------------------------------------------*/
576 /* pic16_printIvalType - generates ival for int/char */
577 /*-----------------------------------------------------------------*/
579 pic16_printIvalType (symbol *sym, sym_link * type, initList * ilist, char ptype, void *p)
583 // fprintf(stderr, "%s for symbol %s\n",__FUNCTION__, sym->rname);
586 fprintf(stderr, "%s\n",__FUNCTION__);
590 /* if initList is deep */
591 if (ilist && ilist->type == INIT_DEEP)
592 ilist = ilist->init.deep;
594 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
595 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
598 if (!(val = list2val (ilist))) {
599 // assuming a warning has been thrown
603 if (val->type != type) {
604 val = valCastLiteral(type, floatFromVal(val));
607 switch (getSize (type)) {
609 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
613 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
614 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
617 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
618 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
619 pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
621 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
622 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
623 pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
624 pic16_emitDB(pic16aopLiteral(val, 3), ptype, p);
629 /*--------------------------------------------------------------------*/
630 /* pic16_printIvalChar - generates initital value for character array */
631 /*--------------------------------------------------------------------*/
633 pic16_printIvalChar (symbol *sym, sym_link * type, initList * ilist, char *s, char ptype, void *p)
636 int remain, len, ilen;
642 fprintf(stderr, "%s\n",__FUNCTION__);
646 val = list2val (ilist);
648 /* if the value is a character string */
649 if(IS_ARRAY (val->type) && IS_CHAR (val->etype)) {
650 /* length of initializer string (might contain \0, so do not use strlen) */
651 ilen = DCL_ELEM(val->type);
654 DCL_ELEM (type) = ilen;
656 /* len is 0 if declartion equals initializer,
657 * >0 if declaration greater than initializer
658 * <0 if declaration less than initializer
659 * Strategy: if >0 emit 0x00 for the rest of the length,
660 * if <0 then emit only the length of declaration elements
663 len = DCL_ELEM (type) - ilen;
665 // fprintf(stderr, "%s:%d ilen = %i len = %i DCL_ELEM(type) = %i SPEC_CVAL-len = %i\n", __FILE__, __LINE__,
666 // ilen, len, DCL_ELEM(type), strlen(SPEC_CVAL(val->etype).v_char));
669 /* emit initializer */
670 for(remain=0; remain<ilen; remain++)
671 pic16_emitDB(SPEC_CVAL(val->etype).v_char[ remain ], ptype, p);
673 /* fill array with 0x00 */
675 pic16_emitDB(0x00, ptype, p);
678 werror (W_EXCESS_INITIALIZERS, "array of chars", sym->name, sym->lineDef);
680 for(remain=0; remain<DCL_ELEM (type); remain++)
681 pic16_emitDB(SPEC_CVAL(val->etype).v_char[ remain ], ptype, p);
685 // if((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0) {
690 for(remain=0; remain<strlen(s); remain++) {
691 pic16_emitDB(s[remain], ptype, p);
697 /*-----------------------------------------------------------------*/
698 /* pic16_printIvalArray - generates code for array initialization */
699 /*-----------------------------------------------------------------*/
701 pic16_printIvalArray (symbol * sym, sym_link * type, initList * ilist,
705 int lcnt = 0, size = 0;
712 fprintf(stderr, "%s\n",__FUNCTION__);
714 /* take care of the special case */
715 /* array of characters can be init */
717 if (IS_CHAR (type->next)) {
718 if (!IS_LITERAL(list2val(ilist)->etype)) {
719 werror (W_INIT_WRONG);
723 if(pic16_printIvalChar (sym, type,
724 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
725 SPEC_CVAL (sym->etype).v_char, ptype, p))
728 /* not the special case */
729 if (ilist && ilist->type != INIT_DEEP)
731 werror (E_INIT_STRUCT, sym->name);
735 iloop = ilist->init.deep;
736 lcnt = DCL_ELEM (type);
741 pic16_printIval (sym, type->next, iloop, ptype, p);
742 iloop = (iloop ? iloop->next : NULL);
745 /* if not array limits given & we */
746 /* are out of initialisers then */
747 if (!DCL_ELEM (type) && !iloop)
750 /* no of elements given and we */
751 /* have generated for all of them */
753 /* if initializers left */
755 werror (W_EXCESS_INITIALIZERS, "array", sym->name, sym->lineDef);
761 /* if we have not been given a size */
762 if (!DCL_ELEM (type))
763 DCL_ELEM (type) = size;
768 /*-----------------------------------------------------------------*/
769 /* pic16_printIvalBitFields - generate initializer for bitfields */
770 /*-----------------------------------------------------------------*/
771 void pic16_printIvalBitFields(symbol **sym, initList **ilist, char ptype, void *p)
775 initList *lilist = *ilist ;
776 unsigned long ival = 0;
781 fprintf(stderr, "%s\n",__FUNCTION__);
787 val = list2val(lilist);
789 if (SPEC_BLEN(lsym->etype) > 8) {
790 size += ((SPEC_BLEN (lsym->etype) / 8) +
791 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
794 size = ((SPEC_BLEN (lsym->etype) / 8) +
795 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
797 i = (unsigned long)floatFromVal(val);
798 i <<= SPEC_BSTR (lsym->etype);
800 if (! ( lsym->next &&
801 (lilist && lilist->next) &&
802 (IS_BITFIELD(lsym->next->type)) &&
803 (SPEC_BSTR(lsym->next->etype)))) break;
805 lilist = lilist->next;
809 pic16_emitDB(BYTE_IN_LONG(ival, 0), ptype, p);
813 pic16_emitDB(BYTE_IN_LONG(ival, 0), ptype, p);
814 pic16_emitDB(BYTE_IN_LONG(ival, 1), ptype, p);
817 case 4: /* EEP: why is this db and not dw? */
818 pic16_emitDB(BYTE_IN_LONG(ival, 0), ptype, p);
819 pic16_emitDB(BYTE_IN_LONG(ival, 1), ptype, p);
820 pic16_emitDB(BYTE_IN_LONG(ival, 2), ptype, p);
821 pic16_emitDB(BYTE_IN_LONG(ival, 3), ptype, p);
824 /* VR - only 1,2,4 size long can be handled???? Why? */
825 fprintf(stderr, "%s:%d: unhandled case. Contact author.\n", __FILE__, __LINE__);
833 /*-----------------------------------------------------------------*/
834 /* printIvalStruct - generates initial value for structures */
835 /*-----------------------------------------------------------------*/
836 void pic16_printIvalStruct (symbol * sym, sym_link * type,
837 initList * ilist, char ptype, void *p)
840 initList *iloop = NULL;
844 fprintf(stderr, "%s\n",__FUNCTION__);
847 sflds = SPEC_STRUCT (type)->fields;
850 if (ilist->type != INIT_DEEP) {
851 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
855 iloop = ilist->init.deep;
858 for (; (sflds && iloop); sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
859 // fprintf(stderr, "%s:%d sflds: %p\tiloop = %p\n", __FILE__, __LINE__, sflds, iloop);
860 if (IS_BITFIELD(sflds->type)) {
861 pic16_printIvalBitFields(&sflds, &iloop, ptype, p);
863 pic16_printIval (sym, sflds->type, iloop, ptype, p);
867 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
872 /*-----------------------------------------------------------------*/
873 /* printIvalUnion - generates initial value for unions */
874 /*-----------------------------------------------------------------*/
875 void pic16_printIvalUnion (symbol * sym, sym_link * type,
876 initList * ilist, char ptype, void *p)
879 initList *iloop = NULL;
884 fprintf(stderr, "%s\n",__FUNCTION__);
896 if (type) size = SPEC_STRUCT(type)->size;
898 if (i == 1 && size >= 0 && size <= sizeof(long))
900 unsigned long val = (unsigned long)floatFromVal(list2val(ilist));
903 pic16_emitDB(val, ptype, p);
909 fprintf( stderr, "INCOMPLETE SUPPORT FOR INITIALIZED union---FALLING BACK TO struct\n" );
910 fprintf( stderr, "This is a bug. Please file a bug-report with your source attached.\n" );
911 pic16_printIvalStruct( sym, type, ilist, ptype, p );
915 pic16_isUnion( symbol *sym, sym_link *type )
917 if (type && SPEC_STRUCT(type)->type == UNION) return 1;
921 /*--------------------------------------------------------------------------*/
922 /* pic16_printIvalCharPtr - generates initial values for character pointers */
923 /*--------------------------------------------------------------------------*/
924 int pic16_printIvalCharPtr (symbol * sym, sym_link * type, value * val, char ptype, void *p)
928 /* PENDING: this is _very_ mcs51 specific, including a magic
930 It's also endin specific.
932 VR - Attempting to port this function to pic16 port - 8-Jun-2004
937 fprintf(stderr, "%s\n",__FUNCTION__);
940 size = getSize (type);
942 if (val->name && strlen (val->name))
944 if (size == 1) /* This appears to be Z80 specific?? */
946 pic16_emitDS(val->name, ptype, p);
950 pic16_printPointerType (val->name, ptype, p);
955 if (IS_PTR (val->type)) {
956 type = DCL_TYPE (val->type);
958 type = PTR_TYPE (SPEC_OCLS (val->etype));
960 if (val->sym && val->sym->isstrlit) {
961 // this is a literal string
964 pic16_printGPointerType(val->name, type, ptype, p);
968 fprintf (stderr, "*** internal error: unknown size in "
969 "printIvalCharPtr.\n");
975 // these are literals assigned to pointers
979 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
982 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
983 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
986 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
987 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
988 pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
996 if (val->sym && val->sym->isstrlit) { // && !isinSet(statsg->syms, val->sym)) {
997 if(ptype == 'p' && !isinSet(statsg->syms, val->sym))addSet (&statsg->syms, val->sym);
998 else if(ptype == 'f' /*&& !isinSet(rel_idataSymSet, val->sym)*/)addSet(&rel_idataSymSet, val->sym);
1004 /*-----------------------------------------------------------------------*/
1005 /* pic16_printIvalFuncPtr - generate initial value for function pointers */
1006 /*-----------------------------------------------------------------------*/
1007 void pic16_printIvalFuncPtr (sym_link * type, initList * ilist, char ptype, void *p)
1014 fprintf(stderr, "%s\n",__FUNCTION__);
1018 val = list2val (ilist);
1020 val = valCastLiteral(type, 0.0);
1023 // an error has been thrown already
1027 if (IS_LITERAL(val->etype)) {
1028 if (compareType(type, val->etype) == 0) {
1029 werrorfl (ilist->filename, ilist->lineno, E_INCOMPAT_TYPES);
1030 printFromToType (val->type, type);
1032 pic16_printIvalCharPtr (NULL, type, val, ptype, p);
1036 /* check the types */
1037 if ((dLvl = compareType (val->type, type->next)) <= 0)
1039 pic16_emitDB(0x00, ptype, p);
1043 /* now generate the name */
1045 pic16_printGPointerType (val->name, DCL_TYPE(val->type), ptype, p);
1047 pic16_printGPointerType (val->sym->rname, DCL_TYPE(val->type), ptype, p);
1049 if(IS_FUNC(val->sym->type) && !val->sym->used && !IS_STATIC(val->sym->etype)) {
1051 if(!checkSym(publics, val->sym))
1052 if(checkAddSym(&externs, val->sym) && (ptype == 'f')) {
1053 /* this has not been declared as extern
1054 * so declare it as a 'late extern' just after the symbol */
1055 fprintf((FILE *)p, ";\tdeclare symbol as extern\n");
1056 fprintf((FILE *)p, "\textern\t%s\n", val->sym->rname);
1057 fprintf((FILE *)p, ";\tcontinue variable declaration\n");
1066 /*-----------------------------------------------------------------*/
1067 /* pic16_printIvalPtr - generates initial value for pointers */
1068 /*-----------------------------------------------------------------*/
1069 void pic16_printIvalPtr (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p)
1075 fprintf(stderr, "%s:%d initialising pointer: %s size: %d\n", __FILE__, __LINE__,
1076 sym->rname, getSize(sym->type));
1080 if (ilist && (ilist->type == INIT_DEEP))
1081 ilist = ilist->init.deep;
1083 /* function pointer */
1084 if (IS_FUNC (type->next))
1086 pic16_printIvalFuncPtr (type, ilist, ptype, p);
1090 if (!(val = pic16_initPointer (ilist, type)))
1093 /* if character pointer */
1094 if (IS_CHAR (type->next))
1095 if (pic16_printIvalCharPtr (sym, type, val, ptype, p))
1098 /* check the type */
1099 if (compareType (type, val->type) == 0) {
1100 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
1101 printFromToType (val->type, type);
1104 /* if val is literal */
1105 if (IS_LITERAL (val->etype))
1107 switch (getSize (type))
1110 pic16_emitDB((unsigned int)floatFromVal(val) & 0xff, ptype, p);
1113 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
1114 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
1117 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
1118 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
1119 pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
1122 fprintf(stderr, "%s:%d size = %d\n", __FILE__, __LINE__, getSize(type));
1129 size = getSize (type);
1131 if (size == 1) /* Z80 specific?? */
1133 pic16_emitDS(val->name, ptype, p);
1137 pic16_printPointerType (val->name, ptype, p);
1141 pic16_printGPointerType (val->name, (IS_PTR(type)?DCL_TYPE(type):PTR_TYPE(SPEC_OCLS(sym->etype))),
1150 /*-----------------------------------------------------------------*/
1151 /* pic16_printIval - generates code for initial value */
1152 /*-----------------------------------------------------------------*/
1153 void pic16_printIval (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p)
1161 fprintf(stderr, "%s:%d generating init for %s\n", __FILE__, __LINE__, sym->name);
1162 fprintf(stderr, "%s: IS_STRUCT: %d IS_ARRAY: %d IS_PTR: %d IS_SPEC: %d\n", sym->name,
1163 IS_STRUCT(type), IS_ARRAY(type), IS_PTR(type), IS_SPEC(type));
1166 /* if structure then */
1167 if (IS_STRUCT (type))
1169 if (pic16_isUnion(sym, type))
1171 //fprintf(stderr,"%s union\n",__FUNCTION__);
1172 pic16_printIvalUnion (sym, type, ilist, ptype, p);
1174 //fprintf(stderr,"%s struct\n",__FUNCTION__);
1175 pic16_printIvalStruct (sym, type, ilist, ptype, p);
1180 /* if this is an array */
1181 if (IS_ARRAY (type))
1183 // fprintf(stderr,"%s array\n",__FUNCTION__);
1184 pic16_printIvalArray (sym, type, ilist, ptype, p);
1191 // not an aggregate, ilist must be a node
1192 if (ilist->type!=INIT_NODE) {
1193 // or a 1-element list
1194 if (ilist->init.deep->next) {
1195 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar",
1198 ilist=ilist->init.deep;
1203 // and the type must match
1204 itype=ilist->init.node->ftype;
1206 if (compareType(type, itype)==0) {
1207 // special case for literal strings
1208 if (IS_ARRAY (itype) && IS_CHAR (getSpec(itype)) &&
1209 // which are really code pointers
1210 IS_PTR(type) && DCL_TYPE(type)==CPOINTER) {
1213 // werrorfl (ilist->filename, ilist->lineno, E_TYPE_MISMATCH, "assignment", " ");
1214 // printFromToType(itype, type);
1221 /* if this is a pointer */
1224 // fprintf(stderr,"%s pointer\n",__FUNCTION__);
1225 pic16_printIvalPtr (sym, type, ilist, ptype, p);
1230 /* if type is SPECIFIER */
1233 // fprintf(stderr,"%s spec\n",__FUNCTION__);
1234 pic16_printIvalType (sym, type, ilist, ptype, p);
1239 int PIC16_IS_CONFIG_ADDRESS(int address)
1241 return ((address >= pic16->cwInfo.confAddrStart && address <= pic16->cwInfo.confAddrEnd));
1244 int PIC16_IS_IDLOC_ADDRESS(int address)
1246 return ((address >= pic16->idInfo.idAddrStart && address <= pic16->idInfo.idAddrEnd));
1249 /* wrapper function for the above */
1250 int PIC16_IS_HWREG_ADDRESS(int address)
1252 return (PIC16_IS_CONFIG_ADDRESS(address) || PIC16_IS_IDLOC_ADDRESS(address));
1256 /*-----------------------------------------------------------------*/
1257 /* emitStaticSeg - emitcode for the static segment */
1258 /*-----------------------------------------------------------------*/
1260 pic16emitStaticSeg (memmap * map)
1263 static int didcode=0;
1265 //fprintf(stderr, "%s\n",__FUNCTION__);
1269 /* for all variables in this segment do */
1270 for (sym = setFirstItem (map->syms); sym;
1271 sym = setNextItem (map->syms))
1275 fprintf(stderr, "%s\t%s: sym: %s\tused: %d\tSPEC_ABSA: %d\tSPEC_AGGREGATE: %d\tCODE: %d\n\
1276 CODESPACE: %d\tCONST: %d\tPTRCONST: %d\tSPEC_CONST: %d\n", __FUNCTION__,
1277 map->sname, sym->name, sym->used, SPEC_ABSA(sym->etype), IS_AGGREGATE(sym->type),
1278 IS_CODE(sym->etype), IN_CODESPACE( SPEC_OCLS(sym->etype)), IS_CONSTANT(sym->etype),
1279 IS_PTR_CONST(sym->etype), SPEC_CONST(sym->etype));
1280 printTypeChain( sym->type, stderr );
1281 fprintf(stderr, "\n");
1284 if(SPEC_ABSA(sym->etype) && PIC16_IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype))) {
1285 pic16_assignConfigWordValue(SPEC_ADDR(sym->etype),
1286 (int) floatFromVal(list2val(sym->ival)));
1291 if(SPEC_ABSA(sym->etype) && PIC16_IS_IDLOC_ADDRESS(SPEC_ADDR(sym->etype))) {
1292 pic16_assignIdByteValue(SPEC_ADDR(sym->etype),
1293 (char) floatFromVal(list2val(sym->ival)));
1298 /* if it is "extern" then do nothing */
1299 if (IS_EXTERN (sym->etype)/* && !SPEC_ABSA(sym->etype)*/) {
1300 checkAddSym(&externs, sym);
1304 /* if it is not static add it to the public
1306 if (!IS_STATIC (sym->etype)) {
1307 /* do not emit if it is a config word declaration */
1308 checkAddSym(&publics, sym);
1311 /* print extra debug info if required */
1312 if (options.debug || sym->level == 0) {
1313 /* NOTE to me - cdbFile may be null in which case,
1314 * the sym name will be printed to stdout. oh well */
1315 debugFile->writeSymbol(sym);
1318 /* if it has an absolute address */
1319 if (SPEC_ABSA (sym->etype)) {
1320 // fprintf(stderr, "%s:%d spec_absa is true for symbol: %s\n",
1321 // __FILE__, __LINE__, sym->name);
1323 /* if it has an initial value */
1331 /* symbol has absolute address and initial value */
1333 resolveIvalSym (sym->ival, sym->type);
1334 asym = newSymbol(sym->rname, 0);
1335 abSym = Safe_calloc(1, sizeof(absSym));
1336 strcpy(abSym->name, sym->rname);
1337 abSym->address = SPEC_ADDR( sym->etype );
1338 addSet(&absSymSet, abSym);
1340 pb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute Ival"));
1341 pic16_addpBlock(pb);
1343 pcf = pic16_newpCodeFunction(moduleName, asym->name);
1344 PCF(pcf)->absblock = 1;
1346 pic16_addpCode2pBlock(pb,pcf);
1347 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
1348 //fprintf(stderr, "%s:%d [1] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1349 pic16_printIval(sym, sym->type, sym->ival, 'p', (void *)pb);
1350 pic16_flushDB('p', (void *)pb);
1352 pic16_addpCode2pBlock(pb, pic16_newpCodeFunction(NULL, NULL));
1358 /* symbol has absolute address but no initial value */
1360 /* allocate space */
1361 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
1363 /* special case for character strings */
1364 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1365 SPEC_CVAL (sym->etype).v_char) {
1367 // fprintf(stderr, "%s:%d printing code string from %s\n", __FILE__, __LINE__, sym->rname);
1369 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
1371 fprintf (stderr, "%s:%u(%s): do not know how to intialize symbol %s\n", __FILE__, __LINE__, __FUNCTION__, sym->rname);
1377 // fprintf(stderr, "%s:%d spec_absa is false for symbol: %s\n",
1378 // __FILE__, __LINE__, sym->name);
1381 /* if it has an initial value */
1385 /* symbol doesn't have absolute address but has initial value */
1386 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
1388 resolveIvalSym (sym->ival, sym->type);
1390 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block for Ival"));
1391 pic16_addpBlock(pb);
1394 /* make sure that 'code' directive is emitted before, once */
1395 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir("code", NULL));
1400 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
1401 //fprintf(stderr, "%s:%d [2] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1402 pic16_printIval(sym, sym->type, sym->ival, 'p', (void *)pb);
1403 pic16_flushDB('p', (void *)pb);
1407 /* symbol doesn't have absolute address and no initial value */
1408 /* allocate space */
1409 // fprintf(stderr, "%s:%d [3] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1410 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
1411 /* special case for character strings */
1412 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1413 SPEC_CVAL (sym->etype).v_char) {
1415 // fprintf(stderr, "%s:%d printing code string for %s\n", __FILE__, __LINE__, sym->rname);
1417 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
1428 /*-----------------------------------------------------------------*/
1429 /* pic16_emitConfigRegs - emits the configuration registers */
1430 /*-----------------------------------------------------------------*/
1431 void pic16_emitConfigRegs(FILE *of)
1435 for(i=0;i<=(pic16->cwInfo.confAddrEnd-pic16->cwInfo.confAddrStart);i++)
1436 if(pic16->cwInfo.crInfo[i].emit) //mask != -1)
1437 fprintf (of, "\t__config 0x%x, 0x%hhx\n",
1438 pic16->cwInfo.confAddrStart+i,
1439 pic16->cwInfo.crInfo[i].value);
1442 void pic16_emitIDRegs(FILE *of)
1446 for(i=0;i<=(pic16->idInfo.idAddrEnd-pic16->idInfo.idAddrStart);i++)
1447 if(pic16->idInfo.irInfo[i].emit)
1448 fprintf (of, "\t__idlocs 0x%06x, 0x%hhx\n",
1449 pic16->idInfo.idAddrStart+i,
1450 pic16->idInfo.irInfo[i].value);
1457 /* no special considerations for the following
1458 data, idata & bit & xdata */
1459 pic16emitRegularMap (data, TRUE, TRUE);
1460 pic16emitRegularMap (idata, TRUE, TRUE);
1461 pic16emitRegularMap (bit, TRUE, FALSE);
1462 pic16emitRegularMap (xdata, TRUE, TRUE);
1463 pic16emitRegularMap (sfr, FALSE, FALSE);
1464 pic16emitRegularMap (sfrbit, FALSE, FALSE);
1465 pic16emitRegularMap (code, TRUE, FALSE);
1466 pic16emitStaticSeg (statsg);
1467 pic16emitStaticSeg (c_abs);
1470 /*-----------------------------------------------------------------*/
1471 /* createInterruptVect - creates the interrupt vector */
1472 /*-----------------------------------------------------------------*/
1474 pic16createInterruptVect (struct dbuf_s * vBuf)
1476 /* if the main is only a prototype ie. no body then do nothing */
1478 if (!IFFUNC_HASBODY(mainf->type)) {
1479 /* if ! compile only then main function should be present */
1480 if (!options.cc_only)
1486 if((!pic16_options.omit_ivt) || (pic16_options.omit_ivt && pic16_options.leave_reset)) {
1487 dbuf_printf (vBuf, ";\t.area\t%s\n", CODE_NAME);
1488 dbuf_printf (vBuf, ".intvecs\tcode\t0x%06x\n", pic16_options.ivt_loc);
1490 /* this is an overkill since WE are the port,
1491 * and we know if we have a genIVT function! */
1493 port->genIVT(vFile, interrupts, maxInterrupts);
1501 /*-----------------------------------------------------------------*/
1502 /* pic16initialComments - puts in some initial comments */
1503 /*-----------------------------------------------------------------*/
1505 pic16initialComments (FILE * afile)
1507 initialComments (afile);
1508 fprintf (afile, "; PIC16 port for the Microchip 16-bit core micros\n");
1510 fprintf (afile, "; * Extended Instruction Set\n");
1512 if(pic16_mplab_comp)
1513 fprintf(afile, "; * MPLAB/MPASM/MPASMWIN/MPLINK compatibility mode enabled\n");
1514 fprintf (afile, iComments2);
1517 fprintf (afile, "\n\t.ident \"SDCC version %s #%s [pic16 port]%s\"\n",
1518 SDCC_VERSION_STR, getBuildNumber(), (!xinst?"":" {extended}") );
1523 pic16_stringInSet(const char *str, set **world, int autoAdd)
1530 for (s = setFirstItem(*world); s; s = setNextItem(*world))
1533 if (0 == strcmp(s, str)) return 1;
1537 if (autoAdd) addSet(world, Safe_strdup(str));
1542 pic16_emitSymbolIfNew(FILE *file, const char *fmt, const char *sym, int checkLocals)
1544 static set *emitted = NULL;
1546 if (!pic16_stringInSet(sym, &emitted, 1)) {
1547 /* sym was not in emittedSymbols */
1548 if (!checkLocals || !pic16_stringInSet(sym, &pic16_localFunctions, 0)) {
1549 /* sym is not a locally defined function---avoid bug #1443651 */
1550 fprintf( file, fmt, sym );
1557 /*-----------------------------------------------------------------*/
1558 /* printPublics - generates global declarations for publics */
1559 /*-----------------------------------------------------------------*/
1561 pic16printPublics (FILE *afile)
1565 fprintf (afile, "\n%s", iComments2);
1566 fprintf (afile, "; public variables in this module\n");
1567 fprintf (afile, "%s", iComments2);
1569 for(sym = setFirstItem (publics); sym; sym = setNextItem (publics))
1571 if(!IS_STATIC(sym->etype))
1572 pic16_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1575 /*-----------------------------------------------------------------*/
1576 /* printExterns - generates extern declarations for externs */
1577 /*-----------------------------------------------------------------*/
1579 pic16_printExterns(FILE *afile)
1583 /* print nothing if no externs to declare */
1584 if(!elementsInSet(externs) && !elementsInSet(pic16_builtin_functions))
1587 fprintf(afile, "\n%s", iComments2);
1588 fprintf(afile, "; extern variables in this module\n");
1589 fprintf(afile, "%s", iComments2);
1591 for(sym = setFirstItem(externs); sym; sym = setNextItem(externs))
1592 pic16_emitSymbolIfNew(afile, "\textern %s\n", sym->rname, 1);
1594 for(sym = setFirstItem(pic16_builtin_functions); sym; sym = setNextItem(pic16_builtin_functions))
1595 pic16_emitSymbolIfNew(afile, "\textern _%s\n", sym->name, 1);
1598 /*-----------------------------------------------------------------*/
1599 /* emitOverlay - will emit code for the overlay stuff */
1600 /*-----------------------------------------------------------------*/
1602 pic16emitOverlay (struct dbuf_s *aBuf)
1606 if (!elementsInSet (ovrSetSets))
1607 dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name);
1609 /* for each of the sets in the overlay segment do */
1610 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1611 ovrset = setNextItem (ovrSetSets))
1616 if (elementsInSet (ovrset))
1618 /* this dummy area is used to fool the assembler
1619 otherwise the assembler will append each of these
1620 declarations into one chunk and will not overlay
1622 dbuf_printf (aBuf, ";\t.area _DUMMY\n");
1623 /* output the area informtion */
1624 dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1627 for (sym = setFirstItem (ovrset); sym;
1628 sym = setNextItem (ovrset))
1631 /* if extern then do nothing */
1632 if (IS_EXTERN (sym->etype))
1635 /* if allocation required check is needed
1636 then check if the symbol really requires
1637 allocation only for local variables */
1638 if (!IS_AGGREGATE (sym->type) &&
1639 !(sym->_isparm && !IS_REGPARM (sym->etype))
1640 && !sym->allocreq && sym->level)
1643 /* if global variable & not static or extern
1644 and addPublics allowed then add it to the public set */
1645 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1646 && !IS_STATIC (sym->etype)) {
1647 // fprintf(stderr, "%s:%d %s accessed\n", __FILE__, __LINE__, __FUNCTION__);
1648 checkAddSym(&publics, sym);
1649 // addSetHead (&publics, sym);
1652 /* if extern then do nothing or is a function
1654 if (IS_FUNC (sym->type))
1658 /* if is has an absolute address then generate
1659 an equate for this no need to allocate space */
1660 if (SPEC_ABSA (sym->etype))
1663 if (options.debug || sym->level == 0)
1664 dbuf_printf (aBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1666 dbuf_printf (aBuf, "%s\t=\t0x%04x\n",
1668 SPEC_ADDR (sym->etype));
1672 if (options.debug || sym->level == 0)
1673 dbuf_printf (aBuf, "==.\n");
1675 /* allocate space */
1676 dbuf_printf (aBuf, "%s:\n", sym->rname);
1677 dbuf_printf (aBuf, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1684 void emitStatistics(FILE *asmFile)
1686 unsigned long isize, udsize, ramsize;
1687 statistics.isize = pic16_countInstructions();
1688 isize = (statistics.isize >= 0) ? statistics.isize : 0;
1689 udsize = (statistics.udsize >= 0) ? statistics.udsize : 0;
1690 ramsize = pic16 ? pic16->RAMsize : 0x200;
1691 ramsize -= 256; /* ignore access bank and SFRs */
1692 if (ramsize == 0) ramsize = 64; /* prevent division by zero (below) */
1694 fprintf (asmFile, "\n\n; Statistics:\n");
1695 fprintf (asmFile, "; code size:\t%5ld (0x%04lx) bytes (%5.2f%%)\n; \t%5ld (0x%04lx) words\n",
1696 isize, isize, (isize*100.0)/(128UL << 10),
1697 isize>>1, isize>>1);
1698 fprintf (asmFile, "; udata size:\t%5ld (0x%04lx) bytes (%5.2f%%)\n",
1699 udsize, udsize, (udsize*100.0) / (1.0 * ramsize));
1700 fprintf (asmFile, "; access size:\t%5ld (0x%04lx) bytes\n",
1701 statistics.intsize, statistics.intsize);
1703 fprintf (asmFile, "\n\n");
1708 /*-----------------------------------------------------------------*/
1709 /* glue - the final glue that hold the whole thing together */
1710 /*-----------------------------------------------------------------*/
1715 struct dbuf_s ovrBuf;
1718 dbuf_init(&ovrBuf, 4096);
1719 dbuf_init(&vBuf, 4096);
1721 mainf = newSymbol ("main", 0);
1724 mainf = findSymWithLevel(SymbolTab, mainf);
1726 pic16_pCodeInitRegisters();
1728 if(pic16_options.no_crt && mainf && IFFUNC_HASBODY(mainf->type)) {
1729 pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
1731 pic16_addpBlock(pb);
1733 /* entry point @ start of CSEG */
1734 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup",-1));
1737 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1738 pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("_stack_end"))));
1739 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1740 pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("_stack_end"))));
1743 /* put in the call to main */
1744 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
1746 if (options.mainreturn) {
1747 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
1748 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
1750 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
1751 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
1755 /* At this point we've got all the code in the form of pCode structures */
1756 /* Now it needs to be rearranged into the order it should be placed in the */
1759 pic16_movepBlock2Head('P'); // Last
1760 pic16_movepBlock2Head(code->dbName);
1761 pic16_movepBlock2Head('X');
1762 pic16_movepBlock2Head(statsg->dbName); // First
1764 /* print the global struct definitions */
1766 /* PENDING: this isnt the best place but it will do */
1767 if (port->general.glue_up_main) {
1768 /* create the interrupt vector table */
1769 pic16createInterruptVect (&vBuf);
1772 /* emit code for the all the variables declared */
1775 /* do the overlay segments */
1776 pic16emitOverlay(&ovrBuf);
1777 pic16_AnalyzepCode('*');
1780 if(pic16_options.dumpcalltree) {
1783 sprintf(buffer, dstFileName);
1784 strcat(buffer, ".calltree");
1785 cFile = fopen(buffer, "w");
1786 pic16_printCallTree( cFile );
1791 pic16_InlinepCode();
1792 pic16_AnalyzepCode('*');
1795 if(pic16_debug_verbose)
1798 /* now put it all together into the assembler file */
1799 /* create the assembler file name */
1800 if((noAssemble || options.c1mode) && fullDstFileName) {
1801 sprintf (buffer, fullDstFileName);
1803 sprintf (buffer, dstFileName);
1804 strcat (buffer, ".asm");
1807 if(!(asmFile = fopen (buffer, "w"))) {
1808 werror (E_FILE_OPEN_ERR, buffer);
1812 /* initial comments */
1813 pic16initialComments (asmFile);
1815 /* print module name */
1817 fprintf(asmFile, "\t.file\t\"%s\"\n", fullSrcFileName);
1819 /* Let the port generate any global directives, etc. */
1820 if(port->genAssemblerPreamble) {
1821 port->genAssemblerPreamble(asmFile);
1824 /* Put all variables into a cblock */
1825 pic16_AnalyzeBanking();
1828 if(pic16_options.opt_flags & OF_LR_SUPPORT) {
1829 pic16_OptimizeLocalRegs();
1833 /* remove redundant BANKSELs -- added by RN 2005-01-17 */
1834 if(pic16_options.opt_banksel > 1) {
1835 pic16_OptimizeBanksel();
1838 /* turn GOTOs into BRAs -- added by RN 2004-11-16 */
1839 if(pic16_options.opt_flags & OF_OPTIMIZE_GOTO) {
1840 pic16_OptimizeJumps();
1843 /* print the global variables in this module */
1844 pic16printPublics (asmFile);
1846 /* print the extern variables to this module */
1847 pic16_printExterns(asmFile);
1849 pic16_writeUsedRegs(asmFile);
1852 /* no xdata in pic */
1853 /* if external stack then reserve space of it */
1854 if(mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1855 fprintf (asmFile, "%s", iComments2);
1856 fprintf (asmFile, "; external stack \n");
1857 fprintf (asmFile, "%s", iComments2);
1858 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1859 fprintf (asmFile,";\t.ds 256\n");
1864 /* no xdata in pic */
1865 /* copy xtern ram data */
1866 fprintf (asmFile, "%s", iComments2);
1867 fprintf (asmFile, "; external ram data\n");
1868 fprintf (asmFile, "%s", iComments2);
1869 dbuf_write_and_destroy (&xdata->oBuf, asmFile);
1873 /* copy the bit segment */
1874 fprintf (asmFile, "%s", iComments2);
1875 fprintf (asmFile, "; bit data\n");
1876 fprintf (asmFile, "%s", iComments2);
1877 dbuf_write_and_destroy (&bit->oBuf, asmFile);
1880 /* copy the interrupt vector table */
1881 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1882 fprintf (asmFile, "\n%s", iComments2);
1883 fprintf (asmFile, "; interrupt vector \n");
1884 fprintf (asmFile, "%s", iComments2);
1885 dbuf_write_and_destroy (&vBuf, asmFile);
1888 /* copy global & static initialisations */
1889 fprintf (asmFile, "\n%s", iComments2);
1890 fprintf (asmFile, "; global & static initialisations\n");
1891 fprintf (asmFile, "%s", iComments2);
1893 if(pic16_debug_verbose)
1894 fprintf(asmFile, "; A code from now on!\n");
1896 pic16_copypCode(asmFile, 'A');
1898 if(pic16_options.no_crt) {
1899 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1900 fprintf(asmFile, "\tcode\n");
1901 fprintf(asmFile,"__sdcc_gsinit_startup:\n");
1905 // dbuf_write_and_destroy (&code->oBuf, stderr);
1907 fprintf(asmFile, "; I code from now on!\n");
1908 pic16_copypCode(asmFile, 'I');
1910 if(pic16_debug_verbose)
1911 fprintf(asmFile, "; dbName from now on!\n");
1913 pic16_copypCode(asmFile, statsg->dbName);
1915 if(pic16_options.no_crt) {
1916 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
1917 fprintf (asmFile,"\tgoto\t__sdcc_program_startup\n");
1921 if(pic16_debug_verbose)
1922 fprintf(asmFile, "; X code from now on!\n");
1924 pic16_copypCode(asmFile, 'X');
1926 if(pic16_debug_verbose)
1927 fprintf(asmFile, "; M code from now on!\n");
1929 pic16_copypCode(asmFile, 'M');
1931 pic16_copypCode(asmFile, code->dbName);
1933 pic16_copypCode(asmFile, 'P');
1935 emitStatistics(asmFile);
1937 fprintf (asmFile,"\tend\n");