* src/SDCCsymt.c (initCSupport): change return type of divschar to
authortecodev <tecodev@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Sun, 18 Jun 2006 16:42:39 +0000 (16:42 +0000)
committertecodev <tecodev@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Sun, 18 Jun 2006 16:42:39 +0000 (16:42 +0000)
  int for PIC16
* src/pic16/genarith.c (genAddLit): sign-extend via standard routine
  (pic16_genMinusBits): simplified sign-extension
  (pic16_genUMult8XLit_8,pic16_genUMult8X8_8): renamed to
    pic16_genMult8XLit_n resp. pic16_genMult8X8_n, fixed and
    adjusted to correctly handle mixed-signed operands, disabled
    now unused multiplciation routines
* src/pic16/gen.c (pic16_pushpCodeOp): fixed to handle literals
  (assignResultValue): added argument denoting the size of the result
    as returned by the function (fixes upcasts in assigning from
    function calls: char foo(); int i = foo();)
  (genCall,genPcall,genGenPointerGet,genReceive): pass size of
    function result to assignResultValue
  (genMult): disabled inlined multiplication code
  (genDiv): augmented to also handle the modulus operator, fixed to
    handle mixed-signed operands correctly
  (genMod): simply call genDiv, disabled unused code
  (genAssign): fixed missing (sign-)extension on result
* src/pic16/main.c (_hasNativeMulFor): accept literals [-128..256) as
    valid char operands, allow signed operands for native code, added
    division and modulo operator handling
* device/lib/pic16/libsdcc/char/divschar.c: divschar returns an int

As a consequence, onebyte.c (if split into two files) and muldiv.c
pass regression tests.

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

ChangeLog
device/lib/pic16/libsdcc/char/divschar.c
src/SDCCsymt.c
src/pic16/gen.c
src/pic16/genarith.c
src/pic16/main.c

index f7d2e4d0cce261b89dc36b7a20ee5351a93e6c91..7db19ff33d7b8908576a867ad298004e1b72646e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+2006-06-18 Raphael Neider <rneider AT web.de>
+
+       * src/SDCCsymt.c (initCSupport): change return type of divschar to
+         int for PIC16
+       * src/pic16/genarith.c (genAddLit): sign-extend via standard routine
+         (pic16_genMinusBits): simplified sign-extension
+         (pic16_genUMult8XLit_8,pic16_genUMult8X8_8): renamed to
+           pic16_genMult8XLit_n resp. pic16_genMult8X8_n, fixed and
+           adjusted to correctly handle mixed-signed operands, disabled
+           now unused multiplciation routines
+       * src/pic16/gen.c (pic16_pushpCodeOp): fixed to handle literals
+         (assignResultValue): added argument denoting the size of the result
+           as returned by the function (fixes upcasts in assigning from
+           function calls: char foo(); int i = foo();)
+         (genCall,genPcall,genGenPointerGet,genReceive): pass size of
+           function result to assignResultValue
+         (genMult): disabled inlined multiplication code
+         (genDiv): augmented to also handle the modulus operator, fixed to
+           handle mixed-signed operands correctly
+         (genMod): simply call genDiv, disabled unused code
+         (genAssign): fixed missing (sign-)extension on result
+       * src/pic16/main.c (_hasNativeMulFor): accept literals [-128..256) as
+           valid char operands, allow signed operands for native code, added
+           division and modulo operator handling
+       * device/lib/pic16/libsdcc/char/divschar.c: divschar returns an int
+       
+       As a consequence, onebyte.c (if split into two files) and muldiv.c
+       pass regression tests.
+
 2006-06-17 Frieder Ferlemann <Frieder.Ferlemann AT web.de>
 
        * doc/Makefile.in: two runs of makeindex seem needed to get
index 173ea905e813c0dbc33cc4238b03baafdd8f6da9..9cfeb7c6b184b690f73992f1b49497fb693226b6 100644 (file)
@@ -33,9 +33,9 @@
 
 unsigned char _divuchar (unsigned char a, unsigned char b);
 
-char _divschar (char a, char b) _IL_REENTRANT
+int _divschar (char a, char b) _IL_REENTRANT
 {
-  register char r;
+  register unsigned char r;
   char ta, tb;
 
     if(a<0)ta = -a; else ta = a;
index 8031d9fce9013670b908847798febf6a74f6f26d..6e2b7aed87d039adef6bdc1b8cd4822d5a203e13 100644 (file)
@@ -3456,17 +3456,50 @@ initCSupport ()
         {
           for (muldivmod = 1; muldivmod < 3; muldivmod++)
             {
-              /* div and mod */
-              SNPRINTF (buffer, sizeof(buffer),
-                        "_%s%s%s",
-                       smuldivmod[muldivmod],
-                       ssu[su],
-                       sbwd[bwd]);
-              __muldiv[muldivmod][bwd][su] = funcOfType (_mangleFunctionName(buffer), __multypes[bwd][su], __multypes[bwd][su], 2, options.intlong_rent);
-              FUNC_NONBANKED (__muldiv[muldivmod][bwd][su]->type) = 1;
+              /* div and mod : s8_t x s8_t -> s8_t should be s8_t x s8_t -> s16_t, see below */
+             if (!TARGET_IS_PIC16 || muldivmod != 1 || bwd != 0 || su != 0)
+             {
+               SNPRINTF (buffer, sizeof(buffer),
+                   "_%s%s%s",
+                   smuldivmod[muldivmod],
+                   ssu[su],
+                   sbwd[bwd]);
+               __muldiv[muldivmod][bwd][su] = funcOfType (
+                   _mangleFunctionName(buffer),
+                   __multypes[bwd][su],
+                   __multypes[bwd][su],
+                   2,
+                   options.intlong_rent);
+               FUNC_NONBANKED (__muldiv[muldivmod][bwd][su]->type) = 1;
+             }
             }
         }
     }
