* device/lib/_modsint.c,
authorbernhardheld <bernhardheld@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Wed, 11 Feb 2004 21:30:33 +0000 (21:30 +0000)
committerbernhardheld <bernhardheld@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Wed, 11 Feb 2004 21:30:33 +0000 (21:30 +0000)
* device/lib/_modslong.c: sign follows divisor only
* src/hc08/gen.c (genMultOneByte): if result size is 1, signs or signedness can be ignored
* src/SDCCast.c (addCast): cosmetic - added lineno to CAST
* src/SDCCast.c (resultTypePropagate): added even more ops: +, - and *, added optimization for IFX,
(decorateType): Mult/Div/ModOneByte ops can handle all kind of signed arguments;
reenabled optimization for IFX, which was removed on 2004-01-11
* src/SDCCast.h: added return type IFX
* src/SDCCicode.c: Mult/Div/ModOneByte ops can handle all kind of signed arguments with 8 or 16 bit results; pic14 and pic16 ports use old promotion behaviour;
env. var. SDCC_NEWONEBYTEOPS selects the new, SDCC_OLDONEBYTEOPS selects the old behaviour
* src/SDCCsymt.c (computeType): type2 can be NULL (for LEFT_OP);
changed again and commented promotion rule (it's still not perfect)
* src/SDCCval.c (valDiv): promotion no longer necessary
* src/ds390/gen.c (genMultOneByte) (genDivOneByte) (genModOneByte),
* src/mcs51/gen.c (genMultOneByte) (genDivOneByte) (genModOneByte): rewritten
* support/regression/tests/onebyte.c: added

git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@3192 4a8a32a2-be11-0410-ad9d-d568d2c75423

12 files changed:
ChangeLog
device/lib/_modsint.c
device/lib/_modslong.c
src/SDCCast.c
src/SDCCast.h
src/SDCCicode.c
src/SDCCsymt.c
src/SDCCval.c
src/ds390/gen.c
src/hc08/gen.c
src/mcs51/gen.c
support/regression/tests/onebyte.c [new file with mode: 0644]

index dbce719b6e29135bb8c818f3e9779a91c6c386cd..1c8a3a10e323ed871fb601f877257c60f114f955 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,28 @@
+2004-02-11 Bernhard Held <bernhard AT bernhardheld.de>
+
+       * device/lib/_modsint.c,
+       * device/lib/_modslong.c: sign follows divisor only
+       * src/hc08/gen.c (genMultOneByte): if result size is 1,
+       signs or signedness can be ignored
+       * src/SDCCast.c (addCast): cosmetic - added lineno to CAST
+       * src/SDCCast.c (resultTypePropagate): added even more ops: +, - and *,
+       added optimization for IFX,
+       (decorateType): Mult/Div/ModOneByte ops can handle all kind of signed
+       arguments;
+       reenabled optimization for IFX, which was removed on 2004-01-11
+       * src/SDCCast.h: added return type IFX
+       * src/SDCCicode.c: Mult/Div/ModOneByte ops can handle all kind of signed
+       arguments with 8 or 16 bit results; pic14 and pic16 ports use old
+       promotion behaviour; env. var. SDCC_NEWONEBYTEOPS selects the new,
+       SDCC_OLDONEBYTEOPS selects the old behaviour
+       * src/SDCCsymt.c (computeType): type2 can be NULL (for LEFT_OP);
+       changed again and commented promotion rule (it's still not perfect)
+       * src/SDCCval.c (valDiv): promotion no longer necessary
+       * src/ds390/gen.c (genMultOneByte) (genDivOneByte) (genModOneByte),
+       * src/mcs51/gen.c (genMultOneByte) (genDivOneByte) (genModOneByte):
+       rewritten
+       * support/regression/tests/onebyte.c: added
+
 2004-02-11 Vangelis Rokas <vrokas AT otenet.gr>
 
        * gen.c (genInline): reverted to old code for assemnling inline
 
        * pcode.c (pic16initMnemonics): fixed typo in assignment to PCOP_RLNCF
        PCOP_RLCF was overwritten!
-       * gen.c (genSkip) commented out calls to pic16_emitcode,
-       * (genCmpEQ) fixed "long" compares, only high word did get compared,
+       * gen.c (genSkip): commented out calls to pic16_emitcode,
+       * (genCmpEQ): fixed "long" compares, only high word did get compared,
        * (genlshTwo),
-       * (genRRC) added debugging info,
-       * (shiftL2Left2Result) Fixed bug, if offr > offl. Result got
+       * (genRRC): added debugging info,
+       * (shiftL2Left2Result): Fixed bug, if offr > offl. Result got
        overwritten while shifting,
-       * (shiftR2Left2Result) Fixed bug, if offr < offl. Result got
+       * (shiftR2Left2Result): Fixed bug, if offr < offl. Result got
        overwritten while shifting,
        * (AccLsh),
        * (AccRsh),
        * (shiftLLeftOrResult),
        * (shiftRLeftOrResult),
        * (shiftRLong),
-       * (shiftLLong) Implemented with pic16_emitpcode
-       * (genlshFour) Replaced pic16_aopPut with pic16_emitpcode,
-       * (genLeftShift) Fixed bug, operand for shift by variable always
+       * (shiftLLong): Implemented with pic16_emitpcode
+       * (genlshFour): Replaced pic16_aopPut with pic16_emitpcode,
+       * (genLeftShift): Fixed bug, operand for shift by variable always
        was "and"ed with 0x0f,
        * (genLeftShiftLiteral),
        * (genrshTwo),
-       * (genRightShiftLiteral) added debugging info,
-       * (genrshFour) added comment,
-       * (genRightShift) determined signedness from operand "left"
+       * (genRightShiftLiteral): added debugging info,
+       * (genrshFour): added comment,
+       * (genRightShift): determined signedness from operand "left"
        instead of "result"
 
 2004-02-04 Erik Petrich <epetrich AT ivorytower.norman.ok.us>
index abf270b0e81fce0b4f384835337f32a9262b852b..a46268a36b097176fa89f273dcf373ea685429f8 100644 (file)
@@ -90,8 +90,6 @@ _modsint_dummy (void) _naked
                mov     a,b1
                jnb     acc.7,b_not_negative
 
-               cpl     F0
-
                clr     a
                clr     c
                subb    a,b0
index 99c3f8d98cf6290312f40191d2493a36048ee7a1..22140ee1fe5c036d9139e544e464fe1f43f464bc 100644 (file)
@@ -101,8 +101,6 @@ _modslong_dummy (void) _naked
                mov     a,b3
                jnb     acc.7,b_not_negative
 
-               cpl     F0
-
                clr     a               ; b = -b;
                clr     c
                subb    a,b0
index 62efaa6d37eedbaefafaf494df821cadcbd0fd49..57435e5df0065e77319e9d74a61903a76d414705 100644 (file)
@@ -2084,6 +2084,7 @@ addCast (ast *tree, RESULT_TYPE resultType, bool upcast)
     }
   tree->decorated = 0;
   tree = newNode (CAST, newAst_LINK (newLink), tree);
+  tree->lineno = tree->right->lineno;
   /* keep unsigned type during cast to smaller type,
      but not when promoting from char to int */
   if (!upCasted)
@@ -2104,6 +2105,10 @@ resultTypePropagate (ast *tree, RESULT_TYPE resultType)
       case ':':
       case '|':
       case '^':
+      case '*':
+      case '+':
+      case '-':
+      case LABEL:
        return resultType;
       case '&':
        if (!tree->right)
@@ -2111,6 +2116,8 @@ resultTypePropagate (ast *tree, RESULT_TYPE resultType)
          return RESULT_TYPE_NONE;
        else
          return resultType;
+      case IFX:
+       return RESULT_TYPE_IFX;
       default:
        return RESULT_TYPE_NONE;
     }
@@ -2792,10 +2799,11 @@ decorateType (ast * tree, RESULT_TYPE resultType)
        }
 
       LRVAL (tree) = RRVAL (tree) = 1;
+
       TETYPE (tree) = getSpec (TTYPE (tree) =
                               computeType (LTYPE (tree),
                                            RTYPE (tree),
-               ! (IS_UNSIGNED (LTYPE (tree)) && IS_UNSIGNED (RTYPE (tree)))));
+                              resultType == RESULT_TYPE_CHAR ? FALSE : TRUE));
 
       /* if right is a literal and */
       /* left is also a division by a literal then */
@@ -2861,7 +2869,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
       TETYPE (tree) = getSpec (TTYPE (tree) =
                               computeType (LTYPE (tree),
                                            RTYPE (tree),
-               ! (IS_UNSIGNED (LTYPE (tree)) && IS_UNSIGNED (RTYPE (tree)))));
+                              resultType == RESULT_TYPE_CHAR ? FALSE : TRUE));
       return tree;
 
       /*------------------------------------------------------------------*/
