Added support for DS390 Arithmetic Accelerator
[fw/sdcc] / src / ds390 / gen.c
index 8895de11b20ae4d7c8a14295c021aada09b2e64a..ae0a0f2a0bf433f3f2cba27aad01ca9eb0dd0e5d 100644 (file)
@@ -469,7 +469,7 @@ aopForSym (iCode * ic, symbol * sym, bool result, bool useDP2)
        {
          if (options.model == MODEL_FLAT24)
            emitcode ("mov", "dpx1,#0x40");
-   TR_DPTR("#2");
+         TR_DPTR("#2");
          emitcode ("mov", "dph1,#0x00");
          emitcode ("mov", "dpl1, a");
        }
@@ -987,8 +987,8 @@ aopGet (asmop * aop,
          genSetDPTR (1);
          if (!canClobberACC)
            {
-       TR_AP("#1");
-             emitcode ("xch", "a, %s", DP2_RESULT_REG);
+                   TR_AP("#1");
+                   emitcode ("xch", "a, %s", DP2_RESULT_REG);
            }
        }
 
@@ -3358,6 +3358,8 @@ adjustArithmeticResult (iCode * ic)
     }
 }
 
+#if 0 // AOP_OP_3 is deprecated; nobody likes Ack errors.
+      // Please don't bring it back without a really good reason.
 // Macro to aopOp all three operands of an ic. Will fatal if this cannot be done
 // (because all three operands are in far space).
 #define AOP_OP_3(ic) \
@@ -3372,6 +3374,7 @@ adjustArithmeticResult (iCode * ic)
         fprintf(stderr,                                  \
                "Ack: three operands in far space! (%s:%d %s:%d)\n", __FILE__, __LINE__, ic->filename, ic->lineno);   \
     }
+#endif
 
 // Macro to aopOp all three operands of an ic. If this cannot be done, 
 // the IC_LEFT and IC_RIGHT operands will be aopOp'd, and the rc parameter
@@ -3919,10 +3922,12 @@ release:
 static void
 genMultbits (operand * left,
             operand * right,
-            operand * result)
+            operand * result,
+            iCode   * ic)
 {
   emitcode ("mov", "c,%s", AOP (left)->aopu.aop_dir);
   emitcode ("anl", "c,%s", AOP (right)->aopu.aop_dir);
+  aopOp(result, ic, TRUE, FALSE);
   outBitC (result);
 }
 
@@ -3933,18 +3938,12 @@ genMultbits (operand * left,
 static void
 genMultOneByte (operand * left,
                operand * right,
-               operand * result)
+               operand * result,
+               iCode   * ic)
 {
   sym_link *opetype = operandType (result);
   symbol *lbl;
-  int size=AOP_SIZE(result);
 
-  if (size<1 || size>2) {
-    // this should never happen
-      fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
-              AOP_SIZE(result), __FILE__, lineno);
-      exit (1);
-  }
 
   /* (if two literals: the value is computed before) */
   /* if one literal, literal on the right */
@@ -3965,8 +3964,22 @@ genMultOneByte (operand * left,
     emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE, TRUE));
     MOVA (aopGet (AOP (left), 0, FALSE, FALSE, TRUE));
     emitcode ("mul", "ab");
+   
+    _G.accInUse++;
+    aopOp(result, ic, TRUE, FALSE);
+      
+      if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
+      {
+         // this should never happen
+         fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
+                  AOP_SIZE(result), __FILE__, lineno);
+         exit (1);
+      }      
+      
     aopPut (AOP (result), "a", 0);
-    if (size==2) {
+    _G.accInUse--;
+    if (AOP_SIZE(result)==2) 
+    {
       aopPut (AOP (result), "b", 1);
     }
     return;
@@ -4010,11 +4023,22 @@ genMultOneByte (operand * left,
   }
   emitcode ("mul", "ab");
     
+  _G.accInUse++;
+  aopOp(result, ic, TRUE, FALSE);
+    
+  if (AOP_SIZE(result)<1 || AOP_SIZE(result)>2) 
+  {
+    // this should never happen
+      fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
+              AOP_SIZE(result), __FILE__, lineno);
+      exit (1);
+  }    
+    
   lbl=newiTempLabel(NULL);
   emitcode ("jnb", "F0,%05d$", lbl->key+100);
   // only ONE op was negative, we have to do a 8/16-bit two's complement
   emitcode ("cpl", "a"); // lsb
