* device/lib/_modsint.c,
[fw/sdcc] / src / ds390 / gen.c
index 979d993e9373525f442027e43f4c535d761dc278..315f06425e48d868c648139c8fa713dc6ff51b8e 100644 (file)
@@ -3894,7 +3894,7 @@ bool aopOp3(iCode * ic)
 {
     bool dp1InUse, dp2InUse;
     bool useDp2;
-    
+
     // First, generate the right opcode. DPTR may be used if neither left nor result are
     // of type AOP_STR.
     
@@ -3954,13 +3954,17 @@ bool aopOp3(iCode * ic)
         
     // We've op'd the left & right. So, if left or right are the same operand as result, 
     // we know aopOp will succeed, and we can just do it & bail.
-    if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)) ||
-       isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
-    {
+    if (isOperandEqual(IC_LEFT(ic),IC_RESULT(ic)))
+      {
+       aopOp (IC_RESULT (ic), ic, TRUE, AOP_USESDPTR2 (IC_LEFT (ic)));
+       return TRUE;
+      }
+    if (isOperandEqual(IC_RIGHT(ic),IC_RESULT(ic)))
+      {
 //     D(emitcode(";", "aopOp3: (left | right) & result equal"););
-       aopOp(IC_RESULT(ic),ic,TRUE, FALSE);
+       aopOp(IC_RESULT(ic),ic,TRUE, AOP_USESDPTR2 (IC_RIGHT (ic)));
        return TRUE;
-    }
+      }
     
     // Operands may be equivalent (but not equal) if they share a spill location. If
     // so, use the same DPTR or DPTR2.
@@ -4611,9 +4615,11 @@ genMultOneByte (operand * left,
                operand * result,
                iCode   * ic)
 {
-  sym_link *opetype = operandType (result);
+  int size;
   symbol *lbl;
-
+  bool runtimeSign, compiletimeSign;
+  bool lUnsigned, rUnsigned;
+  
 
   /* (if two literals: the value is computed before) */
   /* if one literal, literal on the right */
@@ -4625,105 +4631,197 @@ genMultOneByte (operand * left,
       emitcode (";", "swapped left and right");
     }
 
-  if (SPEC_USIGN(opetype)
-      // ignore the sign of left and right, what else can we do?
-      || (SPEC_USIGN(operandType(left)) && 
-         SPEC_USIGN(operandType(right)))) {
-    // just an unsigned 8*8=8/16 multiply
-    //emitcode (";","unsigned");
-    emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
-    MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
-    emitcode ("mul", "ab");
-   
-    _G.accInUse++; _G.bInUse++;
-    aopOp(result, ic, TRUE, FALSE);
-      
-      if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
-      {
-         // this should never happen
-         fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
-                  AOP_SIZE(result), __FILE__, lineno);
-         exit (1);
-      }      
-      
-    aopPut (AOP (result), "a", 0);
-    _G.accInUse--; _G.bInUse--;
-    if (AOP_SIZE(result)==2) 
+  /* (if two literals: the value is computed before) */
+  /* if one literal, literal on the right */
+  if (AOP_TYPE (left) == AOP_LIT)
     {
-      aopPut (AOP (result), "b", 1);
+      operand *t = right;
+      right = left;
+      left = t;
+      /* emitcode (";", "swapped left and right"); */
+    }
+  /* if no literal, unsigned on the right: shorter code */
+  if (   AOP_TYPE (right) != AOP_LIT
+      && SPEC_USIGN (getSpec (operandType (left))))
+    {
+      operand *t = right;
+      right = left;
+      left = t;
     }
-    return;
-  }
 
-  // we have to do a signed multiply
+  lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
+  rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
 
-  emitcode (";", "signed");
-  emitcode ("clr", "F0"); // reset sign flag
-  MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
+  if ((lUnsigned && rUnsigned)
+/* sorry, I don't know how to get size
+   without calling aopOp (result,...);
+   see Feature Request  */
+      /* || size == 1 */ ) /* no, this is not a bug; with a 1 byte result there's
+                  no need to take care about the signedness! */
+    {
+      /* just an unsigned 8 * 8 = 8 multiply
+         or 8u * 8u = 16u */
+      /* emitcode (";","unsigned"); */
+      emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
+      MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
+      emitcode ("mul", "ab");
+    
+      _G.accInUse++; _G.bInUse++;
+      aopOp (result, ic, TRUE, FALSE);
+      size = AOP_SIZE (result);
+  
+      if (size < 1 || size > 2)
+        {
+          /* this should never happen */
+          fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n",
+                  size, __FILE__, lineno);
+          exit (1);
+        }
+  
+      aopPut (AOP (result), "a", 0);
+      _G.accInUse--; _G.bInUse--;
+      if (size == 2) 
+       aopPut (AOP (result), "b", 1);
+      return;
+    }
 
