From b84cf8c09bd4d579e1fe6ba9d4da20d4030fa738 Mon Sep 17 00:00:00 2001 From: bernhardheld Date: Tue, 19 Aug 2003 15:47:57 +0000 Subject: [PATCH] pic patches by Slade git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@2838 4a8a32a2-be11-0410-ad9d-d568d2c75423 --- ChangeLog | 26 +++++ src/pic/device.c | 43 ++++++-- src/pic/gen.c | 68 +++++++++---- src/pic/genarith.c | 149 ++++++++++++++++++--------- src/pic/glue.c | 24 ++--- src/pic/pcode.c | 249 +++++++++++++++++++++++++++++++++++---------- src/pic/pcode.h | 4 +- src/pic/ralloc.c | 8 +- src/pic/ralloc.h | 1 + 9 files changed, 430 insertions(+), 142 deletions(-) diff --git a/ChangeLog b/ChangeLog index 949a959a..9ebd65e3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,29 @@ +2003-08-19 Bernhard Held + + pic patch provided by Slade Rich + 1. Interrupt would not compile properly. Ensure PCLATH register is saved + during interrupts. Ensure WSAVE is located at a shared bank address. + 2. Fixed page selection in some places + 3. Fixed BTFSS/C to where necessary use registers directly and not simply + the registers name strings. + 4. Fixed "signed / unsigned compare" compiler warnings. + 5. The PIC port manages its own allocation of the general purpose + registers, but makes no attempt to reuse them. As a result when + compiling it soon runs out of general purpose registers. Some + additional code was added to the files pcode.c and device.c to walk + through the function call tree and rename the registers so that they + get reused. + + * src/pic/device.c + * src/pic/gen.c + * src/pic/glue.c + * src/pic/pcode.c + * src/pic/pcode.h + * src/pic/ralloc.c + * src/pic/ralloc.h + * src/pic/genarith.c: Fixed problems with PIC 14 port in functions + genPlus() & genMinus() when the result is the same as left or right + 2003-08-18 Erik Petrich * src/z80/gen.c (isUnsplitable, fetchPairLog): fixed bug #770454 diff --git a/src/pic/device.c b/src/pic/device.c index 2a2cd646..ab3e15a1 100644 --- a/src/pic/device.c +++ b/src/pic/device.c @@ -167,7 +167,7 @@ int isREGinBank(regs *reg, int bank) if(!reg || !pic) return 0; - if(((reg->address | reg->alias) & pic->bankMask & bank) == bank) + if((int)((reg->address | reg->alias) & pic->bankMask & bank) == bank) return 1; return 0; @@ -257,10 +257,18 @@ void dump_sfr(FILE *of) (!finalMapping[start].instance) && (!finalMapping[start].isSFR)) { - fprintf(of,"%s\tres\t%i\n", + if (finalMapping[start].reg->isFixed) { + unsigned i; + for (i=0; isize; i++) { + fprintf(of,"%s\tEQU\t0x%04x\n", + finalMapping[start].reg->name, + finalMapping[start].reg->address+i); + } + } else { + fprintf(of,"%s\tres\t%i\n", finalMapping[start].reg->name, finalMapping[start].reg->size); - + } finalMapping[start].reg->isEmitted = 1; } } @@ -440,7 +448,7 @@ int validAddress(int address, int reg_size) void mapRegister(regs *reg) { - int i; + unsigned i; int alias; if(!reg || !reg->size) { @@ -553,9 +561,30 @@ void assignRelocatableRegisters(set *regset, int used) //fprintf(stdout,"assigning %s isFixed=%d, wasUsed=%d\n",reg->name,reg->isFixed,reg->wasUsed); - if((!reg->isFixed) && ( used || reg->wasUsed)) - address = assignRegister(reg,address); - + if((!reg->isFixed) && ( used || reg->wasUsed)) { + /* If register have been reused then shall not print it a second time. */ +// Undefine REUSE_GPR in files pcode.c & device.c to prevent local function registers being reused. +#define REUSE_GPR +#ifdef REUSE_GPR + set *s; + int done = 0; + for (s = regset; s; s = s->next) { + regs *r; + r = s->item; + if (r == reg) + break; + if((!r->isFixed) && ( used || r->wasUsed)) { + if (r->rIdx == reg->rIdx) { + reg->address = r->address; + done = 1; + break; + } + } + } + if (!done) +#endif // REUSE_GPR + address = assignRegister(reg,address); + } } } diff --git a/src/pic/gen.c b/src/pic/gen.c index 9979c39a..eadf223a 100644 --- a/src/pic/gen.c +++ b/src/pic/gen.c @@ -216,7 +216,6 @@ void emitpLabel(int key) void emitpcode(PIC_OPCODE poc, pCodeOp *pcop) { - if(pcop) addpCode2pBlock(pb,newpCode(poc,pcop)); else @@ -230,6 +229,16 @@ void emitpcodeNULLop(PIC_OPCODE poc) } +void emitpcodePagesel(const char *label) +{ + + char code[81]; + strcpy(code,"\tpagesel "); + strcat(code,label); + addpCode2pBlock(pb,newpCodeInlineP(code)); + +} + /*-----------------------------------------------------------------*/ /* pic14_emitcode - writes the code into a file : for now it is simple */ /*-----------------------------------------------------------------*/ @@ -1182,12 +1191,28 @@ pCodeOp *popGetLabel(unsigned int key) DEBUGpic14_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, labelOffset); - if(key>max_key) + if(key>(unsigned int)max_key) max_key = key; return newpCodeOpLabel(NULL,key+100+labelOffset); } +/*-------------------------------------------------------------------*/ +/* popGetLabel - create a new pCodeOp of type PO_LABEL with offset=1 */ +/*-------------------------------------------------------------------*/ +pCodeOp *popGetHighLabel(unsigned int key) +{ + pCodeOp *pcop; + DEBUGpic14_emitcode ("; ***","%s key=%d, label offset %d",__FUNCTION__,key, labelOffset); + + if(key>(unsigned int)max_key) + max_key = key; + + pcop = newpCodeOpLabel(NULL,key+100+labelOffset); + PCOLAB(pcop)->offset = 1; + return pcop; +} + /*-----------------------------------------------------------------*/ /* popCopyReg - copy a pcode operator */ /*-----------------------------------------------------------------*/ @@ -2554,6 +2579,7 @@ static void genPcall (iCode *ic) } */ emitpcode(POC_CALL,popGetLabel(albl->key)); + emitpcodePagesel(popGetLabel(blbl->key)->name); /* Must restore PCLATH before goto, without destroying W */ emitpcode(POC_GOTO,popGetLabel(blbl->key)); emitpLabel(albl->key); @@ -2691,17 +2717,21 @@ static void genFunction (iCode *ic) } #endif - /* if this is an interrupt service routine then - save acc, b, dpl, dph */ + /* if this is an interrupt service routine */ if (IFFUNC_ISISR(sym->type)) { +/* already done in pic14createInterruptVect() - delete me addpCode2pBlock(pb,newpCode(POC_GOTO,newpCodeOp("END_OF_INTERRUPT+1",PO_STR))); emitpcodeNULLop(POC_NOP); emitpcodeNULLop(POC_NOP); emitpcodeNULLop(POC_NOP); +*/ emitpcode(POC_MOVWF, popCopyReg(&pc_wsave)); emitpcode(POC_SWAPFW, popCopyReg(&pc_status)); emitpcode(POC_CLRF, popCopyReg(&pc_status)); emitpcode(POC_MOVWF, popCopyReg(&pc_ssave)); + emitpcode(POC_MOVFW, popCopyReg(&pc_pclath)); + emitpcode(POC_MOVWF, popCopyReg(&pc_psave)); + emitpcode(POC_CLRF, popCopyReg(&pc_pclath));/* durring an interrupt PCLATH must be cleared before a goto or call statement */ pBlockConvert2ISR(pb); #if 0 @@ -2936,18 +2966,17 @@ static void genEndFunction (iCode *ic) pic14_emitcode(";","XG$%s$0$0 ==.",currFunc->name); _G.debugLine = 0; } - - pic14_emitcode ("reti",""); - - emitpcode(POC_CLRF, popCopyReg(&pc_status)); - emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave)); - emitpcode(POC_MOVWF, popCopyReg(&pc_status)); - emitpcode(POC_SWAPF, popCopyReg(&pc_wsave)); - emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave)); - addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1)); - - emitpcodeNULLop(POC_RETFIE); + pic14_emitcode ("reti",""); + emitpcode(POC_MOVFW, popCopyReg(&pc_psave)); + emitpcode(POC_MOVWF, popCopyReg(&pc_pclath)); + emitpcode(POC_CLRF, popCopyReg(&pc_status)); + emitpcode(POC_SWAPFW, popCopyReg(&pc_ssave)); + emitpcode(POC_MOVWF, popCopyReg(&pc_status)); + emitpcode(POC_SWAPF, popCopyReg(&pc_wsave)); + emitpcode(POC_SWAPFW, popCopyReg(&pc_wsave)); + addpCode2pBlock(pb,newpCodeLabel("END_OF_INTERRUPT",-1)); + emitpcodeNULLop(POC_RETFIE); } else { if (IFFUNC_ISCRITICAL(sym->type)) @@ -5424,7 +5453,7 @@ static void genAnd (iCode *ic, iCode *ifx) } else { pic14_emitcode("movlw","0x%x", (lit & 0xff)); pic14_emitcode("andwf","%s,f",aopGet(AOP(left),offset,FALSE,TRUE)); - if(know_W != (lit&0xff)) + if(know_W != (int)(lit&0xff)) emitpcode(POC_MOVLW, popGetLit(lit & 0xff)); know_W = lit &0xff; emitpcode(POC_ANDWF,popGet(AOP(left),offset)); @@ -5731,7 +5760,7 @@ static void genOr (iCode *ic, iCode *ifx) emitpcode(POC_BSF, newpCodeOpBit(aopGet(AOP(left),offset,FALSE,FALSE),p,0)); } else { - if(know_W != (lit & 0xff)) + if(know_W != (int)(lit & 0xff)) emitpcode(POC_MOVLW, popGetLit(lit & 0xff)); know_W = lit & 0xff; emitpcode(POC_IORWF, popGet(AOP(left),offset)); @@ -8370,6 +8399,7 @@ static void genConstPointerGet (operand *left, DEBUGpic14_emitcode ("; "," %d getting const pointer",__LINE__); emitpcode(POC_CALL,popGetLabel(albl->key)); + emitpcodePagesel(popGetLabel(blbl->key)->name); /* Must restore PCLATH before goto, without destroying W */ emitpcode(POC_GOTO,popGetLabel(blbl->key)); emitpLabel(albl->key); @@ -9328,7 +9358,7 @@ static void genAssign (iCode *ic) DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__); if(AOP_TYPE(right) == AOP_LIT) { if(lit&0xff) { - if(know_W != (lit&0xff)) + if(know_W != (int)(lit&0xff)) emitpcode(POC_MOVLW,popGetLit(lit&0xff)); know_W = lit&0xff; emitpcode(POC_MOVWF, popGet(AOP(result),offset)); @@ -9380,6 +9410,8 @@ static void genJumpTab (iCode *ic) pic14_emitcode("jmp","@a+dptr"); pic14_emitcode("","%05d_DS_:",jtab->key+100); + emitpcode(POC_MOVLW, popGetHighLabel(jtab->key)); + emitpcode(POC_MOVWF, popCopyReg(&pc_pclath)); emitpcode(POC_MOVLW, popGetLabel(jtab->key)); emitpcode(POC_ADDFW, popGet(AOP(IC_JTCOND(ic)),0)); emitSKPNC; diff --git a/src/pic/genarith.c b/src/pic/genarith.c index b96dcdac..3809c711 100644 --- a/src/pic/genarith.c +++ b/src/pic/genarith.c @@ -977,30 +977,47 @@ void genPlus (iCode *ic) offset = 1; - while(size--){ - if (!pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) { - emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset)); - emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset)); - - pic14_emitcode("movf","%s,w", aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE)); - pic14_emitcode("movwf","%s", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE)); + if(size){ + if (pic14_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic)))) { + if ((AOP_TYPE(IC_LEFT(ic)) == AOP_PCODE) && ( + (AOP(IC_LEFT(ic))->aopu.pcop->type == PO_LITERAL) || + (AOP(IC_LEFT(ic))->aopu.pcop->type == PO_IMMEDIATE))) { + while(size--){ + emitpcode(POC_MOVFW, popGet(AOP(IC_RIGHT(ic)),offset)); + emitSKPNC; + emitpcode(POC_INCFSZW, popGet(AOP(IC_RIGHT(ic)),offset)); + emitpcode(POC_ADDLW, popGet(AOP(IC_LEFT(ic)),offset)); + emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset)); + offset++; + } + } else { + while(size--){ + emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset)); + emitSKPNC; + emitpcode(POC_INCFSZW, popGet(AOP(IC_LEFT(ic)),offset)); + emitpcode(POC_ADDWF, popGet(AOP(IC_RESULT(ic)),offset)); + offset++; + } + } + } else { + PIC_OPCODE poc = POC_MOVFW; + if ((AOP_TYPE(IC_LEFT(ic)) == AOP_PCODE) && ( + (AOP(IC_LEFT(ic))->aopu.pcop->type == PO_LITERAL) || + (AOP(IC_LEFT(ic))->aopu.pcop->type == PO_IMMEDIATE))) + poc = POC_MOVLW; + while(size--){ + if (!pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) { + emitpcode(poc, popGet(AOP(IC_LEFT(ic)),offset)); + emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset)); + } + emitpcode(POC_MOVFW, popGet(AOP(IC_RIGHT(ic)),offset)); + emitSKPNC; + emitpcode(POC_INCFSZW, popGet(AOP(IC_RIGHT(ic)),offset)); + emitpcode(POC_ADDWF, popGet(AOP(IC_RESULT(ic)),offset)); + offset++; + } } - - emitpcode(POC_MOVFW, popGet(AOP(IC_RIGHT(ic)),offset)); - emitSKPNC; - emitpcode(POC_INCFSZW, popGet(AOP(IC_RIGHT(ic)),offset)); - emitpcode(POC_ADDWF, popGet(AOP(IC_RESULT(ic)),offset)); - - /* - pic14_emitcode("movf","%s,w", aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE)); - emitSKPNC; - pic14_emitcode("incfsz","%s,w",aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE)); - pic14_emitcode("addwf","%s,f", aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE)); - */ - - offset++; } - } if (AOP_SIZE(IC_RESULT(ic)) > AOP_SIZE(IC_RIGHT(ic))) { @@ -1012,8 +1029,28 @@ void genPlus (iCode *ic) size = AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_RIGHT(ic)) - 1; /* First grab the carry from the lower bytes */ - emitpcode(POC_CLRF, popGet(AOP(IC_RESULT(ic)),offset)); - emitpcode(POC_RLF, popGet(AOP(IC_RESULT(ic)),offset)); + if (AOP_SIZE(IC_LEFT(ic)) > AOP_SIZE(IC_RIGHT(ic))) { + int leftsize = AOP_SIZE(IC_LEFT(ic)) - AOP_SIZE(IC_RIGHT(ic)); + PIC_OPCODE poc = POC_MOVFW; + if ((AOP_TYPE(IC_LEFT(ic)) == AOP_PCODE) && ( + (AOP(IC_LEFT(ic))->aopu.pcop->type == PO_LITERAL) || + (AOP(IC_LEFT(ic))->aopu.pcop->type == PO_IMMEDIATE))) + poc = POC_MOVLW; + while(leftsize-- > 0) { + emitpcode(poc, popGet(AOP(IC_LEFT(ic)),offset)); + emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset)); + emitSKPNC; + emitpcode(POC_INCF, popGet(AOP(IC_RESULT(ic)),offset)); + offset++; + if (size) + size--; + else + break; + } + } else { + emitpcode(POC_CLRF, popGet(AOP(IC_RESULT(ic)),offset)); + emitpcode(POC_RLF, popGet(AOP(IC_RESULT(ic)),offset)); + } if(sign) { @@ -1507,35 +1544,53 @@ void genMinus (iCode *ic) } } - /* - emitpcode(POC_MOVFW, popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE)); - - if (pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) { - emitpcode(POC_SUBFW, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE)); - } else { - emitpcode(POC_SUBFW, popGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE)); - emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE)); - } - */ + size = min( AOP_SIZE(IC_RESULT(ic)), AOP_SIZE(IC_RIGHT(ic))) - 1; offset = 1; - size--; - while(size--){ - if (!pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) { - emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset)); - emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset)); + if(size){ + if (pic14_sameRegs(AOP(IC_RIGHT(ic)), AOP(IC_RESULT(ic)))) { + if ((AOP_TYPE(IC_LEFT(ic)) == AOP_PCODE) && ( + (AOP(IC_LEFT(ic))->aopu.pcop->type == PO_LITERAL) || + (AOP(IC_LEFT(ic))->aopu.pcop->type == PO_IMMEDIATE))) { + while(size--){ + emitpcode(POC_MOVFW, popGet(AOP(IC_RIGHT(ic)),offset)); + emitSKPC; + emitpcode(POC_INCFSZW, popGet(AOP(IC_RIGHT(ic)),offset)); + emitpcode(POC_SUBLW, popGet(AOP(IC_LEFT(ic)),offset)); + emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset)); + offset++; + } + } else { + while(size--){ + emitpcode(POC_MOVFW, popGet(AOP(IC_RIGHT(ic)),offset)); + emitSKPC; + emitpcode(POC_INCFSZW, popGet(AOP(IC_RIGHT(ic)),offset)); + emitpcode(POC_SUBFW, popGet(AOP(IC_LEFT(ic)),offset)); + emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset)); + offset++; + } + } + } else { + PIC_OPCODE poc = POC_MOVFW; + if ((AOP_TYPE(IC_LEFT(ic)) == AOP_PCODE) && ( + (AOP(IC_LEFT(ic))->aopu.pcop->type == PO_LITERAL) || + (AOP(IC_LEFT(ic))->aopu.pcop->type == PO_IMMEDIATE))) + poc = POC_MOVLW; + while(size--){ + if (!pic14_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) { + emitpcode(POC_MOVFW, popGet(AOP(IC_LEFT(ic)),offset)); + emitpcode(POC_MOVWF, popGet(AOP(IC_RESULT(ic)),offset)); + } + emitpcode(POC_MOVFW, popGet(AOP(IC_RIGHT(ic)),offset)); + emitSKPC; + emitpcode(POC_INCFSZW,popGet(AOP(IC_RIGHT(ic)),offset)); + emitpcode(POC_SUBWF, popGet(AOP(IC_RESULT(ic)),offset)); + offset++; + } } - emitpcode(POC_MOVFW, popGet(AOP(IC_RIGHT(ic)),offset)); - emitSKPC; - emitpcode(POC_INCFSZW,popGet(AOP(IC_RIGHT(ic)),offset)); - emitpcode(POC_SUBWF, popGet(AOP(IC_RESULT(ic)),offset)); - - offset++; } - } - // adjustArithmeticResult(ic); release: diff --git a/src/pic/glue.c b/src/pic/glue.c index 7699fbad..8a393a8c 100644 --- a/src/pic/glue.c +++ b/src/pic/glue.c @@ -106,10 +106,10 @@ pic14emitRegularMap (memmap * map, bool addPublics, bool arFlag) symbol *sym; int bitvars = 0;; + /* print the area name */ if (addPublics) fprintf (map->oFile, ";\t.area\t%s\n", map->sname); - /* print the area name */ for (sym = setFirstItem (map->syms); sym; sym = setNextItem (map->syms)) { @@ -307,7 +307,7 @@ printIvalChar (sym_link * type, initList * ilist, pBlock *pb, char *s) else { //printChar (oFile, s, strlen (s) + 1); - for(remain=0; remaindbName); fprintf (asmFile,"\tpagesel _main\n"); fprintf (asmFile,"\tgoto _main\n"); - - /* interrupt service routine */ - fprintf (asmFile, "__sdcc_interrupt:\n"); - copypCode(asmFile, 'I'); - fprintf (asmFile,"\tgoto $\n"); } #if 0 diff --git a/src/pic/pcode.c b/src/pic/pcode.c index 3b2b7d91..295ff336 100644 --- a/src/pic/pcode.c +++ b/src/pic/pcode.c @@ -60,6 +60,7 @@ pCodeOpReg pc_pclath = {{PO_PCLATH, "PCLATH"}, -1, NULL,0,NULL}; pCodeOpReg pc_kzero = {{PO_GPR_REGISTER, "KZ"}, -1, NULL,0,NULL}; pCodeOpReg pc_wsave = {{PO_GPR_REGISTER, "WSAVE"}, -1, NULL,0,NULL}; pCodeOpReg pc_ssave = {{PO_GPR_REGISTER, "SSAVE"}, -1, NULL,0,NULL}; +pCodeOpReg pc_psave = {{PO_GPR_REGISTER, "PSAVE"}, -1, NULL,0,NULL}; static int mnemonics_initialized = 0; @@ -1226,7 +1227,7 @@ void SAFE_snprintf(char **str, size_t *size, const char *format, ...) va_end (val); len = strlen(*str); - if(len > *size) { + if((size_t)len > *size) { fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__); fprintf(stderr,"len = %d is > str size %d\n",len,(int)*size); } @@ -1277,6 +1278,7 @@ extern void init_pic(char *); void pCodeInitRegisters(void) { static int initialized=0; + int shareBankAddress; if(initialized) return; @@ -1299,13 +1301,19 @@ void pCodeInitRegisters(void) pc_pcl.rIdx = IDX_PCL; pc_pclath.rIdx = IDX_PCLATH; - pc_kzero.r = allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0); - pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0x80); - pc_wsave.r = allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0); + pc_kzero.r = allocInternalRegister(IDX_KZ,"KZ",PO_GPR_REGISTER,0); /* Known Zero - actually just a general purpose reg. */ + pc_wsave.r = allocInternalRegister(IDX_WSAVE,"WSAVE", PO_GPR_REGISTER, 0x80); /* Interupt storage for working register - must be same address in all banks ie section SHAREBANK. */ + pc_ssave.r = allocInternalRegister(IDX_SSAVE,"SSAVE", PO_GPR_REGISTER, 0); /* Interupt storage for status register. */ + pc_psave.r = allocInternalRegister(IDX_PSAVE,"PSAVE", PO_GPR_REGISTER, 0); /* Interupt storage for pclath register. */ + + pc_kzero.rIdx = pc_kzero.r->rIdx; + pc_wsave.rIdx = pc_wsave.r->rIdx; + pc_ssave.rIdx = pc_ssave.r->rIdx; + pc_psave.rIdx = pc_psave.r->rIdx; - pc_kzero.rIdx = IDX_KZ; - pc_wsave.rIdx = IDX_WSAVE; - pc_ssave.rIdx = IDX_SSAVE; + shareBankAddress = 0x7f; /* FIXME - this is different for some PICs ICs if the sharebank does not exist then this address needs to be reserved across all banks. */ + pc_wsave.r->isFixed = 1; + pc_wsave.r->address = shareBankAddress; /* probably should put this in a separate initialization routine */ pb_dead_pcodes = newpBlock(); @@ -1621,16 +1629,20 @@ static int RegCond(pCodeOp *pcop) if(!pcop) return 0; - if(pcop->type == PO_GPR_BIT && !strcmp(pcop->name, pc_status.pcop.name)) { - switch(PCORB(pcop)->bit) { - case PIC_C_BIT: - return PCC_C; - case PIC_DC_BIT: - return PCC_DC; - case PIC_Z_BIT: - return PCC_Z; - } - + if (pcop->type == PO_GPR_BIT) { + char *name = pcop->name; + if (!name) + name = PCOR(pcop)->r->name; +// if (strcmp(name, pc_status.pcop.name) != 0) { <<< This breaks the peep 2 optimisation + switch(PCORB(pcop)->bit) { + case PIC_C_BIT: + return PCC_C; + case PIC_DC_BIT: + return PCC_DC; + case PIC_Z_BIT: + return PCC_Z; + } +// } } return 0; @@ -2049,6 +2061,7 @@ pCodeOp *newpCodeOpLabel(char *name, int key) else s = name, key = label_key--; + PCOLAB(pcop)->offset = 0; if(s) pcop->name = Safe_strdup(s); @@ -2148,20 +2161,31 @@ pCodeOp *newpCodeOpWild(int id, pCodeWildBlock *pcwb, pCodeOp *subtype) pCodeOp *newpCodeOpBit(char *s, int bit, int inBitSpace) { pCodeOp *pcop; + struct regs *r = 0; pcop = Safe_calloc(1,sizeof(pCodeOpRegBit) ); pcop->type = PO_GPR_BIT; - if(s) - pcop->name = Safe_strdup(s); - else - pcop->name = NULL; PCORB(pcop)->bit = bit; PCORB(pcop)->inBitSpace = inBitSpace; /* pCodeOpBit is derived from pCodeOpReg. We need to init this too */ - PCOR(pcop)->r = NULL; - PCOR(pcop)->rIdx = 0; + if (s && !inBitSpace) { + r = dirregWithName(s); + if (!r) { + unsigned char idx = ((s[3] - (((s[3]>='0')&&(s[3]<='9'))?'0':'A'-10))<<4)|(s[4] - (((s[4]>='0')&&(s[4]<='9'))?'0':'A'-10)); + r = pic14_regWithIdx(idx); + } + } + if (r) { + pcop->name = NULL; + PCOR(pcop)->r = r; + PCOR(pcop)->rIdx = r->rIdx; + } else { + pcop->name = Safe_strdup(s); + PCOR(pcop)->r = NULL; + PCOR(pcop)->rIdx = 0; + } return pcop; } @@ -2587,6 +2611,16 @@ char *get_op(pCodeOp *pcop,char *buffer, size_t size) SAFE_snprintf(&s,&size,"%s",pcop->name); return buffer; + case PO_LABEL: + s = buffer; + if (pcop->name) { + if(PCOLAB(pcop)->offset == 1) + SAFE_snprintf(&s,&size,"HIGH(%s)",pcop->name); + else + SAFE_snprintf(&s,&size,"%s",pcop->name); + } + return buffer; + default: if (pcop->name) { if(use_buffer) { @@ -2642,13 +2676,14 @@ char *pCode2str(char *str, size_t size, pCode *pc) if(PCI(pc)->isBitInst) { if(PCI(pc)->pcop->type == PO_GPR_BIT) { - if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) ) - SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", - PCI(pc)->pcop->name , - PCI(pc)->pcop->name ); - else - SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)), - (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit )); + char *name = PCI(pc)->pcop->name; + if (!name) + name = PCOR(PCI(pc)->pcop)->r->name; + if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) ) + SAFE_snprintf(&s,&size,"(%s >> 3), (%s & 7)", name, name); + else + SAFE_snprintf(&s,&size,"%s,%d", name, + (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit)&7); } else if(PCI(pc)->pcop->type == PO_GPR_BIT) { SAFE_snprintf(&s,&size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit); }else @@ -3330,7 +3365,8 @@ void AnalyzepBlock(pBlock *pb) /* Is this an instruction with operands? */ if(pc->type == PC_OPCODE && PCI(pc)->pcop) { - if(PCI(pc)->pcop->type == PO_GPR_TEMP) { + if((PCI(pc)->pcop->type == PO_GPR_TEMP) + || ((PCI(pc)->pcop->type == PO_GPR_BIT) && PCOR(PCI(pc)->pcop)->r && (PCOR(PCI(pc)->pcop)->r->pc_type == PO_GPR_TEMP))) { /* Loop through all of the registers declared so far in this block and see if we find this one there */ @@ -4968,23 +5004,122 @@ void AnalyzeBanking(void) } +// Undefine REUSE_GPR in files pcode.c & device.c to prevent local function registers being reused. +#define REUSE_GPR +#ifdef REUSE_GPR +/*-----------------------------------------------------------------*/ +/*-----------------------------------------------------------------*/ +DEFSETFUNC (resetrIdx) +{ + if (!((regs *)item)->isFixed) + ((regs *)item)->rIdx = 0; + + return 0; +} + +pCode *findFunction(char *fname); + +/*-----------------------------------------------------------------*/ +/*-----------------------------------------------------------------*/ +unsigned register_reassign(pBlock *pb, unsigned idx) +{ + pCode *pc; + + /* check recursion */ + pc = setFirstItem(pb->function_entries); + if(!pc) + return idx; + + DFPRINTF((stderr," reassigning registers for function \"%s\"\n",PCF(pc)->fname)); + + if (pb->tregisters) { + regs *r; + for (r = setFirstItem(pb->tregisters); r; r = setNextItem(pb->tregisters)) { + if (r->type == REG_GPR) { + if (!r->isFixed) { + if (r->rIdx < (int)idx) { + char s[20]; + r->rIdx = idx++; + sprintf(s,"r0x%02X", r->rIdx); + DFPRINTF((stderr," reassigning register \"%s\" to \"%s\"\n",r->name,s)); + free(r->name); + r->name = Safe_strdup(s); + } + } + } + } + } + for(pc = setFirstItem(pb->function_calls); pc; pc = setNextItem(pb->function_calls)) { + + if(pc->type == PC_OPCODE && PCI(pc)->op == POC_CALL) { + char *dest = get_op_from_instruction(PCI(pc)); + + pCode *pcn = findFunction(dest); + if(pcn) { + register_reassign(pcn->pb,idx); + } + } + + } + + return idx; +} + +/*-----------------------------------------------------------------*/ +/* Re-allocate the GPR for optimum reuse for a given pblock */ +/* eg if a function m() calls function f1() and f2(), where f1 */ +/* allocates a local variable vf1 and f2 allocates a local */ +/* variable vf2. Then providing f1 and f2 do not call each other */ +/* they may share the same general purpose registers for vf1 and */ +/* vf2. */ +/* This is done by first setting the the regs rIdx to start after */ +/* all the global variables, then walking through the call tree */ +/* renaming the registers to match their new idx and incrementng */ +/* it as it goes. If a function has already been called it will */ +/* only rename the registers if it has already used up those */ +/* registers ie rIdx of the function's registers is lower than the */ +/* current rIdx. That way the register will not be reused while */ +/* still being used by an eariler function call. */ +/*-----------------------------------------------------------------*/ +void register_reusage(pBlock *mainPb) +{ + static int exercised = 0; + if (!exercised) { /* Only do this once */ + /* Find end of statically allocated variables for start idx */ + unsigned idx = 0x20; /* Start from begining of GPR. Note may not be 0x20 on some PICs */ + regs *r; + for (r = setFirstItem(dynDirectRegs); r; r = setNextItem(dynDirectRegs)) { + if (r->type != REG_SFR) { + idx += r->size; /* Increment for all statically allocated variables */ + } + } + + applyToSet(dynAllocRegs,resetrIdx); /* Reset all rIdx to zero. */ + + if (mainPb) + idx = register_reassign(mainPb,idx); /* Do main and all the functions that are called from it. */ + idx = register_reassign(the_pFile->pbHead,idx); /* Do the other functions such as interrupts. */ + } + exercised++; +} +#endif // REUSE_GPR + /*-----------------------------------------------------------------*/ /* buildCallTree - look at the flow and extract all of the calls */ /* */ /*-----------------------------------------------------------------*/ set *register_usage(pBlock *pb); + void buildCallTree(void ) { pBranch *pbr; - pBlock *pb; + pBlock *pb, *mainPb = 0; pCode *pc; if(!the_pFile) return; - - /* Now build the call tree. First we examine all of the pCodes for functions. Keep in mind that the function boundaries coincide @@ -5015,37 +5150,43 @@ void buildCallTree(void ) pCode *pc_fstart=NULL; for(pc = pb->pcHead; pc; pc = pc->next) { if(isPCF(pc)) { - if (PCF(pc)->fname) { + pCodeFunction *pcf = PCF(pc); + if (pcf->fname) { - if(STRCASECMP(PCF(pc)->fname, "_main") == 0) { - //fprintf(stderr," found main \n"); - pb->cmemmap = NULL; /* FIXME do we need to free ? */ - pb->dbName = 'M'; - } + if(STRCASECMP(pcf->fname, "_main") == 0) { + //fprintf(stderr," found main \n"); + pb->cmemmap = NULL; /* FIXME do we need to free ? */ + pb->dbName = 'M'; + mainPb = pb; + } - pbr = Safe_calloc(1,sizeof(pBranch)); - pbr->pc = pc_fstart = pc; - pbr->next = NULL; + pbr = Safe_calloc(1,sizeof(pBranch)); + pbr->pc = pc_fstart = pc; + pbr->next = NULL; - the_pFile->functions = pBranchAppend(the_pFile->functions,pbr); + the_pFile->functions = pBranchAppend(the_pFile->functions,pbr); - // Here's a better way of doing the same: - addSet(&pb->function_entries, pc); + // Here's a better way of doing the same: + addSet(&pb->function_entries, pc); - } else { - // Found an exit point in a function, e.g. return - // (Note, there may be more than one return per function) - if(pc_fstart) - pBranchLink(PCF(pc_fstart), PCF(pc)); + } else { + // Found an exit point in a function, e.g. return + // (Note, there may be more than one return per function) + if(pc_fstart) + pBranchLink(PCF(pc_fstart), pcf); - addSet(&pb->function_exits, pc); - } + addSet(&pb->function_exits, pc); + } } else if(isCALL(pc)) { - addSet(&pb->function_calls,pc); + addSet(&pb->function_calls,pc); } } } +#ifdef REUSE_GPR + register_reusage(mainPb); /* Comment out this line to prevent local function registers being reused. Note from this point onwards finding a GPR by its rIdx value will no longer work.*/ +#endif // REUSE_GPR + /* Re-allocate the registers so that there are no collisions * between local variables when one function call another */ diff --git a/src/pic/pcode.h b/src/pic/pcode.h index e8b44159..1c3a024f 100644 --- a/src/pic/pcode.h +++ b/src/pic/pcode.h @@ -326,6 +326,7 @@ typedef struct pCodeOpLabel { pCodeOp pcop; int key; + int offset; /* low or high byte of label */ } pCodeOpLabel; typedef struct pCodeOpReg @@ -832,8 +833,9 @@ extern pCodeOpReg pc_fsr; extern pCodeOpReg pc_pcl; extern pCodeOpReg pc_pclath; extern pCodeOpReg pc_kzero; -extern pCodeOpReg pc_wsave; /* wsave and ssave are used to save W and the Status */ +extern pCodeOpReg pc_wsave; /* wsave, ssave and psave are used to save W, the Status and PCLATH*/ extern pCodeOpReg pc_ssave; /* registers during an interrupt */ +extern pCodeOpReg pc_psave; /* registers during an interrupt */ #endif // __PCODE_H__ diff --git a/src/pic/ralloc.c b/src/pic/ralloc.c index b1a37641..5c8e6dd1 100644 --- a/src/pic/ralloc.c +++ b/src/pic/ralloc.c @@ -487,7 +487,7 @@ regWithIdx (set *dRegs, int idx, int fixed) for (dReg = setFirstItem(dRegs) ; dReg ; dReg = setNextItem(dRegs)) { - if(idx == dReg->rIdx && (fixed == dReg->isFixed)) { + if(idx == dReg->rIdx && (fixed == (int)dReg->isFixed)) { return dReg; } } @@ -838,6 +838,8 @@ pic14_allocWithIdx (int idx) debugLog ("Found a Processor Register!\n"); } else if( (dReg = regWithIdx ( dynInternalRegs, idx,0)) != NULL ) { debugLog ("Found an Internal Register!\n"); + } else if( (dReg = regWithIdx ( dynInternalRegs, idx,1)) != NULL ) { + debugLog ("Found an Internal Register!\n"); } else { debugLog ("Dynamic Register not found\n"); @@ -1075,6 +1077,7 @@ void writeUsedRegs(FILE *of) { packBits(dynDirectBitRegs); + assignFixedRegisters(dynInternalRegs); assignFixedRegisters(dynAllocRegs); assignFixedRegisters(dynStackRegs); assignFixedRegisters(dynDirectRegs); @@ -2134,7 +2137,6 @@ serialRegAssign (eBBlock ** ebbs, int count) debugLog (" %d - \n", __LINE__); if(debugF) bitVectDebugOn(_G.regAssigned, debugF); - for (j = 0; j < sym->nRegs; j++) { if (sym->regType == REG_PTR) @@ -2142,7 +2144,7 @@ serialRegAssign (eBBlock ** ebbs, int count) else sym->regs[j] = getRegGpr (ic, ebbs[i], sym); - /* if the allocation falied which means + /* if the allocation failed which means this was spilt then break */ if (!sym->regs[j]) break; diff --git a/src/pic/ralloc.h b/src/pic/ralloc.h index a330ece3..5c6d77b8 100644 --- a/src/pic/ralloc.h +++ b/src/pic/ralloc.h @@ -122,5 +122,6 @@ regs *allocRegByName (char *name, int size ); #define IDX_KZ 0x7fff /* Known zero - actually just a general purpose reg. */ #define IDX_WSAVE 0x7ffe #define IDX_SSAVE 0x7ffd +#define IDX_PSAVE 0x7ffc #endif -- 2.47.2