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 */
22 /* this is a set of sets each set containing
23 symbols in a single overlay */
24 set *ovrSetSets = NULL;
26 extern set *operKeyReset ;
27 extern set *tmpfileSet ;
28 extern symbol *interrupts[];
30 int fatalError = 0 ;/* fatal error flag */
32 /*-----------------------------------------------------------------*/
33 /* allocMap - allocates a memory map */
34 /*-----------------------------------------------------------------*/
35 memmap *allocMap (char rspace, /* sfr space */
36 char farmap, /* far or near segment */
37 char paged , /* can this segment be paged */
38 char direct, /* directly addressable */
39 char bitaddr, /* bit addressable space*/
40 char codemap, /* this is code space */
41 unsigned sloc, /* starting location */
42 const char *name, /* 2 character name */
48 if (!(map = GC_malloc(sizeof(memmap)))) {
49 werror(E_OUT_OF_MEM,__FILE__,sizeof(memmap));
53 memset(map, ZERO, sizeof(memmap));
57 map->direct = direct ;
58 map->bitsp = bitaddr ;
59 map->codesp = codemap ;
62 map->dbName = dbName ;
63 if (!(map->oFile = tmpfile())) {
64 werror(E_TMPFILE_FAILED);
67 addSetHead (&tmpfileSet,map->oFile);
72 /*-----------------------------------------------------------------*/
73 /* initMem - allocates and initializes all the segments */
74 /*-----------------------------------------------------------------*/
78 /* allocate all the segments */
79 /* xternal stack segment ;
86 xstack = allocMap (0, 1, 1, 0, 0, 0, options.xstack_loc, XSTACK_NAME,'A');
88 /* internal stack segment ;
95 istack = allocMap (0, 0, 0, 0, 0, 0,options.stack_loc, ISTACK_NAME,'B');
104 code = allocMap (0, 1, 0, 0, 0, 1, options.code_loc, CODE_NAME,'C');
106 /* Static segment (code for variables );
113 statsg = allocMap (0, 1, 0, 0, 0, 1,0, STATIC_NAME,'D');
115 /* Data segment - internal storage segment ;
122 data = allocMap (0, 0, 0, 1, 0, 0, options.data_loc, DATA_NAME,'E');
124 /* overlay segment - same as internal storage segment ;
131 overlay = allocMap (0, 0, 0, 1, 0, 0, options.data_loc, DATA_NAME,'E');
133 /* Xternal Data segment -
140 xdata = allocMap (0, 1, 0, 0, 0, 0, options.xdata_loc, XDATA_NAME,'F' );
142 /* Inderectly addressed internal data segment
149 idata = allocMap (0, 0, 0, 0, 0, 0, options.idata_loc,IDATA_NAME,'G' );
151 /* Static segment (code for variables );
158 bit = allocMap (0, 0, 0, 1, 1, 0,0, BIT_NAME,'H');
160 /* Special function register space :-
167 sfr = allocMap (1,0, 0, 1, 0, 0,0, REG_NAME,'I');
176 reg = allocMap (1,0, 0, 0, 0, 0, 0,REG_NAME,' ');
185 sfrbit = allocMap (1,0, 0, 1, 1, 0,0, REG_NAME,'J' );
187 /* the unknown map */
188 generic = allocMap (1,0, 0, 1, 1, 0,0, REG_NAME,' ' );
192 /*-----------------------------------------------------------------*/
193 /* allocIntoSeg - puts a symbol into a memory segment */
194 /*-----------------------------------------------------------------*/
195 void allocIntoSeg (symbol *sym)
197 memmap *segment = SPEC_OCLS(sym->etype);
199 addSet (&segment->syms,sym);
202 /*-----------------------------------------------------------------*/
203 /* allocGlobal - aassigns the output segment to a global var */
204 /*-----------------------------------------------------------------*/
205 void allocGlobal ( symbol *sym )
207 /* symbol name is internal name */
208 sprintf (sym->rname,"_%s",sym->name);
210 /* add it to the operandKey reset */
211 addSet(&operKeyReset,sym);
213 /* if this is a literal e.g. enumerated type */
214 /* put it in the data segment & do nothing */
215 if (IS_LITERAL(sym->etype)) {
216 SPEC_OCLS(sym->etype) = data ;
220 /* if this is a function then assign code space */
221 if (IS_FUNC(sym->type)) {
222 SPEC_OCLS(sym->etype) = code ;
223 /* if this is an interrupt service routine
224 then put it in the interrupt service array */
225 if (IS_ISR(sym->etype)) {
227 if (interrupts[SPEC_INTN(sym->etype)])
228 werror(E_INT_DEFINED,
229 SPEC_INTN(sym->etype),
230 interrupts[SPEC_INTN(sym->etype)]->name);
232 interrupts[SPEC_INTN(sym->etype)] = sym;
234 /* automagically extend the maximum interrupts */
235 if (SPEC_INTN(sym->etype) >= maxInterrupts )
236 maxInterrupts = SPEC_INTN(sym->etype) + 1;
238 /* if it is not compiler defined */
245 /* if this is a SFR or SBIT */
246 if ( SPEC_SCLS(sym->etype) == S_SFR ||
247 SPEC_SCLS(sym->etype) == S_SBIT ) {
249 /* if both absolute address & initial */
250 /* value specified then error */
251 if ( IS_ABSOLUTE (sym->etype) && sym->ival ) {
252 werror(E_SFR_INIT,sym->name);
256 SPEC_OCLS(sym->etype) =
257 (SPEC_SCLS(sym->etype) == S_SFR ? sfr : sfrbit);
263 /* if this is a bit variable and no storage class */
264 if ( SPEC_NOUN(sym->etype) == V_BIT
265 && SPEC_SCLS(sym->etype) == S_BIT ) {
266 SPEC_OCLS(sym->etype) = bit ;
271 /* if bit storage class */
272 if ( SPEC_SCLS(sym->etype) == S_SBIT ) {
273 SPEC_OCLS(sym->etype) = bit;
278 /* register storage class ignored changed to FIXED */
279 if ( SPEC_SCLS(sym->etype) == S_REGISTER )
280 SPEC_SCLS(sym->etype) = S_FIXED ;
282 /* if data specified then */
283 if (SPEC_SCLS(sym->etype) == S_DATA) {
284 /* set the output class */
285 SPEC_OCLS(sym->etype) = data ;
286 /* generate the symbol */
291 /* if it is fixed, then allocate depending on the */
292 /* current memory model,same for automatics */
293 if ( SPEC_SCLS(sym->etype) == S_FIXED ||
294 SPEC_SCLS(sym->etype) == S_AUTO ) {
295 /* set the output class */
296 SPEC_OCLS(sym->etype) = ( options.model ? xdata : data ) ;
297 /* generate the symbol */
302 /* if code change to constant */
303 if ( SPEC_SCLS(sym->etype) == S_CODE ||
304 SPEC_SCLS(sym->etype) == S_CONSTANT ) {
305 SPEC_OCLS(sym->etype) = statsg ;
310 if ( SPEC_SCLS(sym->etype) == S_XDATA ) {
311 SPEC_OCLS(sym->etype) = xdata ;
316 if ( SPEC_SCLS(sym->etype) == S_IDATA ) {
317 SPEC_OCLS(sym->etype) = idata ;
326 /*-----------------------------------------------------------------*/
327 /* allocParms - parameters are always passed on stack */
328 /*-----------------------------------------------------------------*/
329 void allocParms ( value *val )
334 for ( lval = val ; lval ; lval = lval->next, pNum++ ) {
336 /* if this is a literal e.g. enumerated type */
337 if (IS_LITERAL(lval->etype)) {
338 SPEC_OCLS(lval->etype) = SPEC_OCLS(lval->sym->etype) =
339 ( options.model ? xdata : data );
342 /* if this a register parm then allocate
343 it as a local variable by adding it
344 to the first block we see in the body */
345 if (IS_REGPARM(lval->etype))
348 /* check the declaration */
349 checkDecl (lval->sym);
351 /* mark it as my parameter */
352 lval->sym->ismyparm = 1;
353 lval->sym->localof = currFunc;
356 /* if automatic variables r 2b stacked */
357 if ( options.stackAuto || IS_RENT(currFunc->etype)) {
360 lval->sym->onStack = 1;
362 /* choose which stack 2 use */
363 /* use xternal stack */
364 if ( options.useXstack ) {
365 /* PENDING: stack direction support */
366 SPEC_OCLS(lval->etype) = SPEC_OCLS(lval->sym->etype) = xstack ;
367 SPEC_STAK(lval->etype) = SPEC_STAK(lval->sym->etype) = lval->sym->stack =
368 xstackPtr - getSize(lval->type);
369 xstackPtr -= getSize (lval->type);
371 else { /* use internal stack */
372 SPEC_OCLS(lval->etype) = SPEC_OCLS(lval->sym->etype) = istack ;
373 if (port->stack.direction > 0) {
374 SPEC_STAK(lval->etype) = SPEC_STAK(lval->sym->etype) = lval->sym->stack =
375 stackPtr - ( SPEC_BANK(currFunc->etype) ? port->stack.bank_overhead : 0) -
376 getSize(lval->type) -
377 (IS_ISR(currFunc->etype) ? port->stack.isr_overhead : 0);
378 stackPtr -= getSize (lval->type);
381 /* This looks like the wrong order but it turns out OK... */
382 /* PENDING: isr, bank overhead, ... */
383 SPEC_STAK(lval->etype) = SPEC_STAK(lval->sym->etype) = lval->sym->stack = stackPtr;
384 stackPtr += getSize (lval->type);
387 allocIntoSeg(lval->sym);
389 else { /* allocate them in the automatic space */
390 /* generate a unique name */
391 sprintf (lval->sym->rname,"_%s_PARM_%d",currFunc->name,pNum);
392 strcpy (lval->name,lval->sym->rname);
394 /* if declared in external storage */
395 if (SPEC_SCLS(lval->etype) == S_XDATA)
396 SPEC_OCLS(lval->etype) = SPEC_OCLS(lval->sym->etype) = xdata;
398 /* other wise depending on the memory model
399 note here that we put it into the overlay segment
400 first, we will remove it from the overlay segment
401 after the overlay determination has been done */
402 SPEC_OCLS(lval->etype) = SPEC_OCLS(lval->sym->etype) =
403 ( options.model ? xdata : (options.noOverlay ? data :overlay ));
405 allocIntoSeg(lval->sym);
412 /*-----------------------------------------------------------------*/
413 /* deallocParms - parameters are always passed on stack */
414 /*-----------------------------------------------------------------*/
415 void deallocParms ( value *val )
419 for ( lval = val ; lval ; lval = lval->next ) {
421 /* unmark is myparm */
422 lval->sym->ismyparm = 0;
423 /* if on stack then depending on which stack */
425 /* delete it from the symbol table */
426 deleteSym (SymbolTab,lval->sym,lval->sym->name);
428 if (!lval->sym->isref) {
429 lval->sym->allocreq = 1;
430 werror(W_NO_REFERENCE,currFunc->name,
431 "function argument",lval->sym->name);
434 /* move the rname if any to the name for both val & sym */
435 /* and leave a copy of it in the symbol table */
436 if (lval->sym->rname[0]) {
437 char buffer[SDCC_NAME_MAX];
438 strcpy(buffer,lval->sym->rname);
439 lval->sym = copySymbol(lval->sym);
440 strcpy(lval->sym->rname,buffer);
441 strcpy(lval->name,strcpy(lval->sym->name,lval->sym->rname));
442 addSym (SymbolTab, lval->sym, lval->sym->name,
443 lval->sym->level,lval->sym->block);
444 lval->sym->_isparm = 1;
445 addSet(&operKeyReset,lval->sym);
453 /*-----------------------------------------------------------------*/
454 /* allocLocal - allocate local variables */
455 /*-----------------------------------------------------------------*/
456 void allocLocal ( symbol *sym )
459 /* generate an unique name */
460 sprintf(sym->rname,"_%s_%s_%d_%d",
461 currFunc->name,sym->name,sym->level,sym->block);
464 sym->localof = currFunc;
466 /* if this is a static variable */
467 if ( IS_STATIC (sym->etype)) {
468 SPEC_OCLS(sym->etype) = (options.model ? xdata : data );
474 /* if volatile then */
475 if (IS_VOLATILE(sym->etype))
478 /* this is automatic */
480 /* if it to be placed on the stack */
481 if ( options.stackAuto || reentrant) {
484 if ( options.useXstack ) {
485 /* PENDING: stack direction for xstack */
486 SPEC_OCLS(sym->etype) = xstack ;
487 SPEC_STAK(sym->etype) = sym->stack = (xstackPtr + 1);
488 xstackPtr += getSize (sym->type) ;
491 SPEC_OCLS(sym->etype) = istack ;
492 if (port->stack.direction > 0) {
493 SPEC_STAK(sym->etype) = sym->stack = ( stackPtr + 1);
494 stackPtr += getSize (sym->type) ;
497 stackPtr -= getSize (sym->type);
498 SPEC_STAK(sym->etype) = sym->stack = stackPtr;
505 /* else depending on the storage class specified */
506 if ( SPEC_SCLS(sym->etype) == S_XDATA ) {
507 SPEC_OCLS(sym->etype) = xdata ;
512 if ( (SPEC_SCLS(sym->etype) == S_CODE ||
513 SPEC_SCLS(sym->etype) == S_CONSTANT) &&
515 SPEC_OCLS(sym->etype) = statsg ;
520 if ( SPEC_SCLS(sym->etype) == S_IDATA ) {
521 SPEC_OCLS(sym->etype) = idata ;
527 /* if this is a function then assign code space */
528 if (IS_FUNC(sym->type)) {
529 SPEC_OCLS(sym->etype) = code ;
533 /* if this is a SFR or SBIT */
534 if ( SPEC_SCLS(sym->etype) == S_SFR ||
535 SPEC_SCLS(sym->etype) == S_SBIT ) {
537 /* if both absolute address & initial */
538 /* value specified then error */
539 if ( IS_ABSOLUTE (sym->etype) && sym->ival ) {
540 werror(E_SFR_INIT,sym->name);
544 SPEC_OCLS(sym->etype) =
545 (SPEC_SCLS(sym->etype) == S_SFR ? sfr : sfrbit);
551 /* if this is a bit variable and no storage class */
552 if ( SPEC_NOUN(sym->etype) == V_BIT
553 && (SPEC_SCLS(sym->etype) == S_BIT)) {
554 SPEC_OCLS(sym->etype) = bit ;
559 /* again note that we have put it into the overlay segment
560 will remove and put into the 'data' segment if required after
561 overlay analysis has been done */
562 SPEC_OCLS(sym->etype) = ( options.model ? xdata :
563 (options.noOverlay ? data : overlay )) ;
567 /*-----------------------------------------------------------------*/
568 /* deallocLocal - deallocates the local variables */
569 /*-----------------------------------------------------------------*/
570 void deallocLocal ( symbol *csym )
574 for ( sym = csym ; sym ; sym = sym->next) {
578 /* if it is on the stack */
580 if (options.useXstack)
581 xstackPtr -= getSize(sym->type);
583 stackPtr -= getSize(sym->type);
585 /* if not used give a warning */
586 if (!sym->isref && !IS_STATIC(sym->etype))
587 werror(W_NO_REFERENCE,currFunc->name,
588 "local variable",sym->name);
589 /* now delete it from the symbol table */
590 deleteSym (SymbolTab,sym,sym->name);
594 /*-----------------------------------------------------------------*/
595 /* overlay2data - moves declarations from the overlay seg to data */
596 /*-----------------------------------------------------------------*/
601 for (sym = setFirstItem(overlay->syms); sym;
602 sym = setNextItem(overlay->syms)) {
604 SPEC_OCLS(sym->etype) = data;
608 setToNull((void **) &overlay->syms);
612 /*-----------------------------------------------------------------*/
613 /* overlay2Set - will add all symbols from the overlay segment to */
614 /* the set of sets containing the overlable symbols */
615 /*-----------------------------------------------------------------*/
621 for (sym = setFirstItem(overlay->syms); sym;
622 sym = setNextItem(overlay->syms)) {
627 setToNull((void **) &overlay->syms);
628 addSet (&ovrSetSets,oset);
632 /*-----------------------------------------------------------------*/
633 /* allocVariables - creates decl & assign storage class for a v */
634 /*-----------------------------------------------------------------*/
635 int allocVariables ( symbol *symChain )
642 /* go thru the symbol chain */
643 for ( sym = symChain ; sym ; sym = sym->next ) {
645 /* if this is a typedef then add it */
646 /* to the typedef table */
647 if (IS_TYPEDEF(sym->etype)) {
648 /* check if the typedef already exists */
649 csym = findSym (TypedefTab, NULL, sym->name );
650 if ( csym && csym->level == sym->level )
651 werror(E_DUPLICATE_TYPEDEF,sym->name);
653 addSym (TypedefTab, sym , sym->name,sym->level,sym->block);
654 continue ; /* go to the next one */
656 /* make sure it already exist */
657 csym = findSymWithLevel (SymbolTab, sym);
658 if (! csym || (csym && csym->level != sym->level) )
661 /* check the declaration */
664 /* if this is a function or a pointer to function */
665 /* then args processing */
666 if (funcInChain(csym->type)) {
668 processFuncArgs (csym, 1);
669 /* if register bank specified then update maxRegBank */
670 if (maxRegBank < SPEC_BANK(csym->etype))
671 maxRegBank = SPEC_BANK(csym->etype);
674 /* if this is a extern variable then change the */
675 /* level to zero temporarily */
676 if (IS_EXTERN(csym->etype) || IS_FUNC(csym->type) ) {
677 saveLevel = csym->level ;
681 /* if this is a literal then it is an enumerated */
682 /* type so need not allocate it space for it */
683 if (IS_LITERAL(sym->etype))
686 /* generate the actual declaration */
690 stack += getSize(csym->type) ;
695 /* restore the level */
696 if (IS_EXTERN(csym->etype) || IS_FUNC(csym->type))
697 csym->level = saveLevel;
703 /*-----------------------------------------------------------------*/
704 /* redoStackOffsets :- will reassign the values for stack offsets */
705 /*-----------------------------------------------------------------*/
706 void redoStackOffsets ()
712 /* after register allocation is complete we know
713 which variables will need to be assigned space
714 on the stack. We will eliminate those variables
715 which do not have the allocReq flag thus reducing
717 for ( sym = setFirstItem(istack->syms); sym;
718 sym = setNextItem(istack->syms)) {
720 int size = getSize(sym->type);
721 /* nothing to do with parameters so continue */
722 if ((sym->_isparm && !IS_REGPARM(sym->etype)))
725 if ( IS_AGGREGATE(sym->type)) {
726 if (port->stack.direction > 0) {
727 SPEC_STAK(sym->etype) = sym->stack = ( sPtr + 1);
732 SPEC_STAK(sym->etype) = sym->stack = sPtr;
737 /* if allocation not required then subtract
738 size from overall stack size & continue */
739 if (!sym->allocreq) {
740 currFunc->stack -= size;
741 SPEC_STAK(currFunc->etype) -= size;
745 if (port->stack.direction > 0) {
746 SPEC_STAK(sym->etype) = sym->stack = ( sPtr + 1);
751 SPEC_STAK(sym->etype) = sym->stack = sPtr;
755 /* do the same for the external stack */
757 for ( sym = setFirstItem(xstack->syms); sym;
758 sym = setNextItem(xstack->syms)) {
760 int size = getSize(sym->type);
761 /* nothing to do with parameters so continue */
762 if ((sym->_isparm && !IS_REGPARM(sym->etype)))
765 if (IS_AGGREGATE(sym->type)) {
766 SPEC_STAK(sym->etype) = sym->stack = ( xsPtr + 1);
771 /* if allocation not required then subtract
772 size from overall stack size & continue */
773 if (!sym->allocreq) {
774 currFunc->xstack -= size;
775 SPEC_STAK(currFunc->etype) -= size;
779 SPEC_STAK(sym->etype) = sym->stack = ( xsPtr + 1);
783 /* if the debug option is set then output the
784 symbols to the map file */
786 for (sym = setFirstItem(istack->syms); sym;
787 sym = setNextItem(istack->syms))
788 cdbSymbol(sym,cdbFile,FALSE,FALSE);
790 for (sym = setFirstItem(xstack->syms); sym;
791 sym = setNextItem(xstack->syms))
792 cdbSymbol(sym,cdbFile,FALSE,FALSE);