@@ -2977,7 +2985,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
                                   computeType (LTYPE (tree),
                                                RTYPE (tree),
                               resultType == RESULT_TYPE_CHAR ? FALSE : TRUE));
-      
+
       return tree;
 
       /*------------------------------------------------------------------*/
@@ -3363,7 +3371,7 @@ decorateType (ast * tree, RESULT_TYPE resultType)
          tree->left = addCast (tree->left, resultType, TRUE);
          TETYPE (tree) = getSpec (TTYPE (tree) =
                                       computeType (LTYPE (tree),
-                                                   RTYPE (tree),
+                                                   NULL,
                               resultType == RESULT_TYPE_CHAR ? FALSE : TRUE));
        }
       else /* RIGHT_OP */
@@ -3685,8 +3693,14 @@ decorateType (ast * tree, RESULT_TYPE resultType)
            }
          if (tree->opval.op == '>')
            {
-             /* if the parent is an ifx, then we could do */
-             /* return tree->left; */
+             if (resultType == RESULT_TYPE_IFX)
+               {
+                 /* the parent is an ifx: */
+                 /* if (unsigned value) */
+                 return tree->left;
+               }
+             
+             /* (unsigned value) ? 1 : 0 */
              tree->opval.op = '?';
              tree->right = newNode (':',
                                     newAst_VALUE (constVal ("1")),
index be782aae94fea11adf39bc1646cbe23f351394e3..04211fa9e2cbe01b67579f059cc0e423762cf598 100644 (file)
@@ -177,7 +177,8 @@ typedef enum
   RESULT_TYPE_BIT,
   RESULT_TYPE_CHAR,
   RESULT_TYPE_INT,
-  RESULT_TYPE_OTHER
+  RESULT_TYPE_OTHER,
+  RESULT_TYPE_IFX,
 } RESULT_TYPE;
 
 /* forward declarations for global variables */
index 381a2bcb68800c04c9c113714d324b0adfc808ef..e65e7d5de73728ddbaf8bc75bd73b3a0d221f496 100644 (file)
@@ -45,7 +45,7 @@ symbol *entryLabel;           /* function entry  label */
 
 /*-----------------------------------------------------------------*/
 /* forward definition of some functions */
-operand *geniCodeDivision (operand *, operand *);
+operand *geniCodeDivision (operand *, operand *, bool);
 operand *geniCodeAssign (operand *, operand *, int);
 static operand *geniCodeArray (operand *, operand *,int);
 static operand *geniCodeArray2Ptr (operand *);
@@ -1753,36 +1753,90 @@ usualUnaryConversions (operand * op)
 /*-----------------------------------------------------------------*/
 /* perform "usual binary conversions"                              */
 /*-----------------------------------------------------------------*/
+
 static sym_link *
 usualBinaryConversions (operand ** op1, operand ** op2,
-                        bool promoteCharToInt, bool isMul)
+                        bool resultIsInt, char op)
 {
   sym_link *ctype;
   sym_link *rtype = operandType (*op2);
   sym_link *ltype = operandType (*op1);
 
-  ctype = computeType (ltype, rtype, promoteCharToInt);
+#define OLDONEBYTEOPS 1
 
-  /* special for multiplication:
-     This if for 'mul a,b', which takes two chars and returns an int */
-  if (   isMul
-      /* && promoteCharToInt   superfluous, already handled by computeType() */
-      && IS_INT  (getSpec (ctype)))
+#ifdef OLDONEBYTEOPS  
+  bool oldOneByteOps = FALSE;
+  static bool saidHello = FALSE;
+  
+  if (   strcmp (port->target, "pic14") == 0
+      || strcmp (port->target, "pic16") == 0)
+    oldOneByteOps = TRUE;
+  if (getenv ("SDCC_NEWONEBYTEOPS"))
     {
-      sym_link *retype = getSpec (rtype);
-      sym_link *letype = getSpec (ltype);
-
-      if (   IS_CHAR (letype)
-         && IS_CHAR (retype)
-         && IS_UNSIGNED (letype)
-         && IS_UNSIGNED (retype))
-       {
-         return ctype;
+      if (!saidHello)
+        {
+         fprintf (stderr, "Override: oldOneByteOps = FALSE\n");
+         saidHello = TRUE;
+       }
+      oldOneByteOps = FALSE;
+    }
+  else if (getenv ("SDCC_OLDONEBYTEOPS"))
+    {
+      if (!saidHello)
+        {
+          fprintf (stderr, "Override: oldOneByteOps = TRUE\n");
+         saidHello = TRUE;
        }
+      oldOneByteOps = TRUE;
+    }
+
+
+  if (   oldOneByteOps
+      && (   (IS_CHAR (getSpec (ltype)) && !IS_UNSIGNED (getSpec (ltype)))
+         || (IS_CHAR (getSpec (rtype)) && !IS_UNSIGNED (getSpec (rtype)))))
+    /* one or two signed char operands: promote to int */
+    resultIsInt = TRUE;
+#endif
+  
+  ctype = computeType (ltype, rtype, resultIsInt);
+
+#ifdef OLDONEBYTEOPS
+
+  if (oldOneByteOps)
+    {
+      if (   op == '*'
+          && IS_CHAR (getSpec (ltype)) && IS_UNSIGNED (getSpec (ltype))
+         && IS_CHAR (getSpec (rtype)) && IS_UNSIGNED (getSpec (rtype)))
+         {
+           /* two unsigned char operands and Mult: no promotion */
+           return ctype;
+         }
+      *op1 = geniCodeCast (ctype, *op1, TRUE);
+      *op2 = geniCodeCast (ctype, *op2, TRUE);
+
+      return ctype;
     }
+
+#endif
+
+  switch (op)
+    {
+      case '*':
+      case '/':
+      case '%':
+       if (IS_CHAR (getSpec (ltype)) && IS_CHAR (getSpec (rtype)))
+         {
+           /* one byte operations: keep signedness for code generator */
+           return ctype;
+         }
+       break;
+      default:
+       break;
+    }
+
   *op1 = geniCodeCast (ctype, *op1, TRUE);
   *op2 = geniCodeCast (ctype, *op2, TRUE);
-
+       
   return ctype;
 }
 
@@ -2007,7 +2061,7 @@ geniCodeGoto (symbol * label)
 /* geniCodeMultiply - gen intermediate code for multiplication     */
 /*-----------------------------------------------------------------*/
 operand *
-geniCodeMultiply (operand * left, operand * right, int resultIsInt)
+geniCodeMultiply (operand * left, operand * right, bool resultIsInt)
 {
   iCode *ic;
   int p2 = 0;
@@ -2023,7 +2077,7 @@ geniCodeMultiply (operand * left, operand * right, int resultIsInt)
     p2 = powof2 ((TYPE_UDWORD) floatFromVal (right->operand.valOperand));
   }
 
-  resType = usualBinaryConversions (&left, &right, resultIsInt, TRUE);
+  resType = usualBinaryConversions (&left, &right, resultIsInt, '*');
 #if 1
   rtype = operandType (right);
   retype = getSpec (rtype);
@@ -2066,7 +2120,7 @@ geniCodeMultiply (operand * left, operand * right, int resultIsInt)
 /* geniCodeDivision - gen intermediate code for division           */
 /*-----------------------------------------------------------------*/
 operand *
-geniCodeDivision (operand * left, operand * right)
+geniCodeDivision (operand * left, operand * right, bool resultIsInt)
 {
   iCode *ic;
   int p2 = 0;
@@ -2076,9 +2130,7 @@ geniCodeDivision (operand * left, operand * right)
   sym_link *ltype = operandType (left);
   sym_link *letype = getSpec (ltype);
 
-  resType = usualBinaryConversions (&left, &right,
-              (IS_UNSIGNED (retype) && IS_UNSIGNED (letype)) ? FALSE : TRUE,
-             FALSE);
+  resType = usualBinaryConversions (&left, &right, resultIsInt, '/');
 
   /* if the right is a literal & power of 2
      and left is unsigned then make it a
@@ -2106,7 +2158,7 @@ geniCodeDivision (operand * left, operand * right)
 /* geniCodeModulus  - gen intermediate code for modulus            */
 /*-----------------------------------------------------------------*/
 operand *
-geniCodeModulus (operand * left, operand * right)
+geniCodeModulus (operand * left, operand * right, bool resultIsInt)
 {
   iCode *ic;
   sym_link *resType;
@@ -2117,9 +2169,7 @@ geniCodeModulus (operand * left, operand * right)
     return operandFromValue (valMod (left->operand.valOperand,
                                     right->operand.valOperand));
 
-  resType = usualBinaryConversions (&left, &right,
-              (IS_UNSIGNED (retype) && IS_UNSIGNED (letype)) ? FALSE : TRUE,
-             FALSE);
+  resType = usualBinaryConversions (&left, &right, resultIsInt, '%');
 
   /* now they are the same size */
   ic = newiCode ('%', left, right);
@@ -2163,7 +2213,8 @@ subtractExit:
   
   // should we really do this? is this ANSI?
   return geniCodeDivision (result,
-                          operandFromLit (getSize (ltype->next)));
+                          operandFromLit (getSize (ltype->next)),
+                          FALSE);
 }
 
 /*-----------------------------------------------------------------*/
@@ -2198,7 +2249,7 @@ geniCodeSubtract (operand * left, operand * right)
     }
   else
     {                          /* make them the same size */
-      resType = usualBinaryConversions (&left, &right, FALSE, FALSE);
+      resType = usualBinaryConversions (&left, &right, FALSE, '-');
     }
 
   ic = newiCode ('-', left, right);
