* src/port.h (PORT structure): added hook initPaths, now each
[fw/sdcc] / src / pic16 / genarith.c
index 9f6a859579a900255da5c32ce4df61ccb51700a4..ae71c24a3173c7cbff812e47c89330864f354f15 100644 (file)
 #include "pcode.h"
 #include "gen.h"
 
+#if 1
+#define pic16_emitcode DEBUGpic16_emitcode
+#endif
 
 #define BYTEofLONG(l,b) ( (l>> (b<<3)) & 0xff)
 void DEBUGpic16_pic16_AopType(int line_no, operand *left, operand *right, operand *result);
-
+void pic16_emitpcomment(char *, ...);
+pCodeOp *pic16_popGet2p(pCodeOp *src, pCodeOp *dst);
 const char *pic16_AopType(short type)
 {
   switch(type) {
@@ -134,6 +138,12 @@ const char *pic16_pCodeOpType(  pCodeOp *pcop)
       return  "PO_PCL";
     case  PO_PCLATH:
       return  "PO_PCLATH";
+    case  PO_PCLATU:
+      return  "PO_PCLATU";
+    case  PO_PRODL:
+      return  "PO_PRODL";
+    case  PO_PRODH:
+      return  "PO_PRODH";
     case PO_LITERAL:
       return  "PO_LITERAL";
     case PO_REL_ADDR:
@@ -180,8 +190,8 @@ bool pic16_genPlusIncr (iCode *ic)
     
     DEBUGpic16_emitcode ("; ","%s  %d",__FUNCTION__,__LINE__);
     /* if the literal value of the right hand side
-       is greater than 1 then it is faster to add */
-    if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 1)          // this was > 2 why? VR
+       is greater than 2 then it is faster to add */
+    if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
         return FALSE ;
     
     /* if increment 16 bits in register */
@@ -204,7 +214,7 @@ bool pic16_genPlusIncr (iCode *ic)
     
     DEBUGpic16_emitcode ("; ","%s  %d",__FUNCTION__,__LINE__);
     /* if left is in accumulator  - probably a bit operation*/                         // VR - why this is a bit operation?!
-    if( strcmp(pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a")  &&
+    if( (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) &&
        (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) ) {
       
       pic16_emitpcode(POC_BCF, pic16_popGet(AOP(IC_RESULT(ic)),0));
@@ -228,7 +238,6 @@ bool pic16_genPlusIncr (iCode *ic)
     }
 
 
-
     /* if the sizes are greater than 1 then we cannot */
     if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
         AOP_SIZE(IC_LEFT(ic)) > 1   )
@@ -783,294 +792,362 @@ static void genAddLit (iCode *ic, int lit)
 /*-----------------------------------------------------------------*/
 void pic16_genPlus (iCode *ic)
 {
-  int size, offset = 0;
-  operand *result, *left, *right;
-  
-  /* special cases :- */
-  DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+       int i, size, offset = 0;
+       operand *result, *left, *right;
+
+       /* special cases :- */
+       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
 
 
-#if 1
        result = IC_RESULT(ic);
        left = IC_LEFT(ic);
        right = IC_RIGHT(ic);
-  pic16_aopOp (left,ic,FALSE);
-  pic16_aopOp (right,ic,FALSE);
-  pic16_aopOp (result,ic,TRUE);
-  DEBUGpic16_pic16_AopType(__LINE__,left, right, result);
-
-#else
-  pic16_aopOp (IC_LEFT(ic),ic,FALSE);
-  pic16_aopOp (IC_RIGHT(ic),ic,FALSE);
-  pic16_aopOp (IC_RESULT(ic),ic,TRUE);
-  DEBUGpic16_pic16_AopType(__LINE__,IC_LEFT(ic),IC_RIGHT(ic),IC_RESULT(ic));
-#endif
-
-
-  /* if literal, literal on the right or
-     if left requires ACC or right is already
-     in ACC */
-
-  if (AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) {
-    operand *t = IC_RIGHT(ic);
-    IC_RIGHT(ic) = IC_LEFT(ic);
-    IC_LEFT(ic) = t;
-  }
-
-  /* if both left & right are in bit space */
-  if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
-      AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
-    pic16_genPlusBits (ic);
-    goto release ;
-  }
-
-  /* if left in bit space & right literal */
-  if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
-      AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
-    /* if result in bit space */
-    if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY){
-      if((unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit) != 0L) {
-       pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(IC_RESULT(ic)),0));
-       if (!pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
-         pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_LEFT(ic)),0));
-       pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(IC_RESULT(ic)),0));
-      }
-    } else {
-      size = pic16_getDataSize(IC_RESULT(ic));
-      while (size--) {
-       MOVA(pic16_aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));  
-       pic16_emitcode("addc","a,#00  ;%d",__LINE__);
-       pic16_aopPut(AOP(IC_RESULT(ic)),"a",offset++);
-      }
-    }
-    goto release ;
-  }
-
-  /* if I can do an increment instead
-     of add then GOOD for ME */
-  if (pic16_genPlusIncr (ic) == TRUE)
-    goto release;   
-
-  size = pic16_getDataSize(IC_RESULT(ic));
-
-  if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
-    /* Add a literal to something else */
-    //bool know_W=0;
-    unsigned lit = (unsigned) floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
-    //      unsigned l1=0;
-
-    //      offset = 0;
-    DEBUGpic16_emitcode(";","adding lit to something. size %d",size);
-
-    genAddLit (ic,  lit);
-    goto release;
-
-  } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
-
-    pic16_emitcode(";bitadd","right is bit: %s",pic16_aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
-    pic16_emitcode(";bitadd","left is bit: %s",pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
-    pic16_emitcode(";bitadd","result is bit: %s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
-
-    /* here we are adding a bit to a char or int */
-    if(size == 1) {
-      if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
-
-       pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
-       pic16_emitpcode(POC_INCF ,  pic16_popGet(AOP(IC_RESULT(ic)),0));
-
-       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
-                      AOP(IC_RIGHT(ic))->aopu.aop_dir,
-                      AOP(IC_RIGHT(ic))->aopu.aop_dir);
-       pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
-      } else {
-
-       if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
-         pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
-         pic16_emitpcode(POC_XORLW , pic16_popGetLit(1));
-
-         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
-                        AOP(IC_RIGHT(ic))->aopu.aop_dir,
-                        AOP(IC_RIGHT(ic))->aopu.aop_dir);
-         pic16_emitcode(" xorlw","1");
-       } else {
-         pic16_emitpcode(POC_MOVFW , pic16_popGet(AOP(IC_LEFT(ic)),0));
-         pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
-         pic16_emitpcode(POC_INCFW , pic16_popGet(AOP(IC_LEFT(ic)),0));
+       pic16_aopOp (left,ic,FALSE);
+       pic16_aopOp (right,ic,FALSE);
+       pic16_aopOp (result,ic,TRUE);
+       DEBUGpic16_pic16_AopType(__LINE__,left, right, result);
+       // pic16_DumpOp("(left)",left);
+
+       /* if literal, literal on the right or
+       if left requires ACC or right is already
+       in ACC */
+
+       if ( (AOP_TYPE(left) == AOP_LIT) || (pic16_sameRegs(AOP(right), AOP(result))) ) {
+               operand *t = right;
+               right = left;
+               left = t;
+       }
 
-         pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
-         pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
-                        AOP(IC_RIGHT(ic))->aopu.aop_dir,
-                        AOP(IC_RIGHT(ic))->aopu.aop_dir);
-         pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
+       /* if both left & right are in bit space */
+       if (AOP_TYPE(left) == AOP_CRY &&
+               AOP_TYPE(right) == AOP_CRY) {
+               pic16_genPlusBits (ic);
+               goto release ;
        }
+
+       /* if left in bit space & right literal */
+       if (AOP_TYPE(left) == AOP_CRY &&
+               AOP_TYPE(right) == AOP_LIT) {
+               /* if result in bit space */
+               if(AOP_TYPE(result) == AOP_CRY){
+                       if((unsigned long)floatFromVal(AOP(right)->aopu.aop_lit) != 0L) {
+                               pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(result),0));
+                               if (!pic16_sameRegs(AOP(left), AOP(result)) )
+                                       pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(left),0));
+                               pic16_emitpcode(POC_XORWF, pic16_popGet(AOP(result),0));
+                       }
+               } else {
+                       size = pic16_getDataSize(result);
+                       while (size--) {
+                               MOVA(pic16_aopGet(AOP(right),offset,FALSE,FALSE));  
+                               pic16_emitcode("addc","a,#00  ;%d",__LINE__);
+                               pic16_aopPut(AOP(result),"a",offset++);
+                       }
+               }
+       goto release ;
+       } // left == CRY
+
+       /* if I can do an increment instead
+       of add then GOOD for ME */
+       if (pic16_genPlusIncr (ic) == TRUE)
+               goto release;   
+
+       size = pic16_getDataSize(IC_RESULT(ic));
+
+       if(AOP(IC_RIGHT(ic))->type == AOP_LIT) {
+               /* Add a literal to something else */
+               //bool know_W=0;
+               unsigned lit = (unsigned) floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
+               //unsigned l1=0;
+
+               //offset = 0;
+               DEBUGpic16_emitcode(";","adding lit to something. size %d",size);
+
+               genAddLit (ic,  lit);
+               goto release;
+
+       } else if(AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
+
+               pic16_emitcode(";bitadd","right is bit: %s",pic16_aopGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
+               pic16_emitcode(";bitadd","left is bit: %s",pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
+               pic16_emitcode(";bitadd","result is bit: %s",pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+
+               /* here we are adding a bit to a char or int */
+               if(size == 1) {
+                       if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
+
+                               pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
+                               pic16_emitpcode(POC_INCF ,  pic16_popGet(AOP(IC_RESULT(ic)),0));
+
+                               pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
+                                               AOP(IC_RIGHT(ic))->aopu.aop_dir,
+                                               AOP(IC_RIGHT(ic))->aopu.aop_dir);
+                               pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+                       } else { // not same
+
+                               if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
+                                       pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
+                                       pic16_emitpcode(POC_XORLW , pic16_popGetLit(1));
+
+                                       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
+                                       AOP(IC_RIGHT(ic))->aopu.aop_dir,
+                                       AOP(IC_RIGHT(ic))->aopu.aop_dir);
+                                       pic16_emitcode(" xorlw","1");
+                               } else {
+                                       pic16_emitpcode(POC_MOVFW , pic16_popGet(AOP(IC_LEFT(ic)),0));
+                                       pic16_emitpcode(POC_BTFSC , pic16_popGet(AOP(IC_RIGHT(ic)),0));
+                                       pic16_emitpcode(POC_INCFW , pic16_popGet(AOP(IC_LEFT(ic)),0));
+
+                                       pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
+                                       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
+                                       AOP(IC_RIGHT(ic))->aopu.aop_dir,
+                                       AOP(IC_RIGHT(ic))->aopu.aop_dir);
+                                       pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
+                               }
          
-       if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
+                               if(AOP_TYPE(IC_RESULT(ic)) != AOP_ACC) {
            
-         if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
-           pic16_emitpcode(POC_ANDLW , pic16_popGetLit(1));
-           pic16_emitpcode(POC_BCF ,   pic16_popGet(AOP(IC_RESULT(ic)),0));
-           emitSKPZ;
-           pic16_emitpcode(POC_BSF ,   pic16_popGet(AOP(IC_RESULT(ic)),0));
-         } else {
-           pic16_emitpcode(POC_MOVWF ,   pic16_popGet(AOP(IC_RESULT(ic)),0));
-           pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
-         }
-       }
-      }
-
-    } else {
-      int offset = 1;
-      DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
-      if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
-       emitCLRZ;
-       pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_RIGHT(ic)),0));
-       pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
-
-       pic16_emitcode("clrz","");
-
-       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
-                      AOP(IC_RIGHT(ic))->aopu.aop_dir,
-                      AOP(IC_RIGHT(ic))->aopu.aop_dir);
-       pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
-
-      } else {
-
-       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
-       pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_RIGHT(ic)),0));
-       pic16_emitpcode(POC_INCFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
-       //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
-       emitMOVWF(IC_RIGHT(ic),0);
-
-       pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
-       pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
-                      AOP(IC_RIGHT(ic))->aopu.aop_dir,
-                      AOP(IC_RIGHT(ic))->aopu.aop_dir);
-       pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
-       pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
-
-      }
-
-      while(--size){
-       emitSKPZ;
-       pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),offset++));
-       //pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(IC_RIGHT(ic)),offset++,FALSE,FALSE));
-      }
-
-    }
+                                       if(AOP_TYPE(IC_RESULT(ic)) == AOP_CRY) {
+                                               pic16_emitpcode(POC_ANDLW , pic16_popGetLit(1));
+                                               pic16_emitpcode(POC_BCF ,   pic16_popGet(AOP(IC_RESULT(ic)),0));
+                                               emitSKPZ;
+                                               pic16_emitpcode(POC_BSF ,   pic16_popGet(AOP(IC_RESULT(ic)),0));
+                                       } else {
+                                               pic16_emitpcode(POC_MOVWF ,   pic16_popGet(AOP(IC_RESULT(ic)),0));
+                                               pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+                                       }
+                               }
+                       }
+
+               } else {
+                       int offset = 1;
+                       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+                       if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
+                               emitCLRZ;
+                               pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_RIGHT(ic)),0));
+                               pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),0));
+
+                               pic16_emitcode("clrz","");
+
+                               pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
+                                               AOP(IC_RIGHT(ic))->aopu.aop_dir,
+                                               AOP(IC_RIGHT(ic))->aopu.aop_dir);
+                               pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+
+                       } else {
+
+                               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
+                               pic16_emitpcode(POC_BTFSC, pic16_popGet(AOP(IC_RIGHT(ic)),0));
+                               pic16_emitpcode(POC_INCFW, pic16_popGet(AOP(IC_LEFT(ic)),0));
+                               //pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RIGHT(ic)),0,FALSE,FALSE));
+                               emitMOVWF(IC_RIGHT(ic),0);
+
+                               pic16_emitcode("movf","%s,w", pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
+                               pic16_emitcode("btfsc","(%s >> 3), (%s & 7)",
+                                               AOP(IC_RIGHT(ic))->aopu.aop_dir,
+                                               AOP(IC_RIGHT(ic))->aopu.aop_dir);
+                               pic16_emitcode(" incf","%s,w", pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE));
+                               pic16_emitcode("movwf","%s", pic16_aopGet(AOP(IC_RESULT(ic)),0,FALSE,FALSE));
+
+                       }
+
+                       while(--size){
+                               emitSKPZ;
+                               pic16_emitpcode(POC_INCF,  pic16_popGet(AOP(IC_RESULT(ic)),offset++));
+                               //pic16_emitcode(" incf","%s,f", pic16_aopGet(AOP(IC_RIGHT(ic)),offset++,FALSE,FALSE));
+                       }
+
+               }
       