-  lbl=newiTempLabel(NULL);
-  emitcode ("jnb", "acc.7,!tlabel",  lbl->key+100);
-  // left side is negative, 8-bit two's complement, this fails for -128
-  emitcode ("setb", "F0"); // set sign flag
-  emitcode ("cpl", "a");
-  emitcode ("inc", "a");
+  /* we have to do a signed multiply */
+  /* emitcode (";", "signed"); */
+  
+  /* now sign adjust for both left & right */
 
-  emitcode ("", "!tlabeldef", lbl->key+100);
+  /* let's see what's needed: */
+  /* apply negative sign during runtime */
+  runtimeSign = FALSE;
+  /* negative sign from literals */
+  compiletimeSign = FALSE;
 
-  /* if literal */
-  if (AOP_TYPE(right)==AOP_LIT) {
-    signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
-    /* AND literal negative */
-    if ((int) val < 0) {
-      emitcode ("cpl", "F0"); // complement sign flag
-      emitcode ("mov", "b,#!constbyte", -val);
-    } else {
-      emitcode ("mov", "b,#!constbyte", val);
+  if (!lUnsigned)
+    {
+      if (AOP_TYPE(left) == AOP_LIT)
+        {
+          /* signed literal */
+          signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
+          if (val < 0)
+            compiletimeSign = TRUE;
+        }
+      else
+        /* signed but not literal */
+        runtimeSign = TRUE;
     }
-  } else {
-    lbl=newiTempLabel(NULL);
-    emitcode ("mov", "b,a");
-    emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
-    emitcode ("jnb", "acc.7,!tlabel", lbl->key+100);
-    // right side is negative, 8-bit two's complement
-    emitcode ("cpl", "F0"); // complement sign flag
-    emitcode ("cpl", "a");
-    emitcode ("inc", "a");
-    emitcode ("", "!tlabeldef", lbl->key+100);
-  }
+
+  if (!rUnsigned)
+    {
+      if (AOP_TYPE(right) == AOP_LIT)
+        {
+          /* signed literal */
+          signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
+          if (val < 0)
+            compiletimeSign ^= TRUE;
+        }
+      else
+        /* signed but not literal */
+        runtimeSign = TRUE;
+    }
+
+  /* initialize F0, which stores the runtime sign */
+  if (runtimeSign)
+    {
+      if (compiletimeSign)
+       emitcode ("setb", "F0"); /* set sign flag */
+      else
+       emitcode ("clr", "F0"); /* reset sign flag */
+    }
+  
+  /* save the signs of the operands */
+  if (AOP_TYPE(right) == AOP_LIT)
+    {
+      signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
+
+      if (!rUnsigned && val < 0)
+        emitcode ("mov", "b,#!constbyte", -val);
+      else
+        emitcode ("mov", "b,#!constbyte", (unsigned char) val);
+    }
+  else /* ! literal */
+    {
+      if (rUnsigned)  /* emitcode (";", "signed"); */
+        emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
+      else
+        {
+         MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
+         lbl = newiTempLabel (NULL);
+         emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
+         emitcode ("cpl", "F0"); /* complement sign flag */
+         emitcode ("cpl", "a");  /* 2's complement */
+         emitcode ("inc", "a");
+         emitcode ("", "!tlabeldef", lbl->key + 100);
+         emitcode ("mov", "b,a");
+       }
+    }
+
+  if (AOP_TYPE(left) == AOP_LIT)
+    {
+      signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
+
+      if (!lUnsigned && val < 0)
+        emitcode ("mov", "a,#!constbyte", -val);
+      else
+        emitcode ("mov", "a,#!constbyte", (unsigned char) val);
+    }
+  else /* ! literal */
+    {
+      if (lUnsigned)  /* emitcode (";", "signed"); */
+
+        emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
+      else
+        {
+         MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
+         lbl = newiTempLabel (NULL);
+         emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
+         emitcode ("cpl", "F0"); /* complement sign flag */
+         emitcode ("cpl", "a");  /* 2's complement */
+         emitcode ("inc", "a");
+         emitcode ("", "!tlabeldef", lbl->key + 100);
+       }
+    }
+
+  /* now the multiplication */
   emitcode ("mul", "ab");
-    
   _G.accInUse++;_G.bInUse++;
   aopOp(result, ic, TRUE, FALSE);
-    
-  if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
-  {
-    // this should never happen
+  size = AOP_SIZE (result);
+
+  if (size < 1 || size > 2) 
+    {
+      /* this should never happen */
       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
-              AOP_SIZE(result), __FILE__, lineno);
+               size, __FILE__, lineno);
       exit (1);
-  }    
+    }    
     
