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 void pic16_AnalyzeBanking (void);
58 extern void pic16_OptimizeJumps (void);
59 extern void pic16_OptimizeBanksel (void);
60 extern void pic16_InlinepCode (void);
61 extern void pic16_writeUsedRegs (FILE *);
63 extern void initialComments (FILE * afile);
64 extern void printPublics (FILE * afile);
66 void pic16_pCodeInitRegisters (void);
67 pCodeOp *pic16_popCopyReg (pCodeOpReg *pc);
68 extern void pic16_pCodeConstString (char *name, char *value, unsigned length);
71 /*-----------------------------------------------------------------*/
72 /* aopLiteral - string from a literal value */
73 /*-----------------------------------------------------------------*/
74 unsigned int pic16aopLiteral (value *val, int offset)
81 /* if it is a float then it gets tricky */
82 /* otherwise it is fairly simple */
83 if (!(IS_FLOAT(val->type) || IS_FIXED(val->type))) {
84 unsigned long v = ulFromVal (val);
86 return ( (v >> (offset * 8)) & 0xff);
89 if(IS_FIXED16X16(val->type)) {
90 unsigned long v = (unsigned long)fixed16x16FromDouble( floatFromVal( val ) );
92 return ( (v >> (offset * 8)) & 0xff);
95 /* it is type float */
96 fl.f = (float) floatFromVal(val);
97 #ifdef WORDS_BIGENDIAN
98 return fl.c[3-offset];
107 char tbuffer[512], *tbuf=tbuffer;;
110 /*-----------------------------------------------------------------*/
111 /* emitRegularMap - emit code for maps with no special cases */
112 /*-----------------------------------------------------------------*/
114 pic16emitRegularMap (memmap * map, bool addPublics, bool arFlag)
117 // int i, size, bitvars = 0;;
119 // fprintf(stderr, "%s:%d map name= %s\n", __FUNCTION__, __LINE__, map->sname);
122 dbuf_printf (&map->oBuf, ";\t.area\t%s\n", map->sname);
123 /* print the area name */
125 for (sym = setFirstItem (map->syms); sym; sym = setNextItem (map->syms)) {
128 fprintf(stderr, "%s\t%s: sym: %s\tused: %d\textern: %d\tstatic: %d\taggregate: %d\tregister: 0x%x\tfunction: %d\n",
130 map->sname, sym->name, sym->used, IS_EXTERN(sym->etype), IS_STATIC(sym->etype),
131 IS_AGGREGATE(sym->type), (SPEC_SCLS(sym->etype) == S_REGISTER), IS_FUNC(sym->type));
132 printTypeChain( sym->type, stderr );
133 fprintf(stderr, "\n");
136 /* if extern then add to externs */
137 if (IS_EXTERN (sym->etype)) {
138 /* reduce overhead while linking by not declaring
139 * extern unused external functions (usually declared
140 * in header files) */
141 if(IS_FUNC(sym->type) && !sym->used)continue;
143 /* make sure symbol is not in publics section */
144 if(!checkSym(publics, sym))
145 checkAddSym(&externs, sym);
149 /* if allocation required check is needed
150 * then check if the symbol really requires
151 * allocation only for local variables */
152 if (arFlag && !IS_AGGREGATE (sym->type) &&
153 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
154 !sym->allocreq && sym->level) {
156 // fprintf(stderr, "%s:%d special case, continuing...\n", __FILE__, __LINE__);
161 /* if global variable & not static or extern
162 * and addPublics allowed then add it to the public set */
163 if ((sym->used) && (sym->level == 0 ||
164 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
166 !IS_STATIC (sym->etype) && !IS_FUNC(sym->type)) {
168 checkAddSym(&publics, sym);
171 if(IS_STATIC(sym->etype)
172 && !sym->ival) /* && !sym->level*/ {
177 // debugf("adding symbol %s\n", sym->name);
178 #define SET_IMPLICIT 1
181 if(IS_STRUCT(sym->type))
185 reg = pic16_allocDirReg( operandFromSymbol( sym ));
188 for(ssym=setFirstItem(sectSyms); ssym; ssym=setNextItem(sectSyms)) {
189 if(!strcmp(ssym->name, reg->name))found=1;
193 checkAddReg(&pic16_rel_udata, reg);
196 debugf("Did find %s in pic16_rel_udata already. Check!\n", reg->name);
197 // checkAddSym(&publics, sym);
203 /* if extern then do nothing or is a function
205 if (IS_FUNC (sym->type) && !IS_STATIC(sym->etype)) {
206 if(SPEC_OCLS(sym->etype) == code) {
207 // fprintf(stderr, "%s:%d: symbol added: %s\n", __FILE__, __LINE__, sym->rname);
208 checkAddSym(&publics, sym);
213 /* if is has an absolute address then generate
214 an equate for this no need to allocate space */
215 if (SPEC_ABSA (sym->etype)) {
216 // fprintf (stderr,"; %s == 0x%04x\t\treqv= %p nRegs= %d\n",
217 // sym->name, SPEC_ADDR (sym->etype), sym->reqv, sym->regType);
219 dbuf_printf (&map->oBuf, "%s\tEQU\t0x%04x\n",
221 SPEC_ADDR (sym->etype));
223 /* emit only if it is global */
224 if(sym->level == 0) {
227 reg = pic16_dirregWithName( sym->name );
230 // fprintf(stderr, "%s:%d: implicit add of symbol = %s\n",
231 // __FUNCTION__, __LINE__, sym->name);
233 /* if IS_STRUCT is omitted the following
234 * fixes structures but break char/int etc */
236 if(IS_STRUCT(sym->type))
237 sym->implicit = 1; // mark as implicit
240 reg = pic16_allocDirReg( operandFromSymbol(sym) );
242 if(checkAddReg(&pic16_fix_udata, reg)) {
243 /* and add to globals list if not exist */
244 addSet(&publics, sym);
248 addSet(&publics, sym);
252 if(!sym->used && (sym->level == 0)) {
255 /* symbol not used, just declared probably, but its in
256 * level 0, so we must declare it fine as global */
258 // fprintf(stderr, "EXTRA symbol declaration sym= %s\n", sym->name);
261 if(IS_STRUCT(sym->type))
262 sym->implicit = 1; // mark as implicit
265 if(IS_AGGREGATE(sym->type)) {
266 reg=pic16_allocRegByName(sym->rname, getSize( sym->type ), NULL);
268 reg = pic16_allocDirReg( operandFromSymbol( sym ) );
276 fprintf(stderr, "%s:%d sym->rname: %s reg: %p reg->name: %s\n", __FILE__, __LINE__,
277 sym->rname, reg, (reg?reg->name:"<<NULL>>"));
281 for(ssym=setFirstItem(sectSyms); ssym; ssym=setNextItem(sectSyms)) {
282 if(!strcmp(ssym->name, reg->name))found=1;
286 if(checkAddReg(&pic16_rel_udata, reg)) {
287 addSetHead(&publics, sym);
296 addSetHead(&publics, sym);
301 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
302 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
303 /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
304 if (IS_BITVAR (sym->etype)) {
307 dbuf_printf (map->oBuf, "\t%s\n", sym->rname);
308 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1) {
309 for (i = 1; i < size; i++)
310 dbuf_printf (map->oBuf, "\t%s_%d\n", sym->rname, i);
313 dbuf_printf (map->oBuf, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
317 /* FIXME -- VR Fix the following, so that syms to be placed
318 * in the idata section and let linker decide about their fate */
320 /* if it has an initial value then do it only if
321 it is a global variable */
324 && ((sym->level == 0)
325 || IS_STATIC(sym->etype)) ) {
329 if(SPEC_OCLS(sym->etype)==data) {
330 fprintf(stderr, "%s: sym %s placed in data segment\n", map->sname, sym->name);
333 if(SPEC_OCLS(sym->etype)==code) {
334 fprintf(stderr, "%s: sym %s placed in code segment\n", map->sname, sym->name);
339 fprintf(stderr, "'%s': sym '%s' has initial value SPEC_ABSA: %d, IS_AGGREGATE: %d\n",
340 map->sname, sym->name, SPEC_ABSA(sym->etype), IS_AGGREGATE(sym->type));
343 if (IS_AGGREGATE (sym->type)) {
344 if(SPEC_ABSA(sym->etype))
345 addSet(&fix_idataSymSet, copySymbol(sym));
347 addSet(&rel_idataSymSet, copySymbol(sym));
348 // ival = initAggregates (sym, sym->ival, NULL);
350 if(SPEC_ABSA(sym->etype))
351 addSet(&fix_idataSymSet, copySymbol(sym));
353 addSet(&rel_idataSymSet, copySymbol(sym));
355 // ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
356 // decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
360 setAstFileLine (ival, sym->fileDef, sym->lineDef);
361 codeOutBuf = &statsg->oBuf;
363 eBBlockFromiCode (iCodeFromAst (ival));
371 /*-----------------------------------------------------------------*/
372 /* pic16_initPointer - pointer initialization code massaging */
373 /*-----------------------------------------------------------------*/
375 pic16_initPointer (initList * ilist, sym_link *toType)
381 return valCastLiteral(toType, 0.0);
384 expr = decorateType(resolveSymbols( list2expr (ilist) ), FALSE);
385 // expr = list2expr( ilist );
390 /* try it the old way first */
391 if (expr->etype && (val = constExprValue (expr, FALSE)))
394 /* ( ptr + constant ) */
395 if (IS_AST_OP (expr) &&
396 (expr->opval.op == '+' || expr->opval.op == '-') &&
397 IS_AST_SYM_VALUE (expr->left) &&
398 (IS_ARRAY(expr->left->ftype) || IS_PTR(expr->left->ftype)) &&
399 compareType(toType, expr->left->ftype) &&
400 IS_AST_LIT_VALUE (expr->right)) {
401 return valForCastAggr (expr->left, expr->left->ftype,
407 if (IS_AST_OP(expr) && expr->opval.op==CAST &&
408 IS_AST_OP(expr->right) && expr->right->opval.op=='&') {
409 if (compareType(toType, expr->left->ftype)!=1) {
410 werror (W_INIT_WRONG);
411 printFromToType(expr->left->ftype, toType);
417 /* no then we have to do these cludgy checks */
418 /* pointers can be initialized with address of
419 a variable or address of an array element */
420 if (IS_AST_OP (expr) && expr->opval.op == '&') {
421 /* address of symbol */
422 if (IS_AST_SYM_VALUE (expr->left) && expr->left->etype) {
423 val = AST_VALUE (expr->left);
424 val->type = newLink (DECLARATOR);
425 if(SPEC_SCLS (expr->left->etype) == S_CODE) {
426 DCL_TYPE (val->type) = CPOINTER;
427 DCL_PTR_CONST (val->type) = port->mem.code_ro;
429 else if (SPEC_SCLS (expr->left->etype) == S_XDATA)
430 DCL_TYPE (val->type) = FPOINTER;
431 else if (SPEC_SCLS (expr->left->etype) == S_XSTACK)
432 DCL_TYPE (val->type) = PPOINTER;
433 else if (SPEC_SCLS (expr->left->etype) == S_IDATA)
434 DCL_TYPE (val->type) = IPOINTER;
435 else if (SPEC_SCLS (expr->left->etype) == S_EEPROM)
436 DCL_TYPE (val->type) = EEPPOINTER;
438 DCL_TYPE (val->type) = POINTER;
440 val->type->next = expr->left->ftype;
441 val->etype = getSpec (val->type);
445 /* if address of indexed array */
446 if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
447 return valForArray (expr->left);
449 /* if address of structure element then
451 if (IS_AST_OP (expr->left) &&
452 expr->left->opval.op == '.') {
453 return valForStructElem (expr->left->left,
458 (&some_struct)->element */
459 if (IS_AST_OP (expr->left) &&
460 expr->left->opval.op == PTR_OP &&
461 IS_ADDRESS_OF_OP (expr->left->left)) {
462 return valForStructElem (expr->left->left->left,
466 /* case 3. (((char *) &a) +/- constant) */
467 if (IS_AST_OP (expr) &&
468 (expr->opval.op == '+' || expr->opval.op == '-') &&
469 IS_AST_OP (expr->left) && expr->left->opval.op == CAST &&
470 IS_AST_OP (expr->left->right) &&
471 expr->left->right->opval.op == '&' &&
472 IS_AST_LIT_VALUE (expr->right)) {
474 return valForCastAggr (expr->left->right->left,
475 expr->left->left->opval.lnk,
476 expr->right, expr->opval.op);
479 /* case 4. (char *)(array type) */
480 if (IS_CAST_OP(expr) && IS_AST_SYM_VALUE (expr->right) &&
481 IS_ARRAY(expr->right->ftype)) {
483 val = copyValue (AST_VALUE (expr->right));
484 val->type = newLink (DECLARATOR);
485 if (SPEC_SCLS (expr->right->etype) == S_CODE) {
486 DCL_TYPE (val->type) = CPOINTER;
487 DCL_PTR_CONST (val->type) = port->mem.code_ro;
489 else if (SPEC_SCLS (expr->right->etype) == S_XDATA)
490 DCL_TYPE (val->type) = FPOINTER;
491 else if (SPEC_SCLS (expr->right->etype) == S_XSTACK)
492 DCL_TYPE (val->type) = PPOINTER;
493 else if (SPEC_SCLS (expr->right->etype) == S_IDATA)
494 DCL_TYPE (val->type) = IPOINTER;
495 else if (SPEC_SCLS (expr->right->etype) == S_EEPROM)
496 DCL_TYPE (val->type) = EEPPOINTER;
498 DCL_TYPE (val->type) = POINTER;
499 val->type->next = expr->right->ftype->next;
500 val->etype = getSpec (val->type);
506 werrorfl (expr->filename, expr->lineno, E_INCOMPAT_PTYPES);
508 werror (E_INCOMPAT_PTYPES);
514 /*-----------------------------------------------------------------*/
515 /* printPointerType - generates ival for pointer type */
516 /*-----------------------------------------------------------------*/
518 _pic16_printPointerType (const char *name, char ptype, void *p)
522 sprintf (buf, "LOW(%s)", name);
523 pic16_emitDS (buf, ptype, p);
524 sprintf (buf, "HIGH(%s)", name);
525 pic16_emitDS (buf, ptype, p);
528 /*-----------------------------------------------------------------*/
529 /* printPointerType - generates ival for pointer type */
530 /*-----------------------------------------------------------------*/
532 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 /*-----------------------------------------------------------------*/
542 pic16_printGPointerType (const char *iname, const unsigned int itype,
547 _pic16_printPointerType (iname, ptype, p);
551 case CPOINTER: /* fall through */
552 case FUNCTION: /* fall through */
554 /* GPTRs pointing to __data space should be reported as POINTERs */
555 sprintf (buf, "UPPER(%s)", iname);
556 pic16_emitDS (buf, ptype, p);
559 case POINTER: /* fall through */
560 case FPOINTER: /* fall through */
561 case IPOINTER: /* fall through */
562 case PPOINTER: /* __data space */
563 sprintf (buf, "0x%02x", GPTR_TAG_DATA);
564 pic16_emitDS (buf, ptype, p);
568 debugf ("itype = %d\n", itype );
572 if (itype == GPOINTER) {
573 fprintf(stderr, "%s: initialized generic pointer with unknown storage class assumes object in code space\n", __func__);
576 //pic16_flushDB(ptype, p); /* might break char* const arr[] = {...}; */
580 /* set to 0 to disable debug messages */
581 #define DEBUG_PRINTIVAL 0
583 /*-----------------------------------------------------------------*/
584 /* pic16_printIvalType - generates ival for int/char */
585 /*-----------------------------------------------------------------*/
587 pic16_printIvalType (symbol *sym, sym_link * type, initList * ilist, char ptype, void *p)
592 // fprintf(stderr, "%s for symbol %s\n",__FUNCTION__, sym->rname);
595 fprintf(stderr, "%s\n",__FUNCTION__);
599 /* if initList is deep */
600 if (ilist && ilist->type == INIT_DEEP)
601 ilist = ilist->init.deep;
603 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
604 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
607 if (!(val = list2val (ilist))) {
608 // assuming a warning has been thrown
609 val = constCharVal (0);
612 if (val->type != type) {
613 val = valCastLiteral(type, floatFromVal(val));
616 for (i = 0; i < getSize (type); i++) {
617 pic16_emitDB(pic16aopLiteral(val, i), ptype, p);
621 /*--------------------------------------------------------------------*/
622 /* pic16_printIvalChar - generates initital value for character array */
623 /*--------------------------------------------------------------------*/
625 pic16_printIvalChar (symbol *sym, sym_link * type, initList * ilist, char *s, char ptype, void *p)
628 int remain, len, ilen;
634 fprintf(stderr, "%s\n",__FUNCTION__);
638 val = list2val (ilist);
640 /* if the value is a character string */
641 if(IS_ARRAY (val->type) && IS_CHAR (val->etype)) {
642 /* length of initializer string (might contain \0, so do not use strlen) */
643 ilen = DCL_ELEM(val->type);
646 /* This causes structflexarray.c to fail. */
648 DCL_ELEM (type) = ilen;
651 /* len is 0 if declartion equals initializer,
652 * >0 if declaration greater than initializer
653 * <0 if declaration less than initializer
654 * Strategy: if >0 emit 0x00 for the rest of the length,
655 * if <0 then emit only the length of declaration elements
658 len = DCL_ELEM (type) - ilen;
660 // fprintf(stderr, "%s:%d ilen = %i len = %i DCL_ELEM(type) = %i SPEC_CVAL-len = %i\n", __FILE__, __LINE__,
661 // ilen, len, DCL_ELEM(type), strlen(SPEC_CVAL(val->etype).v_char));
664 /* emit initializer */
665 for(remain=0; remain<ilen; remain++) {
666 pic16_emitDB(SPEC_CVAL(val->etype).v_char[ remain ], ptype, p);
669 /* fill array with 0x00 */
671 pic16_emitDB(0x00, ptype, p);
673 } else if (!DCL_ELEM (type)) {
674 // flexible arrays: char str[] = "something"; */
675 for(remain=0; remain<ilen; remain++) {
676 pic16_emitDB(SPEC_CVAL(val->etype).v_char[ remain ], ptype, p);
679 werror (W_EXCESS_INITIALIZERS, "array of chars", sym->name, sym->lineDef);
680 for(remain=0; remain<DCL_ELEM (type); remain++) {
681 pic16_emitDB(SPEC_CVAL(val->etype).v_char[ remain ], ptype, p);
686 // if((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0) {
691 for(remain=0; remain<strlen(s); remain++) {
692 pic16_emitDB(s[remain], ptype, p);
698 /*-----------------------------------------------------------------*/
699 /* pic16_printIvalArray - generates code for array initialization */
700 /*-----------------------------------------------------------------*/
702 pic16_printIvalArray (symbol * sym, sym_link * type, initList * ilist,
706 int lcnt = 0, size = 0;
713 fprintf(stderr, "%s\n",__FUNCTION__);
715 /* take care of the special case */
716 /* array of characters can be init */
718 if (IS_CHAR (type->next) && ilist) {
719 if (!IS_LITERAL(list2val(ilist)->etype)) {
720 werror (W_INIT_WRONG);
724 if(pic16_printIvalChar (sym, type,
725 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
726 SPEC_CVAL (sym->etype).v_char, ptype, p))
729 /* not the special case */
730 if (ilist && ilist->type != INIT_DEEP)
732 werror (E_INIT_STRUCT, sym->name);
736 iloop = (ilist ? ilist->init.deep : NULL);
737 lcnt = DCL_ELEM (type);
742 pic16_printIval (sym, type->next, iloop, ptype, p);
743 iloop = (iloop ? iloop->next : NULL);
746 /* if not array limits given & we */
747 /* are out of initialisers then */
748 if (!DCL_ELEM (type) && !iloop)
751 /* no of elements given and we */
752 /* have generated for all of them */
754 /* if initializers left */
756 werror (W_EXCESS_INITIALIZERS, "array", sym->name, sym->lineDef);
763 /* This causes bug #1843745. */
764 /* if we have not been given a size */
765 if (!DCL_ELEM (type))
766 DCL_ELEM (type) = size;
772 /*-----------------------------------------------------------------*/
773 /* pic16_printIvalBitFields - generate initializer for bitfields */
774 /*-----------------------------------------------------------------*/
776 pic16_printIvalBitFields(symbol **sym, initList **ilist, char ptype, void *p)
780 initList *lilist = *ilist ;
781 unsigned long ival = 0;
787 fprintf(stderr, "%s\n",__FUNCTION__);
792 val = list2val(lilist);
794 if (SPEC_BLEN(lsym->etype) > 8) {
795 size += ((SPEC_BLEN (lsym->etype) / 8) +
796 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
799 size = ((SPEC_BLEN (lsym->etype) / 8) +
800 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
802 i = (ulFromVal (val) & ((1ul << SPEC_BLEN (lsym->etype)) - 1ul));
803 i <<= SPEC_BSTR (lsym->etype);
805 if (! ( lsym->next &&
806 (lilist && lilist->next) &&
807 (IS_BITFIELD(lsym->next->type)) &&
808 (SPEC_BSTR(lsym->next->etype)))) break;
810 lilist = lilist->next;
813 for (i = 0; i < size; i++) {
814 pic16_emitDB(BYTE_IN_LONG(ival, i), ptype, p);
822 /*-----------------------------------------------------------------*/
823 /* printIvalStruct - generates initial value for structures */
824 /*-----------------------------------------------------------------*/
826 pic16_printIvalStruct (symbol * sym, sym_link * type,
827 initList * ilist, char ptype, void *p)
830 initList *iloop = NULL;
834 fprintf(stderr, "%s\n",__FUNCTION__);
837 sflds = SPEC_STRUCT (type)->fields;
840 if (ilist->type != INIT_DEEP) {
841 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
845 iloop = ilist->init.deep;
848 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
849 // fprintf(stderr, "%s:%d sflds: %p\tiloop = %p\n", __FILE__, __LINE__, sflds, iloop);
850 if (IS_BITFIELD(sflds->type)) {
851 pic16_printIvalBitFields(&sflds, &iloop, ptype, p);
853 pic16_printIval (sym, sflds->type, iloop, ptype, p);
857 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
862 /*-----------------------------------------------------------------*/
863 /* printIvalUnion - generates initial value for unions */
864 /*-----------------------------------------------------------------*/
866 pic16_printIvalUnion (symbol * sym, sym_link * type,
867 initList * ilist, char ptype, void *p)
870 initList *iloop = NULL;
872 symbol *sflds = NULL;
875 fprintf(stderr, "%s\n",__FUNCTION__);
880 sflds = SPEC_STRUCT (type)->fields;
883 if (ilist->type != INIT_DEEP) {
884 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
888 iloop = ilist->init.deep;
891 size = SPEC_STRUCT(type)->size;
892 sflds = SPEC_STRUCT(type)->fields;
893 pic16_printIval (sym, sflds->type, iloop, ptype, p);
895 /* if the first field is not the longest, fill with 0s */
896 while (size > getSize (sflds->type)) {
897 pic16_emitDB(0, ptype, p);
903 pic16_isUnion( symbol *sym, sym_link *type )
905 if (type && SPEC_STRUCT(type)->type == UNION) return 1;
909 /*--------------------------------------------------------------------------*/
910 /* pic16_printIvalCharPtr - generates initial values for character pointers */
911 /*--------------------------------------------------------------------------*/
913 pic16_printIvalCharPtr (symbol * sym, sym_link * type, value * val, char ptype, void *p)
918 /* PENDING: this is _very_ mcs51 specific, including a magic
920 It's also endin specific.
922 VR - Attempting to port this function to pic16 port - 8-Jun-2004
927 fprintf(stderr, "%s\n",__FUNCTION__);
930 size = getSize (type);
932 if (val->name && strlen (val->name))
934 if (size == 1) /* This appears to be Z80 specific?? */
936 pic16_emitDS(val->name, ptype, p);
940 pic16_printPointerType (val->name, ptype, p);
945 type = PTR_TYPE (SPEC_OCLS (val->etype));
946 if (val->sym && val->sym->isstrlit) {
947 // this is a literal string
950 pic16_printGPointerType(val->name, type, ptype, p);
954 fprintf (stderr, "*** internal error: unknown size in "
955 "printIvalCharPtr.\n");
961 // these are literals assigned to pointers
962 for (i = 0; i < size; i++)
964 pic16_emitDB(pic16aopLiteral(val, i), ptype, p);
968 if (val->sym && val->sym->isstrlit) { // && !isinSet(statsg->syms, val->sym)) {
969 if(ptype == 'p' && !isinSet(statsg->syms, val->sym))addSet (&statsg->syms, val->sym);
970 else if(ptype == 'f' /*&& !isinSet(rel_idataSymSet, val->sym)*/)addSet(&rel_idataSymSet, val->sym);
976 /*-----------------------------------------------------------------------*/
977 /* pic16_printIvalFuncPtr - generate initial value for function pointers */
978 /*-----------------------------------------------------------------------*/
980 pic16_printIvalFuncPtr (sym_link * type, initList * ilist, char ptype, void *p)
987 fprintf(stderr, "%s\n",__FUNCTION__);
991 val = list2val (ilist);
993 val = valCastLiteral(type, 0.0);
996 // an error has been thrown already
997 val = constCharVal (0);
1000 if (IS_LITERAL(val->etype)) {
1001 if (0 && compareType(type, val->etype) == 0) {
1002 werrorfl (ilist->filename, ilist->lineno, E_INCOMPAT_TYPES);
1003 printFromToType (val->type, type);
1005 pic16_printIvalCharPtr (NULL, type, val, ptype, p);
1009 /* check the types */
1010 if ((dLvl = compareType (val->type, type->next)) <= 0)
1012 pic16_emitDB(0x00, ptype, p);
1016 /* now generate the name */
1018 pic16_printGPointerType (val->name, CPOINTER /*DCL_TYPE(val->type)*/, ptype, p);
1020 pic16_printGPointerType (val->sym->rname, CPOINTER /*DCL_TYPE(val->type)*/, ptype, p);
1022 if(IS_FUNC(val->sym->type) && !val->sym->used && !IS_STATIC(val->sym->etype)) {
1024 if(!checkSym(publics, val->sym))
1025 if(checkAddSym(&externs, val->sym) && (ptype == 'f')) {
1026 /* this has not been declared as extern
1027 * so declare it as a 'late extern' just after the symbol */
1028 fprintf((FILE *)p, ";\tdeclare symbol as extern\n");
1029 fprintf((FILE *)p, "\textern\t%s\n", val->sym->rname);
1030 fprintf((FILE *)p, ";\tcontinue variable declaration\n");
1039 /*-----------------------------------------------------------------*/
1040 /* pic16_printIvalPtr - generates initial value for pointers */
1041 /*-----------------------------------------------------------------*/
1043 pic16_printIvalPtr (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p)
1050 fprintf(stderr, "%s:%d initialising pointer: %s size: %d\n", __FILE__, __LINE__,
1051 sym->rname, getSize(sym->type));
1055 if (ilist && (ilist->type == INIT_DEEP))
1056 ilist = ilist->init.deep;
1058 /* function pointer */
1059 if (IS_FUNC (type->next))
1061 pic16_printIvalFuncPtr (type, ilist, ptype, p);
1065 if (!(val = pic16_initPointer (ilist, type)))
1068 /* if character pointer */
1069 if (IS_CHAR (type->next))
1070 if (pic16_printIvalCharPtr (sym, type, val, ptype, p))
1073 /* check the type */
1074 if (compareType (type, val->type) == 0) {
1075 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
1076 printFromToType (val->type, type);
1079 size = getSize (type);
1081 /* if val is literal */
1082 if (IS_LITERAL (val->etype))
1084 for (i = 0; i < size; i++)
1086 pic16_emitDB(pic16aopLiteral(val, i), ptype, p);
1091 if (size == 1) /* Z80 specific?? */
1093 pic16_emitDS(val->name, ptype, p);
1097 pic16_printPointerType (val->name, ptype, p);
1102 itype = PTR_TYPE (SPEC_OCLS (val->etype));
1103 pic16_printGPointerType (val->name, itype, ptype, p);
1113 /*-----------------------------------------------------------------*/
1114 /* pic16_printIval - generates code for initial value */
1115 /*-----------------------------------------------------------------*/
1116 void pic16_printIval (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p)
1124 fprintf(stderr, "%s:%d generating init for %s\n", __FILE__, __LINE__, sym->name);
1125 fprintf(stderr, "%s: IS_STRUCT: %d IS_ARRAY: %d IS_PTR: %d IS_SPEC: %d\n", sym->name,
1126 IS_STRUCT(type), IS_ARRAY(type), IS_PTR(type), IS_SPEC(type));
1129 /* if structure then */
1130 if (IS_STRUCT (type))
1132 if (pic16_isUnion(sym, type))
1134 //fprintf(stderr,"%s union\n",__FUNCTION__);
1135 pic16_printIvalUnion (sym, type, ilist, ptype, p);
1137 //fprintf(stderr,"%s struct\n",__FUNCTION__);
1138 pic16_printIvalStruct (sym, type, ilist, ptype, p);
1143 /* if this is an array */
1144 if (IS_ARRAY (type))
1146 // fprintf(stderr,"%s array\n",__FUNCTION__);
1147 pic16_printIvalArray (sym, type, ilist, ptype, p);
1154 // not an aggregate, ilist must be a node
1155 if (ilist->type!=INIT_NODE) {
1156 // or a 1-element list
1157 if (ilist->init.deep->next) {
1158 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar",
1161 ilist=ilist->init.deep;
1166 // and the type must match
1167 itype=ilist->init.node->ftype;
1169 if (compareType(type, itype)==0) {
1170 // special case for literal strings
1171 if (IS_ARRAY (itype) && IS_CHAR (getSpec(itype)) &&
1172 // which are really code pointers
1173 IS_PTR(type) && DCL_TYPE(type)==CPOINTER) {
1176 // werrorfl (ilist->filename, ilist->lineno, E_TYPE_MISMATCH, "assignment", " ");
1177 // printFromToType(itype, type);
1184 /* if this is a pointer */
1187 // fprintf(stderr,"%s pointer\n",__FUNCTION__);
1188 pic16_printIvalPtr (sym, type, ilist, ptype, p);
1193 /* if type is SPECIFIER */
1196 // fprintf(stderr,"%s spec\n",__FUNCTION__);
1197 pic16_printIvalType (sym, type, ilist, ptype, p);
1203 PIC16_IS_CONFIG_ADDRESS(int address)
1205 return ((address >= pic16->cwInfo.confAddrStart && address <= pic16->cwInfo.confAddrEnd));
1209 PIC16_IS_IDLOC_ADDRESS(int address)
1211 return ((address >= pic16->idInfo.idAddrStart && address <= pic16->idInfo.idAddrEnd));
1214 /*-----------------------------------------------------------------*/
1215 /* emitStaticSeg - emitcode for the static segment */
1216 /*-----------------------------------------------------------------*/
1218 pic16emitStaticSeg (memmap * map)
1221 static int didcode = 0;
1223 //fprintf(stderr, "%s\n",__FUNCTION__);
1227 /* for all variables in this segment do */
1228 for (sym = setFirstItem (map->syms); sym; sym = setNextItem (map->syms))
1232 fprintf (stderr, "%s\t%s: sym: %s\tused: %d\tSPEC_ABSA: %d\tSPEC_AGGREGATE: %d\tCODE: %d\n\
1233 CODESPACE: %d\tCONST: %d\tPTRCONST: %d\tSPEC_CONST: %d\n", __FUNCTION__, map->sname, sym->name, sym->used, SPEC_ABSA (sym->etype), IS_AGGREGATE (sym->type), IS_CODE (sym->etype), IN_CODESPACE (SPEC_OCLS (sym->etype)), IS_CONSTANT (sym->etype), IS_PTR_CONST (sym->etype), SPEC_CONST (sym->etype));
1234 printTypeChain (sym->type, stderr);
1235 fprintf (stderr, "\n");
1238 if (SPEC_ABSA (sym->etype) && PIC16_IS_CONFIG_ADDRESS (SPEC_ADDR (sym->etype)))
1240 pic16_assignConfigWordValue (SPEC_ADDR (sym->etype), (int) ulFromVal (list2val (sym->ival)));
1245 if (SPEC_ABSA (sym->etype) && PIC16_IS_IDLOC_ADDRESS (SPEC_ADDR (sym->etype)))
1247 pic16_assignIdByteValue (SPEC_ADDR (sym->etype), (char) ulFromVal (list2val (sym->ival)));
1252 /* if it is "extern" then do nothing */
1253 if (IS_EXTERN (sym->etype) /* && !SPEC_ABSA(sym->etype) */ )
1255 checkAddSym (&externs, sym);
1259 /* if it is not static add it to the public
1261 if (!IS_STATIC (sym->etype))
1263 /* do not emit if it is a config word declaration */
1264 checkAddSym (&publics, sym);
1267 /* print extra debug info if required */
1268 if (options.debug || sym->level == 0)
1270 /* NOTE to me - cdbFile may be null in which case,
1271 * the sym name will be printed to stdout. oh well */
1272 debugFile->writeSymbol (sym);
1275 /* if it has an absolute address */
1276 if (SPEC_ABSA (sym->etype))
1278 // fprintf(stderr, "%s:%d spec_absa is true for symbol: %s\n",
1279 // __FILE__, __LINE__, sym->name);
1281 if (!sym->ival && IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) && SPEC_CVAL (sym->etype).v_char)
1283 /* symbol has absolute address but no initial value */
1284 /* special case for character strings */
1286 // fprintf(stderr, "%s:%d printing code string from %s\n", __FILE__, __LINE__, sym->rname);
1288 pic16_pCodeConstString (sym->rname, SPEC_CVAL (sym->etype).v_char, getSize (sym->type));
1297 /* symbol has absolute address and initial value */
1299 resolveIvalSym (sym->ival, sym->type);
1300 asym = newSymbol (sym->rname, 0);
1301 abSym = Safe_calloc (1, sizeof (absSym));
1302 strcpy (abSym->name, sym->rname);
1303 abSym->address = SPEC_ADDR (sym->etype);
1304 addSet (&absSymSet, abSym);
1306 pb = pic16_newpCodeChain (NULL, 'A', pic16_newpCodeCharP ("; Starting pCode block for absolute Ival"));
1307 pic16_addpBlock (pb);
1309 pcf = pic16_newpCodeFunction (moduleName, asym->name);
1310 PCF (pcf)->absblock = 1;
1312 pic16_addpCode2pBlock (pb, pcf);
1313 pic16_addpCode2pBlock (pb, pic16_newpCodeLabel (sym->rname, -1));
1314 //fprintf(stderr, "%s:%d [1] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1315 /* if it has an initial value */
1318 pic16_printIval (sym, sym->type, sym->ival, 'p', (void *) pb);
1319 pic16_flushDB ('p', (void *) pb);
1322 pic16_addpCode2pBlock (pb, pic16_newpCodeFunction (NULL, NULL));
1328 // fprintf(stderr, "%s:%d spec_absa is false for symbol: %s\n",
1329 // __FILE__, __LINE__, sym->name);
1332 /* if it has an initial value */
1337 /* symbol doesn't have absolute address but has initial value */
1338 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
1340 resolveIvalSym (sym->ival, sym->type);
1342 pb = pic16_newpCodeChain (NULL, 'P', pic16_newpCodeCharP ("; Starting pCode block for Ival"));
1343 pic16_addpBlock (pb);
1347 /* make sure that 'code' directive is emitted before, once */
1348 pic16_addpCode2pBlock (pb, pic16_newpCodeAsmDir ("code", NULL));
1353 pic16_addpCode2pBlock (pb, pic16_newpCodeLabel (sym->rname, -1));
1354 //fprintf(stderr, "%s:%d [2] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1355 pic16_printIval (sym, sym->type, sym->ival, 'p', (void *) pb);
1356 pic16_flushDB ('p', (void *) pb);
1362 /* symbol doesn't have absolute address and no initial value */
1363 /* allocate space */
1364 // fprintf(stderr, "%s:%d [3] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1365 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
1366 /* special case for character strings */
1367 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) && SPEC_CVAL (sym->etype).v_char)
1370 // fprintf(stderr, "%s:%d printing code string for %s\n", __FILE__, __LINE__, sym->rname);
1372 pic16_pCodeConstString (sym->rname, SPEC_CVAL (sym->etype).v_char, getSize (sym->type));
1383 /*-----------------------------------------------------------------*/
1384 /* pic16_emitConfigRegs - emits the configuration registers */
1385 /*-----------------------------------------------------------------*/
1386 void pic16_emitConfigRegs(FILE *of)
1390 for(i=0;i<=(pic16->cwInfo.confAddrEnd-pic16->cwInfo.confAddrStart);i++)
1391 if(pic16->cwInfo.crInfo[i].emit) //mask != -1)
1392 fprintf (of, "\t__config 0x%x, 0x%hhx\n",
1393 pic16->cwInfo.confAddrStart+i,
1394 pic16->cwInfo.crInfo[i].value);
1397 void pic16_emitIDRegs(FILE *of)
1401 for(i=0;i<=(pic16->idInfo.idAddrEnd-pic16->idInfo.idAddrStart);i++)
1402 if(pic16->idInfo.irInfo[i].emit)
1403 fprintf (of, "\t__idlocs 0x%06x, 0x%hhx\n",
1404 pic16->idInfo.idAddrStart+i,
1405 pic16->idInfo.irInfo[i].value);
1412 /* no special considerations for the following
1413 data, idata & bit & xdata */
1414 pic16emitRegularMap (data, TRUE, TRUE);
1415 pic16emitRegularMap (idata, TRUE, TRUE);
1416 pic16emitRegularMap (bit, TRUE, FALSE);
1417 pic16emitRegularMap (xdata, TRUE, TRUE);
1418 pic16emitRegularMap (sfr, FALSE, FALSE);
1419 pic16emitRegularMap (sfrbit, FALSE, FALSE);
1420 pic16emitRegularMap (code, TRUE, FALSE);
1421 pic16emitStaticSeg (statsg);
1422 pic16emitStaticSeg (c_abs);
1425 /*-----------------------------------------------------------------*/
1426 /* createInterruptVect - creates the interrupt vector */
1427 /*-----------------------------------------------------------------*/
1429 pic16createInterruptVect (struct dbuf_s * vBuf)
1431 /* if the main is only a prototype ie. no body then do nothing */
1433 if (!IFFUNC_HASBODY(mainf->type)) {
1434 /* if ! compile only then main function should be present */
1435 if (!options.cc_only)
1441 if((!pic16_options.omit_ivt) || (pic16_options.omit_ivt && pic16_options.leave_reset)) {
1442 dbuf_printf (vBuf, ";\t.area\t%s\n", CODE_NAME);
1443 dbuf_printf (vBuf, ".intvecs\tcode\t0x%06x\n", pic16_options.ivt_loc);
1445 /* this is an overkill since WE are the port,
1446 * and we know if we have a genIVT function! */
1448 port->genIVT(vFile, interrupts, maxInterrupts);
1456 /*-----------------------------------------------------------------*/
1457 /* pic16initialComments - puts in some initial comments */
1458 /*-----------------------------------------------------------------*/
1460 pic16initialComments (FILE * afile)
1462 initialComments (afile);
1463 fprintf (afile, "; PIC16 port for the Microchip 16-bit core micros\n");
1464 if (pic16_options.xinst) {
1465 fprintf (afile, "; * Extended Instruction Set\n");
1468 if (pic16_mplab_comp) {
1469 fprintf(afile, "; * MPLAB/MPASM/MPASMWIN/MPLINK compatibility mode enabled\n");
1471 fprintf (afile, "%s", iComments2);
1473 if (options.debug) {
1474 fprintf (afile, "\n\t.ident \"SDCC version %s #%s [pic16 port]%s\"\n",
1475 SDCC_VERSION_STR, getBuildNumber(), (!pic16_options.xinst?"":" {extended}") );
1480 pic16_stringInSet(const char *str, set **world, int autoAdd)
1487 for (s = setFirstItem(*world); s; s = setNextItem(*world))
1490 if (0 == strcmp(s, str)) return 1;
1494 if (autoAdd) addSet(world, Safe_strdup(str));
1499 pic16_emitSymbolIfNew(FILE *file, const char *fmt, const char *sym, int checkLocals)
1501 static set *emitted = NULL;
1503 if (!pic16_stringInSet(sym, &emitted, 1)) {
1504 /* sym was not in emittedSymbols */
1505 if (!checkLocals || !pic16_stringInSet(sym, &pic16_localFunctions, 0)) {
1506 /* sym is not a locally defined function---avoid bug #1443651 */
1507 fprintf( file, fmt, sym );
1514 /*-----------------------------------------------------------------*/
1515 /* printPublics - generates global declarations for publics */
1516 /*-----------------------------------------------------------------*/
1518 pic16printPublics (FILE *afile)
1522 fprintf (afile, "\n%s", iComments2);
1523 fprintf (afile, "; public variables in this module\n");
1524 fprintf (afile, "%s", iComments2);
1526 for(sym = setFirstItem (publics); sym; sym = setNextItem (publics))
1528 if(!IS_STATIC(sym->etype))
1529 pic16_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1532 /*-----------------------------------------------------------------*/
1533 /* printExterns - generates extern declarations for externs */
1534 /*-----------------------------------------------------------------*/
1536 pic16_printExterns(FILE *afile)
1540 /* print nothing if no externs to declare */
1541 if(!elementsInSet(externs) && !elementsInSet(pic16_builtin_functions))
1544 fprintf(afile, "\n%s", iComments2);
1545 fprintf(afile, "; extern variables in this module\n");
1546 fprintf(afile, "%s", iComments2);
1548 for(sym = setFirstItem(externs); sym; sym = setNextItem(externs))
1549 pic16_emitSymbolIfNew(afile, "\textern %s\n", sym->rname, 1);
1551 for(sym = setFirstItem(pic16_builtin_functions); sym; sym = setNextItem(pic16_builtin_functions))
1552 pic16_emitSymbolIfNew(afile, "\textern _%s\n", sym->name, 1);
1555 /*-----------------------------------------------------------------*/
1556 /* emitOverlay - will emit code for the overlay stuff */
1557 /*-----------------------------------------------------------------*/
1559 pic16emitOverlay (struct dbuf_s *aBuf)
1563 if (!elementsInSet (ovrSetSets))
1564 dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name);
1566 /* for each of the sets in the overlay segment do */
1567 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1568 ovrset = setNextItem (ovrSetSets))
1573 if (elementsInSet (ovrset))
1575 /* this dummy area is used to fool the assembler
1576 otherwise the assembler will append each of these
1577 declarations into one chunk and will not overlay
1579 dbuf_printf (aBuf, ";\t.area _DUMMY\n");
1580 /* output the area informtion */
1581 dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1584 for (sym = setFirstItem (ovrset); sym;
1585 sym = setNextItem (ovrset))
1588 /* if extern then do nothing */
1589 if (IS_EXTERN (sym->etype))
1592 /* if allocation required check is needed
1593 then check if the symbol really requires
1594 allocation only for local variables */
1595 if (!IS_AGGREGATE (sym->type) &&
1596 !(sym->_isparm && !IS_REGPARM (sym->etype))
1597 && !sym->allocreq && sym->level)
1600 /* if global variable & not static or extern
1601 and addPublics allowed then add it to the public set */
1602 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1603 && !IS_STATIC (sym->etype)) {
1604 // fprintf(stderr, "%s:%d %s accessed\n", __FILE__, __LINE__, __FUNCTION__);
1605 checkAddSym(&publics, sym);
1606 // addSetHead (&publics, sym);
1609 /* if extern then do nothing or is a function
1611 if (IS_FUNC (sym->type))
1615 /* if is has an absolute address then generate
1616 an equate for this no need to allocate space */
1617 if (SPEC_ABSA (sym->etype))
1620 if (options.debug || sym->level == 0)
1621 dbuf_printf (aBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1623 dbuf_printf (aBuf, "%s\t=\t0x%04x\n",
1625 SPEC_ADDR (sym->etype));
1629 if (options.debug || sym->level == 0)
1630 dbuf_printf (aBuf, "==.\n");
1632 /* allocate space */
1633 dbuf_printf (aBuf, "%s:\n", sym->rname);
1634 dbuf_printf (aBuf, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1642 emitStatistics(FILE *asmFile)
1644 unsigned long isize, udsize, ramsize;
1645 statistics.isize = pic16_countInstructions();
1646 isize = (statistics.isize >= 0) ? statistics.isize : 0;
1647 udsize = (statistics.udsize >= 0) ? statistics.udsize : 0;
1648 ramsize = pic16 ? pic16->RAMsize : 0x200;
1649 ramsize -= 256; /* ignore access bank and SFRs */
1650 if (ramsize == 0) ramsize = 64; /* prevent division by zero (below) */
1652 fprintf (asmFile, "\n\n; Statistics:\n");
1653 fprintf (asmFile, "; code size:\t%5ld (0x%04lx) bytes (%5.2f%%)\n; \t%5ld (0x%04lx) words\n",
1654 isize, isize, (isize*100.0)/(128UL << 10),
1655 isize>>1, isize>>1);
1656 fprintf (asmFile, "; udata size:\t%5ld (0x%04lx) bytes (%5.2f%%)\n",
1657 udsize, udsize, (udsize*100.0) / (1.0 * ramsize));
1658 fprintf (asmFile, "; access size:\t%5ld (0x%04lx) bytes\n",
1659 statistics.intsize, statistics.intsize);
1661 fprintf (asmFile, "\n\n");
1666 /*-----------------------------------------------------------------*/
1667 /* glue - the final glue that hold the whole thing together */
1668 /*-----------------------------------------------------------------*/
1673 struct dbuf_s ovrBuf;
1676 dbuf_init(&ovrBuf, 4096);
1677 dbuf_init(&vBuf, 4096);
1679 mainf = newSymbol ("main", 0);
1682 mainf = findSymWithLevel(SymbolTab, mainf);
1684 pic16_pCodeInitRegisters();
1686 if(pic16_options.no_crt && mainf && IFFUNC_HASBODY(mainf->type)) {
1687 pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
1689 pic16_addpBlock(pb);
1691 /* entry point @ start of CSEG */
1692 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup",-1));
1695 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1696 pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("_stack_end"))));
1697 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1698 pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("_stack_end"))));
1701 /* put in the call to main */
1702 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
1704 if (options.mainreturn) {
1705 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
1706 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
1708 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
1709 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
1713 /* At this point we've got all the code in the form of pCode structures */
1714 /* Now it needs to be rearranged into the order it should be placed in the */
1717 pic16_movepBlock2Head('P'); // Last
1718 pic16_movepBlock2Head(code->dbName);
1719 pic16_movepBlock2Head('X');
1720 pic16_movepBlock2Head(statsg->dbName); // First
1722 /* print the global struct definitions */
1724 /* PENDING: this isnt the best place but it will do */
1725 if (port->general.glue_up_main) {
1726 /* create the interrupt vector table */
1727 pic16createInterruptVect (&vBuf);
1730 /* emit code for the all the variables declared */
1733 /* do the overlay segments */
1734 pic16emitOverlay(&ovrBuf);
1735 pic16_AnalyzepCode('*');
1738 if(pic16_options.dumpcalltree) {
1741 sprintf(buffer, "%s", dstFileName);
1742 strcat(buffer, ".calltree");
1743 cFile = fopen(buffer, "w");
1744 pic16_printCallTree( cFile );
1749 pic16_InlinepCode();
1750 pic16_AnalyzepCode('*');
1753 if(pic16_debug_verbose)
1756 /* now put it all together into the assembler file */
1757 /* create the assembler file name */
1758 if((noAssemble || options.c1mode) && fullDstFileName) {
1759 sprintf (buffer, "%s", fullDstFileName);
1761 sprintf (buffer, "%s", dstFileName);
1762 strcat (buffer, ".asm");
1765 if(!(asmFile = fopen (buffer, "w"))) {
1766 werror (E_FILE_OPEN_ERR, buffer);
1770 /* initial comments */
1771 pic16initialComments (asmFile);
1773 /* print module name */
1775 fprintf(asmFile, "\t.file\t\"%s\"\n", fullSrcFileName);
1777 /* Let the port generate any global directives, etc. */
1778 if(port->genAssemblerPreamble) {
1779 port->genAssemblerPreamble(asmFile);
1782 /* Put all variables into a cblock */
1783 pic16_AnalyzeBanking();
1786 if(pic16_options.opt_flags & OF_LR_SUPPORT) {
1787 pic16_OptimizeLocalRegs();
1791 /* remove redundant BANKSELs -- added by RN 2005-01-17 */
1792 if(pic16_options.opt_banksel > 1) {
1793 pic16_OptimizeBanksel();
1796 /* turn GOTOs into BRAs -- added by RN 2004-11-16 */
1797 if(!(pic16_options.opt_flags & OF_NO_OPTIMIZE_GOTO)) {
1798 pic16_OptimizeJumps();
1801 /* print the global variables in this module */
1802 pic16printPublics (asmFile);
1804 /* print the extern variables to this module */
1805 pic16_printExterns(asmFile);
1807 pic16_writeUsedRegs(asmFile);
1810 /* no xdata in pic */
1811 /* if external stack then reserve space of it */
1812 if(mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1813 fprintf (asmFile, "%s", iComments2);
1814 fprintf (asmFile, "; external stack \n");
1815 fprintf (asmFile, "%s", iComments2);
1816 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1817 fprintf (asmFile,";\t.ds 256\n");
1822 /* no xdata in pic */
1823 /* copy xtern ram data */
1824 fprintf (asmFile, "%s", iComments2);
1825 fprintf (asmFile, "; external ram data\n");
1826 fprintf (asmFile, "%s", iComments2);
1827 dbuf_write_and_destroy (&xdata->oBuf, asmFile);
1831 /* copy the bit segment */
1832 fprintf (asmFile, "%s", iComments2);
1833 fprintf (asmFile, "; bit data\n");
1834 fprintf (asmFile, "%s", iComments2);
1835 dbuf_write_and_destroy (&bit->oBuf, asmFile);
1838 /* copy the interrupt vector table */
1839 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1840 fprintf (asmFile, "\n%s", iComments2);
1841 fprintf (asmFile, "; interrupt vector \n");
1842 fprintf (asmFile, "%s", iComments2);
1843 dbuf_write_and_destroy (&vBuf, asmFile);
1846 /* copy global & static initialisations */
1847 fprintf (asmFile, "\n%s", iComments2);
1848 fprintf (asmFile, "; global & static initialisations\n");
1849 fprintf (asmFile, "%s", iComments2);
1851 if(pic16_debug_verbose)
1852 fprintf(asmFile, "; A code from now on!\n");
1854 pic16_copypCode(asmFile, 'A');
1856 if(pic16_options.no_crt) {
1857 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1858 fprintf(asmFile, "\tcode\n");
1859 fprintf(asmFile,"__sdcc_gsinit_startup:\n");
1863 // dbuf_write_and_destroy (&code->oBuf, stderr);
1865 fprintf(asmFile, "; I code from now on!\n");
1866 pic16_copypCode(asmFile, 'I');
1868 if(pic16_debug_verbose)
1869 fprintf(asmFile, "; dbName from now on!\n");
1871 pic16_copypCode(asmFile, statsg->dbName);
1873 if(pic16_options.no_crt) {
1874 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
1875 fprintf (asmFile,"\tgoto\t__sdcc_program_startup\n");
1879 if(pic16_debug_verbose)
1880 fprintf(asmFile, "; X code from now on!\n");
1882 pic16_copypCode(asmFile, 'X');
1884 if(pic16_debug_verbose)
1885 fprintf(asmFile, "; M code from now on!\n");
1887 pic16_copypCode(asmFile, 'M');
1889 pic16_copypCode(asmFile, code->dbName);
1891 pic16_copypCode(asmFile, 'P');
1893 emitStatistics(asmFile);
1895 fprintf (asmFile,"\tend\n");