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',FPOINTER);
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);
226 /* the unknown map */
227 generic = allocMap (1,0, 0, 1, 1, 0,0, REG_NAME,' ',GPOINTER);
231 /*-----------------------------------------------------------------*/
232 /* allocIntoSeg - puts a symbol into a memory segment */
233 /*-----------------------------------------------------------------*/
234 void allocIntoSeg (symbol *sym)
236 memmap *segment = SPEC_OCLS(sym->etype);
238 addSet (&segment->syms,sym);
241 /*-----------------------------------------------------------------*/
242 /* allocGlobal - aassigns the output segment to a global var */
243 /*-----------------------------------------------------------------*/
244 void allocGlobal ( symbol *sym )
246 /* symbol name is internal name */
247 sprintf (sym->rname,"_%s",sym->name);
249 /* add it to the operandKey reset */
250 addSet(&operKeyReset,sym);
252 /* if this is a literal e.g. enumerated type */
253 /* put it in the data segment & do nothing */
254 if (IS_LITERAL(sym->etype)) {
255 SPEC_OCLS(sym->etype) = data ;
259 /* if this is a function then assign code space */
260 if (IS_FUNC(sym->type)) {
261 SPEC_OCLS(sym->etype) = code ;
262 /* if this is an interrupt service routine
263 then put it in the interrupt service array */
264 if (IS_ISR(sym->etype)) {
266 if (interrupts[SPEC_INTN(sym->etype)])
267 werror(E_INT_DEFINED,
268 SPEC_INTN(sym->etype),
269 interrupts[SPEC_INTN(sym->etype)]->name);
271 interrupts[SPEC_INTN(sym->etype)] = sym;
273 /* automagically extend the maximum interrupts */
274 if (SPEC_INTN(sym->etype) >= maxInterrupts )
275 maxInterrupts = SPEC_INTN(sym->etype) + 1;
277 /* if it is not compiler defined */
284 /* if this is a SFR or SBIT */
285 if ( SPEC_SCLS(sym->etype) == S_SFR ||
286 SPEC_SCLS(sym->etype) == S_SBIT ) {
288 /* if both absolute address & initial */
289 /* value specified then error */
290 if ( IS_ABSOLUTE (sym->etype) && sym->ival ) {
291 werror(E_SFR_INIT,sym->name);
295 SPEC_OCLS(sym->etype) =
296 (SPEC_SCLS(sym->etype) == S_SFR ? sfr : sfrbit);
302 /* if this is a bit variable and no storage class */
303 if ( SPEC_NOUN(sym->etype) == V_BIT
304 && SPEC_SCLS(sym->etype) == S_BIT ) {
305 SPEC_OCLS(sym->etype) = bit ;
310 /* if bit storage class */
311 if ( SPEC_SCLS(sym->etype) == S_SBIT ) {
312 SPEC_OCLS(sym->etype) = bit;
317 /* register storage class ignored changed to FIXED */
318 if ( SPEC_SCLS(sym->etype) == S_REGISTER )
319 SPEC_SCLS(sym->etype) = S_FIXED ;
321 /* if data specified then */
322 if (SPEC_SCLS(sym->etype) == S_DATA) {
323 /* set the output class */
324 SPEC_OCLS(sym->etype) = data ;
325 /* generate the symbol */
330 /* if it is fixed, then allocate depending on the */
331 /* current memory model,same for automatics */
332 if ( SPEC_SCLS(sym->etype) == S_FIXED ||
333 SPEC_SCLS(sym->etype) == S_AUTO ) {
334 /* set the output class */
335 SPEC_OCLS(sym->etype) = ( options.model ? xdata : data ) ;
336 /* generate the symbol */
341 /* if code change to constant */
342 if ( SPEC_SCLS(sym->etype) == S_CODE ||
343 SPEC_SCLS(sym->etype) == S_CONSTANT ) {
344 SPEC_OCLS(sym->etype) = statsg ;
349 if ( SPEC_SCLS(sym->etype) == S_XDATA ) {
350 SPEC_OCLS(sym->etype) = xdata ;
355 if ( SPEC_SCLS(sym->etype) == S_IDATA ) {
356 SPEC_OCLS(sym->etype) = idata ;
365 /*-----------------------------------------------------------------*/
366 /* allocParms - parameters are always passed on stack */
367 /*-----------------------------------------------------------------*/
368 void allocParms ( value *val )
373 for ( lval = val ; lval ; lval = lval->next, pNum++ ) {
375 /* check the declaration */
376 checkDecl (lval->sym);
378 // /* if this is a literal e.g. enumerated type */
379 // if (IS_LITERAL(lval->etype)) {
380 // SPEC_OCLS(lval->etype) = SPEC_OCLS(lval->sym->etype) =
381 // ( options.model ? xdata : data );
384 /* if this a register parm then allocate
385 it as a local variable by adding it
386 to the first block we see in the body */
387 if (IS_REGPARM(lval->etype))
390 /* mark it as my parameter */
391 lval->sym->ismyparm = 1;
392 lval->sym->localof = currFunc;
395 /* if automatic variables r 2b stacked */
396 if ( options.stackAuto || IS_RENT(currFunc->etype)) {
399 lval->sym->onStack = 1;
401 /* choose which stack 2 use */
402 /* use xternal stack */
403 if ( options.useXstack ) {
404 /* PENDING: stack direction support */
405 SPEC_OCLS(lval->etype) = SPEC_OCLS(lval->sym->etype) = xstack ;
406 SPEC_STAK(lval->etype) = SPEC_STAK(lval->sym->etype) = lval->sym->stack =
407 xstackPtr - getSize(lval->type);
408 xstackPtr -= getSize (lval->type);
410 else { /* use internal stack */
411 SPEC_OCLS(lval->etype) = SPEC_OCLS(lval->sym->etype) = istack ;
412 if (port->stack.direction > 0) {
413 SPEC_STAK(lval->etype) = SPEC_STAK(lval->sym->etype) = lval->sym->stack =
414 stackPtr - ( SPEC_BANK(currFunc->etype) ? port->stack.bank_overhead : 0) -
415 getSize(lval->type) -
416 (IS_ISR(currFunc->etype) ? port->stack.isr_overhead : 0);
417 stackPtr -= getSize (lval->type);
420 /* This looks like the wrong order but it turns out OK... */
421 /* PENDING: isr, bank overhead, ... */
422 SPEC_STAK(lval->etype) = SPEC_STAK(lval->sym->etype) = lval->sym->stack = stackPtr;
423 stackPtr += getSize (lval->type);
426 allocIntoSeg(lval->sym);
428 else { /* allocate them in the automatic space */
429 /* generate a unique name */
430 sprintf (lval->sym->rname,"_%s_PARM_%d",currFunc->name,pNum);
431 strcpy (lval->name,lval->sym->rname);
433 /* if declared in external storage */
434 if (SPEC_SCLS(lval->etype) == S_XDATA)
435 SPEC_OCLS(lval->etype) = SPEC_OCLS(lval->sym->etype) = xdata;
437 /* other wise depending on the memory model
438 note here that we put it into the overlay segment
439 first, we will remove it from the overlay segment
440 after the overlay determination has been done */
441 SPEC_OCLS(lval->etype) = SPEC_OCLS(lval->sym->etype) =
442 ( options.model ? xdata : (options.noOverlay ? data :overlay ));
444 allocIntoSeg(lval->sym);
451 /*-----------------------------------------------------------------*/
452 /* deallocParms - parameters are always passed on stack */
453 /*-----------------------------------------------------------------*/
454 void deallocParms ( value *val )
458 for ( lval = val ; lval ; lval = lval->next ) {
460 /* unmark is myparm */
461 lval->sym->ismyparm = 0;
462 /* if on stack then depending on which stack */
464 /* delete it from the symbol table */
465 deleteSym (SymbolTab,lval->sym,lval->sym->name);
467 if (!lval->sym->isref) {
468 lval->sym->allocreq = 1;
469 werror(W_NO_REFERENCE,currFunc->name,
470 "function argument",lval->sym->name);
473 /* move the rname if any to the name for both val & sym */
474 /* and leave a copy of it in the symbol table */
475 if (lval->sym->rname[0]) {
476 char buffer[SDCC_NAME_MAX];
477 strcpy(buffer,lval->sym->rname);
478 lval->sym = copySymbol(lval->sym);
479 strcpy(lval->sym->rname,buffer);
480 strcpy(lval->name,strcpy(lval->sym->name,lval->sym->rname));
481 addSym (SymbolTab, lval->sym, lval->sym->name,
482 lval->sym->level,lval->sym->block);
483 lval->sym->_isparm = 1;
484 addSet(&operKeyReset,lval->sym);
492 /*-----------------------------------------------------------------*/
493 /* allocLocal - allocate local variables */
494 /*-----------------------------------------------------------------*/
495 void allocLocal ( symbol *sym )
498 /* generate an unique name */
499 sprintf(sym->rname,"_%s_%s_%d_%d",
500 currFunc->name,sym->name,sym->level,sym->block);
503 sym->localof = currFunc;
505 /* if this is a static variable */
506 if ( IS_STATIC (sym->etype)) {
507 SPEC_OCLS(sym->etype) = (options.model ? xdata : data );
513 /* if volatile then */
514 if (IS_VOLATILE(sym->etype))
517 /* this is automatic */
519 /* if it to be placed on the stack */
520 if ( options.stackAuto || reentrant) {
523 if ( options.useXstack ) {
524 /* PENDING: stack direction for xstack */
525 SPEC_OCLS(sym->etype) = xstack ;
526 SPEC_STAK(sym->etype) = sym->stack = (xstackPtr + 1);
527 xstackPtr += getSize (sym->type) ;
530 SPEC_OCLS(sym->etype) = istack ;
531 if (port->stack.direction > 0) {
532 SPEC_STAK(sym->etype) = sym->stack = ( stackPtr + 1);
533 stackPtr += getSize (sym->type) ;
536 stackPtr -= getSize (sym->type);
537 SPEC_STAK(sym->etype) = sym->stack = stackPtr;
544 /* else depending on the storage class specified */
545 if ( SPEC_SCLS(sym->etype) == S_XDATA ) {
546 SPEC_OCLS(sym->etype) = xdata ;
551 if ( (SPEC_SCLS(sym->etype) == S_CODE ||
552 SPEC_SCLS(sym->etype) == S_CONSTANT) &&
554 SPEC_OCLS(sym->etype) = statsg ;
559 if ( SPEC_SCLS(sym->etype) == S_IDATA ) {
560 SPEC_OCLS(sym->etype) = idata ;
566 /* if this is a function then assign code space */
567 if (IS_FUNC(sym->type)) {
568 SPEC_OCLS(sym->etype) = code ;
572 /* if this is a SFR or SBIT */
573 if ( SPEC_SCLS(sym->etype) == S_SFR ||
574 SPEC_SCLS(sym->etype) == S_SBIT ) {
576 /* if both absolute address & initial */
577 /* value specified then error */
578 if ( IS_ABSOLUTE (sym->etype) && sym->ival ) {
579 werror(E_SFR_INIT,sym->name);
583 SPEC_OCLS(sym->etype) =
584 (SPEC_SCLS(sym->etype) == S_SFR ? sfr : sfrbit);
590 /* if this is a bit variable and no storage class */
591 if ( SPEC_NOUN(sym->etype) == V_BIT
592 && (SPEC_SCLS(sym->etype) == S_BIT)) {
593 SPEC_OCLS(sym->etype) = bit ;
598 /* again note that we have put it into the overlay segment
599 will remove and put into the 'data' segment if required after
600 overlay analysis has been done */
601 SPEC_OCLS(sym->etype) = ( options.model ? xdata :
602 (options.noOverlay ? data : overlay )) ;
606 /*-----------------------------------------------------------------*/
607 /* deallocLocal - deallocates the local variables */
608 /*-----------------------------------------------------------------*/
609 void deallocLocal ( symbol *csym )
613 for ( sym = csym ; sym ; sym = sym->next) {
617 /* if it is on the stack */
619 if (options.useXstack)
620 xstackPtr -= getSize(sym->type);
622 stackPtr -= getSize(sym->type);
624 /* if not used give a warning */
625 if (!sym->isref && !IS_STATIC(sym->etype))
626 werror(W_NO_REFERENCE,currFunc->name,
627 "local variable",sym->name);
628 /* now delete it from the symbol table */
629 deleteSym (SymbolTab,sym,sym->name);
633 /*-----------------------------------------------------------------*/
634 /* overlay2data - moves declarations from the overlay seg to data */
635 /*-----------------------------------------------------------------*/
640 for (sym = setFirstItem(overlay->syms); sym;
641 sym = setNextItem(overlay->syms)) {
643 SPEC_OCLS(sym->etype) = data;
647 setToNull((void **) &overlay->syms);
651 /*-----------------------------------------------------------------*/
652 /* overlay2Set - will add all symbols from the overlay segment to */
653 /* the set of sets containing the overlable symbols */
654 /*-----------------------------------------------------------------*/
660 for (sym = setFirstItem(overlay->syms); sym;
661 sym = setNextItem(overlay->syms)) {
666 setToNull((void **) &overlay->syms);
667 addSet (&ovrSetSets,oset);
671 /*-----------------------------------------------------------------*/
672 /* allocVariables - creates decl & assign storage class for a v */
673 /*-----------------------------------------------------------------*/
674 int allocVariables ( symbol *symChain )
681 /* go thru the symbol chain */
682 for ( sym = symChain ; sym ; sym = sym->next ) {
684 /* if this is a typedef then add it */
685 /* to the typedef table */
686 if (IS_TYPEDEF(sym->etype)) {
687 /* check if the typedef already exists */
688 csym = findSym (TypedefTab, NULL, sym->name );
689 if ( csym && csym->level == sym->level )
690 werror(E_DUPLICATE_TYPEDEF,sym->name);
692 addSym (TypedefTab, sym , sym->name,sym->level,sym->block);
693 continue ; /* go to the next one */
695 /* make sure it already exist */
696 csym = findSymWithLevel (SymbolTab, sym);
697 if (! csym || (csym && csym->level != sym->level) )
700 /* check the declaration */
703 /* if this is a function or a pointer to function */
704 /* then args processing */
705 if (funcInChain(csym->type)) {
707 processFuncArgs (csym, 1);
708 /* if register bank specified then update maxRegBank */
709 if (maxRegBank < SPEC_BANK(csym->etype))
710 maxRegBank = SPEC_BANK(csym->etype);
713 /* if this is a extern variable then change the */
714 /* level to zero temporarily */
715 if (IS_EXTERN(csym->etype) || IS_FUNC(csym->type) ) {
716 saveLevel = csym->level ;
720 /* if this is a literal then it is an enumerated */
721 /* type so need not allocate it space for it */
722 if (IS_LITERAL(sym->etype))
725 /* generate the actual declaration */
729 stack += getSize(csym->type) ;
734 /* restore the level */
735 if (IS_EXTERN(csym->etype) || IS_FUNC(csym->type))
736 csym->level = saveLevel;
742 /*-----------------------------------------------------------------*/
743 /* redoStackOffsets :- will reassign the values for stack offsets */
744 /*-----------------------------------------------------------------*/
745 void redoStackOffsets ()
751 /* after register allocation is complete we know
752 which variables will need to be assigned space
753 on the stack. We will eliminate those variables
754 which do not have the allocReq flag thus reducing
756 for ( sym = setFirstItem(istack->syms); sym;
757 sym = setNextItem(istack->syms)) {
759 int size = getSize(sym->type);
760 /* nothing to do with parameters so continue */
761 if ((sym->_isparm && !IS_REGPARM(sym->etype)))
764 if ( IS_AGGREGATE(sym->type)) {
765 if (port->stack.direction > 0) {
766 SPEC_STAK(sym->etype) = sym->stack = ( sPtr + 1);
771 SPEC_STAK(sym->etype) = sym->stack = sPtr;
776 /* if allocation not required then subtract
777 size from overall stack size & continue */
778 if (!sym->allocreq) {
779 currFunc->stack -= size;
780 SPEC_STAK(currFunc->etype) -= size;
784 if (port->stack.direction > 0) {
785 SPEC_STAK(sym->etype) = sym->stack = ( sPtr + 1);
790 SPEC_STAK(sym->etype) = sym->stack = sPtr;
794 /* do the same for the external stack */
796 for ( sym = setFirstItem(xstack->syms); sym;
797 sym = setNextItem(xstack->syms)) {
799 int size = getSize(sym->type);
800 /* nothing to do with parameters so continue */
801 if ((sym->_isparm && !IS_REGPARM(sym->etype)))
804 if (IS_AGGREGATE(sym->type)) {
805 SPEC_STAK(sym->etype) = sym->stack = ( xsPtr + 1);
810 /* if allocation not required then subtract
811 size from overall stack size & continue */
812 if (!sym->allocreq) {
813 currFunc->xstack -= size;
814 SPEC_STAK(currFunc->etype) -= size;
818 SPEC_STAK(sym->etype) = sym->stack = ( xsPtr + 1);
822 /* if the debug option is set then output the
823 symbols to the map file */
825 for (sym = setFirstItem(istack->syms); sym;
826 sym = setNextItem(istack->syms))
827 cdbSymbol(sym,cdbFile,FALSE,FALSE);
829 for (sym = setFirstItem(xstack->syms); sym;
830 sym = setNextItem(xstack->syms))
831 cdbSymbol(sym,cdbFile,FALSE,FALSE);