-  } else {
-    DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);    
-
-    /* Add the first bytes */
-
-    if(strcmp(pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
-      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_RIGHT(ic)),0));
-      pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
-    } else {
-
-      if ( AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
-       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(IC_RIGHT(ic)),0));
-       if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
-         pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
-      } else {
-
-       pic16_emitpcode(POC_MOVFW,pic16_popGet(AOP(IC_RIGHT(ic)),0));
+       } else {
+               // add bytes
+
+               // Note: the following is an example of WISC code, eg.
+               // it's supposed to run on a Weird Instruction Set Computer :o)
+
+               DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);    
+
+               if ( AOP_TYPE(left) == AOP_ACC) {
+                       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);    
+                       pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right),0));
+                       if ( AOP_TYPE(result) != AOP_ACC)
+                               pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(result),0));
+                       goto release; // we're done, since WREG is 1 byte
+               }
+
+
+               DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);    
+
+               size = min( AOP_SIZE(result), AOP_SIZE(right) );
+               size = min( size, AOP_SIZE(left) );
+               offset = 0;
+
+               if(pic16_debug_verbose) {
+//                     fprintf(stderr, "%s:%d result: %d\tleft: %d\tright: %d\n", __FILE__, __LINE__,
+//                             AOP_SIZE(result), AOP_SIZE(left), AOP_SIZE(right));
+//                     fprintf(stderr, "%s:%d size of operands: %d\n", __FILE__, __LINE__, size);
+               }
+
+
+
+               if ((AOP_TYPE(left) == AOP_PCODE) && (
+                               (AOP(left)->aopu.pcop->type == PO_LITERAL) || 
+//                             (AOP(left)->aopu.pcop->type == PO_DIR) ||   // patch 9
+                               (AOP(left)->aopu.pcop->type == PO_IMMEDIATE)))
+               {
+                       // add to literal operand
+
+                       // add first bytes
+                       for(i=0; i<size; i++) {
+                               if (AOP_TYPE(right) == AOP_ACC) {
+                                       pic16_emitpcode(POC_ADDLW, pic16_popGet(AOP(left),i));
+                               } else {
+                                       pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),i));
+                                       if(i) { // add with carry
+                                               pic16_emitpcode(POC_ADDFWC, pic16_popGet(AOP(right),i));
+                                       } else { // add without
+                                               pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(right),i));
+                                       }
+                               }
+                               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),i));
+                       }
+
+                       // add leftover bytes
+                       if (SPEC_USIGN(getSpec(operandType(right)))) {
+                               // right is unsigned
+                               for(i=size; i< AOP_SIZE(result); i++) {
+                                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),i));
+                                       pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),i));
+                                       pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),i));
+                               }
+
+                       } else {
+                               // right is signed, oh dear ...
+                               for(i=size; i< AOP_SIZE(result); i++) {
+                                       pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),i));
+                                       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),size-1,FALSE,FALSE),7,0));
+                                       pic16_emitpcode(POC_COMF, pic16_popGet(AOP(result),i));
+                                       pic16_emitpcode(POC_MOVLW, pic16_popGet(AOP(left),i));
+                                       pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),i));
+                               }
+
+                       }
+                       goto release;
+
+               } else {
+                       // add regs
+
+                       // add first bytes
+                       for(i=0; i<size; i++) {
+                               if (AOP_TYPE(right) != AOP_ACC)
+                                       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),i));
+                               if (pic16_sameRegs(AOP(left), AOP(result)))
+                               {
+                                       if(i) { // add with carry
+                                               pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(left),i));
+                                       } else { // add without
+                                               pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),i));
+                                       }
+                               } else { // not same
+                                       if(i) { // add with carry
+                                               pic16_emitpcode(POC_ADDFWC, pic16_popGet(AOP(left),i));
+                                       } else { // add without
+                                               pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),i));
+                                       }
+                                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),i));
+                               }
+                       }
+
+                       // add leftover bytes
+                       if (SPEC_USIGN(getSpec(operandType(right)))) {
+                               // right is unsigned
+                               for(i=size; i< AOP_SIZE(result); i++) {
+                                       if (pic16_sameRegs(AOP(left), AOP(result)))
+                                       {
+                                               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
+                                               pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(left),i));
+                                       } else { // not same
+                                               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),i));
+                                               pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result),i));
+                                       }
+                               }
+                       } else {
+                               // right is signed
+                               for(i=size; i< AOP_SIZE(result); i++) {
+                                       if(size < AOP_SIZE(left)) {
+                                               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
+                                               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),size-1,FALSE,FALSE),7,0));
+                                               pic16_emitpcode(POC_COMFW, pic16_popCopyReg(&pic16_pc_wreg));
+                                               if (pic16_sameRegs(AOP(left), AOP(result)))
+                                               {
+                                                       pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(left),i));
+                                               } else { // not same
+                                                       pic16_emitpcode(POC_ADDFWC, pic16_popGet(AOP(left),i));
+                                                       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),i));
+                                               }
+                                       } else {
+                                               pic16_emitpcode(POC_CLRF, pic16_popCopyReg(&pic16_pc_wreg));
+                                               pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), i));
+                                       }
+                               }
+                       }
+                       goto release;
+               }
 
