1 /*-------------------------------------------------------------------------
2 glue.c - glues everything we have done together into one file.
3
4 Copyright (C) 1998, Sandeep Dutta . sandeep.dutta@usa.net
5
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
9 later version.
10
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.
15
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.
19 -------------------------------------------------------------------------*/
20
21 #include "../common.h"
22 #include <time.h>
23 #include "ralloc.h"
24 #include "pcode.h"
25 #include "newalloc.h"
26 #include "gen.h"
27 #include "device.h"
28 #include "main.h"
29 #include "dbuf_string.h"
30 #include <string.h>
31
32
33 extern symbol *interrupts[256];
34 void pic16_printIval (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p);
35 extern int noAlloc;
36 extern set *publics;
37 extern set *externs;
38 extern unsigned maxInterrupts;
39 extern symbol *mainf;
40 extern char *VersionString;
41 extern struct dbuf_s *codeOutBuf;
42 extern char *iComments1;
43 extern char *iComments2;
44 extern int has_xinst_config;
45
46 extern int initsfpnt;
47 extern unsigned long pFile_isize;
48
49 extern unsigned long pic16_countInstructions();
50 set *pic16_localFunctions = NULL;
51 set *rel_idataSymSet = NULL;
52 set *fix_idataSymSet = NULL;
53
54 extern void pic16_AnalyzeBanking (void);
55 extern void pic16_OptimizeJumps (void);
56 extern void pic16_OptimizeBanksel (void);
57 extern void pic16_InlinepCode (void);
58 extern void pic16_writeUsedRegs (FILE *);
59
60 extern void initialComments (FILE * afile);
61 extern void printPublics (FILE * afile);
62
63 void pic16_pCodeInitRegisters (void);
64 pCodeOp *pic16_popCopyReg (pCodeOpReg *pc);
65 extern void pic16_pCodeConstString (char *name, const char *value, unsigned length);
66
67
68 /*-----------------------------------------------------------------*/
69 /* aopLiteral - string from a literal value */
70 /*-----------------------------------------------------------------*/
pic16aopLiteral(value * val,int offset)71 unsigned int pic16aopLiteral (value *val, int offset)
72 {
73 union {
74 float f;
75 unsigned char c[4];
76 } fl;
77
78 /* if it is a float then it gets tricky */
79 /* otherwise it is fairly simple */
80 if (!(IS_FLOAT(val->type) || IS_FIXED(val->type))) {
81 unsigned long v = ulFromVal (val);
82
83 return ( (v >> (offset * 8)) & 0xff);
84 }
85
86 if(IS_FIXED16X16(val->type)) {
87 unsigned long v = (unsigned long)fixed16x16FromDouble( floatFromVal( val ) );
88
89 return ( (v >> (offset * 8)) & 0xff);
90 }
91
92 /* it is type float */
93 fl.f = (float) floatFromVal(val);
94 #ifdef WORDS_BIGENDIAN
95 return fl.c[3-offset];
96 #else
97 return fl.c[offset];
98 #endif
99
100 }
101
102 iCode *tic;
103 symbol *nsym;
104 char tbuffer[512], *tbuf=tbuffer;
105
106
107 /*-----------------------------------------------------------------*/
108 /* emitRegularMap - emit code for maps with no special cases */
109 /*-----------------------------------------------------------------*/
110 static void
pic16emitRegularMap(memmap * map,bool addPublics,bool arFlag)111 pic16emitRegularMap (memmap * map, bool addPublics, bool arFlag)
112 {
113 symbol *sym;
114 // int i, size, bitvars = 0;;
115
116 // fprintf(stderr, "%s:%d map name= %s\n", __FUNCTION__, __LINE__, map->sname);
117
118 if(addPublics)
119 dbuf_printf (&map->oBuf, ";\t.area\t%s\n", map->sname);
120 /* print the area name */
121
122 for (sym = setFirstItem (map->syms); sym; sym = setNextItem (map->syms)) {
123
124 #if 0
125 fprintf(stderr, "%s\t%s: sym: %s\tused: %d\textern: %d\tstatic: %d\taggregate: %d\tregister: 0x%x\tfunction: %d\n",
126 __FUNCTION__,
127 map->sname, sym->name, sym->used, IS_EXTERN(sym->etype), IS_STATIC(sym->etype),
128 IS_AGGREGATE(sym->type), (SPEC_SCLS(sym->etype) == S_REGISTER), IS_FUNC(sym->type));
129 printTypeChain( sym->type, stderr );
130 fprintf(stderr, "\n");
131 #endif
132
133 /* if extern then add to externs */
134 if (IS_EXTERN (sym->etype)) {
135 /* reduce overhead while linking by not declaring
136 * extern unused external functions (usually declared
137 * in header files) */
138 if(IS_FUNC(sym->type) && !sym->used)continue;
139
140 /* make sure symbol is not in publics section */
141 if(!checkSym(publics, sym))
142 checkAddSym(&externs, sym);
143 continue;
144 }
145
146 /* if allocation required check is needed
147 * then check if the symbol really requires
148 * allocation only for local variables */
149 if (arFlag && !IS_AGGREGATE (sym->type) &&
150 !(sym->_isparm && !IS_REGPARM (sym->etype)) &&
151 !sym->allocreq && sym->level) {
152
153 // fprintf(stderr, "%s:%d special case, continuing...\n", __FILE__, __LINE__);
154
155 continue;
156 }
157
158 /* if global variable & not static or extern
159 * and addPublics allowed then add it to the public set */
160 if ((sym->used) && (sym->level == 0 ||
161 (sym->_isparm && !IS_REGPARM (sym->etype))) &&
162 addPublics &&
163 !IS_STATIC (sym->etype) && !IS_FUNC(sym->type)) {
164
165 checkAddSym(&publics, sym);
166 } else if (IS_AGGREGATE(sym->type) && sym->level == 0 && ! IS_STATIC(sym->etype)) {
167 /* If a global variable is not static and will be included in the published list. */
168
169 checkAddSym(&publics, sym);
170 } else
171 /* new version */
172 if(IS_STATIC(sym->etype)
173 && !sym->ival) /* && !sym->level*/ {
174 reg_info *reg;
175 sectSym *ssym;
176 int found=0;
177
178 // debugf("adding symbol %s\n", sym->name);
179 #define SET_IMPLICIT 1
180
181 #if SET_IMPLICIT
182 if(IS_STRUCT(sym->type))
183 sym->implicit = 1;
184 #endif
185
186 reg = pic16_allocDirReg( operandFromSymbol( sym ));
187
188 if(reg) {
189 for(ssym=setFirstItem(sectSyms); ssym; ssym=setNextItem(sectSyms)) {
190 if(!strcmp(ssym->name, reg->name))found=1;
191 }
192
193 if(!found)
194 checkAddReg(&pic16_rel_udata, reg);
195 #if 0
196 else
197 debugf("Did find %s in pic16_rel_udata already. Check!\n", reg->name);
198 // checkAddSym(&publics, sym);
199 #endif
200
201 }
202 }
203
204 /* if extern then do nothing or is a function
205 * then do nothing */
206 if (IS_FUNC (sym->type) && !IS_STATIC(sym->etype)) {
207 if(SPEC_OCLS(sym->etype) == code) {
208 // fprintf(stderr, "%s:%d: symbol added: %s\n", __FILE__, __LINE__, sym->rname);
209 checkAddSym(&publics, sym);
210 }
211 continue;
212 }
213
214 /* if is has an absolute address then generate
215 an equate for this no need to allocate space */
216 if (SPEC_ABSA (sym->etype)) {
217 // fprintf (stderr,"; %s == 0x%04x\t\treqv= %p nRegs= %d\n",
218 // sym->name, SPEC_ADDR (sym->etype), sym->reqv, sym->regType);
219
220 dbuf_printf (&map->oBuf, "%s\tEQU\t0x%04x\n",
221 sym->rname,
222 SPEC_ADDR (sym->etype));
223
224 /* emit only if it is global */
225 if(sym->level == 0) {
226 reg_info *reg;
227
228 reg = pic16_dirregWithName( sym->name );
229 if(!reg) {
230 /* here */
231 // fprintf(stderr, "%s:%d: implicit add of symbol = %s\n",
232 // __FUNCTION__, __LINE__, sym->name);
233
234 /* if IS_STRUCT is omitted the following
235 * fixes structures but break char/int etc */
236 #if SET_IMPLICIT
237 if(IS_STRUCT(sym->type))
238 sym->implicit = 1; // mark as implicit
239 #endif
240 if(!sym->ival) {
241 reg = pic16_allocDirReg( operandFromSymbol(sym) );
242 if(reg) {
243 if(checkAddReg(&pic16_fix_udata, reg)) {
244 /* and add to globals list if not exist */
245 addSet(&publics, sym);
246 }
247 }
248 } else
249 addSet(&publics, sym);
250 }
251 }
252 } else {
253 if(!sym->used && (sym->level == 0)) {
254 reg_info *reg;
255
256 /* symbol not used, just declared probably, but its in
257 * level 0, so we must declare it fine as global */
258
259 // fprintf(stderr, "EXTRA symbol declaration sym= %s\n", sym->name);
260
261 #if SET_IMPLICIT
262 if(IS_STRUCT(sym->type))
263 sym->implicit = 1; // mark as implicit
264 #endif
265 if(!sym->ival) {
266 if(IS_AGGREGATE(sym->type)) {
267 reg=pic16_allocRegByName(sym->rname, getSize( sym->type ), NULL);
268 } else {
269 reg = pic16_allocDirReg( operandFromSymbol( sym ) );
270 }
271
272 {
273 sectSym *ssym;
274 int found=0;
275
276 #if 0
277 fprintf(stderr, "%s:%d sym->rname: %s reg: %p reg->name: %s\n", __FILE__, __LINE__,
278 sym->rname, reg, (reg?reg->name:"<<NULL>>"));
279 #endif
280
281 if(reg) {
282 for(ssym=setFirstItem(sectSyms); ssym; ssym=setNextItem(sectSyms)) {
283 if(!strcmp(ssym->name, reg->name))found=1;
284 }
285
286 if(!found)
287 if(checkAddReg(&pic16_rel_udata, reg)) {
288 addSetHead(&publics, sym);
289 }
290 }
291 }
292
293
294
295 } else
296
297 addSetHead(&publics, sym);
298 }
299
300 #if 0
301 /* allocate space */
302 /* If this is a bit variable, then allocate storage after 8 bits have been declared */
303 /* unlike the 8051, the pic does not have a separate bit area. So we emulate bit ram */
304 /* by grouping the bits together into groups of 8 and storing them in the normal ram. */
305 if (IS_BITVAR (sym->etype)) {
306 bitvars++;
307 } else {
308 dbuf_printf (map->oBuf, "\t%s\n", sym->rname);
309 if ((size = (unsigned int) getSize (sym->type) & 0xffff) > 1) {
310 for (i = 1; i < size; i++)
311 dbuf_printf (map->oBuf, "\t%s_%d\n", sym->rname, i);
312 }
313 }
314 dbuf_printf (map->oBuf, "\t.ds\t0x%04x\n", (unsigned int)getSize (sym->type) & 0xffff);
315 #endif
316 }
317
318 /* FIXME -- VR Fix the following, so that syms to be placed
319 * in the idata section and let linker decide about their fate */
320
321 /* if it has an initial value then do it only if
322 it is a global variable */
323
324 if (sym->ival
325 && ((sym->level == 0)
326 || IS_STATIC(sym->etype)) ) {
327 ast *ival = NULL;
328
329 #if 0
330 if(SPEC_OCLS(sym->etype)==data) {
331 fprintf(stderr, "%s: sym %s placed in data segment\n", map->sname, sym->name);
332 }
333
334 if(SPEC_OCLS(sym->etype)==code) {
335 fprintf(stderr, "%s: sym %s placed in code segment\n", map->sname, sym->name);
336 }
337 #endif
338
339 #if 0
340 fprintf(stderr, "'%s': sym '%s' has initial value SPEC_ABSA: %d, IS_AGGREGATE: %d\n",
341 map->sname, sym->name, SPEC_ABSA(sym->etype), IS_AGGREGATE(sym->type));
342 #endif
343
344 if (IS_AGGREGATE (sym->type)) {
345 if(SPEC_ABSA(sym->etype))
346 addSet(&fix_idataSymSet, copySymbol(sym));
347 else
348 addSet(&rel_idataSymSet, copySymbol(sym));
349 // ival = initAggregates (sym, sym->ival, NULL);
350 } else {
351 if(SPEC_ABSA(sym->etype))
352 addSet(&fix_idataSymSet, copySymbol(sym));
353 else
354 addSet(&rel_idataSymSet, copySymbol(sym));
355
356 // ival = newNode ('=', newAst_VALUE(symbolVal (sym)),
357 // decorateType (resolveSymbols (list2expr (sym->ival)), RESULT_TYPE_NONE));
358 }
359
360 if(ival) {
361 setAstFileLine (ival, sym->fileDef, sym->lineDef);
362 codeOutBuf = &statsg->oBuf;
363 GcurMemmap = statsg;
364 eBBlockFromiCode (iCodeFromAst (ival));
365 sym->ival = NULL;
366 }
367 }
368 }
369 }
370
371
372 /*-----------------------------------------------------------------*/
373 /* pic16_initPointer - pointer initialization code massaging */
374 /*-----------------------------------------------------------------*/
375 static value *
pic16_initPointer(initList * ilist,sym_link * toType)376 pic16_initPointer (initList * ilist, sym_link *toType)
377 {
378 value *val;
379 ast *expr;
380
381 if (!ilist) {
382 return valCastLiteral(toType, 0.0, 0);
383 }
384
385 expr = decorateType(resolveSymbols( list2expr (ilist) ), FALSE);
386 // expr = list2expr( ilist );
387
388 if (!expr)
389 goto wrong;
390
391 /* try it the old way first */
392 if (expr->etype && (val = constExprValue (expr, FALSE)))
393 return val;
394
395 /* ( ptr + constant ) */
396 if (IS_AST_OP (expr) &&
397 (expr->opval.op == '+' || expr->opval.op == '-') &&
398 IS_AST_SYM_VALUE (expr->left) &&
399 (IS_ARRAY(expr->left->ftype) || IS_PTR(expr->left->ftype)) &&
400 compareType(toType, expr->left->ftype) &&
401 IS_AST_LIT_VALUE (expr->right)) {
402 return valForCastAggr (expr->left, expr->left->ftype,
403 expr->right,
404 expr->opval.op);
405 }
406
407 /* (char *)&a */
408 if (IS_AST_OP(expr) && expr->opval.op==CAST &&
409 IS_AST_OP(expr->right) && expr->right->opval.op=='&') {
410 if (compareType(toType, expr->left->ftype)!=1) {
411 werror (W_INIT_WRONG);
412 printFromToType(expr->left->ftype, toType);
413 }
414 // skip the cast ???
415 expr=expr->right;
416 }
417
418 /* no then we have to do these cludgy checks */
419 /* pointers can be initialized with address of
420 a variable or address of an array element */
421 if (IS_AST_OP (expr) && expr->opval.op == '&') {
422
423 /* AST nodes for symbols of type struct or union may be missing type */
424 /* due to the abuse of the sym->implicit flag, so get the type */
425 /* directly from the symbol if it's missing in the node. */
426 sym_link *etype = expr->left->etype;
427 sym_link *ftype = expr->left->ftype;
428 if (!etype && IS_AST_SYM_VALUE(expr->left))
429 {
430 etype = expr->left->opval.val->sym->etype;
431 ftype = expr->left->opval.val->sym->type;
432 }
433
434 /* address of symbol */
435 if (IS_AST_SYM_VALUE (expr->left) && etype) {
436 val = AST_VALUE (expr->left);
437 val->type = newLink (DECLARATOR);
438 if(SPEC_SCLS (etype) == S_CODE) {
439 DCL_TYPE (val->type) = CPOINTER;
440 CodePtrPointsToConst (val->type);
441 }
442 else if (SPEC_SCLS (etype) == S_XDATA)
443 DCL_TYPE (val->type) = FPOINTER;
444 else if (SPEC_SCLS (etype) == S_XSTACK)
445 DCL_TYPE (val->type) = PPOINTER;
446 else if (SPEC_SCLS (etype) == S_IDATA)
447 DCL_TYPE (val->type) = IPOINTER;
448 else if (SPEC_SCLS (etype) == S_EEPROM)
449 DCL_TYPE (val->type) = EEPPOINTER;
450 else
451 DCL_TYPE (val->type) = POINTER;
452
453 val->type->next = ftype;
454 val->etype = getSpec (val->type);
455 return val;
456 }
457
458 /* if address of indexed array */
459 if (IS_AST_OP (expr->left) && expr->left->opval.op == '[')
460 return valForArray (expr->left);
461
462 /* if address of structure element then
463 case 1. a.b ; */
464 if (IS_AST_OP (expr->left) &&
465 expr->left->opval.op == '.') {
466 return valForStructElem (expr->left->left,
467 expr->left->right);
468 }
469
470 /* case 2. (&a)->b ;
471 (&some_struct)->element */
472 if (IS_AST_OP (expr->left) &&
473 expr->left->opval.op == PTR_OP &&
474 IS_ADDRESS_OF_OP (expr->left->left)) {
475 return valForStructElem (expr->left->left->left,
476 expr->left->right);
477 }
478 }
479 /* case 3. (((char *) &a) +/- constant) */
480 if (IS_AST_OP (expr) &&
481 (expr->opval.op == '+' || expr->opval.op == '-') &&
482 IS_AST_OP (expr->left) && expr->left->opval.op == CAST &&
483 IS_AST_OP (expr->left->right) &&
484 expr->left->right->opval.op == '&' &&
485 IS_AST_LIT_VALUE (expr->right)) {
486
487 return valForCastAggr (expr->left->right->left,
488 expr->left->left->opval.lnk,
489 expr->right, expr->opval.op);
490
491 }
492 /* case 4. (char *)(array type) */
493 if (IS_CAST_OP(expr) && IS_AST_SYM_VALUE (expr->right) &&
494 IS_ARRAY(expr->right->ftype)) {
495
496 val = copyValue (AST_VALUE (expr->right));
497 val->type = newLink (DECLARATOR);
498 if (SPEC_SCLS (expr->right->etype) == S_CODE) {
499 DCL_TYPE (val->type) = CPOINTER;
500 CodePtrPointsToConst (val->type);
501 }
502 else if (SPEC_SCLS (expr->right->etype) == S_XDATA)
503 DCL_TYPE (val->type) = FPOINTER;
504 else if (SPEC_SCLS (expr->right->etype) == S_XSTACK)
505 DCL_TYPE (val->type) = PPOINTER;
506 else if (SPEC_SCLS (expr->right->etype) == S_IDATA)
507 DCL_TYPE (val->type) = IPOINTER;
508 else if (SPEC_SCLS (expr->right->etype) == S_EEPROM)
509 DCL_TYPE (val->type) = EEPPOINTER;
510 else
511 DCL_TYPE (val->type) = POINTER;
512 val->type->next = expr->right->ftype->next;
513 val->etype = getSpec (val->type);
514 return val;
515 }
516
517 wrong:
518 if (expr)
519 werrorfl (expr->filename, expr->lineno, E_INCOMPAT_PTYPES);
520 else
521 werror (E_INCOMPAT_PTYPES);
522 return NULL;
523
524 }
525
526
527 /*-----------------------------------------------------------------*/
528 /* printPointerType - generates ival for pointer type */
529 /*-----------------------------------------------------------------*/
530 static void
_pic16_printPointerType(const char * name,char ptype,void * p)531 _pic16_printPointerType (const char *name, char ptype, void *p)
532 {
533 char buf[256];
534
535 SNPRINTF(buf, sizeof(buf), "LOW(%s)", name);
536 pic16_emitDS (buf, ptype, p);
537 SNPRINTF(buf, sizeof(buf), "HIGH(%s)", name);
538 pic16_emitDS (buf, ptype, p);
539 }
540
541 /*-----------------------------------------------------------------*/
542 /* printPointerType - generates ival for pointer type */
543 /*-----------------------------------------------------------------*/
544 static void
pic16_printPointerType(const char * name,char ptype,void * p)545 pic16_printPointerType (const char *name, char ptype, void *p)
546 {
547 _pic16_printPointerType (name, ptype, p);
548 //pic16_flushDB(ptype, p); /* breaks char* const arr[] = {&c, &c, &c}; */
549 }
550
551 /*-----------------------------------------------------------------*/
552 /* printGPointerType - generates ival for generic pointer type */
553 /*-----------------------------------------------------------------*/
554 static void
pic16_printGPointerType(const char * iname,const unsigned int itype,char ptype,void * p)555 pic16_printGPointerType (const char *iname, const unsigned int itype,
556 char ptype, void *p)
557 {
558 char buf[256];
559
560 _pic16_printPointerType (iname, ptype, p);
561
562 switch (itype)
563 {
564 case CPOINTER: /* fall through */
565 case FUNCTION: /* fall through */
566 case GPOINTER:
567 /* GPTRs pointing to __data space should be reported as POINTERs */
568 SNPRINTF(buf, sizeof(buf), "UPPER(%s)", iname);
569 pic16_emitDS (buf, ptype, p);
570 break;
571
572 case POINTER: /* fall through */
573 case FPOINTER: /* fall through */
574 case IPOINTER: /* fall through */
575 case PPOINTER: /* __data space */
576 SNPRINTF(buf, sizeof(buf), "0x%02x", GPTR_TAG_DATA);
577 pic16_emitDS (buf, ptype, p);
578 break;
579
580 default:
581 debugf ("itype = %d\n", itype );
582 assert (0);
583 }
584
585 if (itype == GPOINTER) {
586 fprintf(stderr, "%s: initialized generic pointer with unknown storage class assumes object in code space\n", __func__);
587 }
588
589 //pic16_flushDB(ptype, p); /* might break char* const arr[] = {...}; */
590 }
591
592
593 /* set to 0 to disable debug messages */
594 #define DEBUG_PRINTIVAL 0
595
596 /*-----------------------------------------------------------------*/
597 /* pic16_printIvalType - generates ival for int/char */
598 /*-----------------------------------------------------------------*/
599 static void
pic16_printIvalType(symbol * sym,sym_link * type,initList * ilist,char ptype,void * p)600 pic16_printIvalType (symbol *sym, sym_link * type, initList * ilist, char ptype, void *p)
601 {
602 value *val;
603 int i;
604
605 // fprintf(stderr, "%s for symbol %s\n",__FUNCTION__, sym->rname);
606
607 #if DEBUG_PRINTIVAL
608 fprintf(stderr, "%s\n",__FUNCTION__);
609 #endif
610
611
612 /* if initList is deep */
613 if (ilist && ilist->type == INIT_DEEP)
614 ilist = ilist->init.deep;
615
616 if (!IS_AGGREGATE(sym->type) && getNelements(type, ilist)>1) {
617 werror (W_EXCESS_INITIALIZERS, "scalar", sym->name, sym->lineDef);
618 }
619
620 if (!(val = list2val (ilist, TRUE))) {
621 // assuming a warning has been thrown
622 val = constCharVal (0);
623 }
624
625 if (val->type != type) {
626 val = valCastLiteral(type, floatFromVal (val), (TYPE_TARGET_ULONGLONG) ullFromVal (val));
627 }
628
629 for (i = 0; i < (int)getSize (type); i++) {
630 pic16_emitDB(pic16aopLiteral(val, i), ptype, p);
631 } // for
632 }
633
634 /*--------------------------------------------------------------------*/
635 /* pic16_printIvalChar - generates initital value for character array */
636 /*--------------------------------------------------------------------*/
637 static int
pic16_printIvalChar(symbol * sym,sym_link * type,initList * ilist,const char * s,char ptype,void * p)638 pic16_printIvalChar (symbol *sym, sym_link * type, initList * ilist, const char *s, char ptype, void *p)
639 {
640 value *val;
641 int len;
642 size_t remain, ilen;
643
644 if(!p)
645 return 0;
646
647 #if DEBUG_PRINTIVAL
648 fprintf(stderr, "%s\n",__FUNCTION__);
649 #endif
650
651 if(!s) {
652 val = list2val (ilist, TRUE);
653
654 /* if the value is a character string */
655 if(IS_ARRAY (val->type) && IS_CHAR (val->etype)) {
656 /* length of initializer string (might contain \0, so do not use strlen) */
657 ilen = DCL_ELEM(val->type);
658
659 #if 0
660 /* This causes structflexarray.c to fail. */
661 if(!DCL_ELEM (type))
662 DCL_ELEM (type) = ilen;
663 #endif
664
665 /* len is 0 if declartion equals initializer,
666 * >0 if declaration greater than initializer
667 * <0 if declaration less than initializer
668 * Strategy: if >0 emit 0x00 for the rest of the length,
669 * if <0 then emit only the length of declaration elements
670 * and warn user
671 */
672 len = DCL_ELEM (type) - ilen;
673
674 // fprintf(stderr, "%s:%d ilen = %i len = %i DCL_ELEM(type) = %i SPEC_CVAL-len = %i\n", __FILE__, __LINE__,
675 // ilen, len, DCL_ELEM(type), strlen(SPEC_CVAL(val->etype).v_char));
676
677 if(len >= 0) {
678 /* emit initializer */
679 for(remain=0; remain<ilen; remain++) {
680 pic16_emitDB(SPEC_CVAL(val->etype).v_char[ remain ], ptype, p);
681 } // for
682
683 /* fill array with 0x00 */
684 while(len--) {
685 pic16_emitDB(0x00, ptype, p);
686 } // while
687 } else if (!DCL_ELEM (type)) {
688 // flexible arrays: char str[] = "something"; */
689 for(remain=0; remain<ilen; remain++) {
690 pic16_emitDB(SPEC_CVAL(val->etype).v_char[ remain ], ptype, p);
691 } // for
692 } else {
693 werror (W_EXCESS_INITIALIZERS, "array of chars", sym->name, sym->lineDef);
694 for(remain=0; remain<DCL_ELEM (type); remain++) {
695 pic16_emitDB(SPEC_CVAL(val->etype).v_char[ remain ], ptype, p);
696 } // for
697 } // if
698
699
700 // if((remain = (DCL_ELEM (type) - strlen (SPEC_CVAL (val->etype).v_char) - 1)) > 0) {
701 // }
702 return 1;
703 } else return 0;
704 } else {
705 for(remain=0; remain<strlen(s); remain++) {
706 pic16_emitDB(s[remain], ptype, p);
707 }
708 }
709 return 1;
710 }
711
712 /*-----------------------------------------------------------------*/
713 /* pic16_printIvalArray - generates code for array initialization */
714 /*-----------------------------------------------------------------*/
715 static void
pic16_printIvalArray(symbol * sym,sym_link * type,initList * ilist,char ptype,void * p)716 pic16_printIvalArray (symbol * sym, sym_link * type, initList * ilist,
717 char ptype, void *p)
718 {
719 initList *iloop;
720 int lcnt = 0, size = 0;
721
722 if(!p)
723 return;
724
725
726 #if DEBUG_PRINTIVAL
727 fprintf(stderr, "%s\n",__FUNCTION__);
728 #endif
729 /* take care of the special case */
730 /* array of characters can be init */
731 /* by a string */
732 if (IS_CHAR (type->next) &&
733 ilist && ilist->type == INIT_NODE) {
734 if (!IS_LITERAL(list2val(ilist, TRUE)->etype)) {
735 werror (W_INIT_WRONG);
736 return;
737 }
738
739 if(pic16_printIvalChar (sym, type,
740 (ilist->type == INIT_DEEP ? ilist->init.deep : ilist),
741 SPEC_CVAL (sym->etype).v_char, ptype, p))
742 return;
743 }
744 /* not the special case */
745 if (ilist && ilist->type != INIT_DEEP)
746 {
747 werror (E_INIT_STRUCT, sym->name);
748 return;
749 }
750
751 iloop = (ilist ? ilist->init.deep : NULL);
752 lcnt = DCL_ELEM (type);
753
754 for (;;)
755 {
756 size++;
757 pic16_printIval (sym, type->next, iloop, ptype, p);
758 iloop = (iloop ? iloop->next : NULL);
759
760
761 /* if not array limits given & we */
762 /* are out of initialisers then */
763 if (!DCL_ELEM (type) && !iloop)
764 break;
765
766 /* no of elements given and we */
767 /* have generated for all of them */
768 if (!--lcnt) {
769 /* if initializers left */
770 if (iloop) {
771 werror (W_EXCESS_INITIALIZERS, "array", sym->name, sym->lineDef);
772 }
773 break;
774 }
775 }
776
777 #if 0
778 /* This causes bug #1843745. */
779 /* if we have not been given a size */
780 if (!DCL_ELEM (type))
781 DCL_ELEM (type) = size;
782 #endif
783
784 return;
785 }
786
787 /*-----------------------------------------------------------------*/
788 /* pic16_printIvalBitFields - generate initializer for bitfields */
789 /*-----------------------------------------------------------------*/
790 static void
pic16_printIvalBitFields(symbol ** sym,initList ** ilist,char ptype,void * p)791 pic16_printIvalBitFields (symbol **sym, initList **ilist, char ptype, void *p)
792 {
793 symbol *lsym = *sym;
794 initList *lilist = *ilist;
795 unsigned long ival = 0;
796 unsigned size = 0;
797 int bit_start = 0;
798 unsigned i;
799
800
801 #if DEBUG_PRINTIVAL
802 fprintf(stderr, "%s\n",__FUNCTION__);
803 #endif
804
805
806 while (lsym && IS_BITFIELD (lsym->type))
807 {
808 unsigned bit_length = SPEC_BLEN (lsym->etype);
809 if (0 == bit_length)
810 {
811 /* bit-field structure member with a width of 0 */
812 lsym = lsym->next;
813 break;
814 }
815 else if (!SPEC_BUNNAMED (lsym->etype))
816 {
817 /* not an unnamed bit-field structure member */
818 value *val = list2val (lilist, TRUE);
819
820 if (size)
821 {
822 if (bit_length > 8)
823 size += (bit_length + 7) / 8;
824 }
825 else
826 size = (bit_length + 7) / 8;
827
828 ival |= (ulFromVal (val) & ((1ul << bit_length) - 1ul)) << bit_start;
829 lilist = (lilist ? lilist->next : NULL);
830 }
831 bit_start += bit_length;
832 lsym = lsym->next;
833 if (lsym && IS_BITFIELD (lsym->type) && (0 == SPEC_BSTR (lsym->etype)))
834 {
835 /* a new integer */
836 break;
837 }
838 }
839
840 for (i = 0; i < size; i++)
841 pic16_emitDB (BYTE_IN_LONG (ival, i), ptype, p);
842
843 *sym = lsym;
844 *ilist = lilist;
845 }
846
847
848 /*-----------------------------------------------------------------*/
849 /* printIvalStruct - generates initial value for structures */
850 /*-----------------------------------------------------------------*/
851 static void
pic16_printIvalStruct(symbol * sym,sym_link * type,initList * ilist,char ptype,void * p)852 pic16_printIvalStruct (symbol * sym, sym_link * type,
853 initList * ilist, char ptype, void *p)
854 {
855 symbol *sflds;
856 initList *iloop = NULL;
857
858
859 #if DEBUG_PRINTIVAL
860 fprintf(stderr, "%s\n",__FUNCTION__);
861 #endif
862
863 sflds = SPEC_STRUCT (type)->fields;
864
865 if (ilist)
866 {
867 if (ilist->type != INIT_DEEP)
868 {
869 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
870 return;
871 }
872
873 iloop = ilist->init.deep;
874 }
875
876 while (sflds)
877 {
878 // fprintf(stderr, "%s:%d sflds: %p\tiloop = %p\n", __FILE__, __LINE__, sflds, iloop);
879 if (IS_BITFIELD (sflds->type))
880 {
881 pic16_printIvalBitFields (&sflds, &iloop, ptype, p);
882 }
883 else
884 {
885 pic16_printIval (sym, sflds->type, iloop, ptype, p);
886 sflds = sflds->next;
887 iloop = iloop ? iloop->next : NULL;
888 }
889 }
890 if (iloop)
891 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "struct", sym->name);
892 }
893
894 /*-----------------------------------------------------------------*/
895 /* printIvalUnion - generates initial value for unions */
896 /*-----------------------------------------------------------------*/
897 static void
pic16_printIvalUnion(symbol * sym,sym_link * type,initList * ilist,char ptype,void * p)898 pic16_printIvalUnion (symbol * sym, sym_link * type,
899 initList * ilist, char ptype, void *p)
900 {
901 //symbol *sflds;
902 initList *iloop = NULL;
903 unsigned int size;
904 symbol *sflds = NULL;
905
906 #if DEBUG_PRINTIVAL
907 fprintf(stderr, "%s\n",__FUNCTION__);
908 #endif
909
910 assert (type);
911
912 sflds = SPEC_STRUCT (type)->fields;
913
914 if (ilist) {
915 if (ilist->type != INIT_DEEP) {
916 werrorfl (sym->fileDef, sym->lineDef, E_INIT_STRUCT, sym->name);
917 return;
918 }
919
920 iloop = ilist->init.deep;
921 }
922
923 size = SPEC_STRUCT(type)->size;
924 sflds = SPEC_STRUCT(type)->fields;
925
926 /* skip past holes, print value */
927 while (iloop && iloop->type == INIT_HOLE)
928 {
929 iloop = iloop->next;
930 sflds = sflds->next;
931 }
932 pic16_printIval (sym, sflds->type, iloop, ptype, p);
933
934 /* if the first field is not the longest, fill with 0s */
935 while (size > getSize (sflds->type)) {
936 pic16_emitDB(0, ptype, p);
937 size--;
938 } // while
939 }
940
941 static int
pic16_isUnion(symbol * sym,sym_link * type)942 pic16_isUnion( symbol *sym, sym_link *type )
943 {
944 if (type && SPEC_STRUCT(type)->type == UNION) return 1;
945 return 0;
946 }
947
948 /*--------------------------------------------------------------------------*/
949 /* pic16_printIvalCharPtr - generates initial values for character pointers */
950 /*--------------------------------------------------------------------------*/
951 static int
pic16_printIvalCharPtr(symbol * sym,sym_link * type,value * val,char ptype,void * p)952 pic16_printIvalCharPtr (symbol * sym, sym_link * type, value * val, char ptype, void *p)
953 {
954 int size = 0;
955 int i;
956
957 /* PENDING: this is _very_ mcs51 specific, including a magic
958 number...
959 It's also endin specific.
960
961 VR - Attempting to port this function to pic16 port - 8-Jun-2004
962 */
963
964
965 #if DEBUG_PRINTIVAL
966 fprintf(stderr, "%s\n",__FUNCTION__);
967 #endif
968
969 size = getSize (type);
970
971 if (val->name && strlen (val->name))
972 {
973 if (size == 1) /* This appears to be Z80 specific?? */
974 {
975 pic16_emitDS(val->name, ptype, p);
976 }
977 else if (size == 2)
978 {
979 pic16_printPointerType (val->name, ptype, p);
980 }
981 else if (size == 3)
982 {
983 int type;
984 type = PTR_TYPE (SPEC_OCLS (val->etype));
985 if (val->sym && val->sym->isstrlit) {
986 // this is a literal string
987 type = CPOINTER;
988 }
989 pic16_printGPointerType(val->name, type, ptype, p);
990 }
991 else
992 {
993 fprintf (stderr, "*** internal error: unknown size in "
994 "printIvalCharPtr.\n");
995 assert(0);
996 }
997 }
998 else
999 {
1000 // these are literals assigned to pointers
1001 for (i = 0; i < size; i++)
1002 {
1003 pic16_emitDB(pic16aopLiteral(val, i), ptype, p);
1004 } // for
1005 }
1006
1007 if (val->sym && val->sym->isstrlit) { // && !isinSet(statsg->syms, val->sym)) {
1008 if(ptype == 'p' && !isinSet(statsg->syms, val->sym))addSet (&statsg->syms, val->sym);
1009 else if(ptype == 'f' /*&& !isinSet(rel_idataSymSet, val->sym)*/)addSet(&rel_idataSymSet, val->sym);
1010 }
1011
1012 return 1;
1013 }
1014
1015 /*-----------------------------------------------------------------------*/
1016 /* pic16_printIvalFuncPtr - generate initial value for function pointers */
1017 /*-----------------------------------------------------------------------*/
1018 static void
pic16_printIvalFuncPtr(sym_link * type,initList * ilist,char ptype,void * p)1019 pic16_printIvalFuncPtr (sym_link * type, initList * ilist, char ptype, void *p)
1020 {
1021 value *val;
1022 int dLvl = 0;
1023
1024
1025 #if DEBUG_PRINTIVAL
1026 fprintf(stderr, "%s\n",__FUNCTION__);
1027 #endif
1028
1029 if (ilist)
1030 val = list2val (ilist, TRUE);
1031 else
1032 val = valCastLiteral(type, 0.0, 0);
1033
1034 if (!val) {
1035 // an error has been thrown already
1036 val = constCharVal (0);
1037 }
1038
1039 if (IS_LITERAL(val->etype)) {
1040 if (0 && compareType(type, val->etype) == 0) {
1041 werrorfl (ilist->filename, ilist->lineno, E_INCOMPAT_TYPES);
1042 printFromToType (val->type, type);
1043 }
1044 pic16_printIvalCharPtr (NULL, type, val, ptype, p);
1045 return;
1046 }
1047
1048 /* check the types */
1049 if ((dLvl = compareType (val->type, type->next)) <= 0)
1050 {
1051 pic16_emitDB(0x00, ptype, p);
1052 return;
1053 }
1054
1055 /* now generate the name */
1056 if (!val->sym) {
1057 pic16_printGPointerType (val->name, CPOINTER /*DCL_TYPE(val->type)*/, ptype, p);
1058 } else {
1059 pic16_printGPointerType (val->sym->rname, CPOINTER /*DCL_TYPE(val->type)*/, ptype, p);
1060
1061 if(IS_FUNC(val->sym->type) && !val->sym->used && !IS_STATIC(val->sym->etype)) {
1062
1063 if(!checkSym(publics, val->sym))
1064 if(checkAddSym(&externs, val->sym) && (ptype == 'f')) {
1065 /* this has not been declared as extern
1066 * so declare it as a 'late extern' just after the symbol */
1067 fprintf((FILE *)p, ";\tdeclare symbol as extern\n");
1068 fprintf((FILE *)p, "\textern\t%s\n", val->sym->rname);
1069 fprintf((FILE *)p, ";\tcontinue variable declaration\n");
1070 }
1071 }
1072 }
1073
1074 return;
1075 }
1076
1077
1078 /*-----------------------------------------------------------------*/
1079 /* pic16_printIvalPtr - generates initial value for pointers */
1080 /*-----------------------------------------------------------------*/
1081 static void
pic16_printIvalPtr(symbol * sym,sym_link * type,initList * ilist,char ptype,void * p)1082 pic16_printIvalPtr (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p)
1083 {
1084 value *val;
1085 int size;
1086 int i;
1087
1088 #if 0
1089 fprintf(stderr, "%s:%d initialising pointer: %s size: %d\n", __FILE__, __LINE__,
1090 sym->rname, getSize(sym->type));
1091 #endif
1092
1093 /* if deep then */
1094 if (ilist && (ilist->type == INIT_DEEP))
1095 ilist = ilist->init.deep;
1096
1097 /* function pointer */
1098 if (IS_FUNC (type->next))
1099 {
1100 pic16_printIvalFuncPtr (type, ilist, ptype, p);
1101 return;
1102 }
1103
1104 if (!(val = pic16_initPointer (ilist, type)))
1105 return;
1106
1107 /* if character pointer */
1108 if (IS_CHAR (type->next))
1109 if (pic16_printIvalCharPtr (sym, type, val, ptype, p))
1110 return;
1111
1112 /* check the type */
1113 if (compareType (type, val->type) == 0) {
1114 werrorfl (ilist->filename, ilist->lineno, W_INIT_WRONG);
1115 printFromToType (val->type, type);
1116 }
1117
1118 size = getSize (type);
1119
1120 /* if val is literal */
1121 if (IS_LITERAL (val->etype))
1122 {
1123 for (i = 0; i < size; i++)
1124 {
1125 pic16_emitDB(pic16aopLiteral(val, i), ptype, p);
1126 } // for
1127 return;
1128 }
1129
1130 if (size == 1) /* Z80 specific?? */
1131 {
1132 pic16_emitDS(val->name, ptype, p);
1133 }
1134 else if (size == 2)
1135 {
1136 pic16_printPointerType (val->name, ptype, p);
1137 }
1138 else if (size == 3)
1139 {
1140 int itype = 0;
1141 itype = PTR_TYPE (SPEC_OCLS (val->etype));
1142 pic16_printGPointerType (val->name, itype, ptype, p);
1143 }
1144 else
1145 {
1146 assert(0);
1147 }
1148 }
1149
1150
1151
1152 /*-----------------------------------------------------------------*/
1153 /* pic16_printIval - generates code for initial value */
1154 /*-----------------------------------------------------------------*/
pic16_printIval(symbol * sym,sym_link * type,initList * ilist,char ptype,void * p)1155 void pic16_printIval (symbol * sym, sym_link * type, initList * ilist, char ptype, void *p)
1156 {
1157 // sym_link *itype;
1158
1159 if (!p)
1160 return;
1161
1162 #if 0
1163 fprintf(stderr, "%s:%d generating init for %s\n", __FILE__, __LINE__, sym->name);
1164 fprintf(stderr, "%s: IS_STRUCT: %d IS_ARRAY: %d IS_PTR: %d IS_SPEC: %d\n", sym->name,
1165 IS_STRUCT(type), IS_ARRAY(type), IS_PTR(type), IS_SPEC(type));
1166 #endif
1167
1168 /* Handle designated initializers */
1169 if (ilist)
1170 ilist = reorderIlist (type, ilist);
1171
1172 /* If this is a hole, substitute an appropriate initializer. */
1173 if (ilist && ilist->type == INIT_HOLE)
1174 {
1175 if (IS_AGGREGATE (type))
1176 {
1177 ilist = newiList(INIT_DEEP, NULL); /* init w/ {} */
1178 }
1179 else
1180 {
1181 ast *ast = newAst_VALUE (constVal("0"));
1182 ast = decorateType (ast, RESULT_TYPE_NONE);
1183 ilist = newiList(INIT_NODE, ast);
1184 }
1185 }
1186
1187 /* if structure then */
1188 if (IS_STRUCT (type))
1189 {
1190 if (pic16_isUnion(sym, type))
1191 {
1192 //fprintf(stderr,"%s union\n",__FUNCTION__);
1193 pic16_printIvalUnion (sym, type, ilist, ptype, p);
1194 } else {
1195 //fprintf(stderr,"%s struct\n",__FUNCTION__);
1196 pic16_printIvalStruct (sym, type, ilist, ptype, p);
1197 }
1198 return;
1199 }
1200
1201 /* if this is an array */
1202 if (IS_ARRAY (type))
1203 {
1204 // fprintf(stderr,"%s array\n",__FUNCTION__);
1205 pic16_printIvalArray (sym, type, ilist, ptype, p);
1206 return;
1207 }
1208
1209 #if 0
1210 if (ilist)
1211 {
1212 // not an aggregate, ilist must be a node
1213 if (ilist->type!=INIT_NODE) {
1214 // or a 1-element list
1215 if (ilist->init.deep->next) {
1216 werrorfl (sym->fileDef, sym->lineDef, W_EXCESS_INITIALIZERS, "scalar",
1217 sym->name);
1218 } else {
1219 ilist=ilist->init.deep;
1220 }
1221 }
1222
1223 #if 0
1224 // and the type must match
1225 itype=ilist->init.node->ftype;
1226
1227 if (compareType(type, itype)==0) {
1228 // special case for literal strings
1229 if (IS_ARRAY (itype) && IS_CHAR (getSpec(itype)) &&
1230 // which are really code pointers
1231 IS_PTR(type) && DCL_TYPE(type)==CPOINTER) {
1232 // no sweat
1233 } else {
1234 // werrorfl (ilist->filename, ilist->lineno, E_TYPE_MISMATCH, "assignment", " ");
1235 // printFromToType(itype, type);
1236 }
1237 }
1238 #endif
1239 }
1240 #endif
1241
1242 /* if this is a pointer */
1243 if (IS_PTR (type))
1244 {
1245 // fprintf(stderr,"%s pointer\n",__FUNCTION__);
1246 pic16_printIvalPtr (sym, type, ilist, ptype, p);
1247 return;
1248 }
1249
1250
1251 /* if type is SPECIFIER */
1252 if (IS_SPEC (type))
1253 {
1254 // fprintf(stderr,"%s spec\n",__FUNCTION__);
1255 pic16_printIvalType (sym, type, ilist, ptype, p);
1256 return;
1257 }
1258 }
1259
1260 static int
PIC16_IS_CONFIG_ADDRESS(int address)1261 PIC16_IS_CONFIG_ADDRESS(int address)
1262 {
1263 return ((address >= pic16->cwInfo.confAddrStart && address <= pic16->cwInfo.confAddrEnd));
1264 }
1265
1266 static int
PIC16_IS_IDLOC_ADDRESS(int address)1267 PIC16_IS_IDLOC_ADDRESS(int address)
1268 {
1269 return ((address >= pic16->idInfo.idAddrStart && address <= pic16->idInfo.idAddrEnd));
1270 }
1271
1272 /*-----------------------------------------------------------------*/
1273 /* emitStaticSeg - emitcode for the static segment */
1274 /*-----------------------------------------------------------------*/
1275 static void
pic16emitStaticSeg(memmap * map)1276 pic16emitStaticSeg (memmap * map)
1277 {
1278 symbol *sym;
1279 static int didcode = 0;
1280
1281 //fprintf(stderr, "%s\n",__FUNCTION__);
1282
1283 pic16_initDB ();
1284
1285 /* for all variables in this segment do */
1286 for (sym = setFirstItem (map->syms); sym; sym = setNextItem (map->syms))
1287 {
1288 int size = getSize (sym->type);
1289
1290 #if 0
1291 fprintf (stderr, "%s\t%s: sym: %s\tused: %d\tSPEC_ABSA: %d\tSPEC_AGGREGATE: %d\tCODE: %d\n\
1292 CODESPACE: %d\tCONST: %d\tPTRCONST: %d\tSPEC_CONST: %d\n", __FUNCTION__, map->sname, sym->name, sym->used, SPEC_ABSA (sym->etype), IS_AGGREGATE (sym->type), IS_CODE (sym->etype), IN_CODESPACE (SPEC_OCLS (sym->etype)), IS_CONSTANT (sym->etype), IS_PTR_CONST (sym->etype), SPEC_CONST (sym->etype));
1293 printTypeChain (sym->type, stderr);
1294 fprintf (stderr, "\n");
1295 #endif
1296
1297 if (SPEC_ABSA (sym->etype) && PIC16_IS_CONFIG_ADDRESS (SPEC_ADDR (sym->etype)))
1298 {
1299 pic16_assignConfigWordValue (SPEC_ADDR (sym->etype), (int) ulFromVal (list2val (sym->ival, TRUE)));
1300 continue;
1301 }
1302
1303 if (SPEC_ABSA (sym->etype) && PIC16_IS_IDLOC_ADDRESS (SPEC_ADDR (sym->etype)))
1304 {
1305 pic16_assignIdByteValue (SPEC_ADDR (sym->etype), (char) ulFromVal (list2val (sym->ival, TRUE)));
1306 continue;
1307 }
1308
1309 /* if it is "extern" then do nothing */
1310 if (IS_EXTERN (sym->etype) /* && !SPEC_ABSA(sym->etype) */ )
1311 {
1312 checkAddSym (&externs, sym);
1313 continue;
1314 }
1315
1316 /* bail out on incomplete types */
1317 if (0 == size)
1318 {
1319 werrorfl (sym->fileDef, sym->lineDef, E_UNKNOWN_SIZE, sym->name);
1320 }
1321
1322 /* if it is not static add it to the public
1323 table */
1324 if (!IS_STATIC (sym->etype))
1325 {
1326 /* do not emit if it is a config word declaration */
1327 checkAddSym (&publics, sym);
1328 }
1329
1330 /* print extra debug info if required */
1331 if (options.debug || sym->level == 0)
1332 {
1333 /* NOTE to me - cdbFile may be null in which case,
1334 * the sym name will be printed to stdout. oh well */
1335 debugFile->writeSymbol (sym);
1336 }
1337
1338 /* if it has an absolute address */
1339 if (SPEC_ABSA (sym->etype))
1340 {
1341 // fprintf(stderr, "%s:%d spec_absa is true for symbol: %s\n",
1342 // __FILE__, __LINE__, sym->name);
1343
1344 if (!sym->ival && IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) && SPEC_CVAL (sym->etype).v_char)
1345 {
1346 /* symbol has absolute address but no initial value */
1347 /* special case for character strings */
1348
1349 // fprintf(stderr, "%s:%d printing code string from %s\n", __FILE__, __LINE__, sym->rname);
1350
1351 pic16_pCodeConstString (sym->rname, SPEC_CVAL (sym->etype).v_char, getSize (sym->type));
1352 }
1353 else
1354 {
1355 pBlock *pb;
1356 symbol *asym;
1357 absSym *abSym;
1358 pCode *pcf;
1359
1360 /* symbol has absolute address and initial value */
1361 ++noAlloc;
1362 resolveIvalSym (sym->ival, sym->type);
1363 asym = newSymbol (sym->rname, 0);
1364 abSym = Safe_alloc(sizeof (absSym));
1365 strncpy(abSym->name, sym->rname, sizeof(abSym->name) - 1);
1366 abSym->name[sizeof(abSym->name) - 1] = '\0';
1367 abSym->address = SPEC_ADDR (sym->etype);
1368 addSet (&absSymSet, abSym);
1369
1370 pb = pic16_newpCodeChain (NULL, 'A', pic16_newpCodeCharP ("; Starting pCode block for absolute Ival"));
1371 pic16_addpBlock (pb);
1372
1373 pcf = pic16_newpCodeFunction (moduleName, asym->name);
1374 PCF (pcf)->absblock = TRUE;
1375
1376 pic16_addpCode2pBlock (pb, pcf);
1377 pic16_addpCode2pBlock (pb, pic16_newpCodeLabel (sym->rname, -1));
1378 //fprintf(stderr, "%s:%d [1] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1379 /* if it has an initial value */
1380 if (sym->ival)
1381 {
1382 pic16_printIval (sym, sym->type, sym->ival, 'p', (void *) pb);
1383 pic16_flushDB ('p', (void *) pb);
1384 }
1385
1386 pic16_addpCode2pBlock (pb, pic16_newpCodeFunction (NULL, NULL));
1387 --noAlloc;
1388 }
1389 }
1390 else
1391 {
1392 // fprintf(stderr, "%s:%d spec_absa is false for symbol: %s\n",
1393 // __FILE__, __LINE__, sym->name);
1394
1395
1396 /* if it has an initial value */
1397 if (sym->ival)
1398 {
1399 pBlock *pb;
1400
1401 /* symbol doesn't have absolute address but has initial value */
1402 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
1403 ++noAlloc;
1404 resolveIvalSym (sym->ival, sym->type);
1405
1406 pb = pic16_newpCodeChain (NULL, 'P', pic16_newpCodeCharP ("; Starting pCode block for Ival"));
1407 pic16_addpBlock (pb);
1408
1409 if (!didcode)
1410 {
1411 /* make sure that 'code' directive is emitted before, once */
1412 pic16_addpCode2pBlock (pb, pic16_newpCodeAsmDir ("code", NULL));
1413
1414 ++didcode;
1415 }
1416
1417 pic16_addpCode2pBlock (pb, pic16_newpCodeLabel (sym->rname, -1));
1418 //fprintf(stderr, "%s:%d [2] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1419 pic16_printIval (sym, sym->type, sym->ival, 'p', (void *) pb);
1420 pic16_flushDB ('p', (void *) pb);
1421 --noAlloc;
1422 }
1423 else
1424 {
1425
1426 /* symbol doesn't have absolute address and no initial value */
1427 /* allocate space */
1428 // fprintf(stderr, "%s:%d [3] generating init for label: %s\n", __FILE__, __LINE__, sym->rname);
1429 dbuf_printf (&code->oBuf, "%s:\n", sym->rname);
1430 /* special case for character strings */
1431 if (IS_ARRAY (sym->type) && IS_CHAR (sym->type->next) && SPEC_CVAL (sym->etype).v_char)
1432 {
1433
1434 // fprintf(stderr, "%s:%d printing code string for %s\n", __FILE__, __LINE__, sym->rname);
1435
1436 pic16_pCodeConstString (sym->rname, SPEC_CVAL (sym->etype).v_char, getSize (sym->type));
1437 }
1438 else
1439 {
1440 assert (0);
1441 }
1442 }
1443 }
1444 }
1445 }
1446
1447 /*-----------------------------------------------------------------*/
1448 /* pic16_emitConfigRegs - emits the configuration registers */
1449 /*-----------------------------------------------------------------*/
pic16_emitConfigRegs(FILE * of)1450 void pic16_emitConfigRegs (FILE *of)
1451 {
1452 int i;
1453
1454 if (pic16_config_options)
1455 {
1456 pic16_config_options_t *p;
1457
1458 /* check if mixing config directives */
1459 for (i = 0; i <= (pic16->cwInfo.confAddrEnd - pic16->cwInfo.confAddrStart); ++i)
1460 if (pic16->cwInfo.crInfo[i].emit)
1461 {
1462 werror (E_MIXING_CONFIG);
1463 break;
1464 }
1465
1466 /* emit new config directives */
1467 for (p = pic16_config_options; p; p = p->next)
1468 fprintf (of, "\t%s\n", p->config_str);
1469 }
1470
1471 /* emit old __config directives */
1472 for (i = 0; i <= (pic16->cwInfo.confAddrEnd - pic16->cwInfo.confAddrStart); ++i)
1473 if (pic16->cwInfo.crInfo[i].emit) //mask != -1)
1474 fprintf (of, "\t__config 0x%06x, 0x%02x\n",
1475 pic16->cwInfo.confAddrStart + i,
1476 (unsigned char) pic16->cwInfo.crInfo[i].value);
1477 }
1478
pic16_emitIDRegs(FILE * of)1479 void pic16_emitIDRegs (FILE *of)
1480 {
1481 int i;
1482
1483 for (i=0; i <= (pic16->idInfo.idAddrEnd - pic16->idInfo.idAddrStart); i++)
1484 if (pic16->idInfo.irInfo[i].emit)
1485 fprintf (of, "\t__idlocs 0x%06x, 0x%02x\n",
1486 pic16->idInfo.idAddrStart + i,
1487 (unsigned char) pic16->idInfo.irInfo[i].value);
1488 }
1489
1490
1491 static void
pic16emitMaps()1492 pic16emitMaps ()
1493 {
1494 /* no special considerations for the following
1495 data, idata & bit & xdata */
1496 pic16emitRegularMap (data, TRUE, TRUE);
1497 pic16emitRegularMap (idata, TRUE, TRUE);
1498 pic16emitRegularMap (bit, TRUE, FALSE);
1499 pic16emitRegularMap (xdata, TRUE, TRUE);
1500 pic16emitRegularMap (sfr, FALSE, FALSE);
1501 pic16emitRegularMap (sfrbit, FALSE, FALSE);
1502 pic16emitRegularMap (code, TRUE, FALSE);
1503 pic16emitStaticSeg (statsg);
1504 pic16emitStaticSeg (c_abs);
1505 }
1506
1507 /*-----------------------------------------------------------------*/
1508 /* createInterruptVect - creates the interrupt vector */
1509 /*-----------------------------------------------------------------*/
1510 static void
pic16createInterruptVect(struct dbuf_s * vBuf)1511 pic16createInterruptVect (struct dbuf_s * vBuf)
1512 {
1513 /* if the main is only a prototype ie. no body then do nothing */
1514 #if 0
1515 if (!IFFUNC_HASBODY(mainf->type)) {
1516 /* if ! compile only then main function should be present */
1517 if (!options.cc_only)
1518 werror (E_NO_MAIN);
1519 return;
1520 }
1521 #endif
1522 #if 0
1523 if((!pic16_options.omit_ivt) || (pic16_options.omit_ivt && pic16_options.leave_reset)) {
1524 dbuf_printf (vBuf, ";\t.area\t%s\n", CODE_NAME);
1525 dbuf_printf (vBuf, ".intvecs\tcode\t0x%06x\n", pic16_options.ivt_loc);
1526
1527 /* this is an overkill since WE are the port,
1528 * and we know if we have a genIVT function! */
1529 if(port->genIVT) {
1530 port->genIVT(vFile, interrupts, maxInterrupts);
1531 }
1532 }
1533 #endif
1534
1535 }
1536
1537
1538 /*-----------------------------------------------------------------*/
1539 /* pic16initialComments - puts in some initial comments */
1540 /*-----------------------------------------------------------------*/
1541 static void
pic16initialComments(FILE * afile)1542 pic16initialComments (FILE * afile)
1543 {
1544 initialComments (afile);
1545 fprintf (afile, "; PIC16 port for the Microchip 16-bit core micros\n");
1546 if (pic16_options.xinst) {
1547 fprintf (afile, "; * Extended Instruction Set\n");
1548 } // if
1549
1550 if (pic16_mplab_comp) {
1551 fprintf(afile, "; * MPLAB/MPASM/MPASMWIN/MPLINK compatibility mode enabled\n");
1552 } // if
1553 fprintf (afile, "%s", iComments2);
1554
1555 if (options.debug) {
1556 fprintf (afile, "\n\t.ident \"SDCC version %s #%s [pic16 port]%s\"\n",
1557 SDCC_VERSION_STR, getBuildNumber(), (!pic16_options.xinst?"":" {extended}") );
1558 } // if
1559 }
1560
1561 int
pic16_stringInSet(const char * str,set ** world,int autoAdd)1562 pic16_stringInSet(const char *str, set **world, int autoAdd)
1563 {
1564 char *s;
1565
1566 if (!str) return 1;
1567 assert(world);
1568
1569 for (s = setFirstItem(*world); s; s = setNextItem(*world))
1570 {
1571 /* found in set */
1572 if (0 == strcmp(s, str)) return 1;
1573 }
1574
1575 /* not found */
1576 if (autoAdd) addSet(world, Safe_strdup(str));
1577 return 0;
1578 }
1579
1580 static int
pic16_emitSymbolIfNew(FILE * file,const char * fmt,const char * sym,int checkLocals)1581 pic16_emitSymbolIfNew(FILE *file, const char *fmt, const char *sym, int checkLocals)
1582 {
1583 static set *emitted = NULL;
1584
1585 if (!pic16_stringInSet(sym, &emitted, 1)) {
1586 /* sym was not in emittedSymbols */
1587 if (!checkLocals || !pic16_stringInSet(sym, &pic16_localFunctions, 0)) {
1588 /* sym is not a locally defined function---avoid bug #1443651 */
1589 fprintf( file, fmt, sym );
1590 return 0;
1591 }
1592 }
1593 return 1;
1594 }
1595
1596 /*-----------------------------------------------------------------*/
1597 /* printPublics - generates global declarations for publics */
1598 /*-----------------------------------------------------------------*/
1599 static void
pic16printPublics(FILE * afile)1600 pic16printPublics (FILE *afile)
1601 {
1602 symbol *sym;
1603
1604 fprintf (afile, "\n%s", iComments2);
1605 fprintf (afile, "; public variables in this module\n");
1606 fprintf (afile, "%s", iComments2);
1607
1608 for(sym = setFirstItem (publics); sym; sym = setNextItem (publics))
1609 /* sanity check */
1610 if(!IS_STATIC(sym->etype))
1611 pic16_emitSymbolIfNew(afile, "\tglobal\t%s\n", sym->rname, 0);
1612 }
1613
1614 /*-----------------------------------------------------------------*/
1615 /* printExterns - generates extern declarations for externs */
1616 /*-----------------------------------------------------------------*/
1617 static void
pic16_printExterns(FILE * afile)1618 pic16_printExterns(FILE *afile)
1619 {
1620 symbol *sym;
1621
1622 /* print nothing if no externs to declare */
1623 if(!elementsInSet(externs) && !elementsInSet(pic16_builtin_functions))
1624 return;
1625
1626 fprintf(afile, "\n%s", iComments2);
1627 fprintf(afile, "; extern variables in this module\n");
1628 fprintf(afile, "%s", iComments2);
1629
1630 for(sym = setFirstItem(externs); sym; sym = setNextItem(externs))
1631 pic16_emitSymbolIfNew(afile, "\textern\t%s\n", sym->rname, 1);
1632
1633 for(sym = setFirstItem(pic16_builtin_functions); sym; sym = setNextItem(pic16_builtin_functions))
1634 pic16_emitSymbolIfNew(afile, "\textern\t_%s\n", sym->name, 1);
1635 }
1636
1637 /*-----------------------------------------------------------------*/
1638 /* emitOverlay - will emit code for the overlay stuff */
1639 /*-----------------------------------------------------------------*/
1640 static void
pic16emitOverlay(struct dbuf_s * aBuf)1641 pic16emitOverlay (struct dbuf_s *aBuf)
1642 {
1643 set *ovrset;
1644
1645 if (!elementsInSet (ovrSetSets))
1646 dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name);
1647
1648 /* for each of the sets in the overlay segment do */
1649 for (ovrset = setFirstItem (ovrSetSets); ovrset;
1650 ovrset = setNextItem (ovrSetSets))
1651 {
1652
1653 symbol *sym;
1654
1655 if (elementsInSet (ovrset))
1656 {
1657 /* this dummy area is used to fool the assembler
1658 otherwise the assembler will append each of these
1659 declarations into one chunk and will not overlay
1660 sad but true */
1661 dbuf_printf (aBuf, ";\t.area _DUMMY\n");
1662 /* output the area informtion */
1663 dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
1664 }
1665
1666 for (sym = setFirstItem (ovrset); sym;
1667 sym = setNextItem (ovrset))
1668 {
1669
1670 /* if extern then do nothing */
1671 if (IS_EXTERN (sym->etype))
1672 continue;
1673
1674 /* if allocation required check is needed
1675 then check if the symbol really requires
1676 allocation only for local variables */
1677 if (!IS_AGGREGATE (sym->type) &&
1678 !(sym->_isparm && !IS_REGPARM (sym->etype))
1679 && !sym->allocreq && sym->level)
1680 continue;
1681
1682 /* if global variable & not static or extern
1683 and addPublics allowed then add it to the public set */
1684 if ((sym->_isparm && !IS_REGPARM (sym->etype))
1685 && !IS_STATIC (sym->etype)) {
1686 // fprintf(stderr, "%s:%d %s accessed\n", __FILE__, __LINE__, __FUNCTION__);
1687 checkAddSym(&publics, sym);
1688 // addSetHead (&publics, sym);
1689 }
1690
1691 /* if extern then do nothing or is a function
1692 then do nothing */
1693 if (IS_FUNC (sym->type))
1694 continue;
1695
1696
1697 /* if is has an absolute address then generate
1698 an equate for this no need to allocate space */
1699 if (SPEC_ABSA (sym->etype))
1700 {
1701
1702 if (options.debug || sym->level == 0)
1703 dbuf_printf (aBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
1704
1705 dbuf_printf (aBuf, "%s\t=\t0x%04x\n",
1706 sym->rname,
1707 SPEC_ADDR (sym->etype));
1708 }
1709 else
1710 {
1711 if (options.debug || sym->level == 0)
1712 dbuf_printf (aBuf, "==.\n");
1713
1714 /* allocate space */
1715 dbuf_printf (aBuf, "%s:\n", sym->rname);
1716 dbuf_printf (aBuf, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
1717 }
1718
1719 }
1720 }
1721 }
1722
1723 static void
emitStatistics(FILE * asmFile)1724 emitStatistics(FILE *asmFile)
1725 {
1726 unsigned long isize, udsize, ramsize;
1727 statistics.isize = pic16_countInstructions();
1728 isize = (((long)statistics.isize) >= 0) ? statistics.isize : 0;
1729 udsize = (((long)statistics.udsize) >= 0) ? statistics.udsize : 0;
1730 ramsize = pic16 ? pic16->RAMsize : 0x200;
1731 ramsize -= 256; /* ignore access bank and SFRs */
1732 if (ramsize == 0) ramsize = 64; /* prevent division by zero (below) */
1733
1734 fprintf (asmFile, "\n\n; Statistics:\n");
1735 fprintf (asmFile, "; code size:\t%5ld (0x%04lx) bytes (%5.2f%%)\n; \t%5ld (0x%04lx) words\n",
1736 isize, isize, (isize*100.0)/(128UL << 10),
1737 isize>>1, isize>>1);
1738 fprintf (asmFile, "; udata size:\t%5ld (0x%04lx) bytes (%5.2f%%)\n",
1739 udsize, udsize, (udsize*100.0) / (1.0 * ramsize));
1740 fprintf (asmFile, "; access size:\t%5ld (0x%04lx) bytes\n",
1741 statistics.intsize, statistics.intsize);
1742
1743 fprintf (asmFile, "\n\n");
1744 }
1745
1746
1747
1748 /*-----------------------------------------------------------------*/
1749 /* glue - the final glue that hold the whole thing together */
1750 /*-----------------------------------------------------------------*/
1751 void
pic16glue()1752 pic16glue ()
1753 {
1754 FILE *asmFile;
1755 struct dbuf_s ovrBuf;
1756 struct dbuf_s vBuf;
1757
1758 dbuf_init(&ovrBuf, 4096);
1759 dbuf_init(&vBuf, 4096);
1760
1761 mainf = newSymbol ("main", 0);
1762 mainf->block = 0;
1763
1764 mainf = findSymWithLevel(SymbolTab, mainf);
1765
1766 if (mainf && IFFUNC_HASBODY(mainf->type) && pic16->xinst && !has_xinst_config)
1767 {
1768 fprintf(stderr, "WARNING: The target device seems to support XINST and no #pragma config XINST=OFF was found.\n");
1769 fprintf(stderr, " The code generated by SDCC does probably not work when XINST is enabled (possibly by default).\n");
1770 fprintf(stderr, " Please make sure to disable XINST.\n");
1771 fprintf(stderr, " (If the target does not actually support XINST, please report this as a bug in SDCC.)\n");
1772 } // if
1773
1774 pic16_pCodeInitRegisters();
1775
1776 if(pic16_options.no_crt && mainf && IFFUNC_HASBODY(mainf->type)) {
1777 pBlock *pb = pic16_newpCodeChain(NULL,'X',pic16_newpCodeCharP("; Starting pCode block"));
1778
1779 pic16_addpBlock(pb);
1780
1781 /* entry point @ start of CSEG */
1782 pic16_addpCode2pBlock(pb,pic16_newpCodeLabel("__sdcc_program_startup",-1));
1783
1784 if(initsfpnt) {
1785 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1786 pic16_popGetLit2(1, pic16_newpCodeOpRegFromStr("_stack_end"))));
1787 pic16_addpCode2pBlock(pb, pic16_newpCode(POC_LFSR,
1788 pic16_popGetLit2(2, pic16_newpCodeOpRegFromStr("_stack_end"))));
1789 }
1790
1791 /* put in the call to main */
1792 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_CALL,pic16_newpCodeOp("_main",PO_STR)));
1793
1794
1795 pic16_addpCode2pBlock(pb,pic16_newpCodeCharP(";\treturn from main will return to caller\n"));
1796 pic16_addpCode2pBlock(pb,pic16_newpCode(POC_RETURN,NULL));
1797 }
1798
1799 /* At this point we've got all the code in the form of pCode structures */
1800 /* Now it needs to be rearranged into the order it should be placed in the */
1801 /* code space */
1802
1803 pic16_movepBlock2Head('P'); // Last
1804 pic16_movepBlock2Head(code->dbName);
1805 pic16_movepBlock2Head('X');
1806 pic16_movepBlock2Head(statsg->dbName); // First
1807
1808 /* print the global struct definitions */
1809
1810 /* PENDING: this isnt the best place but it will do */
1811 if (port->general.glue_up_main) {
1812 /* create the interrupt vector table */
1813 pic16createInterruptVect (&vBuf);
1814 }
1815
1816 /* emit code for the all the variables declared */
1817 pic16emitMaps ();
1818
1819 /* do the overlay segments */
1820 pic16emitOverlay(&ovrBuf);
1821 pic16_AnalyzepCode('*');
1822
1823 #if 1
1824 if(pic16_options.dumpcalltree) {
1825 FILE *cFile;
1826
1827 SNPRINTF(buffer, sizeof(buffer), "%s.calltree", dstFileName);
1828 cFile = fopen(buffer, "w");
1829 pic16_printCallTree( cFile );
1830 fclose(cFile);
1831 }
1832 #endif
1833
1834 pic16_InlinepCode();
1835 pic16_AnalyzepCode('*');
1836
1837 if(pic16_debug_verbose)
1838 pic16_pcode_test();
1839
1840 /* now put it all together into the assembler file */
1841 /* create the assembler file name */
1842 if((noAssemble || options.c1mode) && fullDstFileName) {
1843 SNPRINTF(buffer, sizeof(buffer), "%s", fullDstFileName);
1844 } else {
1845 SNPRINTF(buffer, sizeof(buffer), "%s.asm", dstFileName);
1846 }
1847
1848 if(!(asmFile = fopen (buffer, "w"))) {
1849 werror (E_FILE_OPEN_ERR, buffer);
1850 exit (1);
1851 }
1852
1853 /* initial comments */
1854 pic16initialComments (asmFile);
1855
1856 /* print module name */
1857 if(options.debug)
1858 fprintf(asmFile, "\t.file\t\"%s\"\n", fullSrcFileName);
1859
1860 /* Let the port generate any global directives, etc. */
1861 if(port->genAssemblerPreamble) {
1862 port->genAssemblerPreamble(asmFile);
1863 }
1864
1865 /* Put all variables into a cblock */
1866 pic16_AnalyzeBanking();
1867
1868 #if 0
1869 if(pic16_options.opt_flags & OF_LR_SUPPORT) {
1870 pic16_OptimizeLocalRegs();
1871 }
1872 #endif
1873
1874 /* remove redundant BANKSELs -- added by RN 2005-01-17 */
1875 if(pic16_options.opt_banksel > 1) {
1876 pic16_OptimizeBanksel();
1877 }
1878
1879 /* turn GOTOs into BRAs -- added by RN 2004-11-16 */
1880 if(!(pic16_options.opt_flags & OF_NO_OPTIMIZE_GOTO)) {
1881 pic16_OptimizeJumps();
1882 }
1883
1884 /* print the global variables in this module */
1885 pic16printPublics (asmFile);
1886
1887 /* print the extern variables to this module */
1888 pic16_printExterns(asmFile);
1889
1890 pic16_writeUsedRegs(asmFile);
1891
1892 #if 0
1893 /* no xdata in pic */
1894 /* if external stack then reserve space of it */
1895 if(mainf && IFFUNC_HASBODY(mainf->type) && options.useXstack ) {
1896 fprintf (asmFile, "%s", iComments2);
1897 fprintf (asmFile, "; external stack\n");
1898 fprintf (asmFile, "%s", iComments2);
1899 fprintf (asmFile,";\t.area XSEG (XDATA)\n"); /* MOF */
1900 fprintf (asmFile,";\t.ds 256\n");
1901 }
1902 #endif
1903
1904 #if 0
1905 /* no xdata in pic */
1906 /* copy xtern ram data */
1907 fprintf (asmFile, "%s", iComments2);
1908 fprintf (asmFile, "; external ram data\n");
1909 fprintf (asmFile, "%s", iComments2);
1910 dbuf_write_and_destroy (&xdata->oBuf, asmFile);
1911 #endif
1912
1913 #if 0
1914 /* copy the bit segment */
1915 fprintf (asmFile, "%s", iComments2);
1916 fprintf (asmFile, "; bit data\n");
1917 fprintf (asmFile, "%s", iComments2);
1918 dbuf_write_and_destroy (&bit->oBuf, asmFile);
1919 #endif
1920
1921 /* copy the interrupt vector table */
1922 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1923 fprintf (asmFile, "\n%s", iComments2);
1924 fprintf (asmFile, "; interrupt vector\n");
1925 fprintf (asmFile, "%s", iComments2);
1926 dbuf_write_and_destroy (&vBuf, asmFile);
1927 }
1928
1929 /* copy global & static initialisations */
1930 fprintf (asmFile, "\n%s", iComments2);
1931 fprintf (asmFile, "; global & static initialisations\n");
1932 fprintf (asmFile, "%s", iComments2);
1933
1934 if(pic16_debug_verbose)
1935 fprintf(asmFile, "; A code from now on!\n");
1936
1937 pic16_copypCode(asmFile, 'A');
1938
1939 if(pic16_options.no_crt) {
1940 if(mainf && IFFUNC_HASBODY(mainf->type)) {
1941 fprintf(asmFile, "\tcode\n");
1942 fprintf(asmFile,"__sdcc_gsinit_startup:\n");
1943 }
1944 }
1945
1946 // dbuf_write_and_destroy (&code->oBuf, stderr);
1947
1948 fprintf(asmFile, "; I code from now on!\n");
1949 pic16_copypCode(asmFile, 'I');
1950
1951 if(pic16_debug_verbose)
1952 fprintf(asmFile, "; dbName from now on!\n");
1953
1954 pic16_copypCode(asmFile, statsg->dbName);
1955
1956 if(pic16_options.no_crt) {
1957 if (port->general.glue_up_main && mainf && IFFUNC_HASBODY(mainf->type)) {
1958 fprintf (asmFile,"\tgoto\t__sdcc_program_startup\n");
1959 }
1960 }
1961
1962 if(pic16_debug_verbose)
1963 fprintf(asmFile, "; X code from now on!\n");
1964
1965 pic16_copypCode(asmFile, 'X');
1966
1967 if(pic16_debug_verbose)
1968 fprintf(asmFile, "; M code from now on!\n");
1969
1970 pic16_copypCode(asmFile, 'M');
1971
1972 pic16_copypCode(asmFile, code->dbName);
1973
1974 pic16_copypCode(asmFile, 'P');
1975
1976 emitStatistics(asmFile);
1977
1978 fprintf (asmFile,"\tend\n");
1979 fclose (asmFile);
1980 }
1981