-  lbl=newiTempLabel(NULL);
-  emitcode ("jnb", "F0,!tlabel", lbl->key+100);
-  // only ONE op was negative, we have to do a 8/16-bit two's complement
-  emitcode ("cpl", "a"); // lsb
-  if (AOP_SIZE(result)==1) {
-    emitcode ("inc", "a");
-  } else {
-    emitcode ("add", "a,#1");
-    emitcode ("xch", "a,b");
-    emitcode ("cpl", "a"); // msb
-    emitcode ("addc", "a,#0");
-    emitcode ("xch", "a,b");
-  }
-
-  emitcode ("", "!tlabeldef", lbl->key+100);
+  if (runtimeSign || compiletimeSign)
+    {
+      lbl = newiTempLabel (NULL);
+      if (runtimeSign)
+        emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
+      emitcode ("cpl", "a"); /* lsb 2's complement */
+      if (size != 2)
+        emitcode ("inc", "a"); /* inc doesn't set carry flag */
+      else
+        {
+          emitcode ("add", "a,#1"); /* this sets carry flag */
+          emitcode ("xch", "a,b");
+          emitcode ("cpl", "a"); /* msb 2's complement */
+          emitcode ("addc", "a,#0");
+          emitcode ("xch", "a,b");
+        }
+      emitcode ("", "!tlabeldef", lbl->key + 100);
+    }
   aopPut (AOP (result), "a", 0);
   _G.accInUse--;_G.bInUse--;
-  if (AOP_SIZE(result)==2) {
+  if (size == 2)
     aopPut (AOP (result), "b", 1);
-  }
 }
 
 /*-----------------------------------------------------------------*/
@@ -4962,94 +5060,182 @@ genDivOneByte (operand * left,
               operand * result,
               iCode   * ic)
 {
-  sym_link *opetype = operandType (result);
+  bool lUnsigned, rUnsigned;
+  bool runtimeSign, compiletimeSign;
   char *l;
   symbol *lbl;
   int size, offset;
 
   offset = 1;
+  lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
+  rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
+  
   /* signed or unsigned */
-  if (SPEC_USIGN (opetype))
+  if (lUnsigned && rUnsigned)
     {
-       /* unsigned is easy */
-       LOAD_AB_FOR_DIV (left, right, l);
-       emitcode ("div", "ab");
+      /* unsigned is easy */
+      LOAD_AB_FOR_DIV (left, right, l);
+      emitcode ("div", "ab");
 
-       _G.accInUse++;
-       aopOp(result, ic, TRUE, FALSE);
-       aopPut (AOP (result), "a", 0);
-       _G.accInUse--;
+      _G.accInUse++;
+      aopOp (result, ic, TRUE, FALSE);
+      aopPut (AOP (result), "a", 0);
+      _G.accInUse--;
 
-       size = AOP_SIZE (result) - 1;
-       
-       while (size--)
-       {
-           aopPut (AOP (result), zero, offset++);
-       }
+      size = AOP_SIZE (result) - 1;
+      
+      while (size--)
+       aopPut (AOP (result), zero, offset++);
       return;
     }
 
   /* signed is a little bit more difficult */
 
-  /* save the signs of the operands */
-  MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
-  emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE, FALSE));
-  emitcode ("push", "acc");    /* save it on the stack */
-
   /* now sign adjust for both left & right */
-  MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
-  lbl = newiTempLabel (NULL);
-  emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
-  emitcode ("cpl", "a");
-  emitcode ("inc", "a");
-  emitcode ("", "!tlabeldef", (lbl->key + 100));
-  emitcode ("mov", "b,a");
 