@@ -2257,7 +2308,7 @@ geniCodeAdd (operand * left, operand * right, int lvl)
     }
   else
     { // make them the same size
-      resType = usualBinaryConversions (&left, &right, FALSE, FALSE);
+      resType = usualBinaryConversions (&left, &right, FALSE, '+');
     }
 
   /* if they are both literals then we know */
@@ -2847,7 +2898,7 @@ geniCodeLogic (operand * left, operand * right, int op)
         }
     }
 
-  ctype = usualBinaryConversions (&left, &right, FALSE, FALSE);
+  ctype = usualBinaryConversions (&left, &right, FALSE, ' ');
 
   ic = newiCode (op, left, right);
   IC_RESULT (ic) = newiTempOperand (newCharLink (), 1);
@@ -3803,15 +3854,18 @@ ast2iCode (ast * tree,int lvl)
 
     case '/':
       return geniCodeDivision (geniCodeRValue (left, FALSE),
-                              geniCodeRValue (right, FALSE));
+                              geniCodeRValue (right, FALSE),
+                              IS_INT (tree->ftype));
 
     case '%':
       return geniCodeModulus (geniCodeRValue (left, FALSE),
-                             geniCodeRValue (right, FALSE));
+                             geniCodeRValue (right, FALSE),
+                             IS_INT (tree->ftype));
     case '*':
       if (right)
        return geniCodeMultiply (geniCodeRValue (left, FALSE),
-                                geniCodeRValue (right, FALSE),IS_INT(tree->ftype));
+                                geniCodeRValue (right, FALSE),
+                                IS_INT (tree->ftype));
       else
        return geniCodeDerefPtr (geniCodeRValue (left, FALSE),lvl);
 
@@ -3923,13 +3977,17 @@ ast2iCode (ast * tree,int lvl)
        geniCodeAssign (left,
                geniCodeDivision (geniCodeRValue (operandFromOperand (left),
                                                  FALSE),
-                                 geniCodeRValue (right, FALSE)), 0);
+                                 geniCodeRValue (right, FALSE),
+                                 IS_INT (tree->ftype)),
+                       0);
     case MOD_ASSIGN:
       return
        geniCodeAssign (left,
                 geniCodeModulus (geniCodeRValue (operandFromOperand (left),
                                                  FALSE),
-                                 geniCodeRValue (right, FALSE)), 0);
+                                 geniCodeRValue (right, FALSE),
+                                 IS_INT (tree->ftype)),
+                       0);
     case ADD_ASSIGN:
       {
        sym_link *rtype = operandType (right);
index 88df7febb8e96c0f8cf30fda4f6c22e19535a661..19c88b1755ad3937eb06ef434167bbef754d576a 100644 (file)
@@ -1519,7 +1519,9 @@ computeType (sym_link * type1, sym_link * type2, bool promoteCharToInt)
   sym_link *rType;
   sym_link *reType;
   sym_link *etype1 = getSpec (type1);
-  sym_link *etype2 = getSpec (type2);
+  sym_link *etype2;
+   
+  etype2 = type2 ? getSpec (type2) : type1;
 
   /* if one of them is a float then result is a float */
   /* here we assume that the types passed are okay */
@@ -1554,18 +1556,25 @@ computeType (sym_link * type1, sym_link * type2, bool promoteCharToInt)
   if (IS_CHAR (reType) && promoteCharToInt)
     SPEC_NOUN (reType) = V_INT;
 
-  if (   (   (   SPEC_USIGN (etype1)
+  if (!IS_FLOAT (reType)
+      && (   (   SPEC_USIGN (etype1)
               /* if this operand is promoted to a larger
                 type don't check it's signedness */
              && (getSize (etype1) >= getSize (reType))
-             /* We store signed literals in the range 0...255 as
-                'unsigned char'. If there was no promotion to 'signed int'
-                they must not force an unsigned operation: */
-             && !(IS_CHAR (etype1) && IS_LITERAL (etype1)))
+             /* char has to handled as it would have
+                been promoted to int */
+             && !IS_CHAR (etype1))
+             /* same for 2nd operand */  
          || (   SPEC_USIGN (etype2)
              && (getSize (etype2) >= getSize (reType))
-             && !(IS_CHAR (etype2) && IS_LITERAL (etype2))))
-      && !IS_FLOAT (reType))
+             && !IS_CHAR (etype2))
+         /* if both are unsigned char and not promoted
+            let the result be unsigned too */
+         || (   SPEC_USIGN (etype1)
+             && SPEC_USIGN (etype2)
+             && IS_CHAR (etype1)
+             && IS_CHAR (etype2)
+             && !promoteCharToInt)))
     SPEC_USIGN (reType) = 1;
   else
     SPEC_USIGN (reType) = 0;
index e72baee3c2e524f43b7148ad63eaf424f5901978..542ca5754aa5eb118bf97453c0c47ce251b43cd6 100644 (file)
@@ -1143,7 +1143,7 @@ valDiv (value * lval, value * rval)
   SPEC_LONG  (val->type) = (SPEC_LONG  (lval->etype) | SPEC_LONG  (rval->etype));
   SPEC_USIGN (val->type) = SPEC_USIGN (computeType (lval->etype,
                                                    rval->etype,
-                                                   TRUE));
+                                                   FALSE));
 
   if (IS_FLOAT (val->type))
     SPEC_CVAL (val->type).v_float = floatFromVal (lval) / floatFromVal (rval);
index 1d70bcf3f12f13e1df5d30a9e830189eccab47eb..315f06425e48d868c648139c8fa713dc6ff51b8e 100644 (file)
@@ -4615,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 */
@@ -4629,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;
+    }
+
+  lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
+  rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
+
+  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;
     }
-    return;
-  }
 
-  // we have to do a signed multiply
+  /* we have to do a signed multiply */
+  /* emitcode (";", "signed"); */
+  
+  /* now sign adjust for both left & right */
 
-  emitcode (";", "signed");
-  emitcode ("clr", "F0"); // reset sign flag
-  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);
-  // 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");
+  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;
+    }
 
-  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;
+    }
 
-  /* 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);
+  /* initialize F0, which stores the runtime sign */
+  if (runtimeSign)
+    {
+      if (compiletimeSign)
+       emitcode ("setb", "F0"); /* set sign flag */
+      else
+       emitcode ("clr", "F0"); /* reset sign flag */
     }
-  } 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);
-  }
+  
+  /* 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);
-  }
 }
 
 /*-----------------------------------------------------------------*/
@@ -4966,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--;
 
 }
 
@@ -5249,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--;
 
 }
 
index e9b718cbdf8b937b4c271de126d2016e29beba1c..97748e372cf15a0706d62893e6d7b790f3e18d22 100644 (file)
@@ -3451,7 +3451,7 @@ genMultOneByte (operand * left,
       //emitcode (";", "swapped left and right");
     }
 