-       if (pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) )
-         pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(IC_LEFT(ic)),0));
-       else {
-         PIC_OPCODE poc = POC_ADDFW;
-
-         if ((AOP_TYPE(IC_LEFT(ic)) == AOP_PCODE) && (
-             (AOP(IC_LEFT(ic))->aopu.pcop->type == PO_LITERAL) || 
-             (AOP(IC_LEFT(ic))->aopu.pcop->type == PO_IMMEDIATE)))
-           poc = POC_ADDLW;
-         pic16_emitpcode(poc, pic16_popGet(AOP(IC_LEFT(ic)),0));
-         if ( AOP_TYPE(IC_RESULT(ic)) != AOP_ACC)
-           pic16_emitpcode(POC_MOVWF,pic16_popGet(AOP(IC_RESULT(ic)),0));
        }
-      }
-    }
-
-    size = min( AOP_SIZE(IC_RESULT(ic)), AOP_SIZE(IC_RIGHT(ic))) - 1;
-    offset = 1;
-
-
-    while(size--){
-      if (!pic16_sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
-       pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(IC_LEFT(ic)),offset));
-       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
-
-       pic16_emitcode("movf","%s,w",  pic16_aopGet(AOP(IC_LEFT(ic)),offset,FALSE,FALSE));
-       pic16_emitcode("movwf","%s",  pic16_aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
-      }
 