+
+  if (TARGET_IS_PIC16)
+  {
+    /* PIC16 port wants __divschar/__modschar to return an int, so that both
+     * 100 / -4 = -25 and -128 / -1 = 128 can be handled correctly
+     * (first one would have to be sign extended, second one must not be).
+     * Similarly, modschar should be handled, but the iCode introduces cast
+     * here and forces '% : s8 x s8 -> s8' ... */
+    su = 0; bwd = 0;
+    for (muldivmod = 1; muldivmod < 2; muldivmod++) {
+      SNPRINTF (buffer, sizeof(buffer),
+         "_%s%s%s",
+         smuldivmod[muldivmod],
+         ssu[su],
+         sbwd[bwd]);
+      __muldiv[muldivmod][bwd][su] = funcOfType (
+         _mangleFunctionName(buffer),
+         __multypes[1][su],
+         __multypes[bwd][su],
+         2,
+         options.intlong_rent);
+      FUNC_NONBANKED (__muldiv[muldivmod][bwd][su]->type) = 1;
+    }
+  }
+
   /* mul only */
   muldivmod = 0;
   /* byte */
index 2ac93042e169ee343d481d530f37c9174ad4fed0..74da6f0ec6f7c676010b49cce13805c731129a24 100644 (file)
 /* Wrapper to execute `code' at most once. */
 #define PERFORM_ONCE(id,code)  do { static char id = 0; if (!id) { id = 1; code } } while (0)
 
+void pic16_genMult8X8_n (operand *, operand *,operand *);
+#if 0
 extern void pic16_genUMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
 extern void pic16_genSMult8X8_16 (operand *, operand *,operand *,pCodeOpReg *);
-void pic16_genMult8X8_8 (operand *, operand *,operand *);
 void pic16_genMult16X16_16(operand *, operand *, operand *);
 void pic16_genMult32X32_32(operand *, operand *, operand *);
+#endif
 pCode *pic16_AssembleLine(char *line, int peeps);
 extern void pic16_printpBlock(FILE *of, pBlock *pb);
 static asmop *newAsmop (short type);
@@ -2499,7 +2501,12 @@ void pic16_testStackOverflow(void)
 void pic16_pushpCodeOp(pCodeOp *pcop)
 {
 //     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-  pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
+  if (pcop->type == PO_LITERAL) {
+    pic16_emitpcode(POC_MOVLW, pcop);
+    pic16_emitpcode(POC_MOVWF, pic16_popCopyReg( pic16_stack_postdec ));
+  } else {
+    pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pcop, pic16_popCopyReg( pic16_stack_postdec )));
+  }
   if(pic16_options.gstack)
     pic16_testStackOverflow();
     
@@ -2990,7 +2997,7 @@ void pic16_loadFromReturn(operand *op, int offset, pCodeOp *src)
 /* assignResultValue - assign results to oper, rescall==1 is       */
 /*                     called from genCall() or genPcall()         */
 /*-----------------------------------------------------------------*/
-static void assignResultValue(operand * oper, int rescall)
+static void assignResultValue(operand * oper, int res_size, int rescall)
 {
   int size = AOP_SIZE(oper);
   int offset=0;
@@ -3009,20 +3016,22 @@ static void assignResultValue(operand * oper, int rescall)
         /* 8-bits, result in WREG */
         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(oper), 0));
                        
-        if(size>1) {
+        if(size > 1 && res_size > 1) {
          /* 16-bits, result in PRODL:WREG */
          pic16_loadFromReturn(oper, 1, pic16_popCopyReg(&pic16_pc_prodl));
        }
                        
-       if(size>2) {
+       if(size > 2 && res_size > 2) {
          /* 24-bits, result in PRODH:PRODL:WREG */
          pic16_loadFromReturn(oper, 2, pic16_popCopyReg(&pic16_pc_prodh)); // patch 14
        }
                        
-       if(size>3) {
+       if(size > 3 && res_size > 3) {
          /* 32-bits, result in FSR0L:PRODH:PRODL:WREG */
          pic16_loadFromReturn(oper, 3, pic16_popCopyReg(&pic16_pc_fsr0l)); // patch14
        }
+
+       pic16_addSign(oper, res_size, IS_UNSIGNED(operandType(oper)));
       
       } else {
         /* >32-bits, result on stack, and FSR0 points to beginning.
@@ -3393,7 +3402,11 @@ static void genCall (iCode *ic)
       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
       _G.accInUse--;
 
-      assignResultValue(IC_RESULT(ic), 1);
+      /* Must not assign an 8-bit result to a 16-bit variable;
+       * this would use (used...) the uninitialized PRODL! */
+      /* FIXME: Need a proper way to obtain size of function result type,
+       * OP_SYM_ETYPE does not work: it dereferences pointer types! */
+      assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next), 1);
 
       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
                 pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
@@ -3540,7 +3553,9 @@ static void genPcall (iCode *ic)
       pic16_aopOp(IC_RESULT(ic),ic,FALSE);
       _G.accInUse--;
 
-      assignResultValue(IC_RESULT(ic), 1);
+      /* FIXME: Need proper way to obtain the function result's type.
+       * OP_SYM_TYPE(IC_LEFT(ic))->next does not work --> points to function pointer */
+      assignResultValue(IC_RESULT(ic), getSize(OP_SYM_TYPE(IC_LEFT(ic))->next->next), 1);
 
       DEBUGpic16_emitcode ("; ","%d left %s",__LINE__,
               pic16_AopType(AOP_TYPE(IC_RESULT(ic))));
@@ -4216,9 +4231,10 @@ static void genMultOneByte (operand *left,
                                        pic16_aopGet(AOP(result),0,FALSE,FALSE));
        }
        
-       pic16_genMult8X8_8 (left, right,result);
+       pic16_genMult8X8_n (left, right,result);
 }
 
+#if 0
 /*-----------------------------------------------------------------*/
 /* genMultOneWord : 16 bit multiplication                          */
 /*-----------------------------------------------------------------*/
@@ -4255,7 +4271,9 @@ static void genMultOneWord (operand *left,
        
   pic16_genMult16X16_16(left, right,result);
 }
+#endif
 
+#if 0
 /*-----------------------------------------------------------------*/
 /* genMultOneLong : 32 bit multiplication                          */
 /*-----------------------------------------------------------------*/
@@ -4292,6 +4310,7 @@ static void genMultOneLong (operand *left,
        
   pic16_genMult32X32_32(left, right,result);
 }
+#endif
 
 
 
@@ -4327,6 +4346,7 @@ static void genMult (iCode *ic)
          goto release ;
        }
 
+#if 0
        /* if both are of size == 2 */
        if(AOP_SIZE(left) == 2
                && AOP_SIZE(right) == 2) {
@@ -4340,7 +4360,11 @@ static void genMult (iCode *ic)
                genMultOneLong(left, right, result);
          goto release;
        }
