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)
779 initList *lilist = *ilist;
780 unsigned long ival = 0;
786 fprintf(stderr, "%s\n",__FUNCTION__);
792 if (0 == SPEC_BLEN (lsym->etype))
794 /* bit-field structure member with a width of 0 */
798 else if (!SPEC_BUNNAMED (lsym->etype))
800 /* not an unnamed bit-field structure member */
801 value *val = list2val (lilist);
802 int bit_length = SPEC_BLEN (lsym->etype);
807 size += (bit_length + 7) / 8;
810 size = (bit_length + 7) / 8;
812 ival |= (ulFromVal (val) & ((1ul << bit_length) - 1ul)) << SPEC_BSTR (lsym->etype);
813 lilist = (lilist ? lilist->next : NULL);
818 for (i = 0; i < size; i++)
819 pic16_emitDB (BYTE_IN_LONG (ival, i), ptype, p);
826 /*-----------------------------------------------------------------*/
827 /* printIvalStruct - generates initial value for structures */
828 /*-----------------------------------------------------------------*/
830 pic16_printIvalStruct (symbol * sym, sym_link * type,
831 initList * ilist, char ptype, void *p)
834 initList *iloop = NULL;
838 fprintf(stderr, "%s\n",__FUNCTION__);
841 sflds = SPEC_STRUCT (type)->fields;
845 if (ilist->type != INIT_DEEP)
847 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
851 iloop = ilist->init.deep;
856 // fprintf(stderr, "%s:%d sflds: %p\tiloop = %p\n", __FILE__, __LINE__, sflds, iloop);
857 if (IS_BITFIELD (sflds->type))
859 pic16_printIvalBitFields (&sflds, &iloop, ptype, p);
863 pic16_printIval (sym, sflds->type, iloop, ptype, p);
865 iloop = iloop ? iloop->next : NULL;
869 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
872 /*-----------------------------------------------------------------*/
873 /* printIvalUnion - generates initial value for unions */
874 /*-----------------------------------------------------------------*/
876 pic16_printIvalUnion (symbol * sym, sym_link * type,
877 initList * ilist, char ptype, void *p)
880 initList *iloop = NULL;
882 symbol *sflds = NULL;
885 fprintf(stderr, "%s\n",__FUNCTION__);
890 sflds = SPEC_STRUCT (type)->fields;
893 if (ilist->type != INIT_DEEP) {
894 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
898 iloop = ilist->init.deep;
901 size = SPEC_STRUCT(type)->size;
902 sflds = SPEC_STRUCT(type)->fields;
903 pic16_printIval (sym, sflds->type, iloop, ptype, p);
905 /* if the first field is not the longest, fill with 0s */
906 while (size > getSize (sflds->type)) {
907 pic16_emitDB(0, ptype, p);
913 pic16_isUnion( symbol *sym, sym_link *type )
915 if (type && SPEC_STRUCT(type)->type == UNION) return 1;
919 /*--------------------------------------------------------------------------*/
920 /* pic16_printIvalCharPtr - generates initial values for character pointers */
921 /*--------------------------------------------------------------------------*/
923 pic16_printIvalCharPtr (symbol * sym, sym_link * type, value * val, char ptype, void *p)
928 /* PENDING: this is _very_ mcs51 specific, including a magic
930 It's also endin specific.
932 VR - Attempting to port this function to pic16 port - 8-Jun-2004
937 fprintf(stderr, "%s\n",__FUNCTION__);
940 size = getSize (type);
942 if (val->name && strlen (val->name))
944 if (size == 1) /* This appears to be Z80 specific?? */
946 pic16_emitDS(val->name, ptype, p);
950 pic16_printPointerType (val->name, ptype, p);
955 type = PTR_TYPE (SPEC_OCLS (val->etype));
956 if (val->sym && val->sym->isstrlit) {
957 // this is a literal string
960 pic16_printGPointerType(val->name, type, ptype, p);
964 fprintf (stderr, "*** internal error: unknown size in "
965 "printIvalCharPtr.\n");
971 // these are literals assigned to pointers
972 for (i = 0; i < size; i++)
974 pic16_emitDB(pic16aopLiteral(val, i), ptype, p);
978 if (val->sym && val->sym->isstrlit) { // && !isinSet(statsg->syms, val->sym)) {
979 if(ptype == 'p' && !isinSet(statsg->syms, val->sym))addSet (&statsg->syms, val->sym);
980 else if(ptype == 'f' /*&& !isinSet(rel_idataSymSet, val->sym)*/)addSet(&rel_idataSymSet, val->sym);
986 /*-----------------------------------------------------------------------*/
987 /* pic16_printIvalFuncPtr - generate initial value for function pointers */
988 /*-----------------------------------------------------------------------*/
990 pic16_printIvalFuncPtr (sym_link * type, initList * ilist, char ptype, void *p)
997 fprintf(stderr, "%s\n",__FUNCTION__);
1001 val = list2val (ilist);
1003 val = valCastLiteral(type, 0.0);
1006 // an error has been thrown already
1007 val = constCharVal (0);
1010 if (IS_LITERAL(val->etype)) {
1011 if (0 && compareType(type, val->etype) == 0) {
1012 werrorfl (ilist->filename, ilist->lineno, E_INCOMPAT_TYPES);
1013 printFromToType (val->type, type);
1015 pic16_printIvalCharPtr (NULL, type, val, ptype, p);
1019 /* check the types */
1020 if ((dLvl = compareType (val->type, type->next)) <= 0)
1022 pic16_emitDB(0x00, ptype, p);
1026 /* now generate the name */
1028 pic16_printGPointerType (val->name, CPOINTER /*DCL_TYPE(val->type)*/, ptype, p);
1030 pic16_printGPointerType (val->sym->rname, CPOINTER /*DCL_TYPE(val->type)*/, ptype, p);
1032 if(IS_FUNC(val->sym->type) && !val->sym->used && !IS_STATIC(val->sym->etype)) {
1034 if(!checkSym(publics, val->sym))
1035 if(checkAddSym(&externs, val->sym) && (ptype == 'f')) {
1036 /* this has not been declared as extern
1037 * so declare it as a 'late extern' just after the symbol */
1038 fprintf((FILE *)p, ";\tdeclare symbol as extern\n");
1039 fprintf((FILE *)p, "\textern\t%s\n", val->sym->rname);
1040 fprintf((FILE *)p, ";\tcontinue variable declaration\n");
1049 /*-----------------------------------------------------------------*/
1050 /* pic16_printIvalPtr - generates initial value for pointers */
1051 /*-----------------------------------------------------------------*/
1053 pic16_printIvalPtr (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p)
1060 fprintf(stderr, "%s:%d initialising pointer: %s size: %d\n", __FILE__, __LINE__,
1061 sym->rname, getSize(sym->type));
1065 if (ilist && (ilist->type == INIT_DEEP))
1066 ilist = ilist->init.deep;
1068 /* function pointer */
1069 if (IS_FUNC (type->next))
1071 pic16_printIvalFuncPtr (type, ilist, ptype, p);
1075 if (!(val = pic16_initPointer (ilist, type)))
1078 /* if character pointer */
1079 if (IS_CHAR (type->next))
1080 if (pic16_printIvalCharPtr (sym, type, val, ptype, p))
1083 /* check the type */
1084 if (compareType (type, val->type) == 0) {
1085 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
1086 printFromToType (val->type, type);
1089 size = getSize (type);
1091 /* if val is literal */
1092 if (IS_LITERAL (val->etype))
1094 for (i = 0; i < size; i++)
1096 pic16_emitDB(pic16aopLiteral(val, i), ptype, p);
1101 if (size == 1) /* Z80 specific?? */
1103 pic16_emitDS(val->name, ptype, p);
1107 pic16_printPointerType (val->name, ptype, p);
1112 itype = PTR_TYPE (SPEC_OCLS (val->etype));
1113 pic16_printGPointerType (val->name, itype, ptype, p);
1123 /*-----------------------------------------------------------------*/
1124 /* pic16_printIval - generates code for initial value */
1125 /*-----------------------------------------------------------------*/
1126 void pic16_printIval (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p)
1134 fprintf(stderr, "%s:%d generating init for %s\n", __FILE__, __LINE__, sym->name);
1135 fprintf(stderr, "%s: IS_STRUCT: %d IS_ARRAY: %d IS_PTR: %d IS_SPEC: %d\n", sym->name,
1136 IS_STRUCT(type), IS_ARRAY(type), IS_PTR(type), IS_SPEC(type));
1139 /* if structure then */
1140 if (IS_STRUCT (type))
1142 if (pic16_isUnion(sym, type))
1144 //fprintf(stderr,"%s union\n",__FUNCTION__);
1145 pic16_printIvalUnion (sym, type, ilist, ptype, p);
1147 //fprintf(stderr,"%s struct\n",__FUNCTION__);
1148 pic16_printIvalStruct (sym, type, ilist, ptype, p);
1153 /* if this is an array */
1154 if (IS_ARRAY (type))
1156 // fprintf(stderr,"%s array\n",__FUNCTION__);
1157 pic16_printIvalArray (sym, type, ilist, ptype, p);
1164 // not an aggregate, ilist must be a node
1165 if (ilist->type!=INIT_NODE) {
1166 // or a 1-element list
1167 if (ilist->init.deep->next) {
1168 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar",
1171 ilist=ilist->init.deep;
1176 // and the type must match
1177 itype=ilist->init.node->ftype;
1179 if (compareType(type, itype)==0) {
1180 // special case for literal strings
1181 if (IS_ARRAY (itype) && IS_CHAR (getSpec(itype)) &&
1182 // which are really code pointers
1183 IS_PTR(type) && DCL_TYPE(type)==CPOINTER) {
1186 // werrorfl (ilist->filename, ilist->lineno, E_TYPE_MISMATCH, "assignment", " ");
1187 // printFromToType(itype, type);
1194 /* if this is a pointer */
1197 // fprintf(stderr,"%s pointer\n",__FUNCTION__);
1198 pic16_printIvalPtr (sym, type, ilist, ptype, p);
1203 /* if type is SPECIFIER */
1206 // fprintf(stderr,"%s spec\n",__FUNCTION__);
1207 pic16_printIvalType (sym, type, ilist, ptype, p);
1213 PIC16_IS_CONFIG_ADDRESS(int address)
1215 return ((address >= pic16->cwInfo.confAddrStart && address <= pic16->cwInfo.confAddrEnd));
1219 PIC16_IS_IDLOC_ADDRESS(int address)
1221 return ((address >= pic16->idInfo.idAddrStart && address <= pic16->idInfo.idAddrEnd));
1224 /*-----------------------------------------------------------------*/
1225 /* emitStaticSeg - emitcode for the static segment */
1226 /*-----------------------------------------------------------------*/
1228 pic16emitStaticSeg (memmap * map)
1231 static int didcode = 0;
1233 //fprintf(stderr, "%s\n",__FUNCTION__);
1237 /* for all variables in this segment do */
1238 for (sym = setFirstItem (map->syms); sym; sym = setNextItem (map->syms))
1242 fprintf (stderr, "%s\t%s: sym: %s\tused: %d\tSPEC_ABSA: %d\tSPEC_AGGREGATE: %d\tCODE: %d\n\
1243 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));
1244 printTypeChain (sym->type, stderr);
1245 fprintf (stderr, "\n");
1248 if (SPEC_ABSA (sym->etype) && PIC16_IS_CONFIG_ADDRESS (SPEC_ADDR (sym->etype)))
1250 pic16_assignConfigWordValue (SPEC_ADDR (sym->etype), (int) ulFromVal (list2val (sym->ival)));
1255 if (SPEC_ABSA (sym->etype) && PIC16_IS_IDLOC_ADDRESS (SPEC_ADDR (sym->etype)))
1257 pic16_assignIdByteValue (SPEC_ADDR (sym->etype), (char) ulFromVal (list2val (sym->ival)));
1262 /* if it is "extern" then do nothing */
1263 if (IS_EXTERN (sym->etype) /* && !SPEC_ABSA(sym->etype) */ )
1265 checkAddSym (&externs, sym);
1269 /* if it is not static add it to the public
1271 if (!IS_STATIC (sym->etype))
1273 /* do not emit if it is a config word declaration */
1274 checkAddSym (&publics, sym);
1277 /* print extra debug info if required */
1278 if (options.debug || sym->level == 0)
1280 /* NOTE to me - cdbFile may be null in which case,
1281 * the sym name will be printed to stdout. oh well */
1282 debugFile->writeSymbol (sym);
1285 /* if it has an absolute address */
1286 if (SPEC_ABSA (sym->etype))
1288 // fprintf(stderr, "%s:%d spec_absa is true for symbol: %s\n",
1289 // __FILE__, __LINE__, sym->name);
1291 if (!sym->ival && IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) && SPEC_CVAL (sym->etype).v_char)
1293 /* symbol has absolute address but no initial value */
1294 /* special case for character strings */
1296 // fprintf(stderr, "%s:%d printing code string from %s\n", __FILE__, __LINE__, sym->rname);
1298 pic16_pCodeConstString (sym->rname, SPEC_CVAL (sym->etype).v_char, getSize (sym->type));
1307 /* symbol has absolute address and initial value */
1309 resolveIvalSym (sym->ival, sym->type);
1310 asym = newSymbol (sym->rname, 0);
1311 abSym = Safe_calloc (1, sizeof (absSym));
1312 strcpy (abSym->name, sym->rname);
1313 abSym->address = SPEC_ADDR (sym->etype);
1314 addSet (&absSymSet, abSym);
1316 pb = pic16_newpCodeChain (NULL, 'A', pic16_newpCodeCharP ("; Starting pCode block for absolute Ival"));
1317 pic16_addpBlock (pb);
1319 pcf = pic16_newpCodeFunction (moduleName, asym->name);
1320 PCF (pcf)->absblock = 1;
1322 pic16_addpCode2pBlock (pb, pcf);
1323 pic16_addpCode2pBlock (pb, pic16_newpCodeLabel (sym->rname, -1));
1324 //fprintf(stderr, "%s:%d [1] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1325 /* if it has an initial value */
1328 pic16_printIval (sym, sym->type, sym->ival, 'p', (void *) pb);
1329 pic16_flushDB ('p', (void *) pb);
1332 pic16_addpCode2pBlock (pb, pic16_newpCodeFunction (NULL, NULL));
1338 // fprintf(stderr, "%s:%d spec_absa is false for symbol: %s\n",
1339 // __FILE__, __LINE__, sym->name);
1342 /* if it has an initial value */
1347 /* symbol doesn't have absolute address but has initial value */
1348 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
1350 resolveIvalSym (sym->ival, sym->type);
1352 pb = pic16_newpCodeChain (NULL, 'P', pic16_newpCodeCharP ("; Starting pCode block for Ival"));
1353 pic16_addpBlock (pb);
1357 /* make sure that 'code' directive is emitted before, once */
1358 pic16_addpCode2pBlock (pb, pic16_newpCodeAsmDir ("code", NULL));
1363 pic16_addpCode2pBlock (pb, pic16_newpCodeLabel (sym->rname, -1));
1364 //fprintf(stderr, "%s:%d [2] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1365 pic16_printIval (sym, sym->type, sym->ival, 'p', (void *) pb);
1366 pic16_flushDB ('p', (void *) pb);
1372 /* symbol doesn't have absolute address and no initial value */
1373 /* allocate space */
1374 // fprintf(stderr, "%s:%d [3] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1375 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
1376 /* special case for character strings */
1377 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) && SPEC_CVAL (sym->etype).v_char)
1380 // fprintf(stderr, "%s:%d printing code string for %s\n", __FILE__, __LINE__, sym->rname);
1382 pic16_pCodeConstString (sym->rname, SPEC_CVAL (sym->etype).v_char, getSize (sym->type));
1393 /*-----------------------------------------------------------------*/
1394 /* pic16_emitConfigRegs - emits the configuration registers */
1395 /*-----------------------------------------------------------------*/
1396 void pic16_emitConfigRegs(FILE *of)
1400 for(i=0;i<=(pic16->cwInfo.confAddrEnd-pic16->cwInfo.confAddrStart);i++)
1401 if(pic16->cwInfo.crInfo[i].emit) //mask != -1)
1402 fprintf (of, "\t__config 0x%x, 0x%hhx\n",
1403 pic16->cwInfo.confAddrStart+i,
1404 pic16->cwInfo.crInfo[i].value);
1407 void pic16_emitIDRegs(FILE *of)
1411 for(i=0;i<=(pic16->idInfo.idAddrEnd-pic16->idInfo.idAddrStart);i++)
1412 if(pic16->idInfo.irInfo[i].emit)
1413 fprintf (of, "\t__idlocs 0x%06x, 0x%hhx\n",
1414 pic16->idInfo.idAddrStart+i,
1415 pic16->idInfo.irInfo[i].value);
1422 /* no special considerations for the following
1423 data, idata & bit & xdata */
1424 pic16emitRegularMap (data, TRUE, TRUE);
1425 pic16emitRegularMap (idata, TRUE, TRUE);
1426 pic16emitRegularMap (bit, TRUE, FALSE);
1427 pic16emitRegularMap (xdata, TRUE, TRUE);
1428 pic16emitRegularMap (sfr, FALSE, FALSE);
1429 pic16emitRegularMap (sfrbit, FALSE, FALSE);
1430 pic16emitRegularMap (code, TRUE, FALSE);
1431 pic16emitStaticSeg (statsg);
1432 pic16emitStaticSeg (c_abs);
1435 /*-----------------------------------------------------------------*/
1436 /* createInterruptVect - creates the interrupt vector */
1437 /*-----------------------------------------------------------------*/
1439 pic16createInterruptVect (struct dbuf_s * vBuf)
1441 /* if the main is only a prototype ie. no body then do nothing */
1443 if (!IFFUNC_HASBODY(mainf->type)) {
1444 /* if ! compile only then main function should be present */
1445 if (!options.cc_only)
1451 if((!pic16_options.omit_ivt) || (pic16_options.omit_ivt && pic16_options.leave_reset)) {
1452 dbuf_printf (vBuf, ";\t.area\t%s\n", CODE_NAME);
1453 dbuf_printf (vBuf, ".intvecs\tcode\t0x%06x\n", pic16_options.ivt_loc);
1455 /* this is an overkill since WE are the port,
1456 * and we know if we have a genIVT function! */
1458 port->genIVT(vFile, interrupts, maxInterrupts);
1466 /*-----------------------------------------------------------------*/
1467 /* pic16initialComments - puts in some initial comments */
1468 /*-----------------------------------------------------------------*/
1470 pic16initialComments (FILE * afile)
1472 initialComments (afile);
1473 fprintf (afile, "; PIC16 port for the Microchip 16-bit core micros\n");
1474 if (pic16_options.xinst) {
1475 fprintf (afile, "; * Extended Instruction Set\n");
1478 if (pic16_mplab_comp) {
1479 fprintf(afile, "; * MPLAB/MPASM/MPASMWIN/MPLINK compatibility mode enabled\n");
1481 fprintf (afile, "%s", iComments2);
1483 if (options.debug) {
1484 fprintf (afile, "\n\t.ident \"SDCC version %s #%s [pic16 port]%s\"\n",
1485 SDCC_VERSION_STR, getBuildNumber(), (!pic16_options.xinst?"":" {extended}") );
1490 pic16_stringInSet(const char *str, set **world, int autoAdd)
1497 for (s = setFirstItem(*world); s; s = setNextItem(*world))
1500 if (0 == strcmp(s, str)) return 1;
1504 if (autoAdd) addSet(world, Safe_strdup(str));
1509 pic16_emitSymbolIfNew(FILE *file, const char *fmt, const char *sym, int checkLocals)
1511 static set *emitted = NULL;
1513 if (!pic16_stringInSet(sym, &emitted, 1)) {
1514 /* sym was not in emittedSymbols */
1515 if (!checkLocals || !pic16_stringInSet(sym, &pic16_localFunctions, 0)) {
1516 /* sym is not a locally defined function---avoid bug #1443651 */
1517 fprintf( file, fmt, sym );
1524 /*-----------------------------------------------------------------*/
1525 /* printPublics - generates global declarations for publics */
1526 /*-----------------------------------------------------------------*/
1528 pic16printPublics (FILE *afile)
1532 fprintf (afile, "\n%s", iComments2);
1533 fprintf (afile, "; public variables in this module\n");
1534 fprintf (afile, "%s", iComments2);
1536 for(sym = setFirstItem (publics); sym; sym = setNextItem (publics))
1538 if(!IS_STATIC(sym->etype))
1539 pic16_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1542 /*-----------------------------------------------------------------*/
1543 /* printExterns - generates extern declarations for externs */
1544 /*-----------------------------------------------------------------*/
1546 pic16_printExterns(FILE *afile)
1550 /* print nothing if no externs to declare */
1551 if(!elementsInSet(externs) && !elementsInSet(pic16_builtin_functions))
1554 fprintf(afile, "\n%s", iComments2);
1555 fprintf(afile, "; extern variables in this module\n");
1556 fprintf(afile, "%s", iComments2);
1558 for(sym = setFirstItem(externs); sym; sym = setNextItem(externs))
1559 pic16_emitSymbolIfNew(afile, "\textern %s\n", sym->rname, 1);
1561 for(sym = setFirstItem(pic16_builtin_functions); sym; sym = setNextItem(pic16_builtin_functions))
1562 pic16_emitSymbolIfNew(afile, "\textern _%s\n", sym->name, 1);
1565 /*-----------------------------------------------------------------*/
1566 /* emitOverlay - will emit code for the overlay stuff */
1567 /*-----------------------------------------------------------------*/
1569 pic16emitOverlay (struct dbuf_s *aBuf)
1573 if (!elementsInSet (ovrSetSets))
1574 dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name);
1576 /* for each of the sets in the overlay segment do */
1577 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1578 ovrset = setNextItem (ovrSetSets))
1583 if (elementsInSet (ovrset))
1585 /* this dummy area is used to fool the assembler
1586 otherwise the assembler will append each of these
1587 declarations into one chunk and will not overlay
1589 dbuf_printf (aBuf, ";\t.area _DUMMY\n");
1590 /* output the area informtion */
1591 dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1594 for (sym = setFirstItem (ovrset); sym;
1595 sym = setNextItem (ovrset))
1598 /* if extern then do nothing */
1599 if (IS_EXTERN (sym->etype))
1602 /* if allocation required check is needed
1603 then check if the symbol really requires
1604 allocation only for local variables */
1605 if (!IS_AGGREGATE (sym->type) &&
1606 !(sym->_isparm && !IS_REGPARM (sym->etype))
1607 && !sym->allocreq && sym->level)
1610 /* if global variable & not static or extern
1611 and addPublics allowed then add it to the public set */
1612 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1613 && !IS_STATIC (sym->etype)) {
1614 // fprintf(stderr, "%s:%d %s accessed\n", __FILE__, __LINE__, __FUNCTION__);
1615 checkAddSym(&publics, sym);
1616 // addSetHead (&publics, sym);
1619 /* if extern then do nothing or is a function
1621 if (IS_FUNC (sym->type))
1625 /* if is has an absolute address then generate
1626 an equate for this no need to allocate space */
1627 if (SPEC_ABSA (sym->etype))
1630 if (options.debug || sym->level == 0)
1631 dbuf_printf (aBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1633 dbuf_printf (aBuf, "%s\t=\t0x%04x\n",
1635 SPEC_ADDR (sym->etype));
1639 if (options.debug || sym->level == 0)
1640 dbuf_printf (aBuf, "==.\n");
1642 /* allocate space */
1643 dbuf_printf (aBuf, "%s:\n", sym->rname);
1644 dbuf_printf (aBuf, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1652 emitStatistics(FILE *asmFile)
1654 unsigned long isize, udsize, ramsize;
1655 statistics.isize = pic16_countInstructions();
1656 isize = (statistics.isize >= 0) ? statistics.isize : 0;
1657 udsize = (statistics.udsize >= 0) ? statistics.udsize : 0;
1658 ramsize = pic16 ? pic16->RAMsize : 0x200;
1659 ramsize -= 256; /* ignore access bank and SFRs */
1660 if (ramsize == 0) ramsize = 64; /* prevent division by zero (below) */
1662 fprintf (asmFile, "\n\n; Statistics:\n");
1663 fprintf (asmFile, "; code size:\t%5ld (0x%04lx) bytes (%5.2f%%)\n; \t%5ld (0x%04lx) words\n",
1664 isize, isize, (isize*100.0)/(128UL << 10),
1665 isize>>1, isize>>1);
1666 fprintf (asmFile, "; udata size:\t%5ld (0x%04lx) bytes (%5.2f%%)\n",
1667 udsize, udsize, (udsize*100.0) / (1.0 * ramsize));
1668 fprintf (asmFile, "; access size:\t%5ld (0x%04lx) bytes\n",
1669 statistics.intsize, statistics.intsize);
1671 fprintf (asmFile, "\n\n");
1676 /*-----------------------------------------------------------------*/
1677 /* glue - the final glue that hold the whole thing together */
1678 /*-----------------------------------------------------------------*/
1683 struct dbuf_s ovrBuf;
1686 dbuf_init(&ovrBuf, 4096);
1687 dbuf_init(&vBuf, 4096);
1689 mainf = newSymbol ("main", 0);
1692 mainf = findSymWithLevel(SymbolTab, mainf);
1694 pic16_pCodeInitRegisters();
1696 if(pic16_options.no_crt && mainf && IFFUNC_HASBODY(mainf->type)) {
1697 pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
1699 pic16_addpBlock(pb);
1701 /* entry point @ start of CSEG */
1702 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup",-1));
1705 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1706 pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("_stack_end"))));
1707 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1708 pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("_stack_end"))));
1711 /* put in the call to main */
1712 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
1714 if (options.mainreturn) {
1715 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
1716 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
1718 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
1719 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
1723 /* At this point we've got all the code in the form of pCode structures */
1724 /* Now it needs to be rearranged into the order it should be placed in the */
1727 pic16_movepBlock2Head('P'); // Last
1728 pic16_movepBlock2Head(code->dbName);
1729 pic16_movepBlock2Head('X');
1730 pic16_movepBlock2Head(statsg->dbName); // First
1732 /* print the global struct definitions */
1734 /* PENDING: this isnt the best place but it will do */
1735 if (port->general.glue_up_main) {
1736 /* create the interrupt vector table */
1737 pic16createInterruptVect (&vBuf);
1740 /* emit code for the all the variables declared */
1743 /* do the overlay segments */
1744 pic16emitOverlay(&ovrBuf);
1745 pic16_AnalyzepCode('*');
1748 if(pic16_options.dumpcalltree) {
1751 sprintf(buffer, "%s", dstFileName);
1752 strcat(buffer, ".calltree");
1753 cFile = fopen(buffer, "w");
1754 pic16_printCallTree( cFile );
1759 pic16_InlinepCode();
1760 pic16_AnalyzepCode('*');
1763 if(pic16_debug_verbose)
1766 /* now put it all together into the assembler file */
1767 /* create the assembler file name */
1768 if((noAssemble || options.c1mode) && fullDstFileName) {
1769 sprintf (buffer, "%s", fullDstFileName);
1771 sprintf (buffer, "%s", dstFileName);
1772 strcat (buffer, ".asm");
1775 if(!(asmFile = fopen (buffer, "w"))) {
1776 werror (E_FILE_OPEN_ERR, buffer);
1780 /* initial comments */
1781 pic16initialComments (asmFile);
1783 /* print module name */
1785 fprintf(asmFile, "\t.file\t\"%s\"\n", fullSrcFileName);
1787 /* Let the port generate any global directives, etc. */
1788 if(port->genAssemblerPreamble) {
1789 port->genAssemblerPreamble(asmFile);
1792 /* Put all variables into a cblock */
1793 pic16_AnalyzeBanking();
1796 if(pic16_options.opt_flags & OF_LR_SUPPORT) {
1797 pic16_OptimizeLocalRegs();
1801 /* remove redundant BANKSELs -- added by RN 2005-01-17 */
1802 if(pic16_options.opt_banksel > 1) {
1803 pic16_OptimizeBanksel();
1806 /* turn GOTOs into BRAs -- added by RN 2004-11-16 */
1807 if(!(pic16_options.opt_flags & OF_NO_OPTIMIZE_GOTO)) {
1808 pic16_OptimizeJumps();
1811 /* print the global variables in this module */
1812 pic16printPublics (asmFile);
1814 /* print the extern variables to this module */
1815 pic16_printExterns(asmFile);
1817 pic16_writeUsedRegs(asmFile);
1820 /* no xdata in pic */
1821 /* if external stack then reserve space of it */
1822 if(mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1823 fprintf (asmFile, "%s", iComments2);
1824 fprintf (asmFile, "; external stack \n");
1825 fprintf (asmFile, "%s", iComments2);
1826 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1827 fprintf (asmFile,";\t.ds 256\n");
1832 /* no xdata in pic */
1833 /* copy xtern ram data */
1834 fprintf (asmFile, "%s", iComments2);
1835 fprintf (asmFile, "; external ram data\n");
1836 fprintf (asmFile, "%s", iComments2);
1837 dbuf_write_and_destroy (&xdata->oBuf, asmFile);
1841 /* copy the bit segment */
1842 fprintf (asmFile, "%s", iComments2);
1843 fprintf (asmFile, "; bit data\n");
1844 fprintf (asmFile, "%s", iComments2);
1845 dbuf_write_and_destroy (&bit->oBuf, asmFile);
1848 /* copy the interrupt vector table */
1849 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1850 fprintf (asmFile, "\n%s", iComments2);
1851 fprintf (asmFile, "; interrupt vector \n");
1852 fprintf (asmFile, "%s", iComments2);
1853 dbuf_write_and_destroy (&vBuf, asmFile);
1856 /* copy global & static initialisations */
1857 fprintf (asmFile, "\n%s", iComments2);
1858 fprintf (asmFile, "; global & static initialisations\n");
1859 fprintf (asmFile, "%s", iComments2);
1861 if(pic16_debug_verbose)
1862 fprintf(asmFile, "; A code from now on!\n");
1864 pic16_copypCode(asmFile, 'A');
1866 if(pic16_options.no_crt) {
1867 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1868 fprintf(asmFile, "\tcode\n");
1869 fprintf(asmFile,"__sdcc_gsinit_startup:\n");
1873 // dbuf_write_and_destroy (&code->oBuf, stderr);
1875 fprintf(asmFile, "; I code from now on!\n");
1876 pic16_copypCode(asmFile, 'I');
1878 if(pic16_debug_verbose)
1879 fprintf(asmFile, "; dbName from now on!\n");
1881 pic16_copypCode(asmFile, statsg->dbName);
1883 if(pic16_options.no_crt) {
1884 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
1885 fprintf (asmFile,"\tgoto\t__sdcc_program_startup\n");
1889 if(pic16_debug_verbose)
1890 fprintf(asmFile, "; X code from now on!\n");
1892 pic16_copypCode(asmFile, 'X');
1894 if(pic16_debug_verbose)
1895 fprintf(asmFile, "; M code from now on!\n");
1897 pic16_copypCode(asmFile, 'M');
1899 pic16_copypCode(asmFile, code->dbName);
1901 pic16_copypCode(asmFile, 'P');
1903 emitStatistics(asmFile);
1905 fprintf (asmFile,"\tend\n");