-  /* sign adjust left side */
-  MOVA( aopGet (AOP (left), 0, FALSE, FALSE, NULL));
+  /* let's see what's needed: */
+  /* apply negative sign during runtime */
+  runtimeSign = FALSE;
+  /* negative sign from literals */
+  compiletimeSign = FALSE;
 
-  lbl = newiTempLabel (NULL);
-  emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
-  emitcode ("cpl", "a");
-  emitcode ("inc", "a");
-  emitcode ("", "!tlabeldef", (lbl->key + 100));
+  if (!lUnsigned)
+    {
+      if (AOP_TYPE(left) == AOP_LIT)
+        {
+          /* signed literal */
+          signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
+          if (val < 0)
+            compiletimeSign = TRUE;
+        }
+      else
+        /* signed but not literal */
+        runtimeSign = TRUE;
+    }
+
+  if (!rUnsigned)
+    {
+      if (AOP_TYPE(right) == AOP_LIT)
+        {
+          /* signed literal */
+          signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
+          if (val < 0)
+            compiletimeSign ^= TRUE;
+        }
+      else
+        /* signed but not literal */
+        runtimeSign = TRUE;
+    }
+
+  /* initialize F0, which stores the runtime sign */
+  if (runtimeSign)
+    {
+      if (compiletimeSign)
+       emitcode ("setb", "F0"); /* set sign flag */
+      else
+       emitcode ("clr", "F0"); /* reset sign flag */
+    }
+
+  /* save the signs of the operands */
+  if (AOP_TYPE(right) == AOP_LIT)
+    {
+      signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
 
+      if (!rUnsigned && val < 0)
+        emitcode ("mov", "b,#0x%02x", -val);
+      else
+        emitcode ("mov", "b,#0x%02x", (unsigned char) val);
+    }
+  else /* ! literal */
+    {
+      if (rUnsigned)
+        emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
+      else
+        {
+          MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
+         lbl = newiTempLabel (NULL);
+         emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
+         emitcode ("cpl", "F0"); /* complement sign flag */
+         emitcode ("cpl", "a");  /* 2's complement */
+         emitcode ("inc", "a");
+         emitcode ("", "!tlabeldef", lbl->key + 100);
+          emitcode ("mov", "b,a");
+       }
+    }
+
+  if (AOP_TYPE(left) == AOP_LIT)
+    {
+      signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
+
+      if (!lUnsigned && val < 0)
+        emitcode ("mov", "a,#0x%02x", -val);
+      else
+        emitcode ("mov", "a,#0x%02x", (unsigned char) val);
+    }
+  else /* ! literal */
+    {
+      if (lUnsigned)
+        emitcode ("mov", "a,%s", aopGet (AOP (left), 0, FALSE, FALSE, NULL));
+      else
+        {
+          MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
+         lbl = newiTempLabel (NULL);
+         emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
+         emitcode ("cpl", "F0"); /* complement sign flag */
+         emitcode ("cpl", "a");  /* 2's complement */
+         emitcode ("inc", "a");
+         emitcode ("", "!tlabeldef", lbl->key + 100);
+       }
+    }
+  
   /* now the division */
   emitcode ("nop", "; workaround for DS80C390 div bug.");
   emitcode ("div", "ab");
