Added z80 port (links, may not work). mcs51 still works.
authormichaelh <michaelh@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Mon, 17 Jan 2000 06:04:16 +0000 (06:04 +0000)
committermichaelh <michaelh@4a8a32a2-be11-0410-ad9d-d568d2c75423>
Mon, 17 Jan 2000 06:04:16 +0000 (06:04 +0000)
git-svn-id: https://sdcc.svn.sourceforge.net/svnroot/sdcc/trunk/sdcc@11 4a8a32a2-be11-0410-ad9d-d568d2c75423

21 files changed:
Makefile
clean.mk
src/SDCCglobl.h
src/mcs51/Makefile
src/mcs51/main.c [new file with mode: 0644]
src/mcs51/main.h [new file with mode: 0644]
src/z80/Makefile [new file with mode: 0644]
src/z80/gen.c [new file with mode: 0644]
src/z80/gen.h [new file with mode: 0644]
src/z80/global.h [new file with mode: 0644]
src/z80/glue.c [new file with mode: 0644]
src/z80/glue.h [new file with mode: 0644]
src/z80/icode.c [new file with mode: 0644]
src/z80/main.c [new file with mode: 0644]
src/z80/main.h [new file with mode: 0644]
src/z80/mem.c [new file with mode: 0644]
src/z80/mem.h [new file with mode: 0644]
src/z80/memmaps.h [new file with mode: 0644]
src/z80/port.h [new file with mode: 0644]
src/z80/ralloc.c [new file with mode: 0644]
src/z80/ralloc.h [new file with mode: 0644]

index 4c8a097626ffd373c468411e7e805d903dc69585..fee44c8191fc0ba7b5d4c130f323d79e769da740 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -43,9 +43,7 @@ uninstall:
 # --------------------------------------------------
 clean:
        $(MAKE) -f clean.mk clean
-       @for pkg in $(PKGS); do\
-         cd $$pkg && $(MAKE) -f clean.mk clean; cd ..;\
-       done
+       for pkg in $(PKGS); do $(MAKE) -C $$pkg clean; done
        @for prj in $(PRJS); do\
          cd $$prj && $(MAKE) clean; cd ..;\
        done
index 154ae72da2b933bd28e042c32a800d5da4962a60..0eba397eb0010f2fdca5b3b5584ae9081e889a79 100644 (file)
--- a/clean.mk
+++ b/clean.mk
@@ -3,7 +3,7 @@
 clean:
        rm -f *core *[%~] *.[oa]
        rm -f .[a-z]*~
-       rm -f bin/*
+       -rm -f bin/*
 
 
 # Deleting all files created by configuring or building the program
index 62068c3ec3925eb1f7fb5724a00a0e2fe3609e42..c4e9c977f914947ce581f1498a1e76c3c1c5b9fa 100644 (file)
@@ -5,6 +5,7 @@
 #include <assert.h>
 #include <stdlib.h>
 #include <setjmp.h>
+#include <stdio.h>
 #include "sdccconf.h"
 #include "SDCCerr.h"
 
@@ -203,6 +204,60 @@ struct options {
     int iram_size      ; /* internal ram size (used only for error checking) */
 } ;
 
+/* Processor specific names */
+typedef struct {
+    /** Target name string, used for --help */
+    const char *target_name;
+    struct {
+       /** Command to run (eg as-z80) */
+       const char *exec_name;
+       /** Arguments for debug mode */
+       const char *debug_opts;
+       /** Arguments for normal assembly mode */
+       const char *plain_opts;
+       /** TRUE if the output file name should be pre-pended to the args */
+       bool requires_output_name;
+    } assembler;
+    struct {
+       /** Command to run (eg link-z80) */
+       const char *exec_name;
+    } linker;
+    /** Basic type sizes */
+    struct {
+       int char_size;
+       int short_size;
+       int int_size;
+       int long_size;
+       int ptr_size;
+       int fptr_size;
+       int gptr_size;
+       int bit_size;
+       int float_size;
+       int max_base_size;
+    } s;
+    struct {
+       /** -1 for grows down (z80), +1 for grows up (mcs51) */
+       int direction;
+       /** Extra overhead when calling between banks */
+       int bank_overhead;
+       /** Extra overhead when the function is an ISR */
+       int isr_overhead;
+       /** Standard overhead for a function call */
+       int call_overhead;
+       /** Initial SP offset */
+       int start_sp;
+    } stack;
+    struct {
+       /** One more than the smallest mul/div operation the processor can do nativley 
+           Eg if the processor has an 8 bit mul, nativebelow is 2 */
+       int nativebelow;
+       
+    } muldiv;
+
+} PROCESSOR_CONSTANTS;
+
+extern const PROCESSOR_CONSTANTS port;
+
 /* forward definition for variables accessed globally */
 extern char *currFname ;
 extern char *srcFileName; /* source file name without the extenstion */
index ccf2b5b7ffb6033dc7c156f30bc248287f6642a5..b8f9ab40b42097f1739a07c638f8763900791149 100644 (file)
@@ -2,7 +2,7 @@ PRJDIR = ../..
 
 include $(PRJDIR)/Makefile.common
 
-OBJ = gen.o ralloc.o
+OBJ = gen.o ralloc.o main.o
 LIB = port.a
 
 CFLAGS = -ggdb -Wall
