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);
1387 resolveIvalSym (sym->ival, sym->type);
1389 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block for Ival"));
1390 pic16_addpBlock(pb);
1393 /* make sure that 'code' directive is emitted before, once */
1394 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir("code", NULL));
1399 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
1400 //fprintf(stderr, "%s:%d [2] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1401 pic16_printIval(sym, sym->type, sym->ival, 'p', (void *)pb);
1402 pic16_flushDB('p', (void *)pb);
1406 /* symbol doesn't have absolute address and no initial value */
1407 /* allocate space */
1408 // fprintf(stderr, "%s:%d [3] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1409 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
1410 /* special case for character strings */
1411 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1412 SPEC_CVAL (sym->etype).v_char) {
1414 // fprintf(stderr, "%s:%d printing code string for %s\n", __FILE__, __LINE__, sym->rname);
1416 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
1427 /*-----------------------------------------------------------------*/
1428 /* pic16_emitConfigRegs - emits the configuration registers */
1429 /*-----------------------------------------------------------------*/
1430 void pic16_emitConfigRegs(FILE *of)
1434 for(i=0;i<=(pic16->cwInfo.confAddrEnd-pic16->cwInfo.confAddrStart);i++)
1435 if(pic16->cwInfo.crInfo[i].emit) //mask != -1)
1436 fprintf (of, "\t__config 0x%x, 0x%hhx\n",
1437 pic16->cwInfo.confAddrStart+i,
1438 pic16->cwInfo.crInfo[i].value);
1441 void pic16_emitIDRegs(FILE *of)
1445 for(i=0;i<=(pic16->idInfo.idAddrEnd-pic16->idInfo.idAddrStart);i++)
1446 if(pic16->idInfo.irInfo[i].emit)
1447 fprintf (of, "\t__idlocs 0x%06x, 0x%hhx\n",
1448 pic16->idInfo.idAddrStart+i,
1449 pic16->idInfo.irInfo[i].value);
1456 /* no special considerations for the following
1457 data, idata & bit & xdata */
1458 pic16emitRegularMap (data, TRUE, TRUE);
1459 pic16emitRegularMap (idata, TRUE, TRUE);
1460 pic16emitRegularMap (bit, TRUE, FALSE);
1461 pic16emitRegularMap (xdata, TRUE, TRUE);
1462 pic16emitRegularMap (sfr, FALSE, FALSE);
1463 pic16emitRegularMap (sfrbit, FALSE, FALSE);
1464 pic16emitRegularMap (code, TRUE, FALSE);
1465 pic16emitStaticSeg (statsg);
1466 pic16emitStaticSeg (c_abs);
1469 /*-----------------------------------------------------------------*/
1470 /* createInterruptVect - creates the interrupt vector */
1471 /*-----------------------------------------------------------------*/
1473 pic16createInterruptVect (struct dbuf_s * vBuf)
1475 /* if the main is only a prototype ie. no body then do nothing */
1477 if (!IFFUNC_HASBODY(mainf->type)) {
1478 /* if ! compile only then main function should be present */
1479 if (!options.cc_only)
1485 if((!pic16_options.omit_ivt) || (pic16_options.omit_ivt && pic16_options.leave_reset)) {
1486 dbuf_printf (vBuf, ";\t.area\t%s\n", CODE_NAME);
1487 dbuf_printf (vBuf, ".intvecs\tcode\t0x%06x\n", pic16_options.ivt_loc);
1489 /* this is an overkill since WE are the port,
1490 * and we know if we have a genIVT function! */
1492 port->genIVT(vFile, interrupts, maxInterrupts);
1500 /*-----------------------------------------------------------------*/
1501 /* pic16initialComments - puts in some initial comments */
1502 /*-----------------------------------------------------------------*/
1504 pic16initialComments (FILE * afile)
1506 initialComments (afile);
1507 fprintf (afile, "; PIC16 port for the Microchip 16-bit core micros\n");
1509 fprintf (afile, "; * Extended Instruction Set\n");
1511 if(pic16_mplab_comp)
1512 fprintf(afile, "; * MPLAB/MPASM/MPASMWIN/MPLINK compatibility mode enabled\n");
1513 fprintf (afile, iComments2);
1516 fprintf (afile, "\n\t.ident \"SDCC version %s #%s [pic16 port]%s\"\n",
1517 SDCC_VERSION_STR, getBuildNumber(), (!xinst?"":" {extended}") );
1522 pic16_stringInSet(const char *str, set **world, int autoAdd)
1529 for (s = setFirstItem(*world); s; s = setNextItem(*world))
1532 if (0 == strcmp(s, str)) return 1;
1536 if (autoAdd) addSet(world, Safe_strdup(str));
1541 pic16_emitSymbolIfNew(FILE *file, const char *fmt, const char *sym, int checkLocals)
1543 static set *emitted = NULL;
1545 if (!pic16_stringInSet(sym, &emitted, 1)) {
1546 /* sym was not in emittedSymbols */
1547 if (!checkLocals || !pic16_stringInSet(sym, &pic16_localFunctions, 0)) {
1548 /* sym is not a locally defined function---avoid bug #1443651 */
1549 fprintf( file, fmt, sym );
1556 /*-----------------------------------------------------------------*/
1557 /* printPublics - generates global declarations for publics */
1558 /*-----------------------------------------------------------------*/
1560 pic16printPublics (FILE *afile)
1564 fprintf (afile, "\n%s", iComments2);
1565 fprintf (afile, "; public variables in this module\n");
1566 fprintf (afile, "%s", iComments2);
1568 for(sym = setFirstItem (publics); sym; sym = setNextItem (publics))
1570 if(!IS_STATIC(sym->etype))
1571 pic16_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1574 /*-----------------------------------------------------------------*/
1575 /* printExterns - generates extern declarations for externs */
1576 /*-----------------------------------------------------------------*/
1578 pic16_printExterns(FILE *afile)
1582 /* print nothing if no externs to declare */
1583 if(!elementsInSet(externs) && !elementsInSet(pic16_builtin_functions))
1586 fprintf(afile, "\n%s", iComments2);
1587 fprintf(afile, "; extern variables in this module\n");
1588 fprintf(afile, "%s", iComments2);
1590 for(sym = setFirstItem(externs); sym; sym = setNextItem(externs))
1591 pic16_emitSymbolIfNew(afile, "\textern %s\n", sym->rname, 1);
1593 for(sym = setFirstItem(pic16_builtin_functions); sym; sym = setNextItem(pic16_builtin_functions))
1594 pic16_emitSymbolIfNew(afile, "\textern _%s\n", sym->name, 1);
1597 /*-----------------------------------------------------------------*/
1598 /* emitOverlay - will emit code for the overlay stuff */
1599 /*-----------------------------------------------------------------*/
1601 pic16emitOverlay (struct dbuf_s *aBuf)
1605 if (!elementsInSet (ovrSetSets))
1606 dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name);
1608 /* for each of the sets in the overlay segment do */
1609 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1610 ovrset = setNextItem (ovrSetSets))
1615 if (elementsInSet (ovrset))
1617 /* this dummy area is used to fool the assembler
1618 otherwise the assembler will append each of these
1619 declarations into one chunk and will not overlay
1621 dbuf_printf (aBuf, ";\t.area _DUMMY\n");
1622 /* output the area informtion */
1623 dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1626 for (sym = setFirstItem (ovrset); sym;
1627 sym = setNextItem (ovrset))
1630 /* if extern then do nothing */
1631 if (IS_EXTERN (sym->etype))
1634 /* if allocation required check is needed
1635 then check if the symbol really requires
1636 allocation only for local variables */
1637 if (!IS_AGGREGATE (sym->type) &&
1638 !(sym->_isparm && !IS_REGPARM (sym->etype))
1639 && !sym->allocreq && sym->level)
1642 /* if global variable & not static or extern
1643 and addPublics allowed then add it to the public set */
1644 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1645 && !IS_STATIC (sym->etype)) {
1646 // fprintf(stderr, "%s:%d %s accessed\n", __FILE__, __LINE__, __FUNCTION__);
1647 checkAddSym(&publics, sym);
1648 // addSetHead (&publics, sym);
1651 /* if extern then do nothing or is a function
1653 if (IS_FUNC (sym->type))
1657 /* if is has an absolute address then generate
1658 an equate for this no need to allocate space */
1659 if (SPEC_ABSA (sym->etype))
1662 if (options.debug || sym->level == 0)
1663 dbuf_printf (aBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1665 dbuf_printf (aBuf, "%s\t=\t0x%04x\n",
1667 SPEC_ADDR (sym->etype));
1671 if (options.debug || sym->level == 0)
1672 dbuf_printf (aBuf, "==.\n");
1674 /* allocate space */
1675 dbuf_printf (aBuf, "%s:\n", sym->rname);
1676 dbuf_printf (aBuf, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1683 void emitStatistics(FILE *asmFile)
1685 unsigned long isize, udsize, ramsize;
1686 statistics.isize = pic16_countInstructions();
1687 isize = (statistics.isize >= 0) ? statistics.isize : 0;
1688 udsize = (statistics.udsize >= 0) ? statistics.udsize : 0;
1689 ramsize = pic16 ? pic16->RAMsize : 0x200;
1690 ramsize -= 256; /* ignore access bank and SFRs */
1691 if (ramsize == 0) ramsize = 64; /* prevent division by zero (below) */
1693 fprintf (asmFile, "\n\n; Statistics:\n");
1694 fprintf (asmFile, "; code size:\t%5ld (0x%04lx) bytes (%5.2f%%)\n; \t%5ld (0x%04lx) words\n",
1695 isize, isize, (isize*100.0)/(128UL << 10),
1696 isize>>1, isize>>1);
1697 fprintf (asmFile, "; udata size:\t%5ld (0x%04lx) bytes (%5.2f%%)\n",
1698 udsize, udsize, (udsize*100.0) / (1.0 * ramsize));
1699 fprintf (asmFile, "; access size:\t%5ld (0x%04lx) bytes\n",
1700 statistics.intsize, statistics.intsize);
1702 fprintf (asmFile, "\n\n");
1707 /*-----------------------------------------------------------------*/
1708 /* glue - the final glue that hold the whole thing together */
1709 /*-----------------------------------------------------------------*/
1714 struct dbuf_s ovrBuf;
1717 dbuf_init(&ovrBuf, 4096);
1718 dbuf_init(&vBuf, 4096);
1720 mainf = newSymbol ("main", 0);
1723 mainf = findSymWithLevel(SymbolTab, mainf);
1725 pic16_pCodeInitRegisters();
1727 if(pic16_options.no_crt && mainf && IFFUNC_HASBODY(mainf->type)) {
1728 pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
1730 pic16_addpBlock(pb);
1732 /* entry point @ start of CSEG */
1733 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup",-1));
1736 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1737 pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("_stack_end"))));
1738 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1739 pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("_stack_end"))));
1742 /* put in the call to main */
1743 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
1745 if (options.mainreturn) {
1746 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
1747 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
1749 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
1750 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
1754 /* At this point we've got all the code in the form of pCode structures */
1755 /* Now it needs to be rearranged into the order it should be placed in the */
1758 pic16_movepBlock2Head('P'); // Last
1759 pic16_movepBlock2Head(code->dbName);
1760 pic16_movepBlock2Head('X');
1761 pic16_movepBlock2Head(statsg->dbName); // First
1763 /* print the global struct definitions */
1765 /* PENDING: this isnt the best place but it will do */
1766 if (port->general.glue_up_main) {
1767 /* create the interrupt vector table */
1768 pic16createInterruptVect (&vBuf);
1771 /* emit code for the all the variables declared */
1774 /* do the overlay segments */
1775 pic16emitOverlay(&ovrBuf);
1776 pic16_AnalyzepCode('*');
1779 if(pic16_options.dumpcalltree) {
1782 sprintf(buffer, dstFileName);
1783 strcat(buffer, ".calltree");
1784 cFile = fopen(buffer, "w");
1785 pic16_printCallTree( cFile );
1790 pic16_InlinepCode();
1791 pic16_AnalyzepCode('*');
1794 if(pic16_debug_verbose)
1797 /* now put it all together into the assembler file */
1798 /* create the assembler file name */
1799 if((noAssemble || options.c1mode) && fullDstFileName) {
1800 sprintf (buffer, fullDstFileName);
1802 sprintf (buffer, dstFileName);
1803 strcat (buffer, ".asm");
1806 if(!(asmFile = fopen (buffer, "w"))) {
1807 werror (E_FILE_OPEN_ERR, buffer);
1811 /* initial comments */
1812 pic16initialComments (asmFile);
1814 /* print module name */
1816 fprintf(asmFile, "\t.file\t\"%s\"\n", fullSrcFileName);
1818 /* Let the port generate any global directives, etc. */
1819 if(port->genAssemblerPreamble) {
1820 port->genAssemblerPreamble(asmFile);
1823 /* Put all variables into a cblock */
1824 pic16_AnalyzeBanking();
1827 if(pic16_options.opt_flags & OF_LR_SUPPORT) {
1828 pic16_OptimizeLocalRegs();
1832 /* remove redundant BANKSELs -- added by RN 2005-01-17 */
1833 if(pic16_options.opt_banksel > 1) {
1834 pic16_OptimizeBanksel();
1837 /* turn GOTOs into BRAs -- added by RN 2004-11-16 */
1838 if(pic16_options.opt_flags & OF_OPTIMIZE_GOTO) {
1839 pic16_OptimizeJumps();
1842 /* print the global variables in this module */
1843 pic16printPublics (asmFile);
1845 /* print the extern variables to this module */
1846 pic16_printExterns(asmFile);
1848 pic16_writeUsedRegs(asmFile);
1851 /* no xdata in pic */
1852 /* if external stack then reserve space of it */
1853 if(mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1854 fprintf (asmFile, "%s", iComments2);
1855 fprintf (asmFile, "; external stack \n");
1856 fprintf (asmFile, "%s", iComments2);
1857 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1858 fprintf (asmFile,";\t.ds 256\n");
1863 /* no xdata in pic */
1864 /* copy xtern ram data */
1865 fprintf (asmFile, "%s", iComments2);
1866 fprintf (asmFile, "; external ram data\n");
1867 fprintf (asmFile, "%s", iComments2);
1868 dbuf_write_and_destroy (&xdata->oBuf, asmFile);
1872 /* copy the bit segment */
1873 fprintf (asmFile, "%s", iComments2);
1874 fprintf (asmFile, "; bit data\n");
1875 fprintf (asmFile, "%s", iComments2);
1876 dbuf_write_and_destroy (&bit->oBuf, asmFile);
1879 /* copy the interrupt vector table */
1880 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1881 fprintf (asmFile, "\n%s", iComments2);
1882 fprintf (asmFile, "; interrupt vector \n");
1883 fprintf (asmFile, "%s", iComments2);
1884 dbuf_write_and_destroy (&vBuf, asmFile);
1887 /* copy global & static initialisations */
1888 fprintf (asmFile, "\n%s", iComments2);
1889 fprintf (asmFile, "; global & static initialisations\n");
1890 fprintf (asmFile, "%s", iComments2);
1892 if(pic16_debug_verbose)
1893 fprintf(asmFile, "; A code from now on!\n");
1895 pic16_copypCode(asmFile, 'A');
1897 if(pic16_options.no_crt) {
1898 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1899 fprintf(asmFile, "\tcode\n");
1900 fprintf(asmFile,"__sdcc_gsinit_startup:\n");
1904 // dbuf_write_and_destroy (&code->oBuf, stderr);
1906 fprintf(asmFile, "; I code from now on!\n");
1907 pic16_copypCode(asmFile, 'I');
1909 if(pic16_debug_verbose)
1910 fprintf(asmFile, "; dbName from now on!\n");
1912 pic16_copypCode(asmFile, statsg->dbName);
1914 if(pic16_options.no_crt) {
1915 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
1916 fprintf (asmFile,"\tgoto\t__sdcc_program_startup\n");
1920 if(pic16_debug_verbose)
1921 fprintf(asmFile, "; X code from now on!\n");
1923 pic16_copypCode(asmFile, 'X');
1925 if(pic16_debug_verbose)
1926 fprintf(asmFile, "; M code from now on!\n");
1928 pic16_copypCode(asmFile, 'M');
1930 pic16_copypCode(asmFile, code->dbName);
1932 pic16_copypCode(asmFile, 'P');
1934 emitStatistics(asmFile);
1936 fprintf (asmFile,"\tend\n");