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"
33 #include "dbuf_string.h"
37 extern symbol *interrupts[256];
38 void pic16_printIval (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p);
42 extern unsigned maxInterrupts;
44 extern char *VersionString;
45 extern struct dbuf_s *codeOutBuf;
46 extern char *iComments1;
47 extern char *iComments2;
50 extern unsigned long pFile_isize;
52 extern unsigned long pic16_countInstructions();
53 set *pic16_localFunctions = NULL;
54 set *rel_idataSymSet=NULL;
55 set *fix_idataSymSet=NULL;
57 extern DEFSETFUNC (closeTmpFiles);
58 extern DEFSETFUNC (rmTmpFiles);
60 extern void pic16_AnalyzeBanking (void);
61 extern void pic16_OptimizeJumps ();
62 extern void pic16_OptimizeBanksel ();
63 extern void pic16_InlinepCode(void);
64 extern void pic16_writeUsedRegs(FILE *);
66 extern void initialComments (FILE * afile);
67 extern void printPublics (FILE * afile);
69 void pic16_pCodeInitRegisters(void);
70 pCodeOp *pic16_popCopyReg(pCodeOpReg *pc);
71 extern void pic16_pCodeConstString(char *name, char *value);
74 /*-----------------------------------------------------------------*/
75 /* aopLiteral - string from a literal value */
76 /*-----------------------------------------------------------------*/
77 unsigned int pic16aopLiteral (value *val, int offset)
84 /* if it is a float then it gets tricky */
85 /* otherwise it is fairly simple */
86 if (!(IS_FLOAT(val->type) || IS_FIXED(val->type))) {
87 unsigned long v = ulFromVal (val);
89 return ( (v >> (offset * 8)) & 0xff);
92 if(IS_FIXED16X16(val->type)) {
93 unsigned long v = (unsigned long)fixed16x16FromDouble( floatFromVal( val ) );
95 return ( (v >> (offset * 8)) & 0xff);
98 /* it is type float */
99 fl.f = (float) floatFromVal(val);
100 #ifdef WORDS_BIGENDIAN
101 return fl.c[3-offset];
110 char tbuffer[512], *tbuf=tbuffer;;
113 /*-----------------------------------------------------------------*/
114 /* emitRegularMap - emit code for maps with no special cases */
115 /*-----------------------------------------------------------------*/
117 pic16emitRegularMap (memmap * map, bool addPublics, bool arFlag)
120 // int i, size, bitvars = 0;;
122 // fprintf(stderr, "%s:%d map name= %s\n", __FUNCTION__, __LINE__, map->sname);
125 dbuf_printf (&map->oBuf, ";\t.area\t%s\n", map->sname);
126 /* print the area name */
128 for (sym = setFirstItem (map->syms); sym; sym = setNextItem (map->syms)) {
131 fprintf(stderr, "%s\t%s: sym: %s\tused: %d\textern: %d\tstatic: %d\taggregate: %d\tregister: 0x%x\tfunction: %d\n",
133 map->sname, sym->name, sym->used, IS_EXTERN(sym->etype), IS_STATIC(sym->etype),
134 IS_AGGREGATE(sym->type), (SPEC_SCLS(sym->etype) == S_REGISTER), IS_FUNC(sym->type));
135 printTypeChain( sym->type, stderr );
136 fprintf(stderr, "\n");
139 /* if extern then add to externs */
140 if (IS_EXTERN (sym->etype)) {
141 /* reduce overhead while linking by not declaring
142 * extern unused external functions (usually declared
143 * in header files) */
144 if(IS_FUNC(sym->type) && !sym->used)continue;
146 /* make sure symbol is not in publics section */
147 if(!checkSym(publics, sym))
148 checkAddSym(&externs, sym);
152 /* if allocation required check is needed
153 * then check if the symbol really requires
154 * allocation only for local variables */
155 if (arFlag && !IS_AGGREGATE (sym->type) &&
156 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
157 !sym->allocreq && sym->level) {
159 // fprintf(stderr, "%s:%d special case, continuing...\n", __FILE__, __LINE__);
164 /* if global variable & not static or extern
165 * and addPublics allowed then add it to the public set */
166 if ((sym->used) && (sym->level == 0 ||
167 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
169 !IS_STATIC (sym->etype) && !IS_FUNC(sym->type)) {
171 checkAddSym(&publics, sym);
174 if(IS_STATIC(sym->etype)
175 && !sym->ival) /* && !sym->level*/ {
180 // debugf("adding symbol %s\n", sym->name);
181 #define SET_IMPLICIT 1
184 if(IS_STRUCT(sym->type))
188 reg = pic16_allocDirReg( operandFromSymbol( sym ));
191 for(ssym=setFirstItem(sectSyms); ssym; ssym=setNextItem(sectSyms)) {
192 if(!strcmp(ssym->name, reg->name))found=1;
196 checkAddReg(&pic16_rel_udata, reg);
199 debugf("Did find %s in pic16_rel_udata already. Check!\n", reg->name);
200 // checkAddSym(&publics, sym);
206 /* if extern then do nothing or is a function
208 if (IS_FUNC (sym->type) && !IS_STATIC(sym->etype)) {
209 if(SPEC_OCLS(sym->etype) == code) {
210 // fprintf(stderr, "%s:%d: symbol added: %s\n", __FILE__, __LINE__, sym->rname);
211 checkAddSym(&publics, sym);
216 /* if is has an absolute address then generate
217 an equate for this no need to allocate space */
218 if (SPEC_ABSA (sym->etype)) {
219 // fprintf (stderr,"; %s == 0x%04x\t\treqv= %p nRegs= %d\n",
220 // sym->name, SPEC_ADDR (sym->etype), sym->reqv, sym->regType);
222 dbuf_printf (&map->oBuf, "%s\tEQU\t0x%04x\n",
224 SPEC_ADDR (sym->etype));
226 /* emit only if it is global */
227 if(sym->level == 0) {
230 reg = pic16_dirregWithName( sym->name );
233 // fprintf(stderr, "%s:%d: implicit add of symbol = %s\n",
234 // __FUNCTION__, __LINE__, sym->name);
236 /* if IS_STRUCT is omitted the following
237 * fixes structures but break char/int etc */
239 if(IS_STRUCT(sym->type))
240 sym->implicit = 1; // mark as implicit
243 reg = pic16_allocDirReg( operandFromSymbol(sym) );
245 if(checkAddReg(&pic16_fix_udata, reg)) {
246 /* and add to globals list if not exist */
247 addSet(&publics, sym);
251 addSet(&publics, sym);
255 if(!sym->used && (sym->level == 0)) {
258 /* symbol not used, just declared probably, but its in
259 * level 0, so we must declare it fine as global */
261 // fprintf(stderr, "EXTRA symbol declaration sym= %s\n", sym->name);
264 if(IS_STRUCT(sym->type))
265 sym->implicit = 1; // mark as implicit
268 if(IS_AGGREGATE(sym->type)) {
269 reg=pic16_allocRegByName(sym->rname, getSize( sym->type ), NULL);
271 reg = pic16_allocDirReg( operandFromSymbol( sym ) );
279 fprintf(stderr, "%s:%d sym->rname: %s reg: %p reg->name: %s\n", __FILE__, __LINE__,
280 sym->rname, reg, (reg?reg->name:"<<NULL>>"));
284 for(ssym=setFirstItem(sectSyms); ssym; ssym=setNextItem(sectSyms)) {
285 if(!strcmp(ssym->name, reg->name))found=1;
289 if(checkAddReg(&pic16_rel_udata, reg)) {
290 addSetHead(&publics, sym);
299 addSetHead(&publics, sym);
304 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
305 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
306 /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
307 if (IS_BITVAR (sym->etype)) {
310 dbuf_printf (map->oBuf, "\t%s\n", sym->rname);
311 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1) {
312 for (i = 1; i < size; i++)
313 dbuf_printf (map->oBuf, "\t%s_%d\n", sym->rname, i);
316 dbuf_printf (map->oBuf, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
320 /* FIXME -- VR Fix the following, so that syms to be placed
321 * in the idata section and let linker decide about their fate */
323 /* if it has an initial value then do it only if
324 it is a global variable */
327 && ((sym->level == 0)
328 || IS_STATIC(sym->etype)) ) {
332 if(SPEC_OCLS(sym->etype)==data) {
333 fprintf(stderr, "%s: sym %s placed in data segment\n", map->sname, sym->name);
336 if(SPEC_OCLS(sym->etype)==code) {
337 fprintf(stderr, "%s: sym %s placed in code segment\n", map->sname, sym->name);
342 fprintf(stderr, "'%s': sym '%s' has initial value SPEC_ABSA: %d, IS_AGGREGATE: %d\n",
343 map->sname, sym->name, SPEC_ABSA(sym->etype), IS_AGGREGATE(sym->type));
346 if (IS_AGGREGATE (sym->type)) {
347 if(SPEC_ABSA(sym->etype))
348 addSet(&fix_idataSymSet, copySymbol(sym));
350 addSet(&rel_idataSymSet, copySymbol(sym));
351 // ival = initAggregates (sym, sym->ival, NULL);
353 if(SPEC_ABSA(sym->etype))
354 addSet(&fix_idataSymSet, copySymbol(sym));
356 addSet(&rel_idataSymSet, copySymbol(sym));
358 // ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
359 // decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
363 setAstFileLine (ival, sym->fileDef, sym->lineDef);
364 codeOutBuf = &statsg->oBuf;
366 eBBlockFromiCode (iCodeFromAst (ival));
374 /*-----------------------------------------------------------------*/
375 /* pic16_initPointer - pointer initialization code massaging */
376 /*-----------------------------------------------------------------*/
377 value *pic16_initPointer (initList * ilist, sym_link *toType)
383 return valCastLiteral(toType, 0.0);
386 expr = decorateType(resolveSymbols( list2expr (ilist) ), FALSE);
387 // expr = list2expr( ilist );
392 /* try it the old way first */
393 if (expr->etype && (val = constExprValue (expr, FALSE)))
396 /* ( ptr + constant ) */
397 if (IS_AST_OP (expr) &&
398 (expr->opval.op == '+' || expr->opval.op == '-') &&
399 IS_AST_SYM_VALUE (expr->left) &&
400 (IS_ARRAY(expr->left->ftype) || IS_PTR(expr->left->ftype)) &&
401 compareType(toType, expr->left->ftype) &&
402 IS_AST_LIT_VALUE (expr->right)) {
403 return valForCastAggr (expr->left, expr->left->ftype,
409 if (IS_AST_OP(expr) && expr->opval.op==CAST &&
410 IS_AST_OP(expr->right) && expr->right->opval.op=='&') {
411 if (compareType(toType, expr->left->ftype)!=1) {
412 werror (W_INIT_WRONG);
413 printFromToType(expr->left->ftype, toType);
419 /* no then we have to do these cludgy checks */
420 /* pointers can be initialized with address of
421 a variable or address of an array element */
422 if (IS_AST_OP (expr) && expr->opval.op == '&') {
423 /* address of symbol */
424 if (IS_AST_SYM_VALUE (expr->left) && expr->left->etype) {
425 val = AST_VALUE (expr->left);
426 val->type = newLink (DECLARATOR);
427 if(SPEC_SCLS (expr->left->etype) == S_CODE) {
428 DCL_TYPE (val->type) = CPOINTER;
429 DCL_PTR_CONST (val->type) = port->mem.code_ro;
431 else if (SPEC_SCLS (expr->left->etype) == S_XDATA)
432 DCL_TYPE (val->type) = FPOINTER;
433 else if (SPEC_SCLS (expr->left->etype) == S_XSTACK)
434 DCL_TYPE (val->type) = PPOINTER;
435 else if (SPEC_SCLS (expr->left->etype) == S_IDATA)
436 DCL_TYPE (val->type) = IPOINTER;
437 else if (SPEC_SCLS (expr->left->etype) == S_EEPROM)
438 DCL_TYPE (val->type) = EEPPOINTER;
440 DCL_TYPE (val->type) = POINTER;
442 val->type->next = expr->left->ftype;
443 val->etype = getSpec (val->type);
447 /* if address of indexed array */
448 if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
449 return valForArray (expr->left);
451 /* if address of structure element then
453 if (IS_AST_OP (expr->left) &&
454 expr->left->opval.op == '.') {
455 return valForStructElem (expr->left->left,
460 (&some_struct)->element */
461 if (IS_AST_OP (expr->left) &&
462 expr->left->opval.op == PTR_OP &&
463 IS_ADDRESS_OF_OP (expr->left->left)) {
464 return valForStructElem (expr->left->left->left,
468 /* case 3. (((char *) &a) +/- constant) */
469 if (IS_AST_OP (expr) &&
470 (expr->opval.op == '+' || expr->opval.op == '-') &&
471 IS_AST_OP (expr->left) && expr->left->opval.op == CAST &&
472 IS_AST_OP (expr->left->right) &&
473 expr->left->right->opval.op == '&' &&
474 IS_AST_LIT_VALUE (expr->right)) {
476 return valForCastAggr (expr->left->right->left,
477 expr->left->left->opval.lnk,
478 expr->right, expr->opval.op);
481 /* case 4. (char *)(array type) */
482 if (IS_CAST_OP(expr) && IS_AST_SYM_VALUE (expr->right) &&
483 IS_ARRAY(expr->right->ftype)) {
485 val = copyValue (AST_VALUE (expr->right));
486 val->type = newLink (DECLARATOR);
487 if (SPEC_SCLS (expr->right->etype) == S_CODE) {
488 DCL_TYPE (val->type) = CPOINTER;
489 DCL_PTR_CONST (val->type) = port->mem.code_ro;
491 else if (SPEC_SCLS (expr->right->etype) == S_XDATA)
492 DCL_TYPE (val->type) = FPOINTER;
493 else if (SPEC_SCLS (expr->right->etype) == S_XSTACK)
494 DCL_TYPE (val->type) = PPOINTER;
495 else if (SPEC_SCLS (expr->right->etype) == S_IDATA)
496 DCL_TYPE (val->type) = IPOINTER;
497 else if (SPEC_SCLS (expr->right->etype) == S_EEPROM)
498 DCL_TYPE (val->type) = EEPPOINTER;
500 DCL_TYPE (val->type) = POINTER;
501 val->type->next = expr->right->ftype->next;
502 val->etype = getSpec (val->type);
508 werrorfl (expr->filename, expr->lineno, E_INCOMPAT_PTYPES);
510 werror (E_INCOMPAT_PTYPES);
516 /*-----------------------------------------------------------------*/
517 /* printPointerType - generates ival for pointer type */
518 /*-----------------------------------------------------------------*/
519 void _pic16_printPointerType (const char *name, char ptype, void *p)
523 sprintf (buf, "LOW(%s)", name);
524 pic16_emitDS (buf, ptype, p);
525 sprintf (buf, "HIGH(%s)", name);
526 pic16_emitDS (buf, ptype, p);
529 /*-----------------------------------------------------------------*/
530 /* printPointerType - generates ival for pointer type */
531 /*-----------------------------------------------------------------*/
532 void pic16_printPointerType (const char *name, char ptype, void *p)
534 _pic16_printPointerType (name, ptype, p);
535 //pic16_flushDB(ptype, p); /* breaks char* const arr[] = {&c, &c, &c}; */
538 /*-----------------------------------------------------------------*/
539 /* printGPointerType - generates ival for generic pointer type */
540 /*-----------------------------------------------------------------*/
541 void pic16_printGPointerType (const char *iname, const unsigned int itype,
546 _pic16_printPointerType (iname, ptype, p);
552 sprintf (buf, "UPPER(%s)", iname);
553 pic16_emitDS (buf, ptype, p);
558 sprintf (buf, "0x80");
559 pic16_emitDS (buf, ptype, p);
563 * FPOINTER and IPOINTER are not used in pic16 port
568 debugf ("itype = %d\n", itype );
572 //pic16_flushDB(ptype, p); /* might break char* const arr[] = {...}; */
576 /* set to 0 to disable debug messages */
577 #define DEBUG_PRINTIVAL 0
579 /*-----------------------------------------------------------------*/
580 /* pic16_printIvalType - generates ival for int/char */
581 /*-----------------------------------------------------------------*/
583 pic16_printIvalType (symbol *sym, sym_link * type, initList * ilist, char ptype, void *p)
587 // fprintf(stderr, "%s for symbol %s\n",__FUNCTION__, sym->rname);
590 fprintf(stderr, "%s\n",__FUNCTION__);
594 /* if initList is deep */
595 if (ilist && ilist->type == INIT_DEEP)
596 ilist = ilist->init.deep;
598 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
599 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
602 if (!(val = list2val (ilist))) {
603 // assuming a warning has been thrown
604 val = constCharVal (0);
607 if (val->type != type) {
608 val = valCastLiteral(type, floatFromVal(val));
611 switch (getSize (type)) {
613 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
617 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
618 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
621 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
622 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
623 pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
625 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
626 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
627 pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
628 pic16_emitDB(pic16aopLiteral(val, 3), ptype, p);
633 /*--------------------------------------------------------------------*/
634 /* pic16_printIvalChar - generates initital value for character array */
635 /*--------------------------------------------------------------------*/
637 pic16_printIvalChar (symbol *sym, sym_link * type, initList * ilist, char *s, char ptype, void *p)
640 int remain, len, ilen;
646 fprintf(stderr, "%s\n",__FUNCTION__);
650 val = list2val (ilist);
652 /* if the value is a character string */
653 if(IS_ARRAY (val->type) && IS_CHAR (val->etype)) {
654 /* length of initializer string (might contain \0, so do not use strlen) */
655 ilen = DCL_ELEM(val->type);
658 DCL_ELEM (type) = ilen;
660 /* len is 0 if declartion equals initializer,
661 * >0 if declaration greater than initializer
662 * <0 if declaration less than initializer
663 * Strategy: if >0 emit 0x00 for the rest of the length,
664 * if <0 then emit only the length of declaration elements
667 len = DCL_ELEM (type) - ilen;
669 // fprintf(stderr, "%s:%d ilen = %i len = %i DCL_ELEM(type) = %i SPEC_CVAL-len = %i\n", __FILE__, __LINE__,
670 // ilen, len, DCL_ELEM(type), strlen(SPEC_CVAL(val->etype).v_char));
673 /* emit initializer */
674 for(remain=0; remain<ilen; remain++)
675 pic16_emitDB(SPEC_CVAL(val->etype).v_char[ remain ], ptype, p);
677 /* fill array with 0x00 */
679 pic16_emitDB(0x00, ptype, p);
682 werror (W_EXCESS_INITIALIZERS, "array of chars", sym->name, sym->lineDef);
684 for(remain=0; remain<DCL_ELEM (type); remain++)
685 pic16_emitDB(SPEC_CVAL(val->etype).v_char[ remain ], ptype, p);
689 // if((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0) {
694 for(remain=0; remain<strlen(s); remain++) {
695 pic16_emitDB(s[remain], ptype, p);
701 /*-----------------------------------------------------------------*/
702 /* pic16_printIvalArray - generates code for array initialization */
703 /*-----------------------------------------------------------------*/
705 pic16_printIvalArray (symbol * sym, sym_link * type, initList * ilist,
709 int lcnt = 0, size = 0;
716 fprintf(stderr, "%s\n",__FUNCTION__);
718 /* take care of the special case */
719 /* array of characters can be init */
721 if (IS_CHAR (type->next)) {
722 if (!IS_LITERAL(list2val(ilist)->etype)) {
723 werror (W_INIT_WRONG);
727 if(pic16_printIvalChar (sym, type,
728 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
729 SPEC_CVAL (sym->etype).v_char, ptype, p))
732 /* not the special case */
733 if (ilist && ilist->type != INIT_DEEP)
735 werror (E_INIT_STRUCT, sym->name);
739 iloop = ilist->init.deep;
740 lcnt = DCL_ELEM (type);
745 pic16_printIval (sym, type->next, iloop, ptype, p);
746 iloop = (iloop ? iloop->next : NULL);
749 /* if not array limits given & we */
750 /* are out of initialisers then */
751 if (!DCL_ELEM (type) && !iloop)
754 /* no of elements given and we */
755 /* have generated for all of them */
757 /* if initializers left */
759 werror (W_EXCESS_INITIALIZERS, "array", sym->name, sym->lineDef);
765 /* if we have not been given a size */
766 if (!DCL_ELEM (type))
767 DCL_ELEM (type) = size;
772 /*-----------------------------------------------------------------*/
773 /* pic16_printIvalBitFields - generate initializer for bitfields */
774 /*-----------------------------------------------------------------*/
775 void pic16_printIvalBitFields(symbol **sym, initList **ilist, char ptype, void *p)
779 initList *lilist = *ilist ;
780 unsigned long ival = 0;
785 fprintf(stderr, "%s\n",__FUNCTION__);
791 val = list2val(lilist);
793 if (SPEC_BLEN(lsym->etype) > 8) {
794 size += ((SPEC_BLEN (lsym->etype) / 8) +
795 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
798 size = ((SPEC_BLEN (lsym->etype) / 8) +
799 (SPEC_BLEN (lsym->etype) % 8 ? 1 : 0));
802 i <<= SPEC_BSTR (lsym->etype);
804 if (! ( lsym->next &&
805 (lilist && lilist->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 && iloop); 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 /* printIvalUnion - generates initial value for unions */
878 /*-----------------------------------------------------------------*/
879 void pic16_printIvalUnion (symbol * sym, sym_link * type,
880 initList * ilist, char ptype, void *p)
883 initList *iloop = NULL;
888 fprintf(stderr, "%s\n",__FUNCTION__);
900 if (type) size = SPEC_STRUCT(type)->size;
902 if (i == 1 && size >= 0 && size <= sizeof(long))
904 unsigned long val = ulFromVal (list2val(ilist));
907 pic16_emitDB(val, ptype, p);
913 fprintf( stderr, "INCOMPLETE SUPPORT FOR INITIALIZED union---FALLING BACK TO struct\n" );
914 fprintf( stderr, "This is a bug. Please file a bug-report with your source attached.\n" );
915 pic16_printIvalStruct( sym, type, ilist, ptype, p );
919 pic16_isUnion( symbol *sym, sym_link *type )
921 if (type && SPEC_STRUCT(type)->type == UNION) return 1;
925 /*--------------------------------------------------------------------------*/
926 /* pic16_printIvalCharPtr - generates initial values for character pointers */
927 /*--------------------------------------------------------------------------*/
928 int pic16_printIvalCharPtr (symbol * sym, sym_link * type, value * val, char ptype, void *p)
932 /* PENDING: this is _very_ mcs51 specific, including a magic
934 It's also endin specific.
936 VR - Attempting to port this function to pic16 port - 8-Jun-2004
941 fprintf(stderr, "%s\n",__FUNCTION__);
944 size = getSize (type);
946 if (val->name && strlen (val->name))
948 if (size == 1) /* This appears to be Z80 specific?? */
950 pic16_emitDS(val->name, ptype, p);
954 pic16_printPointerType (val->name, ptype, p);
959 if (IS_PTR (val->type)) {
960 type = DCL_TYPE (val->type);
962 type = PTR_TYPE (SPEC_OCLS (val->etype));
964 if (val->sym && val->sym->isstrlit) {
965 // this is a literal string
968 pic16_printGPointerType(val->name, type, ptype, p);
972 fprintf (stderr, "*** internal error: unknown size in "
973 "printIvalCharPtr.\n");
979 // these are literals assigned to pointers
983 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
986 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
987 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
990 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
991 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
992 pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
1000 if (val->sym && val->sym->isstrlit) { // && !isinSet(statsg->syms, val->sym)) {
1001 if(ptype == 'p' && !isinSet(statsg->syms, val->sym))addSet (&statsg->syms, val->sym);
1002 else if(ptype == 'f' /*&& !isinSet(rel_idataSymSet, val->sym)*/)addSet(&rel_idataSymSet, val->sym);
1008 /*-----------------------------------------------------------------------*/
1009 /* pic16_printIvalFuncPtr - generate initial value for function pointers */
1010 /*-----------------------------------------------------------------------*/
1011 void pic16_printIvalFuncPtr (sym_link * type, initList * ilist, char ptype, void *p)
1018 fprintf(stderr, "%s\n",__FUNCTION__);
1022 val = list2val (ilist);
1024 val = valCastLiteral(type, 0.0);
1027 // an error has been thrown already
1028 val = constCharVal (0);
1031 if (IS_LITERAL(val->etype)) {
1032 if (compareType(type, val->etype) == 0) {
1033 werrorfl (ilist->filename, ilist->lineno, E_INCOMPAT_TYPES);
1034 printFromToType (val->type, type);
1036 pic16_printIvalCharPtr (NULL, type, val, ptype, p);
1040 /* check the types */
1041 if ((dLvl = compareType (val->type, type->next)) <= 0)
1043 pic16_emitDB(0x00, ptype, p);
1047 /* now generate the name */
1049 pic16_printGPointerType (val->name, DCL_TYPE(val->type), ptype, p);
1051 pic16_printGPointerType (val->sym->rname, DCL_TYPE(val->type), ptype, p);
1053 if(IS_FUNC(val->sym->type) && !val->sym->used && !IS_STATIC(val->sym->etype)) {
1055 if(!checkSym(publics, val->sym))
1056 if(checkAddSym(&externs, val->sym) && (ptype == 'f')) {
1057 /* this has not been declared as extern
1058 * so declare it as a 'late extern' just after the symbol */
1059 fprintf((FILE *)p, ";\tdeclare symbol as extern\n");
1060 fprintf((FILE *)p, "\textern\t%s\n", val->sym->rname);
1061 fprintf((FILE *)p, ";\tcontinue variable declaration\n");
1070 /*-----------------------------------------------------------------*/
1071 /* pic16_printIvalPtr - generates initial value for pointers */
1072 /*-----------------------------------------------------------------*/
1073 void pic16_printIvalPtr (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p)
1079 fprintf(stderr, "%s:%d initialising pointer: %s size: %d\n", __FILE__, __LINE__,
1080 sym->rname, getSize(sym->type));
1084 if (ilist && (ilist->type == INIT_DEEP))
1085 ilist = ilist->init.deep;
1087 /* function pointer */
1088 if (IS_FUNC (type->next))
1090 pic16_printIvalFuncPtr (type, ilist, ptype, p);
1094 if (!(val = pic16_initPointer (ilist, type)))
1097 /* if character pointer */
1098 if (IS_CHAR (type->next))
1099 if (pic16_printIvalCharPtr (sym, type, val, ptype, p))
1102 /* check the type */
1103 if (compareType (type, val->type) == 0) {
1104 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
1105 printFromToType (val->type, type);
1108 /* if val is literal */
1109 if (IS_LITERAL (val->etype))
1111 switch (getSize (type))
1114 pic16_emitDB((unsigned int) ulFromVal (val) & 0xff, ptype, p);
1117 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
1118 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
1121 pic16_emitDB(pic16aopLiteral(val, 0), ptype, p);
1122 pic16_emitDB(pic16aopLiteral(val, 1), ptype, p);
1123 pic16_emitDB(pic16aopLiteral(val, 2), ptype, p);
1126 fprintf(stderr, "%s:%d size = %d\n", __FILE__, __LINE__, getSize(type));
1133 size = getSize (type);
1135 if (size == 1) /* Z80 specific?? */
1137 pic16_emitDS(val->name, ptype, p);
1141 pic16_printPointerType (val->name, ptype, p);
1145 pic16_printGPointerType (val->name, (IS_PTR(type)?DCL_TYPE(type):PTR_TYPE(SPEC_OCLS(sym->etype))),
1154 /*-----------------------------------------------------------------*/
1155 /* pic16_printIval - generates code for initial value */
1156 /*-----------------------------------------------------------------*/
1157 void pic16_printIval (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p)
1165 fprintf(stderr, "%s:%d generating init for %s\n", __FILE__, __LINE__, sym->name);
1166 fprintf(stderr, "%s: IS_STRUCT: %d IS_ARRAY: %d IS_PTR: %d IS_SPEC: %d\n", sym->name,
1167 IS_STRUCT(type), IS_ARRAY(type), IS_PTR(type), IS_SPEC(type));
1170 /* if structure then */
1171 if (IS_STRUCT (type))
1173 if (pic16_isUnion(sym, type))
1175 //fprintf(stderr,"%s union\n",__FUNCTION__);
1176 pic16_printIvalUnion (sym, type, ilist, ptype, p);
1178 //fprintf(stderr,"%s struct\n",__FUNCTION__);
1179 pic16_printIvalStruct (sym, type, ilist, ptype, p);
1184 /* if this is an array */
1185 if (IS_ARRAY (type))
1187 // fprintf(stderr,"%s array\n",__FUNCTION__);
1188 pic16_printIvalArray (sym, type, ilist, ptype, p);
1195 // not an aggregate, ilist must be a node
1196 if (ilist->type!=INIT_NODE) {
1197 // or a 1-element list
1198 if (ilist->init.deep->next) {
1199 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar",
1202 ilist=ilist->init.deep;
1207 // and the type must match
1208 itype=ilist->init.node->ftype;
1210 if (compareType(type, itype)==0) {
1211 // special case for literal strings
1212 if (IS_ARRAY (itype) && IS_CHAR (getSpec(itype)) &&
1213 // which are really code pointers
1214 IS_PTR(type) && DCL_TYPE(type)==CPOINTER) {
1217 // werrorfl (ilist->filename, ilist->lineno, E_TYPE_MISMATCH, "assignment", " ");
1218 // printFromToType(itype, type);
1225 /* if this is a pointer */
1228 // fprintf(stderr,"%s pointer\n",__FUNCTION__);
1229 pic16_printIvalPtr (sym, type, ilist, ptype, p);
1234 /* if type is SPECIFIER */
1237 // fprintf(stderr,"%s spec\n",__FUNCTION__);
1238 pic16_printIvalType (sym, type, ilist, ptype, p);
1243 int PIC16_IS_CONFIG_ADDRESS(int address)
1245 return ((address >= pic16->cwInfo.confAddrStart && address <= pic16->cwInfo.confAddrEnd));
1248 int PIC16_IS_IDLOC_ADDRESS(int address)
1250 return ((address >= pic16->idInfo.idAddrStart && address <= pic16->idInfo.idAddrEnd));
1253 /* wrapper function for the above */
1254 int PIC16_IS_HWREG_ADDRESS(int address)
1256 return (PIC16_IS_CONFIG_ADDRESS(address) || PIC16_IS_IDLOC_ADDRESS(address));
1260 /*-----------------------------------------------------------------*/
1261 /* emitStaticSeg - emitcode for the static segment */
1262 /*-----------------------------------------------------------------*/
1264 pic16emitStaticSeg (memmap * map)
1267 static int didcode=0;
1269 //fprintf(stderr, "%s\n",__FUNCTION__);
1273 /* for all variables in this segment do */
1274 for (sym = setFirstItem (map->syms); sym;
1275 sym = setNextItem (map->syms))
1279 fprintf(stderr, "%s\t%s: sym: %s\tused: %d\tSPEC_ABSA: %d\tSPEC_AGGREGATE: %d\tCODE: %d\n\
1280 CODESPACE: %d\tCONST: %d\tPTRCONST: %d\tSPEC_CONST: %d\n", __FUNCTION__,
1281 map->sname, sym->name, sym->used, SPEC_ABSA(sym->etype), IS_AGGREGATE(sym->type),
1282 IS_CODE(sym->etype), IN_CODESPACE( SPEC_OCLS(sym->etype)), IS_CONSTANT(sym->etype),
1283 IS_PTR_CONST(sym->etype), SPEC_CONST(sym->etype));
1284 printTypeChain( sym->type, stderr );
1285 fprintf(stderr, "\n");
1288 if(SPEC_ABSA(sym->etype) && PIC16_IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype))) {
1289 pic16_assignConfigWordValue(SPEC_ADDR(sym->etype),
1290 (int) ulFromVal (list2val(sym->ival)));
1295 if(SPEC_ABSA(sym->etype) && PIC16_IS_IDLOC_ADDRESS(SPEC_ADDR(sym->etype))) {
1296 pic16_assignIdByteValue(SPEC_ADDR(sym->etype),
1297 (char) ulFromVal (list2val(sym->ival)));
1302 /* if it is "extern" then do nothing */
1303 if (IS_EXTERN (sym->etype)/* && !SPEC_ABSA(sym->etype)*/) {
1304 checkAddSym(&externs, sym);
1308 /* if it is not static add it to the public
1310 if (!IS_STATIC (sym->etype)) {
1311 /* do not emit if it is a config word declaration */
1312 checkAddSym(&publics, sym);
1315 /* print extra debug info if required */
1316 if (options.debug || sym->level == 0) {
1317 /* NOTE to me - cdbFile may be null in which case,
1318 * the sym name will be printed to stdout. oh well */
1319 debugFile->writeSymbol(sym);
1322 /* if it has an absolute address */
1323 if (SPEC_ABSA (sym->etype)) {
1324 // fprintf(stderr, "%s:%d spec_absa is true for symbol: %s\n",
1325 // __FILE__, __LINE__, sym->name);
1327 /* if it has an initial value */
1335 /* symbol has absolute address and initial value */
1337 resolveIvalSym (sym->ival, sym->type);
1338 asym = newSymbol(sym->rname, 0);
1339 abSym = Safe_calloc(1, sizeof(absSym));
1340 strcpy(abSym->name, sym->rname);
1341 abSym->address = SPEC_ADDR( sym->etype );
1342 addSet(&absSymSet, abSym);
1344 pb = pic16_newpCodeChain(NULL, 'A', pic16_newpCodeCharP("; Starting pCode block for absolute Ival"));
1345 pic16_addpBlock(pb);
1347 pcf = pic16_newpCodeFunction(moduleName, asym->name);
1348 PCF(pcf)->absblock = 1;
1350 pic16_addpCode2pBlock(pb,pcf);
1351 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
1352 //fprintf(stderr, "%s:%d [1] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1353 pic16_printIval(sym, sym->type, sym->ival, 'p', (void *)pb);
1354 pic16_flushDB('p', (void *)pb);
1356 pic16_addpCode2pBlock(pb, pic16_newpCodeFunction(NULL, NULL));
1362 /* symbol has absolute address but no initial value */
1364 /* allocate space */
1365 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
1367 /* special case for character strings */
1368 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1369 SPEC_CVAL (sym->etype).v_char) {
1371 // fprintf(stderr, "%s:%d printing code string from %s\n", __FILE__, __LINE__, sym->rname);
1373 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
1375 fprintf (stderr, "%s:%u(%s): do not know how to intialize symbol %s\n", __FILE__, __LINE__, __FUNCTION__, sym->rname);
1381 // fprintf(stderr, "%s:%d spec_absa is false for symbol: %s\n",
1382 // __FILE__, __LINE__, sym->name);
1385 /* if it has an initial value */
1389 /* symbol doesn't have absolute address but has initial value */
1390 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
1392 resolveIvalSym (sym->ival, sym->type);
1394 pb = pic16_newpCodeChain(NULL, 'P',pic16_newpCodeCharP("; Starting pCode block for Ival"));
1395 pic16_addpBlock(pb);
1398 /* make sure that 'code' directive is emitted before, once */
1399 pic16_addpCode2pBlock(pb, pic16_newpCodeAsmDir("code", NULL));
1404 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel(sym->rname,-1));
1405 //fprintf(stderr, "%s:%d [2] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1406 pic16_printIval(sym, sym->type, sym->ival, 'p', (void *)pb);
1407 pic16_flushDB('p', (void *)pb);
1411 /* symbol doesn't have absolute address and no initial value */
1412 /* allocate space */
1413 // fprintf(stderr, "%s:%d [3] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1414 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
1415 /* special case for character strings */
1416 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) &&
1417 SPEC_CVAL (sym->etype).v_char) {
1419 // fprintf(stderr, "%s:%d printing code string for %s\n", __FILE__, __LINE__, sym->rname);
1421 pic16_pCodeConstString(sym->rname , SPEC_CVAL (sym->etype).v_char);
1432 /*-----------------------------------------------------------------*/
1433 /* pic16_emitConfigRegs - emits the configuration registers */
1434 /*-----------------------------------------------------------------*/
1435 void pic16_emitConfigRegs(FILE *of)
1439 for(i=0;i<=(pic16->cwInfo.confAddrEnd-pic16->cwInfo.confAddrStart);i++)
1440 if(pic16->cwInfo.crInfo[i].emit) //mask != -1)
1441 fprintf (of, "\t__config 0x%x, 0x%hhx\n",
1442 pic16->cwInfo.confAddrStart+i,
1443 pic16->cwInfo.crInfo[i].value);
1446 void pic16_emitIDRegs(FILE *of)
1450 for(i=0;i<=(pic16->idInfo.idAddrEnd-pic16->idInfo.idAddrStart);i++)
1451 if(pic16->idInfo.irInfo[i].emit)
1452 fprintf (of, "\t__idlocs 0x%06x, 0x%hhx\n",
1453 pic16->idInfo.idAddrStart+i,
1454 pic16->idInfo.irInfo[i].value);
1461 /* no special considerations for the following
1462 data, idata & bit & xdata */
1463 pic16emitRegularMap (data, TRUE, TRUE);
1464 pic16emitRegularMap (idata, TRUE, TRUE);
1465 pic16emitRegularMap (bit, TRUE, FALSE);
1466 pic16emitRegularMap (xdata, TRUE, TRUE);
1467 pic16emitRegularMap (sfr, FALSE, FALSE);
1468 pic16emitRegularMap (sfrbit, FALSE, FALSE);
1469 pic16emitRegularMap (code, TRUE, FALSE);
1470 pic16emitStaticSeg (statsg);
1471 pic16emitStaticSeg (c_abs);
1474 /*-----------------------------------------------------------------*/
1475 /* createInterruptVect - creates the interrupt vector */
1476 /*-----------------------------------------------------------------*/
1478 pic16createInterruptVect (struct dbuf_s * vBuf)
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 dbuf_printf (vBuf, ";\t.area\t%s\n", CODE_NAME);
1492 dbuf_printf (vBuf, ".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");
1513 if (pic16_options.xinst) {
1514 fprintf (afile, "; * Extended Instruction Set\n");
1517 if (pic16_mplab_comp) {
1518 fprintf(afile, "; * MPLAB/MPASM/MPASMWIN/MPLINK compatibility mode enabled\n");
1520 fprintf (afile, iComments2);
1522 if (options.debug) {
1523 fprintf (afile, "\n\t.ident \"SDCC version %s #%s [pic16 port]%s\"\n",
1524 SDCC_VERSION_STR, getBuildNumber(), (!pic16_options.xinst?"":" {extended}") );
1529 pic16_stringInSet(const char *str, set **world, int autoAdd)
1536 for (s = setFirstItem(*world); s; s = setNextItem(*world))
1539 if (0 == strcmp(s, str)) return 1;
1543 if (autoAdd) addSet(world, Safe_strdup(str));
1548 pic16_emitSymbolIfNew(FILE *file, const char *fmt, const char *sym, int checkLocals)
1550 static set *emitted = NULL;
1552 if (!pic16_stringInSet(sym, &emitted, 1)) {
1553 /* sym was not in emittedSymbols */
1554 if (!checkLocals || !pic16_stringInSet(sym, &pic16_localFunctions, 0)) {
1555 /* sym is not a locally defined function---avoid bug #1443651 */
1556 fprintf( file, fmt, sym );
1563 /*-----------------------------------------------------------------*/
1564 /* printPublics - generates global declarations for publics */
1565 /*-----------------------------------------------------------------*/
1567 pic16printPublics (FILE *afile)
1571 fprintf (afile, "\n%s", iComments2);
1572 fprintf (afile, "; public variables in this module\n");
1573 fprintf (afile, "%s", iComments2);
1575 for(sym = setFirstItem (publics); sym; sym = setNextItem (publics))
1577 if(!IS_STATIC(sym->etype))
1578 pic16_emitSymbolIfNew(afile, "\tglobal %s\n", sym->rname, 0);
1581 /*-----------------------------------------------------------------*/
1582 /* printExterns - generates extern declarations for externs */
1583 /*-----------------------------------------------------------------*/
1585 pic16_printExterns(FILE *afile)
1589 /* print nothing if no externs to declare */
1590 if(!elementsInSet(externs) && !elementsInSet(pic16_builtin_functions))
1593 fprintf(afile, "\n%s", iComments2);
1594 fprintf(afile, "; extern variables in this module\n");
1595 fprintf(afile, "%s", iComments2);
1597 for(sym = setFirstItem(externs); sym; sym = setNextItem(externs))
1598 pic16_emitSymbolIfNew(afile, "\textern %s\n", sym->rname, 1);
1600 for(sym = setFirstItem(pic16_builtin_functions); sym; sym = setNextItem(pic16_builtin_functions))
1601 pic16_emitSymbolIfNew(afile, "\textern _%s\n", sym->name, 1);
1604 /*-----------------------------------------------------------------*/
1605 /* emitOverlay - will emit code for the overlay stuff */
1606 /*-----------------------------------------------------------------*/
1608 pic16emitOverlay (struct dbuf_s *aBuf)
1612 if (!elementsInSet (ovrSetSets))
1613 dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name);
1615 /* for each of the sets in the overlay segment do */
1616 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1617 ovrset = setNextItem (ovrSetSets))
1622 if (elementsInSet (ovrset))
1624 /* this dummy area is used to fool the assembler
1625 otherwise the assembler will append each of these
1626 declarations into one chunk and will not overlay
1628 dbuf_printf (aBuf, ";\t.area _DUMMY\n");
1629 /* output the area informtion */
1630 dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1633 for (sym = setFirstItem (ovrset); sym;
1634 sym = setNextItem (ovrset))
1637 /* if extern then do nothing */
1638 if (IS_EXTERN (sym->etype))
1641 /* if allocation required check is needed
1642 then check if the symbol really requires
1643 allocation only for local variables */
1644 if (!IS_AGGREGATE (sym->type) &&
1645 !(sym->_isparm && !IS_REGPARM (sym->etype))
1646 && !sym->allocreq && sym->level)
1649 /* if global variable & not static or extern
1650 and addPublics allowed then add it to the public set */
1651 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1652 && !IS_STATIC (sym->etype)) {
1653 // fprintf(stderr, "%s:%d %s accessed\n", __FILE__, __LINE__, __FUNCTION__);
1654 checkAddSym(&publics, sym);
1655 // addSetHead (&publics, sym);
1658 /* if extern then do nothing or is a function
1660 if (IS_FUNC (sym->type))
1664 /* if is has an absolute address then generate
1665 an equate for this no need to allocate space */
1666 if (SPEC_ABSA (sym->etype))
1669 if (options.debug || sym->level == 0)
1670 dbuf_printf (aBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1672 dbuf_printf (aBuf, "%s\t=\t0x%04x\n",
1674 SPEC_ADDR (sym->etype));
1678 if (options.debug || sym->level == 0)
1679 dbuf_printf (aBuf, "==.\n");
1681 /* allocate space */
1682 dbuf_printf (aBuf, "%s:\n", sym->rname);
1683 dbuf_printf (aBuf, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1690 void emitStatistics(FILE *asmFile)
1692 unsigned long isize, udsize, ramsize;
1693 statistics.isize = pic16_countInstructions();
1694 isize = (statistics.isize >= 0) ? statistics.isize : 0;
1695 udsize = (statistics.udsize >= 0) ? statistics.udsize : 0;
1696 ramsize = pic16 ? pic16->RAMsize : 0x200;
1697 ramsize -= 256; /* ignore access bank and SFRs */
1698 if (ramsize == 0) ramsize = 64; /* prevent division by zero (below) */
1700 fprintf (asmFile, "\n\n; Statistics:\n");
1701 fprintf (asmFile, "; code size:\t%5ld (0x%04lx) bytes (%5.2f%%)\n; \t%5ld (0x%04lx) words\n",
1702 isize, isize, (isize*100.0)/(128UL << 10),
1703 isize>>1, isize>>1);
1704 fprintf (asmFile, "; udata size:\t%5ld (0x%04lx) bytes (%5.2f%%)\n",
1705 udsize, udsize, (udsize*100.0) / (1.0 * ramsize));
1706 fprintf (asmFile, "; access size:\t%5ld (0x%04lx) bytes\n",
1707 statistics.intsize, statistics.intsize);
1709 fprintf (asmFile, "\n\n");
1714 /*-----------------------------------------------------------------*/
1715 /* glue - the final glue that hold the whole thing together */
1716 /*-----------------------------------------------------------------*/
1721 struct dbuf_s ovrBuf;
1724 dbuf_init(&ovrBuf, 4096);
1725 dbuf_init(&vBuf, 4096);
1727 mainf = newSymbol ("main", 0);
1730 mainf = findSymWithLevel(SymbolTab, mainf);
1732 pic16_pCodeInitRegisters();
1734 if(pic16_options.no_crt && mainf && IFFUNC_HASBODY(mainf->type)) {
1735 pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
1737 pic16_addpBlock(pb);
1739 /* entry point @ start of CSEG */
1740 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup",-1));
1743 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1744 pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("_stack_end"))));
1745 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1746 pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("_stack_end"))));
1749 /* put in the call to main */
1750 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
1752 if (options.mainreturn) {
1753 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
1754 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
1756 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will lock up\n"));
1757 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_GOTO,pic16_newpCodeOp("$",PO_STR)));
1761 /* At this point we've got all the code in the form of pCode structures */
1762 /* Now it needs to be rearranged into the order it should be placed in the */
1765 pic16_movepBlock2Head('P'); // Last
1766 pic16_movepBlock2Head(code->dbName);
1767 pic16_movepBlock2Head('X');
1768 pic16_movepBlock2Head(statsg->dbName); // First
1770 /* print the global struct definitions */
1772 /* PENDING: this isnt the best place but it will do */
1773 if (port->general.glue_up_main) {
1774 /* create the interrupt vector table */
1775 pic16createInterruptVect (&vBuf);
1778 /* emit code for the all the variables declared */
1781 /* do the overlay segments */
1782 pic16emitOverlay(&ovrBuf);
1783 pic16_AnalyzepCode('*');
1786 if(pic16_options.dumpcalltree) {
1789 sprintf(buffer, dstFileName);
1790 strcat(buffer, ".calltree");
1791 cFile = fopen(buffer, "w");
1792 pic16_printCallTree( cFile );
1797 pic16_InlinepCode();
1798 pic16_AnalyzepCode('*');
1801 if(pic16_debug_verbose)
1804 /* now put it all together into the assembler file */
1805 /* create the assembler file name */
1806 if((noAssemble || options.c1mode) && fullDstFileName) {
1807 sprintf (buffer, fullDstFileName);
1809 sprintf (buffer, dstFileName);
1810 strcat (buffer, ".asm");
1813 if(!(asmFile = fopen (buffer, "w"))) {
1814 werror (E_FILE_OPEN_ERR, buffer);
1818 /* initial comments */
1819 pic16initialComments (asmFile);
1821 /* print module name */
1823 fprintf(asmFile, "\t.file\t\"%s\"\n", fullSrcFileName);
1825 /* Let the port generate any global directives, etc. */
1826 if(port->genAssemblerPreamble) {
1827 port->genAssemblerPreamble(asmFile);
1830 /* Put all variables into a cblock */
1831 pic16_AnalyzeBanking();
1834 if(pic16_options.opt_flags & OF_LR_SUPPORT) {
1835 pic16_OptimizeLocalRegs();
1839 /* remove redundant BANKSELs -- added by RN 2005-01-17 */
1840 if(pic16_options.opt_banksel > 1) {
1841 pic16_OptimizeBanksel();
1844 /* turn GOTOs into BRAs -- added by RN 2004-11-16 */
1845 if(pic16_options.opt_flags & OF_OPTIMIZE_GOTO) {
1846 pic16_OptimizeJumps();
1849 /* print the global variables in this module */
1850 pic16printPublics (asmFile);
1852 /* print the extern variables to this module */
1853 pic16_printExterns(asmFile);
1855 pic16_writeUsedRegs(asmFile);
1858 /* no xdata in pic */
1859 /* if external stack then reserve space of it */
1860 if(mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1861 fprintf (asmFile, "%s", iComments2);
1862 fprintf (asmFile, "; external stack \n");
1863 fprintf (asmFile, "%s", iComments2);
1864 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1865 fprintf (asmFile,";\t.ds 256\n");
1870 /* no xdata in pic */
1871 /* copy xtern ram data */
1872 fprintf (asmFile, "%s", iComments2);
1873 fprintf (asmFile, "; external ram data\n");
1874 fprintf (asmFile, "%s", iComments2);
1875 dbuf_write_and_destroy (&xdata->oBuf, asmFile);
1879 /* copy the bit segment */
1880 fprintf (asmFile, "%s", iComments2);
1881 fprintf (asmFile, "; bit data\n");
1882 fprintf (asmFile, "%s", iComments2);
1883 dbuf_write_and_destroy (&bit->oBuf, asmFile);
1886 /* copy the interrupt vector table */
1887 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1888 fprintf (asmFile, "\n%s", iComments2);
1889 fprintf (asmFile, "; interrupt vector \n");
1890 fprintf (asmFile, "%s", iComments2);
1891 dbuf_write_and_destroy (&vBuf, asmFile);
1894 /* copy global & static initialisations */
1895 fprintf (asmFile, "\n%s", iComments2);
1896 fprintf (asmFile, "; global & static initialisations\n");
1897 fprintf (asmFile, "%s", iComments2);
1899 if(pic16_debug_verbose)
1900 fprintf(asmFile, "; A code from now on!\n");
1902 pic16_copypCode(asmFile, 'A');
1904 if(pic16_options.no_crt) {
1905 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1906 fprintf(asmFile, "\tcode\n");
1907 fprintf(asmFile,"__sdcc_gsinit_startup:\n");
1911 // dbuf_write_and_destroy (&code->oBuf, stderr);
1913 fprintf(asmFile, "; I code from now on!\n");
1914 pic16_copypCode(asmFile, 'I');
1916 if(pic16_debug_verbose)
1917 fprintf(asmFile, "; dbName from now on!\n");
1919 pic16_copypCode(asmFile, statsg->dbName);
1921 if(pic16_options.no_crt) {
1922 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
1923 fprintf (asmFile,"\tgoto\t__sdcc_program_startup\n");
1927 if(pic16_debug_verbose)
1928 fprintf(asmFile, "; X code from now on!\n");
1930 pic16_copypCode(asmFile, 'X');
1932 if(pic16_debug_verbose)
1933 fprintf(asmFile, "; M code from now on!\n");
1935 pic16_copypCode(asmFile, 'M');
1937 pic16_copypCode(asmFile, code->dbName);
1939 pic16_copypCode(asmFile, 'P');
1941 emitStatistics(asmFile);
1943 fprintf (asmFile,"\tend\n");