]> git.gag.com Git - fw/sdcc/blobdiff - src/z80/gen.c
Applied patch #2762516
[fw/sdcc] / src / z80 / gen.c
index ff07195b9d6a0a9eebe9d89c28075ad4f00b7618..b45d7a8516c2fe621b1cb7e75ce53458700e8f8e 100644 (file)
@@ -1385,28 +1385,62 @@ fetchLitPair (PAIR_ID pairId, asmop * left, int offset)
     {
       if (pairId == PAIR_HL || pairId == PAIR_IY)
         {
-          if (_G.pairs[pairId].last_type == left->type)
+          if ((_G.pairs[pairId].last_type == AOP_IMMD && left->type == AOP_IMMD) ||
+            (_G.pairs[pairId].last_type == AOP_IY && left->type == AOP_IY))
             {
               if (_G.pairs[pairId].base && !strcmp (_G.pairs[pairId].base, base))
                 {
                   if (pairId == PAIR_HL && abs (_G.pairs[pairId].offset - offset) < 3)
                     {
                       adjustPair (pair, &_G.pairs[pairId].offset, offset);
-                      return;
+                      goto adjusted;
                     }
                   if (pairId == PAIR_IY && (offset >= INT8MIN && offset <= INT8MAX))
                     {
-                      return;
+                       goto adjusted;
                     }
                 }
             }
         }
+
+      if (pairId == PAIR_HL && left->type == AOP_LIT && _G.pairs[pairId].last_type == AOP_LIT &&
+        !IS_FLOAT (left->aopu.aop_lit->type) && offset == 0 && _G.pairs[pairId].offset == 0)
+        {
+          unsigned new_low, new_high, old_low, old_high;
+          unsigned long v_new = ulFromVal (left->aopu.aop_lit);
+          unsigned long v_old = strtoul (_G.pairs[pairId].base, NULL, 0);
+          new_low = (v_new >> 0) & 0xff;
+          new_high = (v_new >> 8) & 0xff;
+          old_low = (v_old >> 0) & 0xff;
+          old_high = (v_old >> 8) & 0xff;
+
+          /* Change lower byte only. */
+          if(new_high == old_high)
+            {
+              emit2("ld l, %s", aopGet (left, 0, FALSE));
+              goto adjusted;
+            }
+          /* Change upper byte only. */
+          else if(new_low == old_low)
+            {
+              emit2("ld h, %s", aopGet (left, 1, FALSE));
+              goto adjusted;
+            }
+        }
+
+
       _G.pairs[pairId].last_type = left->type;
       _G.pairs[pairId].base = traceAlloc(&_G.trace.aops, Safe_strdup (base));
       _G.pairs[pairId].offset = offset;
     }
   /* Both a lit on the right and a true symbol on the left */
   emit2 ("ld %s,!hashedstr", pair, l);
+  return;
+
+adjusted:
+  _G.pairs[pairId].last_type = left->type;
+  _G.pairs[pairId].base = traceAlloc(&_G.trace.aops, Safe_strdup (base));
+  _G.pairs[pairId].offset = offset;
 }
 
 static PAIR_ID
@@ -1510,10 +1544,10 @@ fetchPairLong (PAIR_ID pairId, asmop * aop, iCode *ic, int offset)
           }
         else
           {
-            /* Swapping register contents within register pair */
-            if(!strcmp(aopGet (aop, offset, FALSE), _pairs[pairId].h))
+            /* Operand resides (partially) in the pair */
+            if(!strcmp(aopGet (aop, offset + 1, FALSE), _pairs[pairId].l))
               {
-                emit2 ("ld a,%s",aopGet (aop, offset + 1, FALSE));
+                emit2 ("ld a,%s", aopGet (aop, offset + 1, FALSE));
                 emit2 ("ld %s,%s", _pairs[pairId].l, aopGet (aop, offset, FALSE));
                 emit2 ("ld %s,a", _pairs[pairId].h);
               }
@@ -1649,6 +1683,14 @@ setupPair (PAIR_ID pairId, asmop * aop, int offset)
   _G.pairs[pairId].last_type = aop->type;
 }
 