-       
+#endif
+
+       fprintf( stderr, "%s: should have been transformed into function call\n",__FUNCTION__ );
+       assert( !"Multiplication should have been transformed into function call!" );
+
        pic16_emitcode("multiply ","sizes are greater than 4 ... need to insert proper algor.");
 
 
@@ -4354,6 +4378,7 @@ release :
        pic16_freeAsmop(result,NULL,ic,TRUE); 
 }
 
+#if 0
 /*-----------------------------------------------------------------*/
 /* genDivbits :- division of bits                                  */
 /*-----------------------------------------------------------------*/
@@ -4523,6 +4548,7 @@ static void genDivOneByte (operand *left,
         pic16_aopPut(AOP(result),"a",offset++);
 
 }
+#endif
 
 /*-----------------------------------------------------------------*/
 /* genDiv - generates code for division                            */
@@ -4532,8 +4558,12 @@ static void genDiv (iCode *ic)
     operand *left = IC_LEFT(ic);
     operand *right = IC_RIGHT(ic);
     operand *result= IC_RESULT(ic);   
-
-
+    int negated = 0;
+    int leftVal = 0, rightVal = 0;
+    int signedLits = 0;
+    char *functions[2][2] = { { "__divschar", "__divuchar" }, { "__modschar", "__moduchar" } };
+    int op = 0;
+    
        /* Division is a very lengthy algorithm, so it is better
         * to call support routines than inlining algorithm.
         * Division functions written here just in case someone
@@ -4546,6 +4576,207 @@ static void genDiv (iCode *ic)
     pic16_aopOp (right,ic,FALSE);
     pic16_aopOp (result,ic,TRUE);
 
+    if (ic->op == '/')
+      op = 0;
+    else if (ic->op == '%')
+      op = 1;
+    else
+      assert( !"invalid operation requested in genDivMod" );
+
+    /* get literal values */
+    if (IS_VALOP(left)) {
+      leftVal = (int)floatFromVal( OP_VALUE(left) );
+      assert( leftVal >= -128 && leftVal < 256 );
+      if (leftVal < 0) { signedLits++; }
+    }
+    if (IS_VALOP(right)) {
+      rightVal = (int)floatFromVal( OP_VALUE(right) );
+      assert( rightVal >= -128 && rightVal < 256 );
+      if (rightVal < 0) { signedLits++; }
+    }
+
+    /* We should only come here to convert all
+     * / : {u8_t, s8_t} x {u8_t, s8_t} -> {u8_t, s8_t}
+     * with exactly one operand being s8_t into
+     * u8_t x u8_t -> u8_t. All other cases should have been
+     * turned into calls to support routines beforehand... */
+    if ((AOP_SIZE(left) == 1 || IS_VALOP(left))
+       && (AOP_SIZE(right) == 1 || IS_VALOP(right)))
+    {
+      if ((!IS_UNSIGNED(operandType(right)) || rightVal < 0)
+         && (!IS_UNSIGNED(operandType(left)) || leftVal < 0))
+      {
+       /* Both operands are signed or negative, use _divschar
+        * instead of _divuchar */
+       pushaop(AOP(right), 0);
+       pushaop(AOP(left), 0);
+
+       /* call _divschar */
+       pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][0]));
+
+       {
+         symbol *sym;
+         sym = newSymbol( functions[op][0], 0 );
+         sym->used++;
+         strcpy(sym->rname, functions[op][0]);
+         checkAddSym(&externs, sym);
+       }
+
+       /* assign result */
+       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
+       if (AOP_SIZE(result) > 1)
+       {
+         pic16_emitpcode(POC_MOVFF,
+             pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
+               pic16_popGet(AOP(result), 1)));
+         /* sign extend */
+         pic16_addSign(result, 2, 1);
+       }
+
+       /* clean up stack */
+       pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
+       pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
+
+       goto release;
+      }
+      
+      /* push right operand */
+      if (IS_VALOP(right)) {
+       if (rightVal < 0) {
+         pic16_pushpCodeOp( pic16_popGetLit(-rightVal) );
+         negated++;
+       } else {
+         pushaop(AOP(right), 0);
+       }
+      } else if (!IS_UNSIGNED(operandType(right))) {
+       pic16_mov2w(AOP(right), 0);
+       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
+       pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
+       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
+       negated++;
+      } else {
+       pushaop(AOP(right), 0);
+      }
+
+      /* push left operand */
+      if (IS_VALOP(left)) {
+       if (leftVal < 0) {
+         pic16_pushpCodeOp(pic16_popGetLit(-leftVal));
+         negated++;
+       } else {
+         pushaop(AOP(left), 0);
+       }
+      } else if (!IS_UNSIGNED(operandType(left))) {
+       pic16_mov2w(AOP(left),0);
+       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
+       pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
+       pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(pic16_stack_postdec));
+       negated++;
+      } else {
+       pushaop(AOP(left), 0);
+      }
+      
+      /* call _divuchar */
+      pic16_emitpcode(POC_CALL, pic16_popGetWithString(functions[op][1]));
+
+      {
+       symbol *sym;
+       sym = newSymbol( functions[op][1], 0 );
+       sym->used++;
+       strcpy(sym->rname, functions[op][1]);
+       checkAddSym(&externs, sym);
+      }
+
+      /* Revert negation(s) from above.
+       * This is inefficient: if both operands are negative, this
+       * should not touch WREG. However, determining that exactly
+       * one operand was negated costs at least 3 instructions,
+       * so there is nothing to be gained here, is there?
+       *
+       * I negate WREG because either operand might share registers with
+       * result, so assigning first might destroy an operand. */
+      
+      /* For the modulus operator, (a/b)*b == a shall hold.
+       * Thus: a>0, b>0 --> a/b >= 0 and a%b >= 0
+       *       a>0, b<0 --> a/b <= 0 and a%b >= 0 (e.g. 128 / -5 = -25, -25*(-5) =  125 and +3 remaining)
+       *       a<0, b>0 --> a/b <= 0 and a%b < 0  (e.g. -128 / 5 = -25, -25*  5  = -125 and -3 remaining)
+       *       a<0, b<0 --> a/b >= 0 and a%b < 0  (e.g. -128 / -5 = 25,  25*(-5) = -125 and -3 remaining)
+       * Only invert the result if the left operand is negative (sigh).
+       */
+      if (AOP_SIZE(result) <= 1 || !negated)
+      {
+       if (ic->op == '/')
+       {
+         if (IS_VALOP(right)) {
+           if (rightVal < 0) {
+             /* we negated this operand above */
+             pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
+           }
+         } else if (!IS_UNSIGNED(operandType(right))) {
+           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
+           pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
+         }
+       }
+
+       if (IS_VALOP(left)) {
+         if (leftVal < 0) {
+           /* we negated this operand above */
+           pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
+         }
+       } else if (!IS_UNSIGNED(operandType(left))) {
+         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
+         pic16_emitpcode(POC_NEGF, pic16_popCopyReg(&pic16_pc_wreg));
+       }
+
+       /* Move result to destination. */
+       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
+
+       /* Zero-extend:  no operand was signed (or result is just a byte). */
+       pic16_addSign(result, 1, 0);
+      } else {
+       assert( AOP_SIZE(result) > 1 );
+       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
+       if (ic->op == '/')
+       {
+         if (IS_VALOP(right)) {
+           if (rightVal < 0) {
+             /* we negated this operand above */
+             pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
+           }
+         } else if (!IS_UNSIGNED(operandType(right))) {
+           pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
+           pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
+         }
+       }
+
+       if (IS_VALOP(left)) {
+         if (leftVal < 0) {
+           /* we negated this operand above */
+           pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
+         }
+       } else if (!IS_UNSIGNED(operandType(left))) {
+         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
+         pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result), 1));
+       }
+
+       /* Move result to destination. */
+       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
+
+       /* Negate result if required. */
+       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(result), 1, 7));
+       pic16_emitpcode(POC_NEGF, pic16_popGet(AOP(result), 0));
+
+       /* Sign-extend. */
+       pic16_addSign(result, 2, 1);
+      }
+
+      /* clean up stack */
+      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
+      pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(pic16_stack_preinc));
+      goto release;
+    }
+
+#if 0
     /* special cases first */
     /* both are bits */
     if (AOP_TYPE(left) == AOP_CRY &&
@@ -4560,6 +4791,7 @@ static void genDiv (iCode *ic)
         genDivOneByte(left,right,result);
         goto release ;
     }
