+2005-07-23 Raphael Neider <rneider AT web.de>
+
+ * src/pic/gen.h: added emitpcode macro for debugging
+ * src/pic/gen.c (emitpcode): renamed to emitpcode_real
+ and replace by macro adding debug information on demand
+ * (genNot): fixed to C semantics (!0 = 1; !x = 0 iff x != 0)
+ * (gencjne): tried to fix; replaced with correct (slower) code
+ * (gen{Unp,P}ackBits): fixed single bit access
+ * src/pic/pcode.c (AnalyzepCode): fixed DFPRINTF argument
+ * src/pic/pcodepeep.c (pCodeSearchCondition): fixed finding
+ previous instruction
+ * src/pic/pcoderegs.c (regIsSpecial): NEW, check whether a
+ register has to be handled with care (forbidding movement
+ of assignments/uses, removing assignments completely, ...)
+ * (pCodeOptime2pCodes): make use of regIsSpecial
+ * added lots of debugging output (commented out)
+ * src/pic/rallloc.c (deassignLRs): prevent operand registers
+ from being reused as result UNLESS it is known to work
+
2005-07-23 Maarten Brock <sourceforge.brock AT dse.nl>
* support/Util/dbuf.h: include <stddef.h> for size_t
addpCode2pBlock(pb,newpCodeLabel(NULL,key+100+labelOffset));
}
-void emitpcode(PIC_OPCODE poc, pCodeOp *pcop)
+/* gen.h defines a macro emitpcode that should be used to call emitpcode
+ * as this allows for easy debugging (ever asked the question: where was
+ * this instruction geenrated? Here is the answer... */
+void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop)
{
if(pcop)
addpCode2pBlock(pb,newpCode(poc,pcop));
/*-----------------------------------------------------------------*/
static void genNot (iCode *ic)
{
- symbol *tlbl;
+ //symbol *tlbl;
int size;
FENTRY;
goto release;
}
+ assert (!pic14_sameRegs (AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))));
size = AOP_SIZE(IC_LEFT(ic));
- if(size == 1) {
- emitpcode(POC_COMFW,popGet(AOP(IC_LEFT(ic)),0));
- emitpcode(POC_ANDLW,popGetLit(1));
- emitpcode(POC_MOVWF,popGet(AOP(IC_RESULT(ic)),0));
- goto release;
+ emitpcode(POC_CLRF,popGet(AOP(IC_RESULT(ic)),0));
+ mov2w (AOP(IC_LEFT(ic)),0);
+ while (--size > 0)
+ {
+ if (aop_isLitLike (AOP(IC_LEFT(ic))))
+ emitpcode (POC_IORLW, popGetAddr (AOP(IC_LEFT(ic)), size, 0));
+ else
+ emitpcode (POC_IORFW, popGet (AOP(IC_LEFT(ic)), size));
}
- pic14_toBoolean(IC_LEFT(ic));
-
- tlbl = newiTempLabel(NULL);
- pic14_emitcode("cjne","a,#0x01,%05d_DS_",tlbl->key+100);
- pic14_emitcode("","%05d_DS_:",tlbl->key+100);
- pic14_outBitC(IC_RESULT(ic));
+ emitSKPNZ;
+ emitpcode(POC_INCF,popGet(AOP(IC_RESULT(ic)),0));
+ goto release;
release:
/* release the aops */
/*-----------------------------------------------------------------*/
static void gencjne(operand *left, operand *right, operand *result, iCode *ifx)
{
- int size = max(AOP_SIZE(left),AOP_SIZE(right));
+ int size = min(AOP_SIZE(left),AOP_SIZE(right));
int offset = 0;
- int res_offset = 0; /* the result may be a different size then left or right */
- int res_size = AOP_SIZE(result);
- resolvedIfx rIfx;
+ //resolvedIfx rIfx;
symbol *lbl;
- unsigned long lit = 0L;
+ //unsigned long lit = 0L;
FENTRY;
if (!ifx && (!result || AOP_TYPE(result) == AOP_CRY)) {
emitpComment ("gencjne: no ifx, no (real) result -- comparison ignored");
}
DEBUGpic14_emitcode ("; ***","%s %d",__FUNCTION__,__LINE__);
DEBUGpic14_AopType(__LINE__,left,right,result);
+
+ assert (!pic14_sameRegs (AOP(left), AOP(result)));
+ assert (!pic14_sameRegs (AOP(right), AOP(result)));
+ if (AOP_SIZE(result)) {
+ for (offset = 0; offset < AOP_SIZE(result); offset++)
+ emitpcode (POC_CLRF, popGet (AOP(result), offset));
+ }
+
+ assert (AOP_SIZE(left) == AOP_SIZE(right));
+ //resolveIfx(&rIfx,ifx);
+ lbl = newiTempLabel (NULL);
+ while (size--)
+ {
+ mov2w (AOP(right),size);
+ emitpcode (POC_XORFW, popGet (AOP(left), size));
+ if (size)
+ {
+ emitSKPZ;
+ emitpcode (POC_GOTO, popGetLabel (lbl->key));
+ }
+ } // while
+ emitpLabel (lbl->key);
+ if (AOP_SIZE(result)) {
+ emitSKPNZ;
+ emitpcode (POC_INCF, popGet (AOP(result), 0));
+ } else {
+ assert (ifx);
+ genSkipz (ifx, NULL != IC_TRUE(ifx));
+ ifx->generated = 1;
+ }
+ return;
+#if 0
if(result)
+ {
DEBUGpic14_emitcode ("; ***","%s %d result is not null",__FUNCTION__,__LINE__);
- resolveIfx(&rIfx,ifx);
- lbl = newiTempLabel(NULL);
+ assert (!pic14_sameRegs (AOP(result), AOP(left)));
+ assert (!pic14_sameRegs (AOP(result), AOP(right)));
+ for (offset=0; offset < AOP_SIZE(result); offset++)
+ {
+ emitpcode (POC_CLRF, popGet (AOP(result), offset));
+ } // for offset
+ }
/* if the left side is a literal or
emitpcode(POC_GOTO,popGetLabel(lbl->key));
break;
default:
+ offset = 0;
while (size--) {
if(lit & 0xff) {
emitpcode(POC_MOVFW,popGet(AOP(left),offset));
emitSKPNZ;
emitpcode(POC_GOTO,popGetLabel(lbl->key));
offset++;
- if(res_offset < res_size-1)
- res_offset++;
lit >>= 8;
}
break;
//int lbl_key = (rIfx.condition) ? rIfx.lbl->key : lbl->key;
int lbl_key = lbl->key;
- if(result) {
- if (AOP_TYPE(result) != AOP_CRY)
- emitpcode(POC_CLRF,popGet(AOP(result),res_offset));
- //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
- }else {
+ if(!result) {
DEBUGpic14_emitcode ("; ***","%s %d -- ERROR",__FUNCTION__,__LINE__);
fprintf(stderr, "%s %d error - expecting result to be non_null\n",
__FUNCTION__,__LINE__);
/* emitpcode(POC_GOTO,popGetLabel(lbl->key)); */
/* break; */
/* default: */
+ offset = 0;
while (size--) {
int emit_skip=1;
if((AOP_TYPE(left) == AOP_DIR) &&
break;
case 1:
emitpcode(POC_DECFSZW,popGet(AOP(left),offset));
- emitpcode(POC_INCF,popGet(AOP(result),res_offset));
- //emitpcode(POC_GOTO,popGetLabel(lbl->key));
+ //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
+ emitpcode(POC_GOTO,popGetLabel(lbl->key));
emit_skip=0;
break;
case 0xff:
else
emitSKPNZ;
emitpcode(POC_GOTO,popGetLabel(lbl_key));
- //emitpcode(POC_INCF,popGet(AOP(result),res_offset));
}
if(ifx)
ifx->generated=1;
}
emit_skip++;
offset++;
- if(res_offset < res_size-1)
- res_offset++;
}
/* break; */
/* } */
} else if(AOP_TYPE(right) == AOP_REG &&
AOP_TYPE(left) != AOP_DIR){
-
+
+ offset = 0;
while(size--) {
emitpcode(POC_MOVFW,popGet(AOP(left),offset));
emitpcode(POC_XORFW,popGet(AOP(right),offset));
emitSKPZ;
emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
offset++;
- if(res_offset < res_size-1)
- res_offset++;
}
}else{
/* right is a pointer reg need both a & b */
+ offset = 0;
while(size--) {
char *l = aopGet(AOP(left),offset,FALSE,FALSE);
if(strcmp(l,"b"))
}
}
- emitpcode(POC_INCF,popGet(AOP(result),res_offset));
+ emitpcode(POC_INCF,popGet(AOP(result),0));
if(!rIfx.condition)
emitpcode(POC_GOTO,popGetLabel(rIfx.lbl->key));
if(ifx)
ifx->generated = 1;
+#endif
}
#if 0
ifx->generated=1;
} else {
pCodeOp *pcop;
-
+ int i;
+ assert (!pic14_sameRegs (AOP(result), AOP(left)));
+ for (i=0; i < AOP_SIZE(result); i++)
+ emitpcode (POC_CLRF, popGet (AOP(result), i));
if (ptype == -1) /* direct */
pcop = newpCodeOpBit(aopGet (AOP(left),0,FALSE,FALSE),bstr,0);
else
pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
emitpcode(POC_BTFSC,pcop);
- emitpcode(POC_BSF,newpCodeOpBit(aopGet(AOP(result), 0,FALSE,FALSE),bstr,0));
- if (ptype == -1) /* direct */
- pcop = newpCodeOpBit(aopGet(AOP(left),0,FALSE,FALSE),bstr,0);
- else
- pcop = newpCodeOpBit(pc_indf.pcop.name,bstr,0);
- emitpcode(POC_BTFSS,pcop);
- emitpcode(POC_BCF,newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),bstr,0));
+ emitpcode(POC_BSF,newpCodeOpBit(aopGet(AOP(result),0,FALSE,FALSE),0,0));
}
return;
}
if (blen==1) {
if (p_type == -1) {
/* Note more efficient code, of pre clearing bit then only setting it if required, can only be done if it is known that the result is not a SFR */
- emitpcode(POC_RLF,popGet(AOP(right),0));
+ emitpcode(POC_RRFW,popGet(AOP(right),0));
emitSKPC;
- emitpcode(POC_BCF,popGet(AOP(result),0));
+ emitpcode(POC_BCF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
emitSKPNC;
- emitpcode(POC_BSF,popGet(AOP(result),0));
+ emitpcode(POC_BSF,newpCodeOpBit (aopGet(AOP(result), 0, FALSE, FALSE), bstr, 0));
+ return;
} else if (p_type!=GPOINTER) {
/* Case with a bitfield length == 1 and no generic pointer
*/
#define emitSETDC emitpcode(POC_BSF, popCopyGPR2Bit(PCOP(&pc_status),PIC_DC_BIT))
int pic14_getDataSize(operand *op);
-void emitpcode(PIC_OPCODE poc, pCodeOp *pcop);
+void emitpcode_real(PIC_OPCODE poc, pCodeOp *pcop);
+#define emitpcode(poc,pcop) do { if (options.debug || debug_verbose) { emitpComment (" >>> %s:%d:%s", __FILE__, __LINE__, __FUNCTION__); } emitpcode_real(poc,pcop); } while(0)
void emitpComment (const char *fmt, ...);
void emitpLabel(int key);
void pic14_emitcode (char *inst,char *fmt, ...);
pBlockMergeLabels(pb);
AnalyzepBlock(pb);
} else {
- DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName));
+ DFPRINTF((stderr," skipping block analysis dbName=%c blockname=%c\n",dbName,getpBlock_dbName(pb)));
}
}
if(PCI(pc)->inCond & cond) {
if (contIfSkip) {
/* If previous instruction is a skip then continue search as condiction is not certain */
- pCode *pcp = findPrevInstruction(pc);
+ pCode *pcp = findPrevInstruction(pc->prev);
if (pcp && !isPCI_SKIP(pcp)) {
return 1;
}
if(PCI(pc)->outCond & cond) {
if (contIfSkip) {
/* If previous instruction is a skip then continue search as condiction is not certain */
- pCode *pcp = findPrevInstruction(pc);
+ pCode *pcp = findPrevInstruction(pc->prev);
if (pcp && !isPCI_SKIP(pcp)) {
return -1;
}
if(!reg || !pc)
return;
-
+
deleteSetItem (&(reg->reglives.usedpCodes),pc);
if(PCI(pc)->label) {
static int debug_code=99;
if(!reg)
return;
+#if 0
+ fprintf (stderr, "%s:%d(%s): %d (reg:%s)\n", __FILE__, __LINE__, __FUNCTION__, debug_code, reg ? reg->name : "???");
+ printpCode (stderr, pc1);
+ printpCode (stderr, pc2);
+#endif
//fprintf(stderr,"%s\n",__FUNCTION__);
if(pc1)
return 0;
}
+int regIsSpecial (regs *reg, int mayBeGlobal)
+{
+ if (!reg) return 0;
+
+ if (reg->type == REG_SFR || reg->type == REG_STK || (!mayBeGlobal && (reg->isPublic || reg->isExtern))) return 1;
+
+ return 0;
+}
+
/*-----------------------------------------------------------------*
* void pCodeOptime2pCodes(pCode *pc1, pCode *pc2)
*
PCI(newpc)->pcflow = PCFL(pcfl_used);
newpc->seq = pc2->seq;
+ //fprintf (stderr, "%s:%d(%s): Remove2pcodes (CLRF reg, ..., MOVF reg,W)\n", __FILE__, __LINE__, __FUNCTION__);
Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
total_registers_saved++; // debugging stats.
}
PCI(pct2)->pcflow = PCFL(pcfl_used);
pCodeInsertAfter(pc1,pct2);
}
+ //fprintf (stderr, "%s:%d(%s): Remove2pcodes (CLRF/IORFW)\n", __FILE__, __LINE__, __FUNCTION__);
Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
total_registers_saved++; // debugging stats.
*/
reg2 = getRegFromInstruction(pct2);
/* Check reg2 is not used for something else before it is loaded with reg */
- if (reg2 && !regUsedinRange(pc1,pc2,reg2)) {
+ if (reg2 && !regIsSpecial (reg2, 1) && !regUsedinRange(pc1,pc2,reg2)) {
pCode *pct3 = findNextInstruction(pct2->next);
/* Check following instructions are not relying on the use of W or the Z flag condiction */
if ((pCodeSearchCondition(pct3,PCC_Z,0) < 1) || (pCodeSearchCondition(pct3,PCC_W,0) < 1)) {
unlinkpCode(pct2);
pCodeInsertBefore(pc1,pct2);
if(regUsedinRange(pct2,0,reg))
+ {
+ //fprintf (stderr, "%s:%d(%s): Remove2pcodes IF (MOVWF reg, ..., MOVW reg,W MOVWF reg2)\n", __FILE__, __LINE__, __FUNCTION__);
Remove2pcodes(pcfl_used, pc2, NULL, reg, can_free);
- else
+ } else {
+ //fprintf (stderr, "%s:%d(%s): Remove2pcodes ELSE (MOVWF reg, ..., MOVW reg,W MOVWF reg2)\n", __FILE__, __LINE__, __FUNCTION__);
Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
-
+ }
total_registers_saved++; // debugging stats.
return 1;
}
(PCI(pc2)->op == POC_MOVFW)) {
reg1 = getRegFromInstruction(pct1);
- if(reg1 && !regUsedinRange(pc1,pc2,reg1)) {
+ if(reg1 && !regIsSpecial (reg1, 0) && !regUsedinRange(pc1,pc2,reg1)) {
DFPRINTF((stderr, " optimising MOVF reg1,W MOVWF reg ... MOVF reg,W\n"));
/*
Change:
pct2->seq = pc2->seq;
if(can_free) {
+ //fprintf (stderr, "%s:%d(%s): Remove2pcodes CANFREE (MOVF reg1,W; MOVWF reg2; MOVF reg2,W)\n", __FILE__, __LINE__, __FUNCTION__);
Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
} else {
/* If we're not freeing the register then that means (probably)
unlinkpCode(pc1);
pCodeInsertAfter(pct2, pc1);
+ //fprintf (stderr, "%s:%d(%s): Remove2pcodes ELSE (MOVF reg1,W; MOVWF reg2; MOVF reg2,W)\n", __FILE__, __LINE__, __FUNCTION__);
Remove2pcodes(pcfl_used, pc2, NULL, reg, can_free);
}
+ //fprintf (stderr, "%s:%d(%s): Remove2pcodes ALWAYS (MOVF reg1,W; MOVWF reg2; MOVF reg2,W)\n", __FILE__, __LINE__, __FUNCTION__);
Remove2pcodes(pcfl_used, pct1, NULL, reg1, 0);
total_registers_saved++; // debugging stats.
fprintf(stderr,"WARNING %s: reg %s used without being assigned\n",__FUNCTION__,reg->name);
} else {
- fprintf(stderr,"WARNING %s: reg %s assigned without being used\n",__FUNCTION__,reg->name);
+ //fprintf(stderr,"WARNING %s.1: reg %s assigned without being used\n",__FUNCTION__,reg->name);
Remove2pcodes(pcfl_assigned, pc1, pc2, reg, 1);
total_registers_saved++; // debugging stats.
}
if(used && !pcfl_used && pcfl_assigned) {
pCode *pc;
- fprintf(stderr,"WARNING %s: reg %s assigned without being used\n",__FUNCTION__,reg->name);
+ //fprintf(stderr,"WARNING %s.2: reg %s assigned without being used\n",__FUNCTION__,reg->name);
pc = setFirstItem(reg->reglives.usedpCodes);
while(pc) {
/* if it does not end here */
if (sym->liveTo > ic->seq)
continue;
-
- /* HACK: result and operand must be disjoint for POINTER_GET/LEFT_OP/RIGHT_OP */
- if (sym->liveTo == ic->seq && (POINTER_GET(ic) || ic->op == LEFT_OP || ic->op == RIGHT_OP))
+
+ /* Prevent the result from being assigned the same registers as (one)
+ * operand as many genXXX-functions fail otherwise.
+ * POINTER_GET(ic) || ic->op == LEFT_OP || ic->op == RIGHT_OP || ic->op == NOT
+ * are known to fail. */
+ if (sym->liveTo == ic->seq && IC_RESULT(ic))
{
- //piCode (ic, stderr); fprintf (stderr, " -- registers NOT deallocated\n");
- continue;
+ switch (ic->op)
+ {
+ case '=': /* assignment */
+ case BITWISEAND: /* bitwise AND */
+ case '|': /* bitwise OR */
+ case '^': /* bitwise XOR */
+ case '~': /* bitwise negate */
+ case RLC: /* rotate through carry */
+ case RRC:
+ case UNARYMINUS:
+ case '+': /* addition */
+ case '-': /* subtraction */
+ /* go ahead, these are safe to use with
+ * non-disjoint register sets */
+ break;
+
+ default:
+ /* do not release operand registers */
+ //fprintf (stderr, "%s:%u: operand not freed: ", __FILE__, __LINE__); piCode (ic, stderr); fprintf (stderr, "\n");
+ continue;
+ } // switch
}
-
+
/* if it was spilt on stack then we can
mark the stack spil location as free */
if (sym->isspilt)