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)) {
99 unsigned long v = (unsigned long) floatFromVal(val);
101 return ( (v >> (offset * 8)) & 0xff);
104 /* it is type float */
105 fl.f = (float) floatFromVal(val);
106 #ifdef WORDS_BIGENDIAN
107 return fl.c[3-offset];
116 char tbuffer[512], *tbuf=tbuffer;;
119 /*-----------------------------------------------------------------*/
120 /* emitRegularMap - emit code for maps with no special cases */
121 /*-----------------------------------------------------------------*/
123 pic16emitRegularMap (memmap * map, bool addPublics, bool arFlag)
126 // int i, size, bitvars = 0;;
128 // fprintf(stderr, "%s:%d map name= %s\n", __FUNCTION__, __LINE__, map->sname);
131 fprintf (map->oFile, ";\t.area\t%s\n", map->sname);
132 /* print the area name */
134 for (sym = setFirstItem (map->syms); sym; sym = setNextItem (map->syms)) {
137 fprintf(stderr, "%s\t%s: sym: %s\tused: %d\textern: %d\tstatic: %d\taggregate: %d\tregister: 0x%x\tfunction: %d\n",
139 map->sname, sym->name, sym->used, IS_EXTERN(sym->etype), IS_STATIC(sym->etype),
140 IS_AGGREGATE(sym->type), (SPEC_SCLS(sym->etype) == S_REGISTER), IS_FUNC(sym->type));
141 printTypeChain( sym->type, stderr );
142 fprintf(stderr, "\n");
145 /* if extern then add to externs */
146 if (IS_EXTERN (sym->etype)) {
147 /* reduce overhead while linking by not declaring
148 * extern unused external functions (usually declared
149 * in header files) */
150 if(IS_FUNC(sym->type) && !sym->used)continue;
152 /* make sure symbol is not in publics section */
153 if(!checkSym(publics, sym))
154 checkAddSym(&externs, sym);
158 /* if allocation required check is needed
159 * then check if the symbol really requires
160 * allocation only for local variables */
161 if (arFlag && !IS_AGGREGATE (sym->type) &&
162 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
163 !sym->allocreq && sym->level) {
165 // fprintf(stderr, "%s:%d special case, continuing...\n", __FILE__, __LINE__);
170 /* if global variable & not static or extern
171 * and addPublics allowed then add it to the public set */
172 if ((sym->used) && (sym->level == 0 ||
173 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
175 !IS_STATIC (sym->etype) && !IS_FUNC(sym->type)) {
177 checkAddSym(&publics, sym);
180 if(IS_STATIC(sym->etype)
181 && !sym->ival) /* && !sym->level*/ {
186 // debugf("adding symbol %s\n", sym->name);
187 #define SET_IMPLICIT 1
190 if(IS_STRUCT(sym->type))
194 reg = pic16_allocDirReg( operandFromSymbol( sym ));
197 for(ssym=setFirstItem(sectSyms); ssym; ssym=setNextItem(sectSyms)) {
198 if(!strcmp(ssym->name, reg->name))found=1;
202 checkAddReg(&pic16_rel_udata, reg);
205 debugf("Did find %s in pic16_rel_udata already. Check!\n", reg->name);
206 // checkAddSym(&publics, sym);
212 /* if extern then do nothing or is a function
214 if (IS_FUNC (sym->type) && !IS_STATIC(sym->etype)) {
215 if(SPEC_OCLS(sym->etype) == code) {
216 // fprintf(stderr, "%s:%d: symbol added: %s\n", __FILE__, __LINE__, sym->rname);
217 checkAddSym(&publics, sym);
222 /* if is has an absolute address then generate
223 an equate for this no need to allocate space */
224 if (SPEC_ABSA (sym->etype)) {
225 // fprintf (stderr,"; %s == 0x%04x\t\treqv= %p nRegs= %d\n",
226 // sym->name, SPEC_ADDR (sym->etype), sym->reqv, sym->regType);
228 fprintf (map->oFile, "%s\tEQU\t0x%04x\n",
230 SPEC_ADDR (sym->etype));
232 /* emit only if it is global */
233 if(sym->level == 0) {
236 reg = pic16_dirregWithName( sym->name );
239 // fprintf(stderr, "%s:%d: implicit add of symbol = %s\n",
240 // __FUNCTION__, __LINE__, sym->name);
242 /* if IS_STRUCT is omitted the following
243 * fixes structures but break char/int etc */
245 if(IS_STRUCT(sym->type))
246 sym->implicit = 1; // mark as implicit
249 reg = pic16_allocDirReg( operandFromSymbol(sym) );
251 if(checkAddReg(&pic16_fix_udata, reg)) {
252 /* and add to globals list if not exist */
253 addSet(&publics, sym);
257 addSet(&publics, sym);
261 if(!sym->used && (sym->level == 0)) {
264 /* symbol not used, just declared probably, but its in
265 * level 0, so we must declare it fine as global */
267 // fprintf(stderr, "EXTRA symbol declaration sym= %s\n", sym->name);
270 if(IS_STRUCT(sym->type))
271 sym->implicit = 1; // mark as implicit
274 if(IS_AGGREGATE(sym->type)) {
275 reg=pic16_allocRegByName(sym->rname, getSize( sym->type ), NULL);
277 reg = pic16_allocDirReg( operandFromSymbol( sym ) );
285 fprintf(stderr, "%s:%d sym->rname: %s reg: %p reg->name: %s\n", __FILE__, __LINE__,
286 sym->rname, reg, (reg?reg->name:"<<NULL>>"));
290 for(ssym=setFirstItem(sectSyms); ssym; ssym=setNextItem(sectSyms)) {
291 if(!strcmp(ssym->name, reg->name))found=1;
295 if(checkAddReg(&pic16_rel_udata, reg)) {
296 addSetHead(&publics, sym);
305 addSetHead(&publics, sym);
310 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
311 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
312 /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
313 if (IS_BITVAR (sym->etype)) {
316 fprintf (map->oFile, "\t%s\n", sym->rname);
317 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1) {
318 for (i = 1; i < size; i++)
319 fprintf (map->oFile, "\t%s_%d\n", sym->rname, i);
322 fprintf (map->oFile, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
326 /* FIXME -- VR Fix the following, so that syms to be placed
327 * in the idata section and let linker decide about their fate */
329 /* if it has an initial value then do it only if
330 it is a global variable */
333 && ((sym->level == 0)
334 || IS_STATIC(sym->etype)) ) {
338 if(SPEC_OCLS(sym->etype)==data) {
339 fprintf(stderr, "%s: sym %s placed in data segment\n", map->sname, sym->name);
342 if(SPEC_OCLS(sym->etype)==code) {
343 fprintf(stderr, "%s: sym %s placed in code segment\n", map->sname, sym->name);
348 fprintf(stderr, "'%s': sym '%s' has initial value SPEC_ABSA: %d, IS_AGGREGATE: %d\n",
349 map->sname, sym->name, SPEC_ABSA(sym->etype), IS_AGGREGATE(sym->type));
352 if (IS_AGGREGATE (sym->type)) {
353 if(SPEC_ABSA(sym->etype))
354 addSet(&fix_idataSymSet, copySymbol(sym));
356 addSet(&rel_idataSymSet, copySymbol(sym));
357 // ival = initAggregates (sym, sym->ival, NULL);
359 if(SPEC_ABSA(sym->etype))
360 addSet(&fix_idataSymSet, copySymbol(sym));
362 addSet(&rel_idataSymSet, copySymbol(sym));
364 // ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
365 // decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
369 setAstLineno(ival, sym->lineDef);
370 codeOutFile = statsg->oFile;
372 eBBlockFromiCode (iCodeFromAst (ival));
380 /*-----------------------------------------------------------------*/
381 /* pic16_initPointer - pointer initialization code massaging */
382 /*-----------------------------------------------------------------*/
383 value *pic16_initPointer (initList * ilist, sym_link *toType)
389 return valCastLiteral(toType, 0.0);
392 expr = decorateType(resolveSymbols( list2expr (ilist) ), FALSE);
393 // expr = list2expr( ilist );
398 /* try it the old way first */
399 if ((val = constExprValue (expr, FALSE)))
402 /* ( ptr + constant ) */
403 if (IS_AST_OP (expr) &&
404 (expr->opval.op == '+' || expr->opval.op == '-') &&
405 IS_AST_SYM_VALUE (expr->left) &&
406 (IS_ARRAY(expr->left->ftype) || IS_PTR(expr->left->ftype)) &&
407 compareType(toType, expr->left->ftype) &&
408 IS_AST_LIT_VALUE (expr->right)) {
409 return valForCastAggr (expr->left, expr->left->ftype,
415 if (IS_AST_OP(expr) && expr->opval.op==CAST &&
416 IS_AST_OP(expr->right) && expr->right->opval.op=='&') {
417 if (compareType(toType, expr->left->ftype)!=1) {
418 werror (W_INIT_WRONG);
419 printFromToType(expr->left->ftype, toType);
425 /* no then we have to do these cludgy checks */
426 /* pointers can be initialized with address of
427 a variable or address of an array element */
428 if (IS_AST_OP (expr) && expr->opval.op == '&') {
429 /* address of symbol */
430 if (IS_AST_SYM_VALUE (expr->left)) {
431 val = copyValue (AST_VALUE (expr->left));
432 val->type = newLink (DECLARATOR);
433 if(SPEC_SCLS (expr->left->etype) == S_CODE) {
434 DCL_TYPE (val->type) = CPOINTER;
435 DCL_PTR_CONST (val->type) = port->mem.code_ro;
437 else if (SPEC_SCLS (expr->left->etype) == S_XDATA)
438 DCL_TYPE (val->type) = FPOINTER;
439 else if (SPEC_SCLS (expr->left->etype) == S_XSTACK)
440 DCL_TYPE (val->type) = PPOINTER;
441 else if (SPEC_SCLS (expr->left->etype) == S_IDATA)
442 DCL_TYPE (val->type) = IPOINTER;
443 else if (SPEC_SCLS (expr->left->etype) == S_EEPROM)
444 DCL_TYPE (val->type) = EEPPOINTER;
446 DCL_TYPE (val->type) = POINTER;
448 val->type->next = expr->left->ftype;
449 val->etype = getSpec (val->type);
453 /* if address of indexed array */
454 if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
455 return valForArray (expr->left);
457 /* if address of structure element then
459 if (IS_AST_OP (expr->left) &&
460 expr->left->opval.op == '.') {
461 return valForStructElem (expr->left->left,
466 (&some_struct)->element */
467 if (IS_AST_OP (expr->left) &&
468 expr->left->opval.op == PTR_OP &&
469 IS_ADDRESS_OF_OP (expr->left->left)) {
470 return valForStructElem (expr->left->left->left,
474 /* case 3. (((char *) &a) +/- constant) */
475 if (IS_AST_OP (expr) &&
476 (expr->opval.op == '+' || expr->opval.op == '-') &&
477 IS_AST_OP (expr->left) && expr->left->opval.op == CAST &&
478 IS_AST_OP (expr->left->right) &&
479 expr->left->right->opval.op == '&' &&
480 IS_AST_LIT_VALUE (expr->right)) {
482 return valForCastAggr (expr->left->right->left,
483 expr->left->left->opval.lnk,
484 expr->right, expr->opval.op);
487 /* case 4. (char *)(array type) */
488 if (IS_CAST_OP(expr) && IS_AST_SYM_VALUE (expr->right) &&
489 IS_ARRAY(expr->right->ftype)) {
491 val = copyValue (AST_VALUE (expr->right));
492 val->type = newLink (DECLARATOR);
493 if (SPEC_SCLS (expr->right->etype) == S_CODE) {
494 DCL_TYPE (val->type) = CPOINTER;
495 DCL_PTR_CONST (val->type) = port->mem.code_ro;
497 else if (SPEC_SCLS (expr->right->etype) == S_XDATA)
498 DCL_TYPE (val->type) = FPOINTER;
499 else if (SPEC_SCLS (expr->right->etype) == S_XSTACK)
500 DCL_TYPE (val->type) = PPOINTER;
501 else if (SPEC_SCLS (expr->right->etype) == S_IDATA)
502 DCL_TYPE (val->type) = IPOINTER;
503 else if (SPEC_SCLS (expr->right->etype) == S_EEPROM)
504 DCL_TYPE (val->type) = EEPPOINTER;
506 DCL_TYPE (val->type) = POINTER;
507 val->type->next = expr->right->ftype->next;
508 val->etype = getSpec (val->type);
514 werrorfl (expr->filename, expr->lineno, E_INCOMPAT_PTYPES);
516 werror (E_INCOMPAT_PTYPES);
522 /*-----------------------------------------------------------------*/
523 /* printPointerType - generates ival for pointer type */
524 /*-----------------------------------------------------------------*/
525 void _pic16_printPointerType (const char *name, char ptype, void *p)
529 sprintf(buf, "LOW(%s)", name);
530 pic16_emitDS(buf, ptype, p);
531 sprintf(buf, "HIGH(%s)", name);
532 pic16_emitDS(buf, ptype, p);
535 /*-----------------------------------------------------------------*/
536 /* printPointerType - generates ival for pointer type */
537 /*-----------------------------------------------------------------*/
538 void pic16_printPointerType (const char *name, char ptype, void *p)
540 _pic16_printPointerType (name, ptype, p);
541 pic16_flushDB(ptype, p);
544 /*-----------------------------------------------------------------*/
545 /* printGPointerType - generates ival for generic pointer type */
546 /*-----------------------------------------------------------------*/
547 void pic16_printGPointerType (const char *iname, const unsigned int itype,
552 _pic16_printPointerType (iname, ptype, p);
560 sprintf(buf, "UPPER(%s)", iname);
561 pic16_emitDS(buf, ptype, p);
565 sprintf(buf, "0x80");
566 pic16_emitDS(buf, ptype, p);
569 debugf("itype = %d\n", itype );
573 pic16_flushDB(ptype, p);
577 /* set to 0 to disable debug messages */
578 #define DEBUG_PRINTIVAL 0
580 /*-----------------------------------------------------------------*/
581 /* pic16_printIvalType - generates ival for int/char */
582 /*-----------------------------------------------------------------*/
584 pic16_printIvalType (symbol *sym, sym_link * type, initList * ilist, char ptype, void *p)
588 // fprintf(stderr, "%s for symbol %s\n",__FUNCTION__, sym->rname);
591 fprintf(stderr, "%s\n",__FUNCTION__);
595 /* if initList is deep */
596 if (ilist && ilist->type == INIT_DEEP)
597 ilist = ilist->init.deep;
599 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
600 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
603 if (!(val = list2val (ilist))) {
604 // assuming a warning has been thrown
608 if (val->type != type) {
609 val = valCastLiteral(type, floatFromVal(val));
612 switch (getSize (type)) {
614 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
618 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
619 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
622 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
623 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
624 pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
626 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
627 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
628 pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
629 pic16_emitDB(pic16aopLiteral(val, 3), ptype, p);
634 /*--------------------------------------------------------------------*/
635 /* pic16_printIvalChar - generates initital value for character array */
636 /*--------------------------------------------------------------------*/
638 pic16_printIvalChar (symbol *sym, sym_link * type, initList * ilist, char *s, char ptype, void *p)
641 int remain, len, ilen;
647 fprintf(stderr, "%s\n",__FUNCTION__);
651 /* length of initializer string (might contain \0, so do not use strlen) */
652 ilen = getNelements (type, ilist);
654 val = list2val (ilist);
655 /* if the value is a character string */
656 if(IS_ARRAY (val->type) && IS_CHAR (val->etype)) {
658 DCL_ELEM (type) = ilen;
660 /* len is 0 if declartion equals initializer,
661 * >0 if declaration greater than initializer
662 * <0 if declaration less than initializer
663 * Strategy: if >0 emit 0x00 for the rest of the length,
664 * if <0 then emit only the length of declaration elements
667 len = DCL_ELEM (type) - ilen;
669 // fprintf(stderr, "%s:%d ilen = %i len = %i DCL_ELEM(type) = %i SPEC_CVAL-len = %i\n", __FILE__, __LINE__,
670 // ilen, len, DCL_ELEM(type), strlen(SPEC_CVAL(val->etype).v_char));
673 /* emit initializer */
674 for(remain=0; remain<ilen; remain++)
675 pic16_emitDB(SPEC_CVAL(val->etype).v_char[ remain ], ptype, p);
677 /* fill array with 0x00 */
679 pic16_emitDB(0x00, ptype, p);
682 werror (W_EXCESS_INITIALIZERS, "array of chars", sym->name, sym->lineDef);
684 for(remain=0; remain<DCL_ELEM (type); remain++)
685 pic16_emitDB(SPEC_CVAL(val->etype).v_char[ remain ], ptype, p);
689 // if((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0) {
694 for(remain=0; remain<strlen(s); remain++) {
695 pic16_emitDB(s[remain], ptype, p);
701 /*-----------------------------------------------------------------*/
702 /* pic16_printIvalArray - generates code for array initialization */
703 /*-----------------------------------------------------------------*/
705 pic16_printIvalArray (symbol * sym, sym_link * type, initList * ilist,
709 int lcnt = 0, size = 0;
716 fprintf(stderr, "%s\n",__FUNCTION__);
718 /* take care of the special case */
719 /* array of characters can be init */
721 if (IS_CHAR (type->next)) {
722 if (!IS_LITERAL(list2val(ilist)->etype)) {
723 werror (W_INIT_WRONG);
727 if(pic16_printIvalChar (sym, type,
728 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
729 SPEC_CVAL (sym->etype).v_char, ptype, p))
732 /* not the special case */
733 if (ilist && ilist->type != INIT_DEEP)
735 werror (E_INIT_STRUCT, sym->name);
739 iloop = ilist->init.deep;
740 lcnt = DCL_ELEM (type);
745 pic16_printIval (sym, type->next, iloop, ptype, p);
746 iloop = (iloop ? iloop->next : NULL);
749 /* if not array limits given & we */
750 /* are out of initialisers then */
751 if (!DCL_ELEM (type) && !iloop)
754 /* no of elements given and we */
755 /* have generated for all of them */
757 /* if initializers left */
759 werror (W_EXCESS_INITIALIZERS, "array", sym->name, sym->lineDef);
765 /* if we have not been given a size */
766 if (!DCL_ELEM (type))
767 DCL_ELEM (type) = size;
772 /*-----------------------------------------------------------------*/
773 /* pic16_printIvalBitFields - generate initializer for bitfields */
774 /*-----------------------------------------------------------------*/
775 void pic16_printIvalBitFields(symbol **sym, initList **ilist, char ptype, void *p)
779 initList *lilist = *ilist ;
780 unsigned long ival = 0;
785 fprintf(stderr, "%s\n",__FUNCTION__);
791 val = list2val(lilist);
793 if (SPEC_BLEN(lsym->etype) > 8) {
794 size += ((SPEC_BLEN (lsym->etype) / 8) +
795 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
798 size = ((SPEC_BLEN (lsym->etype) / 8) +
799 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
801 i = (unsigned long)floatFromVal(val);
802 i <<= SPEC_BSTR (lsym->etype);
804 if (! ( lsym->next &&
805 (IS_BITFIELD(lsym->next->type)) &&
806 (SPEC_BSTR(lsym->next->etype)))) break;
808 lilist = lilist->next;
812 pic16_emitDB(BYTE_IN_LONG(ival, 0), ptype, p);
816 pic16_emitDB(BYTE_IN_LONG(ival, 0), ptype, p);
817 pic16_emitDB(BYTE_IN_LONG(ival, 1), ptype, p);
820 case 4: /* EEP: why is this db and not dw? */
821 pic16_emitDB(BYTE_IN_LONG(ival, 0), ptype, p);
822 pic16_emitDB(BYTE_IN_LONG(ival, 1), ptype, p);
823 pic16_emitDB(BYTE_IN_LONG(ival, 2), ptype, p);
824 pic16_emitDB(BYTE_IN_LONG(ival, 3), ptype, p);
827 /* VR - only 1,2,4 size long can be handled???? Why? */
828 fprintf(stderr, "%s:%d: unhandled case. Contact author.\n", __FILE__, __LINE__);
836 /*-----------------------------------------------------------------*/
837 /* printIvalStruct - generates initial value for structures */
838 /*-----------------------------------------------------------------*/
839 void pic16_printIvalStruct (symbol * sym, sym_link * type,
840 initList * ilist, char ptype, void *p)
843 initList *iloop = NULL;
847 fprintf(stderr, "%s\n",__FUNCTION__);
850 sflds = SPEC_STRUCT (type)->fields;
853 if (ilist->type != INIT_DEEP) {
854 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
858 iloop = ilist->init.deep;
861 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
862 // fprintf(stderr, "%s:%d sflds: %p\tiloop = %p\n", __FILE__, __LINE__, sflds, iloop);
863 if (IS_BITFIELD(sflds->type)) {
864 pic16_printIvalBitFields(&sflds, &iloop, ptype, p);
866 pic16_printIval (sym, sflds->type, iloop, ptype, p);
870 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
875 /*--------------------------------------------------------------------------*/
876 /* pic16_printIvalCharPtr - generates initial values for character pointers */
877 /*--------------------------------------------------------------------------*/
878 int pic16_printIvalCharPtr (symbol * sym, sym_link * type, value * val, char ptype, void *p)
882 /* PENDING: this is _very_ mcs51 specific, including a magic
884 It's also endin specific.
886 VR - Attempting to port this function to pic16 port - 8-Jun-2004
891 fprintf(stderr, "%s\n",__FUNCTION__);
894 size = getSize (type);
896 if (val->name && strlen (val->name))
898 if (size == 1) /* This appears to be Z80 specific?? */
900 pic16_emitDS(val->name, ptype, p);
904 pic16_printPointerType (val->name, ptype, p);
909 if (IS_PTR (val->type)) {
910 type = DCL_TYPE (val->type);
912 type = PTR_TYPE (SPEC_OCLS (val->etype));
914 if (val->sym && val->sym->isstrlit) {
915 // this is a literal string
918 pic16_printGPointerType(val->name, type, ptype, p);
922 fprintf (stderr, "*** internal error: unknown size in "
923 "printIvalCharPtr.\n");
929 // these are literals assigned to pointers
933 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
936 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
937 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
940 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
941 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
942 pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
950 if (val->sym && val->sym->isstrlit) { // && !isinSet(statsg->syms, val->sym)) {
951 if(ptype == 'p' && !isinSet(statsg->syms, val->sym))addSet (&statsg->syms, val->sym);
952 else if(ptype == 'f' /*&& !isinSet(rel_idataSymSet, val->sym)*/)addSet(&rel_idataSymSet, val->sym);
958 /*-----------------------------------------------------------------------*/
959 /* pic16_printIvalFuncPtr - generate initial value for function pointers */
960 /*-----------------------------------------------------------------------*/
961 void pic16_printIvalFuncPtr (sym_link * type, initList * ilist, char ptype, void *p)
968 fprintf(stderr, "%s\n",__FUNCTION__);
972 val = list2val (ilist);
974 val = valCastLiteral(type, 0.0);
977 // an error has been thrown already
981 if (IS_LITERAL(val->etype)) {
982 if (compareType(type, val->etype) == 0) {
983 werrorfl (ilist->filename, ilist->lineno, E_INCOMPAT_TYPES);
984 printFromToType (val->type, type);
986 pic16_printIvalCharPtr (NULL, type, val, ptype, p);
990 /* check the types */
991 if ((dLvl = compareType (val->type, type->next)) <= 0)
993 pic16_emitDB(0x00, ptype, p);
997 /* now generate the name */
999 pic16_printGPointerType (val->name, DCL_TYPE(val->type), ptype, p);
1001 pic16_printGPointerType (val->sym->rname, DCL_TYPE(val->type), ptype, p);
1003 if(IS_FUNC(val->sym->type) && !val->sym->used && !IS_STATIC(val->sym->etype)) {
1005 if(!checkSym(publics, val->sym))
1006 if(checkAddSym(&externs, val->sym) && (ptype == 'f')) {
1007 /* this has not been declared as extern
1008 * so declare it as a 'late extern' just after the symbol */
1009 fprintf((FILE *)p, ";\tdeclare symbol as extern\n");
1010 fprintf((FILE *)p, "\textern\t%s\n", val->sym->rname);
1011 fprintf((FILE *)p, ";\tcontinue variable declaration\n");
1020 /*-----------------------------------------------------------------*/
1021 /* pic16_printIvalPtr - generates initial value for pointers */
1022 /*-----------------------------------------------------------------*/
1023 void pic16_printIvalPtr (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p)
1029 fprintf(stderr, "%s:%d initialising pointer: %s size: %d\n", __FILE__, __LINE__,
1030 sym->rname, getSize(sym->type));
1034 if (ilist && (ilist->type == INIT_DEEP))
1035 ilist = ilist->init.deep;
1037 /* function pointer */
1038 if (IS_FUNC (type->next))
1040 pic16_printIvalFuncPtr (type, ilist, ptype, p);
1044 if (!(val = pic16_initPointer (ilist, type)))
1047 /* if character pointer */
1048 if (IS_CHAR (type->next))
1049 if (pic16_printIvalCharPtr (sym, type, val, ptype, p))
1052 /* check the type */
1053 if (compareType (type, val->type) == 0) {
1054 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
1055 printFromToType (val->type, type);
1058 /* if val is literal */
1059 if (IS_LITERAL (val->etype))
1061 switch (getSize (type))
1064 pic16_emitDB((unsigned int)floatFromVal(val) & 0xff, ptype, p);
1067 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
1068 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
1071 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
1072 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
1073 pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
1076 fprintf(stderr, "%s:%d size = %d\n", __FILE__, __LINE__, getSize(type));
1083 size = getSize (type);
1085 if (size == 1) /* Z80 specific?? */
1087 pic16_emitDS(val->name, ptype, p);
1091 pic16_printPointerType (val->name, ptype, p);
1095 pic16_printGPointerType (val->name, (IS_PTR(type)?DCL_TYPE(type):PTR_TYPE(SPEC_OCLS(sym->etype))),
1104 /*-----------------------------------------------------------------*/
1105 /* pic16_printIval - generates code for initial value */
1106 /*-----------------------------------------------------------------*/
1107 void pic16_printIval (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p)
1115 fprintf(stderr, "%s:%d generating init for %s\n", __FILE__, __LINE__, sym->name);
1116 fprintf(stderr, "%s: IS_STRUCT: %d IS_ARRAY: %d IS_PTR: %d IS_SPEC: %d\n", sym->name,
1117 IS_STRUCT(type), IS_ARRAY(type), IS_PTR(type), IS_SPEC(type));
1120 /* if structure then */
1121 if (IS_STRUCT (type))
1123 // fprintf(stderr,"%s struct\n",__FUNCTION__);
1124 pic16_printIvalStruct (sym, type, ilist, ptype, p);
1128 /* if this is an array */
1129 if (IS_ARRAY (type))
1131 // fprintf(stderr,"%s array\n",__FUNCTION__);
1132 pic16_printIvalArray (sym, type, ilist, ptype, p);
1139 // not an aggregate, ilist must be a node
1140 if (ilist->type!=INIT_NODE) {
1141 // or a 1-element list
1142 if (ilist->init.deep->next) {
1143 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar",
1146 ilist=ilist->init.deep;
1151 // and the type must match
1152 itype=ilist->init.node->ftype;
1154 if (compareType(type, itype)==0) {
1155 // special case for literal strings
1156 if (IS_ARRAY (itype) && IS_CHAR (getSpec(itype)) &&
1157 // which are really code pointers
1158 IS_PTR(type) && DCL_TYPE(type)==CPOINTER) {
1161 // werrorfl (ilist->filename, ilist->lineno, E_TYPE_MISMATCH, "assignment", " ");
1162 // printFromToType(itype, type);
1169 /* if this is a pointer */
1172 // fprintf(stderr,"%s pointer\n",__FUNCTION__);
1173 pic16_printIvalPtr (sym, type, ilist, ptype, p);
1178 /* if type is SPECIFIER */
1181 // fprintf(stderr,"%s spec\n",__FUNCTION__);
1182 pic16_printIvalType (sym, type, ilist, ptype, p);
1187 int PIC16_IS_CONFIG_ADDRESS(int address)
1189 return ((address >= pic16->cwInfo.confAddrStart && address <= pic16->cwInfo.confAddrEnd));
1192 int PIC16_IS_IDLOC_ADDRESS(int address)
1194 return ((address >= pic16->idInfo.idAddrStart && address <= pic16->idInfo.idAddrEnd));
1197 /* wrapper function for the above */
1198 int PIC16_IS_HWREG_ADDRESS(int address)
1200 return (PIC16_IS_CONFIG_ADDRESS(address) || PIC16_IS_IDLOC_ADDRESS(address));
1204 /*-----------------------------------------------------------------*/
1205 /* emitStaticSeg - emitcode for the static segment */
1206 /*-----------------------------------------------------------------*/
1208 pic16emitStaticSeg (memmap * map)
1211 static int didcode=0;
1213 //fprintf(stderr, "%s\n",__FUNCTION__);
1217 /* for all variables in this segment do */
1218 for (sym = setFirstItem (map->syms); sym;
1219 sym = setNextItem (map->syms))
1223 fprintf(stderr, "%s\t%s: sym: %s\tused: %d\tSPEC_ABSA: %d\tSPEC_AGGREGATE: %d\tCODE: %d\n\
1224 CODESPACE: %d\tCONST: %d\tPTRCONST: %d\tSPEC_CONST: %d\n", __FUNCTION__,
1225 map->sname, sym->name, sym->used, SPEC_ABSA(sym->etype), IS_AGGREGATE(sym->type),
1226 IS_CODE(sym->etype), IN_CODESPACE( SPEC_OCLS(sym->etype)), IS_CONSTANT(sym->etype),
1227 IS_PTR_CONST(sym->etype), SPEC_CONST(sym->etype));
1228 printTypeChain( sym->type, stderr );
1229 fprintf(stderr, "\n");
1232 if(SPEC_ABSA(sym->etype) && PIC16_IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype))) {
1233 pic16_assignConfigWordValue(SPEC_ADDR(sym->etype),
1234 (int) floatFromVal(list2val(sym->ival)));
1239 if(SPEC_ABSA(sym->etype) && PIC16_IS_IDLOC_ADDRESS(SPEC_ADDR(sym->etype))) {
1240 pic16_assignIdByteValue(SPEC_ADDR(sym->etype),
1241 (char) floatFromVal(list2val(sym->ival)));
1246 /* if it is "extern" then do nothing */
1247 if (IS_EXTERN (sym->etype) && !SPEC_ABSA(sym->etype)) {
1248 checkAddSym(&externs, sym);
1252 /* if it is not static add it to the public
1254 if (!IS_STATIC (sym->etype)) {
1255 /* do not emit if it is a config word declaration */
1256 checkAddSym(&publics, sym);
1259 /* print extra debug info if required */
1260 if (options.debug || sym->level == 0) {
1261 /* NOTE to me - cdbFile may be null in which case,
1262 * the sym name will be printed to stdout. oh well */
1263 debugFile->writeSymbol(sym);
1266 /* if it has an absolute address */
1267 if (SPEC_ABSA (sym->etype)) {
1268 // fprintf(stderr, "%s:%d spec_absa is true for symbol: %s\n",
1269 // __FILE__, __LINE__, sym->name);
1271 /* if it has an initial value */
1279 /* symbol has absolute address and initial value */
1281 resolveIvalSym (sym->ival, sym->type);
1282 asym = newSymbol(sym->rname, 0);
1283 abSym = Safe_calloc(1, sizeof(absSym));
1284 strcpy(abSym->name, sym->rname);
1285 abSym->address = SPEC_ADDR( sym->etype );
1286 addSet(&absSymSet, abSym);
1288 pb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute Ival"));
1289 pic16_addpBlock(pb);
1291 pcf = pic16_newpCodeFunction(moduleName, asym->name);
1292 PCF(pcf)->absblock = 1;
1294 pic16_addpCode2pBlock(pb,pcf);
1295 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
1296 // fprintf(stderr, "%s:%d [1] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1297 pic16_printIval(sym, sym->type, sym->ival, 'p', (void *)pb);
1298 pic16_flushDB('p', (void *)pb);
1300 pic16_addpCode2pBlock(pb, pic16_newpCodeFunction(NULL, NULL));
1306 /* symbol has absolute address but no initial value */
1308 /* allocate space */
1309 fprintf (code->oFile, "%s:\n", sym->rname);
1311 /* special case for character strings */
1312 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1313 SPEC_CVAL (sym->etype).v_char) {
1315 // fprintf(stderr, "%s:%d printing code string from %s\n", __FILE__, __LINE__, sym->rname);
1317 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
1324 // fprintf(stderr, "%s:%d spec_absa is false for symbol: %s\n",
1325 // __FILE__, __LINE__, sym->name);
1328 /* if it has an initial value */
1332 /* symbol doesn't have absolute address but has initial value */
1333 fprintf (code->oFile, "%s:\n", sym->rname);
1335 resolveIvalSym (sym->ival, sym->type);
1337 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block for Ival"));
1338 pic16_addpBlock(pb);
1341 /* make sure that 'code' directive is emitted before, once */
1342 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir("code", NULL));
1347 // fprintf(stderr, "%s:%d [2] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1349 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
1350 pic16_printIval(sym, sym->type, sym->ival, 'p', (void *)pb);
1351 pic16_flushDB('p', (void *)pb);
1355 /* symbol doesn't have absolute address and no initial value */
1356 /* allocate space */
1357 // fprintf(stderr, "%s:%d [3] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1358 fprintf (code->oFile, "%s:\n", sym->rname);
1359 /* special case for character strings */
1360 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1361 SPEC_CVAL (sym->etype).v_char) {
1363 // fprintf(stderr, "%s:%d printing code string for %s\n", __FILE__, __LINE__, sym->rname);
1365 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
1376 /*-----------------------------------------------------------------*/
1377 /* pic16_emitConfigRegs - emits the configuration registers */
1378 /*-----------------------------------------------------------------*/
1379 void pic16_emitConfigRegs(FILE *of)
1383 for(i=0;i<pic16->cwInfo.confAddrEnd-pic16->cwInfo.confAddrStart;i++)
1384 if(pic16->cwInfo.crInfo[i].emit) //mask != -1)
1385 fprintf (of, "\t__config 0x%x, 0x%hhx\n",
1386 pic16->cwInfo.confAddrStart+i,
1387 pic16->cwInfo.crInfo[i].value);
1390 void pic16_emitIDRegs(FILE *of)
1394 for(i=0;i<pic16->idInfo.idAddrEnd-pic16->idInfo.idAddrStart;i++)
1395 if(pic16->idInfo.irInfo[i].emit)
1396 fprintf (of, "\t__idlocs 0x%06x, 0x%hhx\n",
1397 pic16->idInfo.idAddrStart+i,
1398 pic16->idInfo.irInfo[i].value);
1405 /* no special considerations for the following
1406 data, idata & bit & xdata */
1407 pic16emitRegularMap (data, TRUE, TRUE);
1408 pic16emitRegularMap (idata, TRUE, TRUE);
1409 pic16emitRegularMap (bit, TRUE, FALSE);
1410 pic16emitRegularMap (xdata, TRUE, TRUE);
1411 pic16emitRegularMap (sfr, FALSE, FALSE);
1412 pic16emitRegularMap (sfrbit, FALSE, FALSE);
1413 pic16emitRegularMap (code, TRUE, FALSE);
1414 pic16emitStaticSeg (statsg);
1417 /*-----------------------------------------------------------------*/
1418 /* createInterruptVect - creates the interrupt vector */
1419 /*-----------------------------------------------------------------*/
1421 pic16createInterruptVect (FILE * vFile)
1423 /* if the main is only a prototype ie. no body then do nothing */
1425 if (!IFFUNC_HASBODY(mainf->type)) {
1426 /* if ! compile only then main function should be present */
1427 if (!options.cc_only)
1433 if((!pic16_options.omit_ivt) || (pic16_options.omit_ivt && pic16_options.leave_reset)) {
1434 fprintf (vFile, ";\t.area\t%s\n", CODE_NAME);
1435 fprintf(vFile, ".intvecs\tcode\t0x%06x\n", pic16_options.ivt_loc);
1437 /* this is an overkill since WE are the port,
1438 * and we know if we have a genIVT function! */
1440 port->genIVT(vFile, interrupts, maxInterrupts);
1448 /*-----------------------------------------------------------------*/
1449 /* pic16initialComments - puts in some initial comments */
1450 /*-----------------------------------------------------------------*/
1452 pic16initialComments (FILE * afile)
1454 initialComments (afile);
1455 fprintf (afile, "; PIC16 port for the Microchip 16-bit core micros\n");
1456 if(pic16_mplab_comp)
1457 fprintf(afile, "; MPLAB/MPASM/MPASMWIN/MPLINK compatibility mode enabled\n");
1458 fprintf (afile, iComments2);
1461 fprintf (afile, "\n\t.ident \"SDCC version %s #%s [pic16 port]\"\n",
1462 SDCC_VERSION_STR, getBuildNumber() );
1466 /*-----------------------------------------------------------------*/
1467 /* printPublics - generates global declarations for publics */
1468 /*-----------------------------------------------------------------*/
1470 pic16printPublics (FILE *afile)
1474 fprintf (afile, "\n%s", iComments2);
1475 fprintf (afile, "; public variables in this module\n");
1476 fprintf (afile, "%s", iComments2);
1478 for(sym = setFirstItem (publics); sym; sym = setNextItem (publics))
1480 if(!IS_STATIC(sym->etype))
1481 fprintf(afile, "\tglobal %s\n", sym->rname);
1484 /*-----------------------------------------------------------------*/
1485 /* printExterns - generates extern declarations for externs */
1486 /*-----------------------------------------------------------------*/
1488 pic16_printExterns(FILE *afile)
1492 /* print nothing if no externs to declare */
1493 if(!elementsInSet(externs) && !elementsInSet(pic16_builtin_functions))
1496 fprintf(afile, "\n%s", iComments2);
1497 fprintf(afile, "; extern variables in this module\n");
1498 fprintf(afile, "%s", iComments2);
1500 for(sym = setFirstItem(externs); sym; sym = setNextItem(externs))
1501 fprintf(afile, "\textern %s\n", sym->rname);
1503 for(sym = setFirstItem(pic16_builtin_functions); sym; sym = setNextItem(pic16_builtin_functions))
1504 fprintf(afile, "\textern _%s\n", sym->name);
1507 /*-----------------------------------------------------------------*/
1508 /* emitOverlay - will emit code for the overlay stuff */
1509 /*-----------------------------------------------------------------*/
1511 pic16emitOverlay (FILE * afile)
1515 if (!elementsInSet (ovrSetSets))
1516 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);
1518 /* for each of the sets in the overlay segment do */
1519 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1520 ovrset = setNextItem (ovrSetSets))
1525 if (elementsInSet (ovrset))
1527 /* this dummy area is used to fool the assembler
1528 otherwise the assembler will append each of these
1529 declarations into one chunk and will not overlay
1531 fprintf (afile, ";\t.area _DUMMY\n");
1532 /* output the area informtion */
1533 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1536 for (sym = setFirstItem (ovrset); sym;
1537 sym = setNextItem (ovrset))
1540 /* if extern then do nothing */
1541 if (IS_EXTERN (sym->etype))
1544 /* if allocation required check is needed
1545 then check if the symbol really requires
1546 allocation only for local variables */
1547 if (!IS_AGGREGATE (sym->type) &&
1548 !(sym->_isparm && !IS_REGPARM (sym->etype))
1549 && !sym->allocreq && sym->level)
1552 /* if global variable & not static or extern
1553 and addPublics allowed then add it to the public set */
1554 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1555 && !IS_STATIC (sym->etype)) {
1556 // fprintf(stderr, "%s:%d %s accessed\n", __FILE__, __LINE__, __FUNCTION__);
1557 checkAddSym(&publics, sym);
1558 // addSetHead (&publics, sym);
1561 /* if extern then do nothing or is a function
1563 if (IS_FUNC (sym->type))
1567 /* if is has an absolute address then generate
1568 an equate for this no need to allocate space */
1569 if (SPEC_ABSA (sym->etype))
1572 if (options.debug || sym->level == 0)
1573 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1575 fprintf (afile, "%s\t=\t0x%04x\n",
1577 SPEC_ADDR (sym->etype));
1581 if (options.debug || sym->level == 0)
1582 fprintf (afile, "==.\n");
1584 /* allocate space */
1585 fprintf (afile, "%s:\n", sym->rname);
1586 fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1593 void emitStatistics(FILE *asmFile)
1595 unsigned long isize, udsize;
1596 statistics.isize = pic16_countInstructions();
1597 isize = (statistics.isize >= 0) ? statistics.isize : 0;
1598 udsize = (statistics.udsize >= 0) ? statistics.udsize : 0;
1600 fprintf (asmFile, "\n\n; Statistics:\n");
1601 fprintf (asmFile, "; code size:\t%5ld (0x%04lx) bytes (%3.2f%%)\n; \t%5ld (0x%04lx) words\n",
1602 isize, isize, (isize*100.0)/(128 << 10),
1603 isize>>1, isize>>1);
1604 fprintf (asmFile, "; udata size:\t%5ld (0x%04lx) bytes (%3.2f%%)\n",
1605 udsize, udsize, (udsize*100.0) / ((pic16 ? pic16->RAMsize : 0x200) -256));
1606 fprintf (asmFile, "; access size:\t%5ld (0x%04lx) bytes\n",
1607 statistics.intsize, statistics.intsize);
1609 fprintf (asmFile, "\n\n");
1614 /*-----------------------------------------------------------------*/
1615 /* glue - the final glue that hold the whole thing together */
1616 /*-----------------------------------------------------------------*/
1622 FILE *ovrFile = tempfile();
1624 mainf = newSymbol ("main", 0);
1627 mainf = findSymWithLevel(SymbolTab, mainf);
1629 addSetHead(&tmpfileSet,ovrFile);
1630 pic16_pCodeInitRegisters();
1632 if(pic16_options.no_crt && mainf && IFFUNC_HASBODY(mainf->type)) {
1633 pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
1635 pic16_addpBlock(pb);
1637 /* entry point @ start of CSEG */
1638 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup",-1));
1641 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1642 pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("_stack_end"))));
1643 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1644 pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("_stack_end"))));
1647 /* put in the call to main */
1648 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
1650 if (options.mainreturn) {
1651 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
1652 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
1654 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
1655 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
1659 /* At this point we've got all the code in the form of pCode structures */
1660 /* Now it needs to be rearranged into the order it should be placed in the */
1663 pic16_movepBlock2Head('P'); // Last
1664 pic16_movepBlock2Head(code->dbName);
1665 pic16_movepBlock2Head('X');
1666 pic16_movepBlock2Head(statsg->dbName); // First
1668 /* print the global struct definitions */
1671 /* PENDING: this isnt the best place but it will do */
1672 if (port->general.glue_up_main) {
1673 /* create the interrupt vector table */
1674 pic16createInterruptVect (vFile);
1677 addSetHead(&tmpfileSet,vFile);
1679 /* emit code for the all the variables declared */
1682 /* do the overlay segments */
1683 pic16emitOverlay(ovrFile);
1684 pic16_AnalyzepCode('*');
1687 if(pic16_options.dumpcalltree) {
1690 sprintf(buffer, dstFileName);
1691 strcat(buffer, ".calltree");
1692 cFile = fopen(buffer, "w");
1693 pic16_printCallTree( cFile );
1698 pic16_InlinepCode();
1699 pic16_AnalyzepCode('*');
1702 if(pic16_debug_verbose)
1705 /* now put it all together into the assembler file */
1706 /* create the assembler file name */
1707 if((noAssemble || options.c1mode) && fullDstFileName) {
1708 sprintf (buffer, fullDstFileName);
1710 sprintf (buffer, dstFileName);
1711 strcat (buffer, ".asm");
1714 if(!(asmFile = fopen (buffer, "w"))) {
1715 werror (E_FILE_OPEN_ERR, buffer);
1719 /* initial comments */
1720 pic16initialComments (asmFile);
1722 /* print module name */
1724 fprintf(asmFile, "\t.file\t\"%s\"\n", fullSrcFileName);
1726 /* Let the port generate any global directives, etc. */
1727 if(port->genAssemblerPreamble) {
1728 port->genAssemblerPreamble(asmFile);
1731 /* Put all variables into a cblock */
1732 pic16_AnalyzeBanking();
1735 if(pic16_options.opt_flags & OF_LR_SUPPORT) {
1736 pic16_OptimizeLocalRegs();
1740 /* remove redundant BANKSELs -- added by RN 2005-01-17 */
1741 if(pic16_options.opt_banksel > 1) {
1742 pic16_OptimizeBanksel();
1745 /* turn GOTOs into BRAs -- added by RN 2004-11-16 */
1746 if(pic16_options.opt_flags & OF_OPTIMIZE_GOTO) {
1747 pic16_OptimizeJumps();
1750 /* print the extern variables to this module */
1751 pic16_printExterns(asmFile);
1753 /* print the global variables in this module */
1754 pic16printPublics (asmFile);
1756 pic16_writeUsedRegs(asmFile);
1759 /* no xdata in pic */
1760 /* if external stack then reserve space of it */
1761 if(mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1762 fprintf (asmFile, "%s", iComments2);
1763 fprintf (asmFile, "; external stack \n");
1764 fprintf (asmFile, "%s", iComments2);
1765 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1766 fprintf (asmFile,";\t.ds 256\n");
1771 /* no xdata in pic */
1772 /* copy xtern ram data */
1773 fprintf (asmFile, "%s", iComments2);
1774 fprintf (asmFile, "; external ram data\n");
1775 fprintf (asmFile, "%s", iComments2);
1776 copyFile (asmFile, xdata->oFile);
1780 /* copy the bit segment */
1781 fprintf (asmFile, "%s", iComments2);
1782 fprintf (asmFile, "; bit data\n");
1783 fprintf (asmFile, "%s", iComments2);
1784 copyFile (asmFile, bit->oFile);
1787 /* copy the interrupt vector table */
1788 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1789 fprintf (asmFile, "\n%s", iComments2);
1790 fprintf (asmFile, "; interrupt vector \n");
1791 fprintf (asmFile, "%s", iComments2);
1792 copyFile (asmFile, vFile);
1795 /* copy global & static initialisations */
1796 fprintf (asmFile, "\n%s", iComments2);
1797 fprintf (asmFile, "; global & static initialisations\n");
1798 fprintf (asmFile, "%s", iComments2);
1800 if(pic16_debug_verbose)
1801 fprintf(asmFile, "; A code from now on!\n");
1803 pic16_copypCode(asmFile, 'A');
1805 if(pic16_options.no_crt) {
1806 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1807 fprintf(asmFile, "\tcode\n");
1808 fprintf(asmFile,"__sdcc_gsinit_startup:\n");
1812 // copyFile (stderr, code->oFile);
1814 fprintf(asmFile, "; I code from now on!\n");
1815 pic16_copypCode(asmFile, 'I');
1817 if(pic16_debug_verbose)
1818 fprintf(asmFile, "; dbName from now on!\n");
1820 pic16_copypCode(asmFile, statsg->dbName);
1822 if(pic16_options.no_crt) {
1823 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
1824 fprintf (asmFile,"\tgoto\t__sdcc_program_startup\n");
1828 if(pic16_debug_verbose)
1829 fprintf(asmFile, "; X code from now on!\n");
1831 pic16_copypCode(asmFile, 'X');
1833 if(pic16_debug_verbose)
1834 fprintf(asmFile, "; M code from now on!\n");
1836 pic16_copypCode(asmFile, 'M');
1838 pic16_copypCode(asmFile, code->dbName);
1840 pic16_copypCode(asmFile, 'P');
1842 emitStatistics(asmFile);
1844 fprintf (asmFile,"\tend\n");