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"
38 #ifdef WORDS_BIGENDIAN
39 #define _ENDIAN(x) (3-x)
41 #define _ENDIAN(x) (x)
44 #define BYTE_IN_LONG(x,b) ((x>>(8*_ENDIAN(b)))&0xff)
46 extern symbol *interrupts[256];
47 void pic16_printIval (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p);
51 extern unsigned maxInterrupts;
52 extern int maxRegBank;
54 extern char *VersionString;
55 extern FILE *codeOutFile;
56 extern set *tmpfileSet;
57 extern set *tmpfileNameSet;
58 extern char *iComments1;
59 extern char *iComments2;
62 extern unsigned long pFile_isize;
64 extern unsigned long pic16_countInstructions();
65 set *rel_idataSymSet=NULL;
66 set *fix_idataSymSet=NULL;
68 extern DEFSETFUNC (closeTmpFiles);
69 extern DEFSETFUNC (rmTmpFiles);
71 extern void pic16_AnalyzeBanking (void);
72 extern void pic16_OptimizeJumps ();
73 extern void pic16_OptimizeBanksel ();
74 extern void copyFile (FILE * dest, FILE * src);
75 extern void pic16_InlinepCode(void);
76 extern void pic16_writeUsedRegs(FILE *);
78 extern void initialComments (FILE * afile);
79 extern void printPublics (FILE * afile);
81 void pic16_pCodeInitRegisters(void);
82 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
83 extern void pic16_pCodeConstString(char *name, char *value);
86 /*-----------------------------------------------------------------*/
87 /* aopLiteral - string from a literal value */
88 /*-----------------------------------------------------------------*/
89 int pic16aopLiteral (value *val, int offset)
96 /* if it is a float then it gets tricky */
97 /* otherwise it is fairly simple */
98 if (!(IS_FLOAT(val->type) || IS_FIXED(val->type))) {
99 unsigned long v = (unsigned long) floatFromVal(val);
101 return ( (v >> (offset * 8)) & 0xff);
104 if(IS_FIXED16X16(val->type)) {
105 unsigned long v = (unsigned long)fixed16x16FromDouble( floatFromVal( val ) );
107 return ( (v >> (offset * 8)) & 0xff);
110 /* it is type float */
111 fl.f = (float) floatFromVal(val);
112 #ifdef WORDS_BIGENDIAN
113 return fl.c[3-offset];
122 char tbuffer[512], *tbuf=tbuffer;;
125 /*-----------------------------------------------------------------*/
126 /* emitRegularMap - emit code for maps with no special cases */
127 /*-----------------------------------------------------------------*/
129 pic16emitRegularMap (memmap * map, bool addPublics, bool arFlag)
132 // int i, size, bitvars = 0;;
134 // fprintf(stderr, "%s:%d map name= %s\n", __FUNCTION__, __LINE__, map->sname);
137 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
138 /* print the area name */
140 for (sym = setFirstItem (map->syms); sym; sym = setNextItem (map->syms)) {
143 fprintf(stderr, "%s\t%s: sym: %s\tused: %d\textern: %d\tstatic: %d\taggregate: %d\tregister: 0x%x\tfunction: %d\n",
145 map->sname, sym->name, sym->used, IS_EXTERN(sym->etype), IS_STATIC(sym->etype),
146 IS_AGGREGATE(sym->type), (SPEC_SCLS(sym->etype) == S_REGISTER), IS_FUNC(sym->type));
147 printTypeChain( sym->type, stderr );
148 fprintf(stderr, "\n");
151 /* if extern then add to externs */
152 if (IS_EXTERN (sym->etype)) {
153 /* reduce overhead while linking by not declaring
154 * extern unused external functions (usually declared
155 * in header files) */
156 if(IS_FUNC(sym->type) && !sym->used)continue;
158 /* make sure symbol is not in publics section */
159 if(!checkSym(publics, sym))
160 checkAddSym(&externs, sym);
164 /* if allocation required check is needed
165 * then check if the symbol really requires
166 * allocation only for local variables */
167 if (arFlag && !IS_AGGREGATE (sym->type) &&
168 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
169 !sym->allocreq && sym->level) {
171 // fprintf(stderr, "%s:%d special case, continuing...\n", __FILE__, __LINE__);
176 /* if global variable & not static or extern
177 * and addPublics allowed then add it to the public set */
178 if ((sym->used) && (sym->level == 0 ||
179 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
181 !IS_STATIC (sym->etype) && !IS_FUNC(sym->type)) {
183 checkAddSym(&publics, sym);
186 if(IS_STATIC(sym->etype)
187 && !sym->ival) /* && !sym->level*/ {
192 // debugf("adding symbol %s\n", sym->name);
193 #define SET_IMPLICIT 1
196 if(IS_STRUCT(sym->type))
200 reg = pic16_allocDirReg( operandFromSymbol( sym ));
203 for(ssym=setFirstItem(sectSyms); ssym; ssym=setNextItem(sectSyms)) {
204 if(!strcmp(ssym->name, reg->name))found=1;
208 checkAddReg(&pic16_rel_udata, reg);
211 debugf("Did find %s in pic16_rel_udata already. Check!\n", reg->name);
212 // checkAddSym(&publics, sym);
218 /* if extern then do nothing or is a function
220 if (IS_FUNC (sym->type) && !IS_STATIC(sym->etype)) {
221 if(SPEC_OCLS(sym->etype) == code) {
222 // fprintf(stderr, "%s:%d: symbol added: %s\n", __FILE__, __LINE__, sym->rname);
223 checkAddSym(&publics, sym);
228 /* if is has an absolute address then generate
229 an equate for this no need to allocate space */
230 if (SPEC_ABSA (sym->etype)) {
231 // fprintf (stderr,"; %s == 0x%04x\t\treqv= %p nRegs= %d\n",
232 // sym->name, SPEC_ADDR (sym->etype), sym->reqv, sym->regType);
234 fprintf (map->oFile, "%s\tEQU\t0x%04x\n",
236 SPEC_ADDR (sym->etype));
238 /* emit only if it is global */
239 if(sym->level == 0) {
242 reg = pic16_dirregWithName( sym->name );
245 // fprintf(stderr, "%s:%d: implicit add of symbol = %s\n",
246 // __FUNCTION__, __LINE__, sym->name);
248 /* if IS_STRUCT is omitted the following
249 * fixes structures but break char/int etc */
251 if(IS_STRUCT(sym->type))
252 sym->implicit = 1; // mark as implicit
255 reg = pic16_allocDirReg( operandFromSymbol(sym) );
257 if(checkAddReg(&pic16_fix_udata, reg)) {
258 /* and add to globals list if not exist */
259 addSet(&publics, sym);
263 addSet(&publics, sym);
267 if(!sym->used && (sym->level == 0)) {
270 /* symbol not used, just declared probably, but its in
271 * level 0, so we must declare it fine as global */
273 // fprintf(stderr, "EXTRA symbol declaration sym= %s\n", sym->name);
276 if(IS_STRUCT(sym->type))
277 sym->implicit = 1; // mark as implicit
280 if(IS_AGGREGATE(sym->type)) {
281 reg=pic16_allocRegByName(sym->rname, getSize( sym->type ), NULL);
283 reg = pic16_allocDirReg( operandFromSymbol( sym ) );
291 fprintf(stderr, "%s:%d sym->rname: %s reg: %p reg->name: %s\n", __FILE__, __LINE__,
292 sym->rname, reg, (reg?reg->name:"<<NULL>>"));
296 for(ssym=setFirstItem(sectSyms); ssym; ssym=setNextItem(sectSyms)) {
297 if(!strcmp(ssym->name, reg->name))found=1;
301 if(checkAddReg(&pic16_rel_udata, reg)) {
302 addSetHead(&publics, sym);
311 addSetHead(&publics, sym);
316 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
317 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
318 /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
319 if (IS_BITVAR (sym->etype)) {
322 fprintf (map->oFile, "\t%s\n", sym->rname);
323 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1) {
324 for (i = 1; i < size; i++)
325 fprintf (map->oFile, "\t%s_%d\n", sym->rname, i);
328 fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
332 /* FIXME -- VR Fix the following, so that syms to be placed
333 * in the idata section and let linker decide about their fate */
335 /* if it has an initial value then do it only if
336 it is a global variable */
339 && ((sym->level == 0)
340 || IS_STATIC(sym->etype)) ) {
344 if(SPEC_OCLS(sym->etype)==data) {
345 fprintf(stderr, "%s: sym %s placed in data segment\n", map->sname, sym->name);
348 if(SPEC_OCLS(sym->etype)==code) {
349 fprintf(stderr, "%s: sym %s placed in code segment\n", map->sname, sym->name);
354 fprintf(stderr, "'%s': sym '%s' has initial value SPEC_ABSA: %d, IS_AGGREGATE: %d\n",
355 map->sname, sym->name, SPEC_ABSA(sym->etype), IS_AGGREGATE(sym->type));
358 if (IS_AGGREGATE (sym->type)) {
359 if(SPEC_ABSA(sym->etype))
360 addSet(&fix_idataSymSet, copySymbol(sym));
362 addSet(&rel_idataSymSet, copySymbol(sym));
363 // ival = initAggregates (sym, sym->ival, NULL);
365 if(SPEC_ABSA(sym->etype))
366 addSet(&fix_idataSymSet, copySymbol(sym));
368 addSet(&rel_idataSymSet, copySymbol(sym));
370 // ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
371 // decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
375 setAstLineno(ival, sym->lineDef);
376 codeOutFile = statsg->oFile;
378 eBBlockFromiCode (iCodeFromAst (ival));
386 /*-----------------------------------------------------------------*/
387 /* pic16_initPointer - pointer initialization code massaging */
388 /*-----------------------------------------------------------------*/
389 value *pic16_initPointer (initList * ilist, sym_link *toType)
395 return valCastLiteral(toType, 0.0);
398 expr = decorateType(resolveSymbols( list2expr (ilist) ), FALSE);
399 // expr = list2expr( ilist );
404 /* try it the old way first */
405 if ((val = constExprValue (expr, FALSE)))
408 /* ( ptr + constant ) */
409 if (IS_AST_OP (expr) &&
410 (expr->opval.op == '+' || expr->opval.op == '-') &&
411 IS_AST_SYM_VALUE (expr->left) &&
412 (IS_ARRAY(expr->left->ftype) || IS_PTR(expr->left->ftype)) &&
413 compareType(toType, expr->left->ftype) &&
414 IS_AST_LIT_VALUE (expr->right)) {
415 return valForCastAggr (expr->left, expr->left->ftype,
421 if (IS_AST_OP(expr) && expr->opval.op==CAST &&
422 IS_AST_OP(expr->right) && expr->right->opval.op=='&') {
423 if (compareType(toType, expr->left->ftype)!=1) {
424 werror (W_INIT_WRONG);
425 printFromToType(expr->left->ftype, toType);
431 /* no then we have to do these cludgy checks */
432 /* pointers can be initialized with address of
433 a variable or address of an array element */
434 if (IS_AST_OP (expr) && expr->opval.op == '&') {
435 /* address of symbol */
436 if (IS_AST_SYM_VALUE (expr->left)) {
437 val = copyValue (AST_VALUE (expr->left));
438 val->type = newLink (DECLARATOR);
439 if(SPEC_SCLS (expr->left->etype) == S_CODE) {
440 DCL_TYPE (val->type) = CPOINTER;
441 DCL_PTR_CONST (val->type) = port->mem.code_ro;
443 else if (SPEC_SCLS (expr->left->etype) == S_XDATA)
444 DCL_TYPE (val->type) = FPOINTER;
445 else if (SPEC_SCLS (expr->left->etype) == S_XSTACK)
446 DCL_TYPE (val->type) = PPOINTER;
447 else if (SPEC_SCLS (expr->left->etype) == S_IDATA)
448 DCL_TYPE (val->type) = IPOINTER;
449 else if (SPEC_SCLS (expr->left->etype) == S_EEPROM)
450 DCL_TYPE (val->type) = EEPPOINTER;
452 DCL_TYPE (val->type) = POINTER;
454 val->type->next = expr->left->ftype;
455 val->etype = getSpec (val->type);
459 /* if address of indexed array */
460 if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
461 return valForArray (expr->left);
463 /* if address of structure element then
465 if (IS_AST_OP (expr->left) &&
466 expr->left->opval.op == '.') {
467 return valForStructElem (expr->left->left,
472 (&some_struct)->element */
473 if (IS_AST_OP (expr->left) &&
474 expr->left->opval.op == PTR_OP &&
475 IS_ADDRESS_OF_OP (expr->left->left)) {
476 return valForStructElem (expr->left->left->left,
480 /* case 3. (((char *) &a) +/- constant) */
481 if (IS_AST_OP (expr) &&
482 (expr->opval.op == '+' || expr->opval.op == '-') &&
483 IS_AST_OP (expr->left) && expr->left->opval.op == CAST &&
484 IS_AST_OP (expr->left->right) &&
485 expr->left->right->opval.op == '&' &&
486 IS_AST_LIT_VALUE (expr->right)) {
488 return valForCastAggr (expr->left->right->left,
489 expr->left->left->opval.lnk,
490 expr->right, expr->opval.op);
493 /* case 4. (char *)(array type) */
494 if (IS_CAST_OP(expr) && IS_AST_SYM_VALUE (expr->right) &&
495 IS_ARRAY(expr->right->ftype)) {
497 val = copyValue (AST_VALUE (expr->right));
498 val->type = newLink (DECLARATOR);
499 if (SPEC_SCLS (expr->right->etype) == S_CODE) {
500 DCL_TYPE (val->type) = CPOINTER;
501 DCL_PTR_CONST (val->type) = port->mem.code_ro;
503 else if (SPEC_SCLS (expr->right->etype) == S_XDATA)
504 DCL_TYPE (val->type) = FPOINTER;
505 else if (SPEC_SCLS (expr->right->etype) == S_XSTACK)
506 DCL_TYPE (val->type) = PPOINTER;
507 else if (SPEC_SCLS (expr->right->etype) == S_IDATA)
508 DCL_TYPE (val->type) = IPOINTER;
509 else if (SPEC_SCLS (expr->right->etype) == S_EEPROM)
510 DCL_TYPE (val->type) = EEPPOINTER;
512 DCL_TYPE (val->type) = POINTER;
513 val->type->next = expr->right->ftype->next;
514 val->etype = getSpec (val->type);
520 werrorfl (expr->filename, expr->lineno, E_INCOMPAT_PTYPES);
522 werror (E_INCOMPAT_PTYPES);
528 /*-----------------------------------------------------------------*/
529 /* printPointerType - generates ival for pointer type */
530 /*-----------------------------------------------------------------*/
531 void _pic16_printPointerType (const char *name, char ptype, void *p)
535 sprintf(buf, "LOW(%s)", name);
536 pic16_emitDS(buf, ptype, p);
537 sprintf(buf, "HIGH(%s)", name);
538 pic16_emitDS(buf, ptype, p);
541 /*-----------------------------------------------------------------*/
542 /* printPointerType - generates ival for pointer type */
543 /*-----------------------------------------------------------------*/
544 void pic16_printPointerType (const char *name, char ptype, void *p)
546 _pic16_printPointerType (name, ptype, p);
547 //pic16_flushDB(ptype, p); /* breaks char* const arr[] = {&c, &c, &c}; */
550 /*-----------------------------------------------------------------*/
551 /* printGPointerType - generates ival for generic pointer type */
552 /*-----------------------------------------------------------------*/
553 void pic16_printGPointerType (const char *iname, const unsigned int itype,
558 _pic16_printPointerType (iname, ptype, p);
566 sprintf(buf, "UPPER(%s)", iname);
567 pic16_emitDS(buf, ptype, p);
571 sprintf(buf, "0x80");
572 pic16_emitDS(buf, ptype, p);
575 debugf("itype = %d\n", itype );
579 //pic16_flushDB(ptype, p); /* might break char* const arr[] = {...}; */
583 /* set to 0 to disable debug messages */
584 #define DEBUG_PRINTIVAL 0
586 /*-----------------------------------------------------------------*/
587 /* pic16_printIvalType - generates ival for int/char */
588 /*-----------------------------------------------------------------*/
590 pic16_printIvalType (symbol *sym, sym_link * type, initList * ilist, char ptype, void *p)
594 // fprintf(stderr, "%s for symbol %s\n",__FUNCTION__, sym->rname);
597 fprintf(stderr, "%s\n",__FUNCTION__);
601 /* if initList is deep */
602 if (ilist && ilist->type == INIT_DEEP)
603 ilist = ilist->init.deep;
605 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
606 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
609 if (!(val = list2val (ilist))) {
610 // assuming a warning has been thrown
614 if (val->type != type) {
615 val = valCastLiteral(type, floatFromVal(val));
618 switch (getSize (type)) {
620 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
624 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
625 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
628 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
629 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
630 pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
632 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
633 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
634 pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
635 pic16_emitDB(pic16aopLiteral(val, 3), ptype, p);
640 /*--------------------------------------------------------------------*/
641 /* pic16_printIvalChar - generates initital value for character array */
642 /*--------------------------------------------------------------------*/
644 pic16_printIvalChar (symbol *sym, sym_link * type, initList * ilist, char *s, char ptype, void *p)
647 int remain, len, ilen;
653 fprintf(stderr, "%s\n",__FUNCTION__);
657 val = list2val (ilist);
659 /* if the value is a character string */
660 if(IS_ARRAY (val->type) && IS_CHAR (val->etype)) {
661 /* length of initializer string (might contain \0, so do not use strlen) */
662 ilen = DCL_ELEM(val->type);
665 DCL_ELEM (type) = ilen;
667 /* len is 0 if declartion equals initializer,
668 * >0 if declaration greater than initializer
669 * <0 if declaration less than initializer
670 * Strategy: if >0 emit 0x00 for the rest of the length,
671 * if <0 then emit only the length of declaration elements
674 len = DCL_ELEM (type) - ilen;
676 // fprintf(stderr, "%s:%d ilen = %i len = %i DCL_ELEM(type) = %i SPEC_CVAL-len = %i\n", __FILE__, __LINE__,
677 // ilen, len, DCL_ELEM(type), strlen(SPEC_CVAL(val->etype).v_char));
680 /* emit initializer */
681 for(remain=0; remain<ilen; remain++)
682 pic16_emitDB(SPEC_CVAL(val->etype).v_char[ remain ], ptype, p);
684 /* fill array with 0x00 */
686 pic16_emitDB(0x00, ptype, p);
689 werror (W_EXCESS_INITIALIZERS, "array of chars", sym->name, sym->lineDef);
691 for(remain=0; remain<DCL_ELEM (type); remain++)
692 pic16_emitDB(SPEC_CVAL(val->etype).v_char[ remain ], ptype, p);
696 // if((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0) {
701 for(remain=0; remain<strlen(s); remain++) {
702 pic16_emitDB(s[remain], ptype, p);
708 /*-----------------------------------------------------------------*/
709 /* pic16_printIvalArray - generates code for array initialization */
710 /*-----------------------------------------------------------------*/
712 pic16_printIvalArray (symbol * sym, sym_link * type, initList * ilist,
716 int lcnt = 0, size = 0;
723 fprintf(stderr, "%s\n",__FUNCTION__);
725 /* take care of the special case */
726 /* array of characters can be init */
728 if (IS_CHAR (type->next)) {
729 if (!IS_LITERAL(list2val(ilist)->etype)) {
730 werror (W_INIT_WRONG);
734 if(pic16_printIvalChar (sym, type,
735 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
736 SPEC_CVAL (sym->etype).v_char, ptype, p))
739 /* not the special case */
740 if (ilist && ilist->type != INIT_DEEP)
742 werror (E_INIT_STRUCT, sym->name);
746 iloop = ilist->init.deep;
747 lcnt = DCL_ELEM (type);
752 pic16_printIval (sym, type->next, iloop, ptype, p);
753 iloop = (iloop ? iloop->next : NULL);
756 /* if not array limits given & we */
757 /* are out of initialisers then */
758 if (!DCL_ELEM (type) && !iloop)
761 /* no of elements given and we */
762 /* have generated for all of them */
764 /* if initializers left */
766 werror (W_EXCESS_INITIALIZERS, "array", sym->name, sym->lineDef);
772 /* if we have not been given a size */
773 if (!DCL_ELEM (type))
774 DCL_ELEM (type) = size;
779 /*-----------------------------------------------------------------*/
780 /* pic16_printIvalBitFields - generate initializer for bitfields */
781 /*-----------------------------------------------------------------*/
782 void pic16_printIvalBitFields(symbol **sym, initList **ilist, char ptype, void *p)
786 initList *lilist = *ilist ;
787 unsigned long ival = 0;
792 fprintf(stderr, "%s\n",__FUNCTION__);
798 val = list2val(lilist);
800 if (SPEC_BLEN(lsym->etype) > 8) {
801 size += ((SPEC_BLEN (lsym->etype) / 8) +
802 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
805 size = ((SPEC_BLEN (lsym->etype) / 8) +
806 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
808 i = (unsigned long)floatFromVal(val);
809 i <<= SPEC_BSTR (lsym->etype);
811 if (! ( lsym->next &&
812 (IS_BITFIELD(lsym->next->type)) &&
813 (SPEC_BSTR(lsym->next->etype)))) break;
815 lilist = lilist->next;
819 pic16_emitDB(BYTE_IN_LONG(ival, 0), ptype, p);
823 pic16_emitDB(BYTE_IN_LONG(ival, 0), ptype, p);
824 pic16_emitDB(BYTE_IN_LONG(ival, 1), ptype, p);
827 case 4: /* EEP: why is this db and not dw? */
828 pic16_emitDB(BYTE_IN_LONG(ival, 0), ptype, p);
829 pic16_emitDB(BYTE_IN_LONG(ival, 1), ptype, p);
830 pic16_emitDB(BYTE_IN_LONG(ival, 2), ptype, p);
831 pic16_emitDB(BYTE_IN_LONG(ival, 3), ptype, p);
834 /* VR - only 1,2,4 size long can be handled???? Why? */
835 fprintf(stderr, "%s:%d: unhandled case. Contact author.\n", __FILE__, __LINE__);
843 /*-----------------------------------------------------------------*/
844 /* printIvalStruct - generates initial value for structures */
845 /*-----------------------------------------------------------------*/
846 void pic16_printIvalStruct (symbol * sym, sym_link * type,
847 initList * ilist, char ptype, void *p)
850 initList *iloop = NULL;
854 fprintf(stderr, "%s\n",__FUNCTION__);
857 sflds = SPEC_STRUCT (type)->fields;
860 if (ilist->type != INIT_DEEP) {
861 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
865 iloop = ilist->init.deep;
868 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
869 // fprintf(stderr, "%s:%d sflds: %p\tiloop = %p\n", __FILE__, __LINE__, sflds, iloop);
870 if (IS_BITFIELD(sflds->type)) {
871 pic16_printIvalBitFields(&sflds, &iloop, ptype, p);
873 pic16_printIval (sym, sflds->type, iloop, ptype, p);
877 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
882 /*--------------------------------------------------------------------------*/
883 /* pic16_printIvalCharPtr - generates initial values for character pointers */
884 /*--------------------------------------------------------------------------*/
885 int pic16_printIvalCharPtr (symbol * sym, sym_link * type, value * val, char ptype, void *p)
889 /* PENDING: this is _very_ mcs51 specific, including a magic
891 It's also endin specific.
893 VR - Attempting to port this function to pic16 port - 8-Jun-2004
898 fprintf(stderr, "%s\n",__FUNCTION__);
901 size = getSize (type);
903 if (val->name && strlen (val->name))
905 if (size == 1) /* This appears to be Z80 specific?? */
907 pic16_emitDS(val->name, ptype, p);
911 pic16_printPointerType (val->name, ptype, p);
916 if (IS_PTR (val->type)) {
917 type = DCL_TYPE (val->type);
919 type = PTR_TYPE (SPEC_OCLS (val->etype));
921 if (val->sym && val->sym->isstrlit) {
922 // this is a literal string
925 pic16_printGPointerType(val->name, type, ptype, p);
929 fprintf (stderr, "*** internal error: unknown size in "
930 "printIvalCharPtr.\n");
936 // these are literals assigned to pointers
940 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
943 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
944 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
947 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
948 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
949 pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
957 if (val->sym && val->sym->isstrlit) { // && !isinSet(statsg->syms, val->sym)) {
958 if(ptype == 'p' && !isinSet(statsg->syms, val->sym))addSet (&statsg->syms, val->sym);
959 else if(ptype == 'f' /*&& !isinSet(rel_idataSymSet, val->sym)*/)addSet(&rel_idataSymSet, val->sym);
965 /*-----------------------------------------------------------------------*/
966 /* pic16_printIvalFuncPtr - generate initial value for function pointers */
967 /*-----------------------------------------------------------------------*/
968 void pic16_printIvalFuncPtr (sym_link * type, initList * ilist, char ptype, void *p)
975 fprintf(stderr, "%s\n",__FUNCTION__);
979 val = list2val (ilist);
981 val = valCastLiteral(type, 0.0);
984 // an error has been thrown already
988 if (IS_LITERAL(val->etype)) {
989 if (compareType(type, val->etype) == 0) {
990 werrorfl (ilist->filename, ilist->lineno, E_INCOMPAT_TYPES);
991 printFromToType (val->type, type);
993 pic16_printIvalCharPtr (NULL, type, val, ptype, p);
997 /* check the types */
998 if ((dLvl = compareType (val->type, type->next)) <= 0)
1000 pic16_emitDB(0x00, ptype, p);
1004 /* now generate the name */
1006 pic16_printGPointerType (val->name, DCL_TYPE(val->type), ptype, p);
1008 pic16_printGPointerType (val->sym->rname, DCL_TYPE(val->type), ptype, p);
1010 if(IS_FUNC(val->sym->type) && !val->sym->used && !IS_STATIC(val->sym->etype)) {
1012 if(!checkSym(publics, val->sym))
1013 if(checkAddSym(&externs, val->sym) && (ptype == 'f')) {
1014 /* this has not been declared as extern
1015 * so declare it as a 'late extern' just after the symbol */
1016 fprintf((FILE *)p, ";\tdeclare symbol as extern\n");
1017 fprintf((FILE *)p, "\textern\t%s\n", val->sym->rname);
1018 fprintf((FILE *)p, ";\tcontinue variable declaration\n");
1027 /*-----------------------------------------------------------------*/
1028 /* pic16_printIvalPtr - generates initial value for pointers */
1029 /*-----------------------------------------------------------------*/
1030 void pic16_printIvalPtr (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p)
1036 fprintf(stderr, "%s:%d initialising pointer: %s size: %d\n", __FILE__, __LINE__,
1037 sym->rname, getSize(sym->type));
1041 if (ilist && (ilist->type == INIT_DEEP))
1042 ilist = ilist->init.deep;
1044 /* function pointer */
1045 if (IS_FUNC (type->next))
1047 pic16_printIvalFuncPtr (type, ilist, ptype, p);
1051 if (!(val = pic16_initPointer (ilist, type)))
1054 /* if character pointer */
1055 if (IS_CHAR (type->next))
1056 if (pic16_printIvalCharPtr (sym, type, val, ptype, p))
1059 /* check the type */
1060 if (compareType (type, val->type) == 0) {
1061 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
1062 printFromToType (val->type, type);
1065 /* if val is literal */
1066 if (IS_LITERAL (val->etype))
1068 switch (getSize (type))
1071 pic16_emitDB((unsigned int)floatFromVal(val) & 0xff, ptype, p);
1074 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
1075 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
1078 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
1079 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
1080 pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
1083 fprintf(stderr, "%s:%d size = %d\n", __FILE__, __LINE__, getSize(type));
1090 size = getSize (type);
1092 if (size == 1) /* Z80 specific?? */
1094 pic16_emitDS(val->name, ptype, p);
1098 pic16_printPointerType (val->name, ptype, p);
1102 pic16_printGPointerType (val->name, (IS_PTR(type)?DCL_TYPE(type):PTR_TYPE(SPEC_OCLS(sym->etype))),
1111 /*-----------------------------------------------------------------*/
1112 /* pic16_printIval - generates code for initial value */
1113 /*-----------------------------------------------------------------*/
1114 void pic16_printIval (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p)
1122 fprintf(stderr, "%s:%d generating init for %s\n", __FILE__, __LINE__, sym->name);
1123 fprintf(stderr, "%s: IS_STRUCT: %d IS_ARRAY: %d IS_PTR: %d IS_SPEC: %d\n", sym->name,
1124 IS_STRUCT(type), IS_ARRAY(type), IS_PTR(type), IS_SPEC(type));
1127 /* if structure then */
1128 if (IS_STRUCT (type))
1130 // fprintf(stderr,"%s struct\n",__FUNCTION__);
1131 pic16_printIvalStruct (sym, type, ilist, ptype, p);
1135 /* if this is an array */
1136 if (IS_ARRAY (type))
1138 // fprintf(stderr,"%s array\n",__FUNCTION__);
1139 pic16_printIvalArray (sym, type, ilist, ptype, p);
1146 // not an aggregate, ilist must be a node
1147 if (ilist->type!=INIT_NODE) {
1148 // or a 1-element list
1149 if (ilist->init.deep->next) {
1150 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar",
1153 ilist=ilist->init.deep;
1158 // and the type must match
1159 itype=ilist->init.node->ftype;
1161 if (compareType(type, itype)==0) {
1162 // special case for literal strings
1163 if (IS_ARRAY (itype) && IS_CHAR (getSpec(itype)) &&
1164 // which are really code pointers
1165 IS_PTR(type) && DCL_TYPE(type)==CPOINTER) {
1168 // werrorfl (ilist->filename, ilist->lineno, E_TYPE_MISMATCH, "assignment", " ");
1169 // printFromToType(itype, type);
1176 /* if this is a pointer */
1179 // fprintf(stderr,"%s pointer\n",__FUNCTION__);
1180 pic16_printIvalPtr (sym, type, ilist, ptype, p);
1185 /* if type is SPECIFIER */
1188 // fprintf(stderr,"%s spec\n",__FUNCTION__);
1189 pic16_printIvalType (sym, type, ilist, ptype, p);
1194 int PIC16_IS_CONFIG_ADDRESS(int address)
1196 return ((address >= pic16->cwInfo.confAddrStart && address <= pic16->cwInfo.confAddrEnd));
1199 int PIC16_IS_IDLOC_ADDRESS(int address)
1201 return ((address >= pic16->idInfo.idAddrStart && address <= pic16->idInfo.idAddrEnd));
1204 /* wrapper function for the above */
1205 int PIC16_IS_HWREG_ADDRESS(int address)
1207 return (PIC16_IS_CONFIG_ADDRESS(address) || PIC16_IS_IDLOC_ADDRESS(address));
1211 /*-----------------------------------------------------------------*/
1212 /* emitStaticSeg - emitcode for the static segment */
1213 /*-----------------------------------------------------------------*/
1215 pic16emitStaticSeg (memmap * map)
1218 static int didcode=0;
1220 //fprintf(stderr, "%s\n",__FUNCTION__);
1224 /* for all variables in this segment do */
1225 for (sym = setFirstItem (map->syms); sym;
1226 sym = setNextItem (map->syms))
1230 fprintf(stderr, "%s\t%s: sym: %s\tused: %d\tSPEC_ABSA: %d\tSPEC_AGGREGATE: %d\tCODE: %d\n\
1231 CODESPACE: %d\tCONST: %d\tPTRCONST: %d\tSPEC_CONST: %d\n", __FUNCTION__,
1232 map->sname, sym->name, sym->used, SPEC_ABSA(sym->etype), IS_AGGREGATE(sym->type),
1233 IS_CODE(sym->etype), IN_CODESPACE( SPEC_OCLS(sym->etype)), IS_CONSTANT(sym->etype),
1234 IS_PTR_CONST(sym->etype), SPEC_CONST(sym->etype));
1235 printTypeChain( sym->type, stderr );
1236 fprintf(stderr, "\n");
1239 if(SPEC_ABSA(sym->etype) && PIC16_IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype))) {
1240 pic16_assignConfigWordValue(SPEC_ADDR(sym->etype),
1241 (int) floatFromVal(list2val(sym->ival)));
1246 if(SPEC_ABSA(sym->etype) && PIC16_IS_IDLOC_ADDRESS(SPEC_ADDR(sym->etype))) {
1247 pic16_assignIdByteValue(SPEC_ADDR(sym->etype),
1248 (char) floatFromVal(list2val(sym->ival)));
1253 /* if it is "extern" then do nothing */
1254 if (IS_EXTERN (sym->etype)/* && !SPEC_ABSA(sym->etype)*/) {
1255 checkAddSym(&externs, sym);
1259 /* if it is not static add it to the public
1261 if (!IS_STATIC (sym->etype)) {
1262 /* do not emit if it is a config word declaration */
1263 checkAddSym(&publics, sym);
1266 /* print extra debug info if required */
1267 if (options.debug || sym->level == 0) {
1268 /* NOTE to me - cdbFile may be null in which case,
1269 * the sym name will be printed to stdout. oh well */
1270 debugFile->writeSymbol(sym);
1273 /* if it has an absolute address */
1274 if (SPEC_ABSA (sym->etype)) {
1275 // fprintf(stderr, "%s:%d spec_absa is true for symbol: %s\n",
1276 // __FILE__, __LINE__, sym->name);
1278 /* if it has an initial value */
1286 /* symbol has absolute address and initial value */
1288 resolveIvalSym (sym->ival, sym->type);
1289 asym = newSymbol(sym->rname, 0);
1290 abSym = Safe_calloc(1, sizeof(absSym));
1291 strcpy(abSym->name, sym->rname);
1292 abSym->address = SPEC_ADDR( sym->etype );
1293 addSet(&absSymSet, abSym);
1295 pb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute Ival"));
1296 pic16_addpBlock(pb);
1298 pcf = pic16_newpCodeFunction(moduleName, asym->name);
1299 PCF(pcf)->absblock = 1;
1301 pic16_addpCode2pBlock(pb,pcf);
1302 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
1303 //fprintf(stderr, "%s:%d [1] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1304 pic16_printIval(sym, sym->type, sym->ival, 'p', (void *)pb);
1305 pic16_flushDB('p', (void *)pb);
1307 pic16_addpCode2pBlock(pb, pic16_newpCodeFunction(NULL, NULL));
1313 /* symbol has absolute address but no initial value */
1315 /* allocate space */
1316 fprintf (code->oFile, "%s:\n", sym->rname);
1318 /* special case for character strings */
1319 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1320 SPEC_CVAL (sym->etype).v_char) {
1322 // fprintf(stderr, "%s:%d printing code string from %s\n", __FILE__, __LINE__, sym->rname);
1324 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
1326 fprintf (stderr, "%s:%u(%s): do not know how to intialize symbol %s\n", __FILE__, __LINE__, __FUNCTION__, sym->rname);
1332 // fprintf(stderr, "%s:%d spec_absa is false for symbol: %s\n",
1333 // __FILE__, __LINE__, sym->name);
1336 /* if it has an initial value */
1340 /* symbol doesn't have absolute address but has initial value */
1341 fprintf (code->oFile, "%s:\n", sym->rname);
1343 resolveIvalSym (sym->ival, sym->type);
1345 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block for Ival"));
1346 pic16_addpBlock(pb);
1349 /* make sure that 'code' directive is emitted before, once */
1350 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir("code", NULL));
1355 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
1356 //fprintf(stderr, "%s:%d [2] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1357 pic16_printIval(sym, sym->type, sym->ival, 'p', (void *)pb);
1358 pic16_flushDB('p', (void *)pb);
1362 /* symbol doesn't have absolute address and no initial value */
1363 /* allocate space */
1364 // fprintf(stderr, "%s:%d [3] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1365 fprintf (code->oFile, "%s:\n", sym->rname);
1366 /* special case for character strings */
1367 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1368 SPEC_CVAL (sym->etype).v_char) {
1370 // fprintf(stderr, "%s:%d printing code string for %s\n", __FILE__, __LINE__, sym->rname);
1372 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
1383 /*-----------------------------------------------------------------*/
1384 /* pic16_emitConfigRegs - emits the configuration registers */
1385 /*-----------------------------------------------------------------*/
1386 void pic16_emitConfigRegs(FILE *of)
1390 for(i=0;i<pic16->cwInfo.confAddrEnd-pic16->cwInfo.confAddrStart;i++)
1391 if(pic16->cwInfo.crInfo[i].emit) //mask != -1)
1392 fprintf (of, "\t__config 0x%x, 0x%hhx\n",
1393 pic16->cwInfo.confAddrStart+i,
1394 pic16->cwInfo.crInfo[i].value);
1397 void pic16_emitIDRegs(FILE *of)
1401 for(i=0;i<pic16->idInfo.idAddrEnd-pic16->idInfo.idAddrStart;i++)
1402 if(pic16->idInfo.irInfo[i].emit)
1403 fprintf (of, "\t__idlocs 0x%06x, 0x%hhx\n",
1404 pic16->idInfo.idAddrStart+i,
1405 pic16->idInfo.irInfo[i].value);
1412 /* no special considerations for the following
1413 data, idata & bit & xdata */
1414 pic16emitRegularMap (data, TRUE, TRUE);
1415 pic16emitRegularMap (idata, TRUE, TRUE);
1416 pic16emitRegularMap (bit, TRUE, FALSE);
1417 pic16emitRegularMap (xdata, TRUE, TRUE);
1418 pic16emitRegularMap (sfr, FALSE, FALSE);
1419 pic16emitRegularMap (sfrbit, FALSE, FALSE);
1420 pic16emitRegularMap (code, TRUE, FALSE);
1421 pic16emitStaticSeg (statsg);
1424 /*-----------------------------------------------------------------*/
1425 /* createInterruptVect - creates the interrupt vector */
1426 /*-----------------------------------------------------------------*/
1428 pic16createInterruptVect (FILE * vFile)
1430 /* if the main is only a prototype ie. no body then do nothing */
1432 if (!IFFUNC_HASBODY(mainf->type)) {
1433 /* if ! compile only then main function should be present */
1434 if (!options.cc_only)
1440 if((!pic16_options.omit_ivt) || (pic16_options.omit_ivt && pic16_options.leave_reset)) {
1441 fprintf (vFile, ";\t.area\t%s\n", CODE_NAME);
1442 fprintf(vFile, ".intvecs\tcode\t0x%06x\n", pic16_options.ivt_loc);
1444 /* this is an overkill since WE are the port,
1445 * and we know if we have a genIVT function! */
1447 port->genIVT(vFile, interrupts, maxInterrupts);
1455 /*-----------------------------------------------------------------*/
1456 /* pic16initialComments - puts in some initial comments */
1457 /*-----------------------------------------------------------------*/
1459 pic16initialComments (FILE * afile)
1461 initialComments (afile);
1462 fprintf (afile, "; PIC16 port for the Microchip 16-bit core micros\n");
1463 if(pic16_mplab_comp)
1464 fprintf(afile, "; MPLAB/MPASM/MPASMWIN/MPLINK compatibility mode enabled\n");
1465 fprintf (afile, iComments2);
1468 fprintf (afile, "\n\t.ident \"SDCC version %s #%s [pic16 port]\"\n",
1469 SDCC_VERSION_STR, getBuildNumber() );
1473 /*-----------------------------------------------------------------*/
1474 /* printPublics - generates global declarations for publics */
1475 /*-----------------------------------------------------------------*/
1477 pic16printPublics (FILE *afile)
1481 fprintf (afile, "\n%s", iComments2);
1482 fprintf (afile, "; public variables in this module\n");
1483 fprintf (afile, "%s", iComments2);
1485 for(sym = setFirstItem (publics); sym; sym = setNextItem (publics))
1487 if(!IS_STATIC(sym->etype))
1488 fprintf(afile, "\tglobal %s\n", sym->rname);
1491 /*-----------------------------------------------------------------*/
1492 /* printExterns - generates extern declarations for externs */
1493 /*-----------------------------------------------------------------*/
1495 pic16_printExterns(FILE *afile)
1499 /* print nothing if no externs to declare */
1500 if(!elementsInSet(externs) && !elementsInSet(pic16_builtin_functions))
1503 fprintf(afile, "\n%s", iComments2);
1504 fprintf(afile, "; extern variables in this module\n");
1505 fprintf(afile, "%s", iComments2);
1507 for(sym = setFirstItem(externs); sym; sym = setNextItem(externs))
1508 fprintf(afile, "\textern %s\n", sym->rname);
1510 for(sym = setFirstItem(pic16_builtin_functions); sym; sym = setNextItem(pic16_builtin_functions))
1511 fprintf(afile, "\textern _%s\n", sym->name);
1514 /*-----------------------------------------------------------------*/
1515 /* emitOverlay - will emit code for the overlay stuff */
1516 /*-----------------------------------------------------------------*/
1518 pic16emitOverlay (FILE * afile)
1522 if (!elementsInSet (ovrSetSets))
1523 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);
1525 /* for each of the sets in the overlay segment do */
1526 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1527 ovrset = setNextItem (ovrSetSets))
1532 if (elementsInSet (ovrset))
1534 /* this dummy area is used to fool the assembler
1535 otherwise the assembler will append each of these
1536 declarations into one chunk and will not overlay
1538 fprintf (afile, ";\t.area _DUMMY\n");
1539 /* output the area informtion */
1540 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1543 for (sym = setFirstItem (ovrset); sym;
1544 sym = setNextItem (ovrset))
1547 /* if extern then do nothing */
1548 if (IS_EXTERN (sym->etype))
1551 /* if allocation required check is needed
1552 then check if the symbol really requires
1553 allocation only for local variables */
1554 if (!IS_AGGREGATE (sym->type) &&
1555 !(sym->_isparm && !IS_REGPARM (sym->etype))
1556 && !sym->allocreq && sym->level)
1559 /* if global variable & not static or extern
1560 and addPublics allowed then add it to the public set */
1561 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1562 && !IS_STATIC (sym->etype)) {
1563 // fprintf(stderr, "%s:%d %s accessed\n", __FILE__, __LINE__, __FUNCTION__);
1564 checkAddSym(&publics, sym);
1565 // addSetHead (&publics, sym);
1568 /* if extern then do nothing or is a function
1570 if (IS_FUNC (sym->type))
1574 /* if is has an absolute address then generate
1575 an equate for this no need to allocate space */
1576 if (SPEC_ABSA (sym->etype))
1579 if (options.debug || sym->level == 0)
1580 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1582 fprintf (afile, "%s\t=\t0x%04x\n",
1584 SPEC_ADDR (sym->etype));
1588 if (options.debug || sym->level == 0)
1589 fprintf (afile, "==.\n");
1591 /* allocate space */
1592 fprintf (afile, "%s:\n", sym->rname);
1593 fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1600 void emitStatistics(FILE *asmFile)
1602 unsigned long isize, udsize, ramsize;
1603 statistics.isize = pic16_countInstructions();
1604 isize = (statistics.isize >= 0) ? statistics.isize : 0;
1605 udsize = (statistics.udsize >= 0) ? statistics.udsize : 0;
1606 ramsize = pic16 ? pic16->RAMsize : 0x200;
1607 ramsize -= 256; /* ignore access bank and SFRs */
1608 if (ramsize == 0) ramsize = 64; /* prevent division by zero (below) */
1610 fprintf (asmFile, "\n\n; Statistics:\n");
1611 fprintf (asmFile, "; code size:\t%5ld (0x%04lx) bytes (%5.2f%%)\n; \t%5ld (0x%04lx) words\n",
1612 isize, isize, (isize*100.0)/(128UL << 10),
1613 isize>>1, isize>>1);
1614 fprintf (asmFile, "; udata size:\t%5ld (0x%04lx) bytes (%5.2f%%)\n",
1615 udsize, udsize, (udsize*100.0) / (1.0 * ramsize));
1616 fprintf (asmFile, "; access size:\t%5ld (0x%04lx) bytes\n",
1617 statistics.intsize, statistics.intsize);
1619 fprintf (asmFile, "\n\n");
1624 /*-----------------------------------------------------------------*/
1625 /* glue - the final glue that hold the whole thing together */
1626 /*-----------------------------------------------------------------*/
1632 FILE *ovrFile = tempfile();
1634 mainf = newSymbol ("main", 0);
1637 mainf = findSymWithLevel(SymbolTab, mainf);
1639 addSetHead(&tmpfileSet,ovrFile);
1640 pic16_pCodeInitRegisters();
1642 if(pic16_options.no_crt && mainf && IFFUNC_HASBODY(mainf->type)) {
1643 pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
1645 pic16_addpBlock(pb);
1647 /* entry point @ start of CSEG */
1648 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup",-1));
1651 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1652 pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("_stack_end"))));
1653 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1654 pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("_stack_end"))));
1657 /* put in the call to main */
1658 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
1660 if (options.mainreturn) {
1661 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
1662 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
1664 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
1665 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
1669 /* At this point we've got all the code in the form of pCode structures */
1670 /* Now it needs to be rearranged into the order it should be placed in the */
1673 pic16_movepBlock2Head('P'); // Last
1674 pic16_movepBlock2Head(code->dbName);
1675 pic16_movepBlock2Head('X');
1676 pic16_movepBlock2Head(statsg->dbName); // First
1678 /* print the global struct definitions */
1681 /* PENDING: this isnt the best place but it will do */
1682 if (port->general.glue_up_main) {
1683 /* create the interrupt vector table */
1684 pic16createInterruptVect (vFile);
1687 addSetHead(&tmpfileSet,vFile);
1689 /* emit code for the all the variables declared */
1692 /* do the overlay segments */
1693 pic16emitOverlay(ovrFile);
1694 pic16_AnalyzepCode('*');
1697 if(pic16_options.dumpcalltree) {
1700 sprintf(buffer, dstFileName);
1701 strcat(buffer, ".calltree");
1702 cFile = fopen(buffer, "w");
1703 pic16_printCallTree( cFile );
1708 pic16_InlinepCode();
1709 pic16_AnalyzepCode('*');
1712 if(pic16_debug_verbose)
1715 /* now put it all together into the assembler file */
1716 /* create the assembler file name */
1717 if((noAssemble || options.c1mode) && fullDstFileName) {
1718 sprintf (buffer, fullDstFileName);
1720 sprintf (buffer, dstFileName);
1721 strcat (buffer, ".asm");
1724 if(!(asmFile = fopen (buffer, "w"))) {
1725 werror (E_FILE_OPEN_ERR, buffer);
1729 /* initial comments */
1730 pic16initialComments (asmFile);
1732 /* print module name */
1734 fprintf(asmFile, "\t.file\t\"%s\"\n", fullSrcFileName);
1736 /* Let the port generate any global directives, etc. */
1737 if(port->genAssemblerPreamble) {
1738 port->genAssemblerPreamble(asmFile);
1741 /* Put all variables into a cblock */
1742 pic16_AnalyzeBanking();
1745 if(pic16_options.opt_flags & OF_LR_SUPPORT) {
1746 pic16_OptimizeLocalRegs();
1750 /* remove redundant BANKSELs -- added by RN 2005-01-17 */
1751 if(pic16_options.opt_banksel > 1) {
1752 pic16_OptimizeBanksel();
1755 /* turn GOTOs into BRAs -- added by RN 2004-11-16 */
1756 if(pic16_options.opt_flags & OF_OPTIMIZE_GOTO) {
1757 pic16_OptimizeJumps();
1760 /* print the extern variables to this module */
1761 pic16_printExterns(asmFile);
1763 /* print the global variables in this module */
1764 pic16printPublics (asmFile);
1766 pic16_writeUsedRegs(asmFile);
1769 /* no xdata in pic */
1770 /* if external stack then reserve space of it */
1771 if(mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1772 fprintf (asmFile, "%s", iComments2);
1773 fprintf (asmFile, "; external stack \n");
1774 fprintf (asmFile, "%s", iComments2);
1775 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1776 fprintf (asmFile,";\t.ds 256\n");
1781 /* no xdata in pic */
1782 /* copy xtern ram data */
1783 fprintf (asmFile, "%s", iComments2);
1784 fprintf (asmFile, "; external ram data\n");
1785 fprintf (asmFile, "%s", iComments2);
1786 copyFile (asmFile, xdata->oFile);
1790 /* copy the bit segment */
1791 fprintf (asmFile, "%s", iComments2);
1792 fprintf (asmFile, "; bit data\n");
1793 fprintf (asmFile, "%s", iComments2);
1794 copyFile (asmFile, bit->oFile);
1797 /* copy the interrupt vector table */
1798 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1799 fprintf (asmFile, "\n%s", iComments2);
1800 fprintf (asmFile, "; interrupt vector \n");
1801 fprintf (asmFile, "%s", iComments2);
1802 copyFile (asmFile, vFile);
1805 /* copy global & static initialisations */
1806 fprintf (asmFile, "\n%s", iComments2);
1807 fprintf (asmFile, "; global & static initialisations\n");
1808 fprintf (asmFile, "%s", iComments2);
1810 if(pic16_debug_verbose)
1811 fprintf(asmFile, "; A code from now on!\n");
1813 pic16_copypCode(asmFile, 'A');
1815 if(pic16_options.no_crt) {
1816 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1817 fprintf(asmFile, "\tcode\n");
1818 fprintf(asmFile,"__sdcc_gsinit_startup:\n");
1822 // copyFile (stderr, code->oFile);
1824 fprintf(asmFile, "; I code from now on!\n");
1825 pic16_copypCode(asmFile, 'I');
1827 if(pic16_debug_verbose)
1828 fprintf(asmFile, "; dbName from now on!\n");
1830 pic16_copypCode(asmFile, statsg->dbName);
1832 if(pic16_options.no_crt) {
1833 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
1834 fprintf (asmFile,"\tgoto\t__sdcc_program_startup\n");
1838 if(pic16_debug_verbose)
1839 fprintf(asmFile, "; X code from now on!\n");
1841 pic16_copypCode(asmFile, 'X');
1843 if(pic16_debug_verbose)
1844 fprintf(asmFile, "; M code from now on!\n");
1846 pic16_copypCode(asmFile, 'M');
1848 pic16_copypCode(asmFile, code->dbName);
1850 pic16_copypCode(asmFile, 'P');
1852 emitStatistics(asmFile);
1854 fprintf (asmFile,"\tend\n");