diff --git a/src/mcs51/main.c b/src/mcs51/main.c
new file mode 100644 (file)
index 0000000..dfba234
--- /dev/null
@@ -0,0 +1,28 @@
+#include "SDCCglobl.h"
+#include "main.h"
+
+/* Globals */
+PROCESSOR_CONSTANTS port = {
+    "MCU 8051",                        /* Target name */
+    {  
+       "asx8051",              /* Assembler executable name */
+       "-plosgffc",            /* Options with debug */
+       "-plosgff",             /* Options without debug */
+       FALSE                   /* TRUE if the assembler requires an output name */
+    },
+    {
+       "aslink",               /* Linker executable name */
+    },
+    {
+       /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
+       1, 1, 2, 4, 1, 2, 3, 1, 4, 4
+    },
+    { 
+       +1, 1, 4, 0, 0
+    },
+    /* mcs51 has an 8 bit mul */
+    {
+       1
+    }
+};
+
diff --git a/src/mcs51/main.h b/src/mcs51/main.h
new file mode 100644 (file)
index 0000000..c4d1602
--- /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/z80/Makefile b/src/z80/Makefile
new file mode 100644 (file)
index 0000000..77f51e6
--- /dev/null
@@ -0,0 +1,19 @@
+PRJDIR = ../..
+
+include $(PRJDIR)/Makefile.common
+
+OBJ = icode.o gen.o ralloc.o main.o glue.o mem.o
+LIB = port.a
+
+CFLAGS = -ggdb -Wall
+CFLAGS += -I.. -I. -I../..
+
+all: $(LIB)
+
+$(LIB): $(OBJ)
+       rm -f $(LIB)
+       ar r $(LIB) $(OBJ)
+       ranlib $(LIB)
+
+clean:
+       rm -f $(LIB) *.o *~
diff --git a/src/z80/gen.c b/src/z80/gen.c
new file mode 100644 (file)
index 0000000..41d9cdf
--- /dev/null
@@ -0,0 +1,3754 @@
+/*-------------------------------------------------------------------------
+  SDCCgen51.c - source file for code generation for 8051
+  
+  Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1998)
+         and -  Jean-Louis VERN.jlvern@writeme.com (1999)
+  
+        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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "SDCCglobl.h"
+
+#ifdef HAVE_SYS_ISA_DEFS_H
+#include <sys/isa_defs.h>
+#endif
+
+#include "SDCCast.h"
+#include "SDCCmem.h"
+#include "SDCCy.h"
+#include "SDCChasht.h"
+#include "SDCCbitv.h"
+#include "SDCCset.h"
+#include "SDCCicode.h"
+#include "SDCClabel.h"
+#include "SDCCBBlock.h"
+#include "SDCCloop.h"
+#include "SDCCcse.h"
+#include "SDCCcflow.h"
+#include "SDCCdflow.h"
+#include "SDCClrange.h"
+#include "ralloc.h"
+#include "gen.h"
+#include "SDCCpeeph.h"
+
+/* this is the down and dirty file with all kinds of kludgy & hacky
+   stuff. This is what it is all about CODE GENERATION for a specific MCU.
+   Some of the routines may be reusable, will have to see */
+
+static char *zero = "#0x00";
+static char *one  = "#0x01";
+static char *spname ;
+static char *fReturn[] = {"l", "h", "e", "d" };
+static char *accUse[] = {"a" };
+short rbank = -1;
+short accInUse = 0 ;
+short inLine = 0;
+short debugLine = 0;
+short nregssaved = 0;
+extern int ptrRegReq ;
+extern int nRegs;
+extern FILE *codeOutFile;
+set *sendSet = NULL;
+#define RESULTONSTACK(x) \
+                         (IC_RESULT(x) && IC_RESULT(x)->aop && \
+                         IC_RESULT(x)->aop->type == AOP_STK )
+
+#define MOVA(x) if (strcmp(x,"a")) emitcode("ld","a,%s",x);
+#define CLRC    emitcode("xor","a,a");
+
+#define LABEL_STR      "%05d$"
+
+lineNode *lineHead = NULL;
+lineNode *lineCurr = NULL;
+
+unsigned char   SLMask[] = {0xFF ,0xFE, 0xFC, 0xF8, 0xF0,
+0xE0, 0xC0, 0x80, 0x00};
+unsigned char   SRMask[] = {0xFF, 0x7F, 0x3F, 0x1F, 0x0F,
+0x07, 0x03, 0x01, 0x00};
+
+static int _lastStack = 0;
+
+#define LSB     0
+#define MSB16   1
+#define MSB24   2
+#define MSB32   3
+
+/* Stack frame:
+
+   IX+4                param0  LH
+   IX+2                ret     LH
+   IX+0                ix      LH
+   IX-2                temp0   LH
+*/
+
+/*-----------------------------------------------------------------*/
+/* emitcode - writes the code into a file : for now it is simple    */
+/*-----------------------------------------------------------------*/
+void emitcode (const char *inst, const char *fmt, ...)
+{
+    va_list ap;
+    char lb[MAX_INLINEASM];  
+    char *lbp = lb;
+
+    va_start(ap,fmt);   
+
+    if (*inst != '\0') {
+        sprintf(lb,"%s\t",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 = inLine;
+    lineCurr->isDebug  = debugLine;
+    va_end(ap);
+}
+
+const char *getPairName(asmop *aop)
+{
+    if (aop->type == AOP_REG) {
+       switch (aop->aopu.aop_reg[0]->rIdx) {
+       case C_IDX:
+           return "bc";
+           break;
+       case E_IDX:
+           return "de";
+           break;
+       case L_IDX:
+           return "hl";
+           break;
+       }
+    }
+    else if (aop->type == AOP_STR) {
+       switch (*aop->aopu.aop_str[0]) {
+       case 'c':
+           return "bc";
+           break;
+       case 'e':
+           return "de";
+           break;
+       case 'l':
+           return "hl";
+           break;
+       }
+    }
+    assert(0);
+    return NULL;
+}
+
+/** Returns TRUE if the registers used in aop form a pair (BC, DE, HL) */
+bool isPair(asmop *aop)
+{
+    if (aop->size == 2) {
+       if (aop->type == AOP_REG) {
+           if ((aop->aopu.aop_reg[0]->rIdx == C_IDX)&&(aop->aopu.aop_reg[1]->rIdx == B_IDX)) {
+               return TRUE;
+           }
+           if ((aop->aopu.aop_reg[0]->rIdx == E_IDX)&&(aop->aopu.aop_reg[1]->rIdx == D_IDX)) {
+               return TRUE;
+           }
+           if ((aop->aopu.aop_reg[0]->rIdx == L_IDX)&&(aop->aopu.aop_reg[1]->rIdx == H_IDX)) {
+               return TRUE;
+           }
+       }
+       if (aop->type == AOP_STR) {
+           if (!strcmp(aop->aopu.aop_str[0], "c")&&!strcmp(aop->aopu.aop_str[1], "b")) {
+               return TRUE;
+           }
+           if (!strcmp(aop->aopu.aop_str[0], "e")&&!strcmp(aop->aopu.aop_str[1], "d")) {
+               return TRUE;
+           }
+           if (!strcmp(aop->aopu.aop_str[0], "l")&&!strcmp(aop->aopu.aop_str[1], "h")) {
+               return TRUE;
+           }
+       }
+    }
+    return FALSE;
+}
+
+/** Push a register pair onto the stack */
+void genPairPush(asmop *aop)
+{
+    emitcode("push", "%s", getPairName(aop));
+}
+
+/*-----------------------------------------------------------------*/
+/* newAsmop - creates a new asmOp                                  */
+/*-----------------------------------------------------------------*/
+static asmop *newAsmop (short type)
+{
+    asmop *aop;
+
+    ALLOC(aop,sizeof(asmop));
+    aop->type = type;
+    return aop;
+}
+
+/*-----------------------------------------------------------------*/
+/* aopForSym - for a true symbol                                   */
+/*-----------------------------------------------------------------*/
+static asmop *aopForSym (iCode *ic,symbol *sym,bool result)
+{
+    asmop *aop;
+    memmap *space= SPEC_OCLS(sym->etype);
+
+    /* if already has one */
+    if (sym->aop)
+        return sym->aop;
+
+    /* Assign depending on the storage class */
+    if (sym->onStack || sym->iaccess) {
+        sym->aop = aop = newAsmop(AOP_STK);
+        aop->size = getSize(sym->type);
+
+       aop->aopu.aop_stk = sym->stack;
+        return aop;
+    }
+
+    /* special case for a function */
+    if (IS_FUNC(sym->type)) {   
+        sym->aop = aop = newAsmop(AOP_IMMD);    
+        ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(sym->rname)+1);
+        strcpy(aop->aopu.aop_immd,sym->rname);
+        aop->size = 2;
+        return aop;
+    }
+
+    /* only remaining is far space */
+    /* in which case DPTR gets the address */
+    sym->aop = aop = newAsmop(AOP_IY);
+    emitcode ("ld","iy,#%s", sym->rname);
+    aop->size = getSize(sym->type);
+    aop->aopu.aop_dir = sym->rname;
+
+    /* if it is in code space */
+    if (IN_CODESPACE(space))
+        aop->code = 1;
+
+    return aop;     
+}
+
+/*-----------------------------------------------------------------*/
+/* aopForRemat - rematerialzes an object                           */
+/*-----------------------------------------------------------------*/
+static asmop *aopForRemat (symbol *sym)
+{
+    char *s = buffer;   
+    iCode *ic = sym->rematiCode;
+    asmop *aop = newAsmop(AOP_IMMD);
+
+    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 ;
+        }
+        /* we reached the end */
+        sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
+        break;
+    }
+
+    ALLOC_ATOMIC(aop->aopu.aop_immd,strlen(buffer)+1);
+    strcpy(aop->aopu.aop_immd,buffer);    
+    return aop;        
+}
+
+/*-----------------------------------------------------------------*/
+/* regsInCommon - two operands have some registers in common       */
+/*-----------------------------------------------------------------*/
+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                                        */
+/*-----------------------------------------------------------------*/
+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  &&
+        (sym2->usl.spillLoc == sym1))
+        return TRUE ;
+
+    return FALSE ;
+}
+
+/*-----------------------------------------------------------------*/
+/* sameRegs - two asmops have the same registers                   */
+/*-----------------------------------------------------------------*/
+bool sameRegs (asmop *aop1, asmop *aop2 )
+{
+    int i;
+
+    if (aop1 == aop2)
+        return TRUE ;
+
+    if (aop1->type != AOP_REG ||
+        aop2->type != AOP_REG )
+        return FALSE ;
+
+    if (aop1->size != aop2->size)
+        return FALSE ;
+
+    for (i = 0 ; i < aop1->size ; i++ )
+        if (aop1->aopu.aop_reg[i] !=
+            aop2->aopu.aop_reg[i] )
+            return FALSE ;
+
+    return TRUE ;
+}
+
+/*-----------------------------------------------------------------*/
+/* aopOp - allocates an asmop for an operand  :                    */
+/*-----------------------------------------------------------------*/
+static void aopOp (operand *op, iCode *ic, bool result)
+{
+    asmop *aop;
+    symbol *sym;
+    int i;
+
+    if (!op)
+        return ;
+
+    /* 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));
+        return;
+    }
+
+    /* if already has a asmop then continue */
+    if (op->aop)
+        return ;
+
+    /* if the underlying symbol has a aop */
+    if (IS_SYMOP(op) && OP_SYMBOL(op)->aop) {
+        op->aop = OP_SYMBOL(op)->aop;
+        return;
+    }
+
+    /* if this is a true symbol */
+    if (IS_TRUE_SYMOP(op)) {    
+        op->aop = aopForSym(ic,OP_SYMBOL(op),result);
+        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);
+
+    /* if the type is a conditional */
+    if (sym->regType == REG_CND) {
+        aop = op->aop = sym->aop = newAsmop(AOP_CRY);
+        aop->size = 0;
+        return;
+    }
+
+    /* if it is spilt then two situations
+    a) is rematerialize 
+    b) has a spill location */
+    if (sym->isspilt || sym->nRegs == 0) {
+        /* rematerialize it NOW */
+        if (sym->remat) {
+            sym->aop = op->aop = aop =
+                                      aopForRemat (sym);
+            aop->size = getSize(sym->type);
+            return;
+        }
+
+       if (sym->accuse) {
+           int i;
+            aop = op->aop = sym->aop = newAsmop(AOP_ACC);
+            aop->size = getSize(sym->type);
+            for ( i = 0 ; i < 2 ; i++ )
+                aop->aopu.aop_str[i] = accUse[i];
+            return;  
+       }
+
+        if (sym->ruonly ) {
+            int i;
+            aop = op->aop = sym->aop = newAsmop(AOP_STR);
+            aop->size = getSize(sym->type);
+            for ( i = 0 ; i < 4 ; i++ )
+                aop->aopu.aop_str[i] = fReturn[i];
+            return;
+        }
+
+        /* else spill location  */
+        sym->aop = op->aop = aop = 
+                                  aopForSym(ic,sym->usl.spillLoc,result);
+        aop->size = getSize(sym->type);
+        return;
+    }
+
+    /* 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];
+}
+
+/*-----------------------------------------------------------------*/
+/* freeAsmop - free up the asmop given to an operand               */
+/*----------------------------------------------------------------*/
+static void freeAsmop (operand *op, asmop *aaop, iCode *ic)
+{   
+    asmop *aop ;
+
+    if (!op)
+        aop = aaop;
+    else 
+        aop = op->aop;
+
+    if (!aop)
+        return ;
+
+    if (aop->freed)
+        goto dealloc; 
+
+    aop->freed = 1;
+
+    switch (aop->type) {
+    case AOP_STK :
+       break;
+    }
+
+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;
+        }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* aopLiteral - string from a literal value                        */
+/*-----------------------------------------------------------------*/
+char *aopLiteral (value *val, int offset)
+{
+    char *rs;
+
+    /* if it is a float then it gets tricky */
+    /* otherwise it is fairly simple */
+    if (!IS_FLOAT(val->type)) {
+        unsigned long v = floatFromVal(val);
+
+        v >>= (offset * 8);
+        sprintf(buffer,"#0x%02x",((char) v) & 0xff);
+        ALLOC_ATOMIC(rs,strlen(buffer)+1);
+        return strcpy (rs,buffer);
+    }
+
+    assert(0);
+}
+
+char *aopGetWord(asmop *aop, int offset)
+{
+    char *s = buffer ;
+    char *rs;
+
+    assert(aop->size == 2);
+    assert(offset == 0);
+
+    /* depending on type */
+    switch (aop->type) {
+    case AOP_IMMD:
+       sprintf (s,"#%s",aop->aopu.aop_immd);
+       ALLOC_ATOMIC(rs,strlen(s)+1);
+       strcpy(rs,s);   
+       return rs;
+       
+    case AOP_LIT: {
+       value * val = aop->aopu.aop_lit;
+       /* if it is a float then it gets tricky */
+       /* otherwise it is fairly simple */
+       if (!IS_FLOAT(val->type)) {
+           unsigned long v = floatFromVal(val);
+
+           sprintf(buffer,"#0x%04lx", v);
+           ALLOC_ATOMIC(rs,strlen(buffer)+1);
+           return strcpy (rs,buffer);
+       }
+       assert(0);
+       return NULL;
+    }
+    }
+    return NULL;
+}
+
+/*-----------------------------------------------------------------*/
+/* aopGet - for fetching value of the aop                          */
+/*-----------------------------------------------------------------*/
+static char *aopGet (asmop *aop, int offset, bool bit16)
+{
+    char *s = buffer ;
+    char *rs;
+
+    /* offset is greater than size then zero */
+    if (offset > (aop->size - 1) &&
+        aop->type != AOP_LIT)
+        return zero;
+
+    /* depending on type */
+    switch (aop->type) {
+    case AOP_IMMD:
+       if (bit16) 
+           sprintf (s,"#%s",aop->aopu.aop_immd);
+       else
+           if (offset) {
+               assert(offset == 1);
+               sprintf(s,"#>%s",
+                       aop->aopu.aop_immd);
+           }
+           else
+               sprintf(s,"#<%s",
+                       aop->aopu.aop_immd);
+       ALLOC_ATOMIC(rs,strlen(s)+1);
+       strcpy(rs,s);   
+       return rs;
+       
+    case AOP_DIR:
+       assert(0);
+       emitcode("ld", "a,(%s+%d)", aop->aopu.aop_dir, offset);
+       sprintf(s, "a");
+       ALLOC_ATOMIC(rs,strlen(s)+1);
+       strcpy(rs,s);   
+       return rs;
+       
+    case AOP_REG:
+       return aop->aopu.aop_reg[offset]->name;
+
+    case AOP_IY:
+       sprintf(s,"%d(iy)", offset);
+       ALLOC_ATOMIC(rs,strlen(s)+1);
+       strcpy(rs,s);   
+       return rs;
+
+    case AOP_STK:
+       sprintf(s,"%d(ix) ; %u", aop->aopu.aop_stk+offset, offset);
+       ALLOC_ATOMIC(rs,strlen(s)+1);
+       strcpy(rs,s);   
+       return rs;
+       
+    case AOP_CRY:
+       assert(0);
+       
+    case AOP_ACC:
+       if (!offset) {
+           return "a";
+       }
+       return "#0x00";
+
+    case AOP_LIT:
+       return aopLiteral (aop->aopu.aop_lit,offset);
+       
+    case AOP_STR:
+       aop->coff = offset;
+       return aop->aopu.aop_str[offset];
+    }
+
+    fprintf(stderr, "Type %u\n", aop->type);
+
+    werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
+           "aopget got unsupported aop->type");
+    exit(0);
+}
+
+bool isRegString(char *s)
+{
+    if (!strcmp(s, "b") ||
+       !strcmp(s, "c") ||
+       !strcmp(s, "d") ||
+       !strcmp(s, "e") ||
+       !strcmp(s, "a") ||
+       !strcmp(s, "h") ||
+       !strcmp(s, "l"))
+       return TRUE;
+    return FALSE;
+}
+
+bool isConstant(char *s)
+{
+    return  (*s == '#');
+}
+
+bool canAssignToPtr(char *s)
+{
+    if (isRegString(s))
+       return TRUE;
+    if (isConstant(s))
+       return TRUE;
+    return FALSE;
+}
+
+/*-----------------------------------------------------------------*/
+/* aopPut - puts a string for a aop                                */
+/*-----------------------------------------------------------------*/
+static void aopPut (asmop *aop, char *s, int offset)
+{
+    char *d = buffer ;
+
+    if (aop->size && offset > ( aop->size - 1)) {
+        werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
+               "aopPut got offset > aop->size");
+        exit(0);
+    }
+
+    /* will assign value to value */
+    /* depending on where it is ofcourse */
+    switch (aop->type) {
+    case AOP_DIR:
+       assert(0);
+       /* Direct.  Hmmm. */
+       emitcode("ld", "a,%s", s);
+       emitcode("ld", "(%s+%d),a", d, offset);
+       break;
+       
+    case AOP_REG:
+       /* Dont bother if it's a ld x,x */
+       if (strcmp(aop->aopu.aop_reg[offset]->name,s) != 0) {
+           emitcode("ld","%s,%s",
+                    aop->aopu.aop_reg[offset]->name,s);
+       }
+       break;
+       
+    case AOP_IY:
+       if (!canAssignToPtr(s)) {
+           emitcode("ld", "a,%s", s);
+           emitcode("ld", "%d(iy),a", offset);
+       }
+       else
+           emitcode("ld", "%d(iy),%s", offset, s);
+       break;
+       
+    case AOP_STK:
+       if (!canAssignToPtr(s)) {
+           emitcode("ld", "a,%s", s);
+           emitcode("ld", "%d(ix),a", aop->aopu.aop_stk+offset);
+       }
+       else
+           emitcode("ld", "%d(ix),%s", aop->aopu.aop_stk+offset, s);
+       break;
+       
+    case AOP_CRY:
+       /* if bit variable */
+       if (!aop->aopu.aop_dir) {
+           emitcode("ld", "a,#0");
+           emitcode("rla", "");
+       } else {
+           /* In bit space but not in C - cant happen */
+           assert(0);
+       }
+       break;
+       
+    case AOP_STR:
+       aop->coff = offset;
+       if (strcmp(aop->aopu.aop_str[offset],s)) {
+           emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
+       }
+       break;
+       
+    case AOP_ACC:
+       aop->coff = offset;
+       if (!offset && (strcmp(s,"acc") == 0))
+           break;
+       if (offset>0) {
+           emitcode("", "; Error aopPut AOP_ACC");
+       }
+       else {
+           if (strcmp(aop->aopu.aop_str[offset],s))
+               emitcode ("ld","%s,%s",aop->aopu.aop_str[offset],s);
+       }
+       break;
+
+    default :
+       werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
+              "aopPut got unsupported aop->type");
+       exit(0);    
+    }    
+}
+
+#define AOP(op) op->aop
+#define AOP_TYPE(op) AOP(op)->type
+#define AOP_SIZE(op) AOP(op)->size
+#define AOP_NEEDSACC(x) (AOP(x) && (AOP_TYPE(x) == AOP_CRY))
+
+/*-----------------------------------------------------------------*/
+/* getDataSize - get the operand data size                         */
+/*-----------------------------------------------------------------*/
+int getDataSize(operand *op)
+{
+    int size;
+    size = AOP_SIZE(op);
+    if(size == 3) {
+        /* pointer */
+       assert(0);
+    }
+    return size;
+}
+
+/*-----------------------------------------------------------------*/
+/* movLeft2Result - move byte from left to result                  */
+/*-----------------------------------------------------------------*/
+static void movLeft2Result (operand *left, int offl,
+                            operand *result, int offr, int sign)
+{
+    char *l;
+    if(!sameRegs(AOP(left),AOP(result)) || (offl != offr)){
+        l = aopGet(AOP(left),offl,FALSE);
+
+       if (!sign) {
+           aopPut(AOP(result),l,offr);
+       }
+       else {
+           assert(0);
+        }
+    }
+}
+
+
+/** Put Acc into a register set 
+ */
+void outAcc(operand *result)
+{
+    int size, offset;
+    size = getDataSize(result);
+    if (size){
+        aopPut(AOP(result),"a",0);
+        size--;
+        offset = 1;
+        /* unsigned or positive */
+        while (size--){
+            aopPut(AOP(result),zero,offset++);
+        }
+    }
+}
+
+/** Take the value in carry and put it into a register
+ */
+void outBitC(operand *result)
+{
+    /* if the result is bit */
+    if (AOP_TYPE(result) == AOP_CRY) {
+       emitcode("", "; Note: outBitC form 1");
+        aopPut(AOP(result),"blah",0);
+    }
+    else {
+       emitcode("ld", "a,#0");
+       emitcode("rla", "");
+        outAcc(result);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* toBoolean - emit code for orl a,operator(sizeop)                */
+/*-----------------------------------------------------------------*/
+void toBoolean(operand *oper)
+{
+    int size = AOP_SIZE(oper);
+    int offset = 0;
+    if (size>1) {
+       emitcode("ld", "a,%s", aopGet(AOP(oper), offset++, FALSE));
+       size--;
+       while (size--) 
+           emitcode("or","a,%s",aopGet(AOP(oper),offset++,FALSE));
+    }
+    else {
+       CLRC;
+       emitcode("or","a,%s",aopGet(AOP(oper),0,FALSE));
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genNot - generate code for ! operation                          */
+/*-----------------------------------------------------------------*/
+static void genNot (iCode *ic)
+{
+    link *optype = operandType(IC_LEFT(ic));
+
+    /* assign asmOps to operand & result */
+    aopOp (IC_LEFT(ic),ic,FALSE);
+    aopOp (IC_RESULT(ic),ic,TRUE);
+
+    /* if in bit space then a special case */
+    if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY) {
+       assert(0);
+    }
+
+    /* if type float then do float */
+    if (IS_FLOAT(optype)) {
+       assert(0);
+    }
+
+    toBoolean(IC_LEFT(ic));
+
+    /* Not of A:
+       If A == 0, !A = 1
+       else A = 0
+       So if A = 0, A-1 = 0xFF and C is set, rotate C into reg. */
+    emitcode("sub", "a,#0x01");
+    outBitC(IC_RESULT(ic));
+
+    /* release the aops */
+    freeAsmop(IC_LEFT(ic),NULL,ic);
+    freeAsmop(IC_RESULT(ic),NULL,ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* genCpl - generate code for complement                           */
+/*-----------------------------------------------------------------*/
+static void genCpl (iCode *ic)
+{
+    int offset = 0;
+    int size ;
+
+
+    /* assign asmOps to operand & result */
+    aopOp (IC_LEFT(ic),ic,FALSE);
+    aopOp (IC_RESULT(ic),ic,TRUE);
+
+    /* if both are in bit space then 
+    a special case */
+    if (AOP_TYPE(IC_RESULT(ic)) == AOP_CRY &&
+        AOP_TYPE(IC_LEFT(ic)) == AOP_CRY ) { 
+       assert(0);
+    } 
+
+    size = AOP_SIZE(IC_RESULT(ic));
+    while (size--) {
+        char *l = aopGet(AOP(IC_LEFT(ic)),offset,FALSE);
+        MOVA(l);       
+        emitcode("cpl","");
+        aopPut(AOP(IC_RESULT(ic)),"a",offset++);
+    }
+
+    /* release the aops */
+    freeAsmop(IC_LEFT(ic),NULL,ic);
+    freeAsmop(IC_RESULT(ic),NULL,ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* genUminus - unary minus code generation                         */
+/*-----------------------------------------------------------------*/
+static void genUminus (iCode *ic)
+{
+    assert(0);
+}
+
+
+/*-----------------------------------------------------------------*/
+/* assignResultValue -                                            */
+/*-----------------------------------------------------------------*/
+void assignResultValue(operand * oper)
+{
+    int offset = 0;
+    int size = AOP_SIZE(oper);
+    while (size--) {
+       aopPut(AOP(oper),fReturn[offset],offset);
+       offset++;
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genIpush - genrate code for pushing this gets a little complex  */
+/*-----------------------------------------------------------------*/
+static void genIpush (iCode *ic)
+{
+    int size, offset = 0 ;
+    char *l;
+
+
+    /* 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));
+        /* push it on the stack */
+       if (isPair(AOP(IC_LEFT(ic)))) {
+           emitcode("push", getPairName(AOP(IC_LEFT(ic))));
+       }
+       else {
+           offset = size;
+           while (size--) {
+               l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
+               /* Simple for now - load into A and PUSH AF */
+               emitcode("ld", "a,%s", l);
+               emitcode("push", "af");
+               emitcode("inc", "sp");
+           }
+       }
+       return ;        
+    }
+
+    /* Hmmm... what about saving the currently used registers
+       at this point? */
+
+    /* then do the push */
+    aopOp(IC_LEFT(ic),ic,FALSE);
+
+    size = AOP_SIZE(IC_LEFT(ic));
+
+    if (isPair(AOP(IC_LEFT(ic)))) {
+       emitcode("push", "%s", getPairName(AOP(IC_LEFT(ic))));
+    }
+    else {
+       if (size == 2) {
+           char *s = aopGetWord(AOP(IC_LEFT(ic)), 0);
+           if (s) {
+               emitcode("ld", "hl,%s", s);
+               emitcode("push", "hl");
+               goto release;
+           }
+       }
+       offset = size;
+       while (size--) {
+           l = aopGet(AOP(IC_LEFT(ic)), --offset, FALSE);
+           emitcode("ld", "a,%s", l);
+           emitcode("push", "af");
+           emitcode("inc", "sp");
+       }       
+    }
+ release:
+    freeAsmop(IC_LEFT(ic),NULL,ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* genIpop - recover the registers: can happen only for spilling   */
+/*-----------------------------------------------------------------*/
+static void genIpop (iCode *ic)
+{
+    int size,offset ;
+
+
+    /* 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);
+    if (isPair(AOP(IC_LEFT(ic)))) {
+       emitcode("pop", getPairName(AOP(IC_LEFT(ic))));
+    }
+    else {
+       while (size--) {
+           emitcode("dec", "sp");
+           emitcode("pop", "hl");
+           aopPut(AOP(IC_LEFT(ic)), "l", offset--);
+       }
+    }
+
+    freeAsmop(IC_LEFT(ic),NULL,ic);
+}
+
+/** Emit the code for a call statement 
+ */
+static void emitCall (iCode *ic, bool ispcall)
+{
+    /* if caller saves & we have not saved then */
+    if (!ic->regsSaved) {
+       /* PENDING */
+    }
+
+    /* if send set is not empty then assign */
+    if (sendSet) {
+       iCode *sic ;
+
+       for (sic = setFirstItem(sendSet) ; sic ; 
+            sic = setNextItem(sendSet)) {
+           int size, offset = 0;
+           aopOp(IC_LEFT(sic),sic,FALSE);
+           size = AOP_SIZE(IC_LEFT(sic));
+           while (size--) {
+               char *l = aopGet(AOP(IC_LEFT(sic)),offset,
+                               FALSE);
+               if (strcmp(l,fReturn[offset]))
+                   emitcode("ld","%s,%s",
+                            fReturn[offset],
+                            l);
+               offset++;
+           }
+           freeAsmop (IC_LEFT(sic),NULL,sic);
+       }
+       sendSet = NULL;
+    }
+
+    if (ispcall) {
+       symbol *rlbl = newiTempLabel(NULL);
+
+       emitcode("ld", "hl,#" LABEL_STR, (rlbl->key+100));
+       emitcode("push", "hl");
+
+       aopOp(IC_LEFT(ic),ic,FALSE);
+       emitcode("ld", "l,%s", aopGet(AOP(IC_LEFT(ic)), 0,FALSE));
+       emitcode("ld", "h,%s", aopGet(AOP(IC_LEFT(ic)), 1,FALSE));
+       freeAsmop(IC_LEFT(ic),NULL,ic); 
+       
+       emitcode("jp", "(hl)");
+       emitcode("","%05d$:",(rlbl->key+100));
+    }
+    else {
+       /* make the call */
+       emitcode("call", "%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))->spildir )) ||
+        IS_TRUE_SYMOP(IC_RESULT(ic)) ) {
+
+        accInUse++;
+        aopOp(IC_RESULT(ic),ic,FALSE);
+        accInUse--;
+
+       assignResultValue(IC_RESULT(ic));
+               
+        freeAsmop(IC_RESULT(ic),NULL, ic);
+    }
+
+    /* adjust the stack for parameters if required */
+    if (IC_LEFT(ic)->parmBytes) {
+       int i = IC_LEFT(ic)->parmBytes;
+       /* PENDING: do better */
+       while (i>1) {
+           emitcode("pop", "hl");
+           i-=2;
+       }
+       if (i) 
+           emitcode("inc", "sp");
+    }
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genCall - generates a call statement                            */
+/*-----------------------------------------------------------------*/
+static void genCall (iCode *ic)
+{
+    emitCall(ic, FALSE);
+}
+
+/*-----------------------------------------------------------------*/
+/* genPcall - generates a call by pointer statement                */
+/*-----------------------------------------------------------------*/
+static void genPcall (iCode *ic)
+{
+    emitCall(ic, TRUE);
+}
+
+/*-----------------------------------------------------------------*/
+/* 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;
+}
+
+/*-----------------------------------------------------------------*/
+/* genFunction - generated code for function entry                 */
+/*-----------------------------------------------------------------*/
+static void genFunction (iCode *ic)
+{
+    symbol *sym;
+    link *fetype;
+
+    nregssaved = 0;
+    /* create the function header */
+    emitcode(";","-----------------------------------------");
+    emitcode(";"," function %s",(sym = OP_SYMBOL(IC_LEFT(ic)))->name);
+    emitcode(";","-----------------------------------------");
+
+    emitcode("","%s:",sym->rname);
+    fetype = getSpec(operandType(IC_LEFT(ic)));
+
+    /* if critical function then turn interrupts off */
+    if (SPEC_CRTCL(fetype))
+        emitcode("di","");
+
+    /* if this is an interrupt service routine then
+    save acc, b, dpl, dph  */
+    if (IS_ISR(sym->etype)) {
+       emitcode("push", "af");
+       emitcode("push", "bc");
+       emitcode("push", "de");
+       emitcode("push", "hl");
+    } else {
+       /* if callee-save to be used for this function
+          then save the registers being used in this function */
+       if (sym->calleeSave) {
+           /* Handled by ncsv/csv */
+       }
+       else {
+           assert(0);
+       }
+    }
+
+    /* adjust the stack for the function */
+    emitcode("push", "de"); 
+    emitcode("push", "bc");
+    emitcode("push", "ix");
+    emitcode("ld", "ix,#0");
+    emitcode("add", "ix,sp");
+
+    _lastStack = sym->stack;
+
+    if (sym->stack) {
+       emitcode("ld", "hl,#-%d", sym->stack);
+       emitcode("add", "hl,sp");
+       emitcode("ld", "sp,hl");
+    }    
+}
+
+/*-----------------------------------------------------------------*/
+/* genEndFunction - generates epilogue for functions               */
+/*-----------------------------------------------------------------*/
+static void genEndFunction (iCode *ic)
+{
+    symbol *sym = OP_SYMBOL(IC_LEFT(ic));
+
+    if (IS_ISR(sym->etype)) {
+       assert(0);
+    }
+    else {
+        if (SPEC_CRTCL(sym->etype))
+            emitcode("ei", "");
+       
+       if (sym->calleeSave) {
+           /* Handled by cret */
+       }
+       else {
+           assert(0);
+       }
+
+       /* if debug then send end of function */
+       if (options.debug && currFunc) { 
+           debugLine = 1;
+           emitcode("","C$%s$%d$%d$%d ==.",
+                    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);
+           debugLine = 0;
+       }
+       emitcode("ld", "sp,ix");
+       emitcode("pop", "ix");
+       emitcode("pop", "bc");
+       emitcode("pop", "de");
+       emitcode("ret", "");
+    }
+
+}
+
+/*-----------------------------------------------------------------*/
+/* genRet - generate code for return statement                     */
+/*-----------------------------------------------------------------*/
+static void genRet (iCode *ic)
+{
+    char *l;
+    /* Errk.  This is a hack until I can figure out how
+       to cause dehl to spill on a call */
+    int size,offset = 0;
+    
+    /* 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 ((size == 2) && ((l = aopGetWord(AOP(IC_LEFT(ic)), 0)))) {
+           emitcode("ld", "hl,%s", l);
+    }
+    else {
+       while (size--) {
+           l = aopGet(AOP(IC_LEFT(ic)),offset,
+                      FALSE);
+           if (strcmp(fReturn[offset],l))
+               emitcode("ld","%s,%s",fReturn[offset++],l);
+       }
+    }
+    freeAsmop (IC_LEFT(ic),NULL,ic);
+    
+ 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("jp",  LABEL_STR ,(returnLabel->key+100));
+}
+
+/*-----------------------------------------------------------------*/
+/* genLabel - generates a label                                    */
+/*-----------------------------------------------------------------*/
+static void genLabel (iCode *ic)
+{
+    /* special case never generate */
+    if (IC_LABEL(ic) == entryLabel)
+        return ;
+
+    emitcode("", LABEL_STR ":",(IC_LABEL(ic)->key+100));
+}
+
+/*-----------------------------------------------------------------*/
+/* genGoto - generates a ljmp                                      */
+/*-----------------------------------------------------------------*/
+static void genGoto (iCode *ic)
+{
+    emitcode ("jp", LABEL_STR ,(IC_LABEL(ic)->key+100));
+}
+
+/*-----------------------------------------------------------------*/
+/* genPlusIncr :- does addition with increment if possible         */
+/*-----------------------------------------------------------------*/
+static bool genPlusIncr (iCode *ic)
+{
+    unsigned int icount ;
+    unsigned int size = getDataSize(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;
+    
+    /* if the literal value of the right hand side
+       is greater than 4 then it is not worth it */
+    if ((icount =  floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 4)
+        return FALSE ;
+
+    /* Inc a pair */
+    if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
+       isPair(AOP(IC_RESULT(ic)))) {
+       while (icount--) {
+           emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
+       }
+       return TRUE;
+    }
+    /* if increment 16 bits in register */
+    if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
+        (size > 1) &&
+        (icount == 1)) {
+        symbol *tlbl = newiTempLabel(NULL);
+       emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),LSB,FALSE));
+       emitcode("jp", "nz," LABEL_STR ,tlbl->key+100);
+    
+       emitcode("inc","%s",aopGet(AOP(IC_RESULT(ic)),MSB16,FALSE));
+       if(size == 4) {
+           assert(0);
+       }
+       emitcode("", LABEL_STR ":",tlbl->key+100);
+        return TRUE;
+    }
+
+    /* If result is a pair */
+    if (isPair(AOP(IC_RESULT(ic)))) {
+       movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
+       movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
+       while (icount--)
+           emitcode("inc", "%s", getPairName(AOP(IC_RESULT(ic))));
+       return TRUE;
+    }
+
+    /* if the sizes are greater than 1 then we cannot */
+    if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
+        AOP_SIZE(IC_LEFT(ic)) > 1   )
+        return FALSE ;
+    
+    /* we can if the aops of the left & result match or
+       if they are in registers and the registers are the
+       same */
+    if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) ) {
+       while (icount--)
+           emitcode ("inc","%s",aopGet(AOP(IC_LEFT(ic)),0, FALSE));
+       
+        return TRUE ;
+    }
+    
+    return FALSE ;
+}
+
+/*-----------------------------------------------------------------*/
+/* outBitAcc - output a bit in acc                                 */
+/*-----------------------------------------------------------------*/
+void outBitAcc(operand *result)
+{
+    symbol *tlbl = newiTempLabel(NULL);
+    /* if the result is a bit */
+    if (AOP_TYPE(result) == AOP_CRY){
+       assert(0);
+    }
+    else {
+        emitcode("jp","z," LABEL_STR ,tlbl->key+100);
+        emitcode("ld","a,%s",one);
+        emitcode("", LABEL_STR ":",tlbl->key+100);
+        outAcc(result);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genPlus - generates code for addition                           */
+/*-----------------------------------------------------------------*/
+static void genPlus (iCode *ic)
+{
+    int size, offset = 0;
+
+    /* special cases :- */
+
+    aopOp (IC_LEFT(ic),ic,FALSE);
+    aopOp (IC_RIGHT(ic),ic,FALSE);
+    aopOp (IC_RESULT(ic),ic,TRUE);
+
+    /* Swap the left and right operands if:
+
+       if literal, literal on the right or
+       if left requires ACC or right is already
+       in ACC */
+
+    if ((AOP_TYPE(IC_LEFT(ic)) == AOP_LIT) ||
+       (AOP_NEEDSACC(IC_LEFT(ic))) ||
+       AOP_TYPE(IC_RIGHT(ic)) == AOP_ACC ){
+        operand *t = IC_RIGHT(ic);
+        IC_RIGHT(ic) = IC_LEFT(ic);
+        IC_LEFT(ic) = t;
+    }
+
+    /* if both left & right are in bit
+    space */
+    if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
+        AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
+       /* Cant happen */
+       assert(0);
+    }
+
+    /* if left in bit space & right literal */
+    if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
+        AOP_TYPE(IC_RIGHT(ic)) == AOP_LIT) {
+       /* Can happen I guess */
+       assert(0);
+    }
+
+    /* if I can do an increment instead
+    of add then GOOD for ME */
+    if (genPlusIncr (ic) == TRUE)
+        goto release;   
+
+    size = getDataSize(IC_RESULT(ic));
+
+    while(size--) {
+       if (AOP_TYPE(IC_LEFT(ic)) == AOP_ACC) {
+           MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
+           if(offset == 0)
+               emitcode("add","a,%s",
+                        aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
+           else
+               emitcode("adc","a,%s",
+                        aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
+       } else {
+           MOVA(aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
+           if(offset == 0)
+               emitcode("add","a,%s",
+                        aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
+           else
+               emitcode("adc","a,%s",
+                        aopGet(AOP(IC_LEFT(ic)),offset,FALSE));
+       }
+        aopPut(AOP(IC_RESULT(ic)),"a",offset++);      
+    }
+
+    /* Some kind of pointer arith. */
+    if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
+       AOP_SIZE(IC_LEFT(ic)) == 3   &&
+       !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
+       assert(0);
+
+     if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
+       AOP_SIZE(IC_RIGHT(ic)) == 3   &&
+       !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_RIGHT(ic))))
+        assert(0);
+
+   
+release:
+    freeAsmop(IC_LEFT(ic),NULL,ic);
+    freeAsmop(IC_RIGHT(ic),NULL,ic);
+    freeAsmop(IC_RESULT(ic),NULL,ic);
+    
+}
+
+/*-----------------------------------------------------------------*/
+/* genMinusDec :- does subtraction with deccrement if possible     */
+/*-----------------------------------------------------------------*/
+static bool genMinusDec (iCode *ic)
+{
+    unsigned int icount ;
+    unsigned int size = getDataSize(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 ;
+
+    /* if the literal value of the right hand side
+    is greater than 4 then it is not worth it */
+    if ((icount = (unsigned int) floatFromVal (AOP(IC_RIGHT(ic))->aopu.aop_lit)) > 2)
+        return FALSE;
+
+    size = getDataSize(IC_RESULT(ic));
+    /* if decrement 16 bits in register */
+    if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic))) &&
+        (size > 1) && isPair(AOP(IC_RESULT(ic)))) {
+       while (icount--)
+           emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
+        return TRUE;
+    }
+
+    /* If result is a pair */
+    if (isPair(AOP(IC_RESULT(ic)))) {
+       movLeft2Result(IC_LEFT(ic), 0, IC_RESULT(ic), 0, 0);
+       movLeft2Result(IC_LEFT(ic), 1, IC_RESULT(ic), 1, 0);
+       while (icount--)
+           emitcode("dec", "%s", getPairName(AOP(IC_RESULT(ic))));
+       return TRUE;
+    }
+
+    /* if the sizes are greater than 1 then we cannot */
+    if (AOP_SIZE(IC_RESULT(ic)) > 1 ||
+        AOP_SIZE(IC_LEFT(ic)) > 1   )
+        return FALSE ;
+
+    /* we can if the aops of the left & result match or if they are in
+       registers and the registers are the same */
+    if (sameRegs(AOP(IC_LEFT(ic)), AOP(IC_RESULT(ic)))) {
+        while (icount--) 
+            emitcode ("dec","%s",aopGet(AOP(IC_RESULT(ic)),0,FALSE));
+        return TRUE ;
+    }
+
+    return FALSE ;
+}
+
+/*-----------------------------------------------------------------*/
+/* genMinus - generates code for subtraction                       */
+/*-----------------------------------------------------------------*/
+static void genMinus (iCode *ic)
+{
+    int size, offset = 0;
+    unsigned long lit = 0L;
+
+    aopOp (IC_LEFT(ic),ic,FALSE);
+    aopOp (IC_RIGHT(ic),ic,FALSE);
+    aopOp (IC_RESULT(ic),ic,TRUE);
+
+    /* special cases :- */
+    /* if both left & right are in bit space */
+    if (AOP_TYPE(IC_LEFT(ic)) == AOP_CRY &&
+        AOP_TYPE(IC_RIGHT(ic)) == AOP_CRY) {
+       assert(0);
+        goto release ;
+    }
+
+    /* if I can do an decrement instead of subtract then GOOD for ME */
+    if (genMinusDec (ic) == TRUE)
+        goto release;   
+
+    size = getDataSize(IC_RESULT(ic));   
+
+    if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT){
+        CLRC;
+    }
+    else{
+        lit = (unsigned long)floatFromVal(AOP(IC_RIGHT(ic))->aopu.aop_lit);
+        lit = - (long)lit;
+    }
+
+
+    /* if literal, add a,#-lit, else normal subb */
+    while (size--) {
+       MOVA(aopGet(AOP(IC_LEFT(ic)),offset,FALSE));    
+       if (AOP_TYPE(IC_RIGHT(ic)) != AOP_LIT)  
+           emitcode("sbc","a,%s",
+                    aopGet(AOP(IC_RIGHT(ic)),offset,FALSE));
+       else{
+           /* first add without previous c */
+           if (!offset)
+               emitcode("add","a,#0x%02x",
+                        (unsigned int)(lit & 0x0FFL));
+           else
+               emitcode("adc","a,#0x%02x",
+                        (unsigned int)((lit >> (offset*8)) & 0x0FFL));
+       }
+       aopPut(AOP(IC_RESULT(ic)),"a",offset++);      
+    }
+    
+    if (AOP_SIZE(IC_RESULT(ic)) == 3 && 
+       AOP_SIZE(IC_LEFT(ic)) == 3   &&
+       !sameRegs(AOP(IC_RESULT(ic)),AOP(IC_LEFT(ic))))
+       assert(0);
+
+release:
+    freeAsmop(IC_LEFT(ic),NULL,ic);
+    freeAsmop(IC_RIGHT(ic),NULL,ic);
+    freeAsmop(IC_RESULT(ic),NULL,ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* genMult - generates code for multiplication                     */
+/*-----------------------------------------------------------------*/
+static void genMult (iCode *ic)
+{
+    /* Shouldn't occur - all done through function calls */
+    assert(0);
+}
+
+/*-----------------------------------------------------------------*/
+/* genDiv - generates code for division                            */
+/*-----------------------------------------------------------------*/
+static void genDiv (iCode *ic)
+{
+    /* Shouldn't occur - all done through function calls */
+    assert(0);
+}
+
+/*-----------------------------------------------------------------*/
+/* genMod - generates code for division                            */
+/*-----------------------------------------------------------------*/
+static void genMod (iCode *ic)
+{
+    /* Shouldn't occur - all done through function calls */
+    assert(0);
+}
+
+/*-----------------------------------------------------------------*/
+/* genIfxJump :- will create a jump depending on the ifx           */
+/*-----------------------------------------------------------------*/
+static void genIfxJump (iCode *ic, char *jval)
+{
+    symbol *jlbl ;
+    const char *inst;
+
+    /* if true label then we jump if condition
+    supplied is true */
+    if ( IC_TRUE(ic) ) {
+        jlbl = IC_TRUE(ic);
+       if (!strcmp(jval, "a")) {
+           inst = "nz";
+       }
+       else if (!strcmp(jval, "c")) {
+           inst = "c";
+       }
+       else {
+           /* The buffer contains the bit on A that we should test */
+           inst = "nz";
+       }
+    }
+    else {
+        /* false label is present */
+        jlbl = IC_FALSE(ic) ;
+       if (!strcmp(jval, "a")) {
+           inst = "z";
+       }
+       else if (!strcmp(jval, "c")) {
+           inst = "nc";
+       }
+       else {
+           /* The buffer contains the bit on A that we should test */
+           inst = "z";
+       }
+    }
+    /* Z80 can do a conditional long jump */
+    if (!strcmp(jval, "a")) {
+       emitcode("or", "a,a");
+    }
+    else if (!strcmp(jval, "c")) {
+    }
+    else {
+       emitcode("bit", "%s,a", jval);
+    }
+    emitcode("jp", "%s," LABEL_STR , inst, jlbl->key+100);
+
+    /* mark the icode as generated */
+    ic->generated = 1;
+}
+
+/** Generic compare for > or <
+ */
+static void genCmp (operand *left,operand *right,
+                    operand *result, iCode *ifx, int sign)
+{
+    int size, offset = 0 ;
+    unsigned long lit = 0L;
+
+    /* if left & right are bit variables */
+    if (AOP_TYPE(left) == AOP_CRY &&
+        AOP_TYPE(right) == AOP_CRY ) {
+       /* Cant happen on the Z80 */
+       assert(0);
+    } else {
+        /* 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 unsigned char cmp with lit, just compare */
+        if((size == 1) && !sign &&
+           (AOP_TYPE(right) == AOP_LIT && AOP_TYPE(left) != AOP_DIR )){
+           emitcode("ld", "a,%s", aopGet(AOP(left), offset, FALSE));
+           emitcode("cp", "%s", aopGet(AOP(right), offset, FALSE));
+        } 
+       else {
+            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) {
+                       /* No sign so it's always false */
+                        CLRC;
+                    }
+                    else{
+                       /* Just load in the top most bit */
+                        MOVA(aopGet(AOP(left),AOP_SIZE(left)-1,FALSE));
+                        if(!(AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) && ifx) {
+                           assert(0);
+                            genIfxJump (ifx,"acc.7");
+                            return;
+                        }
+                        else    
+                            emitcode("rlc","a");
+                    }
+                    goto release;
+                }
+            }
+            while (size--) {
+               /* Do a long subtract */
+                MOVA(aopGet(AOP(left),offset,FALSE));
+                if (sign && size == 0) {
+                   /* Case where it's signed and we've hit the end */
+                   assert(0);
+                } else {
+                   /* Subtract through, propagating the carry */
+                   if (offset==0) {
+                       emitcode("sub","a,%s",aopGet(AOP(right),offset++,FALSE));
+                   }
+                   else
+                       emitcode("sbc","a,%s",aopGet(AOP(right),offset++,FALSE));
+               }
+            }
+        }
+    }
+
+release:
+    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 )
+            genIfxJump (ifx,"c");
+        else
+            outBitC(result);
+        /* leave the result in acc */
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genCmpGt :- greater than comparison                             */
+/*-----------------------------------------------------------------*/
+static void genCmpGt (iCode *ic, iCode *ifx)
+{
+    operand *left, *right, *result;
+    link *letype , *retype;
+    int sign ;
+
+    left = IC_LEFT(ic);
+    right= IC_RIGHT(ic);
+    result = IC_RESULT(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);
+
+    freeAsmop(left,NULL,ic);
+    freeAsmop(right,NULL,ic);
+    freeAsmop(result,NULL,ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* genCmpLt - less than comparisons                                */
+/*-----------------------------------------------------------------*/
+static void genCmpLt (iCode *ic, iCode *ifx)
+{
+    operand *left, *right, *result;
+    link *letype , *retype;
+    int sign ;
+
+    left = IC_LEFT(ic);
+    right= IC_RIGHT(ic);
+    result = IC_RESULT(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);
+
+    freeAsmop(left,NULL,ic);
+    freeAsmop(right,NULL,ic);
+    freeAsmop(result,NULL,ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* gencjneshort - compare and jump if not equal                    */
+/*-----------------------------------------------------------------*/
+static void gencjneshort(operand *left, operand *right, symbol *lbl)
+{
+    int size = max(AOP_SIZE(left),AOP_SIZE(right));
+    int offset = 0;
+    unsigned long lit = 0L;
+
+    /* Swap the left and right if it makes the computation easier */
+    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);
+
+    /* if the right side is a literal then anything goes */
+    if (AOP_TYPE(right) == AOP_LIT &&
+        AOP_TYPE(left) != AOP_DIR ) {
+        while (size--) {
+           emitcode("ld", "a,%s", aopGet(AOP(left),offset,FALSE));
+           emitcode("cp", "a,%s", aopGet(AOP(right),offset,FALSE));
+            emitcode("jp", "nz," LABEL_STR , lbl->key+100);
+            offset++;
+        }
+    }
+    /* if the right side is in a register or in direct space or
+    if the left is a pointer register & right is not */    
+    else if (AOP_TYPE(right) == AOP_REG ||
+             AOP_TYPE(right) == AOP_DIR || 
+             (AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT)) {
+        while (size--) {
+            MOVA(aopGet(AOP(left),offset,FALSE));
+            if((AOP_TYPE(left) == AOP_DIR && AOP_TYPE(right) == AOP_LIT) &&
+               ((unsigned int)((lit >> (offset*8)) & 0x0FFL) == 0))
+               /* PENDING */
+                emitcode("jp","nz," LABEL_STR ,lbl->key+100);
+            else {
+               emitcode("cp", "%s", aopGet(AOP(right),offset,FALSE));
+               emitcode("jp", "nz," LABEL_STR , lbl->key+100);
+           }
+            offset++;
+        }
+    } else {
+       assert(0);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* gencjne - compare and jump if not equal                         */
+/*-----------------------------------------------------------------*/
+static void gencjne(operand *left, operand *right, symbol *lbl)
+{
+    symbol *tlbl  = newiTempLabel(NULL);
+
+    gencjneshort(left, right, lbl);
+
+    /* PENDING: ?? */
+    emitcode("ld","a,%s",one);
+    emitcode("jp", LABEL_STR ,tlbl->key+100);
+    emitcode("", LABEL_STR ":",lbl->key+100);
+    emitcode("xor","a,a");
+    emitcode("", LABEL_STR ":",tlbl->key+100);
+}
+
+/*-----------------------------------------------------------------*/
+/* genCmpEq - generates code for equal to                          */
+/*-----------------------------------------------------------------*/
+static void genCmpEq (iCode *ic, iCode *ifx)
+{
+    operand *left, *right, *result;
+
+    aopOp((left=IC_LEFT(ic)),ic,FALSE);
+    aopOp((right=IC_RIGHT(ic)),ic,FALSE);
+    aopOp((result=IC_RESULT(ic)),ic,TRUE);
+
+    /* Swap operands if it makes the operation easier. ie if:
+       1.  Left is a literal.
+    */
+    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;
+        /* if they are both bit variables */
+        if (AOP_TYPE(left) == AOP_CRY &&
+            ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
+           assert(0);
+        } else {
+            tlbl = newiTempLabel(NULL);
+            gencjneshort(left, right, tlbl);
+            if ( IC_TRUE(ifx) ) {
+                emitcode("jp", LABEL_STR ,IC_TRUE(ifx)->key+100);
+                emitcode("", LABEL_STR ":",tlbl->key+100);                
+            } else {
+               /* PENDING: do this better */
+                symbol *lbl = newiTempLabel(NULL);
+                emitcode("jp", LABEL_STR ,lbl->key+100);
+                emitcode("", LABEL_STR ":",tlbl->key+100);                
+                emitcode("jp", LABEL_STR ,IC_FALSE(ifx)->key+100);
+                emitcode("", LABEL_STR ":",lbl->key+100);             
+            }
+        }
+        /* mark the icode as generated */
+        ifx->generated = 1;
+        goto release ;
+    }
+
+    /* if they are both bit variables */
+    if (AOP_TYPE(left) == AOP_CRY &&
+        ((AOP_TYPE(right) == AOP_CRY) || (AOP_TYPE(right) == AOP_LIT))) {
+       assert(0);
+    } else {
+        gencjne(left,right,newiTempLabel(NULL));    
+        if (AOP_TYPE(result) == AOP_CRY && AOP_SIZE(result)) {
+           assert(0);
+        }
+        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);
+       }
+        /* leave the result in acc */
+    }
+
+release:
+    freeAsmop(left,NULL,ic);
+    freeAsmop(right,NULL,ic);
+    freeAsmop(result,NULL,ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* 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;
+}
+
+/*-----------------------------------------------------------------*/
+/* genAndOp - for && operation                                     */
+/*-----------------------------------------------------------------*/
+static void genAndOp (iCode *ic)
+{
+    operand *left,*right, *result;
+    symbol *tlbl;
+
+    /* 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);
+
+    /* if both are bit variables */
+    if (AOP_TYPE(left) == AOP_CRY &&
+        AOP_TYPE(right) == AOP_CRY ) {
+       assert(0);
+    } else {
+        tlbl = newiTempLabel(NULL);
+        toBoolean(left);    
+        emitcode("jp","z," LABEL_STR ,tlbl->key+100);
+        toBoolean(right);
+        emitcode("", LABEL_STR ":",tlbl->key+100);
+        outBitAcc(result);
+    }
+
+    freeAsmop(left,NULL,ic);
+    freeAsmop(right,NULL,ic);
+    freeAsmop(result,NULL,ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* genOrOp - for || operation                                      */
+/*-----------------------------------------------------------------*/
+static void genOrOp (iCode *ic)
+{
+    operand *left,*right, *result;
+    symbol *tlbl;
+
+    /* 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);
+
+    /* if both are bit variables */
+    if (AOP_TYPE(left) == AOP_CRY &&
+        AOP_TYPE(right) == AOP_CRY ) {
+       assert(0);
+    } else {
+        tlbl = newiTempLabel(NULL);
+        toBoolean(left);
+        emitcode("jp","nz," LABEL_STR,tlbl->key+100);
+        toBoolean(right);
+        emitcode("", LABEL_STR,tlbl->key+100);
+        outBitAcc(result);
+    }
+
+    freeAsmop(left,NULL,ic);
+    freeAsmop(right,NULL,ic);
+    freeAsmop(result,NULL,ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* isLiteralBit - test if lit == 2^n                               */
+/*-----------------------------------------------------------------*/
+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;
+}
+
+/*-----------------------------------------------------------------*/
+/* genAnd  - code for and                                          */
+/*-----------------------------------------------------------------*/
+static void genAnd (iCode *ic, iCode *ifx)
+{
+    operand *left, *right, *result;
+    int size, offset=0;  
+    unsigned long lit = 0L;
+    int bytelit = 0;
+
+    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) ||
+       AOP_NEEDSACC(left)) {
+        operand *tmp = right ;
+        right = left;
+        left = tmp;
+    }
+
+    /* if result = right then exchange them */
+    if(sameRegs(AOP(result),AOP(right))){
+        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 (AOP_TYPE(left) == AOP_CRY){
+       assert(0);
+        goto release ;
+    }
+
+    // if(val & 0xZZ)       - size = 0, ifx != FALSE  -
+    // bit = val & 0xZZ     - size = 1, ifx = FALSE -
+    if((AOP_TYPE(right) == AOP_LIT) &&
+       (AOP_TYPE(result) == AOP_CRY) &&
+       (AOP_TYPE(left) != AOP_CRY)) {
+        int posbit = isLiteralBit(lit);
+        /* left &  2^n */
+        if(posbit){
+            posbit--;
+            MOVA(aopGet(AOP(left),posbit>>3,FALSE));
+            // bit = left & 2^n
+            if(size) {
+               assert(0);
+                emitcode("mov","c,acc.%d",posbit&0x07);
+           }
+            // if(left &  2^n)
+            else{
+                if (ifx) {
+                    sprintf(buffer, "%d", posbit&0x07);
+                    genIfxJump(ifx, buffer);
+                }
+               else {
+                   assert(0);
+               }
+                goto release;
+            }
+        } else {
+            symbol *tlbl = newiTempLabel(NULL);
+            int sizel = AOP_SIZE(left);
+            if(size) {
+               assert(0);
+                emitcode("setb","c");
+           }
+            while(sizel--){
+                if((bytelit = ((lit >> (offset*8)) & 0x0FFL)) != 0x0L){
+                    MOVA( aopGet(AOP(left),offset,FALSE));
+                    // byte ==  2^n ?
+                    if((posbit = isLiteralBit(bytelit)) != 0) {
+                       assert(0);
+                        emitcode("jb","acc.%d,%05d$",(posbit-1)&0x07,tlbl->key+100);
+                   }
+                    else{
+                        if(bytelit != 0x0FFL)
+                            emitcode("and","a,%s",
+                                     aopGet(AOP(right),offset,FALSE));
+                        emitcode("jr","nz, %05d$",tlbl->key+100);
+                    }
+                }
+                offset++;
+            }
+            // bit = left & literal
+            if (size){
+                emitcode("clr","c");
+                emitcode("","%05d$:",tlbl->key+100);
+            }
+            // if(left & literal)
+            else{
+                if(ifx)
+#if 0
+                    jmpTrueOrFalse(ifx, tlbl);
+#else
+               assert(0);
+#endif
+                goto release ;
+            }
+        }
+        outBitC(result);
+        goto release ;
+    }
+
+    /* if left is same as result */
+    if(sameRegs(AOP(result),AOP(left))){
+        for(;size--; offset++) {
+            if(AOP_TYPE(right) == AOP_LIT){
+                if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF)
+                    continue;
+                else {
+                   if (bytelit == 0)
+                       aopPut(AOP(result),zero,offset);
+                   else {
+                       MOVA(aopGet(AOP(left),offset,FALSE));
+                       emitcode("and","a,%s",
+                                aopGet(AOP(right),offset,FALSE));
+                       emitcode("ld", "%s,a", aopGet(AOP(left),offset,FALSE));
+                   }
+               }
+
+            } else {
+               if (AOP_TYPE(left) == AOP_ACC) {
+                   assert(0);
+               }
+               else {
+                   MOVA(aopGet(AOP(right),offset,FALSE));
+                   emitcode("and","%s,a",
+                            aopGet(AOP(left),offset,FALSE));
+               }
+            }
+        }
+    } else {
+        // left & result in different registers
+        if(AOP_TYPE(result) == AOP_CRY){
+           assert(0);
+        } else {
+           for(;(size--);offset++) {
+               // normal case
+               // result = left & right
+               if(AOP_TYPE(right) == AOP_LIT){
+                   if((bytelit = (int)((lit >> (offset*8)) & 0x0FFL)) == 0x0FF){
+                       aopPut(AOP(result),
+                              aopGet(AOP(left),offset,FALSE),
+                              offset);
+                       continue;
+                   } else if(bytelit == 0){
+                       aopPut(AOP(result),zero,offset);
+                       continue;
+                   }
+               }
+               // faster than result <- left, anl result,right
+               // and better if result is SFR
+               if (AOP_TYPE(left) == AOP_ACC) 
+                   emitcode("and","a,%s",aopGet(AOP(right),offset,FALSE));
+               else {
+                   MOVA(aopGet(AOP(right),offset,FALSE));
+                   emitcode("and","a,%s",
+                            aopGet(AOP(left),offset,FALSE));
+               }
+               aopPut(AOP(result),"a",offset);
+           }
+       }
+
+    }
+
+release :
+    freeAsmop(left,NULL,ic);
+    freeAsmop(right,NULL,ic);
+    freeAsmop(result,NULL,ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* genOr  - code for or                                            */
+/*-----------------------------------------------------------------*/
+static void genOr (iCode *ic, iCode *ifx)
+{
+    operand *left, *right, *result;
+    int size, offset=0;
+    unsigned long lit = 0L;
+
+    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) ||
+       AOP_NEEDSACC(left)) {
+        operand *tmp = right ;
+        right = left;
+        left = tmp;
+    }
+
+    /* if result = right then exchange them */
+    if(sameRegs(AOP(result),AOP(right))){
+        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 (AOP_TYPE(left) == AOP_CRY){
+       assert(0);
+        goto release ;
+    }
+
+    if((AOP_TYPE(right) == AOP_LIT) &&
+       (AOP_TYPE(result) == AOP_CRY) &&
+       (AOP_TYPE(left) != AOP_CRY)){
+       assert(0);
+        goto release ;
+    }
+
+    /* if left is same as result */
+    if(sameRegs(AOP(result),AOP(left))){
+        for(;size--; offset++) {
+            if(AOP_TYPE(right) == AOP_LIT){
+                if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
+                    continue;
+                else 
+                   emitcode("or","%s,%s",
+                            aopGet(AOP(left),offset,FALSE),
+                            aopGet(AOP(right),offset,FALSE));
+            } else {
+               if (AOP_TYPE(left) == AOP_ACC) 
+                   emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
+               else {              
+                   MOVA(aopGet(AOP(right),offset,FALSE));
+                   emitcode("or","a,%s",
+                            aopGet(AOP(left),offset,FALSE));
+                   aopPut(AOP(result),"a",0);
+               }
+            }
+        }
+    } else {
+        // left & result in different registers
+        if(AOP_TYPE(result) == AOP_CRY){
+           assert(0);
+        } else for(;(size--);offset++){
+            // normal case
+            // result = left & right
+            if(AOP_TYPE(right) == AOP_LIT){
+                if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
+                    aopPut(AOP(result),
+                           aopGet(AOP(left),offset,FALSE),
+                           offset);
+                    continue;
+                }
+            }
+            // faster than result <- left, anl result,right
+            // and better if result is SFR
+           if (AOP_TYPE(left) == AOP_ACC) 
+               emitcode("or","a,%s",aopGet(AOP(right),offset,FALSE));
+           else {
+               MOVA(aopGet(AOP(right),offset,FALSE));
+               emitcode("or","a,%s",
+                        aopGet(AOP(left),offset,FALSE));
+               aopPut(AOP(result),"a",0);
+           }
+           aopPut(AOP(result),"a",offset);                     
+        }
+    }
+
+release :
+    freeAsmop(left,NULL,ic);
+    freeAsmop(right,NULL,ic);
+    freeAsmop(result,NULL,ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* genXor - code for xclusive or                                   */
+/*-----------------------------------------------------------------*/
+static void genXor (iCode *ic, iCode *ifx)
+{
+    operand *left, *right, *result;
+    int size, offset=0;
+    unsigned long lit = 0L;
+
+    aopOp((left = IC_LEFT(ic)),ic,FALSE);
+    aopOp((right= IC_RIGHT(ic)),ic,FALSE);
+    aopOp((result=IC_RESULT(ic)),ic,TRUE);
+
+    /* if left is a literal & right is not then exchange them */
+    if ((AOP_TYPE(left) == AOP_LIT && AOP_TYPE(right) != AOP_LIT) ||
+       AOP_NEEDSACC(left)) {
+        operand *tmp = right ;
+        right = left;
+        left = tmp;
+    }
+
+    /* if result = right then exchange them */
+    if(sameRegs(AOP(result),AOP(right))){
+        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 (AOP_TYPE(left) == AOP_CRY){
+       assert(0);
+        goto release ;
+    }
+
+    if((AOP_TYPE(right) == AOP_LIT) &&
+       (AOP_TYPE(result) == AOP_CRY) &&
+       (AOP_TYPE(left) != AOP_CRY)){
+       assert(0);
+        goto release ;
+    }
+
+    /* if left is same as result */
+    if(sameRegs(AOP(result),AOP(left))){
+        for(;size--; offset++) {
+            if(AOP_TYPE(right) == AOP_LIT){
+                if(((lit >> (offset*8)) & 0x0FFL) == 0x00L)
+                    continue;
+                else {
+                   MOVA(aopGet(AOP(right),offset,FALSE));
+                   emitcode("xor","a,%s",
+                            aopGet(AOP(left),offset,FALSE));
+                   aopPut(AOP(result),"a",0);
+               }
+            } else {
+               if (AOP_TYPE(left) == AOP_ACC) 
+                   emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
+               else {              
+                   MOVA(aopGet(AOP(right),offset,FALSE));
+                   emitcode("xor","a,%s",
+                            aopGet(AOP(left),offset,FALSE));
+                   aopPut(AOP(result),"a",0);
+               }
+            }
+        }
+    } else {
+        // left & result in different registers
+        if(AOP_TYPE(result) == AOP_CRY){
+           assert(0);
+        } else for(;(size--);offset++){
+            // normal case
+            // result = left & right
+            if(AOP_TYPE(right) == AOP_LIT){
+                if(((lit >> (offset*8)) & 0x0FFL) == 0x00L){
+                    aopPut(AOP(result),
+                           aopGet(AOP(left),offset,FALSE),
+                           offset);
+                    continue;
+                }
+            }
+            // faster than result <- left, anl result,right
+            // and better if result is SFR
+           if (AOP_TYPE(left) == AOP_ACC) 
+               emitcode("xor","a,%s",aopGet(AOP(right),offset,FALSE));
+           else {
+               MOVA(aopGet(AOP(right),offset,FALSE));
+               emitcode("xor","a,%s",
+                        aopGet(AOP(left),offset,FALSE));
+               aopPut(AOP(result),"a",0);
+           }
+           aopPut(AOP(result),"a",offset);                     
+        }
+    }
+
+release :
+    freeAsmop(left,NULL,ic);
+    freeAsmop(right,NULL,ic);
+    freeAsmop(result,NULL,ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* genInline - write the inline code out                           */
+/*-----------------------------------------------------------------*/
+static void genInline (iCode *ic)
+{
+    char buffer[MAX_INLINEASM];
+    char *bp = buffer;
+    char *bp1= buffer;
+    
+    inLine += (!options.asmpeep);
+    strcpy(buffer,IC_INLINE(ic));
+
+    /* emit each line as a code */
+    while (*bp) {
+        if (*bp == '\n') {
+            *bp++ = '\0';
+            emitcode(bp1,"");
+            bp1 = bp;
+        } else {
+            if (*bp == ':') {
+                bp++;
+                *bp = '\0';
+                bp++;
+                emitcode(bp1,"");
+                bp1 = bp;
+            } else
+                bp++;
+        }
+    }
+    if (bp1 != bp)
+        emitcode(bp1,"");
+    /*     emitcode("",buffer); */
+    inLine -= (!options.asmpeep);
+}
+
+/*-----------------------------------------------------------------*/
+/* genRRC - rotate right with carry                                */
+/*-----------------------------------------------------------------*/
+static void genRRC (iCode *ic)
+{
+    assert(0);
+}
+
+/*-----------------------------------------------------------------*/
+/* genRLC - generate code for rotate left with carry               */
+/*-----------------------------------------------------------------*/
+static void genRLC (iCode *ic)
+{    
+    assert(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)
+{
+    if(sameRegs(AOP(result), AOP(left)) &&
+       ((offl + MSB16) == offr)){
+       assert(0);
+    } else {
+       movLeft2Result(left, offl, result, offr, 0);
+       movLeft2Result(left, offl+1, result, offr+1, 0);
+    }
+
+    if (sign) {
+       assert(0);
+    }
+    else {
+       /*      if (AOP(result)->type == AOP_REG) {*/
+           int size = 2;
+           int offset = 0;
+           symbol *tlbl , *tlbl1;
+           char *l;
+
+           /* Left is already in result - so now do the shift */
+           if (shCount>1) {
+               emitcode("ld","a,#%u+1", shCount);
+               tlbl = newiTempLabel(NULL);
+               tlbl1 = newiTempLabel(NULL);
+               emitcode("jp", LABEL_STR ,tlbl1->key+100); 
+               emitcode("", LABEL_STR ":",tlbl->key+100);    
+           }
+
+           emitcode("or", "a,a");
+           offset = size;
+           while (size--) {
+               l = aopGet(AOP(result), --offset, FALSE);
+               emitcode("rr","%s", l);         
+           }
+           if (shCount>1) {
+               emitcode("", LABEL_STR ":",tlbl1->key+100);
+               emitcode("dec", "a");
+               emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
+           }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* shiftL2Left2Result - shift left two bytes from left to result   */
+/*-----------------------------------------------------------------*/
+static void shiftL2Left2Result (operand *left, int offl,
+                                operand *result, int offr, int shCount)
+{
+    if(sameRegs(AOP(result), AOP(left)) &&
+       ((offl + MSB16) == offr)){
+       assert(0);
+    } else {
+       /* Copy left into result */
+       movLeft2Result(left,offl, result, offr, 0);
+    }
+    if (AOP(result)->type == AOP_REG) {
+       int size = 2;
+       int offset = 0;
+       symbol *tlbl , *tlbl1;
+       char *l;
+
+       /* Left is already in result - so now do the shift */
+       if (shCount>1) {
+           emitcode("ld","a,#%u+1", shCount);
+           tlbl = newiTempLabel(NULL);
+           tlbl1 = newiTempLabel(NULL);
+           emitcode("jp", LABEL_STR ,tlbl1->key+100); 
+           emitcode("", LABEL_STR ":",tlbl->key+100);    
+       }
+
+       emitcode("or", "a,a");
+       while (size--) {
+           l = aopGet(AOP(result),offset++,FALSE);
+           emitcode("rl","%s", l);         
+       }
+       if (shCount>1) {
+           emitcode("", LABEL_STR ":",tlbl1->key+100);
+           emitcode("dec", "a");
+           emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
+       }
+    }
+    else {
+       /* PENDING: do something */
+       assert(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("rl","a");
+            break;
+        case 2 :
+            emitcode("rl","a");
+            emitcode("rl","a");
+            break;
+        case 3 :
+            emitcode("rl","a");
+            emitcode("rl","a");
+            emitcode("rl","a");
+            break;
+        case 4 :
+            emitcode("rl","a");
+            emitcode("rl","a");
+            emitcode("rl","a");
+            emitcode("rl","a");
+            break;
+        case 5 :
+            emitcode("rr","a");
+            emitcode("rr","a");
+            emitcode("rr","a");
+            break;
+        case 6 :
+            emitcode("rr","a");
+            emitcode("rr","a");
+            break;
+        case 7 :
+            emitcode("rr","a");
+            break;
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* AccLsh - left shift accumulator by known count                  */
+/*-----------------------------------------------------------------*/
+static void AccLsh (int shCount)
+{
+    if(shCount != 0){
+        if(shCount == 1)
+            emitcode("add","a,a");
+        else 
+           if(shCount == 2) {
+            emitcode("add","a,a");
+            emitcode("add","a,a");
+        } else {
+            /* rotate left accumulator */
+            AccRol(shCount);
+            /* and kill the lower order bits */
+            emitcode("and","a,#0x%02x", SLMask[shCount]);
+        }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* shiftL1Left2Result - shift left one byte from left to result    */
+/*-----------------------------------------------------------------*/
+static void shiftL1Left2Result (operand *left, int offl,
+                                operand *result, int offr, int shCount)
+{
+    char *l;
+    l = aopGet(AOP(left),offl,FALSE);
+    MOVA(l);
+    /* shift left accumulator */
+    AccLsh(shCount);
+    aopPut(AOP(result),"a",offr);
+}
+
+
+/*-----------------------------------------------------------------*/
+/* genlshTwo - left shift two bytes by known amount != 0           */
+/*-----------------------------------------------------------------*/
+static void genlshTwo (operand *result,operand *left, int shCount)
+{
+    int size = AOP_SIZE(result);
+
+    assert(size==2);
+
+    /* if shCount >= 8 */
+    if (shCount >= 8) {
+        shCount -= 8 ;
+
+        if (size > 1){
+            if (shCount) {
+                movLeft2Result(left, LSB, result, MSB16, 0);
+               aopPut(AOP(result),zero, 0);   
+               shiftL1Left2Result(left, MSB16, result, MSB16, shCount-8);
+           }
+            else {
+                movLeft2Result(left, LSB, result, MSB16, 0);
+               aopPut(AOP(result),zero, 0);   
+           }
+        }
+        aopPut(AOP(result),zero,LSB);   
+    }
+    /*  1 <= shCount <= 7 */
+    else {  
+        if(size == 1) {
+           assert(0);
+       }
+        else {
+            shiftL2Left2Result(left, LSB, result, LSB, shCount);
+       }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genlshOne - left shift a one byte quantity by known count       */
+/*-----------------------------------------------------------------*/
+static void genlshOne (operand *result, operand *left, int shCount)
+{       
+    shiftL1Left2Result(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;
+
+    freeAsmop(right,NULL,ic);
+
+    aopOp(left,ic,FALSE);
+    aopOp(result,ic,FALSE);
+
+    size = getSize(operandType(result));
+
+#if VIEW_SIZE
+    emitcode("; shift left ","result %d, left %d",size,
+             AOP_SIZE(left));
+#endif
+
+    /* I suppose that the left size >= result size */
+    if (shCount == 0) {
+       assert(0);
+    }
+
+    else if(shCount >= (size * 8))
+        while(size--)
+            aopPut(AOP(result),zero,size);
+    else{
+        switch (size) {
+       case 1:
+           genlshOne (result,left,shCount);
+           break;
+       case 2:
+           genlshTwo (result,left,shCount);
+           break;
+       case 4:
+           assert(0);
+           break;
+       default:
+           assert(0);
+        }
+    }
+    freeAsmop(left,NULL,ic);
+    freeAsmop(result,NULL,ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* genLeftShift - generates code for left shifting                 */
+/*-----------------------------------------------------------------*/
+static void genLeftShift (iCode *ic)
+{
+    int size, offset;
+    char *l;
+    symbol *tlbl , *tlbl1;
+    operand *left,*right, *result;
+
+    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 B : 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 ) */
+    emitcode("ld","a,%s",aopGet(AOP(right),0,FALSE));
+    emitcode("inc","a");
+    freeAsmop (right,NULL,ic);
+    aopOp(left,ic,FALSE);
+    aopOp(result,ic,FALSE);
+
+    /* now move the left to the result if they are not the
+       same */
+#if 1
+    if (!sameRegs(AOP(left),AOP(result))) {
+
+        size = AOP_SIZE(result);
+        offset = 0;
+        while (size--) {
+            l = aopGet(AOP(left),offset,FALSE);
+           aopPut(AOP(result),l,offset);
+            offset++;
+        }
+    }
+#else
+    size = AOP_SIZE(result);
+    offset = 0;
+    while (size--) {
+       l = aopGet(AOP(left),offset,FALSE);
+       aopPut(AOP(result),l,offset);
+       offset++;
+    }
+#endif
+
+
+    tlbl = newiTempLabel(NULL);
+    size = AOP_SIZE(result);
+    offset = 0 ;   
+    tlbl1 = newiTempLabel(NULL);
+
+    emitcode("jp", LABEL_STR ,tlbl1->key+100); 
+    emitcode("", LABEL_STR ":",tlbl->key+100);    
+    l = aopGet(AOP(result),offset,FALSE);
+    emitcode("or", "a,a");
+    while (size--) {
+        l = aopGet(AOP(result),offset++,FALSE);
+        emitcode("rl","%s", l);         
+    }
+    emitcode("", LABEL_STR ":",tlbl1->key+100);
+    emitcode("dec", "a");
+    emitcode("jp","nz," LABEL_STR ,tlbl->key+100);
+
+    freeAsmop(left,NULL,ic);
+    freeAsmop(result,NULL,ic);
+}
+
+/* genlshTwo - left shift two bytes by known amount != 0           */
+/*-----------------------------------------------------------------*/
+static void genrshOne (operand *result,operand *left, int shCount)
+{
+    /* Errk */
+    int size = AOP_SIZE(result);
+    char *l;
+
+    assert(size==1);
+    assert(shCount<8);
+
+    l = aopGet(AOP(left),0,FALSE);
+    if (AOP(result)->type == AOP_REG) {
+       aopPut(AOP(result), l, 0);
+       l = aopGet(AOP(result), 0, FALSE);
+       while (shCount--) 
+           emitcode("srl", "%s", l);
+    }
+    else {
+       MOVA(l);
+       while (shCount--) {
+           emitcode("srl", "a");
+       }
+       aopPut(AOP(result),"a",0);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* AccRsh - right shift accumulator by known count                 */
+/*-----------------------------------------------------------------*/
+static void AccRsh (int shCount)
+{
+    if(shCount != 0){
+        if(shCount == 1){
+            CLRC;
+            emitcode("rr","a");
+        } else {
+            /* rotate right accumulator */
+            AccRol(8 - shCount);
+            /* and kill the higher order bits */
+            emitcode("and","a,#0x%02x", SRMask[shCount]);
+        }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* shiftR1Left2Result - shift right one byte from left to result   */
+/*-----------------------------------------------------------------*/
+static void shiftR1Left2Result (operand *left, int offl,
+                                operand *result, int offr,
+                                int shCount, int sign)
+{
+    MOVA(aopGet(AOP(left),offl,FALSE));
+    if (sign) {
+       assert(0);
+    }
+    else {
+        AccRsh(shCount);
+    }
+    aopPut(AOP(result),"a",offr);
+}
+
+/*-----------------------------------------------------------------*/
+/* genrshTwo - right shift two bytes by known amount != 0          */
+/*-----------------------------------------------------------------*/
+static void genrshTwo (operand *result,operand *left,
+                       int shCount, int sign)
+{
+    /* if shCount >= 8 */
+    if (shCount >= 8) {
+        shCount -= 8 ;
+        if (shCount) {
+           assert(0);
+            shiftR1Left2Result(left, MSB16, result, LSB,
+                               shCount, sign);
+       }
+        else {
+            movLeft2Result(left, MSB16, result, LSB, sign);
+           aopPut(AOP(result),zero,1);
+       }
+    }
+    /*  1 <= shCount <= 7 */
+    else {
+        shiftR2Left2Result(left, LSB, result, LSB, shCount, sign); 
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genRightShiftLiteral - left shifting by known count              */
+/*-----------------------------------------------------------------*/
+static void genRightShiftLiteral (operand *left,
+                                 operand *right,
+                                 operand *result,
+                                 iCode *ic)
+{    
+    int shCount = (int) floatFromVal (AOP(right)->aopu.aop_lit);
+    int size;
+
+    freeAsmop(right,NULL,ic);
+
+    aopOp(left,ic,FALSE);
+    aopOp(result,ic,FALSE);
+
+    size = getSize(operandType(result));
+
+    emitcode("; shift right ","result %d, left %d",size,
+             AOP_SIZE(left));
+
+    /* I suppose that the left size >= result size */
+    if (shCount == 0) {
+       assert(0);
+    }
+
+    else if(shCount >= (size * 8))
+        while(size--)
+            aopPut(AOP(result),zero,size);
+    else{
+        switch (size) {
+       case 1:
+           genrshOne(result, left, shCount);
+           break;
+       case 2:
+           /* PENDING: sign support */
+           genrshTwo(result, left, shCount, FALSE);
+           break;
+       case 4:
+           assert(0);
+           break;
+       default:
+           assert(0);
+        }
+    }
+    freeAsmop(left,NULL,ic);
+    freeAsmop(result,NULL,ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* genRightShift - generate code for right shifting                */
+/*-----------------------------------------------------------------*/
+static void genRightShift (iCode *ic)
+{
+    operand *left,*right, *result;
+
+    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);
+        return ;
+    }
+    else {
+       assert(0);
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* genGenPointerGet - gget value from generic pointer space        */
+/*-----------------------------------------------------------------*/
+static void genGenPointerGet (operand *left,
+                              operand *result, iCode *ic)
+{
+    int size, offset ;
+    link *retype = getSpec(operandType(result));
+
+    aopOp(left,ic,FALSE);
+    aopOp(result,ic,FALSE);
+
+    if (isPair(AOP(left)) && (AOP_SIZE(result)==1)) {
+       /* Just do it */
+       emitcode("ld", "a,(%s)", getPairName(AOP(left)));
+       aopPut(AOP(result),"a", 0);
+       freeAsmop(left,NULL,ic);
+       goto release;
+    }
+
+    /* For now we always load into IY */
+    /* if this is remateriazable */
+    if (AOP_TYPE(left) == AOP_IMMD)
+       emitcode("ld","hl,%s",aopGet(AOP(left),0,TRUE));
+    else { /* we need to get it byte by byte */
+       emitcode("ld", "l,%s", aopGet(AOP(left), 0, FALSE));
+       emitcode("ld", "h,%s", aopGet(AOP(left), 1, FALSE));
+    }
+    /* so iy now contains the address */
+    freeAsmop(left,NULL,ic);
+
+    /* if bit then unpack */
+    if (IS_BITVAR(retype)) {
+       assert(0);
+    }
+    else {
+        size = AOP_SIZE(result);
+        offset = 0 ;
+
+        while (size--) {
+           /* PENDING: make this better */
+           if (AOP(result)->type == AOP_REG) {
+               aopPut(AOP(result),"(hl)",offset++);
+           }
+           else {
+               emitcode("ld", "a,(hl)", offset);
+               aopPut(AOP(result),"a",offset++);
+           }
+           if (size) {
+               emitcode("inc", "hl");
+           }
+        }
+    }
+
+ release:
+    freeAsmop(result,NULL,ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* genPointerGet - generate code for pointer get                   */
+/*-----------------------------------------------------------------*/
+static void genPointerGet (iCode *ic)
+{
+    operand *left, *result ;
+    link *type, *etype;
+
+    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);
+
+    genGenPointerGet (left,result,ic);
+}
+
+bool isRegOrLit(asmop *aop)
+{
+    if (aop->type == AOP_REG || aop->type == AOP_LIT || aop->type == AOP_IMMD)
+       return TRUE;
+    return FALSE;
+}
+
+/*-----------------------------------------------------------------*/
+/* genGenPointerSet - stores the value into a pointer location        */
+/*-----------------------------------------------------------------*/
+static void genGenPointerSet (operand *right,
+                              operand *result, iCode *ic)
+{    
+    int size, offset ;
+    link *retype = getSpec(operandType(right));
+
+    aopOp(result,ic,FALSE);
+    aopOp(right,ic,FALSE);
+
+    /* Handle the exceptions first */
+    if (isPair(AOP(result)) && (AOP_SIZE(right)==1)) {
+       /* Just do it */
+       char *l = aopGet(AOP(right), 0, FALSE);
+       MOVA(l);
+       emitcode("ld", "(%s),a", getPairName(AOP(result)));
+       freeAsmop(result,NULL,ic);
+       goto release;
+    }
+       
+    /* if the operand is already in dptr 
+       then we do nothing else we move the value to dptr */
+    if (AOP_TYPE(result) != AOP_STR) {
+        /* if this is remateriazable */
+        if (AOP_TYPE(result) == AOP_IMMD) {
+           emitcode("", "; Error 2");
+           emitcode("ld", "hl,%s", aopGet(AOP(result), 0, TRUE));
+        }
+        else { /* we need to get it byte by byte */
+           /* PENDING: do this better */
+           emitcode("ld", "l,%s", aopGet(AOP(result), 0, FALSE));
+           emitcode("ld", "h,%s", aopGet(AOP(result), 1, FALSE));
+        }
+    }
+    /* so hl know contains the address */
+    freeAsmop(result,NULL,ic);
+
+    /* if bit then unpack */
+    if (IS_BITVAR(retype)) {
+       assert(0);
+    }
+    else {
+        size = AOP_SIZE(right);
+        offset = 0 ;
+
+        while (size--) {
+            char *l = aopGet(AOP(right),offset,FALSE);
+
+           if (isRegOrLit(AOP(right))) {
+               emitcode("ld", "(hl),%s", l);
+           }
+           else {
+               MOVA(l);
+               emitcode("ld", "(hl),a", offset);
+           }
+           if (size) {
+               emitcode("inc", "hl");
+           }
+           offset++;
+        }
+    }
+    release:
+    freeAsmop(right,NULL,ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* genPointerSet - stores the value into a pointer location        */
+/*-----------------------------------------------------------------*/
+static void genPointerSet (iCode *ic)
+{    
+    operand *right, *result ;
+    link *type, *etype;
+
+    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);
+    
+    genGenPointerSet (right,result,ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* genIfx - generate code for Ifx statement                        */
+/*-----------------------------------------------------------------*/
+static void genIfx (iCode *ic, iCode *popIc)
+{
+    operand *cond = IC_COND(ic);
+    int isbit =0;
+
+    aopOp(cond,ic,FALSE);
+
+    /* get the value into acc */
+    if (AOP_TYPE(cond) != AOP_CRY)
+        toBoolean(cond);
+    else
+        isbit = 1;
+    /* the result is now in the accumulator */
+    freeAsmop(cond,NULL,ic);
+
+    /* 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));
+
+    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 */
+       emitcode("push", "de");
+       emitcode("push", "ix");
+       emitcode("pop", "hl");
+       emitcode("ld", "de,#%d", sym->stack);
+       emitcode("add", "hl,de");
+       emitcode("pop", "de");
+    }
+    else {
+       emitcode("ld", "hl,#%s", sym->rname);
+    }
+    aopPut(AOP(IC_RESULT(ic)), "l", 0);
+    aopPut(AOP(IC_RESULT(ic)), "h", 1);
+
+    freeAsmop(IC_RESULT(ic),NULL,ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* genAssign - generate code for assignment                        */
+/*-----------------------------------------------------------------*/
+static void genAssign (iCode *ic)
+{
+    operand *result, *right;
+    int size, offset ;
+    unsigned long lit = 0L;
+
+    result = IC_RESULT(ic);
+    right  = IC_RIGHT(ic) ;
+
+    /* Dont bother assigning if they are the same */
+    if (operandsEqu (IC_RESULT(ic),IC_RIGHT(ic))) {
+       emitcode("", "; (operands are equal)");
+        return;
+    }
+
+    aopOp(right,ic,FALSE);
+    aopOp(result,ic,TRUE);
+
+    /* if they are the same registers */
+    if (sameRegs(AOP(right),AOP(result))) {
+       emitcode("", "; (registers are the same)");
+        goto release;
+    }
+
+    /* if the result is a bit */
+    if (AOP_TYPE(result) == AOP_CRY) {
+       assert(0);
+    }
+
+    /* general case */
+    size = AOP_SIZE(result);
+    offset = 0;
+
+    if(AOP_TYPE(right) == AOP_LIT)
+       lit = (unsigned long)floatFromVal(AOP(right)->aopu.aop_lit);
+    if((size > 1) &&
+       (AOP_TYPE(result) != AOP_REG) &&
+       (AOP_TYPE(right) == AOP_LIT) &&
+       !IS_FLOAT(operandType(right)) &&
+       (lit < 256L)){
+       emitcode("xor","a,a");
+       /* Work from the top down.
+          Done this way so that we can use the cached copy of 0
+          in A for a fast clear */
+       while (size--) {
+           if((unsigned int)((lit >> (size*8)) & 0x0FFL)== 0)
+               aopPut(AOP(result),"a",size);
+           else
+               aopPut(AOP(result),
+                      aopGet(AOP(right),size,FALSE),
+                      size);
+       }
+    } else {
+       while (size--) {
+           aopPut(AOP(result),
+                  aopGet(AOP(right),offset,FALSE),
+                  offset);
+           offset++;
+       }
+    }
+    
+release:
+    freeAsmop(right,NULL,ic);
+    freeAsmop(result,NULL,ic);
+}   
+
+/*-----------------------------------------------------------------*/
+/* genJumpTab - genrates code for jump table                       */
+/*-----------------------------------------------------------------*/
+static void genJumpTab (iCode *ic)
+{
+    assert(0);
+}
+
+/*-----------------------------------------------------------------*/
+/* genCast - gen code for casting                                  */
+/*-----------------------------------------------------------------*/
+static void genCast (iCode *ic)
+{
+    operand *result = IC_RESULT(ic);
+    link *ctype = operandType(IC_LEFT(ic));
+    operand *right = IC_RIGHT(ic);
+    int size, offset ;
+
+    /* 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 the result is a bit */
+    if (AOP_TYPE(result) == AOP_CRY) {
+       assert(0);
+    }
+
+    /* if they are the same size : or less */
+    if (AOP_SIZE(result) <= AOP_SIZE(right)) {
+
+        /* if they are in the same place */
+        if (sameRegs(AOP(right),AOP(result)))
+            goto release;
+
+        /* if they in different places then copy */
+        size = AOP_SIZE(result);
+        offset = 0 ;
+        while (size--) {
+            aopPut(AOP(result),
+                   aopGet(AOP(right),offset,FALSE),
+                   offset);
+            offset++;
+        }
+        goto release;
+    }
+
+    /* if the result is of type pointer */
+    if (IS_PTR(ctype)) {
+       assert(0);
+    }
+    
+    /* 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--) {
+        aopPut(AOP(result),
+               aopGet(AOP(right),offset,FALSE),
+               offset);
+        offset++;
+    }
+
+    /* now depending on the sign of the destination */
+    size = AOP_SIZE(result) - AOP_SIZE(right);
+    /* Unsigned or not an integral type - right fill with zeros */
+    if (SPEC_USIGN(ctype) || !IS_SPEC(ctype)) {
+        while (size--)
+            aopPut(AOP(result),zero,offset++);
+    } else {
+        /* we need to extend the sign :{ */
+        char *l = aopGet(AOP(right),AOP_SIZE(right) - 1,
+                         FALSE);
+        MOVA(l);
+       emitcode("", "; genCast: sign extend untested.");
+        emitcode("rla", "");
+        emitcode("sbc", "a,a");
+        while (size--)
+            aopPut(AOP(result),"a",offset++);   
+    }
+
+release:
+    freeAsmop(right, NULL, ic);
+    freeAsmop(result, NULL, ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* genReceive - generate code for a receive iCode                  */
+/*-----------------------------------------------------------------*/
+static void genReceive (iCode *ic)
+{    
+    if (isOperandInFarSpace(IC_RESULT(ic)) && 
+       ( OP_SYMBOL(IC_RESULT(ic))->isspilt ||
+         IS_TRUE_SYMOP(IC_RESULT(ic))) ) {
+       assert(0);
+    } else {
+       accInUse++;
+       aopOp(IC_RESULT(ic),ic,FALSE);  
+       accInUse--;
+       assignResultValue(IC_RESULT(ic));       
+    }
+
+    freeAsmop(IC_RESULT(ic),NULL,ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* genZ80Code - generate code for Z80 based controllers            */
+/*-----------------------------------------------------------------*/
+void genZ80Code (iCode *lic)
+{
+    iCode *ic;
+    int cln = 0;
+
+    lineHead = lineCurr = NULL;
+
+    /* if debug information required */
+    if (options.debug && currFunc) { 
+       cdbSymbol(currFunc,cdbFile,FALSE,TRUE);
+       debugLine = 1;
+       if (IS_STATIC(currFunc->etype))
+           emitcode("","F%s$%s$0$0 ==.",moduleName,currFunc->name); 
+       else
+           emitcode("","G$%s$0$0 ==.",currFunc->name);
+       debugLine = 0;
+    }
+    /* stack pointer name */
+    spname = "sp";
+    
+    for (ic = lic ; ic ; ic = ic->next ) {
+       
+       if ( cln != ic->lineno ) {
+           if ( options.debug ) {
+               debugLine = 1;
+               emitcode("","C$%s$%d$%d$%d ==.",
+                        ic->filename,ic->lineno,
+                        ic->level,ic->block);
+               debugLine = 0;
+           }
+           emitcode(";","%s %d",ic->filename,ic->lineno);
+           cln = ic->lineno ;
+       }
+       /* 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 ;
+       
+       /* depending on the operation */
+       switch (ic->op) {
+       case '!' :
+           emitcode("", "; genNot");
+           genNot(ic);
+           break;
+           
+       case '~' :
+           emitcode("", "; genCpl");
+           genCpl(ic);
+           break;
+           
+       case UNARYMINUS:
+           emitcode("", "; genUminus");
+           genUminus (ic);
+           break;
+           
+       case IPUSH:
+           emitcode("", "; genIpush");
+           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))) {
+               emitcode("", "; genIfx");
+               genIfx (ic->next,ic);
+           }
+           else {
+               emitcode("", "; genIpop");
+               genIpop (ic);
+           }
+           break; 
+           
+       case CALL:
+           emitcode("", "; genCall");
+           genCall (ic);
+           break;
+           
+       case PCALL:
+           emitcode("", "; genPcall");
+           genPcall (ic);
+           break;
+           
+       case FUNCTION:
+           emitcode("", "; genFunction");
+           genFunction (ic);
+           break;
+           
+       case ENDFUNCTION:
+           emitcode("", "; genEndFunction");
+           genEndFunction (ic);
+           break;
+           
+       case RETURN:
+           emitcode("", "; genRet");
+           genRet (ic);
+           break;
+           
+       case LABEL:
+           emitcode("", "; genLabel");
+           genLabel (ic);
+           break;
+           
+       case GOTO:
+           emitcode("", "; genGoto");
+           genGoto (ic);
+           break;
+           
+       case '+' :
+           emitcode("", "; genPlus");
+           genPlus (ic) ;
+           break;
+           
+       case '-' :
+           emitcode("", "; genMinus");
+           genMinus (ic);
+           break;
+           
+       case '*' :
+           emitcode("", "; genMult");
+           genMult (ic);
+           break;
+           
+       case '/' :
+           emitcode("", "; genDiv");
+           genDiv (ic) ;
+           break;
+           
+       case '%' :
+           emitcode("", "; genMod");
+           genMod (ic);
+           break;
+           
+       case '>' :
+           emitcode("", "; genCmpGt");
+           genCmpGt (ic,ifxForOp(IC_RESULT(ic),ic));                 
+           break;
+           
+       case '<' :
+           emitcode("", "; genCmpLt");
+           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:
+           emitcode("", "; genCmpEq");
+           genCmpEq (ic,ifxForOp(IC_RESULT(ic),ic));
+           break;          
+           
+       case AND_OP:
+           emitcode("", "; genAndOp");
+           genAndOp (ic);
+           break;
+           
+       case OR_OP:
+           emitcode("", "; genOrOp");
+           genOrOp (ic);
+           break;
+           
+       case '^' :
+           emitcode("", "; genXor");
+           genXor (ic,ifxForOp(IC_RESULT(ic),ic));
+           break;
+           
+       case '|' :
+           emitcode("", "; genOr");
+           genOr (ic,ifxForOp(IC_RESULT(ic),ic));
+           break;
+           
+       case BITWISEAND:
+           emitcode("", "; genAnd");
+            genAnd (ic,ifxForOp(IC_RESULT(ic),ic));
+           break;
+           
+       case INLINEASM:
+           emitcode("", "; genInline");
+           genInline (ic);
+           break;
+           
+       case RRC:
+           emitcode("", "; genRRC");
+           genRRC (ic);
+           break;
+           
+       case RLC:
+           emitcode("", "; genRLC");
+           genRLC (ic);
+           break;
+           
+       case GETHBIT:
+           emitcode("", "; genHBIT");
+           assert(0);
+           
+       case LEFT_OP:
+           emitcode("", "; genLeftShift");
+           genLeftShift (ic);
+           break;
+           
+       case RIGHT_OP:
+           emitcode("", "; genRightShift");
+           genRightShift (ic);
+           break;
+           
+       case GET_VALUE_AT_ADDRESS:
+           emitcode("", "; genPointerGet");
+           genPointerGet(ic);
+           break;
+           
+       case '=' :
+
+           if (POINTER_SET(ic)) {
+               emitcode("", "; genAssign (pointer)");
+               genPointerSet(ic);
+           }
+           else {
+               emitcode("", "; genAssign");
+               genAssign(ic);
+           }
+           break;
+           
+       case IFX:
+           emitcode("", "; genIfx");
+           genIfx (ic,NULL);
+           break;
+           
+       case ADDRESS_OF:
+           emitcode("", "; genAddrOf");
+           genAddrOf (ic);
+           break;
+           
+       case JUMPTABLE:
+           emitcode("", "; genJumpTab");
+           genJumpTab (ic);
+           break;
+           
+       case CAST:
+           emitcode("", "; genCast");
+           genCast (ic);
+           break;
+           
+       case RECEIVE:
+           emitcode("", "; genReceive");
+           genReceive(ic);
+           break;
+           
+       case SEND:
+           emitcode("", "; addSet");
+           addSet(&sendSet,ic);
+           break;
+
+       default :
+           ic = ic;
+           /*      piCode(ic,stdout); */
+           
+        }
+    }
+    
+
+    /* 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/z80/gen.h b/src/z80/gen.h
new file mode 100644 (file)
index 0000000..9af5207
--- /dev/null
@@ -0,0 +1,84 @@
+/*-------------------------------------------------------------------------
+  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 {
+    /* Is a literal */
+    AOP_LIT = 1,
+    /* Is in a register */
+    AOP_REG, 
+    /* Is in direct space */
+    AOP_DIR, 
+    /* Is on the stack */
+    AOP_STK ,
+    /* Is an immediate value */
+    AOP_IMMD, 
+    /* Is a string (?) */
+    AOP_STR,
+    /* Is in the carry register */
+    AOP_CRY, 
+    /* Is pointed to by IY */
+    AOP_IY, 
+    /* Is in A */
+    AOP_ACC };
+
+/* 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    -  direct just a name
+                    AOP_DPTR   -  dptr contains address of operand
+                    AOP_R0/R1  -  r0/r1 contains address of operand               
+                    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_ACC    -  result is in the acc:b pair
+                 */
+    short coff ;  /* current offset */
+    short size ;  /* total size */
+    unsigned code :1 ;         /* is in Code space */
+    unsigned paged:1 ;         /* in paged memory  */
+    unsigned freed:1 ;         /* already freed    */
+    union {
+       value *aop_lit ;       /* if literal */
+       regs  *aop_reg[4];     /* array of registers */
+       char  *aop_dir ;       /* if direct  */
+       char  *aop_immd;       /* if immediate others are implied */    
+       int    aop_stk ;       /* stack offset when AOP_STK */
+       char  *aop_str[4];     /* just a string array containing the location */
+    } aopu;
+} asmop;
+
+void genZ80Code (iCode *);
+
+
+#endif
diff --git a/src/z80/global.h b/src/z80/global.h
new file mode 100644 (file)
index 0000000..f20caa2
--- /dev/null
@@ -0,0 +1,3 @@
+typedef struct {
+} PROCESSOR_OPTIONS;
+
diff --git a/src/z80/glue.c b/src/z80/glue.c
new file mode 100644 (file)
index 0000000..878e082
--- /dev/null
@@ -0,0 +1,22 @@
+#include "SDCCglue.h"
+#include "glue.h"
+
+extern int maxRegBank ;
+
+/* Not yet ported */
+#if 0
+void x_glue(FILE *asmFile)
+{
+    assert(asmFile);
+}
+
+void x_insertMainHook(FILE *asmFile)
+{
+    assert(asmFile);
+
+    if (mainf && mainf->fbody) {
+       fprintf (asmFile,"__sdcc_gsinit_startup:\n");
+    }
+
+}
+#endif
diff --git a/src/z80/glue.h b/src/z80/glue.h
new file mode 100644 (file)
index 0000000..03d38b9
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef GLUE_INCLUDE
+#define GLUE_INCLUDE
+
+#include <stdio.h>
+
+void x_glue(FILE *asmFile);
+void x_insertMainHook(FILE *asmFile);
+
+#endif
diff --git a/src/z80/icode.c b/src/z80/icode.c
new file mode 100644 (file)
index 0000000..e569685
--- /dev/null
@@ -0,0 +1,153 @@
+#include "SDCCglobl.h"
+#include "SDCCast.h"
+#include "SDCCmem.h"
+#include "SDCCy.h"
+#include "SDCChasht.h"
+#include "SDCCicode.h"
+#include "SDCCerr.h"
+#include "ralloc.h"
+
+/* Not ported yet */
+#if 0
+/*-----------------------------------------------------------------*/
+/* aggrToPtr - changes an aggregate to pointer to an aggregate     */
+/*-----------------------------------------------------------------*/
+link *aggrToPtr ( link *type, bool force)
+{
+    link *etype ;
+    link *ptype ;
+
+    
+    if (IS_PTR(type) && !force)
+       return type;
+
+    etype = getSpec(type);
+    ptype = newLink();
+
+    ptype->next = type;
+    /* if the output class is generic */
+    if (SPEC_OCLS(etype) == generic)
+       DCL_TYPE(ptype) = GPOINTER;
+    else
+       if (SPEC_OCLS(etype)->codesp ) {
+           DCL_TYPE(ptype) = POINTER ;
+           DCL_PTR_CONST(ptype) = 1;
+       }
+       else
+           DCL_TYPE(ptype) = POINTER ;
+    
+    /* if the variable was declared a constant */
+    /* then the pointer points to a constant */
+    if (IS_CONSTANT(etype) )
+       DCL_PTR_CONST(ptype) = 1;
+
+    /* the variable was volatile then pointer to volatile */
+    if (IS_VOLATILE(etype))
+       DCL_PTR_VOLATILE(ptype) = 1;
+    return ptype; 
+}
+
+/*-----------------------------------------------------------------*/
+/* geniCodeArray2Ptr - array to pointer                            */
+/*-----------------------------------------------------------------*/
+operand *geniCodeArray2Ptr (operand *op)
+{
+    link *optype = operandType(op);
+    link *opetype = getSpec(optype);
+    
+    /* set the pointer depending on the storage class */
+    if (SPEC_OCLS(opetype)->codesp ) {
+       DCL_TYPE(optype) = POINTER ;
+       DCL_PTR_CONST(optype) = 1;
+    }
+    else {
+       DCL_TYPE(optype) = POINTER;
+    }
+    
+    /* if the variable was declared a constant */
+    /* then the pointer points to a constant */
+    if (IS_CONSTANT(opetype) )
+       DCL_PTR_CONST(optype) = 1;
+
+    /* the variable was volatile then pointer to volatile */
+    if (IS_VOLATILE(opetype))
+       DCL_PTR_VOLATILE(optype) = 1;
+    op->isaddr = 0;
+    return op;
+}
+
+/*-----------------------------------------------------------------*/
+/* geniCodeAddressOf - gens icode for '&' address of operator      */
+/*-----------------------------------------------------------------*/
+operand *geniCodeAddressOf (operand *op) 
+{
+    iCode *ic;
+    link *p ;
+    link *optype = operandType(op);
+    link *opetype= getSpec(optype);
+    
+    /* this must be a lvalue */
+    if (!op->isaddr && !IS_AGGREGATE(optype)) {
+       werror (E_LVALUE_REQUIRED,"&");
+       return op;
+    }
+    
+    p = newLink();
+    p->class = DECLARATOR ;
+    /* set the pointer depending on the storage class */
+    if (SPEC_OCLS(opetype)->codesp ) {
+       DCL_TYPE(p) = POINTER ;
+       DCL_PTR_CONST(p) = 1;
+    }
+    else {
+       DCL_TYPE(p) = POINTER ;
+    }
+    
+    /* make sure we preserve the const & volatile */
+    if (IS_CONSTANT(opetype)) 
+       DCL_PTR_CONST(p) = 1;
+
+    if (IS_VOLATILE(opetype))
+       DCL_PTR_VOLATILE(p) = 1;
+    
+    p->next = copyLinkChain(optype);
+    
+    /* if already a temp */
+    if (IS_ITEMP(op)) {
+       setOperandType (op,p);     
+       op->isaddr= 0;
+       return op;
+    }
+    
+    /* other wise make this of the type coming in */
+    ic = newiCode(ADDRESS_OF,op,NULL);
+    IC_RESULT(ic) = newiTempOperand(p,1);
+    IC_RESULT(ic)->isaddr = 0;
+    ADDTOCHAIN(ic);
+    return IC_RESULT(ic);
+}
+
+/*-----------------------------------------------------------------*/
+/* setOClass - sets the output class depending on the pointer type */
+/*-----------------------------------------------------------------*/
+void setOClass (link *ptr, link *spec)
+{
+    switch (DCL_TYPE(ptr)) {
+    case POINTER:
+       SPEC_OCLS(spec) = data ;
+       break ;
+       
+    case CPOINTER:
+       SPEC_OCLS(spec) = code ;
+       break ;  
+
+    case GPOINTER:
+       SPEC_OCLS(spec) = generic;
+       break;
+
+    default:
+       assert(0);
+    }
+}
+
+#endif
diff --git a/src/z80/main.c b/src/z80/main.c
new file mode 100644 (file)
index 0000000..c22fc0c
--- /dev/null
@@ -0,0 +1,45 @@
+#include "SDCCglobl.h"
+#include "main.h"
+
+/* Globals */
+PROCESSOR_CONSTANTS port = {
+    "Zilog Z80",               /* Target name */
+    {  
+       "as-z80",               /* Assembler executable name */
+       "-plosgff",             /* Options with debug */
+       "-plosgff",             /* Options without debug */
+       TRUE                    /* TRUE if the assembler requires an output name */
+    },
+    {
+       "link-z80",             /* Linker executable name */
+    },
+    {
+       /* Sizes: char, short, int, long, ptr, fptr, gptr, bit, float, max */
+       1, 1, 2, 4, 2, 2, 2, 1, 4, 4
+    },
+    { 
+       -1, 0, 0, 8, 0
+    },
+    /* Z80 has no native mul/div commands */
+    {  
+       0
+    }
+};
+
+bool x_parseOptions(char **argv, int *pargc)
+{
+    int i = *pargc;
+    bool fRecognised = FALSE;
+
+    *pargc = i;
+    return fRecognised;
+}
+
+void x_finaliseOptions(void)
+{
+}
+
+void x_setDefaultOptions(void)
+{    
+}
+
diff --git a/src/z80/main.h b/src/z80/main.h
new file mode 100644 (file)
index 0000000..c4d1602
--- /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/z80/mem.c b/src/z80/mem.c
new file mode 100644 (file)
index 0000000..adc7e72
--- /dev/null
@@ -0,0 +1,16 @@
+#include "SDCCglobl.h"
+#include "SDCCmem.h"
+#include "mem.h"
+
+memmap  *xstack= NULL ;         /* xternal stack data         */
+memmap  *xdata = NULL;  /* external data                          */
+memmap  *idata = NULL;  /* internal data upto 256     */
+memmap  *bit   = NULL;  /* bit addressable space      */
+memmap  *sfr   = NULL;   /* register space              */
+memmap  *sfrbit= NULL;   /* sfr bit space               */
+memmap  *overlay=NULL;   /* overlay segment             */
+
+void x_initMem(void)
+{
+}
+
diff --git a/src/z80/mem.h b/src/z80/mem.h
new file mode 100644 (file)
index 0000000..78b5f60
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef MEM_INCLUDE
+#define MEM_INCLUDE
+
+/* memory map prefixes  MOF added the DATA,CODE,XDATA,BIT */
+#define  OVERLAY_NAME          "_OVERLAY"
+#define  CODE_NAME             "_CODE"
+#define  DATA_NAME             "_DATA"
+#define  STATIC_NAME           "GSINIT"
+#define GENERIC_NAME           "GENERIC"
+#define ISTACK_NAME            "_STACK"
+
+#define IN_STACK(x)  (IS_SPEC(x) && (SPEC_OCLS(x) == istack ))
+#define IN_FARSPACE(x) FALSE
+
+typedef struct {
+} X_MEMMAP;
+
+#endif
diff --git a/src/z80/memmaps.h b/src/z80/memmaps.h
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/z80/port.h b/src/z80/port.h
new file mode 100644 (file)
index 0000000..aa265dc
--- /dev/null
@@ -0,0 +1,21 @@
+/** Set to target the 8051 */
+#define PROCESSOR_Z80          1
+
+#define HAS_BITSPACE           0
+#define HAS_REGSPACE           0
+#define HAS_PAGEDSPACE         0
+#define HAS_DIRECTSPACE                0
+#define HAS_XDATA              0
+#define HAS_OVERLAY            0
+#define HAS_IDATA              0
+#define HAS_SFRSPACE           0
+#define HAS_SFRBITSPACE                0
+#define HAS_XSTACK             0
+
+#define HAS_INTERRUPT_TABLE    0
+
+/** Setting this is equivalent to --stack-auto --no-peep --main-return --callee-saves --noregparms --xstack */
+#define USE_CLEAN_OPTIONS      1
+/** Set if the callee should save _all_ registers */
+#define USE_CALLEE_SAVES_ALL   1
+
diff --git a/src/z80/ralloc.c b/src/z80/ralloc.c
new file mode 100644 (file)
index 0000000..1731828
--- /dev/null
@@ -0,0 +1,1979 @@
+/** @name Z80 Register allocation functions.
+    @author Michael Hope
+
+    Note: much of this is ripped straight from Sandeep's mcs51 code.
+
+    This code maps the virtual symbols and code onto the real
+    hardware.  It allocates based on usage and how long the varible
+    lives into registers or temporary memory on the stack.
+
+    On the Z80 hl, ix, iy, and a are reserved for the code generator,
+    leaving bc and de for allocation.  The extra register pressure
+    from reserving hl is made up for by how much easier the sub
+    operations become.  You could swap hl for iy if the undocumented
+    iyl/iyh instructions are available.
+
+    The stack frame is the common ix-bp style.  Basically:
+
+    ix+4+n:    param 1 
+    ix+4:      param 0 
+    ix+2:      return address 
+    ix+0:      calling functions ix 
+    ix-n:      local varibles 
+    ...  
+    sp:        end of local varibles
+
+    There is currently no support for bit spaces or banked functions.
+    
+    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 <stdio.h>
+#include <stdlib.h>
+#include "SDCCglobl.h"
+#include "SDCCast.h"
+#include "SDCCmem.h"
+#include "SDCCy.h" 
+#include "SDCChasht.h"
+#include "SDCCbitv.h"
+#include "SDCCset.h"
+#include "SDCCicode.h"
+#include "SDCClabel.h"
+#include "SDCCBBlock.h"
+#include "SDCCloop.h"
+#include "SDCCcse.h"
+#include "SDCCcflow.h"
+#include "SDCCdflow.h"
+#include "SDCClrange.h"
+#include "ralloc.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      */
+/*-----------------------------------------------------------------*/
+
+bitVect *spiltSet = NULL ; 
+set *stackSpil = NULL;
+bitVect *regAssigned = NULL;
+short blockSpil = 0;
+int slocNum = 0 ;
+extern void genZ80Code(iCode *);
+int ptrRegReq = 0; /* one byte pointer register required */
+bitVect *funcrUsed = NULL; /* registers used in a function */
+int stackExtend = 0;
+int dataExtend  = 0;
+
+/** Set to help debug register pressure related problems */
+#define DEBUG_FAKE_EXTRA_REGS  0
+
+regs regsZ80[] = 
+{
+    { REG_GPR, C_IDX , "c", 1 },
+    { REG_GPR, B_IDX , "b", 1 },
+    { REG_GPR, E_IDX , "e", 1 },
+    { REG_GPR, D_IDX , "d", 1 },
+    /*    { REG_GPR, L_IDX , "l", 1 },
+    { REG_GPR, H_IDX , "h", 1 },*/
+#if DEBUG_FAKE_EXTRA_REGS
+    { REG_GPR, M_IDX , "m", 1 },
+    { REG_GPR, N_IDX , "n", 1 },
+    { REG_GPR, O_IDX , "o", 1 },
+    { REG_GPR, P_IDX , "p", 1 },
+    { REG_GPR, Q_IDX , "q", 1 },
+    { REG_GPR, R_IDX , "r", 1 },
+    { REG_GPR, S_IDX , "s", 1 },
+    { REG_GPR, T_IDX , "t", 1 },
+#endif
+    { REG_CND, CND_IDX, "c", 1}
+};
+
+/** Number of usable registers (all but C) */
+#define MAX_REGS ((sizeof(regsZ80)/sizeof(regs))-1)
+
+int nRegs = MAX_REGS;
+
+void spillThis (symbol *);
+
+/** Allocates register of given type.
+    'type' is not used on the z80 version.  It was used to select
+    between pointer and general purpose registers on the mcs51 version.
+
+    @return            Pointer to the newly allocated register.
+ */
+regs *allocReg (short type)
+{
+    int i;
+
+    for ( i = 0 ; i < nRegs ; i++ ) {
+       /* For now we allocate from any free */
+       if (regsZ80[i].isFree ) {
+           regsZ80[i].isFree = 0;
+           if (currFunc)
+               currFunc->regsUsed = 
+                   bitVectSetBit(currFunc->regsUsed,i);
+           return &regsZ80[i];
+       }
+    }
+    return NULL;
+}
+
+/** Returns pointer to register wit index number
+ */
+regs *regWithIdx (int idx)
+{
+    int i;
+    
+    for (i=0;i < nRegs;i++)
+       if (regsZ80[i].rIdx == idx)
+           return &regsZ80[i];
+
+    werror(E_INTERNAL_ERROR,__FILE__,__LINE__,
+          "regWithIdx not found");
+    exit(1);
+}
+
+/** Frees a register.
+ */
+void freeReg (regs *reg)
+{
+    assert(!reg->isFree);
+    reg->isFree = 1;
+}
+
+
+/** Returns number of free registers.
+ */
+int nFreeRegs (int type)
+{
+    int i;
+    int nfr=0;
+    
+    for (i = 0 ; i < nRegs; i++ ) {
+       /* For now only one reg type */
+       if (regsZ80[i].isFree)
+           nfr++;
+    }
+    return nfr;
+}
+
+/** Free registers with type.
+ */
+int nfreeRegsType (int type)
+{
+    int nfr ;
+    if (type == REG_PTR) {
+       if ((nfr = nFreeRegs(type)) == 0)
+           return nFreeRegs(REG_GPR);
+    } 
+    
+    return nFreeRegs(type);
+}
+
+
+/*-----------------------------------------------------------------*/
+/* allDefsOutOfRange - all definitions are out of a range          */
+/*-----------------------------------------------------------------*/
+bool allDefsOutOfRange (bitVect *defs,int fseq, int toseq) 
+{
+    int i ;
+
+    if (!defs)
+       return TRUE ;
+
+    for ( i = 0 ;i < defs->size ; i++ ) {
+       iCode *ic;
+
+       if (bitVectBitValue(defs,i)             &&
+           (ic = hTabItemWithKey(iCodehTab,i)) &&
+           ( ic->seq >= fseq  && ic->seq <= toseq))
+           
+           return FALSE;
+       
+    }
+    
+    return TRUE;
+}
+  
+/*-----------------------------------------------------------------*/
+/* computeSpillable - given a point find the spillable live ranges */
+/*-----------------------------------------------------------------*/
+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,spiltSet); /* those already spilt */
+    spillable = 
+       bitVectCplAnd(spillable,ic->uses); /* used in this one */    
+    bitVectUnSetBit(spillable,ic->defKey);
+    spillable = bitVectIntersect(spillable,regAssigned);
+    return spillable;
+    
+}
+
+/*-----------------------------------------------------------------*/
+/* noSpilLoc - return true if a variable has no spil location      */
+/*-----------------------------------------------------------------*/
+int noSpilLoc (symbol *sym, eBBlock *ebp,iCode *ic)
+{
+    return (sym->usl.spillLoc ? 0 : 1);
+}
+
+/*-----------------------------------------------------------------*/
+/* hasSpilLoc - will return 1 if the symbol has spil location      */
+/*-----------------------------------------------------------------*/
+int hasSpilLoc (symbol *sym, eBBlock *ebp, iCode *ic)
+{
+    return (sym->usl.spillLoc ? 1 : 0);
+}
+
+/*-----------------------------------------------------------------*/
+/* directSpilLoc - will return 1 if the splilocation is in direct  */
+/*-----------------------------------------------------------------*/
+int directSpilLoc (symbol *sym, eBBlock *ebp, iCode *ic)
+{
+    /* No such thing as direct space */
+    return 0;
+}
+
+/*-----------------------------------------------------------------*/
+/* hasSpilLocnoUptr - will return 1 if the symbol has spil location*/
+/*                    but is not used as a pointer                 */
+/*-----------------------------------------------------------------*/
+int hasSpilLocnoUptr (symbol *sym, eBBlock *ebp, iCode *ic)
+{
+#if 0
+    return sym->usl.spillLoc ? 1:0;
+#else
+    return ((sym->usl.spillLoc && !sym->uptr) ? 1 : 0);
+#endif
+}
+
+/** Will return 1 if the remat flag is set.
+    A symbol is rematerialisable if it doesnt need to be allocated
+    into registers at creation as it can be re-created at any time -
+    i.e. it's constant in some way.
+*/
+int rematable (symbol *sym, eBBlock *ebp, iCode *ic)
+{
+    return sym->remat;
+}
+
+/*-----------------------------------------------------------------*/
+/* notUsedInBlock - not used in this block                         */
+/*-----------------------------------------------------------------*/
+int notUsedInBlock (symbol *sym, eBBlock *ebp, iCode *ic)
+{   
+    return (!bitVectBitsInCommon(sym->defs,ebp->usesDefs) &&
+           allDefsOutOfRange (sym->defs,ebp->fSeq,ebp->lSeq));
+/*     return (!bitVectBitsInCommon(sym->defs,ebp->usesDefs)); */
+}
+
+/*-----------------------------------------------------------------*/
+/* notUsedInRemaining - not used or defined in remain of the block */
+/*-----------------------------------------------------------------*/
+int notUsedInRemaining (symbol *sym, eBBlock *ebp, iCode *ic)
+{
+    return ((usedInRemaining (operandFromSymbol(sym),ic) ? 0 : 1) &&
+           allDefsOutOfRange (sym->defs,ic->seq,ebp->lSeq));
+}
+
+/*-----------------------------------------------------------------*/
+/* allLRs - return true for all                                    */
+/*-----------------------------------------------------------------*/
+int allLRs (symbol *sym, eBBlock *ebp, iCode *ic)
+{
+    return 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* liveRangesWith - applies function to a given set of live range  */
+/*-----------------------------------------------------------------*/
+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(regAssigned,sym->key))
+           addSetHead(&rset,sym);
+    }
+
+    return rset;
+}
+
+
+/*-----------------------------------------------------------------*/
+/* leastUsedLR - given a set determines which is the least used    */
+/*-----------------------------------------------------------------*/
+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  */
+/*-----------------------------------------------------------------*/
+int noOverLap (set *itmpStack, symbol *fsym)
+{
+    symbol *sym;
+   
+
+    for (sym = setFirstItem(itmpStack); sym;
+        sym = setNextItem(itmpStack)) {
+       if (sym->liveTo > fsym->liveFrom )
+           return 0;
+           
+    }
+
+    return 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* isFree - will return 1 if the a free spil location is found     */
+/*-----------------------------------------------------------------*/
+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  */
+/*-----------------------------------------------------------------*/
+void spillLRWithPtrReg (symbol *forSym)
+{
+    /* Always just return */
+}
+
+/*-----------------------------------------------------------------*/
+/* createStackSpil - create a location on the stack to spil        */
+/*-----------------------------------------------------------------*/
+symbol *createStackSpil (symbol *sym)
+{
+    symbol *sloc= NULL;
+
+    /* first go try and find a free one that is already 
+       existing on the stack */
+    if (applyToSet(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 */
+       
+    sprintf(buffer,"sloc%d",slocNum++);
+    sloc = newiTemp(buffer);
+
+    /* set the type to the spilling symbol */
+    sloc->type = copyLinkChain(sym->type);
+    sloc->etype = getSpec(sloc->type);
+    SPEC_SCLS(sloc->etype) = S_AUTO ;    
+
+    /* 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
+       and turn off overlaying 
+    */
+    allocLocal(sloc);
+
+    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);
+       stackExtend += getSize(sloc->type);
+    } else
+       dataExtend += getSize(sloc->type);
+
+    /* add it to the stackSpil set */
+    addSetHead(&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  */
+/*-----------------------------------------------------------------*/
+bool isSpiltOnStack (symbol *sym)
+{
+    link *etype;
+
+    if (!sym)
+       return FALSE ;
+    
+    if (!sym->isspilt)
+       return FALSE ;
+
+/*     if (sym->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                            */
+/*-----------------------------------------------------------------*/
+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 = 1;
+    spiltSet = bitVectSetBit(spiltSet,sym->key);
+       
+    bitVectUnSetBit(regAssigned,sym->key);
+
+    for (i = 0 ; i < sym->nRegs ; i++)
+
+       if (sym->regs[i]) {
+           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 (!ptrRegReq && isSpiltOnStack(sym)) {
+       ptrRegReq++ ;
+       spillLRWithPtrReg(sym);
+    }
+
+    if (sym->usl.spillLoc && !sym->remat)
+       sym->usl.spillLoc->allocreq = 1;
+    return;
+}
+
+/** Select a iTemp to spil : rather a simple procedure.
+ */
+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);
+    }
+
+#if 0
+    /* 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 = 1;
+       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 (!blockSpil && (selectS = liveRangesWith(lrcs,notUsedInBlock,ebp,ic))) {
+           sym = leastUsedLR(selectS);
+           /* if this is not rematerializable */
+           if (!sym->remat) {
+               blockSpil++;
+               sym->blockSpil = 1;
+           }
+           return sym;
+       } 
+
+       /* check if there are any live ranges that not
+          used in the remainder of the block */
+       if (!blockSpil && (selectS = liveRangesWith(lrcs,notUsedInRemaining,ebp,ic))) {
+           sym = leastUsedLR (selectS);
+           if (!sym->remat) {
+               sym->remainSpil = 1;
+               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 = 1;
+       return sym;
+    }
+#endif   
+
+    /* find live ranges with spillocation */
+    if ((selectS = liveRangesWith(lrcs,hasSpilLoc,ebp,ic))) {
+       
+       sym = leastUsedLR(selectS);
+       sym->usl.spillLoc->allocreq = 1;
+       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 = 1;
+       return sym;
+    }
+    
+    /* this is an extreme situation we will spill
+       this one : happens very rarely but it does happen */
+    spillThis ( forSym );
+    return forSym;
+   
+}
+
+/** Spil some variable & mark registers as free.
+    A spill occurs when an iTemp wont fit into the available registers.
+ */
+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 = 1;
+    spiltSet = bitVectSetBit(spiltSet,ssym->key);
+    
+    /* mark it as not register assigned &
+       take it away from the set */   
+    bitVectUnSetBit(regAssigned,ssym->key);
+    /* mark the registers as free */    
+    for (i = 0 ; i < ssym->nRegs ;i++ )
+       if (ssym->regs[i])
+           freeReg(ssym->regs[i]);
+     
+#if 0
+    /* if spilt on stack then free up r0 & r1 
+       if they could have been assigned to as gprs */
+    if (!ptrRegReq && isSpiltOnStack(ssym) ) {
+       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);    
+    }
+#endif
+
+    if (ssym == forSym )
+       return FALSE ;
+    else
+       return TRUE ;
+}
+
+/** Will try for GPR if not spil.
+ */
+regs *getRegGpr (iCode *ic, eBBlock *ebp,symbol *sym)
+{
+    regs *reg;
+
+ tryAgain:
+    /* try for gpr type */
+    if ((reg = allocReg(REG_GPR)))        
+       return reg;    
+
+    if (!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 ;    
+}
+
+/** 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;
+}
+
+/** Check the live to and if they have registers & are not spilt then
+    free up the registers 
+*/
+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(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(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)   &&
+               (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(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 < max(sym->nRegs,result->nRegs) ; i++)
+                   if (i < sym->nRegs )
+                       result->regs[i] = sym->regs[i] ;
+                   else
+                       result->regs[i] = getRegGpr (ic,ebp,result);
+
+               regAssigned = bitVectSetBit(regAssigned,result->key);
+           }                   
+           
+           /* free the remaining */
+           for (; i < sym->nRegs ; i++) {
+               if (psym) {
+                   if (!symHasReg(psym,sym->regs[i]))
+                       freeReg(sym->regs[i]);
+               } else
+                   freeReg(sym->regs[i]);
+           }
+       }
+    }
+}
+
+
+/** Reassign this to registers.
+ */
+void reassignLR (operand *op)
+{
+    symbol *sym = OP_SYMBOL(op);
+    int i;
+
+    /* not spilt any more */     
+    sym->isspilt = sym->blockSpil  = sym->remainSpil = 0;
+    bitVectUnSetBit(spiltSet,sym->key);
+      
+    regAssigned = bitVectSetBit(regAssigned,sym->key);
+
+    blockSpil--;
+
+    for (i=0;i<sym->nRegs;i++)
+       sym->regs[i]->isFree = 0;
+}
+
+/** Determines if allocating will cause a spill.
+ */
+int willCauseSpill ( int nr, int rt)
+{
+    /* first check if there are any avlb registers
+       of te type required */
+    if (nFreeRegs(0) >= nr)
+       return 0;
+
+    /* it will cause a spil */
+    return 1;
+}
+
+/** The allocator can allocate same registers to result and operand,
+    if this happens make sure they are in the same position as the operand
+    otherwise chaos results.
+*/
+static void positionRegs (symbol *result, symbol *opsym, int lineno)
+{
+       int count = min(result->nRegs,opsym->nRegs);
+       int i , j = 0, shared = 0;
+
+       /* if the result has been spilt then cannot share */
+       if (opsym->isspilt)
+               return ;
+ 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;          
+               goto again;
+       }
+}
+
+/** Try to allocate a pair of registers to the symbol.
+ */
+bool tryAllocatingRegPair(symbol *sym)
+{
+    int i;
+    assert(sym->nRegs == 2);
+    for ( i = 0 ; i < nRegs ; i+=2 ) {
+       if ((regsZ80[i].isFree)&&(regsZ80[i+1].isFree)) {
+           regsZ80[i].isFree = 0;
+           sym->regs[0] = &regsZ80[i];
+           regsZ80[i+1].isFree = 0;
+           sym->regs[1] = &regsZ80[i+1];
+           if (currFunc) {
+               currFunc->regsUsed = 
+                   bitVectSetBit(currFunc->regsUsed,i);
+               currFunc->regsUsed = 
+                   bitVectSetBit(currFunc->regsUsed,i+1);
+           }
+           return TRUE;
+       }
+    }
+    return FALSE;
+}
+
+/** Serially allocate registers to the variables.
+    This is the main register allocation function.  It is called after
+    packing.
+ */
+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 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 = 1;
+
+           /* take away registers from live
+              ranges that end at this instruction */      
+           deassignLRs (ic, ebbs[i]) ;         
+                   
+           /* some don't need registers */
+           /* MLH: removed RESULT and POINTER_SET condition */
+           if (SKIP_IC2(ic) ||
+               ic->op == JUMPTABLE ||
+               ic->op == IFX ||
+               ic->op == IPUSH ||
+               ic->op == IPOP)
+               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;
+
+               /* 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(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 (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 && sym->usl.spillLoc ) {
+
+                   symbol *leastUsed = 
+                       leastUsedLR(liveRangesWith (spillable ,
+                                                   allLRs,
+                                                   ebbs[i],
+                                                   ic));
+                   if (leastUsed && 
+                       leastUsed->used > sym->used) {
+                       spillThis (sym);
+                       continue;
+                   }
+               }               
+
+               /* else we assign registers to it */            
+               regAssigned = bitVectSetBit(regAssigned,sym->key);
+
+               /* Special case:  Try to fit into a reg pair if
+                  available */
+               if ((sym->nRegs == 2)&&tryAllocatingRegPair(sym)) {
+               }
+               else {
+                   for (j = 0 ; j < sym->nRegs ;j++ ) {
+                       sym->regs[j] = getRegGpr(ic,ebbs[i],sym);
+                       
+                       /* if the allocation falied 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)),ic->lineno);
+               /* do the same for the right operand */
+               if (IC_RIGHT(ic) && IS_SYMOP(IC_RIGHT(ic)) &&
+                   OP_SYMBOL(IC_RIGHT(ic))->nRegs && ic->op != '=')
+                       positionRegs(OP_SYMBOL(IC_RESULT(ic)),
+                                    OP_SYMBOL(IC_RIGHT(ic)),ic->lineno);
+               
+           }       
+       }
+    }
+}
+
+/*-----------------------------------------------------------------*/
+/* rUmaskForOp :- returns register mask for an operand             */
+/*-----------------------------------------------------------------*/
+bitVect *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(nRegs);
+
+    for (j = 0; j < sym->nRegs; j++) {
+       rumask = bitVectSetBit(rumask,
+                              sym->regs[j]->rIdx);
+    }
+
+    return rumask;
+}
+
+/** Returns bit vector of registers used in iCode.
+ */
+bitVect *regsUsedIniCode (iCode *ic)
+{
+    bitVect *rmask = newBitVect(nRegs);
+
+    /* do the special cases first */
+    if (ic->op == IFX ) {
+       rmask = bitVectUnion(rmask,
+                            rUmaskForOp(IC_COND(ic)));
+       goto ret;
+    }
+
+    /* for the jumptable */
+    if (ic->op == JUMPTABLE) {
+       rmask = bitVectUnion(rmask,
+                            rUmaskForOp(IC_JTCOND(ic)));
+
+        goto ret;
+    }
+
+    /* of all other cases */
+    if (IC_LEFT(ic)) 
+       rmask = bitVectUnion(rmask,
+                            rUmaskForOp(IC_LEFT(ic)));
+       
+    
+    if (IC_RIGHT(ic))
+       rmask = bitVectUnion(rmask,
+                            rUmaskForOp(IC_RIGHT(ic)));
+
+    if (IC_RESULT(ic))
+       rmask = bitVectUnion(rmask,
+                            rUmaskForOp(IC_RESULT(ic)));
+
+ ret:
+    return rmask;
+}
+
+/** For each instruction will determine the regsUsed.
+ */
+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);
+           funcrUsed = bitVectUnion(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(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");
+                   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);
+           }
+       }
+    }
+}
+
+/** Returns the rematerialized string for a remat var.
+ */
+char *rematStr (symbol *sym)
+{
+    char *s = buffer;   
+    iCode *ic = sym->rematiCode;    
+
+    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 ;
+        }
+        /* we reached the end */
+        sprintf(s,"%s",OP_SYMBOL(IC_LEFT(ic))->rname);
+        break;
+    }
+
+    return buffer ;
+}
+
+/*-----------------------------------------------------------------*/
+/* regTypeNum - computes the type & number of registers required   */
+/*-----------------------------------------------------------------*/
+void regTypeNum ()
+{
+    symbol *sym;
+    int k;
+
+    /* 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 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 */
+           /* Always general purpose */
+           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 ;    
+    }
+    
+}
+
+/** Mark all registers as free.
+ */
+void freeAllRegs()
+{
+    int i;
+
+    for (i=0;i< nRegs;i++ )
+       regsZ80[i].isFree = 1;
+}
+
+/*-----------------------------------------------------------------*/
+/* deallocStackSpil - this will set the stack pointer back         */
+/*-----------------------------------------------------------------*/
+DEFSETFUNC(deallocStackSpil)
+{
+    symbol *sym = item;
+
+    deallocLocal(sym);
+    return 0;
+}
+
+/** Register reduction for assignment.
+ */
+int packRegsForAssign (iCode *ic,eBBlock *ebp)
+{
+    iCode *dic, *sic;
+    
+    if (
+       !IS_TRUE_SYMOP(IC_RESULT(ic)) ||
+       !IS_ITEMP(IC_RIGHT(ic))       ||        
+       OP_LIVETO(IC_RIGHT(ic)) > ic->seq ||
+       OP_SYMBOL(IC_RIGHT(ic))->isind)
+       return 0;
+
+#if 0        
+    /* if the true symbol is defined in far space or on stack
+       then we should not since this will increase register pressure */
+    if (isOperandInFarSpace(IC_RESULT(ic))) {
+       if ((dic = farSpacePackable(ic)))
+           goto pack;
+       else
+           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 there is a function call and this is
+          a parameter & not my parameter then don't pack it */
+       if ( (dic->op == CALL || dic->op == PCALL) &&
+            (OP_SYMBOL(IC_RESULT(ic))->_isparm &&
+             !OP_SYMBOL(IC_RESULT(ic))->ismyparm)) {
+           dic = NULL;
+           break;
+       }
+
+       if (SKIP_IC2(dic))
+           continue;
+
+#if 0  
+       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;
+       }
+#endif
+    }
+    
+    if (!dic)
+       return 0 ; /* did not find */
+           
+    /* 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 */
+    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;
+    }
+    /* 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);
+    return 1;
+    
+}
+
+/** Scanning backwards looks for first assig found.
+ */
+iCode *findAssignToSym (operand *op,iCode *ic)
+{
+    iCode *dic;
+
+    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))*/
+           {      
+
+           /* we are interested only if defined in far space */
+           /* or in stack space in case of + & - */
+
+           /* if assigned to a non-symbol then return
+              true */
+           if (!IS_SYMOP(IC_RIGHT(dic)))
+               break ;
+
+           /* 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 ((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;
+           }           
+
+           break ;
+               
+       }
+
+       /* 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;
+    }
+
+    /* 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;
+       
+       
+}
+
+/*-----------------------------------------------------------------*/
+/* packRegsForSupport :- reduce some registers for support calls   */
+/*-----------------------------------------------------------------*/
+int packRegsForSupport (iCode *ic, eBBlock *ebp)
+{
+    int change = 0 ;
+    /* 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) {
+       iCode *dic = findAssignToSym(IC_LEFT(ic),ic);
+       iCode *sic;
+
+       if (!dic)
+           goto right ;
+
+       /* found it we need to remove it from the
+          block */
+       for ( sic = dic; sic != ic ; sic = sic->next )
+           bitVectUnSetBit(sic->rlive,IC_LEFT(ic)->key);
+
+       IC_LEFT(ic)->operand.symOperand =
+           IC_RIGHT(dic)->operand.symOperand;
+       IC_LEFT(ic)->key = IC_RIGHT(dic)->operand.symOperand->key;
+       remiCodeFromeBBlock(ebp,dic);   
+       change++;      
+    }
+    
+    /* do the same for the right operand */
+ right:    
+    if (!change && 
+       IS_ITEMP(IC_RIGHT(ic)) &&
+       OP_SYMBOL(IC_RIGHT(ic))->liveTo <= ic->seq) {
+       iCode *dic = findAssignToSym(IC_RIGHT(ic),ic);
+       iCode *sic;
+       
+       if (!dic)
+           return change ;
+
+       /* found it we need to remove it from the block */
+       for ( sic = dic; sic != ic ; sic = sic->next )
+           bitVectUnSetBit(sic->rlive,IC_RIGHT(ic)->key);
+       
+       IC_RIGHT(ic)->operand.symOperand =
+           IC_RIGHT(dic)->operand.symOperand;
+       IC_RIGHT(ic)->key = IC_RIGHT(dic)->operand.symOperand->key;
+       
+       remiCodeFromeBBlock(ebp,dic);
+       change ++;
+    }
+   
+    return change ;
+}
+
+#define IS_OP_RUONLY(x) (x && IS_SYMOP(x) && OP_SYMBOL(x)->ruonly)
+
+/** 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)) > 2 && 
+       ic->op != RETURN             &&
+       ic->op != SEND)
+       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 the that definition */
+    if (!(dic = 
+         hTabItemWithKey(iCodehTab,
+                         bitVectFirstBit(OP_DEFS(op)))))
+       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) {
+           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 (POINTER_SET(dic))
+      return NULL;
+
+    if (POINTER_GET(dic))
+      return NULL;
+    
+    sic = dic;
+
+    /* also make sure the intervenening instructions
+       don't have any thing in far space */
+    for (dic = dic->next ; dic && dic != 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 (POINTER_SET(dic))
+           return NULL ;
+       
+       if (POINTER_GET(dic))
+           return NULL ;
+
+       /* if address of & the result is remat the okay */
+       if (dic->op == ADDRESS_OF &&
+           OP_SYMBOL(IC_RESULT(dic))->remat)
+           continue ;
+          
+       /* 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;
+       }
+    }
+               
+    OP_SYMBOL(op)->ruonly = 1;
+    return sic;
+}
+
+/*-----------------------------------------------------------------*/
+/* isBitwiseOptimizable - requirements of JEAN LOUIS VERN          */
+/*-----------------------------------------------------------------*/
+static bool isBitwiseOptimizable (iCode *ic)
+{
+    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))
+       return TRUE;
+    return FALSE; 
+}
+
+/** Pack registers for acc use.
+    When the result of this operation is small and short lived it may
+    be able to be stored in the accumelator.
+ */
+void packRegsForAccUse (iCode *ic)
+{
+    iCode *uic;
+    
+    /* 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 not 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 ;
+       
+    /* 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 the usage is not is an assignment or an 
+       arithmetic / bitwise / shift operation then not */
+    if (POINTER_SET(uic) && 
+       getSize(aggrToPtr(operandType(IC_RESULT(uic)),FALSE)) > 1)
+       return;
+#endif
+
+    if (uic->op != '=' && 
+       !IS_ARITHMETIC_OP(uic) &&
+       !IS_BITWISE_OP(uic)    &&
+       uic->op != LEFT_OP &&
+       uic->op != RIGHT_OP )
+       return;
+
+    /* if used in ^ operation then make sure right is not a 
+       literl */
+    if (uic->op == '^' && isOperandLiteral(IC_RIGHT(uic)))
+       return ;
+
+    /* if shift operation make sure right side is not a literal */
+    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 ;
+           
+#if 0
+    /* make sure that the result of this icode is not on the
+       stack, since acc is used to compute stack offset */
+    if (IS_TRUE_SYMOP(IC_RESULT(uic)) &&
+       OP_SYMBOL(IC_RESULT(uic))->onStack)
+       return ;
+#endif
+
+#if 0
+    /* if either one of them in far space then we cannot */
+    if ((IS_TRUE_SYMOP(IC_LEFT(uic)) &&
+        isOperandInFarSpace(IC_LEFT(uic))) ||
+       (IS_TRUE_SYMOP(IC_RIGHT(uic)) &&
+        isOperandInFarSpace(IC_RIGHT(uic))))
+       return ;
+#endif
+
+    /* if the usage has only one operand then we can */
+    if (IC_LEFT(uic) == NULL ||
+       IC_RIGHT(uic) == NULL) 
+       goto accuse;
+
+    /* make sure this is on the left side if not
+       a '+' since '+' is commutative */
+    if (ic->op != '+' &&
+       IC_LEFT(uic)->key != IC_RESULT(ic)->key)
+       return;
+
+    /* 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 ;
+    }
+
+    /** This is confusing :)  Guess for now */
+    if (IC_LEFT(uic)->key == IC_RESULT(ic)->key &&
+       (IS_ITEMP(IC_RIGHT(uic)) ||
+        (IS_TRUE_SYMOP(IC_RIGHT(uic)))))
+       goto accuse;
+    
+    if (IC_RIGHT(uic)->key == IC_RESULT(ic)->key &&
+       (IS_ITEMP(IC_LEFT(uic)) ||
+        (IS_TRUE_SYMOP(IC_LEFT(uic)))))
+       goto accuse ;
+    return ;
+ accuse:
+    OP_SYMBOL(IC_RESULT(ic))->accuse = 1;
+}
+
+/** Does some transformations to reduce register pressure.
+ */
+void packRegisters (eBBlock *ebp)
+{
+    iCode *ic ;
+    int change = 0 ;
+    
+    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 ) {
+       /* Safe: address of a true sym is always constant. */
+       /* if this is an itemp & result of a 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;
+       }
+
+       /* Safe: just propagates the remat flag */
+       /* 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 &&
+           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 the condition of an if instruction is defined in the
+          previous instruction then mark the itemp as a conditional */
+       if ((IS_CONDITIONAL(ic) ||
+            ( ( ic->op == BITWISEAND      ||
+                ic->op == '|'             ||
+                ic->op == '^' ) &&
+              isBitwiseOptimizable(ic))) &&        
+           ic->next && ic->next->op == IFX &&
+           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 ;
+       }
+
+#if 0
+       /* reduce for support function calls */
+       if (ic->supportRtn || ic->op == '+' || ic->op == '-' )
+           packRegsForSupport(ic,ebp); 
+#endif
+
+#if 0
+       /* some cases the redundant moves can
+          can be eliminated for return statements */
+       if ((ic->op == RETURN || ic->op == SEND) &&
+           !isOperandInFarSpace(IC_LEFT(ic))    &&
+           !options.model)
+           packRegsForOneuse (ic,IC_LEFT(ic),ebp);     
+#endif
+
+#if 0
+       /* 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);
+#endif
+
+#if 0
+       /* if pointer get */
+       if (POINTER_GET(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);
+#endif
+
+       /* 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_BITWISE_OP(ic) 
+            || ic->op == LEFT_OP || ic->op == RIGHT_OP
+            ) &&
+           IS_ITEMP(IC_RESULT(ic)) &&
+           getSize(operandType(IC_RESULT(ic))) <= 2)
+           packRegsForAccUse (ic);
+    }
+}
+  
+/*-----------------------------------------------------------------*/
+/* assignRegisters - assigns registers to each live range as need  */
+/*-----------------------------------------------------------------*/
+void assignRegisters (eBBlock **ebbs, int count)
+{
+    iCode *ic;
+    int i ;
+
+    setToNull((void *)&funcrUsed);
+    ptrRegReq = stackExtend = dataExtend = 0;
+    /* if not register extentions then reduce number
+       of registers */
+    nRegs = MAX_REGS;
+
+    /* 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(".dumppack",ebbs,count);
+
+    /* first determine for each live range the number of 
+       registers & the type of registers required for each */
+    regTypeNum ();
+    
+    /* and serially allocate registers */ 
+    serialRegAssign(ebbs,count);
+
+    /* if stack was extended then tell the user */
+    if (stackExtend) {
+/*     werror(W_TOOMANY_SPILS,"stack", */
+/*            stackExtend,currFunc->name,""); */
+       stackExtend = 0 ;
+    }
+
+    if (dataExtend) {
+/*     werror(W_TOOMANY_SPILS,"data space", */
+/*            dataExtend,currFunc->name,""); */
+       dataExtend = 0 ;
+    }
+
+    if (options.dump_rassgn)
+       dumpEbbsToFileExt(".dumprassgn",ebbs,count);
+
+    /* after that create the register mask
+       for each of the instruction */
+    createRegMask (ebbs,count);
+
+    /* now get back the chain */
+    ic = iCodeLabelOptimize(iCodeFromeBBlock (ebbs,count));
+
+    /* redo that offsets for stacked automatic variables */
+    redoStackOffsets ();
+
+    genZ80Code(ic);
+
+    /* free up any stackSpil locations allocated */   
+    applyToSet(stackSpil,deallocStackSpil);
+    slocNum = 0;
+    setToNull((void **)&stackSpil);
+    setToNull((void **)&spiltSet);
+    /* mark all registers as free */
+    freeAllRegs();
+
+    return ;
+}
diff --git a/src/z80/ralloc.h b/src/z80/ralloc.h
new file mode 100644 (file)
index 0000000..d3af052
--- /dev/null
@@ -0,0 +1,68 @@
+/*-------------------------------------------------------------------------
+
+  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
+
+#define DEBUG_FAKE_EXTRA_REGS  0
+
+enum { C_IDX = 0,
+       B_IDX, 
+       E_IDX,
+       D_IDX, 
+       L_IDX, 
+       H_IDX,
+#if DEBUG_FAKE_EXTRA_REGS
+       M_IDX,
+       N_IDX,
+       O_IDX,
+       P_IDX,
+       Q_IDX,
+       R_IDX,
+       S_IDX,
+       T_IDX,
+#endif
+       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 */
+    char *name ;         /* name */
+    unsigned isFree :1;  /* is currently unassigned  */    
+} regs;
+
+extern regs regsZ80[];
+
+void   assignRegisters (eBBlock **, int );
+regs  *regWithIdx (int);
+
+#endif