1 /*-----------------------------------------------------------------*/
2 /* SDCCmem.c - 8051 memory management routines */
3 /*-----------------------------------------------------------------*/
8 memmap *xstack= NULL ; /* xternal stack data */
9 memmap *istack= NULL; /* internal stack */
10 memmap *code = NULL; /* code segment */
11 memmap *data = NULL; /* internal data upto 128 */
12 memmap *xdata = NULL; /* external data */
13 memmap *idata = NULL; /* internal data upto 256 */
14 memmap *bit = NULL; /* bit addressable space */
15 memmap *statsg= NULL; /* the constant data segment */
16 memmap *sfr = NULL; /* register space */
17 memmap *reg = NULL; /* register space */
18 memmap *sfrbit= NULL; /* sfr bit space */
19 memmap *generic=NULL; /* is a generic pointer */
20 memmap *overlay=NULL; /* overlay segment */
21 memmap *eeprom =NULL; /* eeprom location */
23 /* this is a set of sets each set containing
24 symbols in a single overlay */
25 set *ovrSetSets = NULL;
27 extern set *operKeyReset ;
28 extern set *tmpfileSet ;
29 extern symbol *interrupts[];
31 int fatalError = 0 ;/* fatal error flag */
33 /*-----------------------------------------------------------------*/
34 /* allocMap - allocates a memory map */
35 /*-----------------------------------------------------------------*/
36 memmap *allocMap (char rspace, /* sfr space */
37 char farmap, /* far or near segment */
38 char paged , /* can this segment be paged */
39 char direct, /* directly addressable */
40 char bitaddr, /* bit addressable space*/
41 char codemap, /* this is code space */
42 unsigned sloc, /* starting location */
43 const char *name, /* 2 character name */
44 char dbName , /* debug name */
45 int ptrType /* pointer type for this space */
50 if (!(map = GC_malloc(sizeof(memmap)))) {
51 werror(E_OUT_OF_MEM,__FILE__,sizeof(memmap));
55 memset(map, ZERO, sizeof(memmap));
59 map->direct = direct ;
60 map->bitsp = bitaddr ;
61 map->codesp = codemap ;
64 map->dbName = dbName ;
65 map->ptrType= ptrType;
66 if (!(map->oFile = tempfile())) {
67 werror(E_TMPFILE_FAILED);
70 addSetHead (&tmpfileSet,map->oFile);
75 /*-----------------------------------------------------------------*/
76 /* initMem - allocates and initializes all the segments */
77 /*-----------------------------------------------------------------*/
80 /* allocate all the segments */
81 /* xternal stack segment ;
89 POINTER-TYPE - FPOINTER
91 xstack = allocMap (0, 1, 1, 0, 0, 0, options.xstack_loc, XSTACK_NAME,'A',PPOINTER);
93 /* internal stack segment ;
101 POINTER-TYPE - POINTER
103 istack = allocMap (0, 0, 0, 0, 0, 0,options.stack_loc, ISTACK_NAME,'B',POINTER);
113 POINTER-TYPE - CPOINTER
115 code = allocMap (0, 1, 0, 0, 0, 1, options.code_loc, CODE_NAME,'C',CPOINTER);
117 /* Static segment (code for variables );
125 POINTER-TYPE - CPOINTER
127 statsg = allocMap (0, 1, 0, 0, 0, 1,0, STATIC_NAME,'D',CPOINTER);
129 /* Data segment - internal storage segment ;
137 POINTER-TYPE - POINTER
139 data = allocMap (0, 0, 0, 1, 0, 0, options.data_loc, DATA_NAME,'E',POINTER);
141 /* overlay segment - same as internal storage segment ;
149 POINTER-TYPE - POINTER
151 overlay = allocMap (0, 0, 0, 1, 0, 0, options.data_loc, DATA_NAME,'E',POINTER);
153 /* Xternal Data segment -
161 POINTER-TYPE - FPOINTER
163 xdata = allocMap (0, 1, 0, 0, 0, 0, options.xdata_loc, XDATA_NAME,'F',FPOINTER);
165 /* Inderectly addressed internal data segment
173 POINTER-TYPE - IPOINTER
175 idata = allocMap (0, 0, 0, 0, 0, 0, options.idata_loc,IDATA_NAME,'G',IPOINTER);
177 /* Static segment (code for variables );
185 POINTER-TYPE - _NONE_
187 bit = allocMap (0, 0, 0, 1, 1, 0,0, BIT_NAME,'H',0);
189 /* Special function register space :-
197 POINTER-TYPE - _NONE_
199 sfr = allocMap (1,0, 0, 1, 0, 0,0, REG_NAME,'I',0);
209 POINTER-TYPE - _NONE_
211 reg = allocMap (1,0, 0, 0, 0, 0, 0,REG_NAME,' ',0);
221 POINTER-TYPE - _NONE_
223 sfrbit = allocMap (1,0, 0, 1, 1, 0,0, REG_NAME,'J',0);
233 POINTER-TYPE - EEPPOINTER
235 eeprom = allocMap (0,1, 0, 0, 0, 0,0, REG_NAME,'K',EEPPOINTER);
237 /* the unknown map */
238 generic = allocMap (1,0, 0, 1, 1, 0,0, REG_NAME,' ',GPOINTER);
242 /*-----------------------------------------------------------------*/
243 /* allocIntoSeg - puts a symbol into a memory segment */
244 /*-----------------------------------------------------------------*/
245 void allocIntoSeg (symbol *sym)
247 memmap *segment = SPEC_OCLS(sym->etype);
248 addSet (&segment->syms,sym);
251 /*-----------------------------------------------------------------*/
252 /* allocGlobal - aassigns the output segment to a global var */
253 /*-----------------------------------------------------------------*/
254 void allocGlobal ( symbol *sym )
256 /* symbol name is internal name */
257 sprintf (sym->rname,"%s%s", port->fun_prefix, sym->name);
259 /* add it to the operandKey reset */
260 addSet(&operKeyReset,sym);
262 /* if this is a literal e.g. enumerated type */
263 /* put it in the data segment & do nothing */
264 if (IS_LITERAL(sym->etype)) {
265 SPEC_OCLS(sym->etype) = data ;
269 /* if this is a function then assign code space */
270 if (IS_FUNC(sym->type)) {
271 SPEC_OCLS(sym->etype) = code ;
272 /* if this is an interrupt service routine
273 then put it in the interrupt service array */
274 if (IS_ISR(sym->etype)) {
276 if (interrupts[SPEC_INTN(sym->etype)])
277 werror(E_INT_DEFINED,
278 SPEC_INTN(sym->etype),
279 interrupts[SPEC_INTN(sym->etype)]->name);
281 interrupts[SPEC_INTN(sym->etype)] = sym;
283 /* automagically extend the maximum interrupts */
284 if (SPEC_INTN(sym->etype) >= maxInterrupts )
285 maxInterrupts = SPEC_INTN(sym->etype) + 1;
287 /* if it is not compiler defined */
294 /* if this is a SFR or SBIT */
295 if ( SPEC_SCLS(sym->etype) == S_SFR ||
296 SPEC_SCLS(sym->etype) == S_SBIT ) {
298 /* if both absolute address & initial */
299 /* value specified then error */
300 if ( IS_ABSOLUTE (sym->etype) && sym->ival ) {
301 werror(E_SFR_INIT,sym->name);
305 SPEC_OCLS(sym->etype) =
306 (SPEC_SCLS(sym->etype) == S_SFR ? sfr : sfrbit);
312 /* if this is a bit variable and no storage class */
313 if ( SPEC_NOUN(sym->etype) == V_BIT
314 && SPEC_SCLS(sym->etype) == S_BIT ) {
315 SPEC_OCLS(sym->etype) = bit ;
320 /* if bit storage class */
321 if ( SPEC_SCLS(sym->etype) == S_SBIT ) {
322 SPEC_OCLS(sym->etype) = bit;
327 /* register storage class ignored changed to FIXED */
328 if ( SPEC_SCLS(sym->etype) == S_REGISTER )
329 SPEC_SCLS(sym->etype) = S_FIXED ;
331 /* if data specified then */
332 if (SPEC_SCLS(sym->etype) == S_DATA) {
333 /* set the output class */
334 SPEC_OCLS(sym->etype) = data ;
335 /* generate the symbol */
340 /* if it is fixed, then allocate depending on the */
341 /* current memory model,same for automatics */
342 if ( SPEC_SCLS(sym->etype) == S_FIXED ||
343 SPEC_SCLS(sym->etype) == S_AUTO ) {
344 /* set the output class */
345 SPEC_OCLS(sym->etype) = port->mem.default_globl_map ;
346 /* generate the symbol */
351 /* if code change to constant */
352 if ( SPEC_SCLS(sym->etype) == S_CODE ||
353 SPEC_SCLS(sym->etype) == S_CONSTANT ) {
354 SPEC_OCLS(sym->etype) = statsg ;
359 if ( SPEC_SCLS(sym->etype) == S_XDATA ) {
360 SPEC_OCLS(sym->etype) = xdata ;
365 if ( SPEC_SCLS(sym->etype) == S_IDATA ) {
366 SPEC_OCLS(sym->etype) = idata ;
372 if ( SPEC_SCLS(sym->etype) == S_EEPROM ) {
373 SPEC_OCLS(sym->etype) = eeprom ;
381 /*-----------------------------------------------------------------*/
382 /* allocParms - parameters are always passed on stack */
383 /*-----------------------------------------------------------------*/
384 void allocParms ( value *val )
389 for ( lval = val ; lval ; lval = lval->next, pNum++ ) {
391 /* check the declaration */
392 checkDecl (lval->sym);
394 /* if this a register parm then allocate
395 it as a local variable by adding it
396 to the first block we see in the body */
397 if (IS_REGPARM(lval->etype))
400 /* mark it as my parameter */
401 lval->sym->ismyparm = 1;
402 lval->sym->localof = currFunc;
405 /* if automatic variables r 2b stacked */
406 if ( options.stackAuto || IS_RENT(currFunc->etype)) {
409 lval->sym->onStack = 1;
411 /* choose which stack 2 use */
412 /* use xternal stack */
413 if ( options.useXstack ) {
414 /* PENDING: stack direction support */
415 SPEC_OCLS(lval->etype) = SPEC_OCLS(lval->sym->etype) = xstack ;
416 SPEC_STAK(lval->etype) = SPEC_STAK(lval->sym->etype) = lval->sym->stack =
417 xstackPtr - getSize(lval->type);
418 xstackPtr -= getSize (lval->type);
420 else { /* use internal stack */
421 SPEC_OCLS(lval->etype) = SPEC_OCLS(lval->sym->etype) = istack ;
422 if (port->stack.direction > 0) {
423 SPEC_STAK(lval->etype) = SPEC_STAK(lval->sym->etype) = lval->sym->stack =
424 stackPtr - ( SPEC_BANK(currFunc->etype) ? port->stack.bank_overhead : 0) -
425 getSize(lval->type) -
426 (IS_ISR(currFunc->etype) ? port->stack.isr_overhead : 0);
427 stackPtr -= getSize (lval->type);
430 /* This looks like the wrong order but it turns out OK... */
431 /* PENDING: isr, bank overhead, ... */
432 SPEC_STAK(lval->etype) = SPEC_STAK(lval->sym->etype) = lval->sym->stack =
434 (IS_BANKED(currFunc->etype) ? port->stack.banked_overhead : 0) +
435 (IS_ISR(currFunc->etype) ? port->stack.isr_overhead : 0) +
437 stackPtr += getSize (lval->type);
440 allocIntoSeg(lval->sym);
442 else { /* allocate them in the automatic space */
443 /* generate a unique name */
444 sprintf (lval->sym->rname,"%s%s_PARM_%d", port->fun_prefix, currFunc->name,pNum);
445 strcpy (lval->name,lval->sym->rname);
447 /* if declared in external storage */
448 if (SPEC_SCLS(lval->etype) == S_XDATA)
449 SPEC_OCLS(lval->etype) = SPEC_OCLS(lval->sym->etype) = xdata;
451 /* other wise depending on the memory model
452 note here that we put it into the overlay segment
453 first, we will remove it from the overlay segment
454 after the overlay determination has been done */
455 SPEC_OCLS(lval->etype) = SPEC_OCLS(lval->sym->etype) =
456 ( options.model ? port->mem.default_local_map :
457 (options.noOverlay ? port->mem.default_local_map
460 allocIntoSeg(lval->sym);
467 /*-----------------------------------------------------------------*/
468 /* deallocParms - parameters are always passed on stack */
469 /*-----------------------------------------------------------------*/
470 void deallocParms ( value *val )
474 for ( lval = val ; lval ; lval = lval->next ) {
476 /* unmark is myparm */
477 lval->sym->ismyparm = 0;
478 /* if on stack then depending on which stack */
480 /* delete it from the symbol table */
481 deleteSym (SymbolTab,lval->sym,lval->sym->name);
483 if (!lval->sym->isref) {
484 lval->sym->allocreq = 1;
485 werror(W_NO_REFERENCE,currFunc->name,
486 "function argument",lval->sym->name);
489 /* move the rname if any to the name for both val & sym */
490 /* and leave a copy of it in the symbol table */
491 if (lval->sym->rname[0]) {
492 char buffer[SDCC_NAME_MAX];
493 strcpy(buffer,lval->sym->rname);
494 lval->sym = copySymbol(lval->sym);
495 strcpy(lval->sym->rname,buffer);
496 strcpy(lval->name,strcpy(lval->sym->name,lval->sym->rname));
497 addSym (SymbolTab, lval->sym, lval->sym->name,
498 lval->sym->level,lval->sym->block);
499 lval->sym->_isparm = 1;
500 addSet(&operKeyReset,lval->sym);
508 /*-----------------------------------------------------------------*/
509 /* allocLocal - allocate local variables */
510 /*-----------------------------------------------------------------*/
511 void allocLocal ( symbol *sym )
514 /* generate an unique name */
515 sprintf(sym->rname,"%s%s_%s_%d_%d",
517 currFunc->name,sym->name,sym->level,sym->block);
520 sym->localof = currFunc;
522 /* if this is a static variable */
523 if ( IS_STATIC (sym->etype)) {
524 /* SPEC_OCLS(sym->etype) = (options.model ? xdata : data ); */
525 SPEC_OCLS(sym->etype) = port->mem.default_local_map;
531 /* if volatile then */
532 if (IS_VOLATILE(sym->etype))
535 /* this is automatic */
537 /* if it to be placed on the stack */
538 if ( options.stackAuto || reentrant) {
541 if ( options.useXstack ) {
542 /* PENDING: stack direction for xstack */
543 SPEC_OCLS(sym->etype) = xstack ;
544 SPEC_STAK(sym->etype) = sym->stack = (xstackPtr + 1);
545 xstackPtr += getSize (sym->type) ;
548 SPEC_OCLS(sym->etype) = istack ;
549 if (port->stack.direction > 0) {
550 SPEC_STAK(sym->etype) = sym->stack = ( stackPtr + 1);
551 stackPtr += getSize (sym->type) ;
554 stackPtr -= getSize (sym->type);
555 SPEC_STAK(sym->etype) = sym->stack = stackPtr;
562 /* else depending on the storage class specified */
563 if ( SPEC_SCLS(sym->etype) == S_XDATA ) {
564 SPEC_OCLS(sym->etype) = xdata ;
569 if ( (SPEC_SCLS(sym->etype) == S_CODE ||
570 SPEC_SCLS(sym->etype) == S_CONSTANT) &&
572 SPEC_OCLS(sym->etype) = statsg ;
577 if ( SPEC_SCLS(sym->etype) == S_IDATA ) {
578 SPEC_OCLS(sym->etype) = idata ;
584 /* if this is a function then assign code space */
585 if (IS_FUNC(sym->type)) {
586 SPEC_OCLS(sym->etype) = code ;
590 /* if this is a SFR or SBIT */
591 if ( SPEC_SCLS(sym->etype) == S_SFR ||
592 SPEC_SCLS(sym->etype) == S_SBIT ) {
594 /* if both absolute address & initial */
595 /* value specified then error */
596 if ( IS_ABSOLUTE (sym->etype) && sym->ival ) {
597 werror(E_SFR_INIT,sym->name);
601 SPEC_OCLS(sym->etype) =
602 (SPEC_SCLS(sym->etype) == S_SFR ? sfr : sfrbit);
608 /* if this is a bit variable and no storage class */
609 if ( SPEC_NOUN(sym->etype) == V_BIT
610 && (SPEC_SCLS(sym->etype) == S_BIT)) {
611 SPEC_OCLS(sym->etype) = bit ;
616 if ( SPEC_SCLS(sym->etype) == S_DATA ) {
617 SPEC_OCLS(sym->etype) = (options.noOverlay ? data : overlay );
622 if ( SPEC_SCLS(sym->etype) == S_EEPROM ) {
623 SPEC_OCLS(sym->etype) = eeprom;
628 /* again note that we have put it into the overlay segment
629 will remove and put into the 'data' segment if required after
630 overlay analysis has been done */
631 SPEC_OCLS(sym->etype) = ( options.model ? port->mem.default_local_map :
632 (options.noOverlay ? port->mem.default_local_map
637 /*-----------------------------------------------------------------*/
638 /* deallocLocal - deallocates the local variables */
639 /*-----------------------------------------------------------------*/
640 void deallocLocal ( symbol *csym )
644 for ( sym = csym ; sym ; sym = sym->next) {
648 /* if it is on the stack */
650 if (options.useXstack)
651 xstackPtr -= getSize(sym->type);
653 stackPtr -= getSize(sym->type);
655 /* if not used give a warning */
656 if (!sym->isref && !IS_STATIC(sym->etype))
657 werror(W_NO_REFERENCE,currFunc->name,
658 "local variable",sym->name);
659 /* now delete it from the symbol table */
660 deleteSym (SymbolTab,sym,sym->name);
664 /*-----------------------------------------------------------------*/
665 /* overlay2data - moves declarations from the overlay seg to data */
666 /*-----------------------------------------------------------------*/
671 for (sym = setFirstItem(overlay->syms); sym;
672 sym = setNextItem(overlay->syms)) {
674 SPEC_OCLS(sym->etype) = data;
678 setToNull((void **) &overlay->syms);
682 /*-----------------------------------------------------------------*/
683 /* overlay2Set - will add all symbols from the overlay segment to */
684 /* the set of sets containing the overlable symbols */
685 /*-----------------------------------------------------------------*/
691 for (sym = setFirstItem(overlay->syms); sym;
692 sym = setNextItem(overlay->syms)) {
697 setToNull((void **) &overlay->syms);
698 addSet (&ovrSetSets,oset);
702 /*-----------------------------------------------------------------*/
703 /* allocVariables - creates decl & assign storage class for a v */
704 /*-----------------------------------------------------------------*/
705 int allocVariables ( symbol *symChain )
712 /* go thru the symbol chain */
713 for ( sym = symChain ; sym ; sym = sym->next ) {
715 /* if this is a typedef then add it */
716 /* to the typedef table */
717 if (IS_TYPEDEF(sym->etype)) {
718 /* check if the typedef already exists */
719 csym = findSym (TypedefTab, NULL, sym->name );
720 if ( csym && csym->level == sym->level )
721 werror(E_DUPLICATE_TYPEDEF,sym->name);
723 addSym (TypedefTab, sym , sym->name,sym->level,sym->block);
724 continue ; /* go to the next one */
726 /* make sure it already exist */
727 csym = findSymWithLevel (SymbolTab, sym);
728 if (! csym || (csym && csym->level != sym->level) )
731 /* check the declaration */
734 /* if this is a function or a pointer to function */
735 /* then args processing */
736 if (funcInChain(csym->type)) {
738 processFuncArgs (csym, 1);
739 /* if register bank specified then update maxRegBank */
740 if (maxRegBank < SPEC_BANK(csym->etype))
741 maxRegBank = SPEC_BANK(csym->etype);
744 /* if this is a extern variable then change the */
745 /* level to zero temporarily */
746 if (IS_EXTERN(csym->etype) || IS_FUNC(csym->type) ) {
747 saveLevel = csym->level ;
751 /* if this is a literal then it is an enumerated */
752 /* type so need not allocate it space for it */
753 if (IS_LITERAL(sym->etype))
756 /* generate the actual declaration */
760 stack += getSize(csym->type) ;
765 /* restore the level */
766 if (IS_EXTERN(csym->etype) || IS_FUNC(csym->type))
767 csym->level = saveLevel;
773 /*-----------------------------------------------------------------*/
774 /* redoStackOffsets :- will reassign the values for stack offsets */
775 /*-----------------------------------------------------------------*/
776 void redoStackOffsets ()
782 /* after register allocation is complete we know
783 which variables will need to be assigned space
784 on the stack. We will eliminate those variables
785 which do not have the allocReq flag thus reducing
787 for ( sym = setFirstItem(istack->syms); sym;
788 sym = setNextItem(istack->syms)) {
790 int size = getSize(sym->type);
791 /* nothing to do with parameters so continue */
792 if ((sym->_isparm && !IS_REGPARM(sym->etype)))
795 if ( IS_AGGREGATE(sym->type)) {
796 if (port->stack.direction > 0) {
797 SPEC_STAK(sym->etype) = sym->stack = ( sPtr + 1);
802 SPEC_STAK(sym->etype) = sym->stack = sPtr;
807 /* if allocation not required then subtract
808 size from overall stack size & continue */
809 if (!sym->allocreq) {
810 currFunc->stack -= size;
811 SPEC_STAK(currFunc->etype) -= size;
815 if (port->stack.direction > 0) {
816 SPEC_STAK(sym->etype) = sym->stack = ( sPtr + 1);
821 SPEC_STAK(sym->etype) = sym->stack = sPtr;
825 /* do the same for the external stack */
827 for ( sym = setFirstItem(xstack->syms); sym;
828 sym = setNextItem(xstack->syms)) {
830 int size = getSize(sym->type);
831 /* nothing to do with parameters so continue */
832 if ((sym->_isparm && !IS_REGPARM(sym->etype)))
835 if (IS_AGGREGATE(sym->type)) {
836 SPEC_STAK(sym->etype) = sym->stack = ( xsPtr + 1);
841 /* if allocation not required then subtract
842 size from overall stack size & continue */
843 if (!sym->allocreq) {
844 currFunc->xstack -= size;
845 SPEC_STAK(currFunc->etype) -= size;
849 SPEC_STAK(sym->etype) = sym->stack = ( xsPtr + 1);
853 /* if the debug option is set then output the
854 symbols to the map file */
856 for (sym = setFirstItem(istack->syms); sym;
857 sym = setNextItem(istack->syms))
858 cdbSymbol(sym,cdbFile,FALSE,FALSE);
860 for (sym = setFirstItem(xstack->syms); sym;
861 sym = setNextItem(xstack->syms))
862 cdbSymbol(sym,cdbFile,FALSE,FALSE);
866 /*-----------------------------------------------------------------*/
867 /* printAllocInfoSeg- print the allocation for a given section */
868 /*-----------------------------------------------------------------*/
869 static void printAllocInfoSeg ( memmap *map, symbol *func, FILE *of)
874 if (!map->syms) return;
876 for (sym = setFirstItem(map->syms); sym;
877 sym = setNextItem(map->syms)) {
879 if (sym->level == 0) continue;
880 if (sym->localof != func) continue ;
881 fprintf(of,";%-25s Allocated to ",sym->name);
883 /* if assigned to registers */
884 if (!sym->allocreq && sym->reqv) {
886 sym = OP_SYMBOL(sym->reqv);
887 fprintf(of,"registers ");
888 for (i = 0 ; i < 4 && sym->regs[i] ; i++)
889 fprintf(of,"%s ",port->getRegName(sym->regs[i]));
896 fprintf(of,"stack - offset %d\n",sym->stack);
900 /* otherwise give rname */
901 fprintf(of,"in memory with name '%s'\n",sym->rname);
905 /*-----------------------------------------------------------------*/
906 /* printAllocInfo - prints allocation information for a function */
907 /*-----------------------------------------------------------------*/
908 void printAllocInfo( symbol * func, FILE *of)
910 if (!of) of = stdout;
912 /* must be called after register allocation is complete */
913 fprintf(of,";------------------------------------------------------------\n");
914 fprintf(of,";Allocation info for local variables in function '%s'\n",func->name);
915 fprintf(of,";------------------------------------------------------------\n");
917 printAllocInfoSeg(xstack,func,of);
918 printAllocInfoSeg(istack,func,of);
919 printAllocInfoSeg(code,func,of);
920 printAllocInfoSeg(data,func,of);
921 printAllocInfoSeg(xdata,func,of);
922 printAllocInfoSeg(idata,func,of);
923 printAllocInfoSeg(sfr,func,of);
924 printAllocInfoSeg(sfrbit,func,of);