fixed bug #444971
[fw/sdcc] / src / mcs51 / gen.c
index f4f069deba928771602f3c4497d84dca9748ad3d..2c38a068d64bb89f14ae334c886a7bd4f134ad9f 100644 (file)
@@ -28,6 +28,9 @@
       Made everything static
 -------------------------------------------------------------------------*/
 
+#define D
+//#define D(x) x
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -41,7 +44,7 @@
 #ifdef HAVE_ENDIAN_H
 #include <endian.h>
 #else
-#if !defined(__BORLANDC__) && !defined(_MSC_VER)
+#if !defined(__BORLANDC__) && !defined(_MSC_VER) && !defined(__MINGW32__)
 #warning "Cannot determine ENDIANESS of this machine assuming LITTLE_ENDIAN"
 #warning "If you running sdcc on an INTEL 80x86 Platform you are okay"
 #endif
@@ -89,7 +92,7 @@ _G;
 extern int mcs51_ptrRegReq;
 extern int mcs51_nRegs;
 extern FILE *codeOutFile;
-static void saverbank (int, iCode *, bool);
+static void saveRBank (int, iCode *, bool);
 #define RESULTONSTACK(x) \
                          (IC_RESULT(x) && IC_RESULT(x)->aop && \
                          IC_RESULT(x)->aop->type == AOP_STK )
@@ -120,7 +123,7 @@ static void
 emitcode (char *inst, char *fmt,...)
 {
   va_list ap;
-  char lb[MAX_INLINEASM];
+  char lb[INITIAL_INLINEASM];
   char *lbp = lb;
 
   va_start (ap, fmt);
@@ -252,21 +255,6 @@ newAsmop (short type)
   return aop;
 }
 
-static void
-genSetDPTR (int n)
-{
-  if (!n)
-    {
-      emitcode (";", "Select standard DPTR");
-      emitcode ("mov", "dps, #0x00");
-    }
-  else
-    {
-      emitcode (";", "Select alternate DPTR");
-      emitcode ("mov", "dps, #0x01");
-    }
-}
-
 /*-----------------------------------------------------------------*/
 /* pointerCode - returns the code for a pointer type               */
 /*-----------------------------------------------------------------*/
@@ -779,13 +767,6 @@ aopGet (asmop * aop, int offset, bool bit16, bool dname)
       return rs;
 
     case AOP_DPTR:
-    case AOP_DPTR2:
-
-      if (aop->type == AOP_DPTR2)
-       {
-         genSetDPTR (1);
-       }
-
       while (offset > aop->coff)
        {
          emitcode ("inc", "dptr");
@@ -808,12 +789,6 @@ aopGet (asmop * aop, int offset, bool bit16, bool dname)
        {
          emitcode ("movx", "a,@dptr");
        }
-
-      if (aop->type == AOP_DPTR2)
-       {
-         genSetDPTR (0);
-       }
-
       return (dname ? "acc" : "a");
 
 
@@ -929,13 +904,6 @@ aopPut (asmop * aop, char *s, int offset)
       break;
 
     case AOP_DPTR:
-    case AOP_DPTR2:
-
-      if (aop->type == AOP_DPTR2)
-       {
-         genSetDPTR (1);
-       }
-
       if (aop->code)
        {
          werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
@@ -961,11 +929,6 @@ aopPut (asmop * aop, char *s, int offset)
       MOVA (s);
 
       emitcode ("movx", "@dptr,a");
-
-      if (aop->type == AOP_DPTR2)
-       {
-         genSetDPTR (0);
-       }
       break;
 
     case AOP_R0:
@@ -1043,7 +1006,7 @@ aopPut (asmop * aop, char *s, int offset)
                }
              {
                symbol *lbl = newiTempLabel (NULL);
-               emitcode ("clr", "c");
+               emitcode ("clr", "c; oops");
                emitcode ("jz", "%05d$", lbl->key + 100);
                emitcode ("cpl", "c");
                emitcode ("", "%05d$:", lbl->key + 100);
@@ -1111,7 +1074,6 @@ pointToEnd (asmop * aop)
 static void
 reAdjustPreg (asmop * aop)
 {
-  aop->coff = 0;
   if ((aop->coff==0) || aop->size <= 1)
     return;
 
@@ -1123,24 +1085,13 @@ reAdjustPreg (asmop * aop)
        emitcode ("dec", "%s", aop->aopu.aop_ptr->name);
       break;
     case AOP_DPTR:
-    case AOP_DPTR2:
-      if (aop->type == AOP_DPTR2)
-       {
-         genSetDPTR (1);
-       }
       while (aop->coff--)
        {
          emitcode ("lcall", "__decdptr");
        }
-
-      if (aop->type == AOP_DPTR2)
-       {
-         genSetDPTR (0);
-       }
       break;
-
     }
-
+  aop->coff = 0;
 }
 
 #define AOP(op) op->aop
@@ -1150,8 +1101,7 @@ reAdjustPreg (asmop * aop)
                        AOP_TYPE(x) == AOP_R0))
 
 #define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY ||  \