-      pic16_emitpcode(POC_MOVFW,   pic16_popGet(AOP(IC_RIGHT(ic)),offset));
-      emitSKPNC;
-      pic16_emitpcode(POC_INCFSZW, pic16_popGet(AOP(IC_RIGHT(ic)),offset));
-      pic16_emitpcode(POC_ADDWF,   pic16_popGet(AOP(IC_RESULT(ic)),offset));
+       // TODO:        anything from here to before "release:" is probably obsolete and should be removed
+       //              when the regression tests are stable
 
-      /*
-       pic16_emitcode("movf","%s,w",  pic16_aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
-       emitSKPNC;
-       pic16_emitcode("incfsz","%s,w",pic16_aopGet(AOP(IC_RIGHT(ic)),offset,FALSE,FALSE));
-       pic16_emitcode("addwf","%s,f", pic16_aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE));
-      */
+       if (AOP_SIZE(IC_RESULT(ic)) > AOP_SIZE(IC_RIGHT(ic))) {
+               int sign =  !(SPEC_USIGN(getSpec(operandType(IC_LEFT(ic)))) |
+                               SPEC_USIGN(getSpec(operandType(IC_RIGHT(ic)))) );
 
-      offset++;
-    }
-
-  }
 
-  if (AOP_SIZE(IC_RESULT(ic)) > AOP_SIZE(IC_RIGHT(ic))) {
-    int sign =  !(SPEC_USIGN(getSpec(operandType(IC_LEFT(ic)))) |
-                 SPEC_USIGN(getSpec(operandType(IC_RIGHT(ic)))) );
+               /* Need to extend result to higher bytes */
+               size = AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_RIGHT(ic)) - 1;
 
+               /* First grab the carry from the lower bytes */
+               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
+               pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
 
-    /* Need to extend result to higher bytes */
-    size = AOP_SIZE(IC_RESULT(ic)) - AOP_SIZE(IC_RIGHT(ic)) - 1;
 
-    /* First grab the carry from the lower bytes */
-    pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
-    pic16_emitpcode(POC_RLCF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
+               if(sign) {
+                       /* Now this is really horrid. Gotta check the sign of the addends and propogate
+                       * to the result */
 
+                       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(IC_LEFT(ic)),offset-1,FALSE,FALSE),7,0));
+                       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
+                       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(IC_RIGHT(ic)),offset-1,FALSE,FALSE),7,0));
+                       pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
 
-    if(sign) {
-      /* Now this is really horrid. Gotta check the sign of the addends and propogate
-       * to the result */
-
-      pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(IC_LEFT(ic)),offset-1,FALSE,FALSE),7,0));
-      pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
-      pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(IC_RIGHT(ic)),offset-1,FALSE,FALSE),7,0));
-      pic16_emitpcode(POC_DECF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
-
-      /* if chars or ints or being signed extended to longs: */
-      if(size) {
-       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
-       pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE),7,0));
-       pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
-      }
-    }
+                       /* if chars or ints or being signed extended to longs: */
+                       if(size) {
+                               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0));
+                               pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(IC_RESULT(ic)),offset,FALSE,FALSE),7,0));
+                               pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
+                       }
+               }
 
-    offset++;
-    while(size--) {
+               offset++;
+               while(size--) {
       
-      if(sign)
-       pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
-      else
-       pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
+                       if(sign)
+                               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(IC_RESULT(ic)),offset));
+                       else
+                               pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(IC_RESULT(ic)),offset));
 
-      offset++;
-    }
-  }
+                       offset++;
+               }
+       }
 
 
-  //adjustArithmeticResult(ic);
+       //adjustArithmeticResult(ic);
 
- release:
-  pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-  pic16_freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
-  pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
      release:
+       pic16_freeAsmop(IC_LEFT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+       pic16_freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
+       pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
 }
 
 /*-----------------------------------------------------------------*/
@@ -1199,7 +1276,7 @@ void pic16_addSign(operand *result, int offset, int sign)
        pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(result),offset-1,FALSE,FALSE),7,0));
        pic16_emitpcode(POC_MOVLW, pic16_popGetLit(0xff));
        while(size--)