-  if (size==1) {
+  if (AOP_SIZE(result)==1) {
     emitcode ("inc", "a");
   } else {
     emitcode ("add", "a,#1");
@@ -4026,11 +4050,142 @@ genMultOneByte (operand * left,
 
   emitcode ("", "%05d$:", lbl->key+100);
   aopPut (AOP (result), "a", 0);
-  if (size==2) {
+  _G.accInUse--;
+  if (AOP_SIZE(result)==2) {
     aopPut (AOP (result), "b", 1);
   }
 }
 
+/*-----------------------------------------------------------------*/
+/* genMultTwoByte - use the DS390 MAC unit to do 16*16 multiply    */
+/*-----------------------------------------------------------------*/
+static void genMultTwoByte (operand *left, operand *right, 
+                           operand *result, iCode *ic)
+{
+       sym_link *retype = getSpec(operandType(right));
+       sym_link *letype = getSpec(operandType(left));
+       int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
+       symbol *lbl;
+
+       if (AOP_TYPE (left) == AOP_LIT) {
+               operand *t = right;
+               right = left;
+               left = t;
+       }
+       /* load up MB with right */
+       if (!umult) {
+               emitcode("clr","F0");
+               if (AOP_TYPE(right) == AOP_LIT) {
+                       int val=floatFromVal (AOP (right)->aopu.aop_lit);
+                       if (val < 0) {
+                               emitcode("setb","F0");
+                               val = -val;
+                       } 
+                       emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
+                       emitcode ("mov","mb,#0x%02x",val & 0xff);
+               } else {
+                       lbl = newiTempLabel(NULL);
+                       emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
+                       emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
+                       emitcode ("jnb","acc.7,%05d$",lbl->key+100);            
+                       emitcode ("xch", "a,b");
+                       emitcode ("cpl","a");
+                       emitcode ("add", "a,#1");
+                       emitcode ("xch", "a,b");
+                       emitcode ("cpl", "a"); // msb
+                       emitcode ("addc", "a,#0");
+                       emitcode ("setb","F0");
+                       emitcode ("","%05d$:",lbl->key+100);
+                       emitcode ("mov","mb,b");
+                       emitcode ("mov","mb,a");
+               }
+       } else {
+               emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
+               emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
+       }
+       /* load up MA with left */
+       if (!umult) {
+               lbl = newiTempLabel(NULL);
+               emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
+               emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
+               emitcode ("jnb","acc.7,%05d$",lbl->key+100);
+               emitcode ("xch", "a,b");
+               emitcode ("cpl","a");
+               emitcode ("add", "a,#1");
+               emitcode ("xch", "a,b");
+               emitcode ("cpl", "a"); // msb
+               emitcode ("addc","a,#0");
+               emitcode ("jbc","F0,%05d$",lbl->key+100);
+               emitcode ("setb","F0");
+               emitcode ("","%05d$:",lbl->key+100);
+               emitcode ("mov","ma,b");
+               emitcode ("mov","ma,a");
+       } else {
+               emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
+               emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
+       }
+       /* wait for multiplication to finish */
+       lbl = newiTempLabel(NULL);
+       emitcode("","%05d$:", lbl->key+100);
+       emitcode("mov","a,mcnt1");
+       emitcode("anl","a,#0x80");
+       emitcode("jnz","%05d$",lbl->key+100);
+       
+       freeAsmop (left, NULL, ic, TRUE);
+       freeAsmop (right, NULL, ic,TRUE);
+       aopOp(result, ic, TRUE, FALSE);
+
+       /* if unsigned then simple */   
+       if (umult) {
+               emitcode ("mov","a,ma");
+               if (AOP_SIZE(result) >= 4) aopPut(AOP(result),"a",3);
+               emitcode ("mov","a,ma");
+               if (AOP_SIZE(result) >= 3) aopPut(AOP(result),"a",2);
+               aopPut(AOP(result),"ma",1);
+               aopPut(AOP(result),"ma",0);
+       } else {
+               emitcode("push","ma");
+               emitcode("push","ma");
+               emitcode("push","ma");
+               MOVA("ma");
+               /* negate result if needed */
+               lbl = newiTempLabel(NULL);      
+               emitcode("jnb","F0,%05d$",lbl->key+100);
+               emitcode("cpl","a");
+               emitcode("add","a,#1");
+               emitcode("","%05d$:", lbl->key+100);
+               aopPut(AOP(result),"a",0);
+               emitcode("pop","acc");
+               lbl = newiTempLabel(NULL);      
+               emitcode("jnb","F0,%05d$",lbl->key+100);
+               emitcode("cpl","a");
+               emitcode("addc","a,#0");
+               emitcode("","%05d$:", lbl->key+100);
+               aopPut(AOP(result),"a",1);
+               emitcode("pop","acc");
+               if (AOP_SIZE(result) >= 3) {
+                       lbl = newiTempLabel(NULL);      
+                       emitcode("jnb","F0,%05d$",lbl->key+100);
+                       emitcode("cpl","a");
+                       emitcode("addc","a,#0");                        
+                       emitcode("","%05d$:", lbl->key+100);
+                       aopPut(AOP(result),"a",2);
+               }
+               emitcode("pop","acc");
+               if (AOP_SIZE(result) >= 4) {
+                       lbl = newiTempLabel(NULL);      
+                       emitcode("jnb","F0,%05d$",lbl->key+100);
+                       emitcode("cpl","a");
+                       emitcode("addc","a,#0");                        
+                       emitcode("","%05d$:", lbl->key+100);
+                       aopPut(AOP(result),"a",3);
+               }
+               
+       }
+       freeAsmop (result, NULL, ic, TRUE);
+       return ;
+}
+
 /*-----------------------------------------------------------------*/
 /* genMult - generates code for multiplication                     */
 /*-----------------------------------------------------------------*/
@@ -4044,14 +4199,14 @@ genMult (iCode * ic)
   D (emitcode (";", "genMult "););
 
   /* assign the amsops */
-  AOP_OP_3 (ic);
+  AOP_OP_2 (ic);
 
   /* special cases first */
   /* both are bits */
   if (AOP_TYPE (left) == AOP_CRY &&
       AOP_TYPE (right) == AOP_CRY)
     {
-      genMultbits (left, right, result);
+      genMultbits (left, right, result, ic);
       goto release;
     }
 
@@ -4059,12 +4214,17 @@ genMult (iCode * ic)
   if (AOP_SIZE (left) == 1 &&
       AOP_SIZE (right) == 1)
     {
-      genMultOneByte (left, right, result);
+      genMultOneByte (left, right, result, ic);
       goto release;
     }
 
+  if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
+         /* use the ds390 ARITHMETIC accel UNIT */
+         genMultTwoByte (left, right, result, ic);
+         return ;
+  }
   /* should have been converted to function call */
-  assert (1);
+  assert (0);
 
 release:
   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
@@ -4078,7 +4238,8 @@ release:
 static void
 genDivbits (operand * left,
            operand * right,
-           operand * result)
+           operand * result,
+           iCode   * ic)
 {
 
   char *l;
@@ -4087,6 +4248,8 @@ genDivbits (operand * left,
   LOAD_AB_FOR_DIV (left, right, l);
   emitcode ("div", "ab");
   emitcode ("rrc", "a");
+  aopOp(result, ic, TRUE, FALSE);
+    
   aopPut (AOP (result), "c", 0);
 }
 
@@ -4096,24 +4259,33 @@ genDivbits (operand * left,
 static void
 genDivOneByte (operand * left,
               operand * right,
-              operand * result)
+              operand * result,
+              iCode   * ic)
 {
   sym_link *opetype = operandType (result);
   char *l;
   symbol *lbl;
   int size, offset;
 
-  size = AOP_SIZE (result) - 1;
   offset = 1;
   /* signed or unsigned */
   if (SPEC_USIGN (opetype))
     {
-      /* unsigned is easy */
-      LOAD_AB_FOR_DIV (left, right, l);
-      emitcode ("div", "ab");
-      aopPut (AOP (result), "a", 0);
-      while (size--)
-       aopPut (AOP (result), zero, offset++);
+       /* unsigned is easy */
+       LOAD_AB_FOR_DIV (left, right, l);
+       emitcode ("div", "ab");
+
+       _G.accInUse++;
+       aopOp(result, ic, TRUE, FALSE);
+       aopPut (AOP (result), "a", 0);
+       _G.accInUse--;
+
+       size = AOP_SIZE (result) - 1;
+       
+       while (size--)
+       {
+           aopPut (AOP (result), zero, offset++);
+       }
       return;
     }
 
@@ -4164,15 +4336,129 @@ genDivOneByte (operand * left,
   emitcode ("", "%05d$:", (lbl->key + 100));
 
   /* now we are done */
-  aopPut (AOP (result), "b", 0);
-  if (size > 0)
+    _G.accInUse++;
+    aopOp(result, ic, TRUE, FALSE);
+    
+    aopPut (AOP (result), "b", 0);
+    
+    size = AOP_SIZE (result) - 1;
+    
+    if (size > 0)
     {
       emitcode ("mov", "c,b.7");
       emitcode ("subb", "a,acc");
     }
-  while (size--)
-    aopPut (AOP (result), "a", offset++);
+    while (size--)
+    {
+       aopPut (AOP (result), "a", offset++);
+    }
+    _G.accInUse--;
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genDivTwoByte - use the DS390 MAC unit to do 16/16 divide       */
+/*-----------------------------------------------------------------*/
+static void genDivTwoByte (operand *left, operand *right, 
+                           operand *result, iCode *ic)
+{
+       sym_link *retype = getSpec(operandType(right));
+       sym_link *letype = getSpec(operandType(left));
+       int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
+       symbol *lbl;
+
+       /* load up MA with left */
+       if (!umult) {
+               emitcode("clr","F0");
+               lbl = newiTempLabel(NULL);
+               emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
+               emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
+               emitcode ("jnb","acc.7,%05d$",lbl->key+100);
+               emitcode ("xch", "a,b");
+               emitcode ("cpl","a");
+               emitcode ("add", "a,#1");
+               emitcode ("xch", "a,b");
+               emitcode ("cpl", "a"); // msb
+               emitcode ("addc","a,#0");
+               emitcode ("setb","F0");
+               emitcode ("","%05d$:",lbl->key+100);
+               emitcode ("mov","ma,b");
+               emitcode ("mov","ma,a");
+       } else {
+               emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
+               emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
+       }
+
+       /* load up MB with right */
+       if (!umult) {
+               if (AOP_TYPE(right) == AOP_LIT) {
+                       int val=floatFromVal (AOP (right)->aopu.aop_lit);
+                       if (val < 0) {
+                               lbl = newiTempLabel(NULL);
+                               emitcode ("jbc","F0,%05d$",lbl->key+100);
+                               emitcode("setb","F0");
+                               emitcode ("","%05d$:",lbl->key+100);
+                               val = -val;
+                       } 
+                       emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
+                       emitcode ("mov","mb,#0x%02x",val & 0xff);
+               } else {
+                       lbl = newiTempLabel(NULL);
+                       emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
+                       emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
+                       emitcode ("jnb","acc.7,%05d$",lbl->key+100);            
+                       emitcode ("xch", "a,b");
+                       emitcode ("cpl","a");
+                       emitcode ("add", "a,#1");
+                       emitcode ("xch", "a,b");
+                       emitcode ("cpl", "a"); // msb
+                       emitcode ("addc", "a,#0");
+                       emitcode ("jbc","F0,%05d$",lbl->key+100);
+                       emitcode ("setb","F0");
+                       emitcode ("","%05d$:",lbl->key+100);
+                       emitcode ("mov","mb,b");
+                       emitcode ("mov","mb,a");
+               }
+       } else {
+               emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
+               emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
+       }
 
+       /* wait for multiplication to finish */
+       lbl = newiTempLabel(NULL);
+       emitcode("","%05d$:", lbl->key+100);
+       emitcode("mov","a,mcnt1");
+       emitcode("anl","a,#0x80");
+       emitcode("jnz","%05d$",lbl->key+100);
+       
+       freeAsmop (left, NULL, ic, TRUE);
+       freeAsmop (right, NULL, ic,TRUE);
+       aopOp(result, ic, TRUE, FALSE);
+
+       /* if unsigned then simple */   
+       if (umult) {
+               aopPut(AOP(result),"ma",1);
+               aopPut(AOP(result),"ma",0);
+       } else {
+               emitcode("push","ma");
+               MOVA("ma");
+               /* negate result if needed */
+               lbl = newiTempLabel(NULL);      
+               emitcode("jnb","F0,%05d$",lbl->key+100);
+               emitcode("cpl","a");
+               emitcode("add","a,#1");
+               emitcode("","%05d$:", lbl->key+100);
+               aopPut(AOP(result),"a",0);
+               emitcode("pop","acc");
+               lbl = newiTempLabel(NULL);      
+               emitcode("jnb","F0,%05d$",lbl->key+100);
+               emitcode("cpl","a");
+               emitcode("addc","a,#0");
+               emitcode("","%05d$:", lbl->key+100);
+               aopPut(AOP(result),"a",1);
+       }
+       freeAsmop (result, NULL, ic, TRUE);
+       return ;
 }
 
 /*-----------------------------------------------------------------*/
@@ -4185,18 +4471,17 @@ genDiv (iCode * ic)
   operand *right = IC_RIGHT (ic);
   operand *result = IC_RESULT (ic);
 
-  D (emitcode (";", "genDiv ");
-    );
+  D (emitcode (";", "genDiv "););
 
   /* assign the amsops */
-  AOP_OP_3 (ic);
+  AOP_OP_2 (ic);
 
   /* special cases first */
   /* both are bits */
   if (AOP_TYPE (left) == AOP_CRY &&
       AOP_TYPE (right) == AOP_CRY)
     {
-      genDivbits (left, right, result);
+      genDivbits (left, right, result, ic);
       goto release;
     }
 
@@ -4204,12 +4489,17 @@ genDiv (iCode * ic)
   if (AOP_SIZE (left) == 1 &&
       AOP_SIZE (right) == 1)
     {
-      genDivOneByte (left, right, result);
+      genDivOneByte (left, right, result, ic);
       goto release;
     }
 
+  if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
+         /* use the ds390 ARITHMETIC accel UNIT */
+         genDivTwoByte (left, right, result, ic);
+         return ;
+  }
   /* should have been converted to function call */
-  assert (1);
+  assert (0);
 release:
   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
   freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
@@ -4222,7 +4512,8 @@ release:
 static void
 genModbits (operand * left,
            operand * right,
-           operand * result)
+           operand * result,
+           iCode   * ic)
 {
 
   char *l;
@@ -4232,6 +4523,7 @@ genModbits (operand * left,
   emitcode ("div", "ab");
   emitcode ("mov", "a,b");
   emitcode ("rrc", "a");
+  aopOp(result, ic, TRUE, FALSE);
   aopPut (AOP (result), "c", 0);
 }
 
@@ -4241,7 +4533,8 @@ genModbits (operand * left,
 static void
 genModOneByte (operand * left,
               operand * right,
-              operand * result)
+              operand * result,
+              iCode   * ic)
 {
   sym_link *opetype = operandType (result);
   char *l;
@@ -4253,6 +4546,7 @@ genModOneByte (operand * left,
       /* unsigned is easy */
       LOAD_AB_FOR_DIV (left, right, l);
       emitcode ("div", "ab");
+      aopOp(result, ic, TRUE, FALSE);  
       aopPut (AOP (result), "b", 0);
       return;
     }
@@ -4305,10 +4599,88 @@ genModOneByte (operand * left,
   emitcode ("", "%05d$:", (lbl->key + 100));
 
   /* now we are done */
+  aopOp(result, ic, TRUE, FALSE);    
   aopPut (AOP (result), "b", 0);
 
 }
 
+/*-----------------------------------------------------------------*/
+/* genModTwoByte - use the DS390 MAC unit to do 16%16 modulus      */
+/*-----------------------------------------------------------------*/
+static void genModTwoByte (operand *left, operand *right, 
+                           operand *result, iCode *ic)
+{
+       sym_link *retype = getSpec(operandType(right));
+       sym_link *letype = getSpec(operandType(left));
+       int umult = SPEC_USIGN(retype) | SPEC_USIGN(letype);
+       symbol *lbl;
+
+       /* load up MA with left */
+       if (!umult) {
+               lbl = newiTempLabel(NULL);
+               emitcode ("mov","b,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
+               emitcode ("mov","a,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
+               emitcode ("jnb","acc.7,%05d$",lbl->key+100);
+               emitcode ("xch", "a,b");
+               emitcode ("cpl","a");
+               emitcode ("add", "a,#1");
+               emitcode ("xch", "a,b");
+               emitcode ("cpl", "a"); // msb
+               emitcode ("addc","a,#0");
+               emitcode ("","%05d$:",lbl->key+100);
+               emitcode ("mov","ma,b");
+               emitcode ("mov","ma,a");
+       } else {
+               emitcode ("mov","ma,%s",aopGet(AOP(left),0,FALSE,FALSE,TRUE));
+               emitcode ("mov","ma,%s",aopGet(AOP(left),1,FALSE,FALSE,TRUE));
+       }
+
+       /* load up MB with right */
+       if (!umult) {
+               if (AOP_TYPE(right) == AOP_LIT) {
+                       int val=floatFromVal (AOP (right)->aopu.aop_lit);
+                       if (val < 0) {
+                               val = -val;
+                       } 
+                       emitcode ("mov","mb,#0x%02x",(val >> 8) & 0xff);
+                       emitcode ("mov","mb,#0x%02x",val & 0xff);
+               } else {
+                       lbl = newiTempLabel(NULL);
+                       emitcode ("mov","b,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
+                       emitcode ("mov","a,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
+                       emitcode ("jnb","acc.7,%05d$",lbl->key+100);            
+                       emitcode ("xch", "a,b");
+                       emitcode ("cpl","a");
+                       emitcode ("add", "a,#1");
+                       emitcode ("xch", "a,b");
+                       emitcode ("cpl", "a"); // msb
+                       emitcode ("addc", "a,#0");
+                       emitcode ("","%05d$:",lbl->key+100);
+                       emitcode ("mov","mb,b");
+                       emitcode ("mov","mb,a");
+               }
+       } else {
+               emitcode ("mov","mb,%s",aopGet(AOP(right),0,FALSE,FALSE,TRUE));
+               emitcode ("mov","mb,%s",aopGet(AOP(right),1,FALSE,FALSE,TRUE));
+       }
+
+       /* wait for multiplication to finish */
+       lbl = newiTempLabel(NULL);
+       emitcode("","%05d$:", lbl->key+100);
+       emitcode("mov","a,mcnt1");
+       emitcode("anl","a,#0x80");
+       emitcode("jnz","%05d$",lbl->key+100);
+       
+       freeAsmop (left, NULL, ic, TRUE);
+       freeAsmop (right, NULL, ic,TRUE);
+       aopOp(result, ic, TRUE, FALSE);
+
+       aopPut(AOP(result),"mb",1);
+       aopPut(AOP(result),"mb",0);
+       freeAsmop (result, NULL, ic, TRUE);
+       return ;
+}
+
 /*-----------------------------------------------------------------*/
 /* genMod - generates code for division                            */
 /*-----------------------------------------------------------------*/
@@ -4319,18 +4691,17 @@ genMod (iCode * ic)
   operand *right = IC_RIGHT (ic);
   operand *result = IC_RESULT (ic);
 
-  D (emitcode (";", "genMod ");
-    );
+  D (emitcode (";", "genMod "); );
 
   /* assign the amsops */
-  AOP_OP_3 (ic);
+  AOP_OP_2 (ic);
 
   /* special cases first */
   /* both are bits */
   if (AOP_TYPE (left) == AOP_CRY &&
       AOP_TYPE (right) == AOP_CRY)
     {
-      genModbits (left, right, result);
+      genModbits (left, right, result, ic);
       goto release;
     }
 
@@ -4338,12 +4709,18 @@ genMod (iCode * ic)
   if (AOP_SIZE (left) == 1 &&
       AOP_SIZE (right) == 1)
     {
-      genModOneByte (left, right, result);
+      genModOneByte (left, right, result, ic);
       goto release;
     }
 
+  if (AOP_SIZE (left) == 2 && AOP_SIZE(right) == 2) {
+         /* use the ds390 ARITHMETIC accel UNIT */
+         genModTwoByte (left, right, result, ic);
+         return ;
+  }
+
   /* should have been converted to function call */
-  assert (1);
+  assert (0);
 
 release:
   freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
@@ -5163,8 +5540,11 @@ genAnd (iCode * ic, iCode * ifx)
 #endif
 
   /* if left is a literal & right is not then exchange them */
-  if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
-      AOP_NEEDSACC (left))
+  if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
+#ifdef LOGIC_OPS_BROKEN      
+    ||  AOP_NEEDSACC (left)
+#endif
+    )
     {
       operand *tmp = right;
       right = left;
@@ -5419,8 +5799,7 @@ genAnd (iCode * ic, iCode * ifx)
                      aopPut (AOP (result), zero, offset);
                      continue;
                    }
-                 D (emitcode (";", "better literal AND.");
-                   );
+                 D (emitcode (";", "better literal AND."););
                  MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
                  emitcode ("anl", "a, %s", aopGet (AOP (right), offset,
                                                    FALSE, FALSE, FALSE));
@@ -5437,10 +5816,16 @@ genAnd (iCode * ic, iCode * ifx)
                    }
                  else
                    {
-                     MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
-                     emitcode ("anl", "a,%s",
-                         aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
-                   }
+                     char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
+                     if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
+                     {
+                         emitcode("mov", "b,a");
+                         rOp = "b";
+                     }
+                       
+                     MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
+                     emitcode ("anl", "a,%s", rOp);
+                   }                   
                }
              aopPut (AOP (result), "a", offset);
            }
@@ -5487,8 +5872,11 @@ genOr (iCode * ic, iCode * ifx)
 #endif
 
   /* if left is a literal & right is not then exchange them */
-  if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
-      AOP_NEEDSACC (left))
+  if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
+#ifdef LOGIC_OPS_BROKEN
+   || AOP_NEEDSACC (left) // I think this is a net loss now.
+#endif      
+      )
     {
       operand *tmp = right;
       right = left;
@@ -5708,6 +6096,7 @@ genOr (iCode * ic, iCode * ifx)
        }
       else
        {
+           _startLazyDPSEvaluation();
          for (; (size--); offset++)
            {
              // normal case
@@ -5721,8 +6110,7 @@ genOr (iCode * ic, iCode * ifx)
                              offset);
                      continue;
                    }
-                 D (emitcode (";", "better literal OR.");
-                   );
+                 D (emitcode (";", "better literal OR."););
                  MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
                  emitcode ("orl", "a, %s", aopGet (AOP (right), offset,
                                                    FALSE, FALSE, FALSE));
@@ -5739,13 +6127,21 @@ genOr (iCode * ic, iCode * ifx)
                    }
                  else
                    {
-                     MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
-                     emitcode ("orl", "a,%s",
-                         aopGet (AOP (left), offset, FALSE, FALSE, FALSE));
+                     char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
+                       
+                     if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
+                     {
+                         emitcode("mov", "b,a");
+                         rOp = "b";
+                     }
+                       
+                     MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
+                     emitcode ("orl", "a,%s", rOp);
                    }
                }
              aopPut (AOP (result), "a", offset);
            }