+#endif
 
     /* should have been converted to function call */
     assert(0);
@@ -4569,6 +4801,7 @@ release :
     pic16_freeAsmop(result,NULL,ic,TRUE); 
 }
 
+#if 0
 /*-----------------------------------------------------------------*/
 /* genModbits :- modulus of bits                                   */
 /*-----------------------------------------------------------------*/
@@ -4668,12 +4901,16 @@ static void genModOneByte (operand *left,
     pic16_aopPut(AOP(result),"b",0);
 
 }
+#endif
 
 /*-----------------------------------------------------------------*/
 /* genMod - generates code for division                            */
 /*-----------------------------------------------------------------*/
 static void genMod (iCode *ic)
 {
+  /* Task deferred to genDiv */
+  genDiv(ic);
+#if 0
   operand *left = IC_LEFT(ic);
   operand *right = IC_RIGHT(ic);
   operand *result= IC_RESULT(ic);  
@@ -4707,6 +4944,7 @@ release :
     pic16_freeAsmop(left,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
     pic16_freeAsmop(right,NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
     pic16_freeAsmop(result,NULL,ic,TRUE); 
+#endif
 }
 
 /*-----------------------------------------------------------------*/
@@ -7693,6 +7931,7 @@ static void genOr (iCode *ic, iCode *ifx)
     unsigned long lit = 0L;
 
     DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+    FENTRY;
 
     pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
     pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
@@ -7998,6 +8237,7 @@ static void genXor (iCode *ic, iCode *ifx)
   unsigned long lit = 0L;
 
   DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+  FENTRY;
 
   pic16_aopOp((left = IC_LEFT(ic)),ic,FALSE);
   pic16_aopOp((right= IC_RIGHT(ic)),ic,FALSE);
@@ -11218,7 +11458,7 @@ static void genGenPointerGet (operand *left,
       pic16_mov2w(AOP(left), 2);
       pic16_callGenericPointerRW(0, size);
       
-      assignResultValue(result, 1);
+      assignResultValue(result, size, 1);
       
       goto release;
     }
@@ -12536,47 +12776,50 @@ static void genAssign (iCode *ic)
     }
 #endif
 
-  know_W=-1;
-  while (size--) {
-    DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
-    if(AOP_TYPE(right) == AOP_LIT) {
-      if(lit&0xff) {
-       if(know_W != (lit&0xff))
-         pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
-       know_W = lit&0xff;
-       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
-      } else
-       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
+    size = AOP_SIZE(right);
+    if (size > AOP_SIZE(result)) size = AOP_SIZE(result);
+    know_W=-1;
+    while (size--) {
+      DEBUGpic16_emitcode ("; ***","%s  %d size %d",__FUNCTION__,__LINE__, size);
+      if(AOP_TYPE(right) == AOP_LIT) {
+       if(lit&0xff) {
+         if(know_W != (lit&0xff))
+           pic16_emitpcode(POC_MOVLW,pic16_popGetLit(lit&0xff));
+         know_W = lit&0xff;
+         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
+       } else
+         pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
 
-      lit >>= 8;
+       lit >>= 8;
 
-    } else if (AOP_TYPE(right) == AOP_CRY) {
-      pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
-      if(offset == 0) {
-        //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
-       pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
-       pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
-      }
-    } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
+      } else if (AOP_TYPE(right) == AOP_CRY) {
+       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),offset));
+       if(offset == 0) {
+         //debugf("%s: BTFSS offset == 0\n", __FUNCTION__);
+         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(right),0));
+         pic16_emitpcode(POC_INCF, pic16_popGet(AOP(result),0));
+       }
+      } else if ( (AOP_TYPE(right) == AOP_PCODE) && (AOP(right)->aopu.pcop->type == PO_IMMEDIATE) ) {
        pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(right),offset));
        pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset));
-    } else {
-      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+      } else {
+       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
 
-      if(!_G.resDirect) {                                              /* use this aopForSym feature */
-          if(AOP_TYPE(result) == AOP_ACC) {
-            pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
-          } else
-          if(AOP_TYPE(right) == AOP_ACC) {
-            pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
-          } else {
-            pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
-          }
+       if(!_G.resDirect) {                                             /* use this aopForSym feature */
+         if(AOP_TYPE(result) == AOP_ACC) {
+           pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right), offset));
+         } else
+           if(AOP_TYPE(right) == AOP_ACC) {
+             pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), offset));
+           } else {
+             pic16_emitpcode(POC_MOVFF, pic16_popGet2(AOP(right), AOP(result), offset));
+           }
+       }
       }
