static void FixRegisterBanking(pBlock *pb);
-#if defined(__BORLANDC__) || defined(_MSC_VER)
-#define STRCASECMP stricmp
-#else
-#define STRCASECMP strcasecmp
-#endif
-
/****************************************************************/
/****************************************************************/
return pcodeId++;
}
-#ifdef HAVE_VSNPRINTF
-// Alas, vsnprintf is not ANSI standard, and does not exist
-// on Solaris (and probably other non-Gnu flavored Unixes).
-
-/*-----------------------------------------------------------------*/
-/* SAFE_snprintf - like snprintf except the string pointer is */
-/* after the string has been printed to. This is */
-/* useful for printing to string as though if it */
-/* were a stream. */
-/*-----------------------------------------------------------------*/
-void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
-{
- va_list val;
- int len;
-
- if(!str || !*str)
- return;
-
- va_start(val, format);
-
- vsnprintf(*str, *size, format, val);
-
- va_end (val);
-
- len = strlen(*str);
- 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);
- }
-
- *str += len;
- *size -= len;
-
-}
-
-#else // HAVE_VSNPRINTF
-
-// This version is *not* safe, despite the name.
-
-void SAFE_snprintf(char **str, size_t *size, const char *format, ...)
-{
- va_list val;
- int len;
- static char buffer[1024]; /* grossly conservative, but still not inherently safe */
-
- if(!str || !*str)
- return;
-
- va_start(val, format);
-
- vsprintf(buffer, format, val);
- va_end (val);
-
- len = strlen(buffer);
- if(len > *size) {
- fprintf(stderr,"WARNING, it looks like %s has overflowed\n",__FUNCTION__);
- fprintf(stderr,"len = %d is > str size %d\n",len,*size);
- }
-
- strcpy(*str, buffer);
- *str += len;
- *size -= len;
-
-}
-
-#endif // HAVE_VSNPRINTF
-
-
extern void initStack(int base_address, int size, int shared);
extern regs *allocProcessorRegister(int rIdx, char * name, short po_type, int alias);
extern regs *allocInternalRegister(int rIdx, char * name, PIC_OPTYPE po_type, int alias);
void addpCode2pBlock(pBlock *pb, pCode *pc)
{
- if(!pc)
+ if(!pb || !pc)
return;
if(!pb->pcHead) {
case PO_INDF:
case PO_FSR:
if(use_buffer) {
- SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
+ SNPRINTF(buffer,size,"%s",PCOR(pcop)->r->name);
return buffer;
}
- //return PCOR(pcop)->r->name;
return pcop->name;
break;
case PO_GPR_TEMP:
r = pic14_regWithIdx(PCOR(pcop)->r->rIdx);
if(use_buffer) {
- SAFE_snprintf(&buffer,&size,"%s",r->name);
+ SNPRINTF(buffer,size,"%s",r->name);
return buffer;
}
return r->name;
-
+ break;
case PO_IMMEDIATE:
s = buffer;
if( PCOI(pcop)->offset >= 0 && PCOI(pcop)->offset<4) {
switch(PCOI(pcop)->offset) {
case 0:
- SAFE_snprintf(&s,&size,"low (%s+%d)",pcop->name, PCOI(pcop)->index);
+ SNPRINTF(s,size,"low (%s+%d)",pcop->name, PCOI(pcop)->index);
break;
case 1:
- SAFE_snprintf(&s,&size,"high (%s+%d)",pcop->name, PCOI(pcop)->index);
+ SNPRINTF(s,size,"high (%s+%d)",pcop->name, PCOI(pcop)->index);
+ break;
+ case 2:
+ SNPRINTF(s,size,"0x%02x",PCOI(pcop)->_const ? GPTRTAG_CODE : GPTRTAG_DATA);
break;
default:
fprintf (stderr, "PO_IMMEDIATE/_const/offset=%d\n", PCOI(pcop)->offset);
assert ( !"offset too large" );
- SAFE_snprintf(&s,&size,"(((%s+%d) >> %d)&0xff)",
+ SNPRINTF(s,size,"(((%s+%d) >> %d)&0xff)",
pcop->name,
PCOI(pcop)->index,
8 * PCOI(pcop)->offset );
}
} else
- SAFE_snprintf(&s,&size,"LOW (%s+%d)",pcop->name,PCOI(pcop)->index);
+ SNPRINTF(s,size,"LOW (%s+%d)",pcop->name,PCOI(pcop)->index);
} else {
if( !PCOI(pcop)->offset) { // && PCOI(pcc->pcop)->offset<4)
- SAFE_snprintf(&s,&size,"(%s + %d)",
+ SNPRINTF(s,size,"(%s + %d)",
pcop->name,
PCOI(pcop)->index);
} else {
switch(PCOI(pcop)->offset) {
case 0:
- SAFE_snprintf(&s,&size,"(%s + %d)",pcop->name, PCOI(pcop)->index);
+ SNPRINTF(s,size,"(%s + %d)",pcop->name, PCOI(pcop)->index);
break;
case 1:
- SAFE_snprintf(&s,&size,"high (%s + %d)",pcop->name, PCOI(pcop)->index);
+ SNPRINTF(s,size,"high (%s + %d)",pcop->name, PCOI(pcop)->index);
+ break;
+ case 2:
+ SNPRINTF(s,size,"0x%02x",PCOI(pcop)->_const ? GPTRTAG_CODE : GPTRTAG_DATA);
break;
default:
fprintf (stderr, "PO_IMMEDIATE/mutable/offset=%d\n", PCOI(pcop)->offset);
assert ( !"offset too large" );
- SAFE_snprintf(&s,&size,"((%s + %d) >> %d)&0xff",pcop->name, PCOI(pcop)->index, 8*PCOI(pcop)->offset);
+ SNPRINTF(s,size,"((%s + %d) >> %d)&0xff",pcop->name, PCOI(pcop)->index, 8*PCOI(pcop)->offset);
break;
}
}
}
-
return buffer;
+ break;
case PO_DIR:
s = buffer;
- //size = sizeof(buffer);
if( PCOR(pcop)->instance) {
- SAFE_snprintf(&s,&size,"(%s + %d)",
+ SNPRINTF(s,size,"(%s + %d)",
pcop->name,
PCOR(pcop)->instance );
- //fprintf(stderr,"PO_DIR %s\n",buffer);
} else
- SAFE_snprintf(&s,&size,"%s",pcop->name);
+ SNPRINTF(s,size,"%s",pcop->name);
return buffer;
+ break;
case PO_LABEL:
s = buffer;
if (pcop->name) {
if(PCOLAB(pcop)->offset == 1)
- SAFE_snprintf(&s,&size,"HIGH(%s)",pcop->name);
+ SNPRINTF(s,size,"HIGH(%s)",pcop->name);
else
- SAFE_snprintf(&s,&size,"%s",pcop->name);
+ SNPRINTF(s,size,"%s",pcop->name);
}
return buffer;
+ break;
case PO_GPR_BIT:
if(PCOR(pcop)->r) {
if(use_buffer) {
- SAFE_snprintf(&buffer,&size,"%s",PCOR(pcop)->r->name);
+ SNPRINTF(buffer,size,"%s",PCOR(pcop)->r->name);
return buffer;
}
return PCOR(pcop)->r->name;
}
-
/* fall through to the default case */
+
default:
if(pcop->name) {
if(use_buffer) {
- SAFE_snprintf(&buffer,&size,"%s",pcop->name);
+ SNPRINTF(buffer,size,"%s",pcop->name);
return buffer;
}
return pcop->name;
/*-----------------------------------------------------------------*/
char *pCode2str(char *str, size_t size, pCode *pc)
{
- char *s = str;
+ char *s = str;
- switch(pc->type) {
+ switch(pc->type) {
- case PC_OPCODE:
+ case PC_OPCODE:
- SAFE_snprintf(&s,&size, "\t%s\t", PCI(pc)->mnemonic);
-
- if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
-
- if(PCI(pc)->isBitInst) {
- if(PCI(pc)->pcop->type == PO_GPR_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
- SAFE_snprintf(&s,&size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
- //PCI(pc)->pcop->t.bit );
- } else {
- if(PCI(pc)->pcop->type == PO_GPR_BIT) {
- if( PCI(pc)->num_ops == 2)
- SAFE_snprintf(&s,&size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
- else
- SAFE_snprintf(&s,&size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
- } else {
- SAFE_snprintf(&s,&size,"%s",get_op_from_instruction(PCI(pc)));
- if( PCI(pc)->num_ops == 2)
- SAFE_snprintf(&s,&size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
- }
- }
- }
- break;
+ SNPRINTF(s,size, "\t%s\t", PCI(pc)->mnemonic);
+ size -= strlen(s);
+ s += strlen(s);
+
+ if( (PCI(pc)->num_ops >= 1) && (PCI(pc)->pcop)) {
+ if(PCI(pc)->isBitInst) {
+ if(PCI(pc)->pcop->type == PO_GPR_BIT) {
+ char *name = PCI(pc)->pcop->name;
+ if (!name)
+ name = PCOR(PCI(pc)->pcop)->r->name;
+ if( (((pCodeOpRegBit *)(PCI(pc)->pcop))->inBitSpace) )
+ SNPRINTF(s,size,"(%s >> 3), (%s & 7)", name, name);
+ else
+ SNPRINTF(s,size,"%s,%d", name, (((pCodeOpRegBit *)(PCI(pc)->pcop))->bit)&7);
+ } else if(PCI(pc)->pcop->type == PO_GPR_BIT) {
+ SNPRINTF(s,size,"%s,%d", get_op_from_instruction(PCI(pc)),PCORB(PCI(pc)->pcop)->bit);
+ } else
+ SNPRINTF(s,size,"%s,0 ; ?bug", get_op_from_instruction(PCI(pc)));
+ } else {
+ if(PCI(pc)->pcop->type == PO_GPR_BIT) {
+ if( PCI(pc)->num_ops == 2)
+ SNPRINTF(s,size,"(%s >> 3),%c",get_op_from_instruction(PCI(pc)),((PCI(pc)->isModReg) ? 'F':'W'));
+ else
+ SNPRINTF(s,size,"(1 << (%s & 7))",get_op_from_instruction(PCI(pc)));
+ } else {
+ SNPRINTF(s,size,"%s",get_op_from_instruction(PCI(pc)));
+ size -= strlen(s);
+ s += strlen(s);
+ if( PCI(pc)->num_ops == 2)
+ SNPRINTF(s,size,",%c", ( (PCI(pc)->isModReg) ? 'F':'W'));
+ }
+ }
+ }
+ break;
- case PC_COMMENT:
- /* assuming that comment ends with a \n */
- SAFE_snprintf(&s,&size,";%s", ((pCodeComment *)pc)->comment);
- break;
+ case PC_COMMENT:
+ /* assuming that comment ends with a \n */
+ SNPRINTF(s,size,";%s", ((pCodeComment *)pc)->comment);
+ break;
- case PC_INLINE:
- /* assuming that inline code ends with a \n */
- SAFE_snprintf(&s,&size,"%s", ((pCodeComment *)pc)->comment);
- break;
+ case PC_INLINE:
+ /* assuming that inline code ends with a \n */
+ SNPRINTF(s,size,"%s", ((pCodeComment *)pc)->comment);
+ break;
- case PC_LABEL:
- SAFE_snprintf(&s,&size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
- break;
- case PC_FUNCTION:
- SAFE_snprintf(&s,&size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
- break;
- case PC_WILD:
- SAFE_snprintf(&s,&size,";\tWild opcode: id=%d\n",PCW(pc)->id);
- break;
- case PC_FLOW:
- SAFE_snprintf(&s,&size,";\t--FLOW change\n");
- break;
- case PC_CSOURCE:
-// SAFE_snprintf(&s,&size,";#CSRC\t%s %d\n; %s\n", PCCS(pc)->file_name, PCCS(pc)->line_number, PCCS(pc)->line);
- SAFE_snprintf(&s,&size,"%s\t.line\t%d; \"%s\"\t%s\n",(options.debug?"":";"),PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
- break;
- case PC_ASMDIR:
- if(PCAD(pc)->directive) {
- SAFE_snprintf(&s,&size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
- } else if(PCAD(pc)->arg) {
- /* special case to handle inline labels without a tab */
- SAFE_snprintf(&s,&size,"%s\n", PCAD(pc)->arg);
+ case PC_LABEL:
+ SNPRINTF(s,size,";label=%s, key=%d\n",PCL(pc)->label,PCL(pc)->key);
+ break;
+ case PC_FUNCTION:
+ SNPRINTF(s,size,";modname=%s,function=%s: id=%d\n",PCF(pc)->modname,PCF(pc)->fname);
+ break;
+ case PC_WILD:
+ SNPRINTF(s,size,";\tWild opcode: id=%d\n",PCW(pc)->id);
+ break;
+ case PC_FLOW:
+ SNPRINTF(s,size,";\t--FLOW change\n");
+ break;
+ case PC_CSOURCE:
+ SNPRINTF(s,size,"%s\t.line\t%d; \"%s\"\t%s\n",(options.debug?"":";"),PCCS(pc)->line_number, PCCS(pc)->file_name, PCCS(pc)->line);
+ break;
+ case PC_ASMDIR:
+ if(PCAD(pc)->directive) {
+ SNPRINTF(s,size,"\t%s%s%s\n", PCAD(pc)->directive, PCAD(pc)->arg?"\t":"", PCAD(pc)->arg?PCAD(pc)->arg:"");
+ } else if(PCAD(pc)->arg) {
+ /* special case to handle inline labels without a tab */
+ SNPRINTF(s,size,"%s\n", PCAD(pc)->arg);
+ }
+ break;
+
+ case PC_BAD:
+ SNPRINTF(s,size,";A bad pCode is being used\n");
}
- break;
-
- case PC_BAD:
- SAFE_snprintf(&s,&size,";A bad pCode is being used\n");
- }
- return str;
+ return str;
}
/*-----------------------------------------------------------------*/
//fprintf(stderr,"linkflow \n");
+ if (!pb) return;
+
for( pcflow = findNextpCode(pb->pcHead, PC_FLOW);
pcflow != NULL;
pcflow = findNextpCode(pcflow->next, PC_FLOW) ) {
insertPCodeInstruction(pci, PCI(new_pc));
}
+/*
+ * isValidIdChar - check if c may be present in an identifier
+ */
+static int isValidIdChar (char c)
+{
+ if (c >= 'a' && c <= 'z') return 1;
+ if (c >= 'A' && c <= 'Z') return 1;
+ if (c >= '0' && c <= '9') return 1;
+ if (c == '_') return 1;
+ return 0;
+}
+
+/*
+ * bankcompare - check if two operand string refer to the same register
+ * This functions handles NAME and (NAME + x) in both operands.
+ * Returns 1 on same register, 0 on different (or unknown) registers.
+ */
+static int bankCompare(const char *op1, const char *op2)
+{
+ int i;
+
+ if (!op1 && !op2) return 0; // both unknown, might be different though!
+ if (!op1 || !op2) return 0;
+
+ // find start of operand name
+ while (op1[0] == '(' || op1[0] == ' ') op1++;
+ while (op2[0] == '(' || op2[0] == ' ') op2++;
+
+ // compare till first non-identifier character
+ for (i = 0; (op1[i] == op2[i]) && isValidIdChar(op1[i]); i++);
+ if (!isValidIdChar(op1[i]) && !isValidIdChar(op2[i])) return 1;
+
+ // play safe---assume different operands
+ return 0;
+}
+
/*-----------------------------------------------------------------*/
/*-----------------------------------------------------------------*/
-static int sameBank(regs *reg, const char *new_bank, const char *cur_bank)
+extern int pic14_operandsAllocatedInSameBank(const char *str1, const char *str2);
+static int sameBank(regs *reg, regs *previous_reg, const char *new_bank, const char *cur_bank, unsigned max_mask)
{
if (!cur_bank) return 0;
- // identify '(regname + X)' and 'regname'
- if (reg && reg->name && reg->name[0] == '(' && !strncmp(®->name[1], cur_bank, strlen(cur_bank))) return 1;
- if (new_bank && new_bank[0] == '(' && !strncmp(&new_bank[1], cur_bank, strlen(cur_bank))) return 1;
- if (cur_bank[0] == '(' && reg && reg->name && !strncmp(reg->name, &cur_bank[1], strlen(reg->name))) return 1;
- if (cur_bank[0] == '(' && new_bank && !strncmp(new_bank, &cur_bank[1], strlen(new_bank))) return 1;
-
- // XXX: identify '(regname + X)' and '(regname + Y)'
-
- return ((reg && reg->name && !strcmp(reg->name, cur_bank)) || (new_bank && !strcmp(new_bank, cur_bank)));
+ if (previous_reg && reg && previous_reg->isFixed && reg->isFixed && ((previous_reg->address & max_mask) == (reg->address & max_mask))) // only if exists
+ return 1; // if we have address info, we use it for banksel optimization
+
+ // regard '(regname + X)' and '(regname + Y)' as equal
+ if (reg && reg->name && bankCompare(reg->name, cur_bank)) return 1;
+ if (new_bank && bankCompare(new_bank, cur_bank)) return 1;
+
+ // check allocation policy from glue.c
+ if (reg && reg->name && pic14_operandsAllocatedInSameBank(reg->name, cur_bank)) return 1;
+ if (new_bank && pic14_operandsAllocatedInSameBank(new_bank, cur_bank)) return 1;
+
+ // seems to be a different operand--might be a different bank
+ //printf ("BANKSEL from %s to %s/%s\n", cur_bank, reg->name, new_bank);
+ return 0;
}
/*-----------------------------------------------------------------*/
pCode *pc;
pCodeInstruction *pci;
regs *reg;
+ regs *previous_reg; // contains the previous variable access info
const char *cur_bank, *new_bank;
unsigned cur_mask, new_mask, max_mask;
int allRAMmshared;
max_mask = pic14_getPIC()->bankMask;
cur_mask = max_mask;
cur_bank = NULL;
+ previous_reg = NULL;
allRAMmshared = pic14_allRAMShared();
// this one has a label---might check bank at all jumps here...
if (isPCI(pc) && (PCI(pc)->label || PCI(pc)->op == POC_CALL)) {
addpCodeComment(pc->prev, "BANKOPT3 drop assumptions: PCI with label or call found");
+ previous_reg = NULL;
cur_bank = NULL; // start new flow
cur_mask = max_mask;
}
// this one is/might be a label or BANKSEL---assume nothing
if (isPCL(pc) || isPCASMDIR(pc)) {
addpCodeComment(pc->prev, "BANKOPT4 drop assumptions: label or ASMDIR found");
+ previous_reg = NULL;
cur_bank = NULL;
cur_mask = max_mask;
}
new_mask = 0; // unknown, assume worst case
} else {
assert(!"Could not get register from instruction.");
+ new_bank = "UNKNOWN";
+ new_mask = 0; // unknown, assume worst case
}
// optimizations...
// is in (as well as the previous registers)
cur_mask &= new_mask;
- if (sameBank(reg, new_bank, cur_bank)) {
+ if (sameBank(reg, previous_reg, new_bank, cur_bank, max_mask)) {
// no BANKSEL required
addpCodeComment(pc->prev, "BANKOPT2 BANKSEL dropped; %s present in same bank as %s", new_bank, cur_bank);
continue;
cur_mask = new_mask;
cur_bank = new_bank;
+ previous_reg = reg;
insertBankSel(pci, cur_bank);
} // if
} // if
{
pCode *pc; pCodeLabel *pcl;
- if(!pb)
+ if(!pb || !pb->pcHead)
return;
for(pc = pb->pcHead; (pc=findNextInstruction(pc->next)) != NULL; ) {
/*-----------------------------------------------------------------*/
/* InitRegReuse - Initialises variables for code analyzer */
/*-----------------------------------------------------------------*/
-
void InitReuseReg(void)
{
/* Find end of statically allocated variables for start idx */
/*-----------------------------------------------------------------*/
/*-----------------------------------------------------------------*/
-static unsigned register_reassign(pBlock *pb, unsigned idx)
+static unsigned register_reassign(pBlock *pb, unsigned idx, unsigned level)
{
- pCode *pc;
-
- /* check recursion */
- pc = setFirstItem(pb->function_entries);
- if(!pc)
- return idx;
-
- pb->visited = 1;
-
- 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++;
- if (peakIdx < idx) peakIdx = 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);
- }
- }
- }
+ pCode *pc;
+
+ /* check recursion */
+ pc = setFirstItem(pb->function_entries);
+ if(!pc)
+ return idx;
+
+ if (pb->visited) {
+ /* TODO: Recursion detection missing, should emit a warning as recursive code will fail. */
+ return idx;
+ }
+
+ pb->visited = 1;
+
+ DFPRINTF((stderr," (%u) reassigning registers for function \"%s\"\n",level,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];
+ set *regset;
+ // make sure, idx is not yet used in this routine...
+ do {
+ regset = pb->tregisters;
+ // do not touch s->curr ==> outer loop!
+ while (regset && ((regs *)regset->item)->rIdx != idx) {
+ regset = regset->next;
+ }
+ if (regset) idx++;
+ } while (regset);
+ r->rIdx = idx++;
+ if (peakIdx < idx) peakIdx = idx;
+ sprintf(s,"r0x%02X", r->rIdx);
+ DFPRINTF((stderr," (%u) reassigning register %p \"%s\" to \"%s\"\n",level,r,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);
- }
- }
-
+ }
+ 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) {
+ /* This index increment from subroutines is not required, as all subroutines
+ * may share registers NOT used by this one (< idx).
+ * BUT if called functions A and B share a register, which gets assigned
+ * rIdx = idx + 4 while analyzing A, we must not assign idx + 4 again while
+ * analyzing B!
+ * As an alternative to this "solution" we could check above whether an
+ * to-be-assigned rIdx is already present in the register set of the
+ * current function. This would increase the reused registers and make this
+ * `idx =' irrelevant.
+ * UPDATE: Implemented above; not fast, but works.
+ * (Problem shown with regression test src/regression/sub2.c)
+ */
+ /*idx = */register_reassign(pcn->pb,idx,level+1);
+ }
}
-
- return idx;
+ }
+
+ return idx;
}
/*------------------------------------------------------------------*/
void ReuseReg(void)
{
pBlock *pb;
- if (!the_pFile) return;
+ if (options.noOverlay || !the_pFile) return;
InitReuseReg();
for(pb = the_pFile->pbHead; pb; pb = pb->next) {
/* Non static functions can be called from other modules so their registers must reassign */
- if (pb->function_entries&&(PCF(setFirstItem(pb->function_entries))->isPublic||!pb->visited))
- register_reassign(pb,peakIdx);
+ if (pb->function_entries && (PCF(setFirstItem(pb->function_entries))->isPublic || !pb->visited))
+ register_reassign(pb,peakIdx,0);
}
}