-                        AOP_TYPE(x) == AOP_DPTR || AOP_TYPE(x) == AOP_DPTR2 || \
-                         AOP(x)->paged))
+                        AOP_TYPE(x) == AOP_DPTR || AOP(x)->paged))
 
 #define AOP_INPREG(x) (x && (x->type == AOP_REG &&                        \
                       (x->aopu.aop_reg[0] == mcs51_regWithIdx(R0_IDX) || \
@@ -1496,9 +1446,10 @@ saveRegisters (iCode * lic)
       return;
     }
 
-  /* if the registers have been saved already then
+  /* if the registers have been saved already or don't need to be then
      do nothing */
-  if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave))
+  if (ic->regsSaved || (OP_SYMBOL (IC_LEFT (ic))->calleeSave) ||
+      SPEC_NAKED(OP_SYM_ETYPE(IC_LEFT (ic))))
     return;
 
   /* find the registers in use at this time
@@ -1536,12 +1487,6 @@ saveRegisters (iCode * lic)
       }
 
   detype = getSpec (operandType (IC_LEFT (ic)));
-  if (detype &&
-      (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
-      IS_ISR (currFunc->etype) &&
-      !ic->bankSaved)
-
-    saverbank (SPEC_BANK (detype), ic, TRUE);
 
 }
 /*-----------------------------------------------------------------*/
@@ -1669,6 +1614,7 @@ genIpush (iCode * ic)
   int size, offset = 0;
   char *l;
 
+  D(emitcode (";", "genIpush"));
 
   /* if this is not a parm push : ie. it is spill push
      and spill push is always done on the local stack */
@@ -1756,31 +1702,42 @@ genIpop (iCode * ic)
 }
 
 /*-----------------------------------------------------------------*/
-/* unsaverbank - restores the resgister bank from stack            */
+/* unsaveRBank - restores the resgister bank from stack            */
 /*-----------------------------------------------------------------*/
 static void