-    }
-      
+
       offset++;
     }
+    pic16_addSign(result, AOP_SIZE(right), !IS_UNSIGNED(operandType(right)));
   
 release:
   pic16_freeAsmop (right,NULL,ic,FALSE);
@@ -13310,7 +13553,9 @@ static void genReceive (iCode *ic)
     GpsuedoStkPtr = ic->parmBytes;
 
     /* setting GpsuedoStkPtr has side effects here: */
-    assignResultValue(IC_RESULT(ic), 0);
+    /* FIXME: What's the correct size of the return(ed) value?
+     *        For now, assuming '4' as before... */
+    assignResultValue(IC_RESULT(ic), 4, 0);
   }
 
   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
index 1664b0cf493ff6f1edd8cc2c344f133ff98f7171..68fdf921a77726cb367b5ed71776a23c92d033ae 100644 (file)
@@ -750,13 +750,11 @@ static void genAddLit (iCode *ic, int lit)
 
   operand *result;
   operand *left;
-  sym_link *lleft;
 
     FENTRY;
 
 
   left = IC_LEFT(ic);
-  lleft = operandType (left);
   result = IC_RESULT(ic);
   same = pic16_sameRegs(AOP(left), AOP(result));
   size = pic16_getDataSize(result);
@@ -771,27 +769,7 @@ static void genAddLit (iCode *ic, int lit)
 #undef MIN
 
   /* extend to result size */
-  if (IS_UNSIGNED(lleft)) {
-    /* zero-extend */
-    for (i = sizeL; i < size; i++) {
-      pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), i));
-    } // for i
-  } else {
-    /* sign-extend */
-    if (size == sizeL + 1) {
-      pic16_emitpcode (POC_CLRF, pic16_popGet (AOP(result), sizeL));
-      pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit_simple (AOP(left),sizeL-1,7));
-      pic16_emitpcode (POC_SETF, pic16_popGet (AOP(result), sizeL));
-    } else {
-      pic16_emitpcode (POC_CLRF, pic16_popCopyReg (&pic16_pc_wreg));
-      pic16_emitpcode (POC_BTFSC, pic16_newpCodeOpBit_simple (AOP(left),sizeL-1,7));
-      pic16_emitpcode (POC_SETF, pic16_popCopyReg (&pic16_pc_wreg));
-      
-      for (i=sizeL; i < size; i++) {
-        pic16_emitpcode (POC_MOVWF, pic16_popGet (AOP(result), i));
-      } // for i
-    } // if
-  } // if (SIGNED)
+  pic16_addSign(result, sizeL, !IS_UNSIGNED(operandType(left)));
 
   /* special cases */
   if (lit == 0) {
@@ -1580,7 +1558,7 @@ void pic16_genMinusBits (iCode *ic)
         pic16_emitcode("inc","a");
         pic16_emitcode("","%05d_DS_:",(lbl->key+100));
         pic16_aopPut(AOP(IC_RESULT(ic)),"a",0);
-        pic16_addSign(IC_RESULT(ic), MSB16, SPEC_USIGN(getSpec(operandType(IC_RESULT(ic)))));
+        pic16_addSign(IC_RESULT(ic), MSB16, !IS_UNSIGNED(operandType(IC_RESULT(ic))));
     }
 }
 
@@ -1883,103 +1861,127 @@ void pic16_genMinus (iCode *ic)
 
 
 /*-----------------------------------------------------------------*
- * pic_genUMult8XLit_8 - unsigned multiplication of two 8-bit numbers.
+ * pic_genMult8XLit_n - multiplication of two 8-bit numbers.
  * 
  * 
  *-----------------------------------------------------------------*/
-void pic16_genUMult8XLit_8 (operand *left,
-                            operand *right,
-                            operand *result)
+void pic16_genMult8XLit_n (operand *left,
+    operand *right,
+    operand *result)
 {
-  unsigned int lit;
+  int lit;
   int same;
   int size = AOP_SIZE(result);
   int i;
 
-    FENTRY;
-       DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
+  FENTRY;
+  DEBUGpic16_pic16_AopType(__LINE__,left,right,result);
 
-       if (AOP_TYPE(right) != AOP_LIT){
-               fprintf(stderr,"%s %d - right operand is not a literal\n",__FILE__,__LINE__);
-               exit(1);
-       }
+  if (AOP_TYPE(right) != AOP_LIT){
+    fprintf(stderr,"%s %d - right operand is not a literal\n",__FILE__,__LINE__);
+    exit(1);
+  }
 
-       lit = (unsigned int)floatFromVal(AOP(right)->aopu.aop_lit);
-       lit &= 0xff;
-       pic16_emitpcomment("Unrolled 8 X 8 multiplication");
-       pic16_emitpcomment("FIXME: the function does not support result==WREG");
+  lit = (int)floatFromVal(AOP(right)->aopu.aop_lit);
+  assert( (lit >= -128) && (lit < 256) );
+  pic16_emitpcomment("Unrolled 8 X 8 multiplication");
+  pic16_emitpcomment("FIXME: the function does not support result==WREG");
+
+  same = pic16_sameRegs(AOP(left), AOP(result));
+  if(same) {
+    switch(lit & 0x00ff) {
+      case 0:
+       while (size--) {
+         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),size));
+       } // while
+       return;
        
-       same = pic16_sameRegs(AOP(left), AOP(result));
-       if(same) {
-               switch(lit) {
-                       case 0:
-                               while (size--) {
-                                 pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),size));
-                               } // while
-                               return;
-                       case 2:
-                               // its faster to left shift
-                               for (i=1; i < size; i++) {
-                                 pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),i));
-                               } // for
-                               emitCLRC;
-                               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),0));
-                               if (size > 1)
-                                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),1));
-                               return;
+      case 2:
+       /* sign extend left in result */
+       pic16_addSign(result, 1, !IS_UNSIGNED(operandType(left)));
+       // its faster to left shift
+       emitCLRC;
+       pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),0));
+       if (size > 1)
+         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),1));
+       return;
 