+/* Can be used for local labels where Code generation takes care of spilling */
+static void
+emitLabelNoSpill (int key)
+{
+  emit2 ("!tlabeldef", key);
+  _G.lines.current->isLabel = 1;
+}
+
 static void
 emitLabel (int key)
 {
@@ -2676,7 +2718,6 @@ genIpush (iCode * ic)
         {
           fetchHL (AOP (IC_LEFT (ic)));
           emit2 ("push hl");
-          spillPair (PAIR_HL);
           _G.stack.pushed += 2;
           goto release;
         }
@@ -2684,11 +2725,9 @@ genIpush (iCode * ic)
         {
           fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 2);
           emit2 ("push hl");
-          spillPair (PAIR_HL);
           _G.stack.pushed += 2;
           fetchPairLong (PAIR_HL, AOP (IC_LEFT (ic)), ic, 0);
           emit2 ("push hl");
-          spillPair (PAIR_HL);
           _G.stack.pushed += 2;
           goto release;
         }
@@ -3599,7 +3638,7 @@ genPlusIncr (iCode * ic)
               emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
             }
         }
-      emitLabel (tlbl->key + 100);
+      emitLabelNoSpill (tlbl->key + 100);
       return TRUE;
     }
 
@@ -3651,7 +3690,7 @@ outBitAcc (operand * result)
     {
       emit2 ("!shortjp Z,!tlabel", tlbl->key + 100);
       emit2 ("ld a,!one");
-      emitLabel (tlbl->key + 100);
+      emitLabelNoSpill (tlbl->key + 100);
       outAcc (result);
     }
 }
@@ -3983,7 +4022,7 @@ genPlus (iCode * ic)
               emit2 ("ld a, b");
               emit2 ("pop bc");
             }
-          
+
         }
       emit2 ("adc a,%s", aopGet (AOP (IC_RIGHT (ic)), 1, FALSE));
       aopPut (AOP (IC_RESULT (ic)), "a", 1);
@@ -3996,7 +4035,7 @@ genPlus (iCode * ic)
       if (offset == 0)
       {
         if(size == 0 && AOP_TYPE (IC_RIGHT (ic)) == AOP_LIT && ulFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit) == 1)
-         emit2 ("inc a");
+          emit2 ("inc a");
         else
           emit2 ("add a,%s", aopGet (AOP (IC_RIGHT (ic)), offset, FALSE));
       }
@@ -4257,11 +4296,11 @@ genMultOneChar (iCode * ic)
   emit2 ("ld l,#0x00");
   emit2 ("ld d,l");
   emit2 ("ld b,#0x08");
-  emitLabel (tlbl1->key + 100);
+  emitLabelNoSpill (tlbl1->key + 100);
   emit2 ("add hl,hl");
   emit2 ("jp NC,!tlabel", tlbl2->key + 100);
   emit2 ("add hl,de");
-  emitLabel (tlbl2->key + 100);
+  emitLabelNoSpill (tlbl2->key + 100);
   emit2 ("djnz !tlabel", tlbl1->key + 100);
 
   spillPair(PAIR_HL);
@@ -4986,7 +5025,7 @@ gencjneshort (operand * left, operand * right, symbol * lbl)
             }
           else
             {
-              emit2 ("sub %s", aopGet (AOP (right), offset, FALSE));
+              emit2 ("sub a,%s", aopGet (AOP (right), offset, FALSE));
               emit2 ("jp NZ,!tlabel", lbl->key + 100);
             }
           offset++;
@@ -5010,7 +5049,7 @@ gencjneshort (operand * left, operand * right, symbol * lbl)
           emit2 ("; direct compare");
           _emitMove (_pairs[pair].l, aopGet (AOP (left), offset, FALSE));
           _moveA (aopGet (AOP (right), offset, FALSE));
-          emit2 ("sub %s", _pairs[pair].l);
+          emit2 ("sub a,%s", _pairs[pair].l);
           emit2 ("!shortjp NZ,!tlabel", lbl->key + 100);
           offset++;
         }