-unsaverbank (int bank, iCode * ic, bool popPsw)
+unsaveRBank (int bank, iCode * ic, bool popPsw)
 {
   int i;
-  asmop *aop;
+  asmop *aop = NULL;
   regs *r = NULL;
 
+  if (options.useXstack)
+  {
+      if (!ic)
+      {
+         /* Assume r0 is available for use. */
+         r = mcs51_regWithIdx (R0_IDX);;          
+      }        
+      else
+      {
+         aop = newAsmop (0);
+         r = getFreePtr (ic, &aop, FALSE);
+      }
+      emitcode ("mov", "%s,_spx", r->name);      
+  }
+  
   if (popPsw)
     {
       if (options.useXstack)
-       {
-         aop = newAsmop (0);
-         r = getFreePtr (ic, &aop, FALSE);
-
-
-         emitcode ("mov", "%s,_spx", r->name);
+      {
          emitcode ("movx", "a,@%s", r->name);
          emitcode ("mov", "psw,a");
          emitcode ("dec", "%s", r->name);
-
        }
       else
+      {
        emitcode ("pop", "psw");
+      }
     }
 
   for (i = (mcs51_nRegs - 1); i >= 0; i--)
@@ -1800,30 +1757,38 @@ unsaverbank (int bank, iCode * ic, bool popPsw)
 
   if (options.useXstack)
     {
-
       emitcode ("mov", "_spx,%s", r->name);
-      freeAsmop (NULL, aop, ic, TRUE);
-
     }
+    
+  if (aop)
+  {
+      freeAsmop (NULL, aop, ic, TRUE);  
+  }    
 }
 
 /*-----------------------------------------------------------------*/
-/* saverbank - saves an entire register bank on the stack          */
+/* saveRBank - saves an entire register bank on the stack          */
 /*-----------------------------------------------------------------*/
 static void
-saverbank (int bank, iCode * ic, bool pushPsw)
+saveRBank (int bank, iCode * ic, bool pushPsw)
 {
   int i;
-  asmop *aop;
+  asmop *aop = NULL;
   regs *r = NULL;
 
   if (options.useXstack)
     {
-
-      aop = newAsmop (0);
-      r = getFreePtr (ic, &aop, FALSE);
+      if (!ic)
+      {
+         /* Assume r0 is available for use. */
+         r = mcs51_regWithIdx (R0_IDX);;
+      }
+      else
+      {
+         aop = newAsmop (0);
+         r = getFreePtr (ic, &aop, FALSE);
+      }
       emitcode ("mov", "%s,_spx", r->name);
-
     }
 
   for (i = 0; i < mcs51_nRegs; i++)
@@ -1848,16 +1813,25 @@ saverbank (int bank, iCode * ic, bool pushPsw)
          emitcode ("movx", "@%s,a", r->name);
          emitcode ("inc", "%s", r->name);
          emitcode ("mov", "_spx,%s", r->name);
-         freeAsmop (NULL, aop, ic, TRUE);
 
        }
       else
+      {
        emitcode ("push", "psw");
+      }
 
       emitcode ("mov", "psw,#0x%02x", (bank << 3) & 0x00ff);
     }
-  ic->bankSaved = 1;
 
+    if (aop)
+    {
+        freeAsmop (NULL, aop, ic, TRUE);
+    }
+
+  if (ic)
+  {  
+      ic->bankSaved = 1;
+  }
 }
 
 /*-----------------------------------------------------------------*/
@@ -1867,22 +1841,10 @@ static void
 genCall (iCode * ic)
 {
   sym_link *detype;
+  bool restoreBank = FALSE;
+  bool swapBanks = FALSE;
 
-  /* if caller saves & we have not saved then */
-  if (!ic->regsSaved)
-    saveRegisters (ic);
-
-  /* if we are calling a function that is not using
-     the same register bank then we need to save the
-     destination registers on the stack */
-  detype = getSpec (operandType (IC_LEFT (ic)));
-  if (detype &&
-      (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
-      IS_ISR (currFunc->etype) &&
-      !ic->bankSaved)
-
-    saverbank (SPEC_BANK (detype), ic, TRUE);
-
+  D(emitcode(";", "genCall"));
   /* if send set is not empty the assign */
   if (_G.sendSet)
     {
@@ -1908,11 +1870,47 @@ genCall (iCode * ic)
        }
       _G.sendSet = NULL;
     }
+
+  /* if we are calling a not _naked function that is not using
+     the same register bank then we need to save the
+     destination registers on the stack */
+  detype = getSpec (operandType (IC_LEFT (ic)));
+  if (detype && !SPEC_NAKED(detype) &&
+      (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)) &&
+      IS_ISR (currFunc->etype))
+  {
+      if (!ic->bankSaved) 
+      {
+           /* This is unexpected; the bank should have been saved in
+            * genFunction.
+            */
+          saveRBank (SPEC_BANK (detype), ic, FALSE);
+          restoreBank = TRUE;
+      }
+      swapBanks = TRUE;  
+  } 
+    
+  /* if caller saves & we have not saved then */
+  if (!ic->regsSaved)
+      saveRegisters (ic);
+
+  if (swapBanks)
+  {
+        emitcode ("mov", "psw,#0x%02x", 
+           ((SPEC_BANK(detype)) << 3) & 0xff);
+  }
+
   /* make the call */
   emitcode ("lcall", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
                            OP_SYMBOL (IC_LEFT (ic))->rname :
                            OP_SYMBOL (IC_LEFT (ic))->name));
 