-                       default:
-                               if(AOP_TYPE(left) != AOP_ACC)
-                                       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
-                               pic16_emitpcode(POC_MULLW, pic16_popGetLit(lit));
-                               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
-                                       pic16_popGet(AOP(result), 0)));
-                               if (size > 1) {
-                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodh),
-                                                                           pic16_popGet(AOP(result), 1)));
-                                 for (i=2; i < size; i++) {
-                                   pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),i));
-                                 } // for
-                               } // if
-                               return;
-               }
+      default:
+       if(AOP_TYPE(left) != AOP_ACC)
+         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
+       pic16_emitpcode(POC_MULLW, pic16_popGetLit(lit & 0x00ff));
+       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(
+               &pic16_pc_prodl), pic16_popGet(AOP(result), 0)));
+       /* Adjust result's high bytes below! */
+    }
+  } else {
+    // operands different
+    switch(lit & 0x00ff) {
+      case 0:
+       while (size--) {
+         pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),size));
+       } // while
+       return;
+       
+      case 2:
+       if (IS_UNSIGNED(operandType(result))) {
+         for (i=1; i < size; i++) {
+           pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),i));
+         } // for
        } else {
-               // operands different
-               switch(lit) {
-                       case 0:
-                               while (size--) {
-                                 pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),size));
-                               } // while
-                               return;
-                       case 2:
-                               for (i=1; i < size; i++) {
-                                 pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),i));
-                               } // for
-                               emitCLRC;
-                               pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 0));
-                               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
-                               if (size > 1)
-                                 pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),1));
-                               return;
-                       default:
-                               if(AOP_TYPE(left) != AOP_ACC)
-                                       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
-                               pic16_emitpcode(POC_MULLW, pic16_popGetLit(lit));
-                               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
-                                       pic16_popGet(AOP(result), 0)));
-
-                               if (size > 1) {
-                                 pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodh),
-                                                                           pic16_popGet(AOP(result), 1)));
-                                 for (i=2; i < size; i++) {
-                                   pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),i));
-                                 } // for
-                               } // if
-                               return;
-               }
+         /* sign extend left to result */
+         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
+         pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
+         pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
+         for (i=1; i < size; i++) {
+           pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(result),i));
+         } // for
        }
+       emitCLRC;
+       pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 0));
+       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
+       if (size > 1)
+         pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(result),1));
+       return;
+       
+      default:
+       if(AOP_TYPE(left) != AOP_ACC)
+         pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
+       pic16_emitpcode(POC_MULLW, pic16_popGetLit(lit));
+       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(
+               &pic16_pc_prodl), pic16_popGet(AOP(result), 0)));
+       /* Adjust result's high bytes below! */
+    }
+  }
+
+  if (size > 1) {
+    /* We need to fix PRODH for
+     * (a) literals < 0 and
+     * (b) signed register operands < 0.
+     */
+    //printf( "%s: lit %d, left unsigned: %d\n", __FUNCTION__, lit, SPEC_USIGN(getSpec(operandType(left))));
+    if (lit < 0) {
+      /* literal negative (i.e. in [-128..-1]), high byte == -1 */
+      pic16_mov2w(AOP(left), 0);
+      pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(&pic16_pc_prodh));
+    }
+
+    if (!SPEC_USIGN(getSpec(operandType(left)))) {
+      /* register operand signed, determine signedness of high byte */
+      pic16_emitpcode(POC_MOVLW, pic16_popGetLit(lit & 0x00ff));
+      pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
+      pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(&pic16_pc_prodh));
+    }
+
+    pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(
+           &pic16_pc_prodh), pic16_popGet(AOP(result), 1)));
+
+    /* Need to sign-extend here. */
+    pic16_addSign(result, 2, !IS_UNSIGNED(operandType(result)));
+  } // if
 }
 
+#if 0
 /*-----------------------------------------------------------------------*
  * pic_genUMult16XLit_16 - unsigned multiplication of two 16-bit numbers *
  *-----------------------------------------------------------------------*/
@@ -2092,73 +2094,101 @@ void pic16_genUMult16XLit_16 (operand *left,
                }
        }
 }
+#endif
 
 
 /*-----------------------------------------------------------------*
- * genUMult8X8_8 - unsigned multiplication of two 8-bit numbers.
+ * genMult8X8_n - multiplication of two 8-bit numbers.
  * 
  * 
  *-----------------------------------------------------------------*/
-void pic16_genUMult8X8_8 (operand *left,
-                          operand *right,
-                          operand *result)
+void pic16_genMult8X8_n (operand *left, operand *right, operand *result)
 
 {
   FENTRY;
-  
 
-       if (AOP_TYPE(right) == AOP_LIT) {
-               pic16_genUMult8XLit_8(left,right,result);
-         return;
-       }
 
-       /* cases:
-               A = A x B       B = A x B
-               A = B x C
-               W = A x B
-               W = W x B       W = B x W
-       */
-       /* if result == right then exchange left and right */
-       if(pic16_sameRegs(AOP(result), AOP(right))) {
-         operand *tmp;
-               tmp = left;
-               left = right;
-               right = tmp;
-       }
-               
-       if(AOP_TYPE(left) != AOP_ACC) {
-               // left is not WREG
-               if(AOP_TYPE(right) != AOP_ACC) {
-                       pic16_mov2w(AOP(left), 0);
-                       pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
-               } else {
-                       pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
-               }
-       } else {
-               // left is WREG, right cannot be WREG (or can?!)
-               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(right), 0));
-       }
-       
-       /* result is in PRODL:PRODH */
-       if(AOP_TYPE(result) != AOP_ACC) {
-               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodl),
-                       pic16_popGet(AOP(result), 0)));
+  if (AOP_TYPE(right) == AOP_LIT) {
+    pic16_genMult8XLit_n(left,right,result);
+    return;
+  }
+
+  /* cases:
+     A = A x B B = A x B
+     A = B x C
+     W = A x B
+     W = W x B W = B x W
+     */
+  /* if result == right then exchange left and right */
+  if(pic16_sameRegs(AOP(result), AOP(right))) {
+    operand *tmp;
+    tmp = left;
+    left = right;
+    right = tmp;
+  }
+
+  if(AOP_TYPE(left) != AOP_ACC) {
+    // left is not WREG
+    if(AOP_TYPE(right) != AOP_ACC) {
+      pic16_mov2w(AOP(left), 0);
+      pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
+    } else {
+      pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
+    }
+  } else {
+    // left is WREG, right cannot be WREG (or can?!)
+    pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(right), 0));
+  }
 
