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 = tmpfile())) {
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 ;
377 /*-----------------------------------------------------------------*/
378 /* allocParms - parameters are always passed on stack */
379 /*-----------------------------------------------------------------*/
380 void allocParms ( value *val )
385 for ( lval = val ; lval ; lval = lval->next, pNum++ ) {
387 /* check the declaration */
388 checkDecl (lval->sym);
390 /* if this a register parm then allocate
391 it as a local variable by adding it
392 to the first block we see in the body */
393 if (IS_REGPARM(lval->etype))
396 /* mark it as my parameter */
397 lval->sym->ismyparm = 1;
398 lval->sym->localof = currFunc;
401 /* if automatic variables r 2b stacked */
402 if ( options.stackAuto || IS_RENT(currFunc->etype)) {
405 lval->sym->onStack = 1;
407 /* choose which stack 2 use */
408 /* use xternal stack */
409 if ( options.useXstack ) {
410 /* PENDING: stack direction support */
411 SPEC_OCLS(lval->etype) = SPEC_OCLS(lval->sym->etype) = xstack ;
412 SPEC_STAK(lval->etype) = SPEC_STAK(lval->sym->etype) = lval->sym->stack =
413 xstackPtr - getSize(lval->type);
414 xstackPtr -= getSize (lval->type);
416 else { /* use internal stack */
417 SPEC_OCLS(lval->etype) = SPEC_OCLS(lval->sym->etype) = istack ;
418 if (port->stack.direction > 0) {
419 SPEC_STAK(lval->etype) = SPEC_STAK(lval->sym->etype) = lval->sym->stack =
420 stackPtr - ( SPEC_BANK(currFunc->etype) ? port->stack.bank_overhead : 0) -
421 getSize(lval->type) -
422 (IS_ISR(currFunc->etype) ? port->stack.isr_overhead : 0);
423 stackPtr -= getSize (lval->type);
426 /* This looks like the wrong order but it turns out OK... */
427 /* PENDING: isr, bank overhead, ... */
428 SPEC_STAK(lval->etype) = SPEC_STAK(lval->sym->etype) = lval->sym->stack = stackPtr;
429 stackPtr += getSize (lval->type);
432 allocIntoSeg(lval->sym);
434 else { /* allocate them in the automatic space */
435 /* generate a unique name */
436 sprintf (lval->sym->rname,"_%s_PARM_%d",currFunc->name,pNum);
437 strcpy (lval->name,lval->sym->rname);
439 /* if declared in external storage */
440 if (SPEC_SCLS(lval->etype) == S_XDATA)
441 SPEC_OCLS(lval->etype) = SPEC_OCLS(lval->sym->etype) = xdata;
443 /* other wise depending on the memory model
444 note here that we put it into the overlay segment
445 first, we will remove it from the overlay segment
446 after the overlay determination has been done */
447 SPEC_OCLS(lval->etype) = SPEC_OCLS(lval->sym->etype) =
448 ( options.model ? port->mem.default_local_map :
449 (options.noOverlay ? port->mem.default_local_map
452 allocIntoSeg(lval->sym);
459 /*-----------------------------------------------------------------*/
460 /* deallocParms - parameters are always passed on stack */
461 /*-----------------------------------------------------------------*/
462 void deallocParms ( value *val )
466 for ( lval = val ; lval ; lval = lval->next ) {
468 /* unmark is myparm */
469 lval->sym->ismyparm = 0;
470 /* if on stack then depending on which stack */
472 /* delete it from the symbol table */
473 deleteSym (SymbolTab,lval->sym,lval->sym->name);
475 if (!lval->sym->isref) {
476 lval->sym->allocreq = 1;
477 werror(W_NO_REFERENCE,currFunc->name,
478 "function argument",lval->sym->name);
481 /* move the rname if any to the name for both val & sym */
482 /* and leave a copy of it in the symbol table */
483 if (lval->sym->rname[0]) {
484 char buffer[SDCC_NAME_MAX];
485 strcpy(buffer,lval->sym->rname);
486 lval->sym = copySymbol(lval->sym);
487 strcpy(lval->sym->rname,buffer);
488 strcpy(lval->name,strcpy(lval->sym->name,lval->sym->rname));
489 addSym (SymbolTab, lval->sym, lval->sym->name,
490 lval->sym->level,lval->sym->block);
491 lval->sym->_isparm = 1;
492 addSet(&operKeyReset,lval->sym);
500 /*-----------------------------------------------------------------*/
501 /* allocLocal - allocate local variables */
502 /*-----------------------------------------------------------------*/
503 void allocLocal ( symbol *sym )
506 /* generate an unique name */
507 sprintf(sym->rname,"_%s_%s_%d_%d",
508 currFunc->name,sym->name,sym->level,sym->block);
511 sym->localof = currFunc;
513 /* if this is a static variable */
514 if ( IS_STATIC (sym->etype)) {
515 /* SPEC_OCLS(sym->etype) = (options.model ? xdata : data ); */
516 SPEC_OCLS(sym->etype) = port->mem.default_local_map;
522 /* if volatile then */
523 if (IS_VOLATILE(sym->etype))
526 /* this is automatic */
528 /* if it to be placed on the stack */
529 if ( options.stackAuto || reentrant) {
532 if ( options.useXstack ) {
533 /* PENDING: stack direction for xstack */
534 SPEC_OCLS(sym->etype) = xstack ;
535 SPEC_STAK(sym->etype) = sym->stack = (xstackPtr + 1);
536 xstackPtr += getSize (sym->type) ;
539 SPEC_OCLS(sym->etype) = istack ;
540 if (port->stack.direction > 0) {
541 SPEC_STAK(sym->etype) = sym->stack = ( stackPtr + 1);
542 stackPtr += getSize (sym->type) ;
545 stackPtr -= getSize (sym->type);
546 SPEC_STAK(sym->etype) = sym->stack = stackPtr;
553 /* else depending on the storage class specified */
554 if ( SPEC_SCLS(sym->etype) == S_XDATA ) {
555 SPEC_OCLS(sym->etype) = xdata ;
560 if ( (SPEC_SCLS(sym->etype) == S_CODE ||
561 SPEC_SCLS(sym->etype) == S_CONSTANT) &&
563 SPEC_OCLS(sym->etype) = statsg ;
568 if ( SPEC_SCLS(sym->etype) == S_IDATA ) {
569 SPEC_OCLS(sym->etype) = idata ;
575 /* if this is a function then assign code space */
576 if (IS_FUNC(sym->type)) {
577 SPEC_OCLS(sym->etype) = code ;
581 /* if this is a SFR or SBIT */
582 if ( SPEC_SCLS(sym->etype) == S_SFR ||
583 SPEC_SCLS(sym->etype) == S_SBIT ) {
585 /* if both absolute address & initial */
586 /* value specified then error */
587 if ( IS_ABSOLUTE (sym->etype) && sym->ival ) {
588 werror(E_SFR_INIT,sym->name);
592 SPEC_OCLS(sym->etype) =
593 (SPEC_SCLS(sym->etype) == S_SFR ? sfr : sfrbit);
599 /* if this is a bit variable and no storage class */
600 if ( SPEC_NOUN(sym->etype) == V_BIT
601 && (SPEC_SCLS(sym->etype) == S_BIT)) {
602 SPEC_OCLS(sym->etype) = bit ;
607 if ( SPEC_SCLS(sym->etype) == S_DATA ) {
608 SPEC_OCLS(sym->etype) = (options.noOverlay ? data : overlay );
613 /* again note that we have put it into the overlay segment
614 will remove and put into the 'data' segment if required after
615 overlay analysis has been done */
616 SPEC_OCLS(sym->etype) = ( options.model ? port->mem.default_local_map :
617 (options.noOverlay ? port->mem.default_local_map
622 /*-----------------------------------------------------------------*/
623 /* deallocLocal - deallocates the local variables */
624 /*-----------------------------------------------------------------*/
625 void deallocLocal ( symbol *csym )
629 for ( sym = csym ; sym ; sym = sym->next) {
633 /* if it is on the stack */
635 if (options.useXstack)
636 xstackPtr -= getSize(sym->type);
638 stackPtr -= getSize(sym->type);
640 /* if not used give a warning */
641 if (!sym->isref && !IS_STATIC(sym->etype))
642 werror(W_NO_REFERENCE,currFunc->name,
643 "local variable",sym->name);
644 /* now delete it from the symbol table */
645 deleteSym (SymbolTab,sym,sym->name);
649 /*-----------------------------------------------------------------*/
650 /* overlay2data - moves declarations from the overlay seg to data */
651 /*-----------------------------------------------------------------*/
656 for (sym = setFirstItem(overlay->syms); sym;
657 sym = setNextItem(overlay->syms)) {
659 SPEC_OCLS(sym->etype) = data;
663 setToNull((void **) &overlay->syms);
667 /*-----------------------------------------------------------------*/
668 /* overlay2Set - will add all symbols from the overlay segment to */
669 /* the set of sets containing the overlable symbols */
670 /*-----------------------------------------------------------------*/
676 for (sym = setFirstItem(overlay->syms); sym;
677 sym = setNextItem(overlay->syms)) {
682 setToNull((void **) &overlay->syms);
683 addSet (&ovrSetSets,oset);
687 /*-----------------------------------------------------------------*/
688 /* allocVariables - creates decl & assign storage class for a v */
689 /*-----------------------------------------------------------------*/
690 int allocVariables ( symbol *symChain )
697 /* go thru the symbol chain */
698 for ( sym = symChain ; sym ; sym = sym->next ) {
700 /* if this is a typedef then add it */
701 /* to the typedef table */
702 if (IS_TYPEDEF(sym->etype)) {
703 /* check if the typedef already exists */
704 csym = findSym (TypedefTab, NULL, sym->name );
705 if ( csym && csym->level == sym->level )
706 werror(E_DUPLICATE_TYPEDEF,sym->name);
708 addSym (TypedefTab, sym , sym->name,sym->level,sym->block);
709 continue ; /* go to the next one */
711 /* make sure it already exist */
712 csym = findSymWithLevel (SymbolTab, sym);
713 if (! csym || (csym && csym->level != sym->level) )
716 /* check the declaration */
719 /* if this is a function or a pointer to function */
720 /* then args processing */
721 if (funcInChain(csym->type)) {
723 processFuncArgs (csym, 1);
724 /* if register bank specified then update maxRegBank */
725 if (maxRegBank < SPEC_BANK(csym->etype))
726 maxRegBank = SPEC_BANK(csym->etype);
729 /* if this is a extern variable then change the */
730 /* level to zero temporarily */
731 if (IS_EXTERN(csym->etype) || IS_FUNC(csym->type) ) {
732 saveLevel = csym->level ;
736 /* if this is a literal then it is an enumerated */
737 /* type so need not allocate it space for it */
738 if (IS_LITERAL(sym->etype))
741 /* generate the actual declaration */
745 stack += getSize(csym->type) ;
750 /* restore the level */
751 if (IS_EXTERN(csym->etype) || IS_FUNC(csym->type))
752 csym->level = saveLevel;
758 /*-----------------------------------------------------------------*/
759 /* redoStackOffsets :- will reassign the values for stack offsets */
760 /*-----------------------------------------------------------------*/
761 void redoStackOffsets ()
767 /* after register allocation is complete we know
768 which variables will need to be assigned space
769 on the stack. We will eliminate those variables
770 which do not have the allocReq flag thus reducing
772 for ( sym = setFirstItem(istack->syms); sym;
773 sym = setNextItem(istack->syms)) {
775 int size = getSize(sym->type);
776 /* nothing to do with parameters so continue */
777 if ((sym->_isparm && !IS_REGPARM(sym->etype)))
780 if ( IS_AGGREGATE(sym->type)) {
781 if (port->stack.direction > 0) {
782 SPEC_STAK(sym->etype) = sym->stack = ( sPtr + 1);
787 SPEC_STAK(sym->etype) = sym->stack = sPtr;
792 /* if allocation not required then subtract
793 size from overall stack size & continue */
794 if (!sym->allocreq) {
795 currFunc->stack -= size;
796 SPEC_STAK(currFunc->etype) -= size;
800 if (port->stack.direction > 0) {
801 SPEC_STAK(sym->etype) = sym->stack = ( sPtr + 1);
806 SPEC_STAK(sym->etype) = sym->stack = sPtr;
810 /* do the same for the external stack */
812 for ( sym = setFirstItem(xstack->syms); sym;
813 sym = setNextItem(xstack->syms)) {
815 int size = getSize(sym->type);
816 /* nothing to do with parameters so continue */
817 if ((sym->_isparm && !IS_REGPARM(sym->etype)))
820 if (IS_AGGREGATE(sym->type)) {
821 SPEC_STAK(sym->etype) = sym->stack = ( xsPtr + 1);
826 /* if allocation not required then subtract
827 size from overall stack size & continue */
828 if (!sym->allocreq) {
829 currFunc->xstack -= size;
830 SPEC_STAK(currFunc->etype) -= size;
834 SPEC_STAK(sym->etype) = sym->stack = ( xsPtr + 1);
838 /* if the debug option is set then output the
839 symbols to the map file */
841 for (sym = setFirstItem(istack->syms); sym;
842 sym = setNextItem(istack->syms))
843 cdbSymbol(sym,cdbFile,FALSE,FALSE);
845 for (sym = setFirstItem(xstack->syms); sym;
846 sym = setNextItem(xstack->syms))
847 cdbSymbol(sym,cdbFile,FALSE,FALSE);