@@ -5034,7 +5073,7 @@ gencjne (operand * left, operand * right, symbol * lbl)
   emit2 ("!shortjp !tlabel", tlbl->key + 100);
   emitLabel (lbl->key + 100);
   emit2 ("xor a,a");
-  emitLabel (tlbl->key + 100);
+  emitLabelNoSpill (tlbl->key + 100);
   _pop (pop);
 }
 
@@ -5080,7 +5119,7 @@ genCmpEq (iCode * ic, iCode * ifx)
             {
               _pop (pop);
               emit2 ("jp !tlabel", IC_TRUE (ifx)->key + 100);
-              emitLabel (tlbl->key + 100);
+              emitLabelNoSpill (tlbl->key + 100);
               _pop (pop);
             }
           else
@@ -5089,10 +5128,10 @@ genCmpEq (iCode * ic, iCode * ifx)
               symbol *lbl = newiTempLabel (NULL);
               _pop (pop);
               emit2 ("!shortjp !tlabel", lbl->key + 100);
-              emitLabel (tlbl->key + 100);
+              emitLabelNoSpill (tlbl->key + 100);
               _pop (pop);
               emit2 ("jp !tlabel", IC_FALSE (ifx)->key + 100);
-              emitLabel (lbl->key + 100);
+              emitLabelNoSpill (lbl->key + 100);
             }
         }
       /* mark the icode as generated */
@@ -5187,7 +5226,7 @@ genAndOp (iCode * ic)
       _toBoolean (left);
       emit2 ("!shortjp Z,!tlabel", tlbl->key + 100);
       _toBoolean (right);
-      emitLabel (tlbl->key + 100);
+      emitLabelNoSpill (tlbl->key + 100);
       outBitAcc (result);
     }
 
@@ -5224,7 +5263,7 @@ genOrOp (iCode * ic)
       _toBoolean (left);
       emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
       _toBoolean (right);
-      emitLabel (tlbl->key + 100);
+      emitLabelNoSpill (tlbl->key + 100);
       outBitAcc (result);
     }
 
@@ -5266,14 +5305,14 @@ jmpTrueOrFalse (iCode * ic, symbol * tlbl)
     {
       symbol *nlbl = newiTempLabel (NULL);
       emit2 ("jp !tlabel", nlbl->key + 100);
-      emitLabel (tlbl->key + 100);
+      emitLabelNoSpill (tlbl->key + 100);
       emit2 ("jp !tlabel", IC_TRUE (ic)->key + 100);
-      emitLabel (nlbl->key + 100);
+      emitLabelNoSpill (nlbl->key + 100);
     }
   else
     {
       emit2 ("jp !tlabel", IC_FALSE (ic)->key + 100);
-      emitLabel (tlbl->key + 100);
+      emitLabelNoSpill (tlbl->key + 100);
     }
   ic->generated = 1;
 }
@@ -5356,6 +5395,7 @@ genAnd (iCode * ic, iCode * ifx)
                   /* For the flags */
                   emit2 ("or a,a");
                 }
+          if (size || ifx)  /* emit jmp only, if it is actually used */
               emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
             }
               offset++;
@@ -5539,9 +5579,19 @@ genOr (iCode * ic, iCode * ifx)
           bytelit = (lit >> (offset * 8)) & 0x0FFL;
 
           _moveA (aopGet (AOP (left), offset, FALSE));
-          /* OR with any literal is the same as OR with itself. */
-          emit2 ("or a,a");
-          emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
+
+          if (bytelit != 0)
+            { /* FIXME, allways true, shortcut possible */
+              emit2 ("or a,%s", aopGet (AOP (right), offset, FALSE));
+            }
+          else
+            {
+              /* For the flags */
+              emit2 ("or a,a");
+            }
+
+          if (ifx)  /* emit jmp only, if it is actually used */
+            emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
 
           offset++;
         }