+  /* result is in PRODL:PRODH */
+  if(AOP_TYPE(result) != AOP_ACC) {
+    pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(
+           &pic16_pc_prodl), pic16_popGet(AOP(result), 0)));
+
+
+    if(AOP_SIZE(result)>1) {
+
+      /* If s8 x s8 --> s16 multiplication was called for, fixup high byte.
+       * (left=a1a0, right=b1b0, X1: high byte, X0: low byte)
+       * 
+       *    a1a0 * b1b0
+       * --------------
+       *      a1b0 a0b0
+       * a1b1 a0b1
+       * ---------------
+       *           a0b0  a1= 0, b1= 0 (both unsigned)
+       *       -b0 a0b0  a1=-1, b1= 0 (a signed and < 0, b unsigned or >= 0)
+       *       -a0 a0b0  a1= 0, b1=-1 (b signed and < 0, a unsigned or >= 0)
+       *  -(a0+b0) a0b0  a1=-1, b1=-1 (a and b signed and < 0)
+       *
+       *  Currently, PRODH:PRODL holds a0b0 as 16 bit value; we need to
+       *  subtract a0 and/or b0 from PRODH. */
+      if (!IS_UNSIGNED(operandType(right))) {
+       /* right operand (b1) signed and < 0, then subtract left op (a0) */
+       pic16_mov2w( AOP(left), 0 );
+       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(right), 0, 7));
+       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(&pic16_pc_prodh));
+      }
 
-               if(AOP_SIZE(result)>1) {
-                 int i;
+      if (!IS_UNSIGNED(getSpec(operandType(left)))) {
+       /* left operand (a1) signed and < 0, then subtract right op (b0) */
+       pic16_mov2w( AOP(right), 0 );
+       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit_simple(AOP(left), 0, 7));
+       pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(&pic16_pc_prodh));
+      }
 
-                       pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(&pic16_pc_prodh),
-                       pic16_popGet(AOP(result), 1)));
-                       
-                       for(i=2;i<AOP_SIZE(result);i++)
-                               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), i));
-               }
-       } else {
-               pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
-       }
+      pic16_emitpcode(POC_MOVFF, pic16_popGet2p(pic16_popCopyReg(
+             &pic16_pc_prodh), pic16_popGet(AOP(result), 1)));
+
+      /* Must sign-extend here. */
+      pic16_addSign(result, 2, !IS_UNSIGNED(operandType(left)));
+    }
+  } else {
+    pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
+  }
 }
 
+#if 0
 /*------------------------------------------------------------------*
  * genUMult16X16_16 - unsigned multiplication of two 16-bit numbers *
  *------------------------------------------------------------------*/
@@ -2173,7 +2203,7 @@ void pic16_genUMult16X16_16 (operand *left,
 
 
        if (AOP_TYPE(right) == AOP_LIT) {
-               pic16_genUMult8XLit_8(left,right,result);
+               pic16_genMult8XLit_n(left,right,result);
          return;
        }
 
@@ -2247,14 +2277,16 @@ void pic16_genUMult16X16_16 (operand *left,
                pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), 1));
        }       
 }
+#endif
 
-
+#if 0
 void pic16_genSMult16X16_16(operand *left,
                        operand *right,
                        operand *result)
 {
 
 }
+#endif
 
 #if 0
 /*-----------------------------------------------------------------*
@@ -2299,12 +2331,13 @@ void pic16_genMult8X8_8 (operand *left,
   FENTRY;
   
   if(AOP_TYPE(right) == AOP_LIT)
-    pic16_genUMult8XLit_8(left,right,result);
+    pic16_genMult8XLit_n(left,right,result);
   else
-    pic16_genUMult8X8_8(left,right,result);
+    pic16_genMult8X8_n(left,right,result);
 }
 
 
+#if 0
 /*-----------------------------------------------------------------*
  * pic16_genMult16X16_16 - multiplication of two 16-bit numbers    *
  *-----------------------------------------------------------------*/
@@ -2319,10 +2352,10 @@ void pic16_genMult16X16_16 (operand *left,
   else
     pic16_genUMult16X16_16(left,right,result);
 }
+#endif
 
 
-
-
+#if 0
 /*-----------------------------------------------------------------------*
  * pic_genUMult32XLit_32 - unsigned multiplication of two 32-bit numbers *
  *-----------------------------------------------------------------------*/
@@ -2435,8 +2468,9 @@ void pic16_genUMult32XLit_32 (operand *left,
                }
        }
 }
+#endif
 
-
+#if 0
 /*------------------------------------------------------------------*
  * genUMult32X32_32 - unsigned multiplication of two 32-bit numbers *
  *------------------------------------------------------------------*/
@@ -2450,7 +2484,7 @@ void pic16_genUMult32X32_32 (operand *left,
     FENTRY;
     
        if (AOP_TYPE(right) == AOP_LIT) {
-               pic16_genUMult8XLit_8(left,right,result);
+               pic16_genMult8XLit_n(left,right,result);
          return;
        }
 
@@ -2524,8 +2558,10 @@ void pic16_genUMult32X32_32 (operand *left,
                pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), 1));
        }       
 }
+#endif
 
 
+#if 0
 /*-----------------------------------------------------------------*
  * pic16_genMult32X32_32 - multiplication of two 32-bit numbers    *
  *-----------------------------------------------------------------*/
@@ -2540,6 +2576,7 @@ void pic16_genMult32X32_32 (operand *left,
   else
     pic16_genUMult32X32_32(left,right,result);
 }
+#endif
 
 
 
