* sim/ucsim/cmd.src/cmdutil.cc: NUL device is detected as CG_FILE type
[fw/sdcc] / src / hc08 / gen.c
index 5b755ac39e3e95cfceb7d1533065244707cf4845..8c93b380c85b1083471488e31910cd8b5eb77e86 100644 (file)
 
 -------------------------------------------------------------------------*/
 
-#define D(x)
-//#define D(x) x
+/* Use the D macro for basic (unobtrusive) debugging messages */
+//#define D(x)
+#define D(x) x
+/* Use the DD macro for detailed debugging messages */
+#define DD(x)
+//#define DD(x) x
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -47,6 +51,7 @@ char *aopLiteralLong (value * val, int offset, int size);
 extern int allocInfo;
 static int pushReg (regs *reg, bool freereg);
 static void pullReg (regs *reg);
+static void transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs);
 
 static char *zero = "#0x00";
 static char *one = "#0x01";
@@ -78,7 +83,7 @@ static asmop *hc08_aop_pass[4];
 
 extern int hc08_ptrRegReq;
 extern int hc08_nRegs;
-extern FILE *codeOutFile;
+extern struct dbuf_s *codeOutBuf;
 //static void saveRBank (int, iCode *, bool);
 static bool operandsEqu (operand * op1, operand * op2);
 static void loadRegFromConst (regs *reg, char *c);
@@ -162,7 +167,7 @@ emitcode (char *inst, char *fmt,...)
   else
     vsprintf (lb, fmt, ap);
 
-  while (isspace (*lbp))
+  while (isspace ((unsigned char)*lbp))
     lbp++;
 
   if (lbp && *lbp)
@@ -172,6 +177,7 @@ emitcode (char *inst, char *fmt,...)
   lineCurr->isInline = _G.inLine;
   lineCurr->isDebug = _G.debugLine;
   lineCurr->ic = _G.current_iCode;
+  lineCurr->isComment = (*lbp==';');
 
   //printf("%s\n", lb);
   va_end (ap);
@@ -187,6 +193,7 @@ static void
 emitLabel (symbol *tlbl)
 {
   emitcode ("", "%05d$:", (tlbl->key +100));
+  lineCurr->isLabel = 1;
 }
 
 /*-----------------------------------------------------------------*/
@@ -226,7 +233,7 @@ transferRegReg (regs *sreg, regs *dreg, bool freesrc)
       return;
     }
 
-  D(emitcode ("", "; transferRegReg(%s,%s)",
+  DD(emitcode ("", "; transferRegReg(%s,%s)",
             sreg->name, dreg->name));
 
   srcidx = sreg->rIdx;
@@ -410,18 +417,18 @@ pullReg (regs *reg)
        updateCFA();
         break;
       case HX_IDX:
-        emitcode ("pulx", "");
+        emitcode ("pulh", "");
         _G.stackPushes--;
        updateCFA();
-        emitcode ("pulh", "");
+        emitcode ("pulx", "");
         _G.stackPushes--;
        updateCFA();
         break;
       case XA_IDX:
-        emitcode ("pula", "");
+        emitcode ("pulx", "");
         _G.stackPushes--;
        updateCFA();
-        emitcode ("pulx", "");
+        emitcode ("pula", "");
         _G.stackPushes--;
        updateCFA();
         break;
@@ -597,7 +604,7 @@ loadRegFromAop (regs *reg, asmop *aop, int loffset)
     printf(" reg missing operand link\n");
 #endif
 
-  D(emitcode ("", ";     loadRegFromAop (%s, %s, %d)",
+  DD(emitcode ("", ";     loadRegFromAop (%s, %s, %d)",
             reg->name, aopName (aop), loffset));
        
   /* If operand is volatile, we cannot optimize. */
@@ -612,7 +619,7 @@ loadRegFromAop (regs *reg, asmop *aop, int loffset)
       && (reg->aopofs == loffset))
     {
       hc08_useReg(reg);
-      D(emitcode ("","; already had correct value for %s", reg->name));
+      DD(emitcode ("","; already had correct value for %s", reg->name));
       return;
     }
 
@@ -622,7 +629,7 @@ loadRegFromAop (regs *reg, asmop *aop, int loffset)
       && operandsEqu(hc08_reg_h->aop->op,aop->op)
       && (hc08_reg_h->aopofs == loffset))
     {
-      D(emitcode ("","; found correct value for %s in h", reg->name));
+      DD(emitcode ("","; found correct value for %s in h", reg->name));
       transferRegReg (hc08_reg_h, reg, FALSE);
       hc08_useReg (reg);
       return;
@@ -633,7 +640,7 @@ loadRegFromAop (regs *reg, asmop *aop, int loffset)
       && operandsEqu(hc08_reg_x->aop->op,aop->op)
       && (hc08_reg_x->aopofs == loffset))
     {
-      D(emitcode ("","; found correct value for %s in x", reg->name));
+      DD(emitcode ("","; found correct value for %s in x", reg->name));
       transferRegReg (hc08_reg_x, reg, FALSE);
       hc08_useReg (reg);
       return;
@@ -643,7 +650,7 @@ loadRegFromAop (regs *reg, asmop *aop, int loffset)
       && operandsEqu(hc08_reg_a->aop->op,aop->op)
       && (hc08_reg_a->aopofs == loffset))
     {
-      D(emitcode ("","; found correct value for %s in a", reg->name));
+      DD(emitcode ("","; found correct value for %s in a", reg->name));
       transferRegReg (hc08_reg_a, reg, FALSE);
       hc08_useReg (reg);
       return;
@@ -662,7 +669,13 @@ forceload:
               emitcode ("clra", ""); /* TODO: handle sign extension */
           }
         else
-          emitcode ("lda","%s", aopAdrStr (aop, loffset, FALSE));
+          {
+            char * l = aopAdrStr (aop, loffset, FALSE);
+            if (!strcmp (l, zero))
+              emitcode ("clra", "");
+            else
+              emitcode ("lda", "%s", l);
+          }
         break;
       case X_IDX:
         if (aop->type == AOP_REG)
@@ -673,9 +686,23 @@ forceload:
               emitcode ("clrx", ""); /* TODO: handle sign extension */
           }
         else
-          emitcode ("ldx","%s", aopAdrStr (aop, loffset, FALSE));
+          {
+            char * l = aopAdrStr (aop, loffset, FALSE);
+            if (!strcmp (l, zero))
+              emitcode ("clrx", "");
+            else
+              emitcode ("ldx", "%s", l);
+          }
         break;
       case H_IDX:
+        {
+          char * l = aopAdrStr (aop, loffset, FALSE);
+          if (!strcmp (l, zero))
+            {
+              emitcode ("clrh", "");
+              break;
+            }
+        }
         if (hc08_reg_a->isFree)
           {
             loadRegFromAop (hc08_reg_a, aop, loffset);
@@ -747,25 +774,51 @@ forceload:
 /*--------------------------------------------------------------------------*/
 /* forceStackedAop - Reserve space on the stack for asmop aop; when         */
 /*                   freeAsmop is called with aop, the stacked data will    */
-/*                   be copied to the original aop location and             */
+/*                   be copied to the original aop location.                */
 /*--------------------------------------------------------------------------*/
 static asmop *
-forceStackedAop (asmop *aop)
+forceStackedAop (asmop *aop, bool copyOrig)
 {
+  regs *reg;
   int loffset;
   asmop *newaop = newAsmop (aop->type);
   memcpy (newaop, aop, sizeof(*newaop));
   
-  D(emitcode("", "; forcedStackAop %s", aopName(aop)));
+  DD(emitcode("", "; forcedStackAop %s", aopName(aop)));
+
+  if (copyOrig && hc08_reg_a->isFree)
+    reg = hc08_reg_a;
+  else if (copyOrig && hc08_reg_x->isFree)
+    reg = hc08_reg_x;
+  else
+    reg = NULL;
   for (loffset=0; loffset < newaop->size; loffset++)
     {
       asmop *aopsof = newAsmop (AOP_SOF);
       aopsof->size = 1;
-      aopsof->aopu.aop_stk = pushReg (hc08_reg_a, FALSE);
+      if (copyOrig && reg)
+        {
+          loadRegFromAop (reg, aop, loffset);
+          aopsof->aopu.aop_stk = pushReg (reg, FALSE);
+        }
+      else
+        {
+          aopsof->aopu.aop_stk = pushReg (hc08_reg_a, FALSE);
+        }
       aopsof->op = aop->op;
       newaop->stk_aop[loffset] = aopsof;
     }
   newaop->stacked = 1;
+
+  if (!reg && copyOrig)
+    {
+      for (loffset=0; loffset < newaop->size; loffset++)
+        {
+         transferAopAop (aop, loffset, newaop, loffset);
+       }
+    }
+
   return newaop;
 }
 
@@ -782,7 +835,7 @@ storeRegToAop (regs *reg, asmop *aop, int loffset)
   int otheridx;
   #endif
 
-  D(emitcode ("", ";     storeRegToAop (%s, %s, %d), stacked=%d, isaddr=%d",
+  DD(emitcode ("", ";     storeRegToAop (%s, %s, %d), stacked=%d, isaddr=%d",
             reg->name, aopName (aop), loffset, aop->stacked, aop->isaddr));
 
   if ((reg->rIdx == HX_IDX) && aop->stacked
@@ -818,7 +871,10 @@ storeRegToAop (regs *reg, asmop *aop, int loffset)
 
   if (aop->type == AOP_DUMMY)
     return;
-    
+
+  if (aop->type == AOP_CRY) /* This can only happen if IFX was optimized */
+    return;                 /* away, so just toss the result */
+
   switch (regidx)
     {
       case A_IDX:
@@ -899,19 +955,19 @@ storeRegToAop (regs *reg, asmop *aop, int loffset)
                 && operandsEqu(otherreg->aop->op,aop->op)
                 && (otherreg->aopofs == loffset))
               {
-                D(emitcode("","; marking %s stale", otherreg->name));
+                DD(emitcode("","; marking %s stale", otherreg->name));
                 otherreg->aop=NULL;
               }
           }
       if ((!hc08_reg_x->aop || !hc08_reg_h->aop) && hc08_reg_hx->aop)
         {
           hc08_reg_hx->aop = NULL;
-          D(emitcode("","; marking hx stale"));
+          DD(emitcode("","; marking hx stale"));
         }
       if ((!hc08_reg_x->aop || !hc08_reg_a->aop) && hc08_reg_xa->aop)
         {
           hc08_reg_xa->aop = NULL;
-          D(emitcode("","; marking xa stale"));
+          DD(emitcode("","; marking xa stale"));
         }
     
       reg->aop = aop;
@@ -1110,7 +1166,7 @@ storeRegToFullAop (regs *reg, asmop *aop, bool isSigned)
 
 /*--------------------------------------------------------------------------*/
 /* transferAopAop - Transfer the value at logical offset srcofs of asmop    */
-/*                  srcaop to logical offset dstofs of asmop dstofs.        */
+/*                  srcaop to logical offset dstofs of asmop dstaop.        */
 /*--------------------------------------------------------------------------*/
 static void
 transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs)
@@ -1120,6 +1176,13 @@ transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs)
   int regIdx;
   bool keepreg = FALSE;
 
+  /* ignore transfers at the same byte, unless its volatile */
+  if (srcaop->op && !isOperandVolatile (srcaop->op, FALSE)
+      && dstaop->op && !isOperandVolatile (dstaop->op, FALSE)
+      && operandsEqu(srcaop->op, dstaop->op) && srcofs == dstofs
+      && dstaop->type == srcaop->type)
+    return;
+      
   if (srcaop->stacked && srcaop->stk_aop[srcofs])
     {
       transferAopAop (srcaop->stk_aop[srcofs], 0, dstaop, dstofs);
@@ -1132,10 +1195,10 @@ transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs)
       return;
     }
 
-//  D(emitcode ("", "; transferAopAop (%s, %d, %s, %d)",
+//  DD(emitcode ("", "; transferAopAop (%s, %d, %s, %d)",
 //            aopName (srcaop), srcofs, aopName (dstaop), dstofs));
-//  D(emitcode ("", "; srcaop->type = %d", srcaop->type));
-//  D(emitcode ("", "; dstaop->type = %d", dstaop->type));
+//  DD(emitcode ("", "; srcaop->type = %d", srcaop->type));
+//  DD(emitcode ("", "; dstaop->type = %d", dstaop->type));
   
   if (dstofs >= dstaop->size)
     return;
@@ -1143,6 +1206,21 @@ transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs)
   if ((dstaop->type == AOP_DIR)
       && ((srcaop->type == AOP_DIR) || (srcaop->type == AOP_LIT)) )
     {
+      if (srcaop->type == AOP_LIT)
+        {
+          unsigned long lit;
+          unsigned long bytemask;
+          
+          lit = (unsigned long) floatFromVal (srcaop->aopu.aop_lit);
+          bytemask = (lit >> (srcofs*8)) & 0xff;
+          
+          if (bytemask == 0)
+            {
+              emitcode ("clr", "%s", aopAdrStr(dstaop, dstofs, FALSE));
+              return;
+            }
+        }
+
       emitcode("mov", "%s,%s", aopAdrStr(srcaop, srcofs, FALSE),
                aopAdrStr(dstaop, dstofs, FALSE));
       return;
@@ -1275,7 +1353,7 @@ rmwWithReg (char *rmwop, regs *reg)
 /*--------------------------------------------------------------------------*/
 /* accopWithAop - Emit read/modify/write instruction rmwop with the byte at */
 /*                logical offset loffset of asmop aop.                      */
-/*                Supports: com, dec, inc, lsl, lsr, neg, rol, ror          */
+/*                Supports: com, dec, inc, lsl, lsr, neg, rol, ror, tst     */
 /*--------------------------------------------------------------------------*/
 static void
 rmwWithAop (char *rmwop, asmop *aop, int loffset)
@@ -1295,9 +1373,10 @@ rmwWithAop (char *rmwop, asmop *aop, int loffset)
         break;
       case AOP_EXT:
         needpula = pushRegIfUsed (hc08_reg_a);
-       loadRegFromAop (hc08_reg_a, aop, loffset);
+        loadRegFromAop (hc08_reg_a, aop, loffset);
         rmwWithReg (rmwop, hc08_reg_a);
-       storeRegToAop (hc08_reg_a, aop, loffset);
+        if (strcmp ("tst", rmwop))
+          storeRegToAop (hc08_reg_a, aop, loffset);
         pullOrFreeReg (hc08_reg_a, needpula);
         break;
       case AOP_DUMMY:
@@ -1755,14 +1834,22 @@ aopOp (operand * op, iCode * ic, bool result)
       /* else spill location  */
       if (sym->usl.spillLoc)
         {
+          asmop *oldAsmOp = NULL;
+
           if (sym->usl.spillLoc->aop
               && sym->usl.spillLoc->aop->size != getSize (sym->type))
             {
              /* force a new aop if sizes differ */
+              oldAsmOp = sym->usl.spillLoc->aop;
              sym->usl.spillLoc->aop = NULL;
              //printf ("forcing new aop\n");
             }
          sym->aop = op->aop = aop = aopForSym (ic, sym->usl.spillLoc, result);
+          if (sym->usl.spillLoc->aop->size != getSize (sym->type))
+            {
+              /* Don't reuse the new aop, go with the last one */
+              sym->usl.spillLoc->aop = oldAsmOp;
+            }
          aop->size = getSize (sym->type);
          aop->op = op;
          aop->isaddr = op->isaddr;
@@ -1814,7 +1901,7 @@ freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
       int stackAdjust;
       int loffset;
 
-      D(emitcode ("","; freeAsmop restoring stacked %s", aopName(aop)));
+      DD(emitcode ("","; freeAsmop restoring stacked %s", aopName(aop)));
       aop->stacked = 0;
       stackAdjust = 0;
       for (loffset=0; loffset<aop->size; loffset++)
@@ -1856,7 +1943,7 @@ aopDerefAop (asmop *aop)
   sym_link *type, *etype;
   int p_type;
   
-  D(emitcode ("", ";     aopDerefAop(%s)", aopName(aop)));
+  DD(emitcode ("", ";     aopDerefAop(%s)", aopName(aop)));
   if (aop->op)
     {
     
@@ -2042,67 +2129,6 @@ getDataSize (operand * op)
   return size;
 }
 
-/*-----------------------------------------------------------------*/
-/* outAcc - output Acc                                             */
-/*-----------------------------------------------------------------*/
-static void
-outAcc (operand * result)
-{
-  int size, offset;
-  size = getDataSize (result);
-  if (size)
-    {
-      storeRegToAop (hc08_reg_a, AOP (result), 0);
-      size--;
-      offset = 1;
-      /* unsigned or positive */
-      while (size--)
-       {
-         storeConstToAop (zero, AOP (result), offset++);
-       }
-    }
-}
-
-/*-----------------------------------------------------------------*/
-/* outBitC - output a bit C                                        */
-/*-----------------------------------------------------------------*/
-static void
-outBitC (operand * result)
-{
-
-#if 0
-  /* if the result is bit */
-  if (AOP_TYPE (result) == AOP_CRY)
-    aopPut (AOP (result), "c", 0);
-  else
-#endif
-    {
-      emitcode ("clra", "");
-      emitcode ("rola", "");
-      outAcc (result);
-    }
-}
-
-/*-----------------------------------------------------------------*/
-/* outBitNV - output a bit N^V                                     */
-/*-----------------------------------------------------------------*/
-static void
-outBitNV (operand * result)
-{
-  symbol *tlbl, *tlbl1;
-
-  tlbl = newiTempLabel (NULL);
-  tlbl1 = newiTempLabel (NULL);
-
-  emitBranch ("blt", tlbl);
-  loadRegFromConst (hc08_reg_a, zero);
-  emitBranch ("bra", tlbl1);
-  emitLabel (tlbl);
-  loadRegFromConst (hc08_reg_a, one);
-  emitLabel (tlbl1);
-  outAcc (result);
-}
-
 
 /*-----------------------------------------------------------------*/
 /* asmopToBool - Emit code to convert an asmop to a boolean.       */
@@ -2162,7 +2188,7 @@ asmopToBool (asmop *aop, bool resultInA)
             emitcode ("tsta", "");
             emitcode ("bne", "%05d$", (tlbl->key + 100));
             emitcode ("tstx", "");
-            emitcode ("", "%05d$:", (tlbl->key + 100));
+            emitLabel (tlbl);
           }
         else
           {
@@ -2187,6 +2213,14 @@ asmopToBool (asmop *aop, bool resultInA)
             flagsonly = FALSE;
           }
         break;
+      case AOP_LIT:
+        /* Higher levels should optimize this case away but let's be safe */
+        if ((unsigned long) floatFromVal (aop->aopu.aop_lit))
+          loadRegFromConst (hc08_reg_a, one);
+        else
+          loadRegFromConst (hc08_reg_a, zero);
+        hc08_freeReg(hc08_reg_a);
+        break;
       default:
         if (size==1)
           {
@@ -2215,7 +2249,7 @@ asmopToBool (asmop *aop, bool resultInA)
                 emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
                 emitcode ("bne", "%05d$", (tlbl->key + 100));
                 emitcode ("tst", "%s", aopAdrStr (aop, 1, FALSE));
-                emitcode ("", "%05d$:", (tlbl->key + 100));
+                emitLabel (tlbl);
                 break;
               }
           }
