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 (lilist && lilist->next) &&
813 (IS_BITFIELD(lsym->next->type)) &&
814 (SPEC_BSTR(lsym->next->etype)))) break;
816 lilist = lilist->next;
820 pic16_emitDB(BYTE_IN_LONG(ival, 0), ptype, p);
824 pic16_emitDB(BYTE_IN_LONG(ival, 0), ptype, p);
825 pic16_emitDB(BYTE_IN_LONG(ival, 1), ptype, p);
828 case 4: /* EEP: why is this db and not dw? */
829 pic16_emitDB(BYTE_IN_LONG(ival, 0), ptype, p);
830 pic16_emitDB(BYTE_IN_LONG(ival, 1), ptype, p);
831 pic16_emitDB(BYTE_IN_LONG(ival, 2), ptype, p);
832 pic16_emitDB(BYTE_IN_LONG(ival, 3), ptype, p);
835 /* VR - only 1,2,4 size long can be handled???? Why? */
836 fprintf(stderr, "%s:%d: unhandled case. Contact author.\n", __FILE__, __LINE__);
844 /*-----------------------------------------------------------------*/
845 /* printIvalStruct - generates initial value for structures */
846 /*-----------------------------------------------------------------*/
847 void pic16_printIvalStruct (symbol * sym, sym_link * type,
848 initList * ilist, char ptype, void *p)
851 initList *iloop = NULL;
855 fprintf(stderr, "%s\n",__FUNCTION__);
858 sflds = SPEC_STRUCT (type)->fields;
861 if (ilist->type != INIT_DEEP) {
862 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
866 iloop = ilist->init.deep;
869 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
870 // fprintf(stderr, "%s:%d sflds: %p\tiloop = %p\n", __FILE__, __LINE__, sflds, iloop);
871 if (IS_BITFIELD(sflds->type)) {
872 pic16_printIvalBitFields(&sflds, &iloop, ptype, p);
874 pic16_printIval (sym, sflds->type, iloop, ptype, p);
878 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
883 /*-----------------------------------------------------------------*/
884 /* printIvalUnion - generates initial value for unions */
885 /*-----------------------------------------------------------------*/
886 void pic16_printIvalUnion (symbol * sym, sym_link * type,
887 initList * ilist, char ptype, void *p)
890 initList *iloop = NULL;
895 fprintf(stderr, "%s\n",__FUNCTION__);
907 if (type) size = SPEC_STRUCT(type)->size;
909 if (i == 1 && size >= 0 && size <= sizeof(long))
911 unsigned long val = (unsigned long)floatFromVal(list2val(ilist));
914 pic16_emitDB(val, ptype, p);
920 fprintf( stderr, "INCOMPLETE SUPPORT FOR INITIALIZED union---FALLING BACK TO struct\n" );
921 fprintf( stderr, "This is a bug. Please file a bug-report with your source attached.\n" );
922 pic16_printIvalStruct( sym, type, ilist, ptype, p );
926 pic16_isUnion( symbol *sym, sym_link *type )
928 if (type && SPEC_STRUCT(type)->type == UNION) return 1;
932 /*--------------------------------------------------------------------------*/
933 /* pic16_printIvalCharPtr - generates initial values for character pointers */
934 /*--------------------------------------------------------------------------*/
935 int pic16_printIvalCharPtr (symbol * sym, sym_link * type, value * val, char ptype, void *p)
939 /* PENDING: this is _very_ mcs51 specific, including a magic
941 It's also endin specific.
943 VR - Attempting to port this function to pic16 port - 8-Jun-2004
948 fprintf(stderr, "%s\n",__FUNCTION__);
951 size = getSize (type);
953 if (val->name && strlen (val->name))
955 if (size == 1) /* This appears to be Z80 specific?? */
957 pic16_emitDS(val->name, ptype, p);
961 pic16_printPointerType (val->name, ptype, p);
966 if (IS_PTR (val->type)) {
967 type = DCL_TYPE (val->type);
969 type = PTR_TYPE (SPEC_OCLS (val->etype));
971 if (val->sym && val->sym->isstrlit) {
972 // this is a literal string
975 pic16_printGPointerType(val->name, type, ptype, p);
979 fprintf (stderr, "*** internal error: unknown size in "
980 "printIvalCharPtr.\n");
986 // these are literals assigned to pointers
990 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
993 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
994 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
997 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
998 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
999 pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
1007 if (val->sym && val->sym->isstrlit) { // && !isinSet(statsg->syms, val->sym)) {
1008 if(ptype == 'p' && !isinSet(statsg->syms, val->sym))addSet (&statsg->syms, val->sym);
1009 else if(ptype == 'f' /*&& !isinSet(rel_idataSymSet, val->sym)*/)addSet(&rel_idataSymSet, val->sym);
1015 /*-----------------------------------------------------------------------*/
1016 /* pic16_printIvalFuncPtr - generate initial value for function pointers */
1017 /*-----------------------------------------------------------------------*/
1018 void pic16_printIvalFuncPtr (sym_link * type, initList * ilist, char ptype, void *p)
1025 fprintf(stderr, "%s\n",__FUNCTION__);
1029 val = list2val (ilist);
1031 val = valCastLiteral(type, 0.0);
1034 // an error has been thrown already
1038 if (IS_LITERAL(val->etype)) {
1039 if (compareType(type, val->etype) == 0) {
1040 werrorfl (ilist->filename, ilist->lineno, E_INCOMPAT_TYPES);
1041 printFromToType (val->type, type);
1043 pic16_printIvalCharPtr (NULL, type, val, ptype, p);
1047 /* check the types */
1048 if ((dLvl = compareType (val->type, type->next)) <= 0)
1050 pic16_emitDB(0x00, ptype, p);
1054 /* now generate the name */
1056 pic16_printGPointerType (val->name, DCL_TYPE(val->type), ptype, p);
1058 pic16_printGPointerType (val->sym->rname, DCL_TYPE(val->type), ptype, p);
1060 if(IS_FUNC(val->sym->type) && !val->sym->used && !IS_STATIC(val->sym->etype)) {
1062 if(!checkSym(publics, val->sym))
1063 if(checkAddSym(&externs, val->sym) && (ptype == 'f')) {
1064 /* this has not been declared as extern
1065 * so declare it as a 'late extern' just after the symbol */
1066 fprintf((FILE *)p, ";\tdeclare symbol as extern\n");
1067 fprintf((FILE *)p, "\textern\t%s\n", val->sym->rname);
1068 fprintf((FILE *)p, ";\tcontinue variable declaration\n");
1077 /*-----------------------------------------------------------------*/
1078 /* pic16_printIvalPtr - generates initial value for pointers */
1079 /*-----------------------------------------------------------------*/
1080 void pic16_printIvalPtr (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p)
1086 fprintf(stderr, "%s:%d initialising pointer: %s size: %d\n", __FILE__, __LINE__,
1087 sym->rname, getSize(sym->type));
1091 if (ilist && (ilist->type == INIT_DEEP))
1092 ilist = ilist->init.deep;
1094 /* function pointer */
1095 if (IS_FUNC (type->next))
1097 pic16_printIvalFuncPtr (type, ilist, ptype, p);
1101 if (!(val = pic16_initPointer (ilist, type)))
1104 /* if character pointer */
1105 if (IS_CHAR (type->next))
1106 if (pic16_printIvalCharPtr (sym, type, val, ptype, p))
1109 /* check the type */
1110 if (compareType (type, val->type) == 0) {
1111 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
1112 printFromToType (val->type, type);
1115 /* if val is literal */
1116 if (IS_LITERAL (val->etype))
1118 switch (getSize (type))
1121 pic16_emitDB((unsigned int)floatFromVal(val) & 0xff, ptype, p);
1124 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
1125 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
1128 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
1129 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
1130 pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
1133 fprintf(stderr, "%s:%d size = %d\n", __FILE__, __LINE__, getSize(type));
1140 size = getSize (type);
1142 if (size == 1) /* Z80 specific?? */
1144 pic16_emitDS(val->name, ptype, p);
1148 pic16_printPointerType (val->name, ptype, p);
1152 pic16_printGPointerType (val->name, (IS_PTR(type)?DCL_TYPE(type):PTR_TYPE(SPEC_OCLS(sym->etype))),
1161 /*-----------------------------------------------------------------*/
1162 /* pic16_printIval - generates code for initial value */
1163 /*-----------------------------------------------------------------*/
1164 void pic16_printIval (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p)
1172 fprintf(stderr, "%s:%d generating init for %s\n", __FILE__, __LINE__, sym->name);
1173 fprintf(stderr, "%s: IS_STRUCT: %d IS_ARRAY: %d IS_PTR: %d IS_SPEC: %d\n", sym->name,
1174 IS_STRUCT(type), IS_ARRAY(type), IS_PTR(type), IS_SPEC(type));
1177 /* if structure then */
1178 if (IS_STRUCT (type))
1180 if (pic16_isUnion(sym, type))
1182 //fprintf(stderr,"%s union\n",__FUNCTION__);
1183 pic16_printIvalUnion (sym, type, ilist, ptype, p);
1185 //fprintf(stderr,"%s struct\n",__FUNCTION__);
1186 pic16_printIvalStruct (sym, type, ilist, ptype, p);
1191 /* if this is an array */
1192 if (IS_ARRAY (type))
1194 // fprintf(stderr,"%s array\n",__FUNCTION__);
1195 pic16_printIvalArray (sym, type, ilist, ptype, p);
1202 // not an aggregate, ilist must be a node
1203 if (ilist->type!=INIT_NODE) {
1204 // or a 1-element list
1205 if (ilist->init.deep->next) {
1206 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar",
1209 ilist=ilist->init.deep;
1214 // and the type must match
1215 itype=ilist->init.node->ftype;
1217 if (compareType(type, itype)==0) {
1218 // special case for literal strings
1219 if (IS_ARRAY (itype) && IS_CHAR (getSpec(itype)) &&
1220 // which are really code pointers
1221 IS_PTR(type) && DCL_TYPE(type)==CPOINTER) {
1224 // werrorfl (ilist->filename, ilist->lineno, E_TYPE_MISMATCH, "assignment", " ");
1225 // printFromToType(itype, type);
1232 /* if this is a pointer */
1235 // fprintf(stderr,"%s pointer\n",__FUNCTION__);
1236 pic16_printIvalPtr (sym, type, ilist, ptype, p);
1241 /* if type is SPECIFIER */
1244 // fprintf(stderr,"%s spec\n",__FUNCTION__);
1245 pic16_printIvalType (sym, type, ilist, ptype, p);
1250 int PIC16_IS_CONFIG_ADDRESS(int address)
1252 return ((address >= pic16->cwInfo.confAddrStart && address <= pic16->cwInfo.confAddrEnd));
1255 int PIC16_IS_IDLOC_ADDRESS(int address)
1257 return ((address >= pic16->idInfo.idAddrStart && address <= pic16->idInfo.idAddrEnd));
1260 /* wrapper function for the above */
1261 int PIC16_IS_HWREG_ADDRESS(int address)
1263 return (PIC16_IS_CONFIG_ADDRESS(address) || PIC16_IS_IDLOC_ADDRESS(address));
1267 /*-----------------------------------------------------------------*/
1268 /* emitStaticSeg - emitcode for the static segment */
1269 /*-----------------------------------------------------------------*/
1271 pic16emitStaticSeg (memmap * map)
1274 static int didcode=0;
1276 //fprintf(stderr, "%s\n",__FUNCTION__);
1280 /* for all variables in this segment do */
1281 for (sym = setFirstItem (map->syms); sym;
1282 sym = setNextItem (map->syms))
1286 fprintf(stderr, "%s\t%s: sym: %s\tused: %d\tSPEC_ABSA: %d\tSPEC_AGGREGATE: %d\tCODE: %d\n\
1287 CODESPACE: %d\tCONST: %d\tPTRCONST: %d\tSPEC_CONST: %d\n", __FUNCTION__,
1288 map->sname, sym->name, sym->used, SPEC_ABSA(sym->etype), IS_AGGREGATE(sym->type),
1289 IS_CODE(sym->etype), IN_CODESPACE( SPEC_OCLS(sym->etype)), IS_CONSTANT(sym->etype),
1290 IS_PTR_CONST(sym->etype), SPEC_CONST(sym->etype));
1291 printTypeChain( sym->type, stderr );
1292 fprintf(stderr, "\n");
1295 if(SPEC_ABSA(sym->etype) && PIC16_IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype))) {
1296 pic16_assignConfigWordValue(SPEC_ADDR(sym->etype),
1297 (int) floatFromVal(list2val(sym->ival)));
1302 if(SPEC_ABSA(sym->etype) && PIC16_IS_IDLOC_ADDRESS(SPEC_ADDR(sym->etype))) {
1303 pic16_assignIdByteValue(SPEC_ADDR(sym->etype),
1304 (char) floatFromVal(list2val(sym->ival)));
1309 /* if it is "extern" then do nothing */
1310 if (IS_EXTERN (sym->etype)/* && !SPEC_ABSA(sym->etype)*/) {
1311 checkAddSym(&externs, sym);
1315 /* if it is not static add it to the public
1317 if (!IS_STATIC (sym->etype)) {
1318 /* do not emit if it is a config word declaration */
1319 checkAddSym(&publics, sym);
1322 /* print extra debug info if required */
1323 if (options.debug || sym->level == 0) {
1324 /* NOTE to me - cdbFile may be null in which case,
1325 * the sym name will be printed to stdout. oh well */
1326 debugFile->writeSymbol(sym);
1329 /* if it has an absolute address */
1330 if (SPEC_ABSA (sym->etype)) {
1331 // fprintf(stderr, "%s:%d spec_absa is true for symbol: %s\n",
1332 // __FILE__, __LINE__, sym->name);
1334 /* if it has an initial value */
1342 /* symbol has absolute address and initial value */
1344 resolveIvalSym (sym->ival, sym->type);
1345 asym = newSymbol(sym->rname, 0);
1346 abSym = Safe_calloc(1, sizeof(absSym));
1347 strcpy(abSym->name, sym->rname);
1348 abSym->address = SPEC_ADDR( sym->etype );
1349 addSet(&absSymSet, abSym);
1351 pb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute Ival"));
1352 pic16_addpBlock(pb);
1354 pcf = pic16_newpCodeFunction(moduleName, asym->name);
1355 PCF(pcf)->absblock = 1;
1357 pic16_addpCode2pBlock(pb,pcf);
1358 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
1359 //fprintf(stderr, "%s:%d [1] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1360 pic16_printIval(sym, sym->type, sym->ival, 'p', (void *)pb);
1361 pic16_flushDB('p', (void *)pb);
1363 pic16_addpCode2pBlock(pb, pic16_newpCodeFunction(NULL, NULL));
1369 /* symbol has absolute address but no initial value */
1371 /* allocate space */
1372 fprintf (code->oFile, "%s:\n", sym->rname);
1374 /* special case for character strings */
1375 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1376 SPEC_CVAL (sym->etype).v_char) {
1378 // fprintf(stderr, "%s:%d printing code string from %s\n", __FILE__, __LINE__, sym->rname);
1380 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
1382 fprintf (stderr, "%s:%u(%s): do not know how to intialize symbol %s\n", __FILE__, __LINE__, __FUNCTION__, sym->rname);
1388 // fprintf(stderr, "%s:%d spec_absa is false for symbol: %s\n",
1389 // __FILE__, __LINE__, sym->name);
1392 /* if it has an initial value */
1396 /* symbol doesn't have absolute address but has initial value */
1397 fprintf (code->oFile, "%s:\n", sym->rname);
1399 resolveIvalSym (sym->ival, sym->type);
1401 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block for Ival"));
1402 pic16_addpBlock(pb);
1405 /* make sure that 'code' directive is emitted before, once */
1406 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir("code", NULL));
1411 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
1412 //fprintf(stderr, "%s:%d [2] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1413 pic16_printIval(sym, sym->type, sym->ival, 'p', (void *)pb);
1414 pic16_flushDB('p', (void *)pb);
1418 /* symbol doesn't have absolute address and no initial value */
1419 /* allocate space */
1420 // fprintf(stderr, "%s:%d [3] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1421 fprintf (code->oFile, "%s:\n", sym->rname);
1422 /* special case for character strings */
1423 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1424 SPEC_CVAL (sym->etype).v_char) {
1426 // fprintf(stderr, "%s:%d printing code string for %s\n", __FILE__, __LINE__, sym->rname);
1428 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
1439 /*-----------------------------------------------------------------*/
1440 /* pic16_emitConfigRegs - emits the configuration registers */
1441 /*-----------------------------------------------------------------*/
1442 void pic16_emitConfigRegs(FILE *of)
1446 for(i=0;i<pic16->cwInfo.confAddrEnd-pic16->cwInfo.confAddrStart;i++)
1447 if(pic16->cwInfo.crInfo[i].emit) //mask != -1)
1448 fprintf (of, "\t__config 0x%x, 0x%hhx\n",
1449 pic16->cwInfo.confAddrStart+i,
1450 pic16->cwInfo.crInfo[i].value);
1453 void pic16_emitIDRegs(FILE *of)
1457 for(i=0;i<pic16->idInfo.idAddrEnd-pic16->idInfo.idAddrStart;i++)
1458 if(pic16->idInfo.irInfo[i].emit)
1459 fprintf (of, "\t__idlocs 0x%06x, 0x%hhx\n",
1460 pic16->idInfo.idAddrStart+i,
1461 pic16->idInfo.irInfo[i].value);
1468 /* no special considerations for the following
1469 data, idata & bit & xdata */
1470 pic16emitRegularMap (data, TRUE, TRUE);
1471 pic16emitRegularMap (idata, TRUE, TRUE);
1472 pic16emitRegularMap (bit, TRUE, FALSE);
1473 pic16emitRegularMap (xdata, TRUE, TRUE);
1474 pic16emitRegularMap (sfr, FALSE, FALSE);
1475 pic16emitRegularMap (sfrbit, FALSE, FALSE);
1476 pic16emitRegularMap (code, TRUE, FALSE);
1477 pic16emitStaticSeg (statsg);
1480 /*-----------------------------------------------------------------*/
1481 /* createInterruptVect - creates the interrupt vector */
1482 /*-----------------------------------------------------------------*/
1484 pic16createInterruptVect (FILE * vFile)
1486 /* if the main is only a prototype ie. no body then do nothing */
1488 if (!IFFUNC_HASBODY(mainf->type)) {
1489 /* if ! compile only then main function should be present */
1490 if (!options.cc_only)
1496 if((!pic16_options.omit_ivt) || (pic16_options.omit_ivt && pic16_options.leave_reset)) {
1497 fprintf (vFile, ";\t.area\t%s\n", CODE_NAME);
1498 fprintf(vFile, ".intvecs\tcode\t0x%06x\n", pic16_options.ivt_loc);
1500 /* this is an overkill since WE are the port,
1501 * and we know if we have a genIVT function! */
1503 port->genIVT(vFile, interrupts, maxInterrupts);
1511 /*-----------------------------------------------------------------*/
1512 /* pic16initialComments - puts in some initial comments */
1513 /*-----------------------------------------------------------------*/
1515 pic16initialComments (FILE * afile)
1517 initialComments (afile);
1518 fprintf (afile, "; PIC16 port for the Microchip 16-bit core micros\n");
1519 if(pic16_mplab_comp)
1520 fprintf(afile, "; MPLAB/MPASM/MPASMWIN/MPLINK compatibility mode enabled\n");
1521 fprintf (afile, iComments2);
1524 fprintf (afile, "\n\t.ident \"SDCC version %s #%s [pic16 port]\"\n",
1525 SDCC_VERSION_STR, getBuildNumber() );
1529 /*-----------------------------------------------------------------*/
1530 /* printPublics - generates global declarations for publics */
1531 /*-----------------------------------------------------------------*/
1533 pic16printPublics (FILE *afile)
1537 fprintf (afile, "\n%s", iComments2);
1538 fprintf (afile, "; public variables in this module\n");
1539 fprintf (afile, "%s", iComments2);
1541 for(sym = setFirstItem (publics); sym; sym = setNextItem (publics))
1543 if(!IS_STATIC(sym->etype))
1544 fprintf(afile, "\tglobal %s\n", sym->rname);
1547 /*-----------------------------------------------------------------*/
1548 /* printExterns - generates extern declarations for externs */
1549 /*-----------------------------------------------------------------*/
1551 pic16_printExterns(FILE *afile)
1555 /* print nothing if no externs to declare */
1556 if(!elementsInSet(externs) && !elementsInSet(pic16_builtin_functions))
1559 fprintf(afile, "\n%s", iComments2);
1560 fprintf(afile, "; extern variables in this module\n");
1561 fprintf(afile, "%s", iComments2);
1563 for(sym = setFirstItem(externs); sym; sym = setNextItem(externs))
1564 fprintf(afile, "\textern %s\n", sym->rname);
1566 for(sym = setFirstItem(pic16_builtin_functions); sym; sym = setNextItem(pic16_builtin_functions))
1567 fprintf(afile, "\textern _%s\n", sym->name);
1570 /*-----------------------------------------------------------------*/
1571 /* emitOverlay - will emit code for the overlay stuff */
1572 /*-----------------------------------------------------------------*/
1574 pic16emitOverlay (FILE * afile)
1578 if (!elementsInSet (ovrSetSets))
1579 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);
1581 /* for each of the sets in the overlay segment do */
1582 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1583 ovrset = setNextItem (ovrSetSets))
1588 if (elementsInSet (ovrset))
1590 /* this dummy area is used to fool the assembler
1591 otherwise the assembler will append each of these
1592 declarations into one chunk and will not overlay
1594 fprintf (afile, ";\t.area _DUMMY\n");
1595 /* output the area informtion */
1596 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1599 for (sym = setFirstItem (ovrset); sym;
1600 sym = setNextItem (ovrset))
1603 /* if extern then do nothing */
1604 if (IS_EXTERN (sym->etype))
1607 /* if allocation required check is needed
1608 then check if the symbol really requires
1609 allocation only for local variables */
1610 if (!IS_AGGREGATE (sym->type) &&
1611 !(sym->_isparm && !IS_REGPARM (sym->etype))
1612 && !sym->allocreq && sym->level)
1615 /* if global variable & not static or extern
1616 and addPublics allowed then add it to the public set */
1617 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1618 && !IS_STATIC (sym->etype)) {
1619 // fprintf(stderr, "%s:%d %s accessed\n", __FILE__, __LINE__, __FUNCTION__);
1620 checkAddSym(&publics, sym);
1621 // addSetHead (&publics, sym);
1624 /* if extern then do nothing or is a function
1626 if (IS_FUNC (sym->type))
1630 /* if is has an absolute address then generate
1631 an equate for this no need to allocate space */
1632 if (SPEC_ABSA (sym->etype))
1635 if (options.debug || sym->level == 0)
1636 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1638 fprintf (afile, "%s\t=\t0x%04x\n",
1640 SPEC_ADDR (sym->etype));
1644 if (options.debug || sym->level == 0)
1645 fprintf (afile, "==.\n");
1647 /* allocate space */
1648 fprintf (afile, "%s:\n", sym->rname);
1649 fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1656 void emitStatistics(FILE *asmFile)
1658 unsigned long isize, udsize, ramsize;
1659 statistics.isize = pic16_countInstructions();
1660 isize = (statistics.isize >= 0) ? statistics.isize : 0;
1661 udsize = (statistics.udsize >= 0) ? statistics.udsize : 0;
1662 ramsize = pic16 ? pic16->RAMsize : 0x200;
1663 ramsize -= 256; /* ignore access bank and SFRs */
1664 if (ramsize == 0) ramsize = 64; /* prevent division by zero (below) */
1666 fprintf (asmFile, "\n\n; Statistics:\n");
1667 fprintf (asmFile, "; code size:\t%5ld (0x%04lx) bytes (%5.2f%%)\n; \t%5ld (0x%04lx) words\n",
1668 isize, isize, (isize*100.0)/(128UL << 10),
1669 isize>>1, isize>>1);
1670 fprintf (asmFile, "; udata size:\t%5ld (0x%04lx) bytes (%5.2f%%)\n",
1671 udsize, udsize, (udsize*100.0) / (1.0 * ramsize));
1672 fprintf (asmFile, "; access size:\t%5ld (0x%04lx) bytes\n",
1673 statistics.intsize, statistics.intsize);
1675 fprintf (asmFile, "\n\n");
1680 /*-----------------------------------------------------------------*/
1681 /* glue - the final glue that hold the whole thing together */
1682 /*-----------------------------------------------------------------*/
1688 FILE *ovrFile = tempfile();
1690 mainf = newSymbol ("main", 0);
1693 mainf = findSymWithLevel(SymbolTab, mainf);
1695 addSetHead(&tmpfileSet,ovrFile);
1696 pic16_pCodeInitRegisters();
1698 if(pic16_options.no_crt && mainf && IFFUNC_HASBODY(mainf->type)) {
1699 pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
1701 pic16_addpBlock(pb);
1703 /* entry point @ start of CSEG */
1704 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup",-1));
1707 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1708 pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("_stack_end"))));
1709 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1710 pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("_stack_end"))));
1713 /* put in the call to main */
1714 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
1716 if (options.mainreturn) {
1717 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
1718 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
1720 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
1721 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
1725 /* At this point we've got all the code in the form of pCode structures */
1726 /* Now it needs to be rearranged into the order it should be placed in the */
1729 pic16_movepBlock2Head('P'); // Last
1730 pic16_movepBlock2Head(code->dbName);
1731 pic16_movepBlock2Head('X');
1732 pic16_movepBlock2Head(statsg->dbName); // First
1734 /* print the global struct definitions */
1737 /* PENDING: this isnt the best place but it will do */
1738 if (port->general.glue_up_main) {
1739 /* create the interrupt vector table */
1740 pic16createInterruptVect (vFile);
1743 addSetHead(&tmpfileSet,vFile);
1745 /* emit code for the all the variables declared */
1748 /* do the overlay segments */
1749 pic16emitOverlay(ovrFile);
1750 pic16_AnalyzepCode('*');
1753 if(pic16_options.dumpcalltree) {
1756 sprintf(buffer, dstFileName);
1757 strcat(buffer, ".calltree");
1758 cFile = fopen(buffer, "w");
1759 pic16_printCallTree( cFile );
1764 pic16_InlinepCode();
1765 pic16_AnalyzepCode('*');
1768 if(pic16_debug_verbose)
1771 /* now put it all together into the assembler file */
1772 /* create the assembler file name */
1773 if((noAssemble || options.c1mode) && fullDstFileName) {
1774 sprintf (buffer, fullDstFileName);
1776 sprintf (buffer, dstFileName);
1777 strcat (buffer, ".asm");
1780 if(!(asmFile = fopen (buffer, "w"))) {
1781 werror (E_FILE_OPEN_ERR, buffer);
1785 /* initial comments */
1786 pic16initialComments (asmFile);
1788 /* print module name */
1790 fprintf(asmFile, "\t.file\t\"%s\"\n", fullSrcFileName);
1792 /* Let the port generate any global directives, etc. */
1793 if(port->genAssemblerPreamble) {
1794 port->genAssemblerPreamble(asmFile);
1797 /* Put all variables into a cblock */
1798 pic16_AnalyzeBanking();
1801 if(pic16_options.opt_flags & OF_LR_SUPPORT) {
1802 pic16_OptimizeLocalRegs();
1806 /* remove redundant BANKSELs -- added by RN 2005-01-17 */
1807 if(pic16_options.opt_banksel > 1) {
1808 pic16_OptimizeBanksel();
1811 /* turn GOTOs into BRAs -- added by RN 2004-11-16 */
1812 if(pic16_options.opt_flags & OF_OPTIMIZE_GOTO) {
1813 pic16_OptimizeJumps();
1816 /* print the extern variables to this module */
1817 pic16_printExterns(asmFile);
1819 /* print the global variables in this module */
1820 pic16printPublics (asmFile);
1822 pic16_writeUsedRegs(asmFile);
1825 /* no xdata in pic */
1826 /* if external stack then reserve space of it */
1827 if(mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1828 fprintf (asmFile, "%s", iComments2);
1829 fprintf (asmFile, "; external stack \n");
1830 fprintf (asmFile, "%s", iComments2);
1831 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1832 fprintf (asmFile,";\t.ds 256\n");
1837 /* no xdata in pic */
1838 /* copy xtern ram data */
1839 fprintf (asmFile, "%s", iComments2);
1840 fprintf (asmFile, "; external ram data\n");
1841 fprintf (asmFile, "%s", iComments2);
1842 copyFile (asmFile, xdata->oFile);
1846 /* copy the bit segment */
1847 fprintf (asmFile, "%s", iComments2);
1848 fprintf (asmFile, "; bit data\n");
1849 fprintf (asmFile, "%s", iComments2);
1850 copyFile (asmFile, bit->oFile);
1853 /* copy the interrupt vector table */
1854 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1855 fprintf (asmFile, "\n%s", iComments2);
1856 fprintf (asmFile, "; interrupt vector \n");
1857 fprintf (asmFile, "%s", iComments2);
1858 copyFile (asmFile, vFile);
1861 /* copy global & static initialisations */
1862 fprintf (asmFile, "\n%s", iComments2);
1863 fprintf (asmFile, "; global & static initialisations\n");
1864 fprintf (asmFile, "%s", iComments2);
1866 if(pic16_debug_verbose)
1867 fprintf(asmFile, "; A code from now on!\n");
1869 pic16_copypCode(asmFile, 'A');
1871 if(pic16_options.no_crt) {
1872 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1873 fprintf(asmFile, "\tcode\n");
1874 fprintf(asmFile,"__sdcc_gsinit_startup:\n");
1878 // copyFile (stderr, code->oFile);
1880 fprintf(asmFile, "; I code from now on!\n");
1881 pic16_copypCode(asmFile, 'I');
1883 if(pic16_debug_verbose)
1884 fprintf(asmFile, "; dbName from now on!\n");
1886 pic16_copypCode(asmFile, statsg->dbName);
1888 if(pic16_options.no_crt) {
1889 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
1890 fprintf (asmFile,"\tgoto\t__sdcc_program_startup\n");
1894 if(pic16_debug_verbose)
1895 fprintf(asmFile, "; X code from now on!\n");
1897 pic16_copypCode(asmFile, 'X');
1899 if(pic16_debug_verbose)
1900 fprintf(asmFile, "; M code from now on!\n");
1902 pic16_copypCode(asmFile, 'M');
1904 pic16_copypCode(asmFile, code->dbName);
1906 pic16_copypCode(asmFile, 'P');
1908 emitStatistics(asmFile);
1910 fprintf (asmFile,"\tend\n");