index e67b89c124bd4af241fec0a0924a399e0fe5aff4..5886b349a062e7aa8aebd04632a8a6f3f79cb807 100644 (file)
@@ -915,6 +915,17 @@ _pic16_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts)
 static bool _hasNativeMulFor (iCode *ic, sym_link *left, sym_link *right)
 {
   //fprintf(stderr,"checking for native mult for %c (size: %d)\n", ic->op, getSize(OP_SYMBOL(IC_RESULT(ic))->type));
+  int symL, symR, symRes, sizeL = 0, sizeR = 0, sizeRes = 0;
+
+  /* left/right are symbols? */
+  symL = IS_SYMOP(IC_LEFT(ic));
+  symR = IS_SYMOP(IC_RIGHT(ic));
+  symRes = IS_SYMOP(IC_RESULT(ic));
+
+  /* --> then determine their sizes */
+  sizeL = symL ? getSize(OP_SYM_TYPE(IC_LEFT(ic))) : 4;
+  sizeR = symR ? getSize(OP_SYM_TYPE(IC_RIGHT(ic))) : 4;
+  sizeRes = symRes ? getSize(OP_SYM_TYPE(IC_RESULT(ic))) : 4;
 
   /* Checks to enable native multiplication.
    * PICs do not offer native division at all...
@@ -924,51 +935,39 @@ static bool _hasNativeMulFor (iCode *ic, sym_link *left, sym_link *right)
    *       (regardless of the operands)
    * ( ii) if left and right are unsigned 8-bit operands,
    *       use native MUL
-   * (iii) if left or right is a literal in the range of [0..255)
+   * (iii) if left or right is a literal in the range of [-128..256)
    *       and the other is an unsigned byte, use native MUL
    */
   if (ic->op == '*')
   {
-    int symL, symR, symRes, sizeL = 0, sizeR = 0, sizeRes = 0;
-
-    /* left/right are symbols? */
-    symL = IS_SYMOP(IC_LEFT(ic));
-    symR = IS_SYMOP(IC_RIGHT(ic));
-    symRes = IS_SYMOP(IC_RESULT(ic));
-
-    /* --> then determine their sizes */
-    sizeL = symL ? getSize(OP_SYM_TYPE(IC_LEFT(ic))) : 4;
-    sizeR = symR ? getSize(OP_SYM_TYPE(IC_RIGHT(ic))) : 4;
-    sizeRes = symRes ? getSize(OP_SYM_TYPE(IC_RESULT(ic))) : 4;
-
     /* use native mult for `*: <?> x <?> --> {u8_t, s8_t}' */
     if (sizeRes == 1) { return TRUE; }
 
     /* use native mult for `u8_t x u8_t --> { u16_t, s16_t }' */
-    if (sizeL == 1 && symL && SPEC_USIGN(OP_SYM_TYPE(IC_LEFT(ic)))) {
+    if (sizeL == 1 && symL /*&& SPEC_USIGN(OP_SYM_TYPE(IC_LEFT(ic)))*/) {
       sizeL = 1;
     } else {
       //printf( "%s: left too large (%u) / signed (%u)\n", __FUNCTION__, sizeL, symL && !SPEC_USIGN(OP_SYM_TYPE(IC_LEFT(ic))));
       sizeL = 4;
     }
-    if (sizeR == 1 && symR && SPEC_USIGN(OP_SYM_TYPE(IC_RIGHT(ic)))) {
+    if (sizeR == 1 && symR /*&& SPEC_USIGN(OP_SYM_TYPE(IC_RIGHT(ic)))*/) {
       sizeR = 1;
     } else {
       //printf( "%s: right too large (%u) / signed (%u)\n", __FUNCTION__, sizeR, symR && !SPEC_USIGN(OP_SYM_TYPE(IC_RIGHT(ic))));
       sizeR = 4;
     }
 
-    /* also allow literals [0..256) for left/right operands */
+    /* also allow literals [-128..256) for left/right operands */
     if (IS_VALOP(IC_LEFT(ic)))
     {
       long l = (long)floatFromVal( OP_VALUE( IC_LEFT(ic) ) );
       sizeL = 4;
       //printf( "%s: val(left) = %ld\n", __FUNCTION__, l );
-      if (l >= 0 && l < 256)
+      if (l >= -128 && l < 256)
       {
        sizeL = 1;
       } else {
-       //printf( "%s: left value %ld outside [0..256)\n", __FUNCTION__, l );
+       //printf( "%s: left value %ld outside [-128..256)\n", __FUNCTION__, l );
       }
     }
     if (IS_VALOP( IC_RIGHT(ic) ))
@@ -976,11 +975,11 @@ static bool _hasNativeMulFor (iCode *ic, sym_link *left, sym_link *right)
       long l = (long)floatFromVal( OP_VALUE( IC_RIGHT(ic) ) );
       sizeR = 4;
       //printf( "%s: val(right) = %ld\n", __FUNCTION__, l );
-      if (l >= 0 && l < 256)
+      if (l >= -128 && l < 256)
       {
        sizeR = 1;
       } else {
-       //printf( "%s: right value %ld outside [0..256)\n", __FUNCTION__, l );
+       //printf( "%s: right value %ld outside [-128..256)\n", __FUNCTION__, l );
       }
     }
 
@@ -988,6 +987,41 @@ static bool _hasNativeMulFor (iCode *ic, sym_link *left, sym_link *right)
     if (sizeL == 1 && sizeR == 1) { return TRUE; }
   }
 
+  if (ic->op == '/' || ic->op == '%')
+  {
+    /* We must catch /: {u8_t,s8_t} x {u8_t,s8_t} --> {u8_t,s8_t},
+     * because SDCC will call 'divuchar' even for u8_t / s8_t.
+     * Example: 128 / -2 becomes 128 / 254 = 0 != -64... */
+    if (sizeL == 1 && sizeR == 1) return TRUE;
+
+    /* What about literals? */
+    if (IS_VALOP( IC_LEFT(ic) ))
+    {
+      long l = (long)floatFromVal( OP_VALUE( IC_LEFT(ic) ) );
+      sizeL = 4;
+      //printf( "%s: val(left) = %ld\n", __FUNCTION__, l );
+      if (l >= -128 && l < 256)
+      {
+       sizeL = 1;
+      } else {
+       //printf( "%s: left value %ld outside [-128..256)\n", __FUNCTION__, l );
+      }
+    }
+    if (IS_VALOP( IC_RIGHT(ic) ))
+    {
+      long l = (long)floatFromVal( OP_VALUE( IC_RIGHT(ic) ) );
+      sizeR = 4;
+      //printf( "%s: val(right) = %ld\n", __FUNCTION__, l );
+      if (l >= -128 && l < 256)
+      {
+       sizeR = 1;
+      } else {
+       //printf( "%s: right value %ld outside [-128..256)\n", __FUNCTION__, l );
+      }
+    }
+    if (sizeL == 1 && sizeR == 1) { return TRUE; }
+  }
+
   return FALSE;
 }