+  if (swapBanks)
+  {
+       emitcode ("mov", "psw,#0x%02x", 
+          ((SPEC_BANK(currFunc->etype)) << 3) & 0xff);
+  }
+
   /* if we need assign a result value */
   if ((IS_ITEMP (IC_RESULT (ic)) &&
        (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
@@ -1943,18 +1941,15 @@ genCall (iCode * ic)
       else
        for (i = 0; i < ic->parmBytes; i++)
          emitcode ("dec", "%s", spname);
-
     }
 
-  /* if register bank was saved then pop them */
-  if (ic->bankSaved)
-    unsaverbank (SPEC_BANK (detype), ic, TRUE);
-
   /* if we hade saved some registers then unsave them */
   if (ic->regsSaved && !(OP_SYMBOL (IC_LEFT (ic))->calleeSave))
     unsaveRegisters (ic);
 
-
+  /* if register bank was saved then pop them */
+  if (restoreBank)
+    unsaveRBank (SPEC_BANK (detype), ic, FALSE);
 }
 
 /*-----------------------------------------------------------------*/
@@ -1978,7 +1973,7 @@ genPcall (iCode * ic)
   if (detype &&
       IS_ISR (currFunc->etype) &&
       (SPEC_BANK (currFunc->etype) != SPEC_BANK (detype)))
-    saverbank (SPEC_BANK (detype), ic, TRUE);
+    saveRBank (SPEC_BANK (detype), ic, TRUE);
 
 
   /* push the return address on to the stack */
@@ -2061,7 +2056,7 @@ genPcall (iCode * ic)
   if (detype &&
       (SPEC_BANK (currFunc->etype) !=
        SPEC_BANK (detype)))
-    unsaverbank (SPEC_BANK (detype), ic, TRUE);
+    unsaveRBank (SPEC_BANK (detype), ic, TRUE);
 
   /* if we hade saved some registers then
      unsave them */
@@ -2124,6 +2119,7 @@ genFunction (iCode * ic)
 {
   symbol *sym;
   sym_link *fetype;
+  bool   switchedPSW = FALSE;
 
   _G.nRegsSaved = 0;
   /* create the function header */
@@ -2134,6 +2130,12 @@ genFunction (iCode * ic)
   emitcode ("", "%s:", sym->rname);
   fetype = getSpec (operandType (IC_LEFT (ic)));
 
+  if (SPEC_NAKED(fetype))
+  {
+      emitcode(";", "naked function: no prologue.");
+      return;
+  }
+
   /* if critical function then turn interrupts off */
   if (SPEC_CRTCL (fetype))
     emitcode ("clr", "ea");
@@ -2201,10 +2203,99 @@ genFunction (iCode * ic)
          else
            {
              /* this function has  a function call cannot
-                determines register usage so we will have the
+                determines register usage so we will have to push the
                 entire bank */
-             saverbank (0, ic, FALSE);
+             saveRBank (0, ic, FALSE);
+           }
+       }
+       else
+       {
+           /* This ISR uses a non-zero bank.
+            *
+            * We assume that the bank is available for our
+            * exclusive use.
+            *
+            * However, if this ISR calls a function which uses some
+            * other bank, we must save that bank entirely.
+            */
+           unsigned long banksToSave = 0;
+           
+           if (sym->hasFcall)
+           {
+
+#define MAX_REGISTER_BANKS 4
+
+               iCode *i;
+               int ix;
+
+               for (i = ic; i; i = i->next)
+               {
+                   if (i->op == ENDFUNCTION)
+                   {
+                       /* we got to the end OK. */
+                       break;
+                   }
+                   
+                   if (i->op == CALL)
+                   {
+                       sym_link *detype;
+                       
+                       detype = getSpec(operandType (IC_LEFT(i)));
+                       if (detype 
+                        && SPEC_BANK(detype) != SPEC_BANK(sym->etype))
+                       {
+                            /* Mark this bank for saving. */
+                            if (SPEC_BANK(detype) >= MAX_REGISTER_BANKS)
+                            {
+                                werror(E_NO_SUCH_BANK, SPEC_BANK(detype));
+                            }
+                            else
+                            {
+                                banksToSave |= (1 << SPEC_BANK(detype));
+                            }
+                            
+                            /* And note that we don't need to do it in 
+                             * genCall.
+                             */
+                            i->bankSaved = 1;
+                       }
+                   }
+                   if (i->op == PCALL)
+                   {
+                       /* This is a mess; we have no idea what
+                        * register bank the called function might
+                        * use.
+                        *
+                        * The only thing I can think of to do is
+                        * throw a warning and hope.
+                        */
+                       werror(W_FUNCPTR_IN_USING_ISR);   
+                   }
+               }
+
+               if (banksToSave && options.useXstack)
+               {
+                   /* Since we aren't passing it an ic, 
+                    * saveRBank will assume r0 is available to abuse.
+                    *
+                    * So switch to our (trashable) bank now, so
+                    * the caller's R0 isn't trashed.
+                    */
+                   emitcode ("push", "psw");
+                   emitcode ("mov", "psw,#0x%02x", 
+                             (SPEC_BANK (sym->etype) << 3) & 0x00ff);
+                   switchedPSW = TRUE;
+               }
+               
+               for (ix = 0; ix < MAX_REGISTER_BANKS; ix++)
+               {
+                    if (banksToSave & (1 << ix))
+                    {
+                        saveRBank(ix, NULL, FALSE);
+                    }
+               }
            }
+           SPEC_ISR_SAVED_BANKS(currFunc->etype) = banksToSave;
        }
     }
   else
