* src/pic16/{pcode.h,genarith.c}:
[fw/sdcc] / src / pic16 / main.c
index 7f799cfea9553e2ac82f9c2267c31a754cbb26e7..c27a2bdfd07cf0f09dbee6d9f53deaadcb31689b 100644 (file)
@@ -53,6 +53,7 @@ static char *_pic16_keywords[] =
   "pdata",
   "reentrant",
   "sfr",
+  "sfr16",
   "using",
   "_data",
   "_code",
@@ -100,7 +101,6 @@ extern set *libFilesSet;
 /* for an unknowned reason. - EEP */
 void pic16_emitDebuggerSymbol (char *);
  
-extern regs* newReg(short type, short pc_type, int rIdx, char *name, int size, int alias, operand *refop);
 extern void pic16_emitConfigRegs(FILE *of);
 extern void pic16_emitIDRegs(FILE *of);
 
@@ -914,21 +914,80 @@ _pic16_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts)
  * False to convert it to function call */
 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));
+  //fprintf(stderr,"checking for native mult for %c (size: %d)\n", ic->op, getSize(OP_SYMBOL(IC_RESULT(ic))->type));
+
+  /* Checks to enable native multiplication.
+   * PICs do not offer native division at all...
+   *
+   * Ideas:
+   * (  i) if result is just one byte, use native MUL
+   *       (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)
+   *       and the other is an unsigned byte, use native MUL
+   */
+  if (ic->op == '*')
+  {
+    int symL, symR, symRes, sizeL = 0, sizeR = 0, sizeRes = 0;
 
-#if 1
-       /* multiplication is fixed */
-       /* support mul for char/int/long */
-       if((ic->op == '*')
-         && (getSize(OP_SYMBOL(IC_LEFT(ic))->type ) < 2))return TRUE;
-#endif
+    /* 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)))) {
+      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)))) {
+      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 */
+    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)
+      {
+       sizeL = 1;
+      } else {
+       //printf( "%s: left value %ld outside [0..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 >= 0 && l < 256)
+      {
+       sizeR = 1;
+      } else {
+       //printf( "%s: right value %ld outside [0..256)\n", __FUNCTION__, l );
+      }
+    }
+
+    /* use native mult iff left and right are (unsigned) 8-bit operands */
+    if (sizeL == 1 && sizeR == 1) { return TRUE; }
+  }
 
-#if 0
-       /* support div for char/int/long */
-       if((getSize(OP_SYMBOL(IC_LEFT(ic))->type ) < 0)
-               && (ic->op == '/'))return TRUE;
-#endif
-       
   return FALSE;
 }