@@ -5946,7 +5996,7 @@ shiftR2Left2Result (operand * left, int offl,
     {
       emit2 ("ld a,!immedbyte", shCount);
 
-      emitLabel (tlbl->key + 100);
+      emitLabelNoSpill (tlbl->key + 100);
 
       emitRsh2 (AOP (result), size, is_signed);
 
@@ -6020,7 +6070,7 @@ shiftL2Left2Result (operand * left, int offl,
           {
             emit2 ("ld a,!immedbyte+1", shCount);
             emit2 ("!shortjp !tlabel", tlbl1->key + 100);
-            emitLabel (tlbl->key + 100);
+            emitLabelNoSpill (tlbl->key + 100);
           }
 
         while (size--)
@@ -6040,7 +6090,7 @@ shiftL2Left2Result (operand * left, int offl,
           }
         if (shCount > 1)
           {
-            emitLabel (tlbl1->key + 100);
+            emitLabelNoSpill (tlbl1->key + 100);
             emit2 ("dec a");
             emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
           }
@@ -6359,7 +6409,7 @@ genLeftShift (iCode * ic)
      _pop (PAIR_AF);
 
   emit2 ("!shortjp !tlabel", tlbl1->key + 100);
-  emitLabel (tlbl->key + 100);
+  emitLabelNoSpill (tlbl->key + 100);
   l = aopGet (AOP (result), offset, FALSE);
 
   while (size--)
@@ -6376,7 +6426,7 @@ genLeftShift (iCode * ic)
         }
       offset++;
     }
-  emitLabel (tlbl1->key + 100);
+  emitLabelNoSpill (tlbl1->key + 100);
   emit2 ("dec a");
   emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
 
@@ -6634,7 +6684,7 @@ genRightShift (iCode * ic)
      _pop (PAIR_AF);
 
   emit2 ("!shortjp !tlabel", tlbl1->key + 100);
-  emitLabel (tlbl->key + 100);
+  emitLabelNoSpill (tlbl->key + 100);
   while (size--)
     {
       l = aopGet (AOP (result), offset--, FALSE);
@@ -6648,7 +6698,7 @@ genRightShift (iCode * ic)
           emit2 ("rr %s", l);
         }
     }
-  emitLabel (tlbl1->key + 100);
+  emitLabelNoSpill (tlbl1->key + 100);
   emit2 ("dec a");
   emit2 ("!shortjp NZ,!tlabel", tlbl->key + 100);
 
@@ -6691,7 +6741,7 @@ genUnpackBits (operand * result, int pair)
           emit2 ("bit %d,a", blen - 1);
           emit2 ("jp Z,!tlabel", tlbl->key + 100);
           emit2 ("or a,!immedbyte", (unsigned char) (0xff << blen));
-          emitLabel (tlbl->key + 100);
+          emitLabelNoSpill (tlbl->key + 100);
         }
       aopPut (AOP (result), "a", offset++);
       goto finish;
@@ -6711,11 +6761,10 @@ genUnpackBits (operand * result, int pair)
         {
           /* signed bitfield */
           symbol *tlbl = newiTempLabel (NULL);
-
-          emit2 ("bit %d,a", blen - 1);
+          emit2 ("bit %d,a", blen - 1 - 8);
           emit2 ("jp Z,!tlabel", tlbl->key + 100);
-          emit2 ("or a,!immedbyte", (unsigned char) (0xff << blen));
-          emitLabel (tlbl->key + 100);
+          emit2 ("or a,!immedbyte", (unsigned char) (0xff << (blen - 8)));
+          emitLabelNoSpill (tlbl->key + 100);
         }
       emit2 ("ld h,a");
       spillPair (PAIR_HL);
@@ -6748,7 +6797,7 @@ genUnpackBits (operand * result, int pair)
           emit2 ("bit %d,a", rlen - 1);
           emit2 ("jp Z,!tlabel", tlbl->key + 100);
           emit2 ("or a,!immedbyte", (unsigned char) (0xff << rlen));
-          emitLabel (tlbl->key + 100);
+          emitLabelNoSpill (tlbl->key + 100);
         }
       aopPut (AOP (result), "a", offset++);
     }
@@ -8085,7 +8134,7 @@ setupForMemcpy (iCode *ic, int nparams, operand **pparams)
                         {
                           fetchPair (dest[i], AOP (pparams[i]));
                           continue;
-                        }         
+                        }
                     }
                 }
             }