* src/SDCCast.c (backPatchLabels): fixed bug #1504636
[fw/sdcc] / src / hc08 / gen.c
index c364471101b43dac26be1cd2d49b26f777b7fd77..7b6009ed9db405edb252b718b269cac542decc8d 100644 (file)
@@ -839,7 +839,10 @@ storeRegToAop (regs *reg, asmop *aop, int loffset)
 
   if (aop->type == AOP_DUMMY)
     return;
-    
+
+  if (aop->type == AOP_CRY) /* This can only happen if IFX was optimized */
+    return;                 /* away, so just toss the result */
+
   switch (regidx)
     {
       case A_IDX:
@@ -1144,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])
@@ -1173,7 +1177,7 @@ transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs)
       if (srcaop->type == AOP_LIT)
         {
           unsigned long lit;
-          unsigned char bytemask;
+          unsigned long bytemask;
           
           lit = (unsigned long) floatFromVal (srcaop->aopu.aop_lit);
           bytemask = (lit >> (srcofs*8)) & 0xff;
@@ -1798,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;
@@ -2169,6 +2181,14 @@ asmopToBool (asmop *aop, bool resultInA)
             flagsonly = FALSE;
           }
         break;
+      case AOP_LIT:
+        /* Higher levels should optimize this case away but let's be safe */
+        if ((unsigned long) floatFromVal (aop->aopu.aop_lit))
+          loadRegFromConst (hc08_reg_a, one);
+        else
+          loadRegFromConst (hc08_reg_a, zero);
+        hc08_freeReg(hc08_reg_a);
+        break;
       default:
         if (size==1)
           {
@@ -3325,7 +3345,7 @@ release:
 }
 
 /*-----------------------------------------------------------------*/
-/* genMinusDec :- does subtraction with deccrement if possible     */
+/* genMinusDec :- does subtraction with decrement if possible      */
 /*-----------------------------------------------------------------*/
 static bool
 genMinusDec (iCode * ic)
@@ -3546,7 +3566,7 @@ genMultOneByte (operand * left,
   /* left unsigned, right signed literal -- literal determines sign handling */
   if (AOP_TYPE(right)==AOP_LIT && lUnsigned && !rUnsigned)
     {
-      signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
+      signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
       
       loadRegFromAop (hc08_reg_a, AOP (left), 0);
       if (val < 0)
@@ -3590,7 +3610,7 @@ genMultOneByte (operand * left,
 
   if (AOP_TYPE(right)==AOP_LIT && !rUnsigned)
     {
-      signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
+      signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
       /* AND literal negative */
       if (val < 0) {
         emitcode ("ldx", "#0x%02x", -val);
@@ -6495,9 +6515,7 @@ genLeftShift (iCode * ic)
   operand *left, *right, *result;
   int size, offset;
   symbol *tlbl, *tlbl1;
-//  int i;
   char *shift;
-  regs *reg;
 
   D(emitcode (";     genLeftShift",""));
 
@@ -6521,14 +6539,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--)
@@ -6544,10 +6564,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);
   
@@ -6557,12 +6575,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);
 }
 
 /*-----------------------------------------------------------------*/
@@ -6814,7 +6833,6 @@ genRightShift (iCode * ic)
   operand *right, *left, *result;
   sym_link *retype;
   int size, offset;
-//  char *l;
   symbol *tlbl, *tlbl1;
   char *shift;
   bool sign;
@@ -6853,19 +6871,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);
@@ -6874,8 +6898,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--)
     {
@@ -6883,11 +6908,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);
 }
 
@@ -7695,6 +7720,30 @@ genIfx (iCode * ic, iCode * popIc)
 
   aopOp (cond, ic, FALSE);
 
+  /* If the condition is a literal, we can just do an unconditional */
+  /* branch or no branch */
+  if (AOP_TYPE (cond) == AOP_LIT)
+    {
+      unsigned long lit = (unsigned long) floatFromVal (AOP (cond)->aopu.aop_lit);
+      freeAsmop (cond, NULL, ic, TRUE);
+
+      /* if there was something to be popped then do it */
+      if (popIc)
+        genIpop (popIc);
+      if (lit)
+        {
+          if (IC_TRUE (ic))
+            emitBranch ("jmp", IC_TRUE (ic));
+        }
+      else
+        {
+          if (IC_FALSE (ic))
+            emitBranch ("jmp", IC_FALSE (ic));
+        }
+      ic->generated = 1;
+      return;
+    }
+
   /* get the value into acc */
   if (AOP_TYPE (cond) != AOP_CRY)
     asmopToBool (AOP (cond), FALSE);