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 /*-----------------------------------------------------------------*/
81 /* allocate all the segments */
82 /* xternal stack segment ;
90 POINTER-TYPE - FPOINTER
92 xstack = allocMap (0, 1, 1, 0, 0, 0, options.xstack_loc, XSTACK_NAME,'A',PPOINTER);
94 /* internal stack segment ;
102 POINTER-TYPE - POINTER
104 istack = allocMap (0, 0, 0, 0, 0, 0,options.stack_loc, ISTACK_NAME,'B',POINTER);
114 POINTER-TYPE - CPOINTER
116 code = allocMap (0, 1, 0, 0, 0, 1, options.code_loc, CODE_NAME,'C',CPOINTER);
118 /* Static segment (code for variables );
126 POINTER-TYPE - CPOINTER
128 statsg = allocMap (0, 1, 0, 0, 0, 1,0, STATIC_NAME,'D',CPOINTER);
130 /* Data segment - internal storage segment ;
138 POINTER-TYPE - POINTER
140 data = allocMap (0, 0, 0, 1, 0, 0, options.data_loc, DATA_NAME,'E',POINTER);
142 /* overlay segment - same as internal storage segment ;
150 POINTER-TYPE - POINTER
152 overlay = allocMap (0, 0, 0, 1, 0, 0, options.data_loc, DATA_NAME,'E',POINTER);
154 /* Xternal Data segment -
162 POINTER-TYPE - FPOINTER
164 xdata = allocMap (0, 1, 0, 0, 0, 0, options.xdata_loc, XDATA_NAME,'F',FPOINTER);
166 /* Inderectly addressed internal data segment
174 POINTER-TYPE - IPOINTER
176 idata = allocMap (0, 0, 0, 0, 0, 0, options.idata_loc,IDATA_NAME,'G',IPOINTER);
178 /* Static segment (code for variables );
186 POINTER-TYPE - _NONE_
188 bit = allocMap (0, 0, 0, 1, 1, 0,0, BIT_NAME,'H',0);
190 /* Special function register space :-
198 POINTER-TYPE - _NONE_
200 sfr = allocMap (1,0, 0, 1, 0, 0,0, REG_NAME,'I',0);
210 POINTER-TYPE - _NONE_
212 reg = allocMap (1,0, 0, 0, 0, 0, 0,REG_NAME,' ',0);
222 POINTER-TYPE - _NONE_
224 sfrbit = allocMap (1,0, 0, 1, 1, 0,0, REG_NAME,'J',0);
234 POINTER-TYPE - EEPPOINTER
236 eeprom = allocMap (0,1, 0, 0, 0, 0,0, REG_NAME,'K',EEPPOINTER);
238 /* the unknown map */
239 generic = allocMap (1,0, 0, 1, 1, 0,0, REG_NAME,' ',GPOINTER);
243 /*-----------------------------------------------------------------*/
244 /* allocIntoSeg - puts a symbol into a memory segment */
245 /*-----------------------------------------------------------------*/
246 void allocIntoSeg (symbol *sym)
248 memmap *segment = SPEC_OCLS(sym->etype);
250 addSet (&segment->syms,sym);
253 /*-----------------------------------------------------------------*/
254 /* allocGlobal - aassigns the output segment to a global var */
255 /*-----------------------------------------------------------------*/
256 void allocGlobal ( symbol *sym )
258 /* symbol name is internal name */
259 sprintf (sym->rname,"_%s",sym->name);
261 /* add it to the operandKey reset */
262 addSet(&operKeyReset,sym);
264 /* if this is a literal e.g. enumerated type */
265 /* put it in the data segment & do nothing */
266 if (IS_LITERAL(sym->etype)) {
267 SPEC_OCLS(sym->etype) = data ;
271 /* if this is a function then assign code space */
272 if (IS_FUNC(sym->type)) {
273 SPEC_OCLS(sym->etype) = code ;
274 /* if this is an interrupt service routine
275 then put it in the interrupt service array */
276 if (IS_ISR(sym->etype)) {
278 if (interrupts[SPEC_INTN(sym->etype)])
279 werror(E_INT_DEFINED,
280 SPEC_INTN(sym->etype),
281 interrupts[SPEC_INTN(sym->etype)]->name);
283 interrupts[SPEC_INTN(sym->etype)] = sym;
285 /* automagically extend the maximum interrupts */
286 if (SPEC_INTN(sym->etype) >= maxInterrupts )
287 maxInterrupts = SPEC_INTN(sym->etype) + 1;
289 /* if it is not compiler defined */
296 /* if this is a SFR or SBIT */
297 if ( SPEC_SCLS(sym->etype) == S_SFR ||
298 SPEC_SCLS(sym->etype) == S_SBIT ) {
300 /* if both absolute address & initial */
301 /* value specified then error */
302 if ( IS_ABSOLUTE (sym->etype) && sym->ival ) {
303 werror(E_SFR_INIT,sym->name);
307 SPEC_OCLS(sym->etype) =
308 (SPEC_SCLS(sym->etype) == S_SFR ? sfr : sfrbit);
314 /* if this is a bit variable and no storage class */
315 if ( SPEC_NOUN(sym->etype) == V_BIT
316 && SPEC_SCLS(sym->etype) == S_BIT ) {
317 SPEC_OCLS(sym->etype) = bit ;
322 /* if bit storage class */
323 if ( SPEC_SCLS(sym->etype) == S_SBIT ) {
324 SPEC_OCLS(sym->etype) = bit;
329 /* register storage class ignored changed to FIXED */
330 if ( SPEC_SCLS(sym->etype) == S_REGISTER )
331 SPEC_SCLS(sym->etype) = S_FIXED ;
333 /* if data specified then */
334 if (SPEC_SCLS(sym->etype) == S_DATA) {
335 /* set the output class */
336 SPEC_OCLS(sym->etype) = data ;
337 /* generate the symbol */
342 /* if it is fixed, then allocate depending on the */
343 /* current memory model,same for automatics */
344 if ( SPEC_SCLS(sym->etype) == S_FIXED ||
345 SPEC_SCLS(sym->etype) == S_AUTO ) {
346 /* set the output class */
347 SPEC_OCLS(sym->etype) = port->mem.default_globl_map ;
348 /* generate the symbol */
353 /* if code change to constant */
354 if ( SPEC_SCLS(sym->etype) == S_CODE ||
355 SPEC_SCLS(sym->etype) == S_CONSTANT ) {
356 SPEC_OCLS(sym->etype) = statsg ;
361 if ( SPEC_SCLS(sym->etype) == S_XDATA ) {
362 SPEC_OCLS(sym->etype) = xdata ;
367 if ( SPEC_SCLS(sym->etype) == S_IDATA ) {
368 SPEC_OCLS(sym->etype) = idata ;
374 if ( SPEC_SCLS(sym->etype) == S_EEPROM ) {
375 SPEC_OCLS(sym->etype) = eeprom ;
383 /*-----------------------------------------------------------------*/
384 /* allocParms - parameters are always passed on stack */
385 /*-----------------------------------------------------------------*/
386 void allocParms ( value *val )
391 for ( lval = val ; lval ; lval = lval->next, pNum++ ) {
393 /* check the declaration */
394 checkDecl (lval->sym);
396 /* if this a register parm then allocate
397 it as a local variable by adding it
398 to the first block we see in the body */
399 if (IS_REGPARM(lval->etype))
402 /* mark it as my parameter */
403 lval->sym->ismyparm = 1;
404 lval->sym->localof = currFunc;
407 /* if automatic variables r 2b stacked */
408 if ( options.stackAuto || IS_RENT(currFunc->etype)) {
411 lval->sym->onStack = 1;
413 /* choose which stack 2 use */
414 /* use xternal stack */
415 if ( options.useXstack ) {
416 /* PENDING: stack direction support */
417 SPEC_OCLS(lval->etype) = SPEC_OCLS(lval->sym->etype) = xstack ;
418 SPEC_STAK(lval->etype) = SPEC_STAK(lval->sym->etype) = lval->sym->stack =
419 xstackPtr - getSize(lval->type);
420 xstackPtr -= getSize (lval->type);
422 else { /* use internal stack */
423 SPEC_OCLS(lval->etype) = SPEC_OCLS(lval->sym->etype) = istack ;
424 if (port->stack.direction > 0) {
425 SPEC_STAK(lval->etype) = SPEC_STAK(lval->sym->etype) = lval->sym->stack =
426 stackPtr - ( SPEC_BANK(currFunc->etype) ? port->stack.bank_overhead : 0) -
427 getSize(lval->type) -
428 (IS_ISR(currFunc->etype) ? port->stack.isr_overhead : 0);
429 stackPtr -= getSize (lval->type);
432 /* This looks like the wrong order but it turns out OK... */
433 /* PENDING: isr, bank overhead, ... */
434 SPEC_STAK(lval->etype) = SPEC_STAK(lval->sym->etype) = lval->sym->stack = stackPtr;
435 stackPtr += getSize (lval->type);
438 allocIntoSeg(lval->sym);
440 else { /* allocate them in the automatic space */
441 /* generate a unique name */
442 sprintf (lval->sym->rname,"_%s_PARM_%d",currFunc->name,pNum);
443 strcpy (lval->name,lval->sym->rname);
445 /* if declared in external storage */
446 if (SPEC_SCLS(lval->etype) == S_XDATA)
447 SPEC_OCLS(lval->etype) = SPEC_OCLS(lval->sym->etype) = xdata;
449 /* other wise depending on the memory model
450 note here that we put it into the overlay segment
451 first, we will remove it from the overlay segment
452 after the overlay determination has been done */
453 SPEC_OCLS(lval->etype) = SPEC_OCLS(lval->sym->etype) =
454 ( options.model ? port->mem.default_local_map :
455 (options.noOverlay ? port->mem.default_local_map
458 allocIntoSeg(lval->sym);
465 /*-----------------------------------------------------------------*/
466 /* deallocParms - parameters are always passed on stack */
467 /*-----------------------------------------------------------------*/
468 void deallocParms ( value *val )
472 for ( lval = val ; lval ; lval = lval->next ) {
474 /* unmark is myparm */
475 lval->sym->ismyparm = 0;
476 /* if on stack then depending on which stack */
478 /* delete it from the symbol table */
479 deleteSym (SymbolTab,lval->sym,lval->sym->name);
481 if (!lval->sym->isref) {
482 lval->sym->allocreq = 1;
483 werror(W_NO_REFERENCE,currFunc->name,
484 "function argument",lval->sym->name);
487 /* move the rname if any to the name for both val & sym */
488 /* and leave a copy of it in the symbol table */
489 if (lval->sym->rname[0]) {
490 char buffer[SDCC_NAME_MAX];
491 strcpy(buffer,lval->sym->rname);
492 lval->sym = copySymbol(lval->sym);
493 strcpy(lval->sym->rname,buffer);
494 strcpy(lval->name,strcpy(lval->sym->name,lval->sym->rname));
495 addSym (SymbolTab, lval->sym, lval->sym->name,
496 lval->sym->level,lval->sym->block);
497 lval->sym->_isparm = 1;
498 addSet(&operKeyReset,lval->sym);
506 /*-----------------------------------------------------------------*/
507 /* allocLocal - allocate local variables */
508 /*-----------------------------------------------------------------*/
509 void allocLocal ( symbol *sym )
512 /* generate an unique name */
513 sprintf(sym->rname,"_%s_%s_%d_%d",
514 currFunc->name,sym->name,sym->level,sym->block);
517 sym->localof = currFunc;
519 /* if this is a static variable */
520 if ( IS_STATIC (sym->etype)) {
521 /* SPEC_OCLS(sym->etype) = (options.model ? xdata : data ); */
522 SPEC_OCLS(sym->etype) = port->mem.default_local_map;
528 /* if volatile then */
529 if (IS_VOLATILE(sym->etype))
532 /* this is automatic */
534 /* if it to be placed on the stack */
535 if ( options.stackAuto || reentrant) {
538 if ( options.useXstack ) {
539 /* PENDING: stack direction for xstack */
540 SPEC_OCLS(sym->etype) = xstack ;
541 SPEC_STAK(sym->etype) = sym->stack = (xstackPtr + 1);
542 xstackPtr += getSize (sym->type) ;
545 SPEC_OCLS(sym->etype) = istack ;
546 if (port->stack.direction > 0) {
547 SPEC_STAK(sym->etype) = sym->stack = ( stackPtr + 1);
548 stackPtr += getSize (sym->type) ;
551 stackPtr -= getSize (sym->type);
552 SPEC_STAK(sym->etype) = sym->stack = stackPtr;
559 /* else depending on the storage class specified */
560 if ( SPEC_SCLS(sym->etype) == S_XDATA ) {
561 SPEC_OCLS(sym->etype) = xdata ;
566 if ( (SPEC_SCLS(sym->etype) == S_CODE ||
567 SPEC_SCLS(sym->etype) == S_CONSTANT) &&
569 SPEC_OCLS(sym->etype) = statsg ;
574 if ( SPEC_SCLS(sym->etype) == S_IDATA ) {
575 SPEC_OCLS(sym->etype) = idata ;
581 /* if this is a function then assign code space */
582 if (IS_FUNC(sym->type)) {
583 SPEC_OCLS(sym->etype) = code ;
587 /* if this is a SFR or SBIT */
588 if ( SPEC_SCLS(sym->etype) == S_SFR ||
589 SPEC_SCLS(sym->etype) == S_SBIT ) {
591 /* if both absolute address & initial */
592 /* value specified then error */
593 if ( IS_ABSOLUTE (sym->etype) && sym->ival ) {
594 werror(E_SFR_INIT,sym->name);
598 SPEC_OCLS(sym->etype) =
599 (SPEC_SCLS(sym->etype) == S_SFR ? sfr : sfrbit);
605 /* if this is a bit variable and no storage class */
606 if ( SPEC_NOUN(sym->etype) == V_BIT
607 && (SPEC_SCLS(sym->etype) == S_BIT)) {
608 SPEC_OCLS(sym->etype) = bit ;
613 if ( SPEC_SCLS(sym->etype) == S_DATA ) {
614 SPEC_OCLS(sym->etype) = (options.noOverlay ? data : overlay );
619 if ( SPEC_SCLS(sym->etype) == S_EEPROM ) {
620 SPEC_OCLS(sym->etype) = eeprom;
625 /* again note that we have put it into the overlay segment
626 will remove and put into the 'data' segment if required after
627 overlay analysis has been done */
628 SPEC_OCLS(sym->etype) = ( options.model ? port->mem.default_local_map :
629 (options.noOverlay ? port->mem.default_local_map
634 /*-----------------------------------------------------------------*/
635 /* deallocLocal - deallocates the local variables */
636 /*-----------------------------------------------------------------*/
637 void deallocLocal ( symbol *csym )
641 for ( sym = csym ; sym ; sym = sym->next) {
645 /* if it is on the stack */
647 if (options.useXstack)
648 xstackPtr -= getSize(sym->type);
650 stackPtr -= getSize(sym->type);
652 /* if not used give a warning */
653 if (!sym->isref && !IS_STATIC(sym->etype))
654 werror(W_NO_REFERENCE,currFunc->name,
655 "local variable",sym->name);
656 /* now delete it from the symbol table */
657 deleteSym (SymbolTab,sym,sym->name);
661 /*-----------------------------------------------------------------*/
662 /* overlay2data - moves declarations from the overlay seg to data */
663 /*-----------------------------------------------------------------*/
668 for (sym = setFirstItem(overlay->syms); sym;
669 sym = setNextItem(overlay->syms)) {
671 SPEC_OCLS(sym->etype) = data;
675 setToNull((void **) &overlay->syms);
679 /*-----------------------------------------------------------------*/
680 /* overlay2Set - will add all symbols from the overlay segment to */
681 /* the set of sets containing the overlable symbols */
682 /*-----------------------------------------------------------------*/
688 for (sym = setFirstItem(overlay->syms); sym;
689 sym = setNextItem(overlay->syms)) {
694 setToNull((void **) &overlay->syms);
695 addSet (&ovrSetSets,oset);
699 /*-----------------------------------------------------------------*/
700 /* allocVariables - creates decl & assign storage class for a v */
701 /*-----------------------------------------------------------------*/
702 int allocVariables ( symbol *symChain )
709 /* go thru the symbol chain */
710 for ( sym = symChain ; sym ; sym = sym->next ) {
712 /* if this is a typedef then add it */
713 /* to the typedef table */
714 if (IS_TYPEDEF(sym->etype)) {
715 /* check if the typedef already exists */
716 csym = findSym (TypedefTab, NULL, sym->name );
717 if ( csym && csym->level == sym->level )
718 werror(E_DUPLICATE_TYPEDEF,sym->name);
720 addSym (TypedefTab, sym , sym->name,sym->level,sym->block);
721 continue ; /* go to the next one */
723 /* make sure it already exist */
724 csym = findSymWithLevel (SymbolTab, sym);
725 if (! csym || (csym && csym->level != sym->level) )
728 /* check the declaration */
731 /* if this is a function or a pointer to function */
732 /* then args processing */
733 if (funcInChain(csym->type)) {
735 processFuncArgs (csym, 1);
736 /* if register bank specified then update maxRegBank */
737 if (maxRegBank < SPEC_BANK(csym->etype))
738 maxRegBank = SPEC_BANK(csym->etype);
741 /* if this is a extern variable then change the */
742 /* level to zero temporarily */
743 if (IS_EXTERN(csym->etype) || IS_FUNC(csym->type) ) {
744 saveLevel = csym->level ;
748 /* if this is a literal then it is an enumerated */
749 /* type so need not allocate it space for it */
750 if (IS_LITERAL(sym->etype))
753 /* generate the actual declaration */
757 stack += getSize(csym->type) ;
762 /* restore the level */
763 if (IS_EXTERN(csym->etype) || IS_FUNC(csym->type))
764 csym->level = saveLevel;
770 /*-----------------------------------------------------------------*/
771 /* redoStackOffsets :- will reassign the values for stack offsets */
772 /*-----------------------------------------------------------------*/
773 void redoStackOffsets ()
779 /* after register allocation is complete we know
780 which variables will need to be assigned space
781 on the stack. We will eliminate those variables
782 which do not have the allocReq flag thus reducing
784 for ( sym = setFirstItem(istack->syms); sym;
785 sym = setNextItem(istack->syms)) {
787 int size = getSize(sym->type);
788 /* nothing to do with parameters so continue */
789 if ((sym->_isparm && !IS_REGPARM(sym->etype)))
792 if ( IS_AGGREGATE(sym->type)) {
793 if (port->stack.direction > 0) {
794 SPEC_STAK(sym->etype) = sym->stack = ( sPtr + 1);
799 SPEC_STAK(sym->etype) = sym->stack = sPtr;
804 /* if allocation not required then subtract
805 size from overall stack size & continue */
806 if (!sym->allocreq) {
807 currFunc->stack -= size;
808 SPEC_STAK(currFunc->etype) -= size;
812 if (port->stack.direction > 0) {
813 SPEC_STAK(sym->etype) = sym->stack = ( sPtr + 1);
818 SPEC_STAK(sym->etype) = sym->stack = sPtr;
822 /* do the same for the external stack */
824 for ( sym = setFirstItem(xstack->syms); sym;
825 sym = setNextItem(xstack->syms)) {
827 int size = getSize(sym->type);
828 /* nothing to do with parameters so continue */
829 if ((sym->_isparm && !IS_REGPARM(sym->etype)))
832 if (IS_AGGREGATE(sym->type)) {
833 SPEC_STAK(sym->etype) = sym->stack = ( xsPtr + 1);
838 /* if allocation not required then subtract
839 size from overall stack size & continue */
840 if (!sym->allocreq) {
841 currFunc->xstack -= size;
842 SPEC_STAK(currFunc->etype) -= size;
846 SPEC_STAK(sym->etype) = sym->stack = ( xsPtr + 1);
850 /* if the debug option is set then output the
851 symbols to the map file */
853 for (sym = setFirstItem(istack->syms); sym;
854 sym = setNextItem(istack->syms))
855 cdbSymbol(sym,cdbFile,FALSE,FALSE);
857 for (sym = setFirstItem(xstack->syms); sym;
858 sym = setNextItem(xstack->syms))
859 cdbSymbol(sym,cdbFile,FALSE,FALSE);