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 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 SPEC_OCLS(lval->etype) = SPEC_OCLS(lval->sym->etype) = xstack ;
366 SPEC_STAK(lval->etype) = SPEC_STAK(lval->sym->etype) = lval->sym->stack =
367 xstackPtr - getSize(lval->type);
368 xstackPtr -= getSize (lval->type);
370 else { /* use internal stack */
371 SPEC_OCLS(lval->etype) = SPEC_OCLS(lval->sym->etype) = istack ;
372 SPEC_STAK(lval->etype) = SPEC_STAK(lval->sym->etype) = lval->sym->stack =
373 stackPtr - ( SPEC_BANK(currFunc->etype) ? 1 : 0) -
374 getSize(lval->type) -
375 (IS_ISR(currFunc->etype) ? 4 : 0);
376 stackPtr -= getSize (lval->type);
378 allocIntoSeg(lval->sym);
380 else { /* allocate them in the automatic space */
381 /* generate a unique name */
382 sprintf (lval->sym->rname,"_%s_PARM_%d",currFunc->name,pNum);
383 strcpy (lval->name,lval->sym->rname);
385 /* if declared in external storage */
386 if (SPEC_SCLS(lval->etype) == S_XDATA)
387 SPEC_OCLS(lval->etype) = SPEC_OCLS(lval->sym->etype) = xdata;
389 /* other wise depending on the memory model
390 note here that we put it into the overlay segment
391 first, we will remove it from the overlay segment
392 after the overlay determination has been done */
393 SPEC_OCLS(lval->etype) = SPEC_OCLS(lval->sym->etype) =
394 ( options.model ? xdata : (options.noOverlay ? data :overlay ));
396 allocIntoSeg(lval->sym);
403 /*-----------------------------------------------------------------*/
404 /* deallocParms - parameters are always passed on stack */
405 /*-----------------------------------------------------------------*/
406 void deallocParms ( value *val )
410 for ( lval = val ; lval ; lval = lval->next ) {
412 /* unmark is myparm */
413 lval->sym->ismyparm = 0;
414 /* if on stack then depending on which stack */
416 /* delete it from the symbol table */
417 deleteSym (SymbolTab,lval->sym,lval->sym->name);
419 if (!lval->sym->isref) {
420 lval->sym->allocreq = 1;
421 werror(W_NO_REFERENCE,currFunc->name,
422 "function argument",lval->sym->name);
425 /* move the rname if any to the name for both val & sym */
426 /* and leave a copy of it in the symbol table */
427 if (lval->sym->rname[0]) {
428 char buffer[SDCC_NAME_MAX];
429 strcpy(buffer,lval->sym->rname);
430 lval->sym = copySymbol(lval->sym);
431 strcpy(lval->sym->rname,buffer);
432 strcpy(lval->name,strcpy(lval->sym->name,lval->sym->rname));
433 addSym (SymbolTab, lval->sym, lval->sym->name,
434 lval->sym->level,lval->sym->block);
435 lval->sym->_isparm = 1;
436 addSet(&operKeyReset,lval->sym);
444 /*-----------------------------------------------------------------*/
445 /* allocLocal - allocate local variables */
446 /*-----------------------------------------------------------------*/
447 void allocLocal ( symbol *sym )
450 /* generate an unique name */
451 sprintf(sym->rname,"_%s_%s_%d_%d",
452 currFunc->name,sym->name,sym->level,sym->block);
455 sym->localof = currFunc;
457 /* if this is a static variable */
458 if ( IS_STATIC (sym->etype)) {
459 SPEC_OCLS(sym->etype) = (options.model ? xdata : data );
465 /* if volatile then */
466 if (IS_VOLATILE(sym->etype))
469 /* this is automatic */
471 /* if it to be placed on the stack */
472 if ( options.stackAuto || reentrant) {
475 if ( options.useXstack ) {
476 SPEC_OCLS(sym->etype) = xstack ;
477 SPEC_STAK(sym->etype) = sym->stack = (xstackPtr + 1);
478 xstackPtr += getSize (sym->type) ;
481 SPEC_OCLS(sym->etype) = istack ;
482 SPEC_STAK(sym->etype) = sym->stack = ( stackPtr + 1);
483 stackPtr += getSize (sym->type) ;
489 /* else depending on the storage class specified */
490 if ( SPEC_SCLS(sym->etype) == S_XDATA ) {
491 SPEC_OCLS(sym->etype) = xdata ;
496 if ( (SPEC_SCLS(sym->etype) == S_CODE ||
497 SPEC_SCLS(sym->etype) == S_CONSTANT) &&
499 SPEC_OCLS(sym->etype) = statsg ;
504 if ( SPEC_SCLS(sym->etype) == S_IDATA ) {
505 SPEC_OCLS(sym->etype) = idata ;
511 /* if this is a function then assign code space */
512 if (IS_FUNC(sym->type)) {
513 SPEC_OCLS(sym->etype) = code ;
517 /* if this is a SFR or SBIT */
518 if ( SPEC_SCLS(sym->etype) == S_SFR ||
519 SPEC_SCLS(sym->etype) == S_SBIT ) {
521 /* if both absolute address & initial */
522 /* value specified then error */
523 if ( IS_ABSOLUTE (sym->etype) && sym->ival ) {
524 werror(E_SFR_INIT,sym->name);
528 SPEC_OCLS(sym->etype) =
529 (SPEC_SCLS(sym->etype) == S_SFR ? sfr : sfrbit);
535 /* if this is a bit variable and no storage class */
536 if ( SPEC_NOUN(sym->etype) == V_BIT
537 && (SPEC_SCLS(sym->etype) == S_BIT)) {
538 SPEC_OCLS(sym->etype) = bit ;
543 /* again note that we have put it into the overlay segment
544 will remove and put into the 'data' segment if required after
545 overlay analysis has been done */
546 SPEC_OCLS(sym->etype) = ( options.model ? xdata :
547 (options.noOverlay ? data : overlay )) ;
551 /*-----------------------------------------------------------------*/
552 /* deallocLocal - deallocates the local variables */
553 /*-----------------------------------------------------------------*/
554 void deallocLocal ( symbol *csym )
558 for ( sym = csym ; sym ; sym = sym->next) {
562 /* if it is on the stack */
564 if (options.useXstack)
565 xstackPtr -= getSize(sym->type);
567 stackPtr -= getSize(sym->type);
569 /* if not used give a warning */
570 if (!sym->isref && !IS_STATIC(sym->etype))
571 werror(W_NO_REFERENCE,currFunc->name,
572 "local variable",sym->name);
573 /* now delete it from the symbol table */
574 deleteSym (SymbolTab,sym,sym->name);
578 /*-----------------------------------------------------------------*/
579 /* overlay2data - moves declarations from the overlay seg to data */
580 /*-----------------------------------------------------------------*/
585 for (sym = setFirstItem(overlay->syms); sym;
586 sym = setNextItem(overlay->syms)) {
588 SPEC_OCLS(sym->etype) = data;
592 setToNull((void **) &overlay->syms);
596 /*-----------------------------------------------------------------*/
597 /* overlay2Set - will add all symbols from the overlay segment to */
598 /* the set of sets containing the overlable symbols */
599 /*-----------------------------------------------------------------*/
605 for (sym = setFirstItem(overlay->syms); sym;
606 sym = setNextItem(overlay->syms)) {
611 setToNull((void **) &overlay->syms);
612 addSet (&ovrSetSets,oset);
616 /*-----------------------------------------------------------------*/
617 /* allocVariables - creates decl & assign storage class for a v */
618 /*-----------------------------------------------------------------*/
619 int allocVariables ( symbol *symChain )
626 /* go thru the symbol chain */
627 for ( sym = symChain ; sym ; sym = sym->next ) {
629 /* if this is a typedef then add it */
630 /* to the typedef table */
631 if (IS_TYPEDEF(sym->etype)) {
632 /* check if the typedef already exists */
633 csym = findSym (TypedefTab, NULL, sym->name );
634 if ( csym && csym->level == sym->level )
635 werror(E_DUPLICATE_TYPEDEF,sym->name);
637 addSym (TypedefTab, sym , sym->name,sym->level,sym->block);
638 continue ; /* go to the next one */
640 /* make sure it already exist */
641 csym = findSymWithLevel (SymbolTab, sym);
642 if (! csym || (csym && csym->level != sym->level) )
645 /* check the declaration */
648 /* if this is a function or a pointer to function */
649 /* then args processing */
650 if (funcInChain(csym->type)) {
652 processFuncArgs (csym, 1);
653 /* if register bank specified then update maxRegBank */
654 if (maxRegBank < SPEC_BANK(csym->etype))
655 maxRegBank = SPEC_BANK(csym->etype);
658 /* if this is a extern variable then change the */
659 /* level to zero temporarily */
660 if (IS_EXTERN(csym->etype) || IS_FUNC(csym->type) ) {
661 saveLevel = csym->level ;
665 /* if this is a literal then it is an enumerated */
666 /* type so need not allocate it space for it */
667 if (IS_LITERAL(sym->etype))
670 /* generate the actual declaration */
674 stack += getSize(csym->type) ;
679 /* restore the level */
680 if (IS_EXTERN(csym->etype) || IS_FUNC(csym->type))
681 csym->level = saveLevel;
687 /*-----------------------------------------------------------------*/
688 /* redoStackOffsets :- will reassign the values for stack offsets */
689 /*-----------------------------------------------------------------*/
690 void redoStackOffsets ()
696 /* after register allocation is complete we know
697 which variables will need to be assigned space
698 on the stack. We will eliminate those variables
699 which do not have the allocReq flag thus reducing
701 for ( sym = setFirstItem(istack->syms); sym;
702 sym = setNextItem(istack->syms)) {
704 int size = getSize(sym->type);
705 /* nothing to do with parameters so continue */
706 if ((sym->_isparm && !IS_REGPARM(sym->etype)))
709 if ( IS_AGGREGATE(sym->type)) {
710 SPEC_STAK(sym->etype) = sym->stack = ( sPtr + 1);
715 /* if allocation not required then subtract
716 size from overall stack size & continue */
717 if (!sym->allocreq) {
718 currFunc->stack -= size;
719 SPEC_STAK(currFunc->etype) -= size;
723 SPEC_STAK(sym->etype) = sym->stack = ( sPtr + 1);
727 /* do the same for the external stack */
729 for ( sym = setFirstItem(xstack->syms); sym;
730 sym = setNextItem(xstack->syms)) {
732 int size = getSize(sym->type);
733 /* nothing to do with parameters so continue */
734 if ((sym->_isparm && !IS_REGPARM(sym->etype)))
737 if (IS_AGGREGATE(sym->type)) {
738 SPEC_STAK(sym->etype) = sym->stack = ( xsPtr + 1);
743 /* if allocation not required then subtract
744 size from overall stack size & continue */
745 if (!sym->allocreq) {
746 currFunc->xstack -= size;
747 SPEC_STAK(currFunc->etype) -= size;
751 SPEC_STAK(sym->etype) = sym->stack = ( xsPtr + 1);
755 /* if the debug option is set then output the
756 symbols to the map file */
758 for (sym = setFirstItem(istack->syms); sym;
759 sym = setNextItem(istack->syms))
760 cdbSymbol(sym,cdbFile,FALSE,FALSE);
762 for (sym = setFirstItem(xstack->syms); sym;
763 sym = setNextItem(xstack->syms))
764 cdbSymbol(sym,cdbFile,FALSE,FALSE);