-  /* we are interested in the lower order
-     only */
-  emitcode ("mov", "b,a");
-  lbl = newiTempLabel (NULL);
-  emitcode ("pop", "acc");
-  /* if there was an over flow we don't
-     adjust the sign of the result */
-  emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
-  emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
-  CLRC;
-  emitcode ("clr", "a");
-  emitcode ("subb", "a,b");
-  emitcode ("mov", "b,a");
-  emitcode ("", "!tlabeldef", (lbl->key + 100));
-
-  /* now we are done */
-  _G.accInUse++;     _G.bInUse++;
-    aopOp(result, ic, TRUE, FALSE);
-    
-    aopPut (AOP (result), "b", 0);
-    
-    size = AOP_SIZE (result) - 1;
-    
-    if (size > 0)
+  
+  if (runtimeSign || compiletimeSign)
     {
-      emitcode ("mov", "c,b.7");
-      emitcode ("subb", "a,acc");
+      lbl = newiTempLabel (NULL);
+      if (runtimeSign)
+        emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
+      emitcode ("cpl", "a"); /* lsb 2's complement */
+      emitcode ("inc", "a");
+      emitcode ("", "!tlabeldef", lbl->key + 100);
+
+      _G.accInUse++;     _G.bInUse++;
+      aopOp (result, ic, TRUE, FALSE);
+      size = AOP_SIZE (result) - 1;
+
+      if (size > 0)
+       {
+         /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
+            then the result will be in b, a */
+         emitcode ("mov", "b,a"); /* 1 */
+         /* msb is 0x00 or 0xff depending on the sign */
+         if (runtimeSign)
+           {
+             emitcode ("mov",  "c,F0");
+             emitcode ("subb", "a,acc");
+             emitcode ("xch",  "a,b"); /* 2 */
+             while (size--)
+               aopPut (AOP (result), "b", offset++); /* write msb's */
+           }
+         else /* compiletimeSign */
+           while (size--)
+             aopPut (AOP (result), "#0xff", offset++); /* write msb's */
+       }
+      aopPut (AOP (result), "a", 0); /* 3: write lsb */
     }
-    while (size--)
+  else
     {
-       aopPut (AOP (result), "a", offset++);
+      _G.accInUse++;     _G.bInUse++;
+      aopOp(result, ic, TRUE, FALSE);
+      size = AOP_SIZE (result) - 1;
+      
+      aopPut (AOP (result), "a", 0);
+      while (size--)
+       aopPut (AOP (result), zero, offset++);
     }
-    _G.accInUse--;     _G.bInUse--;
+  _G.accInUse--;     _G.bInUse--;
 
 }
 
@@ -5245,70 +5431,146 @@ genModOneByte (operand * left,
               operand * result,
               iCode   * ic)
 {
-  sym_link *opetype = operandType (result);
+  bool lUnsigned, rUnsigned;
+  bool runtimeSign, compiletimeSign;
   char *l;
   symbol *lbl;
+  int size, offset;
 
+  offset = 1;
+  lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
+  rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
+  
   /* signed or unsigned */
-  if (SPEC_USIGN (opetype))
+  if (lUnsigned && rUnsigned)
     {
       /* unsigned is easy */
       LOAD_AB_FOR_DIV (left, right, l);
       emitcode ("div", "ab");
-      aopOp(result, ic, TRUE, FALSE);  
+      aopOp (result, ic, TRUE, FALSE); 
       aopPut (AOP (result), "b", 0);
+
+      for (size = AOP_SIZE (result) - 1; size--;)
+       aopPut (AOP (result), zero, offset++);
       return;
     }
 
   /* signed is a little bit more difficult */
 
-  /* save the signs of the operands */
-  MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
-
-  emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE, FALSE));
-  emitcode ("push", "acc");    /* save it on the stack */
-
   /* now sign adjust for both left & right */
-  MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
 
-  lbl = newiTempLabel (NULL);
-  emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
-  emitcode ("cpl", "a");
-  emitcode ("inc", "a");
-  emitcode ("", "!tlabeldef", (lbl->key + 100));
-  emitcode ("mov", "b,a");
+  /* modulus: sign of the right operand has no influence on the result! */
+  if (AOP_TYPE(right) == AOP_LIT)
+    {
+      signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
 
-  /* sign adjust left side */
-  MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
+      if (!rUnsigned && val < 0)
+        emitcode ("mov", "b,#0x%02x", -val);
+      else
+        emitcode ("mov", "b,#0x%02x", (unsigned char) val);
+    }
+  else /* ! literal */
+    {
+      if (rUnsigned)
+        emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, NULL));
+      else
+        {
+          MOVA (aopGet (AOP (right), 0, FALSE, FALSE, NULL));
+         lbl = newiTempLabel (NULL);
+         emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
+         emitcode ("cpl", "a");  /* 2's complement */
+         emitcode ("inc", "a");
+         emitcode ("", "!tlabeldef", lbl->key + 100);
+          emitcode ("mov", "b,a");
+       }
+    }
+  
+  /* let's see what's needed: */
+  /* apply negative sign during runtime */
+  runtimeSign = FALSE;
+  /* negative sign from literals */
+  compiletimeSign = FALSE;
 