-         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),size));
+         pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),offset+size));
 
       }
     } else
@@ -1487,7 +1564,7 @@ void pic16_genMinus (iCode *ic)
                   pic16_AopType(AOP_TYPE(IC_LEFT(ic))),
                   pic16_AopType(AOP_TYPE(IC_RIGHT(ic))));
 
-    if(strcmp(pic16_aopGet(AOP(IC_LEFT(ic)),0,FALSE,FALSE),"a") == 0 ) {
+    if(AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
       pic16_emitpcode(POC_SUBFW, pic16_popGet(AOP(IC_RIGHT(ic)),0));
       pic16_emitpcode(POC_SUBLW, pic16_popGetLit(0));
@@ -1562,362 +1639,643 @@ void pic16_genMinus (iCode *ic)
   pic16_freeAsmop(IC_RIGHT(ic),NULL,ic,(RESULTONSTACK(ic) ? FALSE : TRUE));
   pic16_freeAsmop(IC_RESULT(ic),NULL,ic,TRUE);
 }
+
+
 /*-----------------------------------------------------------------*
- * pic_genUMult8XLit_16 - unsigned multiplication of two 8-bit numbers.
+ * pic_genUMult8XLit_8 - unsigned multiplication of two 8-bit numbers.
  * 
  * 
  *-----------------------------------------------------------------*/
-void pic16_genUMult8XLit_16 (operand *left,
+void pic16_genUMult8XLit_8 (operand *left,
                             operand *right,
-                            operand *result,
-                            pCodeOpReg *result_hi)
-
+                            operand *result)
 {
-
   unsigned int lit;
-  unsigned int i,have_first_bit;
   int same;
-  pCodeOp *temp;
-
-  if (AOP_TYPE(right) != AOP_LIT){
-    fprintf(stderr,"%s %d - right operand is not a literal\n",__FILE__,__LINE__);
-    exit(1);
-  }
 
 
-  if(!result_hi) {
-    result_hi = PCOR(pic16_popGet(AOP(result),1));
-  }
-
-  lit = (unsigned int)floatFromVal(AOP(right)->aopu.aop_lit);
-  lit &= 0xff;
-  pic16_emitcode(";","Unrolled 8 X 8 multiplication");
-
-  same = pic16_sameRegs(AOP(left), AOP(result));
-
-  if(same) {
-    switch(lit) {
-    case 0:
-      pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(left),0));
-      return;
-    case 2:
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      return;
-    case 3:
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      return;
-    case 4:
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      return;
-    case 5:
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 2*F
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 3*F
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 5*F
-      return;
-    case 6:
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      return;
-    case 7:
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 2*F
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 3*F
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 5*F
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 7*F
-      return;
-    case 8:
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 2*F
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 3*F
-      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 5*F
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 8*F
-      return;
-    case 9:
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      return;
-    case 10:
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 2*F
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 3*F
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 5*F
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      return;
-    case 11:
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 2*F
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 3*F
-      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 5*F
-      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 8*F
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 11*F
-      return;
-    case 12:
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));
-      return;
-    case 13:
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 2*F
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 3*F
-      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 5*F
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 8*F
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 13*F
-      return;
-    case 14:
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 2*F
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 3*F
-      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 5*F
-      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 8*F
-      pic16_emitpcode(POC_ADDFW, pic16_popGet(AOP(left),0));  // W = 11*F
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(left),0));  // F = 14*F
-      return;
-    case 15:
-      temp = pic16_popGetTempReg();
-      if(!temp) {
-       fprintf(stderr,"ERROR: unable to allocate register. %s:%d\n",__FUNCTION__,__LINE__);
-       exit(1);
-      }
-      pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_MOVWF,  temp);
-      pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
-      pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_SWAPFW, temp);
-      pic16_emitpcode(POC_SUBWF,  pic16_popGet(AOP(left),0));
-      pic16_popReleaseTempReg(temp);
-      return;
-    case 16:
-      pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
-      pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(left),0));
-      return;
-    case 17:
-      pic16_emitpcode(POC_SWAPFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xf0));
-      pic16_emitpcode(POC_ADDWF,  pic16_popGet(AOP(left),0));
-      return;
-    case 32:
-      pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xe0));
-      pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(left),0));
-      return;
-    case 64:
-      pic16_emitpcode(POC_SWAPF,  pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_RLCF,   pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_RLCFW,  pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_ANDLW,  pic16_popGetLit(0xc0));
-      pic16_emitpcode(POC_MOVWF,  pic16_popGet(AOP(left),0));
-      return;
-    case 128:
-      pic16_emitpcode(POC_RRCFW,  pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_CLRF,   pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_RRCF,   pic16_popGet(AOP(left),0));
-      return;
-
-    }
-  } else {
-
-    switch(lit) {
-    case 0:
-      pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),0));
-      pic16_emitpcode(POC_CLRF,  pic16_popCopyReg(result_hi));
-      return;
-    case 2:
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
-      pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result),0));
-      pic16_emitpcode(POC_CLRF,  pic16_popCopyReg(result_hi));
-      pic16_emitpcode(POC_RLCF,  pic16_popCopyReg(result_hi));
-      return;
-    }
+       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
 
-  }
+       if (AOP_TYPE(right) != AOP_LIT){
+               fprintf(stderr,"%s %d - right operand is not a literal\n",__FILE__,__LINE__);
+               exit(1);
+       }
 
-  pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
-  pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),0));
-  pic16_emitpcode(POC_CLRF,  pic16_popCopyReg(result_hi));
+       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");
+       
+       same = pic16_sameRegs(AOP(left), AOP(result));
+       if(same) {
+               switch(lit) {
+                       case 0:
+                               pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),0));
+                               return;
+                       case 2:
+                               // its faster to left shift
+                               emitCLRC;
+                               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),0));
+                               return;
+
+                       default:
+                               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)));
+                               return;
+               }
+       } else {
+               // operands different
+               switch(lit) {
+                       case 0:
+                               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 0));
+                               return;
+                       case 2:
+                               emitCLRC;
+                               pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 0));
+                               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
+                               return;
+                       default:
+                               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)));
+                               return;
+               }
+       }
+}
 