-  if (SPEC_USIGN(opetype)
+  if (size == 1
       || (SPEC_USIGN(operandType(left)) &&
          SPEC_USIGN(operandType(right))))
     {
index cb4dea5cee49e8d5ff38142b7302c4cda1b0a5ec..c9f3132d5c2d0e75eb97a182af636446f01ac478 100644 (file)
@@ -273,14 +273,14 @@ getTempRegs(regs **tempRegs, int size, iCode *ic)
   bitVect * freeRegs;
   int i;
   int offset;
-  
+
   if (!ic)
     ic = _G.current_iCode;
   if (!ic)
     return 0;
   if (!_G.currentFunc)
     return 0;
+
   freeRegs = newBitVect(8);
   bitVectSetBit (freeRegs, R2_IDX);
   bitVectSetBit (freeRegs, R3_IDX);
@@ -288,7 +288,7 @@ getTempRegs(regs **tempRegs, int size, iCode *ic)
   bitVectSetBit (freeRegs, R5_IDX);
   bitVectSetBit (freeRegs, R6_IDX);
   bitVectSetBit (freeRegs, R7_IDX);
-  
+
   if (IFFUNC_CALLEESAVES(_G.currentFunc->type))
     {
       bitVect * newfreeRegs;
@@ -297,8 +297,8 @@ getTempRegs(regs **tempRegs, int size, iCode *ic)
       freeRegs = newfreeRegs;
     }
   freeRegs = bitVectCplAnd (freeRegs, ic->rMask);
-  
-  offset = 0;    
+
+  offset = 0;
   for (i=0; i<freeRegs->size; i++)
     {
       if (bitVectBitValue(freeRegs,i))
@@ -350,7 +350,7 @@ leftRightUseAcc(iCode *ic)
   int size;
   int accuseSize = 0;
   int accuse = 0;
-  
+
   if (!ic)
     {
       werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
@@ -399,7 +399,7 @@ leftRightUseAcc(iCode *ic)
             accuseSize = size;
         }
     }
-  
+
   if (accuseSize)
     return accuseSize;
   else
@@ -777,7 +777,7 @@ aopOp (operand * op, iCode * ic, bool result)
          aop->size = getSize (sym->type);
          return;
         }
-      
+
       /* else must be a dummy iTemp */
       sym->aop = op->aop = aop = newAsmop (AOP_DUMMY);
       aop->size = getSize (sym->type);
@@ -965,7 +965,7 @@ aopGet (asmop * aop, int offset, bool bit16, bool dname)
     {
     case AOP_DUMMY:
       return zero;
-      
+
     case AOP_R0:
     case AOP_R1:
       /* if we need to increment it */
@@ -1107,7 +1107,7 @@ aopPut (asmop * aop, const char *s, int offset, bool bvolatile)
     case AOP_DUMMY:
       MOVA (s);                /* read s in case it was volatile */
       break;
-      
+
     case AOP_DIR:
       if (offset)
        sprintf (d, "(%s + %d)",
@@ -1681,10 +1681,10 @@ saveRegisters (iCode * lic)
       (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
        IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
     return;
-  
+
   /* safe the registers in use at this time but skip the
      ones for the result */
-  rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
+  rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
                         mcs51_rUmaskForOp (IC_RESULT(ic)));
 
   ic->regsSaved = 1;
@@ -1728,7 +1728,7 @@ unsaveRegisters (iCode * ic)
 
   /* restore the registers in use at this time but skip the
      ones for the result */
-  rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
+  rsave = bitVectCplAnd (bitVectCopy (ic->rMask),
                         mcs51_rUmaskForOp (IC_RESULT(ic)));
 
   if (options.useXstack)
@@ -1948,16 +1948,16 @@ unsaveRBank (int bank, iCode * ic, bool popPsw)
       if (!ic)
       {
          /* Assume r0 is available for use. */
-         r = mcs51_regWithIdx (R0_IDX);;          
-      }        
+         r = mcs51_regWithIdx (R0_IDX);;
+      }
       else
       {
          aop = newAsmop (0);
          r = getFreePtr (ic, &aop, FALSE);
       }
-      emitcode ("mov", "%s,_spx", r->name);      
+      emitcode ("mov", "%s,_spx", r->name);
   }
-  
+
   if (popPsw)
     {
       if (options.useXstack)
@@ -1991,11 +1991,11 @@ unsaveRBank (int bank, iCode * ic, bool popPsw)
     {
       emitcode ("mov", "_spx,%s", r->name);
     }
-    
+
   if (aop)
   {
-      freeAsmop (NULL, aop, ic, TRUE);  
-  }    
+      freeAsmop (NULL, aop, ic, TRUE);
+  }
 }
 
 /*-----------------------------------------------------------------*/
@@ -2061,7 +2061,7 @@ saveRBank (int bank, iCode * ic, bool pushPsw)
     }
 
   if (ic)
-  {  
+  {
       ic->bankSaved = 1;
   }
 }
@@ -2094,7 +2094,7 @@ static void genSend(set *sendSet)
                  emitcode ("mov","b1_%d,%s",rb1_count++,
                            aopGet (AOP (IC_LEFT (sic)), offset++,FALSE, FALSE));
              }
-         }       
+         }
          freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
     }
 }
@@ -2251,7 +2251,7 @@ genPcall (iCode * ic)
 
   if (swapBanks)
   {
-        emitcode ("mov", "psw,#0x%02x", 
+        emitcode ("mov", "psw,#0x%02x",
            ((FUNC_REGBANK(dtype)) << 3) & 0xff);
   }
 
@@ -2262,7 +2262,7 @@ genPcall (iCode * ic)
 
   if (swapBanks)
   {
-       emitcode ("mov", "psw,#0x%02x", 
+       emitcode ("mov", "psw,#0x%02x",
           ((FUNC_REGBANK(currFunc->type)) << 3) & 0xff);
   }
 
@@ -2444,7 +2444,7 @@ genFunction (iCode * ic)
            }
          else
            {
-               
+
              /* this function has  a function call cannot
                 determines register usage so we will have to push the
                 entire bank */
@@ -2468,7 +2468,7 @@ genFunction (iCode * ic)
             * other bank, we must save that bank entirely.
             */
            unsigned long banksToSave = 0;
-           
+
            if (IFFUNC_HASFCALL(sym->type))
            {
 
@@ -2484,11 +2484,11 @@ genFunction (iCode * ic)
                        /* we got to the end OK. */
                        break;
                    }
-                   
+
                    if (i->op == CALL)
                    {
                        sym_link *dtype;
-                       
+
                        dtype = operandType (IC_LEFT(i));
                        if (dtype
                         && FUNC_REGBANK(dtype) != FUNC_REGBANK(sym->type))
@@ -2502,8 +2502,8 @@ genFunction (iCode * ic)
                             {
                                 banksToSave |= (1 << FUNC_REGBANK(dtype));
                             }
-                            
-                            /* And note that we don't need to do it in 
+
+                            /* And note that we don't need to do it in
                              * genCall.
                              */
                             i->bankSaved = 1;
@@ -2518,24 +2518,24 @@ genFunction (iCode * ic)
                         * The only thing I can think of to do is
                         * throw a warning and hope.
                         */
-                       werror(W_FUNCPTR_IN_USING_ISR);   
+                       werror(W_FUNCPTR_IN_USING_ISR);
                    }
                }
 
                if (banksToSave && options.useXstack)
                {
-                   /* Since we aren't passing it an ic, 
+                   /* Since we aren't passing it an ic,
                     * saveRBank will assume r0 is available to abuse.
                     *
                     * So switch to our (trashable) bank now, so
                     * the caller's R0 isn't trashed.
                     */
                    emitcode ("push", "psw");
-                   emitcode ("mov", "psw,#0x%02x", 
+                   emitcode ("mov", "psw,#0x%02x",
                              (FUNC_REGBANK (sym->type) << 3) & 0x00ff);
                    switchedPSW = TRUE;
                }
-               
+
                for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
                {
                     if (banksToSave & (1 << ix))
@@ -2658,7 +2658,7 @@ genFunction (iCode * ic)
       emitcode ("add", "a,#0x%02x", ((char) sym->xstack & 0xff));
       emitcode ("mov", "_spx,a");
     }
-  
+
   /* if critical function then turn interrupts off */
   if (IFFUNC_ISCRITICAL (ftype))
     {
@@ -2685,7 +2685,7 @@ genEndFunction (iCode * ic)
       emitcode(";", "naked function: no epilogue.");
       return;
   }
-      
+
   if (IFFUNC_ISCRITICAL (sym->type))
     {
       emitcode ("pop", "psw"); /* restore ea via c in psw */
@@ -2769,7 +2769,7 @@ genEndFunction (iCode * ic)
            {
              if (options.parms_in_bank1) {
                  int i;
-                 for (i = 7 ; i >= 0 ; i-- ) {               
+                 for (i = 7 ; i >= 0 ; i-- ) {
                      emitcode ("pop","%s",rb1regs[i]);
                  }
              }
@@ -2788,7 +2788,7 @@ genEndFunction (iCode * ic)
             */
            unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
            int ix;
-         
+
            for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
            {
                if (savedBanks & (1 << ix))
@@ -2796,7 +2796,7 @@ genEndFunction (iCode * ic)
                    unsaveRBank(ix, NULL, FALSE);
                }
            }
-           
+
            if (options.useXstack)
            {
                /* Restore bank AFTER calling unsaveRBank,
@@ -2972,7 +2972,7 @@ findLabelBackwards (iCode * ic, int key)
       count++;
 
       /* If we have any pushes or pops, we cannot predict the distance.
-        I don't like this at all, this should be dealt with in the 
+        I don't like this at all, this should be dealt with in the
         back-end */
       if (ic->op == IPUSH || ic->op == IPOP) {
        return 0;
@@ -3011,7 +3011,7 @@ genPlusIncr (iCode * ic)
 
   /* if increment >=16 bits in register or direct space */
   if ((AOP_TYPE(IC_LEFT(ic)) == AOP_REG || AOP_TYPE(IC_LEFT(ic)) == AOP_DIR ) &&
-      sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) && 
+      sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
       (size > 1) &&
       (icount == 1))
     {
@@ -3391,7 +3391,7 @@ genPlus (iCode * ic)
         }
       else
         {
-          if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) || 
+          if( !sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) ||
              isOperandVolatile (IC_RESULT (ic), FALSE))
            {
              /* just move */
@@ -3669,8 +3669,8 @@ genMinus (iCode * ic)
          aopPut (AOP (IC_RESULT (ic)), "a", offset++, isOperandVolatile (IC_RESULT (ic), FALSE));
        }
     }
-  
-  
+
+
   adjustArithmeticResult (ic);
 
 release:
@@ -3695,7 +3695,6 @@ genMultbits (operand * left,
   outBitC (result);
 }
 
-
 /*-----------------------------------------------------------------*/
 /* genMultOneByte : 8*8=8/16 bit multiplication                    */
 /*-----------------------------------------------------------------*/
@@ -3704,18 +3703,20 @@ genMultOneByte (operand * left,
                operand * right,
                operand * result)
 {
-  sym_link *opetype = operandType (result);
   symbol *lbl;
-  int size=AOP_SIZE(result);
+  int size = AOP_SIZE (result);
+  bool runtimeSign, compiletimeSign;
+  bool lUnsigned, rUnsigned;
 
   D(emitcode (";     genMultOneByte",""));
 
-  if (size<1 || size>2) {
-    // this should never happen
+  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);
       exit (1);
-  }
+    }
 
   /* (if two literals: the value is computed before) */
   /* if one literal, literal on the right */
@@ -3724,91 +3725,171 @@ genMultOneByte (operand * left,
       operand *t = right;
       right = left;
       left = t;
-      //emitcode (";", "swapped left and right");
+      /* 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;
     }
 
-  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");
-    // TODO: check for accumulator clash between left & right aops?
-  
-    if( AOP_TYPE(right)==AOP_LIT ){
-      // moving to accumulator first helps peepholes 
-      MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
-      emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
-    } else {
-      emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
-      MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
+  lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
+  rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
+
+  if (size == 1 /* no, this is not a bug; with a 1 byte result there's
+                  no need to take care about the signedness! */
+      || (lUnsigned && rUnsigned))
+    {
+      /* just an unsigned 8 * 8 = 8 multiply
+         or 8u * 8u = 16u */
+      /* emitcode (";","unsigned"); */
+      /* TODO: check for accumulator clash between left & right aops? */
+
+      if (AOP_TYPE (right) == AOP_LIT)
+        {
+          /* moving to accumulator first helps peepholes */
+          MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
+          emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
+        }
+      else
+        {
+          emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
+          MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
+        }
+
+      emitcode ("mul", "ab");
+      aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
+      if (size == 2)
+        aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
+      return;
+    }
+
+  /* we have to do a signed multiply */
+  /* emitcode (";", "signed"); */
+
+  /* now sign adjust for both left & right */
+
+  /* let's see what's needed: */
+  /* apply negative sign during runtime */
+  runtimeSign = FALSE;
+  /* negative sign from literals */
+  compiletimeSign = FALSE;
+
+  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;
     }
-    
-    emitcode ("mul", "ab");
-    aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
-    if (size==2) {
-      aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
+
+  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;
     }
-    return;
-  }
 