@@ -2307,6 +2341,7 @@ genCpl (iCode * ic)
       hc08_useReg (reg);
       storeRegToAop (reg, AOP (IC_RESULT (ic)), offset);
       hc08_freeReg (reg);
+      offset++;
     }
 
   /* release the aops */
@@ -2391,7 +2426,7 @@ genUminus (iCode * ic)
   else
     {
       if (IS_AOP_XA (AOP (IC_RESULT (ic))))
-        result = forceStackedAop (AOP (IC_RESULT (ic)));
+        result = forceStackedAop (AOP (IC_RESULT (ic)), FALSE);
       else
         result = AOP (IC_RESULT (ic));
        
@@ -2621,13 +2656,13 @@ static void genSend(set *sendSet)
 {
     iCode *sic;
 
-    for (sic = setFirstItem (_G.sendSet); sic;
-        sic = setNextItem (_G.sendSet)) {
+    for (sic = setFirstItem (sendSet); sic;
+         sic = setNextItem (sendSet)) {
          int size, offset = 0;
          aopOp (IC_LEFT (sic), sic, FALSE);
          size = AOP_SIZE (IC_LEFT (sic));
 
-         if (sic->argreg) {
+          if (sic->argreg) {
              offset = size-1;
              while (size--) {
                  transferAopAop( AOP (IC_LEFT (sic)), offset,
@@ -2652,7 +2687,7 @@ genCall (iCode * ic)
   D(emitcode(";     genCall",""));
 
   dtype = operandType (IC_LEFT (ic));
-  /* if send set is not empty the assign */
+  /* if send set is not empty then assign */
   if (_G.sendSet)
     {
        if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
@@ -2732,6 +2767,8 @@ genPcall (iCode * ic)
   emitBranch ("bsr", tlbl);
   emitBranch ("bra", rlbl);
   emitLabel (tlbl);
+  _G.stackPushes += 2; /* account for the bsr return address now on stack */
+  updateCFA();
 
   /* Push the function's address */
   aopOp (IC_LEFT (ic), ic, FALSE);
@@ -2750,6 +2787,8 @@ genPcall (iCode * ic)
   emitcode ("rts", "");
 
   emitLabel (rlbl);
+  _G.stackPushes -= 4; /* account for rts here & in called function */
+  updateCFA();
 
 
   /* if we need assign a result value */
@@ -2800,12 +2839,6 @@ resultRemat (iCode * ic)
   return 0;
 }
 
-#if defined(__BORLANDC__) || defined(_MSC_VER)
-#define STRCASECMP stricmp
-#else
-#define STRCASECMP strcasecmp
-#endif
-
 /*-----------------------------------------------------------------*/
 /* inExcludeList - return 1 if the string is in exclude Reg list   */
 /*-----------------------------------------------------------------*/
@@ -2833,18 +2866,21 @@ inExcludeList (char *s)
 static void
 genFunction (iCode * ic)
 {
-  symbol *sym;
+  symbol *sym = OP_SYMBOL (IC_LEFT (ic));
   sym_link *ftype;
-  int calleesaves_saved_register = -1;
+  iCode *ric = (ic->next && ic->next->op == RECEIVE) ? ic->next : NULL;
+  int stackAdjust = sym->stack;
+  int accIsFree = sym->recvSize == 0;
 
   _G.nRegsSaved = 0;
   _G.stackPushes = 0;
   /* create the function header */
   emitcode (";", "-----------------------------------------");
-  emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
+  emitcode (";", " function %s", sym->name);
   emitcode (";", "-----------------------------------------");
 
   emitcode ("", "%s:", sym->rname);
+  lineCurr->isLabel = 1;
   ftype = operandType (IC_LEFT (ic));
   
   _G.stackOfs = 0;
@@ -2857,8 +2893,6 @@ genFunction (iCode * ic)
       return;
   }
 
-
-
   /* if this is an interrupt service routine then
      save h  */
   if (IFFUNC_ISISR (sym->type))
@@ -2867,47 +2901,52 @@ genFunction (iCode * ic)
       if (!inExcludeList ("h"))
         pushReg (hc08_reg_h, FALSE);
     }
-  else
+
+  /* For some cases it is worthwhile to perform a RECEIVE iCode */
+  /* before setting up the stack frame completely. */
+  while (ric && ric->next && ric->next->op == RECEIVE)
+    ric = ric->next;
+  while (ric && IC_RESULT (ric))
     {
-      /* if callee-save to be used for this function
-         then save the registers being used in this function */
-      if (IFFUNC_CALLEESAVES(sym->type))
-       {
-         int i;
+      symbol * rsym = OP_SYMBOL (IC_RESULT (ric));
+      int rsymSize = rsym ? getSize(rsym->type) : 0;
 
-         /* if any registers used */
-         if (sym->regsUsed)
-           {
-             /* save the registers used */
-             for (i = 0; i < sym->regsUsed->size; i++)
-               {
-                 if (bitVectBitValue (sym->regsUsed, i))
-                   {
-                     /* remember one saved register for later usage */
-                     if (calleesaves_saved_register < 0)
-                       calleesaves_saved_register = i;
-                      pushReg (hc08_regWithIdx (i), FALSE);
-                     _G.nRegsSaved++;
-                   }
-               }
-           }
-       }
-    }
+      if (rsym->isitmp)
+        {
+          if (rsym && rsym->regType == REG_CND)
+            rsym = NULL;
+          if (rsym && (rsym->accuse || rsym->ruonly))
+            rsym = NULL;
+          if (rsym && (rsym->isspilt || rsym->nRegs == 0) && rsym->usl.spillLoc)
+            rsym = rsym->usl.spillLoc;
+        }
 
-  if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
-    {
+      /* If the RECEIVE operand immediately spills to the first entry on the  */
+      /* stack, we can push it directly rather than use an sp relative store. */
+      if (rsym && rsym->onStack && rsym->stack == -_G.stackPushes-rsymSize)
+        {
+          int ofs;
 
+          _G.current_iCode = ric;
+          D(emitcode (";     genReceive",""));
+          for (ofs=0; ofs < rsymSize; ofs++)
+            {
+              regs * reg = hc08_aop_pass[ofs+(ric->argreg-1)]->aopu.aop_reg[0];
+              pushReg (reg, TRUE);
+              if (reg->rIdx == A_IDX)
+                accIsFree = 1;
+              stackAdjust--;
+            }
+          _G.current_iCode = ic;
+          ric->generated = 1;
+        }
+      ric = (ric->prev && ric->prev->op == RECEIVE) ? ric->prev : NULL;
     }
 
   /* adjust the stack for the function */
-  if (sym->stack)
+  if (stackAdjust)
     {
-
-      int i = sym->stack;
-//      if (i > 256)
-//     werror (W_STACK_OVERFLOW, sym->name);
-
-      adjustStack (-i);
+      adjustStack (-stackAdjust);
     }
   _G.stackOfs = sym->stack;
   _G.stackPushes = 0;
@@ -2915,7 +2954,7 @@ genFunction (iCode * ic)
   /* if critical function then turn interrupts off */
   if (IFFUNC_ISCRITICAL (ftype))
     {
-      if (IFFUNC_ARGS (ftype))
+      if (!accIsFree)
         {
           /* Function was passed parameters, so make sure A is preserved */
           pushReg (hc08_reg_a, FALSE);
@@ -3122,7 +3161,7 @@ genLabel (iCode * ic)
          
   debugFile->writeLabel(IC_LABEL (ic), ic);
 
-  emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
+  emitLabel (IC_LABEL (ic));
 
 }
 
@@ -3182,7 +3221,7 @@ genPlusIncr (iCode * ic)
   bool needpulh;
   bool needpula;
   unsigned int size = getDataSize (IC_RESULT (ic));
-  int offset;
+  unsigned int offset;
   symbol *tlbl = NULL;
   
   left = IC_LEFT (ic);
@@ -3196,7 +3235,7 @@ genPlusIncr (iCode * ic)
 
   icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
 
-  D(emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left))));
+  DD(emitcode ("", "; IS_AOP_HX = %d", IS_AOP_HX (AOP (left))));
   
   if ((IS_AOP_HX (AOP (left)) ||
        ( (AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR) )
@@ -3222,7 +3261,7 @@ genPlusIncr (iCode * ic)
       return TRUE;
     }
 
-  D(emitcode ("", "; icount = %d, sameRegs=%d", icount, 
+  DD(emitcode ("", "; icount = %d, sameRegs=%d", icount, 
             sameRegs (AOP (left), AOP (result))));
   
   if ((icount > 255) || (icount<0))
@@ -3307,9 +3346,9 @@ genPlus (iCode * ic)
   if (genPlusIncr (ic) == TRUE)
     goto release;
 
-  D(emitcode("",";  left size = %d", getDataSize (IC_LEFT(ic))));
-  D(emitcode("",";  right size = %d", getDataSize (IC_RIGHT(ic))));
-  D(emitcode("",";  result size = %d", getDataSize (IC_RESULT(ic))));
+  DD(emitcode("",";  left size = %d", getDataSize (IC_LEFT(ic))));
+  DD(emitcode("",";  right size = %d", getDataSize (IC_RIGHT(ic))));
+  DD(emitcode("",";  result size = %d", getDataSize (IC_RESULT(ic))));
   
   size = getDataSize (IC_RESULT (ic));
 
@@ -3337,7 +3376,7 @@ release:
 }
 
 /*-----------------------------------------------------------------*/
-/* genMinusDec :- does subtraction with deccrement if possible     */
+/* genMinusDec :- does subtraction with decrement if possible      */
 /*-----------------------------------------------------------------*/
 static bool
 genMinusDec (iCode * ic)
@@ -3452,13 +3491,22 @@ genMinus (iCode * ic)
 
   leftOp = AOP(IC_LEFT(ic));
   rightOp = AOP(IC_RIGHT(ic));
-
   sub = "sub";
   offset = 0;
+
+  if (IS_AOP_A (rightOp))
+    {
+      loadRegFromAop ( hc08_reg_a, rightOp, offset);
+      accopWithAop (sub, leftOp, offset);
+      accopWithMisc ("nega", "");
+      storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
+      goto release;
+    }
+
   while (size--)
     {
       loadRegFromAop ( hc08_reg_a, leftOp, offset);
-      accopWithAop(sub, rightOp, offset);
+      accopWithAop (sub, rightOp, offset);
       storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
       sub = "sbc";
     }
@@ -3486,6 +3534,7 @@ genMultOneByte (operand * left,
   symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
   int size=AOP_SIZE(result);
   bool negLiteral = FALSE;
+  bool lUnsigned, rUnsigned;
 
   D(emitcode (";     genMultOneByte",""));
 
@@ -3503,15 +3552,34 @@ genMultOneByte (operand * left,
       operand *t = right;
       right = left;
       left = t;
-      //D(emitcode (";", "swapped left and right"));
+    }
+  /* if an operand is in A, make sure it is on the left */
+  if (IS_AOP_A (AOP (right)))
+    {
+      operand *t = right;
+      right = left;
+      left = t;
     }
 
+  lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
+  rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
+  
+  /* lUnsigned  rUnsigned  negLiteral  negate     case */
+  /* false      false      false       odd        3    */
+  /* false      false      true        even       3    */
+  /* false      true       false       odd        3    */
+  /* false      true       true        impossible      */
+  /* true       false      false       odd        3    */
+  /* true       false      true        always     2    */
+  /* true       true       false       never      1    */
+  /* true       true       true        impossible      */
+
+  /* case 1 */
   if (size == 1
-      || (SPEC_USIGN(operandType(left)) &&
-         SPEC_USIGN(operandType(right))))
+      || (lUnsigned && rUnsigned))
     {
       // just an unsigned 8*8=8/16 multiply
-      //D(emitcode (";","unsigned"));
+      //DD(emitcode (";","unsigned"));
 
       loadRegFromAop (hc08_reg_a, AOP (left), 0);
       loadRegFromAop (hc08_reg_x, AOP (right), 0);
@@ -3525,22 +3593,55 @@ genMultOneByte (operand * left,
 
   // we have to do a signed multiply
 
+  /* case 2 */
+  /* left unsigned, right signed literal -- literal determines sign handling */
+  if (AOP_TYPE(right)==AOP_LIT && lUnsigned && !rUnsigned)
+    {
+      signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
+      
+      loadRegFromAop (hc08_reg_a, AOP (left), 0);
+      if (val < 0)
+        emitcode ("ldx", "#0x%02x", -val);
+      else
+        emitcode ("ldx", "#0x%02x", val);
+          
+      emitcode ("mul", "");
+          
+      if (val < 0)
+        {
+          rmwWithReg ("neg", hc08_reg_a);
+          tlbl4 = newiTempLabel (NULL);
+          emitBranch ("bcc", tlbl4);
+          rmwWithReg ("inc", hc08_reg_x);
+          emitLabel (tlbl4);
+          rmwWithReg ("neg", hc08_reg_x);
+        }
+      
+      hc08_dirtyReg (hc08_reg_xa, FALSE);
+      storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
+      hc08_freeReg (hc08_reg_xa);
+      return;
+    }
+  
 
-  //D(emitcode (";", "signed"));
+  /* case 3 */
   adjustStack (-1);
   emitcode ("clr", "1,s");
 
-  tlbl1 = newiTempLabel (NULL);
   loadRegFromAop (hc08_reg_a, AOP (left), 0);
-  emitcode ("tsta","");
-  emitBranch ("bpl", tlbl1);
-  emitcode ("inc", "1,s");
-  rmwWithReg ("neg", hc08_reg_a);
-  emitLabel (tlbl1);
+  if (!lUnsigned)
+    {
+      tlbl1 = newiTempLabel (NULL);
+      emitcode ("tsta","");
+      emitBranch ("bpl", tlbl1);
+      emitcode ("inc", "1,s");
+      rmwWithReg ("neg", hc08_reg_a);
+      emitLabel (tlbl1);
+    }
 
-  if (AOP_TYPE(right)==AOP_LIT)
+  if (AOP_TYPE(right)==AOP_LIT && !rUnsigned)
     {
-      signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
+      signed char val=(signed char)floatFromVal (AOP (right)->aopu.aop_lit);
       /* AND literal negative */
       if (val < 0) {
         emitcode ("ldx", "#0x%02x", -val);
@@ -3552,13 +3653,16 @@ genMultOneByte (operand * left,
     }
   else
     {
-      tlbl2 = newiTempLabel (NULL);
       loadRegFromAop (hc08_reg_x, AOP (right), 0);
-      emitcode ("tstx", "");
-      emitBranch ("bpl", tlbl2);
-      emitcode ("inc", "1,s");
-      rmwWithReg ("neg", hc08_reg_x);
-      emitLabel (tlbl2);
+      if (!rUnsigned)
+        {
+          tlbl2 = newiTempLabel (NULL);
+          emitcode ("tstx", "");
+          emitBranch ("bpl", tlbl2);
+          emitcode ("inc", "1,s");
+          rmwWithReg ("neg", hc08_reg_x);
+          emitLabel (tlbl2);
+        }
     }
 
   emitcode ("mul", "");
@@ -3566,20 +3670,17 @@ genMultOneByte (operand * left,
 
   tlbl3 = newiTempLabel (NULL);
   emitcode ("dec", "1,s");
-  if (negLiteral)
-    emitBranch ("bne", tlbl3);
-  else
+  if (!lUnsigned && !rUnsigned && negLiteral)
     emitBranch ("beq", tlbl3);
+  else
+    emitBranch ("bne", tlbl3);
 
   rmwWithReg ("neg", hc08_reg_a);
-  if (size>1)
-    {
-      tlbl4 = newiTempLabel (NULL);
-      emitBranch ("bcc", tlbl4);
-      rmwWithReg ("inc", hc08_reg_x);
-      emitLabel (tlbl4);
-      rmwWithReg ("neg", hc08_reg_x);
-    }
+  tlbl4 = newiTempLabel (NULL);
+  emitBranch ("bcc", tlbl4);
+  rmwWithReg ("inc", hc08_reg_x);
+  emitLabel (tlbl4);
+  rmwWithReg ("neg", hc08_reg_x);
 
   emitLabel (tlbl3);
   adjustStack (1);
@@ -3637,22 +3738,25 @@ genDivOneByte (operand * left,
               operand * right,
               operand * result)
 {
-  sym_link *opetype = operandType (result);
-//  char *l;
-  symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
+  symbol *tlbl1, *tlbl2, *tlbl3;
   int size;
-  bool negLiteral = FALSE;
+  int offset = 0;
+  bool lUnsigned, rUnsigned;
+  bool runtimeSign, compiletimeSign;
+  
+  lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
+  rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
 
   D(emitcode (";     genDivOneByte",""));
 
   size = AOP_SIZE (result);
   /* signed or unsigned */
-  if (SPEC_USIGN (opetype))
+  if (lUnsigned && rUnsigned)
     {
       /* unsigned is easy */
       loadRegFromAop (hc08_reg_h, AOP (left), 1);
-      loadRegFromAop (hc08_reg_a, AOP (left), 0);
       loadRegFromAop (hc08_reg_x, AOP (right), 0);
+      loadRegFromAop (hc08_reg_a, AOP (left), 0);
       emitcode ("div", "");
       hc08_dirtyReg (hc08_reg_a, FALSE);
       hc08_dirtyReg (hc08_reg_h, FALSE);
@@ -3665,66 +3769,146 @@ genDivOneByte (operand * left,
 
   /* signed is a little bit more difficult */
 
-  adjustStack (-1);
-  emitcode ("clr", "1,s");
+  /* now sign adjust for both left & right */
 
-  tlbl1 = newiTempLabel (NULL);
-  tlbl2 = newiTempLabel (NULL);
-  loadRegFromAop (hc08_reg_a, AOP (left), 0);
-  loadRegFromAop (hc08_reg_x, AOP (left), 1);
-  emitBranch ("bpl", tlbl1);
-  emitcode ("inc", "1,s");
-  rmwWithReg ("neg", hc08_reg_a);
-  emitBranch ("bcc", tlbl2);
-  rmwWithReg ("inc", hc08_reg_x);
-  emitLabel (tlbl2);
-  rmwWithReg ("neg", hc08_reg_x);
-  transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
-  emitLabel (tlbl1);
+  /* let's see what's needed: */
+  /* apply negative sign during runtime */
+  runtimeSign = FALSE;
+  /* negative sign from literals */
+  compiletimeSign = FALSE;
 
-  if (AOP_TYPE(right)==AOP_LIT)
+  if (!lUnsigned)
     {
-      signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
-      /* AND literal negative */
-      if (val < 0) {
+      if (AOP_TYPE(left) == AOP_LIT)
+        {
+          /* signed literal */
+          signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
+          if (val < 0)
+            compiletimeSign = TRUE;
+        }
+      else
+        /* signed but not literal */
+        runtimeSign = TRUE;
+    }
+
+  if (!rUnsigned)
+    {
+      if (AOP_TYPE(right) == AOP_LIT)
+        {
+          /* signed literal */
+          signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
+          if (val < 0)
+            compiletimeSign ^= TRUE;
+        }
+      else
+        /* signed but not literal */
+        runtimeSign = TRUE;
+    }
+
+  /* initialize the runtime sign */
+  if (runtimeSign)
+    {
+      if (compiletimeSign)
+        loadRegFromConst (hc08_reg_x, "#1"); /* set sign flag */
+      else
+        loadRegFromConst (hc08_reg_x, zero); /* reset sign flag */
+      pushReg (hc08_reg_x, TRUE);
+    }
+
+  /* save the signs of the operands */
+  if (AOP_TYPE(right) == AOP_LIT)
+    {
+      signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
+
+      if (!rUnsigned && val < 0)
         emitcode ("ldx", "#0x%02x", -val);
-        negLiteral = TRUE;
-      } else {
-        emitcode ("ldx", "#0x%02x", val);
-      }
-      hc08_useReg (hc08_reg_x);
+      else
+        emitcode ("ldx", "#0x%02x", (unsigned char) val);
     }
-  else
+  else /* ! literal */
     {
-      tlbl3 = newiTempLabel (NULL);
       loadRegFromAop (hc08_reg_x, AOP (right), 0);
-      emitBranch ("bpl", tlbl3);
-      emitcode ("inc", "1,s");
-      rmwWithReg ("neg", hc08_reg_x);
-      emitLabel (tlbl3);
+      if (!rUnsigned)
+        {
+          tlbl1 = newiTempLabel (NULL);
+          emitcode ("tstx", "");
+          emitBranch ("bpl", tlbl1);
+          emitcode ("inc", "1,s");
+          rmwWithReg ("neg", hc08_reg_x);
+          emitLabel (tlbl1);
+        }
     }
 
+  if (AOP_TYPE(left) == AOP_LIT)
+    {
+      signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
+
+      if (!lUnsigned && val < 0)
+        emitcode ("lda", "#0x%02x", -val);
+      else
+        emitcode ("lda", "#0x%02x", (unsigned char) val);
+    }
+  else /* ! literal */
+    {
+      loadRegFromAop (hc08_reg_a, AOP (left), 0);
+      if (!lUnsigned)
+        {
+          tlbl2 = newiTempLabel (NULL);
+          emitcode ("tsta", "");
+          emitBranch ("bpl", tlbl2);
+          emitcode ("inc", "1,s");
+          rmwWithReg ("neg", hc08_reg_a);
+          emitLabel (tlbl2);
+        }
+    }
+    
+  loadRegFromConst (hc08_reg_h, zero);
   emitcode ("div", "");
   hc08_dirtyReg (hc08_reg_x, FALSE);
   hc08_dirtyReg (hc08_reg_a, FALSE);
   hc08_dirtyReg (hc08_reg_h, FALSE);
+  
+  if (runtimeSign || compiletimeSign)
+    {
+      tlbl3 = newiTempLabel (NULL);
+      if (runtimeSign)
+        {
+          pullReg (hc08_reg_x);
+          rmwWithReg ("lsr", hc08_reg_x);
+          rmwWithReg ("ror", hc08_reg_x);
+          emitBranch ("bpl", tlbl3);
+        }
+     
+      rmwWithReg ("neg", hc08_reg_a);
+      if (runtimeSign)
+        emitLabel (tlbl3);
+      
+      storeRegToAop (hc08_reg_a, AOP (result), 0);
+      
+      if (size > 1)
+        {
+          /* msb is 0x00 or 0xff depending on the sign */
+          if (runtimeSign)
+            {
+              rmwWithReg ("lsl", hc08_reg_x);
+              emitcode ("clra", "");
+              emitcode ("sbc", "#0");
+              while (--size)
+                storeRegToAop (hc08_reg_a, AOP (result), ++offset);
+            }
+          else /* compiletimeSign */
+            while (--size)
+              storeConstToAop ("#0xff", AOP (result), ++offset);
+        }
+    }
+  else
+    {
+      storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
+    }
 
-  tlbl4 = newiTempLabel (NULL);
-  emitcode ("dec", "1,s");
-  if (negLiteral)
-    emitBranch ("bne", tlbl4);
-  else
-    emitBranch ("beq", tlbl4);
-  rmwWithReg ("neg", hc08_reg_a);
-
-  emitLabel (tlbl4);
-  adjustStack (1);
-  storeRegToFullAop (hc08_reg_a, AOP (result), TRUE);
-  hc08_freeReg (hc08_reg_a);
-  hc08_freeReg (hc08_reg_x);
-  hc08_freeReg (hc08_reg_h);
-
-
+  hc08_freeReg (hc08_reg_a);
+  hc08_freeReg (hc08_reg_x);
+  hc08_freeReg (hc08_reg_h);
 }
 
 /*-----------------------------------------------------------------*/
@@ -3769,94 +3953,145 @@ genModOneByte (operand * left,
               operand * right,
               operand * result)
 {
-  sym_link *opetype = operandType (result);
-//  symbol *lbl;
-  symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
+  symbol *tlbl1, *tlbl2, *tlbl3;
   int size;
-  bool negLiteral = FALSE;
+  int offset = 0;
+  bool lUnsigned, rUnsigned;
+  bool runtimeSign, compiletimeSign;
+  
+  lUnsigned = SPEC_USIGN (getSpec (operandType (left)));
+  rUnsigned = SPEC_USIGN (getSpec (operandType (right)));
 
   D(emitcode (";     genModOneByte",""));
 
   size = AOP_SIZE (result);
-  /* signed or unsigned */
-  if (SPEC_USIGN (opetype))
+  
+  if (lUnsigned && rUnsigned)
     {
       /* unsigned is easy */
+      loadRegFromAop (hc08_reg_x, AOP (right), 0);
       loadRegFromAop (hc08_reg_h, AOP (left), 1);
       loadRegFromAop (hc08_reg_a, AOP (left), 0);
-      loadRegFromAop (hc08_reg_x, AOP (right), 0);
       emitcode ("div", "");
-      hc08_dirtyReg (hc08_reg_a, FALSE);
-      hc08_dirtyReg (hc08_reg_h, FALSE);
-      storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
       hc08_freeReg (hc08_reg_a);
       hc08_freeReg (hc08_reg_x);
+      hc08_dirtyReg (hc08_reg_h, FALSE);
+      storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
       hc08_freeReg (hc08_reg_h);
       return;
     }
 
   /* signed is a little bit more difficult */
-
-  adjustStack (-1);
-  emitcode ("clr", "1,s");
-
-  tlbl1 = newiTempLabel (NULL);
-  tlbl2 = newiTempLabel (NULL);
-  loadRegFromAop (hc08_reg_a, AOP (left), 0);
-  loadRegFromAop (hc08_reg_x, AOP (left), 1);
-  emitBranch ("bpl", tlbl1);
-  emitcode ("inc", "1,s");
-  rmwWithReg ("neg", hc08_reg_a);
-  emitBranch ("bcc", tlbl2);
-  rmwWithReg ("inc", hc08_reg_x);
-  emitLabel (tlbl2);
-  rmwWithReg ("neg", hc08_reg_x);
-  transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
-  emitLabel (tlbl1);
-
-  if (AOP_TYPE(right)==AOP_LIT)
+  
+  if (AOP_TYPE(right) == AOP_LIT)
     {
-      signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
-      /* AND literal negative */
-      if (val < 0) {
+      signed char val = (char) floatFromVal (AOP (right)->aopu.aop_lit);
+
+      if (!rUnsigned && val < 0)
         emitcode ("ldx", "#0x%02x", -val);
-        negLiteral = TRUE;
-      } else {
-        emitcode ("ldx", "#0x%02x", val);
-      }
-      hc08_useReg (hc08_reg_x);
+      else
+        emitcode ("ldx", "#0x%02x", (unsigned char) val);
     }
-  else
+  else /* ! literal */
     {
-      tlbl3 = newiTempLabel (NULL);
       loadRegFromAop (hc08_reg_x, AOP (right), 0);
-      emitBranch ("bpl", tlbl3);
-      emitcode ("inc", "1,s");
-      rmwWithReg ("neg", hc08_reg_x);
-      emitLabel (tlbl3);
+      if (!rUnsigned)
+        {
+          tlbl1 = newiTempLabel (NULL);
+          emitcode ("tstx", "");
+          emitBranch ("bpl", tlbl1);
+          rmwWithReg ("neg", hc08_reg_x);
+          emitLabel (tlbl1);
+        }
     }
+  
+  /* let's see what's needed: */
+  /* apply negative sign during runtime */
+  runtimeSign = FALSE;
+  /* negative sign from literals */
+  compiletimeSign = FALSE;
 
+  /* sign adjust left side */
+  if (AOP_TYPE(left) == AOP_LIT)
+    {
+      signed char val = (char) floatFromVal (AOP (left)->aopu.aop_lit);
+
+      if (!lUnsigned && val < 0)
+        {
+          compiletimeSign = TRUE; /* set sign flag */
+          emitcode ("lda", "#0x%02x", -val);
+        }
+      else
+        emitcode ("lda", "#0x%02x", (unsigned char) val);
+    }
+  else /* ! literal */
+    {
+      if (lUnsigned)
+        loadRegFromAop (hc08_reg_a, AOP (left), 0);
+      else
+        {
+          runtimeSign = TRUE;
+          adjustStack (-1);
+          emitcode ("clr", "1,s");
+          
+          loadRegFromAop (hc08_reg_a, AOP (left), 0);
+          tlbl2 = newiTempLabel (NULL);
+          emitcode ("tsta", "");
+          emitBranch ("bpl", tlbl2);
+          emitcode ("inc", "1,s");
+          rmwWithReg ("neg", hc08_reg_a);
+          emitLabel (tlbl2);
+        }
+    }
+  
+  loadRegFromConst (hc08_reg_h, zero);
   emitcode ("div", "");
-  hc08_dirtyReg (hc08_reg_x, FALSE);
-  hc08_dirtyReg (hc08_reg_a, FALSE);
+  hc08_freeReg (hc08_reg_a);
+  hc08_freeReg (hc08_reg_x);
   hc08_dirtyReg (hc08_reg_h, FALSE);
 
-  tlbl4 = newiTempLabel (NULL);
-  transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
-  emitcode ("dec", "1,s");
-  if (negLiteral)
-    emitBranch ("bne", tlbl4);
+  if (runtimeSign || compiletimeSign)
+    {
+      transferRegReg (hc08_reg_h, hc08_reg_a, TRUE);
+      tlbl3 = newiTempLabel (NULL);
+      if (runtimeSign)
+        {
+          pullReg (hc08_reg_x);
+          rmwWithReg ("lsr", hc08_reg_x);
+          rmwWithReg ("ror", hc08_reg_x);
+          emitBranch ("bpl", tlbl3);
+        }
+     
+      rmwWithReg ("neg", hc08_reg_a);
+      if (runtimeSign)
+        emitLabel (tlbl3);
+      
+      storeRegToAop (hc08_reg_a, AOP (result), 0);
+      
+      if (size > 1)
+        {
+          /* msb is 0x00 or 0xff depending on the sign */
+          if (runtimeSign)
+            {
+              rmwWithReg ("lsl", hc08_reg_x);
+              emitcode ("clra", "");
+              emitcode ("sbc", "#0");
+              while (--size)
+                storeRegToAop (hc08_reg_a, AOP (result), ++offset);
+            }
+          else /* compiletimeSign */
+            while (--size)
+              storeConstToAop ("#0xff", AOP (result), ++offset);
+        }
+    }
   else
-    emitBranch ("beq", tlbl4);
-  rmwWithReg ("neg", hc08_reg_a);
-
-  emitLabel (tlbl4);
-  adjustStack (1);
-  storeRegToFullAop (hc08_reg_a, AOP (result), TRUE);
+    {
+      storeRegToFullAop (hc08_reg_h, AOP (result), FALSE);
+    }
+  
   hc08_freeReg (hc08_reg_a);
   hc08_freeReg (hc08_reg_x);
   hc08_freeReg (hc08_reg_h);
-
 }
 
 /*-----------------------------------------------------------------*/
@@ -3937,108 +4172,146 @@ genIfxJump (iCode * ic, char *jval)
   ic->generated = 1;
 }
 
+
 /*-----------------------------------------------------------------*/
-/* genCmp :- greater or less than comparison                       */
+/* exchangedCmp : returns the opcode need if the two operands are  */
+/*                exchanged in a comparison                        */
 /*-----------------------------------------------------------------*/
-static void
-genCmp (operand * left, operand * right,
-       operand * result, iCode * ifx, int sign, iCode *ic)
-{
-  int size, offset = 0;
-  unsigned long lit = 0L;
-  char *sub;
-  bool needpula = FALSE;
-
-  D(emitcode (";     genCmp",""));
-
-  /* subtract right from left if at the
-     end the carry flag is set then we know that
-     left is greater than right */
-  size = max (AOP_SIZE (left), AOP_SIZE (right));
-
-  if (AOP_TYPE (right) == AOP_LIT)
-    {
-      lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
-      /* optimize if(x < 0) or if(x >= 0) */
-      if (lit == 0L)
-       {
-         if (!sign)
-           {
-             CLRC;
-           }
-         else
-           {
-             loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) -1);
-             emitcode ("rola", "");
-             hc08_useReg (hc08_reg_a);
-           }
-         sign = 0;
-          goto release;
-       }
+static int
+exchangedCmp (int opcode)
+{
+  switch (opcode)
+    {
+    case '<':
+      return '>';
+    case '>':
+      return '<';
+    case LE_OP:
+      return GE_OP;
+    case GE_OP:
+      return LE_OP;
+    case NE_OP:
+      return NE_OP;
+    case EQ_OP:
+      return EQ_OP;
+    default:
+      werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+                 "opcode not a comparison");
     }
+  return EQ_OP; /* shouldn't happen, but need to return something */
+}
 
-  if ((size==2)
-      && ((AOP_TYPE (right) == AOP_LIT) || 
-          ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
-      && hc08_reg_hx->isFree)
-    {
-      loadRegFromAop (hc08_reg_hx, AOP (left), 0);
-      emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
-      hc08_freeReg (hc08_reg_hx);
-      goto release;
+/*------------------------------------------------------------------*/
+/* negatedCmp : returns the equivalent opcode for when a comparison */
+/*              if not true                                         */
+/*------------------------------------------------------------------*/
+static int
+negatedCmp (int opcode)
+{
+  switch (opcode)
+    {
+    case '<':
+      return GE_OP;
+    case '>':
+      return LE_OP;
+    case LE_OP:
+      return '>';
+    case GE_OP:
+      return '<';
+    case NE_OP:
+      return EQ_OP;
+    case EQ_OP:
+      return NE_OP;
+    default:
+      werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+                 "opcode not a comparison");
     }
+  return EQ_OP; /* shouldn't happen, but need to return something */
+}
 
-  offset = 0;
-  if (size==1)
-    sub="cmp";
-  else
-    sub="sub";
-  while (size--)
-    {
-      loadRegFromAop (hc08_reg_a, AOP (left), offset);
-      accopWithAop (sub, AOP (right), offset);
-      hc08_freeReg (hc08_reg_a);
-      offset++;
-      sub="sbc";
+/* compile only if the debugging macro D is enabled */
+#if (D(1) -0)
+static char *
+nameCmp (int opcode)
+{
+  switch (opcode)
+    {
+    case '<':
+      return "<";
+    case '>':
+      return ">";
+    case LE_OP:
+      return "<=";
+    case GE_OP:
+      return ">=";
+    case NE_OP:
+      return "!=";
+    case EQ_OP:
+      return "==";
+    default:
+      return "invalid";
     }
+}
+#endif
 
-release:
-  freeAsmop (right, NULL, ic, TRUE);
-  freeAsmop (left, NULL, ic, TRUE);
-  if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
-    {
-      outBitC (result);
-    }
-  else
+/*------------------------------------------------------------------*/
+/* branchInstCmp : returns the conditional branch instruction that  */
+/*                 will branch if the comparison is true            */
+/*------------------------------------------------------------------*/
+static char *
+branchInstCmp (int opcode, int sign)
+{
+  switch (opcode)
     {
-      /* if the result is used in the next
-         ifx conditional branch then generate
-         code a little differently */
-      if (ifx)
-        {
-          pullOrFreeReg(hc08_reg_a,needpula);
-         genIfxJump (ifx, sign ? "s" : "c");
-        }
+    case '<':
+      if (sign)
+        return "blt";
+      else
+        return "bcs";  /* same as blo */
+    case '>':
+      if (sign)
+        return "bgt";
+      else
+        return "bhi";
+    case LE_OP:
+      if (sign)
+        return "ble";
       else
-        if (!sign)
-         outBitC (result);
-       else
-         outBitNV (result);
-        pullOrFreeReg(hc08_reg_a,needpula);
+        return "bls";
+    case GE_OP:
+      if (sign)
+        return "bge";
+      else
+        return "bcc";  /* same as bhs */
+    case NE_OP:
+      return "bne";
+    case EQ_OP:
+      return "beq";
+    default:
+      werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+                 "opcode not a comparison");
     }
+  return "brn";
 }
 
-/*-----------------------------------------------------------------*/
-/* genCmpGt :- greater than comparison                             */
-/*-----------------------------------------------------------------*/
+
+/*------------------------------------------------------------------*/
+/* genCmp :- greater or less than (and maybe with equal) comparison */
+/*------------------------------------------------------------------*/
 static void
-genCmpGt (iCode * ic, iCode * ifx)
-{
+genCmp (iCode * ic, iCode * ifx)
+{  
   operand *left, *right, *result;
   sym_link *letype, *retype;
-  int sign;
+  int sign, opcode;
+  int size, offset = 0;
+  unsigned long lit = 0L;
+  char *sub;
+  symbol *jlbl = NULL;
+
+  opcode = ic->op;
 
-  D(emitcode (";     genCmpGt",""));
+  D(emitcode (";     genCmp", "(%s)",nameCmp (opcode)));
 
   result = IC_RESULT (ic);
   left = IC_LEFT (ic);
@@ -4052,22 +4325,136 @@ genCmpGt (iCode * ic, iCode * ifx)
   aopOp (right, ic, FALSE);
   aopOp (result, ic, TRUE);
 
-  genCmp (right, left, result, ifx, sign,ic);
+  /* need register operand on left, prefer literal operand on right */
+  if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
+    {
+      operand *temp = left;
+      left = right;
+      right = temp;
+      opcode = exchangedCmp (opcode);
+    }
 
-  freeAsmop (result, NULL, ic, TRUE);
+  if (ifx)
+    {
+      if (IC_TRUE (ifx))
+        {
+          jlbl = IC_TRUE (ifx);
+          opcode = negatedCmp (opcode);
+        }
+      else
+        {
+          /* false label is present */
+          jlbl = IC_FALSE (ifx);
+        }
+    }
+      
+  size = max (AOP_SIZE (left), AOP_SIZE (right));
+  
+  if ((size == 2)
+      && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
+      && ((AOP_TYPE (right) == AOP_LIT) || 
+          ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
+      && hc08_reg_hx->isFree)
+    {
+      loadRegFromAop (hc08_reg_hx, AOP (left), 0);
+      emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
+      hc08_freeReg (hc08_reg_hx);
+    }
+  else
+    {
+      offset = 0;
+      if (size == 1)
+        sub = "cmp";
+      else
+        {
+          sub = "sub";
+        
+          /* These conditions depend on the Z flag bit, but Z is */
+          /* only valid for the last byte of the comparison, not */
+          /* the whole value. So exchange the operands to get a  */
+          /* comparison that doesn't depend on Z. (This is safe  */
+          /* to do here since ralloc won't assign multi-byte     */
+          /* operands to registers for comparisons)              */
+          if ((opcode == '>') || (opcode == LE_OP))
+            {
+              operand *temp = left;
+              left = right;
+              right = temp;
+              opcode = exchangedCmp (opcode);
+            }
+          
+          if ((AOP_TYPE (right) == AOP_LIT) && !isOperandVolatile (left, FALSE))
+            {
+              lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+              while ((size > 1) && (((lit >> (8*offset)) & 0xff) == 0))
+                {
+                  offset++;
+                  size--;
+                }
+            }
+        }
+      while (size--)
+        {
+          loadRegFromAop (hc08_reg_a, AOP (left), offset);
+          accopWithAop (sub, AOP (right), offset);
+          hc08_freeReg (hc08_reg_a);
+          offset++;
+          sub = "sbc";
+        }
+    }
+  freeAsmop (right, NULL, ic, FALSE);
+  freeAsmop (left, NULL, ic, FALSE);
+
+  if (ifx)
+    {
+      symbol *tlbl = newiTempLabel (NULL);
+      char *inst;
+
+      freeAsmop (result, NULL, ic, TRUE);      
+      
+      inst = branchInstCmp (opcode, sign);
+      emitBranch (inst, tlbl);
+      emitBranch ("jmp", jlbl);
+      emitLabel (tlbl);
+
+      /* mark the icode as generated */
+      ifx->generated = 1;
+    }
+  else
+    {
+      symbol *tlbl1 = newiTempLabel (NULL);
+      symbol *tlbl2 = newiTempLabel (NULL);
+      
+      emitBranch (branchInstCmp (opcode, sign), tlbl1);
+      loadRegFromConst (hc08_reg_a, zero);
+      emitBranch ("bra", tlbl2);
+      emitLabel (tlbl1);
+      loadRegFromConst (hc08_reg_a, one);
+      emitLabel (tlbl2);
+      storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
+      freeAsmop (result, NULL, ic, TRUE);      
+    }
+        
 }
 
 /*-----------------------------------------------------------------*/
-/* genCmpLt - less than comparisons                                */
+/* genCmpEQorNE - equal or not equal comparison                    */
 /*-----------------------------------------------------------------*/
 static void
-genCmpLt (iCode * ic, iCode * ifx)
-{
+genCmpEQorNE (iCode * ic, iCode * ifx)
+{  
   operand *left, *right, *result;
   sym_link *letype, *retype;
-  int sign;
+  int sign, opcode;
+  int size, offset = 0;
+  char *sub;
+  symbol *jlbl = NULL;
+  symbol *tlbl_NE = NULL;
+  symbol *tlbl_EQ = NULL;
+  opcode = ic->op;
 
-  D(emitcode (";     genCmpLt",""));
+  D(emitcode (";     genCmpEQorNE", "(%s)",nameCmp (opcode)));
 
   result = IC_RESULT (ic);
   left = IC_LEFT (ic);
@@ -4076,141 +4463,128 @@ genCmpLt (iCode * ic, iCode * ifx)
   letype = getSpec (operandType (left));
   retype = getSpec (operandType (right));
   sign = !(SPEC_USIGN (letype) | SPEC_USIGN (retype));
-
   /* assign the amsops */
   aopOp (left, ic, FALSE);
   aopOp (right, ic, FALSE);
   aopOp (result, ic, TRUE);
-
-  genCmp (left, right, result, ifx, sign,ic);
-
-  freeAsmop (result, NULL, ic, TRUE);
-}
-
-/*-----------------------------------------------------------------*/
-/*  - compare and branch if not equal                    */
-/*-----------------------------------------------------------------*/
-static void
-gencbneshort (operand * left, operand * right, symbol * lbl)
-{
-  int size = max (AOP_SIZE (left), AOP_SIZE (right));
-  int offset = 0;
-  unsigned long lit = 0L;
-
-  /* if the left side is a literal or
-     if the right is in a pointer register and left
-     is not */
-  if (AOP_TYPE (left) == AOP_LIT)
+  
+  /* need register operand on left, prefer literal operand on right */
+  if ((AOP_TYPE (right) == AOP_REG) || AOP_TYPE (left) == AOP_LIT)
     {
-      operand *t = right;
-      right = left;
-      left = t;
+      operand *temp = left;
+      left = right;
+      right = temp;
+      opcode = exchangedCmp (opcode);
     }
-  if (AOP_TYPE (right) == AOP_LIT)
-    lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
 
-  while (size--)
+  if (ifx)
     {
-      loadRegFromAop (hc08_reg_a, AOP (left), offset);
-      accopWithAop ("cmp", AOP (right), offset);
-      hc08_useReg (hc08_reg_a);
-      hc08_freeReg (hc08_reg_a);
-      emitBranch ("bne", lbl);
-      offset++;
+      if (IC_TRUE (ifx))
+        {
+          jlbl = IC_TRUE (ifx);
+          opcode = negatedCmp (opcode);
+        }
+      else
+        {
+          /* false label is present */
+          jlbl = IC_FALSE (ifx);
+        }
     }
-
-}
-
-/*-----------------------------------------------------------------*/
-/* gencjne - compare and jump if not equal                         */
-/*-----------------------------------------------------------------*/
-static void
-gencjne (operand * left, operand * right, symbol * lbl)
-{
-  symbol *tlbl = newiTempLabel (NULL);
-
-  gencbneshort (left, right, lbl);
-
-  loadRegFromConst (hc08_reg_a, one);
-  emitBranch ("bra", tlbl);
-  emitLabel (lbl);
-  loadRegFromConst (hc08_reg_a, zero);
-  emitLabel (tlbl);
-
-  hc08_useReg(hc08_reg_a);
-  hc08_freeReg(hc08_reg_a);
-}
-
-/*-----------------------------------------------------------------*/
-/* genCmpEq - generates code for equal to                          */
-/*-----------------------------------------------------------------*/
-static void
-genCmpEq (iCode * ic, iCode * ifx)
-{
-  operand *left, *right, *result;
-
-  D(emitcode (";     genCmpEq",""));
-
-  aopOp ((left = IC_LEFT (ic)), ic, FALSE);
-  aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
-  aopOp ((result = IC_RESULT (ic)), ic, TRUE);
-
-  /* if literal, literal on the right or
-     if the right is in a pointer register and left
-     is not */
-  if (AOP_TYPE (IC_LEFT (ic)) == AOP_LIT)
+      
+  size = max (AOP_SIZE (left), AOP_SIZE (right));
+  
+  if ((size == 2)
+      && ((AOP_TYPE (left) == AOP_DIR) && (AOP_SIZE (left) == 2))
+      && ((AOP_TYPE (right) == AOP_LIT) || 
+          ((AOP_TYPE (right) == AOP_DIR) && (AOP_SIZE (right) == 2)) )
+      && hc08_reg_hx->isFree)
     {
-      operand *t = IC_RIGHT (ic);
-      IC_RIGHT (ic) = IC_LEFT (ic);
-      IC_LEFT (ic) = t;
+      loadRegFromAop (hc08_reg_hx, AOP (left), 0);
+      emitcode ("cphx","%s", aopAdrStr (AOP (right), 1, TRUE));
+      hc08_freeReg (hc08_reg_hx);
     }
+  else
+    {
+      offset = 0;
+      sub = "cmp";
+      while (size--)
+        {
+          loadRegFromAop (hc08_reg_a, AOP (left), offset);
+          accopWithAop (sub, AOP (right), offset);
+          if (size)
+            {
+              if (!tlbl_NE)
+                tlbl_NE = newiTempLabel (NULL);
+              emitBranch ("bne", tlbl_NE);
+            }
+          hc08_freeReg (hc08_reg_a);
+          offset++;
+        }
+    }
+  freeAsmop (right, NULL, ic, FALSE);
+  freeAsmop (left, NULL, ic, FALSE);
 
-  if (ifx && !AOP_SIZE (result))
+  if (ifx)
     {
-      symbol *tlbl;
-      tlbl = newiTempLabel (NULL);
-      gencbneshort (left, right, tlbl);
-      if (IC_TRUE (ifx))
+      freeAsmop (result, NULL, ic, TRUE);      
+      
+      if (opcode == EQ_OP)
         {
-          emitBranch ("jmp", IC_TRUE (ifx));
-          emitLabel (tlbl);
+          if (!tlbl_EQ)
+            tlbl_EQ = newiTempLabel (NULL);
+          emitBranch ("beq", tlbl_EQ);
+          if (tlbl_NE)
+            emitLabel (tlbl_NE);
+          emitBranch ("jmp", jlbl);
+          emitLabel (tlbl_EQ);
         }
       else
-       {
-         symbol *lbl = newiTempLabel (NULL);
-          emitBranch ("bra", lbl);
-          emitLabel (tlbl);
-          emitBranch ("jmp", IC_FALSE (ifx));
-          emitLabel (lbl);
-       }
-      
+        {
+          if (!tlbl_NE)
+            tlbl_NE = newiTempLabel (NULL);
+          emitBranch ("bne", tlbl_NE);
+          emitBranch ("jmp", jlbl);
+          emitLabel (tlbl_NE);
+        }
+
       /* mark the icode as generated */
       ifx->generated = 1;
-      goto release;
     }
-
-  gencjne (left, right, newiTempLabel (NULL));
-  if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
-    {
-      storeRegToAop (hc08_reg_a, AOP (result), 0);
-      goto release;
-    }
-  if (ifx)
+  else
     {
-      genIfxJump (ifx, "a");
-      goto release;
+      symbol *tlbl = newiTempLabel (NULL);
+      
+      if (opcode == EQ_OP)
+        {
+          if (!tlbl_EQ)
+            tlbl_EQ = newiTempLabel (NULL);
+          emitBranch ("beq", tlbl_EQ);
+          if (tlbl_NE)
+            emitLabel (tlbl_NE);
+          loadRegFromConst (hc08_reg_a, zero);
+          emitBranch ("bra", tlbl);
+          emitLabel (tlbl_EQ);
+          loadRegFromConst (hc08_reg_a, one);
+        }
+      else
+        {
+          if (!tlbl_NE)
+            tlbl_NE = newiTempLabel (NULL);
+          emitBranch ("bne", tlbl_NE);
+          loadRegFromConst (hc08_reg_a, zero);
+          emitBranch ("bra", tlbl);
+          emitLabel (tlbl_NE);
+          loadRegFromConst (hc08_reg_a, one);
+        }
+      
+      emitLabel (tlbl);
+      storeRegToFullAop (hc08_reg_a, AOP(result), FALSE);
+      freeAsmop (result, NULL, ic, TRUE);      
     }
-  /* if the result is used in an arithmetic operation
-     then put the result in place */
-  if (AOP_TYPE (result) != AOP_CRY)
-    outAcc (result);
-
-release:
-  freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
-  freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
-  freeAsmop (result, NULL, ic, TRUE);
+        
 }
 
+
 /*-----------------------------------------------------------------*/
 /* ifxForOp - returns the icode containing the ifx for operand     */
 /*-----------------------------------------------------------------*/
@@ -4238,24 +4612,24 @@ genPointerGetSetOfs (iCode *ic)
 {
   iCode *lic = ic->next;
   bool pset, pget;
-  int offset, size;
+  int size;
   symbol *sym;
   asmop *derefaop;
 
   /* Make sure we have a next iCode */
-  D(emitcode("","; checking lic"));
+  DD(emitcode("","; checking lic"));
   if (!lic)
     return FALSE;
 
   /* Make sure the result of the addition is an iCode */
-  D(emitcode("","; checking IS_ITEMP"));
+  DD(emitcode("","; checking IS_ITEMP"));
   if (!IS_ITEMP (IC_RESULT (ic)))
     return FALSE;
 
   /* Make sure the next iCode is a pointer set or get */
   pset = POINTER_SET(lic);
   pget = POINTER_GET(lic);
-  D(emitcode("","; pset=%d, pget=%d",pset,pget));
+  DD(emitcode("","; pset=%d, pget=%d",pset,pget));
   if (!pset && !pget)
     return FALSE;
 
@@ -4263,25 +4637,25 @@ genPointerGetSetOfs (iCode *ic)
   if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
     return FALSE;
     
-  D(emitcode("", "; checking pset operandsEqu"));
+  DD(emitcode("", "; checking pset operandsEqu"));
   if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
     return FALSE;
 
-  D(emitcode("", "; checking pget operandsEqu"));
+  DD(emitcode("", "; checking pget operandsEqu"));
   if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
     return FALSE;
 
-  D(emitcode("", "; checking IS_SYMOP"));
+  DD(emitcode("", "; checking IS_SYMOP"));
   if (!IS_SYMOP (IC_LEFT (ic)))
     return FALSE;
 
-  D(emitcode("", "; checking !IS_TRUE_SYMOP"));
+  DD(emitcode("", "; checking !IS_TRUE_SYMOP"));
   if (IS_TRUE_SYMOP (IC_LEFT (ic)))
     return FALSE;
 
   sym = OP_SYMBOL (IC_LEFT (ic));
   
-  D(emitcode("", "; checking remat"));
+  DD(emitcode("", "; checking remat"));
   if (!sym->remat)
     return FALSE;
     
@@ -4318,14 +4692,13 @@ genPointerGetSetOfs (iCode *ic)
         loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
       size = AOP_SIZE (IC_RESULT(lic));
       derefaop->size = size;
-      offset=0;
       
       while (size--)
         {
           emitcode ("lda", "%s,x",
-                    aopAdrStr (derefaop, offset, TRUE));
+                    aopAdrStr (derefaop, size, TRUE));
           hc08_useReg (hc08_reg_a);
-          storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), offset++);
+          storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), size);
           hc08_freeReg (hc08_reg_a);
         }
 
@@ -4371,15 +4744,13 @@ genPointerGetSetOfs (iCode *ic)
         loadRegFromAop (hc08_reg_hx, AOP (IC_RIGHT (ic)), 0);
       size = AOP_SIZE (IC_RIGHT(lic));
       derefaop->size = size;
-      offset=0;
       
       while (size--)
         {
-          loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), offset);
+          loadRegFromAop (hc08_reg_a, AOP (IC_RIGHT (lic)), size);
           emitcode ("sta", "%s,x",
-                    aopAdrStr (derefaop, offset, TRUE));
+                    aopAdrStr (derefaop, size, TRUE));
           hc08_freeReg (hc08_reg_a);
-          offset++;
         }
 
       lic->generated = 1;
@@ -4423,7 +4794,7 @@ hasInc (operand *op, iCode *ic,int osize)
       return lic;
     }
     /* if the operand used or deffed */
-    if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
+    if (bitVectBitValue(OP_USES(op),lic->key) || lic->defKey == op->key) {
       return NULL;
     }
     /* if GOTO or IFX */
@@ -4596,6 +4967,7 @@ genAnd (iCode * ic, iCode * ifx)
   int size, offset = 0;
   unsigned long lit = 0L;
   unsigned long litinv;
+  unsigned char bytemask;
 
   
 //  int bytelit = 0;
@@ -4608,10 +4980,10 @@ genAnd (iCode * ic, iCode * ifx)
   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
 
 #ifdef DEBUG_TYPE
-  D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
+  DD(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
            AOP_TYPE (result),
            AOP_TYPE (left), AOP_TYPE (right)));
-  D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
+  DD(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
            AOP_SIZE (result),
            AOP_SIZE (left), AOP_SIZE (right)));
 #endif
@@ -4624,7 +4996,7 @@ genAnd (iCode * ic, iCode * ifx)
       left = tmp;
     }
 
-  /* if left is accumulator & right is not then exchange them */
+  /* if right is accumulator & left is not then exchange them */
   if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
     {
       operand *tmp = right;
@@ -4632,42 +5004,84 @@ genAnd (iCode * ic, iCode * ifx)
       left = tmp;
     }
 
-
-  if (AOP_TYPE (result) == AOP_CRY)
+  if (AOP_TYPE (right) == AOP_LIT)
+    lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+      
+  size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
+  
+  if (AOP_TYPE (result) == AOP_CRY
+      && size > 1
+      && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
     {
-      symbol *tlbl;
-      wassertl (ifx, "AOP_CPY result without ifx");
+      /* this generates ugly code, but meets volatility requirements */
+      loadRegFromConst (hc08_reg_a, zero);
+      pushReg (hc08_reg_a, TRUE);
       
-      tlbl = newiTempLabel (NULL);
-      size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
       offset = 0;
       while (size--)
         {
           loadRegFromAop (hc08_reg_a, AOP (left), offset);
-          if ((AOP_TYPE (right) == AOP_LIT)
-              && (((lit >> (offset*8)) & 0xff) == 0xff))
-            emitcode ("tsta","");
-          else
-            accopWithAop ("and", AOP (right), offset);
-          hc08_freeReg( hc08_reg_a);      
-          if (size)
-            emitBranch ("bne", tlbl);
+          accopWithAop ("and", AOP (right), offset);
+          emitcode ("ora", "1,s");
+          emitcode ("sta", "1,s");
+          offset++;
+        }
+      
+      pullReg (hc08_reg_a);
+      emitcode ("tsta", "");
+      genIfxJump (ifx, "a");
+      goto release;
+    }
+  
+  if (AOP_TYPE (result) == AOP_CRY)
+    {
+      symbol *tlbl = NULL;
+      wassertl (ifx, "AOP_CRY result without ifx");
+      
+      offset = 0;
+      while (size--)
+        {
+          bytemask = (lit >> (offset*8)) & 0xff;
+          
+          if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
+            {
+              /* do nothing */
+            }
+          else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
+            {
+              rmwWithAop ("tst", AOP (left), offset);
+              if (size)
+                {
+                  if (!tlbl)
+                    tlbl = newiTempLabel (NULL);
+                  emitBranch ("bne", tlbl);
+                }
+            }
           else
             {
-              emitLabel (tlbl);
-              genIfxJump (ifx, "a");
+              loadRegFromAop (hc08_reg_a, AOP (left), offset);
+              accopWithAop ("and", AOP (right), offset);
+              hc08_freeReg( hc08_reg_a);
+              if (size)
+                {
+                  if (!tlbl)
+                    tlbl = newiTempLabel (NULL);
+                  emitBranch ("bne", tlbl);
+                }
             }
           offset++;
         }
+        if (tlbl)
+          emitLabel (tlbl);
+        genIfxJump (ifx, "a");
+        goto release;
     }
   
   size = AOP_SIZE (result);
 
   if (AOP_TYPE (right) == AOP_LIT)
     {
-      lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
       litinv = (~lit) & (((unsigned int)0xffffffff) >> (8*(4-size))) ;
-
       if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
           (AOP_TYPE (left) == AOP_DIR) && isLiteralBit(litinv))
         {
@@ -4681,12 +5095,29 @@ genAnd (iCode * ic, iCode * ifx)
   offset = 0;
   while (size--)
     {
-      loadRegFromAop (hc08_reg_a, AOP (left), offset);
-      if ((AOP_TYPE (right) != AOP_LIT)
-          || (((lit >> (offset*8)) & 0xff) != 0xff))
-        accopWithAop ("and", AOP (right), offset);
-      storeRegToAop (hc08_reg_a, AOP (result), offset++);
-      hc08_freeReg( hc08_reg_a);      
+      bytemask = (lit >> (offset*8)) & 0xff;
+      
+      if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
+        {
+          if (isOperandVolatile (left, FALSE))
+            {
+              loadRegFromAop (hc08_reg_a, AOP (left), offset);
+              hc08_freeReg( hc08_reg_a);      
+            }
+          storeConstToAop (zero, AOP (result), offset);
+        }
+      else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
+        {
+          transferAopAop (AOP (left), offset, AOP (result), offset);
+        }
+      else
+        {
+          loadRegFromAop (hc08_reg_a, AOP (left), offset);
+          accopWithAop ("and", AOP (right), offset);
+          storeRegToAop (hc08_reg_a, AOP (result), offset);
+          hc08_freeReg (hc08_reg_a);      
+        }
+      offset++;
     }
 
 release:
@@ -4704,6 +5135,7 @@ genOr (iCode * ic, iCode * ifx)
   operand *left, *right, *result;
   int size, offset = 0;
   unsigned long lit = 0L;
+  unsigned char bytemask;
 
   D(emitcode (";     genOr",""));
 
@@ -4712,10 +5144,10 @@ genOr (iCode * ic, iCode * ifx)
   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
 
 #ifdef DEBUG_TYPE
-  D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
+  DD(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
            AOP_TYPE (result),
            AOP_TYPE (left), AOP_TYPE (right)));
-  D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
+  DD(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
            AOP_SIZE (result),
            AOP_SIZE (left), AOP_SIZE (right)));
 #endif
@@ -4736,32 +5168,72 @@ genOr (iCode * ic, iCode * ifx)
       left = tmp;
     }
 
-  if (AOP_TYPE (result) == AOP_CRY)
+  if (AOP_TYPE (right) == AOP_LIT)
+    lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+      
+  size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
+  
+  if (AOP_TYPE (result) == AOP_CRY
+      && size > 1
+      && (isOperandVolatile (left, FALSE) || isOperandVolatile (right, FALSE)))
     {
-      symbol *tlbl;
-      wassertl (ifx, "AOP_CPY result without ifx");
+      /* this generates ugly code, but meets volatility requirements */
+      loadRegFromConst (hc08_reg_a, zero);
+      pushReg (hc08_reg_a, TRUE);
       
-      tlbl = newiTempLabel (NULL);
-      size = (AOP_SIZE (left) >= AOP_SIZE (right)) ? AOP_SIZE (left) : AOP_SIZE (right);
       offset = 0;
       while (size--)
         {
           loadRegFromAop (hc08_reg_a, AOP (left), offset);
-          if ((AOP_TYPE (right) == AOP_LIT)
-              && (((lit >> (offset*8)) & 0xff) == 0))
-            emitcode ("tsta","");
-          else
-            accopWithAop ("ora", AOP (right), offset);
-          hc08_freeReg( hc08_reg_a);      
-          if (size)
-            emitBranch ("bne", tlbl);
+          accopWithAop ("ora", AOP (right), offset);
+          emitcode ("ora", "1,s");
+          emitcode ("sta", "1,s");
+          offset++;
+        }
+      
+      pullReg (hc08_reg_a);
+      emitcode ("tsta", "");
+      genIfxJump (ifx, "a");
+      goto release;
+    }
+  
+  if (AOP_TYPE (result) == AOP_CRY)
+    {
+      symbol *tlbl = NULL;
+      wassertl (ifx, "AOP_CRY result without ifx");
+      
+      offset = 0;
+      while (size--)
+        {
+          bytemask = (lit >> (offset*8)) & 0xff;
+          
+          if (AOP_TYPE (right) == AOP_LIT && bytemask == 0x00)
+            {
+              rmwWithAop ("tst", AOP (left), offset);
+              if (size)
+                {
+                  if (!tlbl)
+                    tlbl = newiTempLabel (NULL);
+                  emitBranch ("bne", tlbl);
+                }
+            }
           else
             {
-              emitLabel (tlbl);
-              genIfxJump (ifx, "a");
+              loadRegFromAop (hc08_reg_a, AOP (left), offset);
+              accopWithAop ("ora", AOP (right), offset);
+              hc08_freeReg( hc08_reg_a);
+              if (size)
+                {
+                  if (!tlbl)
+                    tlbl = newiTempLabel (NULL);
+                  emitBranch ("bne", tlbl);
+                }
             }
           offset++;
         }
+        if (tlbl)
+          emitLabel (tlbl);
+        genIfxJump (ifx, "a");
     }
   
   if (AOP_TYPE (right) == AOP_LIT)
@@ -4782,10 +5254,29 @@ genOr (iCode * ic, iCode * ifx)
   offset = 0;
   while (size--)
     {
-      loadRegFromAop (hc08_reg_a, AOP (left), offset);
-      accopWithAop ("ora", AOP (right), offset);
-      storeRegToAop (hc08_reg_a, AOP (result), offset++);
-      hc08_freeReg( hc08_reg_a);      
+      bytemask = (lit >> (offset*8)) & 0xff;
+      
+      if (AOP_TYPE (right) == AOP_LIT && bytemask == 0xff)
+        {
+          if (isOperandVolatile (left, FALSE))
+            {
+              loadRegFromAop (hc08_reg_a, AOP (left), offset);
+              hc08_freeReg( hc08_reg_a);      
+            }
+          transferAopAop (AOP (right), offset, AOP (result), offset);
+        }
+      else if (AOP_TYPE (right) == AOP_LIT && bytemask == 0)
+        {
+          transferAopAop (AOP (left), offset, AOP (result), offset);
+        }
+      else
+        {
+          loadRegFromAop (hc08_reg_a, AOP (left), offset);
+          accopWithAop ("ora", AOP (right), offset);
+          storeRegToAop (hc08_reg_a, AOP (result), offset);
+          hc08_freeReg (hc08_reg_a);      
+        }
+      offset++;
     }
 
 
@@ -4812,10 +5303,10 @@ genXor (iCode * ic, iCode * ifx)
   aopOp ((result = IC_RESULT (ic)), ic, TRUE);
 
 #ifdef DEBUG_TYPE
-  D(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
+  DD(emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
            AOP_TYPE (result),
            AOP_TYPE (left), AOP_TYPE (right)));
-  D(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
+  DD(emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
            AOP_SIZE (result),
            AOP_SIZE (left), AOP_SIZE (right)));
 #endif
@@ -4900,7 +5391,7 @@ emitinline (iCode * ic, char *inlin)
       if (*inlin == '_')
         {
           symname = ++inlin;
-          while (isalnum(*inlin) || (*inlin == '_'))
+          while (isalnum((unsigned char)*inlin) || (*inlin == '_'))
             inlin++;
           c = *inlin;
           *inlin = '\0';
@@ -4921,7 +5412,7 @@ emitinline (iCode * ic, char *inlin)
               if (*l=='#')
                 l++;
               sym->isref = 1;
-              if (!sym->allocreq && !sym->ismyparm)
+              if (sym->level && !sym->allocreq && !sym->ismyparm)
                 {
                   werror (E_ID_UNDEF, sym->name);
                   werror (W_CONTINUE,
@@ -5296,11 +5787,15 @@ AccLsh (int shCount)
   switch (shCount)
     {
     case 4:
+      if (optimize.codeSpeed)
+        break;
       accopWithMisc ("nsa", "");
       accopWithMisc ("and", "#0xf0");
       /* total: 5 cycles, 3 bytes */
       return;
     case 5:
+      if (optimize.codeSpeed)
+        break;
       accopWithMisc ("nsa", "");
       accopWithMisc ("and", "#0xf0");
       accopWithMisc ("lsla", "");
@@ -5373,11 +5868,15 @@ AccRsh (int shCount, bool sign)
   switch (shCount)
     {
     case 4:
+      if (optimize.codeSpeed)
+        break;
       accopWithMisc ("nsa", "");
       accopWithMisc ("and", "#0x0f");
       /* total: 5 cycles, 3 bytes */
       return;
     case 5:
+      if (optimize.codeSpeed)
+        break;
       accopWithMisc ("nsa", "");
       accopWithMisc ("and", "#0x0f");
       accopWithMisc ("lsra", "");
@@ -5517,7 +6016,7 @@ XAccSRsh (int shCount)
       ;
     }
 
-  /* asrx/rola is only 2 cycles and bytes, so an unrolled loop is often  */
+  /* asrx/rora is only 2 cycles and bytes, so an unrolled loop is often  */
   /* the fastest and shortest.                                           */
   for (i=0;i<shCount;i++)
     {
@@ -5716,7 +6215,7 @@ shiftL2Left2Result (operand * left, int offl,
             rmwWithReg ("rol", hc08_reg_x);
           }
     }
-  storeRegToAop (hc08_reg_xa, AOP (result), offl);
+  storeRegToAop (hc08_reg_xa, AOP (result), offr);
 
   pullOrFreeReg (hc08_reg_x, needpulx);
   pullOrFreeReg (hc08_reg_a, needpula);
@@ -5841,7 +6340,7 @@ genlshTwo (operand * result, operand * left, int shCount)
 
 /*-----------------------------------------------------------------*/
 /* shiftLLong - shift left one long from left to result            */
-/* offl = LSB or MSB16                                             */
+/* offr = LSB or MSB16                                             */
 /*-----------------------------------------------------------------*/
 static void
 shiftLLong (operand * left, operand * result, int offr)
@@ -5858,10 +6357,10 @@ shiftLLong (operand * left, operand * result, int offr)
   loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
   rmwWithReg ("lsl", hc08_reg_a);
   rmwWithReg ("rol", hc08_reg_x);
-  storeRegToAop (hc08_reg_xa, AOP (result), offr);
 
   if (offr==LSB)
     {
+      storeRegToAop (hc08_reg_xa, AOP (result), offr);
       loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
       rmwWithReg ("rol", hc08_reg_a);
       rmwWithReg ("rol", hc08_reg_x);
@@ -5869,9 +6368,12 @@ shiftLLong (operand * left, operand * result, int offr)
     }
   else if (offr==MSB16)
     {
+      storeRegToAop (hc08_reg_a, AOP (result), offr);
       loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
+      storeRegToAop (hc08_reg_x, AOP (result), offr+1);
       rmwWithReg ("rol", hc08_reg_a);
       storeRegToAop (hc08_reg_a, AOP (result), offr+2);
+      storeConstToAop (zero, AOP (result), 0);
     }
 
   pullOrFreeReg (hc08_reg_x, needpulx);
@@ -5998,7 +6500,7 @@ genLeftShiftLiteral (operand * left,
   size = AOP_SIZE (result);
 
 #if VIEW_SIZE
-  D(emitcode ("; shift left ", "result %d, left %d", size,
+  DD(emitcode ("; shift left ", "result %d, left %d", size,
            AOP_SIZE (left)));
 #endif
 
@@ -6046,9 +6548,8 @@ genLeftShift (iCode * ic)
   operand *left, *right, *result;
   int size, offset;
   symbol *tlbl, *tlbl1;
-//  int i;
   char *shift;
-  regs *reg;
+  asmop *aopResult;
 
   D(emitcode (";     genLeftShift",""));
 
@@ -6067,38 +6568,41 @@ genLeftShift (iCode * ic)
     }
 
   /* shift count is unknown then we have to form
-     a loop get the loop count in A : Note: we take
+     a loop get the loop count in X : Note: we take
      only the lower order byte since shifting
      more that 32 bits make no sense anyway, ( the
      largest size of an object can be only 32 bits ) */
 
-  aopOp (left, ic, FALSE);
   aopOp (result, ic, FALSE);
+  aopOp (left, ic, FALSE);
+  aopResult = AOP (result);
+
+  if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result))
+      || isOperandVolatile (result, FALSE)) 
+    aopResult = forceStackedAop (AOP (result), sameRegs ( AOP (left), AOP (result)));
 
   /* now move the left to the result if they are not the
      same */
-  if (!sameRegs (AOP (left), AOP (result)))
+  if (!sameRegs (AOP (left), aopResult))
     {
-
       size = AOP_SIZE (result);
       offset = 0;
       while (size--)
        {
-         transferAopAop (AOP (left), offset, AOP (result), offset);
+         transferAopAop (AOP (left), offset, aopResult, offset);
          offset++;
        }
     }
   freeAsmop (left, NULL, ic, TRUE);
+  AOP (result) = aopResult;
   
   tlbl = newiTempLabel (NULL);
   size = AOP_SIZE (result);
   offset = 0;
   tlbl1 = newiTempLabel (NULL);
 
-  reg = hc08_reg_a;
-
-  loadRegFromAop (reg, AOP (right), 0);
-  freeAsmop (right, NULL, ic, TRUE);
+  loadRegFromAop (hc08_reg_x, AOP (right), 0);
+  emitcode ("tstx", "");
   emitBranch ("beq", tlbl1);
   emitLabel (tlbl);
   
@@ -6108,12 +6612,13 @@ genLeftShift (iCode * ic)
       rmwWithAop (shift, AOP (result), offset);  
       shift="rol";
     }
-  rmwWithReg ("dec", reg);
+  rmwWithReg ("dec", hc08_reg_x);
   emitBranch ("bne", tlbl);
   emitLabel (tlbl1);
-  hc08_freeReg (reg);
+  hc08_freeReg (hc08_reg_x);
   
   freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (right, NULL, ic, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
@@ -6188,8 +6693,9 @@ shiftRLong (operand * left, int offl,
         rmwWithReg ("asr", hc08_reg_x);
       else
         rmwWithReg ("lsr", hc08_reg_x);
-      rmwWithReg ("rol", hc08_reg_a);
+      rmwWithReg ("ror", hc08_reg_a);
       storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
+      loadRegFromAop (hc08_reg_xa, AOP (left), LSB);
     }
   else if (offl==MSB16)
     {
@@ -6198,14 +6704,27 @@ shiftRLong (operand * left, int offl,
         rmwWithReg ("asr", hc08_reg_a);
       else
         rmwWithReg ("lsr", hc08_reg_a);
+      loadRegFromAop (hc08_reg_x, AOP (left), MSB24);
       storeRegToAop (hc08_reg_a, AOP (result), MSB24);
+      loadRegFromAop (hc08_reg_a, AOP (left), MSB16);
     }
 
-  loadRegFromAop (hc08_reg_xa, AOP (left), offl);
   rmwWithReg ("ror", hc08_reg_x);
   rmwWithReg ("ror", hc08_reg_a);
   storeRegToAop (hc08_reg_xa, AOP (result), LSB);
 
+  if (offl==MSB16)
+    {
+      if (sign)
+        {
+          loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
+          storeRegSignToUpperAop (hc08_reg_a, AOP (result), MSB32, sign);
+        }
+      else
+        {
+          storeConstToAop (zero, AOP (result), MSB32);
+        }
+    }
 
   pullOrFreeReg (hc08_reg_x, needpulx);
   pullOrFreeReg (hc08_reg_a, needpula);
@@ -6262,7 +6781,8 @@ genrshFour (operand * result, operand * left,
          loadRegFromConst (hc08_reg_a, zero);
          XAccRsh (shCount-8, sign);
          accopWithAop ("ora", AOP (result), 1);
-         storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
+         storeRegToAop (hc08_reg_xa, AOP (result), 1);
+          storeRegSignToUpperAop (hc08_reg_x, AOP(result), 3, sign);
        }
     }
   else
@@ -6279,7 +6799,7 @@ genrshFour (operand * result, operand * left,
          loadRegFromAop (hc08_reg_a, AOP (left), 2);
          AccLsh (8-shCount);
          accopWithAop ("ora", AOP (result), 1);
-         storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
+         storeRegToAop (hc08_reg_a, AOP (result), 1);
          loadRegFromAop (hc08_reg_xa, AOP (left), 2);
          XAccRsh (shCount, sign);
          storeRegToAop (hc08_reg_xa, AOP (result), 2);
@@ -6308,7 +6828,7 @@ genRightShiftLiteral (operand * left,
   aopOp (result, ic, FALSE);
 
 #if VIEW_SIZE
-  D(emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
+  DD(emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
            AOP_SIZE (left)));
 #endif
 
@@ -6363,10 +6883,10 @@ genRightShift (iCode * ic)
   operand *right, *left, *result;
   sym_link *retype;
   int size, offset;
-//  char *l;
   symbol *tlbl, *tlbl1;
   char *shift;
   bool sign;
+  asmop *aopResult;
   
   D(emitcode (";     genRightShift",""));
 
@@ -6402,19 +6922,28 @@ genRightShift (iCode * ic)
      more that 32 bits make no sense anyway, ( the
      largest size of an object can be only 32 bits ) */
 
-  aopOp (left, ic, FALSE);
   aopOp (result, ic, FALSE);
+  aopOp (left, ic, FALSE);
+  aopResult = AOP (result);
 
-  if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result)))
-    AOP (result) = forceStackedAop (AOP (result));
-  
-  size = AOP_SIZE (result); 
-  offset = size-1;
-  while (size--)
+  if (sameRegs(AOP (right), AOP (result)) || IS_AOP_XA (AOP (result))
+      || isOperandVolatile (result, FALSE)) 
+    aopResult = forceStackedAop (AOP (result), sameRegs ( AOP (left), AOP (result)));
+
+  /* now move the left to the result if they are not the
+     same */
+  if (!sameRegs (AOP (left), aopResult))
     {
-      transferAopAop (AOP (left), offset, AOP (result), offset);
-      offset--;
+      size = AOP_SIZE (result);
+      offset = 0;
+      while (size--)
+       {
+         transferAopAop (AOP (left), offset, aopResult, offset);
+         offset++;
+       }
     }
+  freeAsmop (left, NULL, ic, TRUE);
+  AOP (result) = aopResult;
   
   tlbl = newiTempLabel (NULL);
   size = AOP_SIZE (result);
@@ -6423,8 +6952,9 @@ genRightShift (iCode * ic)
 
   loadRegFromAop (hc08_reg_x, AOP (right), 0);
   emitcode ("tstx", "");
-  emitcode ("beq", "%05d$", tlbl1->key + 100);
-  emitcode ("", "%05d$:", tlbl->key + 100);
+  emitBranch ("beq", tlbl1);
+  emitLabel (tlbl);
+
   shift= sign ? "asr" : "lsr";
   for (offset=size-1;offset>=0;offset--)
     {
@@ -6432,11 +6962,11 @@ genRightShift (iCode * ic)
       shift="ror";
     }
   rmwWithReg ("dec", hc08_reg_x);
-  emitcode ("bne","%05d$", tlbl->key + 100);
-  emitcode ("", "%05d$:", tlbl1->key + 100);
+  emitBranch ("bne", tlbl);
+  emitLabel (tlbl1);
+  hc08_freeReg (hc08_reg_x);
   
   freeAsmop (result, NULL, ic, TRUE);
-  freeAsmop (left, NULL, ic, TRUE);
   freeAsmop (right, NULL, ic, TRUE);
 }
 
@@ -6461,22 +6991,38 @@ genUnpackBits (operand * result, iCode *ifx)
   blen = SPEC_BLEN (etype);
   bstr = SPEC_BSTR (etype);
 
-  /* If the bitfield length is less than a byte */
-  if (blen < 8)
+  if (ifx && blen <= 8)
     {
       emitcode ("lda", ",x");
       hc08_dirtyReg (hc08_reg_a, FALSE);
-      if (!ifx)
-        {
-          AccRsh (bstr, FALSE);
-          emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
-          storeRegToAop (hc08_reg_a, AOP (result), offset++);
-        }
-      else
+      if (blen < 8)
         {
           emitcode ("and", "#0x%02x",
                     (((unsigned char) -1) >> (8 - blen)) << bstr);
         }
+      genIfxJump (ifx, "a");
+      return;
+    }
+  wassert (!ifx);
+
+  /* If the bitfield length is less than a byte */
+  if (blen < 8)
+    {
+      emitcode ("lda", ",x");
+      hc08_dirtyReg (hc08_reg_a, FALSE);
+      AccRsh (bstr, FALSE);
+      emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
+      if (!SPEC_USIGN (etype))
+        {
+          /* signed bitfield */
+          symbol *tlbl = newiTempLabel (NULL);
+
+          emitcode ("bit", "#0x%02x", 1<<(blen - 1));
+          emitcode ("beq", "%05d$", tlbl->key + 100);
+          emitcode ("ora", "#0x%02x", (unsigned char) (0xff << blen));
+          emitLabel (tlbl);
+        }
+      storeRegToAop (hc08_reg_a, AOP (result), offset++);
       goto finish;
     }
 
@@ -6486,8 +7032,7 @@ genUnpackBits (operand * result, iCode *ifx)
     {
       emitcode ("lda", ",x");
       hc08_dirtyReg (hc08_reg_a, FALSE);
-      if (!ifx)
-        storeRegToAop (hc08_reg_a, AOP (result), offset);
+      storeRegToAop (hc08_reg_a, AOP (result), offset);
       offset++;
       if (rlen>8)
         emitcode ("aix", "#1");
@@ -6498,6 +7043,16 @@ genUnpackBits (operand * result, iCode *ifx)
     {
       emitcode ("lda", ",x");
       emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
+      if (!SPEC_USIGN (etype))
+        {
+          /* signed bitfield */
+          symbol *tlbl = newiTempLabel (NULL);
+
+          emitcode ("bit", "#0x%02x", 1<<(rlen - 1));
+          emitcode ("beq", "%05d$", tlbl->key + 100);
+          emitcode ("ora", "#0x%02x", (unsigned char) (0xff << rlen));
+          emitLabel (tlbl);
+        }
       storeRegToAop (hc08_reg_a, AOP (result), offset++);
     }
 
@@ -6505,13 +7060,21 @@ finish:
   if (offset < rsize)
     {
       rsize -= offset;
-      while (rsize--)
-        storeConstToAop (zero, AOP (result), offset++);
-    }
+      if (SPEC_USIGN (etype))
+        {
+          while (rsize--)
+            storeConstToAop (zero, AOP (result), offset++);
+        }
+      else
+        {
+          /* signed bitfield: sign extension with 0x00 or 0xff */
+          emitcode ("rola", "");
+          emitcode ("clra", "");
+          emitcode ("sbc", zero);
   
-  if (ifx && !ifx->generated)
-    {
-      genIfxJump (ifx, "a");
+          while (rsize--)
+            storeRegToAop (hc08_reg_a, AOP (result), offset++);
+        }
     }
 }
 
@@ -6559,7 +7122,10 @@ genUnpackBitsImmed (operand * left,
           emitcode ("brclr", "#%d,%s,%05d$",
                     bstr, aopAdrStr (derefaop, 0, FALSE),
                     (tlbl->key + 100));
-          rmwWithReg ("inc", hc08_reg_a);
+          if (SPEC_USIGN (etype))
+            rmwWithReg ("inc", hc08_reg_a);
+          else
+            rmwWithReg ("dec", hc08_reg_a);
           emitLabel (tlbl);
           storeRegToAop (hc08_reg_a, AOP (result), offset);
           hc08_freeReg (hc08_reg_a);
@@ -6602,6 +7168,16 @@ genUnpackBitsImmed (operand * left,
           AccRsh (bstr, FALSE);
           emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8 - blen));
           hc08_dirtyReg (hc08_reg_a, FALSE);
+          if (!SPEC_USIGN (etype))
+            {
+              /* signed bitfield */
+              symbol *tlbl = newiTempLabel (NULL);
+
+              emitcode ("bit", "#0x%02x", 1<<(blen - 1));
+              emitcode ("beq", "%05d$", tlbl->key + 100);
+              emitcode ("ora", "#0x%02x", (unsigned char) (0xff << blen));
+              emitLabel (tlbl);
+            }
           storeRegToAop (hc08_reg_a, AOP (result), offset);
         }
       else
@@ -6631,6 +7207,16 @@ genUnpackBitsImmed (operand * left,
     {
       loadRegFromAop (hc08_reg_a, derefaop, size-offset-1);
       emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
+      if (!SPEC_USIGN (etype))
+        {
+          /* signed bitfield */
+          symbol *tlbl = newiTempLabel (NULL);
+
+          emitcode ("bit", "#0x%02x", 1<<(rlen - 1));
+          emitcode ("beq", "%05d$", tlbl->key + 100);
+          emitcode ("ora", "#0x%02x", (unsigned char) (0xff << rlen));
+          emitLabel (tlbl);
+        }
       storeRegToAop (hc08_reg_a, AOP (result), offset++);
     }
 
@@ -6638,8 +7224,21 @@ finish:
   if (offset < rsize)
     {
       rsize -= offset;
-      while (rsize--)
-        storeConstToAop (zero, AOP (result), offset++);
+      if (SPEC_USIGN (etype))
+        {
+          while (rsize--)
+            storeConstToAop (zero, AOP (result), offset++);
+        }
+      else
+        {
+          /* signed bitfield: sign extension with 0x00 or 0xff */
+          emitcode ("rola", "");
+          emitcode ("clra", "");
+          emitcode ("sbc", zero);
+
+          while (rsize--)
+            storeRegToAop (hc08_reg_a, AOP (result), offset++);
+        }
     }
   
   freeAsmop (NULL, derefaop, ic, TRUE);
@@ -6661,7 +7260,7 @@ genDataPointerGet (operand * left,
                   iCode * ic,
                    iCode * ifx)
 {
-  int size, offset = 0;
+  int size;
   asmop *derefaop;
   
   D(emitcode (";     genDataPointerGet",""));
@@ -6676,10 +7275,9 @@ genDataPointerGet (operand * left,
   while (size--)
     {
       if (!ifx)
-        transferAopAop (derefaop, offset, AOP (result), offset);
+        transferAopAop (derefaop, size, AOP (result), size);
       else
-        loadRegFromAop (hc08_reg_a, derefaop, offset);
-      offset++;
+        loadRegFromAop (hc08_reg_a, derefaop, size);
     }
 
   freeAsmop (NULL, derefaop, ic, TRUE);
@@ -7063,7 +7661,7 @@ genDataPointerSet (operand * right,
                   operand * result,
                   iCode * ic)
 {
-  int size, offset = 0;
+  int size;
   asmop *derefaop;
 
   D(emitcode (";     genDataPointerSet",""));
@@ -7077,8 +7675,7 @@ genDataPointerSet (operand * right,
   
   while (size--)
     {
-      transferAopAop (AOP (right), offset, derefaop, offset);
-      offset++;
+      transferAopAop (AOP (right), size, derefaop, size);
     }
 
   freeAsmop (right, NULL, ic, TRUE);
@@ -7177,6 +7774,30 @@ genIfx (iCode * ic, iCode * popIc)
 
   aopOp (cond, ic, FALSE);
 
+  /* If the condition is a literal, we can just do an unconditional */
+  /* branch or no branch */
+  if (AOP_TYPE (cond) == AOP_LIT)
+    {
+      unsigned long lit = (unsigned long) floatFromVal (AOP (cond)->aopu.aop_lit);
+      freeAsmop (cond, NULL, ic, TRUE);
+
+      /* if there was something to be popped then do it */
+      if (popIc)
+        genIpop (popIc);
+      if (lit)
+        {
+          if (IC_TRUE (ic))
+            emitBranch ("jmp", IC_TRUE (ic));
+        }
+      else
+        {
+          if (IC_FALSE (ic))
+            emitBranch ("jmp", IC_FALSE (ic));
+        }
+      ic->generated = 1;
+      return;
+    }
+
   /* get the value into acc */
   if (AOP_TYPE (cond) != AOP_CRY)
     asmopToBool (AOP (cond), FALSE);
@@ -7219,11 +7840,21 @@ genAddrOf (iCode * ic)
      variable */
   if (sym->onStack)
     {
-      /* if it has an offset then we need to compute
-         it */
+      /* if it has an offset then we need to compute it */
+      offset = _G.stackOfs + _G.stackPushes + sym->stack;
       hc08_useReg (hc08_reg_hx);
       emitcode ("tsx", "");
-      emitcode ("aix", "#%d", _G.stackOfs + _G.stackPushes +sym->stack);
+      while (offset > 127)
+        {
+          emitcode ("aix", "#127");
+          offset -= 127;
+        }
+      while (offset < -128)
+        {
+          emitcode ("aix", "#-128");
+          offset += 128;
+        }
+      emitcode ("aix", "#%d", offset);
       storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
       hc08_freeReg (hc08_reg_hx);
 
@@ -7264,7 +7895,7 @@ static void
 genAssign (iCode * ic)
 {
   operand *result, *right;
-  int size, offset;
+  int size;
 //  unsigned long lit = 0L;
 
   D(emitcode(";     genAssign",""));
@@ -7293,12 +7924,9 @@ genAssign (iCode * ic)
     
   /* general case */
   size = AOP_SIZE (result);
-  offset = 0;
-
   while (size--)
     {
-      transferAopAop (AOP (right), offset, AOP (result), offset);
-      offset++;
+      transferAopAop (AOP (right), size, AOP (result), size);
     }
 
 release:
@@ -7307,38 +7935,65 @@ release:
 }
 
 /*-----------------------------------------------------------------*/
-/* genJumpTab - genrates code for jump table                       */
+/* genJumpTab - generates code for jump table                       */
 /*-----------------------------------------------------------------*/
 static void
 genJumpTab (iCode * ic)
 {
   symbol *jtab;
-//  char *l;
-
+  symbol *jtablo = newiTempLabel (NULL);
+  symbol *jtabhi = newiTempLabel (NULL);
+  
   D(emitcode (";     genJumpTab",""));
 
   aopOp (IC_JTCOND (ic), ic, FALSE);
-  /* get the condition into accumulator */
-  loadRegFromAop (hc08_reg_a, AOP (IC_JTCOND (ic)), 0);
-  freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
-  /* multiply by three */
-  pushReg (hc08_reg_a, FALSE);
-  emitcode ("lsla", "");
-  emitcode ("add","1,s");
-  transferRegReg (hc08_reg_a, hc08_reg_x, TRUE);
-  loadRegFromConst (hc08_reg_h, zero);
-  pullReg (hc08_reg_a);
+  
+  if (hc08_reg_x->isFree && hc08_reg_x->isFree)
+    {
+      /* get the condition into x */
+      loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
+      freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
+      loadRegFromConst (hc08_reg_h, zero);
+
+      emitcode ("lda", "%05d$,x", jtabhi->key + 100);
+      emitcode ("ldx", "%05d$,x", jtablo->key + 100);
+      transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
+      emitcode ("jmp", ",x");
+
+      hc08_dirtyReg (hc08_reg_a, TRUE);
+      hc08_dirtyReg (hc08_reg_hx, TRUE);
+    }
+  else
+    {
+      adjustStack(-2);
+      pushReg(hc08_reg_hx, TRUE);
+      
+      /* get the condition into x */
+      loadRegFromAop (hc08_reg_x, AOP (IC_JTCOND (ic)), 0);
+      freeAsmop (IC_JTCOND (ic), NULL, ic, TRUE);
+      loadRegFromConst (hc08_reg_h, zero);
+
+      emitcode ("lda", "%05d$,x", jtabhi->key + 100);
+      emitcode ("sta", "3,s");
+      emitcode ("lda", "%05d$,x", jtablo->key + 100);
+      emitcode ("sta", "4,s");
+      
+      pullReg(hc08_reg_hx);
+      emitcode ("rts", "");
+      _G.stackPushes += 2;
+      updateCFA();
+    }
 
-  jtab = newiTempLabel (NULL);
-  emitcode ("jmp", "%05d$,x", jtab->key + 100);
-  emitcode ("", "%05d$:", jtab->key + 100);
   /* now generate the jump labels */
+  emitLabel (jtablo);
+  for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
+       jtab = setNextItem (IC_JTLABELS (ic)))
+    emitcode (".db", "%05d$", jtab->key + 100);
+  emitLabel (jtabhi);
   for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
        jtab = setNextItem (IC_JTLABELS (ic)))
-    emitcode ("jmp", "%05d$", jtab->key + 100);
+    emitcode (".db", ">%05d$", jtab->key + 100);
 
-  hc08_dirtyReg (hc08_reg_a, TRUE);
-  hc08_dirtyReg (hc08_reg_hx, TRUE);
 }
 
 /*-----------------------------------------------------------------*/
@@ -7429,7 +8084,7 @@ genCast (iCode * ic)
                    exit(1);
                }
            
-               sprintf(gpValStr, "#0x%d", gpVal);
+               sprintf(gpValStr, "#0x%x", gpVal);
                aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
            }       
 #endif
@@ -7685,7 +8340,7 @@ genhc08Code (iCode * lic)
 
   /* print the allocation information */
   if (allocInfo && currFunc)
-    printAllocInfo (currFunc, codeOutFile);
+    printAllocInfo (currFunc, codeOutBuf);
   /* if debug information required */
   if (options.debug && currFunc)
     {
@@ -7757,13 +8412,16 @@ genhc08Code (iCode * lic)
       if (options.iCodeInAsm) {
        char regsInUse[80];
        int i;
+        char *iLine;
 
        for (i=0; i<6; i++) {
          sprintf (&regsInUse[i],
                   "%c", ic->riu & (1<<i) ? i+'0' : '-'); 
        }
        regsInUse[i]=0;
+        iLine = printILine(ic);
        emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
+        dbuf_free(iLine);
       }
       /* if the result is marked as
          spilt and rematerializable or code for
@@ -7902,26 +8560,16 @@ genhc08Code (iCode * lic)
          break;
 
        case '>':
-         genCmpGt (ic, ifxForOp (IC_RESULT (ic), ic));
-         break;
-
        case '<':
-         genCmpLt (ic, ifxForOp (IC_RESULT (ic), ic));
-         break;
-
        case LE_OP:
        case GE_OP:
-       case NE_OP:
-
-         /* note these two are xlated by algebraic equivalence
-            during parsing SDCC.y */
-         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
-                 "got '>=' or '<=' shouldn't have come here");
-         break;
+          genCmp (ic, ifxForOp (IC_RESULT (ic), ic));
+          break;
 
+        case NE_OP:
        case EQ_OP:
-         genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
-         break;
+          genCmpEQorNE (ic, ifxForOp (IC_RESULT (ic), ic));
+          break;
 
        case AND_OP:
          genAndOp (ic);
@@ -8026,15 +8674,15 @@ genhc08Code (iCode * lic)
        }
 
       if (!hc08_reg_a->isFree)
-        D(emitcode("","; forgot to free a"));
+        DD(emitcode("","; forgot to free a"));
       if (!hc08_reg_x->isFree)
-        D(emitcode("","; forgot to free x"));
+        DD(emitcode("","; forgot to free x"));
       if (!hc08_reg_h->isFree)
-        D(emitcode("","; forgot to free h"));
+        DD(emitcode("","; forgot to free h"));
       if (!hc08_reg_hx->isFree)
-        D(emitcode("","; forgot to free hx"));
+        DD(emitcode("","; forgot to free hx"));
       if (!hc08_reg_xa->isFree)
-        D(emitcode("","; forgot to free xa"));
+        DD(emitcode("","; forgot to free xa"));
     }
 
   debugFile->writeFrameAddress (NULL, NULL, 0);  /* have no idea where frame is now */
@@ -8046,6 +8694,6 @@ genhc08Code (iCode * lic)
     peepHole (&lineHead);
 
   /* now do the actual printing */
-  printLine (lineHead, codeOutFile);
+  printLine (lineHead, codeOutBuf);
   return;
 }