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 -------------------------------------------------------------------------*/
26 #include "dbuf_string.h"
38 extern struct dbuf_s *codeOutBuf;
40 extern void initialComments (FILE *afile);
41 extern operand *operandFromAst (ast *tree, int lvl);
42 extern value *initPointer (initList *ilist, sym_link *toType);
45 set *pic14_localFunctions = NULL;
46 int pic14_hasInterrupt = 0; // Indicates whether to emit interrupt handler or not
48 int pic14_stringInSet(const char *str, set **world, int autoAdd);
51 #ifdef WORDS_BIGENDIAN
52 #define _ENDIAN(x) (3-x)
54 #define _ENDIAN(x) (x)
57 #define BYTE_IN_LONG(x,b) ((x>>(8*_ENDIAN(b)))&0xff)
58 #define IS_GLOBAL(sym) ((sym)->level == 0)
59 #define IS_DEFINED_HERE(sym) (!IS_EXTERN(sym->etype))
61 /* dbufs for initialized data (idata and code sections),
62 * extern, and global declarations */
63 static struct dbuf_s *ivalBuf, *extBuf, *gloBuf, *gloDefBuf;
65 static set *emitted = NULL;
67 static void showAllMemmaps (FILE *of); // XXX: emits initialized symbols
70 emitPseudoStack(struct dbuf_s *oBuf, struct dbuf_s *oBufExt)
72 int shared, low, high, size, i;
75 /* also emit STK symbols
76 * XXX: This is ugly and fails as soon as devices start to get
77 * differently sized sharebanks, since STK12 will be
78 * required by larger devices but only up to STK03 might
79 * be defined using smaller devices. */
80 shared = pic14_getSharedStack(&low, &high, &size);
81 if (!pic14_options.isLibrarySource)
85 dbuf_printf (oBuf, "\n");
86 dbuf_printf (oBuf, "\tglobal PSAVE\n");
87 dbuf_printf (oBuf, "\tglobal SSAVE\n");
88 dbuf_printf (oBuf, "\tglobal WSAVE\n");
89 for (i = size - 4; i >= 0; i--) {
90 dbuf_printf (oBuf, "\tglobal STK%02d\n", i);
92 dbuf_printf (oBuf, "\n");
94 // 16f84 has no SHAREBANK (in linkerscript) but memory aliased in two
97 // for single banked devices: use normal, "banked" RAM
98 dbuf_printf (oBuf, "sharebank udata_ovr 0x%04X\n", low);
100 // for devices with at least two banks, require a sharebank section
101 dbuf_printf (oBuf, "sharebank udata_shr\n");
103 dbuf_printf (oBuf, "PSAVE\tres 1\n");
104 dbuf_printf (oBuf, "SSAVE\tres 1\n");
105 dbuf_printf (oBuf, "WSAVE\tres 1\n"); // WSAVE *must* be in sharebank (IRQ handlers)
106 /* fill rest of sharebank with stack STKxx .. STK00 */
107 for (i = size - 4; i >= 0; i--) {
108 dbuf_printf (oBuf, "STK%02d\tres 1\n", i);
111 /* declare STKxx as extern for all files
112 * except the one containing main() */
113 dbuf_printf (oBufExt, "\n");
114 dbuf_printf (oBufExt, "\textern PSAVE\n");
115 dbuf_printf (oBufExt, "\textern SSAVE\n");
116 dbuf_printf (oBufExt, "\textern WSAVE\n");
117 for (i = size - 4; i >= 0; i--) {
119 SNPRINTF(&buffer[0], 127, "STK%02d", i);
120 dbuf_printf (oBufExt, "\textern %s\n", &buffer[0]);
121 pic14_stringInSet(&buffer[0], &emitted, 1);
124 dbuf_printf (oBuf, "\n");
128 emitIfNew(struct dbuf_s *oBuf, set **emitted, const char *fmt,
131 int wasPresent = pic14_stringInSet(name, emitted, 1);
134 dbuf_printf (oBuf, fmt, name);
136 return (!wasPresent);
140 pic14_constructAbsMap (struct dbuf_s *oBuf, struct dbuf_s *gloBuf)
142 memmap *maps[] = { data, sfr, NULL };
147 int addr, min=-1, max=-1;
150 for (i=0; maps[i] != NULL; i++)
152 for (sym = (symbol *)setFirstItem (maps[i]->syms);
153 sym; sym = setNextItem (maps[i]->syms))
155 if (IS_DEFINED_HERE(sym) && SPEC_ABSA(sym->etype))
157 addr = SPEC_ADDR(sym->etype);
159 /* handle CONFIG words here */
160 if (IS_CONFIG_ADDRESS( addr ))
162 //fprintf( stderr, "%s: assignment to CONFIG@0x%x found\n", __FUNCTION__, addr );
163 //fprintf( stderr, "ival: %p (0x%x)\n", sym->ival, (int)list2int( sym->ival ) );
165 pic14_assignConfigWordValue( addr, (int)list2int( sym->ival ) );
167 fprintf( stderr, "ERROR: Symbol %s, which is covering a __CONFIG word must be initialized!\n", sym->name );
172 if (max == -1 || addr > max) max = addr;
173 if (min == -1 || addr < min) min = addr;
174 //fprintf (stderr, "%s: sym %s @ 0x%x\n", __FUNCTION__, sym->name, addr);
175 aliases = hTabItemWithKey (ht, addr);
177 /* May not use addSetHead, as we cannot update the
178 * list's head in the hastable `ht'. */
179 addSet (&aliases, sym);
181 fprintf( stderr, "%s: now %d aliases for %s @ 0x%x\n",
182 __FUNCTION__, elementsInSet(aliases), sym->name, addr);
185 addSet (&aliases, sym);
186 hTabAddItem (&ht, addr, aliases);
192 /* now emit definitions for all absolute symbols */
193 dbuf_printf (oBuf, "%s", iComments2);
194 dbuf_printf (oBuf, "; absolute symbol definitions\n");
195 dbuf_printf (oBuf, "%s", iComments2);
196 for (addr=min; addr <= max; addr++)
199 aliases = hTabItemWithKey (ht, addr);
200 if (aliases && elementsInSet(aliases)) {
201 /* Make sure there is no initialized value at this location! */
202 for (sym = setFirstItem(aliases); sym; sym = setNextItem(aliases)) {
203 if (sym->ival) break;
207 dbuf_printf (oBuf, "UD_abs_%s_%x\tudata_ovr\t0x%04x\n",
208 moduleName, addr, addr);
209 for (sym = setFirstItem (aliases); sym;
210 sym = setNextItem (aliases))
212 if (getSize(sym->type) > size) {
213 size = getSize(sym->type);
216 /* initialized values are handled somewhere else */
217 if (sym->ival) continue;
219 /* emit STATUS as well as _STATUS, required for SFRs only */
220 //dbuf_printf (oBuf, "%s\tres\t0\n", sym->name);
221 dbuf_printf (oBuf, "%s\n", sym->rname);
223 if (IS_GLOBAL(sym) && !IS_STATIC(sym->etype)) {
224 //emitIfNew(gloBuf, &emitted, "\tglobal\t%s\n", sym->name);
225 emitIfNew(gloBuf, &emitted, "\tglobal\t%s\n", sym->rname);
228 dbuf_printf (oBuf, "\tres\t%d\n", size);
233 /*-----------------------------------------------------------------*/
234 /* createInterruptVect - creates the interrupt vector */
235 /*-----------------------------------------------------------------*/
237 pic14createInterruptVect (struct dbuf_s * vBuf)
239 mainf = newSymbol ("main", 0);
242 /* only if the main function exists */
243 if (!(mainf = findSymWithLevel (SymbolTab, mainf)))
245 struct options *op = &options;
246 if (!(op->cc_only || noAssemble))
247 // werror (E_NO_MAIN);
248 fprintf(stderr,"WARNING: function 'main' undefined\n");
252 /* if the main is only a prototype ie. no body then do nothing */
253 if (!IFFUNC_HASBODY(mainf->type))
255 /* if ! compile only then main function should be present */
256 if (!(options.cc_only || noAssemble))
257 // werror (E_NO_MAIN);
258 fprintf(stderr,"WARNING: function 'main' undefined\n");
262 dbuf_printf (vBuf, "%s", iComments2);
263 dbuf_printf (vBuf, "; reset vector \n");
264 dbuf_printf (vBuf, "%s", iComments2);
265 dbuf_printf (vBuf, "STARTUP\t%s\n", CODE_NAME); // Lkr file should place section STARTUP at address 0x0
266 dbuf_printf (vBuf, "\tnop\n"); /* first location for used by incircuit debugger */
267 dbuf_printf (vBuf, "\tpagesel __sdcc_gsinit_startup\n");
268 dbuf_printf (vBuf, "\tgoto\t__sdcc_gsinit_startup\n");
269 popGetExternal("__sdcc_gsinit_startup", 0);
273 /*-----------------------------------------------------------------*/
274 /* initialComments - puts in some initial comments */
275 /*-----------------------------------------------------------------*/
277 pic14initialComments (FILE * afile)
279 initialComments (afile);
280 fprintf (afile, "; PIC port for the 14-bit core\n");
281 fprintf (afile, "%s", iComments2);
286 pic14_stringInSet(const char *str, set **world, int autoAdd)
293 for (s = setFirstItem(*world); s; s = setNextItem(*world))
296 if (0 == strcmp(s, str)) return 1;
300 if (autoAdd) addSet(world, Safe_strdup(str));
305 pic14printLocals (struct dbuf_s *oBuf)
307 set *allregs[6] = { dynAllocRegs/*, dynStackRegs, dynProcessorRegs*/,
308 dynDirectRegs, dynDirectBitRegs/*, dynInternalRegs */ };
311 static unsigned sectionNr = 0;
313 /* emit all registers from all possible sets */
314 for (i = 0; i < 6; i++) {
315 if (allregs[i] == NULL) continue;
317 for (reg = setFirstItem(allregs[i]); reg; reg = setNextItem(allregs[i])) {
318 if (reg->isEmitted) continue;
320 if (reg->wasUsed && !reg->isExtern) {
321 if (!pic14_stringInSet(reg->name, &emitted, 1)) {
323 // Should not happen, really...
324 assert ( !"Compiler-assigned variables should not be pinned... This is a bug." );
325 dbuf_printf(oBuf, "UDL_%s_%u\tudata\t0x%04X\n%s\tres\t%d\n",
326 moduleName, sectionNr++, reg->address, reg->name, reg->size);
328 if (getenv("SDCC_PIC14_SPLIT_LOCALS")) {
329 // assign each local register into its own section
330 dbuf_printf(oBuf, "UDL_%s_%u\tudata\n%s\tres\t%d\n",
331 moduleName, sectionNr++, reg->name, reg->size);
333 // group all local registers into a single section
334 // This should greatly improve BANKSEL generation...
336 dbuf_printf(oBuf, "UDL_%s_%u\tudata\n", moduleName, sectionNr++);
339 dbuf_printf(oBuf, "%s\tres\t%d\n", reg->name, reg->size);
349 /*-----------------------------------------------------------------*/
350 /* emitOverlay - will emit code for the overlay stuff */
351 /*-----------------------------------------------------------------*/
353 pic14emitOverlay (struct dbuf_s * aBuf)
357 /* if (!elementsInSet (ovrSetSets))*/
359 /* the hack below, fixes translates for devices which
360 * only have udata_shr memory */
361 dbuf_printf (aBuf, "%s\t%s\n",
362 (elementsInSet(ovrSetSets)?"":";"),
363 port->mem.overlay_name);
365 /* for each of the sets in the overlay segment do */
366 for (ovrset = setFirstItem (ovrSetSets); ovrset;
367 ovrset = setNextItem (ovrSetSets))
372 if (elementsInSet (ovrset))
374 /* this dummy area is used to fool the assembler
375 otherwise the assembler will append each of these
376 declarations into one chunk and will not overlay
379 /* I don't think this applies to us. We are using gpasm. CRF */
381 dbuf_printf (aBuf, ";\t.area _DUMMY\n");
382 /* output the area informtion */
383 dbuf_printf (aBuf, ";\t.area\t%s\n", port->mem.overlay_name); /* MOF */
386 for (sym = setFirstItem (ovrset); sym;
387 sym = setNextItem (ovrset))
390 /* if extern then do nothing */
391 if (IS_EXTERN (sym->etype))
394 /* if allocation required check is needed
395 then check if the symbol really requires
396 allocation only for local variables */
397 if (!IS_AGGREGATE (sym->type) &&
398 !(sym->_isparm && !IS_REGPARM (sym->etype))
399 && !sym->allocreq && sym->level)
402 /* if global variable & not static or extern
403 and addPublics allowed then add it to the public set */
404 if ((sym->_isparm && !IS_REGPARM (sym->etype))
405 && !IS_STATIC (sym->etype))
406 addSetHead (&publics, sym);
408 /* if extern then do nothing or is a function
410 if (IS_FUNC (sym->type))
413 /* print extra debug info if required */
414 if (options.debug || sym->level == 0)
418 if (IS_STATIC (sym->etype))
419 dbuf_printf (aBuf, "F%s_", moduleName); /* scope is file */
421 dbuf_printf (aBuf, "G_"); /* scope is global */
424 /* symbol is local */
425 dbuf_printf (aBuf, "L%s_",
426 (sym->localof ? sym->localof->name : "-null-"));
427 dbuf_printf (aBuf, "%s_%d_%d", sym->name, sym->level, sym->block);
430 /* if is has an absolute address then generate
431 an equate for this no need to allocate space */
432 if (SPEC_ABSA (sym->etype))
435 if (options.debug || sym->level == 0)
436 dbuf_printf (aBuf, " == 0x%04x\n", SPEC_ADDR (sym->etype));
438 dbuf_printf (aBuf, "%s\t=\t0x%04x\n",
440 SPEC_ADDR (sym->etype));
444 if (options.debug || sym->level == 0)
445 dbuf_printf (aBuf, "==.\n");
448 dbuf_printf (aBuf, "%s:\n", sym->rname);
449 dbuf_printf (aBuf, "\t.ds\t0x%04x\n", (unsigned int) getSize (sym->type) & 0xffff);
458 pic14_emitInterruptHandler (FILE * asmFile)
460 if (pic14_hasInterrupt)
463 fprintf (asmFile, "%s", iComments2);
464 fprintf (asmFile, "; interrupt and initialization code\n");
465 fprintf (asmFile, "%s", iComments2);
466 // Note - for mplink may have to enlarge section vectors in .lnk file
467 // Note: Do NOT name this code_interrupt to avoid nameclashes with
468 // source files's code segment (interrupt.c -> code_interrupt)
469 fprintf (asmFile, "c_interrupt\t%s\t0x4\n", CODE_NAME);
471 /* interrupt service routine */
472 fprintf (asmFile, "__sdcc_interrupt\n");
473 copypCode(asmFile, 'I');
477 /*-----------------------------------------------------------------*/
478 /* glue - the final glue that hold the whole thing together */
479 /*-----------------------------------------------------------------*/
484 struct dbuf_s ovrBuf;
487 dbuf_init(&ovrBuf, 4096);
488 dbuf_init(&vBuf, 4096);
490 pCodeInitRegisters();
492 /* check for main() */
493 mainf = newSymbol ("main", 0);
495 mainf = findSymWithLevel (SymbolTab, mainf);
497 if (!mainf || !IFFUNC_HASBODY(mainf->type))
499 /* main missing -- import stack from main module */
500 //fprintf (stderr, "main() missing -- assuming we are NOT the main module\n");
501 pic14_options.isLibrarySource = 1;
504 /* At this point we've got all the code in the form of pCode structures */
505 /* Now it needs to be rearranged into the order it should be placed in the */
508 movepBlock2Head('P'); // Last
509 movepBlock2Head(code->dbName);
510 movepBlock2Head('X');
511 movepBlock2Head(statsg->dbName); // First
514 /* print the global struct definitions */
518 /* do the overlay segments */
519 pic14emitOverlay(&ovrBuf);
521 /* PENDING: this isnt the best place but it will do */
522 if (port->general.glue_up_main) {
523 /* create the interrupt vector table */
524 pic14createInterruptVect (&vBuf);
529 ReuseReg(); // ReuseReg where call tree permits
535 if (options.debug) pcode_test();
538 /* now put it all together into the assembler file */
539 /* create the assembler file name */
541 if ((noAssemble || options.c1mode) && fullDstFileName)
543 sprintf (buffer, "%s", fullDstFileName);
547 sprintf (buffer, "%s", dstFileName);
548 strcat (buffer, ".asm");
551 if (!(asmFile = fopen (buffer, "w"))) {
552 werror (E_FILE_OPEN_ERR, buffer);
556 /* prepare statistics */
557 resetpCodeStatistics ();
559 /* initial comments */
560 pic14initialComments (asmFile);
562 /* print module name */
563 fprintf (asmFile, "%s\t.file\t\"%s\"\n",
564 options.debug ? "" : ";", fullSrcFileName);
566 /* Let the port generate any global directives, etc. */
567 if (port->genAssemblerPreamble)
569 port->genAssemblerPreamble(asmFile);
572 /* Put all variables into a cblock */
575 /* emit initialized data */
576 showAllMemmaps(asmFile);
578 /* print the locally defined variables in this module */
579 writeUsedRegs(asmFile);
581 /* create the overlay segments */
582 fprintf (asmFile, "%s", iComments2);
583 fprintf (asmFile, "; overlayable items in internal ram \n");
584 fprintf (asmFile, "%s", iComments2);
585 dbuf_write_and_destroy (&ovrBuf, asmFile);
587 /* copy the interrupt vector table */
588 if (mainf && IFFUNC_HASBODY(mainf->type))
589 dbuf_write_and_destroy (&vBuf, asmFile);
593 /* create interupt ventor handler */
594 pic14_emitInterruptHandler (asmFile);
597 fprintf (asmFile, "%s", iComments2);
598 fprintf (asmFile, "; code\n");
599 fprintf (asmFile, "%s", iComments2);
600 fprintf (asmFile, "code_%s\t%s\n", moduleName, port->mem.code_name);
603 copypCode(asmFile, 'X');
606 copypCode(asmFile, 'M');
608 /* other functions */
609 copypCode(asmFile, code->dbName);
612 copypCode(asmFile, 'P');
614 dumppCodeStatistics (asmFile);
616 fprintf (asmFile,"\tend\n");
619 pic14_debugLogClose();
623 * Deal with initializers.
628 #define DEBUGprintf printf
631 #define DEBUGprintf 1 ? (void)0 : (void)printf
635 parseIvalAst (ast *node, int *inCodeSpace) {
640 if (IS_AST_VALUE(node)) {
641 value *val = AST_VALUE(node);
642 symbol *sym = IS_AST_SYM_VALUE(node) ? AST_SYMBOL(node) : NULL;
643 if (inCodeSpace && val->type
644 && (IS_FUNC(val->type) || IS_CODE(getSpec(val->type))))
648 if (inCodeSpace && sym
649 && (IS_FUNC(sym->type)
650 || IS_CODE(getSpec(sym->type))))
655 DEBUGprintf ("%s: AST_VALUE\n", __FUNCTION__);
656 if (IS_AST_LIT_VALUE(node)) {
657 buffer = Safe_alloc(LEN);
658 SNPRINTF(buffer, LEN, "0x%lx", AST_ULONG_VALUE (node));
659 } else if (IS_AST_SYM_VALUE(node)) {
660 assert ( AST_SYMBOL(node) );
662 printf ("sym %s: ", AST_SYMBOL(node)->rname);
663 printTypeChain(AST_SYMBOL(node)->type, stdout);
664 printTypeChain(AST_SYMBOL(node)->etype, stdout);
665 printf ("\n---sym %s: done\n", AST_SYMBOL(node)->rname);
667 buffer = Safe_strdup(AST_SYMBOL(node)->rname);
669 assert ( !"Invalid values type for initializers in AST." );
671 } else if (IS_AST_OP(node)) {
672 DEBUGprintf ("%s: AST_OP\n", __FUNCTION__);
673 switch (node->opval.op) {
675 assert (node->right);
676 buffer = parseIvalAst(node->right, inCodeSpace);
677 DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
680 assert ( node->left && !node->right );
681 buffer = parseIvalAst(node->left, inCodeSpace);
682 DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
685 assert (node->left && node->right );
686 left = parseIvalAst(node->left, inCodeSpace);
687 right = parseIvalAst(node->right, inCodeSpace);
688 buffer = Safe_alloc(LEN);
689 SNPRINTF(buffer, LEN, "(%s + %s)", left, right);
690 DEBUGprintf ("%s: %s\n", __FUNCTION__, buffer);
695 assert ( node->left && node->right );
696 assert ( IS_AST_VALUE(node->left) && AST_VALUE(node->left)->sym );
697 right = parseIvalAst(node->right, inCodeSpace);
698 buffer = Safe_alloc(LEN);
699 SNPRINTF(buffer, LEN, "(%s + %u * %s)",
700 AST_VALUE(node->left)->sym->rname, getSize(AST_VALUE(node->left)->type), right);
702 DEBUGprintf ("%s: %s\n", __FUNCTION__, &buffer[0]);
705 assert ( !"Unhandled operation in initializer." );
709 assert ( !"Invalid construct in initializer." );
716 * Emit the section preamble, absolute location (if any) and
717 * symbol name(s) for intialized data.
720 emitIvalLabel(struct dbuf_s *oBuf, symbol *sym)
723 static int in_code = 0;
724 static int sectionNr = 0;
727 // code or data space?
728 if (IS_CODE(getSpec(sym->type))) {
735 dbuf_printf(oBuf, "\nID_%s_%d\t%s", moduleName, sectionNr++, segname);
736 if (SPEC_ABSA(getSpec(sym->type))) {
737 // specify address for absolute symbols
738 dbuf_printf(oBuf, "\t0x%04X", SPEC_ADDR(getSpec(sym->type)));
740 dbuf_printf(oBuf, "\n%s\n", sym->rname);
742 addSet(&emitted, sym->rname);
748 * Actually emit the initial values in .asm format.
751 emitIvals(struct dbuf_s *oBuf, symbol *sym, initList *list, long lit, int size)
761 assert (size <= sizeof(long));
762 assert (!list || (list->type == INIT_NODE));
763 node = list ? list->init.node : NULL;
765 in_code = emitIvalLabel(oBuf, sym);
766 if (!in_code) dbuf_printf (oBuf, "\tdb\t");
769 // initialize as zero
770 for (i=0; i < size; i++) {
772 dbuf_printf (oBuf, "\tretlw 0x00");
774 dbuf_printf (oBuf, "%s0x00", (i == 0) ? "" : ", ");
777 dbuf_printf (oBuf, "\n");
782 if (constExprTree(node) && (val = constExprValue(node, 0))) {
783 op = operandFromValue(val);
784 DEBUGprintf ("%s: constExpr ", __FUNCTION__);
785 } else if (IS_AST_VALUE(node)) {
786 op = operandFromAst(node, 0);
787 } else if (IS_AST_OP(node)) {
788 str = parseIvalAst(node, &inCodeSpace);
789 DEBUGprintf("%s: AST_OP: %s\n", __FUNCTION__, str);
792 assert ( !"Unhandled construct in intializer." );
798 //printOperand(op, of);
801 for (i=0; i < size; i++) {
805 * FIXME: This is hacky and needs some more thought.
807 if (op && IS_SYMOP(op) && IS_FUNC(OP_SYM_TYPE(op))) {
808 /* This branch is introduced to fix #1427663. */
809 PCOI(AOP(op)->aopu.pcop)->offset+=i;
810 text = get_op(AOP(op)->aopu.pcop, NULL, 0);
811 PCOI(AOP(op)->aopu.pcop)->offset-=i;
813 text = op ? aopGet(AOP(op), i, 0, 0)
814 : get_op(newpCodeOpImmd(str, i, 0, inCodeSpace, 0), NULL, 0);
817 dbuf_printf (oBuf, "\tretlw %s\n", text);
819 dbuf_printf (oBuf, "%s%s", (i == 0) ? "" : ", ", text);
822 dbuf_printf (oBuf, "\n");
826 * For UNIONs, we first have to find the correct alternative to map the
827 * initializer to. This function maps the structure of the initializer to
828 * the UNION members recursively.
829 * Returns the type of the first `fitting' member.
832 matchIvalToUnion (initList *list, sym_link *type, int size)
838 if (IS_PTR(type) || IS_CHAR(type) || IS_INT(type) || IS_LONG(type)
841 if (!list || (list->type == INIT_NODE)) {
842 DEBUGprintf ("OK, simple type\n");
845 DEBUGprintf ("ERROR, simple type\n");
848 } else if (IS_BITFIELD(type)) {
849 if (!list || (list->type == INIT_NODE)) {
850 DEBUGprintf ("OK, bitfield\n");
853 DEBUGprintf ("ERROR, bitfield\n");
856 } else if (IS_STRUCT(type) && SPEC_STRUCT(getSpec(type))->type == STRUCT) {
857 if (!list || (list->type == INIT_DEEP)) {
858 if (list) list = list->init.deep;
859 sym = SPEC_STRUCT(type)->fields;
861 DEBUGprintf ("Checking STRUCT member %s\n", sym->name);
862 if (!matchIvalToUnion(list, sym->type, 0)) {
863 DEBUGprintf ("ERROR, STRUCT member %s\n", sym->name);
866 if (list) list = list->next;
870 // excess initializers?
872 DEBUGprintf ("ERROR, excess initializers\n");
876 DEBUGprintf ("OK, struct\n");
880 } else if (IS_STRUCT(type) && SPEC_STRUCT(getSpec(type))->type == UNION) {
881 if (!list || (list->type == INIT_DEEP)) {
882 if (list) list = list->init.deep;
883 sym = SPEC_STRUCT(type)->fields;
885 DEBUGprintf ("Checking UNION member %s.\n", sym->name);
886 if (((IS_STRUCT(sym->type) || getSize(sym->type) == size))
887 && matchIvalToUnion(list, sym->type, size))
889 DEBUGprintf ("Matched UNION member %s.\n", sym->name);
896 DEBUGprintf ("ERROR, no match found.\n");
899 assert ( !"Unhandled type in UNION." );
902 assert ( !"No match found in UNION for the given initializer structure." );
907 * Parse the type and its initializer and emit it (recursively).
910 emitInitVal(struct dbuf_s *oBuf, symbol *topsym, sym_link *my_type, initList *list)
917 size = getSize(my_type);
919 if (IS_PTR(my_type)) {
920 DEBUGprintf ("(pointer, %d byte) %p\n", size, list ? (void *)(long)list2int(list) : NULL);
921 emitIvals(oBuf, topsym, list, 0, size);
925 if (IS_ARRAY(my_type) && topsym && topsym->isstrlit) {
926 str = (unsigned char *)SPEC_CVAL(topsym->etype).v_char;
927 emitIvalLabel(oBuf, topsym);
929 dbuf_printf (oBuf, "\tretlw 0x%02x ; '%c'\n", str[0], (str[0] >= 0x20 && str[0] < 128) ? str[0] : '.');
934 if (IS_ARRAY(my_type) && list && list->type == INIT_NODE) {
935 fprintf (stderr, "Unhandled initialized symbol: %s\n", topsym->name);
936 assert ( !"Initialized char-arrays are not yet supported, assign at runtime instead." );
940 if (IS_ARRAY(my_type)) {
941 DEBUGprintf ("(array, %d items, %d byte) below\n", DCL_ELEM(my_type), size);
942 assert (!list || list->type == INIT_DEEP);
943 if (list) list = list->init.deep;
944 for (i = 0; i < DCL_ELEM(my_type); i++) {
945 emitInitVal(oBuf, topsym, my_type->next, list);
947 if (list) list = list->next;
952 if (IS_FLOAT(my_type)) {
954 DEBUGprintf ("(float, %d byte) %lf\n", size, list ? list2int(list) : 0.0);
955 emitIvals(oBuf, topsym, list, 0, size);
959 if (IS_CHAR(my_type) || IS_INT(my_type) || IS_LONG(my_type)) {
960 // integral type, 8, 16, or 32 bit
961 DEBUGprintf ("(integral, %d byte) 0x%lx/%ld\n", size, list ? (long)list2int(list) : 0, list ? (long)list2int(list) : 0);
962 emitIvals(oBuf, topsym, list, 0, size);
965 } else if (IS_STRUCT(my_type) && SPEC_STRUCT(my_type)->type == STRUCT) {
967 DEBUGprintf ("(struct, %d byte) handled below\n", size);
968 assert (!list || (list->type == INIT_DEEP));
970 // iterate over struct members and initList
971 if (list) list = list->init.deep;
972 sym = SPEC_STRUCT(my_type)->fields;
976 if (IS_BITFIELD(sym->type)) {
977 while (sym && IS_BITFIELD(sym->type)) {
978 assert (!list || ((list->type == INIT_NODE)
979 && IS_AST_LIT_VALUE(list->init.node)));
980 lit = (long) (list ? list2int(list) : 0);
981 DEBUGprintf ( "(bitfield member) %02lx (%d bit, starting at %d, bitfield %02lx)\n",
982 lit, SPEC_BLEN(getSpec(sym->type)),
983 SPEC_BSTR(getSpec(sym->type)), bitfield);
984 bitfield |= (lit & ((1ul << SPEC_BLEN(getSpec(sym->type))) - 1)) << SPEC_BSTR(getSpec(sym->type));
985 len += SPEC_BLEN(getSpec(sym->type));
988 if (list) list = list->next;
990 assert (len < sizeof (long) * 8); // did we overflow our initializer?!?
991 len = (len + 7) & ~0x07; // round up to full bytes
992 emitIvals(oBuf, topsym, NULL, bitfield, len / 8);
997 emitInitVal(oBuf, topsym, sym->type, list);
1000 if (list) list = list->next;
1004 assert ( !"Excess initializers." );
1008 } else if (IS_STRUCT(my_type) && SPEC_STRUCT(my_type)->type == UNION) {
1010 DEBUGprintf ("(union, %d byte) handled below\n", size);
1011 assert (list && list->type == INIT_DEEP);
1013 // iterate over union members and initList, try to map number and type of fields and initializers
1014 my_type = matchIvalToUnion(list, my_type, size);
1016 emitInitVal(oBuf, topsym, my_type, list->init.deep);
1018 size -= getSize(my_type);
1020 // pad with (leading) zeros
1021 emitIvals(oBuf, NULL, NULL, 0, size);
1026 assert ( !"No UNION member matches the initializer structure.");
1027 } else if (IS_BITFIELD(my_type)) {
1028 assert ( !"bitfields should only occur in structs..." );
1031 printf ("SPEC_NOUN: %d\n", SPEC_NOUN(my_type));
1032 assert( !"Unhandled initialized type.");
1037 * Emit a set of symbols.
1038 * type - 0: have symbol tell whether it is local, extern or global
1039 * 1: assume all symbols in set to be global
1040 * 2: assume all symbols in set to be extern
1043 emitSymbolSet(set *s, int type)
1047 unsigned sectionNr = 0;
1049 for (sym = setFirstItem(s); sym; sym = setNextItem(s)) {
1051 fprintf (stdout, "; name %s, rname %s, level %d, block %d, key %d, local %d, ival %p, static %d, cdef %d, used %d\n",
1052 sym->name, sym->rname, sym->level, sym->block, sym->key, sym->islocal, sym->ival, IS_STATIC(sym->etype), sym->cdef, sym->used);
1055 if (sym->etype && SPEC_ABSA(sym->etype)
1056 && IS_CONFIG_ADDRESS(SPEC_ADDR(sym->etype))
1059 // handle config words
1060 pic14_assignConfigWordValue(SPEC_ADDR(sym->etype),
1061 (int)list2int(sym->ival));
1062 pic14_stringInSet(sym->rname, &emitted, 1);
1066 if (sym->isstrlit) {
1067 // special case: string literals
1068 emitInitVal(ivalBuf, sym, sym->type, NULL);
1072 if (type != 0 || sym->cdef
1073 || (!IS_STATIC(sym->etype)
1076 // bail out for ___fsadd and friends
1077 if (sym->cdef && !sym->used) continue;
1079 /* export or import non-static globals */
1080 if (!pic14_stringInSet(sym->rname, &emitted, 0)) {
1082 if (type == 2 || IS_EXTERN(sym->etype) || sym->cdef)
1084 /* do not add to emitted set, it might occur again! */
1085 //if (!sym->used) continue;
1087 emitIfNew (extBuf, &emitted, "\textern\t%s\n", sym->rname);
1090 emitIfNew (gloBuf, &emitted, "\tglobal\t%s\n", sym->rname);
1091 if (!sym->ival && !IS_FUNC(sym->type)) {
1092 // also define symbol
1093 if (IS_ABSOLUTE(sym->etype)) {
1094 // absolute location?
1095 //dbuf_printf (gloDefBuf, "UD_%s_%u\tudata\t0x%04X\n", moduleName, sectionNr++, SPEC_ADDR(sym->etype));
1096 // deferred to pic14_constructAbsMap
1098 dbuf_printf (gloDefBuf, "UD_%s_%u\tudata\n", moduleName, sectionNr++);
1099 dbuf_printf (gloDefBuf, "%s\tres\t%d\n\n", sym->rname, getSize(sym->type));
1103 pic14_stringInSet(sym->rname, &emitted, 1);
1107 //if (list) showInitList(list, 0);
1109 resolveIvalSym( list, sym->type );
1110 emitInitVal(ivalBuf, sym, sym->type, sym->ival);
1111 dbuf_printf (ivalBuf, "\n");
1117 * Iterate over all memmaps and emit their contents (attributes, symbols).
1120 showAllMemmaps(FILE *of)
1122 struct dbuf_s locBuf;
1124 xstack, istack, code, data, pdata, xdata, xidata, xinit,
1125 idata, bit, statsg, c_abs, x_abs, i_abs, d_abs,
1126 sfr, sfrbit, reg, generic, overlay, eeprom, home };
1130 DEBUGprintf ("---begin memmaps---\n");
1131 if (!extBuf) extBuf = dbuf_new(1024);
1132 if (!gloBuf) gloBuf = dbuf_new(1024);
1133 if (!gloDefBuf) gloDefBuf = dbuf_new(1024);
1134 if (!ivalBuf) ivalBuf = dbuf_new(1024);
1135 dbuf_init(&locBuf, 1024);
1137 dbuf_printf (extBuf, "%s; external declarations\n%s", iComments2, iComments2);
1138 dbuf_printf (gloBuf, "%s; global declarations\n%s", iComments2, iComments2);
1139 dbuf_printf (gloDefBuf, "%s; global definitions\n%s", iComments2, iComments2);
1140 dbuf_printf (ivalBuf, "%s; initialized data\n%s", iComments2, iComments2);
1141 dbuf_printf (&locBuf, "%s; compiler-defined variables\n%s", iComments2, iComments2);
1143 for (i = 0; i < sizeof(maps) / sizeof (memmap *); i++) {
1145 //DEBUGprintf ("memmap %i: %p\n", i, map);
1148 fprintf (stdout, "; pageno %c, sname %s, dbName %c, ptrType %d, slbl %d, sloc %u, fmap %u, paged %u, direct %u, bitsp %u, codesp %u, regsp %u, syms %p\n",
1149 map->pageno, map->sname, map->dbName, map->ptrType, map->slbl,
1150 map->sloc, map->fmap, map->paged, map->direct, map->bitsp,
1151 map->codesp, map->regsp, map->syms);
1153 emitSymbolSet(map->syms, 0);
1156 DEBUGprintf ("---end of memmaps---\n");
1158 emitSymbolSet(publics, 1);
1159 emitSymbolSet(externs, 2);
1161 emitPseudoStack(gloBuf, extBuf);
1162 pic14_constructAbsMap(gloDefBuf, gloBuf);
1163 pic14printLocals (&locBuf);
1164 pic14_emitConfigWord(of); // must be done after all the rest
1166 dbuf_write_and_destroy(extBuf, of);
1167 dbuf_write_and_destroy(gloBuf, of);
1168 dbuf_write_and_destroy(gloDefBuf, of);
1169 dbuf_write_and_destroy(&locBuf, of);
1170 dbuf_write_and_destroy(ivalBuf, of);
1172 extBuf = gloBuf = gloDefBuf = ivalBuf = NULL;