-  // we have to do a signed multiply
+  /* initialize F0, which stores the runtime sign */
+  if (runtimeSign)
+    {
+      if (compiletimeSign)
+       emitcode ("setb", "F0"); /* set sign flag */
+      else
+       emitcode ("clr", "F0"); /* reset sign flag */
+    }
 
-  //emitcode (";", "signed");
-  emitcode ("clr", "F0"); // reset sign flag
-  MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
+  /* save the signs of the operands */
+  if (AOP_TYPE(right) == AOP_LIT)
+    {
+      signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
 
-  lbl=newiTempLabel(NULL);
-  emitcode ("jnb", "acc.7,%05d$",  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");
+      if (!rUnsigned && val < 0)
+        emitcode ("mov", "b,#0x%02x", -val);
+      else
+        emitcode ("mov", "b,#0x%02x", (unsigned char) val);
+    }
+  else /* ! literal */
+    {
+      if (rUnsigned)  /* emitcode (";", "signed"); */
+
+        emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
+      else
+        {
+         MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
+         lbl = newiTempLabel (NULL);
+         emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
+         emitcode ("cpl", "F0"); /* complement sign flag */
+         emitcode ("cpl", "a");  /* 2's complement */
+         emitcode ("inc", "a");
+         emitcode ("", "%05d$:", (lbl->key + 100));
+          emitcode ("mov", "b,a");
+       }
+    }
 
-  emitcode ("", "%05d$:", lbl->key+100);
+  if (AOP_TYPE(left) == AOP_LIT)
+    {
+      signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
 
-  /* if literal */
-  if (AOP_TYPE(right)==AOP_LIT) {
-    signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
-    /* AND literal negative */
-    if (val < 0) {
-      emitcode ("cpl", "F0"); // complement sign flag
-      emitcode ("mov", "b,#0x%02x", -val);
-    } else {
-      emitcode ("mov", "b,#0x%02x", val);
+      if (!lUnsigned && val < 0)
+        emitcode ("mov", "a,#0x%02x", -val);
+      else
+        emitcode ("mov", "a,#0x%02x", (unsigned char) val);
     }
-  } else {
-    lbl=newiTempLabel(NULL);
-    emitcode ("mov", "b,a");
-    emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
-    emitcode ("jnb", "acc.7,%05d$", 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 ("", "%05d$:", lbl->key+100);
-  }
-  emitcode ("mul", "ab");
+  else /* ! literal */
+    {
+      MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
 
-  lbl=newiTempLabel(NULL);
-  emitcode ("jnb", "F0,%05d$", lbl->key+100);
-  // only ONE op was negative, we have to do a 8/16-bit two's complement
-  emitcode ("cpl", "a"); // lsb
-  if (size==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");
-  }
+      if (!lUnsigned)
+        {
+          lbl = newiTempLabel (NULL);
+          emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
+          emitcode ("cpl", "F0"); /* complement sign flag */
+          emitcode ("cpl", "a"); /* 2's complement */
+          emitcode ("inc", "a");
+          emitcode ("", "%05d$:", (lbl->key + 100));
+        }
+    }
 
-  emitcode ("", "%05d$:", lbl->key+100);
+  /* now the multiplication */
+  emitcode ("mul", "ab");
+  if (runtimeSign || compiletimeSign)
+    {
+      lbl = newiTempLabel (NULL);
+      if (runtimeSign)
+        emitcode ("jnb", "F0,%05d$", (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 ("", "%05d$:", (lbl->key + 100));
+    }
   aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
-  if (size==2) {
+  if (size == 2)
     aopPut (AOP (result), "b", 1, isOperandVolatile (result, FALSE));
-  }
 }
 
 /*-----------------------------------------------------------------*/
@@ -3892,84 +3973,189 @@ genDivOneByte (operand * left,
               operand * right,
               operand * result)
 {
-  sym_link *opetype = operandType (result);
-  char *l;
+  bool lUnsigned, rUnsigned;
+  bool runtimeSign, compiletimeSign;
   symbol *lbl;
   int size, offset;
 
   D(emitcode (";     genDivOneByte",""));
 
+  /* Why is it necessary that genDivOneByte() can return an int result?
+     Have a look at:
+     
+       volatile unsigned char uc;
+       volatile signed char sc1, sc2;
+       volatile int i;
+     
+       uc  = 255;
+       sc1 = -1;
+       i = uc / sc1;
+
+     Or:
+  
+       sc1 = -128;
+       sc2 = -1;
+       i = sc1 / sc2;
+
+     In all cases a one byte result would overflow, the following cast to int
+     would return the wrong result.
+  
+     Two possible solution:
+       a) cast operands to int, if ((unsigned) / (signed)) or
+          ((signed) / (signed))
+       b) return an 16 bit signed int; this is what we're doing here!
+  */
+  
   size = AOP_SIZE (result) - 1;
   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 */
       emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
-      l = aopGet (AOP (left), 0, FALSE, FALSE);
-      MOVA (l);
+      MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
       emitcode ("div", "ab");
       aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
       while (size--)
        aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
       return;
     }
-
+  
   /* signed is a little bit more difficult */
 
+  /* now sign adjust for both left & right */
+
+  /* let's see what's needed: */
+  /* apply negative sign during runtime */
+  runtimeSign = FALSE;
+  /* negative sign from literals */
+  compiletimeSign = FALSE;
+
+  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 */
-  l = aopGet (AOP (left), 0, FALSE, FALSE);
-  MOVA (l);
-  emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, TRUE));
-  emitcode ("push", "acc");    /* save it on the stack */
+  if (AOP_TYPE(right) == AOP_LIT)
+    {
+      signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
 
-  /* now sign adjust for both left & right */
-  l = aopGet (AOP (right), 0, FALSE, FALSE);
-  MOVA (l);
-  lbl = newiTempLabel (NULL);
-  emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
-  emitcode ("cpl", "a");
-  emitcode ("inc", "a");
-  emitcode ("", "%05d$:", (lbl->key + 100));
-  emitcode ("mov", "b,a");
+      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));
+      else
+        {
+         MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
+         lbl = newiTempLabel (NULL);
+         emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
+         emitcode ("cpl", "F0"); /* complement sign flag */
+         emitcode ("cpl", "a");  /* 2's complement */
+         emitcode ("inc", "a");
+         emitcode ("", "%05d$:", (lbl->key + 100));
+          emitcode ("mov", "b,a");
+       }
+    }
 