@@ -2233,7 +2324,8 @@ genFunction (iCode * ic)
     }
 
   /* set the register bank to the desired value */
-  if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
+  if ((SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
+   && !switchedPSW)
     {
       emitcode ("push", "psw");
       emitcode ("mov", "psw,#0x%02x", (SPEC_BANK (sym->etype) << 3) & 0x00ff);
@@ -2296,6 +2388,12 @@ genEndFunction (iCode * ic)
 {
   symbol *sym = OP_SYMBOL (IC_LEFT (ic));
 
+  if (SPEC_NAKED(sym->etype))
+  {
+      emitcode(";", "naked function: no epilogue.");
+      return;
+  }
+
   if (IS_RENT (sym->etype) || options.stackAuto)
     {
       emitcode ("mov", "%s,_bp", spname);
@@ -2329,7 +2427,16 @@ genEndFunction (iCode * ic)
 
   /* restore the register bank  */
   if (SPEC_BANK (sym->etype) || IS_ISR (sym->etype))
-    emitcode ("pop", "psw");
+  {
+    if (!SPEC_BANK (sym->etype) || !IS_ISR (sym->etype)
+     || !options.useXstack)
+    {
+        /* Special case of ISR using non-zero bank with useXstack
+         * is handled below.
+         */
+        emitcode ("pop", "psw");
+    }
+  }
 
   if (IS_ISR (sym->etype))
     {
@@ -2340,7 +2447,6 @@ genEndFunction (iCode * ic)
          registers :-) */
       if (!SPEC_BANK (sym->etype))
        {
-
          /* if this function does not call any other
             function then we can be economical and
             save only those registers that are used */
@@ -2364,9 +2470,35 @@ genEndFunction (iCode * ic)
          else
            {
              /* this function has  a function call cannot
-                determines register usage so we will have the
+                determines register usage so we will have to pop the
                 entire bank */
-             unsaverbank (0, ic, FALSE);
+             unsaveRBank (0, ic, FALSE);
+           }
+       }
+       else
+       {
+           /* This ISR uses a non-zero bank.
+            *
+            * Restore any register banks saved by genFunction
+            * in reverse order.
+            */
+           unsigned savedBanks = SPEC_ISR_SAVED_BANKS(currFunc->etype);
+           int ix;
+         
+           for (ix = MAX_REGISTER_BANKS - 1; ix >= 0; ix--)
+           {
+               if (savedBanks & (1 << ix))
+               {
+                   unsaveRBank(ix, NULL, FALSE);
+               }
+           }
+           
+           if (options.useXstack)
+           {
+               /* Restore bank AFTER calling unsaveRBank,
+                * since it can trash r0.
+                */
+               emitcode ("pop", "psw");
            }
        }
 
@@ -2383,8 +2515,8 @@ genEndFunction (iCode * ic)
        emitcode ("setb", "ea");
 
       /* if debug then send end of function */
-/*  if (options.debug && currFunc) { */
-      if (currFunc)
+      /*  if (options.debug && currFunc)  */
+      if (options.debug && currFunc)
        {
          _G.debugLine = 1;
          emitcode ("", "C$%s$%d$%d$%d ==.",
@@ -2423,7 +2555,7 @@ genEndFunction (iCode * ic)
        }
 
       /* if debug then send end of function */
-      if (currFunc)
+      if (options.debug && currFunc)
        {
          _G.debugLine = 1;
          emitcode ("", "C$%s$%d$%d$%d ==.",
@@ -3159,11 +3291,10 @@ genMultOneByte (operand * left,
   symbol *lbl;
   int size=AOP_SIZE(result);
 
-  //emitcode (";",__FUNCTION__);
   if (size<1 || size>2) {
     // this should never happen
       fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
-              AOP_SIZE(result), __FUNCTION__, lineno);
+              AOP_SIZE(result), __FILE__, lineno);
       exit (1);
   }
 
@@ -3197,7 +3328,6 @@ genMultOneByte (operand * left,
 
   //emitcode (";", "signed");
   emitcode ("clr", "F0"); // reset sign flag
-  emitcode ("mov", "b,%s", aopGet (AOP (right), 0, FALSE, FALSE));
   MOVA (aopGet (AOP (left), 0, FALSE, FALSE));
 
   lbl=newiTempLabel(NULL);
@@ -3208,22 +3338,24 @@ genMultOneByte (operand * left,
   emitcode ("inc", "a");
 
   emitcode ("", "%05d$:", lbl->key+100);
-  emitcode ("xch", "a,b");
 
   /* if literal */
   if (AOP_TYPE(right)==AOP_LIT) {
+    signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
     /* AND literal negative */
-    if ((int) floatFromVal (AOP (right)->aopu.aop_lit) < 0) {
-      // two's complement for literal<0
-      emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
-      emitcode ("cpl", "a");
-      emitcode ("inc", "a");
+    if (val < 0) {
+      emitcode ("cpl", "F0"); // complement sign flag
+      emitcode ("mov", "b,#0x%02x", -val);
+    } else {
+      emitcode ("mov", "b,#0x%02x", val);
     }
   } else {
     lbl=newiTempLabel(NULL);
+    emitcode ("mov", "b,a");
+    emitcode ("mov", "a,%s", aopGet (AOP (right), 0, FALSE, FALSE));
     emitcode ("jnb", "acc.7,%05d$", lbl->key+100);
     // right side is negative, 8-bit two's complement
-    emitcode ("xrl", "PSW,#0x20"); // xrl sign flag
+    emitcode ("cpl", "F0"); // complement sign flag
     emitcode ("cpl", "a");
     emitcode ("inc", "a");
     emitcode ("", "%05d$:", lbl->key+100);
@@ -4466,9 +4598,20 @@ genAnd (iCode * ic, iCode * ifx)
            emitcode ("setb", "c");
          while (sizer--)
            {
-             MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
-             emitcode ("anl", "a,%s",
-                       aopGet (AOP (left), offset, FALSE, FALSE));
+             if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
+               emitcode ("anl", "a,%s",
+                         aopGet (AOP (right), offset, FALSE, FALSE));
+             } else {
+               if (AOP_TYPE(left)==AOP_ACC) {
+                 emitcode("mov", "b,a");
+                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
+                 emitcode("anl", "a,b");
+               }else {
+                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
+                 emitcode ("anl", "a,%s",
+                           aopGet (AOP (left), offset, FALSE, FALSE));
+               }
+             }
              emitcode ("jnz", "%05d$", tlbl->key + 100);
              offset++;
            }
@@ -4735,9 +4878,14 @@ genOr (iCode * ic, iCode * ifx)
            emitcode ("setb", "c");
          while (sizer--)
            {
-             MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
-             emitcode ("orl", "a,%s",
-                       aopGet (AOP (left), offset, FALSE, FALSE));
+             if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
+               emitcode ("orl", "a,%s",
+                         aopGet (AOP (right), offset, FALSE, FALSE));
+             } else {
+               MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
+               emitcode ("orl", "a,%s",
+                         aopGet (AOP (left), offset, FALSE, FALSE));
+             }
              emitcode ("jnz", "%05d$", tlbl->key + 100);
              offset++;
            }
@@ -4987,9 +5135,14 @@ genXor (iCode * ic, iCode * ifx)
                }
              else
                {
-                 MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
-                 emitcode ("xrl", "a,%s",
-                           aopGet (AOP (left), offset, FALSE, FALSE));
+                 if (AOP_TYPE(right)==AOP_REG && AOP_TYPE(left)==AOP_ACC) {
+                   emitcode ("xrl", "a,%s",
+                             aopGet (AOP (right), offset, FALSE, FALSE));
+                 } else {
+                   MOVA (aopGet (AOP (right), offset, FALSE, FALSE));
+                   emitcode ("xrl", "a,%s",
+                             aopGet (AOP (left), offset, FALSE, FALSE));
+                 }
                }
              emitcode ("jnz", "%05d$", tlbl->key + 100);
              offset++;
@@ -5044,11 +5197,11 @@ release:
 static void
 genInline (iCode * ic)
 {
-  char buffer[MAX_INLINEASM];
-  char *bp = buffer;
-  char *bp1 = buffer;
+  char *buffer, *bp, *bp1;
 
   _G.inLine += (!options.asmpeep);
+
+  buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
   strcpy (buffer, IC_INLINE (ic));
 
   /* emit each line as a code */
@@ -6025,13 +6178,15 @@ genLeftShiftLiteral (operand * left,
          break;
 
        case 2:
-       case 3:
          genlshTwo (result, left, shCount);
          break;
 
        case 4:
          genlshFour (result, left, shCount);
          break;
+       default:
+         fprintf(stderr, "*** ack! mystery literal shift!\n");
+         break;
        }
     }
   freeAsmop (left, NULL, ic, TRUE);
@@ -6185,22 +6340,48 @@ static void
 shiftRLong (operand * left, int offl,
            operand * result, int sign)
 {
-  if (!sign)
-    emitcode ("clr", "c");
+  int isSameRegs=sameRegs(AOP(left),AOP(result));
+
+  if (isSameRegs && offl>1) {
+    // we are in big trouble, but this shouldn't happen
+    werror(E_INTERNAL_ERROR, __FILE__, __LINE__);
+  }
+
   MOVA (aopGet (AOP (left), MSB32, FALSE, FALSE));
-  if (sign)
+  
+  if (offl==MSB16) {
+    // shift is > 8
+    if (sign) {
+      emitcode ("rlc", "a");
+      emitcode ("subb", "a,acc");
+      emitcode ("xch", "a,%s", aopGet(AOP(left), MSB32, FALSE, FALSE));
+    } else {
+      aopPut (AOP(result), zero, MSB32);
+    }
+  }
+
+  if (!sign) {
+    emitcode ("clr", "c");
+  } else {
     emitcode ("mov", "c,acc.7");
-  emitcode ("rrc", "a");
-  aopPut (AOP (result), "a", MSB32 - offl);
-  if (offl == MSB16)
-    /* add sign of "a" */
-    addSign (result, MSB32, sign);
+  }
 
-  MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
   emitcode ("rrc", "a");
-  aopPut (AOP (result), "a", MSB24 - offl);
 
-  MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
+  if (isSameRegs && offl==MSB16) {
+    emitcode ("xch", "a,%s",aopGet (AOP (left), MSB24, FALSE, FALSE));
+  } else {
+    aopPut (AOP (result), "a", MSB32);
+    MOVA (aopGet (AOP (left), MSB24, FALSE, FALSE));
+  }
+
+  emitcode ("rrc", "a");
+  if (isSameRegs && offl==1) {
+    emitcode ("xch", "a,%s",aopGet (AOP (left), MSB16, FALSE, FALSE));
+  } else {
+    aopPut (AOP (result), "a", MSB24);
+    MOVA (aopGet (AOP (left), MSB16, FALSE, FALSE));
+  }
   emitcode ("rrc", "a");
   aopPut (AOP (result), "a", MSB16 - offl);
 
@@ -7847,8 +8028,7 @@ genAssign (iCode * ic)
   aopOp (right, ic, FALSE);
 
   /* special case both in far space */
-  if ((AOP_TYPE (right) == AOP_DPTR ||
-       AOP_TYPE (right) == AOP_DPTR2) &&
+  if (AOP_TYPE (right) == AOP_DPTR &&
       IS_TRUE_SYMOP (result) &&
       isOperandInFarSpace (result))
     {
@@ -7972,6 +8152,8 @@ genCast (iCode * ic)
   operand *right = IC_RIGHT (ic);
   int size, offset;
 
+  D(emitcode(";", "genCast"));
+
   /* if they are equivalent then do nothing */
   if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
     return;
@@ -8047,8 +8229,13 @@ genCast (iCode * ic)
            p_type = DCL_TYPE (type);
          else
            {
-             /* we have to go by the storage class */
-             p_type = PTR_TYPE (SPEC_OCLS (etype));
+             if (SPEC_SCLS(etype)==S_REGISTER) {
+               // let's assume it is a generic pointer
+               p_type=GPOINTER;
+             } else {
+               /* we have to go by the storage class */
+               p_type = PTR_TYPE (SPEC_OCLS (etype));
+             }
            }
 
          /* the first two bytes are known */
@@ -8074,7 +8261,10 @@ genCast (iCode * ic)
            case CPOINTER:
              l = "#0x02";
              break;
-           case PPOINTER:
+           case GPOINTER:
+             l = "0x03";
+             break;
+           case PPOINTER: // what the fck is this?
              l = "#0x03";
              break;
 
@@ -8117,7 +8307,7 @@ genCast (iCode * ic)
   /* now depending on the sign of the source && destination */
   size = AOP_SIZE (result) - AOP_SIZE (right);
   /* if unsigned or not an integral type */
-  if (SPEC_USIGN (rtype) || !IS_SPEC (rtype))
+  if (SPEC_USIGN (rtype) || !IS_SPEC (rtype) || AOP_TYPE(right)==AOP_CRY)
     {
       while (size--)
        aopPut (AOP (result), zero, offset++);
@@ -8177,7 +8367,30 @@ genDjnz (iCode * ic, iCode * ifx)
 
   aopOp (IC_RESULT (ic), ic, FALSE);
 
-  if (IS_AOP_PREG (IC_RESULT (ic)))
+  if (AOP_NEEDSACC(IC_RESULT(ic)))
+  {
+      /* If the result is accessed indirectly via
+       * the accumulator, we must explicitly write
+       * it back after the decrement.
+       */
+      char *rByte = aopGet(AOP(IC_RESULT(ic)), 0, FALSE, FALSE);
+      
+      if (strcmp(rByte, "a"))
+      {
+           /* Something is hopelessly wrong */
+           fprintf(stderr, "*** warning: internal error at %s:%d\n",
+                  __FILE__, __LINE__);
+           /* We can just give up; the generated code will be inefficient,
+            * but what the hey.
+            */
+           freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+           return 0;
+      }
+      emitcode ("dec", "%s", rByte);
+      aopPut(AOP(IC_RESULT(ic)), rByte, 0);
+      emitcode ("jnz", "%05d$", lbl->key + 100);
+  }
+  else if (IS_AOP_PREG (IC_RESULT (ic)))
     {
       emitcode ("dec", "%s",
                aopGet (AOP (IC_RESULT (ic)), 0, FALSE, FALSE));
@@ -8254,8 +8467,8 @@ gen51Code (iCode * lic)
   if (allocInfo)
     printAllocInfo (currFunc, codeOutFile);
   /* if debug information required */
-/*     if (options.debug && currFunc) { */
-  if (currFunc)
+  /*     if (options.debug && currFunc) { */
+  if (options.debug && currFunc)
     {
       cdbSymbol (currFunc, cdbFile, FALSE, TRUE);
       _G.debugLine = 1;