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 val = list2val (ilist);
653 /* if the value is a character string */
654 if(IS_ARRAY (val->type) && IS_CHAR (val->etype)) {
655 /* length of initializer string (might contain \0, so do not use strlen) */
656 ilen = DCL_ELEM(val->type);
659 DCL_ELEM (type) = ilen;
661 /* len is 0 if declartion equals initializer,
662 * >0 if declaration greater than initializer
663 * <0 if declaration less than initializer
664 * Strategy: if >0 emit 0x00 for the rest of the length,
665 * if <0 then emit only the length of declaration elements
668 len = DCL_ELEM (type) - ilen;
670 // fprintf(stderr, "%s:%d ilen = %i len = %i DCL_ELEM(type) = %i SPEC_CVAL-len = %i\n", __FILE__, __LINE__,
671 // ilen, len, DCL_ELEM(type), strlen(SPEC_CVAL(val->etype).v_char));
674 /* emit initializer */
675 for(remain=0; remain<ilen; remain++)
676 pic16_emitDB(SPEC_CVAL(val->etype).v_char[ remain ], ptype, p);
678 /* fill array with 0x00 */
680 pic16_emitDB(0x00, ptype, p);
683 werror (W_EXCESS_INITIALIZERS, "array of chars", sym->name, sym->lineDef);
685 for(remain=0; remain<DCL_ELEM (type); remain++)
686 pic16_emitDB(SPEC_CVAL(val->etype).v_char[ remain ], ptype, p);
690 // if((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0) {
695 for(remain=0; remain<strlen(s); remain++) {
696 pic16_emitDB(s[remain], ptype, p);
702 /*-----------------------------------------------------------------*/
703 /* pic16_printIvalArray - generates code for array initialization */
704 /*-----------------------------------------------------------------*/
706 pic16_printIvalArray (symbol * sym, sym_link * type, initList * ilist,
710 int lcnt = 0, size = 0;
717 fprintf(stderr, "%s\n",__FUNCTION__);
719 /* take care of the special case */
720 /* array of characters can be init */
722 if (IS_CHAR (type->next)) {
723 if (!IS_LITERAL(list2val(ilist)->etype)) {
724 werror (W_INIT_WRONG);
728 if(pic16_printIvalChar (sym, type,
729 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
730 SPEC_CVAL (sym->etype).v_char, ptype, p))
733 /* not the special case */
734 if (ilist && ilist->type != INIT_DEEP)
736 werror (E_INIT_STRUCT, sym->name);
740 iloop = ilist->init.deep;
741 lcnt = DCL_ELEM (type);
746 pic16_printIval (sym, type->next, iloop, ptype, p);
747 iloop = (iloop ? iloop->next : NULL);
750 /* if not array limits given & we */
751 /* are out of initialisers then */
752 if (!DCL_ELEM (type) && !iloop)
755 /* no of elements given and we */
756 /* have generated for all of them */
758 /* if initializers left */
760 werror (W_EXCESS_INITIALIZERS, "array", sym->name, sym->lineDef);
766 /* if we have not been given a size */
767 if (!DCL_ELEM (type))
768 DCL_ELEM (type) = size;
773 /*-----------------------------------------------------------------*/
774 /* pic16_printIvalBitFields - generate initializer for bitfields */
775 /*-----------------------------------------------------------------*/
776 void pic16_printIvalBitFields(symbol **sym, initList **ilist, char ptype, void *p)
780 initList *lilist = *ilist ;
781 unsigned long ival = 0;
786 fprintf(stderr, "%s\n",__FUNCTION__);
792 val = list2val(lilist);
794 if (SPEC_BLEN(lsym->etype) > 8) {
795 size += ((SPEC_BLEN (lsym->etype) / 8) +
796 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
799 size = ((SPEC_BLEN (lsym->etype) / 8) +
800 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
802 i = (unsigned long)floatFromVal(val);
803 i <<= SPEC_BSTR (lsym->etype);
805 if (! ( lsym->next &&
806 (IS_BITFIELD(lsym->next->type)) &&
807 (SPEC_BSTR(lsym->next->etype)))) break;
809 lilist = lilist->next;
813 pic16_emitDB(BYTE_IN_LONG(ival, 0), ptype, p);
817 pic16_emitDB(BYTE_IN_LONG(ival, 0), ptype, p);
818 pic16_emitDB(BYTE_IN_LONG(ival, 1), ptype, p);
821 case 4: /* EEP: why is this db and not dw? */
822 pic16_emitDB(BYTE_IN_LONG(ival, 0), ptype, p);
823 pic16_emitDB(BYTE_IN_LONG(ival, 1), ptype, p);
824 pic16_emitDB(BYTE_IN_LONG(ival, 2), ptype, p);
825 pic16_emitDB(BYTE_IN_LONG(ival, 3), ptype, p);
828 /* VR - only 1,2,4 size long can be handled???? Why? */
829 fprintf(stderr, "%s:%d: unhandled case. Contact author.\n", __FILE__, __LINE__);
837 /*-----------------------------------------------------------------*/
838 /* printIvalStruct - generates initial value for structures */
839 /*-----------------------------------------------------------------*/
840 void pic16_printIvalStruct (symbol * sym, sym_link * type,
841 initList * ilist, char ptype, void *p)
844 initList *iloop = NULL;
848 fprintf(stderr, "%s\n",__FUNCTION__);
851 sflds = SPEC_STRUCT (type)->fields;
854 if (ilist->type != INIT_DEEP) {
855 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
859 iloop = ilist->init.deep;
862 for (; sflds; sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
863 // fprintf(stderr, "%s:%d sflds: %p\tiloop = %p\n", __FILE__, __LINE__, sflds, iloop);
864 if (IS_BITFIELD(sflds->type)) {
865 pic16_printIvalBitFields(&sflds, &iloop, ptype, p);
867 pic16_printIval (sym, sflds->type, iloop, ptype, p);
871 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
876 /*--------------------------------------------------------------------------*/
877 /* pic16_printIvalCharPtr - generates initial values for character pointers */
878 /*--------------------------------------------------------------------------*/
879 int pic16_printIvalCharPtr (symbol * sym, sym_link * type, value * val, char ptype, void *p)
883 /* PENDING: this is _very_ mcs51 specific, including a magic
885 It's also endin specific.
887 VR - Attempting to port this function to pic16 port - 8-Jun-2004
892 fprintf(stderr, "%s\n",__FUNCTION__);
895 size = getSize (type);
897 if (val->name && strlen (val->name))
899 if (size == 1) /* This appears to be Z80 specific?? */
901 pic16_emitDS(val->name, ptype, p);
905 pic16_printPointerType (val->name, ptype, p);
910 if (IS_PTR (val->type)) {
911 type = DCL_TYPE (val->type);
913 type = PTR_TYPE (SPEC_OCLS (val->etype));
915 if (val->sym && val->sym->isstrlit) {
916 // this is a literal string
919 pic16_printGPointerType(val->name, type, ptype, p);
923 fprintf (stderr, "*** internal error: unknown size in "
924 "printIvalCharPtr.\n");
930 // these are literals assigned to pointers
934 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
937 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
938 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
941 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
942 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
943 pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
951 if (val->sym && val->sym->isstrlit) { // && !isinSet(statsg->syms, val->sym)) {
952 if(ptype == 'p' && !isinSet(statsg->syms, val->sym))addSet (&statsg->syms, val->sym);
953 else if(ptype == 'f' /*&& !isinSet(rel_idataSymSet, val->sym)*/)addSet(&rel_idataSymSet, val->sym);
959 /*-----------------------------------------------------------------------*/
960 /* pic16_printIvalFuncPtr - generate initial value for function pointers */
961 /*-----------------------------------------------------------------------*/
962 void pic16_printIvalFuncPtr (sym_link * type, initList * ilist, char ptype, void *p)
969 fprintf(stderr, "%s\n",__FUNCTION__);
973 val = list2val (ilist);
975 val = valCastLiteral(type, 0.0);
978 // an error has been thrown already
982 if (IS_LITERAL(val->etype)) {
983 if (compareType(type, val->etype) == 0) {
984 werrorfl (ilist->filename, ilist->lineno, E_INCOMPAT_TYPES);
985 printFromToType (val->type, type);
987 pic16_printIvalCharPtr (NULL, type, val, ptype, p);
991 /* check the types */
992 if ((dLvl = compareType (val->type, type->next)) <= 0)
994 pic16_emitDB(0x00, ptype, p);
998 /* now generate the name */
1000 pic16_printGPointerType (val->name, DCL_TYPE(val->type), ptype, p);
1002 pic16_printGPointerType (val->sym->rname, DCL_TYPE(val->type), ptype, p);
1004 if(IS_FUNC(val->sym->type) && !val->sym->used && !IS_STATIC(val->sym->etype)) {
1006 if(!checkSym(publics, val->sym))
1007 if(checkAddSym(&externs, val->sym) && (ptype == 'f')) {
1008 /* this has not been declared as extern
1009 * so declare it as a 'late extern' just after the symbol */
1010 fprintf((FILE *)p, ";\tdeclare symbol as extern\n");
1011 fprintf((FILE *)p, "\textern\t%s\n", val->sym->rname);
1012 fprintf((FILE *)p, ";\tcontinue variable declaration\n");
1021 /*-----------------------------------------------------------------*/
1022 /* pic16_printIvalPtr - generates initial value for pointers */
1023 /*-----------------------------------------------------------------*/
1024 void pic16_printIvalPtr (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p)
1030 fprintf(stderr, "%s:%d initialising pointer: %s size: %d\n", __FILE__, __LINE__,
1031 sym->rname, getSize(sym->type));
1035 if (ilist && (ilist->type == INIT_DEEP))
1036 ilist = ilist->init.deep;
1038 /* function pointer */
1039 if (IS_FUNC (type->next))
1041 pic16_printIvalFuncPtr (type, ilist, ptype, p);
1045 if (!(val = pic16_initPointer (ilist, type)))
1048 /* if character pointer */
1049 if (IS_CHAR (type->next))
1050 if (pic16_printIvalCharPtr (sym, type, val, ptype, p))
1053 /* check the type */
1054 if (compareType (type, val->type) == 0) {
1055 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
1056 printFromToType (val->type, type);
1059 /* if val is literal */
1060 if (IS_LITERAL (val->etype))
1062 switch (getSize (type))
1065 pic16_emitDB((unsigned int)floatFromVal(val) & 0xff, ptype, p);
1068 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
1069 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
1072 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
1073 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
1074 pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
1077 fprintf(stderr, "%s:%d size = %d\n", __FILE__, __LINE__, getSize(type));
1084 size = getSize (type);
1086 if (size == 1) /* Z80 specific?? */
1088 pic16_emitDS(val->name, ptype, p);
1092 pic16_printPointerType (val->name, ptype, p);
1096 pic16_printGPointerType (val->name, (IS_PTR(type)?DCL_TYPE(type):PTR_TYPE(SPEC_OCLS(sym->etype))),
1105 /*-----------------------------------------------------------------*/
1106 /* pic16_printIval - generates code for initial value */
1107 /*-----------------------------------------------------------------*/
1108 void pic16_printIval (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p)
1116 fprintf(stderr, "%s:%d generating init for %s\n", __FILE__, __LINE__, sym->name);
1117 fprintf(stderr, "%s: IS_STRUCT: %d IS_ARRAY: %d IS_PTR: %d IS_SPEC: %d\n", sym->name,
1118 IS_STRUCT(type), IS_ARRAY(type), IS_PTR(type), IS_SPEC(type));
1121 /* if structure then */
1122 if (IS_STRUCT (type))
1124 // fprintf(stderr,"%s struct\n",__FUNCTION__);
1125 pic16_printIvalStruct (sym, type, ilist, ptype, p);
1129 /* if this is an array */
1130 if (IS_ARRAY (type))
1132 // fprintf(stderr,"%s array\n",__FUNCTION__);
1133 pic16_printIvalArray (sym, type, ilist, ptype, p);
1140 // not an aggregate, ilist must be a node
1141 if (ilist->type!=INIT_NODE) {
1142 // or a 1-element list
1143 if (ilist->init.deep->next) {
1144 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar",
1147 ilist=ilist->init.deep;
1152 // and the type must match
1153 itype=ilist->init.node->ftype;
1155 if (compareType(type, itype)==0) {
1156 // special case for literal strings
1157 if (IS_ARRAY (itype) && IS_CHAR (getSpec(itype)) &&
1158 // which are really code pointers
1159 IS_PTR(type) && DCL_TYPE(type)==CPOINTER) {
1162 // werrorfl (ilist->filename, ilist->lineno, E_TYPE_MISMATCH, "assignment", " ");
1163 // printFromToType(itype, type);
1170 /* if this is a pointer */
1173 // fprintf(stderr,"%s pointer\n",__FUNCTION__);
1174 pic16_printIvalPtr (sym, type, ilist, ptype, p);
1179 /* if type is SPECIFIER */
1182 // fprintf(stderr,"%s spec\n",__FUNCTION__);
1183 pic16_printIvalType (sym, type, ilist, ptype, p);
1188 int PIC16_IS_CONFIG_ADDRESS(int address)
1190 return ((address >= pic16->cwInfo.confAddrStart && address <= pic16->cwInfo.confAddrEnd));
1193 int PIC16_IS_IDLOC_ADDRESS(int address)
1195 return ((address >= pic16->idInfo.idAddrStart && address <= pic16->idInfo.idAddrEnd));
1198 /* wrapper function for the above */
1199 int PIC16_IS_HWREG_ADDRESS(int address)
1201 return (PIC16_IS_CONFIG_ADDRESS(address) || PIC16_IS_IDLOC_ADDRESS(address));
1205 /*-----------------------------------------------------------------*/
1206 /* emitStaticSeg - emitcode for the static segment */
1207 /*-----------------------------------------------------------------*/
1209 pic16emitStaticSeg (memmap * map)
1212 static int didcode=0;
1214 //fprintf(stderr, "%s\n",__FUNCTION__);
1218 /* for all variables in this segment do */
1219 for (sym = setFirstItem (map->syms); sym;
1220 sym = setNextItem (map->syms))
1224 fprintf(stderr, "%s\t%s: sym: %s\tused: %d\tSPEC_ABSA: %d\tSPEC_AGGREGATE: %d\tCODE: %d\n\
1225 CODESPACE: %d\tCONST: %d\tPTRCONST: %d\tSPEC_CONST: %d\n", __FUNCTION__,
1226 map->sname, sym->name, sym->used, SPEC_ABSA(sym->etype), IS_AGGREGATE(sym->type),
1227 IS_CODE(sym->etype), IN_CODESPACE( SPEC_OCLS(sym->etype)), IS_CONSTANT(sym->etype),
1228 IS_PTR_CONST(sym->etype), SPEC_CONST(sym->etype));
1229 printTypeChain( sym->type, stderr );
1230 fprintf(stderr, "\n");
1233 if(SPEC_ABSA(sym->etype) && PIC16_IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype))) {
1234 pic16_assignConfigWordValue(SPEC_ADDR(sym->etype),
1235 (int) floatFromVal(list2val(sym->ival)));
1240 if(SPEC_ABSA(sym->etype) && PIC16_IS_IDLOC_ADDRESS(SPEC_ADDR(sym->etype))) {
1241 pic16_assignIdByteValue(SPEC_ADDR(sym->etype),
1242 (char) floatFromVal(list2val(sym->ival)));
1247 /* if it is "extern" then do nothing */
1248 if (IS_EXTERN (sym->etype) && !SPEC_ABSA(sym->etype)) {
1249 checkAddSym(&externs, sym);
1253 /* if it is not static add it to the public
1255 if (!IS_STATIC (sym->etype)) {
1256 /* do not emit if it is a config word declaration */
1257 checkAddSym(&publics, sym);
1260 /* print extra debug info if required */
1261 if (options.debug || sym->level == 0) {
1262 /* NOTE to me - cdbFile may be null in which case,
1263 * the sym name will be printed to stdout. oh well */
1264 debugFile->writeSymbol(sym);
1267 /* if it has an absolute address */
1268 if (SPEC_ABSA (sym->etype)) {
1269 // fprintf(stderr, "%s:%d spec_absa is true for symbol: %s\n",
1270 // __FILE__, __LINE__, sym->name);
1272 /* if it has an initial value */
1280 /* symbol has absolute address and initial value */
1282 resolveIvalSym (sym->ival, sym->type);
1283 asym = newSymbol(sym->rname, 0);
1284 abSym = Safe_calloc(1, sizeof(absSym));
1285 strcpy(abSym->name, sym->rname);
1286 abSym->address = SPEC_ADDR( sym->etype );
1287 addSet(&absSymSet, abSym);
1289 pb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute Ival"));
1290 pic16_addpBlock(pb);
1292 pcf = pic16_newpCodeFunction(moduleName, asym->name);
1293 PCF(pcf)->absblock = 1;
1295 pic16_addpCode2pBlock(pb,pcf);
1296 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
1297 // fprintf(stderr, "%s:%d [1] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1298 pic16_printIval(sym, sym->type, sym->ival, 'p', (void *)pb);
1299 pic16_flushDB('p', (void *)pb);
1301 pic16_addpCode2pBlock(pb, pic16_newpCodeFunction(NULL, NULL));
1307 /* symbol has absolute address but no initial value */
1309 /* allocate space */
1310 fprintf (code->oFile, "%s:\n", sym->rname);
1312 /* special case for character strings */
1313 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1314 SPEC_CVAL (sym->etype).v_char) {
1316 // fprintf(stderr, "%s:%d printing code string from %s\n", __FILE__, __LINE__, sym->rname);
1318 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
1325 // fprintf(stderr, "%s:%d spec_absa is false for symbol: %s\n",
1326 // __FILE__, __LINE__, sym->name);
1329 /* if it has an initial value */
1333 /* symbol doesn't have absolute address but has initial value */
1334 fprintf (code->oFile, "%s:\n", sym->rname);
1336 resolveIvalSym (sym->ival, sym->type);
1338 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block for Ival"));
1339 pic16_addpBlock(pb);
1342 /* make sure that 'code' directive is emitted before, once */
1343 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir("code", NULL));
1348 // fprintf(stderr, "%s:%d [2] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1350 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
1351 pic16_printIval(sym, sym->type, sym->ival, 'p', (void *)pb);
1352 pic16_flushDB('p', (void *)pb);
1356 /* symbol doesn't have absolute address and no initial value */
1357 /* allocate space */
1358 // fprintf(stderr, "%s:%d [3] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1359 fprintf (code->oFile, "%s:\n", sym->rname);
1360 /* special case for character strings */
1361 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1362 SPEC_CVAL (sym->etype).v_char) {
1364 // fprintf(stderr, "%s:%d printing code string for %s\n", __FILE__, __LINE__, sym->rname);
1366 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
1377 /*-----------------------------------------------------------------*/
1378 /* pic16_emitConfigRegs - emits the configuration registers */
1379 /*-----------------------------------------------------------------*/
1380 void pic16_emitConfigRegs(FILE *of)
1384 for(i=0;i<pic16->cwInfo.confAddrEnd-pic16->cwInfo.confAddrStart;i++)
1385 if(pic16->cwInfo.crInfo[i].emit) //mask != -1)
1386 fprintf (of, "\t__config 0x%x, 0x%hhx\n",
1387 pic16->cwInfo.confAddrStart+i,
1388 pic16->cwInfo.crInfo[i].value);
1391 void pic16_emitIDRegs(FILE *of)
1395 for(i=0;i<pic16->idInfo.idAddrEnd-pic16->idInfo.idAddrStart;i++)
1396 if(pic16->idInfo.irInfo[i].emit)
1397 fprintf (of, "\t__idlocs 0x%06x, 0x%hhx\n",
1398 pic16->idInfo.idAddrStart+i,
1399 pic16->idInfo.irInfo[i].value);
1406 /* no special considerations for the following
1407 data, idata & bit & xdata */
1408 pic16emitRegularMap (data, TRUE, TRUE);
1409 pic16emitRegularMap (idata, TRUE, TRUE);
1410 pic16emitRegularMap (bit, TRUE, FALSE);
1411 pic16emitRegularMap (xdata, TRUE, TRUE);
1412 pic16emitRegularMap (sfr, FALSE, FALSE);
1413 pic16emitRegularMap (sfrbit, FALSE, FALSE);
1414 pic16emitRegularMap (code, TRUE, FALSE);
1415 pic16emitStaticSeg (statsg);
1418 /*-----------------------------------------------------------------*/
1419 /* createInterruptVect - creates the interrupt vector */
1420 /*-----------------------------------------------------------------*/
1422 pic16createInterruptVect (FILE * vFile)
1424 /* if the main is only a prototype ie. no body then do nothing */
1426 if (!IFFUNC_HASBODY(mainf->type)) {
1427 /* if ! compile only then main function should be present */
1428 if (!options.cc_only)
1434 if((!pic16_options.omit_ivt) || (pic16_options.omit_ivt && pic16_options.leave_reset)) {
1435 fprintf (vFile, ";\t.area\t%s\n", CODE_NAME);
1436 fprintf(vFile, ".intvecs\tcode\t0x%06x\n", pic16_options.ivt_loc);
1438 /* this is an overkill since WE are the port,
1439 * and we know if we have a genIVT function! */
1441 port->genIVT(vFile, interrupts, maxInterrupts);
1449 /*-----------------------------------------------------------------*/
1450 /* pic16initialComments - puts in some initial comments */
1451 /*-----------------------------------------------------------------*/
1453 pic16initialComments (FILE * afile)
1455 initialComments (afile);
1456 fprintf (afile, "; PIC16 port for the Microchip 16-bit core micros\n");
1457 if(pic16_mplab_comp)
1458 fprintf(afile, "; MPLAB/MPASM/MPASMWIN/MPLINK compatibility mode enabled\n");
1459 fprintf (afile, iComments2);
1462 fprintf (afile, "\n\t.ident \"SDCC version %s #%s [pic16 port]\"\n",
1463 SDCC_VERSION_STR, getBuildNumber() );
1467 /*-----------------------------------------------------------------*/
1468 /* printPublics - generates global declarations for publics */
1469 /*-----------------------------------------------------------------*/
1471 pic16printPublics (FILE *afile)
1475 fprintf (afile, "\n%s", iComments2);
1476 fprintf (afile, "; public variables in this module\n");
1477 fprintf (afile, "%s", iComments2);
1479 for(sym = setFirstItem (publics); sym; sym = setNextItem (publics))
1481 if(!IS_STATIC(sym->etype))
1482 fprintf(afile, "\tglobal %s\n", sym->rname);
1485 /*-----------------------------------------------------------------*/
1486 /* printExterns - generates extern declarations for externs */
1487 /*-----------------------------------------------------------------*/
1489 pic16_printExterns(FILE *afile)
1493 /* print nothing if no externs to declare */
1494 if(!elementsInSet(externs) && !elementsInSet(pic16_builtin_functions))
1497 fprintf(afile, "\n%s", iComments2);
1498 fprintf(afile, "; extern variables in this module\n");
1499 fprintf(afile, "%s", iComments2);
1501 for(sym = setFirstItem(externs); sym; sym = setNextItem(externs))
1502 fprintf(afile, "\textern %s\n", sym->rname);
1504 for(sym = setFirstItem(pic16_builtin_functions); sym; sym = setNextItem(pic16_builtin_functions))
1505 fprintf(afile, "\textern _%s\n", sym->name);
1508 /*-----------------------------------------------------------------*/
1509 /* emitOverlay - will emit code for the overlay stuff */
1510 /*-----------------------------------------------------------------*/
1512 pic16emitOverlay (FILE * afile)
1516 if (!elementsInSet (ovrSetSets))
1517 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);
1519 /* for each of the sets in the overlay segment do */
1520 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1521 ovrset = setNextItem (ovrSetSets))
1526 if (elementsInSet (ovrset))
1528 /* this dummy area is used to fool the assembler
1529 otherwise the assembler will append each of these
1530 declarations into one chunk and will not overlay
1532 fprintf (afile, ";\t.area _DUMMY\n");
1533 /* output the area informtion */
1534 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1537 for (sym = setFirstItem (ovrset); sym;
1538 sym = setNextItem (ovrset))
1541 /* if extern then do nothing */
1542 if (IS_EXTERN (sym->etype))
1545 /* if allocation required check is needed
1546 then check if the symbol really requires
1547 allocation only for local variables */
1548 if (!IS_AGGREGATE (sym->type) &&
1549 !(sym->_isparm && !IS_REGPARM (sym->etype))
1550 && !sym->allocreq && sym->level)
1553 /* if global variable & not static or extern
1554 and addPublics allowed then add it to the public set */
1555 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1556 && !IS_STATIC (sym->etype)) {
1557 // fprintf(stderr, "%s:%d %s accessed\n", __FILE__, __LINE__, __FUNCTION__);
1558 checkAddSym(&publics, sym);
1559 // addSetHead (&publics, sym);
1562 /* if extern then do nothing or is a function
1564 if (IS_FUNC (sym->type))
1568 /* if is has an absolute address then generate
1569 an equate for this no need to allocate space */
1570 if (SPEC_ABSA (sym->etype))
1573 if (options.debug || sym->level == 0)
1574 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1576 fprintf (afile, "%s\t=\t0x%04x\n",
1578 SPEC_ADDR (sym->etype));
1582 if (options.debug || sym->level == 0)
1583 fprintf (afile, "==.\n");
1585 /* allocate space */
1586 fprintf (afile, "%s:\n", sym->rname);
1587 fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1594 void emitStatistics(FILE *asmFile)
1596 unsigned long isize, udsize;
1597 statistics.isize = pic16_countInstructions();
1598 isize = (statistics.isize >= 0) ? statistics.isize : 0;
1599 udsize = (statistics.udsize >= 0) ? statistics.udsize : 0;
1601 fprintf (asmFile, "\n\n; Statistics:\n");
1602 fprintf (asmFile, "; code size:\t%5ld (0x%04lx) bytes (%3.2f%%)\n; \t%5ld (0x%04lx) words\n",
1603 isize, isize, (isize*100.0)/(128 << 10),
1604 isize>>1, isize>>1);
1605 fprintf (asmFile, "; udata size:\t%5ld (0x%04lx) bytes (%3.2f%%)\n",
1606 udsize, udsize, (udsize*100.0) / ((pic16 ? pic16->RAMsize : 0x200) -256));
1607 fprintf (asmFile, "; access size:\t%5ld (0x%04lx) bytes\n",
1608 statistics.intsize, statistics.intsize);
1610 fprintf (asmFile, "\n\n");
1615 /*-----------------------------------------------------------------*/
1616 /* glue - the final glue that hold the whole thing together */
1617 /*-----------------------------------------------------------------*/
1623 FILE *ovrFile = tempfile();
1625 mainf = newSymbol ("main", 0);
1628 mainf = findSymWithLevel(SymbolTab, mainf);
1630 addSetHead(&tmpfileSet,ovrFile);
1631 pic16_pCodeInitRegisters();
1633 if(pic16_options.no_crt && mainf && IFFUNC_HASBODY(mainf->type)) {
1634 pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
1636 pic16_addpBlock(pb);
1638 /* entry point @ start of CSEG */
1639 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup",-1));
1642 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1643 pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("_stack_end"))));
1644 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1645 pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("_stack_end"))));
1648 /* put in the call to main */
1649 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
1651 if (options.mainreturn) {
1652 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
1653 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
1655 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
1656 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
1660 /* At this point we've got all the code in the form of pCode structures */
1661 /* Now it needs to be rearranged into the order it should be placed in the */
1664 pic16_movepBlock2Head('P'); // Last
1665 pic16_movepBlock2Head(code->dbName);
1666 pic16_movepBlock2Head('X');
1667 pic16_movepBlock2Head(statsg->dbName); // First
1669 /* print the global struct definitions */
1672 /* PENDING: this isnt the best place but it will do */
1673 if (port->general.glue_up_main) {
1674 /* create the interrupt vector table */
1675 pic16createInterruptVect (vFile);
1678 addSetHead(&tmpfileSet,vFile);
1680 /* emit code for the all the variables declared */
1683 /* do the overlay segments */
1684 pic16emitOverlay(ovrFile);
1685 pic16_AnalyzepCode('*');
1688 if(pic16_options.dumpcalltree) {
1691 sprintf(buffer, dstFileName);
1692 strcat(buffer, ".calltree");
1693 cFile = fopen(buffer, "w");
1694 pic16_printCallTree( cFile );
1699 pic16_InlinepCode();
1700 pic16_AnalyzepCode('*');
1703 if(pic16_debug_verbose)
1706 /* now put it all together into the assembler file */
1707 /* create the assembler file name */
1708 if((noAssemble || options.c1mode) && fullDstFileName) {
1709 sprintf (buffer, fullDstFileName);
1711 sprintf (buffer, dstFileName);
1712 strcat (buffer, ".asm");
1715 if(!(asmFile = fopen (buffer, "w"))) {
1716 werror (E_FILE_OPEN_ERR, buffer);
1720 /* initial comments */
1721 pic16initialComments (asmFile);
1723 /* print module name */
1725 fprintf(asmFile, "\t.file\t\"%s\"\n", fullSrcFileName);
1727 /* Let the port generate any global directives, etc. */
1728 if(port->genAssemblerPreamble) {
1729 port->genAssemblerPreamble(asmFile);
1732 /* Put all variables into a cblock */
1733 pic16_AnalyzeBanking();
1736 if(pic16_options.opt_flags & OF_LR_SUPPORT) {
1737 pic16_OptimizeLocalRegs();
1741 /* remove redundant BANKSELs -- added by RN 2005-01-17 */
1742 if(pic16_options.opt_banksel > 1) {
1743 pic16_OptimizeBanksel();
1746 /* turn GOTOs into BRAs -- added by RN 2004-11-16 */
1747 if(pic16_options.opt_flags & OF_OPTIMIZE_GOTO) {
1748 pic16_OptimizeJumps();
1751 /* print the extern variables to this module */
1752 pic16_printExterns(asmFile);
1754 /* print the global variables in this module */
1755 pic16printPublics (asmFile);
1757 pic16_writeUsedRegs(asmFile);
1760 /* no xdata in pic */
1761 /* if external stack then reserve space of it */
1762 if(mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1763 fprintf (asmFile, "%s", iComments2);
1764 fprintf (asmFile, "; external stack \n");
1765 fprintf (asmFile, "%s", iComments2);
1766 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1767 fprintf (asmFile,";\t.ds 256\n");
1772 /* no xdata in pic */
1773 /* copy xtern ram data */
1774 fprintf (asmFile, "%s", iComments2);
1775 fprintf (asmFile, "; external ram data\n");
1776 fprintf (asmFile, "%s", iComments2);
1777 copyFile (asmFile, xdata->oFile);
1781 /* copy the bit segment */
1782 fprintf (asmFile, "%s", iComments2);
1783 fprintf (asmFile, "; bit data\n");
1784 fprintf (asmFile, "%s", iComments2);
1785 copyFile (asmFile, bit->oFile);
1788 /* copy the interrupt vector table */
1789 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1790 fprintf (asmFile, "\n%s", iComments2);
1791 fprintf (asmFile, "; interrupt vector \n");
1792 fprintf (asmFile, "%s", iComments2);
1793 copyFile (asmFile, vFile);
1796 /* copy global & static initialisations */
1797 fprintf (asmFile, "\n%s", iComments2);
1798 fprintf (asmFile, "; global & static initialisations\n");
1799 fprintf (asmFile, "%s", iComments2);
1801 if(pic16_debug_verbose)
1802 fprintf(asmFile, "; A code from now on!\n");
1804 pic16_copypCode(asmFile, 'A');
1806 if(pic16_options.no_crt) {
1807 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1808 fprintf(asmFile, "\tcode\n");
1809 fprintf(asmFile,"__sdcc_gsinit_startup:\n");
1813 // copyFile (stderr, code->oFile);
1815 fprintf(asmFile, "; I code from now on!\n");
1816 pic16_copypCode(asmFile, 'I');
1818 if(pic16_debug_verbose)
1819 fprintf(asmFile, "; dbName from now on!\n");
1821 pic16_copypCode(asmFile, statsg->dbName);
1823 if(pic16_options.no_crt) {
1824 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
1825 fprintf (asmFile,"\tgoto\t__sdcc_program_startup\n");
1829 if(pic16_debug_verbose)
1830 fprintf(asmFile, "; X code from now on!\n");
1832 pic16_copypCode(asmFile, 'X');
1834 if(pic16_debug_verbose)
1835 fprintf(asmFile, "; M code from now on!\n");
1837 pic16_copypCode(asmFile, 'M');
1839 pic16_copypCode(asmFile, code->dbName);
1841 pic16_copypCode(asmFile, 'P');
1843 emitStatistics(asmFile);
1845 fprintf (asmFile,"\tend\n");