+2003-08-19 Bernhard Held <bernhard@bernhardheld.de>
+
+ pic patch provided by Slade Rich <slade_rich@yahoo.com>
+ 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 <epetrich@ivorytower.norman.ok.us>
* src/z80/gen.c (isUnsplitable, fetchPairLog): fixed bug #770454
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;
(!finalMapping[start].instance) &&
(!finalMapping[start].isSFR)) {
- fprintf(of,"%s\tres\t%i\n",
+ if (finalMapping[start].reg->isFixed) {
+ unsigned i;
+ for (i=0; i<finalMapping[start].reg->size; 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;
}
}
void mapRegister(regs *reg)
{
- int i;
+ unsigned i;
int alias;
if(!reg || !reg->size) {
//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);
+ }
}
}
void emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
{
-
if(pcop)
addpCode2pBlock(pb,newpCode(poc,pcop));
else
}
+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 */
/*-----------------------------------------------------------------*/
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 */
/*-----------------------------------------------------------------*/
}
*/
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);
}
#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
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))
} 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));
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));
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);
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));
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;
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))) {
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) {
}
}
- /*
- 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:
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)) {
else {
//printChar (oFile, s, strlen (s) + 1);
- for(remain=0; remain<strlen(s); remain++) {
+ for(remain=0; remain<(int)strlen(s); remain++) {
addpCode2pBlock(pb,newpCode(POC_RETLW,newpCodeOpLit(s[remain])));
//fprintf(stderr,"0x%02x ",s[remain]);
}
fprintf (vFile, "\t__config 0x%x\n", getConfigWord(0x2007));
fprintf (vFile, "%s", iComments2);
- fprintf (vFile, "; reset and interrupt vectors \n");
+ fprintf (vFile, "; reset vector \n");
fprintf (vFile, "%s", iComments2);
fprintf (vFile, "STARTUP\t%s\n", CODE_NAME);
+ fprintf (vFile, "\tnop\n"); /* first location used by incircuit debugger */
fprintf (vFile, "\tgoto\t__sdcc_gsinit_startup\n");
- fprintf (vFile, "\tnop\n");
+/* during an interrupt PCLATH must be cleared before a goto - delete me
fprintf (vFile, "\tnop\n");
fprintf (vFile, "\tgoto\t__sdcc_interrupt\n");
-
+*/
}
copyFile (asmFile, vFile);
fprintf (asmFile, "%s", iComments2);
- fprintf (asmFile, "; initialization and interrupt code \n");
+ fprintf (asmFile, "; interrupt and initialization code\n");
fprintf (asmFile, "%s", iComments2);
+ fprintf (asmFile, "code_init\t%s\t0x4\n", CODE_NAME);
+
+ /* interrupt service routine */
+ fprintf (asmFile, "__sdcc_interrupt:\n");
+ copypCode(asmFile, 'I');
/* initialize data memory */
- fprintf (asmFile, "code_init\t%s\t0x10\n", CODE_NAME);
fprintf (asmFile,"__sdcc_gsinit_startup:\n");
/* FIXME: This is temporary. The idata section should be used. If
not, we could add a special feature to the linker. This will
copypCode(asmFile, statsg->dbName);
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
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;
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);
}
void pCodeInitRegisters(void)
{
static int initialized=0;
+ int shareBankAddress;
if(initialized)
return;
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();
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;
else
s = name, key = label_key--;
+ PCOLAB(pcop)->offset = 0;
if(s)
pcop->name = Safe_strdup(s);
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;
}
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) {
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
/* 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 */
}
+// 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
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 */
{
pCodeOp pcop;
int key;
+ int offset; /* low or high byte of label */
} pCodeOpLabel;
typedef struct pCodeOpReg
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__
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;
}
}
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");
{
packBits(dynDirectBitRegs);
+ assignFixedRegisters(dynInternalRegs);
assignFixedRegisters(dynAllocRegs);
assignFixedRegisters(dynStackRegs);
assignFixedRegisters(dynDirectRegs);
debugLog (" %d - \n", __LINE__);
if(debugF)
bitVectDebugOn(_G.regAssigned, debugF);
-
for (j = 0; j < sym->nRegs; j++)
{
if (sym->regType == REG_PTR)
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;
#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