* sim/ucsim/hc08.src/inst.cc (inst_condbranch): fixed simulation of
[fw/sdcc] / src / hc08 / gen.c
index 3d2101b566e885940e9115f67a9ad499c7083a89..c04d92059ca95ee3df24a7256fb340542bc98f9d 100644 (file)
@@ -411,18 +411,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;
@@ -651,7 +651,7 @@ loadRegFromAop (regs *reg, asmop *aop, int loffset)
     }
 
 forceload:
-  
+
   switch (regidx)
     {
       case A_IDX:
@@ -689,6 +689,14 @@ forceload:
           }
         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);
@@ -1123,7 +1131,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)
@@ -1329,10 +1337,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);
         if (strcmp ("tst", rmwop))
-         storeRegToAop (hc08_reg_a, aop, loffset);
+          storeRegToAop (hc08_reg_a, aop, loffset);
         pullOrFreeReg (hc08_reg_a, needpula);
         break;
       case AOP_DUMMY:
@@ -2077,67 +2085,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.       */
@@ -2658,7 +2605,7 @@ static void genSend(set *sendSet)
     iCode *sic;
 
     for (sic = setFirstItem (sendSet); sic;
-        sic = setNextItem (sendSet)) {
+         sic = setNextItem (sendSet)) {
          int size, offset = 0;
          aopOp (IC_LEFT (sic), sic, FALSE);
          size = AOP_SIZE (IC_LEFT (sic));
@@ -2688,7 +2635,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 */
@@ -2869,15 +2816,17 @@ 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);
@@ -2893,8 +2842,6 @@ genFunction (iCode * ic)
       return;
   }
 
-
-
   /* if this is an interrupt service routine then
      save h  */
   if (IFFUNC_ISISR (sym->type))
@@ -2903,47 +2850,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;
@@ -2951,7 +2903,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);
@@ -3218,7 +3170,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);
@@ -4161,108 +4113,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
+        return "bls";
+    case GE_OP:
+      if (sign)
+        return "bge";
       else
-        if (!sign)
-         outBitC (result);
-       else
-         outBitNV (result);
-        pullOrFreeReg(hc08_reg_a,needpula);
+        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);
@@ -4276,22 +4266,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);
@@ -4300,141 +4404,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     */
 /*-----------------------------------------------------------------*/
@@ -4462,7 +4553,7 @@ genPointerGetSetOfs (iCode *ic)
 {
   iCode *lic = ic->next;
   bool pset, pget;
-  int offset, size;
+  int size;
   symbol *sym;
   asmop *derefaop;
 
@@ -4542,14 +4633,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);
         }
 
@@ -4595,15 +4685,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;
@@ -4647,7 +4735,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 */
@@ -5265,7 +5353,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,
@@ -5640,11 +5728,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", "");
@@ -5717,11 +5809,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", "");
@@ -6216,6 +6312,7 @@ shiftLLong (operand * left, operand * result, int offr)
       loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
       rmwWithReg ("rol", hc08_reg_a);
       storeRegToAop (hc08_reg_a, AOP (result), offr+2);
+      storeConstToAop (zero, AOP (result), 0);
     }
 
   pullOrFreeReg (hc08_reg_x, needpulx);
@@ -6543,6 +6640,7 @@ shiftRLong (operand * left, int offl,
       else
         rmwWithReg ("lsr", hc08_reg_a);
       storeRegToAop (hc08_reg_a, AOP (result), MSB24);
+      storeRegSignToUpperAop (hc08_reg_a, AOP (result), MSB32, sign);
     }
 
   loadRegFromAop (hc08_reg_xa, AOP (left), offl);
@@ -6606,7 +6704,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
@@ -7005,7 +7104,7 @@ genDataPointerGet (operand * left,
                   iCode * ic,
                    iCode * ifx)
 {
-  int size, offset = 0;
+  int size;
   asmop *derefaop;
   
   D(emitcode (";     genDataPointerGet",""));
@@ -7020,10 +7119,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);
@@ -7407,7 +7505,7 @@ genDataPointerSet (operand * right,
                   operand * result,
                   iCode * ic)
 {
-  int size, offset = 0;
+  int size;
   asmop *derefaop;
 
   D(emitcode (";     genDataPointerSet",""));
@@ -7421,8 +7519,7 @@ genDataPointerSet (operand * right,
   
   while (size--)
     {
-      transferAopAop (AOP (right), offset, derefaop, offset);
-      offset++;
+      transferAopAop (AOP (right), size, derefaop, size);
     }
 
   freeAsmop (right, NULL, ic, TRUE);
@@ -7608,7 +7705,7 @@ static void
 genAssign (iCode * ic)
 {
   operand *result, *right;
-  int size, offset;
+  int size;
 //  unsigned long lit = 0L;
 
   D(emitcode(";     genAssign",""));
@@ -7637,12 +7734,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:
@@ -7651,38 +7745,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);
 }
 
 /*-----------------------------------------------------------------*/
@@ -8246,26 +8367,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);