-  have_first_bit = 0;
-  for(i=0; i<8; i++) {
+/*-----------------------------------------------------------------------*
+ * pic_genUMult16XLit_16 - unsigned multiplication of two 16-bit numbers *
+ *-----------------------------------------------------------------------*/
+void pic16_genUMult16XLit_16 (operand *left,
+                            operand *right,
+                            operand *result)
+{
+  pCodeOp *pct1, *pct2, *pct3, *pct4;
+  unsigned int lit;
+  int same;
 
-    if(lit & 1) {
-      pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(result_hi));
-      have_first_bit = 1;
-    }
 
-    if(have_first_bit) {
-      pic16_emitpcode(POC_RRCF,  pic16_popCopyReg(result_hi));
-      pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),0));
-    }
+       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
 
-    lit >>= 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 &= 0xffff;
+
+       same = pic16_sameRegs(AOP(left), AOP(result));
+       if(same) {
+               switch(lit) {
+                       case 0:
+                               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
+                               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),1));
+                               return;
+                       case 2:
+                               // its faster to left shift
+                               emitCLRC;
+                               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),0));
+                               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),1));
+                               return;
+
+                       default: {
+                               DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+                               pct1 = pic16_popGetTempReg();
+                               pct2 = pic16_popGetTempReg();
+                               pct3 = pic16_popGetTempReg();
+                               pct4 = pic16_popGetTempReg();
+
+                               pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit & 0xff));
+                               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
+                               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                                       pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct1)));
+                               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                                       pic16_popCopyReg(&pic16_pc_prodh), pic16_pCodeOpCopy(pct2)));
+                                       
+                               /* WREG still holds the low literal */
+                               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 1));
+                               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                                       pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct3)));
+                                       
+                               pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit>>8 ));
+                               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
+                               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                                       pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct4)));
+                                       
+                               /* load result */
+                               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                                       pct1, pic16_popGet(AOP(result), 0)));
+                               pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct2));
+                               pic16_emitpcode(POC_ADDFW, pic16_pCodeOpCopy(pct3));
+                               pic16_emitpcode(POC_ADDFWC, pic16_pCodeOpCopy(pct4));
+                               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
+
+                               pic16_popReleaseTempReg( pct4 );
+                               pic16_popReleaseTempReg( pct3 );
+                               pic16_popReleaseTempReg( pct2 );
+                               pic16_popReleaseTempReg( pct1 );
+                       }; return;
+               }
+       } else {
+               // operands different
+               switch(lit) {
+                       case 0:
+                               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 0));
+                               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
+                               return;
+                       case 2:
+                               emitCLRC;
+                               pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 0));
+                               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
+                               pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 1));
+                               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
+                               return;
+                       default: {
+                                       
+                               pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit & 0xff));
+                               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
+                               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                                       pic16_popCopyReg(&pic16_pc_prodl), pic16_popGet(AOP(result), 0)));
+                               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                                       pic16_popCopyReg(&pic16_pc_prodh), pic16_popGet(AOP(result), 1)));
+                                       
+                               /* WREG still holds the low literal */
+                               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 1));
+                               pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
+                               pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 1));
+                                       
+                               pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit>>8 ));
+                               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
+                               pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
+                               pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), 1));
+
+                       }; return;
+               }
+       }
 }
 
+
 /*-----------------------------------------------------------------*
- * genUMult8X8_16 - unsigned multiplication of two 8-bit numbers.
+ * genUMult8X8_8 - unsigned multiplication of two 8-bit numbers.
  * 
  * 
  *-----------------------------------------------------------------*/
-void pic16_genUMult8X8_16 (operand *left,
+void pic16_genUMult8X8_8 (operand *left,
                           operand *right,
-                          operand *result,
-                          pCodeOpReg *result_hi)
+                          operand *result)
 
 {
+       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
 
-  int i;
-  int looped = 1;
-
-  if(!result_hi) {
-    result_hi = PCOR(pic16_popGet(AOP(result),1));
-  }
-
-  if (AOP_TYPE(right) == AOP_LIT) {
-    pic16_genUMult8XLit_16(left,right,result,result_hi);
-    return;
-  }
-
-  if(!looped) {
-    pic16_emitcode(";","Unrolled 8 X 8 multiplication");
 
-    pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
-    pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),0));
-    pic16_emitpcode(POC_CLRF,  pic16_popCopyReg(result_hi));
-    emitCLRC;
+       if (AOP_TYPE(right) == AOP_LIT) {
+               pic16_genUMult8XLit_8(left,right,result);
+         return;
+       }
 
-    for(i=0; i<8; i++) {
-      pic16_emitpcode(POC_BTFSC,  pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),i,0));
-      pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(result_hi));
-      pic16_emitpcode(POC_RRCF,  pic16_popCopyReg(result_hi));
-      pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),0));
-    }
+       /* 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_emitpcode(POC_MOVFW, pic16_popGet(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)));
 
 
-    /*
-      Here's another version that does the same thing and takes the 
-      same number of instructions. The one above is slightly better
-      because the entry instructions have a higher probability of
-      being optimized out.
-    */
-    /*
-      pic16_emitpcode(POC_CLRF,  pic16_popCopyReg(result_hi));
-      pic16_emitpcode(POC_RRCFW, pic16_popGet(AOP(left),0));
-      pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result),0));
-      pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
-
-      for(i=0; i<8; i++) {
-      emitSKPNC;
-      pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(result_hi));
-      pic16_emitpcode(POC_RRCF,  pic16_popCopyReg(result_hi));
-      pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),0));
-      }
-    */
+               if(AOP_SIZE(result)>1) {
+                 int i;
 
-  } else {
-    symbol  *tlbl = newiTempLabel(NULL);
-    pCodeOp *temp;
+                       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));
+       }
+}
 
+/*------------------------------------------------------------------*
+ * genUMult16X16_16 - unsigned multiplication of two 16-bit numbers *
+ *------------------------------------------------------------------*/
+void pic16_genUMult16X16_16 (operand *left,
+                          operand *right,
+                          operand *result)
 
-    pic16_emitcode(";","Looped 8 X 8 multiplication");
+{
+  pCodeOp *pct1, *pct2, *pct3, *pct4;
 
-    pic16_emitpcode(POC_CLRF,  pic16_popGet(AOP(result),0));
-    pic16_emitpcode(POC_CLRF,  pic16_popCopyReg(result_hi));
+       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
 
-    pic16_emitpcode(POC_BSF,   pic16_newpCodeOpBit(pic16_aopGet(AOP(result),0,FALSE,FALSE),7,0));
 
-    pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(right),0));
+       if (AOP_TYPE(right) == AOP_LIT) {
+               pic16_genUMult8XLit_8(left,right,result);
+         return;
+       }
 