-  /* sign adjust left side */
-  l = aopGet (AOP (left), 0, FALSE, FALSE);
-  MOVA (l);
+  if (AOP_TYPE(left) == AOP_LIT)
+    {
+      signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
 
-  lbl = newiTempLabel (NULL);
-  emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
-  emitcode ("cpl", "a");
-  emitcode ("inc", "a");
-  emitcode ("", "%05d$:", (lbl->key + 100));
+      if (!lUnsigned && val < 0)
+        emitcode ("mov", "a,#0x%02x", -val);
+      else
+        emitcode ("mov", "a,#0x%02x", (unsigned char) val);
+    }
+  else /* ! literal */
+    {
+      MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
+
+      if (!lUnsigned)
+        {
+          lbl = newiTempLabel (NULL);
+          emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
+          emitcode ("cpl", "F0"); /* complement sign flag */
+          emitcode ("cpl", "a");  /* 2's complement */
+          emitcode ("inc", "a");
+          emitcode ("", "%05d$:", (lbl->key + 100));
+        }
+    }
 
   /* now the division */
   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,%05d$", (lbl->key + 100));
-  emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
-  CLRC;
-  emitcode ("clr", "a");
-  emitcode ("subb", "a,b");
-  emitcode ("mov", "b,a");
-  emitcode ("", "%05d$:", (lbl->key + 100));
 
-  /* now we are done */
-  aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
-  if (size > 0)
+  if (runtimeSign || compiletimeSign)
     {
-      emitcode ("mov", "c,b.7");
-      emitcode ("subb", "a,acc");
-    }
-  while (size--)
-    aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
+      lbl = newiTempLabel (NULL);
+      if (runtimeSign)
+        emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
+      emitcode ("cpl", "a"); /* lsb 2's complement */
+      emitcode ("inc", "a");
+      emitcode ("", "%05d$:", (lbl->key + 100));
 
+      aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
+      if (size > 0)
+       {
+         /* msb is 0x00 or 0xff depending on the sign */
+         if (runtimeSign)
+           {
+             emitcode ("mov", "c,F0");
+             emitcode ("subb", "a,acc");
+             while (size--)
+               aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
+           }
+         else /* compiletimeSign */
+           while (size--)
+             aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
+       }
+    }
+  else
+    {
+      aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
+      while (size--)
+       aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
+    }
 }
 
 /*-----------------------------------------------------------------*/
@@ -4047,73 +4233,133 @@ genModOneByte (operand * left,
               operand * right,
               operand * result)
 {
-  sym_link *opetype = operandType (result);
-  char *l;
+  bool lUnsigned, rUnsigned;
+  bool runtimeSign, compiletimeSign;
   symbol *lbl;
+  int size, offset;
 
   D(emitcode (";     genModOneByte",""));
 
+  size = AOP_SIZE (result) - 1;
+  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 */
       emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
-      l = aopGet (AOP (left), 0, FALSE, FALSE);
-      MOVA (l);
+      MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
       emitcode ("div", "ab");
       aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
+      while (size--)
+       aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
       return;
     }
 
   /* signed is a little bit more difficult */
 
-  /* save the signs of the operands */
-  l = aopGet (AOP (left), 0, FALSE, FALSE);
-  MOVA (l);
-
-  emitcode ("xrl", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
-  emitcode ("push", "acc");    /* save it on the stack */
-
   /* now sign adjust for both left & right */
-  l = aopGet (AOP (right), 0, FALSE, FALSE);
-  MOVA (l);
 
-  lbl = newiTempLabel (NULL);
-  emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
-  emitcode ("cpl", "a");
-  emitcode ("inc", "a");
-  emitcode ("", "%05d$:", (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 */
-  l = aopGet (AOP (left), 0, FALSE, FALSE);
-  MOVA (l);
+      if (!rUnsigned && val < 0)
+        emitcode ("mov", "b,#0x%02x", -val);
+      else
+        emitcode ("mov", "b,#0x%02x", (unsigned char) val);
+    }
+  else /* not literal */
+    {
+      if (rUnsigned)
+        emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
+      else
+        {
+         MOVA (aopGet (AOP (right), 0, FALSE, FALSE));
+         lbl = newiTempLabel (NULL);
+         emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
+         emitcode ("cpl", "a"); /* 2's complement */
+         emitcode ("inc", "a");
+         emitcode ("", "%05d$:", (lbl->key + 100));
+          emitcode ("mov", "b,a");
+       }
+    }
 
-  lbl = newiTempLabel (NULL);
-  emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
-  emitcode ("cpl", "a");
-  emitcode ("inc", "a");
-  emitcode ("", "%05d$:", (lbl->key + 100));
+  /* let's see what's needed: */
+  /* apply negative sign during runtime */
+  runtimeSign = FALSE;
+  /* negative sign from literals */
+  compiletimeSign = FALSE;
+  
+  /* sign adjust left side */
+  if (AOP_TYPE(left) == AOP_LIT)
+    {
+      signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
 
-  /* now the multiplication */
-  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,%05d$", (lbl->key + 100));
-  emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
-  CLRC;
-  emitcode ("clr", "a");
-  emitcode ("subb", "a,b");
-  emitcode ("mov", "b,a");
-  emitcode ("", "%05d$:", (lbl->key + 100));
+      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));
 
-  /* now we are done */
-  aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
+      if (!lUnsigned)
+        {
+          runtimeSign = TRUE;
+          emitcode ("clr", "F0"); /* clear sign flag */
+
+          lbl = newiTempLabel (NULL);
+          emitcode ("jnb", "acc.7,%05d$", (lbl->key + 100));
+          emitcode ("setb", "F0"); /* set sign flag */
+          emitcode ("cpl", "a");   /* 2's complement */
+          emitcode ("inc", "a");
+          emitcode ("", "%05d$:", (lbl->key + 100));
+        }
+    }
 
+  /* now the modulus */
+  emitcode ("div", "ab");
+  
+  if (runtimeSign || compiletimeSign)
+    {
+      emitcode ("mov", "a,b");
+      lbl = newiTempLabel (NULL);
+      if (runtimeSign)
+        emitcode ("jnb", "F0,%05d$", (lbl->key + 100));
+      emitcode ("cpl", "a"); /* 2's complement */
+      emitcode ("inc", "a");
+      emitcode ("", "%05d$:", (lbl->key + 100));
+     
+      aopPut (AOP (result), "a", 0, isOperandVolatile (result, FALSE));
+      if (size > 0)
+       {
+         /* msb is 0x00 or 0xff depending on the sign */
+         if (runtimeSign)
+           {
+             emitcode ("mov", "c,F0");
+             emitcode ("subb", "a,acc");
+             while (size--)
+               aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
+           }
+         else /* compiletimeSign */
+           while (size--)
+             aopPut (AOP (result), "#0xff", offset++, isOperandVolatile (result, FALSE));
+       }
+    }
+  else
+    {
+      aopPut (AOP (result), "b", 0, isOperandVolatile (result, FALSE));
+      while (size--)
+       aopPut (AOP (result), zero, offset++, isOperandVolatile (result, FALSE));
+    }
 }
 
 /*-----------------------------------------------------------------*/
@@ -4399,7 +4645,7 @@ gencjneshort (operand * left, operand * right, symbol * lbl)
       right = left;
       left = t;
     }
-  
+
   if (AOP_TYPE (right) == AOP_LIT)
     lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
 
@@ -4671,7 +4917,7 @@ hasInc (operand *op, iCode *ic,int osize)
   sym_link *retype = getSpec (type);
   iCode *lic = ic->next;
   int isize ;
