Initial import
authorepetrich <epetrich@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Wed, 15 Oct 2003 04:30:41 +0000 (04:30 +0000)
committerepetrich <epetrich@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Wed, 15 Oct 2003 04:30:41 +0000 (04:30 +0000)
git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@2939 4a8a32a2-be11-0410-ad9d-d568d2c75423

src/hc08/Makefile [new file with mode: 0644]
src/hc08/Makefile.bcc [new file with mode: 0644]
src/hc08/gen.c [new file with mode: 0644]
src/hc08/gen.h [new file with mode: 0644]
src/hc08/hc08.dsp [new file with mode: 0644]
src/hc08/hc08a.dsp [new file with mode: 0644]
src/hc08/main.c [new file with mode: 0644]
src/hc08/main.h [new file with mode: 0644]
src/hc08/peeph.def [new file with mode: 0644]
src/hc08/ralloc.c [new file with mode: 0644]
src/hc08/ralloc.h [new file with mode: 0644]

diff --git a/src/hc08/Makefile b/src/hc08/Makefile
new file mode 100644 (file)
index 0000000..3b85636
--- /dev/null
@@ -0,0 +1,2 @@
+# Make all in this directory
+include ../port.mk
diff --git a/src/hc08/Makefile.bcc b/src/hc08/Makefile.bcc
new file mode 100644 (file)
index 0000000..8370b9f
--- /dev/null
@@ -0,0 +1,23 @@
+# Makefile for Borlad C++
+
+PRJDIR = ../..
+
+OBJ = gen.obj ralloc.obj main.obj
+LIB = port.lib
+
+!include $(PRJDIR)/Bcc.inc
+CFLAGS = $(CFLAGS) -I.. -I$(PRJDIR)
+
+all: $(LIB)
+
+main.obj: main.c peeph.rul
+
+$(LIB): $(OBJ)
+        if exist $(LIB) del $(LIB)
+        tlib $@ @&&!
++$(**: = &^
++)
+!
+
+.def.rul:
+        gawk -f ../SDCCpeeph.awk $< > $@
diff --git a/src/hc08/gen.c b/src/hc08/gen.c
new file mode 100644 (file)
index 0000000..29637fa
--- /dev/null
@@ -0,0 +1,7644 @@
+/*-------------------------------------------------------------------------
+  gen.c - source file for code generation for the 68HC08
+
+  Hacked for the 68HC08 by Erik Petrich (2003)
+  Adapted from the 8051 code generator by:
+    Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
+           and -  Jean-Louis VERN.jlvern@writeme.com (1999)
+    Bug Fixes  -  Wojciech Stryjewski  wstryj1@tiger.lsu.edu (1999 v2.1.9a)
+
+  This program is free software; you can redistribute it and/or modify it
+  under the terms of the GNU General Public License as published by the
+  Free Software Foundation; either version 2, or (at your option) any
+  later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+  In other words, you are welcome to use, share and improve this program.
+  You are forbidden to forbid anyone else to use, share and improve
+  what you give them.   Help stamp out software-hoarding!
+
+-------------------------------------------------------------------------*/
+
+//#define D(x)
+#define D(x) x
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "SDCCglobl.h"
+#include "newalloc.h"
+
+#include "common.h"
+#include "SDCCpeeph.h"
+#include "ralloc.h"
+#include "gen.h"
+
+char *aopLiteral (value * val, int offset);
+char *aopLiteralLong (value * val, int offset, int size);
+extern int allocInfo;
+
+static char *zero = "#0x00";
+static char *one = "#0x01";
+static char *spname;
+
+char *fReturnhc08[] =
+{"a", "x", "_ret2", "_ret3"};
+unsigned fReturnSizeHC08 = 4;  /* shared with ralloc.c */
+char **fReturn2 = fReturnhc08;
+
+
+static struct
+  {
+    short hxPushed;
+    short iyPushed;
+    short accInUse;
+    short inLine;
+    short debugLine;
+    short nRegsSaved;
+    int stackOfs;
+    int stackPushes;
+    short regsinuse;
+    set *sendSet;
+  }
+_G;
+
+static asmop *hc08_aop_pass[4];
+
+extern int hc08_ptrRegReq;
+extern int hc08_nRegs;
+extern FILE *codeOutFile;
+//static void saveRBank (int, iCode *, bool);
+static bool operandsEqu (operand * op1, operand * op2);
+static void loadRegFromConst (regs *reg, char *c);
+static char *aopName (asmop *aop);
+static asmop * newAsmop (short type);
+static char * aopAdrStr (asmop * aop, int loffset, bool bit16);
+#define RESULTONSTACK(x) \
+                         (IC_RESULT(x) && IC_RESULT(x)->aop && \
+                         IC_RESULT(x)->aop->type == AOP_STK )
+
+#define IS_AOP_HX(x) \
+        (((x)->type == AOP_REG) \
+         && ((x)->aopu.aop_reg[0] == hc08_reg_x) \
+         && ((x)->aopu.aop_reg[1] == hc08_reg_h) )
+
+#define IS_AOP_XA(x) \
+        (((x)->type == AOP_REG) \
+         && ((x)->aopu.aop_reg[0] == hc08_reg_a) \
+         && ((x)->aopu.aop_reg[1] == hc08_reg_x) )
+
+#define IS_AOP_A(x) \
+        (((x)->type == AOP_REG) \
+         && ((x)->aopu.aop_reg[0] == hc08_reg_a) \
+         && ((x)->size == 1) )
+
+#define IS_AOP_X(x) \
+        (((x)->type == AOP_REG) \
+         && ((x)->aopu.aop_reg[0] == hc08_reg_x) \
+         && ((x)->size == 1) )
+
+#define IS_AOP_H(x) \
+        (((x)->type == AOP_REG) \
+         && ((x)->aopu.aop_reg[0] == hc08_reg_h) \
+         && ((x)->size == 1) )
+         
+#define CLRC    emitcode("clc","")
+
+static lineNode *lineHead = NULL;
+static lineNode *lineCurr = NULL;
+
+#if 0
+static unsigned char SLMask[] =
+{0xFF, 0xFE, 0xFC, 0xF8, 0xF0,
+ 0xE0, 0xC0, 0x80, 0x00};
+static unsigned char SRMask[] =
+{0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
+ 0x07, 0x03, 0x01, 0x00};
+#endif
+
+#define LSB     0
+#define MSB16   1
+#define MSB24   2
+#define MSB32   3
+
+#define AOP(op) op->aop
+#define AOP_TYPE(op) AOP(op)->type
+#define AOP_SIZE(op) AOP(op)->size
+#define AOP_OP(aop) aop->op
+
+
+/*-----------------------------------------------------------------*/
+/* emitcode - writes the code into a file : for now it is simple    */
+/*-----------------------------------------------------------------*/
+static void
+emitcode (char *inst, char *fmt,...)
+{
+  va_list ap;
+  char lb[INITIAL_INLINEASM];
+  char *lbp = lb;
+
+  va_start (ap, fmt);
+
+  if (inst && *inst)
+    {
+      if (fmt && *fmt)
+       sprintf (lb, "%s\t", inst);
+      else
+       sprintf (lb, "%s", inst);
+      vsprintf (lb + (strlen (lb)), fmt, ap);
+    }
+  else
+    vsprintf (lb, fmt, ap);
+
+  while (isspace (*lbp))
+    lbp++;
+
+  if (lbp && *lbp)
+    lineCurr = (lineCurr ?
+               connectLine (lineCurr, newLineNode (lb)) :
+               (lineHead = newLineNode (lb)));
+  lineCurr->isInline = _G.inLine;
+  lineCurr->isDebug = _G.debugLine;
+
+  //printf("%s\n", lb);
+  va_end (ap);
+}
+
+static void
+emitBranch (char *branchop, symbol *tlbl)
+{
+  emitcode (branchop, "%05d$", (tlbl->key + 100));
+}
+
+static void
+emitLabel (symbol *tlbl)
+{
+  emitcode ("", "%05d$:", (tlbl->key +100));
+}
+
+
+
+/*--------------------------------------------------------------------------*/
+/* transferRegReg - Transfer from register(s) sreg to register(s) dreg. If  */
+/*                  freesrc is true, sreg is marked free and available for  */
+/*                  reuse. sreg and dreg must be of equal size              */
+/*--------------------------------------------------------------------------*/
+static void
+transferRegReg (regs *sreg, regs *dreg, bool freesrc)
+{
+  int srcidx;
+  int dstidx;
+  char error = 0;
+
+  /* Nothing to do if no destination. */
+  if (!dreg)
+    return;
+
+  /* But it's definately an error if there's no source. */
+  if (!sreg)
+    {
+      werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+             "NULL sreg in transferRegReg");
+      return;
+    }
+
+  emitcode ("", "; transferRegReg(%s,%s)",
+            sreg->name, dreg->name);  
+
+  srcidx = sreg->rIdx;
+  dstidx = dreg->rIdx;
+  
+  if (srcidx==dstidx)
+    return;
+    
+  switch (dstidx)
+    {
+      case A_IDX:
+        switch (srcidx)
+          {
+            case H_IDX: /* H to A */
+              emitcode ("pshh", "");
+              emitcode ("pula", "");
+              break;
+            case X_IDX: /* X to A */
+              emitcode ("txa", "");
+              break;
+            default:
+              error=1;
+          }
+        break;
+      case H_IDX:
+        switch (srcidx)
+          {
+            case A_IDX: /* A to H */
+              emitcode ("psha", "");
+              emitcode ("pulh", "");
+              break;
+            case X_IDX: /* X to H */
+              emitcode ("pshx", "");
+              emitcode ("pulh", "");
+              break;
+            default:
+              error=1;
+          }
+        break;
+      case X_IDX:
+        switch (srcidx)
+          {
+            case A_IDX: /* A to X */
+              emitcode ("tax", "");
+              break;
+            case H_IDX: /* H to X */
+              emitcode ("pshh", "");
+              emitcode ("pulx", "");
+              break;
+            default:
+              error=1;
+          }
+        break;
+      case HX_IDX:
+        switch (srcidx)
+          {
+            case XA_IDX: /* XA to HX */
+              emitcode ("pshx", "");
+              emitcode ("pulh", "");
+              emitcode ("tax", "");
+              break;
+            default:
+              error=1;
+          }
+        break;
+      case XA_IDX:
+        switch (srcidx)
+          {
+            case HX_IDX: /* HX to XA */
+              emitcode ("txa", "");
+              emitcode ("pshh", "");
+              emitcode ("pulx", "");
+              break;
+            default:
+              error=1;
+          }
+        break;
+      default:
+        error=1;
+    }
+
+  wassertl (!error, "bad combo in transferRegReg");
+
+  if (freesrc)
+    hc08_freeReg(sreg);
+
+  dreg->aop = sreg->aop;
+  dreg->aopofs = sreg->aopofs;
+  dreg->isFree = FALSE;
+  hc08_useReg(dreg);
+}
+
+/*--------------------------------------------------------------------------*/
+/* pushReg - Push register reg onto the stack. If freereg is true, reg is   */
+/*           marked free and available for reuse.                           */
+/*--------------------------------------------------------------------------*/
+static int
+pushReg (regs *reg, bool freereg)
+{
+  int regidx = reg->rIdx;
+  
+  switch (regidx)
+    {
+      case A_IDX:
+        emitcode ("psha", "");
+        _G.stackPushes++;
+        break;
+      case X_IDX:
+        emitcode ("pshx", "");
+        _G.stackPushes++;
+        break;
+      case H_IDX:
+        emitcode ("pshh", "");
+        _G.stackPushes++;
+        break;
+      case HX_IDX:
+        emitcode ("pshx", "");
+        emitcode ("pshh", "");
+        _G.stackPushes += 2;
+        break;
+      case XA_IDX:
+        emitcode ("psha", "");
+        emitcode ("pshx", "");
+        _G.stackPushes += 2;
+        break;
+      default:
+        break;
+      }
+   if (freereg)
+     hc08_freeReg(reg);
+  return -_G.stackOfs-_G.stackPushes;
+}
+
+/*--------------------------------------------------------------------------*/
+/* pullReg - Pull register reg off the stack.                               */
+/*--------------------------------------------------------------------------*/
+static void
+pullReg (regs *reg)
+{
+  int regidx = reg->rIdx;
+  
+  switch (regidx)
+    {
+      case A_IDX:
+        emitcode ("pula", "");
+        _G.stackPushes--;
+        break;
+      case X_IDX:
+        emitcode ("pulx", "");
+        _G.stackPushes--;
+        break;
+      case H_IDX:
+        emitcode ("pulh", "");
+        _G.stackPushes--;
+        break;
+      case HX_IDX:
+        emitcode ("pulx", "");
+        emitcode ("pulh", "");
+        _G.stackPushes -= 2;
+        break;
+      case XA_IDX:
+        emitcode ("pula", "");
+        emitcode ("pulx", "");
+        _G.stackPushes -= 2;
+        break;
+      default:
+        break;
+    }
+  hc08_useReg(reg);
+  hc08_dirtyReg(reg, FALSE);
+}
+
+/*--------------------------------------------------------------------------*/
+/* pullNull - Discard n bytes off the top of the stack                      */
+/*--------------------------------------------------------------------------*/
+static void
+pullNull (int n)
+{
+  if (n)
+    {
+      emitcode("ais","#%d",n);
+      _G.stackPushes -= n;
+    }
+}
+
+/*--------------------------------------------------------------------------*/
+/* pushRegIfUsed - Push register reg if marked in use. Returns true if the  */
+/*                 push was performed, false otherwise.                     */
+/*--------------------------------------------------------------------------*/
+static bool
+pushRegIfUsed (regs *reg)
+{
+  if (!reg->isFree)
+    {
+      pushReg (reg, TRUE);
+      return TRUE;
+    }
+  else
+    return FALSE;
+}
+
+/*--------------------------------------------------------------------------*/
+/* pullOrFreeReg - If needpull is true, register reg is pulled from the     */
+/*                 stack. Otherwise register reg is marked as free.         */
+/*--------------------------------------------------------------------------*/
+static void
+pullOrFreeReg (regs *reg, bool needpull)
+{
+  if (needpull)
+    pullReg (reg);
+  else
+    hc08_freeReg (reg);
+}
+
+/*--------------------------------------------------------------------------*/
+/* adjustStack - Adjust the stack pointer by n bytes.                       */
+/*--------------------------------------------------------------------------*/
+static void
+adjustStack (int n)
+{
+  _G.stackPushes -= n;
+  while (n)
+    {
+      if (n>127)
+        {
+          emitcode ("ais","#127");
+          n -= 127;
+        }
+      else if (n<-128)
+        {
+          emitcode ("ais","#-128");
+          n += 128;
+        }
+      else
+        {
+          emitcode ("ais", "#%d", n);
+          n = 0;
+        }
+    }    
+}
+
+
+/*--------------------------------------------------------------------------*/
+/* aopName - Return a string with debugging information about an asmop.     */
+/*--------------------------------------------------------------------------*/
+static char *
+aopName (asmop *aop)
+{
+  static char buffer[256];
+  char *buf = buffer;
+  
+  if (!aop)
+    return "(asmop*)NULL";
+
+  switch (aop->type)
+    {
+      case AOP_IMMD:
+        sprintf (buf,"IMMD(%s)", aop->aopu.aop_immd.aop_immd1);
+        return buf;
+      case AOP_LIT:
+        sprintf (buf,"LIT(%s)", aopLiteral (aop->aopu.aop_lit, 0));
+        return buf;
+      case AOP_DIR:
+        sprintf (buf,"DIR(%s)", aop->aopu.aop_dir);
+        return buf;
+      case AOP_EXT:
+        sprintf (buf,"EXT(%s)", aop->aopu.aop_dir);
+        return buf;
+      case AOP_SOF:
+        sprintf (buf,"SOF(%s)", OP_SYMBOL (aop->op)->name);
+        return buf;
+      case AOP_REG:
+        sprintf (buf, "REG(%s,%s,%s,%s)",
+                 aop->aopu.aop_reg[3] ? aop->aopu.aop_reg[3]->name : "-",
+                 aop->aopu.aop_reg[2] ? aop->aopu.aop_reg[2]->name : "-",
+                 aop->aopu.aop_reg[1] ? aop->aopu.aop_reg[1]->name : "-",
+                 aop->aopu.aop_reg[0] ? aop->aopu.aop_reg[0]->name : "-");
+        return buf;
+      case AOP_STK:
+        return "STK";
+      case AOP_STR:
+        return "STR";
+      default:
+        sprintf (buf,"?%d", aop->type);
+        return buf;
+    }
+
+  return "?";
+}
+
+
+/*--------------------------------------------------------------------------*/
+/* loadRegFromAop - Load register reg from logical offset loffset of aop.   */
+/*--------------------------------------------------------------------------*/
+static void
+loadRegFromAop (regs *reg, asmop *aop, int loffset)
+{
+  int regidx = reg->rIdx;
+
+  if (aop->stacked && aop->stk_aop[loffset])
+    {
+      loadRegFromAop (reg, aop->stk_aop[loffset], 0);
+      return;
+    }
+
+#if 0
+  printf("loadRegFromAop called\n");
+  if (!reg)
+    {
+      printf(" reg = NULL\n");
+      return;
+    }
+  printf(" reg = %s\n", reg->name);
+  if (!aop)
+    {
+      printf(" aop = NULL\n");
+      return;
+    }
+  printf(" aop->type = %d\n", aop->type);
+  printf(" loffset = %d\n", loffset);
+
+  if (aop->op)
+    printf(" aop has operand link\n");
+  else
+    printf(" aop missing operand link\n");
+  if (reg->aop)
+    printf(" reg has operand link\n");
+  else
+    printf(" reg missing operand link\n");
+#endif
+
+  emitcode ("", ";     loadRegFromAop (%s, %s, %d)",
+            reg->name, aopName (aop), loffset);
+       
+  /* If operand is volatile, we cannot optimize. */
+  if (!aop->op || isOperandVolatile (aop->op, FALSE))
+    goto forceload;
+
+      
+  /* If this register already has this offset of the operand
+     then we need only mark it as in use. */
+  if (reg->aop && reg->aop->op && aop->op
+      && operandsEqu(reg->aop->op,aop->op)
+      && (reg->aopofs == loffset))
+    {
+      hc08_useReg(reg);
+      emitcode ("","; already had correct value for %s", reg->name);
+      return;
+    }
+
+  /* TODO: check to see if we can transfer from another register */
+
+  if (hc08_reg_h->aop && hc08_reg_h->aop->op && aop->op
+      && operandsEqu(hc08_reg_h->aop->op,aop->op)
+      && (hc08_reg_h->aopofs == loffset))
+    {
+      emitcode ("","; found correct value for %s in h", reg->name);
+      transferRegReg (hc08_reg_h, reg, FALSE);
+      hc08_useReg (reg);
+      return;
+    }
+      
+
+  if (hc08_reg_x->aop && hc08_reg_x->aop->op && aop->op
+      && operandsEqu(hc08_reg_x->aop->op,aop->op)
+      && (hc08_reg_x->aopofs == loffset))
+    {
+      emitcode ("","; found correct value for %s in x", reg->name);
+      transferRegReg (hc08_reg_x, reg, FALSE);
+      hc08_useReg (reg);
+      return;
+    }
+    
+  if (hc08_reg_a->aop && hc08_reg_a->aop->op && aop->op
+      && operandsEqu(hc08_reg_a->aop->op,aop->op)
+      && (hc08_reg_a->aopofs == loffset))
+    {
+      emitcode ("","; found correct value for %s in a", reg->name);
+      transferRegReg (hc08_reg_a, reg, FALSE);
+      hc08_useReg (reg);
+      return;
+    }
+
+forceload:
+
+  switch (regidx)
+    {
+      case A_IDX:
+        if (aop->type == AOP_REG)
+          {
+            if (loffset < aop->size)
+              transferRegReg(aop->aopu.aop_reg[loffset], reg, FALSE);
+            else
+              emitcode ("clra", ""); /* TODO: handle sign extension */
+          }
+        else
+          emitcode ("lda","%s", aopAdrStr (aop, loffset, FALSE));
+        break;
+      case X_IDX:
+        if (aop->type == AOP_REG)
+          {
+            if (loffset < aop->size)
+              transferRegReg(aop->aopu.aop_reg[loffset], reg, FALSE);
+            else
+              emitcode ("clrx", ""); /* TODO: handle sign extension */
+          }
+        else
+          emitcode ("ldx","%s", aopAdrStr (aop, loffset, FALSE));
+        break;
+      case H_IDX:
+        if (hc08_reg_a->isFree)
+          {
+            loadRegFromAop (hc08_reg_a, aop, loffset);
+            transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
+          }
+        else if (hc08_reg_x->isFree)
+          {
+            loadRegFromAop (hc08_reg_x, aop, loffset);
+            transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
+          }
+        else
+          {
+            pushReg (hc08_reg_a, TRUE);
+            loadRegFromAop (hc08_reg_a, aop, loffset);
+            transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
+            pullReg (hc08_reg_a);
+          }
+        break;
+      case HX_IDX:
+        if (IS_AOP_HX(aop))
+          break;
+        else if (IS_AOP_XA(aop))
+            transferRegReg (hc08_reg_xa, hc08_reg_hx, FALSE);
+        else if ((aop->type == AOP_DIR))
+          {
+            if (aop->size>(loffset+1))
+              emitcode ("ldhx","%s", aopAdrStr (aop, loffset+1, TRUE));
+            else
+              {
+                loadRegFromAop (hc08_reg_x, aop, loffset);
+                loadRegFromConst (hc08_reg_h, zero);
+              }
+          }
+        else if ((aop->type == AOP_LIT) || (aop->type == AOP_IMMD))
+          {
+            emitcode ("ldhx","%s", aopAdrStr (aop, loffset, TRUE));
+          }
+        else
+          {
+            bool needpula;
+            needpula = pushRegIfUsed (hc08_reg_a);
+            loadRegFromAop (hc08_reg_a, aop, loffset+1);
+            loadRegFromAop (hc08_reg_x, aop, loffset);
+            transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
+            pullOrFreeReg (hc08_reg_a, needpula);
+          }
+        break;
+      case XA_IDX:
+        if (IS_AOP_XA(aop))
+          break;
+        else if (IS_AOP_HX(aop))
+          transferRegReg (hc08_reg_hx, hc08_reg_xa, FALSE);
+        else
+          {
+            loadRegFromAop (hc08_reg_a, aop, loffset);
+            loadRegFromAop (hc08_reg_x, aop, loffset+1);
+          }
+        break;
+    }    
+
+// ignore caching for now
+#if 0
+  reg->aop = aop;
+  reg->aopofs = loffset;
+#endif
+}
+
+
+/*--------------------------------------------------------------------------*/
+/* 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             */
+/*--------------------------------------------------------------------------*/
+static asmop *
+forceStackedAop (asmop *aop)
+{
+  int loffset;
+  asmop *newaop = newAsmop (aop->type);
+  memcpy (newaop, aop, sizeof(*newaop));
+  
+  emitcode("", "; forcedStackAop %s", aopName(aop));
+  for (loffset=0; loffset < newaop->size; loffset++)
+    {
+      asmop *aopsof = newAsmop (AOP_SOF);
+      aopsof->size = 1;
+      aopsof->aopu.aop_stk = pushReg (hc08_reg_a, FALSE);
+      aopsof->op = aop->op;
+      newaop->stk_aop[loffset] = aopsof;
+    }
+  newaop->stacked = 1;
+  return newaop;
+}
+
+
+/*--------------------------------------------------------------------------*/
+/* storeRegToAop - Store register reg to logical offset loffset of aop.     */
+/*--------------------------------------------------------------------------*/
+static void
+storeRegToAop (regs *reg, asmop *aop, int loffset)
+{
+  int regidx = reg->rIdx;
+  #if 0
+  regs *otherreg;
+  int otheridx;
+  #endif
+
+  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
+      && (aop->stk_aop[loffset] || aop->stk_aop[loffset+1]))
+    {
+      storeRegToAop (hc08_reg_h, aop, loffset+1);
+      storeRegToAop (hc08_reg_x, aop, loffset);
+      return;
+    }
+
+  if ((reg->rIdx == XA_IDX) && aop->stacked
+      && (aop->stk_aop[loffset] || aop->stk_aop[loffset+1]))
+    {
+      storeRegToAop (hc08_reg_x, aop, loffset+1);
+      storeRegToAop (hc08_reg_a, aop, loffset);
+      return;
+    }
+
+  if (aop->stacked && aop->stk_aop[loffset])
+    {
+      storeRegToAop (reg, aop->stk_aop[loffset], 0);
+      return;
+    }
+
+  if (aop->type == AOP_STR)
+    {
+      if (loffset==0)
+        transferRegReg (reg, hc08_reg_x, FALSE);
+      else if (loffset==1)
+        transferRegReg (reg, hc08_reg_h, FALSE);
+      return;
+    }
+
+    switch (regidx)
+    {
+      case A_IDX:
+        if ((aop->type == AOP_REG) && (loffset < aop->size))
+          transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
+        else
+          emitcode ("sta","%s", aopAdrStr (aop, loffset, FALSE));
+        break;
+      case X_IDX:
+        if ((aop->type == AOP_REG) && (loffset < aop->size))
+          transferRegReg(reg, aop->aopu.aop_reg[loffset], FALSE);
+        else
+          emitcode ("stx","%s", aopAdrStr (aop, loffset, FALSE));
+        break;
+      case H_IDX:
+        if (hc08_reg_a->isFree)
+          {
+            transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
+            storeRegToAop (hc08_reg_a, aop, loffset);
+            hc08_freeReg (hc08_reg_a);
+          }
+        else if (hc08_reg_x->isFree)
+          {
+            transferRegReg (hc08_reg_h, hc08_reg_x, FALSE);
+            storeRegToAop (hc08_reg_x, aop, loffset);
+            hc08_freeReg (hc08_reg_x);
+          }
+        else
+          {
+            pushReg (hc08_reg_a, TRUE);
+            transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
+            storeRegToAop (hc08_reg_a, aop, loffset);
+            pullReg (hc08_reg_a);
+          }
+        break;
+      case HX_IDX:
+        if ((aop->type == AOP_DIR) )
+          {
+            emitcode("sthx","%s", aopAdrStr (aop, loffset+1, TRUE));
+          }
+        else if (IS_AOP_XA(aop))
+          transferRegReg(reg, hc08_reg_xa, FALSE);
+        else if (IS_AOP_HX(aop))
+          break;
+        else
+          {
+            bool needpula;
+            needpula = pushRegIfUsed (hc08_reg_a);
+            transferRegReg (hc08_reg_h, hc08_reg_a, FALSE);
+            storeRegToAop (hc08_reg_a, aop, loffset+1);
+            storeRegToAop (hc08_reg_x, aop, loffset);
+            pullOrFreeReg (hc08_reg_a, needpula);
+          }
+        break;
+      case XA_IDX:
+        if (IS_AOP_HX(aop))
+          transferRegReg(reg, hc08_reg_hx, FALSE);
+        else if (IS_AOP_XA(aop))
+          break;
+        else
+          {
+            storeRegToAop (hc08_reg_a, aop, loffset);
+            storeRegToAop (hc08_reg_x, aop, loffset+1);
+          }
+        break;
+    }    
+
+/* Disable the register tracking for now */
+#if 0
+  //if (!reg->aop || (reg->aop && (reg->aop != aop)))
+    {
+      //if (reg->aop!=aop)
+        for (otheridx=0;otheridx<hc08_nRegs;otheridx++)
+          {
+            otherreg=hc08_regWithIdx(otheridx);
+            if (otherreg && otherreg->aop
+                && otherreg->aop->op && aop->op
+                && operandsEqu(otherreg->aop->op,aop->op)
+                && (otherreg->aopofs == loffset))
+              {
+                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;
+          emitcode("","; marking hx stale");
+        }
+      if ((!hc08_reg_x->aop || !hc08_reg_a->aop) && hc08_reg_xa->aop)
+        {
+          hc08_reg_xa->aop = NULL;
+          emitcode("","; marking xa stale");
+        }
+    
+      reg->aop = aop;
+      reg->aopofs = loffset;
+    }
+#endif
+}
+
+/*--------------------------------------------------------------------------*/
+/* loadRegFromConst - Load register reg from constant c.                    */
+/*--------------------------------------------------------------------------*/
+static void
+loadRegFromConst (regs *reg, char *c)
+{
+  switch (reg->rIdx)
+    {
+      case A_IDX:
+        if (!strcmp(c,zero))
+          emitcode ("clra", "");
+        else
+          emitcode ("lda", "%s", c);
+        break;
+      case X_IDX:
+        if (!strcmp(c,zero))
+          emitcode ("clrx", "");
+        else
+          emitcode ("ldx", "%s", c);
+        break;
+      case H_IDX:
+        if (!strcmp(c,zero))
+          emitcode ("clrh", "");
+        else if (hc08_reg_a->isFree)
+          {
+            loadRegFromConst (hc08_reg_a, c);
+            transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
+          }
+        else if (hc08_reg_x->isFree)
+          {
+            loadRegFromConst (hc08_reg_x, c);
+            transferRegReg (hc08_reg_x, hc08_reg_h, TRUE);
+          }
+        else
+          {
+            pushReg (hc08_reg_a, TRUE);
+            loadRegFromConst (hc08_reg_a, c);
+            transferRegReg (hc08_reg_a, hc08_reg_h, TRUE);
+            pullReg (hc08_reg_a);
+          }
+        break;
+      case HX_IDX:
+        emitcode ("ldhx", "%s", c);
+        break;
+      case XA_IDX:
+        emitcode ("lda", "%s", c);
+        emitcode ("ldx", "%s >> 8", c);
+        break;
+      default:
+        werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+               "Bad rIdx in loadRegFromConst");
+       return;
+    }
+  hc08_useReg (reg);
+}
+
+
+/*--------------------------------------------------------------------------*/
+/* storeConstToAop- Store constant c to logical offset loffset of asmop aop.*/
+/*--------------------------------------------------------------------------*/
+static void
+storeConstToAop (char *c, asmop *aop, int loffset)
+{
+  if (aop->stacked && aop->stk_aop[loffset])
+    {
+      storeConstToAop (c, aop->stk_aop[loffset], 0);
+      return;
+    }
+
+  switch (aop->type)
+    {
+      case AOP_DIR:
+        if (!strcmp(c,zero))
+          emitcode ("clr", "%s", aopAdrStr (aop, loffset, FALSE));
+        else
+          emitcode ("mov", "%s,%s", c, aopAdrStr (aop, loffset, FALSE));
+        break;
+      case AOP_REG:
+        if (loffset>(aop->size-1))
+          break;
+        loadRegFromConst (aop->aopu.aop_reg[loffset], c);
+        break;
+      default:
+        if (hc08_reg_a->isFree)
+          {
+            loadRegFromConst (hc08_reg_a, c);
+            storeRegToAop( hc08_reg_a, aop, loffset);
+            hc08_freeReg (hc08_reg_a);
+          }
+        else if (hc08_reg_x->isFree)
+          {
+            loadRegFromConst (hc08_reg_x, c);
+            storeRegToAop( hc08_reg_x, aop, loffset);
+            hc08_freeReg (hc08_reg_x);
+          }
+        else
+          {
+            pushReg (hc08_reg_a, TRUE);
+            loadRegFromConst (hc08_reg_a, c);
+            storeRegToAop( hc08_reg_a, aop, loffset);
+            pullReg (hc08_reg_a);
+          }
+    }
+}
+
+
+/*--------------------------------------------------------------------------*/
+/* storeRegSignToUpperAop - If isSigned is true, the sign bit of register   */
+/*                          reg is extended to fill logical offsets loffset */
+/*                          and above of asmop aop. Otherwise, logical      */
+/*                          offsets loffset and above of asmop aop are      */
+/*                          zeroed. reg must be an 8-bit register.          */
+/*--------------------------------------------------------------------------*/
+static void
+storeRegSignToUpperAop (regs *reg, asmop *aop, int loffset, bool isSigned)
+{
+//  int regidx = reg->rIdx;
+  int size = aop->size;
+  
+  if (size<=loffset)
+    return;
+  
+  if (!isSigned)
+    {
+      /* Unsigned case */
+      while (loffset<size)
+        storeConstToAop(zero, aop, loffset++);
+    }
+  else
+    {
+      /* Signed case */
+      transferRegReg (reg, hc08_reg_a, FALSE);
+      emitcode ("rola","");
+      emitcode ("clra","");
+      emitcode ("sbc", "#0");
+      hc08_useReg (hc08_reg_a);
+      while (loffset<size)
+        storeRegToAop (hc08_reg_a, aop, loffset++);
+      hc08_freeReg (hc08_reg_a);
+    }
+}
+
+/*--------------------------------------------------------------------------*/
+/* storeRegToFullAop - Store register reg to asmop aop with appropriate     */
+/*                     padding and/or truncation as needed. If isSigned is  */
+/*                     true, sign extension will take place in the padding. */
+/*--------------------------------------------------------------------------*/
+static void
+storeRegToFullAop (regs *reg, asmop *aop, bool isSigned)
+{
+  int regidx = reg->rIdx;
+  int size = aop->size;
+
+  switch (regidx)
+    {
+      case A_IDX:
+      case X_IDX:
+      case H_IDX:
+        storeRegToAop (reg, aop, 0);
+        storeRegSignToUpperAop (reg, aop, 1, isSigned);
+        break;
+      case HX_IDX:
+        if (size==1)
+          {
+            storeRegToAop (hc08_reg_x, aop, 0);
+          }
+        else
+          {
+            storeRegToAop (reg, aop, 0);
+            storeRegSignToUpperAop (hc08_reg_h, aop, 2, isSigned);
+          }
+        break;
+      case XA_IDX:
+        if (size==1)
+          {
+            storeRegToAop (hc08_reg_a, aop, 0);
+          }
+        else
+          {
+            storeRegToAop (reg, aop, 0);
+            storeRegSignToUpperAop (hc08_reg_x, aop, 2, isSigned);
+          }
+        break;
+    }
+}
+
+/*--------------------------------------------------------------------------*/
+/* transferAopAop - Transfer the value at logical offset srcofs of asmop    */
+/*                  srcaop to logical offset dstofs of asmop dstofs.        */
+/*--------------------------------------------------------------------------*/
+static void
+transferAopAop (asmop *srcaop, int srcofs, asmop *dstaop, int dstofs)
+{
+  bool needpula = FALSE;
+  regs *reg = NULL;
+  int regIdx;
+  bool keepreg = FALSE;
+
+  if (srcaop->stacked && srcaop->stk_aop[srcofs])
+    {
+      transferAopAop (srcaop->stk_aop[srcofs], 0, dstaop, dstofs);
+      return;
+    }
+
+  if (dstaop->stacked && dstaop->stk_aop[srcofs])
+    {
+      transferAopAop (srcaop, srcofs, dstaop->stk_aop[dstofs], 0);
+      return;
+    }
+
+//  emitcode ("", "; transferAopAop (%s, %d, %s, %d)",
+//            aopName (srcaop), srcofs, aopName (dstaop), dstofs);  
+//  emitcode ("", "; srcaop->type = %d", srcaop->type);
+//  emitcode ("", "; dstaop->type = %d", dstaop->type);
+  
+  if (dstofs >= dstaop->size)
+    return;
+
+  if ((dstaop->type == AOP_DIR)
+      && ((srcaop->type == AOP_DIR) || (srcaop->type == AOP_LIT)) )
+    {
+      emitcode("mov", "%s,%s", aopAdrStr(srcaop, srcofs, FALSE),
+               aopAdrStr(dstaop, dstofs, FALSE));
+      return;
+    }
+
+  if (dstaop->type == AOP_REG)
+    {
+      regIdx = dstaop->aopu.aop_reg[dstofs]->rIdx;
+      if ((regIdx == A_IDX) || (regIdx == X_IDX))
+        {
+          reg = dstaop->aopu.aop_reg[dstofs];
+          keepreg = TRUE;
+        }
+    }
+
+  if ((srcaop->type == AOP_REG) && (srcaop->aopu.aop_reg[srcofs]))
+    {
+      regIdx = srcaop->aopu.aop_reg[srcofs]->rIdx;
+      if ((regIdx == A_IDX) || (regIdx == X_IDX))
+        {
+          reg = srcaop->aopu.aop_reg[srcofs];
+          keepreg = TRUE;
+        }
+    }
+
+  if (!reg)
+    {
+      if (hc08_reg_a->isFree)
+        reg = hc08_reg_a;
+      else if (hc08_reg_x->isFree)
+        reg = hc08_reg_x;  
+      else
+        {
+          pushReg (hc08_reg_a, TRUE);
+          needpula = TRUE;
+          reg = hc08_reg_a;
+        }
+    }
+  
+  loadRegFromAop (reg, srcaop, srcofs);
+  storeRegToAop (reg, dstaop, dstofs);
+  
+  if (!keepreg)
+    pullOrFreeReg (hc08_reg_a, needpula);
+}
+
+
+/*--------------------------------------------------------------------------*/
+/* accopWithMisc - Emit accumulator modifying instruction accop with the    */
+/*                 parameter param.                                         */
+/*--------------------------------------------------------------------------*/
+static void
+accopWithMisc (char *accop, char *param)
+{
+  emitcode (accop, "%s", param);
+  hc08_dirtyReg (hc08_reg_a, FALSE);
+}
+
+/*--------------------------------------------------------------------------*/
+/* accopWithAop - Emit accumulator modifying instruction accop with the     */
+/*                byte at logical offset loffset of asmop aop.              */
+/*                Supports: adc, add, and, bit, cmp, eor, ora, sbc, sub     */
+/*--------------------------------------------------------------------------*/
+static void
+accopWithAop (char *accop, asmop *aop, int loffset)
+{
+  if (aop->stacked && aop->stk_aop[loffset])
+    {
+      accopWithAop (accop, aop->stk_aop[loffset], 0);
+      return;
+    }
+    
+  if (aop->type == AOP_REG)
+    {
+      pushReg (aop->aopu.aop_reg[loffset], FALSE);
+      emitcode (accop, "1,s");
+      pullNull (1);
+    }
+  else
+    emitcode (accop, "%s", aopAdrStr (aop, loffset, FALSE));
+
+  hc08_dirtyReg (hc08_reg_a, FALSE);
+}
+
+
+/*--------------------------------------------------------------------------*/
+/* rmwWithReg - Emit read/modify/write instruction rmwop with register reg. */
+/*              byte at logical offset loffset of asmop aop. Register reg   */
+/*              must be 8-bit.                                              */
+/*              Supports: com, dec, inc, lsl, lsr, neg, rol, ror            */
+/*--------------------------------------------------------------------------*/
+static void
+rmwWithReg (char *rmwop, regs *reg)
+{
+  char rmwbuf[10];
+  char *rmwaop = rmwbuf;
+
+  if (reg->rIdx == A_IDX)
+    {
+      sprintf(rmwaop,"%sa", rmwop);
+      emitcode (rmwaop, "");
+      hc08_dirtyReg (hc08_reg_a, FALSE);
+    }
+  else if (reg->rIdx == X_IDX)
+    {
+      sprintf(rmwaop,"%sx", rmwop);
+      emitcode (rmwaop, "");
+      hc08_dirtyReg (hc08_reg_a, FALSE);
+    }
+  else if (hc08_reg_a->isFree)
+    {
+      transferRegReg(reg, hc08_reg_a, FALSE);
+      sprintf(rmwaop,"%sa", rmwop);
+      emitcode (rmwaop, "");
+      hc08_dirtyReg (hc08_reg_a, FALSE);
+      transferRegReg(hc08_reg_a, reg, TRUE);
+    }
+  else
+    {
+      pushReg (reg, FALSE);
+      emitcode (rmwop, "1,s");
+      pullReg (reg);
+      hc08_dirtyReg (reg, FALSE);
+    }
+}
+
+/*--------------------------------------------------------------------------*/
+/* 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          */
+/*--------------------------------------------------------------------------*/
+static void
+rmwWithAop (char *rmwop, asmop *aop, int loffset)
+{
+  bool needpula = FALSE;
+
+  if (aop->stacked && aop->stk_aop[loffset])
+    {
+      rmwWithAop (rmwop, aop->stk_aop[loffset], 0);
+      return;
+    }
+  
+  switch (aop->type)
+    {
+      case AOP_REG:
+        rmwWithReg (rmwop, aop->aopu.aop_reg[loffset]);
+        break;
+      case AOP_EXT:
+        needpula = pushRegIfUsed (hc08_reg_a);
+       loadRegFromAop (hc08_reg_a, aop, loffset);
+        rmwWithReg (rmwop, hc08_reg_a);
+       storeRegToAop (hc08_reg_a, aop, loffset);
+        pullOrFreeReg (hc08_reg_a, needpula);
+        break;
+      default:
+        emitcode (rmwop, "%s", aopAdrStr (aop, loffset, FALSE));
+   }
+   
+}
+
+
+/*-----------------------------------------------------------------*/
+/* newAsmop - creates a new asmOp                                  */
+/*-----------------------------------------------------------------*/
+static asmop *
+newAsmop (short type)
+{
+  asmop *aop;
+
+  aop = Safe_calloc (1, sizeof (asmop));
+  aop->type = type;
+  aop->op = NULL;
+  return aop;
+}
+
+#if 0
+/*-----------------------------------------------------------------*/
+/* pointerCode - returns the code for a pointer type               */
+/*-----------------------------------------------------------------*/
+static int
+pointerCode (sym_link * etype)
+{
+
+  return PTR_TYPE (SPEC_OCLS (etype));
+
+}
+#endif
+
+/*-----------------------------------------------------------------*/
+/* aopForSym - for a true symbol                                   */
+/*-----------------------------------------------------------------*/
+static asmop *
+aopForSym (iCode * ic, symbol * sym, bool result)
+{
+  asmop *aop;
+  memmap *space;
+
+  wassertl (ic != NULL, "Got a null iCode");
+  wassertl (sym != NULL, "Got a null symbol");
+
+//  printf("in aopForSym for symbol %s\n", sym->name);
+
+  space = SPEC_OCLS (sym->etype);
+
+  /* if already has one */
+  if (sym->aop)
+    {
+      return sym->aop;
+    }
+
+  /* special case for a function */
+  if (IS_FUNC (sym->type))
+    {
+      sym->aop = aop = newAsmop (AOP_IMMD);
+      aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (sym->rname) + 1);
+      strcpy (aop->aopu.aop_immd.aop_immd1, sym->rname);
+      aop->size = FPTRSIZE;
+      return aop;
+    }
+
+  /* if it is in direct space */
+  if (IN_DIRSPACE (space))
+    {
+      sym->aop = aop = newAsmop (AOP_DIR);
+      aop->aopu.aop_dir = sym->rname;
+      aop->size = getSize (sym->type);
+      return aop;
+    }
+
+  /* if it is in far space */
+  if (IN_FARSPACE (space))
+    {
+      sym->aop = aop = newAsmop (AOP_EXT);
+      aop->aopu.aop_dir = sym->rname;
+      aop->size = getSize (sym->type);
+      return aop;
+    }
+
+  if (IN_STACK (sym->etype))
+    {
+      sym->aop = aop = newAsmop (AOP_SOF);
+      aop->aopu.aop_dir = sym->rname;
+      aop->size = getSize (sym->type);
+      aop->aopu.aop_stk = sym->stack;
+      return aop;
+    }
+    
+
+
+  werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+         "aopForSym should never reach here");
+
+  exit(1);
+  
+  /* if it is in code space */
+  if (IN_CODESPACE (space))
+    aop->code = 1;
+
+  return aop;
+}
+
+/*-----------------------------------------------------------------*/
+/* aopForRemat - rematerialzes an object                           */
+/*-----------------------------------------------------------------*/
+static asmop *
+aopForRemat (symbol * sym)
+{
+  iCode *ic = sym->rematiCode;
+  asmop *aop = newAsmop (AOP_IMMD);
+  int ptr_type=0;
+  int val = 0;
+
+  for (;;)
+    {
+      if (ic->op == '+')
+       val += (int) operandLitValue (IC_RIGHT (ic));
+      else if (ic->op == '-')
+       val -= (int) operandLitValue (IC_RIGHT (ic));
+      else if (IS_CAST_ICODE(ic)) {
+             sym_link *from_type = operandType(IC_RIGHT(ic));
+             aop->aopu.aop_immd.from_cast_remat = 1;
+             ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
+             ptr_type = DCL_TYPE(from_type);
+             if (ptr_type == IPOINTER) {
+               // bug #481053
+               ptr_type = POINTER;
+             }
+             continue ;
+      } else break;
+
+      ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
+    }
+
+  if (val)
+    sprintf (buffer, "(%s %c 0x%04x)",
+            OP_SYMBOL (IC_LEFT (ic))->rname,
+            val >= 0 ? '+' : '-',
+            abs (val) & 0xffff);
+  else
+    strcpy (buffer, OP_SYMBOL (IC_LEFT (ic))->rname);
+
+  aop->aopu.aop_immd.aop_immd1 = Safe_calloc (1, strlen (buffer) + 1);
+  strcpy (aop->aopu.aop_immd.aop_immd1, buffer);
+  /* set immd2 field if required */
+  if (aop->aopu.aop_immd.from_cast_remat) {
+         sprintf(buffer,"#0x%02x",ptr_type);
+         aop->aopu.aop_immd.aop_immd2 = Safe_calloc (1, strlen (buffer) + 1);
+         strcpy (aop->aopu.aop_immd.aop_immd2, buffer);
+  }
+
+  return aop;
+}
+
+/*-----------------------------------------------------------------*/
+/* regsInCommon - two operands have some registers in common       */
+/*-----------------------------------------------------------------*/
+static bool
+regsInCommon (operand * op1, operand * op2)
+{
+  symbol *sym1, *sym2;
+  int i;
+
+  /* if they have registers in common */
+  if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
+    return FALSE;
+
+  sym1 = OP_SYMBOL (op1);
+  sym2 = OP_SYMBOL (op2);
+
+  if (sym1->nRegs == 0 || sym2->nRegs == 0)
+    return FALSE;
+
+  for (i = 0; i < sym1->nRegs; i++)
+    {
+      int j;
+      if (!sym1->regs[i])
+       continue;
+
+      for (j = 0; j < sym2->nRegs; j++)
+       {
+         if (!sym2->regs[j])
+           continue;
+
+         if (sym2->regs[j] == sym1->regs[i])
+           return TRUE;
+       }
+    }
+
+  return FALSE;
+}
+
+/*-----------------------------------------------------------------*/
+/* operandsEqu - equivalent                                        */
+/*-----------------------------------------------------------------*/
+static bool
+operandsEqu (operand * op1, operand * op2)
+{
+  symbol *sym1, *sym2;
+
+  /* if they not symbols */
+  if (!IS_SYMOP (op1) || !IS_SYMOP (op2))
+    return FALSE;
+
+  sym1 = OP_SYMBOL (op1);
+  sym2 = OP_SYMBOL (op2);
+
+  /* if both are itemps & one is spilt
+     and the other is not then false */
+  if (IS_ITEMP (op1) && IS_ITEMP (op2) &&
+      sym1->isspilt != sym2->isspilt)
+    return FALSE;
+
+  /* if they are the same */
+  if (sym1 == sym2)
+    return TRUE;
+
+  if (strcmp (sym1->rname, sym2->rname) == 0)
+    return TRUE;
+
+
+  /* if left is a tmp & right is not */
+  if (IS_ITEMP (op1) &&
+      !IS_ITEMP (op2) &&
+      sym1->isspilt &&
+      (sym1->usl.spillLoc == sym2))
+    return TRUE;
+
+  if (IS_ITEMP (op2) &&
+      !IS_ITEMP (op1) &&
+      sym2->isspilt &&
+      sym1->level > 0 &&
+      (sym2->usl.spillLoc == sym1))
+    return TRUE;
+
+  return FALSE;
+}
+
+/*-----------------------------------------------------------------*/
+/* sameRegs - two asmops have the same registers                   */
+/*-----------------------------------------------------------------*/
+static bool
+sameRegs (asmop * aop1, asmop * aop2)
+{
+  int i;
+
+  if (aop1 == aop2)
+    return TRUE;
+
+//  if (aop1->size != aop2->size)
+//    return FALSE;
+
+  if (aop1->type == aop2->type)
+    {
+      switch (aop1->type)
+        {
+          case AOP_REG:
+            for (i = 0; i < aop1->size; i++)
+              if (aop1->aopu.aop_reg[i] !=
+                  aop2->aopu.aop_reg[i])
+                return FALSE;
+            return TRUE;
+          case AOP_SOF:
+            return (aop1->aopu.aop_stk == aop2->aopu.aop_stk);
+          case AOP_DIR:
+          case AOP_EXT:
+            return (!strcmp (aop1->aopu.aop_dir, aop2->aopu.aop_dir));
+        }
+    }
+
+  return FALSE;
+}
+
+/*-----------------------------------------------------------------*/
+/* aopOp - allocates an asmop for an operand  :                    */
+/*-----------------------------------------------------------------*/
+static void
+aopOp (operand * op, iCode * ic, bool result)
+{
+  asmop *aop = NULL;
+  symbol *sym;
+  int i;
+
+  if (!op)
+    return;
+
+  // Is this a pointer set result?
+  //
+  if ((op==IC_RESULT (ic)) && POINTER_SET (ic))
+    {
+    }
+
+//  printf("checking literal\n");
+  /* if this a literal */
+  if (IS_OP_LITERAL (op))
+    {
+      op->aop = aop = newAsmop (AOP_LIT);
+      aop->aopu.aop_lit = op->operand.valOperand;
+      aop->size = getSize (operandType (op));
+      aop->op = op;
+      aop->isaddr = op->isaddr;
+      return;
+    }
+
+//  printf("checking pre-existing\n");
+  /* if already has a asmop then continue */
+  if (op->aop )
+    {
+      op->aop->op = op;
+      op->aop->isaddr = op->isaddr;
+      return;
+    }
+
+//  printf("checking underlying sym\n");
+  /* if the underlying symbol has a aop */
+  if (IS_SYMOP (op) && OP_SYMBOL (op)->aop)
+    {
+      op->aop = aop = Safe_calloc(1, sizeof(*aop));
+      memcpy (aop, OP_SYMBOL (op)->aop, sizeof(*aop));
+      //op->aop = aop = OP_SYMBOL (op)->aop;
+      aop->size = getSize( operandType (op));
+      //printf ("reusing underlying symbol %s\n",OP_SYMBOL (op)->name);
+      //printf (" with size = %d\n", aop->size);
+      
+      aop->op = op;
+      aop->isaddr = op->isaddr;
+      /* if (aop->isaddr & IS_ITEMP (op))
+        {
+          aop->psize=aop->size;
+          aop->size = getSize( operandType (op)->next);
+        } */
+      return;
+    }
+
+//  printf("checking true sym\n");
+  /* if this is a true symbol */
+  if (IS_TRUE_SYMOP (op))
+    {
+      op->aop = aop = aopForSym (ic, OP_SYMBOL (op), result);
+      aop->op = op;
+      aop->isaddr = op->isaddr;
+      //printf ("new symbol %s\n", OP_SYMBOL (op)->name);
+      //printf (" with size = %d\n", aop->size);
+      return;
+    }
+
+  /* this is a temporary : this has
+     only four choices :
+     a) register
+     b) spillocation
+     c) rematerialize
+     d) conditional
+     e) can be a return use only */
+
+  sym = OP_SYMBOL (op);
+
+//  printf("checking conditional\n");
+  /* if the type is a conditional */
+  if (sym->regType == REG_CND)
+    {
+      aop = op->aop = sym->aop = newAsmop (AOP_CRY);
+      aop->size = 0;
+      aop->op = op;
+      aop->isaddr = op->isaddr;
+      return;
+    }
+
+//  printf("checking spilt\n");
+  /* if it is spilt then two situations
+     a) is rematerialize
+     b) has a spill location */
+  if (sym->isspilt || sym->nRegs == 0)
+    {
+
+//      printf("checking remat\n");
+      /* rematerialize it NOW */
+      if (sym->remat)
+       {
+         sym->aop = op->aop = aop =
+           aopForRemat (sym);
+         aop->size = getSize (sym->type);
+          aop->op = op;
+          aop->isaddr = op->isaddr;
+          /* if (aop->isaddr & IS_ITEMP (op))
+            {
+              aop->psize=aop->size;
+              aop->size = getSize( operandType (op)->next);
+            } */
+         return;
+       }
+
+//      printf("checking accuse\n");
+      if (sym->accuse)
+       {
+         aop = op->aop = sym->aop = newAsmop (AOP_REG);
+         aop->size = getSize (sym->type);
+         switch (sym->accuse)
+           {
+           case ACCUSE_XA:
+              aop->aopu.aop_reg[0] = hc08_reg_a;
+              aop->aopu.aop_reg[1] = hc08_reg_x;
+              break;
+           case ACCUSE_HX:
+              aop->aopu.aop_reg[0] = hc08_reg_x;
+              aop->aopu.aop_reg[1] = hc08_reg_h;
+              break;
+            }
+          aop->op = op;
+          aop->isaddr = op->isaddr;
+         return;
+       }
+
+//      printf("checking ruonly\n");
+#if 1
+      if (sym->ruonly)
+       {
+         unsigned i;
+
+         aop = op->aop = sym->aop = newAsmop (AOP_STR);
+         aop->size = getSize (sym->type);
+         for (i = 0; i < fReturnSizeHC08; i++)
+           aop->aopu.aop_str[i] = fReturn2[i];
+          aop->op = op;
+          aop->isaddr = op->isaddr;
+         return;
+       }
+#endif
+      /* else spill location  */
+//      printf("checking spill loc\n");
+//      if (sym->usl.spillLoc && getSize(sym->type) != getSize(sym->usl.spillLoc->type)) {
+      if (sym->usl.spillLoc && sym->usl.spillLoc->aop
+          && sym->usl.spillLoc->aop->size != getSize (sym->type))
+        {
+         /* force a new aop if sizes differ */
+         sym->usl.spillLoc->aop = NULL;
+         //printf ("forcing new aop\n");
+        }
+      sym->aop = op->aop = aop =
+       aopForSym (ic, sym->usl.spillLoc, result);
+      aop->size = getSize (sym->type);
+      aop->op = op;
+      aop->isaddr = op->isaddr;
+      //printf ("spill symbol %s\n", OP_SYMBOL (op)->name);
+      //printf (" with size = %d\n", aop->size);
+      /* if (aop->isaddr & IS_ITEMP (op))
+        {
+          aop->psize=aop->size;
+          aop->size = getSize( operandType (op)->next);
+        } */
+      return;
+    }
+
+//  printf("assuming register\n");
+  /* must be in a register */
+  sym->aop = op->aop = aop = newAsmop (AOP_REG);
+  aop->size = sym->nRegs;
+  for (i = 0; i < sym->nRegs; i++)
+    aop->aopu.aop_reg[i] = sym->regs[i];
+  aop->op = op;
+  aop->isaddr = op->isaddr;
+
+}
+
+/*-----------------------------------------------------------------*/
+/* freeAsmop - free up the asmop given to an operand               */
+/*----------------------------------------------------------------*/
+static void
+freeAsmop (operand * op, asmop * aaop, iCode * ic, bool pop)
+{
+  asmop *aop;
+
+  if (!op)
+    aop = aaop;
+  else
+    aop = op->aop;
+
+  if (!aop)
+    return;
+
+  if (aop->freed)
+    goto dealloc;
+
+  aop->freed = 1;
+
+  if (aop->stacked)
+    {
+      int stackAdjust;
+      int loffset;
+
+      emitcode ("","; freeAsmop restoring stacked %s", aopName(aop));
+      aop->stacked = 0;
+      stackAdjust = 0;
+      for (loffset=0; loffset<aop->size; loffset++)
+        if (aop->stk_aop[loffset])
+          {
+            transferAopAop (aop->stk_aop[loffset], 0, aop, loffset);
+            stackAdjust++;
+          }
+      pullNull (stackAdjust);
+    }
+    
+dealloc:
+  /* all other cases just dealloc */
+  if (op)
+    {
+      op->aop = NULL;
+      if (IS_SYMOP (op))
+       {
+         OP_SYMBOL (op)->aop = NULL;
+         /* if the symbol has a spill */
+         if (SPIL_LOC (op))
+           SPIL_LOC (op)->aop = NULL;
+       }
+    }
+}
+
+
+/*-----------------------------------------------------------------*/
+/* aopDerefAop - treating the aop parameter as a pointer, return   */
+/*               an asmop for the object it references             */
+/*-----------------------------------------------------------------*/
+asmop *
+aopDerefAop (asmop *aop)
+{
+  int adr;
+  char *s = buffer;
+  char *rs;
+  asmop *newaop = NULL;
+  sym_link *type, *etype;
+  int p_type;
+  
+  emitcode ("", ";     aopDerefAop(%s)", aopName(aop));
+  if (aop->op)
+    {
+    
+      type = operandType (aop->op);
+      etype = getSpec (type);
+      /* if op is of type of pointer then it is simple */
+      if (IS_PTR (type) && !IS_FUNC (type->next))
+        p_type = DCL_TYPE (type);
+      else
+        {
+          /* we have to go by the storage class */
+          p_type = PTR_TYPE (SPEC_OCLS (etype));
+        }
+    }
+  else
+    p_type = UPOINTER;
+  
+  switch (aop->type)
+    {
+    case AOP_IMMD:
+      if (p_type == POINTER)
+        newaop = newAsmop (AOP_DIR);
+      else
+        newaop = newAsmop (AOP_EXT);
+      newaop->aopu.aop_dir = aop->aopu.aop_immd.aop_immd1;
+      break;
+    case AOP_LIT:
+      adr = (int) floatFromVal (aop->aopu.aop_lit);
+      if (p_type == POINTER)
+        adr &= 0xff;
+
+      if (adr<0x100)
+        {
+          newaop = newAsmop (AOP_DIR);
+          sprintf (s, "0x%02x",adr);
+        }
+      else
+        {
+          newaop = newAsmop (AOP_EXT);
+          sprintf (s, "0x%04x",adr);
+        }
+      rs = Safe_calloc (1, strlen (s) + 1);
+      strcpy (rs, s);
+      newaop->aopu.aop_dir = rs;
+      break;
+    default:
+      werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+              "unsupported asmop");
+      return NULL;
+    }
+
+     
+  return newaop;
+}
+
+
+
+/*-----------------------------------------------------------------*/
+/* aopAdrStr - for referencing the address of the aop              */
+/*-----------------------------------------------------------------*/
+static char *
+aopAdrStr (asmop * aop, int loffset, bool bit16)
+{
+  char *s = buffer;
+  char *rs;
+  int offset = aop->size - 1 - loffset;
+
+  /* offset is greater than
+     size then zero */
+  if (loffset > (aop->size - 1) &&
+      aop->type != AOP_LIT)
+    return zero;
+
+  /* depending on type */
+  switch (aop->type)
+    {
+
+    case AOP_IMMD:
+      if (aop->aopu.aop_immd.from_cast_remat && (loffset == (aop->size-1))) {
+             sprintf(s,"%s",aop->aopu.aop_immd.aop_immd2);
+      } else if (bit16)
+       sprintf (s, "#%s", aop->aopu.aop_immd.aop_immd1);
+      else if (loffset)
+        {
+          if (loffset!=1)
+           sprintf (s, "#(%s >> %d)",
+                    aop->aopu.aop_immd.aop_immd1,
+                    loffset * 8);
+         else
+           sprintf (s, "#>%s",
+                    aop->aopu.aop_immd.aop_immd1);
+        }
+      else
+       sprintf (s, "#%s",
+                aop->aopu.aop_immd.aop_immd1);
+      rs = Safe_calloc (1, strlen (s) + 1);
+      strcpy (rs, s);
+      return rs;
+
+    case AOP_DIR:
+      if (offset)
+       sprintf (s, "*(%s + %d)",
+                aop->aopu.aop_dir,
+                offset);
+      else
+       sprintf (s, "*%s", aop->aopu.aop_dir);
+      rs = Safe_calloc (1, strlen (s) + 1);
+      strcpy (rs, s);
+      return rs;
+
+    case AOP_EXT:
+      if (offset)
+       sprintf (s, "(%s + %d)",
+                aop->aopu.aop_dir,
+                offset);
+      else
+       sprintf (s, "%s", aop->aopu.aop_dir);
+      rs = Safe_calloc (1, strlen (s) + 1);
+      strcpy (rs, s);
+      return rs;
+
+    case AOP_REG:
+      return aop->aopu.aop_reg[loffset]->name;
+
+    case AOP_LIT:
+      if (bit16)
+        return aopLiteralLong (aop->aopu.aop_lit, loffset, 2);
+      else
+        return aopLiteral (aop->aopu.aop_lit, loffset);
+
+    case AOP_STR:
+      aop->coff = offset;
+      return aop->aopu.aop_str[loffset];
+
+    case AOP_SOF:
+       sprintf (s, "%d,s", _G.stackOfs + _G.stackPushes + aop->aopu.aop_stk
+                           + offset + 1);
+      rs = Safe_calloc (1, strlen (s) + 1);
+      strcpy (rs, s);
+      return rs;
+
+    }
+
+  werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+         "aopAdrStr got unsupported aop->type");
+  exit (1);
+}
+
+
+
+
+
+#if 0
+/*-----------------------------------------------------------------*/
+/* opIsGptr: returns non-zero if the passed operand is       */
+/* a generic pointer type.             */
+/*-----------------------------------------------------------------*/
+static int
+opIsGptr (operand * op)
+{
+  sym_link *type = operandType (op);
+
+  if ((AOP_SIZE (op) == GPTRSIZE) && IS_GENPTR (type))
+    {
+      return 1;
+    }
+  return 0;
+}
+#endif
+
+/*-----------------------------------------------------------------*/
+/* getDataSize - get the operand data size                         */
+/*-----------------------------------------------------------------*/
+static int
+getDataSize (operand * op)
+{
+  int size;
+  size = AOP_SIZE (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.       */
+/*               Result left in A (0=FALSE, 1=TRUE) if ResultInA,  */
+/*               otherwise result left in Z flag (1=FALSE, 0=TRUE) */
+/*-----------------------------------------------------------------*/
+static void
+asmopToBool (asmop *aop, bool resultInA)
+{
+  symbol *tlbl, *tlbl1;
+  int size = aop->size;
+  bool needpula = FALSE;
+  bool flagsonly = TRUE;
+  int offset = 0;
+
+
+  if (resultInA)
+    hc08_freeReg(hc08_reg_a);
+      
+  switch (aop->type)
+    {
+      case AOP_REG:
+        if (IS_AOP_A(aop))
+          {
+            emitcode ("tsta", "");
+            flagsonly = FALSE;
+          }
+        else if (IS_AOP_X(aop))
+            emitcode ("tstx", "");
+        else if (IS_AOP_H(aop))
+          {
+            if (hc08_reg_a->isFree)
+              {
+                transferRegReg (hc08_reg_h,hc08_reg_a, FALSE);
+                emitcode ("tsta", "");
+                flagsonly = FALSE;
+                hc08_freeReg(hc08_reg_a);
+              }
+            else if (hc08_reg_x->isFree)
+              {
+                transferRegReg (hc08_reg_h,hc08_reg_x, FALSE);
+                emitcode ("tstx", "");
+                hc08_freeReg(hc08_reg_x);
+              }
+            else
+              {
+                emitcode ("pshh", "");
+                emitcode ("tst", "1,s");
+                emitcode ("ais", "#1");
+              }
+          }
+        else if (IS_AOP_HX(aop))
+          emitcode ("cphx", zero);
+        else if (IS_AOP_XA(aop))
+          {
+            symbol *tlbl = newiTempLabel (NULL);
+            emitcode ("tsta", "");
+            emitcode ("bne", "%05d$", (tlbl->key + 100));
+            emitcode ("tstx", "");
+            emitcode ("", "%05d$:", (tlbl->key + 100));
+          }
+        else
+          werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+                  "Bad rIdx in asmToBool");
+          return;
+      case AOP_EXT:
+        if (resultInA)
+          needpula = FALSE;
+        else
+          needpula = pushRegIfUsed (hc08_reg_a);
+        loadRegFromAop (hc08_reg_a, aop, 0);
+        for (offset=1; offset<size; offset++)
+          accopWithAop ("ora", aop, offset);
+        if (needpula)
+          pullReg (hc08_reg_a);
+        else
+          {
+            hc08_freeReg (hc08_reg_a);
+            flagsonly = FALSE;
+          }
+        break;
+      default:
+        if (size==1)
+          {
+            if (resultInA)
+              {
+                loadRegFromAop (hc08_reg_a, aop, 0);
+                hc08_freeReg (hc08_reg_a);
+                flagsonly = FALSE;
+              }
+            else
+              emitcode ("tst", "%s", aopAdrStr (aop, 0, FALSE));
+            break;
+          }
+        else if (size==2)
+          {
+            if (hc08_reg_a->isFree)
+              {
+                loadRegFromAop (hc08_reg_a, aop, 0);
+                accopWithAop ("ora", aop, 1);
+                hc08_freeReg (hc08_reg_a);
+                flagsonly = FALSE;
+              }
+            else
+              {
+                tlbl = newiTempLabel (NULL);
+                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));
+                break;
+              }
+          }
+        else
+          {
+            needpula = pushRegIfUsed (hc08_reg_a);
+            loadRegFromAop (hc08_reg_a, aop, 0);
+            for (offset=1; offset<size; offset++)
+              accopWithAop ("ora", aop, offset);
+            if (needpula)
+              pullReg (hc08_reg_a);
+            else
+              {
+                hc08_freeReg (hc08_reg_a);
+                flagsonly = FALSE;
+              }
+          }
+    }
+
+  if (resultInA)
+    {
+      tlbl = newiTempLabel (NULL);
+
+      if (flagsonly)
+        {
+          tlbl1 = newiTempLabel (NULL);
+          emitBranch ("bne", tlbl1);
+          loadRegFromConst (hc08_reg_a, zero);
+          emitBranch ("bra", tlbl);
+          emitLabel (tlbl1);
+          loadRegFromConst (hc08_reg_a, one);
+        }
+      else
+        {
+          emitBranch ("beq", tlbl);
+          loadRegFromConst (hc08_reg_a, one);
+        }
+      emitLabel (tlbl);
+      hc08_useReg (hc08_reg_a);
+    }
+}
+
+
+
+/*-----------------------------------------------------------------*/
+/* genNot - generate code for ! operation                          */
+/*-----------------------------------------------------------------*/
+static void
+genNot (iCode * ic)
+{
+  D(emitcode (";     genNot",""));
+
+  /* assign asmOps to operand & result */
+  aopOp (IC_LEFT (ic), ic, FALSE);
+  aopOp (IC_RESULT (ic), ic, TRUE);
+
+  asmopToBool ( AOP (IC_LEFT (ic)), TRUE);
+  emitcode ("eor", one);
+  storeRegToFullAop (hc08_reg_a, AOP (IC_RESULT (ic)), FALSE);
+  
+  freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+  freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
+}
+
+
+/*-----------------------------------------------------------------*/
+/* genCpl - generate code for complement                           */
+/*-----------------------------------------------------------------*/
+static void
+genCpl (iCode * ic)
+{
+  int offset = 0;
+  int size;
+  regs* reg = hc08_reg_a;
+  
+//  symbol *tlbl;
+
+  D(emitcode (";     genCpl",""));
+
+  /* assign asmOps to operand & result */
+  aopOp (IC_LEFT (ic), ic, FALSE);
+  aopOp (IC_RESULT (ic), ic, TRUE);
+
+  size = AOP_SIZE (IC_RESULT (ic));
+  while (size--)
+    {
+      loadRegFromAop (reg, AOP (IC_LEFT (ic)), offset);
+      rmwWithReg ("com", reg);
+      hc08_useReg (reg);
+      storeRegToAop (reg, AOP (IC_RESULT (ic)), offset);
+      hc08_freeReg (reg);
+    }
+
+  /* release the aops */
+  freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+  freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genUminusFloat - unary minus for floating points                */
+/*-----------------------------------------------------------------*/
+static void
+genUminusFloat (operand * op, operand * result)
+{
+  int size, offset = 0;
+  bool needpula;
+
+  D(emitcode (";     genUminusFloat",""));
+
+  /* for this we just copy and then flip the bit */
+
+  size = AOP_SIZE (op) - 1;
+
+  while (size--)
+    {
+      if (!size)
+        {
+          needpula = pushRegIfUsed (hc08_reg_a);
+          loadRegFromAop (hc08_reg_a, AOP (op), offset);
+          emitcode ("eor", "#0x80");
+          hc08_useReg (hc08_reg_a);
+          storeRegToAop (hc08_reg_a, AOP (result), offset);
+          pullOrFreeReg (hc08_reg_a, needpula);
+        }
+      else
+        transferAopAop (AOP (op), offset, AOP (result), offset);
+      offset++;
+    }
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genUminus - unary minus code generation                         */
+/*-----------------------------------------------------------------*/
+static void
+genUminus (iCode * ic)
+{
+  int offset, size;
+  sym_link *optype, *rtype;
+  char *sub;
+  bool needpula;
+
+  D(emitcode (";     genUminus",""));
+
+  /* assign asmops */
+  aopOp (IC_LEFT (ic), ic, FALSE);
+  aopOp (IC_RESULT (ic), ic, TRUE);
+
+  optype = operandType (IC_LEFT (ic));
+  rtype = operandType (IC_RESULT (ic));
+
+  /* if float then do float stuff */
+  if (IS_FLOAT (optype))
+    {
+      genUminusFloat (IC_LEFT (ic), IC_RESULT (ic));
+      goto release;
+    }
+
+  /* otherwise subtract from zero */
+  size = AOP_SIZE (IC_LEFT (ic));
+  offset = 0;
+
+  if (size == 1)
+    {
+      needpula = pushRegIfUsed (hc08_reg_a);
+      loadRegFromAop (hc08_reg_a, AOP( IC_LEFT (ic)), 0);
+      emitcode ("nega", "");
+      hc08_freeReg (hc08_reg_a);
+      storeRegToFullAop (hc08_reg_a, AOP( IC_RESULT (ic)), 
+                         SPEC_USIGN (operandType (IC_LEFT (ic))));
+      pullOrFreeReg (hc08_reg_a, needpula);
+    }
+  else
+    {
+      needpula = pushRegIfUsed (hc08_reg_a);
+      sub="sub";
+      while (size--)
+        {
+          loadRegFromConst (hc08_reg_a, zero);
+          accopWithAop (sub, AOP( IC_LEFT (ic)), offset);
+          storeRegToAop (hc08_reg_a, AOP( IC_RESULT (ic)), offset++);
+          sub = "sbc";
+        }
+        storeRegSignToUpperAop (hc08_reg_a, AOP( IC_RESULT (ic)), offset, 
+                                SPEC_USIGN (operandType (IC_LEFT (ic))));
+      pullOrFreeReg (hc08_reg_a, needpula);
+    }
+
+
+
+release:
+  /* release the aops */
+  freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+  freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* saveRegisters - will look for a call and save the registers     */
+/*-----------------------------------------------------------------*/
+static void
+saveRegisters (iCode * lic)
+{
+  int i;
+  iCode *ic;
+  bitVect *rsave;
+
+  /* look for call */
+  for (ic = lic; ic; ic = ic->next)
+    if (ic->op == CALL || ic->op == PCALL)
+      break;
+
+  if (!ic)
+    {
+      fprintf (stderr, "found parameter push with no function call\n");
+      return;
+    }
+
+  /* if the registers have been saved already or don't need to be then
+     do nothing */
+  if (ic->regsSaved)
+    return;
+  if (IS_SYMOP(IC_LEFT(ic)) &&
+      (IFFUNC_CALLEESAVES(OP_SYMBOL(IC_LEFT(ic))->type) ||
+       IFFUNC_ISNAKED(OP_SYM_TYPE(IC_LEFT (ic)))))
+    return;
+  
+  /* safe the registers in use at this time but skip the
+     ones for the result */
+  rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
+                        hc08_rUmaskForOp (IC_RESULT(ic)));
+
+  ic->regsSaved = 1;
+  for (i = 0; i < hc08_nRegs; i++)
+    {
+      if (bitVectBitValue (rsave, i))
+        pushReg ( hc08_regWithIdx (i), FALSE);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* unsaveRegisters - pop the pushed registers                      */
+/*-----------------------------------------------------------------*/
+static void
+unsaveRegisters (iCode * ic)
+{
+  int i;
+  bitVect *rsave;
+
+  /* restore the registers in use at this time but skip the
+     ones for the result */
+  rsave = bitVectCplAnd (bitVectCopy (ic->rMask), 
+                        hc08_rUmaskForOp (IC_RESULT(ic)));
+
+  for (i = hc08_nRegs; i >= 0; i--)
+    {
+      if (bitVectBitValue (rsave, i))
+        pullReg ( hc08_regWithIdx (i));
+    }
+
+}
+
+
+/*-----------------------------------------------------------------*/
+/* pushSide -                */
+/*-----------------------------------------------------------------*/
+static void
+pushSide (operand * oper, int size)
+{
+  int offset = 0;
+  while (size--)
+    {
+      loadRegFromAop (hc08_reg_a, AOP (oper), offset++);
+      pushReg ( hc08_reg_a, TRUE);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* assignResultValue -               */
+/*-----------------------------------------------------------------*/
+static void
+assignResultValue (operand * oper)
+{
+  int size = AOP_SIZE (oper);
+  int offset = 0;
+  while (size--)
+    {
+      transferAopAop(hc08_aop_pass[offset], 0, AOP (oper), offset);
+      if (hc08_aop_pass[offset]->type == AOP_REG)
+        hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
+      offset++;
+    }
+}
+
+
+
+/*-----------------------------------------------------------------*/
+/* genIpush - genrate code for pushing this gets a little complex  */
+/*-----------------------------------------------------------------*/
+static void
+genIpush (iCode * ic)
+{
+  int size, offset = 0;
+//  char *l;
+
+  D(emitcode (";     genIpush",""));
+
+  /* if this is not a parm push : ie. it is spill push
+     and spill push is always done on the local stack */
+  if (!ic->parmPush)
+    {
+
+      /* and the item is spilt then do nothing */
+      if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
+       return;
+
+      aopOp (IC_LEFT (ic), ic, FALSE);
+      size = AOP_SIZE (IC_LEFT (ic));
+      offset = 0;
+      /* push it on the stack */
+      while (size--)
+        {
+          loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
+          pushReg ( hc08_reg_a, TRUE);
+        }
+
+      return;
+    }
+
+  /* this is a paramter push: in this case we call
+     the routine to find the call and save those
+     registers that need to be saved */
+  saveRegisters (ic);
+
+  /* then do the push */
+  aopOp (IC_LEFT (ic), ic, FALSE);
+
+
+  // pushSide(IC_LEFT(ic), AOP_SIZE(IC_LEFT(ic)));
+  size = AOP_SIZE (IC_LEFT (ic));
+  offset = 0;
+
+//  l = aopGet (AOP (IC_LEFT (ic)), 0, FALSE, TRUE);
+  if (AOP_TYPE (IC_LEFT (ic)) == AOP_IMMD)
+    {
+      if ((size==2) && hc08_reg_hx->isFree)
+        {
+          loadRegFromAop (hc08_reg_hx, AOP (IC_LEFT (ic)), 0);
+          pushReg (hc08_reg_hx, TRUE);
+          goto release;
+        }
+    }
+
+  while (size--)
+    {
+//      printf("loading %d\n", offset);
+      loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset++);
+//      printf("pushing \n");
+      pushReg (hc08_reg_a, TRUE);
+    }
+
+release:
+  freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genIpop - recover the registers: can happen only for spilling   */
+/*-----------------------------------------------------------------*/
+static void
+genIpop (iCode * ic)
+{
+  int size, offset;
+
+  D(emitcode (";     genIpop",""));
+
+  /* if the temp was not pushed then */
+  if (OP_SYMBOL (IC_LEFT (ic))->isspilt)
+    return;
+
+  aopOp (IC_LEFT (ic), ic, FALSE);
+  size = AOP_SIZE (IC_LEFT (ic));
+  offset = size - 1;
+  while (size--)
+    {
+      pullReg (hc08_reg_a);
+      storeRegToAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset--);
+    }
+  freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
+}
+
+
+/*-----------------------------------------------------------------*/
+/* genSend - gen code for SEND                                    */
+/*-----------------------------------------------------------------*/
+static void genSend(set *sendSet)
+{
+    iCode *sic;
+
+    for (sic = setFirstItem (_G.sendSet); sic;
+        sic = setNextItem (_G.sendSet)) {
+         int size, offset = 0;
+         aopOp (IC_LEFT (sic), sic, FALSE);
+         size = AOP_SIZE (IC_LEFT (sic));
+
+         if (sic->argreg) {
+             offset = size-1;
+             while (size--) {
+                 transferAopAop( AOP (IC_LEFT (sic)), offset,
+                                 hc08_aop_pass[offset+(sic->argreg-1)], 0);
+                 offset--;
+             }
+         }       
+         freeAsmop (IC_LEFT (sic), NULL, sic, TRUE);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genCall - generates a call statement                            */
+/*-----------------------------------------------------------------*/
+static void
+genCall (iCode * ic)
+{
+  sym_link *dtype;
+//  bool restoreBank = FALSE;
+//  bool swapBanks = FALSE;
+
+  D(emitcode(";     genCall",""));
+
+  dtype = operandType (IC_LEFT (ic));
+  /* if send set is not empty the assign */
+  if (_G.sendSet)
+    {
+       if (IFFUNC_ISREENT(dtype)) { /* need to reverse the send set */
+           genSend(reverseSet(_G.sendSet));
+       } else {
+           genSend(_G.sendSet);
+       }
+
+      _G.sendSet = NULL;
+    }
+
+  /* if caller saves & we have not saved then */
+  if (!ic->regsSaved)
+      saveRegisters (ic);
+
+
+  /* make the call */
+  emitcode ("jsr", "%s", (OP_SYMBOL (IC_LEFT (ic))->rname[0] ?
+                         OP_SYMBOL (IC_LEFT (ic))->rname :
+                         OP_SYMBOL (IC_LEFT (ic))->name));
+
+
+  /* if we need assign a result value */
+  if ((IS_ITEMP (IC_RESULT (ic)) &&
+       (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
+       OP_SYMBOL (IC_RESULT (ic))->accuse || 
+       OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
+      IS_TRUE_SYMOP (IC_RESULT (ic)))
+    {
+
+      _G.accInUse++;
+      aopOp (IC_RESULT (ic), ic, FALSE);
+      _G.accInUse--;
+
+      assignResultValue (IC_RESULT (ic));
+
+      freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+    }
+
+  /* adjust the stack for parameters if
+     required */
+  if (ic->parmBytes)
+    {
+      pullNull (ic->parmBytes);
+    }
+
+  /* if we had saved some registers then unsave them */
+  if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
+    unsaveRegisters (ic);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* -10l - generates a call by pointer statement                */
+/*-----------------------------------------------------------------*/
+static void
+genPcall (iCode * ic)
+{
+  sym_link *dtype;
+  symbol *rlbl = newiTempLabel (NULL);
+  symbol *tlbl = newiTempLabel (NULL);
+//  bool restoreBank=FALSE;
+//  bool swapBanks = FALSE;
+
+  D(emitcode(";     genPCall",""));
+
+  /* if caller saves & we have not saved then */
+  if (!ic->regsSaved)
+    saveRegisters (ic);
+
+  /* if we are calling a not _naked function that is not using
+     the same register bank then we need to save the
+     destination registers on the stack */
+  dtype = operandType (IC_LEFT (ic))->next;
+
+  /* now push the calling address */
+  emitBranch ("bsr", tlbl);
+  emitBranch ("bra", rlbl);
+  emitLabel (tlbl);
+
+  /* Push the function's address */
+  aopOp (IC_LEFT (ic), ic, FALSE);
+  pushSide (IC_LEFT (ic), FPTRSIZE);
+  freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
+
+  /* if send set is not empty the assign */
+  if (_G.sendSet)
+    {
+       genSend(reverseSet(_G.sendSet));
+       _G.sendSet = NULL;
+    }
+
+
+  /* make the call */
+  emitcode ("rts", "");
+
+  emitLabel (rlbl);
+
+
+  /* if we need assign a result value */
+  if ((IS_ITEMP (IC_RESULT (ic)) &&
+       (OP_SYMBOL (IC_RESULT (ic))->nRegs ||
+       OP_SYMBOL (IC_RESULT (ic))->spildir)) ||
+      IS_TRUE_SYMOP (IC_RESULT (ic)))
+    {
+
+      _G.accInUse++;
+      aopOp (IC_RESULT (ic), ic, FALSE);
+      _G.accInUse--;
+
+      assignResultValue (IC_RESULT (ic));
+
+      freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+    }
+
+  /* adjust the stack for parameters if
+     required */
+  if (ic->parmBytes)
+    {
+      pullNull (ic->parmBytes);
+    }
+
+  /* if we hade saved some registers then
+     unsave them */
+  if (ic->regsSaved && !IFFUNC_CALLEESAVES(dtype))
+    unsaveRegisters (ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* resultRemat - result  is rematerializable                       */
+/*-----------------------------------------------------------------*/
+static int
+resultRemat (iCode * ic)
+{
+  if (SKIP_IC (ic) || ic->op == IFX)
+    return 0;
+
+  if (IC_RESULT (ic) && IS_ITEMP (IC_RESULT (ic)))
+    {
+      symbol *sym = OP_SYMBOL (IC_RESULT (ic));
+      if (sym->remat && !POINTER_SET (ic))
+       return 1;
+    }
+
+  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   */
+/*-----------------------------------------------------------------*/
+static int
+regsCmp(void *p1, void *p2)
+{
+  return (STRCASECMP((char *)p1, (char *)(p2)) == 0);
+}
+
+static bool
+inExcludeList (char *s)
+{
+  const char *p = setFirstItem(options.excludeRegsSet);
+
+  if (p == NULL || STRCASECMP(p, "none") == 0)
+    return FALSE;
+
+
+  return isinSetWith(options.excludeRegsSet, s, regsCmp);
+}
+
+/*-----------------------------------------------------------------*/
+/* genFunction - generated code for function entry                 */
+/*-----------------------------------------------------------------*/
+static void
+genFunction (iCode * ic)
+{
+  symbol *sym;
+  sym_link *ftype;
+  int calleesaves_saved_register = -1;
+
+  _G.nRegsSaved = 0;
+  _G.stackPushes = 0;
+  /* create the function header */
+  emitcode (";", "-----------------------------------------");
+  emitcode (";", " function %s", (sym = OP_SYMBOL (IC_LEFT (ic)))->name);
+  emitcode (";", "-----------------------------------------");
+
+  emitcode ("", "%s:", sym->rname);
+  ftype = operandType (IC_LEFT (ic));
+
+  if (IFFUNC_ISNAKED(ftype))
+  {
+      emitcode(";", "naked function: no prologue.");
+      return;
+  }
+
+
+
+  /* if this is an interrupt service routine then
+     save h  */
+  if (IFFUNC_ISISR (sym->type))
+    {
+
+      if (!inExcludeList ("h"))
+       emitcode ("pshh", "");
+    }
+  else
+    {
+      /* 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;
+
+         /* 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 (IFFUNC_ISREENT (sym->type) || options.stackAuto)
+    {
+
+    }
+
+  /* adjust the stack for the function */
+  if (sym->stack)
+    {
+
+      int i = sym->stack;
+//      if (i > 256)
+//     werror (W_STACK_OVERFLOW, sym->name);
+
+      adjustStack (-i);
+    }
+  _G.stackOfs = sym->stack;
+  _G.stackPushes = 0;
+  
+  /* if critical function then turn interrupts off */
+  if (IFFUNC_ISCRITICAL (ftype))
+    {
+      if (IFFUNC_ARGS (ftype))
+        {
+          /* Function was passed parameters, so make sure A is preserved */
+          pushReg (hc08_reg_a, FALSE);
+          pushReg (hc08_reg_a, FALSE);
+          emitcode ("tpa", "");
+          emitcode ("sta", "2,s");
+          emitcode ("sei", "");
+          pullReg (hc08_reg_a);
+        }
+      else
+        {
+          /* No passed parameters, so A can be freely modified */
+          emitcode ("tpa", "");
+          pushReg (hc08_reg_a, TRUE);
+          emitcode ("sei", "");
+        }
+    }
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genEndFunction - generates epilogue for functions               */
+/*-----------------------------------------------------------------*/
+static void
+genEndFunction (iCode * ic)
+{
+  symbol *sym = OP_SYMBOL (IC_LEFT (ic));
+
+  if (IFFUNC_ISNAKED(sym->type))
+  {
+      emitcode(";", "naked function: no epilogue.");
+      return;
+  }
+
+  if (IFFUNC_ISCRITICAL (sym->type))
+    {
+      if (!IS_VOID(sym->type->next))
+        {
+          /* Function has return value, so make sure A is preserved */
+          pushReg (hc08_reg_a, FALSE);
+          emitcode ("lda", "2,s");
+          emitcode ("tap", "");
+          pullReg (hc08_reg_a);
+          pullNull (1);
+        }
+      else
+        {
+          /* Function returns void, so A can be freely modified */
+          pullReg (hc08_reg_a);
+          emitcode ("tap", "");
+        }
+    }
+
+  if (IFFUNC_ISREENT (sym->type) || options.stackAuto)
+    {
+    }
+
+  if (sym->stack)
+    {
+      _G.stackPushes += sym->stack;
+      adjustStack (sym->stack);
+    }
+
+
+  if ((IFFUNC_ISREENT (sym->type) || options.stackAuto))
+    {
+    }
+
+  if (IFFUNC_ISISR (sym->type))
+    {
+
+      if (!inExcludeList ("h"))
+       emitcode ("pulh", "");
+
+
+      /* if debug then send end of function */
+      if (options.debug && currFunc)
+       {
+         _G.debugLine = 1;
+         emitcode ("", "C$%s$%d$%d$%d ==.",
+                   FileBaseName (ic->filename), currFunc->lastLine,
+                   ic->level, ic->block);
+         if (IS_STATIC (currFunc->etype))
+           emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
+         else
+           emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
+         _G.debugLine = 0;
+       }
+
+      emitcode ("rti", "");
+    }
+  else
+    {
+      if (IFFUNC_CALLEESAVES(sym->type))
+       {
+         int i;
+
+         /* if any registers used */
+         if (sym->regsUsed)
+           {
+             /* save the registers used */
+             for (i = sym->regsUsed->size; i >= 0; i--)
+               {
+                 if (bitVectBitValue (sym->regsUsed, i) ||
+                     (hc08_ptrRegReq && (i == HX_IDX || i == HX_IDX)))
+                   emitcode ("pop", "%s", hc08_regWithIdx (i)->dname);
+               }
+           }
+
+       }
+
+      /* if debug then send end of function */
+      if (options.debug && currFunc)
+       {
+         _G.debugLine = 1;
+         emitcode ("", "C$%s$%d$%d$%d ==.",
+                   FileBaseName (ic->filename), currFunc->lastLine,
+                   ic->level, ic->block);
+         if (IS_STATIC (currFunc->etype))
+           emitcode ("", "XF%s$%s$0$0 ==.", moduleName, currFunc->name);
+         else
+           emitcode ("", "XG$%s$0$0 ==.", currFunc->name);
+         _G.debugLine = 0;
+       }
+
+      emitcode ("rts", "");
+    }
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genRet - generate code for return statement                     */
+/*-----------------------------------------------------------------*/
+static void
+genRet (iCode * ic)
+{
+  int size, offset = 0;
+//  int pushed = 0;
+
+  D(emitcode (";     genRet",""));
+
+  /* if we have no return value then
+     just generate the "ret" */
+  if (!IC_LEFT (ic))
+    goto jumpret;
+
+  /* we have something to return then
+     move the return value into place */
+  aopOp (IC_LEFT (ic), ic, FALSE);
+  size = AOP_SIZE (IC_LEFT (ic));
+
+#if 1
+   offset = size - 1;
+   while (size--)
+     {
+       transferAopAop (AOP (IC_LEFT (ic)), offset, hc08_aop_pass[offset], 0);
+       offset--;
+     }
+#else
+  switch (size)
+    {
+      case 4:
+        /* 4 byte return: store value in the global return variable */
+        offset = size-1;
+        while (size--)
+          {
+            loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), offset);
+            STA (fReturn2[offset--], FALSE);
+            hc08_freeReg (hc08_reg_a);
+          }
+        break;
+      case 2:
+        /* 2 byte return: store value in x:a */
+        loadRegFromAop (hc08_reg_xa, AOP (IC_LEFT (ic)), 0);
+        hc08_freeReg (hc08_reg_xa);
+        break;
+      case 1:
+        /* 1 byte return: store value in a */
+        loadRegFromAop (hc08_reg_a, AOP (IC_LEFT (ic)), 0);
+        hc08_freeReg (hc08_reg_a);
+        break;
+    }
+#endif
+
+  freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
+
+jumpret:
+  /* generate a jump to the return label
+     if the next is not the return statement */
+  if (!(ic->next && ic->next->op == LABEL &&
+       IC_LABEL (ic->next) == returnLabel))
+
+    emitcode ("jmp", "%05d$", (returnLabel->key + 100));
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genLabel - generates a label                                    */
+/*-----------------------------------------------------------------*/
+static void
+genLabel (iCode * ic)
+{
+  int i;
+  regs *reg;
+  
+  /* For the high level labels we cannot depend on any */
+  /* register's contents. Amnesia time.                */
+  for (i=A_IDX;i<=XA_IDX;i++)
+    {
+      reg = hc08_regWithIdx(i);
+      if (reg)
+        reg->aop = NULL;
+    }
+
+  /* special case never generate */
+  if (IC_LABEL (ic) == entryLabel)
+    return;
+
+  emitcode ("", "%05d$:", (IC_LABEL (ic)->key + 100));
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genGoto - generates a jmp                                      */
+/*-----------------------------------------------------------------*/
+static void
+genGoto (iCode * ic)
+{
+  emitcode ("jmp", "%05d$", (IC_LABEL (ic)->key + 100));
+}
+
+#if 0
+/*-----------------------------------------------------------------*/
+/* findLabelBackwards: walks back through the iCode chain looking  */
+/* for the given label. Returns number of iCode instructions     */
+/* between that label and given ic.          */
+/* Returns zero if label not found.          */
+/*-----------------------------------------------------------------*/
+static int
+findLabelBackwards (iCode * ic, int key)
+{
+  int count = 0;
+
+  while (ic->prev)
+    {
+      ic = ic->prev;
+      count++;
+
+      /* If we have any pushes or pops, we cannot predict the distance.
+        I don't like this at all, this should be dealt with in the 
+        back-end */
+      if (ic->op == IPUSH || ic->op == IPOP) {
+       return 0;
+      }
+
+      if (ic->op == LABEL && IC_LABEL (ic)->key == key)
+       {
+         return count;
+       }
+    }
+
+  return 0;
+}
+#endif
+
+/*-----------------------------------------------------------------*/
+/* genPlusIncr :- does addition with increment if possible         */
+/*-----------------------------------------------------------------*/
+static bool
+genPlusIncr (iCode * ic)
+{
+  int icount;
+  operand *left;
+  operand *result;
+  bool needpulx;
+  bool needpulh;
+  bool needpula;
+  unsigned int size = getDataSize (IC_RESULT (ic));
+  int offset;
+  symbol *tlbl = NULL;
+  
+  left = IC_LEFT (ic);
+  result = IC_RESULT (ic);
+
+  /* will try to generate an increment */
+  /* if the right side is not a literal
+     we cannot */
+  if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
+    return FALSE;
+
+  icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
+
+  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) )
+      )
+      && (icount>=-128) && (icount<=127) && (size==2))
+    {
+      needpulx = pushRegIfUsed (hc08_reg_x);
+      needpulh = pushRegIfUsed (hc08_reg_h);
+      loadRegFromAop (hc08_reg_hx, AOP(left), 0);
+      emitcode ("aix","#%d", icount);
+      hc08_dirtyReg (hc08_reg_hx, FALSE);
+      storeRegToAop (hc08_reg_hx, AOP(result), 0);
+      pullOrFreeReg (hc08_reg_h, needpulh);
+      pullOrFreeReg (hc08_reg_x, needpulx);
+      return TRUE;
+    }
+
+  emitcode ("", "; icount = %d, sameRegs=%d", icount, 
+            sameRegs (AOP (left), AOP (result)));
+  
+  if ((icount > 255) || (icount<0))
+    return FALSE;
+
+  if (!sameRegs (AOP (left), AOP (result)))
+    return FALSE;
+
+  D(emitcode (";     genPlusIncr",""));
+
+  if (size>1)
+    tlbl = newiTempLabel (NULL);
+
+  if (icount==1)
+    {
+      needpula = FALSE;
+      rmwWithAop ("inc", AOP (result), 0);
+      if (1<size)
+        emitBranch ("bne", tlbl);
+    }
+  else
+    {
+      needpula = pushRegIfUsed (hc08_reg_a);
+      loadRegFromAop (hc08_reg_a, AOP (result), 0);
+      accopWithAop ("add", AOP (IC_RIGHT (ic)), 0);
+      hc08_useReg (hc08_reg_a);
+      storeRegToAop (hc08_reg_a, AOP (result), 0);
+      hc08_freeReg (hc08_reg_a);
+      if (1<size)
+        emitBranch ("bcc", tlbl);
+    }
+  for (offset=1; offset<size; offset++)
+    {
+      rmwWithAop ("inc", AOP (result), offset);
+      if ((offset+1)<size)
+        emitBranch ("bne", tlbl);
+    }
+
+  if (size>1)
+    emitLabel (tlbl);
+  
+  pullOrFreeReg (hc08_reg_a, needpula);
+      
+  return TRUE;
+}
+
+
+
+/*-----------------------------------------------------------------*/
+/* genPlus - generates code for addition                           */
+/*-----------------------------------------------------------------*/
+static void
+genPlus (iCode * ic)
+{
+  int size, offset = 0;
+  char *add;
+  asmop *leftOp, *rightOp;
+
+  /* special cases :- */
+
+  D(emitcode (";     genPlus",""));
+
+  aopOp (IC_LEFT (ic), ic, FALSE);
+  aopOp (IC_RIGHT (ic), ic, FALSE);
+  aopOp (IC_RESULT (ic), ic, TRUE);
+
+  /* we want registers on the left and literals on the right */
+  if ((AOP_TYPE (IC_LEFT (ic)) == AOP_LIT) ||
+      (AOP_TYPE (IC_RIGHT (ic)) == AOP_REG))
+    {
+      operand *t = IC_RIGHT (ic);
+      IC_RIGHT (ic) = IC_LEFT (ic);
+      IC_LEFT (ic) = t;
+    }
+
+
+  /* if I can do an increment instead
+     of add then GOOD for ME */
+  if (genPlusIncr (ic) == TRUE)
+    goto release;
+
+  emitcode("",";  left size = %d", getDataSize (IC_LEFT(ic)));
+  emitcode("",";  right size = %d", getDataSize (IC_RIGHT(ic)));
+  emitcode("",";  result size = %d", getDataSize (IC_RESULT(ic)));
+  
+  size = getDataSize (IC_RESULT (ic));
+
+  leftOp = AOP(IC_LEFT(ic));
+  rightOp = AOP(IC_RIGHT(ic));
+  add = "add";
+
+  offset = 0;
+  while (size--)
+    {
+      loadRegFromAop (hc08_reg_a, leftOp, offset);
+      accopWithAop(add, rightOp, offset);
+      storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
+      hc08_freeReg (hc08_reg_a);
+      add = "adc";  /* further adds must propagate carry */
+    }
+
+
+//  adjustArithmeticResult (ic);
+
+release:
+  freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+  freeAsmop (IC_RIGHT (ic), NULL, ic, TRUE);
+  freeAsmop (IC_LEFT (ic), NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genMinusDec :- does subtraction with deccrement if possible     */
+/*-----------------------------------------------------------------*/
+static bool
+genMinusDec (iCode * ic)
+{
+  unsigned int icount;
+  operand *left;
+  operand *result;
+  bool needpulx;
+  bool needpulh;
+  unsigned int size = getDataSize (IC_RESULT (ic));
+//  int offset;
+//  symbol *tlbl;
+  
+  left = IC_LEFT (ic);
+  result = IC_RESULT (ic);
+
+  /* will try to generate an increment */
+  /* if the right side is not a literal
+     we cannot */
+  if (AOP_TYPE (IC_RIGHT (ic)) != AOP_LIT)
+    return FALSE;
+
+  icount = (unsigned int) floatFromVal (AOP (IC_RIGHT (ic))->aopu.aop_lit);
+
+  if ((AOP_TYPE (left) == AOP_DIR) && (AOP_TYPE (result) == AOP_DIR)
+      && (icount>=-127) && (icount<=128) && (size==2))
+    {
+      needpulx = pushRegIfUsed (hc08_reg_x);
+      needpulh = pushRegIfUsed (hc08_reg_h);
+      loadRegFromAop (hc08_reg_hx, AOP(left), 0);
+      emitcode ("aix","#%d", -icount);
+      hc08_dirtyReg (hc08_reg_hx, FALSE);
+      storeRegToAop (hc08_reg_hx, AOP(result), 0);
+      pullOrFreeReg (hc08_reg_h, needpulh);
+      pullOrFreeReg (hc08_reg_x, needpulx);
+      return TRUE;
+    }
+  
+  if ((icount > 1) || (icount<0))
+    return FALSE;
+
+  if (!sameRegs (AOP (left), AOP (result)))
+    return FALSE;
+
+  if (size!=1)
+    return FALSE;
+
+  D(emitcode (";     genMinusDec",""));
+
+  rmwWithAop ("dec", AOP (result), 0);
+  
+  return TRUE;
+}
+
+/*-----------------------------------------------------------------*/
+/* addSign - complete with sign                                    */
+/*-----------------------------------------------------------------*/
+static void
+addSign (operand * result, int offset, int sign)
+{
+  int size = (getDataSize (result) - offset);
+  if (size > 0)
+    {
+      if (sign)
+       {
+         emitcode ("rola", "");
+         emitcode ("clra", "");
+         emitcode ("sbc", zero);
+         while (size--)
+           storeRegToAop (hc08_reg_a, AOP (result), offset++);
+       }
+      else
+       while (size--)
+         storeConstToAop (zero, AOP (result), offset++);
+    }
+}
+
+
+/*-----------------------------------------------------------------*/
+/* genMinus - generates code for subtraction                       */
+/*-----------------------------------------------------------------*/
+static void
+genMinus (iCode * ic)
+{
+  char *sub;
+  int size, offset = 0;
+
+  D(emitcode (";     genMinus",""));
+
+  aopOp (IC_LEFT (ic), ic, FALSE);
+  aopOp (IC_RIGHT (ic), ic, FALSE);
+  aopOp (IC_RESULT (ic), ic, TRUE);
+
+  /* special cases :- */
+  /* if I can do an decrement instead
+     of subtract then GOOD for ME */
+  if (genMinusDec (ic) == TRUE)
+    goto release;
+
+  size = getDataSize (IC_RESULT (ic));
+
+  asmop *leftOp, *rightOp;
+
+  leftOp = AOP(IC_LEFT(ic));
+  rightOp = AOP(IC_RIGHT(ic));
+
+  sub = "sub";
+  offset = 0;
+  while (size--)
+    {
+      loadRegFromAop ( hc08_reg_a, leftOp, offset);
+      accopWithAop(sub, rightOp, offset);
+      storeRegToAop (hc08_reg_a, AOP (IC_RESULT (ic)), offset++);
+      sub = "sbc";
+    }
+  
+  
+//  adjustArithmeticResult (ic);
+
+release:
+  freeAsmop (IC_LEFT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  freeAsmop (IC_RIGHT (ic), NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+}
+
+
+
+/*-----------------------------------------------------------------*/
+/* genMultOneByte : 8*8=8/16 bit multiplication                    */
+/*-----------------------------------------------------------------*/
+static void
+genMultOneByte (operand * left,
+               operand * right,
+               operand * result)
+{
+  sym_link *opetype = operandType (result);
+  symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
+  int size=AOP_SIZE(result);
+  bool negLiteral = FALSE;
+
+  D(emitcode (";     genMultOneByte",""));
+
+  if (size<1 || size>2) {
+    // this should never happen
+      fprintf (stderr, "size!=1||2 (%d) in %s at line:%d \n", 
+              AOP_SIZE(result), __FILE__, lineno);
+      exit (1);
+  }
+
+  /* (if two literals: the value is computed before) */
+  /* if one literal, literal on the right */
+  if (AOP_TYPE (left) == AOP_LIT)
+    {
+      operand *t = right;
+      right = left;
+      left = t;
+      //emitcode (";", "swapped left and right");
+    }
+
+  if (SPEC_USIGN(opetype))
+    {
+      // just an unsigned 8*8=8/16 multiply
+      //emitcode (";","unsigned");
+
+      loadRegFromAop (hc08_reg_a, AOP (left), 0);
+      loadRegFromAop (hc08_reg_x, AOP (right), 0);
+      emitcode ("mul", "");
+      hc08_dirtyReg (hc08_reg_xa, FALSE);
+      storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
+      hc08_freeReg (hc08_reg_xa);
+      
+      return;
+    }
+
+  // we have to do a signed multiply
+
+
+  //emitcode (";", "signed");
+  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 (AOP_TYPE(right)==AOP_LIT)
+    {
+      signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
+      /* AND literal negative */
+      if (val < 0) {
+        emitcode ("ldx", "#0x%02x", -val);
+        negLiteral = TRUE;
+      } else {
+        emitcode ("ldx", "#0x%02x", val);
+      }
+      hc08_useReg (hc08_reg_x);
+    }
+  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);
+    }
+
+  emitcode ("mul", "");
+  hc08_dirtyReg (hc08_reg_xa, FALSE);
+
+  tlbl3 = newiTempLabel (NULL);
+  emitcode ("dec", "1,s");
+  if (negLiteral)
+    emitBranch ("bne", tlbl3);
+  else
+    emitBranch ("beq", 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);
+    }
+
+  emitLabel (tlbl3);
+  adjustStack (1);
+  storeRegToFullAop (hc08_reg_xa, AOP (result), TRUE);
+  hc08_freeReg (hc08_reg_xa);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genMult - generates code for multiplication                     */
+/*-----------------------------------------------------------------*/
+static void
+genMult (iCode * ic)
+{
+  operand *left = IC_LEFT (ic);
+  operand *right = IC_RIGHT (ic);
+  operand *result = IC_RESULT (ic);
+
+  D(emitcode (";     genMult",""));
+
+  /* assign the amsops */
+  aopOp (left, ic, FALSE);
+  aopOp (right, ic, FALSE);
+  aopOp (result, ic, TRUE);
+
+  /* special cases first */
+  /* if both are of size == 1 */
+//  if (getSize(operandType(left)) == 1 && 
+//      getSize(operandType(right)) == 1)
+  if (AOP_SIZE (left) == 1 && 
+      AOP_SIZE (right) == 1)
+    {
+      genMultOneByte (left, right, result);
+      goto release;
+    }
+
+  /* should have been converted to function call */
+    fprintf (stderr, "left: %d right: %d\n", getSize(OP_SYMBOL(left)->type),
+            getSize(OP_SYMBOL(right)->type));
+    fprintf (stderr, "left: %d right: %d\n", AOP_SIZE (left),
+            AOP_SIZE (right));
+  assert (0);
+
+release:
+  freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  freeAsmop (result, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genDivOneByte : 8 bit division                                  */
+/*-----------------------------------------------------------------*/
+static void
+genDivOneByte (operand * left,
+              operand * right,
+              operand * result)
+{
+  sym_link *opetype = operandType (result);
+//  char *l;
+  symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
+  int size;
+  bool negLiteral = FALSE;
+
+  D(emitcode (";     genDivOneByte",""));
+
+  size = AOP_SIZE (result);
+  /* signed or unsigned */
+  if (SPEC_USIGN (opetype))
+    {
+      /* unsigned is easy */
+      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_a, AOP (result), FALSE);
+      hc08_freeReg (hc08_reg_a);
+      hc08_freeReg (hc08_reg_x);
+      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)
+    {
+      signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
+      /* AND literal negative */
+      if (val < 0) {
+        emitcode ("ldx", "#0x%02x", -val);
+        negLiteral = TRUE;
+      } else {
+        emitcode ("ldx", "#0x%02x", val);
+      }
+      hc08_useReg (hc08_reg_x);
+    }
+  else
+    {
+      tlbl3 = newiTempLabel (NULL);
+      loadRegFromAop (hc08_reg_x, AOP (right), 0);
+      emitBranch ("bpl", tlbl3);
+      emitcode ("inc", "1,s");
+      rmwWithReg ("neg", hc08_reg_x);
+      emitLabel (tlbl3);
+    }
+
+  emitcode ("div", "");
+  hc08_dirtyReg (hc08_reg_x, FALSE);
+  hc08_dirtyReg (hc08_reg_a, FALSE);
+  hc08_dirtyReg (hc08_reg_h, 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);
+
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genDiv - generates code for division                            */
+/*-----------------------------------------------------------------*/
+static void
+genDiv (iCode * ic)
+{
+  operand *left = IC_LEFT (ic);
+  operand *right = IC_RIGHT (ic);
+  operand *result = IC_RESULT (ic);
+
+  D(emitcode (";     genDiv",""));
+
+  /* assign the amsops */
+  aopOp (left, ic, FALSE);
+  aopOp (right, ic, FALSE);
+  aopOp (result, ic, TRUE);
+
+  /* special cases first */
+  /* if both are of size == 1 */
+  if (AOP_SIZE (left) <= 2 &&
+      AOP_SIZE (right) == 1)
+    {
+      genDivOneByte (left, right, result);
+      goto release;
+    }
+
+  /* should have been converted to function call */
+  assert (0);
+release:
+  freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  freeAsmop (result, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genModOneByte : 8 bit modulus                                   */
+/*-----------------------------------------------------------------*/
+static void
+genModOneByte (operand * left,
+              operand * right,
+              operand * result)
+{
+  sym_link *opetype = operandType (result);
+//  symbol *lbl;
+  symbol *tlbl1, *tlbl2, *tlbl3, *tlbl4;
+  int size;
+  bool negLiteral = FALSE;
+
+  D(emitcode (";     genModOneByte",""));
+
+  size = AOP_SIZE (result);
+  /* signed or unsigned */
+  if (SPEC_USIGN (opetype))
+    {
+      /* unsigned is easy */
+      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_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)
+    {
+      signed char val=floatFromVal (AOP (right)->aopu.aop_lit);
+      /* AND literal negative */
+      if (val < 0) {
+        emitcode ("ldx", "#0x%02x", -val);
+        negLiteral = TRUE;
+      } else {
+        emitcode ("ldx", "#0x%02x", val);
+      }
+      hc08_useReg (hc08_reg_x);
+    }
+  else
+    {
+      tlbl3 = newiTempLabel (NULL);
+      loadRegFromAop (hc08_reg_x, AOP (right), 0);
+      emitBranch ("bpl", tlbl3);
+      emitcode ("inc", "1,s");
+      rmwWithReg ("neg", hc08_reg_x);
+      emitLabel (tlbl3);
+    }
+
+  emitcode ("div", "");
+  hc08_dirtyReg (hc08_reg_x, FALSE);
+  hc08_dirtyReg (hc08_reg_a, FALSE);
+  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);
+  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);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genMod - generates code for division                            */
+/*-----------------------------------------------------------------*/
+static void
+genMod (iCode * ic)
+{
+  operand *left = IC_LEFT (ic);
+  operand *right = IC_RIGHT (ic);
+  operand *result = IC_RESULT (ic);
+
+  D(emitcode (";     genMod",""));
+
+  /* assign the amsops */
+  aopOp (left, ic, FALSE);
+  aopOp (right, ic, FALSE);
+  aopOp (result, ic, TRUE);
+
+  /* special cases first */
+  /* if both are of size == 1 */
+  if (AOP_SIZE (left) <= 2 &&
+      AOP_SIZE (right) == 1)
+    {
+      genModOneByte (left, right, result);
+      goto release;
+    }
+
+  /* should have been converted to function call */
+  assert (0);
+
+release:
+  freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  freeAsmop (result, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genIfxJump :- will create a jump depending on the ifx           */
+/*-----------------------------------------------------------------*/
+static void
+genIfxJump (iCode * ic, char *jval)
+{
+  symbol *jlbl;
+  symbol *tlbl = newiTempLabel (NULL);
+  char *inst;
+
+  D(emitcode (";     genIfxJump",""));
+
+  /* if true label then we jump if condition
+     supplied is true */
+  if (IC_TRUE (ic))
+    {
+      jlbl = IC_TRUE (ic);
+      if (!strcmp (jval, "a"))
+        inst = "beq";
+      else if (!strcmp (jval, "c"))
+        inst = "bcc";
+      else
+        inst = "bge";
+    }
+  else
+    {
+      /* false label is present */
+      jlbl = IC_FALSE (ic);
+      if (!strcmp (jval, "a"))
+        inst = "bne";
+      else if (!strcmp (jval, "c"))
+        inst = "bcs";
+      else
+        inst = "blt";
+    }
+  emitBranch (inst, tlbl);
+  emitBranch ("jmp", jlbl);
+  emitLabel (tlbl);
+
+  /* mark the icode as generated */
+  ic->generated = 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* genCmp :- greater or less than 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
+           {
+              needpula = pushRegIfUsed (hc08_reg_a);
+             loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) -1);
+             emitcode ("rola", "");
+             hc08_useReg (hc08_reg_a);
+           }
+         sign = 0;
+          goto release;
+       }
+    }
+
+  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;
+    }
+
+  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";
+    }
+
+release:
+  freeAsmop (right, NULL, ic, TRUE);
+  freeAsmop (left, NULL, ic, TRUE);
+  if (AOP_TYPE (result) == AOP_CRY && AOP_SIZE (result))
+    {
+      outBitC (result);
+    }
+  else
+    {
+      /* 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");
+        }
+      else
+        if (!sign)
+         outBitC (result);
+       else
+         outBitNV (result);
+        pullOrFreeReg(hc08_reg_a,needpula);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genCmpGt :- greater than comparison                             */
+/*-----------------------------------------------------------------*/
+static void
+genCmpGt (iCode * ic, iCode * ifx)
+{
+  operand *left, *right, *result;
+  sym_link *letype, *retype;
+  int sign;
+
+  D(emitcode (";     genCmpGt",""));
+
+  result = IC_RESULT (ic);
+  left = IC_LEFT (ic);
+  right = IC_RIGHT (ic);
+
+  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 (right, left, result, ifx, sign,ic);
+
+  freeAsmop (result, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genCmpLt - less than comparisons                                */
+/*-----------------------------------------------------------------*/
+static void
+genCmpLt (iCode * ic, iCode * ifx)
+{
+  operand *left, *right, *result;
+  sym_link *letype, *retype;
+  int sign;
+
+  D(emitcode (";     genCmpLt",""));
+
+  result = IC_RESULT (ic);
+  left = IC_LEFT (ic);
+  right = IC_RIGHT (ic);
+
+  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)
+    {
+      operand *t = right;
+      right = left;
+      left = t;
+    }
+  if (AOP_TYPE (right) == AOP_LIT)
+    lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+
+  while (size--)
+    {
+      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++;
+    }
+
+}
+
+/*-----------------------------------------------------------------*/
+/* 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)
+    {
+      operand *t = IC_RIGHT (ic);
+      IC_RIGHT (ic) = IC_LEFT (ic);
+      IC_LEFT (ic) = t;
+    }
+
+  if (ifx && !AOP_SIZE (result))
+    {
+      symbol *tlbl;
+      tlbl = newiTempLabel (NULL);
+      gencbneshort (left, right, tlbl);
+      if (IC_TRUE (ifx))
+        {
+          emitBranch ("jmp", IC_TRUE (ifx));
+          emitLabel (tlbl);
+        }
+      else
+       {
+         symbol *lbl = newiTempLabel (NULL);
+          emitBranch ("bra", lbl);
+          emitLabel (tlbl);
+          emitBranch ("jmp", IC_FALSE (ifx));
+          emitLabel (lbl);
+       }
+      
+      /* 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)
+    {
+      genIfxJump (ifx, "a");
+      goto release;
+    }
+  /* 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     */
+/*-----------------------------------------------------------------*/
+static iCode *
+ifxForOp (operand * op, iCode * ic)
+{
+  /* if true symbol then needs to be assigned */
+  if (IS_TRUE_SYMOP (op))
+    return NULL;
+
+  /* if this has register type condition and
+     the next instruction is ifx with the same operand
+     and live to of the operand is upto the ifx only then */
+  if (ic->next &&
+      ic->next->op == IFX &&
+      IC_COND (ic->next)->key == op->key &&
+      OP_SYMBOL (op)->liveTo <= ic->next->seq)
+    return ic->next;
+
+  return NULL;
+}
+
+static bool
+genPointerGetSetOfs (iCode *ic)
+{
+  iCode *lic = ic->next;
+  bool pset, pget;
+  int offset, size;
+  symbol *sym;
+  asmop *derefaop;
+
+  /* Make sure we have a next iCode */
+  emitcode("","; checking lic");
+  if (!lic)
+    return FALSE;
+
+  /* Make sure the result of the addition is an iCode */
+  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);
+  emitcode("","; pset=%d, pget=%d",pset,pget);
+  if (!pset && !pget)
+    return FALSE;
+
+  emitcode("", "; checking pset operandsEqu");
+  if (pset & !operandsEqu (IC_RESULT (ic), IC_RESULT (lic)))
+    return FALSE;
+
+  emitcode("", "; checking pget operandsEqu");
+  if (pget & !operandsEqu (IC_RESULT (ic), IC_LEFT (lic)))
+    return FALSE;
+
+  emitcode("", "; checking IS_SYMOP");
+  if (!IS_SYMOP (IC_LEFT (ic)))
+    return FALSE;
+
+  emitcode("", "; checking !IS_TRUE_SYMOP");
+  if (IS_TRUE_SYMOP (IC_LEFT (ic)))
+    return FALSE;
+
+  sym = OP_SYMBOL (IC_LEFT (ic));
+  
+  emitcode("", "; checking remat");
+  if (!sym->remat)
+    return FALSE;
+    
+  if (pget)
+    {
+      D(emitcode (";     genPointerGetOfs",""));
+      aopOp (IC_LEFT(ic), ic, FALSE);
+      derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
+      freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
+      
+      aopOp (IC_RIGHT(ic), ic, FALSE);
+      aopOp (IC_RESULT(lic), lic, FALSE);
+      
+
+      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));
+          hc08_useReg (hc08_reg_a);
+          storeRegToAop (hc08_reg_a, AOP (IC_RESULT (lic)), offset++);
+          hc08_freeReg (hc08_reg_a);
+        }
+
+      lic->generated = 1;
+      hc08_freeReg (hc08_reg_hx);
+
+      freeAsmop (NULL, derefaop, ic, TRUE);
+      freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
+      freeAsmop (IC_RESULT(lic), NULL, lic, TRUE);
+      
+      return TRUE;
+    }
+
+  if (pset)
+    {
+      D(emitcode (";     genPointerSetOfs",""));
+      aopOp (IC_LEFT(ic), ic, FALSE);
+      derefaop = aopDerefAop (AOP (IC_LEFT (ic)));
+      freeAsmop (IC_LEFT(ic), NULL, ic, TRUE);
+
+      aopOp (IC_RIGHT(ic), ic, FALSE);
+      aopOp (IC_RIGHT(lic), lic, FALSE);
+      
+
+      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);
+          emitcode ("sta", "%s,x",
+                    aopAdrStr (derefaop, offset, TRUE));
+          hc08_freeReg (hc08_reg_a);
+          offset++;
+        }
+
+      lic->generated = 1;
+      hc08_freeReg (hc08_reg_hx);
+
+      freeAsmop (NULL, derefaop, ic, TRUE);
+      freeAsmop (IC_RIGHT(ic), NULL, ic, TRUE);
+      freeAsmop (IC_RIGHT(lic), NULL, lic, TRUE);
+      
+      return TRUE;
+    }
+    
+  return FALSE;
+}
+
+
+/*-----------------------------------------------------------------*/
+/* hasInc - operand is incremented before any other use            */
+/*-----------------------------------------------------------------*/
+static iCode *
+hasInc (operand *op, iCode *ic,int osize)
+{
+  sym_link *type = operandType(op);
+  sym_link *retype = getSpec (type);
+  iCode *lic = ic->next;
+  int isize ;
+  
+  /* this could from a cast, e.g.: "(char xdata *) 0x7654;" */
+  if (!IS_SYMOP(op)) return NULL;
+
+  if (IS_BITVAR(retype)||!IS_PTR(type)) return NULL;
+  if (IS_AGGREGATE(type->next)) return NULL;
+  if (osize != (isize = getSize(type->next))) return NULL;
+
+  while (lic) {
+    /* if operand of the form op = op + <sizeof *op> */
+    if (lic->op == '+' && isOperandEqual(IC_LEFT(lic),op) &&
+       isOperandEqual(IC_RESULT(lic),op) && 
+       isOperandLiteral(IC_RIGHT(lic)) &&
+       operandLitValue(IC_RIGHT(lic)) == isize) {
+      return lic;
+    }
+    /* if the operand used or deffed */
+    if (bitVectBitValue(OP_USES(op),lic->key) || (unsigned) lic->defKey == op->key) {
+      return NULL;
+    }
+    /* if GOTO or IFX */
+    if (lic->op == IFX || lic->op == GOTO || lic->op == LABEL) break;
+    lic = lic->next;
+  }
+  return NULL;
+}
+
+/*-----------------------------------------------------------------*/
+/* genAndOp - for && operation                                     */
+/*-----------------------------------------------------------------*/
+static void
+genAndOp (iCode * ic)
+{
+  operand *left, *right, *result;
+  symbol *tlbl, *tlbl0;
+
+  D(emitcode (";     genAndOp",""));
+
+  /* note here that && operations that are in an
+     if statement are taken away by backPatchLabels
+     only those used in arthmetic operations remain */
+  aopOp ((left = IC_LEFT (ic)), ic, FALSE);
+  aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
+  aopOp ((result = IC_RESULT (ic)), ic, FALSE);
+
+  tlbl = newiTempLabel (NULL);
+  tlbl0 = newiTempLabel (NULL);
+  
+  asmopToBool (AOP (left), FALSE);
+  emitBranch ("beq", tlbl0);
+  asmopToBool (AOP (right), FALSE);
+  emitBranch ("beq", tlbl0);
+  loadRegFromConst (hc08_reg_a,one);
+  emitBranch ("bra", tlbl);
+  emitLabel (tlbl0);
+  loadRegFromConst (hc08_reg_a,zero);
+  emitLabel (tlbl);
+
+  hc08_useReg (hc08_reg_a);
+  hc08_freeReg (hc08_reg_a);
+  
+  storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
+
+  freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  freeAsmop (result, NULL, ic, TRUE);
+}
+
+
+/*-----------------------------------------------------------------*/
+/* genOrOp - for || operation                                      */
+/*-----------------------------------------------------------------*/
+static void
+genOrOp (iCode * ic)
+{
+  operand *left, *right, *result;
+  symbol *tlbl, *tlbl0;
+
+  D(emitcode (";     genOrOp",""));
+
+  /* note here that || operations that are in an
+     if statement are taken away by backPatchLabels
+     only those used in arthmetic operations remain */
+  aopOp ((left = IC_LEFT (ic)), ic, FALSE);
+  aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
+  aopOp ((result = IC_RESULT (ic)), ic, FALSE);
+
+  tlbl = newiTempLabel (NULL);
+  tlbl0 = newiTempLabel (NULL);
+  
+  asmopToBool (AOP (left), FALSE);
+  emitBranch ("bne", tlbl0);
+  asmopToBool (AOP (right), FALSE);
+  emitBranch ("bne", tlbl0);
+  loadRegFromConst (hc08_reg_a,zero);
+  emitBranch ("bra", tlbl);
+  emitLabel (tlbl0);
+  loadRegFromConst (hc08_reg_a,one);
+  emitLabel (tlbl);
+
+  hc08_useReg (hc08_reg_a);
+  hc08_freeReg (hc08_reg_a);
+  
+  storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
+
+
+  freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  freeAsmop (result, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* isLiteralBit - test if lit == 2^n                               */
+/*-----------------------------------------------------------------*/
+static int
+isLiteralBit (unsigned long lit)
+{
+  unsigned long pw[32] =
+  {1L, 2L, 4L, 8L, 16L, 32L, 64L, 128L,
+   0x100L, 0x200L, 0x400L, 0x800L,
+   0x1000L, 0x2000L, 0x4000L, 0x8000L,
+   0x10000L, 0x20000L, 0x40000L, 0x80000L,
+   0x100000L, 0x200000L, 0x400000L, 0x800000L,
+   0x1000000L, 0x2000000L, 0x4000000L, 0x8000000L,
+   0x10000000L, 0x20000000L, 0x40000000L, 0x80000000L};
+  int idx;
+
+  for (idx = 0; idx < 32; idx++)
+    if (lit == pw[idx])
+      return idx + 1;
+  return 0;
+}
+
+#if 0
+/*-----------------------------------------------------------------*/
+/* continueIfTrue -                                                */
+/*-----------------------------------------------------------------*/
+static void
+continueIfTrue (iCode * ic)
+{
+  if (IC_TRUE (ic))
+    emitBranch ("jmp", IC_TRUE (ic));
+  ic->generated = 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* jmpIfTrue -                                                     */
+/*-----------------------------------------------------------------*/
+static void
+jumpIfTrue (iCode * ic)
+{
+  if (!IC_TRUE (ic))
+    emitBranch ("jmp", IC_FALSE (ic));
+  ic->generated = 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* jmpTrueOrFalse -                                                */
+/*-----------------------------------------------------------------*/
+static void
+jmpTrueOrFalse (iCode * ic, symbol * tlbl)
+{
+  // ugly but optimized by peephole
+  if (IC_TRUE (ic))
+    {
+      symbol *nlbl = newiTempLabel (NULL);
+      emitBranch ("bra", nlbl);
+      emitLabel (tlbl);
+      emitBranch ("jmp", IC_TRUE (ic));
+      emitLabel (nlbl);
+    }
+  else
+    {
+      emitBranch ("jmp", IC_FALSE (ic));
+      emitLabel (tlbl);
+    }
+  ic->generated = 1;
+}
+#endif
+
+/*-----------------------------------------------------------------*/
+/* genAnd  - code for and                                          */
+/*-----------------------------------------------------------------*/
+static void
+genAnd (iCode * ic, iCode * ifx)
+{
+  operand *left, *right, *result;
+  int size, offset = 0;
+  unsigned long lit = 0L;
+  unsigned long litinv;
+
+  
+//  int bytelit = 0;
+//  char buffer[10];
+
+  D(emitcode (";     genAnd",""));
+
+  aopOp ((left = IC_LEFT (ic)), ic, FALSE);
+  aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
+  aopOp ((result = IC_RESULT (ic)), ic, TRUE);
+
+#ifdef DEBUG_TYPE
+  emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
+           AOP_TYPE (result),
+           AOP_TYPE (left), AOP_TYPE (right));
+  emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
+           AOP_SIZE (result),
+           AOP_SIZE (left), AOP_SIZE (right));
+#endif
+
+  /* if left is a literal & right is not then exchange them */
+  if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
+    {
+      operand *tmp = right;
+      right = left;
+      left = tmp;
+    }
+
+  /* if left is accumulator & right is not then exchange them */
+  if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
+    {
+      operand *tmp = right;
+      right = left;
+      left = tmp;
+    }
+
+  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))
+        {
+          int bitpos = isLiteralBit(litinv)-1;
+          emitcode ("bclr","#%d,%s",bitpos & 7,
+                    aopAdrStr (AOP (left), bitpos >> 3, FALSE));
+          goto release;
+        }
+    }
+
+  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);      
+    }
+
+release:
+  freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  freeAsmop (result, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genOr  - code for or                                            */
+/*-----------------------------------------------------------------*/
+static void
+genOr (iCode * ic, iCode * ifx)
+{
+  operand *left, *right, *result;
+  int size, offset = 0;
+  unsigned long lit = 0L;
+
+  D(emitcode (";     genOr",""));
+
+  aopOp ((left = IC_LEFT (ic)), ic, FALSE);
+  aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
+  aopOp ((result = IC_RESULT (ic)), ic, TRUE);
+
+#ifdef DEBUG_TYPE
+  emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
+           AOP_TYPE (result),
+           AOP_TYPE (left), AOP_TYPE (right));
+  emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
+           AOP_SIZE (result),
+           AOP_SIZE (left), AOP_SIZE (right));
+#endif
+
+  /* if left is a literal & right is not then exchange them */
+  if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
+    {
+      operand *tmp = right;
+      right = left;
+      left = tmp;
+    }
+
+  /* if left is accumulator & right is not then exchange them */
+  if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
+    {
+      operand *tmp = right;
+      right = left;
+      left = tmp;
+    }
+
+  /* if right is bit then exchange them */
+  if (AOP_TYPE (right) == AOP_CRY &&
+      AOP_TYPE (left) != AOP_CRY)
+    {
+      operand *tmp = right;
+      right = left;
+      left = tmp;
+    }
+  if (AOP_TYPE (right) == AOP_LIT)
+    lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+
+  size = AOP_SIZE (result);
+
+  if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))) &&
+      (AOP_TYPE (right) == AOP_LIT) && isLiteralBit(lit) &&
+      (AOP_TYPE (left) == AOP_DIR))
+    {
+      int bitpos = isLiteralBit(lit)-1;
+      emitcode ("bset","#%d,%s",bitpos & 7,
+                aopAdrStr (AOP (left), bitpos >> 3, FALSE));
+      goto release;
+    }
+    
+
+
+  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);      
+    }
+
+
+release:
+  freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  freeAsmop (result, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genXor - code for xclusive or                                   */
+/*-----------------------------------------------------------------*/
+static void
+genXor (iCode * ic, iCode * ifx)
+{
+  operand *left, *right, *result;
+  int size, offset = 0;
+  unsigned long lit = 0L;
+
+  D(emitcode (";     genXor",""));
+
+  aopOp ((left = IC_LEFT (ic)), ic, FALSE);
+  aopOp ((right = IC_RIGHT (ic)), ic, FALSE);
+  aopOp ((result = IC_RESULT (ic)), ic, TRUE);
+
+#ifdef DEBUG_TYPE
+  emitcode ("", "; Type res[%d] = l[%d]&r[%d]",
+           AOP_TYPE (result),
+           AOP_TYPE (left), AOP_TYPE (right));
+  emitcode ("", "; Size res[%d] = l[%d]&r[%d]",
+           AOP_SIZE (result),
+           AOP_SIZE (left), AOP_SIZE (right));
+#endif
+
+  /* if left is a literal & right is not ||
+     if left needs acc & right does not */
+  if (AOP_TYPE (left) == AOP_LIT && AOP_TYPE (right) != AOP_LIT)
+    {
+      operand *tmp = right;
+      right = left;
+      left = tmp;
+    }
+
+  /* if left is accumulator & right is not then exchange them */
+  if (AOP_TYPE (right) == AOP_REG && AOP_TYPE (left) != AOP_REG)
+    {
+      operand *tmp = right;
+      right = left;
+      left = tmp;
+    }
+
+  /* if right is bit then exchange them */
+  if (AOP_TYPE (right) == AOP_CRY &&
+      AOP_TYPE (left) != AOP_CRY)
+    {
+      operand *tmp = right;
+      right = left;
+      left = tmp;
+    }
+  if (AOP_TYPE (right) == AOP_LIT)
+    lit = (unsigned long) floatFromVal (AOP (right)->aopu.aop_lit);
+
+  size = AOP_SIZE (result);
+  offset = 0;
+  while (size--)
+    {
+      loadRegFromAop (hc08_reg_a, AOP (left), offset);
+      accopWithAop ("eor", AOP (right), offset);
+      storeRegToAop (hc08_reg_a, AOP (result), offset++);
+      hc08_freeReg( hc08_reg_a);      
+    }
+
+
+//release:
+  freeAsmop (left, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  freeAsmop (right, NULL, ic, (RESULTONSTACK (ic) ? FALSE : TRUE));
+  freeAsmop (result, NULL, ic, TRUE);
+}
+
+static void
+emitinline (iCode * ic, char *inlin)
+{
+  char buffer[512];
+  char *symname;
+  char c;
+  char *bp=buffer;
+  symbol *sym, *tempsym;
+  asmop *aop;
+  char *l;
+  
+  while (*inlin)
+    {
+      if (*inlin == '_')
+        {
+          symname = ++inlin;
+          while (isalnum(*inlin) || (*inlin == '_'))
+            inlin++;
+          c = *inlin;
+          *inlin = '\0';
+          //printf("Found possible symbol '%s'\n",symname);
+          tempsym = newSymbol (symname, ic->level);
+          tempsym->block = ic->block;
+          sym = (symbol *) findSymWithLevel(SymbolTab,tempsym);
+          *inlin = c;
+          if (!sym)
+            {
+              *bp++ = '_';
+              inlin = symname;
+            }
+          else
+            {
+              aop = aopForSym (ic, sym, FALSE);
+              l = aopAdrStr (aop, aop->size - 1, TRUE);
+              if (*l=='#')
+                l++;
+              sym->isref = 1;
+              if (!sym->allocreq && !sym->ismyparm)
+                {
+                  werror (E_ID_UNDEF, sym->name);
+                  werror (W_CONTINUE,
+                          "  Add 'volatile' to the variable declaration so that it\n"
+                          "  can be referenced within inline assembly");
+                }
+              //printf("Replacing with '%s'\n",l);
+              while (*l)
+                {
+                  *bp++ = *l++;
+                  if ((2+bp-buffer)>sizeof(buffer))
+                    goto endofline;
+                }
+            }
+        }
+      else
+        {
+          *bp++ = *inlin++;
+        }
+      if ((2+bp-buffer)>sizeof(buffer))
+        goto endofline;
+    }
+
+endofline:
+  *bp = '\0';
+
+  if ((2+bp-buffer)>sizeof(buffer))
+    fprintf(stderr, "Inline assembly buffer overflow\n");
+  
+  //printf("%s\n",buffer);
+  emitcode (buffer,"");
+}
+
+
+/*-----------------------------------------------------------------*/
+/* genInline - write the inline code out                           */
+/*-----------------------------------------------------------------*/
+static void
+genInline (iCode * ic)
+{
+  char *buffer, *bp, *bp1;
+
+  D(emitcode (";     genInline",""));
+
+  _G.inLine += (!options.asmpeep);
+
+  buffer = bp = bp1 = Safe_calloc(1, strlen(IC_INLINE(ic))+1);
+  strcpy (buffer, IC_INLINE (ic));
+
+  /* emit each line as a code */
+  while (*bp)
+    {
+      if (*bp == '\n')
+       {
+         *bp++ = '\0';
+         /* emitcode (bp1, ""); */
+         emitinline (ic, bp1);
+         bp1 = bp;
+       }
+      else
+       {
+         if (*bp == ':')
+           {
+             bp++;
+             *bp = '\0';
+             bp++;
+             emitcode (bp1, "");
+             bp1 = bp;
+           }
+         else
+           bp++;
+       }
+    }
+  if (bp1 != bp)
+    {
+      /* emitcode (bp1, ""); */
+      emitinline (ic, bp1);
+    }
+  /*     emitcode("",buffer); */
+  _G.inLine -= (!options.asmpeep);
+}
+
+/*-----------------------------------------------------------------*/
+/* genRRC - rotate right with carry                                */
+/*-----------------------------------------------------------------*/
+static void
+genRRC (iCode * ic)
+{
+  operand *left, *result;
+  int size, offset = 0;
+  bool needpula = FALSE;
+  bool resultInA = FALSE;
+  char *shift;
+
+  D(emitcode (";     genRRC",""));
+
+  /* rotate right with carry */
+  left = IC_LEFT (ic);
+  result = IC_RESULT (ic);
+  aopOp (left, ic, FALSE);
+  aopOp (result, ic, FALSE);
+
+  if ((AOP_TYPE (result) == AOP_REG)
+      && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
+   resultInA = TRUE;
+
+  size = AOP_SIZE (result);
+  offset = size-1;
+
+  shift="lsr";
+  if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
+    {
+      while (size--)
+        {
+          rmwWithAop (shift, AOP (result), offset--);
+          shift="ror";
+        }
+    }
+  else
+    {
+      while (size--)
+        {
+          loadRegFromAop (hc08_reg_a, AOP (left), offset);
+          rmwWithReg (shift, hc08_reg_a);
+          storeRegToAop (hc08_reg_a, AOP (result), offset--);
+          hc08_freeReg (hc08_reg_a);
+          shift="ror";
+        }
+    }
+
+  if ((!hc08_reg_a->isFree) || resultInA)
+    {
+      pushReg (hc08_reg_a, TRUE);
+      needpula = TRUE;
+    }
+
+  /* now we need to put the carry into the
+     highest order byte of the result */
+  offset = AOP_SIZE (result) - 1;
+  emitcode ("clra","");
+  emitcode ("rora","");
+  hc08_dirtyReg (hc08_reg_a, FALSE);
+  if (resultInA)
+    {
+      emitcode ("ora", "1,s");
+      emitcode ("ais", "#1");
+      hc08_dirtyReg (hc08_reg_a, FALSE);
+      needpula = FALSE;
+    }
+  else
+    accopWithAop ("ora", AOP (result), offset);
+  storeRegToAop (hc08_reg_a, AOP (result), offset);
+
+  pullOrFreeReg (hc08_reg_a, needpula);
+
+  freeAsmop (left, NULL, ic, TRUE);
+  freeAsmop (result, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genRLC - generate code for rotate left with carry               */
+/*-----------------------------------------------------------------*/
+static void
+genRLC (iCode * ic)
+{
+  operand *left, *result;
+  int size, offset = 0;
+  char *shift;
+  bool resultInA = FALSE;
+  bool needpula = FALSE;
+
+  D(emitcode (";     genRLC",""));
+
+  /* rotate right with carry */
+  left = IC_LEFT (ic);
+  result = IC_RESULT (ic);
+  aopOp (left, ic, FALSE);
+  aopOp (result, ic, FALSE);
+
+  if ((AOP_TYPE (result) == AOP_REG)
+      && (AOP (result)->aopu.aop_reg[0]->rIdx == A_IDX))
+   resultInA = TRUE;
+
+  size = AOP_SIZE (result);
+  offset = 0;
+
+  shift="lsl";
+  if (sameRegs (AOP (IC_LEFT (ic)), AOP (IC_RESULT (ic))))
+    {
+      while (size--)
+        {
+          rmwWithAop (shift, AOP (result), offset--);
+          shift="rol";
+        }
+    }
+  else
+    {
+      while (size--)
+        {
+          loadRegFromAop (hc08_reg_a, AOP (left), offset);
+          rmwWithReg (shift, hc08_reg_a);
+          storeRegToAop (hc08_reg_a, AOP (result), offset++);
+          hc08_freeReg (hc08_reg_a);
+          shift="rol";
+        }
+    }
+
+  if ((!hc08_reg_a->isFree) || resultInA)
+    {
+      pushReg (hc08_reg_a, TRUE);
+      needpula = TRUE;
+    }
+
+  /* now we need to put the carry into the
+     lowest order byte of the result */
+  offset = 0;
+  emitcode ("clra","");
+  emitcode ("rola","");
+  hc08_dirtyReg (hc08_reg_a, FALSE);
+  if (resultInA)
+    {
+      emitcode ("ora", "1,s");
+      emitcode ("ais", "#1");
+      hc08_dirtyReg (hc08_reg_a, FALSE);
+      needpula = FALSE;
+    }
+  else
+    accopWithAop ("ora", AOP (result), offset);
+  storeRegToAop (hc08_reg_a, AOP (result), offset);
+
+  pullOrFreeReg (hc08_reg_a, needpula);
+
+  freeAsmop (left, NULL, ic, TRUE);
+  freeAsmop (result, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genGetHbit - generates code get highest order bit               */
+/*-----------------------------------------------------------------*/
+static void
+genGetHbit (iCode * ic)
+{
+  operand *left, *result;
+
+  D(emitcode (";     genGetHbit",""));
+
+  left = IC_LEFT (ic);
+  result = IC_RESULT (ic);
+  aopOp (left, ic, FALSE);
+  aopOp (result, ic, FALSE);
+
+  /* get the highest order byte into a */
+  loadRegFromAop (hc08_reg_a, AOP (left), AOP_SIZE (left) - 1);
+  emitcode ("rola", "");
+  emitcode ("clra", "");
+  emitcode ("rola", "");
+  hc08_dirtyReg (hc08_reg_a, FALSE);
+  storeRegToFullAop (hc08_reg_a, AOP (result), FALSE);
+  
+  freeAsmop (left, NULL, ic, TRUE);
+  freeAsmop (result, NULL, ic, TRUE);
+}
+
+#if 0
+/*-----------------------------------------------------------------*/
+/* AccRol - rotate left accumulator by known count                 */
+/*-----------------------------------------------------------------*/
+static void
+AccRol (int shCount)
+{
+  shCount &= 0x0007;           // shCount : 0..7
+
+  switch (shCount)
+    {
+    case 0:
+      break;
+    case 1:
+      emitcode ("rola", "");   /* 1 cycle */
+      break;
+    case 2:
+      emitcode ("rola", "");   /* 1 cycle */
+      emitcode ("rola", "");   /* 1 cycle */
+      break;
+    case 3:
+      emitcode ("nsa", "");
+      emitcode ("rora", "");
+      break;
+    case 4:
+      emitcode ("nsa", "");    /* 3 cycles */
+      break;
+    case 5:
+      emitcode ("nsa", "");    /* 3 cycles */
+      emitcode ("rola", "");   /* 1 cycle */
+      break;
+    case 6:
+      emitcode ("nsa", "");    /* 3 cycles */
+      emitcode ("rola", "");   /* 1 cycle */
+      emitcode ("rola", "");   /* 1 cycle */
+      break;
+    case 7:
+      emitcode ("nsa", "");    /* 3 cycles */
+      emitcode ("rola", "");   /* 1 cycle */
+      emitcode ("rola", "");   /* 1 cycle */
+      emitcode ("rola", "");   /* 1 cycle */
+      break;
+    }
+}
+#endif
+
+
+/*-----------------------------------------------------------------*/
+/* AccLsh - left shift accumulator by known count                  */
+/*-----------------------------------------------------------------*/
+static void
+AccLsh (int shCount)
+{
+  int i;
+  
+  shCount &= 0x0007;           // shCount : 0..7
+
+  /* Shift counts of 4 and 5 are currently optimized for code size.        */
+  /* Falling through to the unrolled loop would be optimal for code speed. */
+  /* For shift counts of 6 and 7, the unrolled loop is never optimal.      */
+  switch (shCount)
+    {
+    case 4:
+      accopWithMisc ("nsa", "");
+      accopWithMisc ("and", "#0xf0");
+      /* total: 5 cycles, 3 bytes */
+      return;
+    case 5:
+      accopWithMisc ("nsa", "");
+      accopWithMisc ("and", "#0xf0");
+      accopWithMisc ("lsla", "");
+      /* total: 6 cycles, 4 bytes */
+      return;
+    case 6:
+      accopWithMisc ("rora", "");
+      accopWithMisc ("rora", "");
+      accopWithMisc ("rora", "");
+      accopWithMisc ("and", "#0xc0");
+      /* total: 5 cycles, 5 bytes */
+      return;
+    case 7:
+      accopWithMisc ("rora", "");
+      accopWithMisc ("clra", "");
+      accopWithMisc ("rora", "");
+      /* total: 3 cycles, 3 bytes */
+      return;
+    }
+
+    /* lsla is only 1 cycle and byte, so an unrolled loop is often  */
+    /* the fastest (shCount<6) and shortest (shCount<4).            */
+    for (i=0;i<shCount;i++)
+      accopWithMisc ("lsla", "");
+}
+
+
+/*-----------------------------------------------------------------*/
+/* AccSRsh - signed right shift accumulator by known count         */
+/*-----------------------------------------------------------------*/
+static void
+AccSRsh (int shCount)
+{
+  int i;
+  
+  shCount &= 0x0007;           // shCount : 0..7
+
+  if (shCount == 7)
+    {
+      accopWithMisc ("rola", "");
+      accopWithMisc ("clra", "");
+      accopWithMisc ("sbc", zero);
+      /* total: 4 cycles, 4 bytes */
+      return;
+    }
+
+    for (i=0;i<shCount;i++)
+      accopWithMisc ("asra", "");
+}
+
+/*-----------------------------------------------------------------*/
+/* AccRsh - right shift accumulator by known count                 */
+/*-----------------------------------------------------------------*/
+static void
+AccRsh (int shCount, bool sign)
+{
+  int i;
+  
+  if (sign)
+    {
+      AccSRsh (shCount);
+      return;
+    }
+  
+  shCount &= 0x0007;           // shCount : 0..7
+
+  /* Shift counts of 4 and 5 are currently optimized for code size.        */
+  /* Falling through to the unrolled loop would be optimal for code speed. */
+  /* For shift counts of 6 and 7, the unrolled loop is never optimal.      */
+  switch (shCount)
+    {
+    case 4:
+      accopWithMisc ("nsa", "");
+      accopWithMisc ("and", "#0x0f");
+      /* total: 5 cycles, 3 bytes */
+      return;
+    case 5:
+      accopWithMisc ("nsa", "");
+      accopWithMisc ("and", "#0x0f");
+      accopWithMisc ("lsra", "");
+      /* total: 6 cycles, 4 bytes */
+      return;
+    case 6:
+      accopWithMisc ("rola", "");
+      accopWithMisc ("rola", "");
+      accopWithMisc ("rola", "");
+      accopWithMisc ("and", "#0x03");
+      /* total: 5 cycles, 5 bytes */
+      return;
+    case 7:
+      accopWithMisc ("rola", "");
+      accopWithMisc ("clra", "");
+      accopWithMisc ("rola", "");
+      /* total: 3 cycles, 3 bytes */
+      return;
+    }
+
+    /* lsra is only 1 cycle and byte, so an unrolled loop is often  */
+    /* the fastest (shCount<6) and shortest (shCount<4).            */
+    for (i=0;i<shCount;i++)
+      accopWithMisc ("lsra", "");
+}
+
+
+/*-----------------------------------------------------------------*/
+/* XAccLsh - left shift register pair XA by known count            */
+/*-----------------------------------------------------------------*/
+static void
+XAccLsh (int shCount)
+{
+  int i;
+  
+  shCount &= 0x000f;           // shCount : 0..15
+
+  if (shCount>=8)
+    {
+      AccLsh (shCount-8);
+      transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
+      loadRegFromConst (hc08_reg_a, zero);
+      return;
+    }
+
+  /* if we can beat 2n cycles or bytes for some special case, do it here */
+  switch (shCount)
+    {
+    case 7:
+      /*          bytes  cycles     reg x      reg a   carry
+      **                          abcd efgh  ijkl mnop   ?
+      **   lsrx       1  1        0abc defg  ijkl mnop   h
+      **   rora       1  1        0abc defg  hijk lmno   p
+      **   tax        1  1        hijk lmno  hijk lmno   p
+      **   clra       1  1        hijk lmno  0000 0000   p
+      **   rora       1  1        hijk lmno  p000 0000   0
+      ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
+      */
+      rmwWithReg ("lsr", hc08_reg_x);
+      rmwWithReg ("ror", hc08_reg_a);
+      transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
+      loadRegFromConst (hc08_reg_a, zero);
+      rmwWithReg ("ror", hc08_reg_a);
+      return;
+
+    default:
+      ;
+    }
+
+  /* lsla/rolx is only 2 cycles and bytes, so an unrolled loop is often  */
+  /* the fastest and shortest.                                           */
+  for (i=0;i<shCount;i++)
+    {
+      rmwWithReg ("lsl", hc08_reg_a);
+      rmwWithReg ("rol", hc08_reg_x);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* XAccSRsh - signed right shift register pair XA by known count   */
+/*-----------------------------------------------------------------*/
+static void
+XAccSRsh (int shCount)
+{
+  int i;
+  
+  shCount &= 0x000f;           // shCount : 0..7
+
+  /* if we can beat 2n cycles or bytes for some special case, do it here */
+  switch (shCount)
+    {
+    case 15:
+      /*          bytes  cycles     reg x      reg a   carry
+      **                          abcd efgh  ijkl mnop   ?
+      **   lslx       1  1        bcde fgh0  ijkl mnop   a
+      **   clra       1  1        bcde fgh0  0000 0000   a
+      **   rola       1  1        bcde fgh0  0000 000a   0
+      **   nega       1  1        bcde fgh0  aaaa aaaa   a
+      **   tax        1  1        aaaa aaaa  aaaa aaaa   a
+      ** total: 5 cycles, 5 bytes
+      */
+      rmwWithReg ("lsl", hc08_reg_x);
+      loadRegFromConst (hc08_reg_a, zero);
+      rmwWithReg ("rol", hc08_reg_a);
+      rmwWithReg ("neg", hc08_reg_a);
+      transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
+      return;
+
+    case 14:
+    case 13:
+    case 12:
+    case 11:
+    case 10:
+    case 9:
+    case 8:
+      /*          bytes  cycles     reg x      reg a   carry
+      **                          abcd efgh  ijkl mnop   ?
+      **   txa        1  1        abcd efgh  abcd efgh   ?
+      **   (AccSRsh) <8 <8        abcd efgh  LSBresult   ?
+      **   lsla       1  1        abcd efgh  ???? ????   a
+      **   clrx       1  1        0000 0000  ???? ????   a
+      **   rolx       1  1        0000 000a  ???? ????   0
+      **   negx       1  1        aaaa aaaa  ???? ????   a
+      **   rora       1  1        aaaa aaaa  LSBresult   0
+      ** total: n-2 cycles, n-2 bytes (beats 2n cycles, 2n bytes (for n>=8))
+      */
+      transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
+      AccSRsh (shCount-8);
+      rmwWithReg ("lsl", hc08_reg_a);
+      loadRegFromConst (hc08_reg_x, zero);
+      rmwWithReg ("rol", hc08_reg_x);
+      rmwWithReg ("neg", hc08_reg_x);
+      rmwWithReg ("ror", hc08_reg_a);
+      return;
+
+    default:
+      ;
+    }
+
+  /* asrx/rola is only 2 cycles and bytes, so an unrolled loop is often  */
+  /* the fastest and shortest.                                           */
+  for (i=0;i<shCount;i++)
+    {
+      rmwWithReg ("asr", hc08_reg_x);
+      rmwWithReg ("ror", hc08_reg_a);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* XAccRsh - right shift register pair XA by known count           */
+/*-----------------------------------------------------------------*/
+static void
+XAccRsh (int shCount, bool sign)
+{
+  int i;
+  
+  if (sign)
+    {
+      XAccSRsh (shCount);
+      return;
+    }
+  
+  shCount &= 0x000f;           // shCount : 0..7
+
+  /* if we can beat 2n cycles or bytes for some special case, do it here */
+  switch (shCount)
+    {
+    case 15:
+      /*          bytes  cycles     reg x      reg a   carry
+      **                          abcd efgh  ijkl mnop   ?
+      **   clra       1  1        abcd efgh  0000 0000   a
+      **   lslx       1  1        bcde fgh0  0000 0000   a
+      **   rola       1  1        bcde fgh0  0000 000a   0
+      **   clrx       1  1        0000 0000  0000 000a   0
+      ** total: 4 cycles, 4 bytes
+      */
+      loadRegFromConst (hc08_reg_x, zero);
+      rmwWithReg ("lsl", hc08_reg_x);
+      rmwWithReg ("rol", hc08_reg_a);
+      loadRegFromConst (hc08_reg_a, zero);
+      return;
+
+    case 14:
+      /*          bytes  cycles     reg x      reg a   carry
+      **                          abcd efgh  ijkl mnop   ?
+      **   clra       1  1        abcd efgh  0000 0000   a
+      **   lslx       1  1        bcde fgh0  0000 0000   a
+      **   rola       1  1        bcde fgh0  0000 000a   0
+      **   lslx       1  1        cdef gh00  0000 000a   b
+      **   rola       1  1        cdef gh00  0000 00ab   0
+      **   clrx       1  1        0000 0000  0000 000a   0
+      ** total: 6 cycles, 6 bytes
+      */
+      loadRegFromConst (hc08_reg_x, zero);
+      rmwWithReg ("lsl", hc08_reg_x);
+      rmwWithReg ("rol", hc08_reg_a);
+      rmwWithReg ("lsl", hc08_reg_x);
+      rmwWithReg ("rol", hc08_reg_a);
+      loadRegFromConst (hc08_reg_a, zero);
+      return;
+
+    case 13:
+    case 12:
+    case 11:
+    case 10:
+    case 9:
+    case 8:
+      transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
+      AccRsh (shCount-8, FALSE);
+      loadRegFromConst (hc08_reg_x, zero);
+      return;
+
+    case 7:
+      /*          bytes  cycles     reg x      reg a   carry
+      **                          abcd efgh  ijkl mnop   ?
+      **   lsla       1  1        abcd efgh  jklm nop0   i
+      **   txa        1  1        abcd efgh  abcd efgh   i
+      **   rola       1  1        abcd efgh  bcde fghi   a
+      **   clrx       1  1        0000 0000  bcde fghi   a
+      **   rolx       1  1        0000 000a  bcde fghi   0
+      ** total: 5 cycles, 5 bytes (beats 14 cycles, 14 bytes)
+      */
+      rmwWithReg ("lsl", hc08_reg_a);
+      transferRegReg (hc08_reg_x, hc08_reg_a, FALSE);
+      rmwWithReg ("rol", hc08_reg_a);
+      loadRegFromConst (hc08_reg_x, zero);
+      rmwWithReg ("rol", hc08_reg_x);
+      return;
+    case 6:
+      /*          bytes  cycles     reg x      reg a   carry
+      **                          abcd efgh  ijkl mnop   ?
+      **   lsla       1  1        abcd efgh  jklm nop0   i
+      **   rolx       1  1        bcde fghi  jklm nop0   a
+      **   rola       1  1        bcde fghi  klmn op0a   j
+      **   rolx       1  1        cdef ghij  klmn op0a   b
+      **   rola       1  1        cdef ghij  lmno p0ab   k
+      **   and #3     2  2        cdef ghij  0000 00ab   k
+      **   psha       1  2        cdef ghij  0000 00ab   k
+      **   txa        1  1        cdef ghij  cdef ghij   k
+      **   pula       1  2        0000 00ab  cdef ghij   k
+      ** total: 12 cycles, 10 bytes (beats 12 bytes)
+      */
+    default:
+      ;
+    }
+
+  /* lslx/rola is only 2 cycles and bytes, so an unrolled loop is often  */
+  /* the fastest and shortest.                                           */
+  for (i=0;i<shCount;i++)
+    {
+      rmwWithReg ("lsl", hc08_reg_x);
+      rmwWithReg ("rol", hc08_reg_a);
+    }
+
+}
+
+
+#if 0
+/*-----------------------------------------------------------------*/
+/* shiftR1Left2Result - shift right one byte from left to result   */
+/*-----------------------------------------------------------------*/
+static void
+shiftR1Left2Result (operand * left, int offl,
+                   operand * result, int offr,
+                   int shCount, int sign)
+{
+  loadRegFromAop (hc08_reg_a, AOP (left), offl);
+  /* shift right accumulator */
+  AccRsh (shCount, sign);
+  storeRegToAop (hc08_reg_a, AOP (result), offr);
+}
+#endif
+
+/*-----------------------------------------------------------------*/
+/* shiftL1Left2Result - shift left one byte from left to result    */
+/*-----------------------------------------------------------------*/
+static void
+shiftL1Left2Result (operand * left, int offl,
+                   operand * result, int offr, int shCount)
+{
+  loadRegFromAop (hc08_reg_a, AOP (left), offl);
+  /* shift left accumulator */
+  AccLsh (shCount);
+  storeRegToAop (hc08_reg_a, AOP (result), offr);
+}
+
+/*-----------------------------------------------------------------*/
+/* movLeft2Result - move byte from left to result                  */
+/*-----------------------------------------------------------------*/
+static void
+movLeft2Result (operand * left, int offl,
+               operand * result, int offr, int sign)
+{
+  if (!sameRegs (AOP (left), AOP (result)) || (offl != offr))
+    {
+      transferAopAop (AOP (left), offl, AOP (result), offr);
+    }
+}
+
+
+/*-----------------------------------------------------------------*/
+/* AccAXRsh1 - right shift 0->a:x->c by 1                         */
+/*-----------------------------------------------------------------*/
+static void
+AccAXRsh1 (char *x)
+{
+  emitcode ("lsra", "");
+  emitcode ("ror", "%s", x);
+}
+
+
+/*-----------------------------------------------------------------*/
+/* AccAXRshS1 - signed right shift s->a:x->c by 1                         */
+/*-----------------------------------------------------------------*/
+static void
+AccAXRshS1 (char *x)
+{
+  emitcode ("asra", "");
+  emitcode ("ror", "%s", x);
+}
+
+/*-----------------------------------------------------------------*/
+/* AccAXLrl1 - left rotate c<-a:x<-c by 1                          */
+/*-----------------------------------------------------------------*/
+static void
+AccAXLrl1 (char *x)
+{
+  emitcode ("rol", "%s", x);
+  emitcode ("rola", "");
+}
+
+/*-----------------------------------------------------------------*/
+/* AccAXLsh1 - left shift a:x<-0 by 1                              */
+/*-----------------------------------------------------------------*/
+static void
+AccAXLsh1 (char *x)
+{
+  emitcode ("lsl", "%s", x);
+  emitcode ("rola", "");
+}
+
+/*-----------------------------------------------------------------*/
+/* AccAXLsh - left shift a:x by known count (0..7)                 */
+/*-----------------------------------------------------------------*/
+static void
+AccAXLsh (char *x, int shCount)
+{
+  int i;
+
+  for (i=0;i<shCount;i++) {
+    AccAXLsh1 (x);
+  }
+}
+
+/*-----------------------------------------------------------------*/
+/* AccAXRsh - right shift a:x known count (0..7)                   */
+/*-----------------------------------------------------------------*/
+static void
+AccAXRsh (char *x, int shCount)
+{
+  int i;
+
+  for (i=0;i<shCount;i++) {
+    AccAXRsh1 (x);
+  }
+  
+}
+
+/*-----------------------------------------------------------------*/
+/* AccAXRshS - right shift signed a:x known count (0..7)           */
+/*-----------------------------------------------------------------*/
+static void
+AccAXRshS (char *x, int shCount)
+{
+  int i;
+
+  for (i=0;i<shCount;i++) {
+    AccAXRshS1 (x);
+  }
+}
+
+/*-----------------------------------------------------------------*/
+/* shiftL2Left2Result - shift left two bytes from left to result   */
+/*-----------------------------------------------------------------*/
+static void
+shiftL2Left2Result (operand * left, int offl,
+                   operand * result, int offr, int shCount)
+{
+  int i;
+  bool needpula = FALSE;
+  bool needpulx = FALSE;
+
+  needpula = pushRegIfUsed (hc08_reg_a);
+  needpulx = pushRegIfUsed (hc08_reg_x);
+
+  loadRegFromAop (hc08_reg_xa, AOP (left), offl);
+
+  switch (shCount)
+    {
+      case 7:
+        rmwWithReg ("lsr", hc08_reg_x);
+        rmwWithReg ("ror", hc08_reg_a);
+        transferRegReg (hc08_reg_a, hc08_reg_x, FALSE);
+        rmwWithReg ("clr", hc08_reg_a);
+        rmwWithReg ("ror", hc08_reg_a);
+        break;
+      default:
+        for (i=0; i<shCount; i++)
+          {
+            rmwWithReg ("lsl", hc08_reg_a);
+            rmwWithReg ("rol", hc08_reg_x);
+          }
+    }
+  storeRegToAop (hc08_reg_xa, AOP (result), offl);
+
+  pullOrFreeReg (hc08_reg_x, needpulx);
+  pullOrFreeReg (hc08_reg_a, needpula);
+
+}
+
+
+#if 0
+/*-----------------------------------------------------------------*/
+/* shiftR2Left2Result - shift right two bytes from left to result  */
+/*-----------------------------------------------------------------*/
+static void
+shiftR2Left2Result (operand * left, int offl,
+                   operand * result, int offr,
+                   int shCount, int sign)
+{
+  int i;
+  bool needpula = FALSE;
+  bool needpulx = FALSE;
+  
+  needpula = pushRegIfUsed (hc08_reg_a);
+  needpulx = pushRegIfUsed (hc08_reg_x);
+
+  loadRegFromAop (hc08_reg_xa, AOP (left), offl);
+  for (i=0; i<shCount; i++)
+    {
+      if (sign)
+        rmwWithReg ("asr", hc08_reg_x);
+      else
+        rmwWithReg ("lsr", hc08_reg_x);
+      rmwWithReg ("ror", hc08_reg_a);
+    }
+  storeRegToAop (hc08_reg_xa, AOP (result), offl);
+
+  pullOrFreeReg (hc08_reg_x, needpulx);
+  pullOrFreeReg (hc08_reg_a, needpula);
+}
+#endif
+
+#if 0
+/*-----------------------------------------------------------------*/
+/* shiftLLeftOrResult - shift left one byte from left, or to result */
+/*-----------------------------------------------------------------*/
+static void
+shiftLLeftOrResult (operand * left, int offl,
+                   operand * result, int offr, int shCount)
+{
+  loadRegFromAop (hc08_reg_a, AOP (left), offl);
+  /* shift left accumulator */
+  AccLsh (shCount);
+  /* or with result */
+  accopWithAop ("ora", AOP (result), offr);
+  /* back to result */
+  storeRegToAop (hc08_reg_a, AOP (result), offr);
+  hc08_freeReg (hc08_reg_a);
+}
+#endif
+
+/*-----------------------------------------------------------------*/
+/* shiftRLeftOrResult - shift right one byte from left,or to result */
+/*-----------------------------------------------------------------*/
+static void
+shiftRLeftOrResult (operand * left, int offl,
+                   operand * result, int offr, int shCount)
+{
+  loadRegFromAop (hc08_reg_a, AOP (left), offl);
+  /* shift left accumulator */
+  AccRsh (shCount, FALSE);
+  /* or with result */
+  accopWithAop ("ora", AOP (result), offr);
+  /* back to result */
+  storeRegToAop (hc08_reg_a, AOP (result), offr);
+  hc08_freeReg (hc08_reg_a);
+}
+
+/*-----------------------------------------------------------------*/
+/* genlshOne - left shift a one byte quantity by known count       */
+/*-----------------------------------------------------------------*/
+static void
+genlshOne (operand * result, operand * left, int shCount)
+{
+  D(emitcode (";     genlshOne",""));
+
+  shiftL1Left2Result (left, LSB, result, LSB, shCount);
+}
+
+/*-----------------------------------------------------------------*/
+/* genlshTwo - left shift two bytes by known amount != 0           */
+/*-----------------------------------------------------------------*/
+static void
+genlshTwo (operand * result, operand * left, int shCount)
+{
+  int size;
+
+  D(emitcode (";     genlshTwo",""));
+
+  size = getDataSize (result);
+
+  /* if shCount >= 8 */
+  if (shCount >= 8)
+    {
+      shCount -= 8;
+
+      if (size > 1)
+       {
+         if (shCount)
+           shiftL1Left2Result (left, LSB, result, MSB16, shCount);
+         else
+           movLeft2Result (left, LSB, result, MSB16, 0);
+       }
+      storeConstToAop(zero, AOP (result), LSB);
+    }
+
+  /*  1 <= shCount <= 7 */
+  else
+    {
+      if (size == 1)
+       shiftL1Left2Result (left, LSB, result, LSB, shCount);
+      else
+       shiftL2Left2Result (left, LSB, result, LSB, shCount);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* shiftLLong - shift left one long from left to result            */
+/* offl = LSB or MSB16                                             */
+/*-----------------------------------------------------------------*/
+static void
+shiftLLong (operand * left, operand * result, int offr)
+{
+//  char *l;
+//  int size = AOP_SIZE (result);
+
+  bool needpula = FALSE;
+  bool needpulx = FALSE;
+
+  needpula = pushRegIfUsed (hc08_reg_a);
+  needpulx = pushRegIfUsed (hc08_reg_x);
+
+  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)
+    {
+      loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
+      rmwWithReg ("rol", hc08_reg_a);
+      rmwWithReg ("rol", hc08_reg_x);
+      storeRegToAop (hc08_reg_xa, AOP (result), offr+2);
+    }
+  else if (offr==MSB16)
+    {
+      loadRegFromAop (hc08_reg_a, AOP (left), MSB24);
+      rmwWithReg ("rol", hc08_reg_a);
+      storeRegToAop (hc08_reg_a, AOP (result), offr+2);
+    }
+
+  pullOrFreeReg (hc08_reg_x, needpulx);
+  pullOrFreeReg (hc08_reg_a, needpula);
+}
+
+/*-----------------------------------------------------------------*/
+/* genlshFour - shift four byte by a known amount != 0             */
+/*-----------------------------------------------------------------*/
+static void
+genlshFour (operand * result, operand * left, int shCount)
+{
+  int size;
+
+  D(emitcode (";     genlshFour",""));
+
+  size = AOP_SIZE (result);
+
+  /* TODO: deal with the &result == &left case */
+
+  /* if shifting more that 3 bytes */
+  if (shCount >= 24)
+    {
+      shCount -= 24;
+      if (shCount)
+       /* lowest order of left goes to the highest
+          order of the destination */
+       shiftL1Left2Result (left, LSB, result, MSB32, shCount);
+      else
+       movLeft2Result (left, LSB, result, MSB32, 0);
+      storeConstToAop (zero, AOP (result), LSB);
+      storeConstToAop (zero, AOP (result), MSB16);
+      storeConstToAop (zero, AOP (result), MSB24);
+      return;
+    }
+
+  /* more than two bytes */
+  else if (shCount >= 16)
+    {
+      /* lower order two bytes goes to higher order two bytes */
+      shCount -= 16;
+      /* if some more remaining */
+      if (shCount)
+       shiftL2Left2Result (left, LSB, result, MSB24, shCount);
+      else
+       {
+         movLeft2Result (left, MSB16, result, MSB32, 0);
+         movLeft2Result (left, LSB, result, MSB24, 0);
+       }
+      storeConstToAop (zero, AOP (result), LSB);
+      storeConstToAop (zero, AOP (result), MSB16);
+      return;
+    }
+
+  /* if more than 1 byte */
+  else if (shCount >= 8)
+    {
+      /* lower order three bytes goes to higher order  three bytes */
+      shCount -= 8;
+      if (size == 2)
+       {
+         if (shCount)
+           shiftL1Left2Result (left, LSB, result, MSB16, shCount);
+         else
+           movLeft2Result (left, LSB, result, MSB16, 0);
+       }
+      else
+       {                       /* size = 4 */
+         if (shCount == 0)
+           {
+             movLeft2Result (left, MSB24, result, MSB32, 0);
+             movLeft2Result (left, MSB16, result, MSB24, 0);
+             movLeft2Result (left, LSB, result, MSB16, 0);
+              storeConstToAop (zero, AOP (result), LSB);
+           }
+         else if (shCount == 1)
+           shiftLLong (left, result, MSB16);
+         else
+           {
+             shiftL2Left2Result (left, MSB16, result, MSB24, shCount);
+             shiftL1Left2Result (left, LSB, result, MSB16, shCount);
+             shiftRLeftOrResult (left, LSB, result, MSB24, 8 - shCount);
+              storeConstToAop (zero, AOP (result), LSB);
+           }
+       }
+    }
+
+  /* 1 <= shCount <= 7 */
+  else if (shCount <= 2)
+    {
+      shiftLLong (left, result, LSB);
+      if (shCount == 2)
+       shiftLLong (result, result, LSB);
+    }
+  /* 3 <= shCount <= 7, optimize */
+  else
+    {
+      shiftL2Left2Result (left, MSB24, result, MSB24, shCount);
+      shiftRLeftOrResult (left, MSB16, result, MSB24, 8 - shCount);
+      shiftL2Left2Result (left, LSB, result, LSB, shCount);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genLeftShiftLiteral - left shifting by known count              */
+/*-----------------------------------------------------------------*/
+static void
+genLeftShiftLiteral (operand * left,
+                    operand * right,
+                    operand * result,
+                    iCode * ic)
+{
+  int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
+  int size;
+
+  D(emitcode (";     genLeftShiftLiteral",""));
+
+  freeAsmop (right, NULL, ic, TRUE);
+
+  aopOp (left, ic, FALSE);
+  aopOp (result, ic, FALSE);
+
+//  size = getSize (operandType (result));
+  size = AOP_SIZE (result);
+
+#if VIEW_SIZE
+  emitcode ("; shift left ", "result %d, left %d", size,
+           AOP_SIZE (left));
+#endif
+
+  if (shCount == 0)
+    {
+      while (size--)
+        transferAopAop( AOP(left), size, AOP(result), size);
+    }
+  else if (shCount >= (size * 8))
+    {
+      while (size--)
+        storeConstToAop (zero, AOP (result), size);
+    }
+  else
+    {
+      switch (size)
+       {
+       case 1:
+         genlshOne (result, left, shCount);
+         break;
+
+       case 2:
+         genlshTwo (result, left, shCount);
+         break;
+
+       case 4:
+         genlshFour (result, left, shCount);
+         break;
+       default:
+         werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
+                 "*** ack! mystery literal shift!\n");
+         break;
+       }
+    }
+  freeAsmop (left, NULL, ic, TRUE);
+  freeAsmop (result, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genLeftShift - generates code for left shifting                 */
+/*-----------------------------------------------------------------*/
+static void
+genLeftShift (iCode * ic)
+{
+  operand *left, *right, *result;
+  int size, offset;
+  symbol *tlbl, *tlbl1;
+//  int i;
+  char *shift;
+  regs *reg;
+
+  D(emitcode (";     genLeftShift",""));
+
+  right = IC_RIGHT (ic);
+  left = IC_LEFT (ic);
+  result = IC_RESULT (ic);
+
+  aopOp (right, ic, FALSE);
+
+  /* if the shift count is known then do it
+     as efficiently as possible */
+  if (AOP_TYPE (right) == AOP_LIT)
+    {
+      genLeftShiftLiteral (left, right, result, ic);
+      return;
+    }
+
+  /* shift count is unknown then we have to form
+     a loop get the loop count in A : 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);
+
+  /* now move the left to the result if they are not the
+     same */
+  if (!sameRegs (AOP (left), AOP (result)))
+    {
+
+      size = AOP_SIZE (result);
+      offset = 0;
+      while (size--)
+       {
+         transferAopAop (AOP (left), offset, AOP (result), offset);
+         offset++;
+       }
+    }
+  freeAsmop (left, NULL, ic, TRUE);
+  
+  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);
+  emitBranch ("beq", tlbl1);
+  emitLabel (tlbl);
+  
+  shift="lsl";
+  for (offset=0;offset<size;offset++)
+    {
+      rmwWithAop (shift, AOP (result), offset);  
+      shift="rol";
+    }
+  rmwWithReg ("dec", reg);
+  emitBranch ("bne", tlbl);
+  emitLabel (tlbl1);
+  hc08_freeReg (reg);
+  
+  freeAsmop (result, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genrshOne - right shift a one byte quantity by known count      */
+/*-----------------------------------------------------------------*/
+static void
+genrshOne (operand * result, operand * left,
+          int shCount, int sign)
+{
+  D(emitcode (";     genrshOne",""));
+
+  loadRegFromAop (hc08_reg_a, AOP (left), 0);
+  AccRsh (shCount, sign);
+  storeRegToFullAop (hc08_reg_a, AOP (result), sign);
+}
+
+/*-----------------------------------------------------------------*/
+/* genrshTwo - right shift two bytes by known amount != 0          */
+/*-----------------------------------------------------------------*/
+static void
+genrshTwo (operand * result, operand * left,
+          int shCount, int sign)
+{
+  D(emitcode (";     genrshTwo",""));
+
+  /* if shCount >= 8 */
+  if (shCount >= 8)
+    {
+      if (shCount || sign)
+        {
+          loadRegFromAop (hc08_reg_a, AOP (left), 1);
+          AccRsh (shCount-8, sign);
+          storeRegToFullAop (hc08_reg_a, AOP (result), sign);
+        }
+      else
+        {
+          transferAopAop (AOP (left), 1, AOP (result), 0);
+          storeConstToAop (zero, AOP (result), 1);
+        }
+    }
+
+  /*  1 <= shCount <= 7 */
+  else
+    {
+      loadRegFromAop (hc08_reg_xa, AOP (left), 0);
+      XAccRsh (shCount, sign);
+      storeRegToAop (hc08_reg_xa, AOP (result), 0);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* shiftRLong - shift right one long from left to result           */
+/* offl = LSB or MSB16                                             */
+/*-----------------------------------------------------------------*/
+static void
+shiftRLong (operand * left, int offl,
+           operand * result, int sign)
+{
+//  char *l;
+ // int size = AOP_SIZE (result);
+
+  bool needpula = FALSE;
+  bool needpulx = FALSE;
+
+  needpula = pushRegIfUsed (hc08_reg_a);
+  needpulx = pushRegIfUsed (hc08_reg_x);
+
+  if (offl==LSB)
+    {
+      loadRegFromAop (hc08_reg_xa, AOP (left), MSB24);
+      if (sign)
+        rmwWithReg ("asr", hc08_reg_x);
+      else
+        rmwWithReg ("lsr", hc08_reg_x);
+      rmwWithReg ("rol", hc08_reg_a);
+      storeRegToAop (hc08_reg_xa, AOP (result), MSB24);
+    }
+  else if (offl==MSB16)
+    {
+      loadRegFromAop (hc08_reg_a, AOP (left), MSB32);
+      if (sign)
+        rmwWithReg ("asr", hc08_reg_a);
+      else
+        rmwWithReg ("lsr", hc08_reg_a);
+      storeRegToAop (hc08_reg_a, AOP (result), MSB24);
+    }
+
+  loadRegFromAop (hc08_reg_xa, AOP (left), offl);
+  rmwWithReg ("ror", hc08_reg_x);
+  rmwWithReg ("ror", hc08_reg_a);
+  storeRegToAop (hc08_reg_xa, AOP (result), LSB);
+
+
+  pullOrFreeReg (hc08_reg_x, needpulx);
+  pullOrFreeReg (hc08_reg_a, needpula);
+}
+
+/*-----------------------------------------------------------------*/
+/* genrshFour - shift four byte by a known amount != 0             */
+/*-----------------------------------------------------------------*/
+static void
+genrshFour (operand * result, operand * left,
+           int shCount, int sign)
+{
+  /* TODO: handle cases where left == result */
+  
+  D(emitcode (";     genrshFour",""));
+
+  /* if shifting more that 3 bytes */
+  if (shCount >= 24)
+    {
+      loadRegFromAop (hc08_reg_a, AOP (left), 3);
+      AccRsh (shCount-24, sign);
+      storeRegToFullAop (hc08_reg_a, AOP (result), sign);
+      return;
+    }
+  else if (shCount >= 16)
+    {
+      loadRegFromAop (hc08_reg_xa, AOP (left), 2);
+      XAccRsh (shCount-16, sign);
+      storeRegToFullAop (hc08_reg_xa, AOP (result), sign);
+      return;
+    }
+  else if (shCount >= 8)
+    {
+      if (shCount == 1)
+       shiftRLong (left, MSB16, result, sign);
+      else if (shCount == 8)
+       {
+         transferAopAop (AOP (left), 1, AOP (result), 0);
+         transferAopAop (AOP (left), 2, AOP (result), 1);
+         loadRegFromAop (hc08_reg_a, AOP (left), 3);
+          storeRegToAop (hc08_reg_a, AOP (result), 2);
+          storeRegSignToUpperAop (hc08_reg_a, AOP(result), 3, sign);
+       }
+      else if (shCount == 9)
+        {
+         shiftRLong (left, MSB16, result, sign);
+        }
+      else
+       {
+         loadRegFromAop (hc08_reg_xa, AOP (left), 1);
+         XAccRsh (shCount-8, FALSE);
+         storeRegToAop (hc08_reg_xa, AOP (result), 0);
+         loadRegFromAop (hc08_reg_x, AOP (left), 3);
+         loadRegFromConst (hc08_reg_a, zero);
+         XAccRsh (shCount-8, sign);
+         accopWithAop ("ora", AOP (result), 1);
+         storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
+       }
+    }
+  else
+    {                          /* 1 <= shCount <= 7 */
+      if (shCount == 1)
+       {
+         shiftRLong (left, LSB, result, sign);
+       }
+      else
+       {
+         loadRegFromAop (hc08_reg_xa, AOP (left), 0);
+         XAccRsh (shCount, FALSE);
+         storeRegToAop (hc08_reg_xa, AOP (result), 0);
+         loadRegFromAop (hc08_reg_a, AOP (left), 2);
+         AccLsh (8-shCount);
+         accopWithAop ("ora", AOP (result), 1);
+         storeRegToFullAop (hc08_reg_xa, AOP (result), 1);
+         loadRegFromAop (hc08_reg_xa, AOP (left), 2);
+         XAccRsh (shCount, sign);
+         storeRegToAop (hc08_reg_xa, AOP (result), 2);
+       }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genRightShiftLiteral - right shifting by known count            */
+/*-----------------------------------------------------------------*/
+static void
+genRightShiftLiteral (operand * left,
+                     operand * right,
+                     operand * result,
+                     iCode * ic,
+                     int sign)
+{
+  int shCount = (int) floatFromVal (AOP (right)->aopu.aop_lit);
+  int size;
+
+  D(emitcode (";     genRightShiftLiteral",""));
+
+  freeAsmop (right, NULL, ic, TRUE);
+
+  aopOp (left, ic, FALSE);
+  aopOp (result, ic, FALSE);
+
+#if VIEW_SIZE
+  emitcode ("; shift right ", "result %d, left %d", AOP_SIZE (result),
+           AOP_SIZE (left));
+#endif
+
+  size = getDataSize (left);
+  /* test the LEFT size !!! */
+
+  /* I suppose that the left size >= result size */
+  if (shCount == 0)
+    {
+      size = getDataSize (result);
+      while (size--)
+       transferAopAop (AOP (left), size, AOP(result), size);
+    }
+  else if (shCount >= (size * 8))
+    {
+      if (sign) {
+       /* get sign in acc.7 */
+       loadRegFromAop (hc08_reg_a, AOP (left), size -1);
+      }
+      addSign (result, LSB, sign);
+    }
+  else
+    {
+      switch (size)
+       {
+       case 1:
+         genrshOne (result, left, shCount, sign);
+         break;
+
+       case 2:
+         genrshTwo (result, left, shCount, sign);
+         break;
+
+       case 4:
+         genrshFour (result, left, shCount, sign);
+         break;
+       default:
+         break;
+       }
+    }
+  freeAsmop (left, NULL, ic, TRUE);
+  freeAsmop (result, NULL, ic, TRUE);
+}
+
+
+/*-----------------------------------------------------------------*/
+/* genRightShift - generate code for right shifting                */
+/*-----------------------------------------------------------------*/
+static void
+genRightShift (iCode * ic)
+{
+  operand *right, *left, *result;
+  sym_link *retype;
+  int size, offset;
+//  char *l;
+  symbol *tlbl, *tlbl1;
+  char *shift;
+  bool sign;
+  
+  D(emitcode (";     genRightShift",""));
+
+  /* if signed then we do it the hard way preserve the
+     sign bit moving it inwards */
+  retype = getSpec (operandType (IC_RESULT (ic)));
+  sign = !SPEC_USIGN (retype);
+
+  /* signed & unsigned types are treated the same : i.e. the
+     signed is NOT propagated inwards : quoting from the
+     ANSI - standard : "for E1 >> E2, is equivalent to division
+     by 2**E2 if unsigned or if it has a non-negative value,
+     otherwise the result is implementation defined ", MY definition
+     is that the sign does not get propagated */
+
+  right = IC_RIGHT (ic);
+  left = IC_LEFT (ic);
+  result = IC_RESULT (ic);
+
+  aopOp (right, ic, FALSE);
+
+  /* if the shift count is known then do it
+     as efficiently as possible */
+  if (AOP_TYPE (right) == AOP_LIT)
+    {
+      genRightShiftLiteral (left, right, result, ic, sign);
+      return;
+    }
+
+  /* shift count is unknown then we have to form
+     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);
+
+  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--)
+    {
+      transferAopAop (AOP (left), offset, AOP (result), offset);
+      offset--;
+    }
+  
+  tlbl = newiTempLabel (NULL);
+  size = AOP_SIZE (result);
+  offset = 0;
+  tlbl1 = newiTempLabel (NULL);
+
+  loadRegFromAop (hc08_reg_x, AOP (right), 0);
+  emitcode ("tstx", "");
+  emitcode ("beq", "%05d$", tlbl1->key + 100);
+  emitcode ("", "%05d$:", tlbl->key + 100);
+  shift= sign ? "asr" : "lsr";
+  for (offset=size-1;offset>=0;offset--)
+    {
+      rmwWithAop (shift, AOP (result), offset);
+      shift="ror";
+    }
+  rmwWithReg ("dec", hc08_reg_x);
+  emitcode ("bne","%05d$", tlbl->key + 100);
+  emitcode ("", "%05d$:", tlbl1->key + 100);
+  
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (left, NULL, ic, TRUE);
+  freeAsmop (right, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genUnpackBits - generates code for unpacking bits               */
+/*-----------------------------------------------------------------*/
+static void
+genUnpackBits (operand * result)
+{
+  int offset = 0;      /* result byte offset */
+  int rsize;           /* result size */
+  int rlen = 0;                /* remaining bitfield length */
+  sym_link *etype;     /* bitfield type information */
+  int blen;            /* bitfield length */
+  int bstr;            /* bitfield starting bit within byte */
+
+  D(emitcode (";     genUnpackBits",""));
+
+  etype = getSpec (operandType (result));
+  rsize = getSize (operandType (result));
+  blen = SPEC_BLEN (etype);
+  bstr = SPEC_BSTR (etype);
+
+  /* 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));
+      storeRegToAop (hc08_reg_a, AOP (result), offset++);
+      goto finish;
+    }
+
+  /* Bit field did not fit in a byte. Copy all
+     but the partial byte at the end.  */
+  for (rlen=blen;rlen>=8;rlen-=8)
+    {
+      emitcode ("lda", ",x");
+      hc08_dirtyReg (hc08_reg_a, FALSE);
+      storeRegToAop (hc08_reg_a, AOP (result), offset++);
+      if (rlen>8)
+        emitcode ("aix", "#1");
+    }
+
+  /* Handle the partial byte at the end */
+  if (rlen)
+    {
+      emitcode ("lda", ",x");
+      emitcode ("and", "#0x%02x", ((unsigned char) -1) >> (8-rlen));
+      storeRegToAop (hc08_reg_a, AOP (result), offset++);
+    }
+
+finish:
+  if (offset < rsize)
+    {
+      rsize -= offset;
+      while (rsize--)
+        storeConstToAop (zero, AOP (result), offset++);
+    }
+}
+
+
+/*-----------------------------------------------------------------*/
+/* genDataPointerGet - generates code when ptr offset is known     */
+/*-----------------------------------------------------------------*/
+static void
+genDataPointerGet (operand * left,
+                  operand * result,
+                  iCode * ic)
+{
+  int size, offset = 0;
+  asmop *derefaop;
+  
+  D(emitcode (";     genDataPointerGet",""));
+
+  aopOp (result, ic, TRUE);
+  size = AOP_SIZE (result);
+
+  derefaop = aopDerefAop (AOP (left));
+  freeAsmop (left, NULL, ic, TRUE);
+  derefaop->size = size;
+  
+  while (size--)
+    {
+      transferAopAop(derefaop, offset, AOP (result), offset);
+      offset++;
+    }
+
+  freeAsmop (NULL, derefaop, ic, TRUE);
+  freeAsmop (result, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genNearPointerGet - emitcode for near pointer fetch             */
+/*-----------------------------------------------------------------*/
+static void
+genNearPointerGet (operand * left,
+                  operand * result,
+                  iCode * ic,
+                  iCode * pi)
+{
+  int size, offset;
+  sym_link *retype = getSpec (operandType (result));
+
+  D(emitcode (";     genNearPointerGet",""));
+
+  aopOp (left, ic, FALSE);
+
+  /* if left is rematerialisable and
+     result is not bit variable type and
+     the left is pointer to data space i.e
+     lower 128 bytes of space */
+  if ((AOP_TYPE (left) == AOP_IMMD)
+      || (AOP_TYPE (left) == AOP_LIT) 
+      /* !IS_BITVAR (retype) */
+      /* && DCL_TYPE (ltype) == POINTER */ )
+    {
+      genDataPointerGet (left, result, ic);
+      return;
+    }
+
+  /* if the operand is already in hx
+     then we do nothing else we move the value to hx */
+  if (AOP_TYPE (left) != AOP_STR)
+    {
+      /* if this is remateriazable */
+      loadRegFromAop (hc08_reg_x, AOP (left), 0);
+      loadRegFromConst (hc08_reg_h, zero);
+    }
+
+  /* so hx now contains the address */
+  aopOp (result, ic, FALSE);
+
+  /* if bit then unpack */
+  if (IS_BITVAR (retype))
+    genUnpackBits (result);
+  else
+    {
+      size = AOP_SIZE (result);
+      offset = size-1;
+
+      while (size--)
+       {
+         accopWithMisc ("lda", ",x");
+         if (size || pi)
+            {
+              rmwWithReg ("inc", hc08_reg_x);
+            }
+          storeRegToAop (hc08_reg_a, AOP (result), offset--);
+          hc08_freeReg (hc08_reg_a);
+       }
+    }
+
+  freeAsmop (left, NULL, ic, TRUE);
+  freeAsmop (result, NULL, ic, TRUE);
+  
+  if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) {
+    aopOp (IC_RESULT (pi), pi, FALSE);
+    storeRegToAop (hc08_reg_x, AOP (IC_RESULT (pi)), 0);
+    freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
+    pi->generated = 1;
+  }
+
+  hc08_freeReg (hc08_reg_hx);
+  
+}
+
+
+/*-----------------------------------------------------------------*/
+/* genFarPointerGet - get value from far space                     */
+/*-----------------------------------------------------------------*/
+static void
+genFarPointerGet (operand * left,
+                 operand * result, iCode * ic, iCode * pi)
+{
+  int size, offset;
+  sym_link *retype = getSpec (operandType (result));
+
+  D(emitcode (";     genFarPointerGet",""));
+
+  aopOp (left, ic, FALSE);
+
+  /* if left is rematerialisable and
+     result is not bit variable type and
+     the left is pointer to data space i.e
+     lower 128 bytes of space */
+  if (AOP_TYPE (left) == AOP_IMMD &&
+      !IS_BITVAR (retype)
+      /* && DCL_TYPE (ltype) == POINTER */ )
+    {
+      genDataPointerGet (left, result, ic);
+      return;
+    }
+
+  /* if the operand is already in hx
+     then we do nothing else we move the value to hx */
+  if (AOP_TYPE (left) != AOP_STR)
+    {
+      /* if this is remateriazable */
+      loadRegFromAop (hc08_reg_hx, AOP (left), 0);
+    }
+
+  /* so hx now contains the address */
+  aopOp (result, ic, FALSE);
+
+  /* if bit then unpack */
+  if (IS_BITVAR (retype))
+    genUnpackBits (result);
+  else
+    {
+      size = AOP_SIZE (result);
+      offset = size-1;
+
+      while (size--)
+       {
+         accopWithMisc ("lda", ",x");
+         if (size || pi)
+            {
+             emitcode ("aix", "#1");
+             hc08_dirtyReg (hc08_reg_hx, FALSE);
+            }
+          storeRegToAop (hc08_reg_a, AOP (result), offset--);
+          hc08_freeReg (hc08_reg_a);
+       }
+    }
+
+  freeAsmop (left, NULL, ic, TRUE);
+  freeAsmop (result, NULL, ic, TRUE);
+  
+  if (pi /* && AOP_TYPE (left) != AOP_IMMD && AOP_TYPE (left) != AOP_STR */) {
+    aopOp (IC_RESULT (pi), pi, FALSE);
+    storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
+    freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
+    pi->generated = 1;
+  }
+
+  hc08_freeReg (hc08_reg_hx);
+  
+}
+
+
+
+/*-----------------------------------------------------------------*/
+/* genPointerGet - generate code for pointer get                   */
+/*-----------------------------------------------------------------*/
+static void
+genPointerGet (iCode * ic, iCode *pi)
+{
+  operand *left, *result;
+  sym_link *type, *etype;
+  int p_type;
+
+  D(emitcode (";     genPointerGet",""));
+
+  left = IC_LEFT (ic);
+  result = IC_RESULT (ic);
+
+  /* depending on the type of pointer we need to
+     move it to the correct pointer register */
+  type = operandType (left);
+  etype = getSpec (type);
+  /* if left is of type of pointer then it is simple */
+  if (IS_PTR (type) && !IS_FUNC (type->next))
+    p_type = DCL_TYPE (type);
+  else
+    {
+      /* we have to go by the storage class */
+      p_type = PTR_TYPE (SPEC_OCLS (etype));
+    }
+
+  /* special case when cast remat */
+  if (p_type == GPOINTER && OP_SYMBOL(left)->remat &&
+      IS_CAST_ICODE(OP_SYMBOL(left)->rematiCode)) {
+         left = IC_RIGHT(OP_SYMBOL(left)->rematiCode);
+         type = operandType (left);
+         p_type = DCL_TYPE (type);
+  }
+  /* now that we have the pointer type we assign
+     the pointer values */
+  switch (p_type)
+    {
+
+    case POINTER:
+    case IPOINTER:
+#if 0
+      genNearPointerGet (left, result, ic, pi);
+      break;
+#endif
+    case GPOINTER:
+    case CPOINTER:
+    case FPOINTER:
+      genFarPointerGet (left, result, ic, pi);
+      break;
+
+    }
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genPackBits - generates code for packed bit storage             */
+/*-----------------------------------------------------------------*/
+static void
+genPackBits (sym_link * etype,
+            operand * right)
+{
+  int offset = 0;      /* source byte offset */
+  int rlen = 0;                /* remaining bitfield length */
+  int blen;            /* bitfield length */
+  int bstr;            /* bitfield starting bit within byte */
+  int litval;          /* source literal value (if AOP_LIT) */
+  unsigned char mask;  /* bitmask within current byte */
+
+  D(emitcode (";     genPackBits",""));
+
+  blen = SPEC_BLEN (etype);
+  bstr = SPEC_BSTR (etype);
+  
+  /* If the bitfield length is less than a byte */
+  if (blen < 8)
+    {
+      mask = ((unsigned char) (0xFF << (blen + bstr)) |
+             (unsigned char) (0xFF >> (8 - bstr)));
+
+      if (AOP_TYPE (right) == AOP_LIT)
+        {
+          /* Case with a bitfield length <8 and literal source
+          */
+          litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
+          litval <<= bstr;
+          litval &= (~mask) & 0xff;
+
+          emitcode ("lda", ",x");
+          if ((mask|litval)!=0xff)
+            emitcode ("and","#0x%02x", mask);
+          if (litval)
+            emitcode ("ora","#0x%02x", litval);
+          hc08_dirtyReg (hc08_reg_a, FALSE);
+          emitcode ("sta", ",x");
+          
+          hc08_freeReg (hc08_reg_a);
+          return;
+        }
+          
+      /* Case with a bitfield length < 8 and arbitrary source
+      */
+      loadRegFromAop (hc08_reg_a, AOP (right), 0);
+      /* shift and mask source value */
+      AccLsh (bstr);
+      emitcode ("and", "#0x%02x", (~mask) & 0xff);
+      hc08_dirtyReg (hc08_reg_a, FALSE);
+      pushReg (hc08_reg_a, TRUE);
+
+      emitcode ("lda", ",x");
+      emitcode ("and", "#0x%02x", mask);
+      emitcode ("ora", "1,s");
+      emitcode ("sta", ",x");
+      pullReg (hc08_reg_a);
+     
+      hc08_freeReg (hc08_reg_a);
+      return;
+    }
+
+  /* Bit length is greater than 7 bits. In this case, copy  */
+  /* all except the partial byte at the end                 */
+  for (rlen=blen;rlen>=8;rlen-=8)
+    {
+      if (AOP (right)->type == AOP_DIR)
+        {
+          emitcode ("mov", "%s,x+", aopAdrStr(AOP (right), offset, FALSE));
+        }
+      else
+        {
+          loadRegFromAop (hc08_reg_a, AOP (right), offset);
+          emitcode ("sta", "%d,x", offset);
+        }
+      offset++;
+    }
+
+  /* If there was a partial byte at the end */
+  if (rlen)
+    {
+      mask = (((unsigned char) -1 << rlen) & 0xff);
+      
+      if (AOP_TYPE (right) == AOP_LIT)
+        {
+          /* Case with partial byte and literal source
+          */
+          litval = (int) floatFromVal (AOP (right)->aopu.aop_lit);
+          litval >>= (blen-rlen);
+          litval &= (~mask) & 0xff;
+          emitcode ("lda", "%d,x", offset);
+          hc08_dirtyReg (hc08_reg_a, FALSE);
+          if ((mask|litval)!=0xff)
+            emitcode ("and","#0x%02x", mask);
+          if (litval)
+            emitcode ("ora","#0x%02x", litval);
+          emitcode ("sta", "%d,x", offset);
+          hc08_dirtyReg (hc08_reg_a, FALSE);
+          hc08_freeReg (hc08_reg_a);
+          return;
+        }
+      
+      /* Case with partial byte and arbitrary source
+      */
+      loadRegFromAop (hc08_reg_a, AOP (right), offset++);
+      emitcode ("and", "#0x%02x", (~mask) & 0xff);
+      hc08_dirtyReg (hc08_reg_a, FALSE);
+      pushReg (hc08_reg_a, TRUE);
+
+      emitcode ("lda", ",x");
+      emitcode ("and", "#0x%02x", mask);
+      emitcode ("ora", "1,s");
+      emitcode ("sta", ",x");
+    }
+
+  hc08_freeReg (hc08_reg_a);
+}
+
+/*-----------------------------------------------------------------*/
+/* genDataPointerSet - remat pointer to data space                 */
+/*-----------------------------------------------------------------*/
+static void
+genDataPointerSet (operand * right,
+                  operand * result,
+                  iCode * ic)
+{
+  int size, offset = 0;
+  asmop *derefaop;
+
+  D(emitcode (";     genDataPointerSet",""));
+
+  aopOp (right, ic, FALSE);
+  size = AOP_SIZE (right);
+
+  derefaop = aopDerefAop (AOP (result));
+  freeAsmop (result, NULL, ic, TRUE);
+  derefaop->size = size;
+  
+  while (size--)
+    {
+      transferAopAop (AOP (right), offset, derefaop, offset);
+      offset++;
+    }
+
+  freeAsmop (right, NULL, ic, TRUE);
+  freeAsmop (NULL, derefaop, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genNearPointerSet - emitcode for near pointer put                */
+/*-----------------------------------------------------------------*/
+static void
+genNearPointerSet (operand * right,
+                  operand * result,
+                  iCode * ic,
+                  iCode * pi)
+{
+  int size, offset;
+  sym_link *retype = getSpec (operandType (right));
+  sym_link *letype = getSpec (operandType (result));
+
+  D(emitcode (";     genNearPointerSet",""));
+
+  aopOp (result, ic, FALSE);
+
+  /* if the result is rematerializable &
+     in data space & not a bit variable */
+  if (AOP_TYPE (result) == AOP_IMMD &&
+      /* DCL_TYPE (ptype) == POINTER && */
+      !IS_BITVAR (retype) &&
+      !IS_BITVAR (letype))
+    {
+      genDataPointerSet (right, result, ic);
+      return;
+    }
+
+  /* if the operand is already in hx
+     then we do nothing else we move the value to hx */
+  if (AOP_TYPE (result) != AOP_STR)
+    {
+      loadRegFromAop (hc08_reg_x, AOP (result), 0);
+      loadRegFromConst (hc08_reg_h, zero);
+    }
+  /* so hx now contains the address */
+  aopOp (right, ic, FALSE);
+
+  /* if bit then unpack */
+  if (IS_BITVAR (retype) || IS_BITVAR (letype))
+    genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
+  else
+    {
+      size = AOP_SIZE (right);
+      offset = size-1;
+
+      while (size--)
+       {
+          loadRegFromAop (hc08_reg_a, AOP (right), offset--);
+         accopWithMisc ("sta", ",x");
+         if (size || pi)
+           {
+             rmwWithReg ("inc", hc08_reg_x);
+           }
+          hc08_freeReg (hc08_reg_a);
+       }
+    }
+
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (right, NULL, ic, TRUE);
+
+  if (pi /* && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD */) {
+    aopOp (IC_RESULT (pi), pi, FALSE);
+    storeRegToAop (hc08_reg_x, AOP (IC_RESULT (pi)), 0);
+    freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
+    pi->generated=1;
+  }
+
+  hc08_freeReg (hc08_reg_hx);
+  
+}
+
+
+/*-----------------------------------------------------------------*/
+/* genFarPointerSet - set value from far space                     */
+/*-----------------------------------------------------------------*/
+static void
+genFarPointerSet (operand * right,
+                 operand * result, iCode * ic, iCode * pi)
+{
+  int size, offset;
+  sym_link *retype = getSpec (operandType (right));
+  sym_link *letype = getSpec (operandType (result));
+
+  D(emitcode (";     genFarPointerSet",""));
+
+  aopOp (result, ic, FALSE);
+
+  /* if the result is rematerializable &
+     in data space & not a bit variable */
+  if (AOP_TYPE (result) == AOP_IMMD &&
+      /* DCL_TYPE (ptype) == POINTER && */
+      !IS_BITVAR (retype) &&
+      !IS_BITVAR (letype))
+    {
+      genDataPointerSet (right, result, ic);
+      return;
+    }
+
+  /* if the operand is already in hx
+     then we do nothing else we move the value to hx */
+  if (AOP_TYPE (result) != AOP_STR)
+    {
+      loadRegFromAop (hc08_reg_hx, AOP (result), 0);
+    }
+  /* so hx now contains the address */
+  aopOp (right, ic, FALSE);
+
+  /* if bit then unpack */
+  if (IS_BITVAR (retype) || IS_BITVAR (letype))
+    genPackBits ((IS_BITVAR (retype) ? retype : letype), right);
+  else
+    {
+      size = AOP_SIZE (right);
+      offset = size-1;
+
+      while (size--)
+       {
+          loadRegFromAop (hc08_reg_a, AOP (right), offset--);
+         accopWithMisc ("sta", ",x");
+         if (size || pi)
+           {
+             emitcode ("aix", "#1");
+           }
+          hc08_freeReg (hc08_reg_a);
+       }
+    }
+
+  freeAsmop (result, NULL, ic, TRUE);
+  freeAsmop (right, NULL, ic, TRUE);
+
+  if (pi /* && AOP_TYPE (result) != AOP_STR && AOP_TYPE (result) != AOP_IMMD  */) {
+    aopOp (IC_RESULT (pi), pi, FALSE);
+    storeRegToAop (hc08_reg_hx, AOP (IC_RESULT (pi)), 0);
+    freeAsmop (IC_RESULT (pi), NULL, pi, TRUE);
+    pi->generated=1;
+  }
+
+  hc08_freeReg (hc08_reg_hx);
+  
+
+}
+
+
+/*-----------------------------------------------------------------*/
+/* genPointerSet - stores the value into a pointer location        */
+/*-----------------------------------------------------------------*/
+static void
+genPointerSet (iCode * ic, iCode *pi)
+{
+  operand *right, *result;
+  sym_link *type, *etype;
+  int p_type;
+
+  D(emitcode (";     genPointerSet",""));
+
+  right = IC_RIGHT (ic);
+  result = IC_RESULT (ic);
+
+  /* depending on the type of pointer we need to
+     move it to the correct pointer register */
+  type = operandType (result);
+  etype = getSpec (type);
+  /* if left is of type of pointer then it is simple */
+  if (IS_PTR (type) && !IS_FUNC (type->next))
+    {
+      p_type = DCL_TYPE (type);
+    }
+  else
+    {
+      /* we have to go by the storage class */
+      p_type = PTR_TYPE (SPEC_OCLS (etype));
+    }
+
+  /* special case when cast remat */
+  if (p_type == GPOINTER && OP_SYMBOL(result)->remat &&
+      IS_CAST_ICODE(OP_SYMBOL(result)->rematiCode)) {
+         result = IC_RIGHT(OP_SYMBOL(result)->rematiCode);
+         type = operandType (result);
+         p_type = DCL_TYPE (type);
+  }
+  /* now that we have the pointer type we assign
+     the pointer values */
+  switch (p_type)
+    {
+
+    case POINTER:
+    case IPOINTER:
+#if 0
+      genNearPointerSet (right, result, ic, pi);
+      break;
+#endif
+
+    case GPOINTER:
+    case FPOINTER:
+      genFarPointerSet (right, result, ic, pi);
+      break;
+
+    default:
+      werror (E_INTERNAL_ERROR, __FILE__, __LINE__, 
+             "genPointerSet: illegal pointer type");
+    }
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genIfx - generate code for Ifx statement                        */
+/*-----------------------------------------------------------------*/
+static void
+genIfx (iCode * ic, iCode * popIc)
+{
+  operand *cond = IC_COND (ic);
+  int isbit = 0;
+
+  D(emitcode (";     genIfx",""));
+
+  aopOp (cond, ic, FALSE);
+
+  /* get the value into acc */
+  if (AOP_TYPE (cond) != AOP_CRY)
+    asmopToBool (AOP (cond), FALSE);
+  else
+    isbit = 1;
+  /* the result is now in the accumulator */
+  freeAsmop (cond, NULL, ic, TRUE);
+
+  /* if there was something to be popped then do it */
+  if (popIc)
+    genIpop (popIc);
+
+  /* if the condition is  a bit variable */
+  if (isbit && IS_ITEMP (cond) &&
+      SPIL_LOC (cond))
+    genIfxJump (ic, SPIL_LOC (cond)->rname);
+  else if (isbit && !IS_ITEMP (cond))
+    genIfxJump (ic, OP_SYMBOL (cond)->rname);
+  else
+    genIfxJump (ic, "a");
+
+  ic->generated = 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* genAddrOf - generates code for address of                       */
+/*-----------------------------------------------------------------*/
+static void
+genAddrOf (iCode * ic)
+{
+  symbol *sym = OP_SYMBOL (IC_LEFT (ic));
+  int size, offset;
+
+  D(emitcode (";     genAddrOf",""));
+
+  aopOp (IC_RESULT (ic), ic, FALSE);
+
+  /* if the operand is on the stack then we
+     need to get the stack offset of this
+     variable */
+  if (sym->onStack)
+    {
+      /* if it has an offset then we need to compute
+         it */
+      hc08_useReg (hc08_reg_hx);
+      emitcode ("tsx", "");
+      emitcode ("aix", "#%d", _G.stackOfs + _G.stackPushes +sym->stack);
+      storeRegToFullAop (hc08_reg_hx, AOP (IC_RESULT (ic)), FALSE);
+      hc08_freeReg (hc08_reg_hx);
+
+      goto release;
+    }
+
+  /* object not on stack then we need the name */
+  size = AOP_SIZE (IC_RESULT (ic));
+  offset = 0;
+
+  while (size--)
+    {
+      char s[SDCC_NAME_MAX+10];
+      switch (offset) {
+        case 0:
+         sprintf (s, "#%s", sym->rname);
+         break;
+        case 1:
+         sprintf (s, "#>%s", sym->rname);
+         break;
+        default:
+         sprintf (s, "#(%s >> %d)",
+                  sym->rname,
+                  offset * 8);
+      }
+      storeConstToAop(s, AOP (IC_RESULT (ic)), offset++);
+    }
+
+release:
+  freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genAssign - generate code for assignment                        */
+/*-----------------------------------------------------------------*/
+static void
+genAssign (iCode * ic)
+{
+  operand *result, *right;
+  int size, offset;
+//  unsigned long lit = 0L;
+
+  D(emitcode(";     genAssign",""));
+
+  result = IC_RESULT (ic);
+  right = IC_RIGHT (ic);
+
+  /* if they are the same */
+  if (operandsEqu (result, right)) {
+    return;
+  }
+
+  aopOp (right, ic, FALSE);
+  aopOp (result, ic, TRUE);
+
+  /* if they are the same registers */
+  if (sameRegs (AOP (right), AOP (result)))
+    goto release;
+
+  if ((AOP_TYPE (right) == AOP_LIT)
+      && (IS_AOP_HX(AOP(result))))
+    {
+      loadRegFromAop(hc08_reg_hx, AOP (right), 0);
+      goto release;
+    }
+    
+  /* general case */
+  size = AOP_SIZE (result);
+  offset = 0;
+
+  while (size--)
+    {
+      transferAopAop (AOP (right), offset, AOP (result), offset);
+      offset++;
+    }
+
+release:
+  freeAsmop (right, NULL, ic, TRUE);
+  freeAsmop (result, NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genJumpTab - genrates code for jump table                       */
+/*-----------------------------------------------------------------*/
+static void
+genJumpTab (iCode * ic)
+{
+  symbol *jtab;
+//  char *l;
+
+  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);
+
+  jtab = newiTempLabel (NULL);
+  emitcode ("jmp", "%05d$,x", jtab->key + 100);
+  emitcode ("", "%05d$:", jtab->key + 100);
+  /* now generate the jump labels */
+  for (jtab = setFirstItem (IC_JTLABELS (ic)); jtab;
+       jtab = setNextItem (IC_JTLABELS (ic)))
+    emitcode ("jmp", "%05d$", jtab->key + 100);
+
+  hc08_dirtyReg (hc08_reg_a, TRUE);
+  hc08_dirtyReg (hc08_reg_hx, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genCast - gen code for casting                                  */
+/*-----------------------------------------------------------------*/
+static void
+genCast (iCode * ic)
+{
+  operand *result = IC_RESULT (ic);
+  sym_link *ctype = operandType (IC_LEFT (ic));
+  sym_link *rtype = operandType (IC_RIGHT (ic));
+  operand *right = IC_RIGHT (ic);
+  int size, offset;
+
+  D(emitcode(";     genCast",""));
+
+  /* if they are equivalent then do nothing */
+  if (operandsEqu (IC_RESULT (ic), IC_RIGHT (ic)))
+    return;
+
+  aopOp (right, ic, FALSE);
+  aopOp (result, ic, FALSE);
+
+
+  /* if they are the same size : or less */
+  if (AOP_SIZE (result) <= AOP_SIZE (right))
+    {
+
+      /* if they are in the same place */
+      #if 0
+      if (sameRegs (AOP (right), AOP (result)))
+       goto release;
+      #endif
+
+      /* if they in different places then copy */
+      size = AOP_SIZE (result);
+      offset = 0;
+      while (size--)
+       {
+         transferAopAop(AOP (right), offset, AOP (result), offset);
+         offset++;
+       }
+      goto release;
+    }
+
+
+  /* if the result is of type pointer */
+  if (IS_PTR (ctype))
+    {
+
+      int p_type;
+      sym_link *type = operandType (right);
+      sym_link *etype = getSpec (type);
+
+      /* pointer to generic pointer */
+      if (IS_GENPTR (ctype))
+       {
+         if (IS_PTR (type))
+           p_type = DCL_TYPE (type);
+         else
+           {
+             if (SPEC_SCLS(etype)==S_REGISTER) {
+               // let's assume it is a generic pointer
+               p_type=GPOINTER;
+             } else {
+               /* we have to go by the storage class */
+               p_type = PTR_TYPE (SPEC_OCLS (etype));
+             }
+           }
+
+         /* the first two bytes are known */
+         size = GPTRSIZE - 1;
+         offset = 0;
+         while (size--)
+           {
+              transferAopAop(AOP (right), offset, AOP (result), offset);
+             offset++;
+           }
+         /* the last byte depending on type */
+#if 0
+           {
+               int gpVal = pointerTypeToGPByte(p_type, NULL, NULL);
+               char gpValStr[10];
+           
+               if (gpVal == -1)
+               {
+                   // pointerTypeToGPByte will have bitched.
+                   exit(1);
+               }
+           
+               sprintf(gpValStr, "#0x%d", gpVal);
+               aopPut (AOP (result), gpValStr, GPTRSIZE - 1);
+           }       
+#endif
+         goto release;
+       }
+
+      /* just copy the pointers */
+      size = AOP_SIZE (result);
+      offset = 0;
+      while (size--)
+       {
+          transferAopAop(AOP (right), offset, AOP (result), offset);
+         offset++;
+       }
+      goto release;
+    }
+
+  /* so we now know that the size of destination is greater
+     than the size of the source */
+  /* we move to result for the size of source */
+  size = AOP_SIZE (right);
+  offset = 0;
+  while (size--)
+    {
+      transferAopAop(AOP (right), offset, AOP (result), offset);
+      offset++;
+    }
+
+  /* now depending on the sign of the source && destination */
+  size = AOP_SIZE (result) - AOP_SIZE (right);
+  /* if unsigned or not an integral type */
+  if (!IS_SPEC (rtype) || SPEC_USIGN (rtype) || AOP_TYPE(right)==AOP_CRY)
+    {
+      while (size--)
+        storeConstToAop (zero, AOP (result), offset++); 
+    }
+  else
+    {
+      /* we need to extend the sign :{ */
+      loadRegFromAop (hc08_reg_a, AOP (right), AOP_SIZE (right) -1);
+      accopWithMisc ("rola", "");
+      accopWithMisc ("clra", "");
+      accopWithMisc ("sbc", zero);
+      while (size--)
+       storeRegToAop (hc08_reg_a, AOP (result), offset++);
+    }
+
+  /* we are done hurray !!!! */
+
+release:
+  freeAsmop (right, NULL, ic, TRUE);
+  freeAsmop (result, NULL, ic, TRUE);
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genDjnz - generate decrement & jump if not zero instrucion      */
+/*-----------------------------------------------------------------*/
+static int
+genDjnz (iCode * ic, iCode * ifx)
+{
+  symbol *lbl, *lbl1;
+  if (!ifx)
+    return 0;
+
+  D(emitcode (";     genDjnz",""));
+
+  /* if the if condition has a false label
+     then we cannot save */
+  if (IC_FALSE (ifx))
+    return 0;
+
+  /* if the minus is not of the form
+     a = a - 1 */
+  if (!isOperandEqual (IC_RESULT (ic), IC_LEFT (ic)) ||
+      !IS_OP_LITERAL (IC_RIGHT (ic)))
+    return 0;
+
+  if (operandLitValue (IC_RIGHT (ic)) != 1)
+    return 0;
+
+  /* if the size of this greater than one then no
+     saving */
+//  if (getSize (operandType (IC_RESULT (ic))) > 1)
+//    return 0;
+  aopOp (IC_RESULT (ic), ic, FALSE);
+  if (AOP_SIZE (IC_RESULT (ic))>1)
+    {
+      freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+      return 0;
+    }
+
+  /* otherwise we can save BIG */
+  lbl = newiTempLabel (NULL);
+  lbl1 = newiTempLabel (NULL);
+
+
+  emitcode ("dbnz", "%s,%05d$", aopAdrStr (AOP (IC_RESULT (ic)), 0, FALSE),
+               lbl->key + 100);
+  emitBranch ("bra", lbl1);
+  emitLabel (lbl);
+  emitBranch ("jmp", IC_TRUE (ifx));
+  emitLabel (lbl1);
+
+  freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+  ifx->generated = 1;
+  return 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* genReceive - generate code for a receive iCode                  */
+/*-----------------------------------------------------------------*/
+static void
+genReceive (iCode * ic)
+{
+  int size;
+  int offset;
+  D(emitcode (";     genReceive",""));
+
+  aopOp (IC_RESULT (ic), ic, FALSE);
+  size = AOP_SIZE (IC_RESULT (ic));
+  offset = 0;
+  
+  if (ic->argreg) {
+      while (size--) {
+         transferAopAop( hc08_aop_pass[offset+(ic->argreg-1)], 0,
+                         AOP (IC_RESULT (ic)), offset);
+         if (hc08_aop_pass[offset]->type == AOP_REG)
+           hc08_freeReg (hc08_aop_pass[offset]->aopu.aop_reg[0]);
+         offset++;
+      }
+  }      
+
+  freeAsmop (IC_RESULT (ic), NULL, ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genhc08Code - generate code for HC08 based controllers          */
+/*-----------------------------------------------------------------*/
+void
+genhc08Code (iCode * lic)
+{
+  iCode *ic;
+  int cln = 0;
+
+  lineHead = lineCurr = NULL;
+
+  /* print the allocation information */
+  if (allocInfo && currFunc)
+    printAllocInfo (currFunc, codeOutFile);
+  /* if debug information required */
+  if (options.debug && currFunc)
+    {
+      debugFile->writeFunction(currFunc);
+      _G.debugLine = 1;
+      if (IS_STATIC (currFunc->etype))
+       emitcode ("", "F%s$%s$0$0 ==.", moduleName, currFunc->name);
+      else
+       emitcode ("", "G$%s$0$0 ==.", currFunc->name);
+      _G.debugLine = 0;
+    }
+  /* stack pointer name */
+  if (options.useXstack)
+    spname = "_spx";
+  else
+    spname = "sp";
+
+  hc08_aop_pass[0] = newAsmop (AOP_REG);
+  hc08_aop_pass[0]->size=1;
+  hc08_aop_pass[0]->aopu.aop_reg[0] = hc08_reg_a;
+  hc08_aop_pass[1] = newAsmop (AOP_REG);
+  hc08_aop_pass[1]->size=1;
+  hc08_aop_pass[1]->aopu.aop_reg[0] = hc08_reg_x;
+  hc08_aop_pass[2] = newAsmop (AOP_DIR);
+  hc08_aop_pass[2]->size=1;
+  hc08_aop_pass[2]->aopu.aop_dir = "__ret2";
+  hc08_aop_pass[3] = newAsmop (AOP_DIR);
+  hc08_aop_pass[3]->size=1;
+  hc08_aop_pass[3]->aopu.aop_dir = "__ret3";
+
+  for (ic = lic; ic; ic = ic->next)
+    {
+
+      if (ic->lineno && cln != ic->lineno)
+       {
+         if (options.debug)
+           {
+             _G.debugLine = 1;
+             emitcode ("", "C$%s$%d$%d$%d ==.",
+                       FileBaseName (ic->filename), ic->lineno,
+                       ic->level, ic->block);
+             _G.debugLine = 0;
+           }
+         if (!options.noCcodeInAsm) {
+           emitcode ("", ";%s:%d: %s", ic->filename, ic->lineno, 
+                     printCLine(ic->filename, ic->lineno));
+         }
+         cln = ic->lineno;
+       }
+      if (options.iCodeInAsm) {
+       char regsInUse[80];
+       int i;
+
+       for (i=0; i<6; i++) {
+         sprintf (&regsInUse[i],
+                  "%c", ic->riu & (1<<i) ? i+'0' : '-'); 
+       }
+       regsInUse[i]=0;
+       emitcode("", "; [%s] ic:%d: %s", regsInUse, ic->seq, printILine(ic));
+      }
+      /* if the result is marked as
+         spilt and rematerializable or code for
+         this has already been generated then
+         do nothing */
+      if (resultRemat (ic) || ic->generated)
+       continue;
+
+      {
+        int i;
+        regs *reg;
+        symbol *sym;
+        
+        for (i=A_IDX;i<=XA_IDX;i++)
+          {
+            reg = hc08_regWithIdx(i);
+            if (reg->aop)
+              emitcode("","; %s = %s offset %d", reg->name,
+                       aopName(reg->aop), reg->aopofs);
+            reg->isFree = TRUE;
+          }
+        if (IC_LEFT (ic) && IS_ITEMP (IC_LEFT (ic)))
+          {
+            sym = OP_SYMBOL (IC_LEFT (ic));
+            if (sym->accuse == ACCUSE_HX)
+              {
+                hc08_reg_h->isFree = FALSE;
+                hc08_reg_x->isFree = FALSE;
+              }
+            else if (sym->accuse == ACCUSE_XA)
+              {
+                hc08_reg_a->isFree = FALSE;
+                if (sym->nRegs>1)
+                  hc08_reg_x->isFree = FALSE;
+              }
+          }
+        if (IC_RIGHT (ic) && IS_ITEMP (IC_RIGHT (ic)))
+          {
+            sym = OP_SYMBOL (IC_RIGHT (ic));
+            if (sym->accuse == ACCUSE_HX)
+              {
+                hc08_reg_h->isFree = FALSE;
+                hc08_reg_x->isFree = FALSE;
+              }
+            else if (sym->accuse == ACCUSE_XA)
+              {
+                hc08_reg_a->isFree = FALSE;
+                if (sym->nRegs>1)
+                  hc08_reg_x->isFree = FALSE;
+              }
+          }
+      }
+      
+      /* depending on the operation */
+      switch (ic->op)
+       {
+       case '!':
+         genNot (ic);
+         break;
+
+       case '~':
+         genCpl (ic);
+         break;
+
+       case UNARYMINUS:
+         genUminus (ic);
+         break;
+
+       case IPUSH:
+         genIpush (ic);
+         break;
+
+       case IPOP:
+         /* IPOP happens only when trying to restore a
+            spilt live range, if there is an ifx statement
+            following this pop then the if statement might
+            be using some of the registers being popped which
+            would destory the contents of the register so
+            we need to check for this condition and handle it */
+         if (ic->next &&
+             ic->next->op == IFX &&
+             regsInCommon (IC_LEFT (ic), IC_COND (ic->next)))
+           genIfx (ic->next, ic);
+         else
+           genIpop (ic);
+         break;
+
+       case CALL:
+         genCall (ic);
+         break;
+
+       case PCALL:
+         genPcall (ic);
+         break;
+
+       case FUNCTION:
+         genFunction (ic);
+         break;
+
+       case ENDFUNCTION:
+         genEndFunction (ic);
+         break;
+
+       case RETURN:
+         genRet (ic);
+         break;
+
+       case LABEL:
+         genLabel (ic);
+         break;
+
+       case GOTO:
+         genGoto (ic);
+         break;
+
+       case '+':
+          if (!genPointerGetSetOfs (ic))
+           genPlus (ic);
+         break;
+
+       case '-':
+         if (!genDjnz (ic, ifxForOp (IC_RESULT (ic), ic)))
+           genMinus (ic);
+         break;
+
+       case '*':
+         genMult (ic);
+         break;
+
+       case '/':
+         genDiv (ic);
+         break;
+
+       case '%':
+         genMod (ic);
+         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;
+
+       case EQ_OP:
+         genCmpEq (ic, ifxForOp (IC_RESULT (ic), ic));
+         break;
+
+       case AND_OP:
+         genAndOp (ic);
+         break;
+
+       case OR_OP:
+         genOrOp (ic);
+         break;
+
+       case '^':
+         genXor (ic, ifxForOp (IC_RESULT (ic), ic));
+         break;
+
+       case '|':
+         genOr (ic, ifxForOp (IC_RESULT (ic), ic));
+         break;
+
+       case BITWISEAND:
+         genAnd (ic, ifxForOp (IC_RESULT (ic), ic));
+         break;
+
+       case INLINEASM:
+         genInline (ic);
+         break;
+
+       case RRC:
+         genRRC (ic);
+         break;
+
+       case RLC:
+         genRLC (ic);
+         break;
+
+       case GETHBIT:
+         genGetHbit (ic);
+         break;
+
+       case LEFT_OP:
+         genLeftShift (ic);
+         break;
+
+       case RIGHT_OP:
+         genRightShift (ic);
+         break;
+
+       case GET_VALUE_AT_ADDRESS:
+         genPointerGet (ic, hasInc(IC_LEFT(ic),ic,getSize(operandType(IC_RESULT(ic)))));
+         break;
+
+       case '=':
+         if (POINTER_SET (ic))
+           genPointerSet (ic, hasInc (IC_RESULT(ic),ic,getSize(operandType(IC_RIGHT(ic)))));
+         else
+           genAssign (ic);
+         break;
+
+       case IFX:
+         genIfx (ic, NULL);
+         break;
+
+       case ADDRESS_OF:
+         genAddrOf (ic);
+         break;
+
+       case JUMPTABLE:
+         genJumpTab (ic);
+         break;
+
+       case CAST:
+         genCast (ic);
+         break;
+
+       case RECEIVE:
+         genReceive (ic);
+         break;
+
+       case SEND:
+         addSet (&_G.sendSet, ic);
+         break;
+
+       default:
+         ic = ic;
+       }
+
+      if (!hc08_reg_a->isFree)
+        emitcode("","; forgot to free a");
+      if (!hc08_reg_x->isFree)
+        emitcode("","; forgot to free x");
+      if (!hc08_reg_h->isFree)
+        emitcode("","; forgot to free h");
+      if (!hc08_reg_hx->isFree)
+        emitcode("","; forgot to free hx");
+      if (!hc08_reg_xa->isFree)
+        emitcode("","; forgot to free xa");
+    }
+
+
+  /* now we are ready to call the
+     peep hole optimizer */
+  if (!options.nopeep)
+    peepHole (&lineHead);
+
+  /* now do the actual printing */
+  printLine (lineHead, codeOutFile);
+  return;
+}
diff --git a/src/hc08/gen.h b/src/hc08/gen.h
new file mode 100644 (file)
index 0000000..fd9ae77
--- /dev/null
@@ -0,0 +1,96 @@
+/*-------------------------------------------------------------------------
+  SDCCgen51.h - header file for code generation for 8051
+
+             Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+   
+   In other words, you are welcome to use, share and improve this program.
+   You are forbidden to forbid anyone else to use, share and improve
+   what you give them.   Help stamp out software-hoarding!  
+-------------------------------------------------------------------------*/
+
+#ifndef SDCCGEN51_H
+#define SDCCGEN51_H
+
+enum
+  {
+    AOP_LIT = 1,
+    AOP_REG, AOP_DIR,
+    AOP_STK, AOP_IMMD, AOP_STR,
+    AOP_CRY, 
+    AOP_EXT, AOP_SOF,
+  };
+
+enum
+  {
+    ACCUSE_XA = 1,
+    ACCUSE_HX
+  };
+
+/* type asmop : a homogenised type for 
+   all the different spaces an operand can be
+   in */
+typedef struct asmop
+  {
+
+    short type;                        
+    /* can have values
+       AOP_LIT    -  operand is a literal value
+       AOP_REG    -  is in registers
+       AOP_DIR    -  operand using direct addressing mode
+       AOP_STK    -  should be pushed on stack this
+       can happen only for the result
+       AOP_IMMD   -  immediate value for eg. remateriazable 
+       AOP_CRY    -  carry contains the value of this
+       AOP_STR    -  array of strings
+       AOP_SOF    -  operand at an offset on the stack
+       AOP_EXT    -  operand using extended addressing mode
+    */
+    short coff;                        /* current offset */
+    short size;                        /* total size */
+    short psize;               /* pointer size */
+    operand *op;               /* originating operand */
+    unsigned code:1;           /* is in Code space */
+    unsigned paged:1;          /* in paged memory  */
+    unsigned freed:1;          /* already freed    */
+    unsigned isaddr:1;         /* is an address to actual operand */
+    unsigned stacked:1;                /* partial results stored on stack */
+    struct asmop *stk_aop[4];  /* asmops for the results on the stack */
+    union
+      {
+       value *aop_lit;         /* if literal */
+       regs *aop_reg[4];       /* array of registers */
+       char *aop_dir;          /* if direct  */
+       regs *aop_ptr;          /* either -> to r0 or r1 */
+       struct {
+               int  from_cast_remat;   /* cast remat created this : immd2 field used for highest order*/
+               char *aop_immd1;        /* if immediate others are implied */
+               char *aop_immd2;        /* cast remat will generate this   */
+       } aop_immd;
+       int aop_stk;            /* stack offset when AOP_STK */
+       char *aop_str[4];       /* just a string array containing the location */
+      }
+    aopu;
+  }
+asmop;
+
+void genhc08Code (iCode *);
+
+//extern char *fReturn8051[];
+extern unsigned fReturnSizeHC08;
+//extern char **fReturn;
+
+#endif
diff --git a/src/hc08/hc08.dsp b/src/hc08/hc08.dsp
new file mode 100644 (file)
index 0000000..11648f1
--- /dev/null
@@ -0,0 +1,120 @@
+# Microsoft Developer Studio Project File - Name="hc08" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=hc08 - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "hc08.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "hc08.mak" CFG="hc08 - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "hc08 - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE "hc08 - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+RSC=rc.exe
+
+!IF  "$(CFG)" == "hc08 - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /I ".." /I "." /I "..\.." /I "..\..\support\util" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /FD /GZ /Zm500 /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I ".." /I "." /I "..\.." /I "..\..\support\util" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /FR /FD /GZ /Zm1000 /c
+# ADD BASE RSC /l 0x409 /d "_DEBUG"
+# ADD RSC /l 0x409 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"Debug\port.lib"
+# ADD LIB32 /nologo /out:"Debug\port.lib"
+
+!ELSEIF  "$(CFG)" == "hc08 - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /ML /W3 /GX /O2 /I ".." /I "." /I "..\.." /I "..\..\support\util" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /FD /Zm500 /c
+# ADD CPP /nologo /ML /W3 /GX /O2 /I ".." /I "." /I "..\.." /I "..\..\support\util" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /FD /Zm1000 /c
+# ADD BASE RSC /l 0x409 /d "NDEBUG"
+# ADD RSC /l 0x409 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo /out:"Release\port.lib"
+# ADD LIB32 /nologo /out:"Release\port.lib"
+
+!ENDIF 
+
+# Begin Target
+
+# Name "hc08 - Win32 Debug"
+# Name "hc08 - Win32 Release"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\gen.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\main.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\ralloc.c
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\gen.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\main.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\ralloc.h
+# End Source File
+# Begin Source File
+
+SOURCE=..\..\sdcc_vc.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/src/hc08/hc08a.dsp b/src/hc08/hc08a.dsp
new file mode 100644 (file)
index 0000000..cf67ead
--- /dev/null
@@ -0,0 +1,90 @@
+# Microsoft Developer Studio Project File - Name="hc08a" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Generic Project" 0x010a
+
+CFG=hc08a - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE 
+!MESSAGE NMAKE /f "hc08a.mak".
+!MESSAGE 
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE 
+!MESSAGE NMAKE /f "hc08a.mak" CFG="hc08a - Win32 Release"
+!MESSAGE 
+!MESSAGE Possible choices for configuration are:
+!MESSAGE 
+!MESSAGE "hc08a - Win32 Debug" (based on "Win32 (x86) Generic Project")
+!MESSAGE "hc08a - Win32 Release" (based on "Win32 (x86) Generic Project")
+!MESSAGE 
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+MTL=midl.exe
+
+!IF  "$(CFG)" == "hc08a - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir ""
+# PROP Target_Dir ""
+
+!ELSEIF  "$(CFG)" == "hc08a - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Win32_Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ""
+# PROP Intermediate_Dir ""
+# PROP Target_Dir ""
+
+!ENDIF 
+
+# Begin Target
+
+# Name "hc08a - Win32 Debug"
+# Name "hc08a - Win32 Release"
+# Begin Source File
+
+SOURCE=.\peeph.def
+
+!IF  "$(CFG)" == "hc08a - Win32 Debug"
+
+# Begin Custom Build
+InputPath=.\peeph.def
+
+"peeph.rul" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+       gawk -f ../SDCCpeeph.awk $(InputPath) >peeph.rul
+
+# End Custom Build
+
+!ELSEIF  "$(CFG)" == "hc08a - Win32 Release"
+
+# Begin Custom Build
+InputPath=.\peeph.def
+
+"peeph.rul" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
+       gawk -f ../SDCCpeeph.awk $(InputPath) >peeph.rul
+
+# End Custom Build
+
+!ENDIF 
+
+# End Source File
+# End Target
+# End Project
diff --git a/src/hc08/main.c b/src/hc08/main.c
new file mode 100644 (file)
index 0000000..600e768
--- /dev/null
@@ -0,0 +1,392 @@
+/** @file main.c
+    hc08 specific general functions.
+
+    Note that mlh prepended _hc08_ on the static functions.  Makes
+    it easier to set a breakpoint using the debugger.
+*/
+#include "common.h"
+#include "main.h"
+#include "ralloc.h"
+#include "gen.h"
+#include "../SDCCutil.h"
+
+void copyFile(FILE *dest, FILE *src);
+extern char * iComments2;
+
+static char _defaultRules[] =
+{
+#include "peeph.rul"
+};
+
+/* list of key words used by msc51 */
+static char *_hc08_keywords[] =
+{
+  "at",
+  //"bit",
+  "code",
+  "critical",
+  "data",
+  "far",
+  //"idata",
+  "interrupt",
+  "near",
+  //"pdata",
+  "reentrant",
+  //"sfr",
+  //"sbit",
+  //"using",
+  "xdata",
+  "_data",
+  "_code",
+  "_generic",
+  "_near",
+  "_xdata",
+  //"_pdata",
+  //"_idata",
+  "_naked",
+  "_overlay",
+  NULL
+};
+
+
+void hc08_assignRegisters (eBBlock ** ebbs, int count);
+
+static int regParmFlg = 0;     /* determine if we can register a parameter */
+
+static void
+_hc08_init (void)
+{
+  asm_addTree (&asm_asxxxx_mapping);
+}
+
+static void
+_hc08_reset_regparm ()
+{
+  regParmFlg = 0;
+}
+
+static int
+_hc08_regparm (sym_link * l)
+{
+  int size = getSize(l);
+    
+  /* If they fit completely, the first two bytes of parameters can go */
+  /* into A and X, otherwise, they go on the stack. Examples:         */
+  /*   foo(char p1)                    A <- p1                        */
+  /*   foo(char p1, char p2)           A <- p1, X <- p2               */
+  /*   foo(char p1, char p2, char p3)  A <- p1, X <- p2, stack <- p3  */
+  /*   foo(int p1)                     XA <- p1                       */
+  /*   foo(long p1)                    stack <- p1                    */
+  /*   foo(char p1, int p2)            A <- p1, stack <- p2           */
+  /*   foo(int p1, char p2)            XA <- p1, stack <- p2          */
+
+  if (regParmFlg>=2)
+    return 0;
+
+  if ((regParmFlg+size)>2) 
+    {
+      regParmFlg = 2;
+      return 0;
+    }
+
+  regParmFlg += size;
+  return 1+regParmFlg-size;
+}
+
+static bool
+_hc08_parseOptions (int *pargc, char **argv, int *i)
+{
+  return FALSE;
+}
+
+static void
+_hc08_finaliseOptions (void)
+{
+  if (options.noXinitOpt) {
+    port->genXINIT=0;
+  }
+
+  if (options.model == MODEL_LARGE) {
+      port->mem.default_local_map = xdata;
+      port->mem.default_globl_map = xdata;
+    }
+  else
+    {
+      port->mem.default_local_map = data;
+      port->mem.default_globl_map = data;
+    }
+
+}
+
+static void
+_hc08_setDefaultOptions (void)
+{
+  options.code_loc = 0x8000;
+  options.data_loc = 0x80;
+  options.xdata_loc = 0x100;
+  options.stack_loc = 0x7fff;
+  options.out_fmt = 1;         /* use motorola S19 output */
+
+  options.ommitFramePtr = 1;   /* no frame pointer (we use SP */
+                                /* offsets instead)            */
+  
+}
+
+static const char *
+_hc08_getRegName (struct regs *reg)
+{
+  if (reg)
+    return reg->name;
+  return "err";
+}
+
+static void
+_hc08_genAssemblerPreamble (FILE * of)
+{
+   int i;
+  symbol *mainExists=newSymbol("main", 0);
+  mainExists->block=0;
+
+  fprintf (of, "\t.area %s\n",port->mem.code_name);
+  fprintf (of, "\t.area %s\n",port->mem.static_name);
+  fprintf (of, "\t.area %s\n",port->mem.post_static_name);
+  fprintf (of, "\t.area %s\n",port->mem.xinit_name);
+  fprintf (of, "\t.area %s\n",port->mem.data_name);
+  fprintf (of, "\t.area %s\n",port->mem.overlay_name);
+  fprintf (of, "\t.area %s\n",port->mem.bit_name);
+  fprintf (of, "\t.area %s\n",port->mem.xdata_name);
+  fprintf (of, "\t.area %s\n",port->mem.xidata_name);
+
+  if ((mainExists=findSymWithLevel(SymbolTab, mainExists)))
+    {
+      // generate interrupt vector table
+      fprintf (of, "\t.area\tCODEIVT (ABS)\n");
+      fprintf (of, "\t.org\t0x%4x\n", (0xfffe - (maxInterrupts * 2)));
+      
+      for (i=maxInterrupts;i>0;i--)
+        {
+          if (interrupts[i])
+            fprintf (of, "\t.dw\t%s\n", interrupts[i]->rname);
+          else
+            fprintf (of, "\t.dw\t0\n");
+        }
+      fprintf (of, "\t.dw\t%s", "__sdcc_gs_init_startup\n\n");
+        
+      fprintf (of, "\t.area GSINIT\n");
+      fprintf (of, "__sdcc_gs_init_startup:\n");
+      if (options.stack_loc)
+        {
+          fprintf (of, "\tldhx\t#0x%4x\n", options.stack_loc+1);
+          fprintf (of, "\ttxs\n");
+        }
+      else
+        fprintf (of, "\trsp\n");
+      fprintf (of, "\tjsr\t__sdcc_external_startup\n");
+      fprintf (of, "\tbeq\t__sdcc_init_data\n");
+      fprintf (of, "\tjmp\t__sdcc_program_startup\n");
+      fprintf (of, "__sdcc_init_data:\n");
+
+      fprintf (of, "; _hc08_genXINIT() start\n");
+      fprintf (of, "        ldhx #0\n");
+      fprintf (of, "00001$:\n");
+      fprintf (of, "        cphx #l_XINIT\n");
+      fprintf (of, "        beq  00002$\n");
+      fprintf (of, "        lda  s_XINIT,x\n");
+      fprintf (of, "        sta  s_XISEG,x\n");
+      fprintf (of, "        aix  #1\n");
+      fprintf (of, "        bra  00001$\n");
+      fprintf (of, "00002$:\n");
+      fprintf (of, "; _hc08_genXINIT() end\n");
+
+      fprintf (of, "\t.area GSFINAL\n");
+      fprintf (of, "\tjmp\t__sdcc_program_startup\n\n");
+
+      fprintf (of, "\t.area CSEG\n");
+      fprintf (of, "__sdcc_program_startup:\n");
+      fprintf (of, "\tjsr\t_main\n");
+      fprintf (of, "\tbra\t.\n");
+      
+    }
+}
+
+static void
+_hc08_genExtraAreas (FILE * asmFile, bool mainExists)
+{
+    fprintf (asmFile, "%s", iComments2);
+    fprintf (asmFile, "; external ram data\n");
+    fprintf (asmFile, "%s", iComments2);
+    copyFile (asmFile, xdata->oFile);
+}
+
+
+/* Generate interrupt vector table. */
+static int
+_hc08_genIVT (FILE * of, symbol ** interrupts, int maxInterrupts)
+{
+  int i;
+  
+  fprintf (of, "\t.area\tCODEIVT (ABS)\n");
+  fprintf (of, "\t.org\t0x%4x\n",
+    (0xfffe - (maxInterrupts * 2)));
+  
+  for (i=maxInterrupts;i>0;i--)
+    {
+      if (interrupts[i])
+        fprintf (of, "\t.dw\t%s\n", interrupts[i]->rname);
+      else
+        fprintf (of, "\t.dw\t0\n");
+    }
+  fprintf (of, "\t.dw\t%s", "__sdcc_gs_init_startup\n");
+        
+  return TRUE;
+}
+
+/* Generate code to copy XINIT to XISEG */
+static void _hc08_genXINIT (FILE * of) {
+  fprintf (of, ";      _hc08_genXINIT() start\n");
+  fprintf (of, ";      _hc08_genXINIT() end\n");
+}
+
+
+/* Do CSE estimation */
+static bool cseCostEstimation (iCode *ic, iCode *pdic)
+{
+    operand *result = IC_RESULT(ic);
+    sym_link *result_type = operandType(result);
+
+    return 0; /* disable CSE */
+    
+    /* if it is a pointer then return ok for now */
+    if (IC_RESULT(ic) && IS_PTR(result_type)) return 1;
+    
+    if (ic->op == ADDRESS_OF)
+      return 0;
+    
+    /* if bitwise | add & subtract then no since hc08 is pretty good at it 
+       so we will cse only if they are local (i.e. both ic & pdic belong to
+       the same basic block */
+    if (IS_BITWISE_OP(ic) || ic->op == '+' || ic->op == '-') {
+       /* then if they are the same Basic block then ok */
+       if (ic->eBBlockNum == pdic->eBBlockNum) return 1;
+       else return 0;
+    }
+       
+    /* for others it is cheaper to do the cse */
+    return 1;
+}
+
+
+/** $1 is always the basename.
+    $2 is always the output file.
+    $3 varies
+    $l is the list of extra options that should be there somewhere...
+    MUST be terminated with a NULL.
+*/
+static const char *_linkCmd[] =
+{
+  "link-hc08", "-nf", "\"$1\"", NULL
+};
+
+/* $3 is replaced by assembler.debug_opts resp. port->assembler.plain_opts */
+static const char *_asmCmd[] =
+{
+  "as-hc08", "$l", "$3", "\"$1.asm\"", NULL
+};
+
+/* Globals */
+PORT hc08_port =
+{
+  TARGET_ID_HC08,
+  "hc08",
+  "HC08",                      /* Target name */
+  NULL,                                /* Processor name */
+  {
+    glue,
+    FALSE,                     /* Emit glue around main */
+    MODEL_SMALL | MODEL_LARGE,
+    MODEL_LARGE
+  },
+  {
+    _asmCmd,
+    NULL,
+    "-plosgffc",               /* Options with debug */
+    "-plosgff",                        /* Options without debug */
+    0,
+    ".asm",
+    NULL                       /* no do_assemble function */
+  },
+  {
+    _linkCmd,
+    NULL,
+    NULL,
+    ".rel"
+  },
+  {
+    _defaultRules
+  },
+  {
+       /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
+    1, 2, 2, 4, 2, 2, 2, 1, 4, 4
+  },
+  {
+    "XSEG",
+    "STACK",
+    "CSEG",
+    "DSEG",
+    NULL, /* "ISEG" */
+    "XSEG",
+    "BSEG",
+    "RSEG",
+    "GSINIT",
+    "OSEG    (OVR)",
+    "GSFINAL",
+    "HOME",
+    "XISEG", // initialized xdata
+    "XINIT", // a code copy of xiseg
+    NULL,
+    NULL,
+    1
+  },
+  { _hc08_genExtraAreas,
+    NULL },
+  {
+    -1, 0, 4, 2, 0, 0
+  },
+    /* hc08 has an 8 bit mul */
+  {
+    1, -1
+  },
+  "_",
+  _hc08_init,
+  _hc08_parseOptions,
+  NULL,
+  _hc08_finaliseOptions,
+  _hc08_setDefaultOptions,
+  hc08_assignRegisters,
+  _hc08_getRegName,
+  _hc08_keywords,
+  _hc08_genAssemblerPreamble,
+  NULL,                                /* no genAssemblerEnd */
+  _hc08_genIVT,
+  _hc08_genXINIT,
+  _hc08_reset_regparm,
+  _hc08_regparm,
+  NULL,                                /* process_pragma */
+  NULL,                                /* getMangledFunctionName */
+  NULL,                                /* hasNativeMulFor */
+  TRUE,                                /* use_dw_for_init */
+  FALSE,                       /* little endian */
+  0,                           /* leave lt */
+  0,                           /* leave gt */
+  1,                           /* transform <= to ! > */
+  1,                           /* transform >= to ! < */
+  1,                           /* transform != to !(a == b) */
+  0,                           /* leave == */
+  FALSE,                        /* No array initializer support. */
+  cseCostEstimation,
+  NULL,                        /* no builtin functions */
+  GPOINTER,                    /* treat unqualified pointers as "generic" pointers */
+  1,                           /* reset labelKey to 1 */
+  1,                           /* globals & local static allowed */
+  PORT_MAGIC
+};
diff --git a/src/hc08/main.h b/src/hc08/main.h
new file mode 100644 (file)
index 0000000..6555225
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef MAIN_INCLUDE
+#define MAIN_INCLUDE
+
+bool x_parseOptions (char **argv, int *pargc);
+void x_setDefaultOptions (void);
+void x_finaliseOptions (void);
+
+#endif
diff --git a/src/hc08/peeph.def b/src/hc08/peeph.def
new file mode 100644 (file)
index 0000000..6000aa6
--- /dev/null
@@ -0,0 +1,106 @@
+replace {
+       pula
+       psha
+       lda     %1
+} by {
+       ; Peephole 1a   - removed redundant pula/psha
+       lda     %1
+}
+
+replace {
+       pula
+       psha
+       lda     %1,s
+} by {
+       ; Peephole 1b   - removed redundant pula/psha
+       lda     %1,s
+}
+
+replace {
+       pula
+       psha
+       clra
+} by {
+       ; Peephole 1c   - removed redundant pula/psha
+       clra
+}
+
+
+replace {
+       bcs     %1
+       jmp     %5
+%1:
+} by {
+       ; Peephole 2a   - eliminated jmp
+       bcc     %5
+%1:
+} if labelInRange
+
+replace {
+       bcc     %1
+       jmp     %5
+%1:
+} by {
+       ; Peephole 2b   - eliminated jmp
+       bcs     %5
+%1:
+} if labelInRange
+
+replace {
+       beq     %1
+       jmp     %5
+%1:
+} by {
+       ; Peephole 2c   - eliminated jmp
+       bne     %5
+%1:
+} if labelInRange
+
+replace {
+       bne     %1
+       jmp     %5
+%1:
+} by {
+       ; Peephole 2d   - eliminated jmp
+       beq     %5
+%1:
+} if labelInRange
+
+replace {
+       jmp     %5
+} by {
+       ; Peephole 3    - shortened jmp to bra
+       bra     %5
+} if labelInRange
+
+replace {
+       lda     %1
+       tsta
+} by {
+       ; Peephole 4a   - eliminated redundant tsta
+       lda     %1
+}
+
+replace {
+       lda     %1,s
+       tsta
+} by {
+       ; Peephole 4b   - eliminated redundant tsta
+       lda     %1,s
+}
+
+replace {
+       ldx     %1
+       tstx
+} by {
+       ; Peephole 4c   - eliminated redundant tstx
+       ldx     %1
+}
+
+replace {
+       ldx     %1,s
+       tstx
+} by {
+       ; Peephole 4d   - eliminated redundant tstx
+       ldx     %1,s
+}
diff --git a/src/hc08/ralloc.c b/src/hc08/ralloc.c
new file mode 100644 (file)
index 0000000..cbd8b82
--- /dev/null
@@ -0,0 +1,3004 @@
+/*------------------------------------------------------------------------
+
+  SDCCralloc.c - source file for register allocation. (8051) specific
+
+                Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+   
+   In other words, you are welcome to use, share and improve this program.
+   You are forbidden to forbid anyone else to use, share and improve
+   what you give them.   Help stamp out software-hoarding!  
+-------------------------------------------------------------------------*/
+
+#include "common.h"
+#include "ralloc.h"
+#include "gen.h"
+
+/*-----------------------------------------------------------------*/
+/* At this point we start getting processor specific although      */
+/* some routines are non-processor specific & can be reused when   */
+/* targetting other processors. The decision for this will have    */
+/* to be made on a routine by routine basis                        */
+/* routines used to pack registers are most definitely not reusable */
+/* since the pack the registers depending strictly on the MCU      */
+/*-----------------------------------------------------------------*/
+
+extern void genhc08Code (iCode *);
+#define D(x)
+
+/* Global data */
+static struct
+  {
+    bitVect *spiltSet;
+    set *stackSpil;
+    bitVect *regAssigned;
+    bitVect *totRegAssigned;    /* final set of LRs that got into registers */
+    short blockSpil;
+    int slocNum;
+    bitVect *funcrUsed;                /* registers used in a function */
+    int stackExtend;
+    int dataExtend;
+  }
+_G;
+
+/* Shared with gen.c */
+int hc08_ptrRegReq;            /* one byte pointer register required */
+
+/* 8051 registers */
+regs regshc08[] =
+{
+
+  {REG_GPR, A_IDX, REG_GPR, "a", "a", "0", 1, NULL, 0, 1},
+  {REG_GPR, X_IDX, REG_GPR, "x", "x", "0", 2, NULL, 0, 1},
+  {REG_GPR, H_IDX, REG_GPR, "h", "h", "0", 4, NULL, 0, 1},
+  {REG_PTR, HX_IDX, REG_PTR, "hx", "hx", "0", 6, NULL, 0, 1},
+  {REG_GPR, XA_IDX, REG_GPR, "xa", "xa", "0", 3, NULL, 0, 1},
+
+  {REG_CND, CND_IDX, REG_CND, "C", "C", "xreg", 0, NULL, 0, 1},
+};
+int hc08_nRegs = 6;
+
+regs *hc08_reg_a;
+regs *hc08_reg_x;
+regs *hc08_reg_h;
+regs *hc08_reg_hx;
+regs *hc08_reg_xa;
+
+static void spillThis (symbol *);
+static void freeAllRegs ();
+
+/*-----------------------------------------------------------------*/
+/* allocReg - allocates register of given type                     */
+/*-----------------------------------------------------------------*/
+static regs *
+allocReg (short type)
+{
+  return NULL;
+  
+  if ((type==REG_PTR) && (regshc08[HX_IDX].isFree))
+    {
+      regshc08[HX_IDX].isFree = 0;
+      if (currFunc)
+       currFunc->regsUsed =
+         bitVectSetBit (currFunc->regsUsed, HX_IDX);
+      return &regshc08[HX_IDX];
+    }
+  return NULL;
+}
+
+/*-----------------------------------------------------------------*/
+/* hc08_regWithIdx - returns pointer to register wit index number       */
+/*-----------------------------------------------------------------*/
+regs *
+hc08_regWithIdx (int idx)
+{
+  int i;
+
+  for (i = 0; i < hc08_nRegs; i++)
+    if (regshc08[i].rIdx == idx)
+      return &regshc08[i];
+
+  werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+         "regWithIdx not found");
+  exit (1);
+}
+
+/*-----------------------------------------------------------------*/
+/* hc08_freeReg - frees a register                                      */
+/*-----------------------------------------------------------------*/
+void
+hc08_freeReg (regs * reg)
+{
+  if (!reg)
+    {
+      werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+             "hc08_freeReg - Freeing NULL register");
+      exit (1);
+    }
+
+  reg->isFree = 1;
+  
+  switch (reg->rIdx)
+    {
+      case A_IDX:
+        if (hc08_reg_x->isFree)
+          hc08_reg_xa->isFree = 1;
+        break;
+      case X_IDX:
+        if (hc08_reg_a->isFree)
+          hc08_reg_xa->isFree = 1;
+        if (hc08_reg_h->isFree)
+          hc08_reg_hx->isFree = 1;
+        break;
+      case H_IDX:
+        if (hc08_reg_x->isFree)
+          hc08_reg_hx->isFree = 1;
+        break;
+      case HX_IDX:
+        hc08_reg_h->isFree = 1;
+        hc08_reg_x->isFree = 1;
+        if (hc08_reg_a->isFree)
+          hc08_reg_xa->isFree = 1;
+        break;
+      case XA_IDX:
+        hc08_reg_x->isFree = 1;
+        hc08_reg_a->isFree = 1;
+        if (hc08_reg_h->isFree)
+          hc08_reg_hx->isFree = 1;
+        break;
+      default:
+        break;
+    }
+}
+
+
+/*-----------------------------------------------------------------*/
+/* nFreeRegs - returns number of free registers                    */
+/*-----------------------------------------------------------------*/
+static int
+nFreeRegs (int type)
+{
+  int i;
+  int nfr = 0;
+
+  return 0;
+
+  for (i = 0; i < hc08_nRegs; i++)
+    if (regshc08[i].isFree && regshc08[i].type == type)
+      nfr++;
+  return nfr;
+}
+
+/*-----------------------------------------------------------------*/
+/* nfreeRegsType - free registers with type                         */
+/*-----------------------------------------------------------------*/
+static int
+nfreeRegsType (int type)
+{
+  int nfr;
+  if (type == REG_PTR)
+    {
+      if ((nfr = nFreeRegs (type)) == 0)
+       return nFreeRegs (REG_GPR);
+    }
+
+  return nFreeRegs (type);
+}
+
+/*-----------------------------------------------------------------*/
+/* hc08_useReg - marks a register  as used                         */
+/*-----------------------------------------------------------------*/
+void
+hc08_useReg (regs * reg)
+{
+  reg->isFree = 0;
+
+  switch (reg->rIdx)
+    {
+      case A_IDX:
+        hc08_reg_xa->aop = NULL;
+        hc08_reg_xa->isFree = 0;
+       break;
+      case X_IDX:
+        hc08_reg_xa->aop = NULL;
+        hc08_reg_xa->isFree = 0;
+        hc08_reg_hx->aop = NULL;
+        hc08_reg_hx->isFree = 0;
+        break;
+      case H_IDX:
+        hc08_reg_hx->aop = NULL;
+        hc08_reg_hx->isFree = 0;
+        break;
+      case HX_IDX:
+        hc08_reg_h->aop = NULL;
+        hc08_reg_h->isFree = 0;
+        hc08_reg_x->aop = NULL;
+        hc08_reg_x->isFree = 0;
+        break;
+      case XA_IDX:
+        hc08_reg_x->aop = NULL;
+        hc08_reg_x->isFree = 0;
+        hc08_reg_a->aop = NULL;
+        hc08_reg_a->isFree = 0;
+        break;
+      default:
+        break;
+    }
+
+}
+
+/*-----------------------------------------------------------------*/
+/* hc08_dirtyReg - marks a register as dirty                       */
+/*-----------------------------------------------------------------*/
+void
+hc08_dirtyReg (regs * reg, bool freereg)
+{
+  reg->aop = NULL;
+
+  switch (reg->rIdx)
+    {
+      case A_IDX:
+        hc08_reg_xa->aop = NULL;
+        break;
+      case X_IDX:
+        hc08_reg_xa->aop = NULL;
+        hc08_reg_hx->aop = NULL;
+        break;
+      case H_IDX:
+        hc08_reg_hx->aop = NULL;
+        break;
+      case HX_IDX:
+        hc08_reg_h->aop = NULL;
+        hc08_reg_x->aop = NULL;
+        break;
+      case XA_IDX:
+        hc08_reg_x->aop = NULL;
+        hc08_reg_a->aop = NULL;
+        break;
+      default:
+        break;
+    }
+  if (freereg)
+    hc08_freeReg(reg);
+}
+
+/*-----------------------------------------------------------------*/
+/* computeSpillable - given a point find the spillable live ranges */
+/*-----------------------------------------------------------------*/
+static bitVect *
+computeSpillable (iCode * ic)
+{
+  bitVect *spillable;
+
+  /* spillable live ranges are those that are live at this 
+     point . the following categories need to be subtracted
+     from this set. 
+     a) - those that are already spilt
+     b) - if being used by this one
+     c) - defined by this one */
+
+  spillable = bitVectCopy (ic->rlive);
+  spillable =
+    bitVectCplAnd (spillable, _G.spiltSet);    /* those already spilt */
+  spillable =
+    bitVectCplAnd (spillable, ic->uses);       /* used in this one */
+  bitVectUnSetBit (spillable, ic->defKey);
+  spillable = bitVectIntersect (spillable, _G.regAssigned);
+  return spillable;
+
+}
+
+/*-----------------------------------------------------------------*/
+/* noSpilLoc - return true if a variable has no spil location      */
+/*-----------------------------------------------------------------*/
+static int
+noSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
+{
+  return (sym->usl.spillLoc ? 0 : 1);
+}
+
+/*-----------------------------------------------------------------*/
+/* hasSpilLoc - will return 1 if the symbol has spil location      */
+/*-----------------------------------------------------------------*/
+static int
+hasSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
+{
+  return (sym->usl.spillLoc ? 1 : 0);
+}
+
+/*-----------------------------------------------------------------*/
+/* directSpilLoc - will return 1 if the splilocation is in direct  */
+/*-----------------------------------------------------------------*/
+static int
+directSpilLoc (symbol * sym, eBBlock * ebp, iCode * ic)
+{
+  if (sym->usl.spillLoc &&
+      (IN_DIRSPACE (SPEC_OCLS (sym->usl.spillLoc->etype))))
+    return 1;
+  else
+    return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* hasSpilLocnoUptr - will return 1 if the symbol has spil location */
+/*                    but is not used as a pointer                 */
+/*-----------------------------------------------------------------*/
+static int
+hasSpilLocnoUptr (symbol * sym, eBBlock * ebp, iCode * ic)
+{
+  return ((sym->usl.spillLoc && !sym->uptr) ? 1 : 0);
+}
+
+/*-----------------------------------------------------------------*/
+/* rematable - will return 1 if the remat flag is set              */
+/*-----------------------------------------------------------------*/
+static int
+rematable (symbol * sym, eBBlock * ebp, iCode * ic)
+{
+  return sym->remat;
+}
+
+/*-----------------------------------------------------------------*/
+/* notUsedInRemaining - not used or defined in remain of the block */
+/*-----------------------------------------------------------------*/
+static int
+notUsedInRemaining (symbol * sym, eBBlock * ebp, iCode * ic)
+{
+  return ((usedInRemaining (operandFromSymbol (sym), ic) ? 0 : 1) &&
+         allDefsOutOfRange (sym->defs, ebp->fSeq, ebp->lSeq));
+}
+
+/*-----------------------------------------------------------------*/
+/* allLRs - return true for all                                    */
+/*-----------------------------------------------------------------*/
+static int
+allLRs (symbol * sym, eBBlock * ebp, iCode * ic)
+{
+  return 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* liveRangesWith - applies function to a given set of live range  */
+/*-----------------------------------------------------------------*/
+static set *
+liveRangesWith (bitVect * lrs, int (func) (symbol *, eBBlock *, iCode *),
+               eBBlock * ebp, iCode * ic)
+{
+  set *rset = NULL;
+  int i;
+
+  if (!lrs || !lrs->size)
+    return NULL;
+
+  for (i = 1; i < lrs->size; i++)
+    {
+      symbol *sym;
+      if (!bitVectBitValue (lrs, i))
+       continue;
+
+      /* if we don't find it in the live range 
+         hash table we are in serious trouble */
+      if (!(sym = hTabItemWithKey (liveRanges, i)))
+       {
+         werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+                 "liveRangesWith could not find liveRange");
+         exit (1);
+       }
+
+      if (func (sym, ebp, ic) && bitVectBitValue (_G.regAssigned, sym->key))
+       addSetHead (&rset, sym);
+    }
+
+  return rset;
+}
+
+
+/*-----------------------------------------------------------------*/
+/* leastUsedLR - given a set determines which is the least used    */
+/*-----------------------------------------------------------------*/
+static symbol *
+leastUsedLR (set * sset)
+{
+  symbol *sym = NULL, *lsym = NULL;
+
+  sym = lsym = setFirstItem (sset);
+
+  if (!lsym)
+    return NULL;
+
+  for (; lsym; lsym = setNextItem (sset))
+    {
+
+      /* if usage is the same then prefer
+         the spill the smaller of the two */
+      if (lsym->used == sym->used)
+       if (getSize (lsym->type) < getSize (sym->type))
+         sym = lsym;
+
+      /* if less usage */
+      if (lsym->used < sym->used)
+       sym = lsym;
+
+    }
+
+  setToNull ((void **) &sset);
+  sym->blockSpil = 0;
+  return sym;
+}
+
+/*-----------------------------------------------------------------*/
+/* noOverLap - will iterate through the list looking for over lap  */
+/*-----------------------------------------------------------------*/
+static int
+noOverLap (set * itmpStack, symbol * fsym)
+{
+  symbol *sym;
+
+
+  for (sym = setFirstItem (itmpStack); sym;
+       sym = setNextItem (itmpStack))
+    {
+       if (bitVectBitValue(sym->clashes,fsym->key)) return 0;
+    }
+
+  return 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* isFree - will return 1 if the a free spil location is found     */
+/*-----------------------------------------------------------------*/
+static
+DEFSETFUNC (isFree)
+{
+  symbol *sym = item;
+  V_ARG (symbol **, sloc);
+  V_ARG (symbol *, fsym);
+
+  /* if already found */
+  if (*sloc)
+    return 0;
+
+  /* if it is free && and the itmp assigned to
+     this does not have any overlapping live ranges
+     with the one currently being assigned and
+     the size can be accomodated  */
+  if (sym->isFree &&
+      noOverLap (sym->usl.itmpStack, fsym) &&
+      getSize (sym->type) >= getSize (fsym->type))
+    {
+      *sloc = sym;
+      return 1;
+    }
+
+  return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* spillLRWithPtrReg :- will spil those live ranges which use PTR  */
+/*-----------------------------------------------------------------*/
+static void
+spillLRWithPtrReg (symbol * forSym)
+{
+  symbol *lrsym;
+  regs *hx;
+  int k;
+
+  if (!_G.regAssigned ||
+      bitVectIsZero (_G.regAssigned))
+    return;
+
+  hx = hc08_regWithIdx (HX_IDX);
+
+  /* for all live ranges */
+  for (lrsym = hTabFirstItem (liveRanges, &k); lrsym;
+       lrsym = hTabNextItem (liveRanges, &k))
+    {
+      int j;
+
+      /* if no registers assigned to it or spilt */
+      /* if it does not overlap with this then 
+         not need to spill it */
+
+      if (lrsym->isspilt || !lrsym->nRegs ||
+         (lrsym->liveTo < forSym->liveFrom))
+       continue;
+
+      /* go thru the registers : if it is either
+         r0 or r1 then spil it */
+      for (j = 0; j < lrsym->nRegs; j++)
+       if (lrsym->regs[j] == hx)
+         {
+           spillThis (lrsym);
+           break;
+         }
+    }
+
+}
+
+/*-----------------------------------------------------------------*/
+/* createStackSpil - create a location on the stack to spil        */
+/*-----------------------------------------------------------------*/
+static symbol *
+createStackSpil (symbol * sym)
+{
+  symbol *sloc = NULL;
+  int useXstack, model;
+
+  char slocBuffer[30];
+
+  /* first go try and find a free one that is already 
+     existing on the stack */
+  if (applyToSet (_G.stackSpil, isFree, &sloc, sym))
+    {
+      /* found a free one : just update & return */
+      sym->usl.spillLoc = sloc;
+      sym->stackSpil = 1;
+      sloc->isFree = 0;
+      addSetHead (&sloc->usl.itmpStack, sym);
+      return sym;
+    }
+
+  /* could not then have to create one , this is the hard part
+     we need to allocate this on the stack : this is really a
+     hack!! but cannot think of anything better at this time */
+
+  if (sprintf (slocBuffer, "sloc%d", _G.slocNum++) >= sizeof (slocBuffer))
+    {
+      fprintf (stderr, "***Internal error: slocBuffer overflowed: %s:%d\n",
+              __FILE__, __LINE__);
+      exit (1);
+    }
+
+  sloc = newiTemp (slocBuffer);
+
+  /* set the type to the spilling symbol */
+  sloc->type = copyLinkChain (sym->type);
+  sloc->etype = getSpec (sloc->type);
+  SPEC_SCLS (sloc->etype) = S_DATA;
+  SPEC_EXTR (sloc->etype) = 0;
+  SPEC_STAT (sloc->etype) = 0;
+  SPEC_VOLATILE(sloc->etype) = 0;
+  SPEC_ABSA(sloc->etype) = 0;
+
+  /* we don't allow it to be allocated`
+     onto the external stack since : so we
+     temporarily turn it off ; we also
+     turn off memory model to prevent
+     the spil from going to the external storage
+   */
+
+  useXstack = options.useXstack;
+  model = options.model;
+/*     noOverlay = options.noOverlay; */
+/*     options.noOverlay = 1; */
+  options.model = options.useXstack = 0;
+
+  allocLocal (sloc);
+
+  options.useXstack = useXstack;
+  options.model = model;
+/*     options.noOverlay = noOverlay; */
+  sloc->isref = 1;             /* to prevent compiler warning */
+
+  /* if it is on the stack then update the stack */
+  if (IN_STACK (sloc->etype))
+    {
+      currFunc->stack += getSize (sloc->type);
+      _G.stackExtend += getSize (sloc->type);
+    }
+  else
+    _G.dataExtend += getSize (sloc->type);
+
+  /* add it to the _G.stackSpil set */
+  addSetHead (&_G.stackSpil, sloc);
+  sym->usl.spillLoc = sloc;
+  sym->stackSpil = 1;
+
+  /* add it to the set of itempStack set 
+     of the spill location */
+  addSetHead (&sloc->usl.itmpStack, sym);
+  return sym;
+}
+
+/*-----------------------------------------------------------------*/
+/* isSpiltOnStack - returns true if the spil location is on stack  */
+/*-----------------------------------------------------------------*/
+static bool
+isSpiltOnStack (symbol * sym)
+{
+  sym_link *etype;
+
+  if (!sym)
+    return FALSE;
+
+  if (!sym->isspilt)
+    return FALSE;
+
+/*     if (sym->_G.stackSpil) */
+/*      return TRUE; */
+
+  if (!sym->usl.spillLoc)
+    return FALSE;
+
+  etype = getSpec (sym->usl.spillLoc->type);
+  if (IN_STACK (etype))
+    return TRUE;
+
+  return FALSE;
+}
+
+/*-----------------------------------------------------------------*/
+/* spillThis - spils a specific operand                            */
+/*-----------------------------------------------------------------*/
+static void
+spillThis (symbol * sym)
+{
+  int i;
+  /* if this is rematerializable or has a spillLocation
+     we are okay, else we need to create a spillLocation
+     for it */
+  if (!(sym->remat || sym->usl.spillLoc))
+    createStackSpil (sym);
+
+  /* mark it has spilt & put it in the spilt set */
+  sym->isspilt = sym->spillA = 1;
+  _G.spiltSet = bitVectSetBit (_G.spiltSet, sym->key);
+
+  bitVectUnSetBit (_G.regAssigned, sym->key);
+  bitVectUnSetBit (_G.totRegAssigned, sym->key);
+
+  for (i = 0; i < sym->nRegs; i++)
+
+    if (sym->regs[i])
+      {
+       hc08_freeReg (sym->regs[i]);
+       sym->regs[i] = NULL;
+      }
+
+  /* if spilt on stack then free up r0 & r1 
+     if they could have been assigned to some
+     LIVE ranges */
+//  if (!hc08_ptrRegReq && isSpiltOnStack (sym))
+//    {
+//      hc08_ptrRegReq++;
+//      spillLRWithPtrReg (sym);
+//    }
+
+  if (sym->usl.spillLoc && !sym->remat)
+    sym->usl.spillLoc->allocreq++;
+  return;
+}
+
+/*-----------------------------------------------------------------*/
+/* selectSpil - select a iTemp to spil : rather a simple procedure */
+/*-----------------------------------------------------------------*/
+static symbol *
+selectSpil (iCode * ic, eBBlock * ebp, symbol * forSym)
+{
+  bitVect *lrcs = NULL;
+  set *selectS;
+  symbol *sym;
+
+  /* get the spillable live ranges */
+  lrcs = computeSpillable (ic);
+
+  /* get all live ranges that are rematerizable */
+  if ((selectS = liveRangesWith (lrcs, rematable, ebp, ic)))
+    {
+
+      /* return the least used of these */
+      return leastUsedLR (selectS);
+    }
+
+  /* get live ranges with spillLocations in direct space */
+  if ((selectS = liveRangesWith (lrcs, directSpilLoc, ebp, ic)))
+    {
+      sym = leastUsedLR (selectS);
+      strcpy (sym->rname, (sym->usl.spillLoc->rname[0] ?
+                          sym->usl.spillLoc->rname :
+                          sym->usl.spillLoc->name));
+      sym->spildir = 1;
+      /* mark it as allocation required */
+      sym->usl.spillLoc->allocreq++;
+      return sym;
+    }
+
+  /* if the symbol is local to the block then */
+  if (forSym->liveTo < ebp->lSeq)
+    {
+
+      /* check if there are any live ranges allocated
+         to registers that are not used in this block */
+      if (!_G.blockSpil && (selectS = liveRangesWith (lrcs, notUsedInBlock, ebp, ic)))
+       {
+         sym = leastUsedLR (selectS);
+         /* if this is not rematerializable */
+         if (!sym->remat)
+           {
+             _G.blockSpil++;
+             sym->blockSpil = 1;
+           }
+         return sym;
+       }
+
+      /* check if there are any live ranges that not
+         used in the remainder of the block */
+      if (!_G.blockSpil && (selectS = liveRangesWith (lrcs, notUsedInRemaining, ebp, ic)))
+       {
+         sym = leastUsedLR (selectS);
+         if (sym != forSym)
+           {
+             if (!sym->remat)
+               {
+                 sym->remainSpil = 1;
+                 _G.blockSpil++;
+               }
+             return sym;
+           }
+       }
+    }
+
+  /* find live ranges with spillocation && not used as pointers */
+  if ((selectS = liveRangesWith (lrcs, hasSpilLocnoUptr, ebp, ic)))
+    {
+
+      sym = leastUsedLR (selectS);
+      /* mark this as allocation required */
+      sym->usl.spillLoc->allocreq++;
+      return sym;
+    }
+
+  /* find live ranges with spillocation */
+  if ((selectS = liveRangesWith (lrcs, hasSpilLoc, ebp, ic)))
+    {
+
+      sym = leastUsedLR (selectS);
+      sym->usl.spillLoc->allocreq++;
+      return sym;
+    }
+
+  /* couldn't find then we need to create a spil
+     location on the stack , for which one? the least
+     used ofcourse */
+  if ((selectS = liveRangesWith (lrcs, noSpilLoc, ebp, ic)))
+    {
+
+      /* return a created spil location */
+      sym = createStackSpil (leastUsedLR (selectS));
+      sym->usl.spillLoc->allocreq++;
+      return sym;
+    }
+
+  /* this is an extreme situation we will spill
+     this one : happens very rarely but it does happen */
+  spillThis (forSym);
+  return forSym;
+
+}
+
+/*-----------------------------------------------------------------*/
+/* spilSomething - spil some variable & mark registers as free     */
+/*-----------------------------------------------------------------*/
+static bool
+spilSomething (iCode * ic, eBBlock * ebp, symbol * forSym)
+{
+  symbol *ssym;
+  int i;
+
+  /* get something we can spil */
+  ssym = selectSpil (ic, ebp, forSym);
+
+  /* mark it as spilt */
+  ssym->isspilt = ssym->spillA = 1;
+  _G.spiltSet = bitVectSetBit (_G.spiltSet, ssym->key);
+
+  /* mark it as not register assigned &
+     take it away from the set */
+  bitVectUnSetBit (_G.regAssigned, ssym->key);
+  bitVectUnSetBit (_G.totRegAssigned, ssym->key);
+
+  /* mark the registers as free */
+  for (i = 0; i < ssym->nRegs; i++)
+    if (ssym->regs[i])
+      hc08_freeReg (ssym->regs[i]);
+
+  /* if spilt on stack then free up hx
+     if it could have been assigned to as gprs */
+  if (!hc08_ptrRegReq && isSpiltOnStack (ssym))
+    {
+      hc08_ptrRegReq++;
+      spillLRWithPtrReg (ssym);
+    }
+
+  /* if this was a block level spil then insert push & pop 
+     at the start & end of block respectively */
+  if (ssym->blockSpil)
+    {
+      iCode *nic = newiCode (IPUSH, operandFromSymbol (ssym), NULL);
+      /* add push to the start of the block */
+      addiCodeToeBBlock (ebp, nic, (ebp->sch->op == LABEL ?
+                                   ebp->sch->next : ebp->sch));
+      nic = newiCode (IPOP, operandFromSymbol (ssym), NULL);
+      /* add pop to the end of the block */
+      addiCodeToeBBlock (ebp, nic, NULL);
+    }
+
+  /* if spilt because not used in the remainder of the
+     block then add a push before this instruction and
+     a pop at the end of the block */
+  if (ssym->remainSpil)
+    {
+
+      iCode *nic = newiCode (IPUSH, operandFromSymbol (ssym), NULL);
+      /* add push just before this instruction */
+      addiCodeToeBBlock (ebp, nic, ic);
+
+      nic = newiCode (IPOP, operandFromSymbol (ssym), NULL);
+      /* add pop to the end of the block */
+      addiCodeToeBBlock (ebp, nic, NULL);
+    }
+
+  if (ssym == forSym)
+    return FALSE;
+  else
+    return TRUE;
+}
+
+/*-----------------------------------------------------------------*/
+/* getRegPtr - will try for PTR if not a GPR type if not spil      */
+/*-----------------------------------------------------------------*/
+static regs *
+getRegPtr (iCode * ic, eBBlock * ebp, symbol * sym)
+{
+  regs *reg;
+
+tryAgain:
+  /* try for a ptr type */
+  if ((reg = allocReg (REG_PTR)))
+    return reg;
+
+  /* try for gpr type */
+  if ((reg = allocReg (REG_GPR)))
+    return reg;
+
+  /* we have to spil */
+  if (!spilSomething (ic, ebp, sym))
+    return NULL;
+
+  /* this looks like an infinite loop but 
+     in really selectSpil will abort  */
+  goto tryAgain;
+}
+
+/*-----------------------------------------------------------------*/
+/* getRegGpr - will try for GPR if not spil                        */
+/*-----------------------------------------------------------------*/
+static regs *
+getRegGpr (iCode * ic, eBBlock * ebp, symbol * sym)
+{
+  regs *reg;
+
+tryAgain:
+  /* try for gpr type */
+  if ((reg = allocReg (REG_GPR)))
+    return reg;
+
+  if (!hc08_ptrRegReq)
+    if ((reg = allocReg (REG_PTR)))
+      return reg;
+
+  /* we have to spil */
+  if (!spilSomething (ic, ebp, sym))
+    return NULL;
+
+  /* this looks like an infinite loop but 
+     in really selectSpil will abort  */
+  goto tryAgain;
+}
+
+/*-----------------------------------------------------------------*/
+/* getRegPtrNoSpil - get it cannot split                           */
+/*-----------------------------------------------------------------*/
+static regs *getRegPtrNoSpil()
+{
+  regs *reg;
+
+  /* try for a ptr type */
+  if ((reg = allocReg (REG_PTR)))
+    return reg;
+
+  /* try for gpr type */
+  if ((reg = allocReg (REG_GPR)))
+    return reg;
+
+  assert(0);
+
+  /* just to make the compiler happy */
+  return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* getRegGprNoSpil - get it cannot split                           */
+/*-----------------------------------------------------------------*/
+static regs *getRegGprNoSpil()
+{
+
+  regs *reg;
+  if ((reg = allocReg (REG_GPR)))
+    return reg;
+
+  if (!hc08_ptrRegReq)
+    if ((reg = allocReg (REG_PTR)))
+      return reg;
+
+  assert(0);
+
+  /* just to make the compiler happy */
+  return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* symHasReg - symbol has a given register                         */
+/*-----------------------------------------------------------------*/
+static bool
+symHasReg (symbol * sym, regs * reg)
+{
+  int i;
+
+  for (i = 0; i < sym->nRegs; i++)
+    if (sym->regs[i] == reg)
+      return TRUE;
+
+  return FALSE;
+}
+
+/*-----------------------------------------------------------------*/
+/* deassignLRs - check the live to and if they have registers & are */
+/*               not spilt then free up the registers              */
+/*-----------------------------------------------------------------*/
+static void
+deassignLRs (iCode * ic, eBBlock * ebp)
+{
+  symbol *sym;
+  int k;
+  symbol *result;
+
+  for (sym = hTabFirstItem (liveRanges, &k); sym;
+       sym = hTabNextItem (liveRanges, &k))
+    {
+
+      symbol *psym = NULL;
+      /* if it does not end here */
+      if (sym->liveTo > ic->seq)
+       continue;
+
+      /* if it was spilt on stack then we can 
+         mark the stack spil location as free */
+      if (sym->isspilt)
+       {
+         if (sym->stackSpil)
+           {
+             sym->usl.spillLoc->isFree = 1;
+             sym->stackSpil = 0;
+           }
+         continue;
+       }
+
+      if (!bitVectBitValue (_G.regAssigned, sym->key))
+       continue;
+
+      /* special case check if this is an IFX &
+         the privious one was a pop and the 
+         previous one was not spilt then keep track
+         of the symbol */
+      if (ic->op == IFX && ic->prev &&
+         ic->prev->op == IPOP &&
+         !ic->prev->parmPush &&
+         !OP_SYMBOL (IC_LEFT (ic->prev))->isspilt)
+       psym = OP_SYMBOL (IC_LEFT (ic->prev));
+
+      if (sym->nRegs)
+       {
+         int i = 0;
+
+         bitVectUnSetBit (_G.regAssigned, sym->key);
+
+         /* if the result of this one needs registers
+            and does not have it then assign it right
+            away */
+         if (IC_RESULT (ic) &&
+             !(SKIP_IC2 (ic) ||        /* not a special icode */
+               ic->op == JUMPTABLE ||
+               ic->op == IFX ||
+               ic->op == IPUSH ||
+               ic->op == IPOP ||
+               ic->op == RETURN ||
+               POINTER_SET (ic)) &&
+             (result = OP_SYMBOL (IC_RESULT (ic))) &&  /* has a result */
+             result->liveTo > ic->seq &&       /* and will live beyond this */
+             result->liveTo <= ebp->lSeq &&    /* does not go beyond this block */
+             result->regType == sym->regType &&        /* same register types */
+             result->nRegs &&  /* which needs registers */
+             !result->isspilt &&       /* and does not already have them */
+             !result->remat &&
+             !bitVectBitValue (_G.regAssigned, result->key) &&
+         /* the number of free regs + number of regs in this LR
+            can accomodate the what result Needs */
+             ((nfreeRegsType (result->regType) +
+               sym->nRegs) >= result->nRegs)
+           )
+           {
+
+             for (i = 0; i < result->nRegs; i++)
+               if (i < sym->nRegs)
+                 result->regs[i] = sym->regs[i];
+               else
+                 result->regs[i] = getRegGpr (ic, ebp, result);
+
+             _G.regAssigned = bitVectSetBit (_G.regAssigned, result->key);
+             _G.totRegAssigned = bitVectSetBit (_G.totRegAssigned, result->key);
+
+           }
+
+         /* free the remaining */
+         for (; i < sym->nRegs; i++)
+           {
+             if (psym)
+               {
+                 if (!symHasReg (psym, sym->regs[i]))
+                   hc08_freeReg (sym->regs[i]);
+               }
+             else
+               hc08_freeReg (sym->regs[i]);
+           }
+       }
+    }
+}
+
+
+/*-----------------------------------------------------------------*/
+/* reassignLR - reassign this to registers                         */
+/*-----------------------------------------------------------------*/
+static void
+reassignLR (operand * op)
+{
+  symbol *sym = OP_SYMBOL (op);
+  int i;
+
+  /* not spilt any more */
+  sym->isspilt = sym->spillA = sym->blockSpil = sym->remainSpil = 0;
+  bitVectUnSetBit (_G.spiltSet, sym->key);
+
+  _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
+  _G.totRegAssigned = bitVectSetBit (_G.totRegAssigned, sym->key);
+
+  _G.blockSpil--;
+
+  for (i = 0; i < sym->nRegs; i++)
+    sym->regs[i]->isFree = 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* willCauseSpill - determines if allocating will cause a spill    */
+/*-----------------------------------------------------------------*/
+static int
+willCauseSpill (int nr, int rt)
+{
+  /* first check if there are any avlb registers
+     of te type required */
+  if (rt == REG_PTR)
+    {
+      /* special case for pointer type 
+         if pointer type not avlb then 
+         check for type gpr */
+      if (nFreeRegs (rt) >= nr)
+       return 0;
+      if (nFreeRegs (REG_GPR) >= nr)
+       return 0;
+    }
+  else
+    {
+      if (hc08_ptrRegReq)
+       {
+         if (nFreeRegs (rt) >= nr)
+           return 0;
+       }
+      else
+       {
+         if (nFreeRegs (REG_PTR) +
+             nFreeRegs (REG_GPR) >= nr)
+           return 0;
+       }
+    }
+
+  /* it will cause a spil */
+  return 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* positionRegs - the allocator can allocate same registers to res- */
+/* ult and operand, if this happens make sure they are in the same */
+/* position as the operand otherwise chaos results                 */
+/*-----------------------------------------------------------------*/
+static int
+positionRegs (symbol * result, symbol * opsym)
+{
+  int count = min (result->nRegs, opsym->nRegs);
+  int i, j = 0, shared = 0;
+  int change = 0;
+
+  /* if the result has been spilt then cannot share */
+  if (opsym->isspilt)
+    return 0;
+again:
+  shared = 0;
+  /* first make sure that they actually share */
+  for (i = 0; i < count; i++)
+    {
+      for (j = 0; j < count; j++)
+       {
+         if (result->regs[i] == opsym->regs[j] && i != j)
+           {
+             shared = 1;
+             goto xchgPositions;
+           }
+       }
+    }
+xchgPositions:
+  if (shared)
+    {
+      regs *tmp = result->regs[i];
+      result->regs[i] = result->regs[j];
+      result->regs[j] = tmp;
+      change ++;
+      goto again;
+    }
+  return change;
+}
+
+/*-----------------------------------------------------------------*/
+/* serialRegAssign - serially allocate registers to the variables  */
+/*-----------------------------------------------------------------*/
+static void
+serialRegAssign (eBBlock ** ebbs, int count)
+{
+    int i;
+
+    /* for all blocks */
+    for (i = 0; i < count; i++) {
+
+       iCode *ic;
+
+       if (ebbs[i]->noPath &&
+           (ebbs[i]->entryLabel != entryLabel &&
+            ebbs[i]->entryLabel != returnLabel))
+           continue;
+
+       /* of all instructions do */
+       for (ic = ebbs[i]->sch; ic; ic = ic->next) {
+#if 1
+           int reg;
+
+           // update the registers in use at the start of this icode
+           for (reg=0; reg<hc08_nRegs; reg++) {
+             if (regshc08[reg].isFree) {
+               ic->riu &= ~(regshc08[reg].mask);
+             } else {
+               ic->riu |= (regshc08[reg].mask);
+             }
+           }
+#endif
+
+           /* if this is an ipop that means some live
+              range will have to be assigned again */
+           if (ic->op == IPOP)
+               reassignLR (IC_LEFT (ic));
+
+           /* if result is present && is a true symbol */
+           if (IC_RESULT (ic) && ic->op != IFX &&
+               IS_TRUE_SYMOP (IC_RESULT (ic)))
+               OP_SYMBOL (IC_RESULT (ic))->allocreq++;
+
+           /* take away registers from live
+              ranges that end at this instruction */
+           deassignLRs (ic, ebbs[i]);
+
+           /* some don't need registers */
+           if (SKIP_IC2 (ic) ||
+               ic->op == JUMPTABLE ||
+               ic->op == IFX ||
+               ic->op == IPUSH ||
+               ic->op == IPOP ||
+               (IC_RESULT (ic) && POINTER_SET (ic)))
+               continue;
+
+           /* now we need to allocate registers
+              only for the result */
+           if (IC_RESULT (ic)) {
+               symbol *sym = OP_SYMBOL (IC_RESULT (ic));
+               bitVect *spillable;
+               int willCS;
+               int j;
+               int ptrRegSet = 0;
+
+               /* if it does not need or is spilt 
+                  or is already assigned to registers
+                  or will not live beyond this instructions */
+               if (!sym->nRegs ||
+                   sym->isspilt ||
+                   bitVectBitValue (_G.regAssigned, sym->key) ||
+                   sym->liveTo <= ic->seq)
+                   continue;
+
+               /* if some liverange has been spilt at the block level
+                  and this one live beyond this block then spil this
+                  to be safe */
+               if (_G.blockSpil && sym->liveTo > ebbs[i]->lSeq) {
+                   spillThis (sym);
+                   continue;
+               }
+               /* if trying to allocate this will cause
+                  a spill and there is nothing to spill 
+                  or this one is rematerializable then
+                  spill this one */
+               willCS = willCauseSpill (sym->nRegs, sym->regType);
+               spillable = computeSpillable (ic);
+               if (sym->remat || (willCS && bitVectIsZero (spillable))) {                    
+                   spillThis (sym);
+                   continue;                 
+               }
+
+               /* if it has a spillocation & is used less than
+                  all other live ranges then spill this */
+               if (willCS) {
+                   if (sym->usl.spillLoc) {
+                       symbol *leastUsed = leastUsedLR (liveRangesWith (spillable,
+                                                                        allLRs, ebbs[i], ic));
+                       if (leastUsed && leastUsed->used > sym->used) {
+                           spillThis (sym);
+                           continue;
+                       }
+                   } else {
+                       /* if none of the liveRanges have a spillLocation then better
+                          to spill this one than anything else already assigned to registers */
+                       if (liveRangesWith(spillable,noSpilLoc,ebbs[i],ic)) {
+                           /* if this is local to this block then we might find a block spil */
+                           if (!(sym->liveFrom >= ebbs[i]->fSeq && sym->liveTo <= ebbs[i]->lSeq)) {
+                               spillThis (sym);
+                               continue;
+                           }
+                       }
+                   }
+               }
+               /* if we need ptr regs for the right side
+                  then mark it */
+               if (POINTER_GET (ic) && IS_SYMOP (IC_LEFT (ic))
+                   && getSize (OP_SYMBOL (IC_LEFT (ic))->type) <= (unsigned int) PTRSIZE) {
+                   hc08_ptrRegReq++;
+                   ptrRegSet = 1;
+               }
+               /* else we assign registers to it */
+               _G.regAssigned = bitVectSetBit (_G.regAssigned, sym->key);
+               _G.totRegAssigned = bitVectSetBit (_G.totRegAssigned, sym->key);
+
+               for (j = 0; j < sym->nRegs; j++) {
+                   if (sym->regType == REG_PTR)
+                       sym->regs[j] = getRegPtr (ic, ebbs[i], sym);
+                   else
+                       sym->regs[j] = getRegGpr (ic, ebbs[i], sym);
+
+                   /* if the allocation failed which means
+                      this was spilt then break */
+                   if (!sym->regs[j]) {
+                     break;
+                   }
+               }
+
+               /* if it shares registers with operands make sure
+                  that they are in the same position */
+               if (IC_LEFT (ic) && IS_SYMOP (IC_LEFT (ic)) &&
+                   OP_SYMBOL (IC_LEFT (ic))->nRegs && ic->op != '=') {
+                   positionRegs (OP_SYMBOL (IC_RESULT (ic)),
+                                 OP_SYMBOL (IC_LEFT (ic)));
+               }
+               /* do the same for the right operand */
+               if (IC_RIGHT (ic) && IS_SYMOP (IC_RIGHT (ic)) &&
+                   OP_SYMBOL (IC_RIGHT (ic))->nRegs) {
+                   positionRegs (OP_SYMBOL (IC_RESULT (ic)),
+                                 OP_SYMBOL (IC_RIGHT (ic)));
+               }
+
+               if (ptrRegSet) {
+                   hc08_ptrRegReq--;
+                   ptrRegSet = 0;
+               }
+
+           }
+       }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* fillGaps - Try to fill in the Gaps left by Pass1                */
+/*-----------------------------------------------------------------*/
+static void fillGaps()
+{
+    symbol *sym =NULL;
+    int key =0;    
+    
+    if (getenv("DISABLE_FILL_GAPS")) return;
+    
+    /* look for livernages that was spilt by the allocator */
+    for (sym = hTabFirstItem(liveRanges,&key) ; sym ; 
+        sym = hTabNextItem(liveRanges,&key)) {
+
+       int i;
+       int pdone = 0;
+
+       if (!sym->spillA || !sym->clashes || sym->remat) continue ;
+
+       /* find the liveRanges this one clashes with, that are
+          still assigned to registers & mark the registers as used*/
+       for ( i = 0 ; i < sym->clashes->size ; i ++) {
+           int k;
+           symbol *clr;
+
+           if (bitVectBitValue(sym->clashes,i) == 0 ||    /* those that clash with this */
+               bitVectBitValue(_G.totRegAssigned,i) == 0) /* and are still assigned to registers */
+               continue ;
+
+               clr = hTabItemWithKey(liveRanges,i);
+           assert(clr);
+        
+           /* mark these registers as used */
+           for (k = 0 ; k < clr->nRegs ; k++ ) 
+               hc08_useReg(clr->regs[k]);
+       }
+
+       if (willCauseSpill(sym->nRegs,sym->regType)) {
+           /* NOPE :( clear all registers & and continue */
+           freeAllRegs();
+           continue ;
+       }
+
+       /* THERE IS HOPE !!!! */
+       for (i=0; i < sym->nRegs ; i++ ) {
+           if (sym->regType == REG_PTR)
+               sym->regs[i] = getRegPtrNoSpil ();
+           else
+               sym->regs[i] = getRegGprNoSpil ();                
+       }
+
+       /* for all its definitions check if the registers
+          allocated needs positioning NOTE: we can position
+          only ONCE if more than One positioning required 
+          then give up */
+       sym->isspilt = 0;
+       for (i = 0 ; i < sym->defs->size ; i++ ) {
+           if (bitVectBitValue(sym->defs,i)) {
+               iCode *ic;
+               if (!(ic = hTabItemWithKey(iCodehTab,i))) continue ;
+               if (SKIP_IC(ic)) continue;
+               assert(isSymbolEqual(sym,OP_SYMBOL(IC_RESULT(ic)))); /* just making sure */
+               /* if left is assigned to registers */
+               if (IS_SYMOP(IC_LEFT(ic)) && 
+                   bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_LEFT(ic))->key)) {
+                   pdone += positionRegs(sym,OP_SYMBOL(IC_LEFT(ic)));
+               }
+               if (IS_SYMOP(IC_RIGHT(ic)) && 
+                   bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RIGHT(ic))->key)) {
+                   pdone += positionRegs(sym,OP_SYMBOL(IC_RIGHT(ic)));
+               }
+               if (pdone > 1) break;
+           }
+       }
+       for (i = 0 ; i < sym->uses->size ; i++ ) {
+           if (bitVectBitValue(sym->uses,i)) {
+               iCode *ic;
+               if (!(ic = hTabItemWithKey(iCodehTab,i))) continue ;
+               if (SKIP_IC(ic)) continue;
+               if (!IS_ASSIGN_ICODE(ic)) continue ;
+
+               /* if result is assigned to registers */
+               if (IS_SYMOP(IC_RESULT(ic)) && 
+                   bitVectBitValue(_G.totRegAssigned,OP_SYMBOL(IC_RESULT(ic))->key)) {
+                   pdone += positionRegs(sym,OP_SYMBOL(IC_RESULT(ic)));
+               }
+               if (pdone > 1) break;
+           }
+       }
+       /* had to position more than once GIVE UP */
+       if (pdone > 1) {
+           /* UNDO all the changes we made to try this */
+           sym->isspilt = 1;
+           for (i=0; i < sym->nRegs ; i++ ) {
+                   sym->regs[i] = NULL;
+           }
+           freeAllRegs();
+           D(printf ("Fill Gap gave up due to positioning for %s in function %s\n",sym->name, currFunc ? currFunc->name : "UNKNOWN"));
+           continue ;      
+       }
+       D(printf ("FILLED GAP for %s in function %s\n",sym->name, currFunc ? currFunc->name : "UNKNOWN"));
+       _G.totRegAssigned = bitVectSetBit(_G.totRegAssigned,sym->key);
+       sym->isspilt = sym->spillA = 0 ;
+       sym->usl.spillLoc->allocreq--;
+       freeAllRegs();
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* rUmaskForOp :- returns register mask for an operand             */
+/*-----------------------------------------------------------------*/
+bitVect *
+hc08_rUmaskForOp (operand * op)
+{
+  bitVect *rumask;
+  symbol *sym;
+  int j;
+
+  /* only temporaries are assigned registers */
+  if (!IS_ITEMP (op))
+    return NULL;
+
+  sym = OP_SYMBOL (op);
+
+  /* if spilt or no registers assigned to it
+     then nothing */
+  if (sym->isspilt || !sym->nRegs)
+    return NULL;
+
+  rumask = newBitVect (hc08_nRegs);
+
+  for (j = 0; j < sym->nRegs; j++)
+    {
+      rumask = bitVectSetBit (rumask,
+                             sym->regs[j]->rIdx);
+    }
+
+  return rumask;
+}
+
+/*-----------------------------------------------------------------*/
+/* regsUsedIniCode :- returns bit vector of registers used in iCode */
+/*-----------------------------------------------------------------*/
+static bitVect *
+regsUsedIniCode (iCode * ic)
+{
+  bitVect *rmask = newBitVect (hc08_nRegs);
+
+  /* do the special cases first */
+  if (ic->op == IFX)
+    {
+      rmask = bitVectUnion (rmask,
+                           hc08_rUmaskForOp (IC_COND (ic)));
+      goto ret;
+    }
+
+  /* for the jumptable */
+  if (ic->op == JUMPTABLE)
+    {
+      rmask = bitVectUnion (rmask,
+                           hc08_rUmaskForOp (IC_JTCOND (ic)));
+
+      goto ret;
+    }
+
+  /* of all other cases */
+  if (IC_LEFT (ic))
+    rmask = bitVectUnion (rmask,
+                         hc08_rUmaskForOp (IC_LEFT (ic)));
+
+
+  if (IC_RIGHT (ic))
+    rmask = bitVectUnion (rmask,
+                         hc08_rUmaskForOp (IC_RIGHT (ic)));
+
+  if (IC_RESULT (ic))
+    rmask = bitVectUnion (rmask,
+                         hc08_rUmaskForOp (IC_RESULT (ic)));
+
+ret:
+  return rmask;
+}
+
+/*-----------------------------------------------------------------*/
+/* createRegMask - for each instruction will determine the regsUsed */
+/*-----------------------------------------------------------------*/
+static void
+createRegMask (eBBlock ** ebbs, int count)
+{
+  int i;
+
+  /* for all blocks */
+  for (i = 0; i < count; i++)
+    {
+      iCode *ic;
+
+      if (ebbs[i]->noPath &&
+         (ebbs[i]->entryLabel != entryLabel &&
+          ebbs[i]->entryLabel != returnLabel))
+       continue;
+
+      /* for all instructions */
+      for (ic = ebbs[i]->sch; ic; ic = ic->next)
+       {
+
+         int j;
+
+         if (SKIP_IC2 (ic) || !ic->rlive)
+           continue;
+
+         /* first mark the registers used in this
+            instruction */
+         ic->rUsed = regsUsedIniCode (ic);
+         _G.funcrUsed = bitVectUnion (_G.funcrUsed, ic->rUsed);
+
+         /* now create the register mask for those 
+            registers that are in use : this is a
+            super set of ic->rUsed */
+         ic->rMask = newBitVect (hc08_nRegs + 1);
+
+         /* for all live Ranges alive at this point */
+         for (j = 1; j < ic->rlive->size; j++)
+           {
+             symbol *sym;
+             int k;
+
+             /* if not alive then continue */
+             if (!bitVectBitValue (ic->rlive, j))
+               continue;
+
+             /* find the live range we are interested in */
+             if (!(sym = hTabItemWithKey (liveRanges, j)))
+               {
+                 werror (E_INTERNAL_ERROR, __FILE__, __LINE__,
+                         "createRegMask cannot find live range");
+                 fprintf(stderr, "\tmissing live range: key=%d\n", j);
+                 exit (0);
+               }
+
+             /* if no register assigned to it */
+             if (!sym->nRegs || sym->isspilt)
+               continue;
+
+             /* for all the registers allocated to it */
+             for (k = 0; k < sym->nRegs; k++)
+               if (sym->regs[k])
+                 ic->rMask =
+                   bitVectSetBit (ic->rMask, sym->regs[k]->rIdx);
+           }
+       }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* rematStr - returns the rematerialized string for a remat var    */
+/*-----------------------------------------------------------------*/
+static char *
+rematStr (symbol * sym)
+{
+  char *s = buffer;
+  iCode *ic = sym->rematiCode;
+//  int offset = 0;
+  
+  while (1)
+    {
+
+      /* if plus or minus print the right hand side */
+      if (ic->op == '+' || ic->op == '-')
+       {
+         sprintf (s, "0x%04x %c ", (int) operandLitValue (IC_RIGHT (ic)),
+                  ic->op);
+         s += strlen (s);
+         ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
+         continue;
+       }
+/*      
+      if (ic->op == '+')
+        {
+          offset += operandLitValue (IC_RIGHT (ic));
+         ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
+          continue;
+        }
+      if (ic->op == '-')
+        {
+          offset -= operandLitValue (IC_RIGHT (ic));
+         ic = OP_SYMBOL (IC_LEFT (ic))->rematiCode;
+          continue;
+        }
+*/
+      /* cast then continue */
+      if (IS_CAST_ICODE(ic)) {
+         ic = OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
+         continue;
+      }
+      /* we reached the end */
+      sprintf (s, "%s", OP_SYMBOL (IC_LEFT (ic))->rname);
+      break;
+    }
+
+  return buffer;
+}
+
+/*-----------------------------------------------------------------*/
+/* regTypeNum - computes the type & number of registers required   */
+/*-----------------------------------------------------------------*/
+static void
+regTypeNum (eBBlock *ebbs)
+{
+  symbol *sym;
+  int k;
+  iCode *ic;
+
+  /* for each live range do */
+  for (sym = hTabFirstItem (liveRanges, &k); sym;
+       sym = hTabNextItem (liveRanges, &k))
+    {
+
+      /* if used zero times then no registers needed */
+      if ((sym->liveTo - sym->liveFrom) == 0)
+       continue;
+
+
+      /* if the live range is a temporary */
+      if (sym->isitmp)
+       {
+
+         /* if the type is marked as a conditional */
+         if (sym->regType == REG_CND)
+           continue;
+
+         /* if used in return only then we don't 
+            need registers */
+         if (sym->ruonly || sym->accuse)
+           {
+             if (IS_AGGREGATE (sym->type) || sym->isptr)
+               sym->type = aggrToPtr (sym->type, FALSE);
+             continue;
+           }
+
+         /* if the symbol has only one definition &
+            that definition is a get_pointer */
+         if (bitVectnBitsOn (sym->defs) == 1 &&
+             (ic = hTabItemWithKey (iCodehTab,
+                                    bitVectFirstBit (sym->defs))) &&
+             POINTER_GET (ic) &&
+             !sym->noSpilLoc &&
+             !IS_BITVAR (sym->etype))
+           {
+
+
+             /* and that pointer is remat in data space */
+             if (IS_SYMOP (IC_LEFT (ic)) &&
+                 OP_SYMBOL (IC_LEFT (ic))->remat &&
+                 !IS_CAST_ICODE(OP_SYMBOL (IC_LEFT (ic))->rematiCode) &&
+                 DCL_TYPE (aggrToPtr (operandType(IC_LEFT(ic)), FALSE)) == POINTER)
+               {
+                 /* create a psuedo symbol & force a spil */
+                 symbol *psym = newSymbol (rematStr (OP_SYMBOL (IC_LEFT (ic))), 1);
+                 psym->type = sym->type;
+                 psym->etype = sym->etype;
+                 strcpy (psym->rname, psym->name);
+                 sym->isspilt = 1;
+                 sym->usl.spillLoc = psym;
+#if 0 // an alternative fix for bug #480076
+                 /* now this is a useless assignment to itself */
+                 remiCodeFromeBBlock (ebbs, ic);
+#else
+                 /* now this really is an assignment to itself, make it so;
+                    it will be optimized out later */
+                 ic->op='=';
+                 ReplaceOpWithCheaperOp(&IC_RIGHT(ic), IC_RESULT(ic));
+                 IC_LEFT(ic)=NULL;
+#endif
+                 continue;
+               }
+
+             /* if in data space or idata space then try to
+                allocate pointer register */
+
+           }
+
+         /* if not then we require registers */
+         sym->nRegs = ((IS_AGGREGATE (sym->type) || sym->isptr) ?
+                       getSize (sym->type = aggrToPtr (sym->type, FALSE)) :
+                       getSize (sym->type));
+
+         if (sym->nRegs > 4)
+           {
+             fprintf (stderr, "allocated more than 4 or 0 registers for type ");
+             printTypeChain (sym->type, stderr);
+             fprintf (stderr, "\n");
+           }
+
+         /* determine the type of register required */
+         if (sym->nRegs == 1 &&
+             IS_PTR (sym->type) &&
+             sym->uptr)
+           sym->regType = REG_PTR;
+         else
+           sym->regType = REG_GPR;
+
+       }
+      else
+       /* for the first run we don't provide */
+       /* registers for true symbols we will */
+       /* see how things go                  */
+       sym->nRegs = 0;
+         }
+
+}
+
+/*-----------------------------------------------------------------*/
+/* freeAllRegs - mark all registers as free                        */
+/*-----------------------------------------------------------------*/
+static void
+freeAllRegs ()
+{
+  int i;
+
+  for (i = 0; i < hc08_nRegs; i++) {
+    regshc08[i].isFree = 1;
+    regshc08[i].aop = NULL;
+  }
+}
+
+/*-----------------------------------------------------------------*/
+/* deallocStackSpil - this will set the stack pointer back         */
+/*-----------------------------------------------------------------*/
+static
+DEFSETFUNC (deallocStackSpil)
+{
+  symbol *sym = item;
+
+  deallocLocal (sym);
+  return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* farSpacePackable - returns the packable icode for far variables */
+/*-----------------------------------------------------------------*/
+static iCode *
+farSpacePackable (iCode * ic)
+{
+  iCode *dic;
+
+  /* go thru till we find a definition for the
+     symbol on the right */
+  for (dic = ic->prev; dic; dic = dic->prev)
+    {
+      /* if the definition is a call then no */
+      if ((dic->op == CALL || dic->op == PCALL) &&
+         IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
+       {
+         return NULL;
+       }
+
+      /* if shift by unknown amount then not */
+      if ((dic->op == LEFT_OP || dic->op == RIGHT_OP) &&
+         IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
+       return NULL;
+
+#if 0
+      /* if pointer get and size > 1 */
+      if (POINTER_GET (dic) &&
+         getSize (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)) > 1)
+       return NULL;
+
+      if (POINTER_SET (dic) &&
+         getSize (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)) > 1)
+       return NULL;
+#endif
+
+      /* if any three is a true symbol in far space */
+      if (IC_RESULT (dic) &&
+         IS_TRUE_SYMOP (IC_RESULT (dic)) /* &&
+         isOperandInFarSpace (IC_RESULT (dic)) */)
+       return NULL;
+
+      if (IC_RIGHT (dic) &&
+         IS_TRUE_SYMOP (IC_RIGHT (dic)) /* &&
+         isOperandInFarSpace (IC_RIGHT (dic)) */ &&
+         !isOperandEqual (IC_RIGHT (dic), IC_RESULT (ic)))
+       return NULL;
+
+      if (IC_LEFT (dic) &&
+         IS_TRUE_SYMOP (IC_LEFT (dic)) /* &&
+         isOperandInFarSpace (IC_LEFT (dic)) */ &&
+         !isOperandEqual (IC_LEFT (dic), IC_RESULT (ic)))
+       return NULL;
+
+      if (isOperandEqual (IC_RIGHT (ic), IC_RESULT (dic)))
+       {
+         if ((dic->op == LEFT_OP ||
+              dic->op == RIGHT_OP ||
+              dic->op == '-') &&
+             IS_OP_LITERAL (IC_RIGHT (dic)))
+           return NULL;
+         else
+           return dic;
+       }
+    }
+
+  return NULL;
+}
+
+/*-----------------------------------------------------------------*/
+/* packRegsForAssign - register reduction for assignment           */
+/*-----------------------------------------------------------------*/
+static int
+packRegsForAssign (iCode * ic, eBBlock * ebp)
+{
+  iCode *dic, *sic;
+
+  if (!IS_ITEMP (IC_RIGHT (ic)) ||
+      OP_SYMBOL (IC_RIGHT (ic))->isind ||
+      OP_LIVETO (IC_RIGHT (ic)) > ic->seq)
+    {
+      return 0;
+    }
+
+
+  /* if the true symbol is defined in far space or on stack
+     then we should not since this will increase register pressure */
+#if 0
+  if (isOperandInFarSpace(IC_RESULT(ic)) && !farSpacePackable(ic)) {
+    return 0;
+  }
+#endif
+
+  /* find the definition of iTempNN scanning backwards if we find a 
+     a use of the true symbol in before we find the definition then 
+     we cannot */
+  for (dic = ic->prev; dic; dic = dic->prev)
+    {
+
+#if 0 /* jwk: This collides with 1.43 but I really see no need for
+        this anymore. It fixes bug #716790 and substantially improves 
+        redundant register usage around function calls.
+      */
+
+      /* if there is a function call then don't pack it */
+      if ((dic->op == CALL || dic->op == PCALL))
+       {
+         dic = NULL;
+         break;
+       }
+#endif
+
+      if (SKIP_IC2 (dic))
+       continue;
+
+      if (IS_TRUE_SYMOP (IC_RESULT (dic)) &&
+         IS_OP_VOLATILE (IC_RESULT (dic)))
+       {
+         dic = NULL;
+         break;
+       }
+
+      if (IS_SYMOP (IC_RESULT (dic)) &&
+         IC_RESULT (dic)->key == IC_RIGHT (ic)->key)
+       {
+         if (POINTER_SET (dic))
+           dic = NULL;
+
+         break;
+       }
+
+      if (IS_SYMOP (IC_RIGHT (dic)) &&
+         (IC_RIGHT (dic)->key == IC_RESULT (ic)->key ||
+          IC_RIGHT (dic)->key == IC_RIGHT (ic)->key))
+       {
+         dic = NULL;
+         break;
+       }
+
+      if (IS_SYMOP (IC_LEFT (dic)) &&
+         (IC_LEFT (dic)->key == IC_RESULT (ic)->key ||
+          IC_LEFT (dic)->key == IC_RIGHT (ic)->key))
+       {
+         dic = NULL;
+         break;
+       }
+
+      if (POINTER_SET (dic) &&
+         IC_RESULT (dic)->key == IC_RESULT (ic)->key)
+       {
+         dic = NULL;
+         break;
+       }
+    }
+
+  if (!dic)
+    return 0;                  /* did not find */
+
+  /* if assignment then check that right is not a bit */
+  if (ASSIGNMENT (dic) && !POINTER_SET (dic))
+    {
+      sym_link *etype = operandType (IC_RIGHT (dic));
+      if (IS_BITFIELD (etype))
+        {
+          /* if result is a bit too then it's ok */
+         etype = operandType (IC_RESULT (dic));
+          if (!IS_BITFIELD (etype))
+           return 0;
+       }
+    }
+  /* if the result is on stack or iaccess then it must be
+     the same atleast one of the operands */
+  if (OP_SYMBOL (IC_RESULT (ic))->onStack ||
+      OP_SYMBOL (IC_RESULT (ic))->iaccess)
+    {
+
+      /* the operation has only one symbol
+         operator then we can pack */
+      if ((IC_LEFT (dic) && !IS_SYMOP (IC_LEFT (dic))) ||
+         (IC_RIGHT (dic) && !IS_SYMOP (IC_RIGHT (dic))))
+       goto pack;
+
+      if (!((IC_LEFT (dic) &&
+            IC_RESULT (ic)->key == IC_LEFT (dic)->key) ||
+           (IC_RIGHT (dic) &&
+            IC_RESULT (ic)->key == IC_RIGHT (dic)->key)))
+       return 0;
+    }
+pack:
+  /* found the definition */
+  /* replace the result with the result of */
+  /* this assignment and remove this assignment */
+  bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+  ReplaceOpWithCheaperOp(&IC_RESULT (dic), IC_RESULT (ic));
+
+  if (IS_ITEMP (IC_RESULT (dic)) && OP_SYMBOL (IC_RESULT (dic))->liveFrom > dic->seq)
+    {
+      OP_SYMBOL (IC_RESULT (dic))->liveFrom = dic->seq;
+    }
+  // TODO: and the otherway around?
+
+  /* delete from liverange table also 
+     delete from all the points inbetween and the new
+     one */
+  for (sic = dic; sic != ic; sic = sic->next)
+    {
+      bitVectUnSetBit (sic->rlive, IC_RESULT (ic)->key);
+      if (IS_ITEMP (IC_RESULT (dic)))
+       bitVectSetBit (sic->rlive, IC_RESULT (dic)->key);
+    }
+
+  remiCodeFromeBBlock (ebp, ic);
+  bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
+  hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
+  OP_DEFS(IC_RESULT (dic))=bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
+  return 1;
+}
+
+/*------------------------------------------------------------------*/
+/* findAssignToSym : scanning backwards looks for first assig found */
+/*------------------------------------------------------------------*/
+static iCode *
+findAssignToSym (operand * op, iCode * ic)
+{
+  iCode *dic;
+
+  /* This routine is used to find sequences like
+     iTempAA = FOO;
+     ...;  (intervening ops don't use iTempAA or modify FOO)
+     blah = blah + iTempAA;
+
+     and eliminate the use of iTempAA, freeing up its register for
+     other uses.
+  */
+     
+
+  for (dic = ic->prev; dic; dic = dic->prev)
+    {
+
+      /* if definition by assignment */
+      if (dic->op == '=' &&
+         !POINTER_SET (dic) &&
+         IC_RESULT (dic)->key == op->key
+          &&  IS_TRUE_SYMOP(IC_RIGHT(dic)) 
+       )
+       break;  /* found where this temp was defined */
+
+      /* if we find an usage then we cannot delete it */
+      if (IC_LEFT (dic) && IC_LEFT (dic)->key == op->key)
+       return NULL;
+
+      if (IC_RIGHT (dic) && IC_RIGHT (dic)->key == op->key)
+       return NULL;
+
+      if (POINTER_SET (dic) && IC_RESULT (dic)->key == op->key)
+       return NULL;
+    }
+
+  if (!dic)
+    return NULL;   /* didn't find any assignment to op */
+
+  /* we are interested only if defined in far space */
+  /* or in stack space in case of + & - */
+  
+  /* if assigned to a non-symbol then don't repack regs */
+  if (!IS_SYMOP (IC_RIGHT (dic)))
+    return NULL;
+  
+  /* if the symbol is volatile then we should not */
+  if (isOperandVolatile (IC_RIGHT (dic), TRUE))
+    return NULL;
+  /* XXX TODO --- should we be passing FALSE to isOperandVolatile()?
+     What does it mean for an iTemp to be volatile, anyway? Passing
+     TRUE is more cautious but may prevent possible optimizations */
+
+  /* if the symbol is in far space then we should not */
+  /* if (isOperandInFarSpace (IC_RIGHT (dic)))
+    return NULL; */
+  
+  /* for + & - operations make sure that
+     if it is on the stack it is the same
+     as one of the three operands */
+#if 0
+  if ((ic->op == '+' || ic->op == '-') &&
+      OP_SYMBOL (IC_RIGHT (dic))->onStack)
+    {
+      
+      if (IC_RESULT (ic)->key != IC_RIGHT (dic)->key &&
+         IC_LEFT (ic)->key != IC_RIGHT (dic)->key &&
+         IC_RIGHT (ic)->key != IC_RIGHT (dic)->key)
+       return NULL;
+    }
+#endif
+  
+  /* now make sure that the right side of dic
+     is not defined between ic & dic */
+  if (dic)
+    {
+      iCode *sic = dic->next;
+
+      for (; sic != ic; sic = sic->next)
+       if (IC_RESULT (sic) &&
+           IC_RESULT (sic)->key == IC_RIGHT (dic)->key)
+         return NULL;
+    }
+
+  return dic;
+}
+
+/*-----------------------------------------------------------------*/
+/* reassignAliasedSym - used by packRegsForSupport to replace      */
+/*                      redundant iTemp with equivalent symbol     */
+/*-----------------------------------------------------------------*/
+static void
+reassignAliasedSym (eBBlock *ebp, iCode *assignment, iCode *use, operand *op)
+{
+  iCode *ic;
+  unsigned oldSymKey, newSymKey;
+
+  oldSymKey = op->key;
+  newSymKey = IC_RIGHT(assignment)->key;
+
+  /* only track live ranges of compiler-generated temporaries */
+  if (!IS_ITEMP(IC_RIGHT(assignment)))
+    newSymKey = 0;
+
+  /* update the live-value bitmaps */
+  for (ic = assignment; ic != use; ic = ic->next) {
+    bitVectUnSetBit (ic->rlive, oldSymKey);
+    if (newSymKey != 0)
+      ic->rlive = bitVectSetBit (ic->rlive, newSymKey);
+  }
+
+  /* update the sym of the used operand */
+  OP_SYMBOL(op) = OP_SYMBOL(IC_RIGHT(assignment));
+  op->key = OP_SYMBOL(op)->key;
+
+  /* update the sym's liverange */
+  if ( OP_LIVETO(op) < ic->seq )
+    setToRange(op, ic->seq, FALSE);
+
+  /* remove the assignment iCode now that its result is unused */
+  remiCodeFromeBBlock (ebp, assignment);
+  bitVectUnSetBit(OP_SYMBOL(IC_RESULT(assignment))->defs, assignment->key);
+  hTabDeleteItem (&iCodehTab, assignment->key, assignment, DELETE_ITEM, NULL);
+}
+  
+
+/*-----------------------------------------------------------------*/
+/* packRegsForSupport :- reduce some registers for support calls   */
+/*-----------------------------------------------------------------*/
+static int
+packRegsForSupport (iCode * ic, eBBlock * ebp)
+{
+  iCode *dic;
+  
+  /* for the left & right operand :- look to see if the
+     left was assigned a true symbol in far space in that
+     case replace them */
+
+  if (IS_ITEMP (IC_LEFT (ic)) &&
+      OP_SYMBOL (IC_LEFT (ic))->liveTo <= ic->seq)
+    {
+      dic = findAssignToSym (IC_LEFT (ic), ic);
+
+      if (dic)
+       {
+         /* found it we need to remove it from the block */
+         reassignAliasedSym (ebp, dic, ic, IC_LEFT(ic));
+         return 1;
+       }
+    }
+
+  /* do the same for the right operand */
+  if (IS_ITEMP (IC_RIGHT (ic)) &&
+      OP_SYMBOL (IC_RIGHT (ic))->liveTo <= ic->seq)
+    {
+      iCode *dic = findAssignToSym (IC_RIGHT (ic), ic);
+
+      if (dic)
+       {
+         /* if this is a subtraction & the result
+            is a true symbol in far space then don't pack */
+#if 0
+         if (ic->op == '-' && IS_TRUE_SYMOP (IC_RESULT (dic)))
+           {
+             sym_link *etype = getSpec (operandType (IC_RESULT (dic)));
+             if (IN_FARSPACE (SPEC_OCLS (etype)))
+               return 0;
+           }
+#endif
+         /* found it we need to remove it from the
+            block */
+         reassignAliasedSym (ebp, dic, ic, IC_RIGHT(ic));
+         
+         return 1;
+       }
+    }
+
+  return 0;
+}
+
+#define IS_OP_RUONLY(x) (x && IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
+
+
+/*-----------------------------------------------------------------*/
+/* packRegsForOneuse : - will reduce some registers for single Use */
+/*-----------------------------------------------------------------*/
+static iCode *
+packRegsForOneuse (iCode * ic, operand * op, eBBlock * ebp)
+{
+  bitVect *uses;
+  iCode *dic, *sic;
+
+  /* if returning a literal then do nothing */
+  if (!IS_SYMOP (op))
+    return NULL;
+
+  /* only upto 2 bytes since we cannot predict
+     the usage of b, & acc */
+  if (getSize (operandType (op)) > (fReturnSizeHC08 - 2))
+    return NULL;
+
+  return NULL;
+  
+  if (ic->op != SEND //RETURN
+      && ic->op != SEND
+      && !POINTER_SET (ic)
+      && !POINTER_GET (ic) )
+    return NULL;
+  
+  if (ic->op == SEND && ic->argreg != 1) return NULL;
+
+  /* this routine will mark the a symbol as used in one 
+     instruction use only && if the defintion is local 
+     (ie. within the basic block) && has only one definition &&
+     that definiion is either a return value from a 
+     function or does not contain any variables in
+     far space */
+  uses = bitVectCopy (OP_USES (op));
+  bitVectUnSetBit (uses, ic->key);     /* take away this iCode */
+  if (!bitVectIsZero (uses))   /* has other uses */
+    return NULL;
+
+  /* if it has only one defintion */
+  if (bitVectnBitsOn (OP_DEFS (op)) > 1)
+    return NULL;               /* has more than one definition */
+
+  /* get that definition */
+  if (!(dic =
+       hTabItemWithKey (iCodehTab,
+                        bitVectFirstBit (OP_DEFS (op)))))
+    return NULL;
+
+  /* if that only usage is a cast */
+  if (dic->op == CAST) {
+    /* to a bigger type */
+    if (getSize(OP_SYM_TYPE(IC_RESULT(dic))) > 
+       getSize(OP_SYM_TYPE(IC_RIGHT(dic)))) {
+      /* than we can not, since we cannot predict the usage of b & acc */
+      return NULL;
+    }
+  }
+
+  /* found the definition now check if it is local */
+  if (dic->seq < ebp->fSeq ||
+      dic->seq > ebp->lSeq)
+    return NULL;               /* non-local */
+
+  /* now check if it is the return from
+     a function call */
+  if (dic->op == CALL || dic->op == PCALL)
+    {
+      if (ic->op != SEND && ic->op != RETURN &&
+         !POINTER_SET(ic) && !POINTER_GET(ic))
+       {
+         OP_SYMBOL (op)->ruonly = 1;
+         return dic;
+       }
+      dic = dic->next;
+    }
+
+
+  /* otherwise check that the definition does
+     not contain any symbols in far space */
+//  if (isOperandInFarSpace (IC_LEFT (dic)) ||
+//      isOperandInFarSpace (IC_RIGHT (dic)) ||
+//      IS_OP_RUONLY (IC_LEFT (ic)) ||
+//      IS_OP_RUONLY (IC_RIGHT (ic)))
+//    {
+//      return NULL;
+//    }
+
+  /* if pointer set then make sure the pointer
+     is one byte */
+#if 0
+  if (POINTER_SET (dic) &&
+      !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
+    return NULL;
+
+  if (POINTER_GET (dic) &&
+      !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
+    return NULL;
+#endif 
+
+  sic = dic;
+
+  /* also make sure the intervenening instructions
+     don't have any thing in far space */
+  for (dic = dic->next; dic && dic != ic && sic != ic; dic = dic->next)
+    {
+
+      /* if there is an intervening function call then no */
+      if (dic->op == CALL || dic->op == PCALL)
+       return NULL;
+      /* if pointer set then make sure the pointer
+         is one byte */
+#if 0
+      if (POINTER_SET (dic) &&
+         !IS_DATA_PTR (aggrToPtr (operandType (IC_RESULT (dic)), FALSE)))
+       return NULL;
+
+      if (POINTER_GET (dic) &&
+         !IS_DATA_PTR (aggrToPtr (operandType (IC_LEFT (dic)), FALSE)))
+       return NULL;
+#endif
+      /* if address of & the result is remat the okay */
+      if (dic->op == ADDRESS_OF &&
+         OP_SYMBOL (IC_RESULT (dic))->remat)
+       continue;
+
+      /* if operand has size of three or more & this
+         operation is a '*','/' or '%' then 'b' may
+         cause a problem */
+#if 0
+      if ((dic->op == '%' || dic->op == '/' || dic->op == '*') &&
+         getSize (operandType (op)) >= 3)
+       return NULL;
+#endif
+
+      /* if left or right or result is in far space */
+//      if (isOperandInFarSpace (IC_LEFT (dic)) ||
+//       isOperandInFarSpace (IC_RIGHT (dic)) ||
+//       isOperandInFarSpace (IC_RESULT (dic)) ||
+//       IS_OP_RUONLY (IC_LEFT (dic)) ||
+//       IS_OP_RUONLY (IC_RIGHT (dic)) ||
+//       IS_OP_RUONLY (IC_RESULT (dic)))
+//     {
+//       return NULL;
+//     }
+//      /* if left or right or result is on stack */
+//     if (isOperandOnStack(IC_LEFT(dic)) ||
+//       isOperandOnStack(IC_RIGHT(dic)) ||
+//       isOperandOnStack(IC_RESULT(dic))) {
+//     return NULL;
+//     }
+    }
+
+  OP_SYMBOL (op)->ruonly = 1;
+  return sic;
+}
+
+/*-----------------------------------------------------------------*/
+/* isBitwiseOptimizable - requirements of JEAN LOUIS VERN          */
+/*-----------------------------------------------------------------*/
+static bool
+isBitwiseOptimizable (iCode * ic)
+{
+  sym_link *ltype = getSpec (operandType (IC_LEFT (ic)));
+  sym_link *rtype = getSpec (operandType (IC_RIGHT (ic)));
+
+  /* bitwise operations are considered optimizable
+     under the following conditions (Jean-Louis VERN) 
+
+     x & lit
+     bit & bit
+     bit & x
+     bit ^ bit
+     bit ^ x
+     x   ^ lit
+     x   | lit
+     bit | bit
+     bit | x
+  */
+  if (IS_LITERAL(rtype) ||
+      (IS_BITVAR (ltype) && IN_BITSPACE (SPEC_OCLS (ltype))))
+    return TRUE;
+  else
+    return FALSE;
+}
+
+/*-----------------------------------------------------------------*/
+/* isCommutativeOp - tests whether this op cares what order its    */
+/*                   operands are in                               */
+/*-----------------------------------------------------------------*/
+bool isCommutativeOp2(unsigned int op)
+{
+  if (op == '+' || op == '*' || op == EQ_OP ||
+      op == '^' || op == '|' || op == BITWISEAND)
+    return TRUE;
+  else
+    return FALSE;
+}
+
+/*-----------------------------------------------------------------*/
+/* operandUsesAcc2 - determines whether the code generated for this */
+/*                  operand will have to use the accumulator       */
+/*-----------------------------------------------------------------*/
+bool operandUsesAcc2(operand *op)
+{
+  if (!op)
+    return FALSE;
+
+  if (IS_SYMOP(op)) {
+    symbol *sym = OP_SYMBOL(op);
+    memmap *symspace;
+
+    if (sym->accuse)
+      return TRUE;  /* duh! */
+
+//    if (IN_STACK(sym->etype) || sym->onStack ||
+//     (SPIL_LOC(op) && SPIL_LOC(op)->onStack))
+//      return TRUE;  /* acc is used to calc stack offset */
+
+    if (IS_ITEMP(op))
+      {
+       if (SPIL_LOC(op)) {
+         sym = SPIL_LOC(op);  /* if spilled, look at spill location */
+       } else {
+         return FALSE;  /* more checks? */
+       }
+      }
+
+    symspace = SPEC_OCLS(sym->etype);
+
+//    if (sym->iaccess && symspace->paged)
+//      return TRUE;  /* must fetch paged indirect sym via accumulator */
+    
+    if (IN_BITSPACE(symspace))
+      return TRUE;  /* fetching bit vars uses the accumulator */
+    
+    if (IN_FARSPACE(symspace) || IN_CODESPACE(symspace)) 
+      return TRUE;  /* fetched via accumulator and dptr */
+  }
+
+  return FALSE;
+}
+
+/*-----------------------------------------------------------------*/
+/* packRegsForAccUse - pack registers for acc use                  */
+/*-----------------------------------------------------------------*/
+static void
+packRegsForAccUse (iCode * ic)
+{
+  iCode *uic;
+
+  /* if this is an aggregate, e.g. a one byte char array */
+  if (IS_AGGREGATE(operandType(IC_RESULT(ic)))) {
+    return;
+  }
+
+  /* if we are calling a reentrant function that has stack parameters */
+  #if 0
+  if (ic->op == CALL &&
+       IFFUNC_ISREENT(operandType(IC_LEFT(ic))) &&
+       FUNC_HASSTACKPARM(operandType(IC_LEFT(ic))))
+      return;
+
+  if (ic->op == PCALL &&
+       IFFUNC_ISREENT(operandType(IC_LEFT(ic))->next) &&
+       FUNC_HASSTACKPARM(operandType(IC_LEFT(ic))->next))
+      return;
+  #endif
+
+  /* if + or - then it has to be one byte result */
+  if ((ic->op == '+' || ic->op == '-')
+      && getSize (operandType (IC_RESULT (ic))) > 1)
+    return;
+
+
+  /* if shift operation make sure right side is a literal */
+  if (ic->op == RIGHT_OP &&
+      (!isOperandLiteral (IC_RIGHT (ic)) ||
+       (getSize (operandType (IC_RESULT (ic) )) > 1)))
+    return;
+
+  if (ic->op == LEFT_OP &&
+      (!isOperandLiteral (IC_RIGHT (ic)) ||
+       (getSize (operandType (IC_RESULT (ic) )) > 1)))
+    return;
+
+  if (IS_BITWISE_OP (ic) &&
+      getSize (operandType (IC_RESULT (ic))) > 1)
+    return;
+
+
+  /* has only one definition */
+  if (bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) > 1)
+    return;
+
+  /* has only one use */
+  if (bitVectnBitsOn (OP_USES (IC_RESULT (ic))) > 1)
+    return;
+
+  /* and the usage immediately follows this iCode */
+  if (!(uic = hTabItemWithKey (iCodehTab,
+                              bitVectFirstBit (OP_USES (IC_RESULT (ic))))))
+    return;
+
+  if (ic->next != uic)
+    return;
+
+  /* if it is a conditional branch then we definitely can */
+  if (uic->op == IFX)
+    goto accuse;
+
+  if (uic->op == JUMPTABLE)
+    return;
+
+#if 0
+  if (POINTER_SET (uic) &&
+      getSize (aggrToPtr (operandType (IC_RESULT (uic)), FALSE)) > 1)
+    return;
+#endif
+
+  /* if the usage is not is an assignment
+     or an arithmetic / bitwise / shift operation then not */
+  if (uic->op != '=' &&
+      !IS_ARITHMETIC_OP (uic) &&
+      !IS_BITWISE_OP (uic) &&
+      (uic->op != LEFT_OP) &&
+      (uic->op != RIGHT_OP) &&
+      (uic->op != GETHBIT))
+    return;
+
+#if 0
+  /* if used in ^ operation then make sure right is not a 
+     literal (WIML: Why is this?) */
+  if (uic->op == '^' && isOperandLiteral (IC_RIGHT (uic)))
+    return;
+
+  /* if shift operation make sure right side is not a literal */
+  /* WIML: Why is this? */
+  if (uic->op == RIGHT_OP &&
+      (isOperandLiteral (IC_RIGHT (uic)) ||
+       getSize (operandType (IC_RESULT (uic))) > 1))
+    return;
+  if (uic->op == LEFT_OP &&
+      (isOperandLiteral (IC_RIGHT (uic)) ||
+       getSize (operandType (IC_RESULT (uic))) > 1))
+    return;
+#endif
+
+  /* make sure that the result of this icode is not on the
+     stack, since acc is used to compute stack offset */
+#if 0
+  if (IS_TRUE_SYMOP (IC_RESULT (uic)) &&
+      OP_SYMBOL (IC_RESULT (uic))->onStack)
+    return;
+#else
+//  if (isOperandOnStack(IC_RESULT(uic)))
+//    return;
+#endif
+
+  /* if the usage has only one operand then we can */
+  if (IC_LEFT (uic) == NULL ||
+      IC_RIGHT (uic) == NULL)
+    goto accuse;
+
+#if 0
+  /* if the other operand uses the accumulator then we cannot */
+  if ( (IC_LEFT(uic)->key == IC_RESULT(ic)->key &&
+       operandUsesAcc2(IC_RIGHT(uic))) ||
+       (IC_RIGHT(uic)->key == IC_RESULT(ic)->key &&
+       operandUsesAcc2(IC_LEFT(uic))) ) 
+    return;
+
+  /* make sure this is on the left side if not commutative */
+  /* except for '-', which has been written to be able to
+     handle reversed operands */
+  if (!(isCommutativeOp2(ic->op) || ic->op == '-') &&
+       IC_LEFT (uic)->key != IC_RESULT (ic)->key)
+    return;
+#endif
+
+#if 0
+  // this is too dangerous and need further restrictions
+  // see bug #447547
+
+  /* if one of them is a literal then we can */
+  if ((IC_LEFT (uic) && IS_OP_LITERAL (IC_LEFT (uic))) ||
+      (IC_RIGHT (uic) && IS_OP_LITERAL (IC_RIGHT (uic))))
+    {
+      OP_SYMBOL (IC_RESULT (ic))->accuse = 1;
+      return;
+    }
+#endif
+
+accuse:
+
+  if ((POINTER_GET(uic))
+      || (ic->op == ADDRESS_OF && uic->op == '+' && IS_OP_LITERAL (IC_RIGHT (uic))))
+    {
+      OP_SYMBOL (IC_RESULT (ic))->accuse = ACCUSE_HX;
+      return;
+    }
+  
+  OP_SYMBOL (IC_RESULT (ic))->accuse = ACCUSE_XA;
+}
+
+/*-----------------------------------------------------------------*/
+/* packForPush - hueristics to reduce iCode for pushing            */
+/*-----------------------------------------------------------------*/
+static void
+packForPush (iCode * ic, eBBlock ** ebpp, int blockno)
+{
+  iCode *dic, *lic;
+  bitVect *dbv;
+  struct eBBlock * ebp=ebpp[blockno];
+
+  if (ic->op != IPUSH || !IS_ITEMP (IC_LEFT (ic)))
+    return;
+
+  /* must have only definition & one usage */
+  if (bitVectnBitsOn (OP_DEFS (IC_LEFT (ic))) != 1 ||
+      bitVectnBitsOn (OP_USES (IC_LEFT (ic))) != 1)
+    return;
+
+  /* find the definition */
+  if (!(dic = hTabItemWithKey (iCodehTab,
+                              bitVectFirstBit (OP_DEFS (IC_LEFT (ic))))))
+    return;
+
+  if (dic->op != '=' || POINTER_SET (dic))
+    return;
+
+  if (dic->seq < ebp->fSeq) { // Evelyn did this
+    int i;
+    for (i=0; i<blockno; i++) {
+      if (dic->seq >= ebpp[i]->fSeq && dic->seq <= ebpp[i]->lSeq) {
+       ebp=ebpp[i];
+       break;
+      }
+    }
+    wassert (i!=blockno); // no way to recover from here
+  }
+
+  if (IS_SYMOP(IC_RIGHT(dic))) {
+    /* make sure the right side does not have any definitions
+       inbetween */
+    dbv = OP_DEFS(IC_RIGHT(dic));
+    for (lic = ic; lic && lic != dic ; lic = lic->prev) {
+      if (bitVectBitValue(dbv,lic->key)) 
+       return ;
+    }
+    /* make sure they have the same type */
+    if (IS_SPEC(operandType(IC_LEFT(ic))))
+    {
+      sym_link *itype=operandType(IC_LEFT(ic));
+      sym_link *ditype=operandType(IC_RIGHT(dic));
+      
+      if (SPEC_USIGN(itype)!=SPEC_USIGN(ditype) ||
+         SPEC_LONG(itype)!=SPEC_LONG(ditype))
+       return;
+    }
+    /* extend the live range of replaced operand if needed */
+    if (OP_SYMBOL(IC_RIGHT(dic))->liveTo < ic->seq) {
+      OP_SYMBOL(IC_RIGHT(dic))->liveTo = ic->seq;
+    }
+    bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+  } 
+
+  /* we now we know that it has one & only one def & use
+     and the that the definition is an assignment */
+  ReplaceOpWithCheaperOp(&IC_LEFT (ic), IC_RIGHT (dic));
+  remiCodeFromeBBlock (ebp, dic);
+  hTabDeleteItem (&iCodehTab, dic->key, dic, DELETE_ITEM, NULL);
+}
+
+/*-----------------------------------------------------------------*/
+/* packRegisters - does some transformations to reduce register    */
+/*                   pressure                                      */
+/*-----------------------------------------------------------------*/
+static void
+packRegisters (eBBlock ** ebpp, int blockno)
+{
+  iCode *ic;
+  int change = 0;
+  eBBlock *ebp=ebpp[blockno];
+
+  while (1)
+    {
+
+      change = 0;
+
+      /* look for assignments of the form */
+      /* iTempNN = TRueSym (someoperation) SomeOperand */
+      /*       ....                       */
+      /* TrueSym := iTempNN:1             */
+      for (ic = ebp->sch; ic; ic = ic->next)
+       {
+         /* find assignment of the form TrueSym := iTempNN:1 */
+         if (ic->op == '=' && !POINTER_SET (ic) )
+           change += packRegsForAssign (ic, ebp);
+       }
+
+      if (!change)
+       break;
+    }
+
+  for (ic = ebp->sch; ic; ic = ic->next)
+    {
+      /* if this is an itemp & result of an address of a true sym 
+         then mark this as rematerialisable   */
+      if (ic->op == ADDRESS_OF &&
+         IS_ITEMP (IC_RESULT (ic)) &&
+         IS_TRUE_SYMOP (IC_LEFT (ic)) &&
+         bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1 &&
+         !OP_SYMBOL (IC_LEFT (ic))->onStack )
+       {
+
+         OP_SYMBOL (IC_RESULT (ic))->remat = 1;
+         OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
+         OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
+
+       }
+
+      /* if straight assignment then carry remat flag if
+         this is the only definition */
+      if (ic->op == '=' &&
+         !POINTER_SET (ic) &&
+         IS_SYMOP (IC_RIGHT (ic)) &&
+         OP_SYMBOL (IC_RIGHT (ic))->remat &&
+         !IS_CAST_ICODE(OP_SYMBOL (IC_RIGHT (ic))->rematiCode) &&
+         bitVectnBitsOn (OP_SYMBOL (IC_RESULT (ic))->defs) <= 1)
+       {
+
+         OP_SYMBOL (IC_RESULT (ic))->remat =
+           OP_SYMBOL (IC_RIGHT (ic))->remat;
+         OP_SYMBOL (IC_RESULT (ic))->rematiCode =
+           OP_SYMBOL (IC_RIGHT (ic))->rematiCode;
+       }
+
+      /* if cast to a generic pointer & the pointer being
+        cast is remat, then we can remat this cast as well */
+      if (ic->op == CAST && 
+         IS_SYMOP(IC_RIGHT(ic)) &&
+         OP_SYMBOL(IC_RIGHT(ic))->remat &&
+         bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1) {
+             sym_link *to_type = operandType(IC_LEFT(ic));
+             sym_link *from_type = operandType(IC_RIGHT(ic));
+             if (IS_GENPTR(to_type) && IS_PTR(from_type)) {                  
+                     OP_SYMBOL (IC_RESULT (ic))->remat = 1;
+                     OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
+                     OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
+             }
+      }
+
+      /* if this is a +/- operation with a rematerizable 
+         then mark this as rematerializable as well */
+      if ((ic->op == '+' || ic->op == '-') &&
+         (IS_SYMOP (IC_LEFT (ic)) &&
+          IS_ITEMP (IC_RESULT (ic)) &&
+          IS_OP_LITERAL (IC_RIGHT (ic))) &&
+          OP_SYMBOL (IC_LEFT (ic))->remat &&
+         (!IS_SYMOP (IC_RIGHT (ic)) || !IS_CAST_ICODE(OP_SYMBOL (IC_RIGHT (ic))->rematiCode)) &&
+          bitVectnBitsOn (OP_DEFS (IC_RESULT (ic))) == 1)
+       {
+         OP_SYMBOL (IC_RESULT (ic))->remat = 1;
+         OP_SYMBOL (IC_RESULT (ic))->rematiCode = ic;
+         OP_SYMBOL (IC_RESULT (ic))->usl.spillLoc = NULL;
+       }
+
+      /* mark the pointer usages */
+      if (POINTER_SET (ic))
+       OP_SYMBOL (IC_RESULT (ic))->uptr = 1;
+
+      if (POINTER_GET (ic) &&
+         IS_SYMOP(IC_LEFT (ic)))
+       OP_SYMBOL (IC_LEFT (ic))->uptr = 1;
+
+      if (!SKIP_IC2 (ic))
+       {
+#if 0
+         /* if we are using a symbol on the stack
+            then we should say hc08_ptrRegReq */
+         if (ic->op == IFX && IS_SYMOP (IC_COND (ic)))
+           hc08_ptrRegReq += ((OP_SYMBOL (IC_COND (ic))->onStack ||
+                                OP_SYMBOL (IC_COND (ic))->iaccess) ? 1 : 0);
+         else if (ic->op == JUMPTABLE && IS_SYMOP (IC_JTCOND (ic)))
+           hc08_ptrRegReq += ((OP_SYMBOL (IC_JTCOND (ic))->onStack ||
+                             OP_SYMBOL (IC_JTCOND (ic))->iaccess) ? 1 : 0);
+         else
+           {
+             if (IS_SYMOP (IC_LEFT (ic)))
+               hc08_ptrRegReq += ((OP_SYMBOL (IC_LEFT (ic))->onStack ||
+                               OP_SYMBOL (IC_LEFT (ic))->iaccess) ? 1 : 0);
+             if (IS_SYMOP (IC_RIGHT (ic)))
+               hc08_ptrRegReq += ((OP_SYMBOL (IC_RIGHT (ic))->onStack ||
+                              OP_SYMBOL (IC_RIGHT (ic))->iaccess) ? 1 : 0);
+             if (IS_SYMOP (IC_RESULT (ic)))
+               hc08_ptrRegReq += ((OP_SYMBOL (IC_RESULT (ic))->onStack ||
+                             OP_SYMBOL (IC_RESULT (ic))->iaccess) ? 1 : 0);
+           }
+#endif
+       }
+
+      /* if the condition of an if instruction
+         is defined in the previous instruction and
+        this is the only usage then
+         mark the itemp as a conditional */
+      if ((IS_CONDITIONAL (ic) ||
+          (IS_BITWISE_OP(ic) && isBitwiseOptimizable (ic))) &&
+         ic->next && ic->next->op == IFX &&
+         bitVectnBitsOn (OP_USES(IC_RESULT(ic)))==1 &&
+         isOperandEqual (IC_RESULT (ic), IC_COND (ic->next)) &&
+         OP_SYMBOL (IC_RESULT (ic))->liveTo <= ic->next->seq)
+       {
+         OP_SYMBOL (IC_RESULT (ic))->regType = REG_CND;
+         continue;
+       }
+
+      /* reduce for support function calls */
+      if (ic->supportRtn || ic->op == '+' || ic->op == '-')
+       packRegsForSupport (ic, ebp);
+
+      #if 0
+      /* some cases the redundant moves can
+         can be eliminated for return statements */
+      if ((ic->op == RETURN || (ic->op == SEND && ic->argreg == 1)) &&
+         /* !isOperandInFarSpace (IC_LEFT (ic)) && */
+         options.model == MODEL_SMALL) {
+       packRegsForOneuse (ic, IC_LEFT (ic), ebp);
+      }
+
+      /* if pointer set & left has a size more than
+         one and right is not in far space */
+      if (POINTER_SET (ic) &&
+         /* !isOperandInFarSpace (IC_RIGHT (ic)) && */
+         !OP_SYMBOL (IC_RESULT (ic))->remat &&
+         !IS_OP_RUONLY (IC_RIGHT (ic)) 
+         /* && getSize (aggrToPtr (operandType (IC_RESULT (ic)), FALSE)) > 1 */ )
+       packRegsForOneuse (ic, IC_RESULT (ic), ebp);
+
+      /* if pointer get */
+      if (POINTER_GET (ic) &&
+         IS_SYMOP (IC_LEFT (ic)) &&
+         /* !isOperandInFarSpace (IC_RESULT (ic)) && */
+         !OP_SYMBOL (IC_LEFT (ic))->remat &&
+         !IS_OP_RUONLY (IC_RESULT (ic)) 
+          /* && getSize (aggrToPtr (operandType (IC_LEFT (ic)), FALSE)) > 1 */)
+       packRegsForOneuse (ic, IC_LEFT (ic), ebp);
+
+
+      /* if this is cast for intergral promotion then
+         check if only use of  the definition of the 
+         operand being casted/ if yes then replace
+         the result of that arithmetic operation with 
+         this result and get rid of the cast */
+      if (ic->op == CAST)
+       {
+         sym_link *fromType = operandType (IC_RIGHT (ic));
+         sym_link *toType = operandType (IC_LEFT (ic));
+
+         if (IS_INTEGRAL (fromType) && IS_INTEGRAL (toType) &&
+             getSize (fromType) != getSize (toType) &&
+             SPEC_USIGN (fromType) == SPEC_USIGN (toType))
+           {
+
+             iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
+             if (dic)
+               {
+                 if (IS_ARITHMETIC_OP (dic))
+                   {                  
+                     bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+                     ReplaceOpWithCheaperOp(&IC_RESULT (dic), IC_RESULT (ic));
+                     remiCodeFromeBBlock (ebp, ic);
+                     bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
+                     hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
+                     OP_DEFS(IC_RESULT (dic))=bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
+                     ic = ic->prev;
+                   }
+                 else
+                   OP_SYMBOL (IC_RIGHT (ic))->ruonly = 0;
+               }
+           }
+         else
+           {
+
+             /* if the type from and type to are the same
+                then if this is the only use then packit */
+             if (compareType (operandType (IC_RIGHT (ic)),
+                            operandType (IC_LEFT (ic))) == 1)
+               {
+                 iCode *dic = packRegsForOneuse (ic, IC_RIGHT (ic), ebp);
+                 if (dic)
+                   {
+                     bitVectUnSetBit(OP_SYMBOL(IC_RESULT(dic))->defs,dic->key);
+                     ReplaceOpWithCheaperOp(&IC_RESULT (dic), IC_RESULT (ic));
+                     remiCodeFromeBBlock (ebp, ic);
+                     bitVectUnSetBit(OP_SYMBOL(IC_RESULT(ic))->defs,ic->key);
+                     hTabDeleteItem (&iCodehTab, ic->key, ic, DELETE_ITEM, NULL);
+                     OP_DEFS(IC_RESULT (dic))=bitVectSetBit (OP_DEFS (IC_RESULT (dic)), dic->key);
+                     ic = ic->prev;
+                   }
+               }
+           }
+       }
+      #endif
+      
+      /* pack for PUSH 
+         iTempNN := (some variable in farspace) V1
+         push iTempNN ;
+         -------------
+         push V1
+       */
+      if (ic->op == IPUSH)
+       {
+         packForPush (ic, ebpp, blockno);
+       }
+
+
+      #if 0
+      /* pack registers for accumulator use, when the
+         result of an arithmetic or bit wise operation
+         has only one use, that use is immediately following
+         the defintion and the using iCode has only one
+         operand or has two operands but one is literal &
+         the result of that operation is not on stack then
+         we can leave the result of this operation in acc:b
+         combination */
+      if ((IS_ARITHMETIC_OP (ic)
+          || IS_CONDITIONAL(ic)
+          || IS_BITWISE_OP (ic)
+          || ic->op == '='
+          || ic->op == GETHBIT
+          || ic->op == LEFT_OP || ic->op == RIGHT_OP || ic->op == CALL
+          || (ic->op == ADDRESS_OF && isOperandOnStack (IC_LEFT (ic)))
+         ) &&
+         IS_ITEMP (IC_RESULT (ic)) &&
+         getSize (operandType (IC_RESULT (ic))) <= 2)
+
+       packRegsForAccUse (ic);
+      #endif
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* assignRegisters - assigns registers to each live range as need  */
+/*-----------------------------------------------------------------*/
+void
+hc08_assignRegisters (eBBlock ** ebbs, int count)
+{
+  iCode *ic;
+  int i;
+
+  setToNull ((void *) &_G.funcrUsed);
+  setToNull ((void *) &_G.regAssigned);
+  setToNull ((void *) &_G.totRegAssigned);
+  hc08_ptrRegReq = _G.stackExtend = _G.dataExtend = 0;
+  hc08_nRegs = 5;
+  hc08_reg_a = hc08_regWithIdx(A_IDX);
+  hc08_reg_x = hc08_regWithIdx(X_IDX);
+  hc08_reg_h = hc08_regWithIdx(H_IDX);
+  hc08_reg_hx = hc08_regWithIdx(HX_IDX);
+  hc08_reg_xa = hc08_regWithIdx(XA_IDX);
+
+  /* change assignments this will remove some
+     live ranges reducing some register pressure */
+  for (i = 0; i < count; i++)
+    packRegisters (ebbs, i);
+
+  if (options.dump_pack)
+    dumpEbbsToFileExt (DUMP_PACK, ebbs, count);
+
+  /* first determine for each live range the number of 
+     registers & the type of registers required for each */
+  regTypeNum (*ebbs);
+
+  /* and serially allocate registers */
+  serialRegAssign (ebbs, count);
+
+  freeAllRegs ();
+  //setToNull ((void *) &_G.regAssigned);
+  //setToNull ((void *) &_G.totRegAssigned);
+  fillGaps();
+
+  /* if stack was extended then tell the user */
+  if (_G.stackExtend)
+    {
+/*      werror(W_TOOMANY_SPILS,"stack", */
+/*             _G.stackExtend,currFunc->name,""); */
+      _G.stackExtend = 0;
+    }
+
+  if (_G.dataExtend)
+    {
+/*      werror(W_TOOMANY_SPILS,"data space", */
+/*             _G.dataExtend,currFunc->name,""); */
+      _G.dataExtend = 0;
+    }
+
+  /* after that create the register mask
+     for each of the instruction */
+  createRegMask (ebbs, count);
+
+  /* redo that offsets for stacked automatic variables */
+  if (currFunc) {
+    redoStackOffsets ();
+  }
+
+  if (options.dump_rassgn)
+    {
+      dumpEbbsToFileExt (DUMP_RASSGN, ebbs, count);
+      dumpLiveRanges (DUMP_LRANGE, liveRanges);
+    }
+
+  /* do the overlaysegment stuff SDCCmem.c */
+  doOverlays (ebbs, count);
+
+  /* now get back the chain */
+  ic = iCodeLabelOptimize (iCodeFromeBBlock (ebbs, count));
+
+  genhc08Code (ic);
+
+  /* free up any _G.stackSpil locations allocated */
+  applyToSet (_G.stackSpil, deallocStackSpil);
+  _G.slocNum = 0;
+  setToNull ((void **) &_G.stackSpil);
+  setToNull ((void **) &_G.spiltSet);
+  /* mark all registers as free */
+  freeAllRegs ();
+
+  return;
+}
diff --git a/src/hc08/ralloc.h b/src/hc08/ralloc.h
new file mode 100644 (file)
index 0000000..878c9aa
--- /dev/null
@@ -0,0 +1,73 @@
+/*-------------------------------------------------------------------------
+
+  SDCCralloc.h - header file register allocation
+
+                Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
+
+   This program is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by the
+   Free Software Foundation; either version 2, or (at your option) any
+   later version.
+   
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+   
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+   
+   In other words, you are welcome to use, share and improve this program.
+   You are forbidden to forbid anyone else to use, share and improve
+   what you give them.   Help stamp out software-hoarding!  
+-------------------------------------------------------------------------*/
+#include "SDCCicode.h"
+#include "SDCCBBlock.h"
+#ifndef SDCCRALLOC_H
+#define SDCCRALLOC_H 1
+
+enum
+  {
+    A_IDX,
+    H_IDX,
+    X_IDX,
+    HX_IDX,
+    XA_IDX,
+    CND_IDX
+  };
+
+
+#define REG_PTR 0x01
+#define REG_GPR 0x02
+#define REG_CND 0x04
+/* definition for the registers */
+typedef struct regs
+  {
+    short type;                        /* can have value 
+                                  REG_GPR, REG_PTR or REG_CND */
+    short rIdx;                        /* index into register table */
+    short otype;
+    char *name;                        /* name */
+    char *dname;               /* name when direct access needed */
+    char *base;                        /* base address */
+    short mask;                        /* bitmask for pair allocation */
+    struct asmop *aop;         /* last operand */
+    int aopofs;                        /* last operand offset */
+    unsigned isFree:1;         /* is currently unassigned  */
+  }
+regs;
+extern regs regshc08[];
+extern regs *hc08_reg_a;
+extern regs *hc08_reg_x;
+extern regs *hc08_reg_h;
+extern regs *hc08_reg_hx;
+extern regs *hc08_reg_xa;
+
+regs *hc08_regWithIdx (int);
+void hc08_useReg (regs * reg);
+void hc08_freeReg (regs * reg);
+void hc08_dirtyReg (regs * reg, bool freereg);
+bitVect *hc08_rUmaskForOp (operand * op);
+
+#endif