From: sdattalo Date: Thu, 13 Jun 2002 13:57:18 +0000 (+0000) Subject: Improved the Register Banking algorithm. X-Git-Url: https://git.gag.com/?a=commitdiff_plain;h=2c02e0d7cccdf186aea6a2cda046afe06aa094a3;p=fw%2Fsdcc Improved the Register Banking algorithm. git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@2023 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- diff --git a/src/pic/device.c b/src/pic/device.c index 4e92fed4..bf465f38 100644 --- a/src/pic/device.c +++ b/src/pic/device.c @@ -120,6 +120,7 @@ static PIC_device Pics[] = { p16f627_mem, /* ram mem map */ p16f627_sfr, /* sfr mem map */ 0, /* max ram address (calculated) */ + 0x80, /* Bank Mask */ }, { @@ -127,6 +128,7 @@ static PIC_device Pics[] = { p16f627_mem, p16f627_sfr, 0, + 0x80, }, { @@ -134,6 +136,7 @@ static PIC_device Pics[] = { p16f84_mem, p16f84_sfr, 0, + 0x80, }, { @@ -141,6 +144,7 @@ static PIC_device Pics[] = { p16f877_mem, p16f877_sfr, 0, + 0x180, }, }; @@ -204,6 +208,36 @@ static void addMem(memRange *ranges,int type) } +/*-----------------------------------------------------------------* + *-----------------------------------------------------------------*/ + +int isREGinBank(regs *reg, int bank) +{ + + if(!reg || !pic) + return 0; + + if(((reg->address | reg->alias) & pic->bankMask & bank) == bank) + return 1; + + return 0; +} + +/*-----------------------------------------------------------------* + *-----------------------------------------------------------------*/ +int REGallBanks(regs *reg) +{ + + if(!reg || !pic) + return 0; + + return ((reg->address | reg->alias) & pic->bankMask); + +} + +/*-----------------------------------------------------------------* + *-----------------------------------------------------------------*/ + static void addMaps(PIC_device *pPic) { int i; diff --git a/src/pic/device.h b/src/pic/device.h index 2d2a0632..3c5c9e29 100644 --- a/src/pic/device.h +++ b/src/pic/device.h @@ -79,7 +79,8 @@ typedef struct PIC_device { memRange *ram; /* RAM memory map */ memRange *sfr; /* SFR memory map */ - int maxRAMaddress; /* maximum value for a data address */ + int maxRAMaddress; /* maximum value for a data address */ + int bankMask; /* Bitmask that is ANDed with address to extract banking bits */ // int hasAliasedRAM:1; /* True if there are bank independent registers */ } PIC_device; @@ -93,5 +94,7 @@ typedef struct PIC_device { /****************************************/ void assignConfigWordValue(int address, int value); int getConfigWord(int address); +int isREGinBank(regs *reg, int bank); +int REGallBanks(regs *reg); #endif /* __DEVICE_H__ */ diff --git a/src/pic/gen.c b/src/pic/gen.c index 975ead83..4ae2f23c 100644 --- a/src/pic/gen.c +++ b/src/pic/gen.c @@ -819,7 +819,7 @@ void aopOp (operand *op, iCode *ic, bool result) aop->size = getSize(sym->type); for ( i = 0 ; i < 2 ; i++ ) aop->aopu.aop_str[i] = accUse[i]; - DEBUGpic14_emitcode(";","%d",__LINE__); + DEBUGpic14_emitcode(";","%d size=%d",__LINE__,aop->size); return; } @@ -1312,9 +1312,10 @@ pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname) if(PCOR(pcop)->r == NULL) { //fprintf(stderr,"%d - couldn't find %s in allocated registers, size =%d\n",__LINE__,aop->aopu.aop_dir,aop->size); PCOR(pcop)->r = allocRegByName (aop->aopu.aop_dir,aop->size); - } - - DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset); + DEBUGpic14_emitcode(";","%d %s offset=%d - had to alloc by reg name",__LINE__,pcop->name,offset); + } else { + DEBUGpic14_emitcode(";","%d %s offset=%d",__LINE__,pcop->name,offset); + } PCOR(pcop)->instance = offset; return pcop; @@ -1326,6 +1327,9 @@ pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname) pcop = Safe_calloc(1,sizeof(pCodeOpReg) ); PCOR(pcop)->rIdx = rIdx; PCOR(pcop)->r = pic14_regWithIdx(rIdx); + PCOR(pcop)->r->wasUsed=1; + PCOR(pcop)->r->isFree=0; + PCOR(pcop)->instance = offset; pcop->type = PCOR(pcop)->r->pc_type; //rs = aop->aopu.aop_reg[offset]->name; @@ -1357,7 +1361,8 @@ pCodeOp *popGet (asmop *aop, int offset) //, bool bit16, bool dname) */ case AOP_PCODE: - DEBUGpic14_emitcode(";","popGet AOP_PCODE%d",__LINE__); + DEBUGpic14_emitcode(";","popGet AOP_PCODE %d %s",__LINE__, + ((aop->aopu.pcop->name)? (aop->aopu.pcop->name) : "no name")); pcop = pCodeOpCopy(aop->aopu.pcop); PCOI(pcop)->offset = offset; return pcop; diff --git a/src/pic/genarith.c b/src/pic/genarith.c index 2e701a04..8b4aa964 100644 --- a/src/pic/genarith.c +++ b/src/pic/genarith.c @@ -1500,6 +1500,7 @@ void genUMult8XLit_16 (operand *left, unsigned int lit; unsigned int i,have_first_bit; + int same; if (AOP_TYPE(right) != AOP_LIT){ fprintf(stderr,"%s %d - right operand is not a literal\n",__FILE__,__LINE__); @@ -1515,11 +1516,55 @@ void genUMult8XLit_16 (operand *left, lit &= 0xff; pic14_emitcode(";","Unrolled 8 X 8 multiplication"); + same = pic14_sameRegs(AOP(left), AOP(result)); + + if(same) { + switch(lit) { + case 0: + emitpcode(POC_CLRF, popGet(AOP(left),0)); + return; + case 2: + emitpcode(POC_MOVFW, popGet(AOP(left),0)); + emitpcode(POC_ADDWF, popGet(AOP(left),0)); + return; + case 3: + emitpcode(POC_MOVFW, popGet(AOP(left),0)); + emitpcode(POC_ADDWF, popGet(AOP(left),0)); + emitpcode(POC_ADDWF, popGet(AOP(left),0)); + return; + case 4: + emitpcode(POC_MOVFW, popGet(AOP(left),0)); + emitpcode(POC_ADDWF, popGet(AOP(left),0)); + emitpcode(POC_ADDWF, popGet(AOP(left),0)); + return; + case 16: + emitpcode(POC_SWAPFW, popGet(AOP(left),0)); + emitpcode(POC_ANDLW, popGetLit(0xf0)); + emitpcode(POC_MOVWF, popGet(AOP(left),0)); + return; + case 17: + emitpcode(POC_SWAPFW, popGet(AOP(left),0)); + emitpcode(POC_ANDLW, popGetLit(0xf0)); + emitpcode(POC_ADDWF, popGet(AOP(left),0)); + return; + + } + } else { + + switch(lit) { + case 0: + emitpcode(POC_CLRF, popGet(AOP(result),0)); + emitpcode(POC_CLRF, popCopyReg(result_hi)); + return; + case 2: + emitpcode(POC_MOVFW, popGet(AOP(left),0)); + emitpcode(POC_MOVWF, popGet(AOP(result),0)); + emitpcode(POC_ADDWF, popGet(AOP(result),0)); + emitpcode(POC_CLRF, popCopyReg(result_hi)); + emitpcode(POC_RLF, popCopyReg(result_hi)); + return; + } - if(!lit) { - emitpcode(POC_CLRF, popGet(AOP(result),0)); - emitpcode(POC_CLRF, popCopyReg(result_hi)); - return; } emitpcode(POC_MOVFW, popGet(AOP(left),0)); @@ -1563,6 +1608,11 @@ void genUMult8X8_16 (operand *left, result_hi = PCOR(popGet(AOP(result),1)); } + if (AOP_TYPE(right) == AOP_LIT) { + genUMult8XLit_16(left,right,result,result_hi); + return; + } + if(!looped) { pic14_emitcode(";","Unrolled 8 X 8 multiplication"); @@ -1601,16 +1651,19 @@ void genUMult8X8_16 (operand *left, } else { symbol *tlbl = newiTempLabel(NULL); - pCodeOp *temp = popGetTempReg(); + pCodeOp *temp; pic14_emitcode(";","Looped 8 X 8 multiplication"); emitpcode(POC_CLRF, popGet(AOP(result),0)); emitpcode(POC_CLRF, popCopyReg(result_hi)); + emitpcode(POC_BSF, newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),7,0)); emitpcode(POC_MOVFW, popGet(AOP(right),0)); + + temp = popGetTempReg(); emitpcode(POC_MOVWF, popCopyReg(PCOR(temp))); emitpcode(POC_MOVFW, popGet(AOP(left),0)); diff --git a/src/pic/pcode.c b/src/pic/pcode.c index f3d3f56f..1bdeb311 100644 --- a/src/pic/pcode.c +++ b/src/pic/pcode.c @@ -87,6 +87,8 @@ static int GpcFlowSeq = 1; #define isCALL(x) ((isPCI(x)) && (PCI(x)->op == POC_CALL)) #define isSTATUS_REG(r) ((r)->pc_type == PO_STATUS) +#define isPCOLAB(x) ((PCOP(x)->type) == PO_LABEL) + /****************************************************************/ /* Forward declarations */ /****************************************************************/ @@ -111,6 +113,8 @@ int pCodePeepMatchLine(pCodePeep *peepBlock, pCode *pcs, pCode *pcd); int pCodePeepMatchRule(pCode *pc); void pBlockStats(FILE *of, pBlock *pb); extern void pCodeInsertAfter(pCode *pc1, pCode *pc2); +extern pCodeOp *popCopyReg(pCodeOpReg *pc); +pCodeOp *popCopyGPR2Bit(pCodeOp *pc, int bitval); pCodeInstruction pciADDWF = { {PC_OPCODE, NULL, NULL, 0, NULL, @@ -1788,11 +1792,31 @@ pCode *newpCodeFlow(void ) pcflow->inCond = PCC_NONE; pcflow->outCond = PCC_NONE; + pcflow->firstBank = -1; + pcflow->lastBank = -1; + + pcflow->FromConflicts = 0; + pcflow->ToConflicts = 0; + pcflow->end = NULL; return ( (pCode *)pcflow); } +/*-----------------------------------------------------------------*/ +/*-----------------------------------------------------------------*/ +pCodeFlowLink *newpCodeFlowLink(pCodeFlow *pcflow) +{ + pCodeFlowLink *pcflowLink; + + pcflowLink = Safe_calloc(1,sizeof(pCodeFlowLink)); + + pcflowLink->pcflow = pcflow; + pcflowLink->bank_conflict = 0; + + return pcflowLink; +} + /*-----------------------------------------------------------------*/ /* newpCodeCSource - create a new pCode Source Symbol */ /*-----------------------------------------------------------------*/ @@ -2888,6 +2912,23 @@ int checkLabel(pCode *pc) return FALSE; } +/*-----------------------------------------------------------------*/ +/* findLabelinpBlock - Search the pCode for a particular label */ +/*-----------------------------------------------------------------*/ +pCode * findLabelinpBlock(pBlock *pb,pCodeOpLabel *pcop_label) +{ + pCode *pc; + + if(!pb) + return NULL; + + for(pc = pb->pcHead; pc; pc = pc->next) + if(compareLabel(pc,pcop_label)) + return pc; + + return NULL; +} + /*-----------------------------------------------------------------*/ /* findLabel - Search the pCode for a particular label */ /*-----------------------------------------------------------------*/ @@ -2900,10 +2941,8 @@ pCode * findLabel(pCodeOpLabel *pcop_label) return NULL; for(pb = the_pFile->pbHead; pb; pb = pb->next) { - for(pc = pb->pcHead; pc; pc = pc->next) - if(compareLabel(pc,pcop_label)) - return pc; - + if( (pc = findLabelinpBlock(pb,pcop_label)) != NULL) + return pc; } fprintf(stderr,"Couldn't find label %s", pcop_label->pcop.name); @@ -3180,12 +3219,16 @@ void BuildFlow(pBlock *pb) pb->pcHead = pflow; /* Make the Flow object the head */ pflow->pb = pb; - for( pc = findNextInstruction(pb->pcHead); - (pc=findNextInstruction(pc)) != NULL; ) { + for( pc = findNextInstruction(pb->pcHead); + pc != NULL; + pc=findNextInstruction(pc)) { pc->seq = seq++; PCI(pc)->pcflow = PCFL(pflow); + //fprintf(stderr," build: "); + //pflow->print(stderr,pflow); + if( PCI(pc)->isSkip) { /* The two instructions immediately following this one @@ -3324,6 +3367,74 @@ void FlowStats(pCodeFlow *pcflow) } +/*-----------------------------------------------------------------* + * int isBankInstruction(pCode *pc) - examine the pCode *pc to determine + * if it affects the banking bits. + * + * return: -1 == Banking bits are unaffected by this pCode. + * + * return: > 0 == Banking bits are affected. + * + * If the banking bits are affected, then the returned value describes + * which bits are affected and how they're affected. The lower half + * of the integer maps to the bits that are affected, the upper half + * to whether they're set or cleared. + * + *-----------------------------------------------------------------*/ +#define SET_BANK_BIT (1 << 16) +#define CLR_BANK_BIT 0 + +int isBankInstruction(pCode *pc) +{ + regs *reg; + int bank = -1; + + if(!isPCI(pc)) + return -1; + + if( ( (reg = getRegFromInstruction(pc)) != NULL) && isSTATUS_REG(reg)) { + + /* Check to see if the register banks are changing */ + if(PCI(pc)->isModReg) { + + pCodeOp *pcop = PCI(pc)->pcop; + switch(PCI(pc)->op) { + + case POC_BSF: + if(PCORB(pcop)->bit == PIC_RP0_BIT) { + //fprintf(stderr, " isBankInstruction - Set RP0\n"); + return SET_BANK_BIT | PIC_RP0_BIT; + } + + if(PCORB(pcop)->bit == PIC_RP1_BIT) { + //fprintf(stderr, " isBankInstruction - Set RP1\n"); + return CLR_BANK_BIT | PIC_RP0_BIT; + } + break; + + case POC_BCF: + if(PCORB(pcop)->bit == PIC_RP0_BIT) { + //fprintf(stderr, " isBankInstruction - Clr RP0\n"); + return CLR_BANK_BIT | PIC_RP1_BIT; + } + if(PCORB(pcop)->bit == PIC_RP1_BIT) { + //fprintf(stderr, " isBankInstruction - Clr RP1\n"); + return CLR_BANK_BIT | PIC_RP1_BIT; + } + break; + default: + //fprintf(stderr, " isBankInstruction - Status register is getting Modified by:\n"); + //genericPrint(stderr, pc); + ; + } + } + + } + + return bank; +} + + /*-----------------------------------------------------------------*/ /*-----------------------------------------------------------------*/ void FillFlow(pCodeFlow *pcflow) @@ -3347,56 +3458,7 @@ void FillFlow(pCodeFlow *pcflow) cur_bank = -1; do { - regs *reg; - - if(isPCI(pc)) { - - int inCond = PCI(pc)->inCond; - int outCond = PCI(pc)->outCond; - - if( (reg = getRegFromInstruction(pc)) != NULL) { - if(isSTATUS_REG(reg)) { - - //fprintf(stderr, " FillFlow - Status register\n"); - //pc->print(stderr,pc); - /* Check to see if the register banks are changing */ - if(PCI(pc)->isModReg) { - - pCodeOp *pcop = PCI(pc)->pcop; - switch(PCI(pc)->op) { - /* - case POC_BSF: - if(PCORB(pcop)->bit == PIC_RP0_BIT) - fprintf(stderr, " FillFlow - Set RP0\n"); - //outCond |= PCC_REG_BANK1; - if(PCORB(pcop)->bit == PIC_RP1_BIT) - //fprintf(stderr, " FillFlow - Set RP1\n"); - //outCond |= PCC_REG_BANK3; - break; - - case POC_BCF: - if(PCORB(pcop)->bit == PIC_RP0_BIT) - fprintf(stderr, " FillFlow - Clr RP0\n"); - //outCond |= PCC_REG_BANK1; - if(PCORB(pcop)->bit == PIC_RP1_BIT) - fprintf(stderr, " FillFlow - Clr RP1\n"); - //outCond |= PCC_REG_BANK3; - break; - */ - default: - fprintf(stderr, " FillFlow - Status register is getting Modified by:\n"); - genericPrint(stderr, pc); - } - } - - } else - inCond |= PCC_REG_BANK0 << (REG_BANK(reg) & 3); - } - - pcflow->inCond |= (inCond & ~pcflow->outCond); - pcflow->outCond |= outCond; - } - + isBankInstruction(pc); pc = pc->next; } while (pc && (pc != pcflow->end) && !isPCFL(pc)); @@ -3419,12 +3481,16 @@ void FillFlow(pCodeFlow *pcflow) /*-----------------------------------------------------------------*/ void LinkFlow_pCode(pCodeInstruction *from, pCodeInstruction *to) { + pCodeFlowLink *fromLink, *toLink; if(!from || !to || !to->pcflow || !from->pcflow) return; - addSet(&(from->pcflow->to), to->pcflow); - addSet(&(to->pcflow->from), from->pcflow); + fromLink = newpCodeFlowLink(from->pcflow); + toLink = newpCodeFlowLink(to->pcflow); + + addSetIfnotP(&(from->pcflow->to), toLink); //to->pcflow); + addSetIfnotP(&(to->pcflow->from), fromLink); //from->pcflow); } @@ -3437,12 +3503,17 @@ void LinkFlow(pBlock *pb) pCode *pct; //fprintf(stderr,"linkflow \n"); + for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); - (pcflow = findNextpCode(pcflow->next, PC_FLOW)) != NULL;) { + pcflow != NULL; + pcflow = findNextpCode(pcflow->next, PC_FLOW) ) { if(!isPCFL(pcflow)) fprintf(stderr, "LinkFlow - pcflow is not a flow object "); + //fprintf(stderr," link: "); + //pcflow->print(stderr,pcflow); + //FillFlow(PCFL(pcflow)); pc = PCFL(pcflow)->end; @@ -3450,6 +3521,7 @@ void LinkFlow(pBlock *pb) //fprintf(stderr, "LinkFlow - flow block (seq=%d) ", pcflow->seq); if(isPCI_SKIP(pc)) { //fprintf(stderr, "ends with skip\n"); + //pc->print(stderr,pc); pct=findNextInstruction(pc->next); LinkFlow_pCode(PCI(pc),PCI(pct)); pct=findNextInstruction(pct->next); @@ -3457,22 +3529,526 @@ void LinkFlow(pBlock *pb) continue; } - //if(isPCI_BRANCH(pc)) { - //fprintf(stderr, "ends with branch\n"); + if(isPCI_BRANCH(pc)) { + pCodeOpLabel *pcol = PCOLAB(PCI(pc)->pcop); + + //fprintf(stderr, "ends with branch\n "); + //pc->print(stderr,pc); + + if(!(pcol && isPCOLAB(pcol))) { + if((PCI(pc)->op != POC_RETURN) && (PCI(pc)->op != POC_CALL)) { + pc->print(stderr,pc); + fprintf(stderr, "ERROR: %s, branch instruction doesn't have label\n",__FUNCTION__); + } + continue; + } + + if( (pct = findLabelinpBlock(pb,pcol)) != NULL) + LinkFlow_pCode(PCI(pc),PCI(pct)); + else + fprintf(stderr, "ERROR: %s, couldn't find label\n",__FUNCTION__); + + continue; + } - // continue; - //} - #if 0 if(isPCI(pc)) { - fprintf(stderr, "ends with non-branching instruction:\n"); + //fprintf(stderr, "ends with non-branching instruction:\n"); //pc->print(stderr,pc); + + LinkFlow_pCode(PCI(pc),PCI(findNextInstruction(pc->next))); + + continue; + } + + if(pc) { + //fprintf(stderr, "ends with unknown\n"); + //pc->print(stderr,pc); + continue; + } + + //fprintf(stderr, "ends with nothing: ERROR\n"); + + } +} + +/*-----------------------------------------------------------------*/ +/*-----------------------------------------------------------------*/ +int isPCinFlow(pCode *pc, pCode *pcflow) +{ + + if(!pc || !pcflow) + return 0; + + if(!isPCI(pc) || !PCI(pc)->pcflow || !isPCFL(pcflow) ) + return 0; + + if( PCI(pc)->pcflow->pc.seq == pcflow->seq) + return 1; + + return 0; +} + +/*-----------------------------------------------------------------*/ +/*-----------------------------------------------------------------*/ +void BanksUsedFlow2(pCode *pcflow) +{ + pCode *pc=NULL; + + int bank = -1; + bool RegUsed = 0; + + regs *reg; + + if(!isPCFL(pcflow)) { + fprintf(stderr, "BanksUsed - pcflow is not a flow object "); + return; + } + + pc = findNextInstruction(pcflow->next); + + PCFL(pcflow)->lastBank = -1; + + while(isPCinFlow(pc,pcflow)) { + + int bank_selected = isBankInstruction(pc); + + //if(PCI(pc)->pcflow) + //fprintf(stderr,"BanksUsedFlow2, looking at seq %d\n",PCI(pc)->pcflow->pc.seq); + + if(bank_selected > 0) { + //fprintf(stderr,"BanksUsed - mucking with bank %d\n",bank_selected); + + /* This instruction is modifying banking bits before accessing registers */ + if(!RegUsed) + PCFL(pcflow)->firstBank = -1; + + if(PCFL(pcflow)->lastBank == -1) + PCFL(pcflow)->lastBank = 0; + + bank = (1 << (bank_selected & (PIC_RP0_BIT | PIC_RP1_BIT))); + if(bank_selected & SET_BANK_BIT) + PCFL(pcflow)->lastBank |= bank; + + + } else { + reg = getRegFromInstruction(pc); + + if(reg && !isREGinBank(reg, bank)) { + int allbanks = REGallBanks(reg); + if(bank == -1) + PCFL(pcflow)->firstBank = allbanks; + + PCFL(pcflow)->lastBank = allbanks; + + bank = allbanks; + } + RegUsed = 1; + } + + pc = findNextInstruction(pc->next); + } + +// fprintf(stderr,"BanksUsedFlow2 flow seq=%3d, first bank = 0x%03x, Last bank 0x%03x\n", +// pcflow->seq,PCFL(pcflow)->firstBank,PCFL(pcflow)->lastBank); + + + +} +/*-----------------------------------------------------------------*/ +/*-----------------------------------------------------------------*/ +void BanksUsedFlow(pBlock *pb) +{ + pCode *pcflow; + + + //pb->pcHead->print(stderr, pb->pcHead); + + pcflow = findNextpCode(pb->pcHead, PC_FLOW); + //pcflow->print(stderr,pcflow); + + for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); + pcflow != NULL; + pcflow = findNextpCode(pcflow->next, PC_FLOW) ) { + + BanksUsedFlow2(pcflow); + } + +} + + +/*-----------------------------------------------------------------*/ +/*-----------------------------------------------------------------*/ +void insertBankSwitch(pCode *pc, int Set_Clear, int RP_BankBit) +{ + pCode *new_pc; + + if(!pc) + return; + + if(RP_BankBit < 0) + new_pc = newpCode(POC_CLRF, popCopyReg(&pc_status)); + else + new_pc = newpCode((Set_Clear ? POC_BSF : POC_BCF), + popCopyGPR2Bit(PCOP(&pc_status),RP_BankBit)); + + pCodeInsertAfter(pc->prev, new_pc); + + /* Move the label, if there is one */ + + if(PCI(pc)->label) { + PCI(new_pc)->label = PCI(pc)->label; + PCI(pc)->label = NULL; + } + + /* The new instruction has the same pcflow block */ + PCI(new_pc)->pcflow = PCI(pc)->pcflow; + +} +/*-----------------------------------------------------------------*/ +/*-----------------------------------------------------------------*/ +void FixRegisterBankingInFlow(pCodeFlow *pcfl, int cur_bank) +{ + pCode *pc=NULL; + pCode *pcprev=NULL; + pCode *new_pc; + + regs *reg; + + if(!pcfl) + return; + + pc = findNextInstruction(pcfl->pc.next); + + while(isPCinFlow(pc,PCODE(pcfl))) { + + + reg = getRegFromInstruction(pc); +#if 0 + if(reg) { + fprintf(stderr, " %s ",reg->name); + fprintf(stderr, "addr = 0x%03x, bank = %d\n",reg->address,REG_BANK(reg)); + } - else - fprintf(stderr, "has no end pcode\n"); - #endif +#endif + + if(reg && REG_BANK(reg)!=cur_bank) { + /* Examine the instruction before this one to make sure it is + * not a skip type instruction */ + pcprev = findPrevpCode(pc->prev, PC_OPCODE); + if(!pcprev || (pcprev && !isPCI_SKIP(pcprev))) { + int b = cur_bank ^ REG_BANK(reg); + + //fprintf(stderr, "Cool! can switch banks\n"); + cur_bank = REG_BANK(reg); + switch(b & 3) { + case 0: + break; + case 1: + insertBankSwitch(pc, cur_bank&1, PIC_RP0_BIT); + break; + case 2: + insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT); + insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT); + break; + case 3: + if(cur_bank & 3) { + insertBankSwitch(pc, cur_bank&1, PIC_RP0_BIT); + insertBankSwitch(pc, cur_bank&2, PIC_RP1_BIT); + } else + insertBankSwitch(pc, -1, -1); + break; + /* + new_pc = newpCode(((cur_bank&1) ? POC_BSF : POC_BCF), + popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT)); + pCodeInsertAfter(pc->prev, new_pc); + if(PCI(pc)->label) { + PCI(new_pc)->label = PCI(pc)->label; + PCI(pc)->label = NULL; + } + */ + /* + new_pc = newpCode(((cur_bank&1) ? POC_BCF : POC_BSF), + popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT)); + pCodeInsertAfter(pc, new_pc); + */ + + } + + } else { + //fprintf(stderr, "Bummer can't switch banks\n"); + ; + } + } + + pcprev = pc; + pc = findNextInstruction(pc->next); + + } + + if(pcprev && cur_bank) { + /* Brute force - make sure that we point to bank 0 at the + * end of each flow block */ + new_pc = newpCode(POC_BCF, + popCopyGPR2Bit(PCOP(&pc_status),PIC_RP0_BIT)); + pCodeInsertAfter(pcprev, new_pc); + cur_bank = 0; + } + +} + +/*-----------------------------------------------------------------*/ +/*int compareBankFlow - compare the banking requirements between */ +/* flow objects. */ +/*-----------------------------------------------------------------*/ +int compareBankFlow(pCodeFlow *pcflow, pCodeFlowLink *pcflowLink, int toORfrom) +{ + + if(!pcflow || !pcflowLink || !pcflowLink->pcflow) + return 0; + + if(!isPCFL(pcflow) || !isPCFL(pcflowLink->pcflow)) + return 0; + + if(pcflow->firstBank == -1) + return 0; + + + if(pcflowLink->pcflow->firstBank == -1) { + pCodeFlowLink *pctl = setFirstItem( toORfrom ? + pcflowLink->pcflow->to : + pcflowLink->pcflow->from); + return compareBankFlow(pcflow, pctl, toORfrom); + } + + if(toORfrom) { + if(pcflow->lastBank == pcflowLink->pcflow->firstBank) + return 0; + + pcflowLink->bank_conflict++; + pcflowLink->pcflow->FromConflicts++; + pcflow->ToConflicts++; + } else { + if(pcflow->firstBank == pcflowLink->pcflow->lastBank) + return 0; + + pcflowLink->bank_conflict++; + pcflowLink->pcflow->ToConflicts++; + pcflow->FromConflicts++; + } + /* + fprintf(stderr,"compare flow found conflict: seq %d from conflicts %d, to conflicts %d\n", + pcflowLink->pcflow->pc.seq, + pcflowLink->pcflow->FromConflicts, + pcflowLink->pcflow->ToConflicts); + */ + return 1; + } +/*-----------------------------------------------------------------*/ +/*-----------------------------------------------------------------*/ +void FixBankFlow(pBlock *pb) +{ + pCode *pc=NULL; + pCode *pcflow; + pCodeFlowLink *pcfl; + + pCode *pcflow_max_To=NULL; + pCode *pcflow_max_From=NULL; + int max_ToConflicts=0; + int max_FromConflicts=0; + + //fprintf(stderr,"Fix Bank flow \n"); + pcflow = findNextpCode(pb->pcHead, PC_FLOW); + + + /* + First loop through all of the flow objects in this pcode block + and fix the ones that have banking conflicts between the + entry and exit. + */ + + //fprintf(stderr, "FixBankFlow - Phase 1\n"); + + for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); + pcflow != NULL; + pcflow = findNextpCode(pcflow->next, PC_FLOW) ) { + + if(!isPCFL(pcflow)) { + fprintf(stderr, "FixBankFlow - pcflow is not a flow object "); + continue; + } + + if(PCFL(pcflow)->firstBank != PCFL(pcflow)->lastBank && + PCFL(pcflow)->firstBank >= 0 && + PCFL(pcflow)->lastBank >= 0 ) { + + int cur_bank = (PCFL(pcflow)->firstBank < PCFL(pcflow)->lastBank) ? + PCFL(pcflow)->firstBank : PCFL(pcflow)->lastBank; + + FixRegisterBankingInFlow(PCFL(pcflow),cur_bank); + BanksUsedFlow2(pcflow); + + } + } + + //fprintf(stderr, "FixBankFlow - Phase 2\n"); + + for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); + pcflow != NULL; + pcflow = findNextpCode(pcflow->next, PC_FLOW) ) { + + int nFlows; + int nConflicts; + + if(!isPCFL(pcflow)) { + fprintf(stderr, "FixBankFlow - pcflow is not a flow object "); + continue; + } + + PCFL(pcflow)->FromConflicts = 0; + PCFL(pcflow)->ToConflicts = 0; + + nFlows = 0; + nConflicts = 0; + + //fprintf(stderr, " FixBankFlow flow seq %d\n",pcflow->seq); + pcfl = setFirstItem(PCFL(pcflow)->from); + while (pcfl) { + + pc = PCODE(pcfl->pcflow); + + if(!isPCFL(pc)) { + fprintf(stderr,"oops dumpflow - to is not a pcflow\n"); + pc->print(stderr,pc); + } + + nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 0); + nFlows++; + + pcfl=setNextItem(PCFL(pcflow)->from); + } + + if((nFlows >= 2) && nConflicts && (PCFL(pcflow)->firstBank>0)) { + //fprintf(stderr, " From conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts); + + FixRegisterBankingInFlow(PCFL(pcflow),0); + BanksUsedFlow2(pcflow); + + continue; /* Don't need to check the flow from here - it's already been fixed */ + + } + + nFlows = 0; + nConflicts = 0; + + pcfl = setFirstItem(PCFL(pcflow)->to); + while (pcfl) { + + pc = PCODE(pcfl->pcflow); + if(!isPCFL(pc)) { + fprintf(stderr,"oops dumpflow - to is not a pcflow\n"); + pc->print(stderr,pc); + } + + nConflicts += compareBankFlow(PCFL(pcflow), pcfl, 1); + nFlows++; + + pcfl=setNextItem(PCFL(pcflow)->to); + } + + if((nFlows >= 2) && nConflicts &&(nConflicts != nFlows) && (PCFL(pcflow)->lastBank>0)) { + //fprintf(stderr, " To conflicts flow seq %d, nflows %d ,nconflicts %d\n",pcflow->seq,nFlows, nConflicts); + + FixRegisterBankingInFlow(PCFL(pcflow),0); + BanksUsedFlow2(pcflow); + } + } + + /* + Loop through the flow objects again and find the ones with the + maximum conflicts + */ + + for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); + pcflow != NULL; + pcflow = findNextpCode(pcflow->next, PC_FLOW) ) { + + if(PCFL(pcflow)->ToConflicts > max_ToConflicts) + pcflow_max_To = pcflow; + + if(PCFL(pcflow)->FromConflicts > max_FromConflicts) + pcflow_max_From = pcflow; + } +/* + if(pcflow_max_To) + fprintf(stderr,"compare flow Max To conflicts: seq %d conflicts %d\n", + PCFL(pcflow_max_To)->pc.seq, + PCFL(pcflow_max_To)->ToConflicts); + + if(pcflow_max_From) + fprintf(stderr,"compare flow Max From conflicts: seq %d conflicts %d\n", + PCFL(pcflow_max_From)->pc.seq, + PCFL(pcflow_max_From)->FromConflicts); +*/ +} + +/*-----------------------------------------------------------------*/ +/*-----------------------------------------------------------------*/ +void DumpFlow(pBlock *pb) +{ + pCode *pc=NULL; + pCode *pcflow; + pCodeFlowLink *pcfl; + + + fprintf(stderr,"Dump flow \n"); + pb->pcHead->print(stderr, pb->pcHead); + + pcflow = findNextpCode(pb->pcHead, PC_FLOW); + pcflow->print(stderr,pcflow); + + for( pcflow = findNextpCode(pb->pcHead, PC_FLOW); + pcflow != NULL; + pcflow = findNextpCode(pcflow->next, PC_FLOW) ) { + + if(!isPCFL(pcflow)) { + fprintf(stderr, "DumpFlow - pcflow is not a flow object "); + continue; + } + fprintf(stderr,"dumping: "); + pcflow->print(stderr,pcflow); + FlowStats(PCFL(pcflow)); + + for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) { + + pc = PCODE(pcfl->pcflow); + + fprintf(stderr, " from seq %d:\n",pc->seq); + if(!isPCFL(pc)) { + fprintf(stderr,"oops dumpflow - from is not a pcflow\n"); + pc->print(stderr,pc); + } + + } + + for(pcfl = setFirstItem(PCFL(pcflow)->to); pcfl; pcfl=setNextItem(PCFL(pcflow)->to)) { + + pc = PCODE(pcfl->pcflow); + + fprintf(stderr, " to seq %d:\n",pc->seq); + if(!isPCFL(pc)) { + fprintf(stderr,"oops dumpflow - to is not a pcflow\n"); + pc->print(stderr,pc); + } + + } + + } + +} + /*-----------------------------------------------------------------*/ /*-----------------------------------------------------------------*/ int OptimizepBlock(pBlock *pb) @@ -3781,7 +4357,8 @@ void FixRegisterBanking(pBlock *pb) if(!pb) return; - pc = findNextpCode(pb->pcHead, PC_FLOW); + //pc = findNextpCode(pb->pcHead, PC_FLOW); + pc = findNextpCode(pb->pcHead, PC_OPCODE); if(!pc) return; /* loop through all of the flow blocks with in one pblock */ @@ -3795,7 +4372,7 @@ void FixRegisterBanking(pBlock *pb) /* for each flow block, determine the register banking requirements */ - do { + // do { if(isPCI(pc)) { //genericPrint(stderr, pc); @@ -3841,7 +4418,10 @@ void FixRegisterBanking(pBlock *pb) pcprev = pc; pc = pc->next; - } while(pc && !(isPCFL(pc))); + // } while(pc && !(isPCFL(pc))); + + + }while (pc); if(pcprev && cur_bank) { /* Brute force - make sure that we point to bank 0 at the @@ -3852,8 +4432,6 @@ void FixRegisterBanking(pBlock *pb) cur_bank = 0; } - }while (pc); - } void pBlockDestruct(pBlock *pb) @@ -3923,6 +4501,15 @@ void AnalyzeBanking(void) return; + /* Phase 2 - Flow Analysis - Register Banking + * + * In this phase, the individual flow blocks are examined + * and register banking is fixed. + */ + + //for(pb = the_pFile->pbHead; pb; pb = pb->next) + //FixRegisterBanking(pb); + /* Phase 2 - Flow Analysis * * In this phase, the pCode is partition into pCodeFlow @@ -3934,6 +4521,7 @@ void AnalyzeBanking(void) for(pb = the_pFile->pbHead; pb; pb = pb->next) BuildFlow(pb); + /* Phase 2 - Flow Analysis - linking flow blocks * * In this phase, the individual flow blocks are examined @@ -3943,9 +4531,29 @@ void AnalyzeBanking(void) for(pb = the_pFile->pbHead; pb; pb = pb->next) LinkFlow(pb); + + /* Phase x - Flow Analysis - Used Banks + * + * In this phase, the individual flow blocks are examined + * to determine the Register Banks they use + */ + for(pb = the_pFile->pbHead; pb; pb = pb->next) - FixRegisterBanking(pb); + BanksUsedFlow(pb); + /* Phase x - Flow Analysis - Used Banks + * + * In this phase, the individual flow blocks are examined + * to determine the Register Banks they use + */ + + for(pb = the_pFile->pbHead; pb; pb = pb->next) + FixBankFlow(pb); + +/* + for(pb = the_pFile->pbHead; pb; pb = pb->next) + DumpFlow(pb); +*/ /* debug stuff */ for(pb = the_pFile->pbHead; pb; pb = pb->next) { pCode *pcflow; @@ -4218,6 +4826,7 @@ void pBlockStats(FILE *of, pBlock *pb) /*-----------------------------------------------------------------*/ /*-----------------------------------------------------------------*/ +#if 0 static void sequencepCode(void) { pBlock *pb; @@ -4233,6 +4842,7 @@ static void sequencepCode(void) } } +#endif /*-----------------------------------------------------------------*/ /*-----------------------------------------------------------------*/ diff --git a/src/pic/pcode.h b/src/pic/pcode.h index f3c05fd5..8e4dd51a 100644 --- a/src/pic/pcode.h +++ b/src/pic/pcode.h @@ -445,8 +445,35 @@ typedef struct pCodeFlow int inCond; /* Input conditions - stuff assumed defined at entry */ int outCond; /* Output conditions - stuff modified by flow block */ + int firstBank; /* The first and last bank flags are the first and last */ + int lastBank; /* register banks used within one flow object */ + + int FromConflicts; + int ToConflicts; + } pCodeFlow; +/************************************************* + pCodeFlowLink + + The Flow Link object is used to record information + about how consecutive excutive Flow objects are related. + The pCodeFlow objects demarcate the pCodeInstructions + into contiguous chunks. The FlowLink records conflicts + in the discontinuities. For example, if one Flow object + references a register in bank 0 and the next Flow object + references a register in bank 1, then there is a discontinuity + in the banking registers. + +*/ +typedef struct pCodeFlowLink +{ + pCodeFlow *pcflow; /* pointer to linked pCodeFlow object */ + + int bank_conflict; /* records bank conflicts */ + +} pCodeFlowLink; + /************************************************* pCodeInstruction diff --git a/src/pic/ralloc.c b/src/pic/ralloc.c index 58258c9a..f417f064 100644 --- a/src/pic/ralloc.c +++ b/src/pic/ralloc.c @@ -645,13 +645,13 @@ allocDirReg (operand *op ) if(!IS_CONFIG_ADDRESS(address)) { reg = newReg(REG_GPR, PO_DIR, rDirectIdx++, name,getSize (OP_SYMBOL (op)->type),0 ); debugLog (" -- added %s to hash, size = %d\n", name,reg->size); - +/* if (SPEC_ABSA ( OP_SYM_ETYPE(op)) ) { reg->isFixed = 1; reg->address = SPEC_ADDR ( OP_SYM_ETYPE(op)); debugLog (" -- and it is at a fixed address 0x%02x\n",reg->address); } - +*/ hTabAddItem(&dynDirectRegNames, regname2key(name), reg); if (IS_BITVAR (OP_SYM_ETYPE(op))) addSet(&dynDirectBitRegs, reg); @@ -663,6 +663,12 @@ allocDirReg (operand *op ) } } + if (SPEC_ABSA ( OP_SYM_ETYPE(op)) ) { + reg->isFixed = 1; + reg->address = SPEC_ADDR ( OP_SYM_ETYPE(op)); + debugLog (" -- and it is at a fixed address 0x%02x\n",reg->address); + } + return reg; } @@ -3113,12 +3119,14 @@ packRegsForAccUse (iCode * ic) if (IS_AGGREGATE(operandType(IC_RESULT(ic)))) { return; } + debugLog (" %s:%d\n", __FUNCTION__,__LINE__); /* if + or - then it has to be one byte result */ if ((ic->op == '+' || ic->op == '-') && getSize (operandType (IC_RESULT (ic))) > 1) return; + debugLog (" %s:%d\n", __FUNCTION__,__LINE__); /* if shift operation make sure right side is not a literal */ if (ic->op == RIGHT_OP && (isOperandLiteral (IC_RIGHT (ic)) || @@ -3148,6 +3156,7 @@ packRegsForAccUse (iCode * ic) bitVectFirstBit (OP_USES (IC_RESULT (ic)))))) return; + debugLog (" %s:%d\n", __FUNCTION__,__LINE__); if (ic->next != uic) return; @@ -3164,6 +3173,7 @@ packRegsForAccUse (iCode * ic) getSize (aggrToPtr (operandType (IC_RESULT (uic)), FALSE)) > 1) return; + debugLog (" %s:%d\n", __FUNCTION__,__LINE__); if (uic->op != '=' && !IS_ARITHMETIC_OP (uic) && !IS_BITWISE_OP (uic) && @@ -3171,6 +3181,7 @@ packRegsForAccUse (iCode * ic) uic->op != RIGHT_OP) return; + debugLog (" %s:%d\n", __FUNCTION__,__LINE__); /* if used in ^ operation then make sure right is not a literl */ if (uic->op == '^' && isOperandLiteral (IC_RIGHT (uic))) @@ -3211,14 +3222,17 @@ packRegsForAccUse (iCode * ic) IC_LEFT (uic)->key != IC_RESULT (ic)->key) return; + debugLog (" %s:%d\n", __FUNCTION__,__LINE__); /* if one of them is a literal then we can */ - if ((IC_LEFT (uic) && IS_OP_LITERAL (IC_LEFT (uic))) || - (IC_RIGHT (uic) && IS_OP_LITERAL (IC_RIGHT (uic)))) + if ( ((IC_LEFT (uic) && IS_OP_LITERAL (IC_LEFT (uic))) || + (IC_RIGHT (uic) && IS_OP_LITERAL (IC_RIGHT (uic)))) && + (getSize (operandType (IC_RESULT (uic))) <= 1)) { OP_SYMBOL (IC_RESULT (ic))->accuse = 1; return; } + debugLog (" %s:%d\n", __FUNCTION__,__LINE__); /* if the other one is not on stack then we can */ if (IC_LEFT (uic)->key == IC_RESULT (ic)->key && (IS_ITEMP (IC_RIGHT (uic)) ||