-    temp = pic16_popGetTempReg();
-    pic16_emitpcode(POC_MOVWF, pic16_popCopyReg(PCOR(temp)));
+       /* cases:
+               A = A x B       B = A x B
+               A = B x C
+       */
+       /* if result == right then exchange left and right */
+       if(pic16_sameRegs(AOP(result), AOP(right))) {
+         operand *tmp;
+               tmp = left;
+               left = right;
+               right = tmp;
+       }
 
-    pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
 
-    pic16_emitpLabel(tlbl->key);
+       if(pic16_sameRegs(AOP(result), AOP(left))) {
+
+               pct1 = pic16_popGetTempReg();
+               pct2 = pic16_popGetTempReg();
+               pct3 = pic16_popGetTempReg();
+               pct4 = pic16_popGetTempReg();
+
+               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
+               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
+               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                       pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct1)));
+               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                       pic16_popCopyReg(&pic16_pc_prodh), pic16_pCodeOpCopy(pct2)));
+                                       
+               /* WREG still holds the lower left */
+               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 1));
+               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                       pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct3)));
+               
+               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 1));
+               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
+               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                       pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct4)));
+                                       
+               /* load result */
+               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                       pic16_pCodeOpCopy( pct1 ), pic16_popGet(AOP(result), 0)));
+               pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy( pct2 ));
+               pic16_emitpcode(POC_ADDFW, pic16_pCodeOpCopy(pct3));
+               pic16_emitpcode(POC_ADDFWC, pic16_pCodeOpCopy(pct4));
+               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
+
+               pic16_popReleaseTempReg( pct4 );
+               pic16_popReleaseTempReg( pct3 );
+               pic16_popReleaseTempReg( pct2 );
+               pic16_popReleaseTempReg( pct1 );
 
-    pic16_emitpcode(POC_RRCF,  pic16_popCopyReg(PCOR(temp)));
-    emitSKPNC;
-    pic16_emitpcode(POC_ADDWF, pic16_popCopyReg(result_hi));
+       } else {
 
-    pic16_emitpcode(POC_RRCF,  pic16_popCopyReg(result_hi));
-    pic16_emitpcode(POC_RRCF,  pic16_popGet(AOP(result),0));
+               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
+               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
+               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                       pic16_popCopyReg(&pic16_pc_prodl), pic16_popGet(AOP(result), 0)));
+               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                       pic16_popCopyReg(&pic16_pc_prodh), pic16_popGet(AOP(result), 1)));
+
+               /* WREG still holds the lower left */
+               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 1));
+               pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
+               pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 1));
+               
+               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 1));
+               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
+               pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
+               pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), 1));
+       }       
+}
 
-    emitSKPC;
-    pic16_emitpcode(POC_GOTO,  pic16_popGetLabel(tlbl->key));
 
-    pic16_popReleaseTempReg(temp);
+void pic16_genSMult16X16_16(operand *left,
+                       operand *right,
+                       operand *result)
+{
 
-  }
 }
 
+#if 0
 /*-----------------------------------------------------------------*
  * pic16_genSMult8X8_16 - signed multiplication of two 8-bit numbers
  *
  *  this routine will call the unsigned multiply routine and then
  * post-fix the sign bit.
  *-----------------------------------------------------------------*/
-void pic16_genSMult8X8_16 (operand *left,
+void pic16_genSMult8X8_8 (operand *left,
                           operand *right,
                           operand *result,
                           pCodeOpReg *result_hi)
 {
+       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
 
   if(!result_hi) {
     result_hi = PCOR(pic16_popGet(AOP(result),1));
   }
 
-  pic16_genUMult8X8_16(left,right,result,result_hi);
 
+  pic16_genUMult8X8_8(left,right,result);
+
+  
+#if 0
   pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(left),0,FALSE,FALSE),7,0));
   pic16_emitpcode(POC_SUBWF, pic16_popCopyReg(result_hi));
   pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left),0));
   pic16_emitpcode(POC_BTFSC, pic16_newpCodeOpBit(pic16_aopGet(AOP(right),0,FALSE,FALSE),7,0));
   pic16_emitpcode(POC_SUBWF, pic16_popGet(AOP(result),1));
-  
+#endif
 }