-  
+
   /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
   if (!IS_SYMOP(op)) return NULL;
 
@@ -4682,7 +4928,7 @@ hasInc (operand *op, iCode *ic,int osize)
   while (lic) {
     /* if operand of the form op = op + <sizeof *op> */
     if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
-       isOperandEqual(IC_RESULT(lic),op) && 
+       isOperandEqual(IC_RESULT(lic),op) &&
        isOperandLiteral(IC_RIGHT(lic)) &&
        operandLitValue(IC_RIGHT(lic)) == isize) {
       return lic;
@@ -5900,7 +6146,7 @@ genSwap (iCode * ic)
   result = IC_RESULT (ic);
   aopOp (left, ic, FALSE);
   aopOp (result, ic, FALSE);
-  
+
   switch (AOP_SIZE (left))
     {
     case 1: /* swap nibbles in byte */
@@ -5940,12 +6186,12 @@ genSwap (iCode * ic)
     default:
       wassertl(FALSE, "unsupported SWAP operand size");
     }
-  
+
   freeAsmop (left, NULL, ic, TRUE);
   freeAsmop (result, NULL, ic, TRUE);
 }
 
-    
+
 /*-----------------------------------------------------------------*/
 /* AccRol - rotate left accumulator by known count                 */
 /*-----------------------------------------------------------------*/
@@ -6225,16 +6471,16 @@ AccAXLsh (char *x, int shCount)
       AccAXRrl1 (x);           // BCCCCCCD:D000000B
       AccAXRrl1 (x);           // BBCCCCCC:DD000000
 #else
-      emitcode("rrc","a"); 
-      emitcode("xch","a,%s", x); 
-      emitcode("rrc","a"); 
-      emitcode("mov","c,acc.0"); //<< get correct bit 
-      emitcode("xch","a,%s", x); 
-
-      emitcode("rrc","a"); 
-      emitcode("xch","a,%s", x); 
-      emitcode("rrc","a"); 
-      emitcode("xch","a,%s", x); 
+      emitcode("rrc","a");
+      emitcode("xch","a,%s", x);
+      emitcode("rrc","a");
+      emitcode("mov","c,acc.0"); //<< get correct bit
+      emitcode("xch","a,%s", x);
+
+      emitcode("rrc","a");
+      emitcode("xch","a,%s", x);
+      emitcode("rrc","a");
+      emitcode("xch","a,%s", x);
 #endif
       break;
     case 7:                    // a:x <<= 7
@@ -6958,7 +7204,7 @@ shiftRLong (operand * left, int offl,
   }
 
   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
