From 15c7b11c3403b08930035ac68c86d404c45f1bd2 Mon Sep 17 00:00:00 2001 From: sandeep Date: Sun, 19 Mar 2000 23:43:25 +0000 Subject: [PATCH] lots of progress in AVR git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@191 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- src/SDCC.lex | 4 + src/SDCCicode.c | 34 ++++--- src/avr/main.c | 12 ++- src/avr/ralloc.c | 253 +++++++++++++++++++++++++---------------------- src/avr/ralloc.h | 3 +- 5 files changed, 172 insertions(+), 134 deletions(-) diff --git a/src/SDCC.lex b/src/SDCC.lex index 821cff05..134615e1 100644 --- a/src/SDCC.lex +++ b/src/SDCC.lex @@ -110,6 +110,7 @@ struct options save_options ; "far" { count(); TKEYWORD(XDATA); } "eeprom" { count(); TKEYWORD(EEPROM); } "float" { count(); return(FLOAT); } +"flash" { count(); TKEYWORD(CODE);} "for" { count(); return(FOR); } "goto" { count(); return(GOTO); } "idata" { count(); TKEYWORD(IDATA);} @@ -127,6 +128,7 @@ struct options save_options ; "short" { count(); return(SHORT); } "signed" { count(); return(SIGNED); } "sizeof" { count(); return(SIZEOF); } +"sram" { count(); TKEYWORD(XDATA);} "static" { count(); return(STATIC); } "struct" { count(); return(STRUCT); } "switch" { count(); return(SWITCH); } @@ -141,8 +143,10 @@ struct options save_options ; "_data" { count(); TKEYWORD(_NEAR); } "_code" { count(); TKEYWORD(_CODE); } "_eeprom" { count(); TKEYWORD(_EEPROM); } +"_flash" { count(); TKEYWORD(_CODE); } "_generic" { count(); TKEYWORD(_GENERIC); } "_near" { count(); TKEYWORD(_NEAR); } +"_sram" { count(); TKEYWORD(_XDATA);} "_xdata" { count(); TKEYWORD(_XDATA);} "_pdata" { count(); TKEYWORD(_PDATA); } "_idata" { count(); TKEYWORD(_IDATA); } diff --git a/src/SDCCicode.c b/src/SDCCicode.c index 1d1e48a8..93d84027 100644 --- a/src/SDCCicode.c +++ b/src/SDCCicode.c @@ -1060,7 +1060,7 @@ operand *operandFromSymbol (symbol *sym) { operand *op ; iCode *ic ; - + int ok =1 ; /* if the symbol's type is a literal */ /* then it is an enumerator type */ if (IS_LITERAL(sym->etype) && SPEC_ENUM(sym->etype)) @@ -1084,6 +1084,11 @@ operand *operandFromSymbol (symbol *sym) /* under the following conditions create a register equivalent for a local symbol */ + if (sym->level && sym->etype && SPEC_OCLS(sym->etype) && + IN_FARSPACE(SPEC_OCLS(sym->etype)) && + options.stackAuto == 0) + ok =0; + if (!IS_AGGREGATE(sym->type) && /* not an aggregate */ !IS_FUNC(sym->type) && /* not a function */ !sym->_isparm && /* not a parameter */ @@ -1093,7 +1098,7 @@ operand *operandFromSymbol (symbol *sym) !IS_VOLATILE(sym->etype) && /* not declared as volatile */ !IS_STATIC(sym->etype) && /* and not declared static */ !sym->islbl && /* not a label */ - !IN_FARSPACE(SPEC_OCLS(sym->etype)) && /* not in far space */ + ok && /* farspace check */ !IS_BITVAR(sym->etype) /* not a bit variable */ ) { @@ -1106,7 +1111,7 @@ operand *operandFromSymbol (symbol *sym) OP_SYMBOL(sym->reqv)->islocal = 1; SPIL_LOC(sym->reqv) = sym; } - + if (!IS_AGGREGATE(sym->type)) { op = newOperand(); op->type = SYMBOL; @@ -2411,16 +2416,19 @@ static void geniCodeReceive (value *args) /* we will use it after all optimizations and before liveRange calculation */ - if (!sym->addrtaken && - !IS_VOLATILE(sym->etype) && - !IN_FARSPACE(SPEC_OCLS(sym->etype))) { - opl = newiTempOperand(args->type,0); - sym->reqv = opl ; - sym->reqv->key = sym->key ; - OP_SYMBOL(sym->reqv)->key = sym->key; - OP_SYMBOL(sym->reqv)->isreqv = 1; - OP_SYMBOL(sym->reqv)->islocal= 0; - SPIL_LOC(sym->reqv) = sym; + if (!sym->addrtaken && !IS_VOLATILE(sym->etype)) { + + if(IN_FARSPACE(SPEC_OCLS(sym->etype)) && + options.stackAuto == 0) { + } else { + opl = newiTempOperand(args->type,0); + sym->reqv = opl ; + sym->reqv->key = sym->key ; + OP_SYMBOL(sym->reqv)->key = sym->key; + OP_SYMBOL(sym->reqv)->isreqv = 1; + OP_SYMBOL(sym->reqv)->islocal= 0; + SPIL_LOC(sym->reqv) = sym; + } } ic = newiCode(RECEIVE,NULL,NULL); diff --git a/src/avr/main.c b/src/avr/main.c index 89d45d50..eb7eb3c6 100644 --- a/src/avr/main.c +++ b/src/avr/main.c @@ -19,15 +19,19 @@ static char *_avr_keywords[] = { "at", "code", "critical", - "eeprom" + "eeprom", "interrupt", "sfr", "sbit", "xdata", "_code", - "_eeprom" + "_eeprom", "_generic", "_xdata", + "sram" , + "_sram", + "flash", + "_flash", NULL }; @@ -41,7 +45,7 @@ static void _avr_reset_regparm() static int _avr_regparm( link *l) { /* the first eight bytes will be passed in - registers r0-r7. but we won't split variables + registers r16-r23. but we won't split variables i.e. if not enough registers left to hold the parameter then the whole parameter along with rest of the parameters go onto the stack */ @@ -163,7 +167,7 @@ PORT avr_port = { NULL, }, { - +1, 1, 4, 1, 1 + -1, 1, 4, 1, 1 }, /* avr has an 8 bit mul */ { diff --git a/src/avr/ralloc.c b/src/avr/ralloc.c index 78192546..ba73c2c0 100644 --- a/src/avr/ralloc.c +++ b/src/avr/ralloc.c @@ -56,43 +56,43 @@ int avr_ptrRegReq; /* pointer register required */ /* AVR registers */ regs regsAVR[] = { - { REG_GPR ,R0_IDX , REG_GPR , "r0", "r0" , "" , 0, 1 }, - { REG_GPR ,R1_IDX , REG_GPR , "r1", "r1" , "" , 0, 1 }, - { REG_GPR ,R2_IDX , REG_GPR , "r2", "r2" , "" , 0, 1 }, - { REG_GPR ,R3_IDX , REG_GPR , "r3", "r3" , "" , 0, 1 }, - { REG_GPR ,R4_IDX , REG_GPR , "r4", "r4" , "" , 0, 1 }, - { REG_GPR ,R5_IDX , REG_GPR , "r5", "r5" , "" , 0, 1 }, - { REG_GPR ,R6_IDX , REG_GPR , "r6", "r6" , "" , 0, 1 }, - { REG_GPR ,R7_IDX , REG_GPR , "r7", "r7" , "" , 0, 1 }, - { REG_GPR ,R8_IDX , REG_GPR , "r8", "r8" , "" , 0, 1 }, - { REG_GPR ,R9_IDX , REG_GPR , "r9", "r9" , "" , 0, 1 }, - { REG_GPR ,R10_IDX, REG_GPR , "r10", "r10", "" , 0, 1 }, - { REG_GPR ,R11_IDX, REG_GPR , "r11", "r11", "" , 0, 1 }, - { REG_GPR ,R12_IDX, REG_GPR , "r12", "r12", "" , 0, 1 }, - { REG_GPR ,R13_IDX, REG_GPR , "r13", "r13", "" , 0, 1 }, - { REG_GPR ,R14_IDX, REG_GPR , "r14", "r14", "" , 0, 1 }, - { REG_GPR ,R15_IDX, REG_GPR , "r15", "r15", "" , 0, 1 }, - { REG_GPR ,R16_IDX, REG_GPR , "r16", "r16", "" , 0, 1 }, - { REG_GPR ,R17_IDX, REG_GPR , "r17", "r17", "" , 0, 1 }, - { REG_GPR ,R18_IDX, REG_GPR , "r18", "r18", "" , 0, 1 }, - { REG_GPR ,R19_IDX, REG_GPR , "r19", "r19", "" , 0, 1 }, - { REG_GPR ,R20_IDX, REG_GPR , "r20", "r20", "" , 0, 1 }, - { REG_GPR ,R21_IDX, REG_GPR , "r21", "r21", "" , 0, 1 }, - { REG_GPR ,R22_IDX, REG_GPR , "r22", "r22", "" , 0, 1 }, - { REG_GPR ,R23_IDX, REG_GPR , "r23", "r23", "" , 0, 1 }, - { REG_GPR ,R24_IDX, REG_GPR , "r24", "r24", "" , 0, 1 }, - { REG_GPR ,R25_IDX, REG_GPR , "r25", "r25", "" , 0, 0 }, /* special literal use */ - { REG_GPR ,R26_IDX, REG_GPR , "r26", "r26", "" , 0, 0 }, /* used as pointer reg */ - { REG_GPR ,R27_IDX, REG_GPR , "r27", "r27", "" , 0, 0 }, - { REG_GPR ,R28_IDX, REG_GPR , "r28", "r28", "" , 0, 0 }, - { REG_GPR ,R29_IDX, REG_GPR , "r29", "r29", "" , 0, 0 }, - { REG_GPR ,R30_IDX, REG_GPR , "r30", "r30", "" , 0, 0 }, - { REG_GPR ,R31_IDX, REG_GPR , "r31", "r31", "" , 0, 0 }, - { REG_PTR ,X_IDX , REG_PTR , "X" , "X" , "" , 0, 1 }, - { REG_PTR ,Z_IDX , REG_PTR , "Z" , "Z" , "" , 0, 1 }, + { REG_GPR ,R0_IDX , REG_GPR , "r0", "r0" , "" , 0, 0, 0 }, /* used as scratch */ + { REG_GPR ,R1_IDX , REG_GPR , "r1", "r1" , "" , 0, 0, 0 }, /* used as scratch */ + { REG_GPR ,R2_IDX , REG_GPR , "r2", "r2" , "" , 0, 1, 1 }, /* gpr */ + { REG_GPR ,R3_IDX , REG_GPR , "r3", "r3" , "" , 0, 1, 1 }, /* gpr */ + { REG_GPR ,R4_IDX , REG_GPR , "r4", "r4" , "" , 0, 1, 1 }, /* gpr */ + { REG_GPR ,R5_IDX , REG_GPR , "r5", "r5" , "" , 0, 1, 1 }, /* gpr */ + { REG_GPR ,R6_IDX , REG_GPR , "r6", "r6" , "" , 0, 1, 1 }, /* gpr */ + { REG_GPR ,R7_IDX , REG_GPR , "r7", "r7" , "" , 0, 1, 1 }, /* gpr */ + { REG_GPR ,R8_IDX , REG_GPR , "r8", "r8" , "" , 0, 1, 1 }, /* gpr */ + { REG_GPR ,R9_IDX , REG_GPR , "r9", "r9" , "" , 0, 1, 1 }, /* gpr */ + { REG_GPR ,R10_IDX, REG_GPR , "r10", "r10", "" , 0, 1, 1 }, /* gpr */ + { REG_GPR ,R11_IDX, REG_GPR , "r11", "r11", "" , 0, 1, 1 }, /* gpr */ + { REG_GPR ,R12_IDX, REG_GPR , "r12", "r12", "" , 0, 1, 1 }, /* gpr */ + { REG_GPR ,R13_IDX, REG_GPR , "r13", "r13", "" , 0, 1, 1 }, /* gpr */ + { REG_GPR ,R14_IDX, REG_GPR , "r14", "r14", "" , 0, 1, 1 }, /* gpr */ + { REG_GPR ,R15_IDX, REG_GPR , "r15", "r15", "" , 0, 1, 1 }, /* gpr */ + { REG_GPR ,R16_IDX, REG_GPR , "r16", "r16", "" , 0, 1, 0 }, /* parm/gpr */ + { REG_GPR ,R17_IDX, REG_GPR , "r17", "r17", "" , 0, 1, 0 }, /* parm/gpr */ + { REG_GPR ,R18_IDX, REG_GPR , "r18", "r18", "" , 0, 1, 0 }, /* parm/gpr */ + { REG_GPR ,R19_IDX, REG_GPR , "r19", "r19", "" , 0, 1, 0 }, /* parm/gpr */ + { REG_GPR ,R20_IDX, REG_GPR , "r20", "r20", "" , 0, 1, 0 }, /* parm/gpr */ + { REG_GPR ,R21_IDX, REG_GPR , "r21", "r21", "" , 0, 1, 0 }, /* parm/gpr */ + { REG_GPR ,R22_IDX, REG_GPR , "r22", "r22", "" , 0, 1, 0 }, /* parm/gpr */ + { REG_GPR ,R23_IDX, REG_GPR , "r23", "r23", "" , 0, 1, 0 }, /* parm/gpr */ + { REG_GPR ,R24_IDX, REG_GPR , "r24", "r24", "" , 0, 0, 0 }, /* scratch */ + { REG_GPR ,R25_IDX, REG_GPR , "r25", "r25", "" , 0, 0, 0 }, /* scratch */ + { REG_GPR ,R26_IDX, REG_GPR , "r26", "r26", "" , 0, 1, 1 }, /* used as pointer reg X */ + { REG_GPR ,R27_IDX, REG_GPR , "r27", "r27", "" , 0, 1, 1 }, /* used as pointer reg X */ + { REG_GPR ,R28_IDX, REG_GPR , "r28", "r28", "" , 0, 1, 0 }, /* stack frame Y */ + { REG_GPR ,R29_IDX, REG_GPR , "r29", "r29", "" , 0, 1, 0 }, /* stack frame Y */ + { REG_GPR ,R30_IDX, REG_GPR , "r30", "r30", "" , 0, 1, 1 }, /* used as pointer reg Z */ + { REG_GPR ,R31_IDX, REG_GPR , "r31", "r31", "" , 0, 1, 1 }, /* used as pointer reg Z */ + { REG_PTR ,X_IDX , REG_PTR , "X" , "X" , "" , 0, 1, 0 }, + { REG_PTR ,Z_IDX , REG_PTR , "Z" , "Z" , "" , 0, 1, 0 }, }; -int avr_nRegs = 25; -int avr_fReg = 8; /* first allocatable register */ +int avr_nRegs = 32; +int avr_fReg = 0; /* first allocatable register */ static void spillThis (symbol *); @@ -103,21 +103,6 @@ static regs *allocReg (short type) { int i; - /* if type is a pointer register then - look for X or Z */ - if (type == REG_PTR) { - /* two choices */ - if (regsAVR[X_IDX].isFree) { - regsAVR[X_IDX].isFree = 0; - return ®sAVR[X_IDX]; - } - if (regsAVR[Z_IDX].isFree ) { - regsAVR[Z_IDX].isFree = 0; - return ®sAVR[Z_IDX]; - } - return NULL; - } - for ( i = avr_fReg ; i < avr_nRegs ; i++ ) { /* if type is given as 0 then any @@ -1024,7 +1009,6 @@ static void serialRegAssign (eBBlock **ebbs, int count) bitVect *spillable; int willCS ; int j; - int ptrRegSet = 0; /* if it does not need or is spilt or is already assigned to registers @@ -1072,15 +1056,7 @@ static void serialRegAssign (eBBlock **ebbs, int count) } } - /* if we need ptr regs for the right side - then mark it */ - if (POINTER_GET(ic) && - getSize(OP_SYMBOL(IC_LEFT(ic))->type) <= 2) - { - avr_ptrRegReq++; - ptrRegSet = 1; - } - /* else we assign registers to it */ + /* we assign registers to it */ _G.regAssigned = bitVectSetBit(_G.regAssigned,sym->key); for (j = 0 ; j < sym->nRegs ;j++ ) { @@ -1105,12 +1081,7 @@ static void serialRegAssign (eBBlock **ebbs, int count) OP_SYMBOL(IC_RIGHT(ic))->nRegs && ic->op != '=') positionRegs(OP_SYMBOL(IC_RESULT(ic)), OP_SYMBOL(IC_RIGHT(ic)),ic->lineno); - - if (ptrRegSet) { - avr_ptrRegReq--; - ptrRegSet = 0; - } - + } } } @@ -1320,22 +1291,7 @@ static void regTypeNum () bitVectFirstBit(sym->defs))) && POINTER_GET(ic) && !IS_BITVAR(sym->etype)) { - - - /* if remat in data space */ -/* if (OP_SYMBOL(IC_LEFT(ic))->remat && */ -/* DCL_TYPE(aggrToPtr(sym->type,FALSE)) == POINTER) { */ - - /* create a psuedo symbol & force a spil */ -/* symbol *psym = newSymbol(rematStr(OP_SYMBOL(IC_LEFT(ic))),1); */ -/* psym->type = sym->type; */ -/* psym->etype = sym->etype; */ -/* strcpy(psym->rname,psym->name); */ -/* sym->isspilt = 1; */ -/* sym->usl.spillLoc = psym; */ -/* continue ; */ -/* } */ - + /* if in data space or idata space then try to allocate pointer register */ @@ -1352,10 +1308,12 @@ static void regTypeNum () } /* determine the type of register required */ - if (sym->nRegs == 1 && - IS_PTR(sym->type) && - sym->uptr) - sym->regType = REG_PTR ; + if (sym->nRegs == 2 && /* size is two */ + IS_PTR(sym->type) && /* is a pointer */ + sym->uptr) { /* has has pointer usage i.e. get/set pointer */ + sym->regType = REG_PTR ; + avr_ptrRegReq++; + } else sym->regType = REG_GPR ; @@ -1368,17 +1326,6 @@ static void regTypeNum () } -/*-----------------------------------------------------------------*/ -/* freeAllRegs - mark all registers as free */ -/*-----------------------------------------------------------------*/ -static void freeAllRegs() -{ - int i; - - for (i=0;i< avr_nRegs;i++ ) - regsAVR[i].isFree = 1; -} - /*-----------------------------------------------------------------*/ /* deallocStackSpil - this will set the stack pointer back */ /*-----------------------------------------------------------------*/ @@ -1466,15 +1413,6 @@ static int packRegsForAssign (iCode *ic,eBBlock *ebp) return 0; } - /* if the true symbol is defined in far space or on stack - then we should not since this will increase register pressure */ - if (isOperandInFarSpace(IC_RESULT(ic))) { - if ((dic = farSpacePackable(ic))) - goto pack; - else - return 0; - - } /* find the definition of iTempNN scanning backwards if we find a a use of the true symbol in before we find the definition then we cannot */ @@ -2229,6 +2167,92 @@ static void packRegisters (eBBlock *ebp) } } + +/*-----------------------------------------------------------------*/ +/* preAssignParms - we have a leaf function preassign registers */ +/*-----------------------------------------------------------------*/ +static void preAssignParms (iCode *ic) +{ + int i = R16_IDX; + /* look for receives and assign registers + to the result of the receives */ + while (ic) { + /* if it is a receive */ + if (ic->op == RECEIVE) { + symbol *r = OP_SYMBOL(IC_RESULT(ic)); + int size = getSize(r->type); + if (r->regType == REG_GPR) { + int j = 0; + while (size--) { + r->regs[j++] = ®sAVR[i++]; + regsAVR[i-1].isFree = 0; + } + /* put in the regassigned vector */ + _G.regAssigned = bitVectSetBit(_G.regAssigned,r->key); + } else { + /* not a GPR then we should mark as free */ + while (size--) { + regsAVR[i++].isFree =1; + } + } + } + ic = ic->next; + } + /* mark anything remaining as free */ + while (i <= R23_IDX) + regsAVR[i++].isFree =1; +} + +/*-----------------------------------------------------------------*/ +/* setdefaultRegs - do setup stuff for register allocation */ +/*-----------------------------------------------------------------*/ +static void setDefaultRegs(eBBlock **ebbs,int count) +{ + + /* if no pointer registers required in this function + then mark r26-27 & r30-r31 as GPR & free */ + if (!avr_ptrRegReq) { + regsAVR[R26_IDX].isFree = + regsAVR[R27_IDX].isFree = + regsAVR[R30_IDX].isFree = + regsAVR[R31_IDX].isFree = 1; + regsAVR[R26_IDX].type = + regsAVR[R27_IDX].type = + regsAVR[R30_IDX].type = + regsAVR[R31_IDX].type = REG_GPR ; + } else { + regsAVR[R26_IDX].isFree = + regsAVR[R27_IDX].isFree = + regsAVR[R30_IDX].isFree = + regsAVR[R31_IDX].isFree = 1; + regsAVR[R26_IDX].type = + regsAVR[R27_IDX].type = + regsAVR[R30_IDX].type = + regsAVR[R31_IDX].type = REG_PTR ; + } + + /* registers 0-1 / 24-25 used as scratch */ + regsAVR[R0_IDX].isFree = + regsAVR[R1_IDX].isFree = + regsAVR[R24_IDX].isFree = + regsAVR[R25_IDX].isFree = 0; + + /* if this has no function calls then we need + to do something special + a) pre-assign registers to parameters RECEIVE + b) mark the remaining parameter regs as free */ + if (!currFunc->hasFcall) { + preAssignParms(ebbs[0]->sch); + } else { + int i=0; + for (i= R16_IDX ; i <= R23_IDX ;i++) + regsAVR[i].isFree = 0; + } + + /* Y - is not allocated (it is the stack frame) */ + regsAVR[R28_IDX].isFree = + regsAVR[R28_IDX].isFree =0; +} /*-----------------------------------------------------------------*/ /* assignRegisters - assigns registers to each live range as need */ @@ -2240,13 +2264,8 @@ void avr_assignRegisters (eBBlock **ebbs, int count) setToNull((void *)&_G.funcrUsed); avr_ptrRegReq = _G.stackExtend = _G.dataExtend = 0; - - /* is a leaf function then we can allocate the - parameter registers as well */ - if (!currFunc->hasFcall) - avr_fReg =0; - else - avr_fReg = 8; + + /* setup other default register allocation */ /* change assignments this will remove some live ranges reducing some register pressure */ for (i = 0 ; i < count ;i++ ) @@ -2258,7 +2277,10 @@ void avr_assignRegisters (eBBlock **ebbs, int count) /* first determine for each live range the number of registers & the type of registers required for each */ regTypeNum (); - + + /* setup the default registers */ + setDefaultRegs(ebbs,count); + /* and serially allocate registers */ serialRegAssign(ebbs,count); @@ -2297,7 +2319,6 @@ void avr_assignRegisters (eBBlock **ebbs, int count) setToNull((void **)&_G.stackSpil); setToNull((void **)&_G.spiltSet); /* mark all registers as free */ - freeAllRegs(); return ; } diff --git a/src/avr/ralloc.h b/src/avr/ralloc.h index f2d8367a..303c6b93 100644 --- a/src/avr/ralloc.h +++ b/src/avr/ralloc.h @@ -51,7 +51,8 @@ typedef struct regs char *dname; /* name when direct access needed */ char *base ; /* base address */ short offset; /* offset from the base */ - unsigned isFree :1; /* is currently unassigned */ + unsigned isFree :1; /* is currently unassigned */ + unsigned saveReq:1; /* save required @ function entry ? */ } regs; extern regs regsAVR[]; -- 2.30.2