+#endif
 
 /*-----------------------------------------------------------------*
- * pic16_genMult8X8_8 - multiplication of two 8-bit numbers
- *
- *  this routine will call the unsigned multiply 8X8=>16 routine and
- * then throw away the high byte of the result.
- *
+ * pic16_genMult8X8_8 - multiplication of two 8-bit numbers        *
  *-----------------------------------------------------------------*/
 void pic16_genMult8X8_8 (operand *left,
                         operand *right,
                         operand *result)
 {
-  pCodeOp *result_hi = pic16_popGetTempReg();
+       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+       if(AOP_TYPE(right) == AOP_LIT)
+               pic16_genUMult8XLit_8(left,right,result);
+       else
+               pic16_genUMult8X8_8(left,right,result);
+}
+
+
+/*-----------------------------------------------------------------*
+ * pic16_genMult16X16_16 - multiplication of two 16-bit numbers    *
+ *-----------------------------------------------------------------*/
+void pic16_genMult16X16_16 (operand *left,
+                        operand *right,
+                        operand *result)
+{
+       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+       if (AOP_TYPE(right) == AOP_LIT)
+               pic16_genUMult16XLit_16(left,right,result);
+       else
+               pic16_genUMult16X16_16(left,right,result);
+
+}
+
+
+
+
+/*-----------------------------------------------------------------------*
+ * pic_genUMult32XLit_32 - unsigned multiplication of two 32-bit numbers *
+ *-----------------------------------------------------------------------*/
+void pic16_genUMult32XLit_32 (operand *left,
+                            operand *right,
+                            operand *result)
+{
+  pCodeOp *pct1, *pct2, *pct3, *pct4;
+  unsigned int lit;
+  int same;
 
-  if (AOP_TYPE(right) == AOP_LIT)
-    pic16_genUMult8XLit_16(left,right,result,PCOR(result_hi));
-  else
-    pic16_genUMult8X8_16(left,right,result,PCOR(result_hi));
 
-  pic16_popReleaseTempReg(result_hi);
+       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+       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 &= 0xffff;
+
+       same = pic16_sameRegs(AOP(left), AOP(result));
+       if(same) {
+               switch(lit) {
+                       case 0:
+                               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),0));
+                               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result),1));
+                               return;
+                       case 2:
+                               // its faster to left shift
+                               emitCLRC;
+                               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),0));
+                               pic16_emitpcode(POC_RLCF, pic16_popGet(AOP(left),1));
+                               return;
+
+                       default: {
+                               DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+                               pct1 = pic16_popGetTempReg();
+                               pct2 = pic16_popGetTempReg();
+                               pct3 = pic16_popGetTempReg();
+                               pct4 = pic16_popGetTempReg();
+
+                               pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit & 0xff));
+                               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
+                               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                                       pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct1)));
+                               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                                       pic16_popCopyReg(&pic16_pc_prodh), pic16_pCodeOpCopy(pct2)));
+                                       
+                               /* WREG still holds the low literal */
+                               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 1));
+                               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                                       pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct3)));
+                                       
+                               pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit>>8 ));
+                               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
+                               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                                       pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct4)));
+                                       
+                               /* load result */
+                               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                                       pct1, pic16_popGet(AOP(result), 0)));
+                               pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy(pct2));
+                               pic16_emitpcode(POC_ADDFW, pic16_pCodeOpCopy(pct3));
+                               pic16_emitpcode(POC_ADDFWC, pic16_pCodeOpCopy(pct4));
+                               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
+
+                               pic16_popReleaseTempReg( pct4 );
+                               pic16_popReleaseTempReg( pct3 );
+                               pic16_popReleaseTempReg( pct2 );
+                               pic16_popReleaseTempReg( pct1 );
+                       }; return;
+               }
+       } else {
+               // operands different
+               switch(lit) {
+                       case 0:
+                               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 0));
+                               pic16_emitpcode(POC_CLRF, pic16_popGet(AOP(result), 1));
+                               return;
+                       case 2:
+                               emitCLRC;
+                               pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 0));
+                               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 0));
+                               pic16_emitpcode(POC_RLCFW, pic16_popGet(AOP(left), 1));
+                               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
+                               return;
+                       default: {
+                                       
+                               pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit & 0xff));
+                               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
+                               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                                       pic16_popCopyReg(&pic16_pc_prodl), pic16_popGet(AOP(result), 0)));
+                               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                                       pic16_popCopyReg(&pic16_pc_prodh), pic16_popGet(AOP(result), 1)));
+                                       
+                               /* WREG still holds the low literal */
+                               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 1));
+                               pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
+                               pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 1));
+                                       
+                               pic16_emitpcode(POC_MOVLW, pic16_popGetLit( lit>>8 ));
+                               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(left), 0));
+                               pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
+                               pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), 1));
+
+                       }; return;
+               }
+       }
 }
+
+
+/*------------------------------------------------------------------*
+ * genUMult32X32_32 - unsigned multiplication of two 32-bit numbers *
+ *------------------------------------------------------------------*/
+void pic16_genUMult32X32_32 (operand *left,
+                          operand *right,
+                          operand *result)
+
+{
+  pCodeOp *pct1, *pct2, *pct3, *pct4;
+
+       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+
+       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
+       */
+       /* if result == right then exchange left and right */
+       if(pic16_sameRegs(AOP(result), AOP(right))) {
+         operand *tmp;
+               tmp = left;
+               left = right;
+               right = tmp;
+       }
+
+
+       if(pic16_sameRegs(AOP(result), AOP(left))) {
+
+               pct1 = pic16_popGetTempReg();
+               pct2 = pic16_popGetTempReg();
+               pct3 = pic16_popGetTempReg();
+               pct4 = pic16_popGetTempReg();
+
+               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
+               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
+               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                       pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct1)));
+               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                       pic16_popCopyReg(&pic16_pc_prodh), pic16_pCodeOpCopy(pct2)));
+                                       
+               /* WREG still holds the lower left */
+               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 1));
+               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                       pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct3)));
+               
+               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 1));
+               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
+               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                       pic16_popCopyReg(&pic16_pc_prodl), pic16_pCodeOpCopy(pct4)));
+                                       
+               /* load result */
+               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                       pic16_pCodeOpCopy( pct1 ), pic16_popGet(AOP(result), 0)));
+               pic16_emitpcode(POC_MOVFW, pic16_pCodeOpCopy( pct2 ));
+               pic16_emitpcode(POC_ADDFW, pic16_pCodeOpCopy(pct3));
+               pic16_emitpcode(POC_ADDFWC, pic16_pCodeOpCopy(pct4));
+               pic16_emitpcode(POC_MOVWF, pic16_popGet(AOP(result), 1));
+
+               pic16_popReleaseTempReg( pct4 );
+               pic16_popReleaseTempReg( pct3 );
+               pic16_popReleaseTempReg( pct2 );
+               pic16_popReleaseTempReg( pct1 );
+
+       } else {
+
+               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 0));
+               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
+               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                       pic16_popCopyReg(&pic16_pc_prodl), pic16_popGet(AOP(result), 0)));
+               pic16_emitpcode(POC_MOVFF, pic16_popGet2p(
+                       pic16_popCopyReg(&pic16_pc_prodh), pic16_popGet(AOP(result), 1)));
+
+               /* WREG still holds the lower left */
+               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 1));
+               pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
+               pic16_emitpcode(POC_ADDWF, pic16_popGet(AOP(result), 1));
+               
+               pic16_emitpcode(POC_MOVFW, pic16_popGet(AOP(left), 1));
+               pic16_emitpcode(POC_MULWF, pic16_popGet(AOP(right), 0));
+               pic16_emitpcode(POC_MOVFW, pic16_popCopyReg(&pic16_pc_prodl));
+               pic16_emitpcode(POC_ADDWFC, pic16_popGet(AOP(result), 1));
+       }       
+}
+
+
+/*-----------------------------------------------------------------*
+ * pic16_genMult32X32_32 - multiplication of two 32-bit numbers    *
+ *-----------------------------------------------------------------*/
+void pic16_genMult32X32_32 (operand *left,
+                        operand *right,
+                        operand *result)
+{
+       DEBUGpic16_emitcode ("; ***","%s  %d",__FUNCTION__,__LINE__);
+
+       if (AOP_TYPE(right) == AOP_LIT)
+               pic16_genUMult32XLit_32(left,right,result);
+       else
+               pic16_genUMult32X32_32(left,right,result);
+
+}
+
+
+
+
+
+
+
 #if 0
 /*-----------------------------------------------------------------*/
 /* constMult - generates code for multiplication by a constant     */