- //fprintf(stderr,"pCodeOptime2pCodes\n");
- //pc1->print(stderr,pc1);
- //pc2->print(stderr,pc2);
-
- if((PCI(pc1)->op == POC_CLRF) && (PCI(pc2)->op == POC_MOVFW) ){
- pCode *pc;
- int regUsed = 0;
- int wUsed = 0;
- int wSaved = 0;
- int wChgd = 0;
-
- /*
- clrf reg
- stuff...
- movf reg,w
-
- can be replaced with (only if next instructions are not going to use W and reg is not used again later)
-
- stuff...
- movlw 0 or clrf reg
- */
-
- pCode *newpc;
- DFPRINTF((stderr, " optimising CLRF reg ... MOVF reg,W to ... MOVLW 0\n"));
- pct1 = pc = findNextInstruction(pc2->next);
-
- if(PCI(pct1)->op == POC_MOVWF) {
- wSaved = wUsed = 1; /* Maybe able to replace with clrf pc2->next->reg. */
- pc = findNextInstruction(pc->next);
- }
- for (; pc; pc = findNextInstruction(pc->next)) {
- if (isPCI(pc)) {
- regs *r;
- if (!wChgd) {
- if (PCI(pc)->inCond & PCC_W)
- wUsed = 1;
- if (PCI(pc)->outCond & PCC_W) {
- pCode *pcp = findPrevInstruction(pc);
- if (pcp && !isPCI_SKIP(pcp)) {
- wChgd = 1; /* W has changed so we no longer care if it is used, however if there is a preceding skip instruction then maybe current W is still going to be used */
- if (regUsed)
- break;
- }
- }
- }
- r = getRegFromInstruction(pc); /* Check if reg is used later. */
- if (r && (r->rIdx==reg->rIdx)) {
- if (!(PCI(pc)->outCond & PCC_REGISTER))
- regUsed = 1;
- if (wChgd)
- break;
- }
- }
- }
- if(regUsed&&wUsed) {
- /* Do not optimise as exisiting code is required. */
- } else {
- /* Can optimise. */
- if(regUsed) {
- newpc = newpCode(POC_CLRF, PCI(pc1)->pcop);
- } else if(wSaved && !wUsed) {
- newpc = newpCode(POC_CLRF, PCI(pct1)->pcop);
- pct1->destruct(pct1);
- } else {
- newpc = newpCode(POC_MOVLW, newpCodeOpLit(0));
- }
-
- pCodeInsertAfter(pc2, newpc);
- PCI(newpc)->pcflow = PCFL(pcfl_used);
- newpc->seq = pc2->seq;
-
- Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
- total_registers_saved++; // debugging stats.
- }
- } else if((PCI(pc1)->op == POC_CLRF) && (PCI(pc2)->op == POC_IORFW) ){
- DFPRINTF((stderr, " optimising CLRF/IORFW\n"));
-
- pct2 = findNextInstruction(pc2->next);
-
- if(pCodeSearchCondition(pct2, PCC_Z) > 0) {
- pct2 = newpCode(POC_IORLW, newpCodeOpLit(0));
- pct2->seq = pc2->seq;
- PCI(pct2)->pcflow = PCFL(pcfl_used);
- pCodeInsertAfter(pc1,pct2);
- }
- Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
- total_registers_saved++; // debugging stats.
-
- } else if(PCI(pc1)->op == POC_MOVWF) {
- // Optimising MOVWF reg ...
-
- pct2 = findNextInstruction(pc2->next);
-
- if(PCI(pc2)->op == POC_MOVFW) {
- // Optimising MOVWF reg ... MOVF reg,W
-
- if(PCI(pct2)->op == POC_MOVWF) {
- /*
- Change:
-
- movwf reg
-
- stuff...
-
- movf reg,w
- movwf reg2
-
- To:
-
-
- */
- reg2 = getRegFromInstruction(pct2);
- if(reg2 && !regUsedinRange(pc1,pc2,reg2)) {
-
- if(pCodeSearchCondition(pct2, PCC_Z) < 1) {
- pCode *pct3 = findNextInstruction(pct2->next);
- DFPRINTF((stderr, " optimising MOVF reg ... MOVF reg,W MOVWF reg2\n"));
- pct2->seq = pc1->seq;
- unlinkpCode(pct2);
- pCodeInsertAfter(findPrevInstruction(pc1->prev),pct2);
-
-#define usesW(x) ((x) && (isPCI(x)) && ( (PCI(x)->inCond & PCC_W) != 0))
-
- if(usesW(pct3))
- ; // Remove2pcodes(pcfl_used, pc1, NULL, reg, can_free);
- else
- Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
-
- total_registers_saved++; // debugging stats.
- return 1;
- } else {
- //fprintf(stderr,"didn't optimize because Z bit is used\n");
- }
- }
-/*
- fprintf(stderr, " couldn't optimize\n");
- if(reg2)
- fprintf(stderr, " %s is used in range\n",reg2->name);
- else
- fprintf(stderr, " reg2 is NULL\n");
-*/
- }
- }
-
- pct1 = findPrevInstruction(pc1->prev);
- if(pct1 && (PCI(pct1)->pcflow == PCI(pc1)->pcflow)) {
-
- if ( (PCI(pct1)->op == POC_MOVFW) &&
- (PCI(pc2)->op == POC_MOVFW)) {
-
- reg1 = getRegFromInstruction(pct1);
- if(reg1 && !regUsedinRange(pc1,pc2,reg1)) {
- DFPRINTF((stderr, " optimising MOVF reg1,W MOVWF reg ... MOVF reg,W\n"));
- /*
- Change:
-
- movf reg1,w
- movwf reg
-
- stuff...
- movf reg,w
-
- To:
-
- stuff...
-
- movf reg1,w
-
- Or, if we're not deleting the register then the "To" is:
-
- stuff...
-
- movf reg1,w
- movwf reg
- */
- pct2 = newpCode(PCI(pc2)->op, PCI(pct1)->pcop);
- pCodeInsertAfter(pc2, pct2);
- PCI(pct2)->pcflow = PCFL(pcfl_used);
- pct2->seq = pc2->seq;
-
- if(can_free) {
- Remove2pcodes(pcfl_used, pc1, pc2, reg, can_free);
- } else {
- /* If we're not freeing the register then that means (probably)
- * the register is needed somewhere else.*/
- unlinkpCode(pc1);
- pCodeInsertAfter(pct2, pc1);
-
- Remove2pcodes(pcfl_used, pc2, NULL, reg, can_free);
- }
-
- Remove2pcodes(pcfl_used, pct1, NULL, reg1, 0);
- total_registers_saved++; // debugging stats.
-
- }
-/* Note this else if is same conditional as the if - DELETE ME
- } else if ( (PCI(pct1)->op == POC_MOVWF) &&
- (PCI(pc2)->op == POC_MOVFW)) {
- DFPRINTF(stderr, " optimising MOVF reg1,W MOVWF reg ... MOVF reg,W\n");
- if(optimize_level > 1 && can_free) {
- pct2 = newpCode(POC_MOVFW, PCI(pc1)->pcop);
- pCodeInsertAfter(pc2, pct2);
- Remove2pcodes(pcfl_used, pc1, pc2, reg, 1);
- total_registers_saved++; // debugging stats.
- }
-*/
- }
- }
+ /* disable this optimization for now -- it's buggy */
+ if(pic14_options.disable_df) return 0;
+
+ //fprintf(stderr,"pCodeOptime2pCodes\n");
+ //pc1->print(stderr,pc1);
+ //pc2->print(stderr,pc2);
+
+ if((PCI(pc1)->op == POC_CLRF) && (PCI(pc2)->op == POC_MOVFW) ){
+ pCode *newpc;
+ int regUsed = 0;
+ int wUsed = 0;
+ int wSaved = 0;
+ /*
+ clrf reg ; pc1
+ stuff...
+ movf reg,w ; pc2
+
+ can be replaced with (only if following instructions are not going to use W and reg is not used again later)
+
+ stuff...
+ movlw 0 or clrf reg
+ */
+ DFPRINTF((stderr, " optimising CLRF reg ... MOVF reg,W to ... MOVLW 0\n"));
+ pct2 = findNextInstruction(pc2->next);
+
+ if(pct2 && PCI(pct2)->op == POC_MOVWF) {
+ wSaved = wUsed = 1; /* Maybe able to replace with clrf pc2->next->reg. */
+ } else {
+ wUsed = pCodeSearchCondition(pct2,PCC_W,1) != -1;
+ }
+ regUsed = regUsedinRange(pct2,0,reg);
+ if ((regUsed&&wUsed) || (pCodeSearchCondition(pct2,PCC_Z,0) != -1)) {
+ /* Do not optimise as exisiting code is required. */
+ } else {
+ /* Can optimise. */
+ if(regUsed) {
+ newpc = newpCode(POC_CLRF, PCI(pc1)->pcop);
+ } else if(wSaved && !wUsed) {
+ newpc = newpCode(POC_CLRF, PCI(pct2)->pcop);
+ pct2->destruct(pct2);
+ } else {
+ newpc = newpCode(POC_MOVLW, newpCodeOpLit(0));
+ }
+
+ pCodeInsertAfter(pc2, newpc);
+ 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.
+ }
+ } else if((PCI(pc1)->op == POC_CLRF) && (PCI(pc2)->op == POC_IORFW) ){
+ DFPRINTF((stderr, " optimising CLRF/IORFW\n"));
+
+ pct2 = findNextInstruction(pc2->next);
+
+ /* We must ensure that is destroyed before being read---IORLW must be performed unless this is proven. */
+ if(pCodeSearchCondition(pct2, PCC_Z,0) != -1) {
+ pct2 = newpCode(POC_IORLW, newpCodeOpLit(0));
+ pct2->seq = pc2->seq;
+ 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.
+
+ } else if(PCI(pc1)->op == POC_MOVWF) {
+ // Optimising MOVWF reg ...
+
+ pct2 = findNextInstruction(pc2->next);
+
+ if(PCI(pc2)->op == POC_MOVFW) {
+ // Optimising MOVWF reg ... MOVF reg,W
+
+ if(PCI(pct2)->op == POC_MOVWF) {
+ /*
+ Change:
+
+ movwf reg ; pc1
+ stuff...
+ movf reg,w ; pc2
+ movwf reg2 ; pct2
+
+ To: ( as long as 'stuff' does not use reg2 or if following instructions do not use W or reg is not used later)
+
+ movwf reg2
+ stuff...
+
+ */
+ reg2 = getRegFromInstruction(pct2);
+ /* Check reg2 is not used for something else before it is loaded with reg */
+ 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 */
+ /* XXX: We must ensure that this value is destroyed before use---otherwise it might be used in
+ * subsequent flows (checking for < 1 is insufficient). */
+ if ((pCodeSearchCondition(pct3,PCC_Z,0) == -1) && (pCodeSearchCondition(pct3,PCC_W,0) == -1)) {
+ DFPRINTF((stderr, " optimising MOVF reg ... MOVF reg,W MOVWF reg2 to MOVWF reg2 ...\n"));
+ pct2->seq = pc1->seq;
+ 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 {
+ //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;
+ }
+ }
+ }
+ }
+
+ pct1 = findPrevInstruction(pc1->prev);
+ if(pct1 && (PCI(pct1)->pcflow == PCI(pc1)->pcflow)) {
+
+ if ( (PCI(pct1)->op == POC_MOVFW) &&
+ (PCI(pc2)->op == POC_MOVFW)) {
+
+ reg1 = getRegFromInstruction(pct1);
+ if(reg1 && !regIsSpecial (reg1, 0) && !regUsedinRange(pc1,pc2,reg1)) {
+ DFPRINTF((stderr, " optimising MOVF reg1,W MOVWF reg ... MOVF reg,W\n"));
+ /*
+ Change:
+
+ movf reg1,w
+ movwf reg
+
+ stuff...
+ movf reg,w
+
+ To:
+
+ stuff...
+
+ movf reg1,w
+
+ Or, if we're not deleting the register then the "To" is:
+
+ stuff...
+
+ movf reg1,w
+ movwf reg
+ */
+ pct2 = newpCode(PCI(pc2)->op, PCI(pct1)->pcop);
+ pCodeInsertAfter(pc2, pct2);
+ PCI(pct2)->pcflow = PCFL(pcfl_used);
+ 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)
+ * the register is needed somewhere else.*/
+ 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.
+
+ }
+ }
+ }