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 */
797 else if (!SPEC_BUNNAMED (lsym->etype))
799 /* not an unnamed bit-field structure member */
800 value *val = list2val (lilist);
801 int bit_length = SPEC_BLEN (lsym->etype);
806 size += (bit_length + 7) / 8;
809 size = (bit_length + 7) / 8;
811 ival |= (ulFromVal (val) & ((1ul << bit_length) - 1ul)) << SPEC_BSTR (lsym->etype);
812 lilist = lilist->next;
817 for (i = 0; i < size; i++)
818 pic16_emitDB (BYTE_IN_LONG (ival, i), ptype, p);
825 /*-----------------------------------------------------------------*/
826 /* printIvalStruct - generates initial value for structures */
827 /*-----------------------------------------------------------------*/
829 pic16_printIvalStruct (symbol * sym, sym_link * type,
830 initList * ilist, char ptype, void *p)
833 initList *iloop = NULL;
837 fprintf(stderr, "%s\n",__FUNCTION__);
840 sflds = SPEC_STRUCT (type)->fields;
844 if (ilist->type != INIT_DEEP)
846 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
850 iloop = ilist->init.deep;
855 // fprintf(stderr, "%s:%d sflds: %p\tiloop = %p\n", __FILE__, __LINE__, sflds, iloop);
856 if (IS_BITFIELD (sflds->type))
858 pic16_printIvalBitFields (&sflds, &iloop, ptype, p);
862 pic16_printIval (sym, sflds->type, iloop, ptype, p);
864 iloop = iloop ? iloop->next : NULL;
868 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
871 /*-----------------------------------------------------------------*/
872 /* printIvalUnion - generates initial value for unions */
873 /*-----------------------------------------------------------------*/
875 pic16_printIvalUnion (symbol * sym, sym_link * type,
876 initList * ilist, char ptype, void *p)
879 initList *iloop = NULL;
881 symbol *sflds = NULL;
884 fprintf(stderr, "%s\n",__FUNCTION__);
889 sflds = SPEC_STRUCT (type)->fields;
892 if (ilist->type != INIT_DEEP) {
893 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
897 iloop = ilist->init.deep;
900 size = SPEC_STRUCT(type)->size;
901 sflds = SPEC_STRUCT(type)->fields;
902 pic16_printIval (sym, sflds->type, iloop, ptype, p);
904 /* if the first field is not the longest, fill with 0s */
905 while (size > getSize (sflds->type)) {
906 pic16_emitDB(0, ptype, p);
912 pic16_isUnion( symbol *sym, sym_link *type )
914 if (type && SPEC_STRUCT(type)->type == UNION) return 1;
918 /*--------------------------------------------------------------------------*/
919 /* pic16_printIvalCharPtr - generates initial values for character pointers */
920 /*--------------------------------------------------------------------------*/
922 pic16_printIvalCharPtr (symbol * sym, sym_link * type, value * val, char ptype, void *p)
927 /* PENDING: this is _very_ mcs51 specific, including a magic
929 It's also endin specific.
931 VR - Attempting to port this function to pic16 port - 8-Jun-2004
936 fprintf(stderr, "%s\n",__FUNCTION__);
939 size = getSize (type);
941 if (val->name && strlen (val->name))
943 if (size == 1) /* This appears to be Z80 specific?? */
945 pic16_emitDS(val->name, ptype, p);
949 pic16_printPointerType (val->name, ptype, p);
954 type = PTR_TYPE (SPEC_OCLS (val->etype));
955 if (val->sym && val->sym->isstrlit) {
956 // this is a literal string
959 pic16_printGPointerType(val->name, type, ptype, p);
963 fprintf (stderr, "*** internal error: unknown size in "
964 "printIvalCharPtr.\n");
970 // these are literals assigned to pointers
971 for (i = 0; i < size; i++)
973 pic16_emitDB(pic16aopLiteral(val, i), ptype, p);
977 if (val->sym && val->sym->isstrlit) { // && !isinSet(statsg->syms, val->sym)) {
978 if(ptype == 'p' && !isinSet(statsg->syms, val->sym))addSet (&statsg->syms, val->sym);
979 else if(ptype == 'f' /*&& !isinSet(rel_idataSymSet, val->sym)*/)addSet(&rel_idataSymSet, val->sym);
985 /*-----------------------------------------------------------------------*/
986 /* pic16_printIvalFuncPtr - generate initial value for function pointers */
987 /*-----------------------------------------------------------------------*/
989 pic16_printIvalFuncPtr (sym_link * type, initList * ilist, char ptype, void *p)
996 fprintf(stderr, "%s\n",__FUNCTION__);
1000 val = list2val (ilist);
1002 val = valCastLiteral(type, 0.0);
1005 // an error has been thrown already
1006 val = constCharVal (0);
1009 if (IS_LITERAL(val->etype)) {
1010 if (0 && compareType(type, val->etype) == 0) {
1011 werrorfl (ilist->filename, ilist->lineno, E_INCOMPAT_TYPES);
1012 printFromToType (val->type, type);
1014 pic16_printIvalCharPtr (NULL, type, val, ptype, p);
1018 /* check the types */
1019 if ((dLvl = compareType (val->type, type->next)) <= 0)
1021 pic16_emitDB(0x00, ptype, p);
1025 /* now generate the name */
1027 pic16_printGPointerType (val->name, CPOINTER /*DCL_TYPE(val->type)*/, ptype, p);
1029 pic16_printGPointerType (val->sym->rname, CPOINTER /*DCL_TYPE(val->type)*/, ptype, p);
1031 if(IS_FUNC(val->sym->type) && !val->sym->used && !IS_STATIC(val->sym->etype)) {
1033 if(!checkSym(publics, val->sym))
1034 if(checkAddSym(&externs, val->sym) && (ptype == 'f')) {
1035 /* this has not been declared as extern
1036 * so declare it as a 'late extern' just after the symbol */
1037 fprintf((FILE *)p, ";\tdeclare symbol as extern\n");
1038 fprintf((FILE *)p, "\textern\t%s\n", val->sym->rname);
1039 fprintf((FILE *)p, ";\tcontinue variable declaration\n");
1048 /*-----------------------------------------------------------------*/
1049 /* pic16_printIvalPtr - generates initial value for pointers */
1050 /*-----------------------------------------------------------------*/
1052 pic16_printIvalPtr (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p)
1059 fprintf(stderr, "%s:%d initialising pointer: %s size: %d\n", __FILE__, __LINE__,
1060 sym->rname, getSize(sym->type));
1064 if (ilist && (ilist->type == INIT_DEEP))
1065 ilist = ilist->init.deep;
1067 /* function pointer */
1068 if (IS_FUNC (type->next))
1070 pic16_printIvalFuncPtr (type, ilist, ptype, p);
1074 if (!(val = pic16_initPointer (ilist, type)))
1077 /* if character pointer */
1078 if (IS_CHAR (type->next))
1079 if (pic16_printIvalCharPtr (sym, type, val, ptype, p))
1082 /* check the type */
1083 if (compareType (type, val->type) == 0) {
1084 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
1085 printFromToType (val->type, type);
1088 size = getSize (type);
1090 /* if val is literal */
1091 if (IS_LITERAL (val->etype))
1093 for (i = 0; i < size; i++)
1095 pic16_emitDB(pic16aopLiteral(val, i), ptype, p);
1100 if (size == 1) /* Z80 specific?? */
1102 pic16_emitDS(val->name, ptype, p);
1106 pic16_printPointerType (val->name, ptype, p);
1111 itype = PTR_TYPE (SPEC_OCLS (val->etype));
1112 pic16_printGPointerType (val->name, itype, ptype, p);
1122 /*-----------------------------------------------------------------*/
1123 /* pic16_printIval - generates code for initial value */
1124 /*-----------------------------------------------------------------*/
1125 void pic16_printIval (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p)
1133 fprintf(stderr, "%s:%d generating init for %s\n", __FILE__, __LINE__, sym->name);
1134 fprintf(stderr, "%s: IS_STRUCT: %d IS_ARRAY: %d IS_PTR: %d IS_SPEC: %d\n", sym->name,
1135 IS_STRUCT(type), IS_ARRAY(type), IS_PTR(type), IS_SPEC(type));
1138 /* if structure then */
1139 if (IS_STRUCT (type))
1141 if (pic16_isUnion(sym, type))
1143 //fprintf(stderr,"%s union\n",__FUNCTION__);
1144 pic16_printIvalUnion (sym, type, ilist, ptype, p);
1146 //fprintf(stderr,"%s struct\n",__FUNCTION__);
1147 pic16_printIvalStruct (sym, type, ilist, ptype, p);
1152 /* if this is an array */
1153 if (IS_ARRAY (type))
1155 // fprintf(stderr,"%s array\n",__FUNCTION__);
1156 pic16_printIvalArray (sym, type, ilist, ptype, p);
1163 // not an aggregate, ilist must be a node
1164 if (ilist->type!=INIT_NODE) {
1165 // or a 1-element list
1166 if (ilist->init.deep->next) {
1167 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar",
1170 ilist=ilist->init.deep;
1175 // and the type must match
1176 itype=ilist->init.node->ftype;
1178 if (compareType(type, itype)==0) {
1179 // special case for literal strings
1180 if (IS_ARRAY (itype) && IS_CHAR (getSpec(itype)) &&
1181 // which are really code pointers
1182 IS_PTR(type) && DCL_TYPE(type)==CPOINTER) {
1185 // werrorfl (ilist->filename, ilist->lineno, E_TYPE_MISMATCH, "assignment", " ");
1186 // printFromToType(itype, type);
1193 /* if this is a pointer */
1196 // fprintf(stderr,"%s pointer\n",__FUNCTION__);
1197 pic16_printIvalPtr (sym, type, ilist, ptype, p);
1202 /* if type is SPECIFIER */
1205 // fprintf(stderr,"%s spec\n",__FUNCTION__);
1206 pic16_printIvalType (sym, type, ilist, ptype, p);
1212 PIC16_IS_CONFIG_ADDRESS(int address)
1214 return ((address >= pic16->cwInfo.confAddrStart && address <= pic16->cwInfo.confAddrEnd));
1218 PIC16_IS_IDLOC_ADDRESS(int address)
1220 return ((address >= pic16->idInfo.idAddrStart && address <= pic16->idInfo.idAddrEnd));
1223 /*-----------------------------------------------------------------*/
1224 /* emitStaticSeg - emitcode for the static segment */
1225 /*-----------------------------------------------------------------*/
1227 pic16emitStaticSeg (memmap * map)
1230 static int didcode = 0;
1232 //fprintf(stderr, "%s\n",__FUNCTION__);
1236 /* for all variables in this segment do */
1237 for (sym = setFirstItem (map->syms); sym; sym = setNextItem (map->syms))
1241 fprintf (stderr, "%s\t%s: sym: %s\tused: %d\tSPEC_ABSA: %d\tSPEC_AGGREGATE: %d\tCODE: %d\n\
1242 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));
1243 printTypeChain (sym->type, stderr);
1244 fprintf (stderr, "\n");
1247 if (SPEC_ABSA (sym->etype) && PIC16_IS_CONFIG_ADDRESS (SPEC_ADDR (sym->etype)))
1249 pic16_assignConfigWordValue (SPEC_ADDR (sym->etype), (int) ulFromVal (list2val (sym->ival)));
1254 if (SPEC_ABSA (sym->etype) && PIC16_IS_IDLOC_ADDRESS (SPEC_ADDR (sym->etype)))
1256 pic16_assignIdByteValue (SPEC_ADDR (sym->etype), (char) ulFromVal (list2val (sym->ival)));
1261 /* if it is "extern" then do nothing */
1262 if (IS_EXTERN (sym->etype) /* && !SPEC_ABSA(sym->etype) */ )
1264 checkAddSym (&externs, sym);
1268 /* if it is not static add it to the public
1270 if (!IS_STATIC (sym->etype))
1272 /* do not emit if it is a config word declaration */
1273 checkAddSym (&publics, sym);
1276 /* print extra debug info if required */
1277 if (options.debug || sym->level == 0)
1279 /* NOTE to me - cdbFile may be null in which case,
1280 * the sym name will be printed to stdout. oh well */
1281 debugFile->writeSymbol (sym);
1284 /* if it has an absolute address */
1285 if (SPEC_ABSA (sym->etype))
1287 // fprintf(stderr, "%s:%d spec_absa is true for symbol: %s\n",
1288 // __FILE__, __LINE__, sym->name);
1290 if (!sym->ival && IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) && SPEC_CVAL (sym->etype).v_char)
1292 /* symbol has absolute address but no initial value */
1293 /* special case for character strings */
1295 // fprintf(stderr, "%s:%d printing code string from %s\n", __FILE__, __LINE__, sym->rname);
1297 pic16_pCodeConstString (sym->rname, SPEC_CVAL (sym->etype).v_char, getSize (sym->type));
1306 /* symbol has absolute address and initial value */
1308 resolveIvalSym (sym->ival, sym->type);
1309 asym = newSymbol (sym->rname, 0);
1310 abSym = Safe_calloc (1, sizeof (absSym));
1311 strcpy (abSym->name, sym->rname);
1312 abSym->address = SPEC_ADDR (sym->etype);
1313 addSet (&absSymSet, abSym);
1315 pb = pic16_newpCodeChain (NULL, 'A', pic16_newpCodeCharP ("; Starting pCode block for absolute Ival"));
1316 pic16_addpBlock (pb);
1318 pcf = pic16_newpCodeFunction (moduleName, asym->name);
1319 PCF (pcf)->absblock = 1;
1321 pic16_addpCode2pBlock (pb, pcf);
1322 pic16_addpCode2pBlock (pb, pic16_newpCodeLabel (sym->rname, -1));
1323 //fprintf(stderr, "%s:%d [1] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1324 /* if it has an initial value */
1327 pic16_printIval (sym, sym->type, sym->ival, 'p', (void *) pb);
1328 pic16_flushDB ('p', (void *) pb);
1331 pic16_addpCode2pBlock (pb, pic16_newpCodeFunction (NULL, NULL));
1337 // fprintf(stderr, "%s:%d spec_absa is false for symbol: %s\n",
1338 // __FILE__, __LINE__, sym->name);
1341 /* if it has an initial value */
1346 /* symbol doesn't have absolute address but has initial value */
1347 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
1349 resolveIvalSym (sym->ival, sym->type);
1351 pb = pic16_newpCodeChain (NULL, 'P', pic16_newpCodeCharP ("; Starting pCode block for Ival"));
1352 pic16_addpBlock (pb);
1356 /* make sure that 'code' directive is emitted before, once */
1357 pic16_addpCode2pBlock (pb, pic16_newpCodeAsmDir ("code", NULL));
1362 pic16_addpCode2pBlock (pb, pic16_newpCodeLabel (sym->rname, -1));
1363 //fprintf(stderr, "%s:%d [2] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1364 pic16_printIval (sym, sym->type, sym->ival, 'p', (void *) pb);
1365 pic16_flushDB ('p', (void *) pb);
1371 /* symbol doesn't have absolute address and no initial value */
1372 /* allocate space */
1373 // fprintf(stderr, "%s:%d [3] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1374 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
1375 /* special case for character strings */
1376 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) && SPEC_CVAL (sym->etype).v_char)
1379 // fprintf(stderr, "%s:%d printing code string for %s\n", __FILE__, __LINE__, sym->rname);
1381 pic16_pCodeConstString (sym->rname, SPEC_CVAL (sym->etype).v_char, getSize (sym->type));
1392 /*-----------------------------------------------------------------*/
1393 /* pic16_emitConfigRegs - emits the configuration registers */
1394 /*-----------------------------------------------------------------*/
1395 void pic16_emitConfigRegs(FILE *of)
1399 for(i=0;i<=(pic16->cwInfo.confAddrEnd-pic16->cwInfo.confAddrStart);i++)
1400 if(pic16->cwInfo.crInfo[i].emit) //mask != -1)
1401 fprintf (of, "\t__config 0x%x, 0x%hhx\n",
1402 pic16->cwInfo.confAddrStart+i,
1403 pic16->cwInfo.crInfo[i].value);
1406 void pic16_emitIDRegs(FILE *of)
1410 for(i=0;i<=(pic16->idInfo.idAddrEnd-pic16->idInfo.idAddrStart);i++)
1411 if(pic16->idInfo.irInfo[i].emit)
1412 fprintf (of, "\t__idlocs 0x%06x, 0x%hhx\n",
1413 pic16->idInfo.idAddrStart+i,
1414 pic16->idInfo.irInfo[i].value);
1421 /* no special considerations for the following
1422 data, idata & bit & xdata */
1423 pic16emitRegularMap (data, TRUE, TRUE);
1424 pic16emitRegularMap (idata, TRUE, TRUE);
1425 pic16emitRegularMap (bit, TRUE, FALSE);
1426 pic16emitRegularMap (xdata, TRUE, TRUE);
1427 pic16emitRegularMap (sfr, FALSE, FALSE);
1428 pic16emitRegularMap (sfrbit, FALSE, FALSE);
1429 pic16emitRegularMap (code, TRUE, FALSE);
1430 pic16emitStaticSeg (statsg);
1431 pic16emitStaticSeg (c_abs);
1434 /*-----------------------------------------------------------------*/
1435 /* createInterruptVect - creates the interrupt vector */
1436 /*-----------------------------------------------------------------*/
1438 pic16createInterruptVect (struct dbuf_s * vBuf)
1440 /* if the main is only a prototype ie. no body then do nothing */
1442 if (!IFFUNC_HASBODY(mainf->type)) {
1443 /* if ! compile only then main function should be present */
1444 if (!options.cc_only)
1450 if((!pic16_options.omit_ivt) || (pic16_options.omit_ivt && pic16_options.leave_reset)) {
1451 dbuf_printf (vBuf, ";\t.area\t%s\n", CODE_NAME);
1452 dbuf_printf (vBuf, ".intvecs\tcode\t0x%06x\n", pic16_options.ivt_loc);
1454 /* this is an overkill since WE are the port,
1455 * and we know if we have a genIVT function! */
1457 port->genIVT(vFile, interrupts, maxInterrupts);
1465 /*-----------------------------------------------------------------*/
1466 /* pic16initialComments - puts in some initial comments */
1467 /*-----------------------------------------------------------------*/
1469 pic16initialComments (FILE * afile)
1471 initialComments (afile);
1472 fprintf (afile, "; PIC16 port for the Microchip 16-bit core micros\n");
1473 if (pic16_options.xinst) {
1474 fprintf (afile, "; * Extended Instruction Set\n");
1477 if (pic16_mplab_comp) {
1478 fprintf(afile, "; * MPLAB/MPASM/MPASMWIN/MPLINK compatibility mode enabled\n");
1480 fprintf (afile, "%s", iComments2);
1482 if (options.debug) {
1483 fprintf (afile, "\n\t.ident \"SDCC version %s #%s [pic16 port]%s\"\n",
1484 SDCC_VERSION_STR, getBuildNumber(), (!pic16_options.xinst?"":" {extended}") );
1489 pic16_stringInSet(const char *str, set **world, int autoAdd)
1496 for (s = setFirstItem(*world); s; s = setNextItem(*world))
1499 if (0 == strcmp(s, str)) return 1;
1503 if (autoAdd) addSet(world, Safe_strdup(str));
1508 pic16_emitSymbolIfNew(FILE *file, const char *fmt, const char *sym, int checkLocals)
1510 static set *emitted = NULL;
1512 if (!pic16_stringInSet(sym, &emitted, 1)) {
1513 /* sym was not in emittedSymbols */
1514 if (!checkLocals || !pic16_stringInSet(sym, &pic16_localFunctions, 0)) {
1515 /* sym is not a locally defined function---avoid bug #1443651 */
1516 fprintf( file, fmt, sym );
1523 /*-----------------------------------------------------------------*/
1524 /* printPublics - generates global declarations for publics */
1525 /*-----------------------------------------------------------------*/
1527 pic16printPublics (FILE *afile)
1531 fprintf (afile, "\n%s", iComments2);
1532 fprintf (afile, "; public variables in this module\n");
1533 fprintf (afile, "%s", iComments2);
1535 for(sym = setFirstItem (publics); sym; sym = setNextItem (publics))
1537 if(!IS_STATIC(sym->etype))
1538 pic16_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1541 /*-----------------------------------------------------------------*/
1542 /* printExterns - generates extern declarations for externs */
1543 /*-----------------------------------------------------------------*/
1545 pic16_printExterns(FILE *afile)
1549 /* print nothing if no externs to declare */
1550 if(!elementsInSet(externs) && !elementsInSet(pic16_builtin_functions))
1553 fprintf(afile, "\n%s", iComments2);
1554 fprintf(afile, "; extern variables in this module\n");
1555 fprintf(afile, "%s", iComments2);
1557 for(sym = setFirstItem(externs); sym; sym = setNextItem(externs))
1558 pic16_emitSymbolIfNew(afile, "\textern %s\n", sym->rname, 1);
1560 for(sym = setFirstItem(pic16_builtin_functions); sym; sym = setNextItem(pic16_builtin_functions))
1561 pic16_emitSymbolIfNew(afile, "\textern _%s\n", sym->name, 1);
1564 /*-----------------------------------------------------------------*/
1565 /* emitOverlay - will emit code for the overlay stuff */
1566 /*-----------------------------------------------------------------*/
1568 pic16emitOverlay (struct dbuf_s *aBuf)
1572 if (!elementsInSet (ovrSetSets))
1573 dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name);
1575 /* for each of the sets in the overlay segment do */
1576 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1577 ovrset = setNextItem (ovrSetSets))
1582 if (elementsInSet (ovrset))
1584 /* this dummy area is used to fool the assembler
1585 otherwise the assembler will append each of these
1586 declarations into one chunk and will not overlay
1588 dbuf_printf (aBuf, ";\t.area _DUMMY\n");
1589 /* output the area informtion */
1590 dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1593 for (sym = setFirstItem (ovrset); sym;
1594 sym = setNextItem (ovrset))
1597 /* if extern then do nothing */
1598 if (IS_EXTERN (sym->etype))
1601 /* if allocation required check is needed
1602 then check if the symbol really requires
1603 allocation only for local variables */
1604 if (!IS_AGGREGATE (sym->type) &&
1605 !(sym->_isparm && !IS_REGPARM (sym->etype))
1606 && !sym->allocreq && sym->level)
1609 /* if global variable & not static or extern
1610 and addPublics allowed then add it to the public set */
1611 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1612 && !IS_STATIC (sym->etype)) {
1613 // fprintf(stderr, "%s:%d %s accessed\n", __FILE__, __LINE__, __FUNCTION__);
1614 checkAddSym(&publics, sym);
1615 // addSetHead (&publics, sym);
1618 /* if extern then do nothing or is a function
1620 if (IS_FUNC (sym->type))
1624 /* if is has an absolute address then generate
1625 an equate for this no need to allocate space */
1626 if (SPEC_ABSA (sym->etype))
1629 if (options.debug || sym->level == 0)
1630 dbuf_printf (aBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1632 dbuf_printf (aBuf, "%s\t=\t0x%04x\n",
1634 SPEC_ADDR (sym->etype));
1638 if (options.debug || sym->level == 0)
1639 dbuf_printf (aBuf, "==.\n");
1641 /* allocate space */
1642 dbuf_printf (aBuf, "%s:\n", sym->rname);
1643 dbuf_printf (aBuf, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1651 emitStatistics(FILE *asmFile)
1653 unsigned long isize, udsize, ramsize;
1654 statistics.isize = pic16_countInstructions();
1655 isize = (statistics.isize >= 0) ? statistics.isize : 0;
1656 udsize = (statistics.udsize >= 0) ? statistics.udsize : 0;
1657 ramsize = pic16 ? pic16->RAMsize : 0x200;
1658 ramsize -= 256; /* ignore access bank and SFRs */
1659 if (ramsize == 0) ramsize = 64; /* prevent division by zero (below) */
1661 fprintf (asmFile, "\n\n; Statistics:\n");
1662 fprintf (asmFile, "; code size:\t%5ld (0x%04lx) bytes (%5.2f%%)\n; \t%5ld (0x%04lx) words\n",
1663 isize, isize, (isize*100.0)/(128UL << 10),
1664 isize>>1, isize>>1);
1665 fprintf (asmFile, "; udata size:\t%5ld (0x%04lx) bytes (%5.2f%%)\n",
1666 udsize, udsize, (udsize*100.0) / (1.0 * ramsize));
1667 fprintf (asmFile, "; access size:\t%5ld (0x%04lx) bytes\n",
1668 statistics.intsize, statistics.intsize);
1670 fprintf (asmFile, "\n\n");
1675 /*-----------------------------------------------------------------*/
1676 /* glue - the final glue that hold the whole thing together */
1677 /*-----------------------------------------------------------------*/
1682 struct dbuf_s ovrBuf;
1685 dbuf_init(&ovrBuf, 4096);
1686 dbuf_init(&vBuf, 4096);
1688 mainf = newSymbol ("main", 0);
1691 mainf = findSymWithLevel(SymbolTab, mainf);
1693 pic16_pCodeInitRegisters();
1695 if(pic16_options.no_crt && mainf && IFFUNC_HASBODY(mainf->type)) {
1696 pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
1698 pic16_addpBlock(pb);
1700 /* entry point @ start of CSEG */
1701 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup",-1));
1704 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1705 pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("_stack_end"))));
1706 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1707 pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("_stack_end"))));
1710 /* put in the call to main */
1711 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
1713 if (options.mainreturn) {
1714 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
1715 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
1717 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
1718 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
1722 /* At this point we've got all the code in the form of pCode structures */
1723 /* Now it needs to be rearranged into the order it should be placed in the */
1726 pic16_movepBlock2Head('P'); // Last
1727 pic16_movepBlock2Head(code->dbName);
1728 pic16_movepBlock2Head('X');
1729 pic16_movepBlock2Head(statsg->dbName); // First
1731 /* print the global struct definitions */
1733 /* PENDING: this isnt the best place but it will do */
1734 if (port->general.glue_up_main) {
1735 /* create the interrupt vector table */
1736 pic16createInterruptVect (&vBuf);
1739 /* emit code for the all the variables declared */
1742 /* do the overlay segments */
1743 pic16emitOverlay(&ovrBuf);
1744 pic16_AnalyzepCode('*');
1747 if(pic16_options.dumpcalltree) {
1750 sprintf(buffer, "%s", dstFileName);
1751 strcat(buffer, ".calltree");
1752 cFile = fopen(buffer, "w");
1753 pic16_printCallTree( cFile );
1758 pic16_InlinepCode();
1759 pic16_AnalyzepCode('*');
1762 if(pic16_debug_verbose)
1765 /* now put it all together into the assembler file */
1766 /* create the assembler file name */
1767 if((noAssemble || options.c1mode) && fullDstFileName) {
1768 sprintf (buffer, "%s", fullDstFileName);
1770 sprintf (buffer, "%s", dstFileName);
1771 strcat (buffer, ".asm");
1774 if(!(asmFile = fopen (buffer, "w"))) {
1775 werror (E_FILE_OPEN_ERR, buffer);
1779 /* initial comments */
1780 pic16initialComments (asmFile);
1782 /* print module name */
1784 fprintf(asmFile, "\t.file\t\"%s\"\n", fullSrcFileName);
1786 /* Let the port generate any global directives, etc. */
1787 if(port->genAssemblerPreamble) {
1788 port->genAssemblerPreamble(asmFile);
1791 /* Put all variables into a cblock */
1792 pic16_AnalyzeBanking();
1795 if(pic16_options.opt_flags & OF_LR_SUPPORT) {
1796 pic16_OptimizeLocalRegs();
1800 /* remove redundant BANKSELs -- added by RN 2005-01-17 */
1801 if(pic16_options.opt_banksel > 1) {
1802 pic16_OptimizeBanksel();
1805 /* turn GOTOs into BRAs -- added by RN 2004-11-16 */
1806 if(!(pic16_options.opt_flags & OF_NO_OPTIMIZE_GOTO)) {
1807 pic16_OptimizeJumps();
1810 /* print the global variables in this module */
1811 pic16printPublics (asmFile);
1813 /* print the extern variables to this module */
1814 pic16_printExterns(asmFile);
1816 pic16_writeUsedRegs(asmFile);
1819 /* no xdata in pic */
1820 /* if external stack then reserve space of it */
1821 if(mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1822 fprintf (asmFile, "%s", iComments2);
1823 fprintf (asmFile, "; external stack \n");
1824 fprintf (asmFile, "%s", iComments2);
1825 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1826 fprintf (asmFile,";\t.ds 256\n");
1831 /* no xdata in pic */
1832 /* copy xtern ram data */
1833 fprintf (asmFile, "%s", iComments2);
1834 fprintf (asmFile, "; external ram data\n");
1835 fprintf (asmFile, "%s", iComments2);
1836 dbuf_write_and_destroy (&xdata->oBuf, asmFile);
1840 /* copy the bit segment */
1841 fprintf (asmFile, "%s", iComments2);
1842 fprintf (asmFile, "; bit data\n");
1843 fprintf (asmFile, "%s", iComments2);
1844 dbuf_write_and_destroy (&bit->oBuf, asmFile);
1847 /* copy the interrupt vector table */
1848 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1849 fprintf (asmFile, "\n%s", iComments2);
1850 fprintf (asmFile, "; interrupt vector \n");
1851 fprintf (asmFile, "%s", iComments2);
1852 dbuf_write_and_destroy (&vBuf, asmFile);
1855 /* copy global & static initialisations */
1856 fprintf (asmFile, "\n%s", iComments2);
1857 fprintf (asmFile, "; global & static initialisations\n");
1858 fprintf (asmFile, "%s", iComments2);
1860 if(pic16_debug_verbose)
1861 fprintf(asmFile, "; A code from now on!\n");
1863 pic16_copypCode(asmFile, 'A');
1865 if(pic16_options.no_crt) {
1866 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1867 fprintf(asmFile, "\tcode\n");
1868 fprintf(asmFile,"__sdcc_gsinit_startup:\n");
1872 // dbuf_write_and_destroy (&code->oBuf, stderr);
1874 fprintf(asmFile, "; I code from now on!\n");
1875 pic16_copypCode(asmFile, 'I');
1877 if(pic16_debug_verbose)
1878 fprintf(asmFile, "; dbName from now on!\n");
1880 pic16_copypCode(asmFile, statsg->dbName);
1882 if(pic16_options.no_crt) {
1883 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
1884 fprintf (asmFile,"\tgoto\t__sdcc_program_startup\n");
1888 if(pic16_debug_verbose)
1889 fprintf(asmFile, "; X code from now on!\n");
1891 pic16_copypCode(asmFile, 'X');
1893 if(pic16_debug_verbose)
1894 fprintf(asmFile, "; M code from now on!\n");
1896 pic16_copypCode(asmFile, 'M');
1898 pic16_copypCode(asmFile, code->dbName);
1900 pic16_copypCode(asmFile, 'P');
1902 emitStatistics(asmFile);
1904 fprintf (asmFile,"\tend\n");