-  lbl = newiTempLabel (NULL);
-  emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
-  emitcode ("cpl", "a");
-  emitcode ("inc", "a");
-  emitcode ("", "!tlabeldef", (lbl->key + 100));
+  /* sign adjust left side */
+  if (AOP_TYPE(left) == AOP_LIT)
+    {
+      signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
 
-  /* now the multiplication */
+      if (!lUnsigned && val < 0)
+       {
+         compiletimeSign = TRUE; /* set sign flag */
+         emitcode ("mov", "a,#0x%02x", -val);
+       }
+      else
+        emitcode ("mov", "a,#0x%02x", (unsigned char) val);
+    }
+  else /* ! literal */
+    {
+      MOVA (aopGet (AOP (left), 0, FALSE, FALSE, NULL));
+      
+      if (!lUnsigned)
+        {
+         runtimeSign = TRUE;
+         emitcode ("clr", "F0"); /* clear sign flag */
+         
+         lbl = newiTempLabel (NULL);
+         emitcode ("jnb", "acc.7,!tlabel", lbl->key + 100);
+         emitcode ("setb", "F0"); /* set sign flag */
+         emitcode ("cpl", "a");   /* 2's complement */
+         emitcode ("inc", "a");
+         emitcode ("", "!tlabeldef", lbl->key + 100);
+       }
+    }
+  
+  /* now the modulus */
   emitcode ("nop", "; workaround for DS80C390 div bug.");
   emitcode ("div", "ab");
-  /* we are interested in the lower order
-     only */
-  lbl = newiTempLabel (NULL);
-  emitcode ("pop", "acc");
-  /* if there was an over flow we don't
-     adjust the sign of the result */
-  emitcode ("jb", "ov,!tlabel", (lbl->key + 100));
-  emitcode ("jnb", "acc.7,!tlabel", (lbl->key + 100));
-  CLRC;
-  emitcode ("clr", "a");
-  emitcode ("subb", "a,b");
-  emitcode ("mov", "b,a");
-  emitcode ("", "!tlabeldef", (lbl->key + 100));
   
-  _G.bInUse++;
-  /* now we are done */
-  aopOp(result, ic, TRUE, FALSE);    
-  aopPut (AOP (result), "b", 0);
-  _G.bInUse--;
+  if (runtimeSign || compiletimeSign)
+    {
+      emitcode ("mov", "a,b");
+      lbl = newiTempLabel (NULL);
+      if (runtimeSign)
+        emitcode ("jnb", "F0,!tlabel", lbl->key + 100);
+      emitcode ("cpl", "a"); /* lsb 2's complement */
+      emitcode ("inc", "a");
+      emitcode ("", "!tlabeldef", lbl->key + 100);
+
+      _G.accInUse++;     _G.bInUse++;
+      aopOp (result, ic, TRUE, FALSE);
+      size = AOP_SIZE (result) - 1;
+      
+      if (size > 0)
+       {
+         /* 123 look strange, but if (OP_SYMBOL (op)->accuse == 1)
+            then the result will be in b, a */
+         emitcode ("mov", "b,a"); /* 1 */
+         /* msb is 0x00 or 0xff depending on the sign */
+         if (runtimeSign)
+           {
+             emitcode ("mov",  "c,F0");
+             emitcode ("subb", "a,acc");
+             emitcode ("xch",  "a,b"); /* 2 */
+             while (size--)
+               aopPut (AOP (result), "b", offset++); /* write msb's */
+           }
+         else /* compiletimeSign */
+           while (size--)
+             aopPut (AOP (result), "#0xff", offset++); /* write msb's */
+       }
+      aopPut (AOP (result), "a", 0); /* 3: write lsb */
+    }
+  else
+    {
+      _G.accInUse++;     _G.bInUse++;
+      aopOp(result, ic, TRUE, FALSE);
+      size = AOP_SIZE (result) - 1;
+      
+      aopPut (AOP (result), "b", 0);
+      while (size--)
+       aopPut (AOP (result), zero, offset++);
+    }
+  _G.accInUse--;     _G.bInUse--;
 
 }
 
