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);
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 setAstLineno(ival, sym->lineDef);
364 codeOutBuf = &statsg->oBuf;
366 eBBlockFromiCode (iCodeFromAst (ival));
374 /*-----------------------------------------------------------------*/
375 /* pic16_initPointer - pointer initialization code massaging */
376 /*-----------------------------------------------------------------*/
377 value *pic16_initPointer (initList * ilist, sym_link *toType)
383 return valCastLiteral(toType, 0.0);
386 expr = decorateType(resolveSymbols( list2expr (ilist) ), FALSE);
387 // expr = list2expr( ilist );
392 /* try it the old way first */
393 if (expr->etype && (val = constExprValue (expr, FALSE)))
396 /* ( ptr + constant ) */
397 if (IS_AST_OP (expr) &&
398 (expr->opval.op == '+' || expr->opval.op == '-') &&
399 IS_AST_SYM_VALUE (expr->left) &&
400 (IS_ARRAY(expr->left->ftype) || IS_PTR(expr->left->ftype)) &&
401 compareType(toType, expr->left->ftype) &&
402 IS_AST_LIT_VALUE (expr->right)) {
403 return valForCastAggr (expr->left, expr->left->ftype,
409 if (IS_AST_OP(expr) && expr->opval.op==CAST &&
410 IS_AST_OP(expr->right) && expr->right->opval.op=='&') {
411 if (compareType(toType, expr->left->ftype)!=1) {
412 werror (W_INIT_WRONG);
413 printFromToType(expr->left->ftype, toType);
419 /* no then we have to do these cludgy checks */
420 /* pointers can be initialized with address of
421 a variable or address of an array element */
422 if (IS_AST_OP (expr) && expr->opval.op == '&') {
423 /* address of symbol */
424 if (IS_AST_SYM_VALUE (expr->left) && expr->left->etype) {
425 val = AST_VALUE (expr->left);
426 val->type = newLink (DECLARATOR);
427 if(SPEC_SCLS (expr->left->etype) == S_CODE) {
428 DCL_TYPE (val->type) = CPOINTER;
429 DCL_PTR_CONST (val->type) = port->mem.code_ro;
431 else if (SPEC_SCLS (expr->left->etype) == S_XDATA)
432 DCL_TYPE (val->type) = FPOINTER;
433 else if (SPEC_SCLS (expr->left->etype) == S_XSTACK)
434 DCL_TYPE (val->type) = PPOINTER;
435 else if (SPEC_SCLS (expr->left->etype) == S_IDATA)
436 DCL_TYPE (val->type) = IPOINTER;
437 else if (SPEC_SCLS (expr->left->etype) == S_EEPROM)
438 DCL_TYPE (val->type) = EEPPOINTER;
440 DCL_TYPE (val->type) = POINTER;
442 val->type->next = expr->left->ftype;
443 val->etype = getSpec (val->type);
447 /* if address of indexed array */
448 if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
449 return valForArray (expr->left);
451 /* if address of structure element then
453 if (IS_AST_OP (expr->left) &&
454 expr->left->opval.op == '.') {
455 return valForStructElem (expr->left->left,
460 (&some_struct)->element */
461 if (IS_AST_OP (expr->left) &&
462 expr->left->opval.op == PTR_OP &&
463 IS_ADDRESS_OF_OP (expr->left->left)) {
464 return valForStructElem (expr->left->left->left,
468 /* case 3. (((char *) &a) +/- constant) */
469 if (IS_AST_OP (expr) &&
470 (expr->opval.op == '+' || expr->opval.op == '-') &&
471 IS_AST_OP (expr->left) && expr->left->opval.op == CAST &&
472 IS_AST_OP (expr->left->right) &&
473 expr->left->right->opval.op == '&' &&
474 IS_AST_LIT_VALUE (expr->right)) {
476 return valForCastAggr (expr->left->right->left,
477 expr->left->left->opval.lnk,
478 expr->right, expr->opval.op);
481 /* case 4. (char *)(array type) */
482 if (IS_CAST_OP(expr) && IS_AST_SYM_VALUE (expr->right) &&
483 IS_ARRAY(expr->right->ftype)) {
485 val = copyValue (AST_VALUE (expr->right));
486 val->type = newLink (DECLARATOR);
487 if (SPEC_SCLS (expr->right->etype) == S_CODE) {
488 DCL_TYPE (val->type) = CPOINTER;
489 DCL_PTR_CONST (val->type) = port->mem.code_ro;
491 else if (SPEC_SCLS (expr->right->etype) == S_XDATA)
492 DCL_TYPE (val->type) = FPOINTER;
493 else if (SPEC_SCLS (expr->right->etype) == S_XSTACK)
494 DCL_TYPE (val->type) = PPOINTER;
495 else if (SPEC_SCLS (expr->right->etype) == S_IDATA)
496 DCL_TYPE (val->type) = IPOINTER;
497 else if (SPEC_SCLS (expr->right->etype) == S_EEPROM)
498 DCL_TYPE (val->type) = EEPPOINTER;
500 DCL_TYPE (val->type) = POINTER;
501 val->type->next = expr->right->ftype->next;
502 val->etype = getSpec (val->type);
508 werrorfl (expr->filename, expr->lineno, E_INCOMPAT_PTYPES);
510 werror (E_INCOMPAT_PTYPES);
516 /*-----------------------------------------------------------------*/
517 /* printPointerType - generates ival for pointer type */
518 /*-----------------------------------------------------------------*/
519 void _pic16_printPointerType (const char *name, char ptype, void *p)
523 sprintf(buf, "LOW(%s)", name);
524 pic16_emitDS(buf, ptype, p);
525 sprintf(buf, "HIGH(%s)", name);
526 pic16_emitDS(buf, ptype, p);
529 /*-----------------------------------------------------------------*/
530 /* printPointerType - generates ival for pointer type */
531 /*-----------------------------------------------------------------*/
532 void pic16_printPointerType (const char *name, char ptype, void *p)
534 _pic16_printPointerType (name, ptype, p);
535 //pic16_flushDB(ptype, p); /* breaks char* const arr[] = {&c, &c, &c}; */
538 /*-----------------------------------------------------------------*/
539 /* printGPointerType - generates ival for generic pointer type */
540 /*-----------------------------------------------------------------*/
541 void pic16_printGPointerType (const char *iname, const unsigned int itype,
546 _pic16_printPointerType (iname, ptype, p);
554 sprintf(buf, "UPPER(%s)", iname);
555 pic16_emitDS(buf, ptype, p);
559 sprintf(buf, "0x80");
560 pic16_emitDS(buf, ptype, p);
563 debugf("itype = %d\n", itype );
567 //pic16_flushDB(ptype, p); /* might break char* const arr[] = {...}; */
571 /* set to 0 to disable debug messages */
572 #define DEBUG_PRINTIVAL 0
574 /*-----------------------------------------------------------------*/
575 /* pic16_printIvalType - generates ival for int/char */
576 /*-----------------------------------------------------------------*/
578 pic16_printIvalType (symbol *sym, sym_link * type, initList * ilist, char ptype, void *p)
582 // fprintf(stderr, "%s for symbol %s\n",__FUNCTION__, sym->rname);
585 fprintf(stderr, "%s\n",__FUNCTION__);
589 /* if initList is deep */
590 if (ilist && ilist->type == INIT_DEEP)
591 ilist = ilist->init.deep;
593 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
594 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
597 if (!(val = list2val (ilist))) {
598 // assuming a warning has been thrown
602 if (val->type != type) {
603 val = valCastLiteral(type, floatFromVal(val));
606 switch (getSize (type)) {
608 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
612 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
613 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
616 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
617 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
618 pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
620 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
621 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
622 pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
623 pic16_emitDB(pic16aopLiteral(val, 3), ptype, p);
628 /*--------------------------------------------------------------------*/
629 /* pic16_printIvalChar - generates initital value for character array */
630 /*--------------------------------------------------------------------*/
632 pic16_printIvalChar (symbol *sym, sym_link * type, initList * ilist, char *s, char ptype, void *p)
635 int remain, len, ilen;
641 fprintf(stderr, "%s\n",__FUNCTION__);
645 val = list2val (ilist);
647 /* if the value is a character string */
648 if(IS_ARRAY (val->type) && IS_CHAR (val->etype)) {
649 /* length of initializer string (might contain \0, so do not use strlen) */
650 ilen = DCL_ELEM(val->type);
653 DCL_ELEM (type) = ilen;
655 /* len is 0 if declartion equals initializer,
656 * >0 if declaration greater than initializer
657 * <0 if declaration less than initializer
658 * Strategy: if >0 emit 0x00 for the rest of the length,
659 * if <0 then emit only the length of declaration elements
662 len = DCL_ELEM (type) - ilen;
664 // fprintf(stderr, "%s:%d ilen = %i len = %i DCL_ELEM(type) = %i SPEC_CVAL-len = %i\n", __FILE__, __LINE__,
665 // ilen, len, DCL_ELEM(type), strlen(SPEC_CVAL(val->etype).v_char));
668 /* emit initializer */
669 for(remain=0; remain<ilen; remain++)
670 pic16_emitDB(SPEC_CVAL(val->etype).v_char[ remain ], ptype, p);
672 /* fill array with 0x00 */
674 pic16_emitDB(0x00, ptype, p);
677 werror (W_EXCESS_INITIALIZERS, "array of chars", sym->name, sym->lineDef);
679 for(remain=0; remain<DCL_ELEM (type); remain++)
680 pic16_emitDB(SPEC_CVAL(val->etype).v_char[ remain ], ptype, p);
684 // if((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0) {
689 for(remain=0; remain<strlen(s); remain++) {
690 pic16_emitDB(s[remain], ptype, p);
696 /*-----------------------------------------------------------------*/
697 /* pic16_printIvalArray - generates code for array initialization */
698 /*-----------------------------------------------------------------*/
700 pic16_printIvalArray (symbol * sym, sym_link * type, initList * ilist,
704 int lcnt = 0, size = 0;
711 fprintf(stderr, "%s\n",__FUNCTION__);
713 /* take care of the special case */
714 /* array of characters can be init */
716 if (IS_CHAR (type->next)) {
717 if (!IS_LITERAL(list2val(ilist)->etype)) {
718 werror (W_INIT_WRONG);
722 if(pic16_printIvalChar (sym, type,
723 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
724 SPEC_CVAL (sym->etype).v_char, ptype, p))
727 /* not the special case */
728 if (ilist && ilist->type != INIT_DEEP)
730 werror (E_INIT_STRUCT, sym->name);
734 iloop = ilist->init.deep;
735 lcnt = DCL_ELEM (type);
740 pic16_printIval (sym, type->next, iloop, ptype, p);
741 iloop = (iloop ? iloop->next : NULL);
744 /* if not array limits given & we */
745 /* are out of initialisers then */
746 if (!DCL_ELEM (type) && !iloop)
749 /* no of elements given and we */
750 /* have generated for all of them */
752 /* if initializers left */
754 werror (W_EXCESS_INITIALIZERS, "array", sym->name, sym->lineDef);
760 /* if we have not been given a size */
761 if (!DCL_ELEM (type))
762 DCL_ELEM (type) = size;
767 /*-----------------------------------------------------------------*/
768 /* pic16_printIvalBitFields - generate initializer for bitfields */
769 /*-----------------------------------------------------------------*/
770 void pic16_printIvalBitFields(symbol **sym, initList **ilist, char ptype, void *p)
774 initList *lilist = *ilist ;
775 unsigned long ival = 0;
780 fprintf(stderr, "%s\n",__FUNCTION__);
786 val = list2val(lilist);
788 if (SPEC_BLEN(lsym->etype) > 8) {
789 size += ((SPEC_BLEN (lsym->etype) / 8) +
790 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
793 size = ((SPEC_BLEN (lsym->etype) / 8) +
794 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
797 i <<= SPEC_BSTR (lsym->etype);
799 if (! ( lsym->next &&
800 (lilist && lilist->next) &&
801 (IS_BITFIELD(lsym->next->type)) &&
802 (SPEC_BSTR(lsym->next->etype)))) break;
804 lilist = lilist->next;
808 pic16_emitDB(BYTE_IN_LONG(ival, 0), ptype, p);
812 pic16_emitDB(BYTE_IN_LONG(ival, 0), ptype, p);
813 pic16_emitDB(BYTE_IN_LONG(ival, 1), ptype, p);
816 case 4: /* EEP: why is this db and not dw? */
817 pic16_emitDB(BYTE_IN_LONG(ival, 0), ptype, p);
818 pic16_emitDB(BYTE_IN_LONG(ival, 1), ptype, p);
819 pic16_emitDB(BYTE_IN_LONG(ival, 2), ptype, p);
820 pic16_emitDB(BYTE_IN_LONG(ival, 3), ptype, p);
823 /* VR - only 1,2,4 size long can be handled???? Why? */
824 fprintf(stderr, "%s:%d: unhandled case. Contact author.\n", __FILE__, __LINE__);
832 /*-----------------------------------------------------------------*/
833 /* printIvalStruct - generates initial value for structures */
834 /*-----------------------------------------------------------------*/
835 void pic16_printIvalStruct (symbol * sym, sym_link * type,
836 initList * ilist, char ptype, void *p)
839 initList *iloop = NULL;
843 fprintf(stderr, "%s\n",__FUNCTION__);
846 sflds = SPEC_STRUCT (type)->fields;
849 if (ilist->type != INIT_DEEP) {
850 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
854 iloop = ilist->init.deep;
857 for (; (sflds && iloop); sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
858 // fprintf(stderr, "%s:%d sflds: %p\tiloop = %p\n", __FILE__, __LINE__, sflds, iloop);
859 if (IS_BITFIELD(sflds->type)) {
860 pic16_printIvalBitFields(&sflds, &iloop, ptype, p);
862 pic16_printIval (sym, sflds->type, iloop, ptype, p);
866 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
871 /*-----------------------------------------------------------------*/
872 /* printIvalUnion - generates initial value for unions */
873 /*-----------------------------------------------------------------*/
874 void pic16_printIvalUnion (symbol * sym, sym_link * type,
875 initList * ilist, char ptype, void *p)
878 initList *iloop = NULL;
883 fprintf(stderr, "%s\n",__FUNCTION__);
895 if (type) size = SPEC_STRUCT(type)->size;
897 if (i == 1 && size >= 0 && size <= sizeof(long))
899 unsigned long val = ulFromVal (list2val(ilist));
902 pic16_emitDB(val, ptype, p);
908 fprintf( stderr, "INCOMPLETE SUPPORT FOR INITIALIZED union---FALLING BACK TO struct\n" );
909 fprintf( stderr, "This is a bug. Please file a bug-report with your source attached.\n" );
910 pic16_printIvalStruct( sym, type, ilist, ptype, p );
914 pic16_isUnion( symbol *sym, sym_link *type )
916 if (type && SPEC_STRUCT(type)->type == UNION) return 1;
920 /*--------------------------------------------------------------------------*/
921 /* pic16_printIvalCharPtr - generates initial values for character pointers */
922 /*--------------------------------------------------------------------------*/
923 int pic16_printIvalCharPtr (symbol * sym, sym_link * type, value * val, char ptype, void *p)
927 /* PENDING: this is _very_ mcs51 specific, including a magic
929 It's also endin specific.
931 VR - Attempting to port this function to pic16 port - 8-Jun-2004
936 fprintf(stderr, "%s\n",__FUNCTION__);
939 size = getSize (type);
941 if (val->name && strlen (val->name))
943 if (size == 1) /* This appears to be Z80 specific?? */
945 pic16_emitDS(val->name, ptype, p);
949 pic16_printPointerType (val->name, ptype, p);
954 if (IS_PTR (val->type)) {
955 type = DCL_TYPE (val->type);
957 type = PTR_TYPE (SPEC_OCLS (val->etype));
959 if (val->sym && val->sym->isstrlit) {
960 // this is a literal string
963 pic16_printGPointerType(val->name, type, ptype, p);
967 fprintf (stderr, "*** internal error: unknown size in "
968 "printIvalCharPtr.\n");
974 // these are literals assigned to pointers
978 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
981 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
982 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
985 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
986 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
987 pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
995 if (val->sym && val->sym->isstrlit) { // && !isinSet(statsg->syms, val->sym)) {
996 if(ptype == 'p' && !isinSet(statsg->syms, val->sym))addSet (&statsg->syms, val->sym);
997 else if(ptype == 'f' /*&& !isinSet(rel_idataSymSet, val->sym)*/)addSet(&rel_idataSymSet, val->sym);
1003 /*-----------------------------------------------------------------------*/
1004 /* pic16_printIvalFuncPtr - generate initial value for function pointers */
1005 /*-----------------------------------------------------------------------*/
1006 void pic16_printIvalFuncPtr (sym_link * type, initList * ilist, char ptype, void *p)
1013 fprintf(stderr, "%s\n",__FUNCTION__);
1017 val = list2val (ilist);
1019 val = valCastLiteral(type, 0.0);
1022 // an error has been thrown already
1026 if (IS_LITERAL(val->etype)) {
1027 if (compareType(type, val->etype) == 0) {
1028 werrorfl (ilist->filename, ilist->lineno, E_INCOMPAT_TYPES);
1029 printFromToType (val->type, type);
1031 pic16_printIvalCharPtr (NULL, type, val, ptype, p);
1035 /* check the types */
1036 if ((dLvl = compareType (val->type, type->next)) <= 0)
1038 pic16_emitDB(0x00, ptype, p);
1042 /* now generate the name */
1044 pic16_printGPointerType (val->name, DCL_TYPE(val->type), ptype, p);
1046 pic16_printGPointerType (val->sym->rname, DCL_TYPE(val->type), ptype, p);
1048 if(IS_FUNC(val->sym->type) && !val->sym->used && !IS_STATIC(val->sym->etype)) {
1050 if(!checkSym(publics, val->sym))
1051 if(checkAddSym(&externs, val->sym) && (ptype == 'f')) {
1052 /* this has not been declared as extern
1053 * so declare it as a 'late extern' just after the symbol */
1054 fprintf((FILE *)p, ";\tdeclare symbol as extern\n");
1055 fprintf((FILE *)p, "\textern\t%s\n", val->sym->rname);
1056 fprintf((FILE *)p, ";\tcontinue variable declaration\n");
1065 /*-----------------------------------------------------------------*/
1066 /* pic16_printIvalPtr - generates initial value for pointers */
1067 /*-----------------------------------------------------------------*/
1068 void pic16_printIvalPtr (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p)
1074 fprintf(stderr, "%s:%d initialising pointer: %s size: %d\n", __FILE__, __LINE__,
1075 sym->rname, getSize(sym->type));
1079 if (ilist && (ilist->type == INIT_DEEP))
1080 ilist = ilist->init.deep;
1082 /* function pointer */
1083 if (IS_FUNC (type->next))
1085 pic16_printIvalFuncPtr (type, ilist, ptype, p);
1089 if (!(val = pic16_initPointer (ilist, type)))
1092 /* if character pointer */
1093 if (IS_CHAR (type->next))
1094 if (pic16_printIvalCharPtr (sym, type, val, ptype, p))
1097 /* check the type */
1098 if (compareType (type, val->type) == 0) {
1099 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
1100 printFromToType (val->type, type);
1103 /* if val is literal */
1104 if (IS_LITERAL (val->etype))
1106 switch (getSize (type))
1109 pic16_emitDB((unsigned int) ulFromVal (val) & 0xff, ptype, p);
1112 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
1113 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
1116 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
1117 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
1118 pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
1121 fprintf(stderr, "%s:%d size = %d\n", __FILE__, __LINE__, getSize(type));
1128 size = getSize (type);
1130 if (size == 1) /* Z80 specific?? */
1132 pic16_emitDS(val->name, ptype, p);
1136 pic16_printPointerType (val->name, ptype, p);
1140 pic16_printGPointerType (val->name, (IS_PTR(type)?DCL_TYPE(type):PTR_TYPE(SPEC_OCLS(sym->etype))),
1149 /*-----------------------------------------------------------------*/
1150 /* pic16_printIval - generates code for initial value */
1151 /*-----------------------------------------------------------------*/
1152 void pic16_printIval (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p)
1160 fprintf(stderr, "%s:%d generating init for %s\n", __FILE__, __LINE__, sym->name);
1161 fprintf(stderr, "%s: IS_STRUCT: %d IS_ARRAY: %d IS_PTR: %d IS_SPEC: %d\n", sym->name,
1162 IS_STRUCT(type), IS_ARRAY(type), IS_PTR(type), IS_SPEC(type));
1165 /* if structure then */
1166 if (IS_STRUCT (type))
1168 if (pic16_isUnion(sym, type))
1170 //fprintf(stderr,"%s union\n",__FUNCTION__);
1171 pic16_printIvalUnion (sym, type, ilist, ptype, p);
1173 //fprintf(stderr,"%s struct\n",__FUNCTION__);
1174 pic16_printIvalStruct (sym, type, ilist, ptype, p);
1179 /* if this is an array */
1180 if (IS_ARRAY (type))
1182 // fprintf(stderr,"%s array\n",__FUNCTION__);
1183 pic16_printIvalArray (sym, type, ilist, ptype, p);
1190 // not an aggregate, ilist must be a node
1191 if (ilist->type!=INIT_NODE) {
1192 // or a 1-element list
1193 if (ilist->init.deep->next) {
1194 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar",
1197 ilist=ilist->init.deep;
1202 // and the type must match
1203 itype=ilist->init.node->ftype;
1205 if (compareType(type, itype)==0) {
1206 // special case for literal strings
1207 if (IS_ARRAY (itype) && IS_CHAR (getSpec(itype)) &&
1208 // which are really code pointers
1209 IS_PTR(type) && DCL_TYPE(type)==CPOINTER) {
1212 // werrorfl (ilist->filename, ilist->lineno, E_TYPE_MISMATCH, "assignment", " ");
1213 // printFromToType(itype, type);
1220 /* if this is a pointer */
1223 // fprintf(stderr,"%s pointer\n",__FUNCTION__);
1224 pic16_printIvalPtr (sym, type, ilist, ptype, p);
1229 /* if type is SPECIFIER */
1232 // fprintf(stderr,"%s spec\n",__FUNCTION__);
1233 pic16_printIvalType (sym, type, ilist, ptype, p);
1238 int PIC16_IS_CONFIG_ADDRESS(int address)
1240 return ((address >= pic16->cwInfo.confAddrStart && address <= pic16->cwInfo.confAddrEnd));
1243 int PIC16_IS_IDLOC_ADDRESS(int address)
1245 return ((address >= pic16->idInfo.idAddrStart && address <= pic16->idInfo.idAddrEnd));
1248 /* wrapper function for the above */
1249 int PIC16_IS_HWREG_ADDRESS(int address)
1251 return (PIC16_IS_CONFIG_ADDRESS(address) || PIC16_IS_IDLOC_ADDRESS(address));
1255 /*-----------------------------------------------------------------*/
1256 /* emitStaticSeg - emitcode for the static segment */
1257 /*-----------------------------------------------------------------*/
1259 pic16emitStaticSeg (memmap * map)
1262 static int didcode=0;
1264 //fprintf(stderr, "%s\n",__FUNCTION__);
1268 /* for all variables in this segment do */
1269 for (sym = setFirstItem (map->syms); sym;
1270 sym = setNextItem (map->syms))
1274 fprintf(stderr, "%s\t%s: sym: %s\tused: %d\tSPEC_ABSA: %d\tSPEC_AGGREGATE: %d\tCODE: %d\n\
1275 CODESPACE: %d\tCONST: %d\tPTRCONST: %d\tSPEC_CONST: %d\n", __FUNCTION__,
1276 map->sname, sym->name, sym->used, SPEC_ABSA(sym->etype), IS_AGGREGATE(sym->type),
1277 IS_CODE(sym->etype), IN_CODESPACE( SPEC_OCLS(sym->etype)), IS_CONSTANT(sym->etype),
1278 IS_PTR_CONST(sym->etype), SPEC_CONST(sym->etype));
1279 printTypeChain( sym->type, stderr );
1280 fprintf(stderr, "\n");
1283 if(SPEC_ABSA(sym->etype) && PIC16_IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype))) {
1284 pic16_assignConfigWordValue(SPEC_ADDR(sym->etype),
1285 (int) ulFromVal (list2val(sym->ival)));
1290 if(SPEC_ABSA(sym->etype) && PIC16_IS_IDLOC_ADDRESS(SPEC_ADDR(sym->etype))) {
1291 pic16_assignIdByteValue(SPEC_ADDR(sym->etype),
1292 (char) ulFromVal (list2val(sym->ival)));
1297 /* if it is "extern" then do nothing */
1298 if (IS_EXTERN (sym->etype)/* && !SPEC_ABSA(sym->etype)*/) {
1299 checkAddSym(&externs, sym);
1303 /* if it is not static add it to the public
1305 if (!IS_STATIC (sym->etype)) {
1306 /* do not emit if it is a config word declaration */
1307 checkAddSym(&publics, sym);
1310 /* print extra debug info if required */
1311 if (options.debug || sym->level == 0) {
1312 /* NOTE to me - cdbFile may be null in which case,
1313 * the sym name will be printed to stdout. oh well */
1314 debugFile->writeSymbol(sym);
1317 /* if it has an absolute address */
1318 if (SPEC_ABSA (sym->etype)) {
1319 // fprintf(stderr, "%s:%d spec_absa is true for symbol: %s\n",
1320 // __FILE__, __LINE__, sym->name);
1322 /* if it has an initial value */
1330 /* symbol has absolute address and initial value */
1332 resolveIvalSym (sym->ival, sym->type);
1333 asym = newSymbol(sym->rname, 0);
1334 abSym = Safe_calloc(1, sizeof(absSym));
1335 strcpy(abSym->name, sym->rname);
1336 abSym->address = SPEC_ADDR( sym->etype );
1337 addSet(&absSymSet, abSym);
1339 pb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute Ival"));
1340 pic16_addpBlock(pb);
1342 pcf = pic16_newpCodeFunction(moduleName, asym->name);
1343 PCF(pcf)->absblock = 1;
1345 pic16_addpCode2pBlock(pb,pcf);
1346 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
1347 //fprintf(stderr, "%s:%d [1] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1348 pic16_printIval(sym, sym->type, sym->ival, 'p', (void *)pb);
1349 pic16_flushDB('p', (void *)pb);
1351 pic16_addpCode2pBlock(pb, pic16_newpCodeFunction(NULL, NULL));
1357 /* symbol has absolute address but no initial value */
1359 /* allocate space */
1360 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
1362 /* special case for character strings */
1363 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1364 SPEC_CVAL (sym->etype).v_char) {
1366 // fprintf(stderr, "%s:%d printing code string from %s\n", __FILE__, __LINE__, sym->rname);
1368 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
1370 fprintf (stderr, "%s:%u(%s): do not know how to intialize symbol %s\n", __FILE__, __LINE__, __FUNCTION__, sym->rname);
1376 // fprintf(stderr, "%s:%d spec_absa is false for symbol: %s\n",
1377 // __FILE__, __LINE__, sym->name);
1380 /* if it has an initial value */
1384 /* symbol doesn't have absolute address but has initial value */
1385 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
1386 resolveIvalSym (sym->ival, sym->type);
1388 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block for Ival"));
1389 pic16_addpBlock(pb);
1392 /* make sure that 'code' directive is emitted before, once */
1393 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir("code", NULL));
1398 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
1399 //fprintf(stderr, "%s:%d [2] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1400 pic16_printIval(sym, sym->type, sym->ival, 'p', (void *)pb);
1401 pic16_flushDB('p', (void *)pb);
1404 /* symbol doesn't have absolute address and no initial value */
1405 /* allocate space */
1406 // fprintf(stderr, "%s:%d [3] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1407 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
1408 /* special case for character strings */
1409 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1410 SPEC_CVAL (sym->etype).v_char) {
1412 // fprintf(stderr, "%s:%d printing code string for %s\n", __FILE__, __LINE__, sym->rname);
1414 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
1425 /*-----------------------------------------------------------------*/
1426 /* pic16_emitConfigRegs - emits the configuration registers */
1427 /*-----------------------------------------------------------------*/
1428 void pic16_emitConfigRegs(FILE *of)
1432 for(i=0;i<=(pic16->cwInfo.confAddrEnd-pic16->cwInfo.confAddrStart);i++)
1433 if(pic16->cwInfo.crInfo[i].emit) //mask != -1)
1434 fprintf (of, "\t__config 0x%x, 0x%hhx\n",
1435 pic16->cwInfo.confAddrStart+i,
1436 pic16->cwInfo.crInfo[i].value);
1439 void pic16_emitIDRegs(FILE *of)
1443 for(i=0;i<=(pic16->idInfo.idAddrEnd-pic16->idInfo.idAddrStart);i++)
1444 if(pic16->idInfo.irInfo[i].emit)
1445 fprintf (of, "\t__idlocs 0x%06x, 0x%hhx\n",
1446 pic16->idInfo.idAddrStart+i,
1447 pic16->idInfo.irInfo[i].value);
1454 /* no special considerations for the following
1455 data, idata & bit & xdata */
1456 pic16emitRegularMap (data, TRUE, TRUE);
1457 pic16emitRegularMap (idata, TRUE, TRUE);
1458 pic16emitRegularMap (bit, TRUE, FALSE);
1459 pic16emitRegularMap (xdata, TRUE, TRUE);
1460 pic16emitRegularMap (sfr, FALSE, FALSE);
1461 pic16emitRegularMap (sfrbit, FALSE, FALSE);
1462 pic16emitRegularMap (code, TRUE, FALSE);
1463 pic16emitStaticSeg (statsg);
1464 pic16emitStaticSeg (c_abs);
1467 /*-----------------------------------------------------------------*/
1468 /* createInterruptVect - creates the interrupt vector */
1469 /*-----------------------------------------------------------------*/
1471 pic16createInterruptVect (struct dbuf_s * vBuf)
1473 /* if the main is only a prototype ie. no body then do nothing */
1475 if (!IFFUNC_HASBODY(mainf->type)) {
1476 /* if ! compile only then main function should be present */
1477 if (!options.cc_only)
1483 if((!pic16_options.omit_ivt) || (pic16_options.omit_ivt && pic16_options.leave_reset)) {
1484 dbuf_printf (vBuf, ";\t.area\t%s\n", CODE_NAME);
1485 dbuf_printf (vBuf, ".intvecs\tcode\t0x%06x\n", pic16_options.ivt_loc);
1487 /* this is an overkill since WE are the port,
1488 * and we know if we have a genIVT function! */
1490 port->genIVT(vFile, interrupts, maxInterrupts);
1498 /*-----------------------------------------------------------------*/
1499 /* pic16initialComments - puts in some initial comments */
1500 /*-----------------------------------------------------------------*/
1502 pic16initialComments (FILE * afile)
1504 initialComments (afile);
1505 fprintf (afile, "; PIC16 port for the Microchip 16-bit core micros\n");
1507 fprintf (afile, "; * Extended Instruction Set\n");
1509 if(pic16_mplab_comp)
1510 fprintf(afile, "; * MPLAB/MPASM/MPASMWIN/MPLINK compatibility mode enabled\n");
1511 fprintf (afile, iComments2);
1514 fprintf (afile, "\n\t.ident \"SDCC version %s #%s [pic16 port]%s\"\n",
1515 SDCC_VERSION_STR, getBuildNumber(), (!xinst?"":" {extended}") );
1520 pic16_stringInSet(const char *str, set **world, int autoAdd)
1527 for (s = setFirstItem(*world); s; s = setNextItem(*world))
1530 if (0 == strcmp(s, str)) return 1;
1534 if (autoAdd) addSet(world, Safe_strdup(str));
1539 pic16_emitSymbolIfNew(FILE *file, const char *fmt, const char *sym, int checkLocals)
1541 static set *emitted = NULL;
1543 if (!pic16_stringInSet(sym, &emitted, 1)) {
1544 /* sym was not in emittedSymbols */
1545 if (!checkLocals || !pic16_stringInSet(sym, &pic16_localFunctions, 0)) {
1546 /* sym is not a locally defined function---avoid bug #1443651 */
1547 fprintf( file, fmt, sym );
1554 /*-----------------------------------------------------------------*/
1555 /* printPublics - generates global declarations for publics */
1556 /*-----------------------------------------------------------------*/
1558 pic16printPublics (FILE *afile)
1562 fprintf (afile, "\n%s", iComments2);
1563 fprintf (afile, "; public variables in this module\n");
1564 fprintf (afile, "%s", iComments2);
1566 for(sym = setFirstItem (publics); sym; sym = setNextItem (publics))
1568 if(!IS_STATIC(sym->etype))
1569 pic16_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1572 /*-----------------------------------------------------------------*/
1573 /* printExterns - generates extern declarations for externs */
1574 /*-----------------------------------------------------------------*/
1576 pic16_printExterns(FILE *afile)
1580 /* print nothing if no externs to declare */
1581 if(!elementsInSet(externs) && !elementsInSet(pic16_builtin_functions))
1584 fprintf(afile, "\n%s", iComments2);
1585 fprintf(afile, "; extern variables in this module\n");
1586 fprintf(afile, "%s", iComments2);
1588 for(sym = setFirstItem(externs); sym; sym = setNextItem(externs))
1589 pic16_emitSymbolIfNew(afile, "\textern %s\n", sym->rname, 1);
1591 for(sym = setFirstItem(pic16_builtin_functions); sym; sym = setNextItem(pic16_builtin_functions))
1592 pic16_emitSymbolIfNew(afile, "\textern _%s\n", sym->name, 1);
1595 /*-----------------------------------------------------------------*/
1596 /* emitOverlay - will emit code for the overlay stuff */
1597 /*-----------------------------------------------------------------*/
1599 pic16emitOverlay (struct dbuf_s *aBuf)
1603 if (!elementsInSet (ovrSetSets))
1604 dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name);
1606 /* for each of the sets in the overlay segment do */
1607 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1608 ovrset = setNextItem (ovrSetSets))
1613 if (elementsInSet (ovrset))
1615 /* this dummy area is used to fool the assembler
1616 otherwise the assembler will append each of these
1617 declarations into one chunk and will not overlay
1619 dbuf_printf (aBuf, ";\t.area _DUMMY\n");
1620 /* output the area informtion */
1621 dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1624 for (sym = setFirstItem (ovrset); sym;
1625 sym = setNextItem (ovrset))
1628 /* if extern then do nothing */
1629 if (IS_EXTERN (sym->etype))
1632 /* if allocation required check is needed
1633 then check if the symbol really requires
1634 allocation only for local variables */
1635 if (!IS_AGGREGATE (sym->type) &&
1636 !(sym->_isparm && !IS_REGPARM (sym->etype))
1637 && !sym->allocreq && sym->level)
1640 /* if global variable & not static or extern
1641 and addPublics allowed then add it to the public set */
1642 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1643 && !IS_STATIC (sym->etype)) {
1644 // fprintf(stderr, "%s:%d %s accessed\n", __FILE__, __LINE__, __FUNCTION__);
1645 checkAddSym(&publics, sym);
1646 // addSetHead (&publics, sym);
1649 /* if extern then do nothing or is a function
1651 if (IS_FUNC (sym->type))
1655 /* if is has an absolute address then generate
1656 an equate for this no need to allocate space */
1657 if (SPEC_ABSA (sym->etype))
1660 if (options.debug || sym->level == 0)
1661 dbuf_printf (aBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1663 dbuf_printf (aBuf, "%s\t=\t0x%04x\n",
1665 SPEC_ADDR (sym->etype));
1669 if (options.debug || sym->level == 0)
1670 dbuf_printf (aBuf, "==.\n");
1672 /* allocate space */
1673 dbuf_printf (aBuf, "%s:\n", sym->rname);
1674 dbuf_printf (aBuf, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1681 void emitStatistics(FILE *asmFile)
1683 unsigned long isize, udsize, ramsize;
1684 statistics.isize = pic16_countInstructions();
1685 isize = (statistics.isize >= 0) ? statistics.isize : 0;
1686 udsize = (statistics.udsize >= 0) ? statistics.udsize : 0;
1687 ramsize = pic16 ? pic16->RAMsize : 0x200;
1688 ramsize -= 256; /* ignore access bank and SFRs */
1689 if (ramsize == 0) ramsize = 64; /* prevent division by zero (below) */
1691 fprintf (asmFile, "\n\n; Statistics:\n");
1692 fprintf (asmFile, "; code size:\t%5ld (0x%04lx) bytes (%5.2f%%)\n; \t%5ld (0x%04lx) words\n",
1693 isize, isize, (isize*100.0)/(128UL << 10),
1694 isize>>1, isize>>1);
1695 fprintf (asmFile, "; udata size:\t%5ld (0x%04lx) bytes (%5.2f%%)\n",
1696 udsize, udsize, (udsize*100.0) / (1.0 * ramsize));
1697 fprintf (asmFile, "; access size:\t%5ld (0x%04lx) bytes\n",
1698 statistics.intsize, statistics.intsize);
1700 fprintf (asmFile, "\n\n");
1705 /*-----------------------------------------------------------------*/
1706 /* glue - the final glue that hold the whole thing together */
1707 /*-----------------------------------------------------------------*/
1712 struct dbuf_s ovrBuf;
1715 dbuf_init(&ovrBuf, 4096);
1716 dbuf_init(&vBuf, 4096);
1718 mainf = newSymbol ("main", 0);
1721 mainf = findSymWithLevel(SymbolTab, mainf);
1723 pic16_pCodeInitRegisters();
1725 if(pic16_options.no_crt && mainf && IFFUNC_HASBODY(mainf->type)) {
1726 pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
1728 pic16_addpBlock(pb);
1730 /* entry point @ start of CSEG */
1731 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup",-1));
1734 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1735 pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("_stack_end"))));
1736 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1737 pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("_stack_end"))));
1740 /* put in the call to main */
1741 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
1743 if (options.mainreturn) {
1744 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
1745 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
1747 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
1748 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
1752 /* At this point we've got all the code in the form of pCode structures */
1753 /* Now it needs to be rearranged into the order it should be placed in the */
1756 pic16_movepBlock2Head('P'); // Last
1757 pic16_movepBlock2Head(code->dbName);
1758 pic16_movepBlock2Head('X');
1759 pic16_movepBlock2Head(statsg->dbName); // First
1761 /* print the global struct definitions */
1763 /* PENDING: this isnt the best place but it will do */
1764 if (port->general.glue_up_main) {
1765 /* create the interrupt vector table */
1766 pic16createInterruptVect (&vBuf);
1769 /* emit code for the all the variables declared */
1772 /* do the overlay segments */
1773 pic16emitOverlay(&ovrBuf);
1774 pic16_AnalyzepCode('*');
1777 if(pic16_options.dumpcalltree) {
1780 sprintf(buffer, dstFileName);
1781 strcat(buffer, ".calltree");
1782 cFile = fopen(buffer, "w");
1783 pic16_printCallTree( cFile );
1788 pic16_InlinepCode();
1789 pic16_AnalyzepCode('*');
1792 if(pic16_debug_verbose)
1795 /* now put it all together into the assembler file */
1796 /* create the assembler file name */
1797 if((noAssemble || options.c1mode) && fullDstFileName) {
1798 sprintf (buffer, fullDstFileName);
1800 sprintf (buffer, dstFileName);
1801 strcat (buffer, ".asm");
1804 if(!(asmFile = fopen (buffer, "w"))) {
1805 werror (E_FILE_OPEN_ERR, buffer);
1809 /* initial comments */
1810 pic16initialComments (asmFile);
1812 /* print module name */
1814 fprintf(asmFile, "\t.file\t\"%s\"\n", fullSrcFileName);
1816 /* Let the port generate any global directives, etc. */
1817 if(port->genAssemblerPreamble) {
1818 port->genAssemblerPreamble(asmFile);
1821 /* Put all variables into a cblock */
1822 pic16_AnalyzeBanking();
1825 if(pic16_options.opt_flags & OF_LR_SUPPORT) {
1826 pic16_OptimizeLocalRegs();
1830 /* remove redundant BANKSELs -- added by RN 2005-01-17 */
1831 if(pic16_options.opt_banksel > 1) {
1832 pic16_OptimizeBanksel();
1835 /* turn GOTOs into BRAs -- added by RN 2004-11-16 */
1836 if(pic16_options.opt_flags & OF_OPTIMIZE_GOTO) {
1837 pic16_OptimizeJumps();
1840 /* print the global variables in this module */
1841 pic16printPublics (asmFile);
1843 /* print the extern variables to this module */
1844 pic16_printExterns(asmFile);
1846 pic16_writeUsedRegs(asmFile);
1849 /* no xdata in pic */
1850 /* if external stack then reserve space of it */
1851 if(mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1852 fprintf (asmFile, "%s", iComments2);
1853 fprintf (asmFile, "; external stack \n");
1854 fprintf (asmFile, "%s", iComments2);
1855 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1856 fprintf (asmFile,";\t.ds 256\n");
1861 /* no xdata in pic */
1862 /* copy xtern ram data */
1863 fprintf (asmFile, "%s", iComments2);
1864 fprintf (asmFile, "; external ram data\n");
1865 fprintf (asmFile, "%s", iComments2);
1866 dbuf_write_and_destroy (&xdata->oBuf, asmFile);
1870 /* copy the bit segment */
1871 fprintf (asmFile, "%s", iComments2);
1872 fprintf (asmFile, "; bit data\n");
1873 fprintf (asmFile, "%s", iComments2);
1874 dbuf_write_and_destroy (&bit->oBuf, asmFile);
1877 /* copy the interrupt vector table */
1878 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1879 fprintf (asmFile, "\n%s", iComments2);
1880 fprintf (asmFile, "; interrupt vector \n");
1881 fprintf (asmFile, "%s", iComments2);
1882 dbuf_write_and_destroy (&vBuf, asmFile);
1885 /* copy global & static initialisations */
1886 fprintf (asmFile, "\n%s", iComments2);
1887 fprintf (asmFile, "; global & static initialisations\n");
1888 fprintf (asmFile, "%s", iComments2);
1890 if(pic16_debug_verbose)
1891 fprintf(asmFile, "; A code from now on!\n");
1893 pic16_copypCode(asmFile, 'A');
1895 if(pic16_options.no_crt) {
1896 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1897 fprintf(asmFile, "\tcode\n");
1898 fprintf(asmFile,"__sdcc_gsinit_startup:\n");
1902 // dbuf_write_and_destroy (&code->oBuf, stderr);
1904 fprintf(asmFile, "; I code from now on!\n");
1905 pic16_copypCode(asmFile, 'I');
1907 if(pic16_debug_verbose)
1908 fprintf(asmFile, "; dbName from now on!\n");
1910 pic16_copypCode(asmFile, statsg->dbName);
1912 if(pic16_options.no_crt) {
1913 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
1914 fprintf (asmFile,"\tgoto\t__sdcc_program_startup\n");
1918 if(pic16_debug_verbose)
1919 fprintf(asmFile, "; X code from now on!\n");
1921 pic16_copypCode(asmFile, 'X');
1923 if(pic16_debug_verbose)
1924 fprintf(asmFile, "; M code from now on!\n");
1926 pic16_copypCode(asmFile, 'M');
1928 pic16_copypCode(asmFile, code->dbName);
1930 pic16_copypCode(asmFile, 'P');
1932 emitStatistics(asmFile);
1934 fprintf (asmFile,"\tend\n");