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);
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);
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);
1331 // fprintf(stderr, "%s:%d spec_absa is false for symbol: %s\n",
1332 // __FILE__, __LINE__, sym->name);
1335 /* if it has an initial value */
1339 /* symbol doesn't have absolute address but has initial value */
1340 fprintf (code->oFile, "%s:\n", sym->rname);
1342 resolveIvalSym (sym->ival, sym->type);
1344 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block for Ival"));
1345 pic16_addpBlock(pb);
1348 /* make sure that 'code' directive is emitted before, once */
1349 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir("code", NULL));
1354 // fprintf(stderr, "%s:%d [2] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1356 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
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;
1603 statistics.isize = pic16_countInstructions();
1604 isize = (statistics.isize >= 0) ? statistics.isize : 0;
1605 udsize = (statistics.udsize >= 0) ? statistics.udsize : 0;
1607 fprintf (asmFile, "\n\n; Statistics:\n");
1608 fprintf (asmFile, "; code size:\t%5ld (0x%04lx) bytes (%3.2f%%)\n; \t%5ld (0x%04lx) words\n",
1609 isize, isize, (isize*100.0)/(128 << 10),
1610 isize>>1, isize>>1);
1611 fprintf (asmFile, "; udata size:\t%5ld (0x%04lx) bytes (%3.2f%%)\n",
1612 udsize, udsize, (udsize*100.0) / ((pic16 ? pic16->RAMsize : 0x200) -256));
1613 fprintf (asmFile, "; access size:\t%5ld (0x%04lx) bytes\n",
1614 statistics.intsize, statistics.intsize);
1616 fprintf (asmFile, "\n\n");
1621 /*-----------------------------------------------------------------*/
1622 /* glue - the final glue that hold the whole thing together */
1623 /*-----------------------------------------------------------------*/
1629 FILE *ovrFile = tempfile();
1631 mainf = newSymbol ("main", 0);
1634 mainf = findSymWithLevel(SymbolTab, mainf);
1636 addSetHead(&tmpfileSet,ovrFile);
1637 pic16_pCodeInitRegisters();
1639 if(pic16_options.no_crt && mainf && IFFUNC_HASBODY(mainf->type)) {
1640 pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
1642 pic16_addpBlock(pb);
1644 /* entry point @ start of CSEG */
1645 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup",-1));
1648 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1649 pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("_stack_end"))));
1650 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1651 pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("_stack_end"))));
1654 /* put in the call to main */
1655 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
1657 if (options.mainreturn) {
1658 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
1659 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
1661 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
1662 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
1666 /* At this point we've got all the code in the form of pCode structures */
1667 /* Now it needs to be rearranged into the order it should be placed in the */
1670 pic16_movepBlock2Head('P'); // Last
1671 pic16_movepBlock2Head(code->dbName);
1672 pic16_movepBlock2Head('X');
1673 pic16_movepBlock2Head(statsg->dbName); // First
1675 /* print the global struct definitions */
1678 /* PENDING: this isnt the best place but it will do */
1679 if (port->general.glue_up_main) {
1680 /* create the interrupt vector table */
1681 pic16createInterruptVect (vFile);
1684 addSetHead(&tmpfileSet,vFile);
1686 /* emit code for the all the variables declared */
1689 /* do the overlay segments */
1690 pic16emitOverlay(ovrFile);
1691 pic16_AnalyzepCode('*');
1694 if(pic16_options.dumpcalltree) {
1697 sprintf(buffer, dstFileName);
1698 strcat(buffer, ".calltree");
1699 cFile = fopen(buffer, "w");
1700 pic16_printCallTree( cFile );
1705 pic16_InlinepCode();
1706 pic16_AnalyzepCode('*');
1709 if(pic16_debug_verbose)
1712 /* now put it all together into the assembler file */
1713 /* create the assembler file name */
1714 if((noAssemble || options.c1mode) && fullDstFileName) {
1715 sprintf (buffer, fullDstFileName);
1717 sprintf (buffer, dstFileName);
1718 strcat (buffer, ".asm");
1721 if(!(asmFile = fopen (buffer, "w"))) {
1722 werror (E_FILE_OPEN_ERR, buffer);
1726 /* initial comments */
1727 pic16initialComments (asmFile);
1729 /* print module name */
1731 fprintf(asmFile, "\t.file\t\"%s\"\n", fullSrcFileName);
1733 /* Let the port generate any global directives, etc. */
1734 if(port->genAssemblerPreamble) {
1735 port->genAssemblerPreamble(asmFile);
1738 /* Put all variables into a cblock */
1739 pic16_AnalyzeBanking();
1742 if(pic16_options.opt_flags & OF_LR_SUPPORT) {
1743 pic16_OptimizeLocalRegs();
1747 /* remove redundant BANKSELs -- added by RN 2005-01-17 */
1748 if(pic16_options.opt_banksel > 1) {
1749 pic16_OptimizeBanksel();
1752 /* turn GOTOs into BRAs -- added by RN 2004-11-16 */
1753 if(pic16_options.opt_flags & OF_OPTIMIZE_GOTO) {
1754 pic16_OptimizeJumps();
1757 /* print the extern variables to this module */
1758 pic16_printExterns(asmFile);
1760 /* print the global variables in this module */
1761 pic16printPublics (asmFile);
1763 pic16_writeUsedRegs(asmFile);
1766 /* no xdata in pic */
1767 /* if external stack then reserve space of it */
1768 if(mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1769 fprintf (asmFile, "%s", iComments2);
1770 fprintf (asmFile, "; external stack \n");
1771 fprintf (asmFile, "%s", iComments2);
1772 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1773 fprintf (asmFile,";\t.ds 256\n");
1778 /* no xdata in pic */
1779 /* copy xtern ram data */
1780 fprintf (asmFile, "%s", iComments2);
1781 fprintf (asmFile, "; external ram data\n");
1782 fprintf (asmFile, "%s", iComments2);
1783 copyFile (asmFile, xdata->oFile);
1787 /* copy the bit segment */
1788 fprintf (asmFile, "%s", iComments2);
1789 fprintf (asmFile, "; bit data\n");
1790 fprintf (asmFile, "%s", iComments2);
1791 copyFile (asmFile, bit->oFile);
1794 /* copy the interrupt vector table */
1795 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1796 fprintf (asmFile, "\n%s", iComments2);
1797 fprintf (asmFile, "; interrupt vector \n");
1798 fprintf (asmFile, "%s", iComments2);
1799 copyFile (asmFile, vFile);
1802 /* copy global & static initialisations */
1803 fprintf (asmFile, "\n%s", iComments2);
1804 fprintf (asmFile, "; global & static initialisations\n");
1805 fprintf (asmFile, "%s", iComments2);
1807 if(pic16_debug_verbose)
1808 fprintf(asmFile, "; A code from now on!\n");
1810 pic16_copypCode(asmFile, 'A');
1812 if(pic16_options.no_crt) {
1813 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1814 fprintf(asmFile, "\tcode\n");
1815 fprintf(asmFile,"__sdcc_gsinit_startup:\n");
1819 // copyFile (stderr, code->oFile);
1821 fprintf(asmFile, "; I code from now on!\n");
1822 pic16_copypCode(asmFile, 'I');
1824 if(pic16_debug_verbose)
1825 fprintf(asmFile, "; dbName from now on!\n");
1827 pic16_copypCode(asmFile, statsg->dbName);
1829 if(pic16_options.no_crt) {
1830 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
1831 fprintf (asmFile,"\tgoto\t__sdcc_program_startup\n");
1835 if(pic16_debug_verbose)
1836 fprintf(asmFile, "; X code from now on!\n");
1838 pic16_copypCode(asmFile, 'X');
1840 if(pic16_debug_verbose)
1841 fprintf(asmFile, "; M code from now on!\n");
1843 pic16_copypCode(asmFile, 'M');
1845 pic16_copypCode(asmFile, code->dbName);
1847 pic16_copypCode(asmFile, 'P');
1849 emitStatistics(asmFile);
1851 fprintf (asmFile,"\tend\n");