@@ -9331,12 +9593,12 @@ genNearPointerGet (operand * left,
   aopOp (left, ic, FALSE, FALSE);
 
   /* if left is rematerialisable and
-     result is not bit variable type and
+     result is not bitfield variable type and
      the left is pointer to data space i.e
      lower 128 bytes of space */
   if (AOP_TYPE (left) == AOP_IMMD &&
-      !IS_BITVAR (retype) &&
-      !IS_BITVAR (letype) &&
+      !IS_BITFIELD (retype) &&
+      !IS_BITFIELD (letype) &&
       DCL_TYPE (ltype) == POINTER)
     {
       genDataPointerGet (left, result, ic);
@@ -9362,7 +9624,7 @@ genNearPointerGet (operand * left,
   aopOp (result, ic, FALSE, FALSE);
 
   /* if bitfield then unpack the bits */
-  if (IS_BITVAR (retype) || IS_BITVAR (letype))
+  if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
     genUnpackBits (result, rname, POINTER);
   else
     {
@@ -9462,7 +9724,7 @@ genPagedPointerGet (operand * left,
   aopOp (result, ic, FALSE, FALSE);
 
   /* if bitfield then unpack the bits */
-  if (IS_BITVAR (retype) || IS_BITVAR (letype))
+  if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
     genUnpackBits (result, rname, PPOINTER);
   else
     {
@@ -9567,7 +9829,7 @@ genFarPointerGet (operand * left,
   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
 
   /* if bit then unpack */
-  if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
+  if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
       if (AOP_INDPTRn(left)) {
          genSetDPTR(AOP(left)->aopu.dptr);
       }
@@ -9687,7 +9949,7 @@ genCodePointerGet (operand * left,
   aopOp (result, ic, FALSE, (AOP_INDPTRn(left) ? FALSE : TRUE));
 
   /* if bit then unpack */
-  if (IS_BITVAR (retype)) {
+  if (IS_BITFIELD (retype)) {
       if (AOP_INDPTRn(left)) {
          genSetDPTR(AOP(left)->aopu.dptr);
       }
@@ -9812,7 +10074,7 @@ genGenPointerGet (operand * left,
   _G.bInUse--;
 
   /* if bit then unpack */
-  if (IS_BITVAR (retype) || IS_BITVAR (letype))
+  if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
   {
     genUnpackBits (result, "dptr", GPOINTER);
   }
@@ -10149,8 +10411,8 @@ genNearPointerSet (operand * right,
   aopOp (right, ic, FALSE, FALSE);
 
   /* if bitfield then unpack the bits */
-  if (IS_BITVAR (retype) || IS_BITVAR (letype))
-    genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, POINTER);
+  if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
+    genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, POINTER);
   else
     {
       /* we have can just get the values */
@@ -10245,8 +10507,8 @@ genPagedPointerSet (operand * right,
   aopOp (right, ic, FALSE, FALSE);
 
   /* if bitfield then unpack the bits */
-  if (IS_BITVAR (retype) || IS_BITVAR (letype))
-    genPackBits ((IS_BITVAR (retype) ? retype : letype), right, rname, PPOINTER);
+  if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
+    genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, rname, PPOINTER);
   else
     {
       /* we have can just get the values */
@@ -10352,11 +10614,11 @@ genFarPointerSet (operand * right,
   aopOp (right, ic, FALSE, (AOP_INDPTRn(result) ? FALSE : TRUE));
 
   /* if bit then unpack */
-  if (IS_BITVAR (retype) || IS_BITVAR (letype)) {
+  if (IS_BITFIELD (retype) || IS_BITFIELD (letype)) {
       if (AOP_INDPTRn(result)) {
          genSetDPTR(AOP(result)->aopu.dptr);
       }
-      genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", FPOINTER);
+      genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", FPOINTER);
       if (AOP_INDPTRn(result)) {
          genSetDPTR(0);
       }
@@ -10474,9 +10736,9 @@ genGenPointerSet (operand * right,
     
 
   /* if bit then unpack */
-  if (IS_BITVAR (retype) || IS_BITVAR (letype))
+  if (IS_BITFIELD (retype) || IS_BITFIELD (letype))
     {
-       genPackBits ((IS_BITVAR (retype) ? retype : letype), right, "dptr", GPOINTER);
+       genPackBits ((IS_BITFIELD (retype) ? retype : letype), right, "dptr", GPOINTER);
     }
   else
     {
@@ -11162,7 +11424,7 @@ genCast (iCode * ic)
   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
     return;
 
-  aopOp (right, ic, FALSE, FALSE);
+  aopOp (right, ic, FALSE, AOP_IS_STR (result));
   aopOp (result, ic, FALSE, (AOP_TYPE(right) == AOP_DPTR));
 
   /* if the result is a bit */