-  
+
   if (offl==MSB16) {
     // shift is > 8
     if (sign) {
@@ -7394,7 +7640,7 @@ emitPtrByteGet (char *rname, int p_type, bool preserveAinB)
         emitcode ("mov", "b,a");
       emitcode ("movx", "a,@%s", rname);
       break;
-      
+
     case FPOINTER:
       if (preserveAinB)
         emitcode ("mov", "b,a");
@@ -7445,7 +7691,7 @@ emitPtrByteSet (char *rname, int p_type, char *src)
       MOVA (src);
       emitcode ("movx", "@%s,a", rname);
       break;
-      
+
     case FPOINTER:
       MOVA (src);
       emitcode ("movx", "@dptr,a");
@@ -7787,7 +8033,7 @@ loadDptrFromOperand (operand *op, bool loadBToo)
          emitcode ("mov", "dptr,%s", aopGet (AOP (op), 0, TRUE, FALSE));
           if (loadBToo)
             {
-             if (AOP(op)->aopu.aop_immd.from_cast_remat) 
+             if (AOP(op)->aopu.aop_immd.from_cast_remat)
                emitcode ("mov", "b,%s",aopGet(AOP (op), AOP_SIZE(op)-1, FALSE, FALSE));
              else
                 {
@@ -7847,7 +8093,7 @@ genFarPointerGet (operand * left,
 
   aopOp (left, ic, FALSE);
   loadDptrFromOperand (left, FALSE);
-  
+
   /* so dptr now contains the address */
   aopOp (result, ic, FALSE);
 
@@ -7867,7 +8113,7 @@ genFarPointerGet (operand * left,
            emitcode ("inc", "dptr");
        }
     }
-  
+
   if (pi && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR) {
     aopPut ( AOP (left), "dpl", 0, isOperandVolatile (left, FALSE));
     aopPut ( AOP (left), "dph", 1, isOperandVolatile (left, FALSE));
@@ -7891,7 +8137,7 @@ genCodePointerGet (operand * left,
 
   aopOp (left, ic, FALSE);
   loadDptrFromOperand (left, FALSE);
-  
+
   /* so dptr now contains the address */
   aopOp (result, ic, FALSE);
 
@@ -7913,7 +8159,7 @@ genCodePointerGet (operand * left,
              emitcode ("inc", "dptr");
            }
          else
-           { 
+           {
              emitcode ("mov", "a,#0x%02x", offset);
              emitcode ("movc", "a,@a+dptr");
              aopPut (AOP (result), "a", offset++, isOperandVolatile (result, FALSE));
@@ -7944,7 +8190,7 @@ genGenPointerGet (operand * left,
 
   aopOp (left, ic, FALSE);
   loadDptrFromOperand (left, TRUE);
-  
+
   /* so dptr know contains the address */
   aopOp (result, ic, FALSE);
 
@@ -8122,7 +8368,7 @@ genPackBits (sym_link * etype,
   /* all except the partial byte at the end                 */
   for (rlen=blen;rlen>=8;rlen-=8)
     {
-      emitPtrByteSet (rname, p_type, 
+      emitPtrByteSet (rname, p_type,
                       aopGet (AOP (right), offset++, FALSE, TRUE) );
       if (rlen>8)
         emitcode ("inc", "%s", rname);
@@ -8132,7 +8378,7 @@ genPackBits (sym_link * etype,
   if (rlen)
     {
       mask = (((unsigned char) -1 << rlen) & 0xff);
-      
+
       if (AOP_TYPE (right) == AOP_LIT)
         {
           /* Case with partial byte and literal source
@@ -8437,7 +8683,7 @@ genFarPointerSet (operand * right,
 
   aopOp (result, ic, FALSE);
   loadDptrFromOperand (result, FALSE);
-  
+
   /* so dptr know contains the address */
   aopOp (right, ic, FALSE);
 
@@ -8482,7 +8728,7 @@ genGenPointerSet (operand * right,
 
   aopOp (result, ic, FALSE);
   loadDptrFromOperand (result, TRUE);
-  
+
   /* so dptr know contains the address */
   aopOp (right, ic, FALSE);
 
@@ -8573,7 +8819,7 @@ genPointerSet (iCode * ic, iCode *pi)
       break;
 
     default:
-      werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
+      werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
              "genPointerSet: illegal pointer type");
     }
 
@@ -8972,16 +9218,16 @@ genCast (iCode * ic)
            {
                int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
                char gpValStr[10];
-           
+
                if (gpVal == -1)
                {
                    // pointerTypeToGPByte will have bitched.
                    exit(1);
                }
-           
+
                sprintf(gpValStr, "#0x%d", gpVal);
                aopPut (AOP (result), gpValStr, GPTRSIZE - 1, isOperandVolatile (result, FALSE));
-           }       
+           }
          goto release;
        }
 
@@ -9085,7 +9331,7 @@ genDjnz (iCode * ic, iCode * ifx)
        * it back after the decrement.
        */
       char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
-      
+
       if (strcmp(rByte, "a"))
       {
            /* Something is hopelessly wrong */
@@ -9141,11 +9387,11 @@ genReceive (iCode * ic)
          regs *tempRegs[4];
          int receivingA = 0;
          int roffset = 0;
-             
+
          for (offset = 0; offset<size; offset++)
            if (!strcmp (fReturn[offset], "a"))
              receivingA = 1;
-         
+
          if (!receivingA)
            {
              if (size==1 || getTempRegs(tempRegs, size-1, ic))
@@ -9207,7 +9453,7 @@ genReceive (iCode * ic)
       }
   }
 
-release:  
+release:
   freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
 }
 
@@ -9280,7 +9526,7 @@ genCritical (iCode *ic)
   symbol *tlbl = newiTempLabel (NULL);
 
   D(emitcode(";     genCritical",""));
-  
+
   if (IC_RESULT (ic))
     aopOp (IC_RESULT (ic), ic, TRUE);
 
@@ -9305,7 +9551,7 @@ static void
 genEndCritical (iCode *ic)
 {
   D(emitcode(";     genEndCritical",""));
-  
+
   if (IC_RIGHT (ic))
     {
       aopOp (IC_RIGHT (ic), ic, FALSE);
@@ -9366,7 +9612,7 @@ gen51Code (iCode * lic)
   for (ic = lic; ic; ic = ic->next)
     {
       _G.current_iCode = ic;
-      
+
       if (ic->lineno && cln != ic->lineno)
        {
          if (options.debug)
@@ -9378,7 +9624,7 @@ gen51Code (iCode * lic)
              _G.debugLine = 0;
            }
          if (!options.noCcodeInAsm) {
-           emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno, 
+           emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno,
                      printCLine(ic->filename, ic->lineno));
          }
          cln = ic->lineno;
@@ -9389,7 +9635,7 @@ gen51Code (iCode * lic)
 
        for (i=0; i<8; i++) {
          sprintf (&regsInUse[i],
-                  "%c", ic->riu & (1<<i) ? i+'0' : '-'); 
+                  "%c", ic->riu & (1<<i) ? i+'0' : '-');
        }
        regsInUse[i]=0;
        emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
diff --git a/support/regression/tests/onebyte.c b/support/regression/tests/onebyte.c
new file mode 100644 (file)
index 0000000..a5fb515
--- /dev/null
@@ -0,0 +1,123 @@
+/** test one byte mul/div/mod operations.
+
+  attrL: volatile,
+  attrR: volatile,
+*/
+#include <testfwk.h>
+
+void
+testMul(void)
+{
+  {attrL}            char  cL;
+  {attrL}  unsigned  char ucL;
+  {attrR}            char  cR;
+  {attrR}  unsigned  char ucR;
+  volatile           char   r8 , r8b;
+  volatile unsigned  char  ur8, ur8b;
+  volatile           short r16, r16b;
+
+  cL = -127; cR =   -5; r16 =  cL * cR; r16b = cR *  cL; ASSERT(r16 ==  635); ASSERT(r16b ==  635);
+  cL =  127; cR =   -5; r16 =  cL * cR; r16b = cR *  cL; ASSERT(r16 == -635); ASSERT(r16b == -635);
+  cL = -127; cR =    5; r16 =  cL * cR; r16b = cR *  cL; ASSERT(r16 == -635); ASSERT(r16b == -635);
+  cL =  127; cR =    5; r16 =  cL * cR; r16b = cR *  cL; ASSERT(r16 ==  635); ASSERT(r16b ==  635);
+
+  cL = -128; cR =   -1; ur8  =  cL * cR; ur8b  = cR *  cL; ASSERT(ur8  ==  128); ASSERT(ur8b  ==  128);
+  cL =  128; cR =   -1;  r8  =  cL * cR;  r8b  = cR *  cL; ASSERT( r8  == -128); ASSERT( r8b  == -128);
+  cL = -128; cR =    1;  r8  =  cL * cR;  r8b  = cR *  cL; ASSERT( r8  == -128); ASSERT( r8b  == -128);
+  cL =  128; cR =    1; ur8  =  cL * cR; ur8b  = cR *  cL; ASSERT(ur8  ==  128); ASSERT(ur8b  ==  128);
+
+#ifndef SDCC_z80
+  ucL = 128; cR =   -5; r16 = ucL * cR; r16b = cR * ucL; ASSERT(r16 == -640); ASSERT(r16b == -640);
+  ucL = 128; cR =    5; r16 = ucL * cR; r16b = cR * ucL; ASSERT(r16 ==  640); ASSERT(r16b ==  640);
+#endif
+
+  ucL = 127;  cR =  -1;  r8 = ucL * cR;   r8b  = cR * ucL; ASSERT( r8 == -127); ASSERT( r8b  == -127);
+  ucL = 128;  cR =   1; ur8 = ucL * cR;  ur8b  = cR * ucL; ASSERT(ur8 ==  128); ASSERT(ur8b  ==  128);
+  ucL = 128; ucR =   5; r16 = ucL * ucR; r16b = ucR * ucL; ASSERT(r16 ==  640); ASSERT(r16b ==  640);
+  ucL = 128; ucR =   1; ur8 = ucL * ucR; ur8b = ucR * ucL; ASSERT(ur8 ==  128); ASSERT(ur8b ==  128);
+}
+
+void
+testDiv(void)
+{
+  {attrL}           char  cL;
+  {attrL}  unsigned char ucL;
+  {attrR}           char  cR;
+  {attrR}  unsigned char ucR;
+  volatile          char  r8;
+  volatile unsigned char ur8;
+  volatile         short r16;
+
+   cL = -128;  cR =   -2; r8  = cL / cR; ASSERT(r8  ==  64);
+   cL = -128;  cR =   -2; r16 = cL / cR; ASSERT(r16 ==  64);
+  ucL =  255; ucR =    3; r8 = ucL / ucR; ASSERT(r8 ==  85);
+  ucL =  255; ucR =  255; r8 = ucL / ucR; ASSERT(r8 ==   1);
+  ucL =    3; ucR =  255; r8 = ucL / ucR; ASSERT(r8 ==   0);
+
+   cL =  127;  cR =    3; r8 =  cL /  cR; ASSERT(r8 ==  42);
+   cL = -127;  cR =    3; r8 =  cL /  cR; ASSERT(r8 == -42);
+   cL =  127;  cR =   -3; r8 =  cL /  cR; ASSERT(r8 == -42);
+   cL = -127;  cR =   -3; r8 =  cL /  cR; ASSERT(r8 ==  42);
+
+  ucL =  127;  cR =    3; r8 = ucL /  cR; ASSERT(r8 ==  42);
+  ucL =  255;  cR =    3; r8 = ucL /  cR; ASSERT(r8 ==  85);
+#ifndef SDCC_z80
+  ucL =  127;  cR =   -3; r8 = ucL /  cR; ASSERT(r8 == -42);
+  ucL =  255;  cR =   -3; r8 = ucL /  cR; ASSERT(r8 == -85);
+#endif
+   
+   cL =  127; ucR =    3; r8 =  cL / ucR; ASSERT(r8 ==  42);
+   cL = -127; ucR =    3; r8 =  cL / ucR; ASSERT(r8 == -42);
+   cL =  127; ucR =  128; r8 =  cL / ucR; ASSERT(r8 ==   0);
+   cL = -127; ucR =  128; r8 =  cL / ucR; ASSERT(r8 ==   0);
+
+   cL =  127;  cR =    1; r8  =  cL /  cR; ASSERT(r8  == 127);
+   cL =  127;  cR =    1; r16 =  cL /  cR; ASSERT(r16 == 127);
+
+  ucL = 251;   cR =    1; ur8 = ucL /  cR; ASSERT(ur8 == 251);
+  ucL = 251;   cR =    1; r16 = ucL /  cR; ASSERT(r16 == 251);
+  
+#ifndef SDCC_z80
+  ucL = 253;   cR =   -3; r8  = ucL /  cR; ASSERT(r8  == -84);
+  ucL = 253;   cR =   -3; r16 = ucL /  cR; ASSERT(r16 == -84);
+  
+  ucL =  254;  cR =   -1; r16 = ucL /  cR; ASSERT(r16 == -254);
+#endif
+   cL = -128;  cR =   -1; r16 =  cL /  cR; ASSERT(r16 ==  128);
+}
+
+void
+testMod(void)
+{
+  {attrL}           char  cL;
+  {attrL}  unsigned char ucL;
+  {attrR}           char  cR;
+  {attrR}  unsigned char ucR;
+  volatile          char  r8;
+  volatile unsigned char ur8;
+  volatile         short r16;
+
+  ucL =  128;  cR =    5; r16 = ucL %  cR; ASSERT(r16 ==  3);
+#ifndef SDCC_z80
+  ucL =  128;  cR =   -5; r16 = ucL %  cR; ASSERT(r16 ==  3);
+#endif
+  ucL =  128; ucR =    5; r16 = ucL % ucR; ASSERT(r16 ==  3);
+
+  ucL =  128; ucR =  255; ur8 = ucL % ucR; ASSERT(ur8 == 128);
+  ucL =  128; ucR =  255; r16 = ucL % ucR; ASSERT(r16 == 128);
+
+  ucL =  128;  cR =  127; r8  = ucL %  cR; ASSERT(r8  ==  1);
+   
+   cL =  127;  cR =    5; r16 =  cL %  cR; ASSERT(r16 ==  2);
+   r16 = -1;
+   cL =  127;  cR =   -5; r16 =  cL %  cR; ASSERT(r16 ==  2);
+   r16 = -1;
+   cL =  127; ucR =    5; r16 =  cL % ucR; ASSERT(r16 ==  2);
+  
+   cL = -128;  cR =    5; r16 =  cL %  cR; ASSERT(r16 == -3);
+   r16 = 0;
+   cL = -128;  cR =   -5; r16 =  cL %  cR; ASSERT(r16 == -3);
+   r16 = 0;
+   cL = -128; ucR =    5; r16 =  cL % ucR; ASSERT(r16 == -3);
+}