* device/lib/libsdcc.lib: added module rand
[fw/sdcc] / src / hc08 / gen.c
index 3b834a005fe12c559119fd6dbaccf862e07f20f9..2897a99541cdfeaecc10c23c2eb0e211f37dce2e 100644 (file)
@@ -27,8 +27,8 @@
 
 -------------------------------------------------------------------------*/
 
-#define D(x)
-//#define D(x) x
+//#define D(x)
+#define D(x) x
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -1147,7 +1147,8 @@ transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs)
   /* ignore transfers at the same byte, unless its volatile */
   if (srcaop->op && !isOperandVolatile (srcaop->op, FALSE)
       && dstaop->op && !isOperandVolatile (dstaop->op, FALSE)
-      && operandsEqu(srcaop->op, dstaop->op) && srcofs == dstofs)
+      && operandsEqu(srcaop->op, dstaop->op) && srcofs == dstofs
+      && dstaop->type == srcaop->type)
     return;
       
   if (srcaop->stacked && srcaop->stk_aop[srcofs])
@@ -1801,14 +1802,22 @@ aopOp (operand * op, iCode * ic, bool result)
       /* else spill location  */
       if (sym->usl.spillLoc)
         {
+          asmop *oldAsmOp = NULL;
+
           if (sym->usl.spillLoc->aop
               && sym->usl.spillLoc->aop->size != getSize (sym->type))
             {
              /* force a new aop if sizes differ */
+              oldAsmOp = sym->usl.spillLoc->aop;
              sym->usl.spillLoc->aop = NULL;
              //printf ("forcing new aop\n");
             }
          sym->aop = op->aop = aop = aopForSym (ic, sym->usl.spillLoc, result);
+          if (sym->usl.spillLoc->aop->size != getSize (sym->type))
+            {
+              /* Don't reuse the new aop, go with the last one */
+              sym->usl.spillLoc->aop = oldAsmOp;
+            }
          aop->size = getSize (sym->type);
          aop->op = op;
          aop->isaddr = op->isaddr;
@@ -6300,7 +6309,7 @@ genlshTwo (operand * result, operand * left, int shCount)
 
 /*-----------------------------------------------------------------*/
 /* shiftLLong - shift left one long from left to result            */
-/* offl = LSB or MSB16                                             */
+/* offr = LSB or MSB16                                             */
 /*-----------------------------------------------------------------*/
 static void
 shiftLLong (operand * left, operand * result, int offr)
@@ -6317,10 +6326,10 @@ shiftLLong (operand * left, operand * result, int offr)
   loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
   rmwWithReg ("lsl", hc08_reg_a);
   rmwWithReg ("rol", hc08_reg_x);
-  storeRegToAop (hc08_reg_xa, AOP (result), offr);
 
   if (offr==LSB)
     {
+      storeRegToAop (hc08_reg_xa, AOP (result), offr);
       loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
       rmwWithReg ("rol", hc08_reg_a);
       rmwWithReg ("rol", hc08_reg_x);
@@ -6328,7 +6337,9 @@ shiftLLong (operand * left, operand * result, int offr)
     }
   else if (offr==MSB16)
     {
+      storeRegToAop (hc08_reg_a, AOP (result), offr);
       loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
+      storeRegToAop (hc08_reg_x, AOP (result), offr+1);
       rmwWithReg ("rol", hc08_reg_a);
       storeRegToAop (hc08_reg_a, AOP (result), offr+2);
       storeConstToAop (zero, AOP (result), 0);
@@ -6506,9 +6517,7 @@ genLeftShift (iCode * ic)
   operand *left, *right, *result;
   int size, offset;
   symbol *tlbl, *tlbl1;
-//  int i;
   char *shift;
-  regs *reg;
 
   D(emitcode (";     genLeftShift",""));
 
@@ -6532,14 +6541,16 @@ genLeftShift (iCode * ic)
      more that 32 bits make no sense anyway, ( the
      largest size of an object can be only 32 bits ) */
 
-  aopOp (left, ic, FALSE);
   aopOp (result, ic, FALSE);
+  aopOp (left, ic, FALSE);
+
+  if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
+    AOP (result) = forceStackedAop (AOP (result));
 
   /* now move the left to the result if they are not the
      same */
   if (!sameRegs (AOP (left), AOP (result)))
     {
-
       size = AOP_SIZE (result);
       offset = 0;
       while (size--)
@@ -6555,10 +6566,8 @@ genLeftShift (iCode * ic)
   offset = 0;
   tlbl1 = newiTempLabel (NULL);
 
-  reg = hc08_reg_a;
-
-  loadRegFromAop (reg, AOP (right), 0);
-  freeAsmop (right, NULL, ic, TRUE);
+  loadRegFromAop (hc08_reg_x, AOP (right), 0);
+  emitcode ("tstx", "");
   emitBranch ("beq", tlbl1);
   emitLabel (tlbl);
   
@@ -6568,12 +6577,13 @@ genLeftShift (iCode * ic)
       rmwWithAop (shift, AOP (result), offset);  
       shift="rol";
     }
-  rmwWithReg ("dec", reg);
+  rmwWithReg ("dec", hc08_reg_x);
   emitBranch ("bne", tlbl);
   emitLabel (tlbl1);
-  hc08_freeReg (reg);
+  hc08_freeReg (hc08_reg_x);
   
   freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (right, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
@@ -6650,6 +6660,7 @@ shiftRLong (operand * left, int offl,
         rmwWithReg ("lsr", hc08_reg_x);
       rmwWithReg ("ror", hc08_reg_a);
       storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
+      loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
     }
   else if (offl==MSB16)
     {
@@ -6658,15 +6669,27 @@ shiftRLong (operand * left, int offl,
         rmwWithReg ("asr", hc08_reg_a);
       else
         rmwWithReg ("lsr", hc08_reg_a);
+      loadRegFromAop (hc08_reg_x, AOP (left), MSB24);
       storeRegToAop (hc08_reg_a, AOP (result), MSB24);
-      storeRegSignToUpperAop (hc08_reg_a, AOP (result), MSB32, sign);
+      loadRegFromAop (hc08_reg_a, AOP (left), MSB16);
     }
 
-  loadRegFromAop (hc08_reg_xa, AOP (left), offl);
   rmwWithReg ("ror", hc08_reg_x);
   rmwWithReg ("ror", hc08_reg_a);
   storeRegToAop (hc08_reg_xa, AOP (result), LSB);
 
+  if (offl==MSB16)
+    {
+      if (sign)
+        {
+          loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
+          storeRegSignToUpperAop (hc08_reg_a, AOP (result), MSB32, sign);
+        }
+      else
+        {
+          storeConstToAop (zero, AOP (result), MSB32);
+        }
+    }
 
   pullOrFreeReg (hc08_reg_x, needpulx);
   pullOrFreeReg (hc08_reg_a, needpula);
@@ -6825,7 +6848,6 @@ genRightShift (iCode * ic)
   operand *right, *left, *result;
   sym_link *retype;
   int size, offset;
-//  char *l;
   symbol *tlbl, *tlbl1;
   char *shift;
   bool sign;
@@ -6864,19 +6886,25 @@ genRightShift (iCode * ic)
      more that 32 bits make no sense anyway, ( the
      largest size of an object can be only 32 bits ) */
 
-  aopOp (left, ic, FALSE);
   aopOp (result, ic, FALSE);
+  aopOp (left, ic, FALSE);
 
   if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
     AOP (result) = forceStackedAop (AOP (result));
   
-  size = AOP_SIZE (result); 
-  offset = size-1;
-  while (size--)
+  /* now move the left to the result if they are not the
+     same */
+  if (!sameRegs (AOP (left), AOP (result)))
     {
-      transferAopAop (AOP (left), offset, AOP (result), offset);
-      offset--;
+      size = AOP_SIZE (result); 
+      offset = 0;
+      while (size--)
+        {
+          transferAopAop (AOP (left), offset, AOP (result), offset);
+          offset++;
+        }
     }
+  freeAsmop (left, NULL, ic, TRUE);
   
   tlbl = newiTempLabel (NULL);
   size = AOP_SIZE (result);
@@ -6885,8 +6913,9 @@ genRightShift (iCode * ic)
 
   loadRegFromAop (hc08_reg_x, AOP (right), 0);
   emitcode ("tstx", "");
-  emitcode ("beq", "%05d$", tlbl1->key + 100);
-  emitcode ("", "%05d$:", tlbl->key + 100);
+  emitBranch ("beq", tlbl1);
+  emitLabel (tlbl);
+
   shift= sign ? "asr" : "lsr";
   for (offset=size-1;offset>=0;offset--)
     {
@@ -6894,11 +6923,11 @@ genRightShift (iCode * ic)
       shift="ror";
     }
   rmwWithReg ("dec", hc08_reg_x);
-  emitcode ("bne","%05d$", tlbl->key + 100);
-  emitcode ("", "%05d$:", tlbl1->key + 100);
+  emitBranch ("bne", tlbl);
+  emitLabel (tlbl1);
+  hc08_freeReg (hc08_reg_x);
   
   freeAsmop (result, NULL, ic, TRUE);
-  freeAsmop (left, NULL, ic, TRUE);
   freeAsmop (right, NULL, ic, TRUE);
 }
 
@@ -7772,11 +7801,21 @@ genAddrOf (iCode * ic)
      variable */
   if (sym->onStack)
     {
-      /* if it has an offset then we need to compute
-         it */
+      /* if it has an offset then we need to compute it */
+      offset = _G.stackOfs + _G.stackPushes + sym->stack;
       hc08_useReg (hc08_reg_hx);
       emitcode ("tsx", "");
-      emitcode ("aix", "#%d", _G.stackOfs + _G.stackPushes +sym->stack);
+      while (offset > 127)
+        {
+          emitcode ("aix", "#127");
+          offset -= 127;
+        }
+      while (offset < -128)
+        {
+          emitcode ("aix", "#-128");
+          offset += 128;
+        }
+      emitcode ("aix", "#%d", offset);
       storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
       hc08_freeReg (hc08_reg_hx);