+           _endLazyDPSEvaluation();
        }
     }
 
@@ -5788,8 +6184,11 @@ genXor (iCode * ic, iCode * ifx)
 
   /* if left is a literal & right is not ||
      if left needs acc & right does not */
-  if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) ||
-      (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right)))
+  if ((AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT) 
+#ifdef LOGIC_OPS_BROKEN      
+      || (AOP_NEEDSACC (left) && !AOP_NEEDSACC (right))
+#endif
+     )
     {
       operand *tmp = right;
       right = left;
@@ -6017,9 +6416,15 @@ genXor (iCode * ic, iCode * ifx)
                  }
                else
                  {
-                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE, TRUE));
-                   emitcode ("xrl", "a,%s",
-                          aopGet (AOP (left), offset, FALSE, TRUE, FALSE));
+                     char *rOp = aopGet (AOP (right), offset, FALSE, FALSE, TRUE);
+                     if (!strcmp(rOp, "a") || !strcmp(rOp, "acc"))
+                     {
+                         emitcode("mov", "b,a");
+                         rOp = "b";
+                     }
+                       
+                     MOVA (aopGet (AOP (left), offset, FALSE, FALSE, TRUE));
+                     emitcode ("xrl", "a,%s", rOp);
                  }
              }
            aopPut (AOP (result), "a", offset);