more about genUnpackBits
[fw/sdcc] / src / mcs51 / gen.c
index 2dfdd90de4ebc44b3b7c2b966d1b154fe96dac7b..c9b86b9725967ccc04255d6728639214d3f45a9e 100644 (file)
@@ -2412,7 +2412,7 @@ static void
 saveRBank (int bank, iCode * ic, bool pushPsw)
 {
   int i;
-  int count = mcs51_nRegs + (pushPsw ? 1 : 0);
+  int count = 8 + ((mcs51_nRegs > 8) ? 1 : 0) + (pushPsw ? 1 : 0);
   asmop *aop = NULL;
   regs *r = NULL;
 
@@ -2435,7 +2435,7 @@ saveRBank (int bank, iCode * ic, bool pushPsw)
       emitcode ("mov", "%s,a", spname);
     }
 
-  for (i = 0; i < mcs51_nRegs; i++)
+  for (i = 0; i < 8; i++)
     {
       if (options.useXstack)
         {
@@ -2450,6 +2450,22 @@ saveRBank (int bank, iCode * ic, bool pushPsw)
                   regs8051[i].base, 8 * bank + regs8051[i].offset);
     }
 
+  if (mcs51_nRegs > 8)
+    {
+      if (options.useXstack)
+        {
+          emitcode ("mov", "a,bits");
+          emitcode ("movx", "@%s,a", r->name);
+          if (--count)
+            emitcode ("inc", "%s", r->name);
+        }
+      else
+        {
+          emitcode ("push", "bits");
+        }
+      BitBankUsed = 1;
+    }
+
   if (pushPsw)
     {
       if (options.useXstack)
@@ -2516,7 +2532,21 @@ unsaveRBank (int bank, iCode * ic, bool popPsw)
         }
     }
 
-  for (i = (mcs51_nRegs - 1); i >= 0; i--)
+  if (mcs51_nRegs > 8)
+    {
+      if (options.useXstack)
+        {
+          emitcode ("dec", "%s", r->name);
+          emitcode ("movx", "a,@%s", r->name);
+          emitcode ("mov", "bits,a");
+        }
+      else
+        {
+          emitcode ("pop", "bits");
+        }
+    }
+
+  for (i = 7; i >= 0; i--)
     {
       if (options.useXstack)
         {
@@ -4471,9 +4501,20 @@ genMinusDec (iCode * ic)
      same */
   if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
     {
+      char *l;
+
+      if (aopGetUsesAcc (IC_LEFT (ic), 0))
+        {
+          MOVA (aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
+          l = "a";
+        }
+      else
+        {
+          l = aopGet (IC_RESULT (ic), 0, FALSE, FALSE);
+        }
 
       while (icount--)
-        emitcode ("dec", "%s", aopGet (IC_RESULT (ic), 0, FALSE, FALSE));
+        emitcode ("dec", "%s", l);
 
       if (AOP_NEEDSACC (IC_RESULT (ic)))
         aopPut (IC_RESULT (ic), "a", 0, isOperandVolatile (IC_RESULT (ic), FALSE));
@@ -8205,9 +8246,8 @@ shiftR2Left2Result (operand * left, int offl,
       movLeft2Result (left, offl, result, offr, 0);
       pushedB = pushB ();
       usedB = TRUE;
-      emitcode ("mov", "b,%s", aopGet (left, offl + MSB16, FALSE, FALSE));
-      MOVA (aopGet (result, offr, FALSE, FALSE));
-      emitcode ("xch", "a,b");
+      emitcode ("mov", "b,%s", aopGet (result, offr, FALSE, FALSE));
+      MOVA (aopGet (left, offl + MSB16, FALSE, FALSE));
       x = "b";
     }
   else
@@ -8223,7 +8263,9 @@ shiftR2Left2Result (operand * left, int offl,
     AccAXRsh (x, shCount);
   if (usedB)
     {
-      aopPut (result, "b", offr, isOperandVolatile (result, FALSE));
+      emitcode ("xch", "a,b");
+      aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
+      emitcode ("xch", "a,b");
       popB (pushedB);
     }
   if (getDataSize (result) > 1)
@@ -8241,7 +8283,16 @@ shiftLLeftOrResult (operand * left, int offl,
   /* shift left accumulator */
   AccLsh (shCount);
   /* or with result */
-  emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
+  if (aopGetUsesAcc (result, offr))
+    {
+      emitcode ("xch", "a,b");
+      MOVA (aopGet (result, offr, FALSE, FALSE));
+      emitcode ("orl", "a,b");
+    }
+  else
+    {
+      emitcode ("orl", "a,%s", aopGet (result, offr, FALSE, FALSE));
+    }
   /* back to result */
   aopPut (result, "a", offr, isOperandVolatile (result, FALSE));
 }
@@ -8693,7 +8744,7 @@ static void
 shiftRLong (operand * left, int offl,
             operand * result, int sign)
 {
-  int isSameRegs=sameRegs(AOP(left),AOP(result));
+  int isSameRegs = sameRegs (AOP (left), AOP (result));
 
   if (isSameRegs && offl>1) {
     // we are in big trouble, but this shouldn't happen
@@ -9256,6 +9307,15 @@ genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
       emitPtrByteGet (rname, ptype, FALSE);
       AccRsh (bstr);
       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8 - blen));
+      if (!SPEC_USIGN (etype))
+        {
+          /* signed bitfield */
+          symbol *tlbl = newiTempLabel (NULL);
+
+          emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
+          emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << blen));
+          emitcode ("", "%05d$:", tlbl->key + 100);
+        }
       aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
       goto finish;
     }
@@ -9275,15 +9335,36 @@ genUnpackBits (operand * result, char *rname, int ptype, iCode *ifx)
     {
       emitPtrByteGet (rname, ptype, FALSE);
       emitcode ("anl", "a,#0x%02x", ((unsigned char) -1) >> (8-rlen));
+      if (!SPEC_USIGN (etype))
+        {
+          /* signed bitfield */
+          symbol *tlbl = newiTempLabel (NULL);
+
+          emitcode ("jnb", "acc.%d,%05d$", blen - 1, tlbl->key + 100);
+          emitcode ("orl", "a,#0x%02x", (unsigned char) (0xff << rlen));
+          emitcode ("", "%05d$:", tlbl->key + 100);
+        }
       aopPut (result, "a", offset++, isOperandVolatile (result, FALSE));
     }
 
 finish:
   if (offset < rsize)
     {
+      char *source;
+
+      if (SPEC_USIGN (etype))
+        source = zero;
+      else
+        {
+          /* signed bitfield: sign extension with 0x00 or 0xff */
+          emitcode ("rlc", "a");
+          emitcode ("subb", "a,acc");
+
+          source = "a";
+        }
       rsize -= offset;
       while (rsize--)
-        aopPut (result, zero, offset++, isOperandVolatile (result, FALSE));
+        aopPut (result, source, offset++, isOperandVolatile (result, FALSE));
     }
 }