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"
39 extern symbol *interrupts[256];
40 void pic16_printIval (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p);
44 extern unsigned maxInterrupts;
45 extern int maxRegBank;
47 extern char *VersionString;
48 extern FILE *codeOutFile;
49 extern set *tmpfileSet;
50 extern set *tmpfileNameSet;
51 extern char *iComments1;
52 extern char *iComments2;
55 extern unsigned long pFile_isize;
57 extern unsigned long pic16_countInstructions();
58 set *pic16_localFunctions = NULL;
59 set *rel_idataSymSet=NULL;
60 set *fix_idataSymSet=NULL;
62 extern DEFSETFUNC (closeTmpFiles);
63 extern DEFSETFUNC (rmTmpFiles);
65 extern void pic16_AnalyzeBanking (void);
66 extern void pic16_OptimizeJumps ();
67 extern void pic16_OptimizeBanksel ();
68 extern void copyFile (FILE * dest, FILE * src);
69 extern void pic16_InlinepCode(void);
70 extern void pic16_writeUsedRegs(FILE *);
72 extern void initialComments (FILE * afile);
73 extern void printPublics (FILE * afile);
75 void pic16_pCodeInitRegisters(void);
76 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
77 extern void pic16_pCodeConstString(char *name, char *value);
80 /*-----------------------------------------------------------------*/
81 /* aopLiteral - string from a literal value */
82 /*-----------------------------------------------------------------*/
83 unsigned int pic16aopLiteral (value *val, int offset)
90 /* if it is a float then it gets tricky */
91 /* otherwise it is fairly simple */
92 if (!(IS_FLOAT(val->type) || IS_FIXED(val->type))) {
93 unsigned long v = (unsigned long) floatFromVal(val);
95 return ( (v >> (offset * 8)) & 0xff);
98 if(IS_FIXED16X16(val->type)) {
99 unsigned long v = (unsigned long)fixed16x16FromDouble( 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 = 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); /* breaks char* const arr[] = {&c, &c, &c}; */
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); /* might break char* const arr[] = {...}; */
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 (lilist && lilist->next) &&
807 (IS_BITFIELD(lsym->next->type)) &&
808 (SPEC_BSTR(lsym->next->etype)))) break;
810 lilist = lilist->next;
814 pic16_emitDB(BYTE_IN_LONG(ival, 0), ptype, p);
818 pic16_emitDB(BYTE_IN_LONG(ival, 0), ptype, p);
819 pic16_emitDB(BYTE_IN_LONG(ival, 1), ptype, p);
822 case 4: /* EEP: why is this db and not dw? */
823 pic16_emitDB(BYTE_IN_LONG(ival, 0), ptype, p);
824 pic16_emitDB(BYTE_IN_LONG(ival, 1), ptype, p);
825 pic16_emitDB(BYTE_IN_LONG(ival, 2), ptype, p);
826 pic16_emitDB(BYTE_IN_LONG(ival, 3), ptype, p);
829 /* VR - only 1,2,4 size long can be handled???? Why? */
830 fprintf(stderr, "%s:%d: unhandled case. Contact author.\n", __FILE__, __LINE__);
838 /*-----------------------------------------------------------------*/
839 /* printIvalStruct - generates initial value for structures */
840 /*-----------------------------------------------------------------*/
841 void pic16_printIvalStruct (symbol * sym, sym_link * type,
842 initList * ilist, char ptype, void *p)
845 initList *iloop = NULL;
849 fprintf(stderr, "%s\n",__FUNCTION__);
852 sflds = SPEC_STRUCT (type)->fields;
855 if (ilist->type != INIT_DEEP) {
856 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
860 iloop = ilist->init.deep;
863 for (; (sflds && iloop); sflds = sflds->next, iloop = (iloop ? iloop->next : NULL)) {
864 // fprintf(stderr, "%s:%d sflds: %p\tiloop = %p\n", __FILE__, __LINE__, sflds, iloop);
865 if (IS_BITFIELD(sflds->type)) {
866 pic16_printIvalBitFields(&sflds, &iloop, ptype, p);
868 pic16_printIval (sym, sflds->type, iloop, ptype, p);
872 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
877 /*-----------------------------------------------------------------*/
878 /* printIvalUnion - generates initial value for unions */
879 /*-----------------------------------------------------------------*/
880 void pic16_printIvalUnion (symbol * sym, sym_link * type,
881 initList * ilist, char ptype, void *p)
884 initList *iloop = NULL;
889 fprintf(stderr, "%s\n",__FUNCTION__);
901 if (type) size = SPEC_STRUCT(type)->size;
903 if (i == 1 && size >= 0 && size <= sizeof(long))
905 unsigned long val = (unsigned long)floatFromVal(list2val(ilist));
908 pic16_emitDB(val, ptype, p);
914 fprintf( stderr, "INCOMPLETE SUPPORT FOR INITIALIZED union---FALLING BACK TO struct\n" );
915 fprintf( stderr, "This is a bug. Please file a bug-report with your source attached.\n" );
916 pic16_printIvalStruct( sym, type, ilist, ptype, p );
920 pic16_isUnion( symbol *sym, sym_link *type )
922 if (type && SPEC_STRUCT(type)->type == UNION) return 1;
926 /*--------------------------------------------------------------------------*/
927 /* pic16_printIvalCharPtr - generates initial values for character pointers */
928 /*--------------------------------------------------------------------------*/
929 int pic16_printIvalCharPtr (symbol * sym, sym_link * type, value * val, char ptype, void *p)
933 /* PENDING: this is _very_ mcs51 specific, including a magic
935 It's also endin specific.
937 VR - Attempting to port this function to pic16 port - 8-Jun-2004
942 fprintf(stderr, "%s\n",__FUNCTION__);
945 size = getSize (type);
947 if (val->name && strlen (val->name))
949 if (size == 1) /* This appears to be Z80 specific?? */
951 pic16_emitDS(val->name, ptype, p);
955 pic16_printPointerType (val->name, ptype, p);
960 if (IS_PTR (val->type)) {
961 type = DCL_TYPE (val->type);
963 type = PTR_TYPE (SPEC_OCLS (val->etype));
965 if (val->sym && val->sym->isstrlit) {
966 // this is a literal string
969 pic16_printGPointerType(val->name, type, ptype, p);
973 fprintf (stderr, "*** internal error: unknown size in "
974 "printIvalCharPtr.\n");
980 // these are literals assigned to pointers
984 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
987 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
988 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
991 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
992 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
993 pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
1001 if (val->sym && val->sym->isstrlit) { // && !isinSet(statsg->syms, val->sym)) {
1002 if(ptype == 'p' && !isinSet(statsg->syms, val->sym))addSet (&statsg->syms, val->sym);
1003 else if(ptype == 'f' /*&& !isinSet(rel_idataSymSet, val->sym)*/)addSet(&rel_idataSymSet, val->sym);
1009 /*-----------------------------------------------------------------------*/
1010 /* pic16_printIvalFuncPtr - generate initial value for function pointers */
1011 /*-----------------------------------------------------------------------*/
1012 void pic16_printIvalFuncPtr (sym_link * type, initList * ilist, char ptype, void *p)
1019 fprintf(stderr, "%s\n",__FUNCTION__);
1023 val = list2val (ilist);
1025 val = valCastLiteral(type, 0.0);
1028 // an error has been thrown already
1032 if (IS_LITERAL(val->etype)) {
1033 if (compareType(type, val->etype) == 0) {
1034 werrorfl (ilist->filename, ilist->lineno, E_INCOMPAT_TYPES);
1035 printFromToType (val->type, type);
1037 pic16_printIvalCharPtr (NULL, type, val, ptype, p);
1041 /* check the types */
1042 if ((dLvl = compareType (val->type, type->next)) <= 0)
1044 pic16_emitDB(0x00, ptype, p);
1048 /* now generate the name */
1050 pic16_printGPointerType (val->name, DCL_TYPE(val->type), ptype, p);
1052 pic16_printGPointerType (val->sym->rname, DCL_TYPE(val->type), ptype, p);
1054 if(IS_FUNC(val->sym->type) && !val->sym->used && !IS_STATIC(val->sym->etype)) {
1056 if(!checkSym(publics, val->sym))
1057 if(checkAddSym(&externs, val->sym) && (ptype == 'f')) {
1058 /* this has not been declared as extern
1059 * so declare it as a 'late extern' just after the symbol */
1060 fprintf((FILE *)p, ";\tdeclare symbol as extern\n");
1061 fprintf((FILE *)p, "\textern\t%s\n", val->sym->rname);
1062 fprintf((FILE *)p, ";\tcontinue variable declaration\n");
1071 /*-----------------------------------------------------------------*/
1072 /* pic16_printIvalPtr - generates initial value for pointers */
1073 /*-----------------------------------------------------------------*/
1074 void pic16_printIvalPtr (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p)
1080 fprintf(stderr, "%s:%d initialising pointer: %s size: %d\n", __FILE__, __LINE__,
1081 sym->rname, getSize(sym->type));
1085 if (ilist && (ilist->type == INIT_DEEP))
1086 ilist = ilist->init.deep;
1088 /* function pointer */
1089 if (IS_FUNC (type->next))
1091 pic16_printIvalFuncPtr (type, ilist, ptype, p);
1095 if (!(val = pic16_initPointer (ilist, type)))
1098 /* if character pointer */
1099 if (IS_CHAR (type->next))
1100 if (pic16_printIvalCharPtr (sym, type, val, ptype, p))
1103 /* check the type */
1104 if (compareType (type, val->type) == 0) {
1105 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
1106 printFromToType (val->type, type);
1109 /* if val is literal */
1110 if (IS_LITERAL (val->etype))
1112 switch (getSize (type))
1115 pic16_emitDB((unsigned int)floatFromVal(val) & 0xff, ptype, p);
1118 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
1119 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
1122 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
1123 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
1124 pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
1127 fprintf(stderr, "%s:%d size = %d\n", __FILE__, __LINE__, getSize(type));
1134 size = getSize (type);
1136 if (size == 1) /* Z80 specific?? */
1138 pic16_emitDS(val->name, ptype, p);
1142 pic16_printPointerType (val->name, ptype, p);
1146 pic16_printGPointerType (val->name, (IS_PTR(type)?DCL_TYPE(type):PTR_TYPE(SPEC_OCLS(sym->etype))),
1155 /*-----------------------------------------------------------------*/
1156 /* pic16_printIval - generates code for initial value */
1157 /*-----------------------------------------------------------------*/
1158 void pic16_printIval (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p)
1166 fprintf(stderr, "%s:%d generating init for %s\n", __FILE__, __LINE__, sym->name);
1167 fprintf(stderr, "%s: IS_STRUCT: %d IS_ARRAY: %d IS_PTR: %d IS_SPEC: %d\n", sym->name,
1168 IS_STRUCT(type), IS_ARRAY(type), IS_PTR(type), IS_SPEC(type));
1171 /* if structure then */
1172 if (IS_STRUCT (type))
1174 if (pic16_isUnion(sym, type))
1176 //fprintf(stderr,"%s union\n",__FUNCTION__);
1177 pic16_printIvalUnion (sym, type, ilist, ptype, p);
1179 //fprintf(stderr,"%s struct\n",__FUNCTION__);
1180 pic16_printIvalStruct (sym, type, ilist, ptype, p);
1185 /* if this is an array */
1186 if (IS_ARRAY (type))
1188 // fprintf(stderr,"%s array\n",__FUNCTION__);
1189 pic16_printIvalArray (sym, type, ilist, ptype, p);
1196 // not an aggregate, ilist must be a node
1197 if (ilist->type!=INIT_NODE) {
1198 // or a 1-element list
1199 if (ilist->init.deep->next) {
1200 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar",
1203 ilist=ilist->init.deep;
1208 // and the type must match
1209 itype=ilist->init.node->ftype;
1211 if (compareType(type, itype)==0) {
1212 // special case for literal strings
1213 if (IS_ARRAY (itype) && IS_CHAR (getSpec(itype)) &&
1214 // which are really code pointers
1215 IS_PTR(type) && DCL_TYPE(type)==CPOINTER) {
1218 // werrorfl (ilist->filename, ilist->lineno, E_TYPE_MISMATCH, "assignment", " ");
1219 // printFromToType(itype, type);
1226 /* if this is a pointer */
1229 // fprintf(stderr,"%s pointer\n",__FUNCTION__);
1230 pic16_printIvalPtr (sym, type, ilist, ptype, p);
1235 /* if type is SPECIFIER */
1238 // fprintf(stderr,"%s spec\n",__FUNCTION__);
1239 pic16_printIvalType (sym, type, ilist, ptype, p);
1244 int PIC16_IS_CONFIG_ADDRESS(int address)
1246 return ((address >= pic16->cwInfo.confAddrStart && address <= pic16->cwInfo.confAddrEnd));
1249 int PIC16_IS_IDLOC_ADDRESS(int address)
1251 return ((address >= pic16->idInfo.idAddrStart && address <= pic16->idInfo.idAddrEnd));
1254 /* wrapper function for the above */
1255 int PIC16_IS_HWREG_ADDRESS(int address)
1257 return (PIC16_IS_CONFIG_ADDRESS(address) || PIC16_IS_IDLOC_ADDRESS(address));
1261 /*-----------------------------------------------------------------*/
1262 /* emitStaticSeg - emitcode for the static segment */
1263 /*-----------------------------------------------------------------*/
1265 pic16emitStaticSeg (memmap * map)
1268 static int didcode=0;
1270 //fprintf(stderr, "%s\n",__FUNCTION__);
1274 /* for all variables in this segment do */
1275 for (sym = setFirstItem (map->syms); sym;
1276 sym = setNextItem (map->syms))
1280 fprintf(stderr, "%s\t%s: sym: %s\tused: %d\tSPEC_ABSA: %d\tSPEC_AGGREGATE: %d\tCODE: %d\n\
1281 CODESPACE: %d\tCONST: %d\tPTRCONST: %d\tSPEC_CONST: %d\n", __FUNCTION__,
1282 map->sname, sym->name, sym->used, SPEC_ABSA(sym->etype), IS_AGGREGATE(sym->type),
1283 IS_CODE(sym->etype), IN_CODESPACE( SPEC_OCLS(sym->etype)), IS_CONSTANT(sym->etype),
1284 IS_PTR_CONST(sym->etype), SPEC_CONST(sym->etype));
1285 printTypeChain( sym->type, stderr );
1286 fprintf(stderr, "\n");
1289 if(SPEC_ABSA(sym->etype) && PIC16_IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype))) {
1290 pic16_assignConfigWordValue(SPEC_ADDR(sym->etype),
1291 (int) floatFromVal(list2val(sym->ival)));
1296 if(SPEC_ABSA(sym->etype) && PIC16_IS_IDLOC_ADDRESS(SPEC_ADDR(sym->etype))) {
1297 pic16_assignIdByteValue(SPEC_ADDR(sym->etype),
1298 (char) floatFromVal(list2val(sym->ival)));
1303 /* if it is "extern" then do nothing */
1304 if (IS_EXTERN (sym->etype)/* && !SPEC_ABSA(sym->etype)*/) {
1305 checkAddSym(&externs, sym);
1309 /* if it is not static add it to the public
1311 if (!IS_STATIC (sym->etype)) {
1312 /* do not emit if it is a config word declaration */
1313 checkAddSym(&publics, sym);
1316 /* print extra debug info if required */
1317 if (options.debug || sym->level == 0) {
1318 /* NOTE to me - cdbFile may be null in which case,
1319 * the sym name will be printed to stdout. oh well */
1320 debugFile->writeSymbol(sym);
1323 /* if it has an absolute address */
1324 if (SPEC_ABSA (sym->etype)) {
1325 // fprintf(stderr, "%s:%d spec_absa is true for symbol: %s\n",
1326 // __FILE__, __LINE__, sym->name);
1328 /* if it has an initial value */
1336 /* symbol has absolute address and initial value */
1338 resolveIvalSym (sym->ival, sym->type);
1339 asym = newSymbol(sym->rname, 0);
1340 abSym = Safe_calloc(1, sizeof(absSym));
1341 strcpy(abSym->name, sym->rname);
1342 abSym->address = SPEC_ADDR( sym->etype );
1343 addSet(&absSymSet, abSym);
1345 pb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute Ival"));
1346 pic16_addpBlock(pb);
1348 pcf = pic16_newpCodeFunction(moduleName, asym->name);
1349 PCF(pcf)->absblock = 1;
1351 pic16_addpCode2pBlock(pb,pcf);
1352 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
1353 //fprintf(stderr, "%s:%d [1] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1354 pic16_printIval(sym, sym->type, sym->ival, 'p', (void *)pb);
1355 pic16_flushDB('p', (void *)pb);
1357 pic16_addpCode2pBlock(pb, pic16_newpCodeFunction(NULL, NULL));
1363 /* symbol has absolute address but no initial value */
1365 /* allocate space */
1366 fprintf (code->oFile, "%s:\n", sym->rname);
1368 /* special case for character strings */
1369 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1370 SPEC_CVAL (sym->etype).v_char) {
1372 // fprintf(stderr, "%s:%d printing code string from %s\n", __FILE__, __LINE__, sym->rname);
1374 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
1376 fprintf (stderr, "%s:%u(%s): do not know how to intialize symbol %s\n", __FILE__, __LINE__, __FUNCTION__, sym->rname);
1382 // fprintf(stderr, "%s:%d spec_absa is false for symbol: %s\n",
1383 // __FILE__, __LINE__, sym->name);
1386 /* if it has an initial value */
1390 /* symbol doesn't have absolute address but has initial value */
1391 fprintf (code->oFile, "%s:\n", sym->rname);
1393 resolveIvalSym (sym->ival, sym->type);
1395 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block for Ival"));
1396 pic16_addpBlock(pb);
1399 /* make sure that 'code' directive is emitted before, once */
1400 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir("code", NULL));
1405 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
1406 //fprintf(stderr, "%s:%d [2] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1407 pic16_printIval(sym, sym->type, sym->ival, 'p', (void *)pb);
1408 pic16_flushDB('p', (void *)pb);
1412 /* symbol doesn't have absolute address and no initial value */
1413 /* allocate space */
1414 // fprintf(stderr, "%s:%d [3] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1415 fprintf (code->oFile, "%s:\n", sym->rname);
1416 /* special case for character strings */
1417 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1418 SPEC_CVAL (sym->etype).v_char) {
1420 // fprintf(stderr, "%s:%d printing code string for %s\n", __FILE__, __LINE__, sym->rname);
1422 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
1433 /*-----------------------------------------------------------------*/
1434 /* pic16_emitConfigRegs - emits the configuration registers */
1435 /*-----------------------------------------------------------------*/
1436 void pic16_emitConfigRegs(FILE *of)
1440 for(i=0;i<=(pic16->cwInfo.confAddrEnd-pic16->cwInfo.confAddrStart);i++)
1441 if(pic16->cwInfo.crInfo[i].emit) //mask != -1)
1442 fprintf (of, "\t__config 0x%x, 0x%hhx\n",
1443 pic16->cwInfo.confAddrStart+i,
1444 pic16->cwInfo.crInfo[i].value);
1447 void pic16_emitIDRegs(FILE *of)
1451 for(i=0;i<=(pic16->idInfo.idAddrEnd-pic16->idInfo.idAddrStart);i++)
1452 if(pic16->idInfo.irInfo[i].emit)
1453 fprintf (of, "\t__idlocs 0x%06x, 0x%hhx\n",
1454 pic16->idInfo.idAddrStart+i,
1455 pic16->idInfo.irInfo[i].value);
1462 /* no special considerations for the following
1463 data, idata & bit & xdata */
1464 pic16emitRegularMap (data, TRUE, TRUE);
1465 pic16emitRegularMap (idata, TRUE, TRUE);
1466 pic16emitRegularMap (bit, TRUE, FALSE);
1467 pic16emitRegularMap (xdata, TRUE, TRUE);
1468 pic16emitRegularMap (sfr, FALSE, FALSE);
1469 pic16emitRegularMap (sfrbit, FALSE, FALSE);
1470 pic16emitRegularMap (code, TRUE, FALSE);
1471 pic16emitStaticSeg (statsg);
1474 /*-----------------------------------------------------------------*/
1475 /* createInterruptVect - creates the interrupt vector */
1476 /*-----------------------------------------------------------------*/
1478 pic16createInterruptVect (FILE * vFile)
1480 /* if the main is only a prototype ie. no body then do nothing */
1482 if (!IFFUNC_HASBODY(mainf->type)) {
1483 /* if ! compile only then main function should be present */
1484 if (!options.cc_only)
1490 if((!pic16_options.omit_ivt) || (pic16_options.omit_ivt && pic16_options.leave_reset)) {
1491 fprintf (vFile, ";\t.area\t%s\n", CODE_NAME);
1492 fprintf(vFile, ".intvecs\tcode\t0x%06x\n", pic16_options.ivt_loc);
1494 /* this is an overkill since WE are the port,
1495 * and we know if we have a genIVT function! */
1497 port->genIVT(vFile, interrupts, maxInterrupts);
1505 /*-----------------------------------------------------------------*/
1506 /* pic16initialComments - puts in some initial comments */
1507 /*-----------------------------------------------------------------*/
1509 pic16initialComments (FILE * afile)
1511 initialComments (afile);
1512 fprintf (afile, "; PIC16 port for the Microchip 16-bit core micros\n");
1514 fprintf (afile, "; * Extended Instruction Set\n");
1516 if(pic16_mplab_comp)
1517 fprintf(afile, "; * MPLAB/MPASM/MPASMWIN/MPLINK compatibility mode enabled\n");
1518 fprintf (afile, iComments2);
1521 fprintf (afile, "\n\t.ident \"SDCC version %s #%s [pic16 port]%s\"\n",
1522 SDCC_VERSION_STR, getBuildNumber(), (!xinst?"":" {extended}") );
1527 pic16_stringInSet(const char *str, set **world, int autoAdd)
1534 for (s = setFirstItem(*world); s; s = setNextItem(*world))
1537 if (0 == strcmp(s, str)) return 1;
1541 if (autoAdd) addSet(world, Safe_strdup(str));
1546 pic16_emitSymbolIfNew(FILE *file, const char *fmt, const char *sym, int checkLocals)
1548 static set *emitted = NULL;
1550 if (!pic16_stringInSet(sym, &emitted, 1)) {
1551 /* sym was not in emittedSymbols */
1552 if (!checkLocals || !pic16_stringInSet(sym, &pic16_localFunctions, 0)) {
1553 /* sym is not a locally defined function---avoid bug #1443651 */
1554 fprintf( file, fmt, sym );
1561 /*-----------------------------------------------------------------*/
1562 /* printPublics - generates global declarations for publics */
1563 /*-----------------------------------------------------------------*/
1565 pic16printPublics (FILE *afile)
1569 fprintf (afile, "\n%s", iComments2);
1570 fprintf (afile, "; public variables in this module\n");
1571 fprintf (afile, "%s", iComments2);
1573 for(sym = setFirstItem (publics); sym; sym = setNextItem (publics))
1575 if(!IS_STATIC(sym->etype))
1576 pic16_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1579 /*-----------------------------------------------------------------*/
1580 /* printExterns - generates extern declarations for externs */
1581 /*-----------------------------------------------------------------*/
1583 pic16_printExterns(FILE *afile)
1587 /* print nothing if no externs to declare */
1588 if(!elementsInSet(externs) && !elementsInSet(pic16_builtin_functions))
1591 fprintf(afile, "\n%s", iComments2);
1592 fprintf(afile, "; extern variables in this module\n");
1593 fprintf(afile, "%s", iComments2);
1595 for(sym = setFirstItem(externs); sym; sym = setNextItem(externs))
1596 pic16_emitSymbolIfNew(afile, "\textern %s\n", sym->rname, 1);
1598 for(sym = setFirstItem(pic16_builtin_functions); sym; sym = setNextItem(pic16_builtin_functions))
1599 pic16_emitSymbolIfNew(afile, "\textern _%s\n", sym->name, 1);
1602 /*-----------------------------------------------------------------*/
1603 /* emitOverlay - will emit code for the overlay stuff */
1604 /*-----------------------------------------------------------------*/
1606 pic16emitOverlay (FILE * afile)
1610 if (!elementsInSet (ovrSetSets))
1611 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name);
1613 /* for each of the sets in the overlay segment do */
1614 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1615 ovrset = setNextItem (ovrSetSets))
1620 if (elementsInSet (ovrset))
1622 /* this dummy area is used to fool the assembler
1623 otherwise the assembler will append each of these
1624 declarations into one chunk and will not overlay
1626 fprintf (afile, ";\t.area _DUMMY\n");
1627 /* output the area informtion */
1628 fprintf (afile, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1631 for (sym = setFirstItem (ovrset); sym;
1632 sym = setNextItem (ovrset))
1635 /* if extern then do nothing */
1636 if (IS_EXTERN (sym->etype))
1639 /* if allocation required check is needed
1640 then check if the symbol really requires
1641 allocation only for local variables */
1642 if (!IS_AGGREGATE (sym->type) &&
1643 !(sym->_isparm && !IS_REGPARM (sym->etype))
1644 && !sym->allocreq && sym->level)
1647 /* if global variable & not static or extern
1648 and addPublics allowed then add it to the public set */
1649 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1650 && !IS_STATIC (sym->etype)) {
1651 // fprintf(stderr, "%s:%d %s accessed\n", __FILE__, __LINE__, __FUNCTION__);
1652 checkAddSym(&publics, sym);
1653 // addSetHead (&publics, sym);
1656 /* if extern then do nothing or is a function
1658 if (IS_FUNC (sym->type))
1662 /* if is has an absolute address then generate
1663 an equate for this no need to allocate space */
1664 if (SPEC_ABSA (sym->etype))
1667 if (options.debug || sym->level == 0)
1668 fprintf (afile, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1670 fprintf (afile, "%s\t=\t0x%04x\n",
1672 SPEC_ADDR (sym->etype));
1676 if (options.debug || sym->level == 0)
1677 fprintf (afile, "==.\n");
1679 /* allocate space */
1680 fprintf (afile, "%s:\n", sym->rname);
1681 fprintf (afile, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1688 void emitStatistics(FILE *asmFile)
1690 unsigned long isize, udsize, ramsize;
1691 statistics.isize = pic16_countInstructions();
1692 isize = (statistics.isize >= 0) ? statistics.isize : 0;
1693 udsize = (statistics.udsize >= 0) ? statistics.udsize : 0;
1694 ramsize = pic16 ? pic16->RAMsize : 0x200;
1695 ramsize -= 256; /* ignore access bank and SFRs */
1696 if (ramsize == 0) ramsize = 64; /* prevent division by zero (below) */
1698 fprintf (asmFile, "\n\n; Statistics:\n");
1699 fprintf (asmFile, "; code size:\t%5ld (0x%04lx) bytes (%5.2f%%)\n; \t%5ld (0x%04lx) words\n",
1700 isize, isize, (isize*100.0)/(128UL << 10),
1701 isize>>1, isize>>1);
1702 fprintf (asmFile, "; udata size:\t%5ld (0x%04lx) bytes (%5.2f%%)\n",
1703 udsize, udsize, (udsize*100.0) / (1.0 * ramsize));
1704 fprintf (asmFile, "; access size:\t%5ld (0x%04lx) bytes\n",
1705 statistics.intsize, statistics.intsize);
1707 fprintf (asmFile, "\n\n");
1712 /*-----------------------------------------------------------------*/
1713 /* glue - the final glue that hold the whole thing together */
1714 /*-----------------------------------------------------------------*/
1720 FILE *ovrFile = tempfile();
1722 mainf = newSymbol ("main", 0);
1725 mainf = findSymWithLevel(SymbolTab, mainf);
1727 addSetHead(&tmpfileSet,ovrFile);
1728 pic16_pCodeInitRegisters();
1730 if(pic16_options.no_crt && mainf && IFFUNC_HASBODY(mainf->type)) {
1731 pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
1733 pic16_addpBlock(pb);
1735 /* entry point @ start of CSEG */
1736 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup",-1));
1739 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1740 pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("_stack_end"))));
1741 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1742 pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("_stack_end"))));
1745 /* put in the call to main */
1746 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
1748 if (options.mainreturn) {
1749 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
1750 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
1752 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
1753 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
1757 /* At this point we've got all the code in the form of pCode structures */
1758 /* Now it needs to be rearranged into the order it should be placed in the */
1761 pic16_movepBlock2Head('P'); // Last
1762 pic16_movepBlock2Head(code->dbName);
1763 pic16_movepBlock2Head('X');
1764 pic16_movepBlock2Head(statsg->dbName); // First
1766 /* print the global struct definitions */
1769 /* PENDING: this isnt the best place but it will do */
1770 if (port->general.glue_up_main) {
1771 /* create the interrupt vector table */
1772 pic16createInterruptVect (vFile);
1775 addSetHead(&tmpfileSet,vFile);
1777 /* emit code for the all the variables declared */
1780 /* do the overlay segments */
1781 pic16emitOverlay(ovrFile);
1782 pic16_AnalyzepCode('*');
1785 if(pic16_options.dumpcalltree) {
1788 sprintf(buffer, dstFileName);
1789 strcat(buffer, ".calltree");
1790 cFile = fopen(buffer, "w");
1791 pic16_printCallTree( cFile );
1796 pic16_InlinepCode();
1797 pic16_AnalyzepCode('*');
1800 if(pic16_debug_verbose)
1803 /* now put it all together into the assembler file */
1804 /* create the assembler file name */
1805 if((noAssemble || options.c1mode) && fullDstFileName) {
1806 sprintf (buffer, fullDstFileName);
1808 sprintf (buffer, dstFileName);
1809 strcat (buffer, ".asm");
1812 if(!(asmFile = fopen (buffer, "w"))) {
1813 werror (E_FILE_OPEN_ERR, buffer);
1817 /* initial comments */
1818 pic16initialComments (asmFile);
1820 /* print module name */
1822 fprintf(asmFile, "\t.file\t\"%s\"\n", fullSrcFileName);
1824 /* Let the port generate any global directives, etc. */
1825 if(port->genAssemblerPreamble) {
1826 port->genAssemblerPreamble(asmFile);
1829 /* Put all variables into a cblock */
1830 pic16_AnalyzeBanking();
1833 if(pic16_options.opt_flags & OF_LR_SUPPORT) {
1834 pic16_OptimizeLocalRegs();
1838 /* remove redundant BANKSELs -- added by RN 2005-01-17 */
1839 if(pic16_options.opt_banksel > 1) {
1840 pic16_OptimizeBanksel();
1843 /* turn GOTOs into BRAs -- added by RN 2004-11-16 */
1844 if(pic16_options.opt_flags & OF_OPTIMIZE_GOTO) {
1845 pic16_OptimizeJumps();
1848 /* print the global variables in this module */
1849 pic16printPublics (asmFile);
1851 /* print the extern variables to this module */
1852 pic16_printExterns(asmFile);
1854 pic16_writeUsedRegs(asmFile);
1857 /* no xdata in pic */
1858 /* if external stack then reserve space of it */
1859 if(mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1860 fprintf (asmFile, "%s", iComments2);
1861 fprintf (asmFile, "; external stack \n");
1862 fprintf (asmFile, "%s", iComments2);
1863 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1864 fprintf (asmFile,";\t.ds 256\n");
1869 /* no xdata in pic */
1870 /* copy xtern ram data */
1871 fprintf (asmFile, "%s", iComments2);
1872 fprintf (asmFile, "; external ram data\n");
1873 fprintf (asmFile, "%s", iComments2);
1874 copyFile (asmFile, xdata->oFile);
1878 /* copy the bit segment */
1879 fprintf (asmFile, "%s", iComments2);
1880 fprintf (asmFile, "; bit data\n");
1881 fprintf (asmFile, "%s", iComments2);
1882 copyFile (asmFile, bit->oFile);
1885 /* copy the interrupt vector table */
1886 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1887 fprintf (asmFile, "\n%s", iComments2);
1888 fprintf (asmFile, "; interrupt vector \n");
1889 fprintf (asmFile, "%s", iComments2);
1890 copyFile (asmFile, vFile);
1893 /* copy global & static initialisations */
1894 fprintf (asmFile, "\n%s", iComments2);
1895 fprintf (asmFile, "; global & static initialisations\n");
1896 fprintf (asmFile, "%s", iComments2);
1898 if(pic16_debug_verbose)
1899 fprintf(asmFile, "; A code from now on!\n");
1901 pic16_copypCode(asmFile, 'A');
1903 if(pic16_options.no_crt) {
1904 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1905 fprintf(asmFile, "\tcode\n");
1906 fprintf(asmFile,"__sdcc_gsinit_startup:\n");
1910 // copyFile (stderr, code->oFile);
1912 fprintf(asmFile, "; I code from now on!\n");
1913 pic16_copypCode(asmFile, 'I');
1915 if(pic16_debug_verbose)
1916 fprintf(asmFile, "; dbName from now on!\n");
1918 pic16_copypCode(asmFile, statsg->dbName);
1920 if(pic16_options.no_crt) {
1921 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
1922 fprintf (asmFile,"\tgoto\t__sdcc_program_startup\n");
1926 if(pic16_debug_verbose)
1927 fprintf(asmFile, "; X code from now on!\n");
1929 pic16_copypCode(asmFile, 'X');
1931 if(pic16_debug_verbose)
1932 fprintf(asmFile, "; M code from now on!\n");
1934 pic16_copypCode(asmFile, 'M');
1936 pic16_copypCode(asmFile, code->dbName);
1938 pic16_copypCode(asmFile, 'P');
1940 emitStatistics(asmFile);
1942 fprintf (asmFile,"\tend\n");